commit 40c0f755c998d2615fe8466aab20c6d81bd463e7
Author: Ryan <ry@tinyclouds.org>
Date:   Wed Apr 22 19:35:47 2009 +0200

    import full versions of dependency libraries!

diff --git a/configure b/configure
index db2d3c5..fbe2e5a 100755
--- a/configure
+++ b/configure
@@ -4,19 +4,11 @@
 
 # Fancy colors used to beautify the output a bit.
 #
-if [ "$NOCOLOR" ] ; then
-    NORMAL=""
-    BOLD=""
-    RED=""
-    YELLOW=""
-    GREEN=""
-else
-    NORMAL='\\033[0m'
-    BOLD='\\033[01;1m'
-    RED='\\033[01;91m'
-    YELLOW='\\033[00;33m'
-    GREEN='\\033[01;92m'
-fi
+NORMAL=""
+BOLD=""
+RED=""
+YELLOW=""
+GREEN=""
 
 EXIT_SUCCESS=0
 EXIT_FAILURE=1
diff --git a/deps/libebb/.gitignore b/deps/libebb/.gitignore
new file mode 100644
index 0000000..f65038b
--- /dev/null
+++ b/deps/libebb/.gitignore
@@ -0,0 +1,5 @@
+*.o
+examples/hello_world
+test_request_parser
+ebb_request_parser.c
+tags
diff --git a/deps/libebb/LICENSE b/deps/libebb/LICENSE
new file mode 100644
index 0000000..91b52e6
--- /dev/null
+++ b/deps/libebb/LICENSE
@@ -0,0 +1,21 @@
+Copyright (c) 2008 Ryan Dahl (ry@ndahl.us)
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+
diff --git a/deps/libebb/README b/deps/libebb/README
new file mode 100644
index 0000000..d5b7ce3
--- /dev/null
+++ b/deps/libebb/README
@@ -0,0 +1,7 @@
+see doc/index.html and examples/hello_world.c for explanation
+
+webpage: http://tinyclouds.org/libebb/
+git repository: http://github.com/ry/libebb/tree/master
+
+To build libebb please edit config.mk to reflect your system's parameters.
+
diff --git a/deps/libebb/config.mk b/deps/libebb/config.mk
new file mode 100644
index 0000000..5564bdd
--- /dev/null
+++ b/deps/libebb/config.mk
@@ -0,0 +1,38 @@
+PREFIX = $(HOME)/local/libebb
+
+# libev
+EVINC  = $(HOME)/local/libev/include
+EVLIB  = $(HOME)/local/libev/lib
+EVLIBS = -L${EVLIB} -lev
+
+# GnuTLS, comment if you don't want it (necessary for HTTPS)
+GNUTLSLIB   = /usr/lib
+GNUTLSINC   = /usr/include
+GNUTLSLIBS  = -L${GNUTLSLIB} -lgnutls
+GNUTLSFLAGS = -DHAVE_GNUTLS
+
+# includes and libs
+INCS = -I${EVINC} -I${GNUTLSINC}
+LIBS = ${EVLIBS} ${GNUTLSLIBS} -lefence
+
+# flags
+CPPFLAGS = -DVERSION=\"$(VERSION)\" ${GNUTLSFLAGS}
+CFLAGS   = -O2 -g -Wall ${INCS} ${CPPFLAGS} -fPIC
+LDFLAGS  = -s ${LIBS}
+LDOPT    = -shared
+SUFFIX   = so
+SONAME   = -Wl,-soname,$(OUTPUT_LIB)
+
+# Solaris
+#CFLAGS  = -fast ${INCS} -DVERSION=\"$(VERSION)\" -fPIC
+#LDFLAGS = ${LIBS}
+#SONAME  = 
+
+# Darwin
+# LDOPT  = -dynamiclib 
+# SUFFIX = dylib
+# SONAME = -current_version $(VERSION) -compatibility_version $(VERSION)
+
+# compiler and linker
+CC = cc
+RANLIB = ranlib
diff --git a/deps/libebb/doc/icon.png b/deps/libebb/doc/icon.png
new file mode 100644
index 0000000..702f4b5
Binary files /dev/null and b/deps/libebb/doc/icon.png differ
diff --git a/deps/libebb/doc/index.html b/deps/libebb/doc/index.html
new file mode 100644
index 0000000..612c9e9
--- /dev/null
+++ b/deps/libebb/doc/index.html
@@ -0,0 +1,240 @@
+
+<html>
+  <style>
+    body {
+      background: #fff;
+      color: #2e3436;
+      font-size: 12pt;
+      line-height: 16pt;
+  /*  font-family: Palatino;  */
+      margin: 3em 0 3em 3em; 
+    }
+
+    code, pre {
+    }
+
+    #contents {
+      max-width: 40em;
+    }
+
+    ul {
+      padding-left: 0;
+    }
+
+    li {
+      margin-top: 0.5em;
+      margin-bottom: 0.5em;
+    }
+
+    p {
+      text-align: left;
+    }
+
+
+    img {
+      float: left;
+      margin: 0 1em 1em 0;
+    }
+
+    p { clear: both; }
+  </style>
+  <body> <div id="contents">
+    <img src="icon.png"/>
+    <h1>libebb</h1>
+
+    <p>
+      libebb is a lightweight HTTP server library for C.  It lays the
+      foundation for writing a web server by providing the socket juggling
+      and request parsing. By implementing the HTTP/1.1 grammar provided in
+      RFC2612,  libebb understands most most valid HTTP/1.1 connections
+      (persistent, pipelined, and chunked requests included) and rejects
+      invalid or malicious requests.  libebb supports SSL over HTTP.  
+    </p>
+
+    <p>
+      The library embraces a minimalistic single-threaded evented design.
+      No control is removed from the user. For example, all allocations are
+      done through callbacks so that the user might implement in optimal
+      ways for their specific application.  By design libebb is not
+      thread-safe and all provided callbacks must not block.  libebb uses
+      the <a href="http://libev.schmorp.de/bench.html">high-performance</a>
+      libev event loop, but does not control it. The user of the library may
+      start and stop the loop at will, they may attach thier own watchers. 
+    </p>
+
+    <p>
+      libebb depends on POSIX sockets, libev, and optionally GnuTLS. 
+    </p>
+
+    <p>
+      libebb is in the early stages of development and probably contains
+      many bugs. The API is subject to radical changes.  If you're
+      interested <a href="http://github.com/ry/libebb/tree/master">checkout
+        the source code</a> and <a
+        href="http://groups.google.com/group/ebbebb">join the mailing
+        list</a>.  A release will be made when it proves stable.
+    </p>
+
+    <p>libebb is released under <a
+      href="http://www.gnu.org/licenses/license-list.html#X11License">the
+      X11 license</a>.</p>
+
+    <h2>Usage</h2>
+
+    <p>
+      libebb is a simple API, mostly it is providing callbacks.  There are
+      two types of callbacks that one will work with: 
+    </p>
+
+    <ul>
+      <li>callbacks to allocate and initialize data for libebb. These are
+      named <code>new_*</code> like <code>new_connection</code> and
+      <code>new_request</code></li>
+      <li>callbacks which happen on an event and might provide a pointer to
+      a chunk of data. These are named <code>on_*</code> like
+      <code>on_body</code> and <code>on_close</code>.</li>
+    </ul>
+
+    <p>
+      In libebb there are three important classes: <code>ebb_server</code>,
+      <code>ebb_connection</code>, and <code>ebb_request</code>. 
+      Each server has many peer connections. Each peer connection may have many
+      requests.
+      There are two additional classes <code>ebb_buf</code> and <code>ebb_request_parser</code>
+      which may or may not be useful.
+    </p>
+
+    <h3><code>ebb_server</code></h3>
+    <p>
+      <code>ebb_server</code> represents a single web server listening on a
+      single port. The user must allocate the structure themselves, then
+      call <code>ebb_server_init()</code> and provide a libev event loop.
+      <code>ebb_server_set_secure()</code> will make the server understand
+      HTTPS connections.
+    </p>
+
+    <p>
+      After initialized the <code>ebb_server_listen_on_port()</code> can be
+      called to open the server up to new connections. libebb does not
+      control the event loop, it is the user's responsibility to start the
+      event loop  (using <code>ev_loop()</code>) after
+      <code>ebb_server_listen_on_port()</code> is called.
+    </p>
+
+    <p>
+      To accept connections you must provide the new server with a callback
+      called <code>new_connection</code>. This callback must return an allocated
+      and initialized <code>ebb_connection</code> structure.     
+      To set this callback do
+    </p>
+
+    <pre>my_server-&gt;new_connection = my_new_connection_callback;</pre>
+
+    <p>
+      Additional documentation can be found in <code>ebb.h</code>
+    </p>
+
+    <h3><code>ebb_connection</code></h3>
+
+    <p>
+      This structure contains information and callbacks for a single client
+      connection. It is allocated and initialized through the
+      <code>new_connection</code> callback in <code>ebb_server</code>.
+      To initialize a newly allocated <code>ebb_connection</code> use
+      <code>ebb_connection_init()</code>.
+    </p>
+
+    <p>
+      After <code>ebb_connection_init()</code> is called a number of
+      callbacks can be set: <code>new_request</code>, <code>new_buf</code>,
+      <code>on_timeout</code>, and <code>on_close</code>.
+    </p>
+
+    <p>
+      When an <code>ebb_connection</code> is returned to an
+      <code>ebb_server</code>, data is immediately data is read from the
+      socket.  This data must be stored somewhere. Because libebb is
+      agnostic about allocation decisions, it passes this off to the user in
+      the form of a callback: <code>connection-&gt;new_buf</code>.  This
+      callback returns a newly allocated and initialized
+      <code>ebb_buf</code> structure.  How much libebb attempts to read from
+      the socket is determined by how large the returned
+      <code>ebb_buf</code> structure is.  Using <code>new_buf</code> is
+      optional.  By default libebb reads data into a static buffer
+      (allocated at compile time), writing over it on each read. In many
+      web server using the static buffer will be sufficent because callbacks
+      made during the parsing will buffer the data elsewhere. Providing a
+      <code>new_buf</code> callback is necessary only if you want to save
+      the raw data coming from the socket.
+    </p>
+
+    <p>
+      The <code>new_request</code> callback is called at the beginning of a
+      request. It must return a newly allocated and initialized
+      <code>ebb_request</code> structure. Because HTTP/1.1 supports <a
+        href="http://en.wikipedia.org/wiki/HTTP_persistent_connection">peristant</a>
+      connections, there may be many requests per connection.
+    </p>
+
+    <p>
+      You may access the file descriptor for the client socket inside the
+      <code>ebb_connection</code> structure. Writing the response, in valid
+      HTTP, is the user's responsibility.  Remember, requests must be
+      returned to client in the same order that they were received.
+    </p>
+
+    <p>
+      A convience function, <coe>ebb_connection_write</code>, is provided
+      which will write a single string to the peer. You may use
+      this function or you may write to the file descriptor directly.
+    </p>
+
+    <p>
+      To close a peer connection use
+      <code>ebb_connnection_schedule_close()</code>. Because SSL may require
+      some additional communication to close the connection properly, the
+      file descriptor cannot be closed immediately. The
+      <code>on_close</code> callback will be made when the peer socket is
+      finally closed. 
+      <em>Only once <code>on_close</code> is called may the
+        user free the <code>ebb_connection</code> structure.</em> 
+    </p>
+
+
+    <h3><code>ebb_request</code></h3>
+
+    <p>
+      This structure provides information about a request. For example,
+      <code>request-&gt;method == EBB_POST</code> would mean the method of
+      the request is <code>POST</code>. There are also many callbacks
+      which can be set to handle data from a request as it is parsed.
+    </p>
+
+    <p>
+      The <code>on_uri</code> callback and all other
+      <code>ebb_element_cb</code> callbacks provide pointers to request
+      data.  The annoying thing is they do not necessarily provide a
+      complete string.  This is because the reads from the socket may not
+      contain an entire request and for efficency libebb does not attempt to
+      buffer the data.  Theoretically, one might receive an
+      <code>on_uri</code> callback 10 times, each providing just a single
+      character of the request's URI.  See <code>ebb_request_parser.h</code> for
+      a full list of callbacks that you may provide. (If you don't set them,
+      they are ignored.)
+    </p>
+
+    <p>
+      The <code>on_complete</code> callback is called at the end of
+      each request.
+      <em>Only once <code>on_complete</code> is called may the
+        user free the <code>ebb_request</code> structure.</em> 
+    </p>
+
+    <h2>Example</h2>
+
+    <p>
+      A simple example is provided in <code>examples/hello_world.c</code>.
+    </p>
+    
+  </div></body>
+</html>
diff --git a/deps/libebb/ebb.c b/deps/libebb/ebb.c
new file mode 100644
index 0000000..a4c5e78
--- /dev/null
+++ b/deps/libebb/ebb.c
@@ -0,0 +1,798 @@
+/* This file is part of libebb.
+ *
+ * Copyright (c) 2008 Ryan Dahl (ry@ndahl.us)
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+ */
+#include <assert.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/tcp.h> /* TCP_NODELAY */
+#include <netinet/in.h>  /* inet_ntoa */
+#include <arpa/inet.h>   /* inet_ntoa */
+#include <unistd.h>
+#include <stdio.h>      /* perror */
+#include <errno.h>      /* perror */
+#include <stdlib.h> /* for the default methods */
+#include <ev.h>
+
+#include "ebb.h"
+#include "ebb_request_parser.h"
+#ifdef HAVE_GNUTLS
+# include <gnutls/gnutls.h>
+# include "rbtree.h" /* for session_cache */
+#endif
+
+#ifndef TRUE
+# define TRUE 1
+#endif
+#ifndef FALSE
+# define FALSE 0
+#endif 
+#ifndef MIN
+# define MIN(a,b) (a < b ? a : b)
+#endif
+
+#define error(FORMAT, ...) fprintf(stderr, "error: " FORMAT "\n", ##__VA_ARGS__)
+
+#define CONNECTION_HAS_SOMETHING_TO_WRITE (connection->to_write != NULL)
+
+static void 
+set_nonblock (int fd)
+{
+  int flags = fcntl(fd, F_GETFL, 0);
+  int r = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+  assert(0 <= r && "Setting socket non-block failed!");
+}
+
+static ssize_t 
+nosigpipe_push(void *data, const void *buf, size_t len)
+{
+  int fd = (int)data;
+  int flags = 0;
+#ifdef MSG_NOSIGNAL
+  flags = MSG_NOSIGNAL;
+#endif
+  return send(fd, buf, len, flags);
+}
+
+static void 
+close_connection(ebb_connection *connection)
+{
+#ifdef HAVE_GNUTLS
+  if(connection->server->secure)
+    ev_io_stop(connection->server->loop, &connection->handshake_watcher);
+#endif
+  ev_io_stop(connection->server->loop, &connection->read_watcher);
+  ev_io_stop(connection->server->loop, &connection->write_watcher);
+  ev_timer_stop(connection->server->loop, &connection->timeout_watcher);
+
+  if(0 > close(connection->fd))
+    error("problem closing connection fd");
+
+  connection->open = FALSE;
+
+  if(connection->on_close)
+    connection->on_close(connection);
+  /* No access to the connection past this point! 
+   * The user is allowed to free in the callback
+   */
+}
+
+#ifdef HAVE_GNUTLS
+#define GNUTLS_NEED_WRITE (gnutls_record_get_direction(connection->session) == 1)
+#define GNUTLS_NEED_READ (gnutls_record_get_direction(connection->session) == 0)
+
+#define EBB_MAX_SESSION_KEY 32
+#define EBB_MAX_SESSION_VALUE 512
+
+struct session_cache {
+  struct rbtree_node_t node;
+
+  gnutls_datum_t key;
+  gnutls_datum_t value;
+
+  char key_storage[EBB_MAX_SESSION_KEY];
+  char value_storage[EBB_MAX_SESSION_VALUE];
+};
+
+static int 
+session_cache_compare (void *left, void *right) 
+{
+  gnutls_datum_t *left_key = left;
+  gnutls_datum_t *right_key = right;
+  if(left_key->size < right_key->size)
+    return -1;
+  else if(left_key->size > right_key->size)
+    return 1;
+  else
+    return memcmp( left_key->data
+                 , right_key->data
+                 , MIN(left_key->size, right_key->size)
+                 );
+}
+
+static int
+session_cache_store(void *data, gnutls_datum_t key, gnutls_datum_t value)
+{
+  rbtree tree = data;
+
+  if( tree == NULL
+   || key.size > EBB_MAX_SESSION_KEY
+   || value.size > EBB_MAX_SESSION_VALUE
+    ) return -1;
+
+  struct session_cache *cache = gnutls_malloc(sizeof(struct session_cache));
+
+  memcpy (cache->key_storage, key.data, key.size);
+  cache->key.size = key.size;
+  cache->key.data = (void*)cache->key_storage;
+
+  memcpy (cache->value_storage, value.data, value.size);
+  cache->value.size = value.size;
+  cache->value.data = (void*)cache->value_storage;
+
+  cache->node.key = &cache->key;
+  cache->node.value = &cache;
+
+  rbtree_insert(tree, (rbtree_node)cache);
+
+  //printf("session_cache_store\n");
+
+  return 0;
+}
+
+static gnutls_datum_t
+session_cache_retrieve (void *data, gnutls_datum_t key)
+{
+  rbtree tree = data;
+  gnutls_datum_t res = { NULL, 0 };
+  struct session_cache *cache = rbtree_lookup(tree, &key);
+
+  if(cache == NULL)
+    return res;
+
+  res.size = cache->value.size;
+  res.data = gnutls_malloc (res.size);
+  if(res.data == NULL)
+    return res;
+
+  memcpy(res.data, cache->value.data, res.size);
+
+  //printf("session_cache_retrieve\n");
+
+  return res;
+}
+
+static int
+session_cache_remove (void *data, gnutls_datum_t key)
+{
+  rbtree tree = data;
+
+  if(tree == NULL)
+    return -1;
+
+  struct session_cache *cache = (struct session_cache *)rbtree_delete(tree, &key);
+  if(cache == NULL)
+    return -1;
+
+  gnutls_free(cache);
+
+  //printf("session_cache_remove\n");
+
+  return 0;
+}
+
+static void 
+on_handshake(struct ev_loop *loop ,ev_io *watcher, int revents)
+{
+  ebb_connection *connection = watcher->data;
+
+  //printf("on_handshake\n");
+
+  assert(ev_is_active(&connection->timeout_watcher));
+  assert(!ev_is_active(&connection->read_watcher));
+  assert(!ev_is_active(&connection->write_watcher));
+
+  if(EV_ERROR & revents) {
+    error("on_handshake() got error event, closing connection.n");
+    goto error;
+  }
+
+  int r = gnutls_handshake(connection->session);
+  if(r < 0) {
+    if(gnutls_error_is_fatal(r)) goto error;
+    if(r == GNUTLS_E_INTERRUPTED || r == GNUTLS_E_AGAIN)
+      ev_io_set( watcher
+               , connection->fd
+               , (GNUTLS_NEED_WRITE ? EV_WRITE : EV_READ)
+               );
+    return;
+  }
+
+  ebb_connection_reset_timeout(connection);
+  ev_io_stop(loop, watcher);
+
+  ev_io_start(loop, &connection->read_watcher);
+  if(CONNECTION_HAS_SOMETHING_TO_WRITE)
+    ev_io_start(loop, &connection->write_watcher);
+
+  return;
+error:
+  close_connection(connection);
+}
+
+#endif /* HAVE_GNUTLS */
+
+
+/* Internal callback 
+ * called by connection->timeout_watcher
+ */
+static void 
+on_timeout(struct ev_loop *loop, ev_timer *watcher, int revents)
+{
+  ebb_connection *connection = watcher->data;
+
+  assert(watcher == &connection->timeout_watcher);
+
+  //printf("on_timeout\n");
+
+  /* if on_timeout returns true, we don't time out */
+  if(connection->on_timeout) {
+    int r = connection->on_timeout(connection);
+
+    if(r == EBB_AGAIN) {
+      ebb_connection_reset_timeout(connection);
+      return;
+    }
+  }
+
+  ebb_connection_schedule_close(connection);
+}
+
+/* Internal callback 
+ * called by connection->read_watcher
+ */
+static void 
+on_readable(struct ev_loop *loop, ev_io *watcher, int revents)
+{
+  ebb_connection *connection = watcher->data;
+  char recv_buffer[TCP_MAXWIN];
+  ssize_t recved;
+
+  //printf("on_readable\n");
+  // TODO -- why is this broken?
+  //assert(ev_is_active(&connection->timeout_watcher));
+  assert(watcher == &connection->read_watcher);
+
+  if(EV_ERROR & revents) {
+    error("on_readable() got error event, closing connection.");
+    goto error;
+  }
+
+#ifdef HAVE_GNUTLS
+  assert(!ev_is_active(&connection->handshake_watcher));
+
+  if(connection->server->secure) {
+    recved = gnutls_record_recv( connection->session
+                               , recv_buffer
+                               , TCP_MAXWIN
+                               );
+    if(recved <= 0) {
+      if(gnutls_error_is_fatal(recved)) goto error;
+      if( (recved == GNUTLS_E_INTERRUPTED || recved == GNUTLS_E_AGAIN)
+       && GNUTLS_NEED_WRITE
+        ) ev_io_start(loop, &connection->write_watcher);
+      return; 
+    } 
+  } else {
+#endif /* HAVE_GNUTLS */
+
+    recved = recv(connection->fd, recv_buffer, TCP_MAXWIN, 0);
+    if(recved <= 0) goto error;
+
+#ifdef HAVE_GNUTLS
+  }
+#endif /* HAVE_GNUTLS */
+
+  ebb_connection_reset_timeout(connection);
+
+  ebb_request_parser_execute(&connection->parser, recv_buffer, recved);
+
+  /* parse error? just drop the client. screw the 400 response */
+  if(ebb_request_parser_has_error(&connection->parser)) goto error;
+  return;
+error:
+  ebb_connection_schedule_close(connection);
+}
+
+/* Internal callback 
+ * called by connection->write_watcher
+ */
+static void 
+on_writable(struct ev_loop *loop, ev_io *watcher, int revents)
+{
+  ebb_connection *connection = watcher->data;
+  ssize_t sent;
+  
+  //printf("on_writable\n");
+
+  assert(CONNECTION_HAS_SOMETHING_TO_WRITE);
+  assert(connection->written <= connection->to_write_len);
+  // TODO -- why is this broken?
+  //assert(ev_is_active(&connection->timeout_watcher));
+  assert(watcher == &connection->write_watcher);
+
+  if(connection->to_write == 0)
+    goto stop_writing;
+
+#ifdef HAVE_GNUTLS
+  assert(!ev_is_active(&connection->handshake_watcher));
+
+  if(connection->server->secure) {
+    sent = gnutls_record_send( connection->session
+                             , connection->to_write + connection->written
+                             , connection->to_write_len - connection->written
+                             ); 
+    if(sent < 0) {
+      if(gnutls_error_is_fatal(sent)) goto error;
+      if( (sent == GNUTLS_E_INTERRUPTED || sent == GNUTLS_E_AGAIN)
+       && GNUTLS_NEED_READ
+        ) ev_io_stop(loop, watcher);
+      return; 
+    }
+  } else {
+#endif /* HAVE_GNUTLS */
+
+    sent = nosigpipe_push( (void*)connection->fd
+                         , connection->to_write + connection->written
+                         , connection->to_write_len - connection->written
+                         );
+    if(sent < 0) goto error;
+    if(sent == 0) return;
+
+#ifdef HAVE_GNUTLS
+  }
+#endif /* HAVE_GNUTLS */
+
+  ebb_connection_reset_timeout(connection);
+
+  connection->written += sent;
+
+  if(connection->written == connection->to_write_len) {
+    goto stop_writing;
+  }
+  return;
+stop_writing:
+  ev_io_stop(loop, watcher);
+  connection->to_write = NULL;
+
+  if(connection->after_write_cb)
+    connection->after_write_cb(connection);
+  return;
+error:
+  error("close connection on write.");
+  ebb_connection_schedule_close(connection);
+}
+
+#ifdef HAVE_GNUTLS
+
+static void 
+on_goodbye_tls(struct ev_loop *loop, ev_io *watcher, int revents)
+{
+  ebb_connection *connection = watcher->data;
+  assert(watcher == &connection->goodbye_tls_watcher);
+
+  if(EV_ERROR & revents) {
+    error("on_goodbye() got error event, closing connection.");
+    goto die;
+  }
+
+  int r = gnutls_bye(connection->session, GNUTLS_SHUT_RDWR);
+  if(r < 0) {
+    if(gnutls_error_is_fatal(r)) goto die;
+    if(r == GNUTLS_E_INTERRUPTED || r == GNUTLS_E_AGAIN)
+      ev_io_set( watcher
+               , connection->fd
+               , (GNUTLS_NEED_WRITE ? EV_WRITE : EV_READ)
+               );
+    return;
+  }
+
+die:
+  ev_io_stop(loop, watcher);
+  if(connection->session) 
+    gnutls_deinit(connection->session);
+  close_connection(connection);
+}
+#endif /* HAVE_GNUTLS*/
+
+static void 
+on_goodbye(struct ev_loop *loop, ev_timer *watcher, int revents)
+{
+  ebb_connection *connection = watcher->data;
+  assert(watcher == &connection->goodbye_watcher);
+
+  close_connection(connection);
+}
+
+
+static ebb_request* 
+new_request_wrapper(void *data)
+{
+  ebb_connection *connection = data;
+  if(connection->new_request)
+    return connection->new_request(connection);
+  return NULL;
+}
+
+/* Internal callback 
+ * Called by server->connection_watcher.
+ */
+static void 
+on_connection(struct ev_loop *loop, ev_io *watcher, int revents)
+{
+  ebb_server *server = watcher->data;
+
+  //printf("on connection!\n");
+
+  assert(server->listening);
+  assert(server->loop == loop);
+  assert(&server->connection_watcher == watcher);
+  
+  if(EV_ERROR & revents) {
+    error("on_connection() got error event, closing server.");
+    ebb_server_unlisten(server);
+    return;
+  }
+  
+  struct sockaddr_in addr; // connector's address information
+  socklen_t addr_len = sizeof(addr); 
+  int fd = accept( server->fd
+                 , (struct sockaddr*) & addr
+                 , & addr_len
+                 );
+  if(fd < 0) {
+    perror("accept()");
+    return;
+  }
+
+  ebb_connection *connection = NULL;
+  if(server->new_connection)
+    connection = server->new_connection(server, &addr);
+  if(connection == NULL) {
+    close(fd);
+    return;
+  } 
+  
+  set_nonblock(fd);
+  connection->fd = fd;
+  connection->open = TRUE;
+  connection->server = server;
+  memcpy(&connection->sockaddr, &addr, addr_len);
+  if(server->port[0] != '\0')
+    connection->ip = inet_ntoa(connection->sockaddr.sin_addr);  
+
+#ifdef SO_NOSIGPIPE
+  int arg = 1;
+  setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &arg, sizeof(int));
+#endif
+
+#ifdef HAVE_GNUTLS
+  if(server->secure) {
+    gnutls_init(&connection->session, GNUTLS_SERVER);
+    gnutls_transport_set_lowat(connection->session, 0); 
+    gnutls_set_default_priority(connection->session);
+    gnutls_credentials_set(connection->session, GNUTLS_CRD_CERTIFICATE, connection->server->credentials);
+
+    gnutls_transport_set_ptr(connection->session, (gnutls_transport_ptr) fd); 
+    gnutls_transport_set_push_function(connection->session, nosigpipe_push);
+
+    gnutls_db_set_ptr (connection->session, &server->session_cache);
+    gnutls_db_set_store_function (connection->session, session_cache_store);
+    gnutls_db_set_retrieve_function (connection->session, session_cache_retrieve);
+    gnutls_db_set_remove_function (connection->session, session_cache_remove);
+  }
+
+  ev_io_set(&connection->handshake_watcher, connection->fd, EV_READ | EV_WRITE);
+#endif /* HAVE_GNUTLS */
+
+  /* Note: not starting the write watcher until there is data to be written */
+  ev_io_set(&connection->write_watcher, connection->fd, EV_WRITE);
+  ev_io_set(&connection->read_watcher, connection->fd, EV_READ);
+  /* XXX: seperate error watcher? */
+
+  ev_timer_again(loop, &connection->timeout_watcher);
+
+#ifdef HAVE_GNUTLS
+  if(server->secure) {
+    ev_io_start(loop, &connection->handshake_watcher);
+    return;
+  }
+#endif
+
+  ev_io_start(loop, &connection->read_watcher);
+}
+
+/**
+ * Begin the server listening on a file descriptor.  This DOES NOT start the
+ * event loop.  Start the event loop after making this call.
+ */
+int 
+ebb_server_listen_on_fd(ebb_server *server, const int fd)
+{
+  assert(server->listening == FALSE);
+
+  if (listen(fd, EBB_MAX_CONNECTIONS) < 0) {
+    perror("listen()");
+    return -1;
+  }
+  
+  set_nonblock(fd); /* XXX superfluous? */
+  
+  server->fd = fd;
+  server->listening = TRUE;
+  
+  ev_io_set (&server->connection_watcher, server->fd, EV_READ);
+  ev_io_start (server->loop, &server->connection_watcher);
+  
+  return server->fd;
+}
+
+
+/**
+ * Begin the server listening on a file descriptor This DOES NOT start the
+ * event loop. Start the event loop after making this call.
+ */
+int 
+ebb_server_listen_on_port(ebb_server *server, const int port)
+{
+  int fd = -1;
+  struct linger ling = {0, 0};
+  struct sockaddr_in addr;
+  int flags = 1;
+  
+  if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+    perror("socket()");
+    goto error;
+  }
+  
+  flags = 1;
+  setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
+  setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
+  setsockopt(fd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
+
+  /* XXX: Sending single byte chunks in a response body? Perhaps there is a
+   * need to enable the Nagel algorithm dynamically. For now disabling.
+   */
+  setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags));
+  
+  /* the memset call clears nonstandard fields in some impementations that
+   * otherwise mess things up.
+   */
+  memset(&addr, 0, sizeof(addr));
+  
+  addr.sin_family = AF_INET;
+  addr.sin_port = htons(port);
+  addr.sin_addr.s_addr = htonl(INADDR_ANY);
+  
+  if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+    perror("bind()");
+    goto error;
+  }
+  
+  int ret = ebb_server_listen_on_fd(server, fd);
+  if (ret >= 0) {
+    sprintf(server->port, "%d", port);
+  }
+  return ret;
+error:
+  if(fd > 0) close(fd);
+  return -1;
+}
+
+/**
+ * Stops the server. Will not accept new connections.  Does not drop
+ * existing connections.
+ */
+void 
+ebb_server_unlisten(ebb_server *server)
+{
+  if(server->listening) {
+    ev_io_stop(server->loop, &server->connection_watcher);
+    close(server->fd);
+    server->port[0] = '\0';
+    server->listening = FALSE;
+  }
+}
+
+/**
+ * Initialize an ebb_server structure.  After calling ebb_server_init set
+ * the callback server->new_connection and, optionally, callback data
+ * server->data.  The new connection MUST be initialized with
+ * ebb_connection_init before returning it to the server.
+ *
+ * @param server the server to initialize
+ * @param loop a libev loop
+ */
+void 
+ebb_server_init(ebb_server *server, struct ev_loop *loop)
+{
+  server->loop = loop;
+  server->listening = FALSE;
+  server->port[0] = '\0';
+  server->fd = -1;
+  server->connection_watcher.data = server;
+  ev_init (&server->connection_watcher, on_connection);
+  server->secure = FALSE;
+
+#ifdef HAVE_GNUTLS
+  rbtree_init(&server->session_cache, session_cache_compare);
+  server->credentials = NULL;
+#endif
+
+  server->new_connection = NULL;
+  server->data = NULL;
+}
+
+
+#ifdef HAVE_GNUTLS
+/* similar to server_init. 
+ *
+ * the user of secure server might want to set additional callbacks from
+ * GNUTLS. In particular 
+ * gnutls_global_set_mem_functions() 
+ * gnutls_global_set_log_function()
+ * Also see the note above ebb_connection_init() about setting gnutls cache
+ * access functions
+ *
+ * cert_file: the filename of a PEM certificate file
+ *
+ * key_file: the filename of a private key. Currently only PKCS-1 encoded
+ * RSA and DSA private keys are accepted. 
+ */
+int 
+ebb_server_set_secure (ebb_server *server, const char *cert_file, const char *key_file)
+{
+  server->secure = TRUE;
+  gnutls_global_init();
+  gnutls_certificate_allocate_credentials(&server->credentials);
+  /* todo gnutls_certificate_free_credentials */
+  int r = gnutls_certificate_set_x509_key_file( server->credentials
+                                              , cert_file
+                                              , key_file
+                                              , GNUTLS_X509_FMT_PEM
+                                              );
+  if(r < 0) {
+    error("loading certificates");
+    return -1;
+  }
+  return 1;
+}
+#endif /* HAVE_GNUTLS */
+
+/**
+ * Initialize an ebb_connection structure. After calling this function you
+ * must setup callbacks for the different actions the server can take. See
+ * server.h for which callbacks are availible. 
+ * 
+ * This should be called immediately after allocating space for a new
+ * ebb_connection structure. Most likely, this will only be called within
+ * the ebb_server->new_connection callback which you supply. 
+ *
+ * If using SSL do consider setting
+ *   gnutls_db_set_retrieve_function (connection->session, _);
+ *   gnutls_db_set_remove_function (connection->session, _);
+ *   gnutls_db_set_store_function (connection->session, _);
+ *   gnutls_db_set_ptr (connection->session, _);
+ * To provide a better means of storing SSL session caches. libebb provides
+ * only a simple default implementation. 
+ *
+ * @param connection the connection to initialize
+ * @param timeout    the timeout in seconds
+ */
+void 
+ebb_connection_init(ebb_connection *connection)
+{
+  connection->fd = -1;
+  connection->server = NULL;
+  connection->ip = NULL;
+  connection->open = FALSE;
+
+  ebb_request_parser_init( &connection->parser );
+  connection->parser.data = connection;
+  connection->parser.new_request = new_request_wrapper;
+  
+  ev_init (&connection->write_watcher, on_writable);
+  connection->write_watcher.data = connection;
+  connection->to_write = NULL;
+
+  ev_init(&connection->read_watcher, on_readable);
+  connection->read_watcher.data = connection;
+
+#ifdef HAVE_GNUTLS
+  connection->handshake_watcher.data = connection;
+  ev_init(&connection->handshake_watcher, on_handshake);
+
+  ev_init(&connection->goodbye_tls_watcher, on_goodbye_tls);
+  connection->goodbye_tls_watcher.data = connection;
+
+  connection->session = NULL;
+#endif /* HAVE_GNUTLS */
+
+  ev_timer_init(&connection->goodbye_watcher, on_goodbye, 0., 0.);
+  connection->goodbye_watcher.data = connection;  
+
+  ev_timer_init(&connection->timeout_watcher, on_timeout, 0., EBB_DEFAULT_TIMEOUT);
+  connection->timeout_watcher.data = connection;  
+
+  connection->new_request = NULL;
+  connection->on_timeout = NULL;
+  connection->on_close = NULL;
+  connection->data = NULL;
+}
+
+void 
+ebb_connection_schedule_close (ebb_connection *connection)
+{
+#ifdef HAVE_GNUTLS
+  if(connection->server->secure) {
+    ev_io_set(&connection->goodbye_tls_watcher, connection->fd, EV_READ | EV_WRITE);
+    ev_io_start(connection->server->loop, &connection->goodbye_tls_watcher);
+    return;
+  }
+#endif
+  ev_timer_start(connection->server->loop, &connection->goodbye_watcher);
+}
+
+/* 
+ * Resets the timeout to stay alive for another connection->timeout seconds
+ */
+void 
+ebb_connection_reset_timeout(ebb_connection *connection)
+{
+  ev_timer_again(connection->server->loop, &connection->timeout_watcher);
+}
+
+/**
+ * Writes a string to the socket. This is actually sets a watcher
+ * which may take multiple iterations to write the entire string.
+ *
+ * This can only be called once at a time. If you call it again
+ * while the connection is writing another buffer the ebb_connection_write
+ * will return FALSE and ignore the request.
+ */
+int 
+ebb_connection_write (ebb_connection *connection, const char *buf, size_t len, ebb_after_write_cb cb)
+{
+  if(ev_is_active(&connection->write_watcher))
+    return FALSE;
+  assert(!CONNECTION_HAS_SOMETHING_TO_WRITE);
+  connection->to_write = buf;
+  connection->to_write_len = len;
+  connection->written = 0;
+  connection->after_write_cb = cb;
+  ev_io_start(connection->server->loop, &connection->write_watcher);
+  return TRUE;
+}
+
diff --git a/deps/libebb/ebb.h b/deps/libebb/ebb.h
new file mode 100644
index 0000000..e5e90b4
--- /dev/null
+++ b/deps/libebb/ebb.h
@@ -0,0 +1,120 @@
+/* This file is part of libebb.
+ *
+ * Copyright (c) 2008 Ryan Dahl (ry@ndahl.us)
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+ */
+#ifndef EBB_H
+#define EBB_H
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <ev.h>
+#ifdef HAVE_GNUTLS
+# include <gnutls/gnutls.h>
+# include "rbtree.h" /* for ebb_server.session_cache */
+#endif 
+#include "ebb_request_parser.h"
+
+#define EBB_MAX_CONNECTIONS 1024
+#define EBB_DEFAULT_TIMEOUT 30.0
+
+#define EBB_AGAIN 0
+#define EBB_STOP 1
+
+typedef struct ebb_server     ebb_server;
+typedef struct ebb_connection ebb_connection;
+typedef void (*ebb_after_write_cb) (ebb_connection *connection); 
+typedef void (*ebb_connection_cb)(ebb_connection *connection, void *data);
+
+struct ebb_server {
+  int fd;                                       /* ro */
+  struct sockaddr_in sockaddr;                  /* ro */
+  socklen_t socklen;                            /* ro */
+  char port[6];                                 /* ro */
+  struct ev_loop *loop;                         /* ro */
+  unsigned listening:1;                         /* ro */
+  unsigned secure:1;                            /* ro */
+#ifdef HAVE_GNUTLS
+  gnutls_certificate_credentials_t credentials; /* private */
+  struct rbtree_t session_cache;                /* private */
+#endif
+  ev_io connection_watcher;                     /* private */
+
+  /* Public */
+
+  /* Allocates and initializes an ebb_connection.  NULL by default. */
+  ebb_connection* (*new_connection) (ebb_server*, struct sockaddr_in*);
+
+  void *data;
+};
+
+struct ebb_connection {
+  int fd;                      /* ro */
+  struct sockaddr_in sockaddr; /* ro */
+  socklen_t socklen;           /* ro */ 
+  ebb_server *server;          /* ro */
+  char *ip;                    /* ro */
+  unsigned open:1;             /* ro */
+
+  const char *to_write;              /* ro */
+  size_t to_write_len;               /* ro */
+  size_t written;                    /* ro */ 
+  ebb_after_write_cb after_write_cb; /* ro */
+
+  ebb_request_parser parser;   /* private */
+  ev_io write_watcher;         /* private */
+  ev_io read_watcher;          /* private */
+  ev_timer timeout_watcher;    /* private */
+  ev_timer goodbye_watcher;    /* private */
+#ifdef HAVE_GNUTLS
+  ev_io handshake_watcher;     /* private */
+  gnutls_session_t session;    /* private */
+  ev_io goodbye_tls_watcher;       /* private */
+#endif
+
+  /* Public */
+
+  ebb_request* (*new_request) (ebb_connection*); 
+
+  /* Returns EBB_STOP or EBB_AGAIN. NULL by default.  */
+  int (*on_timeout) (ebb_connection*); 
+
+  void (*on_close) (ebb_connection*); 
+
+  void *data;
+};
+
+void ebb_server_init (ebb_server *server, struct ev_loop *loop);
+#ifdef HAVE_GNUTLS
+int ebb_server_set_secure (ebb_server *server, const char *cert_file, 
+                           const char *key_file);
+#endif
+int ebb_server_listen_on_port (ebb_server *server, const int port);
+int ebb_server_listen_on_fd (ebb_server *server, const int sfd);
+void ebb_server_unlisten (ebb_server *server);
+
+void ebb_connection_init (ebb_connection *);
+void ebb_connection_schedule_close (ebb_connection *);
+void ebb_connection_reset_timeout (ebb_connection *);
+int ebb_connection_write (ebb_connection *, const char *buf, size_t len, ebb_after_write_cb);
+
+#endif
diff --git a/deps/libebb/ebb_request_parser.h b/deps/libebb/ebb_request_parser.h
new file mode 100644
index 0000000..93d502f
--- /dev/null
+++ b/deps/libebb/ebb_request_parser.h
@@ -0,0 +1,117 @@
+/* This file is part of the libebb web server library
+ *
+ * Copyright (c) 2008 Ryan Dahl (ry@ndahl.us)
+ * All rights reserved.
+ *
+ * This parser is based on code from Zed Shaw's Mongrel.
+ * Copyright (c) 2005 Zed A. Shaw
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+ */
+#ifndef ebb_request_parser_h
+#define ebb_request_parser_h
+#ifdef __cplusplus
+extern "C" {
+#endif 
+
+
+#include <sys/types.h> 
+
+typedef struct ebb_request ebb_request;
+typedef struct ebb_request_parser  ebb_request_parser;
+typedef void (*ebb_header_cb)(ebb_request*, const char *at, size_t length, int header_index);
+typedef void (*ebb_element_cb)(ebb_request*, const char *at, size_t length);
+
+#define EBB_MAX_MULTIPART_BOUNDARY_LEN 20
+
+/* HTTP Methods */
+#define EBB_COPY       0x00000001
+#define EBB_DELETE     0x00000002
+#define EBB_GET        0x00000004
+#define EBB_HEAD       0x00000008
+#define EBB_LOCK       0x00000010
+#define EBB_MKCOL      0x00000020
+#define EBB_MOVE       0x00000040
+#define EBB_OPTIONS    0x00000080
+#define EBB_POST       0x00000100
+#define EBB_PROPFIND   0x00000200
+#define EBB_PROPPATCH  0x00000400
+#define EBB_PUT        0x00000800
+#define EBB_TRACE      0x00001000
+#define EBB_UNLOCK     0x00002000
+
+/* Transfer Encodings */
+#define EBB_IDENTITY   0x00000001
+#define EBB_CHUNKED    0x00000002
+
+struct ebb_request {
+  int method;
+  int transfer_encoding;         /* ro */
+  int expect_continue;               /* ro */
+  unsigned int version_major;        /* ro */
+  unsigned int version_minor;        /* ro */
+  int number_of_headers;             /* ro */
+  int keep_alive;                    /* private - use ebb_request_should_keep_alive */
+  size_t content_length;             /* ro - 0 if unknown */
+  size_t body_read;                  /* ro */
+
+  /* Public  - ordered list of callbacks */
+  ebb_element_cb on_path;
+  ebb_element_cb on_query_string;
+  ebb_element_cb on_uri;
+  ebb_element_cb on_fragment;
+  ebb_header_cb  on_header_field;
+  ebb_header_cb  on_header_value;
+  void (*on_headers_complete)(ebb_request *);
+  ebb_element_cb on_body;
+  void (*on_complete)(ebb_request *);
+  void *data;
+};
+
+struct ebb_request_parser {
+  int cs;                           /* private */
+  size_t chunk_size;                /* private */
+  unsigned eating:1;                /* private */
+  ebb_request *current_request;     /* ro */
+  const char *header_field_mark; 
+  const char *header_value_mark; 
+  const char *query_string_mark; 
+  const char *path_mark; 
+  const char *uri_mark; 
+  const char *fragment_mark; 
+
+  /* Public */
+  ebb_request* (*new_request)(void*);
+  void *data;
+};
+
+void ebb_request_parser_init(ebb_request_parser *parser);
+size_t ebb_request_parser_execute(ebb_request_parser *parser, const char *data, size_t len);
+int ebb_request_parser_has_error(ebb_request_parser *parser);
+int ebb_request_parser_is_finished(ebb_request_parser *parser);
+void ebb_request_init(ebb_request *);
+int ebb_request_should_keep_alive(ebb_request *request);
+#define ebb_request_has_body(request) \
+  (request->transfer_encoding == EBB_CHUNKED || request->content_length > 0 )
+
+#ifdef __cplusplus
+}
+#endif 
+#endif
diff --git a/deps/libebb/ebb_request_parser.rl b/deps/libebb/ebb_request_parser.rl
new file mode 100644
index 0000000..63e36a8
--- /dev/null
+++ b/deps/libebb/ebb_request_parser.rl
@@ -0,0 +1,413 @@
+/* This file is part of the libebb web server library
+ *
+ * Copyright (c) 2008 Ryan Dahl (ry@ndahl.us)
+ * All rights reserved.
+ *
+ * This parser is based on code from Zed Shaw's Mongrel.
+ * Copyright (c) 2005 Zed A. Shaw
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+ */
+#include "ebb_request_parser.h"
+
+#include <stdio.h>
+#include <assert.h>
+
+static int unhex[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+                     ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+                     ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+                     , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
+                     ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
+                     ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+                     ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
+                     ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+                     };
+#define TRUE 1
+#define FALSE 0
+#define MIN(a,b) (a < b ? a : b)
+
+#define REMAINING (pe - p)
+#define CURRENT (parser->current_request)
+#define CONTENT_LENGTH (parser->current_request->content_length)
+#define CALLBACK(FOR)                               \
+  if(parser->FOR##_mark && CURRENT->on_##FOR) {     \
+    CURRENT->on_##FOR( CURRENT                      \
+                , parser->FOR##_mark                \
+                , p - parser->FOR##_mark            \
+                );                                  \
+ }
+#define HEADER_CALLBACK(FOR)                        \
+  if(parser->FOR##_mark && CURRENT->on_##FOR) {     \
+    CURRENT->on_##FOR( CURRENT                      \
+                , parser->FOR##_mark                \
+                , p - parser->FOR##_mark            \
+                , CURRENT->number_of_headers        \
+                );                                  \
+ }
+#define END_REQUEST                        \
+    if(CURRENT->on_complete)               \
+      CURRENT->on_complete(CURRENT);       \
+    CURRENT = NULL;
+
+
+%%{
+  machine ebb_request_parser;
+
+  action mark_header_field   { parser->header_field_mark   = p; }
+  action mark_header_value   { parser->header_value_mark   = p; }
+  action mark_fragment       { parser->fragment_mark       = p; }
+  action mark_query_string   { parser->query_string_mark   = p; }
+  action mark_request_path   { parser->path_mark           = p; }
+  action mark_request_uri    { parser->uri_mark            = p; }
+
+  action write_field { 
+    HEADER_CALLBACK(header_field);
+    parser->header_field_mark = NULL;
+  }
+
+  action write_value {
+    HEADER_CALLBACK(header_value);
+    parser->header_value_mark = NULL;
+  }
+
+  action request_uri { 
+    CALLBACK(uri);
+    parser->uri_mark = NULL;
+  }
+
+  action fragment { 
+    CALLBACK(fragment);
+    parser->fragment_mark = NULL;
+  }
+
+  action query_string { 
+    CALLBACK(query_string);
+    parser->query_string_mark = NULL;
+  }
+
+  action request_path {
+    CALLBACK(path);
+    parser->path_mark = NULL;
+  }
+
+  action content_length {
+    CURRENT->content_length *= 10;
+    CURRENT->content_length += *p - '0';
+  }
+
+  action use_identity_encoding { CURRENT->transfer_encoding = EBB_IDENTITY; }
+  action use_chunked_encoding { CURRENT->transfer_encoding = EBB_CHUNKED; }
+
+  action set_keep_alive { CURRENT->keep_alive = TRUE; }
+  action set_not_keep_alive { CURRENT->keep_alive = FALSE; }
+
+  action expect_continue {
+    CURRENT->expect_continue = TRUE;
+  }
+
+  action trailer {
+    /* not implemenetd yet. (do requests even have trailing headers?) */
+  }
+
+  action version_major {
+    CURRENT->version_major *= 10;
+    CURRENT->version_major += *p - '0';
+  }
+
+  action version_minor {
+    CURRENT->version_minor *= 10;
+    CURRENT->version_minor += *p - '0';
+  }
+
+  action end_header_line {
+    CURRENT->number_of_headers++;
+  }
+
+  action end_headers {
+    if(CURRENT->on_headers_complete)
+      CURRENT->on_headers_complete(CURRENT);
+  }
+
+  action add_to_chunk_size {
+    parser->chunk_size *= 16;
+    parser->chunk_size += unhex[(int)*p];
+  }
+
+  action skip_chunk_data {
+    skip_body(&p, parser, MIN(parser->chunk_size, REMAINING));
+    fhold; 
+    if(parser->chunk_size > REMAINING) {
+      fbreak;
+    } else {
+      fgoto chunk_end; 
+    }
+  }
+
+  action end_chunked_body {
+    END_REQUEST;
+    fnext main;
+  }
+
+  action start_req {
+    assert(CURRENT == NULL);
+    CURRENT = parser->new_request(parser->data);
+  }
+
+  action body_logic {
+    if(CURRENT->transfer_encoding == EBB_CHUNKED) {
+      fnext ChunkedBody;
+    } else {
+      /* this is pretty stupid. i'd prefer to combine this with skip_chunk_data */
+      parser->chunk_size = CURRENT->content_length;
+      p += 1;  
+      skip_body(&p, parser, MIN(REMAINING, CURRENT->content_length));
+      fhold;
+      if(parser->chunk_size > REMAINING) {
+        fbreak;
+      } 
+    }
+  }
+
+#
+##
+###
+#### HTTP/1.1 STATE MACHINE
+###
+##   RequestHeaders and character types are from
+#    Zed Shaw's beautiful Mongrel parser.
+
+  CRLF = "\r\n";
+
+# character types
+  CTL = (cntrl | 127);
+  safe = ("$" | "-" | "_" | ".");
+  extra = ("!" | "*" | "'" | "(" | ")" | ",");
+  reserved = (";" | "/" | "?" | ":" | "@" | "&" | "=" | "+");
+  unsafe = (CTL | " " | "\"" | "#" | "%" | "<" | ">");
+  national = any -- (alpha | digit | reserved | extra | safe | unsafe);
+  unreserved = (alpha | digit | safe | extra | national);
+  escape = ("%" xdigit xdigit);
+  uchar = (unreserved | escape);
+  pchar = (uchar | ":" | "@" | "&" | "=" | "+");
+  tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\"" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t");
+
+# elements
+  token = (ascii -- (CTL | tspecials));
+  quote = "\"";
+#  qdtext = token -- "\""; 
+#  quoted_pair = "\" ascii;
+#  quoted_string = "\"" (qdtext | quoted_pair )* "\"";
+
+#  headers
+
+  Method = ( "COPY"      %{ CURRENT->method = EBB_COPY;      }
+           | "DELETE"    %{ CURRENT->method = EBB_DELETE;    }
+           | "GET"       %{ CURRENT->method = EBB_GET;       }
+           | "HEAD"      %{ CURRENT->method = EBB_HEAD;      }
+           | "LOCK"      %{ CURRENT->method = EBB_LOCK;      }
+           | "MKCOL"     %{ CURRENT->method = EBB_MKCOL;     }
+           | "MOVE"      %{ CURRENT->method = EBB_MOVE;      }
+           | "OPTIONS"   %{ CURRENT->method = EBB_OPTIONS;   }
+           | "POST"      %{ CURRENT->method = EBB_POST;      }
+           | "PROPFIND"  %{ CURRENT->method = EBB_PROPFIND;  }
+           | "PROPPATCH" %{ CURRENT->method = EBB_PROPPATCH; }
+           | "PUT"       %{ CURRENT->method = EBB_PUT;       }
+           | "TRACE"     %{ CURRENT->method = EBB_TRACE;     }
+           | "UNLOCK"    %{ CURRENT->method = EBB_UNLOCK;    }
+           ); # Not allowing extension methods
+
+  HTTP_Version = "HTTP/" digit+ $version_major "." digit+ $version_minor;
+
+  scheme = ( alpha | digit | "+" | "-" | "." )* ;
+  absolute_uri = (scheme ":" (uchar | reserved )*);
+  path = ( pchar+ ( "/" pchar* )* ) ;
+  query = ( uchar | reserved )* >mark_query_string %query_string ;
+  param = ( pchar | "/" )* ;
+  params = ( param ( ";" param )* ) ;
+  rel_path = ( path? (";" params)? ) ;
+  absolute_path = ( "/"+ rel_path ) >mark_request_path %request_path ("?" query)?;
+  Request_URI = ( "*" | absolute_uri | absolute_path ) >mark_request_uri %request_uri;
+  Fragment = ( uchar | reserved )* >mark_fragment %fragment;
+
+  field_name = ( token -- ":" )+;
+  Field_Name = field_name >mark_header_field %write_field;
+
+  field_value = ((any - " ") any*)?;
+  Field_Value = field_value >mark_header_value %write_value;
+
+  hsep = ":" " "*;
+  header = (field_name hsep field_value) :> CRLF;
+  Header = ( ("Content-Length"i hsep digit+ $content_length)
+           | ("Connection"i hsep 
+               ( "Keep-Alive"i %set_keep_alive
+               | "close"i %set_not_keep_alive
+               )
+             )
+           | ("Transfer-Encoding"i %use_chunked_encoding hsep "identity" %use_identity_encoding)
+         # | ("Expect"i hsep "100-continue"i %expect_continue)
+         # | ("Trailer"i hsep field_value %trailer)
+           | (Field_Name hsep Field_Value)
+           ) :> CRLF;
+
+  Request_Line = ( Method " " Request_URI ("#" Fragment)? " " HTTP_Version CRLF ) ;
+  RequestHeader = Request_Line (Header %end_header_line)* :> CRLF @end_headers;
+
+# chunked message
+  trailing_headers = header*;
+  #chunk_ext_val   = token | quoted_string;
+  chunk_ext_val = token*;
+  chunk_ext_name = token*;
+  chunk_extension = ( ";" " "* chunk_ext_name ("=" chunk_ext_val)? )*;
+  last_chunk = "0"+ chunk_extension CRLF;
+  chunk_size = (xdigit* [1-9a-fA-F] xdigit*) $add_to_chunk_size;
+  chunk_end  = CRLF;
+  chunk_body = any >skip_chunk_data;
+  chunk_begin = chunk_size chunk_extension CRLF;
+  chunk = chunk_begin chunk_body chunk_end;
+  ChunkedBody := chunk* last_chunk trailing_headers CRLF @end_chunked_body;
+
+  Request = RequestHeader >start_req @body_logic;
+
+  main := Request*; # sequence of requests (for keep-alive)
+}%%
+
+%% write data;
+
+static void
+skip_body(const char **p, ebb_request_parser *parser, size_t nskip) {
+  if(CURRENT->on_body && nskip > 0) {
+    CURRENT->on_body(CURRENT, *p, nskip);
+  }
+  CURRENT->body_read += nskip;
+  parser->chunk_size -= nskip;
+  *p += nskip;
+  if(0 == parser->chunk_size) {
+    parser->eating = FALSE;
+    if(CURRENT->transfer_encoding == EBB_IDENTITY) {
+      END_REQUEST;
+    }
+  } else {
+    parser->eating = TRUE;
+  }
+}
+
+void ebb_request_parser_init(ebb_request_parser *parser) 
+{
+  int cs = 0;
+  %% write init;
+  parser->cs = cs;
+
+  parser->chunk_size = 0;
+  parser->eating = 0;
+  
+  parser->current_request = NULL;
+
+  parser->header_field_mark = parser->header_value_mark   = 
+  parser->query_string_mark = parser->path_mark           = 
+  parser->uri_mark          = parser->fragment_mark       = NULL;
+
+  parser->new_request = NULL;
+}
+
+
+/** exec **/
+size_t ebb_request_parser_execute(ebb_request_parser *parser, const char *buffer, size_t len)
+{
+  const char *p, *pe;
+  int cs = parser->cs;
+
+  assert(parser->new_request && "undefined callback");
+
+  p = buffer;
+  pe = buffer+len;
+
+  if(0 < parser->chunk_size && parser->eating) {
+    /* eat body */
+    size_t eat = MIN(len, parser->chunk_size);
+    skip_body(&p, parser, eat);
+  } 
+
+  if(parser->header_field_mark)   parser->header_field_mark   = buffer;
+  if(parser->header_value_mark)   parser->header_value_mark   = buffer;
+  if(parser->fragment_mark)       parser->fragment_mark       = buffer;
+  if(parser->query_string_mark)   parser->query_string_mark   = buffer;
+  if(parser->path_mark)           parser->path_mark           = buffer;
+  if(parser->uri_mark)            parser->uri_mark            = buffer;
+
+  %% write exec;
+
+  parser->cs = cs;
+
+  HEADER_CALLBACK(header_field);
+  HEADER_CALLBACK(header_value);
+  CALLBACK(fragment);
+  CALLBACK(query_string);
+  CALLBACK(path);
+  CALLBACK(uri);
+
+  assert(p <= pe && "buffer overflow after parsing execute");
+
+  return(p - buffer);
+}
+
+int ebb_request_parser_has_error(ebb_request_parser *parser) 
+{
+  return parser->cs == ebb_request_parser_error;
+}
+
+int ebb_request_parser_is_finished(ebb_request_parser *parser) 
+{
+  return parser->cs == ebb_request_parser_first_final;
+}
+
+void ebb_request_init(ebb_request *request)
+{
+  request->expect_continue = FALSE;
+  request->body_read = 0;
+  request->content_length = 0;
+  request->version_major = 0;
+  request->version_minor = 0;
+  request->number_of_headers = 0;
+  request->transfer_encoding = EBB_IDENTITY;
+  request->keep_alive = -1;
+
+  request->on_complete = NULL;
+  request->on_headers_complete = NULL;
+  request->on_body = NULL;
+  request->on_header_field = NULL;
+  request->on_header_value = NULL;
+  request->on_uri = NULL;
+  request->on_fragment = NULL;
+  request->on_path = NULL;
+  request->on_query_string = NULL;
+}
+
+int ebb_request_should_keep_alive(ebb_request *request)
+{
+  if(request->keep_alive == -1)
+    if(request->version_major == 1)
+      return (request->version_minor != 0);
+    else if(request->version_major == 0)
+      return FALSE;
+    else
+      return TRUE;
+  else
+    return request->keep_alive;
+}
diff --git a/deps/libebb/examples/ca-cert.pem b/deps/libebb/examples/ca-cert.pem
new file mode 100644
index 0000000..606283b
--- /dev/null
+++ b/deps/libebb/examples/ca-cert.pem
@@ -0,0 +1,12 @@
+-----BEGIN CERTIFICATE-----
+MIIBzDCCATegAwIBAgIESIuNVTALBgkqhkiG9w0BAQUwADAeFw0wODA3MjYyMDQ3
+MTlaFw0xMTA0MjIyMDQ3MjVaMAAwgZwwCwYJKoZIhvcNAQEBA4GMADCBiAKBgOm9
+l/FoXbTIcEusk/QlS5YrlR04+oWIbSdZIf3GJBEWEUPljDxAX96qHsTcaVnGK+EP
+keU4cIZvdY+hzbqa5cc1j2/9IeJNejL8gpQ/ocyMM69yq5Ib2F8K4mGWm1xr30hU
+bYpY5D0MrZ1b0HtYFVc8KVAr0ADGG+pye0P9c3B/AgMBAAGjWjBYMAwGA1UdEwEB
+/wQCMAAwFAYDVR0RBA0wC4IJbG9jYWxob3N0MBMGA1UdJQQMMAoGCCsGAQUFBwMB
+MB0GA1UdDgQWBBTYgVB7kJnnm+jgX9DgrapzGfUmxjALBgkqhkiG9w0BAQUDgYEA
+GkadA2H8CAzU3w4oCGZu9Ry9Tj/9Agw1XMFKvoJuG7VLPk7+B25JvNFVsmpROLxO
+0TJ6mIU2hz5/rLvEfTBGQ+DYtbsjIxCz1fD7R5c1kKBtA0d0u8mY8pTlPNlxFPSW
+3ymx5DB2zyDa/HuX6m6/VmzMYmA0vp7Dp1cl+pA9Nhs=
+-----END CERTIFICATE-----
diff --git a/deps/libebb/examples/ca-key.pem b/deps/libebb/examples/ca-key.pem
new file mode 100644
index 0000000..afb953d
--- /dev/null
+++ b/deps/libebb/examples/ca-key.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQDpvZfxaF20yHBLrJP0JUuWK5UdOPqFiG0nWSH9xiQRFhFD5Yw8
+QF/eqh7E3GlZxivhD5HlOHCGb3WPoc26muXHNY9v/SHiTXoy/IKUP6HMjDOvcquS
+G9hfCuJhlptca99IVG2KWOQ9DK2dW9B7WBVXPClQK9AAxhvqcntD/XNwfwIDAQAB
+AoGAJqo3LTbfcV1KvinhG5zjwQaalwfq4RXtQHoNFmalZrIozvt01C6t7S5lApmX
+T8NpVMR3lNxeOM7NOqJAXuLqqVVqk81YEYuMx6E4gB/Ifl7jVZk1jstmLILhh59D
+pXrlpzvvm5X2hVsI7lp/YGAvtdLS1iVy37bGgmQWfCeeZiECQQDtZLfcJb4oE1yR
+ZfLOcPDlBCw02wGMNFpAjwbspf/du3Yn3ONWHVfhSCCcCe262h9PLblL97LoB+gF
+OHOlM9JvAkEA/A+U3/p9pwL4L742pxZP62/rmk6p5mZFIykk2jIUTpdilXBWBlcT
+OjgjnpquZpwnaClmvgFpkzdhIPF7Nq4K8QJBAITVKagOmnOUOeTF1fI78h9DkXTV
+4uzP0nxzS52ZWS16Gqg9ihuCecz97flB+Prn2EMWw6tFY58/5U0ehF85OxMCQQDF
+08TYdVSg+6emcPeb89sNwW18UjjuZ13j1qrhxWRCunXZK62YlEa27tCl7mjqh6w2
+CChm/9zIejJ1FJHLvJVBAkBj63ZbwggMYkxuj60jIBbNrEtDx9y7zM0sXkiJqcKp
+5uGtJNafG+yZrLAHE6/b4aqUOtGsCGsiZpT9ms7CoaVr
+-----END RSA PRIVATE KEY-----
diff --git a/deps/libebb/examples/hello_world.c b/deps/libebb/examples/hello_world.c
new file mode 100644
index 0000000..bec0070
--- /dev/null
+++ b/deps/libebb/examples/hello_world.c
@@ -0,0 +1,101 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include <ev.h>
+#include "ebb.h"
+
+#define MSG ("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 12\r\n\r\nhello world\n")
+static int c = 0;
+
+struct hello_connection {
+  unsigned int responses_to_write;
+};
+
+void on_close(ebb_connection *connection)
+{
+  free(connection->data);
+  free(connection);
+}
+
+static void continue_responding(ebb_connection *connection)
+{
+  int r;
+  struct hello_connection *connection_data = connection->data;
+  //printf("response complete \n");
+  if(--connection_data->responses_to_write > 0) {
+    /* write another response */
+    r = ebb_connection_write(connection, MSG, sizeof MSG, continue_responding);
+    assert(r);
+  } else {
+    ebb_connection_schedule_close(connection);
+  }
+}
+
+static void request_complete(ebb_request *request)
+{
+  //printf("request complete \n");
+  ebb_connection *connection = request->data;
+  struct hello_connection *connection_data = connection->data;
+
+  if(ebb_request_should_keep_alive(request))
+    connection_data->responses_to_write++;
+  else
+    connection_data->responses_to_write = 1;
+
+  ebb_connection_write(connection, MSG, sizeof MSG, continue_responding);
+  free(request);
+}
+
+static ebb_request* new_request(ebb_connection *connection)
+{
+  //printf("request %d\n", ++c);
+  ebb_request *request = malloc(sizeof(ebb_request));
+  ebb_request_init(request);
+  request->data = connection;
+  request->on_complete = request_complete;
+  return request;
+}
+
+ebb_connection* new_connection(ebb_server *server, struct sockaddr_in *addr)
+{
+  struct hello_connection *connection_data = malloc(sizeof(struct hello_connection));
+  if(connection_data == NULL)
+    return NULL;
+  connection_data->responses_to_write = 0;
+
+  ebb_connection *connection = malloc(sizeof(ebb_connection));
+  if(connection == NULL) {
+    free(connection_data);
+    return NULL;
+  }
+
+  ebb_connection_init(connection);
+  connection->data = connection_data;
+  connection->new_request = new_request;
+  connection->on_close = on_close;
+  
+  printf("connection: %d\n", c++);
+  return connection;
+}
+
+int main(int argc, char **_) 
+{
+  struct ev_loop *loop = ev_default_loop(0);
+  ebb_server server;
+
+  ebb_server_init(&server, loop);
+  if(argc > 1) {
+    printf("using SSL\n");
+    ebb_server_set_secure(&server, "ca-cert.pem", "ca-key.pem");
+  }
+  server.new_connection = new_connection;
+
+  printf("hello_world listening on port 5000\n");
+  ebb_server_listen_on_port(&server, 5000);
+  ev_loop(loop, 0);
+
+  return 0;
+}
diff --git a/deps/libebb/rbtree.c b/deps/libebb/rbtree.c
new file mode 100644
index 0000000..4a66972
--- /dev/null
+++ b/deps/libebb/rbtree.c
@@ -0,0 +1,412 @@
+/* Copyright (c) 2008 Derrick Coetzee
+ * http://en.literateprograms.org/Red-black_tree_(C)?oldid=7982
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the
+ * following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
+ * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "rbtree.h"
+#include <assert.h>
+
+#ifndef NULL
+# define NULL ((void*)0)
+#endif
+
+
+typedef rbtree_node node;
+typedef enum rbtree_node_color color;
+
+
+static node grandparent(node n);
+static node sibling(node n);
+static node uncle(node n);
+static void verify_properties(rbtree t);
+static void verify_property_1(node root);
+/* static void verify_property_2(node root); */
+static color node_color(node n);
+static void verify_property_4(node root);
+/* static void verify_property_5(node root); */
+static void verify_property_5_helper(node n, int black_count, int* black_count_path);
+
+static node lookup_node(rbtree t, void* key);
+static void rotate_left(rbtree t, node n);
+static void rotate_right(rbtree t, node n);
+
+static void replace_node(rbtree t, node oldn, node newn);
+static void insert_case1(rbtree t, node n);
+static void insert_case2(rbtree t, node n);
+static void insert_case3(rbtree t, node n);
+static void insert_case4(rbtree t, node n);
+static void insert_case5(rbtree t, node n);
+static node maximum_node(node root);
+static void delete_case1(rbtree t, node n);
+static void delete_case2(rbtree t, node n);
+static void delete_case3(rbtree t, node n);
+static void delete_case4(rbtree t, node n);
+static void delete_case5(rbtree t, node n);
+static void delete_case6(rbtree t, node n);
+
+node grandparent(node n) {
+    assert (n != NULL);
+    assert (n->parent != NULL); /* Not the root node */
+    assert (n->parent->parent != NULL); /* Not child of root */
+    return n->parent->parent;
+}
+
+node sibling(node n) {
+    assert (n != NULL);
+    assert (n->parent != NULL); /* Root node has no sibling */
+    if (n == n->parent->left)
+        return n->parent->right;
+    else
+        return n->parent->left;
+}
+
+node uncle(node n) {
+    assert (n != NULL);
+    assert (n->parent != NULL); /* Root node has no uncle */
+    assert (n->parent->parent != NULL); /* Children of root have no uncle */
+    return sibling(n->parent);
+}
+
+void verify_properties(rbtree t) {
+#ifdef VERIFY_RBTREE
+    verify_property_1(t->root);
+    verify_property_2(t->root);
+    /* Property 3 is implicit */
+    verify_property_4(t->root);
+    verify_property_5(t->root);
+#endif
+}
+
+void verify_property_1(node n) {
+    assert(node_color(n) == RED || node_color(n) == BLACK);
+    if (n == NULL) return;
+    verify_property_1(n->left);
+    verify_property_1(n->right);
+}
+
+/*
+void verify_property_2(node root) {
+    assert(node_color(root) == BLACK);
+}
+*/
+
+color node_color(node n) {
+    return n == NULL ? BLACK : n->color;
+}
+
+void verify_property_4(node n) {
+    if (node_color(n) == RED) {
+        assert (node_color(n->left)   == BLACK);
+        assert (node_color(n->right)  == BLACK);
+        assert (node_color(n->parent) == BLACK);
+    }
+    if (n == NULL) return;
+    verify_property_4(n->left);
+    verify_property_4(n->right);
+}
+
+/*
+void verify_property_5(node root) {
+    int black_count_path = -1;
+    verify_property_5_helper(root, 0, &black_count_path);
+}
+*/
+
+void verify_property_5_helper(node n, int black_count, int* path_black_count) {
+    if (node_color(n) == BLACK) {
+        black_count++;
+    }
+    if (n == NULL) {
+        if (*path_black_count == -1) {
+            *path_black_count = black_count;
+        } else {
+            assert (black_count == *path_black_count);
+        }
+        return;
+    }
+    verify_property_5_helper(n->left,  black_count, path_black_count);
+    verify_property_5_helper(n->right, black_count, path_black_count);
+}
+
+void rbtree_init(rbtree t, rbtree_compare_func compare) {
+    t->root = NULL;
+    t->compare = compare;
+    verify_properties(t);
+}
+
+node lookup_node(rbtree t, void* key) {
+    node n = t->root;
+    while (n != NULL) {
+        int comp_result = t->compare(key, n->key);
+        if (comp_result == 0) {
+            return n;
+        } else if (comp_result < 0) {
+            n = n->left;
+        } else {
+            assert(comp_result > 0);
+            n = n->right;
+        }
+    }
+    return n;
+}
+
+void* rbtree_lookup(rbtree t, void* key) {
+    node n = lookup_node(t, key);
+    return n == NULL ? NULL : n->value;
+}
+
+void rotate_left(rbtree t, node n) {
+    node r = n->right;
+    replace_node(t, n, r);
+    n->right = r->left;
+    if (r->left != NULL) {
+        r->left->parent = n;
+    }
+    r->left = n;
+    n->parent = r;
+}
+
+void rotate_right(rbtree t, node n) {
+    node L = n->left;
+    replace_node(t, n, L);
+    n->left = L->right;
+    if (L->right != NULL) {
+        L->right->parent = n;
+    }
+    L->right = n;
+    n->parent = L;
+}
+
+void replace_node(rbtree t, node oldn, node newn) {
+    if (oldn->parent == NULL) {
+        t->root = newn;
+    } else {
+        if (oldn == oldn->parent->left)
+            oldn->parent->left = newn;
+        else
+            oldn->parent->right = newn;
+    }
+    if (newn != NULL) {
+        newn->parent = oldn->parent;
+    }
+}
+
+void rbtree_insert(rbtree t, rbtree_node inserted_node) {
+    inserted_node->color = RED;
+    inserted_node->left = NULL;
+    inserted_node->right = NULL;
+    inserted_node->parent = NULL;
+
+    if (t->root == NULL) {
+        t->root = inserted_node;
+    } else {
+        node n = t->root;
+        while (1) {
+            int comp_result = t->compare(inserted_node->key, n->key);
+            if (comp_result == 0) {
+                n->value = inserted_node->value;
+                return;
+            } else if (comp_result < 0) {
+                if (n->left == NULL) {
+                    n->left = inserted_node;
+                    break;
+                } else {
+                    n = n->left;
+                }
+            } else {
+                assert (comp_result > 0);
+                if (n->right == NULL) {
+                    n->right = inserted_node;
+                    break;
+                } else {
+                    n = n->right;
+                }
+            }
+        }
+        inserted_node->parent = n;
+    }
+    insert_case1(t, inserted_node);
+    verify_properties(t);
+}
+
+void insert_case1(rbtree t, node n) {
+    if (n->parent == NULL)
+        n->color = BLACK;
+    else
+        insert_case2(t, n);
+}
+
+void insert_case2(rbtree t, node n) {
+    if (node_color(n->parent) == BLACK)
+        return; /* Tree is still valid */
+    else
+        insert_case3(t, n);
+}
+
+void insert_case3(rbtree t, node n) {
+    if (node_color(uncle(n)) == RED) {
+        n->parent->color = BLACK;
+        uncle(n)->color = BLACK;
+        grandparent(n)->color = RED;
+        insert_case1(t, grandparent(n));
+    } else {
+        insert_case4(t, n);
+    }
+}
+
+void insert_case4(rbtree t, node n) {
+    if (n == n->parent->right && n->parent == grandparent(n)->left) {
+        rotate_left(t, n->parent);
+        n = n->left;
+    } else if (n == n->parent->left && n->parent == grandparent(n)->right) {
+        rotate_right(t, n->parent);
+        n = n->right;
+    }
+    insert_case5(t, n);
+}
+
+void insert_case5(rbtree t, node n) {
+    n->parent->color = BLACK;
+    grandparent(n)->color = RED;
+    if (n == n->parent->left && n->parent == grandparent(n)->left) {
+        rotate_right(t, grandparent(n));
+    } else {
+        assert (n == n->parent->right && n->parent == grandparent(n)->right);
+        rotate_left(t, grandparent(n));
+    }
+}
+
+rbtree_node rbtree_delete(rbtree t, void* key) {
+    node child;
+    node n = lookup_node(t, key);
+    if (n == NULL) return NULL;  /* Key not found, do nothing */
+    if (n->left != NULL && n->right != NULL) {
+        /* Copy key/value from predecessor and then delete it instead */
+        node pred = maximum_node(n->left);
+        n->key   = pred->key;
+        n->value = pred->value;
+        n = pred;
+    }
+
+    assert(n->left == NULL || n->right == NULL);
+    child = n->right == NULL ? n->left  : n->right;
+    if (node_color(n) == BLACK) {
+        n->color = node_color(child);
+        delete_case1(t, n);
+    }
+    replace_node(t, n, child);
+
+    verify_properties(t);
+    return n;
+}
+
+static node maximum_node(node n) {
+    assert (n != NULL);
+    while (n->right != NULL) {
+        n = n->right;
+    }
+    return n;
+}
+
+void delete_case1(rbtree t, node n) {
+    if (n->parent == NULL)
+        return;
+    else
+        delete_case2(t, n);
+}
+
+void delete_case2(rbtree t, node n) {
+    if (node_color(sibling(n)) == RED) {
+        n->parent->color = RED;
+        sibling(n)->color = BLACK;
+        if (n == n->parent->left)
+            rotate_left(t, n->parent);
+        else
+            rotate_right(t, n->parent);
+    }
+    delete_case3(t, n);
+}
+
+void delete_case3(rbtree t, node n) {
+    if (node_color(n->parent) == BLACK &&
+        node_color(sibling(n)) == BLACK &&
+        node_color(sibling(n)->left) == BLACK &&
+        node_color(sibling(n)->right) == BLACK)
+    {
+        sibling(n)->color = RED;
+        delete_case1(t, n->parent);
+    }
+    else
+        delete_case4(t, n);
+}
+
+void delete_case4(rbtree t, node n) {
+    if (node_color(n->parent) == RED &&
+        node_color(sibling(n)) == BLACK &&
+        node_color(sibling(n)->left) == BLACK &&
+        node_color(sibling(n)->right) == BLACK)
+    {
+        sibling(n)->color = RED;
+        n->parent->color = BLACK;
+    }
+    else
+        delete_case5(t, n);
+}
+
+void delete_case5(rbtree t, node n) {
+    if (n == n->parent->left &&
+        node_color(sibling(n)) == BLACK &&
+        node_color(sibling(n)->left) == RED &&
+        node_color(sibling(n)->right) == BLACK)
+    {
+        sibling(n)->color = RED;
+        sibling(n)->left->color = BLACK;
+        rotate_right(t, sibling(n));
+    }
+    else if (n == n->parent->right &&
+             node_color(sibling(n)) == BLACK &&
+             node_color(sibling(n)->right) == RED &&
+             node_color(sibling(n)->left) == BLACK)
+    {
+        sibling(n)->color = RED;
+        sibling(n)->right->color = BLACK;
+        rotate_left(t, sibling(n));
+    }
+    delete_case6(t, n);
+}
+
+void delete_case6(rbtree t, node n) {
+    sibling(n)->color = node_color(n->parent);
+    n->parent->color = BLACK;
+    if (n == n->parent->left) {
+        assert (node_color(sibling(n)->right) == RED);
+        sibling(n)->right->color = BLACK;
+        rotate_left(t, n->parent);
+    }
+    else
+    {
+        assert (node_color(sibling(n)->left) == RED);
+        sibling(n)->left->color = BLACK;
+        rotate_right(t, n->parent);
+    }
+}
+
+
diff --git a/deps/libebb/rbtree.h b/deps/libebb/rbtree.h
new file mode 100644
index 0000000..5962a3c
--- /dev/null
+++ b/deps/libebb/rbtree.h
@@ -0,0 +1,54 @@
+/* Copyright (c) 2008 Derrick Coetzee
+ * http://en.literateprograms.org/Red-black_tree_(C)?oldid=7982
+ * Small changes by Ryah Dahl
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the
+ * following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
+ * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _RBTREE_H_
+#define _RBTREE_H_
+
+enum rbtree_node_color { RED, BLACK };
+
+typedef int (*rbtree_compare_func)(void* left_key, void* right_key);
+
+typedef struct rbtree_node_t {
+    struct rbtree_node_t* left;    /* private */
+    struct rbtree_node_t* right;   /* private */
+    struct rbtree_node_t* parent;  /* private */
+    enum rbtree_node_color color;  /* private */
+    void* key;   /* public */
+    void* value; /* public */
+} *rbtree_node;
+
+typedef struct rbtree_t {
+    rbtree_node root;             /* private */
+    rbtree_compare_func compare;  /* private */
+} *rbtree;
+
+
+void rbtree_init(rbtree t, rbtree_compare_func);
+void* rbtree_lookup(rbtree t, void* key);
+void rbtree_insert(rbtree t, rbtree_node);
+/* you must free the returned node */
+rbtree_node rbtree_delete(rbtree t, void* key);
+
+#endif
+
diff --git a/deps/libebb/test_examples.rb b/deps/libebb/test_examples.rb
new file mode 100644
index 0000000..2af658c
--- /dev/null
+++ b/deps/libebb/test_examples.rb
@@ -0,0 +1,60 @@
+require 'test/unit'
+require 'socket'
+
+REQ = "GET /hello/%d HTTP/1.1\r\n\r\n"
+HOST = '0.0.0.0'
+PORT = 5000
+
+class TCPSocket
+  def full_send(string)
+    written = 0
+    while(written < string.length) 
+      sent = write(string)
+      string = string.slice(sent, 10000)
+    end
+    written
+  end
+
+  def full_read
+    response = ""
+    while chunk = read(10000)
+      response += chunk
+    end
+    response
+  end
+
+end
+
+class EbbTest < Test::Unit::TestCase
+
+  def setup
+    @socket = TCPSocket.new(HOST, PORT)
+  end
+
+  def test_bad_req
+    @socket.full_send("hello")
+    assert_equal "", @socket.full_read
+    #assert @socket.closed?
+  end
+  
+  def test_single
+    written = 0
+    req = REQ % 1
+    @socket.full_send(req)
+    response = @socket.full_read()
+    count = 0
+    response.scan("hello world") { count += 1 }
+
+    assert_equal 1, count
+  end
+
+  def test_pipeline
+    written = 0
+    req = (REQ % 1) + (REQ % 2) + (REQ % 3) + (REQ % 4)
+    @socket.full_send(req)
+    response = @socket.full_read()
+    count = 0
+    response.scan("hello world") { count += 1 }
+    assert_equal 4, count
+  end
+end
diff --git a/deps/libebb/test_rbtree.c b/deps/libebb/test_rbtree.c
new file mode 100644
index 0000000..f5ee1d6
--- /dev/null
+++ b/deps/libebb/test_rbtree.c
@@ -0,0 +1,108 @@
+/* Copyright (c) 2008 Derrick Coetzee
+ * http://en.literateprograms.org/Red-black_tree_(C)?oldid=7982
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the
+ * following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
+ * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "rbtree.h"
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h> /* rand(), malloc(), free() */
+
+static int compare_int(void* left, void* right);
+static void print_tree(rbtree t);
+static void print_tree_helper(rbtree_node n, int indent);
+
+int compare_int(void* leftp, void* rightp) {
+    int left = (int)leftp;
+    int right = (int)rightp;
+    if (left < right) 
+        return -1;
+    else if (left > right)
+        return 1;
+    else {
+        assert (left == right);
+        return 0;
+    }
+}
+
+#define INDENT_STEP  4
+
+void print_tree_helper(rbtree_node n, int indent);
+
+void print_tree(rbtree t) {
+    print_tree_helper(t->root, 0);
+    puts("");
+}
+
+void print_tree_helper(rbtree_node n, int indent) {
+    int i;
+    if (n == NULL) {
+        fputs("<empty tree>", stdout);
+        return;
+    }
+    if (n->right != NULL) {
+        print_tree_helper(n->right, indent + INDENT_STEP);
+    }
+    for(i=0; i<indent; i++)
+        fputs(" ", stdout);
+    if (n->color == BLACK)
+        printf("%d\n", (int)n->key);
+    else
+        printf("<%d>\n", (int)n->key);
+    if (n->left != NULL) {
+        print_tree_helper(n->left, indent + INDENT_STEP);
+    }
+}
+
+int main() {
+    int i;
+    struct rbtree_t t;
+    rbtree_init(&t, compare_int); 
+    print_tree(&t);
+
+    for(i=0; i<5000; i++) {
+        int x = rand() % 10000;
+        int y = rand() % 10000;
+#ifdef TRACE
+        print_tree(&t);
+        printf("Inserting %d -> %d\n\n", x, y);
+#endif
+        rbtree_node node = (rbtree_node) malloc(sizeof(struct rbtree_node_t));
+        node->key = (void*)x;
+        node->value = (void*)y;
+        rbtree_insert(&t, node);
+        assert(rbtree_lookup(&t, (void*)x) == (void*)y);
+    }
+    for(i=0; i<60000; i++) {
+        int x = rand() % 10000;
+#ifdef TRACE
+        print_tree(&t);
+        printf("Deleting key %d\n\n", x);
+#endif
+        rbtree_node n = rbtree_delete(&t, (void*)x);
+        if(n != NULL) {
+            free(n);
+        }
+    }
+    printf("Okay\n");
+    return 0;
+}
+
diff --git a/deps/libebb/test_request_parser.c b/deps/libebb/test_request_parser.c
new file mode 100644
index 0000000..5a5dca3
--- /dev/null
+++ b/deps/libebb/test_request_parser.c
@@ -0,0 +1,746 @@
+/* unit tests for request parser
+ * Copyright 2008 ryah dahl, ry@ndahl.us
+ *
+ * This software may be distributed under the "MIT" license included in the
+ * README
+ */
+#include "ebb_request_parser.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#define TRUE 1
+#define FALSE 0
+
+#define MAX_HEADERS 500
+#define MAX_ELEMENT_SIZE 500
+
+static ebb_request_parser parser;
+struct request_data {
+  const char *raw;
+  int request_method;
+  char request_path[MAX_ELEMENT_SIZE];
+  char request_uri[MAX_ELEMENT_SIZE];
+  char fragment[MAX_ELEMENT_SIZE];
+  char query_string[MAX_ELEMENT_SIZE];
+  char body[MAX_ELEMENT_SIZE];
+  int num_headers;
+  char header_fields[MAX_HEADERS][MAX_ELEMENT_SIZE];
+  char header_values[MAX_HEADERS][MAX_ELEMENT_SIZE];
+  int should_keep_alive;
+  ebb_request request;
+};
+static struct request_data requests[5];
+static int num_requests;
+
+const struct request_data curl_get = 
+  { raw: "GET /test HTTP/1.1\r\n"
+         "User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1\r\n"
+         "Host: 0.0.0.0:5000\r\n"
+         "Accept: */*\r\n"
+         "\r\n"
+  , should_keep_alive: TRUE
+  , request_method: EBB_GET
+  , query_string: ""
+  , fragment: ""
+  , request_path: "/test"
+  , request_uri: "/test"
+  , num_headers: 3
+  , header_fields: { "User-Agent", "Host", "Accept" }
+  , header_values: { "curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1", "0.0.0.0:5000", "*/*" }
+  , body: ""
+  };
+
+const struct request_data firefox_get = 
+  { raw: "GET /favicon.ico HTTP/1.1\r\n"
+         "Host: 0.0.0.0:5000\r\n"
+         "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0\r\n"
+         "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
+         "Accept-Language: en-us,en;q=0.5\r\n"
+         "Accept-Encoding: gzip,deflate\r\n"
+         "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
+         "Keep-Alive: 300\r\n"
+         "Connection: keep-alive\r\n"
+         "\r\n"
+  , should_keep_alive: TRUE
+  , request_method: EBB_GET
+  , query_string: ""
+  , fragment: ""
+  , request_path: "/favicon.ico"
+  , request_uri: "/favicon.ico"
+  , num_headers: 8
+  , header_fields: 
+    { "Host"
+    , "User-Agent"
+    , "Accept"
+    , "Accept-Language"
+    , "Accept-Encoding"
+    , "Accept-Charset"
+    , "Keep-Alive"
+    , "Connection" 
+    }
+  , header_values: 
+    { "0.0.0.0:5000"
+    , "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0"
+    , "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
+    , "en-us,en;q=0.5"
+    , "gzip,deflate"
+    , "ISO-8859-1,utf-8;q=0.7,*;q=0.7"
+    , "300"
+    , "keep-alive"
+    }
+  , body: ""
+  };
+
+const struct request_data dumbfuck =
+  { raw: "GET /dumbfuck HTTP/1.1\r\n"
+         "aaaaaaaaaaaaa:++++++++++\r\n"
+         "\r\n"
+  , should_keep_alive: TRUE
+  , request_method: EBB_GET
+  , query_string: ""
+  , fragment: ""
+  , request_path: "/dumbfuck"
+  , request_uri: "/dumbfuck"
+  , num_headers: 1
+  , header_fields: { "aaaaaaaaaaaaa" }
+  , header_values: {  "++++++++++" }
+  , body: ""
+  };
+
+const struct request_data fragment_in_uri = 
+  { raw: "GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n"
+         "\r\n"
+  , should_keep_alive: TRUE
+  , request_method: EBB_GET
+  , query_string: "page=1"
+  , fragment: "posts-17408"
+  , request_path: "/forums/1/topics/2375"
+  /* XXX request uri does not include fragment? */
+  , request_uri: "/forums/1/topics/2375?page=1" 
+  , num_headers: 0
+  , body: ""
+  };
+
+
+// get - no headers - no body
+const struct request_data get_no_headers_no_body =  
+  { raw: "GET /get_no_headers_no_body/world HTTP/1.1\r\n"
+         "\r\n"
+  , should_keep_alive: TRUE
+  , request_method: EBB_GET
+  , query_string: ""
+  , fragment: ""
+  , request_path: "/get_no_headers_no_body/world"
+  , request_uri: "/get_no_headers_no_body/world"
+  , num_headers: 0
+  , body: ""
+  };
+
+// get - one header - no body
+const struct request_data get_one_header_no_body =  
+  { raw: "GET /get_one_header_no_body HTTP/1.1\r\n"
+         "Accept: */*\r\n"
+         "\r\n"
+  , should_keep_alive: TRUE
+  , request_method: EBB_GET
+  , query_string: ""
+  , fragment: ""
+  , request_path: "/get_one_header_no_body"
+  , request_uri: "/get_one_header_no_body"
+  , num_headers: 1
+  , header_fields: { "Accept" }
+  , header_values: { "*/*" }
+  , body: ""
+  };
+
+// get - no headers - body "HELLO"
+const struct request_data get_funky_content_length_body_hello =  
+  { raw: "GET /get_funky_content_length_body_hello HTTP/1.0\r\n"
+         "conTENT-Length: 5\r\n"
+         "\r\n"
+         "HELLO"
+  , should_keep_alive: FALSE
+  , request_method: EBB_GET
+  , query_string: ""
+  , fragment: ""
+  , request_path: "/get_funky_content_length_body_hello"
+  , request_uri: "/get_funky_content_length_body_hello"
+  , num_headers: 1
+  , header_fields: { "conTENT-Length" }
+  , header_values: { "5" }
+  , body: "HELLO"
+  };
+
+// post - one header - body "World"
+const struct request_data post_identity_body_world =  
+  { raw: "POST /post_identity_body_world?q=search#hey HTTP/1.1\r\n"
+         "Accept: */*\r\n"
+         "Transfer-Encoding: identity\r\n"
+         "Content-Length: 5\r\n"
+         "\r\n"
+         "World"
+  , should_keep_alive: TRUE
+  , request_method: EBB_POST
+  , query_string: "q=search"
+  , fragment: "hey"
+  , request_path: "/post_identity_body_world"
+  , request_uri: "/post_identity_body_world?q=search"
+  , num_headers: 3
+  , header_fields: { "Accept", "Transfer-Encoding", "Content-Length" }
+  , header_values: { "*/*", "identity", "5" }
+  , body: "World"
+  };
+
+// post - no headers - chunked body "all your base are belong to us"
+const struct request_data post_chunked_all_your_base =  
+  { raw: "POST /post_chunked_all_your_base HTTP/1.1\r\n"
+         "Transfer-Encoding: chunked\r\n"
+         "\r\n"
+         "1e\r\nall your base are belong to us\r\n"
+         "0\r\n"
+         "\r\n"
+  , should_keep_alive: TRUE
+  , request_method: EBB_POST
+  , query_string: ""
+  , fragment: ""
+  , request_path: "/post_chunked_all_your_base"
+  , request_uri: "/post_chunked_all_your_base"
+  , num_headers: 1
+  , header_fields: { "Transfer-Encoding" }
+  , header_values: { "chunked" }
+  , body: "all your base are belong to us"
+  };
+
+// two chunks ; triple zero ending
+const struct request_data two_chunks_mult_zero_end =  
+  { raw: "POST /two_chunks_mult_zero_end HTTP/1.1\r\n"
+         "Transfer-Encoding: chunked\r\n"
+         "\r\n"
+         "5\r\nhello\r\n"
+         "6\r\n world\r\n"
+         "000\r\n"
+         "\r\n"
+  , should_keep_alive: TRUE
+  , request_method: EBB_POST
+  , query_string: ""
+  , fragment: ""
+  , request_path: "/two_chunks_mult_zero_end"
+  , request_uri: "/two_chunks_mult_zero_end"
+  , num_headers: 1
+  , header_fields: { "Transfer-Encoding" }
+  , header_values: { "chunked" }
+  , body: "hello world"
+  };
+
+
+// chunked with trailing headers. blech.
+const struct request_data chunked_w_trailing_headers =  
+  { raw: "POST /chunked_w_trailing_headers HTTP/1.1\r\n"
+         "Transfer-Encoding: chunked\r\n"
+         "\r\n"
+         "5\r\nhello\r\n"
+         "6\r\n world\r\n"
+         "0\r\n"
+         "Vary: *\r\n"
+         "Content-Type: text/plain\r\n"
+         "\r\n"
+  , should_keep_alive: TRUE
+  , request_method: EBB_POST
+  , query_string: ""
+  , fragment: ""
+  , request_path: "/chunked_w_trailing_headers"
+  , request_uri: "/chunked_w_trailing_headers"
+  , num_headers: 1
+  , header_fields: { "Transfer-Encoding" }
+  , header_values: { "chunked" }
+  , body: "hello world"
+  };
+
+// with bullshit after the length
+const struct request_data chunked_w_bullshit_after_length =  
+  { raw: "POST /chunked_w_bullshit_after_length HTTP/1.1\r\n"
+         "Transfer-Encoding: chunked\r\n"
+         "\r\n"
+         "5; ihatew3;whatthefuck=aretheseparametersfor\r\nhello\r\n"
+         "6; blahblah; blah\r\n world\r\n"
+         "0\r\n"
+         "\r\n"
+  , should_keep_alive: TRUE
+  , request_method: EBB_POST
+  , query_string: ""
+  , fragment: ""
+  , request_path: "/chunked_w_bullshit_after_length"
+  , request_uri: "/chunked_w_bullshit_after_length"
+  , num_headers: 1
+  , header_fields: { "Transfer-Encoding" }
+  , header_values: { "chunked" }
+  , body: "hello world"
+  };
+
+const struct request_data *fixtures[] =
+  { &curl_get 
+  , &firefox_get 
+  , &dumbfuck
+  , &fragment_in_uri 
+  , &get_no_headers_no_body  
+  , &get_one_header_no_body  
+  , &get_funky_content_length_body_hello  
+  , &post_identity_body_world  
+  , &post_chunked_all_your_base  
+  , &two_chunks_mult_zero_end  
+  , &chunked_w_trailing_headers  
+  , &chunked_w_bullshit_after_length  
+  , NULL
+  };
+
+
+int request_data_eq
+  ( struct request_data *r1
+  , const struct request_data *r2
+  )
+{ 
+  if(ebb_request_should_keep_alive(&r1->request) != r2->should_keep_alive) {
+    printf("requests disagree on keep-alive");
+    return FALSE;
+  }
+
+  if(0 != strcmp(r1->body, r2->body)) {
+    printf("body '%s' != '%s'\n", r1->body, r2->body);
+    return FALSE;
+  }
+  if(0 != strcmp(r1->fragment, r2->fragment)) {
+    printf("fragment '%s' != '%s'\n", r1->fragment, r2->fragment);
+    return FALSE;
+  }
+  if(0 != strcmp(r1->query_string, r2->query_string)) {
+    printf("query_string '%s' != '%s'\n", r1->query_string, r2->query_string);
+    return FALSE;
+  }
+  if(r1->request.method != r2->request_method) {
+    printf("request_method '%d' != '%d'\n", r1->request.method, r2->request_method);
+    return FALSE;
+  }
+  if(0 != strcmp(r1->request_path, r2->request_path)) {
+    printf("request_path '%s' != '%s'\n", r1->request_path, r2->request_path);
+    return FALSE;
+  }
+  if(0 != strcmp(r1->request_uri, r2->request_uri)) {
+    printf("request_uri '%s' != '%s'\n", r1->request_uri, r2->request_uri);
+    return FALSE;
+  }
+  if(r1->num_headers != r2->num_headers) {
+    printf("num_headers '%d' != '%d'\n", r1->num_headers, r2->num_headers);
+    return FALSE;
+  }
+  int i;
+  for(i = 0; i < r1->num_headers; i++) {
+    if(0 != strcmp(r1->header_fields[i], r2->header_fields[i])) {
+      printf("header field '%s' != '%s'\n", r1->header_fields[i], r2->header_fields[i]);
+      return FALSE;
+    }
+    if(0 != strcmp(r1->header_values[i], r2->header_values[i])) {
+      printf("header field '%s' != '%s'\n", r1->header_values[i], r2->header_values[i]);
+      return FALSE;
+    }
+  }
+  return TRUE;
+}
+
+int request_eq
+  ( int index
+  , const struct request_data *expected
+  )
+{
+  return request_data_eq(&requests[index], expected);
+}
+
+void request_complete(ebb_request *info)
+{
+  num_requests++;
+}
+
+void request_path_cb(ebb_request *request, const char *p, size_t len)
+{
+  strncat(requests[num_requests].request_path, p, len);
+}
+
+void request_uri_cb(ebb_request *request, const char *p, size_t len)
+{
+  strncat(requests[num_requests].request_uri, p, len);
+}
+
+void query_string_cb(ebb_request *request, const char *p, size_t len)
+{
+  strncat(requests[num_requests].query_string, p, len);
+}
+
+void fragment_cb(ebb_request *request, const char *p, size_t len)
+{
+  strncat(requests[num_requests].fragment, p, len);
+}
+
+void header_field_cb(ebb_request *request, const char *p, size_t len, int header_index)
+{
+  strncat(requests[num_requests].header_fields[header_index], p, len);
+}
+
+void header_value_cb(ebb_request *request, const char *p, size_t len, int header_index)
+{
+  strncat(requests[num_requests].header_values[header_index], p, len);
+  requests[num_requests].num_headers = header_index + 1;
+}
+
+void body_handler(ebb_request *request, const char *p, size_t len)
+{
+  strncat(requests[num_requests].body, p, len);
+ // printf("body_handler: '%s'\n", requests[num_requests].body);
+}
+
+ebb_request* new_request ()
+{
+  requests[num_requests].num_headers = 0;
+  requests[num_requests].request_method = -1;
+  requests[num_requests].request_path[0] = 0;
+  requests[num_requests].request_uri[0] = 0;
+  requests[num_requests].fragment[0] = 0;
+  requests[num_requests].query_string[0] = 0;
+  requests[num_requests].body[0] = 0;
+  int i; 
+  for(i = 0; i < MAX_HEADERS; i++) {
+    requests[num_requests].header_fields[i][0] = 0;
+    requests[num_requests].header_values[i][0] = 0;
+  }
+    
+  ebb_request *r = &requests[num_requests].request;
+  ebb_request_init(r);
+
+  r->on_complete = request_complete;
+  r->on_header_field = header_field_cb;
+  r->on_header_value = header_value_cb;
+  r->on_path = request_path_cb;
+  r->on_uri = request_uri_cb;
+  r->on_fragment = fragment_cb;
+  r->on_query_string = query_string_cb;
+  r->on_body = body_handler;
+  r->on_headers_complete = NULL;
+
+  r->data = &requests[num_requests];
+ // printf("new request %d\n", num_requests);
+  return r;
+}
+
+void parser_init()
+{
+  num_requests = 0;
+
+  ebb_request_parser_init(&parser);
+
+  parser.new_request = new_request;
+}
+
+int test_request
+  ( const struct request_data *request_data
+  )
+{
+  size_t traversed = 0;
+  parser_init();
+
+  traversed = ebb_request_parser_execute( &parser
+                                        , request_data->raw 
+                                        , strlen(request_data->raw)
+                                        );
+  if( ebb_request_parser_has_error(&parser) )
+    return FALSE;
+  if(! ebb_request_parser_is_finished(&parser) )
+    return FALSE;
+  if(num_requests != 1)
+    return FALSE;
+
+  return request_eq(0, request_data);
+}
+
+int test_error
+  ( const char *buf
+  )
+{
+  size_t traversed = 0;
+  parser_init();
+
+  traversed = ebb_request_parser_execute(&parser, buf, strlen(buf));
+
+  return ebb_request_parser_has_error(&parser);
+}
+
+
+int test_multiple3
+  ( const struct request_data *r1
+  , const struct request_data *r2
+  , const struct request_data *r3
+  )
+{
+  char total[80*1024] = "\0";
+
+  strcat(total, r1->raw); 
+  strcat(total, r2->raw); 
+  strcat(total, r3->raw); 
+
+  size_t traversed = 0;
+  parser_init();
+
+  traversed = ebb_request_parser_execute(&parser, total, strlen(total));
+
+
+  if( ebb_request_parser_has_error(&parser) )
+    return FALSE;
+  if(! ebb_request_parser_is_finished(&parser) )
+    return FALSE;
+  if(num_requests != 3)
+    return FALSE;
+
+  if(!request_eq(0, r1)){
+    printf("request 1 error.\n");
+    return FALSE;
+  }
+  if(!request_eq(1, r2)){
+    printf("request 2 error.\n");
+    return FALSE;
+  }
+  if(!request_eq(2, r3)){
+    printf("request 3 error.\n");
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+ * SCAN through every possible breaking to make sure the 
+ * parser can handle getting the content in any chunks that
+ * might come from the socket
+ */
+int test_scan2
+  ( const struct request_data *r1
+  , const struct request_data *r2
+  , const struct request_data *r3
+  )
+{
+  char total[80*1024] = "\0";
+  char buf1[80*1024] = "\0";
+  char buf2[80*1024] = "\0";
+
+  strcat(total, r1->raw); 
+  strcat(total, r2->raw); 
+  strcat(total, r3->raw); 
+
+  int total_len = strlen(total);
+
+  //printf("total_len = %d\n", total_len);
+  int i;
+  for(i = 1; i < total_len - 1; i ++ ) {
+
+    parser_init();
+
+    int buf1_len = i;
+    strncpy(buf1, total, buf1_len);
+    buf1[buf1_len] = 0;
+
+    int buf2_len = total_len - i;
+    strncpy(buf2, total+i, buf2_len);
+    buf2[buf2_len] = 0;
+
+    ebb_request_parser_execute(&parser, buf1, buf1_len);
+
+    if( ebb_request_parser_has_error(&parser) ) {
+      return FALSE;
+    }
+    /*
+    if(ebb_request_parser_is_finished(&parser)) 
+      return FALSE;
+    */
+
+    ebb_request_parser_execute(&parser, buf2, buf2_len);
+
+    if( ebb_request_parser_has_error(&parser))
+      return FALSE;
+    if(!ebb_request_parser_is_finished(&parser)) 
+      return FALSE;
+
+    if(3 != num_requests) {
+      printf("scan error: got %d requests in iteration %d\n", num_requests, i);
+      return FALSE;
+    }
+
+    if(!request_eq(0, r1)) {
+      printf("not maching r1\n");
+      return FALSE;
+    }
+    if(!request_eq(1, r2)) {
+      printf("not maching r2\n");
+      return FALSE;
+    }
+    if(!request_eq(2, r3)) {
+      printf("not maching r3\n");
+      return FALSE;
+    }
+  }
+  return TRUE;
+}
+
+int test_scan3
+  ( const struct request_data *r1
+  , const struct request_data *r2
+  , const struct request_data *r3
+  )
+{
+  char total[80*1024] = "\0";
+  char buf1[80*1024] = "\0";
+  char buf2[80*1024] = "\0";
+  char buf3[80*1024] = "\0";
+
+  strcat(total, r1->raw); 
+  strcat(total, r2->raw); 
+  strcat(total, r3->raw); 
+
+  int total_len = strlen(total);
+
+  //printf("total_len = %d\n", total_len);
+  int i,j;
+  for(j = 2; j < total_len - 1; j ++ ) {
+    for(i = 1; i < j; i ++ ) {
+
+      parser_init();
+
+
+
+
+      int buf1_len = i;
+      strncpy(buf1, total, buf1_len);
+      buf1[buf1_len] = 0;
+
+      int buf2_len = j - i;
+      strncpy(buf2, total+i, buf2_len);
+      buf2[buf2_len] = 0;
+
+      int buf3_len = total_len - j;
+      strncpy(buf3, total+j, buf3_len);
+      buf3[buf3_len] = 0;
+
+      /*
+      printf("buf1: %s - %d\n", buf1, buf1_len);
+      printf("buf2: %s - %d \n", buf2, buf2_len );
+      printf("buf3: %s - %d\n\n", buf3, buf3_len);
+      */
+
+      ebb_request_parser_execute(&parser, buf1, buf1_len);
+
+      if( ebb_request_parser_has_error(&parser) ) {
+        return FALSE;
+      }
+
+      ebb_request_parser_execute(&parser, buf2, buf2_len);
+
+      if( ebb_request_parser_has_error(&parser) ) {
+        return FALSE;
+      }
+
+      ebb_request_parser_execute(&parser, buf3, buf3_len);
+
+      if( ebb_request_parser_has_error(&parser))
+        return FALSE;
+      if(!ebb_request_parser_is_finished(&parser)) 
+        return FALSE;
+
+      if(3 != num_requests) {
+        printf("scan error: only got %d requests in iteration %d\n", num_requests, i);
+        return FALSE;
+      }
+
+      if(!request_eq(0, r1)) {
+        printf("not maching r1\n");
+        return FALSE;
+      }
+      if(!request_eq(1, r2)) {
+        printf("not maching r2\n");
+        return FALSE;
+      }
+      if(!request_eq(2, r3)) {
+        printf("not maching r3\n");
+        return FALSE;
+      }
+    }
+  }
+  return TRUE;
+}
+
+int main() 
+{
+
+  assert(test_error("hello world"));
+  assert(test_error("GET / HTP/1.1\r\n\r\n"));
+
+  assert(test_request(&curl_get));
+  assert(test_request(&firefox_get));
+
+  // Zed's header tests
+
+  assert(test_request(&dumbfuck));
+
+  const char *dumbfuck2 = "GET / HTTP/1.1\r\nX-SSL-Bullshit:   -----BEGIN CERTIFICATE-----\r\n\tMIIFbTCCBFWgAwIBAgICH4cwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVUsx\r\n\tETAPBgNVBAoTCGVTY2llbmNlMRIwEAYDVQQLEwlBdXRob3JpdHkxCzAJBgNVBAMT\r\n\tAkNBMS0wKwYJKoZIhvcNAQkBFh5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMu\r\n\tdWswHhcNMDYwNzI3MTQxMzI4WhcNMDcwNzI3MTQxMzI4WjBbMQswCQYDVQQGEwJV\r\n\tSzERMA8GA1UEChMIZVNjaWVuY2UxEzARBgNVBAsTCk1hbmNoZXN0ZXIxCzAJBgNV\r\n\tBAcTmrsogriqMWLAk1DMRcwFQYDVQQDEw5taWNoYWVsIHBhcmQYJKoZIhvcNAQEB\r\n\tBQADggEPADCCAQoCggEBANPEQBgl1IaKdSS1TbhF3hEXSl72G9J+WC/1R64fAcEF\r\n\tW51rEyFYiIeZGx/BVzwXbeBoNUK41OK65sxGuflMo5gLflbwJtHBRIEKAfVVp3YR\r\n\tgW7cMA/s/XKgL1GEC7rQw8lIZT8RApukCGqOVHSi/F1SiFlPDxuDfmdiNzL31+sL\r\n\t0iwHDdNkGjy5pyBSB8Y79dsSJtCW/iaLB0/n8Sj7HgvvZJ7x0fr+RQjYOUUfrePP\r\n\tu2MSpFyf+9BbC/aXgaZuiCvSR+8Snv3xApQY+fULK/xY8h8Ua51iXoQ5jrgu2SqR\r\n\twgA7BUi3G8LFzMBl8FRCDYGUDy7M6QaHXx1ZWIPWNKsCAwEAAaOCAiQwggIgMAwG\r\n\tA1UdEwEB/wQCMAAwEQYJYIZIAYb4QgEBBAQDAgWgMA4GA1UdDwEB/wQEAwID6DAs\r\n\tBglghkgBhvhCAQ0EHxYdVUsgZS1TY2llbmNlIFVzZXIgQ2VydGlmaWNhdGUwHQYD\r\n\tVR0OBBYEFDTt/sf9PeMaZDHkUIldrDYMNTBZMIGaBgNVHSMEgZIwgY+AFAI4qxGj\r\n\tloCLDdMVKwiljjDastqooXSkcjBwMQswCQYDVQQGEwJVSzERMA8GA1UEChMIZVNj\r\n\taWVuY2UxEjAQBgNVBAsTCUF1dGhvcml0eTELMAkGA1UEAxMCQ0ExLTArBgkqhkiG\r\n\t9w0BCQEWHmNhLW9wZXJhdG9yQGdyaWQtc3VwcG9ydC5hYy51a4IBADApBgNVHRIE\r\n\tIjAggR5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMudWswGQYDVR0gBBIwEDAO\r\n\tBgwrBgEEAdkvAQEBAQYwPQYJYIZIAYb4QgEEBDAWLmh0dHA6Ly9jYS5ncmlkLXN1\r\n\tcHBvcnQuYWMudmT4sopwqlBWsvcHViL2NybC9jYWNybC5jcmwwPQYJYIZIAYb4QgEDBDAWLmh0\r\n\tdHA6Ly9jYS5ncmlkLXN1cHBvcnQuYWMudWsvcHViL2NybC9jYWNybC5jcmwwPwYD\r\n\tVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NhLmdyaWQt5hYy51ay9wdWIv\r\n\tY3JsL2NhY3JsLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAS/U4iiooBENGW/Hwmmd3\r\n\tXCy6Zrt08YjKCzGNjorT98g8uGsqYjSxv/hmi0qlnlHs+k/3Iobc3LjS5AMYr5L8\r\n\tUO7OSkgFFlLHQyC9JzPfmLCAugvzEbyv4Olnsr8hbxF1MbKZoQxUZtMVu29wjfXk\r\n\thTeApBv7eaKCWpSp7MCbvgzm74izKhu3vlDk9w6qVrxePfGgpKPqfHiOoGhFnbTK\r\n\twTC6o2xq5y0qZ03JonF7OJspEd3I5zKY3E+ov7/ZhW6DqT8UFvsAdjvQbXyhV8Eu\r\n\tYhixw1aKEPzNjNowuIseVogKOLXxWI5vAi5HgXdS0/ES5gDGsABo4fqovUKlgop3\r\n\tRA==\r\n\t-----END CERTIFICATE-----\r\n\r\n";
+  assert(test_error(dumbfuck2));
+
+  assert(test_request(&fragment_in_uri));
+
+  /* TODO sending junk and large headers gets rejected */
+
+
+  /* check to make sure our predefined requests are okay */
+
+  assert(test_request(&get_no_headers_no_body));
+  assert(test_request(&get_one_header_no_body));
+  assert(test_request(&get_no_headers_no_body));
+
+  // no content-length
+  const char *bad_get_no_headers_no_body = "GET /bad_get_no_headers_no_body/world HTTP/1.1\r\nAccept: */*\r\nHELLO\r\n";
+  assert(test_error(bad_get_no_headers_no_body)); // error if there is a body without content length
+
+  assert(test_request(&get_funky_content_length_body_hello));
+  assert(test_request(&post_identity_body_world));
+  assert(test_request(&post_chunked_all_your_base));
+  assert(test_request(&two_chunks_mult_zero_end));
+  assert(test_request(&chunked_w_trailing_headers));
+
+  assert(test_request(&chunked_w_bullshit_after_length));
+  assert(1 == requests[0].request.version_major); 
+  assert(1 == requests[0].request.version_minor);
+
+  // three requests - no bodies
+  assert( test_multiple3( &get_no_headers_no_body
+                        , &get_one_header_no_body
+                        , &get_no_headers_no_body
+                        ));
+
+  // three requests - one body
+  assert( test_multiple3(&get_no_headers_no_body, &get_funky_content_length_body_hello, &get_no_headers_no_body));
+
+  // three requests with bodies -- last is chunked
+  assert( test_multiple3(&get_funky_content_length_body_hello, &post_identity_body_world, &post_chunked_all_your_base));
+
+  // three chunked requests
+  assert( test_multiple3(&two_chunks_mult_zero_end, &post_chunked_all_your_base, &chunked_w_trailing_headers));
+
+
+  assert(test_scan2(&get_no_headers_no_body, &get_one_header_no_body, &get_no_headers_no_body));
+  assert(test_scan2(&get_funky_content_length_body_hello, &post_identity_body_world, &post_chunked_all_your_base));
+  assert(test_scan2(&two_chunks_mult_zero_end, &chunked_w_trailing_headers, &chunked_w_bullshit_after_length));
+
+  assert(test_scan3(&get_no_headers_no_body, &get_one_header_no_body, &get_no_headers_no_body));
+  assert(test_scan3(&get_funky_content_length_body_hello, &post_identity_body_world, &post_chunked_all_your_base));
+  assert(test_scan3(&two_chunks_mult_zero_end, &chunked_w_trailing_headers, &chunked_w_bullshit_after_length));
+
+
+  printf("okay\n");
+  return 0;
+}
+
diff --git a/deps/liboi/LICENSE b/deps/liboi/LICENSE
new file mode 100644
index 0000000..a5a6e01
--- /dev/null
+++ b/deps/liboi/LICENSE
@@ -0,0 +1,23 @@
+liboi is Copyright (C) 2009 Ryan Dahl.
+
+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.
+
+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.
diff --git a/deps/liboi/README b/deps/liboi/README
new file mode 100644
index 0000000..0609ab4
--- /dev/null
+++ b/deps/liboi/README
@@ -0,0 +1,36 @@
+liboi is a C library for doing evented I/O. It is intended for building
+efficent internet programs.
+
+liboi is released under the X11 license.
+
+= Feature Summary
+ 
+ * The library has a minimalist design
+   - Does not make internal allocations 
+   - Does not wrap functionality of GnuTLS or libev. The user must use those
+     libraries in conjuction with liboi. 
+ * Supports both server and client sockets.
+ * Supports evented file I/O emulation through a thread pool.
+ * SSL support 
+ * Sendfile (file to socket) with emulation on platforms that do not support
+   it.
+
+= Building
+
+ 1 Edit config.mk. You almost certainly will need to set the EVDIR and
+   GNUTLSDIR variables.
+ 2 Run "make"
+
+= Documentation
+
+ 1 make doc
+ 2 man ./oi.3
+
+= Website 
+
+http://github.com/ry/liboi
+
+= Author 
+
+Ryan Dahl (ry@tinyclouds.org)
+
diff --git a/deps/liboi/config.mk b/deps/liboi/config.mk
new file mode 100644
index 0000000..311f8cb
--- /dev/null
+++ b/deps/liboi/config.mk
@@ -0,0 +1,33 @@
+# Define EVDIR=/foo/bar if your libev header and library files are in
+# /foo/bar/include and /foo/bar/lib directories.
+EVDIR=$(HOME)/local/libev
+
+# Define GNUTLSDIR=/foo/bar if your gnutls header and library files are in
+# /foo/bar/include and /foo/bar/lib directories.
+#GNUTLSDIR=/usr
+#
+#
+# Define NO_PREAD if you have a problem with pread() system call (e.g.
+# cygwin.dll before v1.5.22).
+#
+#
+# Define NO_SENDFILE if you have a problem with the sendfile() system call
+#
+#
+
+uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
+uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not')
+uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not')
+uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
+uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not')
+
+# CFLAGS and LDFLAGS are for the users to override from the command line.
+CFLAGS	= -g
+LDFLAGS	= 
+
+PREFIX = $(HOME)/local/liboi
+
+CC = gcc
+AR = ar
+RM = rm -f
+RANLIB = ranlib
diff --git a/deps/liboi/oi.h b/deps/liboi/oi.h
new file mode 100644
index 0000000..c7145ea
--- /dev/null
+++ b/deps/liboi/oi.h
@@ -0,0 +1,8 @@
+#ifndef oi_h
+#define oi_h
+
+#include <oi_socket.h>
+#include <oi_async.h>
+#include <oi_file.h>
+
+#endif
diff --git a/deps/liboi/oi.pod b/deps/liboi/oi.pod
new file mode 100644
index 0000000..8b07115
--- /dev/null
+++ b/deps/liboi/oi.pod
@@ -0,0 +1,278 @@
+=head1 NAME
+
+liboi - a C library for doing evented I/O.
+
+=head1 SYNOPSIS
+
+    #include <oi.h>
+
+=head1 DESCRIPTION
+
+liboi is an object oriented library for doing evented socket and file I/O.
+The API is mostly about registering callbacks to be executed on certain
+events.
+
+Because most systems do not support asynchornous file I/O, the behavior is
+emulated with an internal thread pool. The thread pool is accessed with the
+C<oi_async> and C<oi_task> objects. Typically one will not need to use these
+directly as C<oi_file> wraps that functionality. 
+
+=head2 CONVENTIONS
+
+liboi's goal is to be very simple layer above the POSIX API. To that end it
+avoids internal allocations as much as possible. Unless otherwise noted you
+should assume all pointers passed into liboi will remain your responsibility
+to maintain.  That means you should not free the data passed into liboi
+until the object in question has completed.
+
+C<oi_socket> and C<oi_file> objects must be attached to an event loop. This
+is completed with the C<*_attach> and C<*_detach>  methods. When an object
+is detached, other methods can be called - just the loop will not churn out
+callbacks.
+
+Both C<oi_socket> and C<oi_file> contain a number of callback pointers.
+These are to be set manually after calling their initalization functions.
+All classes include a C<void *data> member which is left for you to use.
+
+=head1 ERROR HANDLING
+
+
+=head1 Sockets
+
+The C<oi_socket> structure represents a socket.
+The callbacks inside C<oi_socket> are 
+    void (*on_connect)   (oi_socket *);
+    void (*on_read)      (oi_socket *, const void *buf, size_t count);
+    void (*on_drain)     (oi_socket *);
+    void (*on_error)     (oi_socket *, struct oi_error e);
+    void (*on_close)     (oi_socket *);
+    void (*on_timeout)   (oi_socket *);
+
+A the memory for a socket is released when the C<on_close()> callback is
+made. That is, the user may free the memory for the socket with-in the
+C<on_close()> callback.
+
+=over 4
+
+=item void oi_socket_init (oi_socket *, float timeout);
+
+Initialize a socket. C<timeout> is the number of seconds of inactivity that
+is allowed before the socket closes. The timeout only starts once the
+socket is attached to a loop and open.
+
+A C<timeout> argument of 0.0 signals that no timeout should be used.
+
+After calling this function, register your callbacks manually. Thus your
+code will probably look like this 
+    oi_socket socket;
+    oi_socket_init(&socket, 60.0);
+    socket.on_connect = my_on_connect;
+    socket.on_read = my_on_read;
+    /* etc */
+
+
+=item int oi_socket_connect (oi_socket *, struct addrinfo *addrinfo);
+
+Open a client connect to the specified address. When the connection is made
+C<socket.on_connect> will be called. 
+
+Here is an example of filling in C<addrinfo> for a local TCP connection on
+port 5555:
+    struct addrinfo *servinfo;
+    struct addrinfo hints;
+    memset(&hints, 0, sizeof hints);
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_flags = AI_PASSIVE;
+    r = getaddrinfo(NULL, "5555", &hints, &servinfo);
+    assert(r == 0);
+    oi_socket_connect(socket, servinfo);
+
+=item void oi_socket_attach (oi_socket *, struct ev_loop *loop);
+
+A socket must be attached to a loop in order before any callbacks will be
+made. 
+
+=item void oi_socket_detach (oi_socket *);
+
+Detaching a socket will not close the connection.
+
+=item void oi_socket_read_start (oi_socket *);
+
+This will make the socket start receiving data. When data is received the
+C<socket.on_read> callback is made. The maximum amount of data that can be
+receive at a time is controlled by C<socket.chunksize>. 
+
+The buffer returned by C<socket.on_read> is statically allocated exists only
+for the length of the callback. That means if you need to save any of the
+data coming down the line, you must copy it to a new buffer. 
+
+Ideally you will have a parser attached to the C<on_read> callback which can
+be interrupted at any time. 
+
+C<socket.chunksize> can be changed at any time.
+
+=item void oi_socket_read_stop (oi_socket *);
+
+Stops receiving data. You may receive spurious C<on_read> attempts even
+though the socket reading is stopped - be prepared to handle them. 
+
+=item void oi_socket_reset_timeout (oi_socket *);
+
+Reset the timeout to allow the socket to exist for another few seconds
+(however long you specified in the initialization function).  
+
+=item void oi_socket_write (oi_socket *socket, oi_buf *buf);
+
+Write the I<buf> to the socket. Each socket has a queue of C<oi_buf> objects
+to be written - this appends the specified buffer to the end of that queue.
+You will be notified when the queue is empty with the C<socket.on_drain()>
+callback. When the socket has written the buffer C<buf.release()> will be
+called. The release callback does not imply that the buffer was successfully
+written.
+
+=item void oi_socket_write_simple (oi_socket *, const char *str, size_t len);
+
+Sometimes you are just hacking around and need to quickly write a string to
+the socket. This convenience function allocates an C<oi_buf> object, and
+C<strdup>s  the given string. The allocated buffer will be freed by liboi
+internally. 
+
+Most production most applications will use their own memory pool and will
+not need this function. 
+
+=item void oi_socket_write_eof (oi_socket *);
+
+This closes the write end of the socket. Further writes are not allowed
+after this. 
+
+=item void oi_socket_close (oi_socket *);
+
+Attempts to close the socket. 
+
+If the socket is secure, an SSL bye message will be sent. 
+SSL recommends that you wait for a bye response from the peer however this
+tends to be overkill for most people. By default liboi will not wait for
+peer to send a matching bye message. If you require this then set
+C<socket.wait_for_secure_hangup> to 1.
+
+When the close is complete C<on_close()> is made. The C<on_close()>
+callback is not made until the program returns to the event loop. This is
+because C<on_close()> may free the socket memory and if C<on_close()> was
+called from C<oi_socket_close()>, then the socket object might unexpectedly
+be gone. To summarize: C<oi_socket_close()> does not call C<on_close()> and
+the socket memory is still accessable immediately after making calling
+C<oi_socket_close()>. 
+
+=item void oi_socket_set_secure_session (oi_socket *, gnutls_session_t);
+
+This make a socket use SSL. You must create the GnuTLS session yourself and
+assign its credentials.
+
+=back
+
+=head1 Servers
+
+A server simply listens on an address for new connections. The connections
+come in the form of C<oi_socket> objects. The key is to give a
+C<server.on_connection()> callback which returns an initialized C<oi_socket>.
+The callback looks like this 
+
+    oi_socket* (*on_connection) (oi_server *, struct sockaddr *remote_addr, socklen_t remove_addr_len);
+
+Returning NULL from C<on_connection()> will reject the connection.
+
+=over 4
+
+=item void oi_server_init (oi_server *, int backlog);
+
+Initializes a server object. C<backlog> is the argument given
+internally to C<listen()>. Set the C<server.on_connection()> callback
+after calling this.
+
+=item int oi_server_listen (oi_server *, struct addrinfo *addrinfo);
+
+Listens on the specified address. The server will not accept connections
+until it is attached to a loop, however.
+
+=item void oi_server_attach (oi_server *, struct ev_loop *loop);
+
+Attaches a server to a loop. 
+
+=item void oi_server_detach (oi_server *);
+
+Detaches a server to a loop. Does not close the server.
+
+=item void oi_server_close (oi_server *); 
+
+Stops the server from listening. 
+
+=back
+
+=head1 Files
+
+Files internally use a thread pool to operate without blocking.
+The thread pool is started once a file is attached and it continues until
+program termination. 
+
+The following callbacks are used inside of the file object
+    void (*on_open)  (oi_file *);
+    void (*on_read)  (oi_file *, size_t count);
+    void (*on_drain) (oi_file *);
+    void (*on_error) (oi_file *, struct oi_error);
+    void (*on_close) (oi_file *);
+
+=over 4
+
+=item int oi_file_init (oi_file *);
+
+Initializes a file object.
+
+=item void oi_file_attach (oi_file *, struct ev_loop *);
+
+Attaches a file object to a loop. If the thread pool has not been started,
+then it is started at this call. 
+
+=item void oi_file_detach (oi_file *);
+
+Detaches a file object from the loop.
+
+=item int  oi_file_open_path (oi_file *, const char *path, int flags, mode_t mode);
+
+Opens a file specified by the path. The C<flag> and C<mode> arguments are
+the same as used by L<open.2>. The C<file.on_open> callback is triggered
+when the file is opened. Returns 0 on success. Returns -1 if the given file
+is already open.
+
+WARNING: path argument must be valid until C<oi_file> object is closed and
+the C<file.on_close()> callback is made. I.E., liboi does not strdup the path
+pointer. 
+
+=item int oi_file_open_stdin (oi_file *);
+
+=item int oi_file_open_stdout (oi_file *);
+
+=item int oi_file_open_stderr (oi_file *);
+
+=item void oi_file_read_start (oi_file *, void *buffer, size_t bufsize);
+
+
+
+=item void oi_file_read_stop (oi_file *);
+
+=item int oi_file_write (oi_file *, oi_buf *to_write);
+
+=item int oi_file_write_simple (oi_file *, const char *, size_t);
+
+=item int oi_file_send (oi_file *source, oi_socket *destination, off_t offset, size_t length);
+
+=item void oi_file_close (oi_file *);
+
+=over 4
+
+=back
+
+=head1 AUTHOR
+
+Ryan Dahl <ry@tinyclouds.org>
+
diff --git a/deps/liboi/oi_async.c b/deps/liboi/oi_async.c
new file mode 100644
index 0000000..1d5459d
--- /dev/null
+++ b/deps/liboi/oi_async.c
@@ -0,0 +1,486 @@
+#include <stdlib.h> /* malloc()        */
+#include <stdio.h>  /* perror()        */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h> /* read(), write() */
+#include <fcntl.h>
+#include <errno.h>
+#include <assert.h>
+#include <pthread.h>
+
+#if HAVE_SENDFILE
+# if __linux
+#  include <sys/sendfile.h>
+# elif __freebsd
+#  include <sys/socket.h>
+#  include <sys/uio.h>
+# elif __hpux
+#  include <sys/socket.h>
+# elif __solaris /* not yet */
+#  include <sys/sendfile.h>
+# else
+#  error sendfile support requested but not available
+# endif
+#endif
+
+#include <ev.h>
+#include <oi.h>
+
+#define NWORKERS 4 
+/* TODO make adjustable 
+ * once it is fix sleeping_tasks
+ */
+
+static int active_watchers = 0;
+static int active_workers = 0;
+static int readiness_pipe[2] = {-1, -1};
+static oi_queue waiting_tasks;
+static pthread_mutex_t queue_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t finished_lock = PTHREAD_MUTEX_INITIALIZER;
+
+struct worker {
+  oi_task *task;
+  pthread_t thread;
+  pthread_attr_t thread_attr;
+};
+
+/* Sendfile and pread emulation come from Marc Lehmann's libeio and are
+ * Copyright (C)2007,2008 Marc Alexander Lehmann.
+ * Many ideas of oi_async.* are taken from libeio and in fact, I plan to
+ * use libeio once it becomes usable for me. (The problem is issuing tasks
+ * from multiple threads.)
+ */
+
+#if !HAVE_PREADWRITE
+/*
+ * make our pread/pwrite emulation safe against themselves, but not against
+ * normal read/write by using a mutex. slows down execution a lot,
+ * but that's your problem, not mine.
+ */
+static pthread_mutex_t preadwritelock = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+#if !HAVE_PREADWRITE
+# undef pread
+# undef pwrite
+# define pread  eio__pread
+# define pwrite eio__pwrite
+
+static ssize_t
+eio__pread (int fd, void *buf, size_t count, off_t offset)
+{
+  ssize_t res;
+  off_t ooffset;
+
+  pthread_mutex_lock(&preadwritelock);
+    ooffset = lseek (fd, 0, SEEK_CUR);
+    lseek (fd, offset, SEEK_SET);
+    res = read (fd, buf, count);
+    lseek (fd, ooffset, SEEK_SET);
+  pthread_mutex_unlock(&preadwritelock);
+
+  return res;
+}
+
+static ssize_t
+eio__pwrite (int fd, void *buf, size_t count, off_t offset)
+{
+  ssize_t res;
+  off_t ooffset;
+
+  pthread_mutex_lock(&preadwritelock);
+    ooffset = lseek (fd, 0, SEEK_CUR);
+    lseek (fd, offset, SEEK_SET);
+    res = write (fd, buf, count);
+    lseek (fd, offset, SEEK_SET);
+  pthread_mutex_unlock(&preadwritelock);
+
+  return res;
+}
+#endif
+
+
+/* sendfile always needs emulation */
+static ssize_t
+eio__sendfile (int ofd, int ifd, off_t offset, size_t count)
+{
+  ssize_t res;
+
+  if (!count)
+    return 0;
+
+#if HAVE_SENDFILE
+# if __linux
+  res = sendfile (ofd, ifd, &offset, count);
+
+# elif __freebsd
+  /*
+   * Of course, the freebsd sendfile is a dire hack with no thoughts
+   * wasted on making it similar to other I/O functions.
+   */
+  {
+    off_t sbytes;
+    res = sendfile (ifd, ofd, offset, count, 0, &sbytes, 0);
+
+    if (res < 0 && sbytes)
+      /* maybe only on EAGAIN: as usual, the manpage leaves you guessing */
+      res = sbytes;
+  }
+
+# elif __hpux
+  res = sendfile (ofd, ifd, offset, count, 0, 0);
+
+# elif __solaris
+  {
+    struct sendfilevec vec;
+    size_t sbytes;
+
+    vec.sfv_fd   = ifd;
+    vec.sfv_flag = 0;
+    vec.sfv_off  = offset;
+    vec.sfv_len  = count;
+
+    res = sendfilev (ofd, &vec, 1, &sbytes);
+
+    if (res < 0 && sbytes)
+      res = sbytes;
+  }
+
+# endif
+#else
+  res = -1;
+  errno = ENOSYS;
+#endif
+
+  if (res <  0
+    && (errno == ENOSYS || errno == EINVAL || errno == ENOTSOCK
+#if __solaris
+      || errno == EAFNOSUPPORT || errno == EPROTOTYPE
+#endif
+       )
+     )
+  {
+    /* emulate sendfile. this is a major pain in the ass */
+/* buffer size for various temporary buffers */
+#define EIO_BUFSIZE 65536
+    char *eio_buf = malloc (EIO_BUFSIZE);
+    errno = ENOMEM;
+    if (!eio_buf)
+      return -1;
+
+    res = 0;
+
+    while (count) {
+      ssize_t cnt;
+      
+      cnt = pread (ifd, eio_buf, count > EIO_BUFSIZE ? EIO_BUFSIZE : count, offset);
+
+      if (cnt <= 0) {
+        if (cnt && !res) res = -1;
+        break;
+      }
+
+      cnt = write (ofd, eio_buf, cnt);
+
+      if (cnt <= 0) {
+        if (cnt && !res) res = -1;
+        break;
+      }
+
+      offset += cnt;
+      res    += cnt;
+      count  -= cnt;
+    }
+
+    free(eio_buf);
+  }
+
+  return res;
+}
+
+static oi_task*
+queue_shift(pthread_mutex_t *lock, oi_queue *queue)
+{
+  oi_queue *last = NULL;
+  pthread_mutex_lock(lock);
+    if(!oi_queue_empty(queue)) {
+      last = oi_queue_last(queue);
+      oi_queue_remove(last); 
+    }
+  pthread_mutex_unlock(lock);
+
+  if(last == NULL) 
+    return NULL;
+
+  return oi_queue_data(last, oi_task, queue);
+}
+
+#define P1(name,a) { \
+  t->params.name.result = name( t->params.name.a ); \
+  break; \
+}
+
+#define P2(name,a,b) { \
+  t->params.name.result = name( t->params.name.a \
+                              , t->params.name.b \
+                              ); \
+  break; \
+}
+
+#define P3(name,a,b,c) { \
+  t->params.name.result = name( t->params.name.a \
+                              , t->params.name.b \
+                              , t->params.name.c \
+                              ); \
+  break; \
+}
+
+#define P4(name,a,b,c,d) { \
+  t->params.name.result = name( t->params.name.a \
+                              , t->params.name.b \
+                              , t->params.name.c \
+                              , t->params.name.d \
+                              ); \
+  break; \
+}
+
+static void
+execute_task(oi_task *t)
+{
+  errno = 0;
+  switch(t->type) {
+    case OI_TASK_OPEN:        P3(open, pathname, flags, mode);
+    case OI_TASK_READ:        P3(read, fd, buf, count);
+    case OI_TASK_WRITE:       P3(write, fd, buf, count);
+    case OI_TASK_CLOSE:       P1(close, fd);
+    case OI_TASK_SLEEP:       P1(sleep, seconds);
+    case OI_TASK_SENDFILE:    P4(eio__sendfile, out_fd, in_fd, offset, count);
+    case OI_TASK_GETADDRINFO: P4(getaddrinfo, nodename, servname, hints, res);
+    case OI_TASK_LSTAT:       P2(lstat, path, buf);
+    default: 
+      assert(0 && "unknown task type");
+      break;
+  }
+  t->errorno = errno;
+}
+
+static void
+attempt_to_get_a_task(struct worker *worker)
+{
+  char dummy;
+  assert(readiness_pipe[0] > 0);
+  int r = read(readiness_pipe[0], &dummy, 1);
+  if(r == -1 && (errno != EAGAIN || errno != EINTR)) {
+    perror("read(readiness_pipe[0])");
+    return;
+  }
+
+  // 1 pop task from queue
+  assert(worker->task == NULL);
+  oi_task *task =  queue_shift(&queue_lock, &waiting_tasks);
+  if(task == NULL) return;
+  worker->task = task;
+  
+  // 2 run task
+  execute_task(task);
+  
+  // 3 notify complition
+  oi_async *async = task->async;
+  assert(async != NULL);
+  pthread_mutex_lock(&finished_lock);
+    oi_queue_insert_head(&async->finished_tasks, &task->queue);
+  pthread_mutex_unlock(&finished_lock);
+  ev_async_send(async->loop, &async->watcher);
+  worker->task = NULL;
+
+  /* attempt to pull another task */
+  return attempt_to_get_a_task(worker);
+}
+
+void *
+worker_loop(void *data)
+{
+  int r;
+  struct worker *worker = data;
+  fd_set readfds;
+  FD_ZERO(&readfds);
+  FD_SET(readiness_pipe[0], &readfds);
+
+  active_workers++;
+  assert(active_workers <= NWORKERS);
+
+  while(1) {
+    r = select(1+readiness_pipe[0], &readfds, 0, 0, 0);
+    if(r == -1) break;
+    attempt_to_get_a_task(worker);
+  }
+  active_workers--;
+
+  return NULL;
+}
+
+static struct worker*
+worker_new()
+{
+  int r;
+  struct worker *worker = calloc(sizeof(struct worker), 1);
+  if(worker == NULL ) { return NULL; }
+
+  worker->task = NULL;
+  pthread_attr_setdetachstate(&worker->thread_attr, PTHREAD_CREATE_DETACHED);
+
+  r = pthread_create( &worker->thread
+                    , NULL // &worker->thread_attr
+                    , worker_loop
+                    , worker
+                    ); 
+  if(r != 0) {
+    /* TODO: error checking */
+    perror("pthread_create");
+    goto error; 
+  }
+
+  return worker;
+error:
+  free(worker);
+  return NULL;
+}
+
+static void
+start_workers()
+{
+  assert(readiness_pipe[0] == -1);
+  assert(readiness_pipe[1] == -1);
+  assert(active_workers == 0);
+
+  int r = pipe(readiness_pipe);
+  if(r < 0) {
+    perror("pipe()");
+    assert(0 && "TODO HANDLE ME"); 
+  }
+
+  /* set the write end non-blocking */
+  int flags = fcntl(readiness_pipe[1], F_GETFL, 0);
+  r = fcntl(readiness_pipe[1], F_SETFL, flags | O_NONBLOCK);
+  if(r < 0) {
+    assert(0 && "error setting pipe to non-blocking?");
+    /* TODO error report */
+  }
+
+  oi_queue_init(&waiting_tasks);
+
+  int i;
+  for(i = 0; i < NWORKERS; i++)
+    worker_new();
+}
+
+/*
+static void
+stop_workers()
+{
+  assert(0 && "TODO implement me");
+}
+*/
+
+static void
+on_completion(struct ev_loop *loop, ev_async *watcher, int revents)
+{
+  oi_async *async = watcher->data;
+  oi_task *task;
+
+  while((task = queue_shift(&finished_lock, &async->finished_tasks))) {
+    assert(task->active);
+    task->active = 0;
+    errno = task->errorno;
+#   define done_cb(kind) { \
+      assert(task->params.kind.cb); \
+      task->params.kind.cb(task, task->params.kind.result); \
+      break; \
+    }
+    switch(task->type) {
+      case OI_TASK_OPEN:  done_cb(open);
+      case OI_TASK_READ:  done_cb(read);
+      case OI_TASK_WRITE: done_cb(write);
+      case OI_TASK_CLOSE: done_cb(close);
+      case OI_TASK_SLEEP: done_cb(sleep);
+      case OI_TASK_SENDFILE: done_cb(eio__sendfile);
+      case OI_TASK_GETADDRINFO: done_cb(getaddrinfo);
+      case OI_TASK_LSTAT: done_cb(lstat);
+    }
+    /* the task is possibly freed by callback. do not access it again. */
+  }
+}
+
+void
+oi_async_init (oi_async *async)
+{
+  ev_async_init(&async->watcher, on_completion);
+
+  oi_queue_init(&async->finished_tasks);
+  oi_queue_init(&async->new_tasks);
+
+  async->watcher.data = async;
+}
+
+static void
+dispatch_tasks(oi_async *async)
+{
+  while(!oi_queue_empty(&async->new_tasks)) {
+      oi_queue *last = oi_queue_last(&async->new_tasks);
+    oi_queue_remove(last);
+    oi_task *task = oi_queue_data(last, oi_task, queue);
+
+    // 1. add task to task queue.
+    pthread_mutex_lock(&queue_lock);
+      oi_queue_insert_head(&waiting_tasks, &task->queue);
+    pthread_mutex_unlock(&queue_lock);
+    
+    // 2. write byte to pipe
+    char dummy;
+    int written = write(readiness_pipe[1], &dummy, 1);
+
+    // 3. TODO make sure byte is written
+    assert(written == 1);
+  }
+}
+
+void
+oi_async_attach (struct ev_loop *loop, oi_async *async)
+{
+  if(active_watchers == 0 && active_workers == 0)
+    start_workers();
+  active_watchers++;
+
+  ev_async_start(loop, &async->watcher);
+  async->loop = loop;
+
+  dispatch_tasks(async);
+}
+
+void
+oi_async_detach (oi_async *async)
+{
+  if(async->loop == NULL)
+    return;
+  ev_async_stop(async->loop, &async->watcher);
+  async->loop = NULL;
+  active_watchers--;
+  if(active_watchers == 0) {
+    //stop_workers();
+  }
+}
+
+void
+oi_async_submit (oi_async *async, oi_task *task)
+{
+  assert(!task->active);
+  assert(task->async == NULL);
+  task->async = async;
+  task->active = 1;
+
+  oi_queue_insert_head(&async->new_tasks, &task->queue);
+  if(ev_is_active(&async->watcher)) {
+    dispatch_tasks(async);
+  }
+}
+
diff --git a/deps/liboi/oi_async.h b/deps/liboi/oi_async.h
new file mode 100644
index 0000000..f3ba937
--- /dev/null
+++ b/deps/liboi/oi_async.h
@@ -0,0 +1,218 @@
+#include <ev.h>
+#include <pthread.h>
+#include <netdb.h>
+#include <oi.h>
+
+#ifndef oi_async_h
+#define oi_async_h
+#ifdef __cplusplus
+extern "C" {
+#endif 
+
+typedef struct oi_async oi_async;
+typedef struct oi_task  oi_task;
+
+struct oi_async {
+  /* private */
+  ev_async watcher;  
+  struct ev_loop *loop;
+
+  oi_queue finished_tasks;
+  oi_queue new_tasks;
+
+  /* public */
+  void *data;
+}; 
+
+typedef void (*oi_task_int_cb)(oi_task *, int result);
+typedef void (*oi_task_uint_cb)(oi_task *, unsigned int result);
+typedef void (*oi_task_ssize_cb)(oi_task *, ssize_t result);
+
+struct oi_task {
+  /* private */
+  oi_async *async;
+  oi_queue queue;
+  int type;
+  union {
+
+    struct {
+      const char *pathname;
+      int flags;
+      mode_t mode;
+      oi_task_int_cb cb;
+      int result;
+    } open;
+
+    struct {
+      int fd;
+      void *buf;
+      size_t count;
+      oi_task_ssize_cb cb;
+      ssize_t result;
+    } read;
+
+    struct {
+      int fd;
+      const void *buf;
+      size_t count;
+      oi_task_ssize_cb cb;
+      ssize_t result;
+    } write;
+
+    struct {
+      int fd;
+      oi_task_int_cb cb;
+      int result;
+    } close;
+
+    struct {
+      unsigned int seconds;
+      oi_task_uint_cb cb;
+      unsigned int result;
+    } sleep;
+
+    struct {
+      int out_fd;
+      int in_fd;
+      off_t offset;
+      size_t count;
+      oi_task_ssize_cb cb;
+      ssize_t result;
+    } eio__sendfile;
+
+    struct {
+      const char *nodename; /* restrict ? */
+      const char *servname; /* restrict ? */
+      struct addrinfo *hints;
+      struct addrinfo **res; /* restrict ? */
+      oi_task_int_cb cb;
+      int result;
+    } getaddrinfo;
+
+    struct {
+      const char *path;
+      struct stat *buf;
+      oi_task_int_cb cb;
+      int result;
+    } lstat;
+    
+  } params;
+
+  /* read-only */
+  volatile unsigned active:1;
+  int errorno;
+
+  /* public */
+  void *data;
+}; 
+
+void oi_async_init    (oi_async *);
+void oi_async_attach  (struct ev_loop *loop, oi_async *);
+void oi_async_detach  (oi_async *);
+void oi_async_submit  (oi_async *, oi_task *);
+
+/* To submit a task for async processing
+ * (0) allocate memory for your task
+ * (1) initialize the task with one of the functions below
+ * (2) optionally set the task->data pointer
+ * (3) oi_async_submit() the task 
+ */
+
+enum { OI_TASK_OPEN
+     , OI_TASK_READ
+     , OI_TASK_WRITE
+     , OI_TASK_CLOSE
+     , OI_TASK_SLEEP
+     , OI_TASK_SENDFILE
+     , OI_TASK_GETADDRINFO
+     , OI_TASK_LSTAT
+     };
+
+#define oi_task_init_common(task, _type) do {\
+  (task)->active = 0;\
+  (task)->async = NULL;\
+  (task)->type = _type;\
+} while(0)
+
+static inline void 
+oi_task_init_open(oi_task *t, oi_task_int_cb cb, const char *pathname, int flags, mode_t mode) 
+{
+  oi_task_init_common(t, OI_TASK_OPEN);
+  t->params.open.cb = cb;
+  t->params.open.pathname = pathname;
+  t->params.open.flags = flags;
+  t->params.open.mode = mode;
+}
+
+static inline void 
+oi_task_init_read(oi_task *t, oi_task_ssize_cb cb, int fd, void *buf, size_t count) 
+{
+  oi_task_init_common(t, OI_TASK_READ);
+  t->params.read.cb = cb;
+  t->params.read.fd = fd;
+  t->params.read.buf = buf;
+  t->params.read.count = count;
+}
+
+static inline void 
+oi_task_init_write(oi_task *t, oi_task_ssize_cb cb, int fd, const void *buf, size_t count) 
+{
+  oi_task_init_common(t, OI_TASK_WRITE);
+  t->params.write.cb = cb;
+  t->params.write.fd = fd;
+  t->params.write.buf = buf;
+  t->params.write.count = count;
+}
+
+static inline void 
+oi_task_init_close(oi_task *t, oi_task_int_cb cb, int fd) 
+{
+  oi_task_init_common(t, OI_TASK_CLOSE);
+  t->params.close.cb = cb;
+  t->params.close.fd = fd;
+}
+
+static inline void 
+oi_task_init_sleep(oi_task *t, oi_task_uint_cb cb, unsigned int seconds) 
+{
+  oi_task_init_common(t, OI_TASK_SLEEP);
+  t->params.sleep.cb = cb;
+  t->params.sleep.seconds = seconds;
+}
+
+static inline void 
+oi_task_init_sendfile(oi_task *t, oi_task_ssize_cb cb, int out_fd, int in_fd, off_t offset, size_t count) 
+{
+  oi_task_init_common(t, OI_TASK_SENDFILE);
+  t->params.eio__sendfile.cb = cb;
+  t->params.eio__sendfile.out_fd = out_fd;
+  t->params.eio__sendfile.in_fd = in_fd;
+  t->params.eio__sendfile.offset = offset;
+  t->params.eio__sendfile.count = count;
+}
+
+static inline void 
+oi_task_init_getaddrinfo(oi_task *t, oi_task_int_cb cb, const char *node, 
+                          const char *service, struct addrinfo *hints, struct addrinfo **res) 
+{
+  oi_task_init_common(t, OI_TASK_GETADDRINFO);
+  t->params.getaddrinfo.cb = cb;
+  t->params.getaddrinfo.nodename = node;
+  t->params.getaddrinfo.servname = service;
+  t->params.getaddrinfo.hints = hints;
+  t->params.getaddrinfo.res = res;
+}
+
+static inline void 
+oi_task_init_lstat(oi_task *t, oi_task_int_cb cb, const char *path, struct stat *buf) 
+{
+  oi_task_init_common(t, OI_TASK_LSTAT);
+  t->params.lstat.cb = cb;
+  t->params.lstat.path = path;
+  t->params.lstat.buf = buf;
+}
+
+#ifdef __cplusplus
+}
+#endif 
+#endif /* oi_async_h */
diff --git a/deps/liboi/oi_buf.c b/deps/liboi/oi_buf.c
new file mode 100644
index 0000000..a192f7d
--- /dev/null
+++ b/deps/liboi/oi_buf.c
@@ -0,0 +1,41 @@
+#include <oi_buf.h>
+#include <stdlib.h>
+#include <string.h>
+
+void oi_buf_destroy 
+  ( oi_buf *buf
+  )
+{
+  free(buf->base);
+  free(buf);
+}
+
+oi_buf * oi_buf_new2
+  ( size_t len
+  )
+{
+  oi_buf *buf = malloc(sizeof(oi_buf));
+  if(!buf) 
+    return NULL;
+  buf->base = malloc(len);
+  if(!buf->base) {
+    free(buf);
+    return NULL; 
+  }
+  buf->len = len;
+  buf->release = oi_buf_destroy;
+  return buf;
+}
+
+oi_buf * oi_buf_new
+  ( const char *base
+  , size_t len
+  )
+{
+  oi_buf *buf = oi_buf_new2(len);
+  if(!buf) 
+    return NULL;
+  memcpy(buf->base, base, len);
+  return buf;
+}
+
diff --git a/deps/liboi/oi_buf.h b/deps/liboi/oi_buf.h
new file mode 100644
index 0000000..b810c05
--- /dev/null
+++ b/deps/liboi/oi_buf.h
@@ -0,0 +1,30 @@
+#include <oi_queue.h>
+
+#ifndef oi_buf_h
+#define oi_buf_h
+#ifdef __cplusplus
+extern "C" {
+#endif 
+
+typedef struct oi_buf oi_buf;
+
+struct oi_buf {
+  /* public */
+  char *base;
+  size_t len;
+  void (*release) (oi_buf *); /* called when oi is done with the object */
+  void *data;
+
+  /* private */
+  size_t written;
+  oi_queue queue;
+};
+
+oi_buf * oi_buf_new     (const char* base, size_t len);
+oi_buf * oi_buf_new2    (size_t len);
+void     oi_buf_destroy (oi_buf *);
+
+#ifdef __cplusplus
+}
+#endif 
+#endif // oi_buf_h
diff --git a/deps/liboi/oi_error.h b/deps/liboi/oi_error.h
new file mode 100644
index 0000000..0f8730f
--- /dev/null
+++ b/deps/liboi/oi_error.h
@@ -0,0 +1,25 @@
+#ifndef oi_error_h
+#define oi_error_h
+#ifdef __cplusplus
+extern "C" {
+#endif 
+
+struct oi_error {
+  enum { OI_ERROR_GNUTLS
+       , OI_ERROR_EV
+       , OI_ERROR_CLOSE
+       , OI_ERROR_SHUTDOWN
+       , OI_ERROR_OPEN
+       , OI_ERROR_SEND
+       , OI_ERROR_RECV
+       , OI_ERROR_WRITE
+       , OI_ERROR_READ
+       , OI_ERROR_SENDFILE
+       } domain;
+  int code; /* errno */
+};
+
+#ifdef __cplusplus
+}
+#endif 
+#endif // oi_error_h
diff --git a/deps/liboi/oi_file.c b/deps/liboi/oi_file.c
new file mode 100644
index 0000000..1073b08
--- /dev/null
+++ b/deps/liboi/oi_file.c
@@ -0,0 +1,391 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <ev.h>
+#include <oi.h>
+
+#define RELEASE_BUF(buf) if(buf->release) { buf->release(buf); }
+#define DRAIN_CB(file)   if(file->on_drain) { file->on_drain(file); }
+#define RAISE_ERROR(s, _domain, _code) do { \
+  if(s->on_error) { \
+    struct oi_error __oi_error; \
+    __oi_error.domain = _domain; \
+    __oi_error.code = _code; \
+    s->on_error(s, __oi_error); \
+  } \
+} while(0) \
+
+/* forwards */
+static void dispatch_write_buf (oi_file *file);
+static void maybe_do_read (oi_file *file);
+
+static void
+after_read(oi_task *task, ssize_t recved)
+{
+  oi_file *file = task->data;
+
+  if(recved == -1) {
+    RAISE_ERROR(file, OI_ERROR_READ, errno);
+    return;
+  }
+
+  if(recved == 0)
+    oi_file_read_stop(file);
+
+  if(file->on_read)
+    file->on_read(file, recved);
+
+  maybe_do_read(file);
+}
+
+static void
+maybe_do_read(oi_file *file)
+{
+  if ( file->read_buffer == NULL
+    || file->write_buf != NULL
+    || file->write_socket != NULL
+    || !oi_queue_empty(&file->write_queue)
+    || file->io_task.active
+     ) return;
+
+  assert(file->fd > 0);
+
+  oi_task_init_read ( &file->io_task
+                    , after_read
+                    , file->fd
+                    , file->read_buffer
+                    , file->read_buffer_size
+                    );
+  file->io_task.data = file;
+  oi_async_submit(&file->async, &file->io_task);
+}
+
+static void 
+submit_read (oi_file *file)
+{
+}
+
+int 
+oi_file_init (oi_file *file)
+{
+  oi_async_init(&file->async);
+  file->async.data = file;
+
+  oi_queue_init(&file->write_queue);
+
+  file->fd = -1;
+  file->loop = NULL;
+  file->write_buf = NULL;
+  file->read_buffer = NULL;
+
+  file->on_open = NULL;
+  file->on_read = NULL;
+  file->on_drain = NULL;
+  file->on_error = NULL;
+  file->on_close = NULL;
+  return 0;
+}
+
+void
+oi_file_read_start (oi_file *file, void *buffer, size_t bufsize)
+{
+  file->read_buffer = buffer;
+  file->read_buffer_size = bufsize;
+  maybe_do_read(file);
+}
+
+void
+oi_file_read_stop (oi_file *file)
+{
+  file->read_buffer = NULL;
+}
+
+void
+oi_api_free_buf_with_heap_base(oi_buf *buf)
+{
+  free(buf->base);
+  free(buf);
+}
+
+static void 
+after_open(oi_task *task, int result)
+{
+  oi_file *file = task->data;
+
+  if(result == -1) {
+    RAISE_ERROR(file, OI_ERROR_OPEN, errno);
+    return;
+  }
+
+  file->fd = result;
+
+  if(file->on_open) {
+    file->on_open(file);
+  }
+
+  maybe_do_read(file);
+}
+
+int
+oi_file_open_path (oi_file *file, const char *path, int flags, mode_t mode)
+{
+  if(file->fd >= 0)
+    return -1;
+  oi_task_init_open( &file->io_task
+                   , after_open
+                   , path
+                   , flags
+                   , mode 
+                   );
+  file->io_task.data = file;
+  oi_async_submit(&file->async, &file->io_task);
+  return 0;
+}
+
+int
+oi_file_open_stdin (oi_file *file)
+{
+  if(file->fd >= 0)
+    return -1;
+  file->fd = STDIN_FILENO;
+  if(file->on_open)
+    file->on_open(file);
+  return 0;
+}
+
+int
+oi_file_open_stdout (oi_file *file)
+{
+  if(file->fd >= 0)
+    return -1;
+  file->fd = STDOUT_FILENO;
+  if(file->on_open)
+    file->on_open(file);
+  return 0;
+}
+
+int
+oi_file_open_stderr (oi_file *file)
+{
+  if(file->fd >= 0)
+    return -1;
+  file->fd = STDERR_FILENO;
+  if(file->on_open)
+    file->on_open(file);
+  return 0;
+}
+
+void
+oi_file_attach (oi_file *file, struct ev_loop *loop)
+{
+  oi_async_attach (loop, &file->async);
+  file->loop = loop;
+}
+
+void
+oi_file_detach (oi_file *file)
+{
+  oi_async_detach (&file->async);
+  file->loop = NULL;
+}
+
+static void 
+after_write(oi_task *task, ssize_t result)
+{
+  oi_file *file = task->data;
+
+  if(result == -1) {
+    RAISE_ERROR(file, OI_ERROR_WRITE, errno);
+    return;
+  }
+
+  assert(file->write_buf != NULL);
+  oi_buf *buf = file->write_buf;
+
+  buf->written += result;
+  if(buf->written < buf->len) {
+    oi_task_init_write ( &file->io_task
+                       , after_write
+                       , file->fd
+                       , buf->base + buf->written
+                       , buf->len - buf->written
+                       );
+    file->io_task.data = file;
+    oi_async_submit(&file->async, &file->io_task);
+    return;
+  }
+
+  assert(buf->written == buf->len);
+
+  RELEASE_BUF(file->write_buf);
+  file->write_buf = NULL;
+
+  if(oi_queue_empty(&file->write_queue)) {
+    DRAIN_CB(file);
+    maybe_do_read(file);
+  } else {
+    dispatch_write_buf(file);
+  }
+
+  return;
+}
+
+static void
+dispatch_write_buf(oi_file *file)
+{
+  if(file->write_buf != NULL)
+    return;
+  if(oi_queue_empty(&file->write_queue)) 
+    return;
+
+  oi_queue *q = oi_queue_last(&file->write_queue);
+  oi_queue_remove(q);
+  oi_buf *buf = file->write_buf = oi_queue_data(q, oi_buf, queue);
+
+  assert(!file->io_task.active);
+  oi_task_init_write ( &file->io_task
+                     , after_write
+                     , file->fd
+                     , buf->base + buf->written
+                     , buf->len - buf->written
+                     );
+  file->io_task.data = file;
+  oi_async_submit(&file->async, &file->io_task);
+}
+
+int
+oi_file_write (oi_file *file, oi_buf *buf)
+{
+  if(file->fd < 0)
+    return -1;
+  if(file->read_buffer)
+    return -2;
+  /* TODO better business check*/
+
+  buf->written = 0;
+  oi_queue_insert_head(&file->write_queue, &buf->queue);
+  dispatch_write_buf(file);
+
+  return 0;
+}
+
+// Writes a string to the file. 
+// NOTE: Allocates memory. Avoid for performance applications.
+int
+oi_file_write_simple (oi_file *file, const char *str, size_t len)
+{
+  if(file->fd < 0)
+    return -1;
+  if(file->read_buffer)
+    return -2;
+  /* TODO better business check*/
+
+  oi_buf *buf = malloc(sizeof(oi_buf));
+  buf->base = malloc(len);
+  memcpy(buf->base, str, len);
+  buf->len = len;
+  buf->release = oi_api_free_buf_with_heap_base;
+
+  oi_file_write(file, buf);
+  return 0;
+}
+
+static void
+clear_write_queue(oi_file *file)
+{
+  while(!oi_queue_empty(&file->write_queue)) {
+    oi_queue *q = oi_queue_last(&file->write_queue);
+    oi_queue_remove(q);
+    oi_buf *buf = oi_queue_data(q, oi_buf, queue);
+    RELEASE_BUF(buf);
+  }
+}
+
+static void 
+after_close(oi_task *task, int result)
+{
+  oi_file *file = task->data;
+
+  assert(oi_queue_empty(&file->write_queue));
+
+  if(result == -1) {
+    RAISE_ERROR(file, OI_ERROR_CLOSE, errno);
+    return;
+    // TODO try to close again? 
+  }
+
+  file->fd = -1;
+  // TODO deinit task_queue, detach thread_pool_result_watcher 
+
+  if(file->on_close) {
+    file->on_close(file);
+  }
+
+  return;
+}
+
+void
+oi_file_close (oi_file *file)
+{
+  assert(file->fd >= 0 && "file not open!");
+  clear_write_queue(file);
+  oi_task_init_close ( &file->io_task
+                     , after_close
+                     , file->fd
+                     );
+  file->io_task.data = file;
+  oi_async_submit(&file->async, &file->io_task);
+}
+
+static void
+after_sendfile(oi_task *task, ssize_t sent)
+{
+  oi_file *file = task->data;
+  oi_socket *socket = file->write_socket;
+  assert(socket != NULL);
+  file->write_socket = NULL;
+
+  if(sent == -1) {
+    RAISE_ERROR(file, OI_ERROR_SENDFILE, errno);
+    return;
+  }
+
+  if(socket->on_drain) {
+    socket->on_drain(socket);
+  }
+
+  maybe_do_read(file);
+}
+
+int
+oi_file_send (oi_file *file, oi_socket *destination, off_t offset, size_t count)
+{
+  if(file->fd < 0)
+    return -1;
+  if(file->read_buffer)
+    return -2;
+  /* TODO better business check*/
+
+  assert(file->write_socket == NULL);
+  // (1) make sure the write queue on the socket is cleared.
+  // 
+  // (2)
+  // 
+  file->write_socket = destination;
+  oi_task_init_sendfile ( &file->io_task
+                        , after_sendfile
+                        , destination->fd
+                        , file->fd
+                        , offset
+                        , count
+                        );
+  file->io_task.data = file;
+  oi_async_submit(&file->async, &file->io_task);
+
+  return 0;
+}
+
diff --git a/deps/liboi/oi_file.h b/deps/liboi/oi_file.h
new file mode 100644
index 0000000..6cd917e
--- /dev/null
+++ b/deps/liboi/oi_file.h
@@ -0,0 +1,58 @@
+#include <oi.h>
+#include <ev.h>
+#ifdef __cplusplus
+extern "C" {
+#endif 
+
+#ifndef oi_file_h
+#define oi_file_h
+
+typedef struct oi_file oi_file;
+
+int  oi_file_init         (oi_file *);
+
+void oi_file_attach       (oi_file *, struct ev_loop *);
+void oi_file_detach       (oi_file *);
+
+/* WARNING oi_file_open_path: path argument must be valid until oi_file
+ * object is closed and the on_close() callback is made. oi does not strdup
+ * the path pointer. */
+int  oi_file_open_path    (oi_file *, const char *path, int flags, mode_t mode);
+int  oi_file_open_stdin   (oi_file *);
+int  oi_file_open_stdout  (oi_file *);
+int  oi_file_open_stderr  (oi_file *);
+
+void oi_file_read_start   (oi_file *, void *buffer, size_t bufsize);
+void oi_file_read_stop    (oi_file *);
+int  oi_file_write        (oi_file *, oi_buf *to_write);
+int  oi_file_write_simple (oi_file *, const char *, size_t);
+int  oi_file_send         (oi_file *source, oi_socket *destination, off_t offset, size_t length);
+void oi_file_close        (oi_file *);
+
+struct oi_file {
+  /* private */
+  oi_async async;
+  oi_task io_task;
+  struct ev_loop *loop;
+  oi_queue write_queue;
+  oi_buf *write_buf; /* TODO this pointer is unnecessary - remove and just look at first element of the queue */
+  oi_socket *write_socket;
+  void *read_buffer;
+  size_t read_buffer_size;
+
+  /* read-only */
+  int fd;
+   
+  /* public */
+  void (*on_open)  (oi_file *);
+  void (*on_read)  (oi_file *, size_t count);
+  void (*on_drain) (oi_file *);
+  void (*on_error) (oi_file *, struct oi_error);
+  void (*on_close) (oi_file *);
+  void *data;
+};
+
+#ifdef __cplusplus
+}
+#endif 
+#endif /*  oi_file_h */
diff --git a/deps/liboi/oi_queue.h b/deps/liboi/oi_queue.h
new file mode 100644
index 0000000..0405e33
--- /dev/null
+++ b/deps/liboi/oi_queue.h
@@ -0,0 +1,69 @@
+/* Copyright (C) 2002-2009 Igor Sysoev
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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 oi_queue_h
+#define oi_queue_h
+#ifdef __cplusplus
+extern "C" {
+#endif 
+
+#include <stddef.h> /* offsetof() */
+
+typedef struct oi_queue oi_queue;
+struct oi_queue {
+    oi_queue  *prev;
+    oi_queue  *next;
+};
+
+#define oi_queue_init(q)                                                     \
+    (q)->prev = q;                                                            \
+    (q)->next = q
+
+#define oi_queue_empty(h)                                                    \
+    (h == (h)->prev)
+
+#define oi_queue_insert_head(h, x)                                           \
+    (x)->next = (h)->next;                                                    \
+    (x)->next->prev = x;                                                      \
+    (x)->prev = h;                                                            \
+    (h)->next = x
+
+#define oi_queue_head(h)                                                     \
+    (h)->next
+
+#define oi_queue_last(h)                                                     \
+    (h)->prev
+
+#define oi_queue_remove(x)                                                   \
+    (x)->next->prev = (x)->prev;                                              \
+    (x)->prev->next = (x)->next;                                              \
+    (x)->prev = NULL;                                                         \
+    (x)->next = NULL
+
+#define oi_queue_data(q, type, link)                                         \
+    (type *) ((unsigned char *) q - offsetof(type, link))
+
+#ifdef __cplusplus
+}
+#endif 
+#endif // oi_queue_h
diff --git a/deps/liboi/oi_socket.c b/deps/liboi/oi_socket.c
new file mode 100644
index 0000000..f922d23
--- /dev/null
+++ b/deps/liboi/oi_socket.c
@@ -0,0 +1,941 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <unistd.h> /* close() */
+#include <fcntl.h>  /* fcntl() */
+#include <errno.h> /* for the default methods */
+#include <string.h> /* memset */
+
+#include <netinet/tcp.h> /* TCP_NODELAY */
+
+#include <ev.h>
+#include <oi_socket.h>
+
+#if HAVE_GNUTLS
+# include <gnutls/gnutls.h>
+# define GNUTLS_NEED_WRITE (gnutls_record_get_direction(socket->session) == 1)
+# define GNUTLS_NEED_READ (gnutls_record_get_direction(socket->session) == 0)
+#endif
+
+#undef TRUE
+#define TRUE 1
+#undef FALSE
+#define FALSE 0
+#undef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+#define OKAY  0
+#define AGAIN 1
+#define ERROR 2 
+
+#define RAISE_ERROR(s, _domain, _code) do { \
+  if(s->on_error) { \
+    struct oi_error __oi_error; \
+    __oi_error.domain = _domain; \
+    __oi_error.code = _code; \
+    s->on_error(s, __oi_error); \
+  } \
+} while(0) \
+
+static int 
+full_close(oi_socket *socket)
+{
+  if(-1 == close(socket->fd) && errno == EINTR) {
+    /* TODO fd still open. next loop call close again? */
+    assert(0 && "implement me");  
+    return ERROR;
+  }
+
+  socket->read_action = NULL;
+  socket->write_action = NULL;
+
+  if(socket->loop) {
+    ev_feed_event(socket->loop, &socket->read_watcher, EV_READ);
+  }
+  return OKAY;
+}
+
+static int 
+half_close(oi_socket *socket)
+{
+  int r = shutdown(socket->fd, SHUT_WR);
+
+  if(r == -1) {
+    RAISE_ERROR(socket, OI_ERROR_SHUTDOWN, errno);
+    return ERROR;
+  }
+
+  socket->write_action = NULL;
+
+  /* TODO set timer to zero  so we get a callback soon */
+  return OKAY;
+}
+
+static void
+update_write_buffer_after_send(oi_socket *socket, ssize_t sent)
+{
+  oi_queue *q = oi_queue_last(&socket->out_stream);
+  oi_buf *to_write = oi_queue_data(q, oi_buf, queue);
+  to_write->written += sent;
+  socket->written += sent;
+
+  if(to_write->written == to_write->len) {
+
+    oi_queue_remove(q);
+
+    if(to_write->release) {
+      to_write->release(to_write);
+    }  
+
+    if(oi_queue_empty(&socket->out_stream)) {
+      ev_io_stop(socket->loop, &socket->write_watcher);
+      if(socket->on_drain)
+        socket->on_drain(socket);
+    }
+  }
+}
+
+
+#if HAVE_GNUTLS
+static int secure_socket_send(oi_socket *socket);
+static int secure_socket_recv(oi_socket *socket);
+
+/* TODO can this be done without ignoring SIGPIPE?  */
+static ssize_t 
+nosigpipe_push(gnutls_transport_ptr_t data, const void *buf, size_t len)
+{
+  oi_socket *socket = (oi_socket*)data;
+  assert(socket->secure);
+  int flags = 0;
+#ifdef MSG_NOSIGNAL
+  flags |= MSG_NOSIGNAL;
+#endif
+#ifdef MSG_DONTWAIT
+  flags |= MSG_DONTWAIT;
+#endif
+  int r = send(socket->fd, buf, len, flags);
+
+  if(r == -1) {
+    gnutls_transport_set_errno(socket->session, errno); /* necessary ? */
+  }
+
+  return r;
+}
+
+static int
+secure_handshake(oi_socket *socket)
+{
+  assert(socket->secure);
+
+  int r = gnutls_handshake(socket->session);
+
+  if(gnutls_error_is_fatal(r)) {
+    RAISE_ERROR(socket, OI_ERROR_GNUTLS, r);
+    return ERROR;
+  }
+
+  if(r == GNUTLS_E_INTERRUPTED || r == GNUTLS_E_AGAIN)
+    return AGAIN;
+
+  oi_socket_reset_timeout(socket);
+
+  if(!socket->connected) {
+    socket->connected = TRUE;
+    if(socket->on_connect)
+      socket->on_connect(socket);
+  }
+
+  if(socket->read_action)
+    socket->read_action = secure_socket_recv;
+ 
+  if(socket->write_action)
+    socket->write_action = secure_socket_send;
+
+  return OKAY;
+}
+
+static int
+secure_socket_send(oi_socket *socket)
+{
+  ssize_t sent;
+
+  if(oi_queue_empty(&socket->out_stream)) {
+    ev_io_stop(socket->loop, &socket->write_watcher);
+    return AGAIN;
+  }
+
+  oi_queue *q = oi_queue_last(&socket->out_stream);
+  oi_buf *to_write = oi_queue_data(q, oi_buf, queue);
+
+  assert(socket->secure);
+
+  sent = gnutls_record_send( socket->session
+                           , to_write->base + to_write->written
+                           , to_write->len - to_write->written
+                           ); 
+
+  if(gnutls_error_is_fatal(sent)) {
+    RAISE_ERROR(socket, OI_ERROR_GNUTLS, sent);
+    return ERROR;
+  }
+
+  if(sent == 0)
+    return AGAIN;
+
+  oi_socket_reset_timeout(socket);
+
+  if(sent == GNUTLS_E_INTERRUPTED || sent == GNUTLS_E_AGAIN) {
+    if(GNUTLS_NEED_READ) {
+      if(socket->read_action) {
+        socket->read_action = secure_socket_send;
+      } else {
+        /* TODO GnuTLS needs read but already got EOF */
+        assert(0 && "needs read but already got EOF");
+        return ERROR;
+      }
+    }
+    return AGAIN;
+  }
+
+  if(sent > 0) {
+    /* make sure the callbacks are correct */
+    if(socket->read_action)
+      socket->read_action = secure_socket_recv;
+    update_write_buffer_after_send(socket, sent);
+    return OKAY;
+  }
+
+  assert(0 && "Unhandled return code from gnutls_record_send()!");
+  return ERROR;
+}
+
+static int
+secure_socket_recv(oi_socket *socket)
+{
+  char recv_buffer[TCP_MAXWIN];
+  size_t recv_buffer_size = MIN(TCP_MAXWIN, socket->chunksize);
+  ssize_t recved;
+
+  assert(socket->secure);
+
+  recved = gnutls_record_recv(socket->session, recv_buffer, recv_buffer_size);
+
+  //printf("secure socket recv %d %p\n", recved, socket->on_connect);
+
+  if(gnutls_error_is_fatal(recved)) {
+    RAISE_ERROR(socket, OI_ERROR_GNUTLS, recved);
+    return ERROR;
+  }
+
+  if(recved == GNUTLS_E_INTERRUPTED || recved == GNUTLS_E_AGAIN)  {
+    if(GNUTLS_NEED_WRITE) {
+      if(socket->write_action) {
+        printf("need write\n");
+        socket->write_action = secure_socket_recv;
+      } else {
+        /* TODO GnuTLS needs send but already closed write end */
+        assert(0 && "needs read but cannot");
+        return ERROR;
+      }
+    }
+    return AGAIN;
+  }
+
+  oi_socket_reset_timeout(socket);
+
+  /* A server may also receive GNUTLS_E_REHANDSHAKE when a client has
+   * initiated a handshake. In that case the server can only initiate a
+   * handshake or terminate the connection. */
+  if(recved == GNUTLS_E_REHANDSHAKE) {
+    if(socket->write_action) {
+      socket->read_action = secure_handshake;
+      socket->write_action = secure_handshake;
+      return OKAY;
+    } else {
+      /* TODO */
+      assert(0 && "needs read but cannot");
+      return ERROR;
+    }
+  }
+
+  if(recved >= 0) {
+    /* Got EOF */
+    if(recved == 0)
+      socket->read_action = NULL;
+
+    if(socket->write_action) 
+      socket->write_action = secure_socket_send;
+
+    if(socket->on_read) { socket->on_read(socket, recv_buffer, recved); }
+
+    return OKAY;
+  }
+
+  assert(0 && "Unhandled return code from gnutls_record_send()!");
+  return ERROR;
+}
+
+static int
+secure_goodbye(oi_socket *socket, gnutls_close_request_t how)
+{
+  assert(socket->secure);
+
+  int r = gnutls_bye(socket->session, how);
+
+  if(gnutls_error_is_fatal(r))  {
+    RAISE_ERROR(socket, OI_ERROR_GNUTLS, r);
+    return ERROR;
+  }
+
+  if(r == GNUTLS_E_INTERRUPTED || r == GNUTLS_E_AGAIN)
+    return AGAIN;
+
+  return OKAY;
+}
+
+static int
+secure_full_goodbye(oi_socket *socket)
+{
+  int r = secure_goodbye(socket, GNUTLS_SHUT_RDWR);
+  if(OKAY == r) {
+    return full_close(socket);
+  }
+  return r;
+}
+
+static int
+secure_half_goodbye(oi_socket *socket)
+{
+  int r = secure_goodbye(socket, GNUTLS_SHUT_WR);
+  if(OKAY == r) {
+    return half_close(socket);
+  }
+  return r;
+}
+
+/* Tells the socket to use transport layer security (SSL). liboi does not
+ * want to make any decisions about security requirements, so the
+ * majoirty of GnuTLS configuration is left to the user. Only the transport
+ * layer of GnuTLS is controlled by liboi.
+ *
+ * That is, do not use gnutls_transport_* functions. 
+ * Do use the rest of GnuTLS's API.
+ */
+void
+oi_socket_set_secure_session (oi_socket *socket, gnutls_session_t session)
+{
+  socket->session = session;
+  socket->secure = TRUE;
+}
+#endif /* HAVE GNUTLS */
+
+static int
+socket_send(oi_socket *socket)
+{
+  ssize_t sent;
+
+  assert(socket->secure == FALSE);
+
+  if(oi_queue_empty(&socket->out_stream)) {
+    ev_io_stop(socket->loop, &socket->write_watcher);
+    return AGAIN;
+  }
+
+  oi_queue *q = oi_queue_last(&socket->out_stream);
+  oi_buf *to_write = oi_queue_data(q, oi_buf, queue);
+  
+  int flags = 0;
+#ifdef MSG_NOSIGNAL
+  flags |= MSG_NOSIGNAL;
+#endif
+#ifdef MSG_DONTWAIT
+  flags |= MSG_DONTWAIT;
+#endif
+
+  /* TODO use writev() here */
+
+  sent = send( socket->fd
+             , to_write->base + to_write->written
+             , to_write->len - to_write->written
+             , flags
+             );
+
+  if(sent < 0) {
+    switch(errno) {
+      case EAGAIN:
+        return AGAIN;
+
+      case ECONNREFUSED:
+      case ECONNRESET:
+        socket->write_action = NULL;
+        /* TODO maybe just clear write buffer instead of error? 
+         * They should be able to read still from the socket. 
+         */
+        RAISE_ERROR(socket, OI_ERROR_SEND, errno);
+        return ERROR;
+
+      default:
+        perror("send()");
+        assert(0 && "oi shouldn't let this happen.");
+        return ERROR;
+    }
+  }
+
+  oi_socket_reset_timeout(socket);
+
+  if(!socket->connected) {
+    socket->connected = TRUE;
+    if(socket->on_connect) { socket->on_connect(socket); }
+  }
+
+  update_write_buffer_after_send(socket, sent);
+
+  return OKAY;
+}
+
+static int
+socket_recv(oi_socket *socket)
+{
+  char buf[TCP_MAXWIN];
+  size_t buf_size = TCP_MAXWIN;
+  ssize_t recved;
+
+  assert(socket->secure == FALSE);
+
+  if(!socket->connected) {
+    socket->connected = TRUE;
+    if(socket->on_connect) { socket->on_connect(socket); }
+    return OKAY;
+  }
+
+  recved = recv(socket->fd, buf, buf_size, 0);
+
+  if(recved < 0) {
+    switch(errno) {
+      case EAGAIN: 
+      case EINTR:  
+        return AGAIN;
+
+      /* A remote host refused to allow the network connection (typically
+       * because it is not running the requested service). */
+      case ECONNREFUSED:
+        RAISE_ERROR(socket, OI_ERROR_RECV, errno);
+        return ERROR; 
+
+      case ECONNRESET:
+        RAISE_ERROR(socket, OI_ERROR_RECV, errno);
+        return ERROR; 
+
+      default:
+        perror("recv()");
+        printf("unmatched errno %d\n", errno);
+        assert(0 && "recv returned error that oi should have caught before.");
+        return ERROR;
+    }
+  }
+
+  oi_socket_reset_timeout(socket);
+
+  if(recved == 0) {
+    oi_socket_read_stop(socket);
+    socket->read_action = NULL;
+  }
+
+  /* NOTE: EOF is signaled with recved == 0 on callback */
+  if(socket->on_read) { socket->on_read(socket, buf, recved); }
+
+  return OKAY;
+}
+
+static void
+assign_file_descriptor(oi_socket *socket, int fd)
+{
+  socket->fd = fd;
+
+  ev_io_set (&socket->read_watcher, fd, EV_READ);
+  ev_io_set (&socket->write_watcher, fd, EV_WRITE);
+
+  socket->read_action = socket_recv;
+  socket->write_action = socket_send;
+
+#if HAVE_GNUTLS
+  if(socket->secure) {
+    gnutls_transport_set_lowat(socket->session, 0); 
+    gnutls_transport_set_push_function(socket->session, nosigpipe_push);
+    gnutls_transport_set_ptr2 ( socket->session
+                 /* recv */   , (gnutls_transport_ptr_t)fd 
+                 /* send */   , socket 
+                              );
+    socket->read_action = secure_handshake;
+    socket->write_action = secure_handshake;
+  }
+#endif 
+}
+
+
+/* Internal callback 
+ * Called by server->connection_watcher.
+ */
+static void 
+on_connection(struct ev_loop *loop, ev_io *watcher, int revents)
+{
+  oi_server *server = watcher->data;
+
+ // printf("on connection!\n");
+
+  assert(server->listening);
+  assert(server->loop == loop);
+  assert(&server->connection_watcher == watcher);
+  
+  if(EV_ERROR & revents) {
+    oi_server_close(server);
+    return;
+  }
+  
+  struct sockaddr address; /* connector's address information */
+  socklen_t addr_len = sizeof(address);
+  
+  /* TODO accept all possible connections? currently: just one */
+  int fd = accept(server->fd, (struct sockaddr*)&address, &addr_len);
+  if(fd < 0) {
+    perror("accept()");
+    return;
+  }
+
+  oi_socket *socket = NULL;
+  if(server->on_connection)
+    socket = server->on_connection(server, (struct sockaddr*)&address, addr_len);
+
+  if(socket == NULL) {
+    close(fd);
+    return;
+  } 
+  
+  int flags = fcntl(fd, F_GETFL, 0);
+  int r = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+  if(r < 0) {
+    /* TODO error report */
+  }
+  
+#ifdef SO_NOSIGPIPE
+  flags = 1;
+  setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &flags, sizeof(flags));
+#endif
+
+  socket->server = server;
+  assign_file_descriptor(socket, fd);
+  oi_socket_attach(socket, loop);
+}
+
+int
+oi_server_listen(oi_server *server, struct addrinfo *addrinfo)
+{
+  int fd = -1;
+  struct linger ling = {0, 0};
+  assert(server->listening == FALSE);
+
+  fd = socket( addrinfo->ai_family
+             , addrinfo->ai_socktype
+             , addrinfo->ai_protocol
+             );
+  if(fd < 0) {
+    perror("socket()");
+    return -1;
+  }
+
+  int flags = fcntl(fd, F_GETFL, 0);
+  int r = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+  if(r < 0) {
+    perror("fcntl()");
+    return -1;
+  }
+
+  flags = 1;
+  setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
+  setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
+  setsockopt(fd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
+
+  /* XXX: Sending single byte chunks in a response body? Perhaps there is a
+   * need to enable the Nagel algorithm dynamically. For now disabling.
+   */
+  //setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags));
+
+  if (bind(fd, addrinfo->ai_addr, addrinfo->ai_addrlen) < 0) {
+    perror("bind()");
+    close(fd);
+    return -1;
+  }
+  
+  if (listen(fd, server->backlog) < 0) {
+    perror("listen()");
+    close(fd);
+    return -1;
+  }
+  
+  server->fd = fd;
+  server->listening = TRUE;
+  ev_io_set (&server->connection_watcher, server->fd, EV_READ);
+  
+  return 0;
+}
+
+/**
+ * Stops the server. Will not accept new connections.  Does not drop
+ * existing connections.
+ */
+void 
+oi_server_close(oi_server *server)
+{
+  if(server->listening) {
+    oi_server_detach(server);
+    close(server->fd);
+    /* TODO do this on the loop? check return value? */
+    server->listening = FALSE;
+  }
+}
+
+void
+oi_server_attach (oi_server *server, struct ev_loop *loop)
+{
+  ev_io_start (loop, &server->connection_watcher);
+  server->loop = loop;
+}
+
+void
+oi_server_detach (oi_server *server)
+{
+  ev_io_stop (server->loop, &server->connection_watcher);
+  server->loop = NULL;
+}
+
+void 
+oi_server_init(oi_server *server, int backlog)
+{
+  server->backlog = backlog;
+  server->listening = FALSE;
+  server->fd = -1;
+  server->connection_watcher.data = server;
+  ev_init (&server->connection_watcher, on_connection);
+
+  server->on_connection = NULL;
+  server->on_error = NULL;
+  server->data = NULL;
+}
+
+/* Internal callback. called by socket->timeout_watcher */
+static void 
+on_timeout(struct ev_loop *loop, ev_timer *watcher, int revents)
+{
+  oi_socket *socket = watcher->data;
+
+  assert(watcher == &socket->timeout_watcher);
+
+ // printf("on_timeout\n");
+
+  if(socket->on_timeout) { socket->on_timeout(socket); }
+
+
+  /* TODD set timer to zero */
+  full_close(socket);
+}
+
+static void
+release_write_buffer(oi_socket *socket)
+{
+  while(!oi_queue_empty(&socket->out_stream)) {
+    oi_queue *q = oi_queue_last(&socket->out_stream);
+    oi_buf *buf = oi_queue_data(q, oi_buf, queue);
+    oi_queue_remove(q);
+    if(buf->release) { buf->release(buf); }
+  }
+}
+
+/* Internal callback. called by socket->read_watcher */
+static void 
+on_io_event(struct ev_loop *loop, ev_io *watcher, int revents)
+{
+  oi_socket *socket = watcher->data;
+
+  if(revents & EV_ERROR) {
+    RAISE_ERROR(socket, OI_ERROR_EV, 0);
+    goto close;
+  }
+
+  int r;
+  int have_read_event = TRUE;
+  int have_write_event = TRUE;
+
+  while(have_read_event || have_write_event) {
+
+    if(socket->read_action) {
+      r = socket->read_action(socket);
+      if(r == ERROR) goto close;
+      if(r == AGAIN) have_read_event = FALSE;
+    } else {
+      have_read_event = FALSE;
+    }
+
+    if(socket->write_action) {
+      r = socket->write_action(socket);
+      if(r == ERROR) goto close;
+      if(r == AGAIN) have_write_event = FALSE;
+    } else {
+      have_write_event = FALSE;
+    }
+
+
+    if(socket->read_watcher.active == FALSE)
+      have_read_event = FALSE;
+    if(socket->write_watcher.active == FALSE)
+      have_write_event = FALSE;
+  }
+
+  if(socket->write_action == NULL && socket->read_action == NULL)
+    goto close;
+
+  return;
+
+close:
+  release_write_buffer(socket);
+
+  ev_clear_pending (socket->loop, &socket->write_watcher);
+  ev_clear_pending (socket->loop, &socket->read_watcher);
+  ev_clear_pending (socket->loop, &socket->timeout_watcher);
+
+  oi_socket_detach(socket);
+
+  if(socket->on_close) { socket->on_close(socket); }
+  /* WARNING: user can free socket in on_close so no more 
+   * access beyond this point. */
+}
+
+/**
+ * If using SSL do consider setting
+ *   gnutls_db_set_retrieve_function (socket->session, _);
+ *   gnutls_db_set_remove_function (socket->session, _);
+ *   gnutls_db_set_store_function (socket->session, _);
+ *   gnutls_db_set_ptr (socket->session, _);
+ */
+void 
+oi_socket_init(oi_socket *socket, float timeout)
+{
+  socket->fd = -1;
+  socket->server = NULL;
+  socket->loop = NULL;
+  socket->connected = FALSE;
+
+  oi_queue_init(&socket->out_stream);
+
+  ev_init (&socket->write_watcher, on_io_event);
+  socket->write_watcher.data = socket;
+
+  ev_init(&socket->read_watcher, on_io_event);
+  socket->read_watcher.data = socket;
+
+  socket->secure = FALSE;
+  socket->wait_for_secure_hangup = FALSE;
+#if HAVE_GNUTLS
+  socket->session = NULL;
+#endif 
+
+  /* TODO higher resolution timer */
+  ev_timer_init(&socket->timeout_watcher, on_timeout, 0., timeout);
+  socket->timeout_watcher.data = socket;  
+
+  socket->read_action = NULL;
+  socket->write_action = NULL;
+
+  socket->chunksize = TCP_MAXWIN; 
+  socket->on_connect = NULL;
+  socket->on_read = NULL;
+  socket->on_drain = NULL;
+  socket->on_error = NULL;
+  socket->on_timeout = NULL;
+}
+
+void 
+oi_socket_write_eof (oi_socket *socket)
+{
+#if HAVE_GNUTLS
+  /* try to hang up properly for secure connections */
+  if(socket->secure) 
+  {
+    if( socket->connected /* completed handshake */ 
+     && socket->write_action /* write end is open */
+      ) 
+    {
+      socket->write_action = secure_half_goodbye;
+      if(socket->loop)
+        ev_io_start(socket->loop, &socket->write_watcher);
+      return;
+    }
+    /* secure servers cannot handle half-closed connections? */
+    full_close(socket); 
+    return;
+  }
+#endif // HAVE_GNUTLS
+
+  if(socket->write_action)
+    half_close(socket);
+  else
+    full_close(socket);
+}
+
+void 
+oi_socket_close (oi_socket *socket)
+{
+#if HAVE_GNUTLS
+  /* try to hang up properly for secure connections */
+  if( socket->secure 
+   && socket->connected /* completed handshake */ 
+   && socket->write_action /* write end is open */
+    ) 
+  {
+    if(socket->wait_for_secure_hangup && socket->read_action) {
+      socket->write_action = secure_full_goodbye;
+      socket->read_action = secure_full_goodbye;
+    } else {
+      socket->write_action = secure_half_goodbye;
+      socket->read_action = NULL;
+    }
+
+    if(socket->loop)
+      ev_io_start(socket->loop, &socket->write_watcher);
+
+    return;
+  }
+#endif // HAVE_GNUTLS
+
+  full_close(socket);
+}
+
+/* 
+ * Resets the timeout to stay alive for another socket->timeout seconds
+ */
+void 
+oi_socket_reset_timeout(oi_socket *socket)
+{
+  ev_timer_again(socket->loop, &socket->timeout_watcher);
+}
+
+/**
+ * Writes a string to the socket. This is actually sets a watcher which may
+ * take multiple iterations to write the entire string.
+ */
+void 
+oi_socket_write(oi_socket *socket, oi_buf *buf)
+{
+  if(socket->write_action == NULL)
+    return;
+
+  oi_queue_insert_head(&socket->out_stream, &buf->queue);
+
+  buf->written = 0;
+  ev_io_start(socket->loop, &socket->write_watcher);
+}
+
+static void
+free_simple_buf ( oi_buf *buf )
+{
+  free(buf->base);
+  free(buf);
+}
+
+/* Writes a string to the socket. 
+ * NOTE: Allocates memory. Avoid for performance applications.
+ */ 
+void
+oi_socket_write_simple(oi_socket *socket, const char *str, size_t len)
+{
+  oi_buf *buf = malloc(sizeof(oi_buf));
+  buf->release = free_simple_buf;
+  buf->base = strdup(str);
+  buf->len = len;
+
+  oi_socket_write(socket, buf);
+}
+
+void
+oi_socket_attach(oi_socket *socket, struct ev_loop *loop)
+{
+  socket->loop = loop;
+
+  ev_timer_again(loop, &socket->timeout_watcher);
+
+  if(socket->read_action) 
+    ev_io_start(loop, &socket->read_watcher);
+
+  if(socket->write_action) 
+    ev_io_start(loop, &socket->write_watcher);
+
+  /* make sure the io_event happens soon  in the case we're being reattached */
+  ev_feed_event(loop, &socket->read_watcher, EV_READ);
+}
+
+void
+oi_socket_detach(oi_socket *socket)
+{
+  if(socket->loop) {
+    ev_io_stop(socket->loop, &socket->write_watcher);
+    ev_io_stop(socket->loop, &socket->read_watcher);
+    ev_timer_stop(socket->loop, &socket->timeout_watcher);
+    socket->loop = NULL;
+  }
+}
+
+void
+oi_socket_read_stop (oi_socket *socket)
+{
+  ev_io_stop(socket->loop, &socket->read_watcher);
+  ev_clear_pending (socket->loop, &socket->read_watcher);
+}
+
+void
+oi_socket_read_start (oi_socket *socket)
+{
+  if(socket->read_action) {
+    ev_io_start(socket->loop, &socket->read_watcher);
+    /* XXX feed event? */
+  }
+}
+
+int
+oi_socket_connect(oi_socket *s, struct addrinfo *addrinfo)
+{
+  int fd = socket( addrinfo->ai_family
+                 , addrinfo->ai_socktype
+                 , addrinfo->ai_protocol
+                 );
+  if(fd < 0) {
+    perror("socket()");
+    return -1;
+  }
+
+  int flags = fcntl(fd, F_GETFL, 0);
+  int r = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+  if(r < 0) {
+    perror("fcntl()");
+    return -1;
+  }
+      
+#ifdef SO_NOSIGPIPE
+  flags = 1;
+  setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &flags, sizeof(flags));
+#endif
+
+  r = connect( fd
+             , addrinfo->ai_addr
+             , addrinfo->ai_addrlen
+             );
+
+  if(r < 0 && errno != EINPROGRESS) {
+    perror("connect");
+    close(fd);
+    return -1;
+  }
+
+  assign_file_descriptor(s, fd);
+
+  return 0;
+}
+
diff --git a/deps/liboi/oi_socket.h b/deps/liboi/oi_socket.h
new file mode 100644
index 0000000..1b51f0f
--- /dev/null
+++ b/deps/liboi/oi_socket.h
@@ -0,0 +1,98 @@
+#include <netdb.h>
+#include <ev.h>
+#include <oi_queue.h>
+#include <oi_error.h>
+#include <oi_buf.h>
+
+#ifndef oi_socket_h
+#define oi_socket_h
+#ifdef __cplusplus
+extern "C" {
+#endif 
+
+#ifndef HAVE_GNUTLS
+# define HAVE_GNUTLS 0
+#endif
+#if HAVE_GNUTLS
+# include <gnutls/gnutls.h>
+#endif
+
+typedef struct oi_server  oi_server;
+typedef struct oi_socket  oi_socket;
+
+void oi_server_init          (oi_server *, int backlog);
+ int oi_server_listen        (oi_server *, struct addrinfo *addrinfo);
+void oi_server_attach        (oi_server *, struct ev_loop *loop);
+void oi_server_detach        (oi_server *);
+void oi_server_close         (oi_server *); 
+
+void oi_socket_init          (oi_socket *, float timeout);
+ int oi_socket_pair          (oi_socket *a, oi_socket *b); /* TODO */
+ int oi_socket_connect       (oi_socket *, struct addrinfo *addrinfo);
+void oi_socket_attach        (oi_socket *, struct ev_loop *loop);
+void oi_socket_detach        (oi_socket *);
+void oi_socket_read_start    (oi_socket *);
+void oi_socket_read_stop     (oi_socket *);
+void oi_socket_reset_timeout (oi_socket *);
+void oi_socket_write         (oi_socket *, oi_buf *);
+void oi_socket_write_simple  (oi_socket *, const char *str, size_t len);
+void oi_socket_write_eof     (oi_socket *);
+void oi_socket_close         (oi_socket *);
+#if HAVE_GNUTLS
+void oi_socket_set_secure_session (oi_socket *, gnutls_session_t);
+#endif
+
+struct oi_server {
+  /* read only */
+  int fd;
+  int backlog;
+  struct ev_loop *loop;
+  unsigned listening:1;
+
+  /* private */
+  ev_io connection_watcher;
+
+  /* public */
+  oi_socket* (*on_connection) (oi_server *, struct sockaddr *remote_addr, socklen_t remove_addr_len);
+  void       (*on_error)      (oi_server *, struct oi_error e);
+  void *data;
+};
+
+struct oi_socket {
+  /* read only */
+  int fd;
+  struct ev_loop *loop;
+  oi_server *server;
+  oi_queue out_stream;
+  size_t written;
+  unsigned connected:1;
+  unsigned secure:1;
+  unsigned wait_for_secure_hangup:1;
+
+  /* if these are NULL then it means that end of the socket is closed. */
+  int (*read_action)  (oi_socket *);
+  int (*write_action) (oi_socket *);
+
+  /* private */  
+  ev_io write_watcher;
+  ev_io read_watcher;
+  ev_timer timeout_watcher;
+#if HAVE_GNUTLS
+  gnutls_session_t session;
+#endif
+  
+  /* public */
+  size_t chunksize; /* the maximum chunk that on_read() will return */
+  void (*on_connect)   (oi_socket *);
+  void (*on_read)      (oi_socket *, const void *buf, size_t count);
+  void (*on_drain)     (oi_socket *);
+  void (*on_error)     (oi_socket *, struct oi_error e);
+  void (*on_close)     (oi_socket *);
+  void (*on_timeout)   (oi_socket *);
+  void *data;
+};
+
+#ifdef __cplusplus
+}
+#endif 
+#endif /* oi_socket_h */
diff --git a/deps/liboi/test/common.c b/deps/liboi/test/common.c
new file mode 100644
index 0000000..4703b40
--- /dev/null
+++ b/deps/liboi/test/common.c
@@ -0,0 +1,110 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+
+
+#include <ev.h>
+#include <oi.h>
+#include <gnutls/gnutls.h>
+
+#define HOST "127.0.0.1"
+#define SOCKFILE "/tmp/oi.sock"
+#define PORT "5000"
+
+int nconnections; 
+
+static void 
+on_peer_close(oi_socket *socket)
+{
+  //printf("server connection closed\n");
+#if HAVE_GNUTLS
+#if SECURE
+  gnutls_deinit(socket->session);
+#endif
+#endif
+  free(socket);
+}
+
+static void 
+on_client_timeout(oi_socket *socket)
+{
+  printf("client connection timeout\n");
+  assert(0);
+}
+
+static void 
+on_peer_timeout(oi_socket *socket)
+{
+  fprintf(stderr, "peer connection timeout\n");
+  assert(0);
+}
+
+static void 
+on_client_error(oi_socket *socket, struct oi_error e)
+{
+  assert(0);
+}
+
+
+#if HAVE_GNUTLS
+#if SECURE
+#define DH_BITS 768
+gnutls_anon_server_credentials_t server_credentials;
+const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };
+static gnutls_dh_params_t dh_params;
+
+void anon_tls_init()
+{
+  gnutls_global_init();
+
+  gnutls_dh_params_init (&dh_params);
+
+  fprintf(stderr, "..");
+  fsync((int)stderr);
+  gnutls_dh_params_generate2 (dh_params, DH_BITS);
+  fprintf(stderr, ".");
+
+  gnutls_anon_allocate_server_credentials (&server_credentials);
+  gnutls_anon_set_server_dh_params (server_credentials, dh_params);
+}
+
+void anon_tls_server(oi_socket *socket)
+{
+  gnutls_session_t session;
+  socket->data = session;
+
+  int r = gnutls_init(&session, GNUTLS_SERVER);
+  assert(r == 0);
+  gnutls_set_default_priority(session);
+  gnutls_kx_set_priority (session, kx_prio);
+  gnutls_credentials_set(session, GNUTLS_CRD_ANON, server_credentials);
+  gnutls_dh_set_prime_bits(session, DH_BITS);
+
+  oi_socket_set_secure_session(socket, session);
+}
+
+void anon_tls_client(oi_socket *socket)
+{
+  gnutls_session_t client_session;
+  gnutls_anon_client_credentials_t client_credentials;
+
+  gnutls_anon_allocate_client_credentials (&client_credentials);
+  gnutls_init (&client_session, GNUTLS_CLIENT);
+  gnutls_set_default_priority(client_session);
+  gnutls_kx_set_priority(client_session, kx_prio);
+  /* Need to enable anonymous KX specifically. */
+  gnutls_credentials_set (client_session, GNUTLS_CRD_ANON, client_credentials);
+
+  oi_socket_set_secure_session(socket, client_session);
+  assert(socket->secure);
+}
+
+#endif // SECURE
+#endif // HAVE_GNUTLS
diff --git a/deps/liboi/test/connection_interruption.c b/deps/liboi/test/connection_interruption.c
new file mode 100644
index 0000000..0b9169a
--- /dev/null
+++ b/deps/liboi/test/connection_interruption.c
@@ -0,0 +1,159 @@
+#include "test/common.c"
+#define NCONN 100
+#define TIMEOUT 1000.0
+
+static oi_server server;
+
+static void 
+on_peer_read(oi_socket *socket, const void *base, size_t len)
+{
+  assert(len == 0);
+  oi_socket_write_simple(socket, "BYE", 3);
+  //printf("server wrote bye\n");
+}
+
+static void 
+on_peer_drain(oi_socket *socket)
+{
+  oi_socket_close(socket);
+}
+
+static void 
+on_peer_error2(oi_socket *socket, struct oi_error e)
+{
+  if(e.domain == OI_ERROR_GNUTLS) return;
+  assert(0);
+}
+
+static oi_socket* 
+on_server_connection(oi_server *server, struct sockaddr *addr, socklen_t len)
+{
+  oi_socket *socket = malloc(sizeof(oi_socket));
+  oi_socket_init(socket, TIMEOUT);
+  socket->on_read    = on_peer_read;
+  socket->on_drain   = on_peer_drain;
+  socket->on_error   = on_peer_error2;
+  socket->on_close   = on_peer_close;
+  socket->on_timeout = on_peer_timeout;
+
+#if HAVE_GNUTLS
+# if SECURE
+  anon_tls_server(socket);
+# endif
+#endif
+
+  //printf("on server connection\n");
+
+  return socket;
+}
+
+static void 
+on_client_connect(oi_socket *socket)
+{
+  //printf("on client connection\n");
+  oi_socket_write_eof(socket);
+}
+
+static void 
+on_client_close(oi_socket *socket)
+{
+  oi_socket_close(socket); // already closed, but it shouldn't crash if we try to do it again
+
+  //printf("client connection closed\n");
+  if(++nconnections == NCONN) {
+    oi_server_detach(&server);
+    //printf("detaching server\n");
+  }
+}
+
+static void 
+on_client_read(oi_socket *socket, const void *base, size_t len)
+{
+  char buf[200000];
+  strncpy(buf, base, len);
+  buf[len] = 0;
+
+  //printf("client got message: %s\n", buf);
+  
+  if(strcmp(buf, "BYE") == 0) {
+    oi_socket_close(socket);
+  } else {
+    assert(0);
+  }
+}
+
+int 
+main(int argc, const char *argv[])
+{
+  int r;
+  struct ev_loop *loop = ev_default_loop(0);
+
+  oi_server_init(&server, 1000);
+  server.on_connection = on_server_connection;
+#if HAVE_GNUTLS
+# if SECURE
+  anon_tls_init();
+# endif
+#endif
+
+  struct addrinfo *servinfo;
+  struct addrinfo hints;
+  memset(&hints, 0, sizeof hints);
+#if TCP
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_flags = AI_PASSIVE;
+    r = getaddrinfo(NULL, PORT, &hints, &servinfo);
+    assert(r == 0);
+#else
+    struct stat tstat;
+    if (lstat(SOCKFILE, &tstat) == 0) {
+      if (S_ISSOCK(tstat.st_mode))
+        unlink(SOCKFILE);
+    }
+
+    servinfo = malloc(sizeof(struct addrinfo));
+    servinfo->ai_family = AF_UNIX;
+    servinfo->ai_socktype = SOCK_STREAM;
+    servinfo->ai_protocol = 0;
+
+    struct sockaddr_un *sockaddr = calloc(sizeof(struct sockaddr_un), 1);
+    sockaddr->sun_family = AF_UNIX;
+    strcpy(sockaddr->sun_path, SOCKFILE);
+
+    servinfo->ai_addr = (struct sockaddr*)sockaddr;
+    servinfo->ai_addrlen = sizeof(struct sockaddr_un);
+#endif
+
+  oi_server_listen(&server, servinfo);
+  oi_server_attach(&server, loop);
+
+  int i;
+  for(i = 0; i < NCONN; i++) {
+    oi_socket *client = malloc(sizeof(oi_socket));
+    oi_socket_init(client, TIMEOUT);
+    client->on_read    = on_client_read;
+    client->on_error   = on_client_error;
+    client->on_connect = on_client_connect;
+    client->on_close   = on_client_close;
+    client->on_timeout = on_client_timeout;
+#if HAVE_GNUTLS
+#if SECURE
+    anon_tls_client(client);
+#endif
+#endif
+    r = oi_socket_connect(client, servinfo);
+    assert(r == 0 && "problem connecting");
+    oi_socket_attach(client, loop);
+  }
+
+  ev_loop(loop, 0);
+
+  assert(nconnections == NCONN);
+
+#if TCP
+  freeaddrinfo(servinfo);
+#endif
+
+  return 0;
+}
diff --git a/deps/liboi/test/echo.c b/deps/liboi/test/echo.c
new file mode 100644
index 0000000..c68b94c
--- /dev/null
+++ b/deps/liboi/test/echo.c
@@ -0,0 +1,102 @@
+#include "test/common.c"
+
+int successful_ping_count; 
+
+static void 
+on_peer_read(oi_socket *socket, const void *base, size_t len)
+{
+  if(len == 0) 
+    return;
+
+  oi_socket_write_simple(socket, base, len);
+}
+
+static void 
+on_peer_error(oi_socket *socket, struct oi_error e)
+{
+  assert(0);
+}
+
+static oi_socket* 
+on_server_connection(oi_server *server, struct sockaddr *addr, socklen_t len)
+{
+  oi_socket *socket = malloc(sizeof(oi_socket));
+  oi_socket_init(socket, 5.0);
+  socket->on_read = on_peer_read;
+  socket->on_error = on_peer_error;
+  socket->on_close = on_peer_close;
+  socket->on_timeout = on_peer_timeout;
+
+  nconnections++;
+
+#if HAVE_GNUTLS
+# if SECURE
+  anon_tls_server(socket);
+# endif
+#endif
+
+  //printf("on server connection\n");
+
+  return socket;
+}
+
+int 
+main(int argc, const char *argv[])
+{
+  int r;
+  struct ev_loop *loop = ev_default_loop(0);
+  oi_server server;
+  oi_socket client;
+
+  //printf("sizeof(oi_server): %d\n", sizeof(oi_server));
+  //printf("sizeof(oi_socket): %d\n", sizeof(oi_socket));
+
+  oi_server_init(&server, 10);
+  server.on_connection = on_server_connection;
+
+#if HAVE_GNUTLS
+# if SECURE
+  anon_tls_init();
+# endif
+#endif
+
+  struct addrinfo *servinfo;
+  struct addrinfo hints;
+  memset(&hints, 0, sizeof hints);
+#if TCP
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_flags = AI_PASSIVE;
+    r = getaddrinfo(NULL, PORT, &hints, &servinfo);
+    assert(r == 0);
+#else
+    struct stat tstat;
+    if (lstat(SOCKFILE, &tstat) == 0) {
+      if (S_ISSOCK(tstat.st_mode))
+        unlink(SOCKFILE);
+    }
+
+    servinfo = malloc(sizeof(struct addrinfo));
+    servinfo->ai_family = AF_UNIX;
+    servinfo->ai_socktype = SOCK_STREAM;
+    servinfo->ai_protocol = 0;
+
+    struct sockaddr_un *sockaddr = calloc(sizeof(struct sockaddr_un), 1);
+    sockaddr->sun_family = AF_UNIX;
+    strcpy(sockaddr->sun_path, SOCKFILE);
+
+    servinfo->ai_addr = (struct sockaddr*)sockaddr;
+    servinfo->ai_addrlen = sizeof(struct sockaddr_un);
+#endif
+  r = oi_server_listen(&server, servinfo);
+  assert(r == 0);
+  oi_server_attach(&server, loop);
+
+  ev_loop(loop, 0);
+
+#if TCP
+  freeaddrinfo(servinfo);
+#endif
+
+  return 0;
+}
diff --git a/deps/liboi/test/fancy_copy.c b/deps/liboi/test/fancy_copy.c
new file mode 100644
index 0000000..f5d2ba7
--- /dev/null
+++ b/deps/liboi/test/fancy_copy.c
@@ -0,0 +1,223 @@
+/* This test uses most of oi's facilities. It starts by opening a new file
+ * and writing N characters to it. Once the first chunk is written, it opens
+ * that file with another handle 
+ *
+ * /tmp/oi_test_src == /tmp/oi_test_dst
+ *        |                  ^
+ *        |                  |
+ * stream |                  | write
+ *        |                  |
+ *        V                  |
+ *     client  ----------> server/connection
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdint.h>
+
+#ifndef TRUE
+# define TRUE 1
+#endif
+#ifndef FALSE
+# define FALSE 0
+#endif
+
+#include <oi.h>
+#include <oi_file.h>
+
+#define PORT "5555"
+
+static struct ev_loop *loop;
+static oi_file file_src;
+static oi_file file_dst;
+static oi_socket client;
+static oi_server server;
+static oi_socket connection;
+static int got_connection = 0;
+
+static char *src_filename;
+static char *dst_filename;
+
+static void
+file_error(oi_file *_)
+{
+  assert(0);
+}
+
+static void
+on_file_dst_open (oi_file *_)
+{
+  assert(connection.fd > 0);
+  oi_socket_read_start(&connection);
+  //printf("file_dst is open\n");
+}
+
+static void
+on_file_dst_close (oi_file *_)
+{
+  //printf("file dst closed\n");
+  oi_file_detach(&file_dst);
+}
+
+static void
+on_connection_read (oi_socket *_, const void *buf, size_t count)
+{
+  assert(file_dst.fd > 0);
+  if(count == 0) {
+    file_dst.on_drain = oi_file_close;
+    oi_socket_close(&connection);
+  } else {
+    oi_file_write_simple(&file_dst, buf, count);
+  }
+}
+
+static void
+on_connection_connect (oi_socket *_)
+{
+  oi_file_init(&file_dst);
+  file_dst.on_open  = on_file_dst_open;
+  file_dst.on_close = on_file_dst_close;
+  oi_file_open_path(&file_dst, dst_filename, O_WRONLY | O_CREAT, 0644);
+  oi_file_attach(&file_dst, loop);
+
+  oi_socket_read_stop(&connection);
+}
+
+static void
+on_connection_timeout (oi_socket *_)
+{
+  assert(0);
+}
+
+static void
+on_connection_error (oi_socket *_, struct oi_error e)
+{
+  assert(0);
+}
+
+static void
+on_connection_close (oi_socket *_)
+{
+  oi_server_close(&server);
+  oi_server_detach(&server);
+}
+
+static oi_socket* 
+on_server_connection(oi_server *_, struct sockaddr *addr, socklen_t len)
+{
+  assert(got_connection == FALSE);
+  oi_socket_init(&connection, 5.0);
+  connection.on_connect = on_connection_connect;
+  connection.on_read    = on_connection_read;
+  connection.on_error   = on_connection_error;
+  connection.on_close   = on_connection_close;
+  connection.on_timeout = on_connection_timeout;
+  connection.on_drain   = oi_socket_close;
+  got_connection = TRUE;
+  //printf("on server connection\n");
+  return &connection;
+}
+
+static void
+on_client_read (oi_socket *_, const void *buf, size_t count)
+{
+  assert(0);
+}
+
+static void
+on_client_error (oi_socket *_, struct oi_error e)
+{
+  assert(0);
+}
+
+static void
+on_client_connect (oi_socket *_)
+{
+  if(file_src.fd > 0) {
+    oi_file_send(&file_src, &client, 0, 50*1024); 
+  }
+}
+
+static void
+on_client_drain (oi_socket *_)
+{
+  oi_socket_close(&client);
+  oi_file_close(&file_src);
+}
+
+static void
+on_file_src_open (oi_file *_)
+{
+  if(client.fd > 0)  {
+    oi_file_send(&file_src, &client, 0, 50*1024); 
+  }
+}
+
+static void
+on_client_timeout (oi_socket *_)
+{
+  assert(0);
+}
+
+int
+main(int argc, char *argv[])
+{
+  int r; 
+  loop = ev_default_loop(0);
+
+  assert(argc == 3);
+  src_filename = argv[1];
+  dst_filename = argv[2];
+
+  assert(strlen(src_filename) > 0);
+  assert(strlen(dst_filename) > 0);
+
+  oi_server_init(&server, 10);
+  server.on_connection = on_server_connection;
+
+  struct addrinfo *servinfo;
+  struct addrinfo hints;
+  memset(&hints, 0, sizeof hints);
+
+  hints.ai_family = AF_UNSPEC;
+  hints.ai_socktype = SOCK_STREAM;
+  hints.ai_flags = AI_PASSIVE;
+  r = getaddrinfo(NULL, PORT, &hints, &servinfo);
+  assert(r == 0);
+
+  r = oi_server_listen(&server, servinfo);
+  assert(r >= 0 && "problem listening");
+  oi_server_attach(&server, loop);
+
+  oi_socket_init(&client, 5.0);
+  client.on_read    = on_client_read;
+  client.on_error   = on_client_error;
+  client.on_connect = on_client_connect;
+  client.on_timeout = on_client_timeout;
+  //client.on_close   = oi_socket_detach;
+  client.on_drain   = on_client_drain;
+  r = oi_socket_connect(&client, servinfo);
+  assert(r == 0 && "problem connecting");
+  oi_socket_attach(&client, loop);
+
+  oi_file_init(&file_src);
+  file_src.on_open = on_file_src_open;
+  file_src.on_drain = file_error;
+  file_src.on_close = oi_file_detach;
+  oi_file_open_path(&file_src, src_filename, O_RDONLY, 0700);
+  oi_file_attach(&file_src, loop);
+
+  ev_loop(loop, 0);
+
+  printf("\noi_file: %d bytes\n", sizeof(oi_file));
+  printf("oi_socket: %d bytes\n", sizeof(oi_socket));
+
+  return 0;
+}
+
diff --git a/deps/liboi/test/ping_pong.c b/deps/liboi/test/ping_pong.c
new file mode 100644
index 0000000..93199ea
--- /dev/null
+++ b/deps/liboi/test/ping_pong.c
@@ -0,0 +1,165 @@
+#include "test/common.c"
+
+#define PING "PING"
+#define PONG "PONG"
+#define EXCHANGES 100
+
+int successful_ping_count; 
+
+static void 
+on_peer_read(oi_socket *socket, const void *base, size_t len)
+{
+  if(len == 0) 
+    return;
+
+  char buf[2000];
+  strncpy(buf, base, len);
+  buf[len] = 0;
+  //printf("server got message: %s\n", buf);
+
+  oi_socket_write_simple(socket, PONG, sizeof PONG);
+}
+
+static void 
+on_peer_error(oi_socket *socket, struct oi_error e)
+{
+  assert(0);
+}
+
+static void 
+on_client_close(oi_socket *socket)
+{
+  //printf("client connection closed\n");
+  ev_unloop(socket->loop, EVUNLOOP_ALL);
+}
+
+static oi_socket* 
+on_server_connection(oi_server *server, struct sockaddr *addr, socklen_t len)
+{
+  oi_socket *socket = malloc(sizeof(oi_socket));
+  oi_socket_init(socket, 5.0);
+  socket->on_read = on_peer_read;
+  socket->on_error = on_peer_error;
+  socket->on_close = on_peer_close;
+  socket->on_timeout = on_peer_timeout;
+
+  nconnections++;
+
+#if HAVE_GNUTLS
+# if SECURE
+  anon_tls_server(socket);
+# endif
+#endif
+
+  //printf("on server connection\n");
+
+  return socket;
+}
+
+static void 
+on_client_connect(oi_socket *socket)
+{
+  //printf("client connected. sending ping\n");
+  oi_socket_write_simple(socket, PING, sizeof PING);
+}
+
+static void 
+on_client_read(oi_socket *socket, const void *base, size_t len)
+{
+  char buf[200000];
+  strncpy(buf, base, len);
+  buf[len] = 0;
+  //printf("client got message: %s\n", buf);
+  
+  if(strcmp(buf, PONG) == 0) {
+
+    if(++successful_ping_count > EXCHANGES) {
+      oi_socket_close(socket);
+      return;
+    } 
+    oi_socket_write_simple(socket, PING, sizeof PING);
+  } else {
+    assert(0);
+  }
+}
+
+int 
+main(int argc, const char *argv[])
+{
+  int r;
+  struct ev_loop *loop = ev_default_loop(0);
+  oi_server server;
+  oi_socket client;
+
+  //printf("sizeof(oi_server): %d\n", sizeof(oi_server));
+  //printf("sizeof(oi_socket): %d\n", sizeof(oi_socket));
+
+  oi_server_init(&server, 10);
+  server.on_connection = on_server_connection;
+
+#if HAVE_GNUTLS
+# if SECURE
+  anon_tls_init();
+# endif
+#endif
+
+  struct addrinfo *servinfo;
+  struct addrinfo hints;
+  memset(&hints, 0, sizeof hints);
+#if TCP
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_flags = AI_PASSIVE;
+    r = getaddrinfo(NULL, PORT, &hints, &servinfo);
+    assert(r == 0);
+#else
+    struct stat tstat;
+    if (lstat(SOCKFILE, &tstat) == 0) {
+      if (S_ISSOCK(tstat.st_mode))
+        unlink(SOCKFILE);
+    }
+
+    servinfo = malloc(sizeof(struct addrinfo));
+    servinfo->ai_family = AF_UNIX;
+    servinfo->ai_socktype = SOCK_STREAM;
+    servinfo->ai_protocol = 0;
+
+    struct sockaddr_un *sockaddr = calloc(sizeof(struct sockaddr_un), 1);
+    sockaddr->sun_family = AF_UNIX;
+    strcpy(sockaddr->sun_path, SOCKFILE);
+
+    servinfo->ai_addr = (struct sockaddr*)sockaddr;
+    servinfo->ai_addrlen = sizeof(struct sockaddr_un);
+#endif
+  r = oi_server_listen(&server, servinfo);
+  assert(r == 0);
+  oi_server_attach(&server, loop);
+
+  oi_socket_init(&client, 5.0);
+  client.on_read    = on_client_read;
+  client.on_error   = on_client_error;
+  client.on_connect = on_client_connect;
+  client.on_close   = on_client_close;
+  client.on_timeout = on_client_timeout;
+
+#if HAVE_GNUTLS
+# if SECURE
+  anon_tls_client(&client);
+# endif
+#endif
+
+  r = oi_socket_connect(&client, servinfo);
+  assert(r == 0 && "problem connecting");
+  oi_socket_attach(&client, loop);
+
+  ev_loop(loop, 0);
+
+  assert(successful_ping_count == EXCHANGES + 1);
+  assert(nconnections == 1);
+
+#if TCP
+  freeaddrinfo(servinfo);
+#endif
+
+  return 0;
+}
diff --git a/deps/liboi/test/sleeping_tasks.c b/deps/liboi/test/sleeping_tasks.c
new file mode 100644
index 0000000..d9aeadb
--- /dev/null
+++ b/deps/liboi/test/sleeping_tasks.c
@@ -0,0 +1,54 @@
+#include <unistd.h> /* sleep() */
+#include <stdlib.h> /* malloc(), free() */
+#include <assert.h>
+#include <ev.h>
+#include <oi_async.h>
+
+#define SLEEPS 4
+static int runs = 0;
+
+static void
+done (oi_task *task, unsigned int result)
+{
+  assert(result == 0);
+  if(++runs == SLEEPS) {
+    ev_timer *timer = task->data;
+    ev_timer_stop(task->async->loop, timer);
+    oi_async_detach(task->async);
+  }
+  free(task);
+}
+
+static void
+on_timeout(struct ev_loop *loop, ev_timer *w, int events)
+{
+  assert(0 && "timeout before all sleeping tasks were complete!");
+}
+
+int
+main()
+{
+  struct ev_loop *loop = ev_default_loop(0);
+  oi_async async;
+  ev_timer timer;
+  int i;
+
+  oi_async_init(&async);
+  for(i = 0; i < SLEEPS; i++) {
+    oi_task *task = malloc(sizeof(oi_task));
+    oi_task_init_sleep(task, done, 1);
+    task->data = &timer;
+    oi_async_submit(&async, task);
+  }
+  oi_async_attach(loop, &async);
+
+  
+  ev_timer_init (&timer, on_timeout, 1.2, 0.);
+  ev_timer_start (loop, &timer);
+
+  ev_loop(loop, 0);
+
+  assert(runs == SLEEPS);
+
+  return 0;
+}
diff --git a/deps/liboi/test/stdout.c b/deps/liboi/test/stdout.c
new file mode 100644
index 0000000..1bb2469
--- /dev/null
+++ b/deps/liboi/test/stdout.c
@@ -0,0 +1,64 @@
+#include <unistd.h> /* sleep() */
+#include <stdlib.h> /* malloc(), free() */
+#include <stdio.h> 
+#include <errno.h> 
+#include <assert.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <ev.h>
+#include <oi_file.h>
+
+static  oi_file file; 
+static  oi_file out; 
+
+#define READ_BUFSIZE (5)
+static char read_buf[READ_BUFSIZE];
+# define SEP "~~~~~~~~~~~~~~~~~~~~~~\n"
+
+static void
+on_open(oi_file *f)
+{
+  oi_file_write_simple(&out, "\n", 1);
+  oi_file_write_simple(&out, SEP, sizeof(SEP));
+  oi_file_read_start(f, read_buf, READ_BUFSIZE);
+}
+
+static void
+on_close(oi_file *f)
+{
+  oi_file_write_simple(&out, SEP, sizeof(SEP));
+  oi_file_detach(f);  
+  out.on_drain = oi_file_detach;
+}
+
+static void
+on_read(oi_file *f, size_t recved)
+{
+  if(recved == 0) /* EOF */
+    oi_file_close(f);
+  else
+    oi_file_write_simple(&out, read_buf, recved);
+}
+
+int
+main()
+{
+  struct ev_loop *loop = ev_default_loop(0);
+
+  oi_file_init(&file);
+  file.on_open = on_open;
+  file.on_read = on_read;
+  file.on_close = on_close;
+  oi_file_open_path(&file, "LICENSE", O_RDONLY, 0);
+  oi_file_attach(&file, loop);
+
+  oi_file_init(&out);
+  oi_file_open_stdout(&out);
+  oi_file_attach(&out, loop);
+
+  ev_loop(loop, 0);
+  return 0;
+}
diff --git a/deps/liboi/test/timeout.rb b/deps/liboi/test/timeout.rb
new file mode 100755
index 0000000..dd1dd72
--- /dev/null
+++ b/deps/liboi/test/timeout.rb
@@ -0,0 +1,96 @@
+#!/usr/bin/env ruby
+
+def test(description)
+  pid = fork do
+    exec(File.dirname(__FILE__) + "/echo")
+  end
+
+  begin
+    sleep 0.5 # give time for the server to start
+    yield(pid)
+  rescue
+    puts "\033[1;31mFAIL\033[m: #{description}"
+    raise $!
+  ensure
+    `kill -9 #{pid}`
+  end
+  puts "\033[1;32mPASS\033[m: #{description}"
+end
+
+test("make sure echo server works") do 
+  socket = TCPSocket.open("localhost", 5000)
+  w = socket.write("hello");
+  raise "error" unless w == 5
+
+  got = socket.recv(5);
+  raise "error" unless got == "hello" 
+
+  socket.close
+end
+
+test("doing nothing should not timeout the server") do |pid|
+  10.times do
+    print "."
+    STDOUT.flush
+    if Process.waitpid(pid, Process::WNOHANG)
+      raise "server died when it shouldn't have"
+    end
+    sleep 1
+  end
+  puts ""
+end
+
+test("connecting and doing nothing to should timeout in 5 seconds") do |pid|
+  socket = TCPSocket.open("localhost", 5000)
+  i = 0
+  10.times do
+    print "."
+    STDOUT.flush
+    break if Process.waitpid(pid, Process::WNOHANG)
+    sleep 1
+    i+=1
+  end
+  puts ""
+  raise "died too soon (after #{i} seconds)" if i < 5
+  raise "died too late (after #{i} seconds)" if i > 6
+end
+
+
+test("connecting and writing once to should timeout in 5 seconds") do |pid|
+  socket = TCPSocket.open("localhost", 5000)
+  w = socket.write("hello");
+  raise "error" unless w == 5
+
+  i = 0
+  10.times do
+    print "."
+    STDOUT.flush
+    break if Process.waitpid(pid, Process::WNOHANG)
+    sleep 1
+    i+=1
+  end
+  puts ""
+  raise "died too soon (after #{i} seconds)" if i < 5
+  raise "died too late (after #{i} seconds)" if i > 6
+end
+
+test("connecting waiting 3, writing once to should timeout in 8 seconds") do |pid|
+  socket = TCPSocket.open("localhost", 5000)
+
+  sleep 3
+
+  w = socket.write("hello");
+  raise "error" unless w == 5
+
+  i = 0
+  10.times do
+    print "."
+    STDOUT.flush
+    break if Process.waitpid(pid, Process::WNOHANG)
+    sleep 1
+    i+=1
+  end
+  puts ""
+  raise "died too soon (after #{i} seconds)" if i < 5
+  raise "died too late (after #{i} seconds)" if i > 6
+end
diff --git a/deps/v8/AUTHORS b/deps/v8/AUTHORS
new file mode 100644
index 0000000..060393f
--- /dev/null
+++ b/deps/v8/AUTHORS
@@ -0,0 +1,15 @@
+# Below is a list of people and organizations that have contributed
+# to the V8 project.  Names should be added to the list like so:
+#
+#   Name/Organization <email address>
+
+Google Inc.
+
+Rene Rebe <rene@exactcode.de>
+Rafal Krypa <rafal@krypa.net>
+Jay Freeman <saurik@saurik.com>
+Daniel James <dnljms@gmail.com>
+Paolo Giarrusso <p.giarrusso@gmail.com>
+Daniel Andersson <kodandersson@gmail.com>
+Alexander Botero-Lowry <alexbl@FreeBSD.org>
+Matt Hanselman <mjhanselman@gmail.com>
diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog
new file mode 100644
index 0000000..d5c30c7
--- /dev/null
+++ b/deps/v8/ChangeLog
@@ -0,0 +1,816 @@
+2009-04-15: Version 1.1.10
+
+        Fixed crash bug that occurred when loading a const variable in the
+        presence of eval.
+
+        Allowed using with and eval in registered extensions in debug mode
+        by fixing bogus assert.
+
+        Fixed the source position for function returns to enable the
+        debugger to break there.
+
+
+2009-04-14: Version 1.1.9
+
+        Made the stack traversal code in the profiler robust by avoiding
+        to look into the heap.
+
+        Added name inferencing for anonymous functions to facilitate
+        debugging and profiling.
+
+        Re-enabled stats timers in the developer shell (d8).
+
+        Fixed issue 303 by avoiding to shortcut cons-symbols.
+
+
+2009-04-11: Version 1.1.8
+
+        Changed test-debug/ThreadedDebugging to be non-flaky (issue 96).
+
+        Fixed step-in handling for Function.prototype.apply and call in 
+        the debugger (issue 269).
+
+        Fixed v8::Object::DeleteHiddenValue to not bail out when there
+        are no hidden properties.
+
+        Added workaround for crash bug, where external symbol table 
+        entries with deleted resources would lead to NPEs when looking
+        up in the symbol table.
+
+
+2009-04-07: Version 1.1.7
+
+        Added support for easily importing additional environment
+        variables into the SCons build.
+
+        Optimized strict equality checks.
+
+        Fixed crash in indexed setters on objects without a corresponding
+        getter (issue 298).
+
+        Re-enabled script compilation cache.
+
+
+2009-04-01: Version 1.1.6
+
+        Reverted an unsafe code generator change.
+
+
+2009-04-01: Version 1.1.5
+
+        Fixed bug that caused function literals to not be optimized as
+        much as other functions.
+
+        Improved profiler support.
+
+        Fixed a crash bug in connection with debugger unloading.
+
+        Fixed a crash bug in the code generator caused by losing the
+        information that a frame element was copied.
+
+        Fixed an exception propagation bug that could cause non-null
+        return values when exceptions were thrown.
+
+
+2009-03-30: Version 1.1.4
+
+        Optimized String.prototype.match.
+
+        Improved the stack information in profiles.
+
+        Fixed bug in ARM port making it possible to compile the runtime
+        system for thumb mode again.
+
+        Implemented a number of optimizations in the code generator.
+
+        Fixed a number of memory leaks in tests.
+
+        Fixed crash bug in connection with script source code and external
+        strings.
+
+
+2009-03-24: Version 1.1.3
+
+        Fixed assertion failures in compilation of loop conditions.
+
+        Removed STL dependency from developer shell (d8).
+
+        Added infrastructure for protecting the V8 heap from corruption
+        caused by memory modifications from the outside.
+
+
+2009-03-24: Version 1.1.2
+
+        Improved frame merge code generated by the code generator.
+
+        Optimized String.prototype.replace.
+
+        Implemented __defineGetter__ and __defineSetter__ for properties
+        with integer keys on non-array objects.
+
+        Improved debugger and profiler support.
+
+        Fixed a number of portability issues to allow compilation for
+        smaller ARM devices.
+
+        Exposed object cloning through the API.
+
+        Implemented hidden properties.  This is used to expose an identity
+        hash for objects through the API.
+
+        Implemented restarting of regular expressions if their input
+        string changes representation during preemption.
+
+        Fixed a code generator bug that could cause assignments in loops
+        to be ignored if using continue to break out of the loop (issue
+        284).
+
+
+2009-03-12: Version 1.1.1
+
+        Fixed an assertion in the new compiler to take stack overflow
+        exceptions into account.
+
+        Removed exception propagation code that could cause crashes.
+
+        Fixed minor bug in debugger line number computations.
+
+        8-byte align the C stack on Linux and Windows to speed up floating
+        point computations.
+
+
+2009-03-12: Version 1.1.0
+
+        Improved code generation infrastructure by doing simple register
+        allocation and constant folding and propagation.
+
+        Optimized regular expression matching by avoiding to create
+        intermediate string arrays and by flattening nested array
+        representations of RegExp data.
+
+        Traverse a few stack frames when recording profiler samples to
+        include partial call graphs in the profiling output.
+
+        Added support for using OProfile to profile generated code.
+
+        Added remote debugging support to the D8 developer shell.
+
+        Optimized creation of nested literals like JSON objects.
+
+        Fixed a bug in garbage collecting unused maps and turned it on by
+        default (--collect-maps).
+
+        Added support for running tests under Valgrind.
+
+
+2009-02-27: Version 1.0.3
+
+        Optimized double-to-integer conversions in bit operations by using
+        SSE3 instructions if available.
+
+        Optimized initialization sequences that store to multiple
+        properties of the same object.
+
+        Changed the D8 debugger frontend to use JSON messages.
+
+        Force garbage collections when disposing contexts.
+
+        Align code objects at 32-byte boundaries.
+
+
+2009-02-25: Version 1.0.2
+
+        Improved profiling support by performing simple call stack
+        sampling for ticks and by fixing a bug in the logging of code
+        addresses.
+
+        Fixed a number of debugger issues.
+
+        Optimized code that uses eval.
+
+        Fixed a couple of bugs in the regular expression engine.
+
+        Reduced the size of generated code for certain regular expressions.
+
+        Removed JSCRE completely.
+
+        Fixed issue where test could not be run if there was a dot in the
+        checkout path.
+
+
+2009-02-13: Version 1.0.1
+
+        Fixed two crash-bugs in irregexp (issue 231 and 233).
+
+        Fixed a number of minor bugs (issue 87, 227 and 228).
+
+        Added support for morphing strings to external strings on demand
+        to avoid having to create copies in the embedding code.
+
+        Removed experimental support for external symbol callbacks.
+
+
+2009-02-09: Version 1.0.0
+
+        Fixed crash-bug in the code generation for case independent 16 bit
+        backreferences.
+
+        Made shells more robust in the presence of string conversion
+        failures (issue 224).
+
+        Fixed a potential infinite loop when attempting to resolve
+        eval (issue 221).
+
+        Miscellaneous fixes to the new regular expression engine.
+
+        Reduced binary by stripping unneeded text from JavaScript library and
+        minifying some JavaScript files.
+
+
+2009-01-27: Version 0.4.9
+
+        Enabled new regular expression engine.
+
+        Made a number of changes to the debugger protocol.
+
+        Fixed a number of bugs in the preemption support.
+
+        Added -p option to the developer shell to run files in parallel
+        using preemption.
+
+        Fixed a number of minor bugs (including issues 176, 187, 189, 192,
+        193, 198 and 201).
+
+        Fixed a number of bugs in the serialization/deserialization
+        support for the ARM platform.
+
+
+2009-01-19: Version 0.4.8.1
+
+        Minor patch to debugger support.
+
+
+2009-01-16: Version 0.4.8
+
+        Fixed string length bug on ARM (issue 171).
+
+        Made most methods in the API const.
+
+        Optimized object literals by improving data locality.
+
+        Fixed bug that caused incomplete functions to be cached in case of
+        stack overflow exceptions.
+
+        Fixed bugs that caused catch variables and variables introduced by
+        eval to behave incorrectly when using accessors (issues 186, 190
+        and 191).
+
+
+2009-01-06: Version 0.4.7
+
+        Minor bugfixes and optimizations.
+
+        Added command line debugger to D8 shell.
+
+        Fixed subtle bug that caused the wrong 'this' to be used when
+        calling a caught function in a catch clause.
+
+        Inline array loads within loops directly in the code instead of
+        always calling a stub.
+
+
+2008-12-11: Version 0.4.6
+
+        Fixed exception reporting bug where certain exceptions were
+        incorrectly reported as uncaught.
+
+        Improved the memory allocation strategy used during compilation to
+        make running out of memory when compiling huge scripts less
+        likely.
+
+        Optimized String.replace by avoiding the construction of certain
+        sub strings.
+
+        Fixed bug in code generation for large switch statements on ARM.
+
+        Fixed bug that caused V8 to change the global object template
+        passed in by the user.
+
+        Changed the API for creating object groups used during garbage
+        collection.  Entire object groups are now passed to V8 instead of
+        individual members of the groups.
+
+
+2008-12-03: Version 0.4.5
+
+        Added experimental API support for allocating V8 symbols as
+        external strings.
+
+        Fixed bugs in debugging support on ARM.
+
+        Changed eval implementation to correctly detect whether or not a
+        call to eval is aliased.
+
+        Fixed bug caused by a combination of the compilation cache and
+        dictionary probing in native code.  The bug caused us to sometimes
+        call functions that had not yet been compiled.
+
+        Added platform support for FreeBSD.
+
+        Added support for building V8 on Windows with either the shared or
+        static version of MSVCRT
+
+        Added the v8::jscre namespace around the jscre functions to avoid
+        link errors (duplicate symbols) when building Google Chrome.
+
+        Added support for calling a JavaScript function with the current
+        debugger execution context as its argument to the debugger
+        interface.
+
+        Changed the type of names of counters from wchar_t to char.
+
+        Changed the Windows system call used to compute daylight savings
+        time.  The system call that we used to use became four times
+        slower on WinXP SP3.
+
+        Added support in the d8 developer shell for memory-mapped counters
+        and added a stats-viewer tool.
+
+        Fixed bug in upper/lower case mappings (issue 149).
+
+
+2008-11-17: Version 0.4.4
+
+        Reduced code size by using shorter instruction encoding when
+        possible.
+
+        Added a --help option to the shell sample and to the d8 shell.
+
+        Added visual studio project files for building the ARM simulator.
+
+        Fixed a number of ARM simulator issues.
+
+        Fixed bug in out-of-memory handling on ARM.
+
+        Implemented shell support for passing arguments to a script from
+        the command line.
+
+        Fixed bug in date code that made certain date functions return -0
+        instead of 0 for dates before the epoch.
+
+        Restricted applications of eval so it can only be used in the
+        context of the associated global object.
+
+        Treat byte-order marks as whitespace characters.
+
+
+2008-11-04: Version 0.4.3
+
+        Added support for API accessors that prohibit overwriting by
+        accessors defined in JavaScript code by using __defineGetter__ and
+        __defineSetter__.
+
+        Improved handling of conditionals in test status files.
+
+        Introduced access control in propertyIsEnumerable.
+
+        Improved performance of some string operations by caching
+        information about the type of the string between operations.
+
+        Fixed bug in fast-case code for switch statements that only have
+        integer labels.
+
+
+2008-10-30: Version 0.4.2
+
+        Improved performance of Array.prototype.concat by moving the
+        implementation to C++ (issue 123).
+
+        Fixed heap growth policy to avoid growing old space to its maximum
+        capacity before doing a garbage collection and fixed issue that
+        would lead to artificial out of memory situations (issue 129).
+
+        Fixed Date.prototype.toLocaleDateString to return the date in the
+        same format as WebKit.
+
+        Added missing initialization checks to debugger API.
+
+        Added removing of unused maps during GC.
+
+
+2008-10-28: Version 0.4.1
+
+        Added caching of RegExp data in compilation cache.
+
+        Added Visual Studio project file for d8 shell.
+
+        Fixed function call performance regression introduced in version
+        0.4.0 when splitting the global object in two parts (issue 120).
+
+        Fixed issue 131 by checking for empty handles before throwing and
+        reporting exceptions.
+
+
+2008-10-23: Version 0.4.0
+
+        Split the global object into two parts: The state holding global
+        object and the global object proxy.
+
+        Fixed bug that affected the value of an assignment to an element
+        in certain cases (issue 116).
+
+        Added GetPropertyNames functionality (issue 33) and extra Date
+        functions (issue 77) to the API.
+
+        Changed WeakReferenceCallback to take a Persistent<Value> instead
+        of a Persistent<Object> (issue 101).
+
+        Fixed issues with message reporting for exceptions in try-finally
+        blocks (issues 73 and 75).
+
+        Optimized flattening of strings and string equality checking.
+
+        Improved Boyer-Moore implementation for faster indexOf operations.
+
+        Added development shell (d8) which includes counters and
+        completion support.
+
+        Fixed problem with the receiver passed to functions called from
+        eval (issue 124).
+
+
+2008-10-16: Version 0.3.5
+
+        Improved string hash-code distribution by excluding bit-field bits
+        from the hash-code.
+
+        Changed string search algorithm used in indexOf from KMP to
+        Boyer-Moore.
+
+        Improved the generated code for the instanceof operator.
+
+        Improved performance of slow-case string equality checks by
+        specializing the code based on the string representation.
+
+        Improve the handling of out-of-memory situations (issue 70).
+
+        Improved performance of strict equality checks.
+
+        Improved profiler output to make it easier to see anonymous
+        functions.
+
+        Improved performance of slow-case keyed loads.
+
+        Improved property access performance by allocating a number of
+        properties in the front object.
+
+        Changed the toString behavior on the built-in object constructors
+        to print [native code] instead of the actual source.  Some web
+        applications do not like constructors with complex toString
+        results.
+
+
+2008-10-06: Version 0.3.4
+
+        Changed Array.prototype.sort to use quick sort.
+
+        Fixed code generation issue where leaving a finally block with
+        break or continue would accumulate elements on the expression
+        stack (issue 86).
+
+        Made sure that the name accessor on functions returns the expected
+        names for builtin JavaScript functions and C++ callback functions.
+
+        Added fast case code for extending the property storage array of
+        JavaScript objects.
+
+        Ported switch statement optimizations introduced in version 0.3.3
+        to the ARM code generator.
+
+        Allowed GCC to use strict-aliasing rules when compiling.
+
+        Improved performance of arguments object allocation by taking care
+        of arguments adaptor frames in the generated code.
+
+        Updated the V8 benchmark suite to version 2.
+
+
+2008-09-25: Version 0.3.3
+
+        Improved handling of relocation information to enable more
+        peep-hole optimizations.
+
+        Optimized switch statements where all labels are constant small
+        integers.
+
+        Optimized String.prototype.indexOf for common cases.
+
+        Fixed more build issues (issue 80).
+
+        Fixed a couple of profiler issues.
+
+        Fixed bug where the body of a function created using the Function
+        constructor was not allowed to end with a single-line comment
+        (issue 85).
+
+        Improved handling of object literals by canonicalizing object
+        literal maps.  This will allow JSON objects with the same set of
+        properties to share the same map making inline caching work better
+        for JSON objects.
+
+
+2008-09-17: Version 0.3.2
+
+        Generalized the EvalCache into a CompilationCache and enabled it
+        for scripts too.  The current strategy is to retire all entries
+        whenever a mark-sweep collection is started.
+
+        Fixed bug where switch statements containing only a default case
+        would lead to an unbalanced stack (issue 69).
+
+        Fixed bug that made access to the function in a named function
+        expression impossible in certain situations (issue 24).
+
+        Fixed even more build issues.
+
+        Optimized calling conventions on ARM.  The conventions on ARM and
+        IA-32 now match.
+
+        Removed static initializers for flags and counters.
+
+        Improved inline caching behavior for uncommon cases where lazily
+        loading Date and RegExp code could force certain code paths go
+        megamorphic.
+
+        Removed arguments adaption for builtins written in C++.  This
+        makes Array.prototype.push and Array.prototype.pop slightly
+        faster.
+
+
+2008-09-11: Version 0.3.1
+
+        Fixed a number of build issues.
+
+        Fixed problem with missing I-cache flusing on ARM.
+
+        Changed space layout in memory management by splitting up
+        code space into old data space and code space.
+
+        Added utf-8 conversion support to the API (issue 57).
+
+        Optimized repeated calls to eval with the same strings.  These
+        repeated calls are common in web applications.
+
+        Added Xcode project file.
+
+        Optimized a couple of Array operation.
+
+        Fixed parser bug by checking for end-of-string when parsing break
+        and continue (issue 35).
+
+        Fixed problem where asian characters were not categorized as
+        letters.
+
+        Fixed bug that disallowed calling functions fetched from an array
+        using a string as an array index (issue 32).
+
+        Fixed bug where the internal field count on object templates were
+        sometimes ignored (issue 54).
+
+        Added -f option to the shell sample for compatibility with other
+        engines (issue 18).
+
+        Added source info to TryCatches in the API.
+
+        Fixed problem where the seed for the random number generator was
+        clipped in a double to unsigned int conversion.
+
+        Fixed bug where cons string symbols were sometimes converted to
+        non-symbol flat strings during GC.
+
+        Fixed bug in error reporting when attempting to convert null to an
+        object.
+
+
+2008-09-04: Version 0.3.0
+
+        Added support for running tests on the ARM simulator.
+
+        Fixed bug in the 'in' operator where negative indices were not
+        treated correctly.
+
+        Fixed build issues on gcc-4.3.1.
+
+        Changed Date.prototype.toLocaleTimeString to not print the
+        timezone part of the time.
+
+        Renamed debug.h to v8-debug.h to reduce the risk of name conflicts
+        with user code.
+
+
+2008-09-02: Version 0.2.5
+
+        Renamed the top level directory 'public' to 'include'.
+
+        Added 'env' option to the SCons build scripts to support
+        overriding the ENV part of the build environment.  This is mostly
+        to support Windows builds in cases where SCons cannot find the
+        correct paths to the Windows SDK, as these paths cannot be passed
+        through shell environment variables.
+
+        Enabled "Buffer Security Check" on for the Windows SCons build and
+        added the linker option /OPT:ICF as an optimization.
+
+        Added the V8 benchmark suite to the repository.
+
+
+2008-09-01: Version 0.2.4
+
+        Included mjsunit JavaScript test suite and C++ unit tests.
+
+        Changed the shell sample to not print the result of executing a
+        script provided on the command line.
+
+        Fixed issue when building samples on Windows using a shared V8
+        library.  Added visibility option on Linux build which makes the
+        generated library 18% smaller.
+
+        Changed build system to accept multiple build modes in one build
+        and generate separate objects, libraries and executables for each
+        mode.
+
+        Removed deferred negation optimization (a * -b => -(a * b)) since
+        this visibly changes operand conversion order.
+
+        Improved parsing performance by introducing stack guard in
+        preparsing.  Without a stack guard preparsing always bails out
+        with stack overflow.
+
+        Changed shell sample to take flags directly from the command-line.
+        Added API call that implements this.
+
+        Added load, quit and version functions to the shell sample so it's
+        easier to run benchmarks and tests.
+
+        Fixed issue with building samples and cctests on 64-bit machines.
+
+        Fixed bug in the runtime system where the prototype chain was not
+        always searched for a setter when setting a property that does not
+        exist locally.
+
+
+2008-08-14: Version 0.2.3
+
+        Improved performance of garbage collection by moving the
+        function that updates pointers during compacting collection
+        into the updating visitor.  This gives the compiler a better
+        chance to inline and avoid a function call per (potential)
+        pointer.
+
+        Extended the shell sample with a --runtime-flags option.
+
+        Added Visual Studio project files for the shell.cc and
+        process.cc samples.
+
+
+2008-08-13: Version 0.2.2
+
+        Improved performance of garbage collection by changing the way
+        we use the marking stack in the event of stack overflow during
+        full garbage collection and by changing the way we mark roots.
+
+        Cleaned up ARM version by removing top of stack caching and by
+        introducing push/pop elimination.
+
+        Cleaned up the way runtime functions are called to allow
+        runtime calls with no arguments.
+
+        Changed Windows build options to make sure that exceptions are
+        disabled and that optimization flags are enabled.
+
+        Added first version of Visual Studio project files.
+
+
+2008-08-06: Version 0.2.1
+
+        Improved performance of unary addition by avoiding runtime calls.
+
+        Fixed the handling of '>' and '<=' to use right-to-left conversion
+        and left-to-right evaluation as specified by ECMA-262.
+
+        Fixed a branch elimination bug on the ARM platform where incorrect
+        code was generated because of overly aggressive branch
+        elimination.
+
+        Improved performance of code that repeatedly assigns the same
+        function to the same property of different objects with the same
+        map.
+
+        Untangled DEBUG and ENABLE_DISASSEMBLER defines.  The disassembler
+        no longer expects DEBUG to be defined.
+
+        Added platform-nullos.cc to serve as the basis for new platform
+        implementations.
+
+
+2008-07-30: Version 0.2.0
+
+        Changed all text files to have native svn:eol-style.
+
+        Added a few samples and support for building them. The samples
+        include a simple shell that can be used to benchmark and test V8.
+
+        Changed V8::GetVersion to return the version as a string.
+
+        Added source for lazily loaded scripts to snapshots and made
+        serialization non-destructive.
+
+        Improved ARM support by fixing the write barrier code to use
+        aligned loads and stores and by removing premature locals
+        optimization that relied on broken support for callee-saved
+        registers (removed).
+
+        Refactored the code for marking live objects during garbage
+        collection and the code for allocating objects in paged
+        spaces. Introduced an abstraction for the map word of a heap-
+        allocated object and changed the memory allocator to allocate
+        executable memory only for spaces that may contain code objects.
+
+        Moved StringBuilder to utils.h and ScopedLock to platform.h, where
+        they can be used by debugging and logging modules. Added
+        thread-safe message queues for dealing with debugger events.
+
+        Fixed the source code reported by toString for certain builtin
+        empty functions and made sure that the prototype property of a
+        function is enumerable.
+
+        Improved performance of converting values to condition flags in
+        generated code.
+
+        Merged disassembler-{arch} files.
+
+
+2008-07-28: Version 0.1.4
+
+        Added support for storing JavaScript stack traces in a stack
+        allocated buffer to make it visible in shallow core dumps.
+        Controlled by the --preallocate-message-memory flag which is
+        disabled by default.
+
+
+2008-07-25: Version 0.1.3
+
+        Fixed bug in JSObject::GetPropertyAttributePostInterceptor where
+        map transitions would count as properties.
+
+        Allowed aliased eval invocations by treating them as evals in the
+        global context. This may change in the future.
+
+        Added support for accessing the last entered context through the
+        API and renamed Context::Current to Context::GetCurrent and
+        Context::GetSecurityContext to Context::GetCurrentSecurityContext.
+
+        Fixed bug in the debugger that would cause the debugger scripts to
+        be recursively loaded and changed all disabling of interrupts to
+        be block-structured.
+
+        Made snapshot data read-only to allow it to be more easily shared
+        across multiple users of V8 when linked as a shared library.
+
+
+2008-07-16: Version 0.1.2
+
+        Fixed building on Mac OS X by recognizing i386 and friends as
+        IA-32 platforms.
+
+        Added propagation of stack overflow exceptions that occur while
+        compiling nested functions.
+
+        Improved debugger with support for recursive break points and
+        handling of exceptions that occur in the debugger JavaScript code.
+
+        Renamed GetInternal to GetInternalField and SetInternal to
+        SetInternalField in the API and moved InternalFieldCount and
+        SetInternalFieldCount from FunctionTemplate to ObjectTemplate.
+
+
+2008-07-09: Version 0.1.1
+
+        Fixed bug in stack overflow check code for IA-32 targets where a
+        non-tagged value in register eax was pushed to the stack.
+
+        Fixed potential quadratic behavior when converting strings to
+        numbers.
+
+        Fixed bug where the return value from Object::SetProperty could
+        end up being the property holder instead of the written value.
+
+        Improved debugger support by allowing nested break points and by
+        dealing with stack-overflows when compiling functions before
+        setting break points in them.
+
+
+2008-07-03: Version 0.1.0
+
+        Initial export.
+
diff --git a/deps/v8/LICENSE b/deps/v8/LICENSE
new file mode 100644
index 0000000..7301556
--- /dev/null
+++ b/deps/v8/LICENSE
@@ -0,0 +1,51 @@
+This license applies to all parts of V8 that are not externally
+maintained libraries.  The externally maintained libraries used by V8
+are:
+
+  - PCRE test suite, located in test/mjsunit/regexp-pcre.js.  This is
+    based on the test suite from PCRE-7.3, which is copyrighted by the
+    University of Cambridge and Google, Inc.  The copyright notice and
+    license are embedded in regexp-pcre.js.
+
+  - 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.
+    This code is copyrighted by Sun Microsystems Inc. and released
+    under a 3-clause BSD license.
+
+  - JSMin JavaScript minifier, located at tools/jsmin.py.  This code is
+    copyrighted by Douglas Crockford and Baruch Even and released under
+    an MIT license.
+
+These libraries have their own licenses; we recommend you read them,
+as their terms may differ from the terms below.
+
+Copyright 2006-2009, Google Inc. 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.
diff --git a/deps/v8/SConstruct b/deps/v8/SConstruct
new file mode 100644
index 0000000..01083cc
--- /dev/null
+++ b/deps/v8/SConstruct
@@ -0,0 +1,775 @@
+# Copyright 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.
+
+import platform
+import re
+import sys
+import os
+from os.path import join, dirname, abspath
+from types import DictType, StringTypes
+root_dir = dirname(File('SConstruct').rfile().abspath)
+sys.path.append(join(root_dir, 'tools'))
+import js2c, utils
+
+# ANDROID_TOP is the top of the Android checkout, fetched from the environment
+# variable 'TOP'.   You will also need to set the CXX, CC, AR and RANLIB
+# environment variables to the cross-compiling tools.
+ANDROID_TOP = os.environ.get('TOP')
+if ANDROID_TOP is None:
+  ANDROID_TOP=""
+
+ANDROID_FLAGS = ['-march=armv5te',
+                 '-mtune=xscale',
+                 '-msoft-float',
+                 '-fpic',
+                 '-mthumb-interwork',
+                 '-funwind-tables',
+                 '-fstack-protector',
+                 '-fno-short-enums',
+                 '-fmessage-length=0',
+                 '-finline-functions',
+                 '-fno-inline-functions-called-once',
+                 '-fgcse-after-reload',
+                 '-frerun-cse-after-loop',
+                 '-frename-registers',
+                 '-fomit-frame-pointer',
+                 '-fno-strict-aliasing',
+                 '-finline-limit=64',
+                 '-MD']
+
+ANDROID_INCLUDES = [ANDROID_TOP + '/bionic/libc/arch-arm/include',
+                    ANDROID_TOP + '/bionic/libc/include',
+                    ANDROID_TOP + '/bionic/libstdc++/include',
+                    ANDROID_TOP + '/bionic/libc/kernel/common',
+                    ANDROID_TOP + '/bionic/libc/kernel/arch-arm',
+                    ANDROID_TOP + '/bionic/libm/include',
+                    ANDROID_TOP + '/bionic/libm/include/arch/arm',
+                    ANDROID_TOP + '/bionic/libthread_db/include']
+
+ANDROID_LINKFLAGS = ['-nostdlib',
+                     '-Bdynamic',
+                     '-Wl,-T,' + ANDROID_TOP + '/build/core/armelf.x',
+                     '-Wl,-dynamic-linker,/system/bin/linker',
+                     '-Wl,--gc-sections',
+                     '-Wl,-z,nocopyreloc',
+                     '-Wl,-rpath-link=' + ANDROID_TOP + '/out/target/product/generic/obj/lib',
+                     ANDROID_TOP + '/out/target/product/generic/obj/lib/crtbegin_dynamic.o',
+                     ANDROID_TOP + '/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/lib/gcc/arm-eabi/4.2.1/interwork/libgcc.a',
+                     ANDROID_TOP + '/out/target/product/generic/obj/lib/crtend_android.o'];
+
+LIBRARY_FLAGS = {
+  'all': {
+    'CPPDEFINES':   ['ENABLE_LOGGING_AND_PROFILING']
+  },
+  'gcc': {
+    'all': {
+      'CCFLAGS':      ['$DIALECTFLAGS', '$WARNINGFLAGS'],
+      'CXXFLAGS':     ['$CCFLAGS', '-fno-rtti', '-fno-exceptions'],
+    },
+    'mode:debug': {
+      'CCFLAGS':      ['-g', '-O0'],
+      'CPPDEFINES':   ['ENABLE_DISASSEMBLER', 'DEBUG'],
+      'os:android': {
+        'CCFLAGS':    ['-mthumb']
+      }
+    },
+    'mode:release': {
+      'CCFLAGS':      ['-O3', '-fomit-frame-pointer', '-fdata-sections',
+                       '-ffunction-sections'],
+      'os:android': {
+        'CCFLAGS':    ['-mthumb', '-Os'],
+        'CPPDEFINES': ['SK_RELEASE', 'NDEBUG']
+      }
+    },
+    'os:linux': {
+      'CCFLAGS':      ['-ansi'],
+      'library:shared': {
+        'LIBS': ['pthread', 'rt']
+      }
+    },
+    'os:macos': {
+      'CCFLAGS':      ['-ansi'],
+    },
+    'os:freebsd': {
+      'CCFLAGS':      ['-ansi'],
+    },
+    'os:win32': {
+      'CCFLAGS':      ['-DWIN32'],
+      'CXXFLAGS':     ['-DWIN32'],
+    },
+    'os:android': {
+      'CPPDEFINES':   ['ANDROID', '__ARM_ARCH_5__', '__ARM_ARCH_5T__',
+                       '__ARM_ARCH_5E__', '__ARM_ARCH_5TE__'],
+      'CCFLAGS':      ANDROID_FLAGS,
+      'WARNINGFLAGS': ['-Wall', '-Wno-unused', '-Werror=return-type',
+                       '-Wstrict-aliasing=2'],
+      'CPPPATH':      ANDROID_INCLUDES,
+    },
+    'wordsize:64': {
+      'CCFLAGS':      ['-m32'],
+      'LINKFLAGS':    ['-m32']
+    },
+    'prof:oprofile': {
+      'CPPDEFINES':   ['ENABLE_OPROFILE_AGENT']
+    }
+  },
+  'msvc': {
+    'all': {
+      'DIALECTFLAGS': ['/nologo'],
+      'CCFLAGS':      ['$DIALECTFLAGS', '$WARNINGFLAGS'],
+      'CXXFLAGS':     ['$CCFLAGS', '/GR-', '/Gy'],
+      'CPPDEFINES':   ['WIN32', '_USE_32BIT_TIME_T'],
+      'LINKFLAGS':    ['/NOLOGO', '/MACHINE:X86', '/INCREMENTAL:NO',
+          '/NXCOMPAT', '/IGNORE:4221'],
+      'ARFLAGS':      ['/NOLOGO'],
+      'CCPDBFLAGS':   ['/Zi']
+    },
+    'mode:debug': {
+      'CCFLAGS':      ['/Od', '/Gm'],
+      'CPPDEFINES':   ['_DEBUG', 'ENABLE_DISASSEMBLER', 'DEBUG'],
+      'LINKFLAGS':    ['/DEBUG'],
+      'msvcrt:static': {
+        'CCFLAGS': ['/MTd']
+      },
+      'msvcrt:shared': {
+        'CCFLAGS': ['/MDd']
+      }
+    },
+    'mode:release': {
+      'CCFLAGS':      ['/O2', '/GL'],
+      'LINKFLAGS':    ['/OPT:REF', '/OPT:ICF', '/LTCG'],
+      'ARFLAGS':      ['/LTCG'],
+      'msvcrt:static': {
+        'CCFLAGS': ['/MT']
+      },
+      'msvcrt:shared': {
+        'CCFLAGS': ['/MD']
+      }
+    },
+  }
+}
+
+
+V8_EXTRA_FLAGS = {
+  'gcc': {
+    'all': {
+      'CXXFLAGS':     [], #['-fvisibility=hidden'],
+      'WARNINGFLAGS': ['-Wall', '-Werror', '-W',
+          '-Wno-unused-parameter']
+    },
+    'arch:arm': {
+      'CPPDEFINES':   ['ARM']
+    },
+    'arch:android': {
+      'CPPDEFINES':   ['ARM']
+    },
+    'os:win32': {
+      'WARNINGFLAGS': ['-pedantic', '-Wno-long-long']
+    },
+    'os:linux': {
+      'WARNINGFLAGS': ['-pedantic']
+    },
+    'os:macos': {
+      'WARNINGFLAGS': ['-pedantic']
+    },
+    'disassembler:on': {
+      'CPPDEFINES':   ['ENABLE_DISASSEMBLER']
+    }
+  },
+  'msvc': {
+    'all': {
+      'WARNINGFLAGS': ['/W3', '/WX', '/wd4355', '/wd4800']
+    },
+    'library:shared': {
+      'CPPDEFINES':   ['BUILDING_V8_SHARED'],
+      'LIBS': ['winmm', 'ws2_32']
+    },
+    'arch:arm': {
+      'CPPDEFINES':   ['ARM'],
+      # /wd4996 is to silence the warning about sscanf
+      # used by the arm simulator.
+      'WARNINGFLAGS': ['/wd4996']
+    },
+    'disassembler:on': {
+      'CPPDEFINES':   ['ENABLE_DISASSEMBLER']
+    }
+  }
+}
+
+
+MKSNAPSHOT_EXTRA_FLAGS = {
+  'gcc': {
+    'os:linux': {
+      'LIBS': ['pthread', 'rt'],
+    },
+    'os:macos': {
+      'LIBS': ['pthread'],
+    },
+    'os:freebsd': {
+      'LIBS': ['pthread'],
+    },
+    'os:win32': {
+      'LIBS': ['winmm', 'ws2_32'],
+    },
+  },
+  'msvc': {
+    'all': {
+      'LIBS': ['winmm', 'ws2_32']
+    }
+  }
+}
+
+
+DTOA_EXTRA_FLAGS = {
+  'gcc': {
+    'all': {
+      'WARNINGFLAGS': ['-Werror', '-Wno-uninitialized']
+    }
+  },
+  'msvc': {
+    'all': {
+      'WARNINGFLAGS': ['/WX', '/wd4018', '/wd4244']
+    }
+  }
+}
+
+
+CCTEST_EXTRA_FLAGS = {
+  'all': {
+    'CPPPATH': [join(root_dir, 'src')],
+    'LIBS': ['$LIBRARY']
+  },
+  'gcc': {
+    'all': {
+      'LIBPATH': [abspath('.')]
+    },
+    'os:linux': {
+      'LIBS':         ['pthread', 'rt'],
+    },
+    'os:macos': {
+      'LIBS':         ['pthread'],
+    },
+    'os:freebsd': {
+      'LIBS':         ['execinfo', 'pthread']
+    },
+    'os:win32': {
+      'LIBS': ['winmm', 'ws2_32']
+    },
+    'wordsize:64': {
+      'CCFLAGS':      ['-m32'],
+      'LINKFLAGS':    ['-m32']
+    },
+  },
+  'msvc': {
+    'all': {
+      'CPPDEFINES': ['_HAS_EXCEPTIONS=0'],
+      'LIBS': ['winmm', 'ws2_32']
+    },
+    'library:shared': {
+      'CPPDEFINES': ['USING_V8_SHARED']
+    }
+  }
+}
+
+
+SAMPLE_FLAGS = {
+  'all': {
+    'CPPPATH': [join(abspath('.'), 'include')],
+    'LIBS': ['$LIBRARY'],
+  },
+  'gcc': {
+    'all': {
+      'LIBPATH': ['.'],
+      'CCFLAGS': ['-fno-rtti', '-fno-exceptions']
+    },
+    'os:linux': {
+      'LIBS':         ['pthread', 'rt'],
+    },
+    'os:macos': {
+      'LIBS':         ['pthread'],
+    },
+    'os:freebsd': {
+      'LIBS':         ['execinfo', 'pthread']
+    },
+    'os:win32': {
+      'LIBS':         ['winmm', 'ws2_32']
+    },
+    'os:android': {
+      'CPPDEFINES':   ['ANDROID', '__ARM_ARCH_5__', '__ARM_ARCH_5T__',
+                       '__ARM_ARCH_5E__', '__ARM_ARCH_5TE__'],
+      'CCFLAGS':      ANDROID_FLAGS,
+      'CPPPATH':      ANDROID_INCLUDES,
+      'LIBPATH':     [ANDROID_TOP + '/out/target/product/generic/obj/lib'],
+      'LINKFLAGS':    ANDROID_LINKFLAGS,
+      'LIBS':         ['c', 'stdc++', 'm'],
+      'mode:release': {
+        'CPPDEFINES': ['SK_RELEASE', 'NDEBUG']
+      }
+    },
+    'wordsize:64': {
+      'CCFLAGS':      ['-m32'],
+      'LINKFLAGS':    ['-m32']
+    },
+    'mode:release': {
+      'CCFLAGS':      ['-O2']
+    },
+    'mode:debug': {
+      'CCFLAGS':      ['-g', '-O0']
+    },
+    'prof:oprofile': {
+      'LIBPATH': ['/usr/lib32', '/usr/lib32/oprofile'],
+      'LIBS': ['opagent']
+    }
+  },
+  'msvc': {
+    'all': {
+      'CCFLAGS': ['/nologo'],
+      'LINKFLAGS': ['/nologo'],
+      'LIBS': ['winmm', 'ws2_32']
+    },
+    'library:shared': {
+      'CPPDEFINES': ['USING_V8_SHARED']
+    },
+    'prof:on': {
+      'LINKFLAGS': ['/MAP']
+    },
+    'mode:release': {
+      'CCFLAGS':   ['/O2'],
+      'LINKFLAGS': ['/OPT:REF', '/OPT:ICF', '/LTCG'],
+      'msvcrt:static': {
+        'CCFLAGS': ['/MT']
+      },
+      'msvcrt:shared': {
+        'CCFLAGS': ['/MD']
+      }
+    },
+    'mode:debug': {
+      'CCFLAGS':   ['/Od'],
+      'LINKFLAGS': ['/DEBUG'],
+      'msvcrt:static': {
+        'CCFLAGS': ['/MTd']
+      },
+      'msvcrt:shared': {
+        'CCFLAGS': ['/MDd']
+      }
+    }
+  }
+}
+
+
+D8_FLAGS = {
+  'gcc': {
+    'console:readline': {
+      'LIBS': ['readline']
+    },
+    'os:linux': {
+      'LIBS': ['pthread', 'rt'],
+    },
+    'os:macos': {
+      'LIBS': ['pthread'],
+    },
+    'os:freebsd': {
+      'LIBS': ['pthread'],
+    },
+    'os:android': {
+      'LIBPATH':     [ANDROID_TOP + '/out/target/product/generic/obj/lib'],
+      'LINKFLAGS':    ANDROID_LINKFLAGS,
+      'LIBS':         ['c', 'stdc++', 'm'],
+    },
+    'os:win32': {
+      'LIBS': ['winmm', 'ws2_32'],
+    },
+  },
+  'msvc': {
+    'all': {
+      'LIBS': ['winmm', 'ws2_32']
+    }
+  }
+}
+
+
+SUFFIXES = {
+  'release': '',
+  'debug': '_g'
+}
+
+
+def Abort(message):
+  print message
+  sys.exit(1)
+
+
+def GuessToolchain(os):
+  tools = Environment()['TOOLS']
+  if 'gcc' in tools:
+    return 'gcc'
+  elif 'msvc' in tools:
+    return 'msvc'
+  else:
+    return None
+
+
+OS_GUESS = utils.GuessOS()
+TOOLCHAIN_GUESS = GuessToolchain(OS_GUESS)
+ARCH_GUESS = utils.GuessArchitecture()
+WORDSIZE_GUESS = utils.GuessWordsize()
+
+
+SIMPLE_OPTIONS = {
+  'toolchain': {
+    'values': ['gcc', 'msvc'],
+    'default': TOOLCHAIN_GUESS,
+    'help': 'the toolchain to use'
+  },
+  'os': {
+    'values': ['freebsd', 'linux', 'macos', 'win32', 'android'],
+    'default': OS_GUESS,
+    'help': 'the os to build for'
+  },
+  'arch': {
+    'values':['arm', 'ia32'],
+    'default': ARCH_GUESS,
+    'help': 'the architecture to build for'
+  },
+  'snapshot': {
+    'values': ['on', 'off', 'nobuild'],
+    'default': 'off',
+    'help': 'build using snapshots for faster start-up'
+  },
+  'prof': {
+    'values': ['on', 'off', 'oprofile'],
+    'default': 'off',
+    'help': 'enable profiling of build target'
+  },
+  'library': {
+    'values': ['static', 'shared'],
+    'default': 'static',
+    'help': 'the type of library to produce'
+  },
+  'msvcrt': {
+    'values': ['static', 'shared'],
+    'default': 'static',
+    'help': 'the type of MSVCRT library to use'
+  },
+  'wordsize': {
+    'values': ['64', '32'],
+    'default': WORDSIZE_GUESS,
+    'help': 'the word size'
+  },
+  'simulator': {
+    'values': ['arm', 'none'],
+    'default': 'none',
+    'help': 'build with simulator'
+  },
+  'disassembler': {
+    'values': ['on', 'off'],
+    'default': 'off',
+    'help': 'enable the disassembler to inspect generated code'
+  },
+  'sourcesignatures': {
+    'values': ['MD5', 'timestamp'],
+    'default': 'MD5',
+    'help': 'set how the build system detects file changes'
+  },
+  'console': {
+    'values': ['dumb', 'readline'],
+    'default': 'dumb',
+    'help': 'the console to use for the d8 shell'
+  }
+}
+
+
+def GetOptions():
+  result = Options()
+  result.Add('mode', 'compilation mode (debug, release)', 'release')
+  result.Add('sample', 'build sample (shell, process)', '')
+  result.Add('env', 'override environment settings (NAME0:value0,NAME1:value1,...)', '')
+  result.Add('importenv', 'import environment settings (NAME0,NAME1,...)', '')
+  for (name, option) in SIMPLE_OPTIONS.iteritems():
+    help = '%s (%s)' % (name, ", ".join(option['values']))
+    result.Add(name, help, option.get('default'))
+  return result
+
+
+def SplitList(str):
+  return [ s for s in str.split(",") if len(s) > 0 ]
+
+
+def IsLegal(env, option, values):
+  str = env[option]
+  for s in SplitList(str):
+    if not s in values:
+      Abort("Illegal value for option %s '%s'." % (option, s))
+      return False
+  return True
+
+
+def VerifyOptions(env):
+  if not IsLegal(env, 'mode', ['debug', 'release']):
+    return False
+  if not IsLegal(env, 'sample', ["shell", "process"]):
+    return False
+  if env['os'] == 'win32' and env['library'] == 'shared' and env['prof'] == 'on':
+    Abort("Profiling on windows only supported for static library.")
+  if env['prof'] == 'oprofile' and env['os'] != 'linux':
+    Abort("OProfile is only supported on Linux.")
+  for (name, option) in SIMPLE_OPTIONS.iteritems():
+    if (not option.get('default')) and (name not in ARGUMENTS):
+      message = ("A value for option %s must be specified (%s)." %
+          (name, ", ".join(option['values'])))
+      Abort(message)
+    if not env[name] in option['values']:
+      message = ("Unknown %s value '%s'.  Possible values are (%s)." %
+          (name, env[name], ", ".join(option['values'])))
+      Abort(message)
+
+
+class BuildContext(object):
+
+  def __init__(self, options, env_overrides, samples):
+    self.library_targets = []
+    self.mksnapshot_targets = []
+    self.cctest_targets = []
+    self.sample_targets = []
+    self.d8_targets = []
+    self.options = options
+    self.env_overrides = env_overrides
+    self.samples = samples
+    self.use_snapshot = (options['snapshot'] != 'off')
+    self.build_snapshot = (options['snapshot'] == 'on')
+    self.flags = None
+
+  def AddRelevantFlags(self, initial, flags):
+    result = initial.copy()
+    self.AppendFlags(result, flags.get('all'))
+    toolchain = self.options['toolchain']
+    if toolchain in flags:
+      self.AppendFlags(result, flags[toolchain].get('all'))
+      for option in sorted(self.options.keys()):
+        value = self.options[option]
+        self.AppendFlags(result, flags[toolchain].get(option + ':' + value))
+    return result
+
+  def AddRelevantSubFlags(self, options, flags):
+    self.AppendFlags(options, flags.get('all'))
+    for option in sorted(self.options.keys()):
+      value = self.options[option]
+      self.AppendFlags(options, flags.get(option + ':' + value))
+
+  def GetRelevantSources(self, source):
+    result = []
+    result += source.get('all', [])
+    for (name, value) in self.options.iteritems():
+      result += source.get(name + ':' + value, [])
+    return sorted(result)
+
+  def AppendFlags(self, options, added):
+    if not added:
+      return
+    for (key, value) in added.iteritems():
+      if key.find(':') != -1:
+        self.AddRelevantSubFlags(options, { key: value })
+      else:
+        if not key in options:
+          options[key] = value
+        else:
+          prefix = options[key]
+          if isinstance(prefix, StringTypes): prefix = prefix.split()
+          options[key] = prefix + value
+
+  def ConfigureObject(self, env, input, **kw):
+    if (kw.has_key('CPPPATH') and env.has_key('CPPPATH')):
+      kw['CPPPATH'] += env['CPPPATH']
+    if self.options['library'] == 'static':
+      return env.StaticObject(input, **kw)
+    else:
+      return env.SharedObject(input, **kw)
+
+  def ApplyEnvOverrides(self, env):
+    if not self.env_overrides:
+      return
+    if type(env['ENV']) == DictType:
+      env['ENV'].update(**self.env_overrides)
+    else:
+      env['ENV'] = self.env_overrides
+
+
+def PostprocessOptions(options):
+  # Adjust architecture if the simulator option has been set
+  if (options['simulator'] != 'none') and (options['arch'] != options['simulator']):
+    if 'arch' in ARGUMENTS:
+      # Print a warning if arch has explicitly been set
+      print "Warning: forcing architecture to match simulator (%s)" % options['simulator']
+    options['arch'] = options['simulator']
+
+
+def ParseEnvOverrides(arg, imports):
+  # The environment overrides are in the format NAME0:value0,NAME1:value1,...
+  # The environment imports are in the format NAME0,NAME1,...
+  overrides = {}
+  for var in imports.split(','):
+    if var in os.environ:
+      overrides[var] = os.environ[var]
+  for override in arg.split(','):
+    pos = override.find(':')
+    if pos == -1:
+      continue
+    overrides[override[:pos].strip()] = override[pos+1:].strip()
+  return overrides
+
+
+def BuildSpecific(env, mode, env_overrides):
+  options = {'mode': mode}
+  for option in SIMPLE_OPTIONS:
+    options[option] = env[option]
+  PostprocessOptions(options)
+
+  context = BuildContext(options, env_overrides, samples=SplitList(env['sample']))
+
+  library_flags = context.AddRelevantFlags(os.environ, LIBRARY_FLAGS)
+  v8_flags = context.AddRelevantFlags(library_flags, V8_EXTRA_FLAGS)
+  mksnapshot_flags = context.AddRelevantFlags(library_flags, MKSNAPSHOT_EXTRA_FLAGS)
+  dtoa_flags = context.AddRelevantFlags(library_flags, DTOA_EXTRA_FLAGS)
+  cctest_flags = context.AddRelevantFlags(v8_flags, CCTEST_EXTRA_FLAGS)
+  sample_flags = context.AddRelevantFlags(os.environ, SAMPLE_FLAGS)
+  d8_flags = context.AddRelevantFlags(library_flags, D8_FLAGS)
+
+  context.flags = {
+    'v8': v8_flags,
+    'mksnapshot': mksnapshot_flags,
+    'dtoa': dtoa_flags,
+    'cctest': cctest_flags,
+    'sample': sample_flags,
+    'd8': d8_flags
+  }
+
+  target_id = mode
+  suffix = SUFFIXES[target_id]
+  library_name = 'v8' + suffix
+  env['LIBRARY'] = library_name
+
+  # Build the object files by invoking SCons recursively.
+  (object_files, shell_files, mksnapshot) = env.SConscript(
+    join('src', 'SConscript'),
+    build_dir=join('obj', target_id),
+    exports='context',
+    duplicate=False
+  )
+
+  context.mksnapshot_targets.append(mksnapshot)
+
+  # Link the object files into a library.
+  env.Replace(**context.flags['v8'])
+  context.ApplyEnvOverrides(env)
+  if context.options['library'] == 'static':
+    library = env.StaticLibrary(library_name, object_files)
+  else:
+    # There seems to be a glitch in the way scons decides where to put
+    # PDB files when compiling using MSVC so we specify it manually.
+    # This should not affect any other platforms.
+    pdb_name = library_name + '.dll.pdb'
+    library = env.SharedLibrary(library_name, object_files, PDB=pdb_name)
+  context.library_targets.append(library)
+
+  d8_env = Environment()
+  d8_env.Replace(**context.flags['d8'])
+  shell = d8_env.Program('d8' + suffix, object_files + shell_files)
+  context.d8_targets.append(shell)
+
+  for sample in context.samples:
+    sample_env = Environment(LIBRARY=library_name)
+    sample_env.Replace(**context.flags['sample'])
+    context.ApplyEnvOverrides(sample_env)
+    sample_object = sample_env.SConscript(
+      join('samples', 'SConscript'),
+      build_dir=join('obj', 'sample', sample, target_id),
+      exports='sample context',
+      duplicate=False
+    )
+    sample_name = sample + suffix
+    sample_program = sample_env.Program(sample_name, sample_object)
+    sample_env.Depends(sample_program, library)
+    context.sample_targets.append(sample_program)
+
+  cctest_program = env.SConscript(
+    join('test', 'cctest', 'SConscript'),
+    build_dir=join('obj', 'test', target_id),
+    exports='context object_files',
+    duplicate=False
+  )
+  context.cctest_targets.append(cctest_program)
+
+  return context
+
+
+def Build():
+  opts = GetOptions()
+  env = Environment(options=opts)
+  Help(opts.GenerateHelpText(env))
+  VerifyOptions(env)
+  env_overrides = ParseEnvOverrides(env['env'], env['importenv'])
+
+  SourceSignatures(env['sourcesignatures'])
+
+  libraries = []
+  mksnapshots = []
+  cctests = []
+  samples = []
+  d8s = []
+  modes = SplitList(env['mode'])
+  for mode in modes:
+    context = BuildSpecific(env.Copy(), mode, env_overrides)
+    libraries += context.library_targets
+    mksnapshots += context.mksnapshot_targets
+    cctests += context.cctest_targets
+    samples += context.sample_targets
+    d8s += context.d8_targets
+
+  env.Alias('library', libraries)
+  env.Alias('mksnapshot', mksnapshots)
+  env.Alias('cctests', cctests)
+  env.Alias('sample', samples)
+  env.Alias('d8', d8s)
+
+  if env['sample']:
+    env.Default('sample')
+  else:
+    env.Default('library')
+
+
+# We disable deprecation warnings because we need to be able to use
+# env.Copy without getting warnings for compatibility with older
+# version of scons.  Also, there's a bug in some revisions that
+# doesn't allow this flag to be set, so we swallow any exceptions.
+# Lovely.
+try:
+  SetOption('warn', 'no-deprecated')
+except:
+  pass
+
+
+Build()
diff --git a/deps/v8/benchmarks/README.txt b/deps/v8/benchmarks/README.txt
new file mode 100644
index 0000000..46aa573
--- /dev/null
+++ b/deps/v8/benchmarks/README.txt
@@ -0,0 +1,42 @@
+V8 Benchmark Suite
+==================
+
+This is the V8 benchmark suite: A collection of pure JavaScript
+benchmarks that we have used to tune V8. The licenses for the
+individual benchmarks are included in the JavaScript files.
+
+In addition to the benchmarks, the suite consists of the benchmark
+framework (base.js), which must be loaded before any of the individual
+benchmark files, and two benchmark runners: An HTML version (run.html)
+and a standalone JavaScript version (run.js).
+
+
+Changes From Version 1 To Version 2
+===================================
+
+For version 2 the crypto benchmark was fixed.  Previously, the
+decryption stage was given plaintext as input, which resulted in an
+error.  Now, the decryption stage is given the output of the
+encryption stage as input.  The result is checked against the original
+plaintext.  For this to give the correct results the crypto objects
+are reset for each iteration of the benchmark.  In addition, the size
+of the plain text has been increased a little and the use of
+Math.random() and new Date() to build an RNG pool has been removed.
+
+Other benchmarks were fixed to do elementary verification of the
+results of their calculations.  This is to avoid accidentally
+obtaining scores that are the result of an incorrect JavaScript engine
+optimization.
+
+
+Changes From Version 2 To Version 3
+===================================
+
+Version 3 adds a new benchmark, RegExp.  The RegExp benchmark is
+generated by loading 50 of the most popular pages on the web and
+logging all regexp operations performed.  Each operation is given a
+weight that is calculated from an estimate of the popularity of the
+pages where it occurs and the number of times it is executed while
+loading each page.  Finally the literal letters in the data are
+encoded using ROT13 in a way that does not affect how the regexps
+match their input.
diff --git a/deps/v8/benchmarks/base.js b/deps/v8/benchmarks/base.js
new file mode 100644
index 0000000..2617332
--- /dev/null
+++ b/deps/v8/benchmarks/base.js
@@ -0,0 +1,233 @@
+// Copyright 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.
+
+
+// Simple framework for running the benchmark suites and
+// computing a score based on the timing measurements.
+
+
+// A benchmark has a name (string) and a function that will be run to
+// do the performance measurement.
+function Benchmark(name, run) {
+  this.name = name;
+  this.run = run;
+}
+
+
+// Benchmark results hold the benchmark and the measured time used to
+// run the benchmark. The benchmark score is computed later once a
+// full benchmark suite has run to completion.
+function BenchmarkResult(benchmark, time) {
+  this.benchmark = benchmark;
+  this.time = time;
+}
+
+
+// Automatically convert results to numbers. Used by the geometric
+// mean computation.
+BenchmarkResult.prototype.valueOf = function() {
+  return this.time;
+}
+
+
+// Suites of benchmarks consist of a name and the set of benchmarks in
+// addition to the reference timing that the final score will be based
+// on. This way, all scores are relative to a reference run and higher
+// scores implies better performance.
+function BenchmarkSuite(name, reference, benchmarks) {
+  this.name = name;
+  this.reference = reference;
+  this.benchmarks = benchmarks;
+  BenchmarkSuite.suites.push(this);
+}
+
+
+// Keep track of all declared benchmark suites.
+BenchmarkSuite.suites = [];
+
+
+// Scores are not comparable across versions. Bump the version if
+// you're making changes that will affect that scores, e.g. if you add
+// a new benchmark or change an existing one.
+BenchmarkSuite.version = '3';
+
+
+// To make the benchmark results predictable, we replace Math.random
+// with a 100% deterministic alternative.
+Math.random = (function() {
+  var seed = 49734321;
+  return function() {
+    // Robert Jenkins' 32 bit integer hash function.
+    seed = ((seed + 0x7ed55d16) + (seed << 12))  & 0xffffffff;
+    seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff;
+    seed = ((seed + 0x165667b1) + (seed << 5))   & 0xffffffff;
+    seed = ((seed + 0xd3a2646c) ^ (seed << 9))   & 0xffffffff;
+    seed = ((seed + 0xd3a2646c) ^ (seed << 9))   & 0xffffffff;
+    seed = ((seed + 0xfd7046c5) + (seed << 3))   & 0xffffffff;
+    seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff;
+    return (seed & 0xfffffff) / 0x10000000;
+  };
+})();
+
+
+// Runs all registered benchmark suites and optionally yields between
+// each individual benchmark to avoid running for too long in the
+// context of browsers. Once done, the final score is reported to the
+// runner.
+BenchmarkSuite.RunSuites = function(runner) {
+  var continuation = null;
+  var suites = BenchmarkSuite.suites;
+  var length = suites.length;
+  BenchmarkSuite.scores = [];
+  var index = 0;
+  function RunStep() {
+    while (continuation || index < length) {
+      if (continuation) {
+        continuation = continuation();
+      } else {
+        var suite = suites[index++];
+        if (runner.NotifyStart) runner.NotifyStart(suite.name);
+        continuation = suite.RunStep(runner);
+      }
+      if (continuation && typeof window != 'undefined' && window.setTimeout) {
+        window.setTimeout(RunStep, 100);
+        return;
+      }
+    }
+    if (runner.NotifyScore) {
+      var score = BenchmarkSuite.GeometricMean(BenchmarkSuite.scores);
+      var formatted = BenchmarkSuite.FormatScore(100 * score);
+      runner.NotifyScore(formatted);
+    }
+  }
+  RunStep();
+}
+
+
+// Counts the total number of registered benchmarks. Useful for
+// showing progress as a percentage.
+BenchmarkSuite.CountBenchmarks = function() {
+  var result = 0;
+  var suites = BenchmarkSuite.suites;
+  for (var i = 0; i < suites.length; i++) {
+    result += suites[i].benchmarks.length;
+  }
+  return result;
+}
+
+
+// Computes the geometric mean of a set of numbers.
+BenchmarkSuite.GeometricMean = function(numbers) {
+  var log = 0;
+  for (var i = 0; i < numbers.length; i++) {
+    log += Math.log(numbers[i]);
+  }
+  return Math.pow(Math.E, log / numbers.length);
+}
+
+
+// Converts a score value to a string with at least three significant
+// digits.
+BenchmarkSuite.FormatScore = function(value) {
+  if (value > 100) {
+    return value.toFixed(0);
+  } else {
+    return value.toPrecision(3);
+  }
+}
+
+// Notifies the runner that we're done running a single benchmark in
+// the benchmark suite. This can be useful to report progress.
+BenchmarkSuite.prototype.NotifyStep = function(result) {
+  this.results.push(result);
+  if (this.runner.NotifyStep) this.runner.NotifyStep(result.benchmark.name);
+}
+
+
+// Notifies the runner that we're done with running a suite and that
+// we have a result which can be reported to the user if needed.
+BenchmarkSuite.prototype.NotifyResult = function() {
+  var mean = BenchmarkSuite.GeometricMean(this.results);
+  var score = this.reference / mean;
+  BenchmarkSuite.scores.push(score);
+  if (this.runner.NotifyResult) {
+    var formatted = BenchmarkSuite.FormatScore(100 * score);
+    this.runner.NotifyResult(this.name, formatted);
+  }
+}
+
+
+// Notifies the runner that running a benchmark resulted in an error.
+BenchmarkSuite.prototype.NotifyError = function(error) {
+  if (this.runner.NotifyError) {
+    this.runner.NotifyError(this.name, error);
+  }
+  if (this.runner.NotifyStep) {
+    this.runner.NotifyStep(this.name);
+  }
+}
+
+
+// Runs a single benchmark for at least a second and computes the
+// average time it takes to run a single iteration.
+BenchmarkSuite.prototype.RunSingle = function(benchmark) {
+  var elapsed = 0;
+  var start = new Date();
+  for (var n = 0; elapsed < 1000; n++) {
+    benchmark.run();
+    elapsed = new Date() - start;
+  }
+  var usec = (elapsed * 1000) / n;
+  this.NotifyStep(new BenchmarkResult(benchmark, usec));
+}
+
+
+// This function starts running a suite, but stops between each
+// individual benchmark in the suite and returns a continuation
+// function which can be invoked to run the next benchmark. Once the
+// last benchmark has been executed, null is returned.
+BenchmarkSuite.prototype.RunStep = function(runner) {
+  this.results = [];
+  this.runner = runner;
+  var length = this.benchmarks.length;
+  var index = 0;
+  var suite = this;
+  function RunNext() {
+    if (index < length) {
+      try {
+        suite.RunSingle(suite.benchmarks[index++]);
+      } catch (e) {
+        suite.NotifyError(e);
+        return null;
+      }
+      return RunNext;
+    }
+    suite.NotifyResult();
+    return null;
+  }
+  return RunNext();
+}
diff --git a/deps/v8/benchmarks/crypto.js b/deps/v8/benchmarks/crypto.js
new file mode 100644
index 0000000..12b88ef
--- /dev/null
+++ b/deps/v8/benchmarks/crypto.js
@@ -0,0 +1,1698 @@
+/*
+ * Copyright (c) 2003-2005  Tom Wu
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following condition applies:
+ *
+ * All redistributions must retain an intact copy of this copyright notice
+ * and disclaimer.
+ */
+
+
+// The code has been adapted for use as a benchmark by Google.
+var Crypto = new BenchmarkSuite('Crypto', 203037, [
+  new Benchmark("Encrypt", encrypt),
+  new Benchmark("Decrypt", decrypt)
+]);
+
+
+// Basic JavaScript BN library - subset useful for RSA encryption.
+
+// Bits per digit
+var dbits;
+var BI_DB;
+var BI_DM;
+var BI_DV;
+
+var BI_FP;
+var BI_FV;
+var BI_F1;
+var BI_F2;
+
+// JavaScript engine analysis
+var canary = 0xdeadbeefcafe;
+var j_lm = ((canary&0xffffff)==0xefcafe);
+
+// (public) Constructor
+function BigInteger(a,b,c) {
+  this.array = new Array();
+  if(a != null)
+    if("number" == typeof a) this.fromNumber(a,b,c);
+    else if(b == null && "string" != typeof a) this.fromString(a,256);
+    else this.fromString(a,b);
+}
+
+// return new, unset BigInteger
+function nbi() { return new BigInteger(null); }
+
+// am: Compute w_j += (x*this_i), propagate carries,
+// c is initial carry, returns final carry.
+// c < 3*dvalue, x < 2*dvalue, this_i < dvalue
+// We need to select the fastest one that works in this environment.
+
+// am1: use a single mult and divide to get the high bits,
+// max digit bits should be 26 because
+// max internal value = 2*dvalue^2-2*dvalue (< 2^53)
+function am1(i,x,w,j,c,n) {
+  var this_array = this.array;
+  var w_array    = w.array;
+  while(--n >= 0) {
+    var v = x*this_array[i++]+w_array[j]+c;
+    c = Math.floor(v/0x4000000);
+    w_array[j++] = v&0x3ffffff;
+  }
+  return c;
+}
+
+// am2 avoids a big mult-and-extract completely.
+// Max digit bits should be <= 30 because we do bitwise ops
+// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
+function am2(i,x,w,j,c,n) {
+  var this_array = this.array;
+  var w_array    = w.array;
+  var xl = x&0x7fff, xh = x>>15;
+  while(--n >= 0) {
+    var l = this_array[i]&0x7fff;
+    var h = this_array[i++]>>15;
+    var m = xh*l+h*xl;
+    l = xl*l+((m&0x7fff)<<15)+w_array[j]+(c&0x3fffffff);
+    c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
+    w_array[j++] = l&0x3fffffff;
+  }
+  return c;
+}
+
+// Alternately, set max digit bits to 28 since some
+// browsers slow down when dealing with 32-bit numbers.
+function am3(i,x,w,j,c,n) {
+  var this_array = this.array;
+  var w_array    = w.array;
+
+  var xl = x&0x3fff, xh = x>>14;
+  while(--n >= 0) {
+    var l = this_array[i]&0x3fff;
+    var h = this_array[i++]>>14;
+    var m = xh*l+h*xl;
+    l = xl*l+((m&0x3fff)<<14)+w_array[j]+c;
+    c = (l>>28)+(m>>14)+xh*h;
+    w_array[j++] = l&0xfffffff;
+  }
+  return c;
+}
+
+// This is tailored to VMs with 2-bit tagging. It makes sure
+// that all the computations stay within the 29 bits available.
+function am4(i,x,w,j,c,n) {
+  var this_array = this.array;
+  var w_array    = w.array;
+
+  var xl = x&0x1fff, xh = x>>13;
+  while(--n >= 0) {
+    var l = this_array[i]&0x1fff;
+    var h = this_array[i++]>>13;
+    var m = xh*l+h*xl;
+    l = xl*l+((m&0x1fff)<<13)+w_array[j]+c;
+    c = (l>>26)+(m>>13)+xh*h;
+    w_array[j++] = l&0x3ffffff;
+  }
+  return c;
+}
+
+// am3/28 is best for SM, Rhino, but am4/26 is best for v8.
+// Kestrel (Opera 9.5) gets its best result with am4/26.
+// IE7 does 9% better with am3/28 than with am4/26.
+// Firefox (SM) gets 10% faster with am3/28 than with am4/26.
+
+setupEngine = function(fn, bits) {
+  BigInteger.prototype.am = fn;
+  dbits = bits;
+
+  BI_DB = dbits;
+  BI_DM = ((1<<dbits)-1);
+  BI_DV = (1<<dbits);
+
+  BI_FP = 52;
+  BI_FV = Math.pow(2,BI_FP);
+  BI_F1 = BI_FP-dbits;
+  BI_F2 = 2*dbits-BI_FP;
+}
+
+
+// Digit conversions
+var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
+var BI_RC = new Array();
+var rr,vv;
+rr = "0".charCodeAt(0);
+for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
+rr = "a".charCodeAt(0);
+for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
+rr = "A".charCodeAt(0);
+for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
+
+function int2char(n) { return BI_RM.charAt(n); }
+function intAt(s,i) {
+  var c = BI_RC[s.charCodeAt(i)];
+  return (c==null)?-1:c;
+}
+
+// (protected) copy this to r
+function bnpCopyTo(r) {
+  var this_array = this.array;
+  var r_array    = r.array;
+
+  for(var i = this.t-1; i >= 0; --i) r_array[i] = this_array[i];
+  r.t = this.t;
+  r.s = this.s;
+}
+
+// (protected) set from integer value x, -DV <= x < DV
+function bnpFromInt(x) {
+  var this_array = this.array;
+  this.t = 1;
+  this.s = (x<0)?-1:0;
+  if(x > 0) this_array[0] = x;
+  else if(x < -1) this_array[0] = x+DV;
+  else this.t = 0;
+}
+
+// return bigint initialized to value
+function nbv(i) { var r = nbi(); r.fromInt(i); return r; }
+
+// (protected) set from string and radix
+function bnpFromString(s,b) {
+  var this_array = this.array;
+  var k;
+  if(b == 16) k = 4;
+  else if(b == 8) k = 3;
+  else if(b == 256) k = 8; // byte array
+  else if(b == 2) k = 1;
+  else if(b == 32) k = 5;
+  else if(b == 4) k = 2;
+  else { this.fromRadix(s,b); return; }
+  this.t = 0;
+  this.s = 0;
+  var i = s.length, mi = false, sh = 0;
+  while(--i >= 0) {
+    var x = (k==8)?s[i]&0xff:intAt(s,i);
+    if(x < 0) {
+      if(s.charAt(i) == "-") mi = true;
+      continue;
+    }
+    mi = false;
+    if(sh == 0)
+      this_array[this.t++] = x;
+    else if(sh+k > BI_DB) {
+      this_array[this.t-1] |= (x&((1<<(BI_DB-sh))-1))<<sh;
+      this_array[this.t++] = (x>>(BI_DB-sh));
+    }
+    else
+      this_array[this.t-1] |= x<<sh;
+    sh += k;
+    if(sh >= BI_DB) sh -= BI_DB;
+  }
+  if(k == 8 && (s[0]&0x80) != 0) {
+    this.s = -1;
+    if(sh > 0) this_array[this.t-1] |= ((1<<(BI_DB-sh))-1)<<sh;
+  }
+  this.clamp();
+  if(mi) BigInteger.ZERO.subTo(this,this);
+}
+
+// (protected) clamp off excess high words
+function bnpClamp() {
+  var this_array = this.array;
+  var c = this.s&BI_DM;
+  while(this.t > 0 && this_array[this.t-1] == c) --this.t;
+}
+
+// (public) return string representation in given radix
+function bnToString(b) {
+  var this_array = this.array;
+  if(this.s < 0) return "-"+this.negate().toString(b);
+  var k;
+  if(b == 16) k = 4;
+  else if(b == 8) k = 3;
+  else if(b == 2) k = 1;
+  else if(b == 32) k = 5;
+  else if(b == 4) k = 2;
+  else return this.toRadix(b);
+  var km = (1<<k)-1, d, m = false, r = "", i = this.t;
+  var p = BI_DB-(i*BI_DB)%k;
+  if(i-- > 0) {
+    if(p < BI_DB && (d = this_array[i]>>p) > 0) { m = true; r = int2char(d); }
+    while(i >= 0) {
+      if(p < k) {
+        d = (this_array[i]&((1<<p)-1))<<(k-p);
+        d |= this_array[--i]>>(p+=BI_DB-k);
+      }
+      else {
+        d = (this_array[i]>>(p-=k))&km;
+        if(p <= 0) { p += BI_DB; --i; }
+      }
+      if(d > 0) m = true;
+      if(m) r += int2char(d);
+    }
+  }
+  return m?r:"0";
+}
+
+// (public) -this
+function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
+
+// (public) |this|
+function bnAbs() { return (this.s<0)?this.negate():this; }
+
+// (public) return + if this > a, - if this < a, 0 if equal
+function bnCompareTo(a) {
+  var this_array = this.array;
+  var a_array = a.array;
+
+  var r = this.s-a.s;
+  if(r != 0) return r;
+  var i = this.t;
+  r = i-a.t;
+  if(r != 0) return r;
+  while(--i >= 0) if((r=this_array[i]-a_array[i]) != 0) return r;
+  return 0;
+}
+
+// returns bit length of the integer x
+function nbits(x) {
+  var r = 1, t;
+  if((t=x>>>16) != 0) { x = t; r += 16; }
+  if((t=x>>8) != 0) { x = t; r += 8; }
+  if((t=x>>4) != 0) { x = t; r += 4; }
+  if((t=x>>2) != 0) { x = t; r += 2; }
+  if((t=x>>1) != 0) { x = t; r += 1; }
+  return r;
+}
+
+// (public) return the number of bits in "this"
+function bnBitLength() {
+  var this_array = this.array;
+  if(this.t <= 0) return 0;
+  return BI_DB*(this.t-1)+nbits(this_array[this.t-1]^(this.s&BI_DM));
+}
+
+// (protected) r = this << n*DB
+function bnpDLShiftTo(n,r) {
+  var this_array = this.array;
+  var r_array = r.array;
+  var i;
+  for(i = this.t-1; i >= 0; --i) r_array[i+n] = this_array[i];
+  for(i = n-1; i >= 0; --i) r_array[i] = 0;
+  r.t = this.t+n;
+  r.s = this.s;
+}
+
+// (protected) r = this >> n*DB
+function bnpDRShiftTo(n,r) {
+  var this_array = this.array;
+  var r_array = r.array;
+  for(var i = n; i < this.t; ++i) r_array[i-n] = this_array[i];
+  r.t = Math.max(this.t-n,0);
+  r.s = this.s;
+}
+
+// (protected) r = this << n
+function bnpLShiftTo(n,r) {
+  var this_array = this.array;
+  var r_array = r.array;
+  var bs = n%BI_DB;
+  var cbs = BI_DB-bs;
+  var bm = (1<<cbs)-1;
+  var ds = Math.floor(n/BI_DB), c = (this.s<<bs)&BI_DM, i;
+  for(i = this.t-1; i >= 0; --i) {
+    r_array[i+ds+1] = (this_array[i]>>cbs)|c;
+    c = (this_array[i]&bm)<<bs;
+  }
+  for(i = ds-1; i >= 0; --i) r_array[i] = 0;
+  r_array[ds] = c;
+  r.t = this.t+ds+1;
+  r.s = this.s;
+  r.clamp();
+}
+
+// (protected) r = this >> n
+function bnpRShiftTo(n,r) {
+  var this_array = this.array;
+  var r_array = r.array;
+  r.s = this.s;
+  var ds = Math.floor(n/BI_DB);
+  if(ds >= this.t) { r.t = 0; return; }
+  var bs = n%BI_DB;
+  var cbs = BI_DB-bs;
+  var bm = (1<<bs)-1;
+  r_array[0] = this_array[ds]>>bs;
+  for(var i = ds+1; i < this.t; ++i) {
+    r_array[i-ds-1] |= (this_array[i]&bm)<<cbs;
+    r_array[i-ds] = this_array[i]>>bs;
+  }
+  if(bs > 0) r_array[this.t-ds-1] |= (this.s&bm)<<cbs;
+  r.t = this.t-ds;
+  r.clamp();
+}
+
+// (protected) r = this - a
+function bnpSubTo(a,r) {
+  var this_array = this.array;
+  var r_array = r.array;
+  var a_array = a.array;
+  var i = 0, c = 0, m = Math.min(a.t,this.t);
+  while(i < m) {
+    c += this_array[i]-a_array[i];
+    r_array[i++] = c&BI_DM;
+    c >>= BI_DB;
+  }
+  if(a.t < this.t) {
+    c -= a.s;
+    while(i < this.t) {
+      c += this_array[i];
+      r_array[i++] = c&BI_DM;
+      c >>= BI_DB;
+    }
+    c += this.s;
+  }
+  else {
+    c += this.s;
+    while(i < a.t) {
+      c -= a_array[i];
+      r_array[i++] = c&BI_DM;
+      c >>= BI_DB;
+    }
+    c -= a.s;
+  }
+  r.s = (c<0)?-1:0;
+  if(c < -1) r_array[i++] = BI_DV+c;
+  else if(c > 0) r_array[i++] = c;
+  r.t = i;
+  r.clamp();
+}
+
+// (protected) r = this * a, r != this,a (HAC 14.12)
+// "this" should be the larger one if appropriate.
+function bnpMultiplyTo(a,r) {
+  var this_array = this.array;
+  var r_array = r.array;
+  var x = this.abs(), y = a.abs();
+  var y_array = y.array;
+
+  var i = x.t;
+  r.t = i+y.t;
+  while(--i >= 0) r_array[i] = 0;
+  for(i = 0; i < y.t; ++i) r_array[i+x.t] = x.am(0,y_array[i],r,i,0,x.t);
+  r.s = 0;
+  r.clamp();
+  if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
+}
+
+// (protected) r = this^2, r != this (HAC 14.16)
+function bnpSquareTo(r) {
+  var x = this.abs();
+  var x_array = x.array;
+  var r_array = r.array;
+
+  var i = r.t = 2*x.t;
+  while(--i >= 0) r_array[i] = 0;
+  for(i = 0; i < x.t-1; ++i) {
+    var c = x.am(i,x_array[i],r,2*i,0,1);
+    if((r_array[i+x.t]+=x.am(i+1,2*x_array[i],r,2*i+1,c,x.t-i-1)) >= BI_DV) {
+      r_array[i+x.t] -= BI_DV;
+      r_array[i+x.t+1] = 1;
+    }
+  }
+  if(r.t > 0) r_array[r.t-1] += x.am(i,x_array[i],r,2*i,0,1);
+  r.s = 0;
+  r.clamp();
+}
+
+// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
+// r != q, this != m.  q or r may be null.
+function bnpDivRemTo(m,q,r) {
+  var pm = m.abs();
+  if(pm.t <= 0) return;
+  var pt = this.abs();
+  if(pt.t < pm.t) {
+    if(q != null) q.fromInt(0);
+    if(r != null) this.copyTo(r);
+    return;
+  }
+  if(r == null) r = nbi();
+  var y = nbi(), ts = this.s, ms = m.s;
+  var pm_array = pm.array;
+  var nsh = BI_DB-nbits(pm_array[pm.t-1]);	// normalize modulus
+  if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
+  else { pm.copyTo(y); pt.copyTo(r); }
+  var ys = y.t;
+
+  var y_array = y.array;
+  var y0 = y_array[ys-1];
+  if(y0 == 0) return;
+  var yt = y0*(1<<BI_F1)+((ys>1)?y_array[ys-2]>>BI_F2:0);
+  var d1 = BI_FV/yt, d2 = (1<<BI_F1)/yt, e = 1<<BI_F2;
+  var i = r.t, j = i-ys, t = (q==null)?nbi():q;
+  y.dlShiftTo(j,t);
+
+  var r_array = r.array;
+  if(r.compareTo(t) >= 0) {
+    r_array[r.t++] = 1;
+    r.subTo(t,r);
+  }
+  BigInteger.ONE.dlShiftTo(ys,t);
+  t.subTo(y,y);	// "negative" y so we can replace sub with am later
+  while(y.t < ys) y_array[y.t++] = 0;
+  while(--j >= 0) {
+    // Estimate quotient digit
+    var qd = (r_array[--i]==y0)?BI_DM:Math.floor(r_array[i]*d1+(r_array[i-1]+e)*d2);
+    if((r_array[i]+=y.am(0,qd,r,j,0,ys)) < qd) {	// Try it out
+      y.dlShiftTo(j,t);
+      r.subTo(t,r);
+      while(r_array[i] < --qd) r.subTo(t,r);
+    }
+  }
+  if(q != null) {
+    r.drShiftTo(ys,q);
+    if(ts != ms) BigInteger.ZERO.subTo(q,q);
+  }
+  r.t = ys;
+  r.clamp();
+  if(nsh > 0) r.rShiftTo(nsh,r);	// Denormalize remainder
+  if(ts < 0) BigInteger.ZERO.subTo(r,r);
+}
+
+// (public) this mod a
+function bnMod(a) {
+  var r = nbi();
+  this.abs().divRemTo(a,null,r);
+  if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
+  return r;
+}
+
+// Modular reduction using "classic" algorithm
+function Classic(m) { this.m = m; }
+function cConvert(x) {
+  if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
+  else return x;
+}
+function cRevert(x) { return x; }
+function cReduce(x) { x.divRemTo(this.m,null,x); }
+function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
+function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
+
+Classic.prototype.convert = cConvert;
+Classic.prototype.revert = cRevert;
+Classic.prototype.reduce = cReduce;
+Classic.prototype.mulTo = cMulTo;
+Classic.prototype.sqrTo = cSqrTo;
+
+// (protected) return "-1/this % 2^DB"; useful for Mont. reduction
+// justification:
+//         xy == 1 (mod m)
+//         xy =  1+km
+//   xy(2-xy) = (1+km)(1-km)
+// x[y(2-xy)] = 1-k^2m^2
+// x[y(2-xy)] == 1 (mod m^2)
+// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
+// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
+// JS multiply "overflows" differently from C/C++, so care is needed here.
+function bnpInvDigit() {
+  var this_array = this.array;
+  if(this.t < 1) return 0;
+  var x = this_array[0];
+  if((x&1) == 0) return 0;
+  var y = x&3;		// y == 1/x mod 2^2
+  y = (y*(2-(x&0xf)*y))&0xf;	// y == 1/x mod 2^4
+  y = (y*(2-(x&0xff)*y))&0xff;	// y == 1/x mod 2^8
+  y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff;	// y == 1/x mod 2^16
+  // last step - calculate inverse mod DV directly;
+  // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
+  y = (y*(2-x*y%BI_DV))%BI_DV;		// y == 1/x mod 2^dbits
+  // we really want the negative inverse, and -DV < y < DV
+  return (y>0)?BI_DV-y:-y;
+}
+
+// Montgomery reduction
+function Montgomery(m) {
+  this.m = m;
+  this.mp = m.invDigit();
+  this.mpl = this.mp&0x7fff;
+  this.mph = this.mp>>15;
+  this.um = (1<<(BI_DB-15))-1;
+  this.mt2 = 2*m.t;
+}
+
+// xR mod m
+function montConvert(x) {
+  var r = nbi();
+  x.abs().dlShiftTo(this.m.t,r);
+  r.divRemTo(this.m,null,r);
+  if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
+  return r;
+}
+
+// x/R mod m
+function montRevert(x) {
+  var r = nbi();
+  x.copyTo(r);
+  this.reduce(r);
+  return r;
+}
+
+// x = x/R mod m (HAC 14.32)
+function montReduce(x) {
+  var x_array = x.array;
+  while(x.t <= this.mt2)	// pad x so am has enough room later
+    x_array[x.t++] = 0;
+  for(var i = 0; i < this.m.t; ++i) {
+    // faster way of calculating u0 = x[i]*mp mod DV
+    var j = x_array[i]&0x7fff;
+    var u0 = (j*this.mpl+(((j*this.mph+(x_array[i]>>15)*this.mpl)&this.um)<<15))&BI_DM;
+    // use am to combine the multiply-shift-add into one call
+    j = i+this.m.t;
+    x_array[j] += this.m.am(0,u0,x,i,0,this.m.t);
+    // propagate carry
+    while(x_array[j] >= BI_DV) { x_array[j] -= BI_DV; x_array[++j]++; }
+  }
+  x.clamp();
+  x.drShiftTo(this.m.t,x);
+  if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
+}
+
+// r = "x^2/R mod m"; x != r
+function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
+
+// r = "xy/R mod m"; x,y != r
+function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
+
+Montgomery.prototype.convert = montConvert;
+Montgomery.prototype.revert = montRevert;
+Montgomery.prototype.reduce = montReduce;
+Montgomery.prototype.mulTo = montMulTo;
+Montgomery.prototype.sqrTo = montSqrTo;
+
+// (protected) true iff this is even
+function bnpIsEven() {
+  var this_array = this.array;
+  return ((this.t>0)?(this_array[0]&1):this.s) == 0;
+}
+
+// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
+function bnpExp(e,z) {
+  if(e > 0xffffffff || e < 1) return BigInteger.ONE;
+  var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
+  g.copyTo(r);
+  while(--i >= 0) {
+    z.sqrTo(r,r2);
+    if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
+    else { var t = r; r = r2; r2 = t; }
+  }
+  return z.revert(r);
+}
+
+// (public) this^e % m, 0 <= e < 2^32
+function bnModPowInt(e,m) {
+  var z;
+  if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
+  return this.exp(e,z);
+}
+
+// protected
+BigInteger.prototype.copyTo = bnpCopyTo;
+BigInteger.prototype.fromInt = bnpFromInt;
+BigInteger.prototype.fromString = bnpFromString;
+BigInteger.prototype.clamp = bnpClamp;
+BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
+BigInteger.prototype.drShiftTo = bnpDRShiftTo;
+BigInteger.prototype.lShiftTo = bnpLShiftTo;
+BigInteger.prototype.rShiftTo = bnpRShiftTo;
+BigInteger.prototype.subTo = bnpSubTo;
+BigInteger.prototype.multiplyTo = bnpMultiplyTo;
+BigInteger.prototype.squareTo = bnpSquareTo;
+BigInteger.prototype.divRemTo = bnpDivRemTo;
+BigInteger.prototype.invDigit = bnpInvDigit;
+BigInteger.prototype.isEven = bnpIsEven;
+BigInteger.prototype.exp = bnpExp;
+
+// public
+BigInteger.prototype.toString = bnToString;
+BigInteger.prototype.negate = bnNegate;
+BigInteger.prototype.abs = bnAbs;
+BigInteger.prototype.compareTo = bnCompareTo;
+BigInteger.prototype.bitLength = bnBitLength;
+BigInteger.prototype.mod = bnMod;
+BigInteger.prototype.modPowInt = bnModPowInt;
+
+// "constants"
+BigInteger.ZERO = nbv(0);
+BigInteger.ONE = nbv(1);
+// Copyright (c) 2005  Tom Wu
+// All Rights Reserved.
+// See "LICENSE" for details.
+
+// Extended JavaScript BN functions, required for RSA private ops.
+
+// (public)
+function bnClone() { var r = nbi(); this.copyTo(r); return r; }
+
+// (public) return value as integer
+function bnIntValue() {
+  var this_array = this.array;
+  if(this.s < 0) {
+    if(this.t == 1) return this_array[0]-BI_DV;
+    else if(this.t == 0) return -1;
+  }
+  else if(this.t == 1) return this_array[0];
+  else if(this.t == 0) return 0;
+  // assumes 16 < DB < 32
+  return ((this_array[1]&((1<<(32-BI_DB))-1))<<BI_DB)|this_array[0];
+}
+
+// (public) return value as byte
+function bnByteValue() {
+  var this_array = this.array;
+  return (this.t==0)?this.s:(this_array[0]<<24)>>24;
+}
+
+// (public) return value as short (assumes DB>=16)
+function bnShortValue() {
+  var this_array = this.array;
+  return (this.t==0)?this.s:(this_array[0]<<16)>>16;
+}
+
+// (protected) return x s.t. r^x < DV
+function bnpChunkSize(r) { return Math.floor(Math.LN2*BI_DB/Math.log(r)); }
+
+// (public) 0 if this == 0, 1 if this > 0
+function bnSigNum() {
+  var this_array = this.array;
+  if(this.s < 0) return -1;
+  else if(this.t <= 0 || (this.t == 1 && this_array[0] <= 0)) return 0;
+  else return 1;
+}
+
+// (protected) convert to radix string
+function bnpToRadix(b) {
+  if(b == null) b = 10;
+  if(this.signum() == 0 || b < 2 || b > 36) return "0";
+  var cs = this.chunkSize(b);
+  var a = Math.pow(b,cs);
+  var d = nbv(a), y = nbi(), z = nbi(), r = "";
+  this.divRemTo(d,y,z);
+  while(y.signum() > 0) {
+    r = (a+z.intValue()).toString(b).substr(1) + r;
+    y.divRemTo(d,y,z);
+  }
+  return z.intValue().toString(b) + r;
+}
+
+// (protected) convert from radix string
+function bnpFromRadix(s,b) {
+  this.fromInt(0);
+  if(b == null) b = 10;
+  var cs = this.chunkSize(b);
+  var d = Math.pow(b,cs), mi = false, j = 0, w = 0;
+  for(var i = 0; i < s.length; ++i) {
+    var x = intAt(s,i);
+    if(x < 0) {
+      if(s.charAt(i) == "-" && this.signum() == 0) mi = true;
+      continue;
+    }
+    w = b*w+x;
+    if(++j >= cs) {
+      this.dMultiply(d);
+      this.dAddOffset(w,0);
+      j = 0;
+      w = 0;
+    }
+  }
+  if(j > 0) {
+    this.dMultiply(Math.pow(b,j));
+    this.dAddOffset(w,0);
+  }
+  if(mi) BigInteger.ZERO.subTo(this,this);
+}
+
+// (protected) alternate constructor
+function bnpFromNumber(a,b,c) {
+  if("number" == typeof b) {
+    // new BigInteger(int,int,RNG)
+    if(a < 2) this.fromInt(1);
+    else {
+      this.fromNumber(a,c);
+      if(!this.testBit(a-1))	// force MSB set
+        this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);
+      if(this.isEven()) this.dAddOffset(1,0); // force odd
+      while(!this.isProbablePrime(b)) {
+        this.dAddOffset(2,0);
+        if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this);
+      }
+    }
+  }
+  else {
+    // new BigInteger(int,RNG)
+    var x = new Array(), t = a&7;
+    x.length = (a>>3)+1;
+    b.nextBytes(x);
+    if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;
+    this.fromString(x,256);
+  }
+}
+
+// (public) convert to bigendian byte array
+function bnToByteArray() {
+  var this_array = this.array;
+  var i = this.t, r = new Array();
+  r[0] = this.s;
+  var p = BI_DB-(i*BI_DB)%8, d, k = 0;
+  if(i-- > 0) {
+    if(p < BI_DB && (d = this_array[i]>>p) != (this.s&BI_DM)>>p)
+      r[k++] = d|(this.s<<(BI_DB-p));
+    while(i >= 0) {
+      if(p < 8) {
+        d = (this_array[i]&((1<<p)-1))<<(8-p);
+        d |= this_array[--i]>>(p+=BI_DB-8);
+      }
+      else {
+        d = (this_array[i]>>(p-=8))&0xff;
+        if(p <= 0) { p += BI_DB; --i; }
+      }
+      if((d&0x80) != 0) d |= -256;
+      if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;
+      if(k > 0 || d != this.s) r[k++] = d;
+    }
+  }
+  return r;
+}
+
+function bnEquals(a) { return(this.compareTo(a)==0); }
+function bnMin(a) { return(this.compareTo(a)<0)?this:a; }
+function bnMax(a) { return(this.compareTo(a)>0)?this:a; }
+
+// (protected) r = this op a (bitwise)
+function bnpBitwiseTo(a,op,r) {
+  var this_array = this.array;
+  var a_array    = a.array;
+  var r_array    = r.array;
+  var i, f, m = Math.min(a.t,this.t);
+  for(i = 0; i < m; ++i) r_array[i] = op(this_array[i],a_array[i]);
+  if(a.t < this.t) {
+    f = a.s&BI_DM;
+    for(i = m; i < this.t; ++i) r_array[i] = op(this_array[i],f);
+    r.t = this.t;
+  }
+  else {
+    f = this.s&BI_DM;
+    for(i = m; i < a.t; ++i) r_array[i] = op(f,a_array[i]);
+    r.t = a.t;
+  }
+  r.s = op(this.s,a.s);
+  r.clamp();
+}
+
+// (public) this & a
+function op_and(x,y) { return x&y; }
+function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; }
+
+// (public) this | a
+function op_or(x,y) { return x|y; }
+function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; }
+
+// (public) this ^ a
+function op_xor(x,y) { return x^y; }
+function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; }
+
+// (public) this & ~a
+function op_andnot(x,y) { return x&~y; }
+function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; }
+
+// (public) ~this
+function bnNot() {
+  var this_array = this.array;
+  var r = nbi();
+  var r_array = r.array;
+
+  for(var i = 0; i < this.t; ++i) r_array[i] = BI_DM&~this_array[i];
+  r.t = this.t;
+  r.s = ~this.s;
+  return r;
+}
+
+// (public) this << n
+function bnShiftLeft(n) {
+  var r = nbi();
+  if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r);
+  return r;
+}
+
+// (public) this >> n
+function bnShiftRight(n) {
+  var r = nbi();
+  if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r);
+  return r;
+}
+
+// return index of lowest 1-bit in x, x < 2^31
+function lbit(x) {
+  if(x == 0) return -1;
+  var r = 0;
+  if((x&0xffff) == 0) { x >>= 16; r += 16; }
+  if((x&0xff) == 0) { x >>= 8; r += 8; }
+  if((x&0xf) == 0) { x >>= 4; r += 4; }
+  if((x&3) == 0) { x >>= 2; r += 2; }
+  if((x&1) == 0) ++r;
+  return r;
+}
+
+// (public) returns index of lowest 1-bit (or -1 if none)
+function bnGetLowestSetBit() {
+  var this_array = this.array;
+  for(var i = 0; i < this.t; ++i)
+    if(this_array[i] != 0) return i*BI_DB+lbit(this_array[i]);
+  if(this.s < 0) return this.t*BI_DB;
+  return -1;
+}
+
+// return number of 1 bits in x
+function cbit(x) {
+  var r = 0;
+  while(x != 0) { x &= x-1; ++r; }
+  return r;
+}
+
+// (public) return number of set bits
+function bnBitCount() {
+  var r = 0, x = this.s&BI_DM;
+  for(var i = 0; i < this.t; ++i) r += cbit(this_array[i]^x);
+  return r;
+}
+
+// (public) true iff nth bit is set
+function bnTestBit(n) {
+  var this_array = this.array;
+  var j = Math.floor(n/BI_DB);
+  if(j >= this.t) return(this.s!=0);
+  return((this_array[j]&(1<<(n%BI_DB)))!=0);
+}
+
+// (protected) this op (1<<n)
+function bnpChangeBit(n,op) {
+  var r = BigInteger.ONE.shiftLeft(n);
+  this.bitwiseTo(r,op,r);
+  return r;
+}
+
+// (public) this | (1<<n)
+function bnSetBit(n) { return this.changeBit(n,op_or); }
+
+// (public) this & ~(1<<n)
+function bnClearBit(n) { return this.changeBit(n,op_andnot); }
+
+// (public) this ^ (1<<n)
+function bnFlipBit(n) { return this.changeBit(n,op_xor); }
+
+// (protected) r = this + a
+function bnpAddTo(a,r) {
+  var this_array = this.array;
+  var a_array = a.array;
+  var r_array = r.array;
+  var i = 0, c = 0, m = Math.min(a.t,this.t);
+  while(i < m) {
+    c += this_array[i]+a_array[i];
+    r_array[i++] = c&BI_DM;
+    c >>= BI_DB;
+  }
+  if(a.t < this.t) {
+    c += a.s;
+    while(i < this.t) {
+      c += this_array[i];
+      r_array[i++] = c&BI_DM;
+      c >>= BI_DB;
+    }
+    c += this.s;
+  }
+  else {
+    c += this.s;
+    while(i < a.t) {
+      c += a_array[i];
+      r_array[i++] = c&BI_DM;
+      c >>= BI_DB;
+    }
+    c += a.s;
+  }
+  r.s = (c<0)?-1:0;
+  if(c > 0) r_array[i++] = c;
+  else if(c < -1) r_array[i++] = BI_DV+c;
+  r.t = i;
+  r.clamp();
+}
+
+// (public) this + a
+function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; }
+
+// (public) this - a
+function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; }
+
+// (public) this * a
+function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }
+
+// (public) this / a
+function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; }
+
+// (public) this % a
+function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; }
+
+// (public) [this/a,this%a]
+function bnDivideAndRemainder(a) {
+  var q = nbi(), r = nbi();
+  this.divRemTo(a,q,r);
+  return new Array(q,r);
+}
+
+// (protected) this *= n, this >= 0, 1 < n < DV
+function bnpDMultiply(n) {
+  var this_array = this.array;
+  this_array[this.t] = this.am(0,n-1,this,0,0,this.t);
+  ++this.t;
+  this.clamp();
+}
+
+// (protected) this += n << w words, this >= 0
+function bnpDAddOffset(n,w) {
+  var this_array = this.array;
+  while(this.t <= w) this_array[this.t++] = 0;
+  this_array[w] += n;
+  while(this_array[w] >= BI_DV) {
+    this_array[w] -= BI_DV;
+    if(++w >= this.t) this_array[this.t++] = 0;
+    ++this_array[w];
+  }
+}
+
+// A "null" reducer
+function NullExp() {}
+function nNop(x) { return x; }
+function nMulTo(x,y,r) { x.multiplyTo(y,r); }
+function nSqrTo(x,r) { x.squareTo(r); }
+
+NullExp.prototype.convert = nNop;
+NullExp.prototype.revert = nNop;
+NullExp.prototype.mulTo = nMulTo;
+NullExp.prototype.sqrTo = nSqrTo;
+
+// (public) this^e
+function bnPow(e) { return this.exp(e,new NullExp()); }
+
+// (protected) r = lower n words of "this * a", a.t <= n
+// "this" should be the larger one if appropriate.
+function bnpMultiplyLowerTo(a,n,r) {
+  var r_array = r.array;
+  var a_array = a.array;
+  var i = Math.min(this.t+a.t,n);
+  r.s = 0; // assumes a,this >= 0
+  r.t = i;
+  while(i > 0) r_array[--i] = 0;
+  var j;
+  for(j = r.t-this.t; i < j; ++i) r_array[i+this.t] = this.am(0,a_array[i],r,i,0,this.t);
+  for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a_array[i],r,i,0,n-i);
+  r.clamp();
+}
+
+// (protected) r = "this * a" without lower n words, n > 0
+// "this" should be the larger one if appropriate.
+function bnpMultiplyUpperTo(a,n,r) {
+  var r_array = r.array;
+  var a_array = a.array;
+  --n;
+  var i = r.t = this.t+a.t-n;
+  r.s = 0; // assumes a,this >= 0
+  while(--i >= 0) r_array[i] = 0;
+  for(i = Math.max(n-this.t,0); i < a.t; ++i)
+    r_array[this.t+i-n] = this.am(n-i,a_array[i],r,0,0,this.t+i-n);
+  r.clamp();
+  r.drShiftTo(1,r);
+}
+
+// Barrett modular reduction
+function Barrett(m) {
+  // setup Barrett
+  this.r2 = nbi();
+  this.q3 = nbi();
+  BigInteger.ONE.dlShiftTo(2*m.t,this.r2);
+  this.mu = this.r2.divide(m);
+  this.m = m;
+}
+
+function barrettConvert(x) {
+  if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);
+  else if(x.compareTo(this.m) < 0) return x;
+  else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }
+}
+
+function barrettRevert(x) { return x; }
+
+// x = x mod m (HAC 14.42)
+function barrettReduce(x) {
+  x.drShiftTo(this.m.t-1,this.r2);
+  if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); }
+  this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);
+  this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);
+  while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1);
+  x.subTo(this.r2,x);
+  while(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
+}
+
+// r = x^2 mod m; x != r
+function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
+
+// r = x*y mod m; x,y != r
+function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
+
+Barrett.prototype.convert = barrettConvert;
+Barrett.prototype.revert = barrettRevert;
+Barrett.prototype.reduce = barrettReduce;
+Barrett.prototype.mulTo = barrettMulTo;
+Barrett.prototype.sqrTo = barrettSqrTo;
+
+// (public) this^e % m (HAC 14.85)
+function bnModPow(e,m) {
+  var e_array = e.array;
+  var i = e.bitLength(), k, r = nbv(1), z;
+  if(i <= 0) return r;
+  else if(i < 18) k = 1;
+  else if(i < 48) k = 3;
+  else if(i < 144) k = 4;
+  else if(i < 768) k = 5;
+  else k = 6;
+  if(i < 8)
+    z = new Classic(m);
+  else if(m.isEven())
+    z = new Barrett(m);
+  else
+    z = new Montgomery(m);
+
+  // precomputation
+  var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1;
+  g[1] = z.convert(this);
+  if(k > 1) {
+    var g2 = nbi();
+    z.sqrTo(g[1],g2);
+    while(n <= km) {
+      g[n] = nbi();
+      z.mulTo(g2,g[n-2],g[n]);
+      n += 2;
+    }
+  }
+
+  var j = e.t-1, w, is1 = true, r2 = nbi(), t;
+  i = nbits(e_array[j])-1;
+  while(j >= 0) {
+    if(i >= k1) w = (e_array[j]>>(i-k1))&km;
+    else {
+      w = (e_array[j]&((1<<(i+1))-1))<<(k1-i);
+      if(j > 0) w |= e_array[j-1]>>(BI_DB+i-k1);
+    }
+
+    n = k;
+    while((w&1) == 0) { w >>= 1; --n; }
+    if((i -= n) < 0) { i += BI_DB; --j; }
+    if(is1) {	// ret == 1, don't bother squaring or multiplying it
+      g[w].copyTo(r);
+      is1 = false;
+    }
+    else {
+      while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; }
+      if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; }
+      z.mulTo(r2,g[w],r);
+    }
+
+    while(j >= 0 && (e_array[j]&(1<<i)) == 0) {
+      z.sqrTo(r,r2); t = r; r = r2; r2 = t;
+      if(--i < 0) { i = BI_DB-1; --j; }
+    }
+  }
+  return z.revert(r);
+}
+
+// (public) gcd(this,a) (HAC 14.54)
+function bnGCD(a) {
+  var x = (this.s<0)?this.negate():this.clone();
+  var y = (a.s<0)?a.negate():a.clone();
+  if(x.compareTo(y) < 0) { var t = x; x = y; y = t; }
+  var i = x.getLowestSetBit(), g = y.getLowestSetBit();
+  if(g < 0) return x;
+  if(i < g) g = i;
+  if(g > 0) {
+    x.rShiftTo(g,x);
+    y.rShiftTo(g,y);
+  }
+  while(x.signum() > 0) {
+    if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x);
+    if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y);
+    if(x.compareTo(y) >= 0) {
+      x.subTo(y,x);
+      x.rShiftTo(1,x);
+    }
+    else {
+      y.subTo(x,y);
+      y.rShiftTo(1,y);
+    }
+  }
+  if(g > 0) y.lShiftTo(g,y);
+  return y;
+}
+
+// (protected) this % n, n < 2^26
+function bnpModInt(n) {
+  var this_array = this.array;
+  if(n <= 0) return 0;
+  var d = BI_DV%n, r = (this.s<0)?n-1:0;
+  if(this.t > 0)
+    if(d == 0) r = this_array[0]%n;
+    else for(var i = this.t-1; i >= 0; --i) r = (d*r+this_array[i])%n;
+  return r;
+}
+
+// (public) 1/this % m (HAC 14.61)
+function bnModInverse(m) {
+  var ac = m.isEven();
+  if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
+  var u = m.clone(), v = this.clone();
+  var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
+  while(u.signum() != 0) {
+    while(u.isEven()) {
+      u.rShiftTo(1,u);
+      if(ac) {
+        if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }
+        a.rShiftTo(1,a);
+      }
+      else if(!b.isEven()) b.subTo(m,b);
+      b.rShiftTo(1,b);
+    }
+    while(v.isEven()) {
+      v.rShiftTo(1,v);
+      if(ac) {
+        if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }
+        c.rShiftTo(1,c);
+      }
+      else if(!d.isEven()) d.subTo(m,d);
+      d.rShiftTo(1,d);
+    }
+    if(u.compareTo(v) >= 0) {
+      u.subTo(v,u);
+      if(ac) a.subTo(c,a);
+      b.subTo(d,b);
+    }
+    else {
+      v.subTo(u,v);
+      if(ac) c.subTo(a,c);
+      d.subTo(b,d);
+    }
+  }
+  if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
+  if(d.compareTo(m) >= 0) return d.subtract(m);
+  if(d.signum() < 0) d.addTo(m,d); else return d;
+  if(d.signum() < 0) return d.add(m); else return d;
+}
+
+var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509];
+var lplim = (1<<26)/lowprimes[lowprimes.length-1];
+
+// (public) test primality with certainty >= 1-.5^t
+function bnIsProbablePrime(t) {
+  var i, x = this.abs();
+  var x_array = x.array;
+  if(x.t == 1 && x_array[0] <= lowprimes[lowprimes.length-1]) {
+    for(i = 0; i < lowprimes.length; ++i)
+      if(x_array[0] == lowprimes[i]) return true;
+    return false;
+  }
+  if(x.isEven()) return false;
+  i = 1;
+  while(i < lowprimes.length) {
+    var m = lowprimes[i], j = i+1;
+    while(j < lowprimes.length && m < lplim) m *= lowprimes[j++];
+    m = x.modInt(m);
+    while(i < j) if(m%lowprimes[i++] == 0) return false;
+  }
+  return x.millerRabin(t);
+}
+
+// (protected) true if probably prime (HAC 4.24, Miller-Rabin)
+function bnpMillerRabin(t) {
+  var n1 = this.subtract(BigInteger.ONE);
+  var k = n1.getLowestSetBit();
+  if(k <= 0) return false;
+  var r = n1.shiftRight(k);
+  t = (t+1)>>1;
+  if(t > lowprimes.length) t = lowprimes.length;
+  var a = nbi();
+  for(var i = 0; i < t; ++i) {
+    a.fromInt(lowprimes[i]);
+    var y = a.modPow(r,this);
+    if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
+      var j = 1;
+      while(j++ < k && y.compareTo(n1) != 0) {
+        y = y.modPowInt(2,this);
+        if(y.compareTo(BigInteger.ONE) == 0) return false;
+      }
+      if(y.compareTo(n1) != 0) return false;
+    }
+  }
+  return true;
+}
+
+// protected
+BigInteger.prototype.chunkSize = bnpChunkSize;
+BigInteger.prototype.toRadix = bnpToRadix;
+BigInteger.prototype.fromRadix = bnpFromRadix;
+BigInteger.prototype.fromNumber = bnpFromNumber;
+BigInteger.prototype.bitwiseTo = bnpBitwiseTo;
+BigInteger.prototype.changeBit = bnpChangeBit;
+BigInteger.prototype.addTo = bnpAddTo;
+BigInteger.prototype.dMultiply = bnpDMultiply;
+BigInteger.prototype.dAddOffset = bnpDAddOffset;
+BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;
+BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;
+BigInteger.prototype.modInt = bnpModInt;
+BigInteger.prototype.millerRabin = bnpMillerRabin;
+
+// public
+BigInteger.prototype.clone = bnClone;
+BigInteger.prototype.intValue = bnIntValue;
+BigInteger.prototype.byteValue = bnByteValue;
+BigInteger.prototype.shortValue = bnShortValue;
+BigInteger.prototype.signum = bnSigNum;
+BigInteger.prototype.toByteArray = bnToByteArray;
+BigInteger.prototype.equals = bnEquals;
+BigInteger.prototype.min = bnMin;
+BigInteger.prototype.max = bnMax;
+BigInteger.prototype.and = bnAnd;
+BigInteger.prototype.or = bnOr;
+BigInteger.prototype.xor = bnXor;
+BigInteger.prototype.andNot = bnAndNot;
+BigInteger.prototype.not = bnNot;
+BigInteger.prototype.shiftLeft = bnShiftLeft;
+BigInteger.prototype.shiftRight = bnShiftRight;
+BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;
+BigInteger.prototype.bitCount = bnBitCount;
+BigInteger.prototype.testBit = bnTestBit;
+BigInteger.prototype.setBit = bnSetBit;
+BigInteger.prototype.clearBit = bnClearBit;
+BigInteger.prototype.flipBit = bnFlipBit;
+BigInteger.prototype.add = bnAdd;
+BigInteger.prototype.subtract = bnSubtract;
+BigInteger.prototype.multiply = bnMultiply;
+BigInteger.prototype.divide = bnDivide;
+BigInteger.prototype.remainder = bnRemainder;
+BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;
+BigInteger.prototype.modPow = bnModPow;
+BigInteger.prototype.modInverse = bnModInverse;
+BigInteger.prototype.pow = bnPow;
+BigInteger.prototype.gcd = bnGCD;
+BigInteger.prototype.isProbablePrime = bnIsProbablePrime;
+
+// BigInteger interfaces not implemented in jsbn:
+
+// BigInteger(int signum, byte[] magnitude)
+// double doubleValue()
+// float floatValue()
+// int hashCode()
+// long longValue()
+// static BigInteger valueOf(long val)
+// prng4.js - uses Arcfour as a PRNG
+
+function Arcfour() {
+  this.i = 0;
+  this.j = 0;
+  this.S = new Array();
+}
+
+// Initialize arcfour context from key, an array of ints, each from [0..255]
+function ARC4init(key) {
+  var i, j, t;
+  for(i = 0; i < 256; ++i)
+    this.S[i] = i;
+  j = 0;
+  for(i = 0; i < 256; ++i) {
+    j = (j + this.S[i] + key[i % key.length]) & 255;
+    t = this.S[i];
+    this.S[i] = this.S[j];
+    this.S[j] = t;
+  }
+  this.i = 0;
+  this.j = 0;
+}
+
+function ARC4next() {
+  var t;
+  this.i = (this.i + 1) & 255;
+  this.j = (this.j + this.S[this.i]) & 255;
+  t = this.S[this.i];
+  this.S[this.i] = this.S[this.j];
+  this.S[this.j] = t;
+  return this.S[(t + this.S[this.i]) & 255];
+}
+
+Arcfour.prototype.init = ARC4init;
+Arcfour.prototype.next = ARC4next;
+
+// Plug in your RNG constructor here
+function prng_newstate() {
+  return new Arcfour();
+}
+
+// Pool size must be a multiple of 4 and greater than 32.
+// An array of bytes the size of the pool will be passed to init()
+var rng_psize = 256;
+// Random number generator - requires a PRNG backend, e.g. prng4.js
+
+// For best results, put code like
+// <body onClick='rng_seed_time();' onKeyPress='rng_seed_time();'>
+// in your main HTML document.
+
+var rng_state;
+var rng_pool;
+var rng_pptr;
+
+// Mix in a 32-bit integer into the pool
+function rng_seed_int(x) {
+  rng_pool[rng_pptr++] ^= x & 255;
+  rng_pool[rng_pptr++] ^= (x >> 8) & 255;
+  rng_pool[rng_pptr++] ^= (x >> 16) & 255;
+  rng_pool[rng_pptr++] ^= (x >> 24) & 255;
+  if(rng_pptr >= rng_psize) rng_pptr -= rng_psize;
+}
+
+// Mix in the current time (w/milliseconds) into the pool
+function rng_seed_time() {
+  // Use pre-computed date to avoid making the benchmark 
+  // results dependent on the current date.
+  rng_seed_int(1122926989487);
+}
+
+// Initialize the pool with junk if needed.
+if(rng_pool == null) {
+  rng_pool = new Array();
+  rng_pptr = 0;
+  var t;
+  while(rng_pptr < rng_psize) {  // extract some randomness from Math.random()
+    t = Math.floor(65536 * Math.random());
+    rng_pool[rng_pptr++] = t >>> 8;
+    rng_pool[rng_pptr++] = t & 255;
+  }
+  rng_pptr = 0;
+  rng_seed_time();
+  //rng_seed_int(window.screenX);
+  //rng_seed_int(window.screenY);
+}
+
+function rng_get_byte() {
+  if(rng_state == null) {
+    rng_seed_time();
+    rng_state = prng_newstate();
+    rng_state.init(rng_pool);
+    for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr)
+      rng_pool[rng_pptr] = 0;
+    rng_pptr = 0;
+    //rng_pool = null;
+  }
+  // TODO: allow reseeding after first request
+  return rng_state.next();
+}
+
+function rng_get_bytes(ba) {
+  var i;
+  for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte();
+}
+
+function SecureRandom() {}
+
+SecureRandom.prototype.nextBytes = rng_get_bytes;
+// Depends on jsbn.js and rng.js
+
+// convert a (hex) string to a bignum object
+function parseBigInt(str,r) {
+  return new BigInteger(str,r);
+}
+
+function linebrk(s,n) {
+  var ret = "";
+  var i = 0;
+  while(i + n < s.length) {
+    ret += s.substring(i,i+n) + "\n";
+    i += n;
+  }
+  return ret + s.substring(i,s.length);
+}
+
+function byte2Hex(b) {
+  if(b < 0x10)
+    return "0" + b.toString(16);
+  else
+    return b.toString(16);
+}
+
+// PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
+function pkcs1pad2(s,n) {
+  if(n < s.length + 11) {
+    alert("Message too long for RSA");
+    return null;
+  }
+  var ba = new Array();
+  var i = s.length - 1;
+  while(i >= 0 && n > 0) ba[--n] = s.charCodeAt(i--);
+  ba[--n] = 0;
+  var rng = new SecureRandom();
+  var x = new Array();
+  while(n > 2) { // random non-zero pad
+    x[0] = 0;
+    while(x[0] == 0) rng.nextBytes(x);
+    ba[--n] = x[0];
+  }
+  ba[--n] = 2;
+  ba[--n] = 0;
+  return new BigInteger(ba);
+}
+
+// "empty" RSA key constructor
+function RSAKey() {
+  this.n = null;
+  this.e = 0;
+  this.d = null;
+  this.p = null;
+  this.q = null;
+  this.dmp1 = null;
+  this.dmq1 = null;
+  this.coeff = null;
+}
+
+// Set the public key fields N and e from hex strings
+function RSASetPublic(N,E) {
+  if(N != null && E != null && N.length > 0 && E.length > 0) {
+    this.n = parseBigInt(N,16);
+    this.e = parseInt(E,16);
+  }
+  else
+    alert("Invalid RSA public key");
+}
+
+// Perform raw public operation on "x": return x^e (mod n)
+function RSADoPublic(x) {
+  return x.modPowInt(this.e, this.n);
+}
+
+// Return the PKCS#1 RSA encryption of "text" as an even-length hex string
+function RSAEncrypt(text) {
+  var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3);
+  if(m == null) return null;
+  var c = this.doPublic(m);
+  if(c == null) return null;
+  var h = c.toString(16);
+  if((h.length & 1) == 0) return h; else return "0" + h;
+}
+
+// Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string
+//function RSAEncryptB64(text) {
+//  var h = this.encrypt(text);
+//  if(h) return hex2b64(h); else return null;
+//}
+
+// protected
+RSAKey.prototype.doPublic = RSADoPublic;
+
+// public
+RSAKey.prototype.setPublic = RSASetPublic;
+RSAKey.prototype.encrypt = RSAEncrypt;
+//RSAKey.prototype.encrypt_b64 = RSAEncryptB64;
+// Depends on rsa.js and jsbn2.js
+
+// Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext
+function pkcs1unpad2(d,n) {
+  var b = d.toByteArray();
+  var i = 0;
+  while(i < b.length && b[i] == 0) ++i;
+  if(b.length-i != n-1 || b[i] != 2)
+    return null;
+  ++i;
+  while(b[i] != 0)
+    if(++i >= b.length) return null;
+  var ret = "";
+  while(++i < b.length)
+    ret += String.fromCharCode(b[i]);
+  return ret;
+}
+
+// Set the private key fields N, e, and d from hex strings
+function RSASetPrivate(N,E,D) {
+  if(N != null && E != null && N.length > 0 && E.length > 0) {
+    this.n = parseBigInt(N,16);
+    this.e = parseInt(E,16);
+    this.d = parseBigInt(D,16);
+  }
+  else
+    alert("Invalid RSA private key");
+}
+
+// Set the private key fields N, e, d and CRT params from hex strings
+function RSASetPrivateEx(N,E,D,P,Q,DP,DQ,C) {
+  if(N != null && E != null && N.length > 0 && E.length > 0) {
+    this.n = parseBigInt(N,16);
+    this.e = parseInt(E,16);
+    this.d = parseBigInt(D,16);
+    this.p = parseBigInt(P,16);
+    this.q = parseBigInt(Q,16);
+    this.dmp1 = parseBigInt(DP,16);
+    this.dmq1 = parseBigInt(DQ,16);
+    this.coeff = parseBigInt(C,16);
+  }
+  else
+    alert("Invalid RSA private key");
+}
+
+// Generate a new random private key B bits long, using public expt E
+function RSAGenerate(B,E) {
+  var rng = new SecureRandom();
+  var qs = B>>1;
+  this.e = parseInt(E,16);
+  var ee = new BigInteger(E,16);
+  for(;;) {
+    for(;;) {
+      this.p = new BigInteger(B-qs,1,rng);
+      if(this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.p.isProbablePrime(10)) break;
+    }
+    for(;;) {
+      this.q = new BigInteger(qs,1,rng);
+      if(this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.q.isProbablePrime(10)) break;
+    }
+    if(this.p.compareTo(this.q) <= 0) {
+      var t = this.p;
+      this.p = this.q;
+      this.q = t;
+    }
+    var p1 = this.p.subtract(BigInteger.ONE);
+    var q1 = this.q.subtract(BigInteger.ONE);
+    var phi = p1.multiply(q1);
+    if(phi.gcd(ee).compareTo(BigInteger.ONE) == 0) {
+      this.n = this.p.multiply(this.q);
+      this.d = ee.modInverse(phi);
+      this.dmp1 = this.d.mod(p1);
+      this.dmq1 = this.d.mod(q1);
+      this.coeff = this.q.modInverse(this.p);
+      break;
+    }
+  }
+}
+
+// Perform raw private operation on "x": return x^d (mod n)
+function RSADoPrivate(x) {
+  if(this.p == null || this.q == null)
+    return x.modPow(this.d, this.n);
+
+  // TODO: re-calculate any missing CRT params
+  var xp = x.mod(this.p).modPow(this.dmp1, this.p);
+  var xq = x.mod(this.q).modPow(this.dmq1, this.q);
+
+  while(xp.compareTo(xq) < 0)
+    xp = xp.add(this.p);
+  return xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq);
+}
+
+// Return the PKCS#1 RSA decryption of "ctext".
+// "ctext" is an even-length hex string and the output is a plain string.
+function RSADecrypt(ctext) {
+  var c = parseBigInt(ctext, 16);
+  var m = this.doPrivate(c);
+  if(m == null) return null;
+  return pkcs1unpad2(m, (this.n.bitLength()+7)>>3);
+}
+
+// Return the PKCS#1 RSA decryption of "ctext".
+// "ctext" is a Base64-encoded string and the output is a plain string.
+//function RSAB64Decrypt(ctext) {
+//  var h = b64tohex(ctext);
+//  if(h) return this.decrypt(h); else return null;
+//}
+
+// protected
+RSAKey.prototype.doPrivate = RSADoPrivate;
+
+// public
+RSAKey.prototype.setPrivate = RSASetPrivate;
+RSAKey.prototype.setPrivateEx = RSASetPrivateEx;
+RSAKey.prototype.generate = RSAGenerate;
+RSAKey.prototype.decrypt = RSADecrypt;
+//RSAKey.prototype.b64_decrypt = RSAB64Decrypt;
+
+
+nValue="a5261939975948bb7a58dffe5ff54e65f0498f9175f5a09288810b8975871e99af3b5dd94057b0fc07535f5f97444504fa35169d461d0d30cf0192e307727c065168c788771c561a9400fb49175e9e6aa4e23fe11af69e9412dd23b0cb6684c4c2429bce139e848ab26d0829073351f4acd36074eafd036a5eb83359d2a698d3";
+eValue="10001";
+dValue="8e9912f6d3645894e8d38cb58c0db81ff516cf4c7e5a14c7f1eddb1459d2cded4d8d293fc97aee6aefb861859c8b6a3d1dfe710463e1f9ddc72048c09751971c4a580aa51eb523357a3cc48d31cfad1d4a165066ed92d4748fb6571211da5cb14bc11b6e2df7c1a559e6d5ac1cd5c94703a22891464fba23d0d965086277a161";
+pValue="d090ce58a92c75233a6486cb0a9209bf3583b64f540c76f5294bb97d285eed33aec220bde14b2417951178ac152ceab6da7090905b478195498b352048f15e7d";
+qValue="cab575dc652bb66df15a0359609d51d1db184750c00c6698b90ef3465c99655103edbf0d54c56aec0ce3c4d22592338092a126a0cc49f65a4a30d222b411e58f";
+dmp1Value="1a24bca8e273df2f0e47c199bbf678604e7df7215480c77c8db39f49b000ce2cf7500038acfff5433b7d582a01f1826e6f4d42e1c57f5e1fef7b12aabc59fd25";
+dmq1Value="3d06982efbbe47339e1f6d36b1216b8a741d410b0c662f54f7118b27b9a4ec9d914337eb39841d8666f3034408cf94f5b62f11c402fc994fe15a05493150d9fd";
+coeffValue="3a3e731acd8960b7ff9eb81a7ff93bd1cfa74cbd56987db58b4594fb09c09084db1734c8143f98b602b981aaa9243ca28deb69b5b280ee8dcee0fd2625e53250";
+
+setupEngine(am3, 28);
+
+var TEXT = "The quick brown fox jumped over the extremely lazy frog! " +
+    "Now is the time for all good men to come to the party.";
+var encrypted;
+
+function encrypt() {
+  var RSA = new RSAKey();
+  RSA.setPublic(nValue, eValue);
+  RSA.setPrivateEx(nValue, eValue, dValue, pValue, qValue, dmp1Value, dmq1Value, coeffValue);
+  encrypted = RSA.encrypt(TEXT);
+}
+
+function decrypt() {
+  var RSA = new RSAKey();
+  RSA.setPublic(nValue, eValue);
+  RSA.setPrivateEx(nValue, eValue, dValue, pValue, qValue, dmp1Value, dmq1Value, coeffValue);
+  var decrypted = RSA.decrypt(encrypted);
+  if (decrypted != TEXT) {
+    throw new Error("Crypto operation failed");
+  }
+}
diff --git a/deps/v8/benchmarks/deltablue.js b/deps/v8/benchmarks/deltablue.js
new file mode 100644
index 0000000..b51afd1
--- /dev/null
+++ b/deps/v8/benchmarks/deltablue.js
@@ -0,0 +1,880 @@
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Copyright 1996 John Maloney and Mario Wolczko.
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+// This implementation of the DeltaBlue benchmark is derived 
+// from the Smalltalk implementation by John Maloney and Mario 
+// Wolczko. Some parts have been translated directly, whereas 
+// others have been modified more aggresively to make it feel 
+// more like a JavaScript program.
+
+
+var DeltaBlue = new BenchmarkSuite('DeltaBlue', 71104, [
+  new Benchmark('DeltaBlue', deltaBlue)
+]);
+
+
+/**
+ * A JavaScript implementation of the DeltaBlue constrain-solving
+ * algorithm, as described in:
+ *
+ * "The DeltaBlue Algorithm: An Incremental Constraint Hierarchy Solver"
+ *   Bjorn N. Freeman-Benson and John Maloney
+ *   January 1990 Communications of the ACM,
+ *   also available as University of Washington TR 89-08-06.
+ *
+ * Beware: this benchmark is written in a grotesque style where
+ * the constraint model is built by side-effects from constructors.
+ * I've kept it this way to avoid deviating too much from the original
+ * implementation.
+ */
+
+
+/* --- O b j e c t   M o d e l --- */
+
+Object.prototype.inherits = function (shuper) {
+  function Inheriter() { }
+  Inheriter.prototype = shuper.prototype;
+  this.prototype = new Inheriter();
+  this.superConstructor = shuper;
+}
+
+function OrderedCollection() {
+  this.elms = new Array();
+}
+
+OrderedCollection.prototype.add = function (elm) {
+  this.elms.push(elm);
+}
+
+OrderedCollection.prototype.at = function (index) {
+  return this.elms[index];
+}
+
+OrderedCollection.prototype.size = function () {
+  return this.elms.length;
+}
+
+OrderedCollection.prototype.removeFirst = function () {
+  return this.elms.pop();
+}
+
+OrderedCollection.prototype.remove = function (elm) {
+  var index = 0, skipped = 0;
+  for (var i = 0; i < this.elms.length; i++) {
+    var value = this.elms[i];
+    if (value != elm) {
+      this.elms[index] = value;
+      index++;
+    } else {
+      skipped++;
+    }
+  }
+  for (var i = 0; i < skipped; i++)
+    this.elms.pop();
+}
+
+/* --- *
+ * S t r e n g t h
+ * --- */
+
+/**
+ * Strengths are used to measure the relative importance of constraints.
+ * New strengths may be inserted in the strength hierarchy without
+ * disrupting current constraints.  Strengths cannot be created outside
+ * this class, so pointer comparison can be used for value comparison.
+ */
+function Strength(strengthValue, name) {
+  this.strengthValue = strengthValue;
+  this.name = name;
+}
+
+Strength.stronger = function (s1, s2) {
+  return s1.strengthValue < s2.strengthValue;
+}
+
+Strength.weaker = function (s1, s2) {
+  return s1.strengthValue > s2.strengthValue;
+}
+
+Strength.weakestOf = function (s1, s2) {
+  return this.weaker(s1, s2) ? s1 : s2;
+}
+
+Strength.strongest = function (s1, s2) {
+  return this.stronger(s1, s2) ? s1 : s2;
+}
+
+Strength.prototype.nextWeaker = function () {
+  switch (this.strengthValue) {
+    case 0: return Strength.WEAKEST;
+    case 1: return Strength.WEAK_DEFAULT;
+    case 2: return Strength.NORMAL;
+    case 3: return Strength.STRONG_DEFAULT;
+    case 4: return Strength.PREFERRED;
+    case 5: return Strength.REQUIRED;
+  }
+}
+
+// Strength constants.
+Strength.REQUIRED        = new Strength(0, "required");
+Strength.STONG_PREFERRED = new Strength(1, "strongPreferred");
+Strength.PREFERRED       = new Strength(2, "preferred");
+Strength.STRONG_DEFAULT  = new Strength(3, "strongDefault");
+Strength.NORMAL          = new Strength(4, "normal");
+Strength.WEAK_DEFAULT    = new Strength(5, "weakDefault");
+Strength.WEAKEST         = new Strength(6, "weakest");
+
+/* --- *
+ * C o n s t r a i n t
+ * --- */
+
+/**
+ * An abstract class representing a system-maintainable relationship
+ * (or "constraint") between a set of variables. A constraint supplies
+ * a strength instance variable; concrete subclasses provide a means
+ * of storing the constrained variables and other information required
+ * to represent a constraint.
+ */
+function Constraint(strength) {
+  this.strength = strength;
+}
+
+/**
+ * Activate this constraint and attempt to satisfy it.
+ */
+Constraint.prototype.addConstraint = function () {
+  this.addToGraph();
+  planner.incrementalAdd(this);
+}
+
+/**
+ * Attempt to find a way to enforce this constraint. If successful,
+ * record the solution, perhaps modifying the current dataflow
+ * graph. Answer the constraint that this constraint overrides, if
+ * there is one, or nil, if there isn't.
+ * Assume: I am not already satisfied.
+ */
+Constraint.prototype.satisfy = function (mark) {
+  this.chooseMethod(mark);
+  if (!this.isSatisfied()) {
+    if (this.strength == Strength.REQUIRED)
+      alert("Could not satisfy a required constraint!");
+    return null;
+  }
+  this.markInputs(mark);
+  var out = this.output();
+  var overridden = out.determinedBy;
+  if (overridden != null) overridden.markUnsatisfied();
+  out.determinedBy = this;
+  if (!planner.addPropagate(this, mark))
+    alert("Cycle encountered");
+  out.mark = mark;
+  return overridden;
+}
+
+Constraint.prototype.destroyConstraint = function () {
+  if (this.isSatisfied()) planner.incrementalRemove(this);
+  else this.removeFromGraph();
+}
+
+/**
+ * Normal constraints are not input constraints.  An input constraint
+ * is one that depends on external state, such as the mouse, the
+ * keybord, a clock, or some arbitraty piece of imperative code.
+ */
+Constraint.prototype.isInput = function () {
+  return false;
+}
+
+/* --- *
+ * U n a r y   C o n s t r a i n t
+ * --- */
+
+/**
+ * Abstract superclass for constraints having a single possible output
+ * variable.
+ */
+function UnaryConstraint(v, strength) {
+  UnaryConstraint.superConstructor.call(this, strength);
+  this.myOutput = v;
+  this.satisfied = false;
+  this.addConstraint();
+}
+
+UnaryConstraint.inherits(Constraint);
+
+/**
+ * Adds this constraint to the constraint graph
+ */
+UnaryConstraint.prototype.addToGraph = function () {
+  this.myOutput.addConstraint(this);
+  this.satisfied = false;
+}
+
+/**
+ * Decides if this constraint can be satisfied and records that
+ * decision.
+ */
+UnaryConstraint.prototype.chooseMethod = function (mark) {
+  this.satisfied = (this.myOutput.mark != mark)
+    && Strength.stronger(this.strength, this.myOutput.walkStrength);
+}
+
+/**
+ * Returns true if this constraint is satisfied in the current solution.
+ */
+UnaryConstraint.prototype.isSatisfied = function () {
+  return this.satisfied;
+}
+
+UnaryConstraint.prototype.markInputs = function (mark) {
+  // has no inputs
+}
+
+/**
+ * Returns the current output variable.
+ */
+UnaryConstraint.prototype.output = function () {
+  return this.myOutput;
+}
+
+/**
+ * Calculate the walkabout strength, the stay flag, and, if it is
+ * 'stay', the value for the current output of this constraint. Assume
+ * this constraint is satisfied.
+ */
+UnaryConstraint.prototype.recalculate = function () {
+  this.myOutput.walkStrength = this.strength;
+  this.myOutput.stay = !this.isInput();
+  if (this.myOutput.stay) this.execute(); // Stay optimization
+}
+
+/**
+ * Records that this constraint is unsatisfied
+ */
+UnaryConstraint.prototype.markUnsatisfied = function () {
+  this.satisfied = false;
+}
+
+UnaryConstraint.prototype.inputsKnown = function () {
+  return true;
+}
+
+UnaryConstraint.prototype.removeFromGraph = function () {
+  if (this.myOutput != null) this.myOutput.removeConstraint(this);
+  this.satisfied = false;
+}
+
+/* --- *
+ * S t a y   C o n s t r a i n t
+ * --- */
+
+/**
+ * Variables that should, with some level of preference, stay the same.
+ * Planners may exploit the fact that instances, if satisfied, will not
+ * change their output during plan execution.  This is called "stay
+ * optimization".
+ */
+function StayConstraint(v, str) {
+  StayConstraint.superConstructor.call(this, v, str);
+}
+
+StayConstraint.inherits(UnaryConstraint);
+
+StayConstraint.prototype.execute = function () {
+  // Stay constraints do nothing
+}
+
+/* --- *
+ * E d i t   C o n s t r a i n t
+ * --- */
+
+/**
+ * A unary input constraint used to mark a variable that the client
+ * wishes to change.
+ */
+function EditConstraint(v, str) {
+  EditConstraint.superConstructor.call(this, v, str);
+}
+
+EditConstraint.inherits(UnaryConstraint);
+
+/**
+ * Edits indicate that a variable is to be changed by imperative code.
+ */
+EditConstraint.prototype.isInput = function () {
+  return true;
+}
+
+EditConstraint.prototype.execute = function () {
+  // Edit constraints do nothing
+}
+
+/* --- *
+ * B i n a r y   C o n s t r a i n t
+ * --- */
+
+var Direction = new Object();
+Direction.NONE     = 0;
+Direction.FORWARD  = 1;
+Direction.BACKWARD = -1;
+
+/**
+ * Abstract superclass for constraints having two possible output
+ * variables.
+ */
+function BinaryConstraint(var1, var2, strength) {
+  BinaryConstraint.superConstructor.call(this, strength);
+  this.v1 = var1;
+  this.v2 = var2;
+  this.direction = Direction.NONE;
+  this.addConstraint();
+}
+
+BinaryConstraint.inherits(Constraint);
+
+/**
+ * Decides if this constratint can be satisfied and which way it
+ * should flow based on the relative strength of the variables related,
+ * and record that decision.
+ */
+BinaryConstraint.prototype.chooseMethod = function (mark) {
+  if (this.v1.mark == mark) {
+    this.direction = (this.v1.mark != mark && Strength.stronger(this.strength, this.v2.walkStrength))
+      ? Direction.FORWARD
+      : Direction.NONE;
+  }
+  if (this.v2.mark == mark) {
+    this.direction = (this.v1.mark != mark && Strength.stronger(this.strength, this.v1.walkStrength))
+      ? Direction.BACKWARD
+      : Direction.NONE;
+  }
+  if (Strength.weaker(this.v1.walkStrength, this.v2.walkStrength)) {
+    this.direction = Strength.stronger(this.strength, this.v1.walkStrength)
+      ? Direction.BACKWARD
+      : Direction.NONE;
+  } else {
+    this.direction = Strength.stronger(this.strength, this.v2.walkStrength)
+      ? Direction.FORWARD
+      : Direction.BACKWARD
+  }
+}
+
+/**
+ * Add this constraint to the constraint graph
+ */
+BinaryConstraint.prototype.addToGraph = function () {
+  this.v1.addConstraint(this);
+  this.v2.addConstraint(this);
+  this.direction = Direction.NONE;
+}
+
+/**
+ * Answer true if this constraint is satisfied in the current solution.
+ */
+BinaryConstraint.prototype.isSatisfied = function () {
+  return this.direction != Direction.NONE;
+}
+
+/**
+ * Mark the input variable with the given mark.
+ */
+BinaryConstraint.prototype.markInputs = function (mark) {
+  this.input().mark = mark;
+}
+
+/**
+ * Returns the current input variable
+ */
+BinaryConstraint.prototype.input = function () {
+  return (this.direction == Direction.FORWARD) ? this.v1 : this.v2;
+}
+
+/**
+ * Returns the current output variable
+ */
+BinaryConstraint.prototype.output = function () {
+  return (this.direction == Direction.FORWARD) ? this.v2 : this.v1;
+}
+
+/**
+ * Calculate the walkabout strength, the stay flag, and, if it is
+ * 'stay', the value for the current output of this
+ * constraint. Assume this constraint is satisfied.
+ */
+BinaryConstraint.prototype.recalculate = function () {
+  var ihn = this.input(), out = this.output();
+  out.walkStrength = Strength.weakestOf(this.strength, ihn.walkStrength);
+  out.stay = ihn.stay;
+  if (out.stay) this.execute();
+}
+
+/**
+ * Record the fact that this constraint is unsatisfied.
+ */
+BinaryConstraint.prototype.markUnsatisfied = function () {
+  this.direction = Direction.NONE;
+}
+
+BinaryConstraint.prototype.inputsKnown = function (mark) {
+  var i = this.input();
+  return i.mark == mark || i.stay || i.determinedBy == null;
+}
+
+BinaryConstraint.prototype.removeFromGraph = function () {
+  if (this.v1 != null) this.v1.removeConstraint(this);
+  if (this.v2 != null) this.v2.removeConstraint(this);
+  this.direction = Direction.NONE;
+}
+
+/* --- *
+ * S c a l e   C o n s t r a i n t
+ * --- */
+
+/**
+ * Relates two variables by the linear scaling relationship: "v2 =
+ * (v1 * scale) + offset". Either v1 or v2 may be changed to maintain
+ * this relationship but the scale factor and offset are considered
+ * read-only.
+ */
+function ScaleConstraint(src, scale, offset, dest, strength) {
+  this.direction = Direction.NONE;
+  this.scale = scale;
+  this.offset = offset;
+  ScaleConstraint.superConstructor.call(this, src, dest, strength);
+}
+
+ScaleConstraint.inherits(BinaryConstraint);
+
+/**
+ * Adds this constraint to the constraint graph.
+ */
+ScaleConstraint.prototype.addToGraph = function () {
+  ScaleConstraint.superConstructor.prototype.addToGraph.call(this);
+  this.scale.addConstraint(this);
+  this.offset.addConstraint(this);
+}
+
+ScaleConstraint.prototype.removeFromGraph = function () {
+  ScaleConstraint.superConstructor.prototype.removeFromGraph.call(this);
+  if (this.scale != null) this.scale.removeConstraint(this);
+  if (this.offset != null) this.offset.removeConstraint(this);
+}
+
+ScaleConstraint.prototype.markInputs = function (mark) {
+  ScaleConstraint.superConstructor.prototype.markInputs.call(this, mark);
+  this.scale.mark = this.offset.mark = mark;
+}
+
+/**
+ * Enforce this constraint. Assume that it is satisfied.
+ */
+ScaleConstraint.prototype.execute = function () {
+  if (this.direction == Direction.FORWARD) {
+    this.v2.value = this.v1.value * this.scale.value + this.offset.value;
+  } else {
+    this.v1.value = (this.v2.value - this.offset.value) / this.scale.value;
+  }
+}
+
+/**
+ * Calculate the walkabout strength, the stay flag, and, if it is
+ * 'stay', the value for the current output of this constraint. Assume
+ * this constraint is satisfied.
+ */
+ScaleConstraint.prototype.recalculate = function () {
+  var ihn = this.input(), out = this.output();
+  out.walkStrength = Strength.weakestOf(this.strength, ihn.walkStrength);
+  out.stay = ihn.stay && this.scale.stay && this.offset.stay;
+  if (out.stay) this.execute();
+}
+
+/* --- *
+ * E q u a l i t  y   C o n s t r a i n t
+ * --- */
+
+/**
+ * Constrains two variables to have the same value.
+ */
+function EqualityConstraint(var1, var2, strength) {
+  EqualityConstraint.superConstructor.call(this, var1, var2, strength);
+}
+
+EqualityConstraint.inherits(BinaryConstraint);
+
+/**
+ * Enforce this constraint. Assume that it is satisfied.
+ */
+EqualityConstraint.prototype.execute = function () {
+  this.output().value = this.input().value;
+}
+
+/* --- *
+ * V a r i a b l e
+ * --- */
+
+/**
+ * A constrained variable. In addition to its value, it maintain the
+ * structure of the constraint graph, the current dataflow graph, and
+ * various parameters of interest to the DeltaBlue incremental
+ * constraint solver.
+ **/
+function Variable(name, initialValue) {
+  this.value = initialValue || 0;
+  this.constraints = new OrderedCollection();
+  this.determinedBy = null;
+  this.mark = 0;
+  this.walkStrength = Strength.WEAKEST;
+  this.stay = true;
+  this.name = name;
+}
+
+/**
+ * Add the given constraint to the set of all constraints that refer
+ * this variable.
+ */
+Variable.prototype.addConstraint = function (c) {
+  this.constraints.add(c);
+}
+
+/**
+ * Removes all traces of c from this variable.
+ */
+Variable.prototype.removeConstraint = function (c) {
+  this.constraints.remove(c);
+  if (this.determinedBy == c) this.determinedBy = null;
+}
+
+/* --- *
+ * P l a n n e r
+ * --- */
+
+/**
+ * The DeltaBlue planner
+ */
+function Planner() {
+  this.currentMark = 0;
+}
+
+/**
+ * Attempt to satisfy the given constraint and, if successful,
+ * incrementally update the dataflow graph.  Details: If satifying
+ * the constraint is successful, it may override a weaker constraint
+ * on its output. The algorithm attempts to resatisfy that
+ * constraint using some other method. This process is repeated
+ * until either a) it reaches a variable that was not previously
+ * determined by any constraint or b) it reaches a constraint that
+ * is too weak to be satisfied using any of its methods. The
+ * variables of constraints that have been processed are marked with
+ * a unique mark value so that we know where we've been. This allows
+ * the algorithm to avoid getting into an infinite loop even if the
+ * constraint graph has an inadvertent cycle.
+ */
+Planner.prototype.incrementalAdd = function (c) {
+  var mark = this.newMark();
+  var overridden = c.satisfy(mark);
+  while (overridden != null)
+    overridden = overridden.satisfy(mark);
+}
+
+/**
+ * Entry point for retracting a constraint. Remove the given
+ * constraint and incrementally update the dataflow graph.
+ * Details: Retracting the given constraint may allow some currently
+ * unsatisfiable downstream constraint to be satisfied. We therefore collect
+ * a list of unsatisfied downstream constraints and attempt to
+ * satisfy each one in turn. This list is traversed by constraint
+ * strength, strongest first, as a heuristic for avoiding
+ * unnecessarily adding and then overriding weak constraints.
+ * Assume: c is satisfied.
+ */
+Planner.prototype.incrementalRemove = function (c) {
+  var out = c.output();
+  c.markUnsatisfied();
+  c.removeFromGraph();
+  var unsatisfied = this.removePropagateFrom(out);
+  var strength = Strength.REQUIRED;
+  do {
+    for (var i = 0; i < unsatisfied.size(); i++) {
+      var u = unsatisfied.at(i);
+      if (u.strength == strength)
+        this.incrementalAdd(u);
+    }
+    strength = strength.nextWeaker();
+  } while (strength != Strength.WEAKEST);
+}
+
+/**
+ * Select a previously unused mark value.
+ */
+Planner.prototype.newMark = function () {
+  return ++this.currentMark;
+}
+
+/**
+ * Extract a plan for resatisfaction starting from the given source
+ * constraints, usually a set of input constraints. This method
+ * assumes that stay optimization is desired; the plan will contain
+ * only constraints whose output variables are not stay. Constraints
+ * that do no computation, such as stay and edit constraints, are
+ * not included in the plan.
+ * Details: The outputs of a constraint are marked when it is added
+ * to the plan under construction. A constraint may be appended to
+ * the plan when all its input variables are known. A variable is
+ * known if either a) the variable is marked (indicating that has
+ * been computed by a constraint appearing earlier in the plan), b)
+ * the variable is 'stay' (i.e. it is a constant at plan execution
+ * time), or c) the variable is not determined by any
+ * constraint. The last provision is for past states of history
+ * variables, which are not stay but which are also not computed by
+ * any constraint.
+ * Assume: sources are all satisfied.
+ */
+Planner.prototype.makePlan = function (sources) {
+  var mark = this.newMark();
+  var plan = new Plan();
+  var todo = sources;
+  while (todo.size() > 0) {
+    var c = todo.removeFirst();
+    if (c.output().mark != mark && c.inputsKnown(mark)) {
+      plan.addConstraint(c);
+      c.output().mark = mark;
+      this.addConstraintsConsumingTo(c.output(), todo);
+    }
+  }
+  return plan;
+}
+
+/**
+ * Extract a plan for resatisfying starting from the output of the
+ * given constraints, usually a set of input constraints.
+ */
+Planner.prototype.extractPlanFromConstraints = function (constraints) {
+  var sources = new OrderedCollection();
+  for (var i = 0; i < constraints.size(); i++) {
+    var c = constraints.at(i);
+    if (c.isInput() && c.isSatisfied())
+      // not in plan already and eligible for inclusion
+      sources.add(c);
+  }
+  return this.makePlan(sources);
+}
+
+/**
+ * Recompute the walkabout strengths and stay flags of all variables
+ * downstream of the given constraint and recompute the actual
+ * values of all variables whose stay flag is true. If a cycle is
+ * detected, remove the given constraint and answer
+ * false. Otherwise, answer true.
+ * Details: Cycles are detected when a marked variable is
+ * encountered downstream of the given constraint. The sender is
+ * assumed to have marked the inputs of the given constraint with
+ * the given mark. Thus, encountering a marked node downstream of
+ * the output constraint means that there is a path from the
+ * constraint's output to one of its inputs.
+ */
+Planner.prototype.addPropagate = function (c, mark) {
+  var todo = new OrderedCollection();
+  todo.add(c);
+  while (todo.size() > 0) {
+    var d = todo.removeFirst();
+    if (d.output().mark == mark) {
+      this.incrementalRemove(c);
+      return false;
+    }
+    d.recalculate();
+    this.addConstraintsConsumingTo(d.output(), todo);
+  }
+  return true;
+}
+
+
+/**
+ * Update the walkabout strengths and stay flags of all variables
+ * downstream of the given constraint. Answer a collection of
+ * unsatisfied constraints sorted in order of decreasing strength.
+ */
+Planner.prototype.removePropagateFrom = function (out) {
+  out.determinedBy = null;
+  out.walkStrength = Strength.WEAKEST;
+  out.stay = true;
+  var unsatisfied = new OrderedCollection();
+  var todo = new OrderedCollection();
+  todo.add(out);
+  while (todo.size() > 0) {
+    var v = todo.removeFirst();
+    for (var i = 0; i < v.constraints.size(); i++) {
+      var c = v.constraints.at(i);
+      if (!c.isSatisfied())
+        unsatisfied.add(c);
+    }
+    var determining = v.determinedBy;
+    for (var i = 0; i < v.constraints.size(); i++) {
+      var next = v.constraints.at(i);
+      if (next != determining && next.isSatisfied()) {
+        next.recalculate();
+        todo.add(next.output());
+      }
+    }
+  }
+  return unsatisfied;
+}
+
+Planner.prototype.addConstraintsConsumingTo = function (v, coll) {
+  var determining = v.determinedBy;
+  var cc = v.constraints;
+  for (var i = 0; i < cc.size(); i++) {
+    var c = cc.at(i);
+    if (c != determining && c.isSatisfied())
+      coll.add(c);
+  }
+}
+
+/* --- *
+ * P l a n
+ * --- */
+
+/**
+ * A Plan is an ordered list of constraints to be executed in sequence
+ * to resatisfy all currently satisfiable constraints in the face of
+ * one or more changing inputs.
+ */
+function Plan() {
+  this.v = new OrderedCollection();
+}
+
+Plan.prototype.addConstraint = function (c) {
+  this.v.add(c);
+}
+
+Plan.prototype.size = function () {
+  return this.v.size();
+}
+
+Plan.prototype.constraintAt = function (index) {
+  return this.v.at(index);
+}
+
+Plan.prototype.execute = function () {
+  for (var i = 0; i < this.size(); i++) {
+    var c = this.constraintAt(i);
+    c.execute();
+  }
+}
+
+/* --- *
+ * M a i n
+ * --- */
+
+/**
+ * This is the standard DeltaBlue benchmark. A long chain of equality
+ * constraints is constructed with a stay constraint on one end. An
+ * edit constraint is then added to the opposite end and the time is
+ * measured for adding and removing this constraint, and extracting
+ * and executing a constraint satisfaction plan. There are two cases.
+ * In case 1, the added constraint is stronger than the stay
+ * constraint and values must propagate down the entire length of the
+ * chain. In case 2, the added constraint is weaker than the stay
+ * constraint so it cannot be accomodated. The cost in this case is,
+ * of course, very low. Typical situations lie somewhere between these
+ * two extremes.
+ */
+function chainTest(n) {
+  planner = new Planner();
+  var prev = null, first = null, last = null;
+
+  // Build chain of n equality constraints
+  for (var i = 0; i <= n; i++) {
+    var name = "v" + i;
+    var v = new Variable(name);
+    if (prev != null)
+      new EqualityConstraint(prev, v, Strength.REQUIRED);
+    if (i == 0) first = v;
+    if (i == n) last = v;
+    prev = v;
+  }
+
+  new StayConstraint(last, Strength.STRONG_DEFAULT);
+  var edit = new EditConstraint(first, Strength.PREFERRED);
+  var edits = new OrderedCollection();
+  edits.add(edit);
+  var plan = planner.extractPlanFromConstraints(edits);
+  for (var i = 0; i < 100; i++) {
+    first.value = i;
+    plan.execute();
+    if (last.value != i)
+      alert("Chain test failed.");
+  }
+}
+
+/**
+ * This test constructs a two sets of variables related to each
+ * other by a simple linear transformation (scale and offset). The
+ * time is measured to change a variable on either side of the
+ * mapping and to change the scale and offset factors.
+ */
+function projectionTest(n) {
+  planner = new Planner();
+  var scale = new Variable("scale", 10);
+  var offset = new Variable("offset", 1000);
+  var src = null, dst = null;
+
+  var dests = new OrderedCollection();
+  for (var i = 0; i < n; i++) {
+    src = new Variable("src" + i, i);
+    dst = new Variable("dst" + i, i);
+    dests.add(dst);
+    new StayConstraint(src, Strength.NORMAL);
+    new ScaleConstraint(src, scale, offset, dst, Strength.REQUIRED);
+  }
+
+  change(src, 17);
+  if (dst.value != 1170) alert("Projection 1 failed");
+  change(dst, 1050);
+  if (src.value != 5) alert("Projection 2 failed");
+  change(scale, 5);
+  for (var i = 0; i < n - 1; i++) {
+    if (dests.at(i).value != i * 5 + 1000)
+      alert("Projection 3 failed");
+  }
+  change(offset, 2000);
+  for (var i = 0; i < n - 1; i++) {
+    if (dests.at(i).value != i * 5 + 2000)
+      alert("Projection 4 failed");
+  }
+}
+
+function change(v, newValue) {
+  var edit = new EditConstraint(v, Strength.PREFERRED);
+  var edits = new OrderedCollection();
+  edits.add(edit);
+  var plan = planner.extractPlanFromConstraints(edits);
+  for (var i = 0; i < 10; i++) {
+    v.value = newValue;
+    plan.execute();
+  }
+  edit.destroyConstraint();
+}
+
+// Global variable holding the current planner.
+var planner = null;
+
+function deltaBlue() {
+  chainTest(100);
+  projectionTest(100);
+}
diff --git a/deps/v8/benchmarks/earley-boyer.js b/deps/v8/benchmarks/earley-boyer.js
new file mode 100644
index 0000000..9016a13
--- /dev/null
+++ b/deps/v8/benchmarks/earley-boyer.js
@@ -0,0 +1,4685 @@
+// This file is automatically generated by scheme2js, except for the
+// benchmark harness code at the beginning and end of the file.
+
+var EarleyBoyer = new BenchmarkSuite('EarleyBoyer', 765819, [
+  new Benchmark("Earley", function () { BgL_earleyzd2benchmarkzd2(); }),
+  new Benchmark("Boyer", function () { BgL_nboyerzd2benchmarkzd2(); })
+]);
+
+
+/************* GENERATED FILE - DO NOT EDIT *************/
+/************* GENERATED FILE - DO NOT EDIT *************/
+/************* GENERATED FILE - DO NOT EDIT *************/
+/************* GENERATED FILE - DO NOT EDIT *************/
+/************* GENERATED FILE - DO NOT EDIT *************/
+/************* GENERATED FILE - DO NOT EDIT *************/
+/************* GENERATED FILE - DO NOT EDIT *************/
+/************* GENERATED FILE - DO NOT EDIT *************/
+/*
+ * To use write/prints/... the default-output port has to be set first.
+ * Simply setting SC_DEFAULT_OUT and SC_ERROR_OUT to the desired values
+ * should do the trick.
+ * In the following example the std-out and error-port are redirected to
+ * a DIV.
+function initRuntime() {
+    function escapeHTML(s) {
+	var tmp = s;
+	tmp = tmp.replace(/&/g, "&amp;");
+	tmp = tmp.replace(/</g, "&lt;");
+	tmp = tmp.replace(/>/g, "&gt;");
+	tmp = tmp.replace(/ /g, "&nbsp;");
+	tmp = tmp.replace(/\n/g, "<br />");
+	tmp = tmp.replace(/\t/g, "&nbsp;&nbsp;&nbsp;&nbsp");
+	return tmp;
+	
+    }
+
+    document.write("<div id='stdout'></div>");
+    SC_DEFAULT_OUT = new sc_GenericOutputPort(
+	function(s) {
+	    var stdout = document.getElementById('stdout');
+	    stdout.innerHTML = stdout.innerHTML + escapeHTML(s);
+	});
+    SC_ERROR_OUT = SC_DEFAULT_OUT;
+}
+*/
+
+
+function sc_print_debug() {
+    sc_print.apply(null, arguments);
+}
+/*** META ((export *js*)) */
+var sc_JS_GLOBALS = this;
+
+var __sc_LINE=-1;
+var __sc_FILE="";
+
+/*** META ((export #t)) */
+function sc_alert() {
+   var len = arguments.length;
+   var s = "";
+   var i;
+
+   for( i = 0; i < len; i++ ) {
+       s += sc_toDisplayString(arguments[ i ]);
+   }
+
+   return alert( s );
+}
+
+/*** META ((export #t)) */
+function sc_typeof( x ) {
+   return typeof x;
+}
+
+/*** META ((export #t)) */
+function sc_error() {
+    var a = [sc_jsstring2symbol("*error*")];
+    for (var i = 0; i < arguments.length; i++) {
+	a[i+1] = arguments[i];
+    }
+    throw a;
+}
+
+/*** META ((export #t)
+           (peephole (prefix "throw ")))
+*/
+function sc_raise(obj) {
+    throw obj;
+}
+
+/*** META ((export with-handler-lambda)) */
+function sc_withHandlerLambda(handler, body) {
+    try {
+	return body();
+    } catch(e) {
+	if (!e._internalException)
+	    return handler(e);
+	else
+	    throw e;
+    }
+}
+
+var sc_properties = new Object();
+
+/*** META ((export #t)) */
+function sc_putpropBang(sym, key, val) {
+    var ht = sc_properties[sym];
+    if (!ht) {
+	ht = new Object();
+	sc_properties[sym] = ht;
+    }
+    ht[key] = val;
+}
+
+/*** META ((export #t)) */
+function sc_getprop(sym, key) {
+    var ht = sc_properties[sym];
+    if (ht) {
+	if (key in ht)
+	    return ht[key];
+	else
+	    return false;
+    } else
+	return false;
+}
+
+/*** META ((export #t)) */
+function sc_rempropBang(sym, key) {
+    var ht = sc_properties[sym];
+    if (ht)
+	delete ht[key];
+}
+
+/*** META ((export #t)) */
+function sc_any2String(o) {
+    return jsstring2string(sc_toDisplayString(o));
+}    
+
+/*** META ((export #t)
+           (peephole (infix 2 2 "==="))
+           (type bool))
+*/
+function sc_isEqv(o1, o2) {
+    return (o1 === o2);
+}
+
+/*** META ((export #t)
+           (peephole (infix 2 2 "==="))
+           (type bool))
+*/
+function sc_isEq(o1, o2) {
+    return (o1 === o2);
+}
+
+/*** META ((export #t)
+           (type bool))
+*/
+function sc_isNumber(n) {
+    return (typeof n === "number");
+}
+
+/*** META ((export #t)
+           (type bool))
+*/
+function sc_isComplex(n) {
+    return sc_isNumber(n);
+}
+
+/*** META ((export #t)
+           (type bool))
+*/
+function sc_isReal(n) {
+    return sc_isNumber(n);
+}
+
+/*** META ((export #t)
+           (type bool))
+*/
+function sc_isRational(n) {
+    return sc_isReal(n);
+}
+
+/*** META ((export #t)
+           (type bool))
+*/
+function sc_isInteger(n) {
+    return (parseInt(n) === n);
+}
+
+/*** META ((export #t)
+           (type bool)
+           (peephole (postfix ", false")))
+*/
+// we don't have exact numbers...
+function sc_isExact(n) {
+    return false;
+}
+
+/*** META ((export #t)
+           (peephole (postfix ", true"))
+	   (type bool))
+*/
+function sc_isInexact(n) {
+    return true;
+}
+
+/*** META ((export = =fx =fl)
+           (type bool)
+           (peephole (infix 2 2 "===")))
+*/
+function sc_equal(x) {
+    for (var i = 1; i < arguments.length; i++)
+	if (x !== arguments[i])
+	    return false;
+    return true;
+}
+
+/*** META ((export < <fx <fl)
+           (type bool)
+           (peephole (infix 2 2 "<")))
+*/
+function sc_less(x) {
+    for (var i = 1; i < arguments.length; i++) {
+	if (x >= arguments[i])
+	    return false;
+	x = arguments[i];
+    }
+    return true;
+}
+
+/*** META ((export > >fx >fl)
+           (type bool)
+           (peephole (infix 2 2 ">")))
+*/
+function sc_greater(x, y) {
+    for (var i = 1; i < arguments.length; i++) {
+	if (x <= arguments[i])
+	    return false;
+	x = arguments[i];
+    }
+    return true;
+}
+
+/*** META ((export <= <=fx <=fl)
+           (type bool)
+           (peephole (infix 2 2 "<=")))
+*/
+function sc_lessEqual(x, y) {
+    for (var i = 1; i < arguments.length; i++) {
+	if (x > arguments[i])
+	    return false;
+	x = arguments[i];
+    }
+    return true;
+}
+
+/*** META ((export >= >=fl >=fx)
+           (type bool)
+           (peephole (infix 2 2 ">=")))
+*/
+function sc_greaterEqual(x, y) {
+    for (var i = 1; i < arguments.length; i++) {
+	if (x < arguments[i])
+	    return false;
+	x = arguments[i];
+    }
+    return true;
+}
+
+/*** META ((export #t)
+           (type bool)
+           (peephole (postfix "=== 0")))
+*/
+function sc_isZero(x) {
+    return (x === 0);
+}
+
+/*** META ((export #t)
+           (type bool)
+           (peephole (postfix "> 0")))
+*/
+function sc_isPositive(x) {
+    return (x > 0);
+}
+
+/*** META ((export #t)
+           (type bool)
+           (peephole (postfix "< 0")))
+*/
+function sc_isNegative(x) {
+    return (x < 0);
+}
+
+/*** META ((export #t)
+           (type bool)
+           (peephole (postfix "%2===1")))
+*/
+function sc_isOdd(x) {
+    return (x % 2 === 1);
+}
+
+/*** META ((export #t)
+           (type bool)
+           (peephole (postfix "%2===0")))
+*/
+function sc_isEven(x) {
+    return (x % 2 === 0);
+}
+
+/*** META ((export #t)) */
+var sc_max = Math.max;
+/*** META ((export #t)) */
+var sc_min = Math.min;
+
+/*** META ((export + +fx +fl)
+           (peephole (infix 0 #f "+" "0")))
+*/
+function sc_plus() {
+    var sum = 0;
+    for (var i = 0; i < arguments.length; i++)
+	sum += arguments[i];
+    return sum;
+}
+
+/*** META ((export * *fx *fl)
+           (peephole (infix 0 #f "*" "1")))
+*/
+function sc_multi() {
+    var product = 1;
+    for (var i = 0; i < arguments.length; i++)
+	product *= arguments[i];
+    return product;
+}
+
+/*** META ((export - -fx -fl)
+           (peephole (minus)))
+*/
+function sc_minus(x) {
+    if (arguments.length === 1)
+	return -x;
+    else {
+	var res = x;
+	for (var i = 1; i < arguments.length; i++)
+	    res -= arguments[i];
+	return res;
+    }
+}
+
+/*** META ((export / /fl)
+           (peephole (div)))
+*/
+function sc_div(x) {
+    if (arguments.length === 1)
+	return 1/x;
+    else {
+	var res = x;
+	for (var i = 1; i < arguments.length; i++)
+	    res /= arguments[i];
+	return res;
+    }
+}
+
+/*** META ((export #t)) */
+var sc_abs = Math.abs;
+
+/*** META ((export quotient /fx)
+           (peephole (hole 2 "parseInt(" x "/" y ")")))
+*/
+function sc_quotient(x, y) {
+    return parseInt(x / y);
+}
+
+/*** META ((export #t)
+           (peephole (infix 2 2 "%")))
+*/
+function sc_remainder(x, y) {
+    return x % y;
+}
+
+/*** META ((export #t)
+           (peephole (modulo)))
+*/
+function sc_modulo(x, y) {
+    var remainder = x % y;
+    // if they don't have the same sign
+    if ((remainder * y) < 0)
+	return remainder + y;
+    else
+	return remainder;
+}
+
+function sc_euclid_gcd(a, b) {
+    var temp;
+    if (a === 0) return b;
+    if (b === 0) return a;
+    if (a < 0) {a = -a;};
+    if (b < 0) {b = -b;};
+    if (b > a) {temp = a; a = b; b = temp;};
+    while (true) {
+	a %= b;
+	if(a === 0) {return b;};
+	b %= a;
+	if(b === 0) {return a;};
+    };
+    return b;
+}
+
+/*** META ((export #t)) */
+function sc_gcd() {
+    var gcd = 0;
+    for (var i = 0; i < arguments.length; i++)
+	gcd = sc_euclid_gcd(gcd, arguments[i]);
+    return gcd;
+}
+
+/*** META ((export #t)) */
+function sc_lcm() {
+    var lcm = 1;
+    for (var i = 0; i < arguments.length; i++) {
+	var f = Math.round(arguments[i] / sc_euclid_gcd(arguments[i], lcm));
+	lcm *= Math.abs(f);
+    }
+    return lcm;
+}
+
+// LIMITATION: numerator and denominator don't make sense in floating point world.
+//var SC_MAX_DECIMALS = 1000000
+//
+// function sc_numerator(x) {
+//     var rounded = Math.round(x * SC_MAX_DECIMALS);
+//     return Math.round(rounded / sc_euclid_gcd(rounded, SC_MAX_DECIMALS));
+// }
+
+// function sc_denominator(x) {
+//     var rounded = Math.round(x * SC_MAX_DECIMALS);
+//     return Math.round(SC_MAX_DECIMALS / sc_euclid_gcd(rounded, SC_MAX_DECIMALS));
+// }
+
+/*** META ((export #t)) */
+var sc_floor = Math.floor;
+/*** META ((export #t)) */
+var sc_ceiling = Math.ceil;
+/*** META ((export #t)) */
+var sc_truncate = parseInt;
+/*** META ((export #t)) */
+var sc_round = Math.round;
+
+// LIMITATION: sc_rationalize doesn't make sense in a floating point world.
+
+/*** META ((export #t)) */
+var sc_exp = Math.exp;
+/*** META ((export #t)) */
+var sc_log = Math.log;
+/*** META ((export #t)) */
+var sc_sin = Math.sin;
+/*** META ((export #t)) */
+var sc_cos = Math.cos;
+/*** META ((export #t)) */
+var sc_tan = Math.tan;
+/*** META ((export #t)) */
+var sc_asin = Math.asin;
+/*** META ((export #t)) */
+var sc_acos = Math.acos;
+/*** META ((export #t)) */
+var sc_atan = Math.atan;
+
+/*** META ((export #t)) */
+var sc_sqrt = Math.sqrt;
+/*** META ((export #t)) */
+var sc_expt = Math.pow;
+
+// LIMITATION: we don't have complex numbers.
+// LIMITATION: the following functions are hence not implemented.
+// LIMITATION: make-rectangular, make-polar, real-part, imag-part, magnitude, angle
+// LIMITATION: 2 argument atan
+
+/*** META ((export #t)
+           (peephole (id)))
+*/
+function sc_exact2inexact(x) {
+    return x;
+}
+
+/*** META ((export #t)
+           (peephole (id)))
+*/
+function sc_inexact2exact(x) {
+    return x;
+}
+
+function sc_number2jsstring(x, radix) {
+    if (radix)
+	return x.toString(radix);
+    else
+	return x.toString();
+}
+
+function sc_jsstring2number(s, radix) {
+    if (s === "") return false;
+
+    if (radix) {
+	var t = parseInt(s, radix);
+	if (!t && t !== 0) return false;
+	// verify that each char is in range. (parseInt ignores leading
+	// white and trailing chars)
+	var allowedChars = "01234567890abcdefghijklmnopqrstuvwxyz".substring(0, radix+1);
+	if ((new RegExp("^["+allowedChars+"]*$", "i")).test(s))
+	    return t;
+	else return false;
+    } else {
+	var t = +s; // does not ignore trailing chars.
+	if (!t && t !== 0) return false;
+	// simply verify that first char is not whitespace.
+	var c = s.charAt(0);
+	// if +c is 0, but the char is not "0", then we have a whitespace.
+	if (+c === 0 && c !== "0") return false;
+	return t;
+    }
+}
+
+/*** META ((export #t)
+           (type bool)
+           (peephole (not)))
+*/
+function sc_not(b) {
+    return b === false;
+}
+
+/*** META ((export #t)
+           (type bool))
+*/
+function sc_isBoolean(b) {
+    return (b === true) || (b === false);
+}
+
+function sc_Pair(car, cdr) {
+    this.car = car;
+    this.cdr = cdr;
+}
+
+sc_Pair.prototype.toString = function() {
+    return sc_toDisplayString(this);
+};
+sc_Pair.prototype.sc_toWriteOrDisplayString = function(writeOrDisplay) {
+    var current = this;
+
+    var res = "(";
+
+    while(true) {
+	res += writeOrDisplay(current.car);
+	if (sc_isPair(current.cdr)) {
+	    res += " ";
+	    current = current.cdr;
+	} else if (current.cdr !== null) {
+	    res += " . " + writeOrDisplay(current.cdr);
+	    break;
+	} else // current.cdr == null
+	    break;
+    }
+	
+    res += ")";
+
+    return res;
+};
+sc_Pair.prototype.sc_toDisplayString = function() {
+    return this.sc_toWriteOrDisplayString(sc_toDisplayString);
+};
+sc_Pair.prototype.sc_toWriteString = function() {
+    return this.sc_toWriteOrDisplayString(sc_toWriteString);
+};
+// sc_Pair.prototype.sc_toWriteCircleString in IO.js
+
+/*** META ((export #t)
+           (type bool)
+           (peephole (postfix " instanceof sc_Pair")))
+*/
+function sc_isPair(p) {
+    return (p instanceof sc_Pair);
+}
+
+function sc_isPairEqual(p1, p2, comp) {
+    return (comp(p1.car, p2.car) && comp(p1.cdr, p2.cdr));
+}
+
+/*** META ((export #t)
+           (peephole (hole 2 "new sc_Pair(" car ", " cdr ")")))
+*/
+function sc_cons(car, cdr) {
+    return new sc_Pair(car, cdr);
+}
+
+/*** META ((export cons*)) */
+function sc_consStar() {
+    var res = arguments[arguments.length - 1];
+    for (var i = arguments.length-2; i >= 0; i--)
+	res = new sc_Pair(arguments[i], res);
+    return res;
+}
+
+/*** META ((export #t)
+           (peephole (postfix ".car")))
+*/
+function sc_car(p) {
+    return p.car;
+}
+
+/*** META ((export #t)
+           (peephole (postfix ".cdr")))
+*/
+function sc_cdr(p) {
+    return p.cdr;
+}
+
+/*** META ((export #t)
+           (peephole (hole 2 p ".car = " val)))
+*/
+function sc_setCarBang(p, val) {
+    p.car = val;
+}
+
+/*** META ((export #t)
+           (peephole (hole 2 p ".cdr = " val)))
+*/
+function sc_setCdrBang(p, val) {
+    p.cdr = val;
+}
+
+/*** META ((export #t)
+           (peephole (postfix ".car.car")))
+*/
+function sc_caar(p) { return p.car.car; }
+/*** META ((export #t)
+           (peephole (postfix ".cdr.car")))
+*/
+function sc_cadr(p) { return p.cdr.car; }
+/*** META ((export #t)
+           (peephole (postfix ".car.cdr")))
+*/
+function sc_cdar(p) { return p.car.cdr; }
+/*** META ((export #t)
+           (peephole (postfix ".cdr.cdr")))
+*/
+function sc_cddr(p) { return p.cdr.cdr; }
+/*** META ((export #t)
+           (peephole (postfix ".car.car.car")))
+*/
+function sc_caaar(p) { return p.car.car.car; }
+/*** META ((export #t)
+           (peephole (postfix ".car.cdr.car")))
+*/
+function sc_cadar(p) { return p.car.cdr.car; }
+/*** META ((export #t)
+           (peephole (postfix ".cdr.car.car")))
+*/
+function sc_caadr(p) { return p.cdr.car.car; }
+/*** META ((export #t)
+           (peephole (postfix ".cdr.cdr.car")))
+*/
+function sc_caddr(p) { return p.cdr.cdr.car; }
+/*** META ((export #t)
+           (peephole (postfix ".car.car.cdr")))
+*/
+function sc_cdaar(p) { return p.car.car.cdr; }
+/*** META ((export #t)
+           (peephole (postfix ".cdr.car.cdr")))
+*/
+function sc_cdadr(p) { return p.cdr.car.cdr; }
+/*** META ((export #t)
+           (peephole (postfix ".car.cdr.cdr")))
+*/
+function sc_cddar(p) { return p.car.cdr.cdr; }
+/*** META ((export #t)
+           (peephole (postfix ".cdr.cdr.cdr")))
+*/
+function sc_cdddr(p) { return p.cdr.cdr.cdr; }
+/*** META ((export #t)
+           (peephole (postfix ".car.car.car.car")))
+*/
+function sc_caaaar(p) { return p.car.car.car.car; }
+/*** META ((export #t)
+           (peephole (postfix ".car.cdr.car.car")))
+*/
+function sc_caadar(p) { return p.car.cdr.car.car; }
+/*** META ((export #t)
+           (peephole (postfix ".cdr.car.car.car")))
+*/
+function sc_caaadr(p) { return p.cdr.car.car.car; }
+/*** META ((export #t)
+           (peephole (postfix ".cdr.cdr.car.car")))
+*/
+function sc_caaddr(p) { return p.cdr.cdr.car.car; }
+/*** META ((export #t)
+           (peephole (postfix ".car.car.car.cdr")))
+*/
+function sc_cdaaar(p) { return p.car.car.car.cdr; }
+/*** META ((export #t)
+           (peephole (postfix ".car.cdr.car.cdr")))
+*/
+function sc_cdadar(p) { return p.car.cdr.car.cdr; }
+/*** META ((export #t)
+           (peephole (postfix ".cdr.car.car.cdr")))
+*/
+function sc_cdaadr(p) { return p.cdr.car.car.cdr; }
+/*** META ((export #t)
+           (peephole (postfix ".cdr.cdr.car.cdr")))
+*/
+function sc_cdaddr(p) { return p.cdr.cdr.car.cdr; }
+/*** META ((export #t)
+           (peephole (postfix ".car.car.cdr.car")))
+*/
+function sc_cadaar(p) { return p.car.car.cdr.car; }
+/*** META ((export #t)
+           (peephole (postfix ".car.cdr.cdr.car")))
+*/
+function sc_caddar(p) { return p.car.cdr.cdr.car; }
+/*** META ((export #t)
+           (peephole (postfix ".cdr.car.cdr.car")))
+*/
+function sc_cadadr(p) { return p.cdr.car.cdr.car; }
+/*** META ((export #t)
+           (peephole (postfix ".cdr.cdr.cdr.car")))
+*/
+function sc_cadddr(p) { return p.cdr.cdr.cdr.car; }
+/*** META ((export #t)
+           (peephole (postfix ".car.car.cdr.cdr")))
+*/
+function sc_cddaar(p) { return p.car.car.cdr.cdr; }
+/*** META ((export #t)
+           (peephole (postfix ".car.cdr.cdr.cdr")))
+*/
+function sc_cdddar(p) { return p.car.cdr.cdr.cdr; }
+/*** META ((export #t)
+           (peephole (postfix ".cdr.car.cdr.cdr")))
+*/
+function sc_cddadr(p) { return p.cdr.car.cdr.cdr; }
+/*** META ((export #t)
+           (peephole (postfix ".cdr.cdr.cdr.cdr")))
+*/
+function sc_cddddr(p) { return p.cdr.cdr.cdr.cdr; }
+
+/*** META ((export #t)) */
+function sc_lastPair(l) {
+    if (!sc_isPair(l)) sc_error("sc_lastPair: pair expected");
+    var res = l;
+    var cdr = l.cdr;
+    while (sc_isPair(cdr)) {
+	res = cdr;
+	cdr = res.cdr;
+    }
+    return res;
+}
+
+/*** META ((export #t)
+           (type bool)
+           (peephole (postfix " === null")))
+*/
+function sc_isNull(o) {
+    return (o === null);
+}
+
+/*** META ((export #t)
+           (type bool))
+*/
+function sc_isList(o) {
+    var rabbit;
+    var turtle;
+
+    var rabbit = o;
+    var turtle = o;
+    while (true) {
+	if (rabbit === null ||
+	    (rabbit instanceof sc_Pair && rabbit.cdr === null))
+	    return true;  // end of list
+	else if ((rabbit instanceof sc_Pair) &&
+		 (rabbit.cdr instanceof sc_Pair)) {
+	    rabbit = rabbit.cdr.cdr;
+	    turtle = turtle.cdr;
+	    if (rabbit === turtle) return false; // cycle
+	} else
+	    return false; // not pair
+    }
+}
+
+/*** META ((export #t)) */
+function sc_list() {
+    var res = null;
+    var a = arguments;
+    for (var i = a.length-1; i >= 0; i--)
+	res = new sc_Pair(a[i], res);
+    return res;
+}
+
+/*** META ((export #t)) */
+function sc_iota(num, init) {
+   var res = null;
+   if (!init) init = 0;
+   for (var i = num - 1; i >= 0; i--)
+      res = new sc_Pair(i + init, res);
+   return res;
+}
+
+/*** META ((export #t)) */
+function sc_makeList(nbEls, fill) {
+    var res = null;
+    for (var i = 0; i < nbEls; i++)
+	res = new sc_Pair(fill, res);
+    return res;
+}
+
+/*** META ((export #t)) */
+function sc_length(l) {
+    var res = 0;
+    while (l !== null) {
+	res++;
+	l = l.cdr;
+    }
+    return res;
+}
+
+/*** META ((export #t)) */
+function sc_remq(o, l) {
+    var dummy = { cdr : null };
+    var tail = dummy;
+    while (l !== null) {
+	if (l.car !== o) {
+	    tail.cdr = sc_cons(l.car, null);
+	    tail = tail.cdr;
+	}
+	l = l.cdr;
+    }
+    return dummy.cdr;
+}
+
+/*** META ((export #t)) */
+function sc_remqBang(o, l) {
+    var dummy = { cdr : null };
+    var tail = dummy;
+    var needsAssig = true;
+    while (l !== null) {
+	if (l.car === o) {
+	    needsAssig = true;
+	} else {
+	    if (needsAssig) {
+		tail.cdr = l;
+		needsAssig = false;
+	    }
+	    tail = l;
+	}
+	l = l.cdr;
+    }
+    tail.cdr = null;
+    return dummy.cdr;
+}
+
+/*** META ((export #t)) */
+function sc_delete(o, l) {
+    var dummy = { cdr : null };
+    var tail = dummy;
+    while (l !== null) {
+	if (!sc_isEqual(l.car, o)) {
+	    tail.cdr = sc_cons(l.car, null);
+	    tail = tail.cdr;
+	}
+	l = l.cdr;
+    }
+    return dummy.cdr;
+}
+
+/*** META ((export #t)) */
+function sc_deleteBang(o, l) {
+    var dummy = { cdr : null };
+    var tail = dummy;
+    var needsAssig = true;
+    while (l !== null) {
+	if (sc_isEqual(l.car, o)) {
+	    needsAssig = true;
+	} else {
+	    if (needsAssig) {
+		tail.cdr = l;
+		needsAssig = false;
+	    }
+	    tail = l;
+	}
+	l = l.cdr;
+    }
+    tail.cdr = null;
+    return dummy.cdr;
+}
+
+function sc_reverseAppendBang(l1, l2) {
+    var res = l2;
+    while (l1 !== null) {
+	var tmp = res;
+	res = l1;
+	l1 = l1.cdr;
+	res.cdr = tmp;
+    }
+    return res;
+}
+	
+function sc_dualAppend(l1, l2) {
+    if (l1 === null) return l2;
+    if (l2 === null) return l1;
+    var rev = sc_reverse(l1);
+    return sc_reverseAppendBang(rev, l2);
+}
+
+/*** META ((export #t)) */
+function sc_append() {
+    if (arguments.length === 0)
+	return null;
+    var res = arguments[arguments.length - 1];
+    for (var i = arguments.length - 2; i >= 0; i--)
+	res = sc_dualAppend(arguments[i], res);
+    return res;
+}
+
+function sc_dualAppendBang(l1, l2) {
+    if (l1 === null) return l2;
+    if (l2 === null) return l1;
+    var tmp = l1;
+    while (tmp.cdr !== null) tmp=tmp.cdr;
+    tmp.cdr = l2;
+    return l1;
+}
+    
+/*** META ((export #t)) */
+function sc_appendBang() {
+    var res = null;
+    for (var i = 0; i < arguments.length; i++)
+	res = sc_dualAppendBang(res, arguments[i]);
+    return res;
+}
+
+/*** META ((export #t)) */
+function sc_reverse(l1) {
+    var res = null;
+    while (l1 !== null) {
+	res = sc_cons(l1.car, res);
+	l1 = l1.cdr;
+    }
+    return res;
+}
+
+/*** META ((export #t)) */
+function sc_reverseBang(l) {
+    return sc_reverseAppendBang(l, null);
+}
+
+/*** META ((export #t)) */
+function sc_listTail(l, k) {
+    var res = l;
+    for (var i = 0; i < k; i++) {
+	res = res.cdr;
+    }
+    return res;
+}
+
+/*** META ((export #t)) */
+function sc_listRef(l, k) {
+    return sc_listTail(l, k).car;
+}
+
+/* // unoptimized generic versions
+function sc_memX(o, l, comp) {
+    while (l != null) {
+	if (comp(l.car, o))
+	    return l;
+	l = l.cdr;
+    }
+    return false;
+}
+function sc_memq(o, l) { return sc_memX(o, l, sc_isEq); }
+function sc_memv(o, l) { return sc_memX(o, l, sc_isEqv); }
+function sc_member(o, l) { return sc_memX(o, l, sc_isEqual); }
+*/
+
+/* optimized versions */
+/*** META ((export #t)) */
+function sc_memq(o, l) {
+    while (l !== null) {
+	if (l.car === o)
+	    return l;
+	l = l.cdr;
+    }
+    return false;
+}
+/*** META ((export #t)) */
+function sc_memv(o, l) {
+    while (l !== null) {
+	if (l.car === o)
+	    return l;
+	l = l.cdr;
+    }
+    return false;
+}
+/*** META ((export #t)) */
+function sc_member(o, l) {
+    while (l !== null) {
+	if (sc_isEqual(l.car,o))
+	    return l;
+	l = l.cdr;
+    }
+    return false;
+}
+
+/* // generic unoptimized versions
+function sc_assX(o, al, comp) {
+    while (al != null) {
+	if (comp(al.car.car, o))
+	    return al.car;
+	al = al.cdr;
+    }
+    return false;
+}
+function sc_assq(o, al) { return sc_assX(o, al, sc_isEq); }
+function sc_assv(o, al) { return sc_assX(o, al, sc_isEqv); }
+function sc_assoc(o, al) { return sc_assX(o, al, sc_isEqual); }
+*/
+// optimized versions
+/*** META ((export #t)) */
+function sc_assq(o, al) {
+    while (al !== null) {
+	if (al.car.car === o)
+	    return al.car;
+	al = al.cdr;
+    }
+    return false;
+}
+/*** META ((export #t)) */
+function sc_assv(o, al) {
+    while (al !== null) {
+	if (al.car.car === o)
+	    return al.car;
+	al = al.cdr;
+    }
+    return false;
+}
+/*** META ((export #t)) */
+function sc_assoc(o, al) {
+    while (al !== null) {
+	if (sc_isEqual(al.car.car, o))
+	    return al.car;
+	al = al.cdr;
+    }
+    return false;
+}
+
+/* can be used for mutable strings and characters */
+function sc_isCharStringEqual(cs1, cs2) { return cs1.val === cs2.val; }
+function sc_isCharStringLess(cs1, cs2) { return cs1.val < cs2.val; }
+function sc_isCharStringGreater(cs1, cs2) { return cs1.val > cs2.val; }
+function sc_isCharStringLessEqual(cs1, cs2) { return cs1.val <= cs2.val; }
+function sc_isCharStringGreaterEqual(cs1, cs2) { return cs1.val >= cs2.val; }
+function sc_isCharStringCIEqual(cs1, cs2)
+    { return cs1.val.toLowerCase() === cs2.val.toLowerCase(); }
+function sc_isCharStringCILess(cs1, cs2)
+    { return cs1.val.toLowerCase() < cs2.val.toLowerCase(); }
+function sc_isCharStringCIGreater(cs1, cs2)
+    { return cs1.val.toLowerCase() > cs2.val.toLowerCase(); }
+function sc_isCharStringCILessEqual(cs1, cs2)
+    { return cs1.val.toLowerCase() <= cs2.val.toLowerCase(); }
+function sc_isCharStringCIGreaterEqual(cs1, cs2)
+    { return cs1.val.toLowerCase() >= cs2.val.toLowerCase(); }
+
+
+
+
+function sc_Char(c) {
+    var cached = sc_Char.lazy[c];
+    if (cached)
+	return cached;
+    this.val = c;
+    sc_Char.lazy[c] = this;
+    // add return, so FF does not complain.
+    return undefined;
+}
+sc_Char.lazy = new Object();
+// thanks to Eric
+sc_Char.char2readable = {
+    "\000": "#\\null",
+    "\007": "#\\bell",
+    "\010": "#\\backspace",
+    "\011": "#\\tab",
+    "\012": "#\\newline",
+    "\014": "#\\page",
+    "\015": "#\\return",
+    "\033": "#\\escape",
+    "\040": "#\\space",
+    "\177": "#\\delete",
+
+  /* poeticless names */
+    "\001": "#\\soh",
+    "\002": "#\\stx",
+    "\003": "#\\etx",
+    "\004": "#\\eot",
+    "\005": "#\\enq",
+    "\006": "#\\ack",
+
+    "\013": "#\\vt",
+    "\016": "#\\so",
+    "\017": "#\\si",
+
+    "\020": "#\\dle",
+    "\021": "#\\dc1",
+    "\022": "#\\dc2",
+    "\023": "#\\dc3",
+    "\024": "#\\dc4",
+    "\025": "#\\nak",
+    "\026": "#\\syn",
+    "\027": "#\\etb",
+
+    "\030": "#\\can",
+    "\031": "#\\em",
+    "\032": "#\\sub",
+    "\033": "#\\esc",
+    "\034": "#\\fs",
+    "\035": "#\\gs",
+    "\036": "#\\rs",
+    "\037": "#\\us"};
+
+sc_Char.readable2char = {
+    "null": "\000",
+    "bell": "\007",
+    "backspace": "\010",
+    "tab": "\011",
+    "newline": "\012",
+    "page": "\014",
+    "return": "\015",
+    "escape": "\033",
+    "space": "\040",
+    "delete": "\000",
+    "soh": "\001",
+    "stx": "\002",
+    "etx": "\003",
+    "eot": "\004",
+    "enq": "\005",
+    "ack": "\006",
+    "bel": "\007",
+    "bs": "\010",
+    "ht": "\011",
+    "nl": "\012",
+    "vt": "\013",
+    "np": "\014",
+    "cr": "\015",
+    "so": "\016",
+    "si": "\017",
+    "dle": "\020",
+    "dc1": "\021",
+    "dc2": "\022",
+    "dc3": "\023",
+    "dc4": "\024",
+    "nak": "\025",
+    "syn": "\026",
+    "etb": "\027",
+    "can": "\030",
+    "em": "\031",
+    "sub": "\032",
+    "esc": "\033",
+    "fs": "\034",
+    "gs": "\035",
+    "rs": "\036",
+    "us": "\037",
+    "sp": "\040",
+    "del": "\177"};
+    
+sc_Char.prototype.toString = function() {
+    return this.val;
+};
+// sc_toDisplayString == toString
+sc_Char.prototype.sc_toWriteString = function() {
+    var entry = sc_Char.char2readable[this.val];
+    if (entry)
+	return entry;
+    else
+	return "#\\" + this.val;
+};
+
+/*** META ((export #t)
+           (type bool)
+           (peephole (postfix "instanceof sc_Char")))
+*/
+function sc_isChar(c) {
+    return (c instanceof sc_Char);
+}
+
+/*** META ((export char=?)
+           (type bool)
+           (peephole (hole 2 c1 ".val === " c2 ".val")))
+*/
+var sc_isCharEqual = sc_isCharStringEqual;
+/*** META ((export char<?)
+           (type bool)
+           (peephole (hole 2 c1 ".val < " c2 ".val")))
+*/
+var sc_isCharLess = sc_isCharStringLess;
+/*** META ((export char>?)
+           (type bool)
+           (peephole (hole 2 c1 ".val > " c2 ".val")))
+*/
+var sc_isCharGreater = sc_isCharStringGreater;
+/*** META ((export char<=?)
+           (type bool)
+           (peephole (hole 2 c1 ".val <= " c2 ".val")))
+*/
+var sc_isCharLessEqual = sc_isCharStringLessEqual;
+/*** META ((export char>=?)
+           (type bool)
+           (peephole (hole 2 c1 ".val >= " c2 ".val")))
+*/
+var sc_isCharGreaterEqual = sc_isCharStringGreaterEqual;
+/*** META ((export char-ci=?)
+           (type bool)
+           (peephole (hole 2 c1 ".val.toLowerCase() === " c2 ".val.toLowerCase()")))
+*/
+var sc_isCharCIEqual = sc_isCharStringCIEqual;
+/*** META ((export char-ci<?)
+           (type bool)
+           (peephole (hole 2 c1 ".val.toLowerCase() < " c2 ".val.toLowerCase()")))
+*/
+var sc_isCharCILess = sc_isCharStringCILess;
+/*** META ((export char-ci>?)
+           (type bool)
+           (peephole (hole 2 c1 ".val.toLowerCase() > " c2 ".val.toLowerCase()")))
+*/
+var sc_isCharCIGreater = sc_isCharStringCIGreater;
+/*** META ((export char-ci<=?)
+           (type bool)
+           (peephole (hole 2 c1 ".val.toLowerCase() <= " c2 ".val.toLowerCase()")))
+*/
+var sc_isCharCILessEqual = sc_isCharStringCILessEqual;
+/*** META ((export char-ci>=?)
+           (type bool)
+           (peephole (hole 2 c1 ".val.toLowerCase() >= " c2 ".val.toLowerCase()")))
+*/
+var sc_isCharCIGreaterEqual = sc_isCharStringCIGreaterEqual;
+
+var SC_NUMBER_CLASS = "0123456789";
+var SC_WHITESPACE_CLASS = ' \r\n\t\f';
+var SC_LOWER_CLASS = 'abcdefghijklmnopqrstuvwxyz';
+var SC_UPPER_CLASS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
+
+function sc_isCharOfClass(c, cl) { return (cl.indexOf(c) != -1); }
+/*** META ((export #t)
+           (type bool))
+*/
+function sc_isCharAlphabetic(c)
+    { return sc_isCharOfClass(c.val, SC_LOWER_CLASS) ||
+	  sc_isCharOfClass(c.val, SC_UPPER_CLASS); }
+/*** META ((export #t)
+           (type bool)
+           (peephole (hole 1 "SC_NUMBER_CLASS.indexOf(" c ".val) != -1")))
+*/
+function sc_isCharNumeric(c)
+    { return sc_isCharOfClass(c.val, SC_NUMBER_CLASS); }
+/*** META ((export #t)
+           (type bool))
+*/
+function sc_isCharWhitespace(c) {
+    var tmp = c.val;
+    return tmp === " " || tmp === "\r" || tmp === "\n" || tmp === "\t" || tmp === "\f";
+}
+/*** META ((export #t)
+           (type bool)
+           (peephole (hole 1 "SC_UPPER_CLASS.indexOf(" c ".val) != -1")))
+*/
+function sc_isCharUpperCase(c)
+    { return sc_isCharOfClass(c.val, SC_UPPER_CLASS); }
+/*** META ((export #t)
+           (type bool)
+           (peephole (hole 1 "SC_LOWER_CLASS.indexOf(" c ".val) != -1")))
+*/
+function sc_isCharLowerCase(c)
+    { return sc_isCharOfClass(c.val, SC_LOWER_CLASS); }
+
+/*** META ((export #t)
+           (peephole (postfix ".val.charCodeAt(0)")))
+*/
+function sc_char2integer(c)
+    { return c.val.charCodeAt(0); }
+/*** META ((export #t)
+           (peephole (hole 1 "new sc_Char(String.fromCharCode(" n "))")))
+*/
+function sc_integer2char(n)
+    { return new sc_Char(String.fromCharCode(n)); }
+
+/*** META ((export #t)
+           (peephole (hole 1 "new sc_Char(" c ".val.toUpperCase())")))
+*/
+function sc_charUpcase(c)
+    { return new sc_Char(c.val.toUpperCase()); }
+/*** META ((export #t)
+           (peephole (hole 1 "new sc_Char(" c ".val.toLowerCase())")))
+*/
+function sc_charDowncase(c)
+    { return new sc_Char(c.val.toLowerCase()); }
+
+function sc_makeJSStringOfLength(k, c) {
+    var fill;
+    if (c === undefined)
+	fill = " ";
+    else
+	fill = c;
+    var res = "";
+    var len = 1;
+    // every round doubles the size of fill.
+    while (k >= len) {
+	if (k & len)
+	    res = res.concat(fill);
+	fill = fill.concat(fill);
+	len *= 2;
+    }
+    return res;
+}
+
+function sc_makejsString(k, c) {
+    var fill;
+    if (c)
+	fill = c.val;
+    else
+	fill = " ";
+    return sc_makeJSStringOfLength(k, fill);
+}
+
+function sc_jsstring2list(s) {
+    var res = null;
+    for (var i = s.length - 1; i >= 0; i--)
+	res = sc_cons(new sc_Char(s.charAt(i)), res);
+    return res;
+}
+
+function sc_list2jsstring(l) {
+    var a = new Array();
+    while(l !== null) {
+	a.push(l.car.val);
+	l = l.cdr;
+    }
+    return "".concat.apply("", a);
+}
+
+var sc_Vector = Array;
+
+sc_Vector.prototype.sc_toWriteOrDisplayString = function(writeOrDisplay) {
+    if (this.length === 0) return "#()";
+
+    var res = "#(" + writeOrDisplay(this[0]);
+    for (var i = 1; i < this.length; i++)
+	res += " " + writeOrDisplay(this[i]);
+    res += ")";
+    return res;
+};
+sc_Vector.prototype.sc_toDisplayString = function() {
+    return this.sc_toWriteOrDisplayString(sc_toDisplayString);
+};
+sc_Vector.prototype.sc_toWriteString = function() {
+    return this.sc_toWriteOrDisplayString(sc_toWriteString);
+};
+
+/*** META ((export vector? array?)
+           (type bool)
+           (peephole (postfix " instanceof sc_Vector")))
+*/
+function sc_isVector(v) {
+    return (v instanceof sc_Vector);
+}
+
+// only applies to vectors
+function sc_isVectorEqual(v1, v2, comp) {
+    if (v1.length !== v2.length) return false;
+    for (var i = 0; i < v1.length; i++)
+	if (!comp(v1[i], v2[i])) return false;
+    return true;
+}
+
+/*** META ((export make-vector make-array)) */
+function sc_makeVector(size, fill) {
+    var a = new sc_Vector(size);
+    if (fill !== undefined)
+	sc_vectorFillBang(a, fill);
+    return a;
+}
+
+/*** META ((export vector array)
+           (peephole (vector)))
+*/
+function sc_vector() {
+    var a = new sc_Vector();
+    for (var i = 0; i < arguments.length; i++)
+	a.push(arguments[i]);
+    return a;
+}
+
+/*** META ((export vector-length array-length)
+           (peephole (postfix ".length")))
+*/
+function sc_vectorLength(v) {
+    return v.length;
+}
+
+/*** META ((export vector-ref array-ref)
+           (peephole (hole 2 v "[" pos "]")))
+*/
+function sc_vectorRef(v, pos) {
+    return v[pos];
+}
+
+/*** META ((export vector-set! array-set!)
+           (peephole (hole 3 v "[" pos "] = " val)))
+*/
+function sc_vectorSetBang(v, pos, val) {
+    v[pos] = val;
+}
+
+/*** META ((export vector->list array->list)) */
+function sc_vector2list(a) {
+    var res = null;
+    for (var i = a.length-1; i >= 0; i--)
+	res = sc_cons(a[i], res);
+    return res;
+}
+
+/*** META ((export list->vector list->array)) */
+function sc_list2vector(l) {
+    var a = new sc_Vector();
+    while(l !== null) {
+	a.push(l.car);
+	l = l.cdr;
+    }
+    return a;
+}
+
+/*** META ((export vector-fill! array-fill!)) */
+function sc_vectorFillBang(a, fill) {
+    for (var i = 0; i < a.length; i++)
+	a[i] = fill;
+}
+
+
+/*** META ((export #t)) */
+function sc_copyVector(a, len) {
+    if (len <= a.length)
+	return a.slice(0, len);
+    else {
+	var tmp = a.concat();
+	tmp.length = len;
+	return tmp;
+    }
+}
+
+/*** META ((export #t)
+           (peephole (hole 3 a ".slice(" start "," end ")")))
+*/
+function sc_vectorCopy(a, start, end) {
+    return a.slice(start, end);
+}
+
+/*** META ((export #t)) */
+function sc_vectorCopyBang(target, tstart, source, sstart, send) {
+    if (!sstart) sstart = 0;
+    if (!send) send = source.length;
+
+    // if target == source we don't want to overwrite not yet copied elements.
+    if (tstart <= sstart) {
+	for (var i = tstart, j = sstart; j < send; i++, j++) {
+	    target[i] = source[j];
+	}
+    } else {
+	var diff = send - sstart;
+	for (var i = tstart + diff - 1, j = send - 1;
+	     j >= sstart;
+	     i--, j--) {
+	    target[i] = source[j];
+	}
+    }
+    return target;
+}
+
+/*** META ((export #t)
+           (type bool)
+           (peephole (hole 1 "typeof " o " === 'function'")))
+*/
+function sc_isProcedure(o) {
+    return (typeof o === "function");
+}
+
+/*** META ((export #t)) */
+function sc_apply(proc) {
+    var args = new Array();
+    // first part of arguments are not in list-form.
+    for (var i = 1; i < arguments.length - 1; i++)
+	args.push(arguments[i]);
+    var l = arguments[arguments.length - 1];
+    while (l !== null) {
+	args.push(l.car);
+	l = l.cdr;
+    }
+    return proc.apply(null, args);
+}
+
+/*** META ((export #t)) */
+function sc_map(proc, l1) {
+    if (l1 === undefined)
+	return null;
+    // else
+    var nbApplyArgs = arguments.length - 1;
+    var applyArgs = new Array(nbApplyArgs);
+    var revres = null;
+    while (l1 !== null) {
+	for (var i = 0; i < nbApplyArgs; i++) {
+	    applyArgs[i] = arguments[i + 1].car;
+	    arguments[i + 1] = arguments[i + 1].cdr;
+	}
+	revres = sc_cons(proc.apply(null, applyArgs), revres);
+    }
+    return sc_reverseAppendBang(revres, null);
+}
+
+/*** META ((export #t)) */
+function sc_mapBang(proc, l1) {
+    if (l1 === undefined)
+	return null;
+    // else
+    var l1_orig = l1;
+    var nbApplyArgs = arguments.length - 1;
+    var applyArgs = new Array(nbApplyArgs);
+    while (l1 !== null) {
+	var tmp = l1;
+	for (var i = 0; i < nbApplyArgs; i++) {
+	    applyArgs[i] = arguments[i + 1].car;
+	    arguments[i + 1] = arguments[i + 1].cdr;
+	}
+	tmp.car = proc.apply(null, applyArgs);
+    }
+    return l1_orig;
+}
+     
+/*** META ((export #t)) */
+function sc_forEach(proc, l1) {
+    if (l1 === undefined)
+	return undefined;
+    // else
+    var nbApplyArgs = arguments.length - 1;
+    var applyArgs = new Array(nbApplyArgs);
+    while (l1 !== null) {
+	for (var i = 0; i < nbApplyArgs; i++) {
+	    applyArgs[i] = arguments[i + 1].car;
+	    arguments[i + 1] = arguments[i + 1].cdr;
+	}
+	proc.apply(null, applyArgs);
+    }
+    // add return so FF does not complain.
+    return undefined;
+}
+
+/*** META ((export #t)) */
+function sc_filter(proc, l1) {
+    var dummy = { cdr : null };
+    var tail = dummy;
+    while (l1 !== null) {
+	if (proc(l1.car) !== false) {
+	    tail.cdr = sc_cons(l1.car, null);
+	    tail = tail.cdr;
+	}
+	l1 = l1.cdr;
+    }
+    return dummy.cdr;
+}
+
+/*** META ((export #t)) */
+function sc_filterBang(proc, l1) {
+    var head = sc_cons("dummy", l1);
+    var it = head;
+    var next = l1;
+    while (next !== null) {
+        if (proc(next.car) !== false) {
+	    it.cdr = next
+	    it = next;
+	}
+	next = next.cdr;
+    }
+    it.cdr = null;
+    return head.cdr;
+}
+
+function sc_filterMap1(proc, l1) {
+    var revres = null;
+    while (l1 !== null) {
+        var tmp = proc(l1.car)
+        if (tmp !== false) revres = sc_cons(tmp, revres);
+        l1 = l1.cdr;
+    }
+    return sc_reverseAppendBang(revres, null);
+}
+function sc_filterMap2(proc, l1, l2) {
+    var revres = null;
+    while (l1 !== null) {
+        var tmp = proc(l1.car, l2.car);
+        if(tmp !== false) revres = sc_cons(tmp, revres);
+	l1 = l1.cdr;
+	l2 = l2.cdr
+    }
+    return sc_reverseAppendBang(revres, null);
+}
+
+/*** META ((export #t)) */
+function sc_filterMap(proc, l1, l2, l3) {
+    if (l2 === undefined)
+	return sc_filterMap1(proc, l1);
+    else if (l3 === undefined)
+	return sc_filterMap2(proc, l1, l2);
+    // else
+    var nbApplyArgs = arguments.length - 1;
+    var applyArgs = new Array(nbApplyArgs);
+    var revres = null;
+    while (l1 !== null) {
+	for (var i = 0; i < nbApplyArgs; i++) {
+	    applyArgs[i] = arguments[i + 1].car;
+	    arguments[i + 1] = arguments[i + 1].cdr;
+	}
+	var tmp = proc.apply(null, applyArgs);
+	if(tmp !== false) revres = sc_cons(tmp, revres);
+    }
+    return sc_reverseAppendBang(revres, null);
+}
+
+/*** META ((export #t)) */
+function sc_any(proc, l) {
+    var revres = null;
+    while (l !== null) {
+        var tmp = proc(l.car);
+        if(tmp !== false) return tmp;
+	l = l.cdr;
+    }
+    return false;
+}
+
+/*** META ((export any?)
+           (peephole (hole 2 "sc_any(" proc "," l ") !== false")))
+*/
+function sc_anyPred(proc, l) {
+    return sc_any(proc, l)!== false;
+}
+
+/*** META ((export #t)) */
+function sc_every(proc, l) {
+    var revres = null;
+    var tmp = true;
+    while (l !== null) {
+        tmp = proc(l.car);
+        if (tmp === false) return false;
+	l = l.cdr;
+    }
+    return tmp;
+}
+
+/*** META ((export every?)
+           (peephole (hole 2 "sc_every(" proc "," l ") !== false")))
+*/
+function sc_everyPred(proc, l) {
+    var tmp = sc_every(proc, l);
+    if (tmp !== false) return true;
+    return false;
+}
+
+/*** META ((export #t)
+           (peephole (postfix "()")))
+*/
+function sc_force(o) {
+    return o();
+}
+
+/*** META ((export #t)) */
+function sc_makePromise(proc) {
+    var isResultReady = false;
+    var result = undefined;
+    return function() {
+	if (!isResultReady) {
+	    var tmp = proc();
+	    if (!isResultReady) {
+		isResultReady = true;
+		result = tmp;
+	    }
+	}
+	return result;
+    };
+}
+
+function sc_Values(values) {
+    this.values = values;
+}
+
+/*** META ((export #t)
+           (peephole (values)))
+*/
+function sc_values() {
+    if (arguments.length === 1)
+	return arguments[0];
+    else
+	return new sc_Values(arguments);
+}
+
+/*** META ((export #t)) */
+function sc_callWithValues(producer, consumer) {
+    var produced = producer();
+    if (produced instanceof sc_Values)
+	return consumer.apply(null, produced.values);
+    else
+	return consumer(produced);
+}
+
+/*** META ((export #t)) */
+function sc_dynamicWind(before, thunk, after) {
+    before();
+    try {
+	var res = thunk();
+	return res;
+    } finally {
+	after();
+    }
+}
+
+
+// TODO: eval/scheme-report-environment/null-environment/interaction-environment
+
+// LIMITATION: 'load' doesn't exist without files.
+// LIMITATION: transcript-on/transcript-off doesn't exist without files.
+
+
+function sc_Struct(name) {
+    this.name = name;
+}
+sc_Struct.prototype.sc_toDisplayString = function() {
+    return "#<struct" + sc_hash(this) + ">";
+};
+sc_Struct.prototype.sc_toWriteString = sc_Struct.prototype.sc_toDisplayString;
+
+/*** META ((export #t)
+           (peephole (hole 1 "new sc_Struct(" name ")")))
+*/
+function sc_makeStruct(name) {
+    return new sc_Struct(name);
+}
+
+/*** META ((export #t)
+           (type bool)
+           (peephole (postfix " instanceof sc_Struct")))
+*/
+function sc_isStruct(o) {
+    return (o instanceof sc_Struct);
+}
+
+/*** META ((export #t)
+           (type bool)
+           (peephole (hole 2 "(" 1 " instanceof sc_Struct) && ( " 1 ".name === " 0 ")")))
+*/
+function sc_isStructNamed(name, s) {
+    return ((s instanceof sc_Struct) && (s.name === name));
+}
+
+/*** META ((export struct-field)
+           (peephole (hole 3 0 "[" 2 "]")))
+*/
+function sc_getStructField(s, name, field) {
+    return s[field];
+}
+
+/*** META ((export struct-field-set!)
+           (peephole (hole 4 0 "[" 2 "] = " 3)))
+*/
+function sc_setStructFieldBang(s, name, field, val) {
+    s[field] = val;
+}
+
+/*** META ((export #t)
+           (peephole (prefix "~")))
+*/
+function sc_bitNot(x) {
+    return ~x;
+}
+
+/*** META ((export #t)
+           (peephole (infix 2 2 "&")))
+*/
+function sc_bitAnd(x, y) {
+    return x & y;
+}
+
+/*** META ((export #t)
+           (peephole (infix 2 2 "|")))
+*/
+function sc_bitOr(x, y) {
+    return x | y;
+}
+
+/*** META ((export #t)
+           (peephole (infix 2 2 "^")))
+*/
+function sc_bitXor(x, y) {
+    return x ^ y;
+}
+
+/*** META ((export #t)
+           (peephole (infix 2 2 "<<")))
+*/
+function sc_bitLsh(x, y) {
+    return x << y;
+}
+
+/*** META ((export #t)
+           (peephole (infix 2 2 ">>")))
+*/
+function sc_bitRsh(x, y) {
+    return x >> y;
+}
+
+/*** META ((export #t)
+           (peephole (infix 2 2 ">>>")))
+*/
+function sc_bitUrsh(x, y) {
+    return x >>> y;
+}
+
+/*** META ((export js-field js-property)
+           (peephole (hole 2 o "[" field "]")))
+*/
+function sc_jsField(o, field) {
+    return o[field];
+}
+
+/*** META ((export js-field-set! js-property-set!)
+           (peephole (hole 3 o "[" field "] = " val)))
+*/
+function sc_setJsFieldBang(o, field, val) {
+    return o[field] = val;
+}
+
+/*** META ((export js-field-delete! js-property-delete!)
+           (peephole (hole 2 "delete" o "[" field "]")))
+*/
+function sc_deleteJsFieldBang(o, field) {
+    delete o[field];
+}
+
+/*** META ((export #t)
+           (peephole (jsCall)))
+*/
+function sc_jsCall(o, fun) {
+    var args = new Array();
+    for (var i = 2; i < arguments.length; i++)
+	args[i-2] = arguments[i];
+    return fun.apply(o, args);
+}
+
+/*** META ((export #t)
+           (peephole (jsMethodCall)))
+*/
+function sc_jsMethodCall(o, field) {
+    var args = new Array();
+    for (var i = 2; i < arguments.length; i++)
+	args[i-2] = arguments[i];
+    return o[field].apply(o, args);
+}
+
+/*** META ((export new js-new)
+           (peephole (jsNew)))
+*/
+function sc_jsNew(c) {
+    var evalStr = "new c(";
+    evalStr +=arguments.length > 1? "arguments[1]": "";
+    for (var i = 2; i < arguments.length; i++)
+	evalStr += ", arguments[" + i + "]";
+    evalStr +=")";
+    return eval(evalStr);
+}    
+
+// ======================== RegExp ====================
+/*** META ((export #t)) */
+function sc_pregexp(re) {
+    return new RegExp(sc_string2jsstring(re));
+}
+
+/*** META ((export #t)) */
+function sc_pregexpMatch(re, s) {
+    var reg = (re instanceof RegExp) ? re : sc_pregexp(re);
+    var tmp = reg.exec(sc_string2jsstring(s));
+    
+    if (tmp == null) return false;
+    
+    var res = null;
+    for (var i = tmp.length-1; i >= 0; i--) {
+	if (tmp[i] !== null) {
+	    res = sc_cons(sc_jsstring2string(tmp[i]), res);
+	} else {
+	    res = sc_cons(false, res);
+	}
+    }
+    return res;
+}
+   
+/*** META ((export #t)) */
+function sc_pregexpReplace(re, s1, s2) {
+   var reg;
+   var jss1 = sc_string2jsstring(s1);
+   var jss2 = sc_string2jsstring(s2);
+
+   if (re instanceof RegExp) {
+       if (re.global)
+	   reg = re;
+       else
+	   reg = new RegExp(re.source);
+   } else {
+       reg = new RegExp(sc_string2jsstring(re));
+   }
+
+   return jss1.replace(reg, jss2);
+}
+   
+/*** META ((export pregexp-replace*)) */
+function sc_pregexpReplaceAll(re, s1, s2) {
+   var reg;
+   var jss1 = sc_string2jsstring(s1);
+   var jss2 = sc_string2jsstring(s2);
+
+   if (re instanceof RegExp) {
+      if (re.global)
+	  reg = re;
+      else
+	  reg = new RegExp(re.source, "g");
+   } else {
+       reg = new RegExp(sc_string2jsstring(re), "g");
+   }
+
+   return jss1.replace(reg, jss2);
+}
+
+/*** META ((export #t)) */
+function sc_pregexpSplit(re, s) {
+   var reg = ((re instanceof RegExp) ?
+	      re :
+	      new RegExp(sc_string2jsstring(re)));
+   var jss = sc_string2jsstring(s);
+   var tmp = jss.split(reg);
+
+   if (tmp == null) return false;
+
+   return sc_vector2list(tmp);
+}
+   
+
+/* =========================================================================== */
+/* Other library stuff */
+/* =========================================================================== */
+
+/*** META ((export #t)
+           (peephole (hole 1 "Math.floor(Math.random()*" 'n ")")))
+*/
+function sc_random(n) {
+    return Math.floor(Math.random()*n);
+}
+
+/*** META ((export current-date)
+           (peephole (hole 0 "new Date()")))
+*/
+function sc_currentDate() {
+   return new Date();
+}
+
+function sc_Hashtable() {
+}
+sc_Hashtable.prototype.toString = function() {
+    return "#{%hashtable}";
+};
+// sc_toWriteString == sc_toDisplayString == toString
+
+function sc_HashtableElement(key, val) {
+    this.key = key;
+    this.val = val;
+}
+
+/*** META ((export #t)
+           (peephole (hole 0 "new sc_Hashtable()")))
+*/
+function sc_makeHashtable() {
+    return new sc_Hashtable();
+}
+
+/*** META ((export #t)) */
+function sc_hashtablePutBang(ht, key, val) {
+    var hash = sc_hash(key);
+    ht[hash] = new sc_HashtableElement(key, val);
+}
+
+/*** META ((export #t)) */
+function sc_hashtableGet(ht, key) {
+    var hash = sc_hash(key);
+    if (hash in ht)
+	return ht[hash].val;
+    else
+	return false;
+}
+
+/*** META ((export #t)) */
+function sc_hashtableForEach(ht, f) {
+    for (var v in ht) {
+	if (ht[v] instanceof sc_HashtableElement)
+	    f(ht[v].key, ht[v].val);
+    }
+}
+
+/*** META ((export hashtable-contains?)
+           (peephole (hole 2 "sc_hash(" 1 ") in " 0)))
+*/
+function sc_hashtableContains(ht, key) {
+    var hash = sc_hash(key);
+    if (hash in ht)
+	return true;
+    else
+	return false;
+}
+
+var SC_HASH_COUNTER = 0;
+
+function sc_hash(o) {
+    if (o === null)
+	return "null";
+    else if (o === undefined)
+	return "undefined";
+    else if (o === true)
+	return "true";
+    else if (o === false)
+	return "false";
+    else if (typeof o === "number")
+	return "num-" + o;
+    else if (typeof o === "string")
+	return "jsstr-" + o;
+    else if (o.sc_getHash)
+	return o.sc_getHash();
+    else
+	return sc_counterHash.call(o);
+}
+function sc_counterHash() {
+    if (!this.sc_hash) {
+	this.sc_hash = "hash-" + SC_HASH_COUNTER;
+	SC_HASH_COUNTER++;
+    }
+    return this.sc_hash;
+}
+
+function sc_Trampoline(args, maxTailCalls) {
+    this['__trampoline return__'] = true;
+    this.args = args;
+    this.MAX_TAIL_CALLs = maxTailCalls;
+}
+// TODO: call/cc stuff
+sc_Trampoline.prototype.restart = function() {
+    var o = this;
+    while (true) {
+	// set both globals.
+	SC_TAIL_OBJECT.calls = o.MAX_TAIL_CALLs-1;
+	var fun = o.args.callee;
+	var res = fun.apply(SC_TAIL_OBJECT, o.args);
+	if (res instanceof sc_Trampoline)
+	    o = res;
+	else
+	    return res;
+    }
+}
+
+/*** META ((export bind-exit-lambda)) */
+function sc_bindExitLambda(proc) {
+    var escape_obj = new sc_BindExitException();
+    var escape = function(res) {
+	escape_obj.res = res;
+	throw escape_obj;
+    };
+    try {
+	return proc(escape);
+    } catch(e) {
+	if (e === escape_obj) {
+	    return e.res;
+	}
+	throw e;
+    }
+}
+function sc_BindExitException() {
+    this._internalException = true;
+}
+
+var SC_SCM2JS_GLOBALS = new Object();
+
+// default tail-call depth.
+// normally the program should set it again. but just in case...
+var SC_TAIL_OBJECT = new Object();
+SC_SCM2JS_GLOBALS.TAIL_OBJECT = SC_TAIL_OBJECT;
+// ======================== I/O =======================
+
+/*------------------------------------------------------------------*/
+
+function sc_EOF() {
+}
+var SC_EOF_OBJECT = new sc_EOF();
+
+function sc_Port() {
+}
+
+/* --------------- Input ports -------------------------------------*/
+
+function sc_InputPort() {
+}
+sc_InputPort.prototype = new sc_Port();
+
+sc_InputPort.prototype.peekChar = function() {
+    if (!("peeked" in this))
+	this.peeked = this.getNextChar();
+    return this.peeked;
+}
+sc_InputPort.prototype.readChar = function() {
+    var tmp = this.peekChar();
+    delete this.peeked;
+    return tmp;
+}
+sc_InputPort.prototype.isCharReady = function() {
+    return true;
+}
+sc_InputPort.prototype.close = function() {
+    // do nothing
+}
+
+/* .............. String port ..........................*/
+function sc_ErrorInputPort() {
+};
+sc_ErrorInputPort.prototype = new sc_InputPort();
+sc_ErrorInputPort.prototype.getNextChar = function() {
+    throw "can't read from error-port.";
+};
+sc_ErrorInputPort.prototype.isCharReady = function() {
+    return false;
+};
+    
+
+/* .............. String port ..........................*/
+
+function sc_StringInputPort(jsStr) {
+    // we are going to do some charAts on the str.
+    // instead of recreating all the time a String-object, we
+    // create one in the beginning. (not sure, if this is really an optim)
+    this.str = new String(jsStr);
+    this.pos = 0;
+}
+sc_StringInputPort.prototype = new sc_InputPort();
+sc_StringInputPort.prototype.getNextChar = function() {
+    if (this.pos >= this.str.length)
+	return SC_EOF_OBJECT;
+    return this.str.charAt(this.pos++);
+};
+
+/* ------------- Read and other lib-funs  -------------------------------*/
+function sc_Token(type, val, pos) {
+    this.type = type;
+    this.val = val;
+    this.pos = pos;
+}
+sc_Token.EOF = 0/*EOF*/;
+sc_Token.OPEN_PAR = 1/*OPEN_PAR*/;
+sc_Token.CLOSE_PAR = 2/*CLOSE_PAR*/;
+sc_Token.OPEN_BRACE = 3/*OPEN_BRACE*/;
+sc_Token.CLOSE_BRACE = 4/*CLOSE_BRACE*/;
+sc_Token.OPEN_BRACKET = 5/*OPEN_BRACKET*/;
+sc_Token.CLOSE_BRACKET = 6/*CLOSE_BRACKET*/;
+sc_Token.WHITESPACE = 7/*WHITESPACE*/;
+sc_Token.QUOTE = 8/*QUOTE*/;
+sc_Token.ID = 9/*ID*/;
+sc_Token.DOT = 10/*DOT*/;
+sc_Token.STRING = 11/*STRING*/;
+sc_Token.NUMBER = 12/*NUMBER*/;
+sc_Token.ERROR = 13/*ERROR*/;
+sc_Token.VECTOR_BEGIN = 14/*VECTOR_BEGIN*/;
+sc_Token.TRUE = 15/*TRUE*/;
+sc_Token.FALSE = 16/*FALSE*/;
+sc_Token.UNSPECIFIED = 17/*UNSPECIFIED*/;
+sc_Token.REFERENCE = 18/*REFERENCE*/;
+sc_Token.STORE = 19/*STORE*/;
+sc_Token.CHAR = 20/*CHAR*/;
+
+var SC_ID_CLASS = SC_LOWER_CLASS + SC_UPPER_CLASS + "!$%*+-./:<=>?@^_~";
+function sc_Tokenizer(port) {
+    this.port = port;
+}
+sc_Tokenizer.prototype.peekToken = function() {
+    if (this.peeked)
+	return this.peeked;
+    var newToken = this.nextToken();
+    this.peeked = newToken;
+    return newToken;
+};
+sc_Tokenizer.prototype.readToken = function() {
+    var tmp = this.peekToken();
+    delete this.peeked;
+    return tmp;
+};
+sc_Tokenizer.prototype.nextToken = function() {
+    var port = this.port;
+    
+    function isNumberChar(c) {
+	return (c >= "0" && c <= "9");
+    };
+    function isIdOrNumberChar(c) {
+	return SC_ID_CLASS.indexOf(c) != -1 || // ID-char
+	    (c >= "0" && c <= "9");
+    }
+    function isWhitespace(c) {
+	return c === " " || c === "\r" || c === "\n" || c === "\t" || c === "\f";
+    };
+    function isWhitespaceOrEOF(c) {
+	return isWhitespace(c) || c === SC_EOF_OBJECT;
+    };
+
+    function readString() {
+	res = "";
+	while (true) {
+	    var c = port.readChar();
+	    switch (c) {
+	    case '"':
+		return new sc_Token(11/*STRING*/, res);
+	    case "\\":
+		var tmp = port.readChar();
+		switch (tmp) {
+		case '0': res += "\0"; break;
+		case 'a': res += "\a"; break;
+		case 'b': res += "\b"; break;
+		case 'f': res += "\f"; break;
+		case 'n': res += "\n"; break;
+		case 'r': res += "\r"; break;
+		case 't': res += "\t"; break;
+		case 'v': res += "\v"; break;
+		case '"': res += '"'; break;
+		case '\\': res += '\\'; break;
+		case 'x':
+		    /* hexa-number */
+		    var nb = 0;
+		    while (true) {
+			var hexC = port.peekChar();
+			if (hexC >= '0' && hexC <= '9') {
+			    port.readChar();
+			    nb = nb * 16 + hexC.charCodeAt(0) - '0'.charCodeAt(0);
+			} else if (hexC >= 'a' && hexC <= 'f') {
+			    port.readChar();
+			    nb = nb * 16 + hexC.charCodeAt(0) - 'a'.charCodeAt(0);
+			} else if (hexC >= 'A' && hexC <= 'F') {
+			    port.readChar();
+			    nb = nb * 16 + hexC.charCodeAt(0) - 'A'.charCodeAt(0);
+			} else {
+			    // next char isn't part of hex.
+			    res += String.fromCharCode(nb);
+			    break;
+			}
+		    }
+		    break;
+		default:
+		    if (tmp === SC_EOF_OBJECT) {
+			return new sc_Token(13/*ERROR*/, "unclosed string-literal" + res);
+		    }
+		    res += tmp;
+		}
+		break;
+	    default:
+		if (c === SC_EOF_OBJECT) {
+		    return new sc_Token(13/*ERROR*/, "unclosed string-literal" + res);
+		}
+		res += c;
+	    }
+	}
+    };
+    function readIdOrNumber(firstChar) {
+	var res = firstChar;
+	while (isIdOrNumberChar(port.peekChar()))
+	    res += port.readChar();
+	if (isNaN(res))
+	    return new sc_Token(9/*ID*/, res);
+	else
+	    return new sc_Token(12/*NUMBER*/, res - 0);
+    };
+    
+    function skipWhitespaceAndComments() {
+	var done = false;
+	while (!done) {
+	    done = true;
+	    while (isWhitespace(port.peekChar()))
+		port.readChar();
+	    if (port.peekChar() === ';') {
+		port.readChar();
+		done = false;
+		while (true) {
+		    curChar = port.readChar();
+		    if (curChar === SC_EOF_OBJECT ||
+			curChar === '\n')
+			break;
+		}
+	    }
+	}
+    };
+    
+    function readDot() {
+	if (isWhitespace(port.peekChar()))
+	    return new sc_Token(10/*DOT*/);
+	else
+	    return readIdOrNumber(".");
+    };
+
+    function readSharp() {
+	var c = port.readChar();
+	if (isWhitespace(c))
+	    return new sc_Token(13/*ERROR*/, "bad #-pattern0.");
+
+	// reference
+	if (isNumberChar(c)) {
+	    var nb = c - 0;
+	    while (isNumberChar(port.peekChar()))
+		nb = nb*10 + (port.readChar() - 0);
+	    switch (port.readChar()) {
+	    case '#':
+		return new sc_Token(18/*REFERENCE*/, nb);
+	    case '=':
+		return new sc_Token(19/*STORE*/, nb);
+	    default:
+		return new sc_Token(13/*ERROR*/, "bad #-pattern1." + nb);
+	    }
+	}
+
+	if (c === "(")
+	    return new sc_Token(14/*VECTOR_BEGIN*/);
+	
+	if (c === "\\") { // character
+	    var tmp = ""
+	    while (!isWhitespaceOrEOF(port.peekChar()))
+		tmp += port.readChar();
+	    switch (tmp.length) {
+	    case 0: // it's escaping a whitespace char:
+		if (sc_isEOFObject(port.peekChar))
+		    return new sc_Token(13/*ERROR*/, "bad #-pattern2.");
+		else
+		    return new sc_Token(20/*CHAR*/, port.readChar());
+	    case 1:
+		return new sc_Token(20/*CHAR*/, tmp);
+	    default:
+		var entry = sc_Char.readable2char[tmp.toLowerCase()];
+		if (entry)
+		    return new sc_Token(20/*CHAR*/, entry);
+		else
+		    return new sc_Token(13/*ERROR*/, "unknown character description: #\\" + tmp);
+	    }
+	}
+
+	// some constants (#t, #f, #unspecified)
+	var res;
+	var needing;
+	switch (c) {
+	case 't': res = new sc_Token(15/*TRUE*/, true); needing = ""; break;
+	case 'f': res = new sc_Token(16/*FALSE*/, false); needing = ""; break;
+	case 'u': res = new sc_Token(17/*UNSPECIFIED*/, undefined); needing = "nspecified"; break;
+	default:
+	    return new sc_Token(13/*ERROR*/, "bad #-pattern3: " + c);
+	}
+	while(true) {
+	    c = port.peekChar();
+	    if ((isWhitespaceOrEOF(c) || c === ')') &&
+		needing == "")
+		return res;
+	    else if (isWhitespace(c) || needing == "")
+		return new sc_Token(13/*ERROR*/, "bad #-pattern4 " + c + " " + needing);
+	    else if (needing.charAt(0) == c) {
+		port.readChar(); // consume
+		needing = needing.slice(1);
+	    } else
+		return new sc_Token(13/*ERROR*/, "bad #-pattern5");
+	}
+	
+    };
+
+    skipWhitespaceAndComments();
+    var curChar = port.readChar();
+    if (curChar === SC_EOF_OBJECT)
+	return new sc_Token(0/*EOF*/, curChar);
+    switch (curChar)
+    {
+    case " ":
+    case "\n":
+    case "\t":
+	return readWhitespace();
+    case "(":
+	return new sc_Token(1/*OPEN_PAR*/);
+    case ")":
+	return new sc_Token(2/*CLOSE_PAR*/);
+    case "{":
+	return new sc_Token(3/*OPEN_BRACE*/);
+    case "}":
+	return new sc_Token(4/*CLOSE_BRACE*/);
+    case "[":
+	return new sc_Token(5/*OPEN_BRACKET*/);
+    case "]":
+	return new sc_Token(6/*CLOSE_BRACKET*/);
+    case "'":
+	return new sc_Token(8/*QUOTE*/);
+    case "#":
+	return readSharp();
+    case ".":
+	return readDot();
+    case '"':
+	return readString();
+    default:
+	if (isIdOrNumberChar(curChar))
+	    return readIdOrNumber(curChar);
+	throw "unexpected character: " + curChar;
+    }
+};
+
+function sc_Reader(tokenizer) {
+    this.tokenizer = tokenizer;
+    this.backref = new Array();
+}
+sc_Reader.prototype.read = function() {
+    function readList(listBeginType) {
+	function matchesPeer(open, close) {
+	    return open === 1/*OPEN_PAR*/ && close === 2/*CLOSE_PAR*/
+	    	|| open === 3/*OPEN_BRACE*/ && close === 4/*CLOSE_BRACE*/
+		|| open === 5/*OPEN_BRACKET*/ && close === 6/*CLOSE_BRACKET*/;
+	};
+	var res = null;
+
+	while (true) {
+	    var token = tokenizer.peekToken();
+	    
+	    switch (token.type) {
+	    case 2/*CLOSE_PAR*/:
+	    case 4/*CLOSE_BRACE*/:
+	    case 6/*CLOSE_BRACKET*/:
+		if (matchesPeer(listBeginType, token.type)) {
+		    tokenizer.readToken(); // consume token
+		    return sc_reverseBang(res);
+		} else
+		    throw "closing par doesn't match: " + listBeginType
+			+ " " + listEndType;
+
+	    case 0/*EOF*/:
+		throw "unexpected end of file";
+
+	    case 10/*DOT*/:
+		tokenizer.readToken(); // consume token
+		var cdr = this.read();
+		var par = tokenizer.readToken();
+		if (!matchesPeer(listBeginType, par.type))
+		    throw "closing par doesn't match: " + listBeginType
+			+ " " + par.type;
+		else
+		    return sc_reverseAppendBang(res, cdr);
+		
+
+	    default:
+		res = sc_cons(this.read(), res);
+	    }
+	}
+    };
+    function readQuote() {
+	return sc_cons("quote", sc_cons(this.read(), null));
+    };
+    function readVector() {
+	// opening-parenthesis is already consumed
+	var a = new Array();
+	while (true) {
+	    var token = tokenizer.peekToken();
+	    switch (token.type) {
+	    case 2/*CLOSE_PAR*/:
+		tokenizer.readToken();
+		return a;
+		
+	    default:
+		a.push(this.read());
+	    }
+	}
+    };
+
+    function storeRefence(nb) {
+	var tmp = this.read();
+	this.backref[nb] = tmp;
+	return tmp;
+    };
+	
+    function readReference(nb) {
+	if (nb in this.backref)
+	    return this.backref[nb];
+	else
+	    throw "bad reference: " + nb;
+    };
+    
+    var tokenizer = this.tokenizer;
+
+    var token = tokenizer.readToken();
+
+    // handle error
+    if (token.type === 13/*ERROR*/)
+	throw token.val;
+    
+    switch (token.type) {
+    case 1/*OPEN_PAR*/:
+    case 3/*OPEN_BRACE*/:
+    case 5/*OPEN_BRACKET*/:
+	return readList.call(this, token.type);
+    case 8/*QUOTE*/:
+	return readQuote.call(this);
+    case 11/*STRING*/:
+	return sc_jsstring2string(token.val);
+    case 20/*CHAR*/:
+	return new sc_Char(token.val);
+    case 14/*VECTOR_BEGIN*/:
+	return readVector.call(this);
+    case 18/*REFERENCE*/:
+	return readReference.call(this, token.val);
+    case 19/*STORE*/:
+	return storeRefence.call(this, token.val);
+    case 9/*ID*/:
+	return sc_jsstring2symbol(token.val);
+    case 0/*EOF*/:
+    case 12/*NUMBER*/:
+    case 15/*TRUE*/:
+    case 16/*FALSE*/:
+    case 17/*UNSPECIFIED*/:
+	return token.val;
+    default:
+	throw "unexpected token " + token.type + " " + token.val;
+    }
+};
+
+/*** META ((export #t)) */
+function sc_read(port) {
+    if (port === undefined) // we assume the port hasn't been given.
+	port = SC_DEFAULT_IN; // THREAD: shared var...
+    var reader = new sc_Reader(new sc_Tokenizer(port));
+    return reader.read();
+}
+/*** META ((export #t)) */
+function sc_readChar(port) {
+    if (port === undefined) // we assume the port hasn't been given.
+	port = SC_DEFAULT_IN; // THREAD: shared var...
+    var t = port.readChar();
+    return t === SC_EOF_OBJECT? t: new sc_Char(t);
+}
+/*** META ((export #t)) */
+function sc_peekChar(port) {
+    if (port === undefined) // we assume the port hasn't been given.
+	port = SC_DEFAULT_IN; // THREAD: shared var...
+    var t = port.peekChar();
+    return t === SC_EOF_OBJECT? t: new sc_Char(t);
+}    
+/*** META ((export #t)
+           (type bool))
+*/
+function sc_isCharReady(port) {
+    if (port === undefined) // we assume the port hasn't been given.
+	port = SC_DEFAULT_IN; // THREAD: shared var...
+    return port.isCharReady();
+}
+/*** META ((export #t)
+           (peephole (postfix ".close()")))
+*/
+function sc_closeInputPort(p) {
+    return p.close();
+}
+
+/*** META ((export #t)
+           (type bool)
+           (peephole (postfix " instanceof sc_InputPort")))
+*/
+function sc_isInputPort(o) {
+    return (o instanceof sc_InputPort);
+}
+
+/*** META ((export eof-object?)
+           (type bool)
+           (peephole (postfix " === SC_EOF_OBJECT")))
+*/
+function sc_isEOFObject(o) {
+    return o === SC_EOF_OBJECT;
+}
+
+/*** META ((export #t)
+           (peephole (hole 0 "SC_DEFAULT_IN")))
+*/
+function sc_currentInputPort() {
+    return SC_DEFAULT_IN;
+}
+
+/* ------------ file operations are not supported -----------*/
+/*** META ((export #t)) */
+function sc_callWithInputFile(s, proc) {
+    throw "can't open " + s;
+}
+
+/*** META ((export #t)) */
+function sc_callWithOutputFile(s, proc) {
+    throw "can't open " + s;
+}
+
+/*** META ((export #t)) */
+function sc_withInputFromFile(s, thunk) {
+    throw "can't open " + s;
+}
+
+/*** META ((export #t)) */
+function sc_withOutputToFile(s, thunk) {
+    throw "can't open " + s;
+}
+
+/*** META ((export #t)) */
+function sc_openInputFile(s) {
+    throw "can't open " + s;
+}
+
+/*** META ((export #t)) */
+function sc_openOutputFile(s) {
+    throw "can't open " + s;
+}
+
+/* ----------------------------------------------------------------------------*/
+/*** META ((export #t)) */
+function sc_basename(p) {
+   var i = p.lastIndexOf('/');
+
+   if(i >= 0)
+      return p.substring(i + 1, p.length);
+   else
+      return '';
+}
+
+/*** META ((export #t)) */
+function sc_dirname(p) {
+   var i = p.lastIndexOf('/');
+
+   if(i >= 0)
+      return p.substring(0, i);
+   else
+      return '';
+}
+
+/* ----------------------------------------------------------------------------*/
+
+/*** META ((export #t)) */
+function sc_withInputFromPort(p, thunk) {
+    try {
+	var tmp = SC_DEFAULT_IN; // THREAD: shared var.
+	SC_DEFAULT_IN = p;
+	return thunk();
+    } finally {
+	SC_DEFAULT_IN = tmp;
+    }
+}
+
+/*** META ((export #t)) */
+function sc_withInputFromString(s, thunk) {
+    return sc_withInputFromPort(new sc_StringInputPort(sc_string2jsstring(s)), thunk);
+}
+
+/*** META ((export #t)) */
+function sc_withOutputToPort(p, thunk) {
+    try {
+	var tmp = SC_DEFAULT_OUT; // THREAD: shared var.
+	SC_DEFAULT_OUT = p;
+	return thunk();
+    } finally {
+	SC_DEFAULT_OUT = tmp;
+    }
+}
+
+/*** META ((export #t)) */
+function sc_withOutputToString(thunk) {
+    var p = new sc_StringOutputPort();
+    sc_withOutputToPort(p, thunk);
+    return p.close();
+}
+
+/*** META ((export #t)) */
+function sc_withOutputToProcedure(proc, thunk) {
+    var t = function(s) { proc(sc_jsstring2string(s)); };
+    return sc_withOutputToPort(new sc_GenericOutputPort(t), thunk);
+}
+
+/*** META ((export #t)
+           (peephole (hole 0 "new sc_StringOutputPort()")))
+*/
+function sc_openOutputString() {
+    return new sc_StringOutputPort();
+}
+
+/*** META ((export #t)) */
+function sc_openInputString(str) {
+    return new sc_StringInputPort(sc_string2jsstring(str));
+}
+
+/* ----------------------------------------------------------------------------*/
+
+function sc_OutputPort() {
+}
+sc_OutputPort.prototype = new sc_Port();
+sc_OutputPort.prototype.appendJSString = function(obj) {
+    /* do nothing */
+}
+sc_OutputPort.prototype.close = function() {
+    /* do nothing */
+}
+
+function sc_StringOutputPort() {
+    this.res = "";
+}
+sc_StringOutputPort.prototype = new sc_OutputPort();
+sc_StringOutputPort.prototype.appendJSString = function(s) {
+    this.res += s;
+}
+sc_StringOutputPort.prototype.close = function() {
+    return sc_jsstring2string(this.res);
+}
+
+/*** META ((export #t)) */
+function sc_getOutputString(sp) {
+    return sc_jsstring2string(sp.res);
+}
+    
+
+function sc_ErrorOutputPort() {
+}
+sc_ErrorOutputPort.prototype = new sc_OutputPort();
+sc_ErrorOutputPort.prototype.appendJSString = function(s) {
+    throw "don't write on ErrorPort!";
+}
+sc_ErrorOutputPort.prototype.close = function() {
+    /* do nothing */
+}
+
+function sc_GenericOutputPort(appendJSString, close) {
+    this.appendJSString = appendJSString;
+    if (close)
+	this.close = close;
+}
+sc_GenericOutputPort.prototype = new sc_OutputPort();
+
+/*** META ((export #t)
+           (type bool)
+           (peephole (postfix " instanceof sc_OutputPort")))
+*/
+function sc_isOutputPort(o) {
+    return (o instanceof sc_OutputPort);
+}
+
+/*** META ((export #t)
+           (peephole (postfix ".close()")))
+*/
+function sc_closeOutputPort(p) {
+    return p.close();
+}
+
+/* ------------------ write ---------------------------------------------------*/
+
+/*** META ((export #t)) */
+function sc_write(o, p) {
+    if (p === undefined) // we assume not given
+	p = SC_DEFAULT_OUT;
+    p.appendJSString(sc_toWriteString(o));
+}
+
+function sc_toWriteString(o) {
+    if (o === null)
+	return "()";
+    else if (o === true)
+	return "#t";
+    else if (o === false)
+	return "#f";
+    else if (o === undefined)
+	return "#unspecified";
+    else if (typeof o === 'function')
+	return "#<procedure " + sc_hash(o) + ">";
+    else if (o.sc_toWriteString)
+	return o.sc_toWriteString();
+    else
+	return o.toString();
+}
+
+function sc_escapeWriteString(s) {
+    var res = "";
+    var j = 0;
+    for (i = 0; i < s.length; i++) {
+	switch (s.charAt(i)) {
+	case "\0": res += s.substring(j, i) + "\\0"; j = i + 1; break;
+	case "\b": res += s.substring(j, i) + "\\b"; j = i + 1; break;
+	case "\f": res += s.substring(j, i) + "\\f"; j = i + 1; break;
+	case "\n": res += s.substring(j, i) + "\\n"; j = i + 1; break;
+	case "\r": res += s.substring(j, i) + "\\r"; j = i + 1; break;
+	case "\t": res += s.substring(j, i) + "\\t"; j = i + 1; break;
+	case "\v": res += s.substring(j, i) + "\\v"; j = i + 1; break;
+	case '"': res += s.substring(j, i) + '\\"'; j = i + 1; break;
+	case "\\": res += s.substring(j, i) + "\\\\"; j = i + 1; break;
+	default:
+	    var c = s.charAt(i);
+	    if ("\a" !== "a" && c == "\a") {
+		res += s.substring(j, i) + "\\a"; j = i + 1; continue;
+	    }
+	    if ("\v" !== "v" && c == "\v") {
+		res += s.substring(j, i) + "\\v"; j = i + 1; continue;
+	    }
+	    //if (s.charAt(i) < ' ' || s.charCodeAt(i) > 127) {
+	    // CARE: Manuel is this OK with HOP?
+	    if (s.charAt(i) < ' ') {
+		/* non printable character and special chars */
+		res += s.substring(j, i) + "\\x" + s.charCodeAt(i).toString(16);
+		j = i + 1;
+	    }
+	    // else just let i increase...
+	}
+    }
+    res += s.substring(j, i);
+    return res;
+}
+
+/* ------------------ display ---------------------------------------------------*/
+
+/*** META ((export #t)) */
+function sc_display(o, p) {
+    if (p === undefined) // we assume not given
+	p = SC_DEFAULT_OUT;
+    p.appendJSString(sc_toDisplayString(o));
+}
+
+function sc_toDisplayString(o) {
+    if (o === null)
+	return "()";
+    else if (o === true)
+	return "#t";
+    else if (o === false)
+	return "#f";
+    else if (o === undefined)
+	return "#unspecified";
+    else if (typeof o === 'function')
+	return "#<procedure " + sc_hash(o) + ">";
+    else if (o.sc_toDisplayString)
+	return o.sc_toDisplayString();
+    else
+	return o.toString();
+}
+
+/* ------------------ newline ---------------------------------------------------*/
+
+/*** META ((export #t)) */
+function sc_newline(p) {
+    if (p === undefined) // we assume not given
+	p = SC_DEFAULT_OUT;
+    p.appendJSString("\n");
+}
+    
+/* ------------------ write-char ---------------------------------------------------*/
+
+/*** META ((export #t)) */
+function sc_writeChar(c, p) {
+    if (p === undefined) // we assume not given
+	p = SC_DEFAULT_OUT;
+    p.appendJSString(c.val);
+}
+
+/* ------------------ write-circle ---------------------------------------------------*/
+
+/*** META ((export #t)) */
+function sc_writeCircle(o, p) {
+    if (p === undefined) // we assume not given
+	p = SC_DEFAULT_OUT;
+    p.appendJSString(sc_toWriteCircleString(o));
+}
+
+function sc_toWriteCircleString(o) {
+    var symb = sc_gensym("writeCircle");
+    var nbPointer = new Object();
+    nbPointer.nb = 0;
+    sc_prepWriteCircle(o, symb, nbPointer);
+    return sc_genToWriteCircleString(o, symb);
+}
+
+function sc_prepWriteCircle(o, symb, nbPointer) {
+    // TODO sc_Struct
+    if (o instanceof sc_Pair ||
+	o instanceof sc_Vector) {
+	if (o[symb] !== undefined) {
+	    // not the first visit.
+	    o[symb]++;
+	    // unless there is already a number, assign one.
+	    if (!o[symb + "nb"]) o[symb + "nb"] = nbPointer.nb++;
+	    return;
+	}
+	o[symb] = 0;
+	if (o instanceof sc_Pair) {
+	    sc_prepWriteCircle(o.car, symb, nbPointer);
+	    sc_prepWriteCircle(o.cdr, symb, nbPointer);
+	} else {
+	    for (var i = 0; i < o.length; i++)
+		sc_prepWriteCircle(o[i], symb, nbPointer);
+	}
+    }
+}
+
+function sc_genToWriteCircleString(o, symb) {
+    if (!(o instanceof sc_Pair ||
+	  o instanceof sc_Vector))
+	return sc_toWriteString(o);
+    return o.sc_toWriteCircleString(symb);
+}
+sc_Pair.prototype.sc_toWriteCircleString = function(symb, inList) {
+    if (this[symb + "use"]) { // use-flag is set. Just use it.
+	var nb = this[symb + "nb"];
+	if (this[symb]-- === 0) { // if we are the last use. remove all fields.
+	    delete this[symb];
+	    delete this[symb + "nb"];
+	    delete this[symb + "use"];
+	}
+	if (inList)
+	    return '. #' + nb + '#';
+	else
+	    return '#' + nb + '#';
+    }
+    if (this[symb]-- === 0) { // if we are the last use. remove all fields.
+	delete this[symb];
+	delete this[symb + "nb"];
+	delete this[symb + "use"];
+    }
+
+    var res = "";
+    
+    if (this[symb] !== undefined) { // implies > 0
+	this[symb + "use"] = true;
+	if (inList)
+	    res += '. #' + this[symb + "nb"] + '=';
+	else
+	    res += '#' + this[symb + "nb"] + '=';
+	inList = false;
+    }
+
+    if (!inList)
+	res += "(";
+    
+    // print car
+    res += sc_genToWriteCircleString(this.car, symb);
+    
+    if (sc_isPair(this.cdr)) {
+	res += " " + this.cdr.sc_toWriteCircleString(symb, true);
+    } else if (this.cdr !== null) {
+	res += " . " + sc_genToWriteCircleString(this.cdr, symb);
+    }
+    if (!inList)
+	res += ")";
+    return res;
+};
+sc_Vector.prototype.sc_toWriteCircleString = function(symb) {
+    if (this[symb + "use"]) { // use-flag is set. Just use it.
+	var nb = this[symb + "nb"];
+	if (this[symb]-- === 0) { // if we are the last use. remove all fields.
+	    delete this[symb];
+	    delete this[symb + "nb"];
+	    delete this[symb + "use"];
+	}
+	return '#' + nb + '#';
+    }
+    if (this[symb]-- === 0) { // if we are the last use. remove all fields.
+	delete this[symb];
+	delete this[symb + "nb"];
+	delete this[symb + "use"];
+    }
+
+    var res = "";
+    if (this[symb] !== undefined) { // implies > 0
+	this[symb + "use"] = true;
+	res += '#' + this[symb + "nb"] + '=';
+    }
+    res += "#(";
+    for (var i = 0; i < this.length; i++) {
+	res += sc_genToWriteCircleString(this[i], symb);
+	if (i < this.length - 1) res += " ";
+    }
+    res += ")";
+    return res;
+};
+
+
+/* ------------------ print ---------------------------------------------------*/
+
+/*** META ((export #t)) */
+function sc_print(s) {
+    if (arguments.length === 1) {
+	sc_display(s);
+	sc_newline();
+    }
+    else {
+	for (var i = 0; i < arguments.length; i++)
+	    sc_display(arguments[i]);
+	sc_newline();
+    }
+}
+
+/* ------------------ format ---------------------------------------------------*/
+/*** META ((export #t)) */
+function sc_format(s, args) {
+   var len = s.length;
+   var p = new sc_StringOutputPort();
+   var i = 0, j = 1;
+
+   while( i < len ) {
+      var i2 = s.indexOf("~", i);
+
+      if (i2 == -1) {
+	  p.appendJSString( s.substring( i, len ) );
+	  return p.close();
+      } else {
+	 if (i2 > i) {
+	    if (i2 == (len - 1)) {
+		p.appendJSString(s.substring(i, len));
+		return p.close();
+	    } else {
+	       p.appendJSString(s.substring(i, i2));
+	       i = i2;
+	    }
+	 }
+
+	 switch(s.charCodeAt(i2 + 1)) {
+	    case 65:
+	    case 97:
+	       // a
+	       sc_display(arguments[j], p);
+	       i += 2; j++;
+	       break;
+
+	    case 83:
+	    case 115:
+	       // s
+	       sc_write(arguments[j], p);
+	       i += 2; j++;
+	       break;
+
+	    case 86:
+	    case 118:
+	       // v
+	       sc_display(arguments[j], p);
+	       p.appendJSString("\n");
+	       i += 2; j++;
+	       break;
+
+	    case 67:
+	    case 99:
+	       // c
+	       p.appendJSString(String.fromCharCode(arguments[j]));
+	       i += 2; j++;
+	       break;
+
+	    case 88:
+	    case 120:
+	       // x
+	       p.appendJSString(arguments[j].toString(6));
+	       i += 2; j++;
+	       break;
+
+	    case 79:
+	    case 111:
+	       // o
+	       p.appendJSString(arguments[j].toString(8));
+	       i += 2; j++;
+	       break;
+
+	    case 66:
+	    case 98:
+	       // b
+	       p.appendJSString(arguments[j].toString(2));
+	       i += 2; j++;
+	       break;
+	       
+	    case 37:
+	    case 110:
+	       // %, n
+	       p.appendJSString("\n");
+	       i += 2; break;
+
+	    case 114:
+	       // r
+	       p.appendJSString("\r");
+	       i += 2; break;
+
+	    case 126:
+	       // ~
+	       p.appendJSString("~");
+	       i += 2; break;
+
+	    default:
+	       sc_error( "format: illegal ~"
+			 + String.fromCharCode(s.charCodeAt(i2 + 1))
+			 + " sequence" );
+	       return "";
+	 }
+      }
+   }
+
+   return p.close();
+}
+
+/* ------------------ global ports ---------------------------------------------------*/
+
+var SC_DEFAULT_IN = new sc_ErrorInputPort();
+var SC_DEFAULT_OUT = new sc_ErrorOutputPort();
+var SC_ERROR_OUT = new sc_ErrorOutputPort();
+
+var sc_SYMBOL_PREFIX = "\u1E9C";
+var sc_KEYWORD_PREFIX = "\u1E9D";
+
+/*** META ((export #t)
+           (peephole (id))) */
+function sc_jsstring2string(s) {
+    return s;
+}
+
+/*** META ((export #t)
+           (peephole (prefix "'\\u1E9C' +")))
+*/
+function sc_jsstring2symbol(s) {
+    return sc_SYMBOL_PREFIX + s;
+}
+
+/*** META ((export #t)
+           (peephole (id)))
+*/
+function sc_string2jsstring(s) {
+    return s;
+}
+
+/*** META ((export #t)
+           (peephole (symbol2jsstring_immutable)))
+*/
+function sc_symbol2jsstring(s) {
+    return s.slice(1);
+}
+
+/*** META ((export #t)
+           (peephole (postfix ".slice(1)")))
+*/
+function sc_keyword2jsstring(k) {
+    return k.slice(1);
+}
+
+/*** META ((export #t)
+           (peephole (prefix "'\\u1E9D' +")))
+*/
+function sc_jsstring2keyword(s) {
+    return sc_KEYWORD_PREFIX + s;
+}
+
+/*** META ((export #t)
+           (type bool))
+*/
+function sc_isKeyword(s) {
+    return (typeof s === "string") &&
+	(s.charAt(0) === sc_KEYWORD_PREFIX);
+}
+
+
+/*** META ((export #t)) */
+var sc_gensym = function() {
+    var counter = 1000;
+    return function(sym) {
+	counter++;
+	if (!sym) sym = sc_SYMBOL_PREFIX;
+	return sym + "s" + counter + "~" + "^sC-GeNsYm ";
+    };
+}();
+
+
+/*** META ((export #t)
+           (type bool))
+*/
+function sc_isEqual(o1, o2) {
+    return ((o1 === o2) ||
+	    (sc_isPair(o1) && sc_isPair(o2)
+	     && sc_isPairEqual(o1, o2, sc_isEqual)) ||
+	    (sc_isVector(o1) && sc_isVector(o2)
+	     && sc_isVectorEqual(o1, o2, sc_isEqual)));
+}
+
+/*** META ((export number->symbol integer->symbol)) */
+function sc_number2symbol(x, radix) {
+    return sc_SYMBOL_PREFIX + sc_number2jsstring(x, radix);
+}
+    
+/*** META ((export number->string integer->string)) */
+var sc_number2string = sc_number2jsstring;
+
+/*** META ((export #t)) */
+function sc_symbol2number(s, radix) {
+    return sc_jsstring2number(s.slice(1), radix);
+}
+
+/*** META ((export #t)) */
+var sc_string2number = sc_jsstring2number;
+
+/*** META ((export #t)
+           (peephole (prefix "+" s)))
+           ;; peephole will only apply if no radix is given.
+*/
+function sc_string2integer(s, radix) {
+    if (!radix) return +s;
+    return parseInt(s, radix);
+}
+
+/*** META ((export #t)
+           (peephole (prefix "+")))
+*/
+function sc_string2real(s) {
+    return +s;
+}
+
+
+/*** META ((export #t)
+           (type bool))
+*/
+function sc_isSymbol(s) {
+    return (typeof s === "string") &&
+	(s.charAt(0) === sc_SYMBOL_PREFIX);
+}
+
+/*** META ((export #t)
+           (peephole (symbol2string_immutable)))
+*/
+function sc_symbol2string(s) {
+    return s.slice(1);
+}
+
+/*** META ((export #t)
+           (peephole (prefix "'\\u1E9C' +")))
+*/
+function sc_string2symbol(s) {
+    return sc_SYMBOL_PREFIX + s;
+}
+
+/*** META ((export symbol-append)
+           (peephole (symbolAppend_immutable)))
+*/
+function sc_symbolAppend() {
+    var res = sc_SYMBOL_PREFIX;
+    for (var i = 0; i < arguments.length; i++)
+	res += arguments[i].slice(1);
+    return res;
+}
+
+/*** META ((export #t)
+           (peephole (postfix ".val")))
+*/
+function sc_char2string(c) { return c.val; }
+
+/*** META ((export #t)
+           (peephole (hole 1 "'\\u1E9C' + " c ".val")))
+*/
+function sc_char2symbol(c) { return sc_SYMBOL_PREFIX + c.val; }
+
+/*** META ((export #t)
+           (type bool))
+*/
+function sc_isString(s) {
+    return (typeof s === "string") &&
+	(s.charAt(0) !== sc_SYMBOL_PREFIX);
+}
+
+/*** META ((export #t)) */
+var sc_makeString = sc_makejsString;
+
+
+/*** META ((export #t)) */
+function sc_string() {
+    for (var i = 0; i < arguments.length; i++)
+	arguments[i] = arguments[i].val;
+    return "".concat.apply("", arguments);
+}
+
+/*** META ((export #t)
+           (peephole (postfix ".length")))
+*/
+function sc_stringLength(s) { return s.length; }
+
+/*** META ((export #t)) */
+function sc_stringRef(s, k) {
+    return new sc_Char(s.charAt(k));
+}
+
+/* there's no stringSet in the immutable version
+function sc_stringSet(s, k, c)
+*/
+
+
+/*** META ((export string=?)
+	   (type bool)
+           (peephole (hole 2 str1 " === " str2)))
+*/
+function sc_isStringEqual(s1, s2) {
+    return s1 === s2;
+}
+/*** META ((export string<?)
+	   (type bool)
+           (peephole (hole 2 str1 " < " str2)))
+*/
+function sc_isStringLess(s1, s2) {
+    return s1 < s2;
+}
+/*** META ((export string>?)
+	   (type bool)
+           (peephole (hole 2 str1 " > " str2)))
+*/
+function sc_isStringGreater(s1, s2) {
+    return s1 > s2;
+}
+/*** META ((export string<=?)
+	   (type bool)
+           (peephole (hole 2 str1 " <= " str2)))
+*/
+function sc_isStringLessEqual(s1, s2) {
+    return s1 <= s2;
+}
+/*** META ((export string>=?)
+	   (type bool)
+           (peephole (hole 2 str1 " >= " str2)))
+*/
+function sc_isStringGreaterEqual(s1, s2) {
+    return s1 >= s2;
+}
+/*** META ((export string-ci=?)
+	   (type bool)
+           (peephole (hole 2 str1 ".toLowerCase() === " str2 ".toLowerCase()")))
+*/
+function sc_isStringCIEqual(s1, s2) {
+    return s1.toLowerCase() === s2.toLowerCase();
+}
+/*** META ((export string-ci<?)
+	   (type bool)
+           (peephole (hole 2 str1 ".toLowerCase() < " str2 ".toLowerCase()")))
+*/
+function sc_isStringCILess(s1, s2) {
+    return s1.toLowerCase() < s2.toLowerCase();
+}
+/*** META ((export string-ci>?)
+	   (type bool)
+           (peephole (hole 2 str1 ".toLowerCase() > " str2 ".toLowerCase()")))
+*/
+function sc_isStringCIGreater(s1, s2) {
+    return s1.toLowerCase() > s2.toLowerCase();
+}
+/*** META ((export string-ci<=?)
+	   (type bool)
+           (peephole (hole 2 str1 ".toLowerCase() <= " str2 ".toLowerCase()")))
+*/
+function sc_isStringCILessEqual(s1, s2) {
+    return s1.toLowerCase() <= s2.toLowerCase();
+}
+/*** META ((export string-ci>=?)
+	   (type bool)
+           (peephole (hole 2 str1 ".toLowerCase() >= " str2 ".toLowerCase()")))
+*/
+function sc_isStringCIGreaterEqual(s1, s2) {
+    return s1.toLowerCase() >= s2.toLowerCase();
+}
+
+/*** META ((export #t)
+           (peephole (hole 3 s ".substring(" start ", " end ")")))
+*/
+function sc_substring(s, start, end) {
+    return s.substring(start, end);
+}
+
+/*** META ((export #t))
+*/
+function sc_isSubstring_at(s1, s2, i) {
+    return s2 == s1.substring(i, i+ s2.length);
+}
+
+/*** META ((export #t)
+           (peephole (infix 0 #f "+" "''")))
+*/
+function sc_stringAppend() {
+    return "".concat.apply("", arguments);
+}
+
+/*** META ((export #t)) */
+var sc_string2list = sc_jsstring2list;
+
+/*** META ((export #t)) */
+var sc_list2string = sc_list2jsstring;
+
+/*** META ((export #t)
+           (peephole (id)))
+*/
+function sc_stringCopy(s) {
+    return s;
+}
+
+/* there's no string-fill in the immutable version
+function sc_stringFill(s, c)
+*/
+
+/*** META ((export #t)
+           (peephole (postfix ".slice(1)")))
+*/
+function sc_keyword2string(o) {
+    return o.slice(1);
+}
+
+/*** META ((export #t)
+           (peephole (prefix "'\\u1E9D' +")))
+*/
+function sc_string2keyword(o) {
+    return sc_KEYWORD_PREFIX + o;
+}
+
+String.prototype.sc_toDisplayString = function() {
+    if (this.charAt(0) === sc_SYMBOL_PREFIX)
+	// TODO: care for symbols with spaces (escape-chars symbols).
+	return this.slice(1);
+    else if (this.charAt(0) === sc_KEYWORD_PREFIX)
+	return ":" + this.slice(1);
+    else
+	return this.toString();
+};
+
+String.prototype.sc_toWriteString = function() {
+    if (this.charAt(0) === sc_SYMBOL_PREFIX)
+	// TODO: care for symbols with spaces (escape-chars symbols).
+	return this.slice(1);
+    else if (this.charAt(0) === sc_KEYWORD_PREFIX)
+	return ":" + this.slice(1);
+    else
+	return '"' + sc_escapeWriteString(this) + '"';
+};
+/* Exported Variables */
+var BgL_testzd2boyerzd2;
+var BgL_nboyerzd2benchmarkzd2;
+var BgL_setupzd2boyerzd2;
+/* End Exports */
+
+var translate_term_nboyer;
+var translate_args_nboyer;
+var untranslate_term_nboyer;
+var BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer;
+var BgL_sc_za2symbolzd2recordszd2alistza2_2z00_nboyer;
+var translate_alist_nboyer;
+var apply_subst_nboyer;
+var apply_subst_lst_nboyer;
+var tautologyp_nboyer;
+var if_constructor_nboyer;
+var rewrite_count_nboyer;
+var rewrite_nboyer;
+var rewrite_args_nboyer;
+var unify_subst_nboyer;
+var one_way_unify1_nboyer;
+var false_term_nboyer;
+var true_term_nboyer;
+var trans_of_implies1_nboyer;
+var is_term_equal_nboyer;
+var is_term_member_nboyer;
+var const_nboyer;
+var sc_const_3_nboyer;
+var sc_const_4_nboyer;
+{
+    (sc_const_4_nboyer = (new sc_Pair("\u1E9Cimplies",(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cimplies",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cimplies",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cimplies",(new sc_Pair("\u1E9Cz",(new sc_Pair("\u1E9Cu",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cimplies",(new sc_Pair("\u1E9Cu",(new sc_Pair("\u1E9Cw",null)))))),null)))))),null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cimplies",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cw",null)))))),null)))))));
+    (sc_const_3_nboyer = sc_list((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ccompile",(new sc_Pair("\u1E9Cform",null)))),(new sc_Pair((new sc_Pair("\u1E9Creverse",(new sc_Pair((new sc_Pair("\u1E9Ccodegen",(new sc_Pair((new sc_Pair("\u1E9Coptimize",(new sc_Pair("\u1E9Cform",null)))),(new sc_Pair((new sc_Pair("\u1E9Cnil",null)),null)))))),null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ceqp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cy",null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cgreaterp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cx",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clesseqp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cx",null)))))),null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cgreatereqp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cboolean",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Ct",null)),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cf",null)),null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ciff",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cimplies",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cimplies",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cx",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ceven1",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Ct",null)),(new sc_Pair((new sc_Pair("\u1E9Codd",(new sc_Pair((new sc_Pair("\u1E9Csub1",(new sc_Pair("\u1E9Cx",null)))),null)))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ccountps-",(new sc_Pair("\u1E9Cl",(new sc_Pair("\u1E9Cpred",null)))))),(new sc_Pair((new sc_Pair("\u1E9Ccountps-loop",(new sc_Pair("\u1E9Cl",(new sc_Pair("\u1E9Cpred",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cfact-",(new sc_Pair("\u1E9Ci",null)))),(new sc_Pair((new sc_Pair("\u1E9Cfact-loop",(new sc_Pair("\u1E9Ci",(new sc_Pair((1),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Creverse-",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Creverse-loop",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cnil",null)),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cdivides",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair((new sc_Pair("\u1E9Cremainder",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cx",null)))))),null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cassume-true",(new sc_Pair("\u1E9Cvar",(new sc_Pair("\u1E9Calist",null)))))),(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair("\u1E9Cvar",(new sc_Pair((new sc_Pair("\u1E9Ct",null)),null)))))),(new sc_Pair("\u1E9Calist",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cassume-false",(new sc_Pair("\u1E9Cvar",(new sc_Pair("\u1E9Calist",null)))))),(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair("\u1E9Cvar",(new sc_Pair((new sc_Pair("\u1E9Cf",null)),null)))))),(new sc_Pair("\u1E9Calist",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ctautology-checker",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Ctautologyp",(new sc_Pair((new sc_Pair("\u1E9Cnormalize",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cnil",null)),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cfalsify",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cfalsify1",(new sc_Pair((new sc_Pair("\u1E9Cnormalize",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cnil",null)),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cprime",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cx",null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cadd1",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))),null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cprime1",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Csub1",(new sc_Pair("\u1E9Cx",null)))),null)))))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair("\u1E9Cp",(new sc_Pair("\u1E9Cq",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Cp",(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Cq",(new sc_Pair((new sc_Pair("\u1E9Ct",null)),(new sc_Pair((new sc_Pair("\u1E9Cf",null)),null)))))))),(new sc_Pair((new sc_Pair("\u1E9Cf",null)),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair("\u1E9Cp",(new sc_Pair("\u1E9Cq",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Cp",(new sc_Pair((new sc_Pair("\u1E9Ct",null)),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Cq",(new sc_Pair((new sc_Pair("\u1E9Ct",null)),(new sc_Pair((new sc_Pair("\u1E9Cf",null)),null)))))))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair("\u1E9Cp",null)))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Cp",(new sc_Pair((new sc_Pair("\u1E9Cf",null)),(new sc_Pair((new sc_Pair("\u1E9Ct",null)),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cimplies",(new sc_Pair("\u1E9Cp",(new sc_Pair("\u1E9Cq",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Cp",(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Cq",(new sc_Pair((new sc_Pair("\u1E9Ct",null)),(new sc_Pair((new sc_Pair("\u1E9Cf",null)),null)))))))),(new sc_Pair((new sc_Pair("\u1E9Ct",null)),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Cnumberp",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",(new sc_Pair("\u1E9Cc",null)))))))),(new sc_Pair("\u1E9Cd",(new sc_Pair("\u1E9Ce",null)))))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Ca",(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Cb",(new sc_Pair("\u1E9Cd",(new sc_Pair("\u1E9Ce",null)))))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Cc",(new sc_Pair("\u1E9Cd",(new sc_Pair("\u1E9Ce",null)))))))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Cnumberp",(new sc_Pair("\u1E9Cx",null)))),null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Ca",null)))),(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cb",null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cx",null)))))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cc",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cb",null)))),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cc",null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cx",null)))))),null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cnumberp",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cy",null)))),null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cmeaning",(new sc_Pair((new sc_Pair("\u1E9Cplus-tree",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))),(new sc_Pair("\u1E9Ca",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair((new sc_Pair("\u1E9Cmeaning",(new sc_Pair((new sc_Pair("\u1E9Cplus-tree",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair("\u1E9Ca",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cmeaning",(new sc_Pair((new sc_Pair("\u1E9Cplus-tree",(new sc_Pair("\u1E9Cy",null)))),(new sc_Pair("\u1E9Ca",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cmeaning",(new sc_Pair((new sc_Pair("\u1E9Cplus-tree",(new sc_Pair((new sc_Pair("\u1E9Cplus-fringe",(new sc_Pair("\u1E9Cx",null)))),null)))),(new sc_Pair("\u1E9Ca",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair((new sc_Pair("\u1E9Cmeaning",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Ca",null)))))),null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Creverse",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair((new sc_Pair("\u1E9Creverse",(new sc_Pair("\u1E9Cb",null)))),(new sc_Pair((new sc_Pair("\u1E9Creverse",(new sc_Pair("\u1E9Ca",null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cz",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cy",null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cexec",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair("\u1E9Cpds",(new sc_Pair("\u1E9Cenvrn",null)))))))),(new sc_Pair((new sc_Pair("\u1E9Cexec",(new sc_Pair("\u1E9Cy",(new sc_Pair((new sc_Pair("\u1E9Cexec",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cpds",(new sc_Pair("\u1E9Cenvrn",null)))))))),(new sc_Pair("\u1E9Cenvrn",null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cmc-flatten",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair((new sc_Pair("\u1E9Cflatten",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair("\u1E9Cy",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Ca",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cb",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Creverse",(new sc_Pair("\u1E9Cy",null)))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clength",(new sc_Pair((new sc_Pair("\u1E9Creverse",(new sc_Pair("\u1E9Cx",null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Clength",(new sc_Pair("\u1E9Cx",null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Ca",(new sc_Pair((new sc_Pair("\u1E9Cintersect",(new sc_Pair("\u1E9Cb",(new sc_Pair("\u1E9Cc",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cc",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cnth",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),(new sc_Pair("\u1E9Ci",null)))))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cexp",(new sc_Pair("\u1E9Ci",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cj",(new sc_Pair("\u1E9Ck",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair((new sc_Pair("\u1E9Cexp",(new sc_Pair("\u1E9Ci",(new sc_Pair("\u1E9Cj",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cexp",(new sc_Pair("\u1E9Ci",(new sc_Pair("\u1E9Ck",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cexp",(new sc_Pair("\u1E9Ci",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cj",(new sc_Pair("\u1E9Ck",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cexp",(new sc_Pair((new sc_Pair("\u1E9Cexp",(new sc_Pair("\u1E9Ci",(new sc_Pair("\u1E9Cj",null)))))),(new sc_Pair("\u1E9Ck",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Creverse-loop",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair((new sc_Pair("\u1E9Creverse",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair("\u1E9Cy",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Creverse-loop",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cnil",null)),null)))))),(new sc_Pair((new sc_Pair("\u1E9Creverse",(new sc_Pair("\u1E9Cx",null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ccount-list",(new sc_Pair("\u1E9Cz",(new sc_Pair((new sc_Pair("\u1E9Csort-lp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair((new sc_Pair("\u1E9Ccount-list",(new sc_Pair("\u1E9Cz",(new sc_Pair("\u1E9Cx",null)))))),(new sc_Pair((new sc_Pair("\u1E9Ccount-list",(new sc_Pair("\u1E9Cz",(new sc_Pair("\u1E9Cy",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cc",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cb",(new sc_Pair("\u1E9Cc",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair((new sc_Pair("\u1E9Cremainder",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cy",(new sc_Pair((new sc_Pair("\u1E9Cquotient",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cx",null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cpower-eval",(new sc_Pair((new sc_Pair("\u1E9Cbig-plus1",(new sc_Pair("\u1E9Cl",(new sc_Pair("\u1E9Ci",(new sc_Pair("\u1E9Cbase",null)))))))),(new sc_Pair("\u1E9Cbase",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair((new sc_Pair("\u1E9Cpower-eval",(new sc_Pair("\u1E9Cl",(new sc_Pair("\u1E9Cbase",null)))))),(new sc_Pair("\u1E9Ci",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cpower-eval",(new sc_Pair((new sc_Pair("\u1E9Cbig-plus",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Ci",(new sc_Pair("\u1E9Cbase",null)))))))))),(new sc_Pair("\u1E9Cbase",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Ci",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair((new sc_Pair("\u1E9Cpower-eval",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cbase",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cpower-eval",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cbase",null)))))),null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cremainder",(new sc_Pair("\u1E9Cy",(new sc_Pair((1),null)))))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair((new sc_Pair("\u1E9Cremainder",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cy",null)))),null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cremainder",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cx",null)))))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair((new sc_Pair("\u1E9Cquotient",(new sc_Pair("\u1E9Ci",(new sc_Pair("\u1E9Cj",null)))))),(new sc_Pair("\u1E9Ci",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Ci",null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cj",null)))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cj",(new sc_Pair((1),null)))))),null)))),null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair((new sc_Pair("\u1E9Cremainder",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair("\u1E9Cx",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cy",null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cx",null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cpower-eval",(new sc_Pair((new sc_Pair("\u1E9Cpower-rep",(new sc_Pair("\u1E9Ci",(new sc_Pair("\u1E9Cbase",null)))))),(new sc_Pair("\u1E9Cbase",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Ci",null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cpower-eval",(new sc_Pair((new sc_Pair("\u1E9Cbig-plus",(new sc_Pair((new sc_Pair("\u1E9Cpower-rep",(new sc_Pair("\u1E9Ci",(new sc_Pair("\u1E9Cbase",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cpower-rep",(new sc_Pair("\u1E9Cj",(new sc_Pair("\u1E9Cbase",null)))))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),(new sc_Pair("\u1E9Cbase",null)))))))))),(new sc_Pair("\u1E9Cbase",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Ci",(new sc_Pair("\u1E9Cj",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cgcd",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cgcd",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cx",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cnth",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair("\u1E9Ci",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair((new sc_Pair("\u1E9Cnth",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Ci",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnth",(new sc_Pair("\u1E9Cb",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair("\u1E9Ci",(new sc_Pair((new sc_Pair("\u1E9Clength",(new sc_Pair("\u1E9Ca",null)))),null)))))),null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair("\u1E9Cx",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cy",null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cx",null)))))),(new sc_Pair("\u1E9Cx",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cy",null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cz",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair("\u1E9Cc",(new sc_Pair("\u1E9Cw",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cc",(new sc_Pair("\u1E9Cx",null)))))),(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cw",(new sc_Pair("\u1E9Cx",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cremainder",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cb",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cc",null)))))),null)))))),(new sc_Pair("\u1E9Ca",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cb",(new sc_Pair("\u1E9Cc",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair((new sc_Pair("\u1E9Cadd1",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),null)))),(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cadd1",(new sc_Pair("\u1E9Cy",null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cz",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cz",null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cy",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cx",null)))),null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cgcd",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cz",(new sc_Pair((new sc_Pair("\u1E9Cgcd",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cvalue",(new sc_Pair((new sc_Pair("\u1E9Cnormalize",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair("\u1E9Ca",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cvalue",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Ca",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cflatten",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair("\u1E9Cy",(new sc_Pair((new sc_Pair("\u1E9Cnil",null)),null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cnlistp",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clistp",(new sc_Pair((new sc_Pair("\u1E9Cgopher",(new sc_Pair("\u1E9Cx",null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Clistp",(new sc_Pair("\u1E9Cx",null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Csamefringe",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cflatten",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cflatten",(new sc_Pair("\u1E9Cy",null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cgreatest-factor",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cy",null)))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cy",(new sc_Pair((1),null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cgreatest-factor",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((1),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair((1),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cnumberp",(new sc_Pair((new sc_Pair("\u1E9Cgreatest-factor",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cy",null)))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cy",(new sc_Pair((1),null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Cnumberp",(new sc_Pair("\u1E9Cx",null)))),null)))),null)))))),null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ctimes-list",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair((new sc_Pair("\u1E9Ctimes-list",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Ctimes-list",(new sc_Pair("\u1E9Cy",null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cprime-list",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cprime-list",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cprime-list",(new sc_Pair("\u1E9Cy",null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cz",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cw",(new sc_Pair("\u1E9Cz",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cnumberp",(new sc_Pair("\u1E9Cz",null)))),(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cz",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cw",(new sc_Pair((1),null)))))),null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cgreatereqp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cnumberp",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cy",(new sc_Pair((1),null)))))),null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cremainder",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cx",null)))))),(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair((1),null)))))),(new sc_Pair(sc_list("\u1E9Cand", (new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Ca",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),null)))), (new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cb",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),null)))), (new sc_Pair("\u1E9Cnumberp",(new sc_Pair("\u1E9Ca",null)))), (new sc_Pair("\u1E9Cnumberp",(new sc_Pair("\u1E9Cb",null)))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Csub1",(new sc_Pair("\u1E9Ca",null)))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Csub1",(new sc_Pair("\u1E9Cb",null)))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair((new sc_Pair("\u1E9Clength",(new sc_Pair((new sc_Pair("\u1E9Cdelete",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cl",null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Clength",(new sc_Pair("\u1E9Cl",null)))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cl",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Csort2",(new sc_Pair((new sc_Pair("\u1E9Cdelete",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cl",null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cdelete",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Csort2",(new sc_Pair("\u1E9Cl",null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cdsort",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Csort2",(new sc_Pair("\u1E9Cx",null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clength",(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair("\u1E9Cx1",(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair("\u1E9Cx2",(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair("\u1E9Cx3",(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair("\u1E9Cx4",(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair("\u1E9Cx5",(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair("\u1E9Cx6",(new sc_Pair("\u1E9Cx7",null)))))),null)))))),null)))))),null)))))),null)))))),null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair((6),(new sc_Pair((new sc_Pair("\u1E9Clength",(new sc_Pair("\u1E9Cx7",null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair((new sc_Pair("\u1E9Cadd1",(new sc_Pair((new sc_Pair("\u1E9Cadd1",(new sc_Pair("\u1E9Cx",null)))),null)))),(new sc_Pair((2),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cx",null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cquotient",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),(new sc_Pair((2),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cquotient",(new sc_Pair("\u1E9Cy",(new sc_Pair((2),null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Csigma",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),(new sc_Pair("\u1E9Ci",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cquotient",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Ci",(new sc_Pair((new sc_Pair("\u1E9Cadd1",(new sc_Pair("\u1E9Ci",null)))),null)))))),(new sc_Pair((2),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cadd1",(new sc_Pair("\u1E9Cy",null)))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Cnumberp",(new sc_Pair("\u1E9Cy",null)))),(new sc_Pair((new sc_Pair("\u1E9Cadd1",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cadd1",(new sc_Pair("\u1E9Cx",null)))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair("\u1E9Cz",(new sc_Pair("\u1E9Cy",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cz",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cx",null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cz",null)))),null)))))),null)))))))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cmeaning",(new sc_Pair((new sc_Pair("\u1E9Cplus-tree",(new sc_Pair((new sc_Pair("\u1E9Cdelete",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))),(new sc_Pair("\u1E9Ca",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair((new sc_Pair("\u1E9Cmeaning",(new sc_Pair((new sc_Pair("\u1E9Cplus-tree",(new sc_Pair("\u1E9Cy",null)))),(new sc_Pair("\u1E9Ca",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cmeaning",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Ca",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cmeaning",(new sc_Pair((new sc_Pair("\u1E9Cplus-tree",(new sc_Pair("\u1E9Cy",null)))),(new sc_Pair("\u1E9Ca",null)))))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cadd1",(new sc_Pair("\u1E9Cy",null)))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Cnumberp",(new sc_Pair("\u1E9Cy",null)))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cx",null)))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cnth",(new sc_Pair((new sc_Pair("\u1E9Cnil",null)),(new sc_Pair("\u1E9Ci",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Ci",null)))),(new sc_Pair((new sc_Pair("\u1E9Cnil",null)),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clast",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Clistp",(new sc_Pair("\u1E9Cb",null)))),(new sc_Pair((new sc_Pair("\u1E9Clast",(new sc_Pair("\u1E9Cb",null)))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Clistp",(new sc_Pair("\u1E9Ca",null)))),(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair((new sc_Pair("\u1E9Ccar",(new sc_Pair((new sc_Pair("\u1E9Clast",(new sc_Pair("\u1E9Ca",null)))),null)))),(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair("\u1E9Cb",null)))))))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ct",null)),(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cf",null)),(new sc_Pair("\u1E9Cz",null)))))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cassignment",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Cassignedp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Ca",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cassignment",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Ca",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cassignment",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cb",null)))))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ccar",(new sc_Pair((new sc_Pair("\u1E9Cgopher",(new sc_Pair("\u1E9Cx",null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Clistp",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Ccar",(new sc_Pair((new sc_Pair("\u1E9Cflatten",(new sc_Pair("\u1E9Cx",null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cflatten",(new sc_Pair((new sc_Pair("\u1E9Ccdr",(new sc_Pair((new sc_Pair("\u1E9Cgopher",(new sc_Pair("\u1E9Cx",null)))),null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Clistp",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Ccdr",(new sc_Pair((new sc_Pair("\u1E9Cflatten",(new sc_Pair("\u1E9Cx",null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),(new sc_Pair((new sc_Pair("\u1E9Cnil",null)),null)))))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cquotient",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cx",null)))))),(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cy",null)))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cx",null)))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cget",(new sc_Pair("\u1E9Cj",(new sc_Pair((new sc_Pair("\u1E9Cset",(new sc_Pair("\u1E9Ci",(new sc_Pair("\u1E9Cval",(new sc_Pair("\u1E9Cmem",null)))))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Ceqp",(new sc_Pair("\u1E9Cj",(new sc_Pair("\u1E9Ci",null)))))),(new sc_Pair("\u1E9Cval",(new sc_Pair((new sc_Pair("\u1E9Cget",(new sc_Pair("\u1E9Cj",(new sc_Pair("\u1E9Cmem",null)))))),null)))))))),null))))))));
+    (const_nboyer = (new sc_Pair((new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cf",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cc",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cf",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cc",(new sc_Pair("\u1E9Cd",null)))))),null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cz",(new sc_Pair("\u1E9Cf",(new sc_Pair((new sc_Pair("\u1E9Creverse",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnil",null)),null)))))),null)))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cu",(new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))))),(new sc_Pair((new sc_Pair("\u1E9Cw",(new sc_Pair("\u1E9Clessp",(new sc_Pair((new sc_Pair("\u1E9Cremainder",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Ca",(new sc_Pair((new sc_Pair("\u1E9Clength",(new sc_Pair("\u1E9Cb",null)))),null)))))),null)))))))),null)))))))))));
+    BgL_nboyerzd2benchmarkzd2 = function() {
+        var args = null;
+        for (var sc_tmp = arguments.length - 1; sc_tmp >= 0; sc_tmp--) {
+            args = sc_cons(arguments[sc_tmp], args);
+        }
+        var n;
+        return ((n = ((args === null)?(0):(args.car))), (BgL_setupzd2boyerzd2()), (BgL_runzd2benchmarkzd2(("nboyer"+(sc_number2string(n))), (1), function() {
+            return (BgL_testzd2boyerzd2(n));
+        }, function(rewrites) {
+            if ((sc_isNumber(rewrites)))
+                switch (n) {
+                case (0):
+                    return (rewrites===(95024));
+                    break;
+                case (1):
+                    return (rewrites===(591777));
+                    break;
+                case (2):
+                    return (rewrites===(1813975));
+                    break;
+                case (3):
+                    return (rewrites===(5375678));
+                    break;
+                case (4):
+                    return (rewrites===(16445406));
+                    break;
+                case (5):
+                    return (rewrites===(51507739));
+                    break;
+                default:
+                    return true;
+                    break;
+                }
+            else
+                return false;
+        })));
+    };
+    BgL_setupzd2boyerzd2 = function() {
+        return true;
+    };
+    BgL_testzd2boyerzd2 = function() {
+        return true;
+    };
+    translate_term_nboyer = function(term) {
+        var lst;
+        return (!(term instanceof sc_Pair)?term:(new sc_Pair((BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer((term.car))), ((lst = (term.cdr)), ((lst === null)?null:(new sc_Pair((translate_term_nboyer((lst.car))), (translate_args_nboyer((lst.cdr))))))))));
+    };
+    translate_args_nboyer = function(lst) {
+        var sc_lst_5;
+        var term;
+        return ((lst === null)?null:(new sc_Pair(((term = (lst.car)), (!(term instanceof sc_Pair)?term:(new sc_Pair((BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer((term.car))), (translate_args_nboyer((term.cdr))))))), ((sc_lst_5 = (lst.cdr)), ((sc_lst_5 === null)?null:(new sc_Pair((translate_term_nboyer((sc_lst_5.car))), (translate_args_nboyer((sc_lst_5.cdr))))))))));
+    };
+    untranslate_term_nboyer = function(term) {
+        var optrOpnd;
+        var tail1131;
+        var L1127;
+        var falseHead1130;
+        var symbol_record;
+        if (!(term instanceof sc_Pair))
+            return term;
+        else
+            {
+                (falseHead1130 = (new sc_Pair(null, null)));
+                (L1127 = (term.cdr));
+                (tail1131 = falseHead1130);
+                while (!(L1127 === null)) {
+                    {
+                        (tail1131.cdr = (new sc_Pair((untranslate_term_nboyer((L1127.car))), null)));
+                        (tail1131 = (tail1131.cdr));
+                        (L1127 = (L1127.cdr));
+                    }
+                }
+                (optrOpnd = (falseHead1130.cdr));
+                return (new sc_Pair(((symbol_record = (term.car)), (symbol_record[(0)])), optrOpnd));
+            }
+    };
+    BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer = function(sym) {
+        var r;
+        var x;
+        return ((x = (sc_assq(sym, BgL_sc_za2symbolzd2recordszd2alistza2_2z00_nboyer))), ((x!== false)?(x.cdr):((r = [sym, null]), (BgL_sc_za2symbolzd2recordszd2alistza2_2z00_nboyer = (new sc_Pair((new sc_Pair(sym, r)), BgL_sc_za2symbolzd2recordszd2alistza2_2z00_nboyer))), r)));
+    };
+    (BgL_sc_za2symbolzd2recordszd2alistza2_2z00_nboyer = null);
+    translate_alist_nboyer = function(alist) {
+        var sc_alist_6;
+        var term;
+        return ((alist === null)?null:(new sc_Pair((new sc_Pair((alist.car.car), ((term = (alist.car.cdr)), (!(term instanceof sc_Pair)?term:(new sc_Pair((BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer((term.car))), (translate_args_nboyer((term.cdr))))))))), ((sc_alist_6 = (alist.cdr)), ((sc_alist_6 === null)?null:(new sc_Pair((new sc_Pair((sc_alist_6.car.car), (translate_term_nboyer((sc_alist_6.car.cdr))))), (translate_alist_nboyer((sc_alist_6.cdr))))))))));
+    };
+    apply_subst_nboyer = function(alist, term) {
+        var lst;
+        var temp_temp;
+        return (!(term instanceof sc_Pair)?((temp_temp = (sc_assq(term, alist))), ((temp_temp!== false)?(temp_temp.cdr):term)):(new sc_Pair((term.car), ((lst = (term.cdr)), ((lst === null)?null:(new sc_Pair((apply_subst_nboyer(alist, (lst.car))), (apply_subst_lst_nboyer(alist, (lst.cdr))))))))));
+    };
+    apply_subst_lst_nboyer = function(alist, lst) {
+        var sc_lst_7;
+        return ((lst === null)?null:(new sc_Pair((apply_subst_nboyer(alist, (lst.car))), ((sc_lst_7 = (lst.cdr)), ((sc_lst_7 === null)?null:(new sc_Pair((apply_subst_nboyer(alist, (sc_lst_7.car))), (apply_subst_lst_nboyer(alist, (sc_lst_7.cdr))))))))));
+    };
+    tautologyp_nboyer = function(sc_x_11, true_lst, false_lst) {
+        var tmp1125;
+        var x;
+        var tmp1126;
+        var sc_x_8;
+        var sc_tmp1125_9;
+        var sc_tmp1126_10;
+        var sc_x_11;
+        var true_lst;
+        var false_lst;
+        while (true) {
+            if ((((sc_tmp1126_10 = (is_term_equal_nboyer(sc_x_11, true_term_nboyer))), ((sc_tmp1126_10!== false)?sc_tmp1126_10:(is_term_member_nboyer(sc_x_11, true_lst))))!== false))
+                return true;
+            else
+                if ((((sc_tmp1125_9 = (is_term_equal_nboyer(sc_x_11, false_term_nboyer))), ((sc_tmp1125_9!== false)?sc_tmp1125_9:(is_term_member_nboyer(sc_x_11, false_lst))))!== false))
+                    return false;
+                else
+                    if (!(sc_x_11 instanceof sc_Pair))
+                        return false;
+                    else
+                        if (((sc_x_11.car)===if_constructor_nboyer))
+                            if ((((sc_x_8 = (sc_x_11.cdr.car)), (tmp1126 = (is_term_equal_nboyer(sc_x_8, true_term_nboyer))), ((tmp1126!== false)?tmp1126:(is_term_member_nboyer(sc_x_8, true_lst))))!== false))
+                                (sc_x_11 = (sc_x_11.cdr.cdr.car));
+                            else
+                                if ((((x = (sc_x_11.cdr.car)), (tmp1125 = (is_term_equal_nboyer(x, false_term_nboyer))), ((tmp1125!== false)?tmp1125:(is_term_member_nboyer(x, false_lst))))!== false))
+                                    (sc_x_11 = (sc_x_11.cdr.cdr.cdr.car));
+                                else
+                                    if (((tautologyp_nboyer((sc_x_11.cdr.cdr.car), (new sc_Pair((sc_x_11.cdr.car), true_lst)), false_lst))!== false))
+                                        {
+                                            (false_lst = (new sc_Pair((sc_x_11.cdr.car), false_lst)));
+                                            (sc_x_11 = (sc_x_11.cdr.cdr.cdr.car));
+                                        }
+                                    else
+                                        return false;
+                        else
+                            return false;
+        }
+    };
+    (if_constructor_nboyer = "\u1E9C*");
+    (rewrite_count_nboyer = (0));
+    rewrite_nboyer = function(term) {
+        var term2;
+        var sc_term_12;
+        var lst;
+        var symbol_record;
+        var sc_lst_13;
+        {
+            (++rewrite_count_nboyer);
+            if (!(term instanceof sc_Pair))
+                return term;
+            else
+                {
+                    (sc_term_12 = (new sc_Pair((term.car), ((sc_lst_13 = (term.cdr)), ((sc_lst_13 === null)?null:(new sc_Pair((rewrite_nboyer((sc_lst_13.car))), (rewrite_args_nboyer((sc_lst_13.cdr))))))))));
+                    (lst = ((symbol_record = (term.car)), (symbol_record[(1)])));
+                    while (true) {
+                        if ((lst === null))
+                            return sc_term_12;
+                        else
+                            if ((((term2 = ((lst.car).cdr.car)), (unify_subst_nboyer = null), (one_way_unify1_nboyer(sc_term_12, term2)))!== false))
+                                return (rewrite_nboyer((apply_subst_nboyer(unify_subst_nboyer, ((lst.car).cdr.cdr.car)))));
+                            else
+                                (lst = (lst.cdr));
+                    }
+                }
+        }
+    };
+    rewrite_args_nboyer = function(lst) {
+        var sc_lst_14;
+        return ((lst === null)?null:(new sc_Pair((rewrite_nboyer((lst.car))), ((sc_lst_14 = (lst.cdr)), ((sc_lst_14 === null)?null:(new sc_Pair((rewrite_nboyer((sc_lst_14.car))), (rewrite_args_nboyer((sc_lst_14.cdr))))))))));
+    };
+    (unify_subst_nboyer = "\u1E9C*");
+    one_way_unify1_nboyer = function(term1, term2) {
+        var lst1;
+        var lst2;
+        var temp_temp;
+        if (!(term2 instanceof sc_Pair))
+            {
+                (temp_temp = (sc_assq(term2, unify_subst_nboyer)));
+                if ((temp_temp!== false))
+                    return (is_term_equal_nboyer(term1, (temp_temp.cdr)));
+                else
+                    if ((sc_isNumber(term2)))
+                        return (sc_isEqual(term1, term2));
+                    else
+                        {
+                            (unify_subst_nboyer = (new sc_Pair((new sc_Pair(term2, term1)), unify_subst_nboyer)));
+                            return true;
+                        }
+            }
+        else
+            if (!(term1 instanceof sc_Pair))
+                return false;
+            else
+                if (((term1.car)===(term2.car)))
+                    {
+                        (lst1 = (term1.cdr));
+                        (lst2 = (term2.cdr));
+                        while (true) {
+                            if ((lst1 === null))
+                                return (lst2 === null);
+                            else
+                                if ((lst2 === null))
+                                    return false;
+                                else
+                                    if (((one_way_unify1_nboyer((lst1.car), (lst2.car)))!== false))
+                                        {
+                                            (lst1 = (lst1.cdr));
+                                            (lst2 = (lst2.cdr));
+                                        }
+                                    else
+                                        return false;
+                        }
+                    }
+                else
+                    return false;
+    };
+    (false_term_nboyer = "\u1E9C*");
+    (true_term_nboyer = "\u1E9C*");
+    trans_of_implies1_nboyer = function(n) {
+        var sc_n_15;
+        return ((sc_isEqual(n, (1)))?(sc_list("\u1E9Cimplies", (0), (1))):(sc_list("\u1E9Cand", (sc_list("\u1E9Cimplies", (n-(1)), n)), ((sc_n_15 = (n-(1))), ((sc_isEqual(sc_n_15, (1)))?(sc_list("\u1E9Cimplies", (0), (1))):(sc_list("\u1E9Cand", (sc_list("\u1E9Cimplies", (sc_n_15-(1)), sc_n_15)), (trans_of_implies1_nboyer((sc_n_15-(1)))))))))));
+    };
+    is_term_equal_nboyer = function(x, y) {
+        var lst1;
+        var lst2;
+        var r2;
+        var r1;
+        if ((x instanceof sc_Pair))
+            if ((y instanceof sc_Pair))
+                if ((((r1 = (x.car)), (r2 = (y.car)), (r1===r2))!== false))
+                    {
+                        (lst1 = (x.cdr));
+                        (lst2 = (y.cdr));
+                        while (true) {
+                            if ((lst1 === null))
+                                return (lst2 === null);
+                            else
+                                if ((lst2 === null))
+                                    return false;
+                                else
+                                    if (((is_term_equal_nboyer((lst1.car), (lst2.car)))!== false))
+                                        {
+                                            (lst1 = (lst1.cdr));
+                                            (lst2 = (lst2.cdr));
+                                        }
+                                    else
+                                        return false;
+                        }
+                    }
+                else
+                    return false;
+            else
+                return false;
+        else
+            return (sc_isEqual(x, y));
+    };
+    is_term_member_nboyer = function(x, lst) {
+        var x;
+        var lst;
+        while (true) {
+            if ((lst === null))
+                return false;
+            else
+                if (((is_term_equal_nboyer(x, (lst.car)))!== false))
+                    return true;
+                else
+                    (lst = (lst.cdr));
+        }
+    };
+    BgL_setupzd2boyerzd2 = function() {
+        var symbol_record;
+        var value;
+        var BgL_sc_symbolzd2record_16zd2;
+        var sym;
+        var sc_sym_17;
+        var term;
+        var lst;
+        var sc_term_18;
+        var sc_term_19;
+        {
+            (BgL_sc_za2symbolzd2recordszd2alistza2_2z00_nboyer = null);
+            (if_constructor_nboyer = (BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer("\u1E9Cif")));
+            (false_term_nboyer = ((sc_term_19 = (new sc_Pair("\u1E9Cf",null))), (!(sc_term_19 instanceof sc_Pair)?sc_term_19:(new sc_Pair((BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer((sc_term_19.car))), (translate_args_nboyer((sc_term_19.cdr))))))));
+            (true_term_nboyer = ((sc_term_18 = (new sc_Pair("\u1E9Ct",null))), (!(sc_term_18 instanceof sc_Pair)?sc_term_18:(new sc_Pair((BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer((sc_term_18.car))), (translate_args_nboyer((sc_term_18.cdr))))))));
+            (lst = sc_const_3_nboyer);
+            while (!(lst === null)) {
+                {
+                    (term = (lst.car));
+                    if (((term instanceof sc_Pair)&&(((term.car)==="\u1E9Cequal")&&((term.cdr.car) instanceof sc_Pair))))
+                        {
+                            (sc_sym_17 = ((term.cdr.car).car));
+                            (value = (new sc_Pair((!(term instanceof sc_Pair)?term:(new sc_Pair((BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer((term.car))), (translate_args_nboyer((term.cdr)))))), ((sym = ((term.cdr.car).car)), (BgL_sc_symbolzd2record_16zd2 = (BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer(sym))), (BgL_sc_symbolzd2record_16zd2[(1)])))));
+                            (symbol_record = (BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer(sc_sym_17)));
+                            (symbol_record[(1)] = value);
+                        }
+                    else
+                        (sc_error("ADD-LEMMA did not like term:  ", term));
+                    (lst = (lst.cdr));
+                }
+            }
+            return true;
+        }
+    };
+    BgL_testzd2boyerzd2 = function(n) {
+        var optrOpnd;
+        var term;
+        var sc_n_20;
+        var answer;
+        var sc_term_21;
+        var sc_term_22;
+        {
+            (rewrite_count_nboyer = (0));
+            (term = sc_const_4_nboyer);
+            (sc_n_20 = n);
+            while (!(sc_n_20=== 0)) {
+                {
+                    (term = (sc_list("\u1E9Cor", term, (new sc_Pair("\u1E9Cf",null)))));
+                    (--sc_n_20);
+                }
+            }
+            (sc_term_22 = term);
+            if (!(sc_term_22 instanceof sc_Pair))
+                (optrOpnd = sc_term_22);
+            else
+                (optrOpnd = (new sc_Pair((BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer((sc_term_22.car))), (translate_args_nboyer((sc_term_22.cdr))))));
+            (sc_term_21 = (apply_subst_nboyer(((const_nboyer === null)?null:(new sc_Pair((new sc_Pair((const_nboyer.car.car), (translate_term_nboyer((const_nboyer.car.cdr))))), (translate_alist_nboyer((const_nboyer.cdr)))))), optrOpnd)));
+            (answer = (tautologyp_nboyer((rewrite_nboyer(sc_term_21)), null, null)));
+            (sc_write(rewrite_count_nboyer));
+            (sc_display(" rewrites"));
+            (sc_newline());
+            if ((answer!== false))
+                return rewrite_count_nboyer;
+            else
+                return false;
+        }
+    };
+}
+/* Exported Variables */
+var BgL_parsezd2ze3nbzd2treesze3;
+var BgL_earleyzd2benchmarkzd2;
+var BgL_parsezd2ze3parsedzf3zc2;
+var test;
+var BgL_parsezd2ze3treesz31;
+var BgL_makezd2parserzd2;
+/* End Exports */
+
+var const_earley;
+{
+    (const_earley = (new sc_Pair((new sc_Pair("\u1E9Cs",(new sc_Pair((new sc_Pair("\u1E9Ca",null)),(new sc_Pair((new sc_Pair("\u1E9Cs",(new sc_Pair("\u1E9Cs",null)))),null)))))),null)));
+    BgL_makezd2parserzd2 = function(grammar, lexer) {
+        var i;
+        var parser_descr;
+        var def_loop;
+        var nb_nts;
+        var names;
+        var steps;
+        var predictors;
+        var enders;
+        var starters;
+        var nts;
+        var sc_names_1;
+        var sc_steps_2;
+        var sc_predictors_3;
+        var sc_enders_4;
+        var sc_starters_5;
+        var nb_confs;
+        var BgL_sc_defzd2loop_6zd2;
+        var BgL_sc_nbzd2nts_7zd2;
+        var sc_nts_8;
+        var BgL_sc_defzd2loop_9zd2;
+        var ind;
+        {
+            ind = function(nt, sc_nts_10) {
+                var i;
+                {
+                    (i = ((sc_nts_10.length)-(1)));
+                    while (true) {
+                        if ((i>=(0)))
+                            if ((sc_isEqual((sc_nts_10[i]), nt)))
+                                return i;
+                            else
+                                (--i);
+                        else
+                            return false;
+                    }
+                }
+            };
+            (sc_nts_8 = ((BgL_sc_defzd2loop_9zd2 = function(defs, sc_nts_11) {
+                var rule_loop;
+                var head;
+                var def;
+                return ((defs instanceof sc_Pair)?((def = (defs.car)), (head = (def.car)), (rule_loop = function(rules, sc_nts_12) {
+                    var nt;
+                    var l;
+                    var sc_nts_13;
+                    var rule;
+                    if ((rules instanceof sc_Pair))
+                        {
+                            (rule = (rules.car));
+                            (l = rule);
+                            (sc_nts_13 = sc_nts_12);
+                            while ((l instanceof sc_Pair)) {
+                                {
+                                    (nt = (l.car));
+                                    (l = (l.cdr));
+                                    (sc_nts_13 = (((sc_member(nt, sc_nts_13))!== false)?sc_nts_13:(new sc_Pair(nt, sc_nts_13))));
+                                }
+                            }
+                            return (rule_loop((rules.cdr), sc_nts_13));
+                        }
+                    else
+                        return (BgL_sc_defzd2loop_9zd2((defs.cdr), sc_nts_12));
+                }), (rule_loop((def.cdr), (((sc_member(head, sc_nts_11))!== false)?sc_nts_11:(new sc_Pair(head, sc_nts_11)))))):(sc_list2vector((sc_reverse(sc_nts_11)))));
+            }), (BgL_sc_defzd2loop_9zd2(grammar, null))));
+            (BgL_sc_nbzd2nts_7zd2 = (sc_nts_8.length));
+            (nb_confs = (((BgL_sc_defzd2loop_6zd2 = function(defs, BgL_sc_nbzd2confs_14zd2) {
+                var rule_loop;
+                var def;
+                return ((defs instanceof sc_Pair)?((def = (defs.car)), (rule_loop = function(rules, BgL_sc_nbzd2confs_15zd2) {
+                    var l;
+                    var BgL_sc_nbzd2confs_16zd2;
+                    var rule;
+                    if ((rules instanceof sc_Pair))
+                        {
+                            (rule = (rules.car));
+                            (l = rule);
+                            (BgL_sc_nbzd2confs_16zd2 = BgL_sc_nbzd2confs_15zd2);
+                            while ((l instanceof sc_Pair)) {
+                                {
+                                    (l = (l.cdr));
+                                    (++BgL_sc_nbzd2confs_16zd2);
+                                }
+                            }
+                            return (rule_loop((rules.cdr), (BgL_sc_nbzd2confs_16zd2+(1))));
+                        }
+                    else
+                        return (BgL_sc_defzd2loop_6zd2((defs.cdr), BgL_sc_nbzd2confs_15zd2));
+                }), (rule_loop((def.cdr), BgL_sc_nbzd2confs_14zd2))):BgL_sc_nbzd2confs_14zd2);
+            }), (BgL_sc_defzd2loop_6zd2(grammar, (0))))+BgL_sc_nbzd2nts_7zd2));
+            (sc_starters_5 = (sc_makeVector(BgL_sc_nbzd2nts_7zd2, null)));
+            (sc_enders_4 = (sc_makeVector(BgL_sc_nbzd2nts_7zd2, null)));
+            (sc_predictors_3 = (sc_makeVector(BgL_sc_nbzd2nts_7zd2, null)));
+            (sc_steps_2 = (sc_makeVector(nb_confs, false)));
+            (sc_names_1 = (sc_makeVector(nb_confs, false)));
+            (nts = sc_nts_8);
+            (starters = sc_starters_5);
+            (enders = sc_enders_4);
+            (predictors = sc_predictors_3);
+            (steps = sc_steps_2);
+            (names = sc_names_1);
+            (nb_nts = (sc_nts_8.length));
+            (i = (nb_nts-(1)));
+            while ((i>=(0))) {
+                {
+                    (sc_steps_2[i] = (i-nb_nts));
+                    (sc_names_1[i] = (sc_list((sc_nts_8[i]), (0))));
+                    (sc_enders_4[i] = (sc_list(i)));
+                    (--i);
+                }
+            }
+            def_loop = function(defs, conf) {
+                var rule_loop;
+                var head;
+                var def;
+                return ((defs instanceof sc_Pair)?((def = (defs.car)), (head = (def.car)), (rule_loop = function(rules, conf, rule_num) {
+                    var i;
+                    var sc_i_17;
+                    var nt;
+                    var l;
+                    var sc_conf_18;
+                    var sc_i_19;
+                    var rule;
+                    if ((rules instanceof sc_Pair))
+                        {
+                            (rule = (rules.car));
+                            (names[conf] = (sc_list(head, rule_num)));
+                            (sc_i_19 = (ind(head, nts)));
+                            (starters[sc_i_19] = (new sc_Pair(conf, (starters[sc_i_19]))));
+                            (l = rule);
+                            (sc_conf_18 = conf);
+                            while ((l instanceof sc_Pair)) {
+                                {
+                                    (nt = (l.car));
+                                    (steps[sc_conf_18] = (ind(nt, nts)));
+                                    (sc_i_17 = (ind(nt, nts)));
+                                    (predictors[sc_i_17] = (new sc_Pair(sc_conf_18, (predictors[sc_i_17]))));
+                                    (l = (l.cdr));
+                                    (++sc_conf_18);
+                                }
+                            }
+                            (steps[sc_conf_18] = ((ind(head, nts))-nb_nts));
+                            (i = (ind(head, nts)));
+                            (enders[i] = (new sc_Pair(sc_conf_18, (enders[i]))));
+                            return (rule_loop((rules.cdr), (sc_conf_18+(1)), (rule_num+(1))));
+                        }
+                    else
+                        return (def_loop((defs.cdr), conf));
+                }), (rule_loop((def.cdr), conf, (1)))):undefined);
+            };
+            (def_loop(grammar, (sc_nts_8.length)));
+            (parser_descr = [lexer, sc_nts_8, sc_starters_5, sc_enders_4, sc_predictors_3, sc_steps_2, sc_names_1]);
+            return function(input) {
+                var optrOpnd;
+                var sc_optrOpnd_20;
+                var sc_optrOpnd_21;
+                var sc_optrOpnd_22;
+                var loop1;
+                var BgL_sc_stateza2_23za2;
+                var toks;
+                var BgL_sc_nbzd2nts_24zd2;
+                var sc_steps_25;
+                var sc_enders_26;
+                var state_num;
+                var BgL_sc_statesza2_27za2;
+                var states;
+                var i;
+                var conf;
+                var l;
+                var tok_nts;
+                var sc_i_28;
+                var sc_i_29;
+                var l1;
+                var l2;
+                var tok;
+                var tail1129;
+                var L1125;
+                var goal_enders;
+                var BgL_sc_statesza2_30za2;
+                var BgL_sc_nbzd2nts_31zd2;
+                var BgL_sc_nbzd2confs_32zd2;
+                var nb_toks;
+                var goal_starters;
+                var sc_states_33;
+                var BgL_sc_nbzd2confs_34zd2;
+                var BgL_sc_nbzd2toks_35zd2;
+                var sc_toks_36;
+                var falseHead1128;
+                var sc_names_37;
+                var sc_steps_38;
+                var sc_predictors_39;
+                var sc_enders_40;
+                var sc_starters_41;
+                var sc_nts_42;
+                var lexer;
+                var sc_ind_43;
+                var make_states;
+                var BgL_sc_confzd2setzd2getza2_44za2;
+                var conf_set_merge_new_bang;
+                var conf_set_adjoin;
+                var BgL_sc_confzd2setzd2adjoinza2_45za2;
+                var BgL_sc_confzd2setzd2adjoinza2za2_46z00;
+                var conf_set_union;
+                var forw;
+                var is_parsed;
+                var deriv_trees;
+                var BgL_sc_derivzd2treesza2_47z70;
+                var nb_deriv_trees;
+                var BgL_sc_nbzd2derivzd2treesza2_48za2;
+                {
+                    sc_ind_43 = function(nt, sc_nts_49) {
+                        var i;
+                        {
+                            (i = ((sc_nts_49.length)-(1)));
+                            while (true) {
+                                if ((i>=(0)))
+                                    if ((sc_isEqual((sc_nts_49[i]), nt)))
+                                        return i;
+                                    else
+                                        (--i);
+                                else
+                                    return false;
+                            }
+                        }
+                    };
+                    make_states = function(BgL_sc_nbzd2toks_50zd2, BgL_sc_nbzd2confs_51zd2) {
+                        var v;
+                        var i;
+                        var sc_states_52;
+                        {
+                            (sc_states_52 = (sc_makeVector((BgL_sc_nbzd2toks_50zd2+(1)), false)));
+                            (i = BgL_sc_nbzd2toks_50zd2);
+                            while ((i>=(0))) {
+                                {
+                                    (v = (sc_makeVector((BgL_sc_nbzd2confs_51zd2+(1)), false)));
+                                    (v[(0)] = (-1));
+                                    (sc_states_52[i] = v);
+                                    (--i);
+                                }
+                            }
+                            return sc_states_52;
+                        }
+                    };
+                    BgL_sc_confzd2setzd2getza2_44za2 = function(state, BgL_sc_statezd2num_53zd2, sc_conf_54) {
+                        var conf_set;
+                        var BgL_sc_confzd2set_55zd2;
+                        return ((BgL_sc_confzd2set_55zd2 = (state[(sc_conf_54+(1))])), ((BgL_sc_confzd2set_55zd2!== false)?BgL_sc_confzd2set_55zd2:((conf_set = (sc_makeVector((BgL_sc_statezd2num_53zd2+(6)), false))), (conf_set[(1)] = (-3)), (conf_set[(2)] = (-1)), (conf_set[(3)] = (-1)), (conf_set[(4)] = (-1)), (state[(sc_conf_54+(1))] = conf_set), conf_set)));
+                    };
+                    conf_set_merge_new_bang = function(conf_set) {
+                        return ((conf_set[((conf_set[(1)])+(5))] = (conf_set[(4)])), (conf_set[(1)] = (conf_set[(3)])), (conf_set[(3)] = (-1)), (conf_set[(4)] = (-1)));
+                    };
+                    conf_set_adjoin = function(state, conf_set, sc_conf_56, i) {
+                        var tail;
+                        return ((tail = (conf_set[(3)])), (conf_set[(i+(5))] = (-1)), (conf_set[(tail+(5))] = i), (conf_set[(3)] = i), ((tail<(0))?((conf_set[(0)] = (state[(0)])), (state[(0)] = sc_conf_56)):undefined));
+                    };
+                    BgL_sc_confzd2setzd2adjoinza2_45za2 = function(sc_states_57, BgL_sc_statezd2num_58zd2, l, i) {
+                        var conf_set;
+                        var sc_conf_59;
+                        var l1;
+                        var state;
+                        {
+                            (state = (sc_states_57[BgL_sc_statezd2num_58zd2]));
+                            (l1 = l);
+                            while ((l1 instanceof sc_Pair)) {
+                                {
+                                    (sc_conf_59 = (l1.car));
+                                    (conf_set = (BgL_sc_confzd2setzd2getza2_44za2(state, BgL_sc_statezd2num_58zd2, sc_conf_59)));
+                                    if (((conf_set[(i+(5))])=== false))
+                                        {
+                                            (conf_set_adjoin(state, conf_set, sc_conf_59, i));
+                                            (l1 = (l1.cdr));
+                                        }
+                                    else
+                                        (l1 = (l1.cdr));
+                                }
+                            }
+                            return undefined;
+                        }
+                    };
+                    BgL_sc_confzd2setzd2adjoinza2za2_46z00 = function(sc_states_60, BgL_sc_statesza2_61za2, BgL_sc_statezd2num_62zd2, sc_conf_63, i) {
+                        var BgL_sc_confzd2setza2_64z70;
+                        var BgL_sc_stateza2_65za2;
+                        var conf_set;
+                        var state;
+                        return ((state = (sc_states_60[BgL_sc_statezd2num_62zd2])), ((((conf_set = (state[(sc_conf_63+(1))])), ((conf_set!== false)?(conf_set[(i+(5))]):false))!== false)?((BgL_sc_stateza2_65za2 = (BgL_sc_statesza2_61za2[BgL_sc_statezd2num_62zd2])), (BgL_sc_confzd2setza2_64z70 = (BgL_sc_confzd2setzd2getza2_44za2(BgL_sc_stateza2_65za2, BgL_sc_statezd2num_62zd2, sc_conf_63))), (((BgL_sc_confzd2setza2_64z70[(i+(5))])=== false)?(conf_set_adjoin(BgL_sc_stateza2_65za2, BgL_sc_confzd2setza2_64z70, sc_conf_63, i)):undefined), true):false));
+                    };
+                    conf_set_union = function(state, conf_set, sc_conf_66, other_set) {
+                        var i;
+                        {
+                            (i = (other_set[(2)]));
+                            while ((i>=(0))) {
+                                if (((conf_set[(i+(5))])=== false))
+                                    {
+                                        (conf_set_adjoin(state, conf_set, sc_conf_66, i));
+                                        (i = (other_set[(i+(5))]));
+                                    }
+                                else
+                                    (i = (other_set[(i+(5))]));
+                            }
+                            return undefined;
+                        }
+                    };
+                    forw = function(sc_states_67, BgL_sc_statezd2num_68zd2, sc_starters_69, sc_enders_70, sc_predictors_71, sc_steps_72, sc_nts_73) {
+                        var next_set;
+                        var next;
+                        var conf_set;
+                        var ender;
+                        var l;
+                        var starter_set;
+                        var starter;
+                        var sc_l_74;
+                        var sc_loop1_75;
+                        var head;
+                        var BgL_sc_confzd2set_76zd2;
+                        var BgL_sc_statezd2num_77zd2;
+                        var state;
+                        var sc_states_78;
+                        var preds;
+                        var BgL_sc_confzd2set_79zd2;
+                        var step;
+                        var sc_conf_80;
+                        var BgL_sc_nbzd2nts_81zd2;
+                        var sc_state_82;
+                        {
+                            (sc_state_82 = (sc_states_67[BgL_sc_statezd2num_68zd2]));
+                            (BgL_sc_nbzd2nts_81zd2 = (sc_nts_73.length));
+                            while (true) {
+                                {
+                                    (sc_conf_80 = (sc_state_82[(0)]));
+                                    if ((sc_conf_80>=(0)))
+                                        {
+                                            (step = (sc_steps_72[sc_conf_80]));
+                                            (BgL_sc_confzd2set_79zd2 = (sc_state_82[(sc_conf_80+(1))]));
+                                            (head = (BgL_sc_confzd2set_79zd2[(4)]));
+                                            (sc_state_82[(0)] = (BgL_sc_confzd2set_79zd2[(0)]));
+                                            (conf_set_merge_new_bang(BgL_sc_confzd2set_79zd2));
+                                            if ((step>=(0)))
+                                                {
+                                                    (sc_l_74 = (sc_starters_69[step]));
+                                                    while ((sc_l_74 instanceof sc_Pair)) {
+                                                        {
+                                                            (starter = (sc_l_74.car));
+                                                            (starter_set = (BgL_sc_confzd2setzd2getza2_44za2(sc_state_82, BgL_sc_statezd2num_68zd2, starter)));
+                                                            if (((starter_set[(BgL_sc_statezd2num_68zd2+(5))])=== false))
+                                                                {
+                                                                    (conf_set_adjoin(sc_state_82, starter_set, starter, BgL_sc_statezd2num_68zd2));
+                                                                    (sc_l_74 = (sc_l_74.cdr));
+                                                                }
+                                                            else
+                                                                (sc_l_74 = (sc_l_74.cdr));
+                                                        }
+                                                    }
+                                                    (l = (sc_enders_70[step]));
+                                                    while ((l instanceof sc_Pair)) {
+                                                        {
+                                                            (ender = (l.car));
+                                                            if ((((conf_set = (sc_state_82[(ender+(1))])), ((conf_set!== false)?(conf_set[(BgL_sc_statezd2num_68zd2+(5))]):false))!== false))
+                                                                {
+                                                                    (next = (sc_conf_80+(1)));
+                                                                    (next_set = (BgL_sc_confzd2setzd2getza2_44za2(sc_state_82, BgL_sc_statezd2num_68zd2, next)));
+                                                                    (conf_set_union(sc_state_82, next_set, next, BgL_sc_confzd2set_79zd2));
+                                                                    (l = (l.cdr));
+                                                                }
+                                                            else
+                                                                (l = (l.cdr));
+                                                        }
+                                                    }
+                                                }
+                                            else
+                                                {
+                                                    (preds = (sc_predictors_71[(step+BgL_sc_nbzd2nts_81zd2)]));
+                                                    (sc_states_78 = sc_states_67);
+                                                    (state = sc_state_82);
+                                                    (BgL_sc_statezd2num_77zd2 = BgL_sc_statezd2num_68zd2);
+                                                    (BgL_sc_confzd2set_76zd2 = BgL_sc_confzd2set_79zd2);
+                                                    sc_loop1_75 = function(l) {
+                                                        var sc_state_83;
+                                                        var BgL_sc_nextzd2set_84zd2;
+                                                        var sc_next_85;
+                                                        var pred_set;
+                                                        var i;
+                                                        var pred;
+                                                        if ((l instanceof sc_Pair))
+                                                            {
+                                                                (pred = (l.car));
+                                                                (i = head);
+                                                                while ((i>=(0))) {
+                                                                    {
+                                                                        (pred_set = ((sc_state_83 = (sc_states_78[i])), (sc_state_83[(pred+(1))])));
+                                                                        if ((pred_set!== false))
+                                                                            {
+                                                                                (sc_next_85 = (pred+(1)));
+                                                                                (BgL_sc_nextzd2set_84zd2 = (BgL_sc_confzd2setzd2getza2_44za2(state, BgL_sc_statezd2num_77zd2, sc_next_85)));
+                                                                                (conf_set_union(state, BgL_sc_nextzd2set_84zd2, sc_next_85, pred_set));
+                                                                            }
+                                                                        (i = (BgL_sc_confzd2set_76zd2[(i+(5))]));
+                                                                    }
+                                                                }
+                                                                return (sc_loop1_75((l.cdr)));
+                                                            }
+                                                        else
+                                                            return undefined;
+                                                    };
+                                                    (sc_loop1_75(preds));
+                                                }
+                                        }
+                                    else
+                                        return undefined;
+                                }
+                            }
+                        }
+                    };
+                    is_parsed = function(nt, i, j, sc_nts_86, sc_enders_87, sc_states_88) {
+                        var conf_set;
+                        var state;
+                        var sc_conf_89;
+                        var l;
+                        var BgL_sc_ntza2_90za2;
+                        {
+                            (BgL_sc_ntza2_90za2 = (sc_ind_43(nt, sc_nts_86)));
+                            if ((BgL_sc_ntza2_90za2!== false))
+                                {
+                                    (sc_nts_86.length);
+                                    (l = (sc_enders_87[BgL_sc_ntza2_90za2]));
+                                    while (true) {
+                                        if ((l instanceof sc_Pair))
+                                            {
+                                                (sc_conf_89 = (l.car));
+                                                if ((((state = (sc_states_88[j])), (conf_set = (state[(sc_conf_89+(1))])), ((conf_set!== false)?(conf_set[(i+(5))]):false))!== false))
+                                                    return true;
+                                                else
+                                                    (l = (l.cdr));
+                                            }
+                                        else
+                                            return false;
+                                    }
+                                }
+                            else
+                                return false;
+                        }
+                    };
+                    deriv_trees = function(sc_conf_91, i, j, sc_enders_92, sc_steps_93, sc_names_94, sc_toks_95, sc_states_96, BgL_sc_nbzd2nts_97zd2) {
+                        var sc_loop1_98;
+                        var prev;
+                        var name;
+                        return ((name = (sc_names_94[sc_conf_91])), ((name!== false)?((sc_conf_91<BgL_sc_nbzd2nts_97zd2)?(sc_list((sc_list(name, ((sc_toks_95[i]).car))))):(sc_list((sc_list(name))))):((prev = (sc_conf_91-(1))), (sc_loop1_98 = function(l1, l2) {
+                            var loop2;
+                            var ender_set;
+                            var state;
+                            var ender;
+                            var l1;
+                            var l2;
+                            while (true) {
+                                if ((l1 instanceof sc_Pair))
+                                    {
+                                        (ender = (l1.car));
+                                        (ender_set = ((state = (sc_states_96[j])), (state[(ender+(1))])));
+                                        if ((ender_set!== false))
+                                            {
+                                                loop2 = function(k, l2) {
+                                                    var loop3;
+                                                    var ender_trees;
+                                                    var prev_trees;
+                                                    var conf_set;
+                                                    var sc_state_99;
+                                                    var k;
+                                                    var l2;
+                                                    while (true) {
+                                                        if ((k>=(0)))
+                                                            if (((k>=i)&&(((sc_state_99 = (sc_states_96[k])), (conf_set = (sc_state_99[(prev+(1))])), ((conf_set!== false)?(conf_set[(i+(5))]):false))!== false)))
+                                                                {
+                                                                    (prev_trees = (deriv_trees(prev, i, k, sc_enders_92, sc_steps_93, sc_names_94, sc_toks_95, sc_states_96, BgL_sc_nbzd2nts_97zd2)));
+                                                                    (ender_trees = (deriv_trees(ender, k, j, sc_enders_92, sc_steps_93, sc_names_94, sc_toks_95, sc_states_96, BgL_sc_nbzd2nts_97zd2)));
+                                                                    loop3 = function(l3, l2) {
+                                                                        var l4;
+                                                                        var sc_l2_100;
+                                                                        var ender_tree;
+                                                                        if ((l3 instanceof sc_Pair))
+                                                                            {
+                                                                                (ender_tree = (sc_list((l3.car))));
+                                                                                (l4 = prev_trees);
+                                                                                (sc_l2_100 = l2);
+                                                                                while ((l4 instanceof sc_Pair)) {
+                                                                                    {
+                                                                                        (sc_l2_100 = (new sc_Pair((sc_append((l4.car), ender_tree)), sc_l2_100)));
+                                                                                        (l4 = (l4.cdr));
+                                                                                    }
+                                                                                }
+                                                                                return (loop3((l3.cdr), sc_l2_100));
+                                                                            }
+                                                                        else
+                                                                            return (loop2((ender_set[(k+(5))]), l2));
+                                                                    };
+                                                                    return (loop3(ender_trees, l2));
+                                                                }
+                                                            else
+                                                                (k = (ender_set[(k+(5))]));
+                                                        else
+                                                            return (sc_loop1_98((l1.cdr), l2));
+                                                    }
+                                                };
+                                                return (loop2((ender_set[(2)]), l2));
+                                            }
+                                        else
+                                            (l1 = (l1.cdr));
+                                    }
+                                else
+                                    return l2;
+                            }
+                        }), (sc_loop1_98((sc_enders_92[(sc_steps_93[prev])]), null)))));
+                    };
+                    BgL_sc_derivzd2treesza2_47z70 = function(nt, i, j, sc_nts_101, sc_enders_102, sc_steps_103, sc_names_104, sc_toks_105, sc_states_106) {
+                        var conf_set;
+                        var state;
+                        var sc_conf_107;
+                        var l;
+                        var trees;
+                        var BgL_sc_nbzd2nts_108zd2;
+                        var BgL_sc_ntza2_109za2;
+                        {
+                            (BgL_sc_ntza2_109za2 = (sc_ind_43(nt, sc_nts_101)));
+                            if ((BgL_sc_ntza2_109za2!== false))
+                                {
+                                    (BgL_sc_nbzd2nts_108zd2 = (sc_nts_101.length));
+                                    (l = (sc_enders_102[BgL_sc_ntza2_109za2]));
+                                    (trees = null);
+                                    while ((l instanceof sc_Pair)) {
+                                        {
+                                            (sc_conf_107 = (l.car));
+                                            if ((((state = (sc_states_106[j])), (conf_set = (state[(sc_conf_107+(1))])), ((conf_set!== false)?(conf_set[(i+(5))]):false))!== false))
+                                                {
+                                                    (l = (l.cdr));
+                                                    (trees = (sc_append((deriv_trees(sc_conf_107, i, j, sc_enders_102, sc_steps_103, sc_names_104, sc_toks_105, sc_states_106, BgL_sc_nbzd2nts_108zd2)), trees)));
+                                                }
+                                            else
+                                                (l = (l.cdr));
+                                        }
+                                    }
+                                    return trees;
+                                }
+                            else
+                                return false;
+                        }
+                    };
+                    nb_deriv_trees = function(sc_conf_110, i, j, sc_enders_111, sc_steps_112, sc_toks_113, sc_states_114, BgL_sc_nbzd2nts_115zd2) {
+                        var sc_loop1_116;
+                        var tmp1124;
+                        var prev;
+                        return ((prev = (sc_conf_110-(1))), ((((tmp1124 = (sc_conf_110<BgL_sc_nbzd2nts_115zd2)), ((tmp1124!== false)?tmp1124:((sc_steps_112[prev])<(0))))!== false)?(1):((sc_loop1_116 = function(l, sc_n_118) {
+                            var nb_ender_trees;
+                            var nb_prev_trees;
+                            var conf_set;
+                            var state;
+                            var k;
+                            var n;
+                            var ender_set;
+                            var sc_state_117;
+                            var ender;
+                            var l;
+                            var sc_n_118;
+                            while (true) {
+                                if ((l instanceof sc_Pair))
+                                    {
+                                        (ender = (l.car));
+                                        (ender_set = ((sc_state_117 = (sc_states_114[j])), (sc_state_117[(ender+(1))])));
+                                        if ((ender_set!== false))
+                                            {
+                                                (k = (ender_set[(2)]));
+                                                (n = sc_n_118);
+                                                while ((k>=(0))) {
+                                                    if (((k>=i)&&(((state = (sc_states_114[k])), (conf_set = (state[(prev+(1))])), ((conf_set!== false)?(conf_set[(i+(5))]):false))!== false)))
+                                                        {
+                                                            (nb_prev_trees = (nb_deriv_trees(prev, i, k, sc_enders_111, sc_steps_112, sc_toks_113, sc_states_114, BgL_sc_nbzd2nts_115zd2)));
+                                                            (nb_ender_trees = (nb_deriv_trees(ender, k, j, sc_enders_111, sc_steps_112, sc_toks_113, sc_states_114, BgL_sc_nbzd2nts_115zd2)));
+                                                            (k = (ender_set[(k+(5))]));
+                                                            (n +=(nb_prev_trees*nb_ender_trees));
+                                                        }
+                                                    else
+                                                        (k = (ender_set[(k+(5))]));
+                                                }
+                                                return (sc_loop1_116((l.cdr), n));
+                                            }
+                                        else
+                                            (l = (l.cdr));
+                                    }
+                                else
+                                    return sc_n_118;
+                            }
+                        }), (sc_loop1_116((sc_enders_111[(sc_steps_112[prev])]), (0))))));
+                    };
+                    BgL_sc_nbzd2derivzd2treesza2_48za2 = function(nt, i, j, sc_nts_119, sc_enders_120, sc_steps_121, sc_toks_122, sc_states_123) {
+                        var conf_set;
+                        var state;
+                        var sc_conf_124;
+                        var l;
+                        var nb_trees;
+                        var BgL_sc_nbzd2nts_125zd2;
+                        var BgL_sc_ntza2_126za2;
+                        {
+                            (BgL_sc_ntza2_126za2 = (sc_ind_43(nt, sc_nts_119)));
+                            if ((BgL_sc_ntza2_126za2!== false))
+                                {
+                                    (BgL_sc_nbzd2nts_125zd2 = (sc_nts_119.length));
+                                    (l = (sc_enders_120[BgL_sc_ntza2_126za2]));
+                                    (nb_trees = (0));
+                                    while ((l instanceof sc_Pair)) {
+                                        {
+                                            (sc_conf_124 = (l.car));
+                                            if ((((state = (sc_states_123[j])), (conf_set = (state[(sc_conf_124+(1))])), ((conf_set!== false)?(conf_set[(i+(5))]):false))!== false))
+                                                {
+                                                    (l = (l.cdr));
+                                                    (nb_trees = ((nb_deriv_trees(sc_conf_124, i, j, sc_enders_120, sc_steps_121, sc_toks_122, sc_states_123, BgL_sc_nbzd2nts_125zd2))+nb_trees));
+                                                }
+                                            else
+                                                (l = (l.cdr));
+                                        }
+                                    }
+                                    return nb_trees;
+                                }
+                            else
+                                return false;
+                        }
+                    };
+                    (lexer = (parser_descr[(0)]));
+                    (sc_nts_42 = (parser_descr[(1)]));
+                    (sc_starters_41 = (parser_descr[(2)]));
+                    (sc_enders_40 = (parser_descr[(3)]));
+                    (sc_predictors_39 = (parser_descr[(4)]));
+                    (sc_steps_38 = (parser_descr[(5)]));
+                    (sc_names_37 = (parser_descr[(6)]));
+                    (falseHead1128 = (new sc_Pair(null, null)));
+                    (L1125 = (lexer(input)));
+                    (tail1129 = falseHead1128);
+                    while (!(L1125 === null)) {
+                        {
+                            (tok = (L1125.car));
+                            (l1 = (tok.cdr));
+                            (l2 = null);
+                            while ((l1 instanceof sc_Pair)) {
+                                {
+                                    (sc_i_29 = (sc_ind_43((l1.car), sc_nts_42)));
+                                    if ((sc_i_29!== false))
+                                        {
+                                            (l1 = (l1.cdr));
+                                            (l2 = (new sc_Pair(sc_i_29, l2)));
+                                        }
+                                    else
+                                        (l1 = (l1.cdr));
+                                }
+                            }
+                            (sc_optrOpnd_22 = (new sc_Pair((tok.car), (sc_reverse(l2)))));
+                            (sc_optrOpnd_21 = (new sc_Pair(sc_optrOpnd_22, null)));
+                            (tail1129.cdr = sc_optrOpnd_21);
+                            (tail1129 = (tail1129.cdr));
+                            (L1125 = (L1125.cdr));
+                        }
+                    }
+                    (sc_optrOpnd_20 = (falseHead1128.cdr));
+                    (sc_toks_36 = (sc_list2vector(sc_optrOpnd_20)));
+                    (BgL_sc_nbzd2toks_35zd2 = (sc_toks_36.length));
+                    (BgL_sc_nbzd2confs_34zd2 = (sc_steps_38.length));
+                    (sc_states_33 = (make_states(BgL_sc_nbzd2toks_35zd2, BgL_sc_nbzd2confs_34zd2)));
+                    (goal_starters = (sc_starters_41[(0)]));
+                    (BgL_sc_confzd2setzd2adjoinza2_45za2(sc_states_33, (0), goal_starters, (0)));
+                    (forw(sc_states_33, (0), sc_starters_41, sc_enders_40, sc_predictors_39, sc_steps_38, sc_nts_42));
+                    (sc_i_28 = (0));
+                    while ((sc_i_28<BgL_sc_nbzd2toks_35zd2)) {
+                        {
+                            (tok_nts = ((sc_toks_36[sc_i_28]).cdr));
+                            (BgL_sc_confzd2setzd2adjoinza2_45za2(sc_states_33, (sc_i_28+(1)), tok_nts, sc_i_28));
+                            (forw(sc_states_33, (sc_i_28+(1)), sc_starters_41, sc_enders_40, sc_predictors_39, sc_steps_38, sc_nts_42));
+                            (++sc_i_28);
+                        }
+                    }
+                    (nb_toks = (sc_toks_36.length));
+                    (BgL_sc_nbzd2confs_32zd2 = (sc_steps_38.length));
+                    (BgL_sc_nbzd2nts_31zd2 = (sc_nts_42.length));
+                    (BgL_sc_statesza2_30za2 = (make_states(nb_toks, BgL_sc_nbzd2confs_32zd2)));
+                    (goal_enders = (sc_enders_40[(0)]));
+                    (l = goal_enders);
+                    while ((l instanceof sc_Pair)) {
+                        {
+                            (conf = (l.car));
+                            (BgL_sc_confzd2setzd2adjoinza2za2_46z00(sc_states_33, BgL_sc_statesza2_30za2, nb_toks, conf, (0)));
+                            (l = (l.cdr));
+                        }
+                    }
+                    (i = nb_toks);
+                    while ((i>=(0))) {
+                        {
+                            (states = sc_states_33);
+                            (BgL_sc_statesza2_27za2 = BgL_sc_statesza2_30za2);
+                            (state_num = i);
+                            (sc_enders_26 = sc_enders_40);
+                            (sc_steps_25 = sc_steps_38);
+                            (BgL_sc_nbzd2nts_24zd2 = BgL_sc_nbzd2nts_31zd2);
+                            (toks = sc_toks_36);
+                            (BgL_sc_stateza2_23za2 = (BgL_sc_statesza2_30za2[i]));
+                            loop1 = function() {
+                                var sc_loop1_127;
+                                var prev;
+                                var BgL_sc_statesza2_128za2;
+                                var sc_states_129;
+                                var j;
+                                var i;
+                                var sc_i_130;
+                                var head;
+                                var conf_set;
+                                var sc_conf_131;
+                                {
+                                    (sc_conf_131 = (BgL_sc_stateza2_23za2[(0)]));
+                                    if ((sc_conf_131>=(0)))
+                                        {
+                                            (conf_set = (BgL_sc_stateza2_23za2[(sc_conf_131+(1))]));
+                                            (head = (conf_set[(4)]));
+                                            (BgL_sc_stateza2_23za2[(0)] = (conf_set[(0)]));
+                                            (conf_set_merge_new_bang(conf_set));
+                                            (sc_i_130 = head);
+                                            while ((sc_i_130>=(0))) {
+                                                {
+                                                    (i = sc_i_130);
+                                                    (j = state_num);
+                                                    (sc_states_129 = states);
+                                                    (BgL_sc_statesza2_128za2 = BgL_sc_statesza2_27za2);
+                                                    (prev = (sc_conf_131-(1)));
+                                                    if (((sc_conf_131>=BgL_sc_nbzd2nts_24zd2)&&((sc_steps_25[prev])>=(0))))
+                                                        {
+                                                            sc_loop1_127 = function(l) {
+                                                                var k;
+                                                                var ender_set;
+                                                                var state;
+                                                                var ender;
+                                                                var l;
+                                                                while (true) {
+                                                                    if ((l instanceof sc_Pair))
+                                                                        {
+                                                                            (ender = (l.car));
+                                                                            (ender_set = ((state = (sc_states_129[j])), (state[(ender+(1))])));
+                                                                            if ((ender_set!== false))
+                                                                                {
+                                                                                    (k = (ender_set[(2)]));
+                                                                                    while ((k>=(0))) {
+                                                                                        {
+                                                                                            if ((k>=i))
+                                                                                                if (((BgL_sc_confzd2setzd2adjoinza2za2_46z00(sc_states_129, BgL_sc_statesza2_128za2, k, prev, i))!== false))
+                                                                                                    (BgL_sc_confzd2setzd2adjoinza2za2_46z00(sc_states_129, BgL_sc_statesza2_128za2, j, ender, k));
+                                                                                            (k = (ender_set[(k+(5))]));
+                                                                                        }
+                                                                                    }
+                                                                                    return (sc_loop1_127((l.cdr)));
+                                                                                }
+                                                                            else
+                                                                                (l = (l.cdr));
+                                                                        }
+                                                                    else
+                                                                        return undefined;
+                                                                }
+                                                            };
+                                                            (sc_loop1_127((sc_enders_26[(sc_steps_25[prev])])));
+                                                        }
+                                                    (sc_i_130 = (conf_set[(sc_i_130+(5))]));
+                                                }
+                                            }
+                                            return (loop1());
+                                        }
+                                    else
+                                        return undefined;
+                                }
+                            };
+                            (loop1());
+                            (--i);
+                        }
+                    }
+                    (optrOpnd = BgL_sc_statesza2_30za2);
+                    return [sc_nts_42, sc_starters_41, sc_enders_40, sc_predictors_39, sc_steps_38, sc_names_37, sc_toks_36, optrOpnd, is_parsed, BgL_sc_derivzd2treesza2_47z70, BgL_sc_nbzd2derivzd2treesza2_48za2];
+                }
+            };
+        }
+    };
+    BgL_parsezd2ze3parsedzf3zc2 = function(parse, nt, i, j) {
+        var is_parsed;
+        var states;
+        var enders;
+        var nts;
+        return ((nts = (parse[(0)])), (enders = (parse[(2)])), (states = (parse[(7)])), (is_parsed = (parse[(8)])), (is_parsed(nt, i, j, nts, enders, states)));
+    };
+    BgL_parsezd2ze3treesz31 = function(parse, nt, i, j) {
+        var BgL_sc_derivzd2treesza2_132z70;
+        var states;
+        var toks;
+        var names;
+        var steps;
+        var enders;
+        var nts;
+        return ((nts = (parse[(0)])), (enders = (parse[(2)])), (steps = (parse[(4)])), (names = (parse[(5)])), (toks = (parse[(6)])), (states = (parse[(7)])), (BgL_sc_derivzd2treesza2_132z70 = (parse[(9)])), (BgL_sc_derivzd2treesza2_132z70(nt, i, j, nts, enders, steps, names, toks, states)));
+    };
+    BgL_parsezd2ze3nbzd2treesze3 = function(parse, nt, i, j) {
+        var BgL_sc_nbzd2derivzd2treesza2_133za2;
+        var states;
+        var toks;
+        var steps;
+        var enders;
+        var nts;
+        return ((nts = (parse[(0)])), (enders = (parse[(2)])), (steps = (parse[(4)])), (toks = (parse[(6)])), (states = (parse[(7)])), (BgL_sc_nbzd2derivzd2treesza2_133za2 = (parse[(10)])), (BgL_sc_nbzd2derivzd2treesza2_133za2(nt, i, j, nts, enders, steps, toks, states)));
+    };
+    test = function(k) {
+        var x;
+        var p;
+        return ((p = (BgL_makezd2parserzd2(const_earley, function(l) {
+            var sc_x_134;
+            var tail1134;
+            var L1130;
+            var falseHead1133;
+            {
+                (falseHead1133 = (new sc_Pair(null, null)));
+                (tail1134 = falseHead1133);
+                (L1130 = l);
+                while (!(L1130 === null)) {
+                    {
+                        (tail1134.cdr = (new sc_Pair(((sc_x_134 = (L1130.car)), (sc_list(sc_x_134, sc_x_134))), null)));
+                        (tail1134 = (tail1134.cdr));
+                        (L1130 = (L1130.cdr));
+                    }
+                }
+                return (falseHead1133.cdr);
+            }
+        }))), (x = (p((sc_vector2list((sc_makeVector(k, "\u1E9Ca"))))))), (sc_length((BgL_parsezd2ze3treesz31(x, "\u1E9Cs", (0), k)))));
+    };
+    BgL_earleyzd2benchmarkzd2 = function() {
+        var args = null;
+        for (var sc_tmp = arguments.length - 1; sc_tmp >= 0; sc_tmp--) {
+            args = sc_cons(arguments[sc_tmp], args);
+        }
+        var k;
+        return ((k = ((args === null)?(7):(args.car))), (BgL_runzd2benchmarkzd2("earley", (1), function() {
+            return (test(k));
+        }, function(result) {
+            return ((sc_display(result)), (sc_newline()), result == 132);
+        })));
+    };
+}
+
+
+/************* END OF GENERATED CODE *************/
+// Invoke this function to run a benchmark.
+// The first argument is a string identifying the benchmark.
+// The second argument is the number of times to run the benchmark.
+// The third argument is a function that runs the benchmark.
+// The fourth argument is a unary function that warns if the result
+// returned by the benchmark is incorrect.
+//
+// Example:
+// RunBenchmark("new Array()",
+//              1,
+//              function () { new Array(1000000); }
+//              function (v) {
+//                return (v instanceof Array) && (v.length == 1000000);
+//              });
+
+SC_DEFAULT_OUT = new sc_GenericOutputPort(function(s) {});
+SC_ERROR_OUT = SC_DEFAULT_OUT;
+
+function RunBenchmark(name, count, run, warn) {
+  for (var n = 0; n < count; ++n) {
+    result = run();
+    if (!warn(result)) {
+      throw new Error("Earley or Boyer did incorrect number of rewrites");
+    }
+  }
+}
+
+var BgL_runzd2benchmarkzd2 = RunBenchmark;
+
diff --git a/deps/v8/benchmarks/raytrace.js b/deps/v8/benchmarks/raytrace.js
new file mode 100644
index 0000000..925d0ed
--- /dev/null
+++ b/deps/v8/benchmarks/raytrace.js
@@ -0,0 +1,3434 @@
+// The ray tracer code in this file is written by Adam Burmister. It
+// is available in its original form from:
+//
+//   http://labs.flog.nz.co/raytracer/
+//
+// It has been modified slightly by Google to work as a standalone
+// benchmark, but the all the computational code remains
+// untouched. This file also contains a copy of the Prototype
+// JavaScript framework which is used by the ray tracer.
+
+var RayTrace = new BenchmarkSuite('RayTrace', 932666, [
+  new Benchmark('RayTrace', renderScene)
+]);
+
+
+var checkNumber;
+
+// Create dummy objects if we're not running in a browser.
+if (typeof document == 'undefined') {
+  document = { };
+  window = { opera: null };
+  navigator = { userAgent: null, appVersion: "" };
+}
+
+
+// ------------------------------------------------------------------------
+// ------------------------------------------------------------------------
+
+
+/*  Prototype JavaScript framework, version 1.5.0
+ *  (c) 2005-2007 Sam Stephenson
+ *
+ *  Prototype is freely distributable under the terms of an MIT-style license.
+ *  For details, see the Prototype web site: http://prototype.conio.net/
+ *
+/*--------------------------------------------------------------------------*/
+
+//--------------------
+var Prototype = {
+  Version: '1.5.0',
+  BrowserFeatures: {
+    XPath: !!document.evaluate
+  },
+
+  ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
+  emptyFunction: function() {},
+  K: function(x) { return x }
+}
+
+var Class = {
+  create: function() {
+    return function() {
+      this.initialize.apply(this, arguments);
+    }
+  }
+}
+
+var Abstract = new Object();
+
+Object.extend = function(destination, source) {
+  for (var property in source) {
+    destination[property] = source[property];
+  }
+  return destination;
+}
+
+Object.extend(Object, {
+  inspect: function(object) {
+    try {
+      if (object === undefined) return 'undefined';
+      if (object === null) return 'null';
+      return object.inspect ? object.inspect() : object.toString();
+    } catch (e) {
+      if (e instanceof RangeError) return '...';
+      throw e;
+    }
+  },
+
+  keys: function(object) {
+    var keys = [];
+    for (var property in object)
+      keys.push(property);
+    return keys;
+  },
+
+  values: function(object) {
+    var values = [];
+    for (var property in object)
+      values.push(object[property]);
+    return values;
+  },
+
+  clone: function(object) {
+    return Object.extend({}, object);
+  }
+});
+
+Function.prototype.bind = function() {
+  var __method = this, args = $A(arguments), object = args.shift();
+  return function() {
+    return __method.apply(object, args.concat($A(arguments)));
+  }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+  var __method = this, args = $A(arguments), object = args.shift();
+  return function(event) {
+    return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments)));
+  }
+}
+
+Object.extend(Number.prototype, {
+  toColorPart: function() {
+    var digits = this.toString(16);
+    if (this < 16) return '0' + digits;
+    return digits;
+  },
+
+  succ: function() {
+    return this + 1;
+  },
+
+  times: function(iterator) {
+    $R(0, this, true).each(iterator);
+    return this;
+  }
+});
+
+var Try = {
+  these: function() {
+    var returnValue;
+
+    for (var i = 0, length = arguments.length; i < length; i++) {
+      var lambda = arguments[i];
+      try {
+        returnValue = lambda();
+        break;
+      } catch (e) {}
+    }
+
+    return returnValue;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create();
+PeriodicalExecuter.prototype = {
+  initialize: function(callback, frequency) {
+    this.callback = callback;
+    this.frequency = frequency;
+    this.currentlyExecuting = false;
+
+    this.registerCallback();
+  },
+
+  registerCallback: function() {
+    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+  },
+
+  stop: function() {
+    if (!this.timer) return;
+    clearInterval(this.timer);
+    this.timer = null;
+  },
+
+  onTimerEvent: function() {
+    if (!this.currentlyExecuting) {
+      try {
+        this.currentlyExecuting = true;
+        this.callback(this);
+      } finally {
+        this.currentlyExecuting = false;
+      }
+    }
+  }
+}
+String.interpret = function(value){
+  return value == null ? '' : String(value);
+}
+
+Object.extend(String.prototype, {
+  gsub: function(pattern, replacement) {
+    var result = '', source = this, match;
+    replacement = arguments.callee.prepareReplacement(replacement);
+
+    while (source.length > 0) {
+      if (match = source.match(pattern)) {
+        result += source.slice(0, match.index);
+        result += String.interpret(replacement(match));
+        source  = source.slice(match.index + match[0].length);
+      } else {
+        result += source, source = '';
+      }
+    }
+    return result;
+  },
+
+  sub: function(pattern, replacement, count) {
+    replacement = this.gsub.prepareReplacement(replacement);
+    count = count === undefined ? 1 : count;
+
+    return this.gsub(pattern, function(match) {
+      if (--count < 0) return match[0];
+      return replacement(match);
+    });
+  },
+
+  scan: function(pattern, iterator) {
+    this.gsub(pattern, iterator);
+    return this;
+  },
+
+  truncate: function(length, truncation) {
+    length = length || 30;
+    truncation = truncation === undefined ? '...' : truncation;
+    return this.length > length ?
+      this.slice(0, length - truncation.length) + truncation : this;
+  },
+
+  strip: function() {
+    return this.replace(/^\s+/, '').replace(/\s+$/, '');
+  },
+
+  stripTags: function() {
+    return this.replace(/<\/?[^>]+>/gi, '');
+  },
+
+  stripScripts: function() {
+    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+  },
+
+  extractScripts: function() {
+    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+    return (this.match(matchAll) || []).map(function(scriptTag) {
+      return (scriptTag.match(matchOne) || ['', ''])[1];
+    });
+  },
+
+  evalScripts: function() {
+    return this.extractScripts().map(function(script) { return eval(script) });
+  },
+
+  escapeHTML: function() {
+    var div = document.createElement('div');
+    var text = document.createTextNode(this);
+    div.appendChild(text);
+    return div.innerHTML;
+  },
+
+  unescapeHTML: function() {
+    var div = document.createElement('div');
+    div.innerHTML = this.stripTags();
+    return div.childNodes[0] ? (div.childNodes.length > 1 ?
+      $A(div.childNodes).inject('',function(memo,node){ return memo+node.nodeValue }) :
+      div.childNodes[0].nodeValue) : '';
+  },
+
+  toQueryParams: function(separator) {
+    var match = this.strip().match(/([^?#]*)(#.*)?$/);
+    if (!match) return {};
+
+    return match[1].split(separator || '&').inject({}, function(hash, pair) {
+      if ((pair = pair.split('='))[0]) {
+        var name = decodeURIComponent(pair[0]);
+        var value = pair[1] ? decodeURIComponent(pair[1]) : undefined;
+
+        if (hash[name] !== undefined) {
+          if (hash[name].constructor != Array)
+            hash[name] = [hash[name]];
+          if (value) hash[name].push(value);
+        }
+        else hash[name] = value;
+      }
+      return hash;
+    });
+  },
+
+  toArray: function() {
+    return this.split('');
+  },
+
+  succ: function() {
+    return this.slice(0, this.length - 1) +
+      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+  },
+
+  camelize: function() {
+    var parts = this.split('-'), len = parts.length;
+    if (len == 1) return parts[0];
+
+    var camelized = this.charAt(0) == '-'
+      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+      : parts[0];
+
+    for (var i = 1; i < len; i++)
+      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+    return camelized;
+  },
+
+  capitalize: function(){
+    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+  },
+
+  underscore: function() {
+    return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+  },
+
+  dasherize: function() {
+    return this.gsub(/_/,'-');
+  },
+
+  inspect: function(useDoubleQuotes) {
+    var escapedString = this.replace(/\\/g, '\\\\');
+    if (useDoubleQuotes)
+      return '"' + escapedString.replace(/"/g, '\\"') + '"';
+    else
+      return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+  }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+  if (typeof replacement == 'function') return replacement;
+  var template = new Template(replacement);
+  return function(match) { return template.evaluate(match) };
+}
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+var Template = Class.create();
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+Template.prototype = {
+  initialize: function(template, pattern) {
+    this.template = template.toString();
+    this.pattern  = pattern || Template.Pattern;
+  },
+
+  evaluate: function(object) {
+    return this.template.gsub(this.pattern, function(match) {
+      var before = match[1];
+      if (before == '\\') return match[2];
+      return before + String.interpret(object[match[3]]);
+    });
+  }
+}
+
+var $break    = new Object();
+var $continue = new Object();
+
+var Enumerable = {
+  each: function(iterator) {
+    var index = 0;
+    try {
+      this._each(function(value) {
+        try {
+          iterator(value, index++);
+        } catch (e) {
+          if (e != $continue) throw e;
+        }
+      });
+    } catch (e) {
+      if (e != $break) throw e;
+    }
+    return this;
+  },
+
+  eachSlice: function(number, iterator) {
+    var index = -number, slices = [], array = this.toArray();
+    while ((index += number) < array.length)
+      slices.push(array.slice(index, index+number));
+    return slices.map(iterator);
+  },
+
+  all: function(iterator) {
+    var result = true;
+    this.each(function(value, index) {
+      result = result && !!(iterator || Prototype.K)(value, index);
+      if (!result) throw $break;
+    });
+    return result;
+  },
+
+  any: function(iterator) {
+    var result = false;
+    this.each(function(value, index) {
+      if (result = !!(iterator || Prototype.K)(value, index))
+        throw $break;
+    });
+    return result;
+  },
+
+  collect: function(iterator) {
+    var results = [];
+    this.each(function(value, index) {
+      results.push((iterator || Prototype.K)(value, index));
+    });
+    return results;
+  },
+
+  detect: function(iterator) {
+    var result;
+    this.each(function(value, index) {
+      if (iterator(value, index)) {
+        result = value;
+        throw $break;
+      }
+    });
+    return result;
+  },
+
+  findAll: function(iterator) {
+    var results = [];
+    this.each(function(value, index) {
+      if (iterator(value, index))
+        results.push(value);
+    });
+    return results;
+  },
+
+  grep: function(pattern, iterator) {
+    var results = [];
+    this.each(function(value, index) {
+      var stringValue = value.toString();
+      if (stringValue.match(pattern))
+        results.push((iterator || Prototype.K)(value, index));
+    })
+    return results;
+  },
+
+  include: function(object) {
+    var found = false;
+    this.each(function(value) {
+      if (value == object) {
+        found = true;
+        throw $break;
+      }
+    });
+    return found;
+  },
+
+  inGroupsOf: function(number, fillWith) {
+    fillWith = fillWith === undefined ? null : fillWith;
+    return this.eachSlice(number, function(slice) {
+      while(slice.length < number) slice.push(fillWith);
+      return slice;
+    });
+  },
+
+  inject: function(memo, iterator) {
+    this.each(function(value, index) {
+      memo = iterator(memo, value, index);
+    });
+    return memo;
+  },
+
+  invoke: function(method) {
+    var args = $A(arguments).slice(1);
+    return this.map(function(value) {
+      return value[method].apply(value, args);
+    });
+  },
+
+  max: function(iterator) {
+    var result;
+    this.each(function(value, index) {
+      value = (iterator || Prototype.K)(value, index);
+      if (result == undefined || value >= result)
+        result = value;
+    });
+    return result;
+  },
+
+  min: function(iterator) {
+    var result;
+    this.each(function(value, index) {
+      value = (iterator || Prototype.K)(value, index);
+      if (result == undefined || value < result)
+        result = value;
+    });
+    return result;
+  },
+
+  partition: function(iterator) {
+    var trues = [], falses = [];
+    this.each(function(value, index) {
+      ((iterator || Prototype.K)(value, index) ?
+        trues : falses).push(value);
+    });
+    return [trues, falses];
+  },
+
+  pluck: function(property) {
+    var results = [];
+    this.each(function(value, index) {
+      results.push(value[property]);
+    });
+    return results;
+  },
+
+  reject: function(iterator) {
+    var results = [];
+    this.each(function(value, index) {
+      if (!iterator(value, index))
+        results.push(value);
+    });
+    return results;
+  },
+
+  sortBy: function(iterator) {
+    return this.map(function(value, index) {
+      return {value: value, criteria: iterator(value, index)};
+    }).sort(function(left, right) {
+      var a = left.criteria, b = right.criteria;
+      return a < b ? -1 : a > b ? 1 : 0;
+    }).pluck('value');
+  },
+
+  toArray: function() {
+    return this.map();
+  },
+
+  zip: function() {
+    var iterator = Prototype.K, args = $A(arguments);
+    if (typeof args.last() == 'function')
+      iterator = args.pop();
+
+    var collections = [this].concat(args).map($A);
+    return this.map(function(value, index) {
+      return iterator(collections.pluck(index));
+    });
+  },
+
+  size: function() {
+    return this.toArray().length;
+  },
+
+  inspect: function() {
+    return '#<Enumerable:' + this.toArray().inspect() + '>';
+  }
+}
+
+Object.extend(Enumerable, {
+  map:     Enumerable.collect,
+  find:    Enumerable.detect,
+  select:  Enumerable.findAll,
+  member:  Enumerable.include,
+  entries: Enumerable.toArray
+});
+var $A = Array.from = function(iterable) {
+  if (!iterable) return [];
+  if (iterable.toArray) {
+    return iterable.toArray();
+  } else {
+    var results = [];
+    for (var i = 0, length = iterable.length; i < length; i++)
+      results.push(iterable[i]);
+    return results;
+  }
+}
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse)
+  Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+  _each: function(iterator) {
+    for (var i = 0, length = this.length; i < length; i++)
+      iterator(this[i]);
+  },
+
+  clear: function() {
+    this.length = 0;
+    return this;
+  },
+
+  first: function() {
+    return this[0];
+  },
+
+  last: function() {
+    return this[this.length - 1];
+  },
+
+  compact: function() {
+    return this.select(function(value) {
+      return value != null;
+    });
+  },
+
+  flatten: function() {
+    return this.inject([], function(array, value) {
+      return array.concat(value && value.constructor == Array ?
+        value.flatten() : [value]);
+    });
+  },
+
+  without: function() {
+    var values = $A(arguments);
+    return this.select(function(value) {
+      return !values.include(value);
+    });
+  },
+
+  indexOf: function(object) {
+    for (var i = 0, length = this.length; i < length; i++)
+      if (this[i] == object) return i;
+    return -1;
+  },
+
+  reverse: function(inline) {
+    return (inline !== false ? this : this.toArray())._reverse();
+  },
+
+  reduce: function() {
+    return this.length > 1 ? this : this[0];
+  },
+
+  uniq: function() {
+    return this.inject([], function(array, value) {
+      return array.include(value) ? array : array.concat([value]);
+    });
+  },
+
+  clone: function() {
+    return [].concat(this);
+  },
+
+  size: function() {
+    return this.length;
+  },
+
+  inspect: function() {
+    return '[' + this.map(Object.inspect).join(', ') + ']';
+  }
+});
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string){
+  string = string.strip();
+  return string ? string.split(/\s+/) : [];
+}
+
+if(window.opera){
+  Array.prototype.concat = function(){
+    var array = [];
+    for(var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+    for(var i = 0, length = arguments.length; i < length; i++) {
+      if(arguments[i].constructor == Array) {
+        for(var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+          array.push(arguments[i][j]);
+      } else {
+        array.push(arguments[i]);
+      }
+    }
+    return array;
+  }
+}
+var Hash = function(obj) {
+  Object.extend(this, obj || {});
+};
+
+Object.extend(Hash, {
+  toQueryString: function(obj) {
+    var parts = [];
+
+	  this.prototype._each.call(obj, function(pair) {
+      if (!pair.key) return;
+
+      if (pair.value && pair.value.constructor == Array) {
+        var values = pair.value.compact();
+        if (values.length < 2) pair.value = values.reduce();
+        else {
+        	key = encodeURIComponent(pair.key);
+          values.each(function(value) {
+            value = value != undefined ? encodeURIComponent(value) : '';
+            parts.push(key + '=' + encodeURIComponent(value));
+          });
+          return;
+        }
+      }
+      if (pair.value == undefined) pair[1] = '';
+      parts.push(pair.map(encodeURIComponent).join('='));
+	  });
+
+    return parts.join('&');
+  }
+});
+
+Object.extend(Hash.prototype, Enumerable);
+Object.extend(Hash.prototype, {
+  _each: function(iterator) {
+    for (var key in this) {
+      var value = this[key];
+      if (value && value == Hash.prototype[key]) continue;
+
+      var pair = [key, value];
+      pair.key = key;
+      pair.value = value;
+      iterator(pair);
+    }
+  },
+
+  keys: function() {
+    return this.pluck('key');
+  },
+
+  values: function() {
+    return this.pluck('value');
+  },
+
+  merge: function(hash) {
+    return $H(hash).inject(this, function(mergedHash, pair) {
+      mergedHash[pair.key] = pair.value;
+      return mergedHash;
+    });
+  },
+
+  remove: function() {
+    var result;
+    for(var i = 0, length = arguments.length; i < length; i++) {
+      var value = this[arguments[i]];
+      if (value !== undefined){
+        if (result === undefined) result = value;
+        else {
+          if (result.constructor != Array) result = [result];
+          result.push(value)
+        }
+      }
+      delete this[arguments[i]];
+    }
+    return result;
+  },
+
+  toQueryString: function() {
+    return Hash.toQueryString(this);
+  },
+
+  inspect: function() {
+    return '#<Hash:{' + this.map(function(pair) {
+      return pair.map(Object.inspect).join(': ');
+    }).join(', ') + '}>';
+  }
+});
+
+function $H(object) {
+  if (object && object.constructor == Hash) return object;
+  return new Hash(object);
+};
+ObjectRange = Class.create();
+Object.extend(ObjectRange.prototype, Enumerable);
+Object.extend(ObjectRange.prototype, {
+  initialize: function(start, end, exclusive) {
+    this.start = start;
+    this.end = end;
+    this.exclusive = exclusive;
+  },
+
+  _each: function(iterator) {
+    var value = this.start;
+    while (this.include(value)) {
+      iterator(value);
+      value = value.succ();
+    }
+  },
+
+  include: function(value) {
+    if (value < this.start)
+      return false;
+    if (this.exclusive)
+      return value < this.end;
+    return value <= this.end;
+  }
+});
+
+var $R = function(start, end, exclusive) {
+  return new ObjectRange(start, end, exclusive);
+}
+
+var Ajax = {
+  getTransport: function() {
+    return Try.these(
+      function() {return new XMLHttpRequest()},
+      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+    ) || false;
+  },
+
+  activeRequestCount: 0
+}
+
+Ajax.Responders = {
+  responders: [],
+
+  _each: function(iterator) {
+    this.responders._each(iterator);
+  },
+
+  register: function(responder) {
+    if (!this.include(responder))
+      this.responders.push(responder);
+  },
+
+  unregister: function(responder) {
+    this.responders = this.responders.without(responder);
+  },
+
+  dispatch: function(callback, request, transport, json) {
+    this.each(function(responder) {
+      if (typeof responder[callback] == 'function') {
+        try {
+          responder[callback].apply(responder, [request, transport, json]);
+        } catch (e) {}
+      }
+    });
+  }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+  onCreate: function() {
+    Ajax.activeRequestCount++;
+  },
+  onComplete: function() {
+    Ajax.activeRequestCount--;
+  }
+});
+
+Ajax.Base = function() {};
+Ajax.Base.prototype = {
+  setOptions: function(options) {
+    this.options = {
+      method:       'post',
+      asynchronous: true,
+      contentType:  'application/x-www-form-urlencoded',
+      encoding:     'UTF-8',
+      parameters:   ''
+    }
+    Object.extend(this.options, options || {});
+
+    this.options.method = this.options.method.toLowerCase();
+    if (typeof this.options.parameters == 'string')
+      this.options.parameters = this.options.parameters.toQueryParams();
+  }
+}
+
+Ajax.Request = Class.create();
+Ajax.Request.Events =
+  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
+  _complete: false,
+
+  initialize: function(url, options) {
+    this.transport = Ajax.getTransport();
+    this.setOptions(options);
+    this.request(url);
+  },
+
+  request: function(url) {
+    this.url = url;
+    this.method = this.options.method;
+    var params = this.options.parameters;
+
+    if (!['get', 'post'].include(this.method)) {
+      // simulate other verbs over post
+      params['_method'] = this.method;
+      this.method = 'post';
+    }
+
+    params = Hash.toQueryString(params);
+    if (params && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_='
+
+    // when GET, append parameters to URL
+    if (this.method == 'get' && params)
+      this.url += (this.url.indexOf('?') > -1 ? '&' : '?') + params;
+
+    try {
+      Ajax.Responders.dispatch('onCreate', this, this.transport);
+
+      this.transport.open(this.method.toUpperCase(), this.url,
+        this.options.asynchronous);
+
+      if (this.options.asynchronous)
+        setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);
+
+      this.transport.onreadystatechange = this.onStateChange.bind(this);
+      this.setRequestHeaders();
+
+      var body = this.method == 'post' ? (this.options.postBody || params) : null;
+
+      this.transport.send(body);
+
+      /* Force Firefox to handle ready state 4 for synchronous requests */
+      if (!this.options.asynchronous && this.transport.overrideMimeType)
+        this.onStateChange();
+
+    }
+    catch (e) {
+      this.dispatchException(e);
+    }
+  },
+
+  onStateChange: function() {
+    var readyState = this.transport.readyState;
+    if (readyState > 1 && !((readyState == 4) && this._complete))
+      this.respondToReadyState(this.transport.readyState);
+  },
+
+  setRequestHeaders: function() {
+    var headers = {
+      'X-Requested-With': 'XMLHttpRequest',
+      'X-Prototype-Version': Prototype.Version,
+      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+    };
+
+    if (this.method == 'post') {
+      headers['Content-type'] = this.options.contentType +
+        (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+      /* Force "Connection: close" for older Mozilla browsers to work
+       * around a bug where XMLHttpRequest sends an incorrect
+       * Content-length header. See Mozilla Bugzilla #246651.
+       */
+      if (this.transport.overrideMimeType &&
+          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+            headers['Connection'] = 'close';
+    }
+
+    // user-defined headers
+    if (typeof this.options.requestHeaders == 'object') {
+      var extras = this.options.requestHeaders;
+
+      if (typeof extras.push == 'function')
+        for (var i = 0, length = extras.length; i < length; i += 2)
+          headers[extras[i]] = extras[i+1];
+      else
+        $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+    }
+
+    for (var name in headers)
+      this.transport.setRequestHeader(name, headers[name]);
+  },
+
+  success: function() {
+    return !this.transport.status
+        || (this.transport.status >= 200 && this.transport.status < 300);
+  },
+
+  respondToReadyState: function(readyState) {
+    var state = Ajax.Request.Events[readyState];
+    var transport = this.transport, json = this.evalJSON();
+
+    if (state == 'Complete') {
+      try {
+        this._complete = true;
+        (this.options['on' + this.transport.status]
+         || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+         || Prototype.emptyFunction)(transport, json);
+      } catch (e) {
+        this.dispatchException(e);
+      }
+
+      if ((this.getHeader('Content-type') || 'text/javascript').strip().
+        match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
+          this.evalResponse();
+    }
+
+    try {
+      (this.options['on' + state] || Prototype.emptyFunction)(transport, json);
+      Ajax.Responders.dispatch('on' + state, this, transport, json);
+    } catch (e) {
+      this.dispatchException(e);
+    }
+
+    if (state == 'Complete') {
+      // avoid memory leak in MSIE: clean up
+      this.transport.onreadystatechange = Prototype.emptyFunction;
+    }
+  },
+
+  getHeader: function(name) {
+    try {
+      return this.transport.getResponseHeader(name);
+    } catch (e) { return null }
+  },
+
+  evalJSON: function() {
+    try {
+      var json = this.getHeader('X-JSON');
+      return json ? eval('(' + json + ')') : null;
+    } catch (e) { return null }
+  },
+
+  evalResponse: function() {
+    try {
+      return eval(this.transport.responseText);
+    } catch (e) {
+      this.dispatchException(e);
+    }
+  },
+
+  dispatchException: function(exception) {
+    (this.options.onException || Prototype.emptyFunction)(this, exception);
+    Ajax.Responders.dispatch('onException', this, exception);
+  }
+});
+
+Ajax.Updater = Class.create();
+
+Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
+  initialize: function(container, url, options) {
+    this.container = {
+      success: (container.success || container),
+      failure: (container.failure || (container.success ? null : container))
+    }
+
+    this.transport = Ajax.getTransport();
+    this.setOptions(options);
+
+    var onComplete = this.options.onComplete || Prototype.emptyFunction;
+    this.options.onComplete = (function(transport, param) {
+      this.updateContent();
+      onComplete(transport, param);
+    }).bind(this);
+
+    this.request(url);
+  },
+
+  updateContent: function() {
+    var receiver = this.container[this.success() ? 'success' : 'failure'];
+    var response = this.transport.responseText;
+
+    if (!this.options.evalScripts) response = response.stripScripts();
+
+    if (receiver = $(receiver)) {
+      if (this.options.insertion)
+        new this.options.insertion(receiver, response);
+      else
+        receiver.update(response);
+    }
+
+    if (this.success()) {
+      if (this.onComplete)
+        setTimeout(this.onComplete.bind(this), 10);
+    }
+  }
+});
+
+Ajax.PeriodicalUpdater = Class.create();
+Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
+  initialize: function(container, url, options) {
+    this.setOptions(options);
+    this.onComplete = this.options.onComplete;
+
+    this.frequency = (this.options.frequency || 2);
+    this.decay = (this.options.decay || 1);
+
+    this.updater = {};
+    this.container = container;
+    this.url = url;
+
+    this.start();
+  },
+
+  start: function() {
+    this.options.onComplete = this.updateComplete.bind(this);
+    this.onTimerEvent();
+  },
+
+  stop: function() {
+    this.updater.options.onComplete = undefined;
+    clearTimeout(this.timer);
+    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+  },
+
+  updateComplete: function(request) {
+    if (this.options.decay) {
+      this.decay = (request.responseText == this.lastText ?
+        this.decay * this.options.decay : 1);
+
+      this.lastText = request.responseText;
+    }
+    this.timer = setTimeout(this.onTimerEvent.bind(this),
+      this.decay * this.frequency * 1000);
+  },
+
+  onTimerEvent: function() {
+    this.updater = new Ajax.Updater(this.container, this.url, this.options);
+  }
+});
+function $(element) {
+  if (arguments.length > 1) {
+    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+      elements.push($(arguments[i]));
+    return elements;
+  }
+  if (typeof element == 'string')
+    element = document.getElementById(element);
+  return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+  document._getElementsByXPath = function(expression, parentElement) {
+    var results = [];
+    var query = document.evaluate(expression, $(parentElement) || document,
+      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+    for (var i = 0, length = query.snapshotLength; i < length; i++)
+      results.push(query.snapshotItem(i));
+    return results;
+  };
+}
+
+document.getElementsByClassName = function(className, parentElement) {
+  if (Prototype.BrowserFeatures.XPath) {
+    var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
+    return document._getElementsByXPath(q, parentElement);
+  } else {
+    var children = ($(parentElement) || document.body).getElementsByTagName('*');
+    var elements = [], child;
+    for (var i = 0, length = children.length; i < length; i++) {
+      child = children[i];
+      if (Element.hasClassName(child, className))
+        elements.push(Element.extend(child));
+    }
+    return elements;
+  }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Element)
+  var Element = new Object();
+
+Element.extend = function(element) {
+  if (!element || _nativeExtensions || element.nodeType == 3) return element;
+
+  if (!element._extended && element.tagName && element != window) {
+    var methods = Object.clone(Element.Methods), cache = Element.extend.cache;
+
+    if (element.tagName == 'FORM')
+      Object.extend(methods, Form.Methods);
+    if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName))
+      Object.extend(methods, Form.Element.Methods);
+
+    Object.extend(methods, Element.Methods.Simulated);
+
+    for (var property in methods) {
+      var value = methods[property];
+      if (typeof value == 'function' && !(property in element))
+        element[property] = cache.findOrStore(value);
+    }
+  }
+
+  element._extended = true;
+  return element;
+};
+
+Element.extend.cache = {
+  findOrStore: function(value) {
+    return this[value] = this[value] || function() {
+      return value.apply(null, [this].concat($A(arguments)));
+    }
+  }
+};
+
+Element.Methods = {
+  visible: function(element) {
+    return $(element).style.display != 'none';
+  },
+
+  toggle: function(element) {
+    element = $(element);
+    Element[Element.visible(element) ? 'hide' : 'show'](element);
+    return element;
+  },
+
+  hide: function(element) {
+    $(element).style.display = 'none';
+    return element;
+  },
+
+  show: function(element) {
+    $(element).style.display = '';
+    return element;
+  },
+
+  remove: function(element) {
+    element = $(element);
+    element.parentNode.removeChild(element);
+    return element;
+  },
+
+  update: function(element, html) {
+    html = typeof html == 'undefined' ? '' : html.toString();
+    $(element).innerHTML = html.stripScripts();
+    setTimeout(function() {html.evalScripts()}, 10);
+    return element;
+  },
+
+  replace: function(element, html) {
+    element = $(element);
+    html = typeof html == 'undefined' ? '' : html.toString();
+    if (element.outerHTML) {
+      element.outerHTML = html.stripScripts();
+    } else {
+      var range = element.ownerDocument.createRange();
+      range.selectNodeContents(element);
+      element.parentNode.replaceChild(
+        range.createContextualFragment(html.stripScripts()), element);
+    }
+    setTimeout(function() {html.evalScripts()}, 10);
+    return element;
+  },
+
+  inspect: function(element) {
+    element = $(element);
+    var result = '<' + element.tagName.toLowerCase();
+    $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+      var property = pair.first(), attribute = pair.last();
+      var value = (element[property] || '').toString();
+      if (value) result += ' ' + attribute + '=' + value.inspect(true);
+    });
+    return result + '>';
+  },
+
+  recursivelyCollect: function(element, property) {
+    element = $(element);
+    var elements = [];
+    while (element = element[property])
+      if (element.nodeType == 1)
+        elements.push(Element.extend(element));
+    return elements;
+  },
+
+  ancestors: function(element) {
+    return $(element).recursivelyCollect('parentNode');
+  },
+
+  descendants: function(element) {
+    return $A($(element).getElementsByTagName('*'));
+  },
+
+  immediateDescendants: function(element) {
+    if (!(element = $(element).firstChild)) return [];
+    while (element && element.nodeType != 1) element = element.nextSibling;
+    if (element) return [element].concat($(element).nextSiblings());
+    return [];
+  },
+
+  previousSiblings: function(element) {
+    return $(element).recursivelyCollect('previousSibling');
+  },
+
+  nextSiblings: function(element) {
+    return $(element).recursivelyCollect('nextSibling');
+  },
+
+  siblings: function(element) {
+    element = $(element);
+    return element.previousSiblings().reverse().concat(element.nextSiblings());
+  },
+
+  match: function(element, selector) {
+    if (typeof selector == 'string')
+      selector = new Selector(selector);
+    return selector.match($(element));
+  },
+
+  up: function(element, expression, index) {
+    return Selector.findElement($(element).ancestors(), expression, index);
+  },
+
+  down: function(element, expression, index) {
+    return Selector.findElement($(element).descendants(), expression, index);
+  },
+
+  previous: function(element, expression, index) {
+    return Selector.findElement($(element).previousSiblings(), expression, index);
+  },
+
+  next: function(element, expression, index) {
+    return Selector.findElement($(element).nextSiblings(), expression, index);
+  },
+
+  getElementsBySelector: function() {
+    var args = $A(arguments), element = $(args.shift());
+    return Selector.findChildElements(element, args);
+  },
+
+  getElementsByClassName: function(element, className) {
+    return document.getElementsByClassName(className, element);
+  },
+
+  readAttribute: function(element, name) {
+    element = $(element);
+    if (document.all && !window.opera) {
+      var t = Element._attributeTranslations;
+      if (t.values[name]) return t.values[name](element, name);
+      if (t.names[name])  name = t.names[name];
+      var attribute = element.attributes[name];
+      if(attribute) return attribute.nodeValue;
+    }
+    return element.getAttribute(name);
+  },
+
+  getHeight: function(element) {
+    return $(element).getDimensions().height;
+  },
+
+  getWidth: function(element) {
+    return $(element).getDimensions().width;
+  },
+
+  classNames: function(element) {
+    return new Element.ClassNames(element);
+  },
+
+  hasClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    var elementClassName = element.className;
+    if (elementClassName.length == 0) return false;
+    if (elementClassName == className ||
+        elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
+      return true;
+    return false;
+  },
+
+  addClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    Element.classNames(element).add(className);
+    return element;
+  },
+
+  removeClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    Element.classNames(element).remove(className);
+    return element;
+  },
+
+  toggleClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className);
+    return element;
+  },
+
+  observe: function() {
+    Event.observe.apply(Event, arguments);
+    return $A(arguments).first();
+  },
+
+  stopObserving: function() {
+    Event.stopObserving.apply(Event, arguments);
+    return $A(arguments).first();
+  },
+
+  // removes whitespace-only text node children
+  cleanWhitespace: function(element) {
+    element = $(element);
+    var node = element.firstChild;
+    while (node) {
+      var nextNode = node.nextSibling;
+      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+        element.removeChild(node);
+      node = nextNode;
+    }
+    return element;
+  },
+
+  empty: function(element) {
+    return $(element).innerHTML.match(/^\s*$/);
+  },
+
+  descendantOf: function(element, ancestor) {
+    element = $(element), ancestor = $(ancestor);
+    while (element = element.parentNode)
+      if (element == ancestor) return true;
+    return false;
+  },
+
+  scrollTo: function(element) {
+    element = $(element);
+    var pos = Position.cumulativeOffset(element);
+    window.scrollTo(pos[0], pos[1]);
+    return element;
+  },
+
+  getStyle: function(element, style) {
+    element = $(element);
+    if (['float','cssFloat'].include(style))
+      style = (typeof element.style.styleFloat != 'undefined' ? 'styleFloat' : 'cssFloat');
+    style = style.camelize();
+    var value = element.style[style];
+    if (!value) {
+      if (document.defaultView && document.defaultView.getComputedStyle) {
+        var css = document.defaultView.getComputedStyle(element, null);
+        value = css ? css[style] : null;
+      } else if (element.currentStyle) {
+        value = element.currentStyle[style];
+      }
+    }
+
+    if((value == 'auto') && ['width','height'].include(style) && (element.getStyle('display') != 'none'))
+      value = element['offset'+style.capitalize()] + 'px';
+
+    if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
+      if (Element.getStyle(element, 'position') == 'static') value = 'auto';
+    if(style == 'opacity') {
+      if(value) return parseFloat(value);
+      if(value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+        if(value[1]) return parseFloat(value[1]) / 100;
+      return 1.0;
+    }
+    return value == 'auto' ? null : value;
+  },
+
+  setStyle: function(element, style) {
+    element = $(element);
+    for (var name in style) {
+      var value = style[name];
+      if(name == 'opacity') {
+        if (value == 1) {
+          value = (/Gecko/.test(navigator.userAgent) &&
+            !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : 1.0;
+          if(/MSIE/.test(navigator.userAgent) && !window.opera)
+            element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
+        } else if(value == '') {
+          if(/MSIE/.test(navigator.userAgent) && !window.opera)
+            element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
+        } else {
+          if(value < 0.00001) value = 0;
+          if(/MSIE/.test(navigator.userAgent) && !window.opera)
+            element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') +
+              'alpha(opacity='+value*100+')';
+        }
+      } else if(['float','cssFloat'].include(name)) name = (typeof element.style.styleFloat != 'undefined') ? 'styleFloat' : 'cssFloat';
+      element.style[name.camelize()] = value;
+    }
+    return element;
+  },
+
+  getDimensions: function(element) {
+    element = $(element);
+    var display = $(element).getStyle('display');
+    if (display != 'none' && display != null) // Safari bug
+      return {width: element.offsetWidth, height: element.offsetHeight};
+
+    // All *Width and *Height properties give 0 on elements with display none,
+    // so enable the element temporarily
+    var els = element.style;
+    var originalVisibility = els.visibility;
+    var originalPosition = els.position;
+    var originalDisplay = els.display;
+    els.visibility = 'hidden';
+    els.position = 'absolute';
+    els.display = 'block';
+    var originalWidth = element.clientWidth;
+    var originalHeight = element.clientHeight;
+    els.display = originalDisplay;
+    els.position = originalPosition;
+    els.visibility = originalVisibility;
+    return {width: originalWidth, height: originalHeight};
+  },
+
+  makePositioned: function(element) {
+    element = $(element);
+    var pos = Element.getStyle(element, 'position');
+    if (pos == 'static' || !pos) {
+      element._madePositioned = true;
+      element.style.position = 'relative';
+      // Opera returns the offset relative to the positioning context, when an
+      // element is position relative but top and left have not been defined
+      if (window.opera) {
+        element.style.top = 0;
+        element.style.left = 0;
+      }
+    }
+    return element;
+  },
+
+  undoPositioned: function(element) {
+    element = $(element);
+    if (element._madePositioned) {
+      element._madePositioned = undefined;
+      element.style.position =
+        element.style.top =
+        element.style.left =
+        element.style.bottom =
+        element.style.right = '';
+    }
+    return element;
+  },
+
+  makeClipping: function(element) {
+    element = $(element);
+    if (element._overflow) return element;
+    element._overflow = element.style.overflow || 'auto';
+    if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
+      element.style.overflow = 'hidden';
+    return element;
+  },
+
+  undoClipping: function(element) {
+    element = $(element);
+    if (!element._overflow) return element;
+    element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+    element._overflow = null;
+    return element;
+  }
+};
+
+Object.extend(Element.Methods, {childOf: Element.Methods.descendantOf});
+
+Element._attributeTranslations = {};
+
+Element._attributeTranslations.names = {
+  colspan:   "colSpan",
+  rowspan:   "rowSpan",
+  valign:    "vAlign",
+  datetime:  "dateTime",
+  accesskey: "accessKey",
+  tabindex:  "tabIndex",
+  enctype:   "encType",
+  maxlength: "maxLength",
+  readonly:  "readOnly",
+  longdesc:  "longDesc"
+};
+
+Element._attributeTranslations.values = {
+  _getAttr: function(element, attribute) {
+    return element.getAttribute(attribute, 2);
+  },
+
+  _flag: function(element, attribute) {
+    return $(element).hasAttribute(attribute) ? attribute : null;
+  },
+
+  style: function(element) {
+    return element.style.cssText.toLowerCase();
+  },
+
+  title: function(element) {
+    var node = element.getAttributeNode('title');
+    return node.specified ? node.nodeValue : null;
+  }
+};
+
+Object.extend(Element._attributeTranslations.values, {
+  href: Element._attributeTranslations.values._getAttr,
+  src:  Element._attributeTranslations.values._getAttr,
+  disabled: Element._attributeTranslations.values._flag,
+  checked:  Element._attributeTranslations.values._flag,
+  readonly: Element._attributeTranslations.values._flag,
+  multiple: Element._attributeTranslations.values._flag
+});
+
+Element.Methods.Simulated = {
+  hasAttribute: function(element, attribute) {
+    var t = Element._attributeTranslations;
+    attribute = t.names[attribute] || attribute;
+    return $(element).getAttributeNode(attribute).specified;
+  }
+};
+
+// IE is missing .innerHTML support for TABLE-related elements
+if (document.all && !window.opera){
+  Element.Methods.update = function(element, html) {
+    element = $(element);
+    html = typeof html == 'undefined' ? '' : html.toString();
+    var tagName = element.tagName.toUpperCase();
+    if (['THEAD','TBODY','TR','TD'].include(tagName)) {
+      var div = document.createElement('div');
+      switch (tagName) {
+        case 'THEAD':
+        case 'TBODY':
+          div.innerHTML = '<table><tbody>' +  html.stripScripts() + '</tbody></table>';
+          depth = 2;
+          break;
+        case 'TR':
+          div.innerHTML = '<table><tbody><tr>' +  html.stripScripts() + '</tr></tbody></table>';
+          depth = 3;
+          break;
+        case 'TD':
+          div.innerHTML = '<table><tbody><tr><td>' +  html.stripScripts() + '</td></tr></tbody></table>';
+          depth = 4;
+      }
+      $A(element.childNodes).each(function(node){
+        element.removeChild(node)
+      });
+      depth.times(function(){ div = div.firstChild });
+
+      $A(div.childNodes).each(
+        function(node){ element.appendChild(node) });
+    } else {
+      element.innerHTML = html.stripScripts();
+    }
+    setTimeout(function() {html.evalScripts()}, 10);
+    return element;
+  }
+};
+
+Object.extend(Element, Element.Methods);
+
+var _nativeExtensions = false;
+
+if(/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+  ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) {
+    var className = 'HTML' + tag + 'Element';
+    if(window[className]) return;
+    var klass = window[className] = {};
+    klass.prototype = document.createElement(tag ? tag.toLowerCase() : 'div').__proto__;
+  });
+
+Element.addMethods = function(methods) {
+  Object.extend(Element.Methods, methods || {});
+
+  function copy(methods, destination, onlyIfAbsent) {
+    onlyIfAbsent = onlyIfAbsent || false;
+    var cache = Element.extend.cache;
+    for (var property in methods) {
+      var value = methods[property];
+      if (!onlyIfAbsent || !(property in destination))
+        destination[property] = cache.findOrStore(value);
+    }
+  }
+
+  if (typeof HTMLElement != 'undefined') {
+    copy(Element.Methods, HTMLElement.prototype);
+    copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+    copy(Form.Methods, HTMLFormElement.prototype);
+    [HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) {
+      copy(Form.Element.Methods, klass.prototype);
+    });
+    _nativeExtensions = true;
+  }
+}
+
+var Toggle = new Object();
+Toggle.display = Element.toggle;
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.Insertion = function(adjacency) {
+  this.adjacency = adjacency;
+}
+
+Abstract.Insertion.prototype = {
+  initialize: function(element, content) {
+    this.element = $(element);
+    this.content = content.stripScripts();
+
+    if (this.adjacency && this.element.insertAdjacentHTML) {
+      try {
+        this.element.insertAdjacentHTML(this.adjacency, this.content);
+      } catch (e) {
+        var tagName = this.element.tagName.toUpperCase();
+        if (['TBODY', 'TR'].include(tagName)) {
+          this.insertContent(this.contentFromAnonymousTable());
+        } else {
+          throw e;
+        }
+      }
+    } else {
+      this.range = this.element.ownerDocument.createRange();
+      if (this.initializeRange) this.initializeRange();
+      this.insertContent([this.range.createContextualFragment(this.content)]);
+    }
+
+    setTimeout(function() {content.evalScripts()}, 10);
+  },
+
+  contentFromAnonymousTable: function() {
+    var div = document.createElement('div');
+    div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
+    return $A(div.childNodes[0].childNodes[0].childNodes);
+  }
+}
+
+var Insertion = new Object();
+
+Insertion.Before = Class.create();
+Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
+  initializeRange: function() {
+    this.range.setStartBefore(this.element);
+  },
+
+  insertContent: function(fragments) {
+    fragments.each((function(fragment) {
+      this.element.parentNode.insertBefore(fragment, this.element);
+    }).bind(this));
+  }
+});
+
+Insertion.Top = Class.create();
+Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
+  initializeRange: function() {
+    this.range.selectNodeContents(this.element);
+    this.range.collapse(true);
+  },
+
+  insertContent: function(fragments) {
+    fragments.reverse(false).each((function(fragment) {
+      this.element.insertBefore(fragment, this.element.firstChild);
+    }).bind(this));
+  }
+});
+
+Insertion.Bottom = Class.create();
+Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
+  initializeRange: function() {
+    this.range.selectNodeContents(this.element);
+    this.range.collapse(this.element);
+  },
+
+  insertContent: function(fragments) {
+    fragments.each((function(fragment) {
+      this.element.appendChild(fragment);
+    }).bind(this));
+  }
+});
+
+Insertion.After = Class.create();
+Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
+  initializeRange: function() {
+    this.range.setStartAfter(this.element);
+  },
+
+  insertContent: function(fragments) {
+    fragments.each((function(fragment) {
+      this.element.parentNode.insertBefore(fragment,
+        this.element.nextSibling);
+    }).bind(this));
+  }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+  initialize: function(element) {
+    this.element = $(element);
+  },
+
+  _each: function(iterator) {
+    this.element.className.split(/\s+/).select(function(name) {
+      return name.length > 0;
+    })._each(iterator);
+  },
+
+  set: function(className) {
+    this.element.className = className;
+  },
+
+  add: function(classNameToAdd) {
+    if (this.include(classNameToAdd)) return;
+    this.set($A(this).concat(classNameToAdd).join(' '));
+  },
+
+  remove: function(classNameToRemove) {
+    if (!this.include(classNameToRemove)) return;
+    this.set($A(this).without(classNameToRemove).join(' '));
+  },
+
+  toString: function() {
+    return $A(this).join(' ');
+  }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+var Selector = Class.create();
+Selector.prototype = {
+  initialize: function(expression) {
+    this.params = {classNames: []};
+    this.expression = expression.toString().strip();
+    this.parseExpression();
+    this.compileMatcher();
+  },
+
+  parseExpression: function() {
+    function abort(message) { throw 'Parse error in selector: ' + message; }
+
+    if (this.expression == '')  abort('empty expression');
+
+    var params = this.params, expr = this.expression, match, modifier, clause, rest;
+    while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
+      params.attributes = params.attributes || [];
+      params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
+      expr = match[1];
+    }
+
+    if (expr == '*') return this.params.wildcard = true;
+
+    while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
+      modifier = match[1], clause = match[2], rest = match[3];
+      switch (modifier) {
+        case '#':       params.id = clause; break;
+        case '.':       params.classNames.push(clause); break;
+        case '':
+        case undefined: params.tagName = clause.toUpperCase(); break;
+        default:        abort(expr.inspect());
+      }
+      expr = rest;
+    }
+
+    if (expr.length > 0) abort(expr.inspect());
+  },
+
+  buildMatchExpression: function() {
+    var params = this.params, conditions = [], clause;
+
+    if (params.wildcard)
+      conditions.push('true');
+    if (clause = params.id)
+      conditions.push('element.readAttribute("id") == ' + clause.inspect());
+    if (clause = params.tagName)
+      conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
+    if ((clause = params.classNames).length > 0)
+      for (var i = 0, length = clause.length; i < length; i++)
+        conditions.push('element.hasClassName(' + clause[i].inspect() + ')');
+    if (clause = params.attributes) {
+      clause.each(function(attribute) {
+        var value = 'element.readAttribute(' + attribute.name.inspect() + ')';
+        var splitValueBy = function(delimiter) {
+          return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
+        }
+
+        switch (attribute.operator) {
+          case '=':       conditions.push(value + ' == ' + attribute.value.inspect()); break;
+          case '~=':      conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break;
+          case '|=':      conditions.push(
+                            splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect()
+                          ); break;
+          case '!=':      conditions.push(value + ' != ' + attribute.value.inspect()); break;
+          case '':
+          case undefined: conditions.push('element.hasAttribute(' + attribute.name.inspect() + ')'); break;
+          default:        throw 'Unknown operator ' + attribute.operator + ' in selector';
+        }
+      });
+    }
+
+    return conditions.join(' && ');
+  },
+
+  compileMatcher: function() {
+    this.match = new Function('element', 'if (!element.tagName) return false; \
+      element = $(element); \
+      return ' + this.buildMatchExpression());
+  },
+
+  findElements: function(scope) {
+    var element;
+
+    if (element = $(this.params.id))
+      if (this.match(element))
+        if (!scope || Element.childOf(element, scope))
+          return [element];
+
+    scope = (scope || document).getElementsByTagName(this.params.tagName || '*');
+
+    var results = [];
+    for (var i = 0, length = scope.length; i < length; i++)
+      if (this.match(element = scope[i]))
+        results.push(Element.extend(element));
+
+    return results;
+  },
+
+  toString: function() {
+    return this.expression;
+  }
+}
+
+Object.extend(Selector, {
+  matchElements: function(elements, expression) {
+    var selector = new Selector(expression);
+    return elements.select(selector.match.bind(selector)).map(Element.extend);
+  },
+
+  findElement: function(elements, expression, index) {
+    if (typeof expression == 'number') index = expression, expression = false;
+    return Selector.matchElements(elements, expression || '*')[index || 0];
+  },
+
+  findChildElements: function(element, expressions) {
+    return expressions.map(function(expression) {
+      return expression.match(/[^\s"]+(?:"[^"]*"[^\s"]+)*/g).inject([null], function(results, expr) {
+        var selector = new Selector(expr);
+        return results.inject([], function(elements, result) {
+          return elements.concat(selector.findElements(result || element));
+        });
+      });
+    }).flatten();
+  }
+});
+
+function $$() {
+  return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+  reset: function(form) {
+    $(form).reset();
+    return form;
+  },
+
+  serializeElements: function(elements, getHash) {
+    var data = elements.inject({}, function(result, element) {
+      if (!element.disabled && element.name) {
+        var key = element.name, value = $(element).getValue();
+        if (value != undefined) {
+          if (result[key]) {
+            if (result[key].constructor != Array) result[key] = [result[key]];
+            result[key].push(value);
+          }
+          else result[key] = value;
+        }
+      }
+      return result;
+    });
+
+    return getHash ? data : Hash.toQueryString(data);
+  }
+};
+
+Form.Methods = {
+  serialize: function(form, getHash) {
+    return Form.serializeElements(Form.getElements(form), getHash);
+  },
+
+  getElements: function(form) {
+    return $A($(form).getElementsByTagName('*')).inject([],
+      function(elements, child) {
+        if (Form.Element.Serializers[child.tagName.toLowerCase()])
+          elements.push(Element.extend(child));
+        return elements;
+      }
+    );
+  },
+
+  getInputs: function(form, typeName, name) {
+    form = $(form);
+    var inputs = form.getElementsByTagName('input');
+
+    if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+    for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+      var input = inputs[i];
+      if ((typeName && input.type != typeName) || (name && input.name != name))
+        continue;
+      matchingInputs.push(Element.extend(input));
+    }
+
+    return matchingInputs;
+  },
+
+  disable: function(form) {
+    form = $(form);
+    form.getElements().each(function(element) {
+      element.blur();
+      element.disabled = 'true';
+    });
+    return form;
+  },
+
+  enable: function(form) {
+    form = $(form);
+    form.getElements().each(function(element) {
+      element.disabled = '';
+    });
+    return form;
+  },
+
+  findFirstElement: function(form) {
+    return $(form).getElements().find(function(element) {
+      return element.type != 'hidden' && !element.disabled &&
+        ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+    });
+  },
+
+  focusFirstElement: function(form) {
+    form = $(form);
+    form.findFirstElement().activate();
+    return form;
+  }
+}
+
+Object.extend(Form, Form.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+  focus: function(element) {
+    $(element).focus();
+    return element;
+  },
+
+  select: function(element) {
+    $(element).select();
+    return element;
+  }
+}
+
+Form.Element.Methods = {
+  serialize: function(element) {
+    element = $(element);
+    if (!element.disabled && element.name) {
+      var value = element.getValue();
+      if (value != undefined) {
+        var pair = {};
+        pair[element.name] = value;
+        return Hash.toQueryString(pair);
+      }
+    }
+    return '';
+  },
+
+  getValue: function(element) {
+    element = $(element);
+    var method = element.tagName.toLowerCase();
+    return Form.Element.Serializers[method](element);
+  },
+
+  clear: function(element) {
+    $(element).value = '';
+    return element;
+  },
+
+  present: function(element) {
+    return $(element).value != '';
+  },
+
+  activate: function(element) {
+    element = $(element);
+    element.focus();
+    if (element.select && ( element.tagName.toLowerCase() != 'input' ||
+      !['button', 'reset', 'submit'].include(element.type) ) )
+      element.select();
+    return element;
+  },
+
+  disable: function(element) {
+    element = $(element);
+    element.disabled = true;
+    return element;
+  },
+
+  enable: function(element) {
+    element = $(element);
+    element.blur();
+    element.disabled = false;
+    return element;
+  }
+}
+
+Object.extend(Form.Element, Form.Element.Methods);
+var Field = Form.Element;
+var $F = Form.Element.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+  input: function(element) {
+    switch (element.type.toLowerCase()) {
+      case 'checkbox':
+      case 'radio':
+        return Form.Element.Serializers.inputSelector(element);
+      default:
+        return Form.Element.Serializers.textarea(element);
+    }
+  },
+
+  inputSelector: function(element) {
+    return element.checked ? element.value : null;
+  },
+
+  textarea: function(element) {
+    return element.value;
+  },
+
+  select: function(element) {
+    return this[element.type == 'select-one' ?
+      'selectOne' : 'selectMany'](element);
+  },
+
+  selectOne: function(element) {
+    var index = element.selectedIndex;
+    return index >= 0 ? this.optionValue(element.options[index]) : null;
+  },
+
+  selectMany: function(element) {
+    var values, length = element.length;
+    if (!length) return null;
+
+    for (var i = 0, values = []; i < length; i++) {
+      var opt = element.options[i];
+      if (opt.selected) values.push(this.optionValue(opt));
+    }
+    return values;
+  },
+
+  optionValue: function(opt) {
+    // extend element because hasAttribute may not be native
+    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = function() {}
+Abstract.TimedObserver.prototype = {
+  initialize: function(element, frequency, callback) {
+    this.frequency = frequency;
+    this.element   = $(element);
+    this.callback  = callback;
+
+    this.lastValue = this.getValue();
+    this.registerCallback();
+  },
+
+  registerCallback: function() {
+    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+  },
+
+  onTimerEvent: function() {
+    var value = this.getValue();
+    var changed = ('string' == typeof this.lastValue && 'string' == typeof value
+      ? this.lastValue != value : String(this.lastValue) != String(value));
+    if (changed) {
+      this.callback(this.element, value);
+      this.lastValue = value;
+    }
+  }
+}
+
+Form.Element.Observer = Class.create();
+Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.Observer = Class.create();
+Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = function() {}
+Abstract.EventObserver.prototype = {
+  initialize: function(element, callback) {
+    this.element  = $(element);
+    this.callback = callback;
+
+    this.lastValue = this.getValue();
+    if (this.element.tagName.toLowerCase() == 'form')
+      this.registerFormCallbacks();
+    else
+      this.registerCallback(this.element);
+  },
+
+  onElementEvent: function() {
+    var value = this.getValue();
+    if (this.lastValue != value) {
+      this.callback(this.element, value);
+      this.lastValue = value;
+    }
+  },
+
+  registerFormCallbacks: function() {
+    Form.getElements(this.element).each(this.registerCallback.bind(this));
+  },
+
+  registerCallback: function(element) {
+    if (element.type) {
+      switch (element.type.toLowerCase()) {
+        case 'checkbox':
+        case 'radio':
+          Event.observe(element, 'click', this.onElementEvent.bind(this));
+          break;
+        default:
+          Event.observe(element, 'change', this.onElementEvent.bind(this));
+          break;
+      }
+    }
+  }
+}
+
+Form.Element.EventObserver = Class.create();
+Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.EventObserver = Class.create();
+Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+if (!window.Event) {
+  var Event = new Object();
+}
+
+Object.extend(Event, {
+  KEY_BACKSPACE: 8,
+  KEY_TAB:       9,
+  KEY_RETURN:   13,
+  KEY_ESC:      27,
+  KEY_LEFT:     37,
+  KEY_UP:       38,
+  KEY_RIGHT:    39,
+  KEY_DOWN:     40,
+  KEY_DELETE:   46,
+  KEY_HOME:     36,
+  KEY_END:      35,
+  KEY_PAGEUP:   33,
+  KEY_PAGEDOWN: 34,
+
+  element: function(event) {
+    return event.target || event.srcElement;
+  },
+
+  isLeftClick: function(event) {
+    return (((event.which) && (event.which == 1)) ||
+            ((event.button) && (event.button == 1)));
+  },
+
+  pointerX: function(event) {
+    return event.pageX || (event.clientX +
+      (document.documentElement.scrollLeft || document.body.scrollLeft));
+  },
+
+  pointerY: function(event) {
+    return event.pageY || (event.clientY +
+      (document.documentElement.scrollTop || document.body.scrollTop));
+  },
+
+  stop: function(event) {
+    if (event.preventDefault) {
+      event.preventDefault();
+      event.stopPropagation();
+    } else {
+      event.returnValue = false;
+      event.cancelBubble = true;
+    }
+  },
+
+  // find the first node with the given tagName, starting from the
+  // node the event was triggered on; traverses the DOM upwards
+  findElement: function(event, tagName) {
+    var element = Event.element(event);
+    while (element.parentNode && (!element.tagName ||
+        (element.tagName.toUpperCase() != tagName.toUpperCase())))
+      element = element.parentNode;
+    return element;
+  },
+
+  observers: false,
+
+  _observeAndCache: function(element, name, observer, useCapture) {
+    if (!this.observers) this.observers = [];
+    if (element.addEventListener) {
+      this.observers.push([element, name, observer, useCapture]);
+      element.addEventListener(name, observer, useCapture);
+    } else if (element.attachEvent) {
+      this.observers.push([element, name, observer, useCapture]);
+      element.attachEvent('on' + name, observer);
+    }
+  },
+
+  unloadCache: function() {
+    if (!Event.observers) return;
+    for (var i = 0, length = Event.observers.length; i < length; i++) {
+      Event.stopObserving.apply(this, Event.observers[i]);
+      Event.observers[i][0] = null;
+    }
+    Event.observers = false;
+  },
+
+  observe: function(element, name, observer, useCapture) {
+    element = $(element);
+    useCapture = useCapture || false;
+
+    if (name == 'keypress' &&
+        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
+        || element.attachEvent))
+      name = 'keydown';
+
+    Event._observeAndCache(element, name, observer, useCapture);
+  },
+
+  stopObserving: function(element, name, observer, useCapture) {
+    element = $(element);
+    useCapture = useCapture || false;
+
+    if (name == 'keypress' &&
+        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
+        || element.detachEvent))
+      name = 'keydown';
+
+    if (element.removeEventListener) {
+      element.removeEventListener(name, observer, useCapture);
+    } else if (element.detachEvent) {
+      try {
+        element.detachEvent('on' + name, observer);
+      } catch (e) {}
+    }
+  }
+});
+
+/* prevent memory leaks in IE */
+if (navigator.appVersion.match(/\bMSIE\b/))
+  Event.observe(window, 'unload', Event.unloadCache, false);
+var Position = {
+  // set to true if needed, warning: firefox performance problems
+  // NOT neeeded for page scrolling, only if draggable contained in
+  // scrollable elements
+  includeScrollOffsets: false,
+
+  // must be called before calling withinIncludingScrolloffset, every time the
+  // page is scrolled
+  prepare: function() {
+    this.deltaX =  window.pageXOffset
+                || document.documentElement.scrollLeft
+                || document.body.scrollLeft
+                || 0;
+    this.deltaY =  window.pageYOffset
+                || document.documentElement.scrollTop
+                || document.body.scrollTop
+                || 0;
+  },
+
+  realOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.scrollTop  || 0;
+      valueL += element.scrollLeft || 0;
+      element = element.parentNode;
+    } while (element);
+    return [valueL, valueT];
+  },
+
+  cumulativeOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      element = element.offsetParent;
+    } while (element);
+    return [valueL, valueT];
+  },
+
+  positionedOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      element = element.offsetParent;
+      if (element) {
+        if(element.tagName=='BODY') break;
+        var p = Element.getStyle(element, 'position');
+        if (p == 'relative' || p == 'absolute') break;
+      }
+    } while (element);
+    return [valueL, valueT];
+  },
+
+  offsetParent: function(element) {
+    if (element.offsetParent) return element.offsetParent;
+    if (element == document.body) return element;
+
+    while ((element = element.parentNode) && element != document.body)
+      if (Element.getStyle(element, 'position') != 'static')
+        return element;
+
+    return document.body;
+  },
+
+  // caches x/y coordinate pair to use with overlap
+  within: function(element, x, y) {
+    if (this.includeScrollOffsets)
+      return this.withinIncludingScrolloffsets(element, x, y);
+    this.xcomp = x;
+    this.ycomp = y;
+    this.offset = this.cumulativeOffset(element);
+
+    return (y >= this.offset[1] &&
+            y <  this.offset[1] + element.offsetHeight &&
+            x >= this.offset[0] &&
+            x <  this.offset[0] + element.offsetWidth);
+  },
+
+  withinIncludingScrolloffsets: function(element, x, y) {
+    var offsetcache = this.realOffset(element);
+
+    this.xcomp = x + offsetcache[0] - this.deltaX;
+    this.ycomp = y + offsetcache[1] - this.deltaY;
+    this.offset = this.cumulativeOffset(element);
+
+    return (this.ycomp >= this.offset[1] &&
+            this.ycomp <  this.offset[1] + element.offsetHeight &&
+            this.xcomp >= this.offset[0] &&
+            this.xcomp <  this.offset[0] + element.offsetWidth);
+  },
+
+  // within must be called directly before
+  overlap: function(mode, element) {
+    if (!mode) return 0;
+    if (mode == 'vertical')
+      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+        element.offsetHeight;
+    if (mode == 'horizontal')
+      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+        element.offsetWidth;
+  },
+
+  page: function(forElement) {
+    var valueT = 0, valueL = 0;
+
+    var element = forElement;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+
+      // Safari fix
+      if (element.offsetParent==document.body)
+        if (Element.getStyle(element,'position')=='absolute') break;
+
+    } while (element = element.offsetParent);
+
+    element = forElement;
+    do {
+      if (!window.opera || element.tagName=='BODY') {
+        valueT -= element.scrollTop  || 0;
+        valueL -= element.scrollLeft || 0;
+      }
+    } while (element = element.parentNode);
+
+    return [valueL, valueT];
+  },
+
+  clone: function(source, target) {
+    var options = Object.extend({
+      setLeft:    true,
+      setTop:     true,
+      setWidth:   true,
+      setHeight:  true,
+      offsetTop:  0,
+      offsetLeft: 0
+    }, arguments[2] || {})
+
+    // find page position of source
+    source = $(source);
+    var p = Position.page(source);
+
+    // find coordinate system to use
+    target = $(target);
+    var delta = [0, 0];
+    var parent = null;
+    // delta [0,0] will do fine with position: fixed elements,
+    // position:absolute needs offsetParent deltas
+    if (Element.getStyle(target,'position') == 'absolute') {
+      parent = Position.offsetParent(target);
+      delta = Position.page(parent);
+    }
+
+    // correct by body offsets (fixes Safari)
+    if (parent == document.body) {
+      delta[0] -= document.body.offsetLeft;
+      delta[1] -= document.body.offsetTop;
+    }
+
+    // set position
+    if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
+    if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
+    if(options.setWidth)  target.style.width = source.offsetWidth + 'px';
+    if(options.setHeight) target.style.height = source.offsetHeight + 'px';
+  },
+
+  absolutize: function(element) {
+    element = $(element);
+    if (element.style.position == 'absolute') return;
+    Position.prepare();
+
+    var offsets = Position.positionedOffset(element);
+    var top     = offsets[1];
+    var left    = offsets[0];
+    var width   = element.clientWidth;
+    var height  = element.clientHeight;
+
+    element._originalLeft   = left - parseFloat(element.style.left  || 0);
+    element._originalTop    = top  - parseFloat(element.style.top || 0);
+    element._originalWidth  = element.style.width;
+    element._originalHeight = element.style.height;
+
+    element.style.position = 'absolute';
+    element.style.top    = top + 'px';
+    element.style.left   = left + 'px';
+    element.style.width  = width + 'px';
+    element.style.height = height + 'px';
+  },
+
+  relativize: function(element) {
+    element = $(element);
+    if (element.style.position == 'relative') return;
+    Position.prepare();
+
+    element.style.position = 'relative';
+    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
+    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+    element.style.top    = top + 'px';
+    element.style.left   = left + 'px';
+    element.style.height = element._originalHeight;
+    element.style.width  = element._originalWidth;
+  }
+}
+
+// Safari returns margins on body which is incorrect if the child is absolutely
+// positioned.  For performance reasons, redefine Position.cumulativeOffset for
+// KHTML/WebKit only.
+if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
+  Position.cumulativeOffset = function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      if (element.offsetParent == document.body)
+        if (Element.getStyle(element, 'position') == 'absolute') break;
+
+      element = element.offsetParent;
+    } while (element);
+
+    return [valueL, valueT];
+  }
+}
+
+Element.addMethods();
+
+
+// ------------------------------------------------------------------------
+// ------------------------------------------------------------------------
+
+// The rest of this file is the actual ray tracer written by Adam
+// Burmister. It's a concatenation of the following files:
+//
+//   flog/color.js
+//   flog/light.js
+//   flog/vector.js
+//   flog/ray.js
+//   flog/scene.js
+//   flog/material/basematerial.js
+//   flog/material/solid.js
+//   flog/material/chessboard.js
+//   flog/shape/baseshape.js
+//   flog/shape/sphere.js
+//   flog/shape/plane.js
+//   flog/intersectioninfo.js
+//   flog/camera.js
+//   flog/background.js
+//   flog/engine.js
+
+
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Color = Class.create();
+
+Flog.RayTracer.Color.prototype = {
+    red : 0.0,
+    green : 0.0,
+    blue : 0.0,
+
+    initialize : function(r, g, b) {
+        if(!r) r = 0.0;
+        if(!g) g = 0.0;
+        if(!b) b = 0.0;
+
+        this.red = r;
+        this.green = g;
+        this.blue = b;
+    },
+
+    add : function(c1, c2){
+        var result = new Flog.RayTracer.Color(0,0,0);
+
+        result.red = c1.red + c2.red;
+        result.green = c1.green + c2.green;
+        result.blue = c1.blue + c2.blue;
+
+        return result;
+    },
+
+    addScalar: function(c1, s){
+        var result = new Flog.RayTracer.Color(0,0,0);
+
+        result.red = c1.red + s;
+        result.green = c1.green + s;
+        result.blue = c1.blue + s;
+
+        result.limit();
+
+        return result;
+    },
+
+    subtract: function(c1, c2){
+        var result = new Flog.RayTracer.Color(0,0,0);
+
+        result.red = c1.red - c2.red;
+        result.green = c1.green - c2.green;
+        result.blue = c1.blue - c2.blue;
+
+        return result;
+    },
+
+    multiply : function(c1, c2) {
+        var result = new Flog.RayTracer.Color(0,0,0);
+
+        result.red = c1.red * c2.red;
+        result.green = c1.green * c2.green;
+        result.blue = c1.blue * c2.blue;
+
+        return result;
+    },
+
+    multiplyScalar : function(c1, f) {
+        var result = new Flog.RayTracer.Color(0,0,0);
+
+        result.red = c1.red * f;
+        result.green = c1.green * f;
+        result.blue = c1.blue * f;
+
+        return result;
+    },
+
+    divideFactor : function(c1, f) {
+        var result = new Flog.RayTracer.Color(0,0,0);
+
+        result.red = c1.red / f;
+        result.green = c1.green / f;
+        result.blue = c1.blue / f;
+
+        return result;
+    },
+
+    limit: function(){
+        this.red = (this.red > 0.0) ? ( (this.red > 1.0) ? 1.0 : this.red ) : 0.0;
+        this.green = (this.green > 0.0) ? ( (this.green > 1.0) ? 1.0 : this.green ) : 0.0;
+        this.blue = (this.blue > 0.0) ? ( (this.blue > 1.0) ? 1.0 : this.blue ) : 0.0;
+    },
+
+    distance : function(color) {
+        var d = Math.abs(this.red - color.red) + Math.abs(this.green - color.green) + Math.abs(this.blue - color.blue);
+        return d;
+    },
+
+    blend: function(c1, c2, w){
+        var result = new Flog.RayTracer.Color(0,0,0);
+        result = Flog.RayTracer.Color.prototype.add(
+                    Flog.RayTracer.Color.prototype.multiplyScalar(c1, 1 - w),
+                    Flog.RayTracer.Color.prototype.multiplyScalar(c2, w)
+                  );
+        return result;
+    },
+
+    brightness : function() {
+        var r = Math.floor(this.red*255);
+        var g = Math.floor(this.green*255);
+        var b = Math.floor(this.blue*255);
+        return (r * 77 + g * 150 + b * 29) >> 8;
+    },
+
+    toString : function () {
+        var r = Math.floor(this.red*255);
+        var g = Math.floor(this.green*255);
+        var b = Math.floor(this.blue*255);
+
+        return "rgb("+ r +","+ g +","+ b +")";
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Light = Class.create();
+
+Flog.RayTracer.Light.prototype = {
+    position: null,
+    color: null,
+    intensity: 10.0,
+
+    initialize : function(pos, color, intensity) {
+        this.position = pos;
+        this.color = color;
+        this.intensity = (intensity ? intensity : 10.0);
+    },
+
+    getIntensity: function(distance){
+        if(distance >= intensity) return 0;
+
+        return Math.pow((intensity - distance) / strength, 0.2);
+    },
+
+    toString : function () {
+        return 'Light [' + this.position.x + ',' + this.position.y + ',' + this.position.z + ']';
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Vector = Class.create();
+
+Flog.RayTracer.Vector.prototype = {
+    x : 0.0,
+    y : 0.0,
+    z : 0.0,
+
+    initialize : function(x, y, z) {
+        this.x = (x ? x : 0);
+        this.y = (y ? y : 0);
+        this.z = (z ? z : 0);
+    },
+
+    copy: function(vector){
+        this.x = vector.x;
+        this.y = vector.y;
+        this.z = vector.z;
+    },
+
+    normalize : function() {
+        var m = this.magnitude();
+        return new Flog.RayTracer.Vector(this.x / m, this.y / m, this.z / m);
+    },
+
+    magnitude : function() {
+        return Math.sqrt((this.x * this.x) + (this.y * this.y) + (this.z * this.z));
+    },
+
+    cross : function(w) {
+        return new Flog.RayTracer.Vector(
+                                            -this.z * w.y + this.y * w.z,
+                                           this.z * w.x - this.x * w.z,
+                                          -this.y * w.x + this.x * w.y);
+    },
+
+    dot : function(w) {
+        return this.x * w.x + this.y * w.y + this.z * w.z;
+    },
+
+    add : function(v, w) {
+        return new Flog.RayTracer.Vector(w.x + v.x, w.y + v.y, w.z + v.z);
+    },
+
+    subtract : function(v, w) {
+        if(!w || !v) throw 'Vectors must be defined [' + v + ',' + w + ']';
+        return new Flog.RayTracer.Vector(v.x - w.x, v.y - w.y, v.z - w.z);
+    },
+
+    multiplyVector : function(v, w) {
+        return new Flog.RayTracer.Vector(v.x * w.x, v.y * w.y, v.z * w.z);
+    },
+
+    multiplyScalar : function(v, w) {
+        return new Flog.RayTracer.Vector(v.x * w, v.y * w, v.z * w);
+    },
+
+    toString : function () {
+        return 'Vector [' + this.x + ',' + this.y + ',' + this.z + ']';
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Ray = Class.create();
+
+Flog.RayTracer.Ray.prototype = {
+    position : null,
+    direction : null,
+    initialize : function(pos, dir) {
+        this.position = pos;
+        this.direction = dir;
+    },
+
+    toString : function () {
+        return 'Ray [' + this.position + ',' + this.direction + ']';
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Scene = Class.create();
+
+Flog.RayTracer.Scene.prototype = {
+    camera : null,
+    shapes : [],
+    lights : [],
+    background : null,
+
+    initialize : function() {
+        this.camera = new Flog.RayTracer.Camera(
+            new Flog.RayTracer.Vector(0,0,-5),
+            new Flog.RayTracer.Vector(0,0,1),
+            new Flog.RayTracer.Vector(0,1,0)
+        );
+        this.shapes = new Array();
+        this.lights = new Array();
+        this.background = new Flog.RayTracer.Background(new Flog.RayTracer.Color(0,0,0.5), 0.2);
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+if(typeof(Flog.RayTracer.Material) == 'undefined') Flog.RayTracer.Material = {};
+
+Flog.RayTracer.Material.BaseMaterial = Class.create();
+
+Flog.RayTracer.Material.BaseMaterial.prototype = {
+
+    gloss: 2.0,             // [0...infinity] 0 = matt
+    transparency: 0.0,      // 0=opaque
+    reflection: 0.0,        // [0...infinity] 0 = no reflection
+    refraction: 0.50,
+    hasTexture: false,
+
+    initialize : function() {
+
+    },
+
+    getColor: function(u, v){
+
+    },
+
+    wrapUp: function(t){
+        t = t % 2.0;
+        if(t < -1) t += 2.0;
+        if(t >= 1) t -= 2.0;
+        return t;
+    },
+
+    toString : function () {
+        return 'Material [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']';
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Material.Solid = Class.create();
+
+Flog.RayTracer.Material.Solid.prototype = Object.extend(
+    new Flog.RayTracer.Material.BaseMaterial(), {
+        initialize : function(color, reflection, refraction, transparency, gloss) {
+            this.color = color;
+            this.reflection = reflection;
+            this.transparency = transparency;
+            this.gloss = gloss;
+            this.hasTexture = false;
+        },
+
+        getColor: function(u, v){
+            return this.color;
+        },
+
+        toString : function () {
+            return 'SolidMaterial [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']';
+        }
+    }
+);
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Material.Chessboard = Class.create();
+
+Flog.RayTracer.Material.Chessboard.prototype = Object.extend(
+    new Flog.RayTracer.Material.BaseMaterial(), {
+        colorEven: null,
+        colorOdd: null,
+        density: 0.5,
+
+        initialize : function(colorEven, colorOdd, reflection, transparency, gloss, density) {
+            this.colorEven = colorEven;
+            this.colorOdd = colorOdd;
+            this.reflection = reflection;
+            this.transparency = transparency;
+            this.gloss = gloss;
+            this.density = density;
+            this.hasTexture = true;
+        },
+
+        getColor: function(u, v){
+            var t = this.wrapUp(u * this.density) * this.wrapUp(v * this.density);
+
+            if(t < 0.0)
+                return this.colorEven;
+            else
+                return this.colorOdd;
+        },
+
+        toString : function () {
+            return 'ChessMaterial [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']';
+        }
+    }
+);
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+if(typeof(Flog.RayTracer.Shape) == 'undefined') Flog.RayTracer.Shape = {};
+
+Flog.RayTracer.Shape.BaseShape = Class.create();
+
+Flog.RayTracer.Shape.BaseShape.prototype = {
+    position: null,
+    material: null,
+
+    initialize : function() {
+        this.position = new Vector(0,0,0);
+        this.material = new Flog.RayTracer.Material.SolidMaterial(
+            new Flog.RayTracer.Color(1,0,1),
+            0,
+            0,
+            0
+        );
+    },
+
+    toString : function () {
+        return 'Material [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']';
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+if(typeof(Flog.RayTracer.Shape) == 'undefined') Flog.RayTracer.Shape = {};
+
+Flog.RayTracer.Shape.Sphere = Class.create();
+
+Flog.RayTracer.Shape.Sphere.prototype = {
+    initialize : function(pos, radius, material) {
+        this.radius = radius;
+        this.position = pos;
+        this.material = material;
+    },
+
+    intersect: function(ray){
+        var info = new Flog.RayTracer.IntersectionInfo();
+        info.shape = this;
+
+        var dst = Flog.RayTracer.Vector.prototype.subtract(ray.position, this.position);
+
+        var B = dst.dot(ray.direction);
+        var C = dst.dot(dst) - (this.radius * this.radius);
+        var D = (B * B) - C;
+
+        if(D > 0){ // intersection!
+            info.isHit = true;
+            info.distance = (-B) - Math.sqrt(D);
+            info.position = Flog.RayTracer.Vector.prototype.add(
+                                                ray.position,
+                                                Flog.RayTracer.Vector.prototype.multiplyScalar(
+                                                    ray.direction,
+                                                    info.distance
+                                                )
+                                            );
+            info.normal = Flog.RayTracer.Vector.prototype.subtract(
+                                            info.position,
+                                            this.position
+                                        ).normalize();
+
+            info.color = this.material.getColor(0,0);
+        } else {
+            info.isHit = false;
+        }
+        return info;
+    },
+
+    toString : function () {
+        return 'Sphere [position=' + this.position + ', radius=' + this.radius + ']';
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+if(typeof(Flog.RayTracer.Shape) == 'undefined') Flog.RayTracer.Shape = {};
+
+Flog.RayTracer.Shape.Plane = Class.create();
+
+Flog.RayTracer.Shape.Plane.prototype = {
+    d: 0.0,
+
+    initialize : function(pos, d, material) {
+        this.position = pos;
+        this.d = d;
+        this.material = material;
+    },
+
+    intersect: function(ray){
+        var info = new Flog.RayTracer.IntersectionInfo();
+
+        var Vd = this.position.dot(ray.direction);
+        if(Vd == 0) return info; // no intersection
+
+        var t = -(this.position.dot(ray.position) + this.d) / Vd;
+        if(t <= 0) return info;
+
+        info.shape = this;
+        info.isHit = true;
+        info.position = Flog.RayTracer.Vector.prototype.add(
+                                            ray.position,
+                                            Flog.RayTracer.Vector.prototype.multiplyScalar(
+                                                ray.direction,
+                                                t
+                                            )
+                                        );
+        info.normal = this.position;
+        info.distance = t;
+
+        if(this.material.hasTexture){
+            var vU = new Flog.RayTracer.Vector(this.position.y, this.position.z, -this.position.x);
+            var vV = vU.cross(this.position);
+            var u = info.position.dot(vU);
+            var v = info.position.dot(vV);
+            info.color = this.material.getColor(u,v);
+        } else {
+            info.color = this.material.getColor(0,0);
+        }
+
+        return info;
+    },
+
+    toString : function () {
+        return 'Plane [' + this.position + ', d=' + this.d + ']';
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.IntersectionInfo = Class.create();
+
+Flog.RayTracer.IntersectionInfo.prototype = {
+    isHit: false,
+    hitCount: 0,
+    shape: null,
+    position: null,
+    normal: null,
+    color: null,
+    distance: null,
+
+    initialize : function() {
+        this.color = new Flog.RayTracer.Color(0,0,0);
+    },
+
+    toString : function () {
+        return 'Intersection [' + this.position + ']';
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Camera = Class.create();
+
+Flog.RayTracer.Camera.prototype = {
+    position: null,
+    lookAt: null,
+    equator: null,
+    up: null,
+    screen: null,
+
+    initialize : function(pos, lookAt, up) {
+        this.position = pos;
+        this.lookAt = lookAt;
+        this.up = up;
+        this.equator = lookAt.normalize().cross(this.up);
+        this.screen = Flog.RayTracer.Vector.prototype.add(this.position, this.lookAt);
+    },
+
+    getRay: function(vx, vy){
+        var pos = Flog.RayTracer.Vector.prototype.subtract(
+            this.screen,
+            Flog.RayTracer.Vector.prototype.subtract(
+                Flog.RayTracer.Vector.prototype.multiplyScalar(this.equator, vx),
+                Flog.RayTracer.Vector.prototype.multiplyScalar(this.up, vy)
+            )
+        );
+        pos.y = pos.y * -1;
+        var dir = Flog.RayTracer.Vector.prototype.subtract(
+            pos,
+            this.position
+        );
+
+        var ray = new Flog.RayTracer.Ray(pos, dir.normalize());
+
+        return ray;
+    },
+
+    toString : function () {
+        return 'Ray []';
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Background = Class.create();
+
+Flog.RayTracer.Background.prototype = {
+    color : null,
+    ambience : 0.0,
+
+    initialize : function(color, ambience) {
+        this.color = color;
+        this.ambience = ambience;
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Engine = Class.create();
+
+Flog.RayTracer.Engine.prototype = {
+    canvas: null, /* 2d context we can render to */
+
+    initialize: function(options){
+        this.options = Object.extend({
+                canvasHeight: 100,
+                canvasWidth: 100,
+                pixelWidth: 2,
+                pixelHeight: 2,
+                renderDiffuse: false,
+                renderShadows: false,
+                renderHighlights: false,
+                renderReflections: false,
+                rayDepth: 2
+            }, options || {});
+
+        this.options.canvasHeight /= this.options.pixelHeight;
+        this.options.canvasWidth /= this.options.pixelWidth;
+
+        /* TODO: dynamically include other scripts */
+    },
+
+    setPixel: function(x, y, color){
+        var pxW, pxH;
+        pxW = this.options.pixelWidth;
+        pxH = this.options.pixelHeight;
+
+        if (this.canvas) {
+          this.canvas.fillStyle = color.toString();
+          this.canvas.fillRect (x * pxW, y * pxH, pxW, pxH);
+        } else {
+          if (x ===  y) {
+            checkNumber += color.brightness();
+          }
+          // print(x * pxW, y * pxH, pxW, pxH);
+        }
+    },
+
+    renderScene: function(scene, canvas){
+        checkNumber = 0;
+        /* Get canvas */
+        if (canvas) {
+          this.canvas = canvas.getContext("2d");
+        } else {
+          this.canvas = null;
+        }
+
+        var canvasHeight = this.options.canvasHeight;
+        var canvasWidth = this.options.canvasWidth;
+
+        for(var y=0; y < canvasHeight; y++){
+            for(var x=0; x < canvasWidth; x++){
+                var yp = y * 1.0 / canvasHeight * 2 - 1;
+          		var xp = x * 1.0 / canvasWidth * 2 - 1;
+
+          		var ray = scene.camera.getRay(xp, yp);
+
+          		var color = this.getPixelColor(ray, scene);
+
+            	this.setPixel(x, y, color);
+            }
+        }
+        if (checkNumber !== 2321) {
+          throw new Error("Scene rendered incorrectly");
+        }
+    },
+
+    getPixelColor: function(ray, scene){
+        var info = this.testIntersection(ray, scene, null);
+        if(info.isHit){
+            var color = this.rayTrace(info, ray, scene, 0);
+            return color;
+        }
+        return scene.background.color;
+    },
+
+    testIntersection: function(ray, scene, exclude){
+        var hits = 0;
+        var best = new Flog.RayTracer.IntersectionInfo();
+        best.distance = 2000;
+
+        for(var i=0; i<scene.shapes.length; i++){
+            var shape = scene.shapes[i];
+
+            if(shape != exclude){
+                var info = shape.intersect(ray);
+                if(info.isHit && info.distance >= 0 && info.distance < best.distance){
+                    best = info;
+                    hits++;
+                }
+            }
+        }
+        best.hitCount = hits;
+        return best;
+    },
+
+    getReflectionRay: function(P,N,V){
+        var c1 = -N.dot(V);
+        var R1 = Flog.RayTracer.Vector.prototype.add(
+            Flog.RayTracer.Vector.prototype.multiplyScalar(N, 2*c1),
+            V
+        );
+        return new Flog.RayTracer.Ray(P, R1);
+    },
+
+    rayTrace: function(info, ray, scene, depth){
+        // Calc ambient
+        var color = Flog.RayTracer.Color.prototype.multiplyScalar(info.color, scene.background.ambience);
+        var oldColor = color;
+        var shininess = Math.pow(10, info.shape.material.gloss + 1);
+
+        for(var i=0; i<scene.lights.length; i++){
+            var light = scene.lights[i];
+
+            // Calc diffuse lighting
+            var v = Flog.RayTracer.Vector.prototype.subtract(
+                                light.position,
+                                info.position
+                            ).normalize();
+
+            if(this.options.renderDiffuse){
+                var L = v.dot(info.normal);
+                if(L > 0.0){
+                    color = Flog.RayTracer.Color.prototype.add(
+                                        color,
+                                        Flog.RayTracer.Color.prototype.multiply(
+                                            info.color,
+                                            Flog.RayTracer.Color.prototype.multiplyScalar(
+                                                light.color,
+                                                L
+                                            )
+                                        )
+                                    );
+                }
+            }
+
+            // The greater the depth the more accurate the colours, but
+            // this is exponentially (!) expensive
+            if(depth <= this.options.rayDepth){
+          // calculate reflection ray
+          if(this.options.renderReflections && info.shape.material.reflection > 0)
+          {
+              var reflectionRay = this.getReflectionRay(info.position, info.normal, ray.direction);
+              var refl = this.testIntersection(reflectionRay, scene, info.shape);
+
+              if (refl.isHit && refl.distance > 0){
+                  refl.color = this.rayTrace(refl, reflectionRay, scene, depth + 1);
+              } else {
+                  refl.color = scene.background.color;
+                        }
+
+                  color = Flog.RayTracer.Color.prototype.blend(
+                    color,
+                    refl.color,
+                    info.shape.material.reflection
+                  );
+          }
+
+                // Refraction
+                /* TODO */
+            }
+
+            /* Render shadows and highlights */
+
+            var shadowInfo = new Flog.RayTracer.IntersectionInfo();
+
+            if(this.options.renderShadows){
+                var shadowRay = new Flog.RayTracer.Ray(info.position, v);
+
+                shadowInfo = this.testIntersection(shadowRay, scene, info.shape);
+                if(shadowInfo.isHit && shadowInfo.shape != info.shape /*&& shadowInfo.shape.type != 'PLANE'*/){
+                    var vA = Flog.RayTracer.Color.prototype.multiplyScalar(color, 0.5);
+                    var dB = (0.5 * Math.pow(shadowInfo.shape.material.transparency, 0.5));
+                    color = Flog.RayTracer.Color.prototype.addScalar(vA,dB);
+                }
+            }
+
+      // Phong specular highlights
+      if(this.options.renderHighlights && !shadowInfo.isHit && info.shape.material.gloss > 0){
+        var Lv = Flog.RayTracer.Vector.prototype.subtract(
+                            info.shape.position,
+                            light.position
+                        ).normalize();
+
+        var E = Flog.RayTracer.Vector.prototype.subtract(
+                            scene.camera.position,
+                            info.shape.position
+                        ).normalize();
+
+        var H = Flog.RayTracer.Vector.prototype.subtract(
+                            E,
+                            Lv
+                        ).normalize();
+
+        var glossWeight = Math.pow(Math.max(info.normal.dot(H), 0), shininess);
+        color = Flog.RayTracer.Color.prototype.add(
+                            Flog.RayTracer.Color.prototype.multiplyScalar(light.color, glossWeight),
+                            color
+                        );
+      }
+        }
+        color.limit();
+        return color;
+    }
+};
+
+
+function renderScene(){
+    var scene = new Flog.RayTracer.Scene();
+
+    scene.camera = new Flog.RayTracer.Camera(
+                        new Flog.RayTracer.Vector(0, 0, -15),
+                        new Flog.RayTracer.Vector(-0.2, 0, 5),
+                        new Flog.RayTracer.Vector(0, 1, 0)
+                    );
+
+    scene.background = new Flog.RayTracer.Background(
+                                new Flog.RayTracer.Color(0.5, 0.5, 0.5),
+                                0.4
+                            );
+
+    var sphere = new Flog.RayTracer.Shape.Sphere(
+        new Flog.RayTracer.Vector(-1.5, 1.5, 2),
+        1.5,
+        new Flog.RayTracer.Material.Solid(
+            new Flog.RayTracer.Color(0,0.5,0.5),
+            0.3,
+            0.0,
+            0.0,
+            2.0
+        )
+    );
+
+    var sphere1 = new Flog.RayTracer.Shape.Sphere(
+        new Flog.RayTracer.Vector(1, 0.25, 1),
+        0.5,
+        new Flog.RayTracer.Material.Solid(
+            new Flog.RayTracer.Color(0.9,0.9,0.9),
+            0.1,
+            0.0,
+            0.0,
+            1.5
+        )
+    );
+
+    var plane = new Flog.RayTracer.Shape.Plane(
+                                new Flog.RayTracer.Vector(0.1, 0.9, -0.5).normalize(),
+                                1.2,
+                                new Flog.RayTracer.Material.Chessboard(
+                                    new Flog.RayTracer.Color(1,1,1),
+                                    new Flog.RayTracer.Color(0,0,0),
+                                    0.2,
+                                    0.0,
+                                    1.0,
+                                    0.7
+                                )
+                            );
+
+    scene.shapes.push(plane);
+    scene.shapes.push(sphere);
+    scene.shapes.push(sphere1);
+
+    var light = new Flog.RayTracer.Light(
+        new Flog.RayTracer.Vector(5, 10, -1),
+        new Flog.RayTracer.Color(0.8, 0.8, 0.8)
+    );
+
+    var light1 = new Flog.RayTracer.Light(
+        new Flog.RayTracer.Vector(-3, 5, -15),
+        new Flog.RayTracer.Color(0.8, 0.8, 0.8),
+        100
+    );
+
+    scene.lights.push(light);
+    scene.lights.push(light1);
+
+    var imageWidth = 100; // $F('imageWidth');
+    var imageHeight = 100; // $F('imageHeight');
+    var pixelSize = "5,5".split(','); //  $F('pixelSize').split(',');
+    var renderDiffuse = true; // $F('renderDiffuse');
+    var renderShadows = true; // $F('renderShadows');
+    var renderHighlights = true; // $F('renderHighlights');
+    var renderReflections = true; // $F('renderReflections');
+    var rayDepth = 2;//$F('rayDepth');
+
+    var raytracer = new Flog.RayTracer.Engine(
+        {
+            canvasWidth: imageWidth,
+            canvasHeight: imageHeight,
+            pixelWidth: pixelSize[0],
+            pixelHeight: pixelSize[1],
+            "renderDiffuse": renderDiffuse,
+            "renderHighlights": renderHighlights,
+            "renderShadows": renderShadows,
+            "renderReflections": renderReflections,
+            "rayDepth": rayDepth
+        }
+    );
+
+    raytracer.renderScene(scene, null, 0);
+}
+
diff --git a/deps/v8/benchmarks/regexp.js b/deps/v8/benchmarks/regexp.js
new file mode 100644
index 0000000..dce15b8
--- /dev/null
+++ b/deps/v8/benchmarks/regexp.js
@@ -0,0 +1,1614 @@
+// 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.
+
+// Automatically generated on 2009-01-30.
+
+// This benchmark is generated by loading 50 of the most popular pages
+// on the web and logging all regexp operations performed.  Each
+// operation is given a weight that is calculated from an estimate of
+// the popularity of the pages where it occurs and the number of times
+// it is executed while loading each page.  Finally the literal
+// letters in the data are encoded using ROT13 in a way that does not
+// affect how the regexps match their input.
+
+var RegRxp = new BenchmarkSuite('RegExp', 995230, [
+  new Benchmark("RegExp", runRegExpBenchmark)
+]);
+
+function runRegExpBenchmark() {
+  var re0 = /^ba/;
+  var re1 = /(((\w+):\/\/)([^\/:]*)(:(\d+))?)?([^#?]*)(\?([^#]*))?(#(.*))?/;
+  var re2 = /^\s*|\s*$/g;
+  var re3 = /\bQBZPbageby_cynprubyqre\b/;
+  var re4 = /,/;
+  var re5 = /\bQBZPbageby_cynprubyqre\b/g;
+  var re6 = /^[\s\xa0]+|[\s\xa0]+$/g;
+  var re7 = /(\d*)(\D*)/g;
+  var re8 = /=/;
+  var re9 = /(^|\s)lhv\-h(\s|$)/;
+  var str0 = 'Zbmvyyn/5.0 (Jvaqbjf; H; Jvaqbjf AG 5.1; ra-HF) NccyrJroXvg/528.9 (XUGZY, yvxr Trpxb) Puebzr/2.0.157.0 Fnsnev/528.9';
+  var re10 = /\#/g;
+  var re11 = /\./g;
+  var re12 = /'/g;
+  var re13 = /\?[\w\W]*(sevraqvq|punaaryvq|tebhcvq)=([^\&\?#]*)/i;
+  var str1 = 'Fubpxjnir Synfu 9.0  e115';
+  var re14 = /\s+/g;
+  var re15 = /^\s*(\S*(\s+\S+)*)\s*$/;
+  var re16 = /(-[a-z])/i;
+  function runBlock0() {
+    for (var i = 0; i < 6511; i++) {
+      re0.exec('pyvpx');
+    }
+    for (var i = 0; i < 1844; i++) {
+      re1.exec('uggc://jjj.snprobbx.pbz/ybtva.cuc');
+    }
+    for (var i = 0; i < 739; i++) {
+      'QBZPbageby_cynprubyqre'.replace(re2, '');
+    }
+    for (var i = 0; i < 598; i++) {
+      re1.exec('uggc://jjj.snprobbx.pbz/');
+    }
+    for (var i = 0; i < 454; i++) {
+      re1.exec('uggc://jjj.snprobbx.pbz/fepu.cuc');
+    }
+    for (var i = 0; i < 352; i++) {
+      /qqqq|qqq|qq|q|ZZZZ|ZZZ|ZZ|Z|llll|ll|l|uu|u|UU|U|zz|z|ff|f|gg|g|sss|ss|s|mmm|mm|m/g.exec('qqqq, ZZZ q, llll');
+    }
+    for (var i = 0; i < 312; i++) {
+      re3.exec('vachggrkg QBZPbageby_cynprubyqre');
+    }
+    for (var i = 0; i < 282; i++) {
+      re4.exec('/ZlFcnprUbzrcntr/Vaqrk-FvgrUbzr,10000000');
+    }
+    for (var i = 0; i < 177; i++) {
+      'vachggrkg'.replace(re5, '');
+    }
+    for (var i = 0; i < 170; i++) {
+      '528.9'.replace(re6, '');
+      re7.exec('528');
+    }
+    for (var i = 0; i < 156; i++) {
+      re8.exec('VCPhygher=ra-HF');
+      re8.exec('CersreerqPhygher=ra-HF');
+    }
+    for (var i = 0; i < 144; i++) {
+      re0.exec('xrlcerff');
+    }
+    for (var i = 0; i < 139; i++) {
+      '521'.replace(re6, '');
+      re7.exec('521');
+      re9.exec('');
+      /JroXvg\/(\S+)/.exec(str0);
+    }
+    for (var i = 0; i < 137; i++) {
+      'qvi .so_zrah'.replace(re10, '');
+      'qvi .so_zrah'.replace(/\[/g, '');
+      'qvi.so_zrah'.replace(re11, '');
+    }
+    for (var i = 0; i < 117; i++) {
+      'uvqqra_ryrz'.replace(re2, '');
+    }
+    for (var i = 0; i < 95; i++) {
+      /(?:^|;)\s*sevraqfgre_ynat=([^;]*)/.exec('sevraqfgre_naba=nvq%3Qn6ss9p85n868ro9s059pn854735956o3%26ers%3Q%26df%3Q%26vpgl%3QHF');
+    }
+    for (var i = 0; i < 93; i++) {
+      'uggc://ubzr.zlfcnpr.pbz/vaqrk.psz'.replace(re12, '');
+      re13.exec('uggc://ubzr.zlfcnpr.pbz/vaqrk.psz');
+    }
+    for (var i = 0; i < 92; i++) {
+      str1.replace(/([a-zA-Z]|\s)+/, '');
+    }
+    for (var i = 0; i < 85; i++) {
+      'svefg'.replace(re14, '');
+      'svefg'.replace(re15, '');
+      'uggc://cebsvyr.zlfcnpr.pbz/vaqrk.psz'.replace(re12, '');
+      'ynfg'.replace(re14, '');
+      'ynfg'.replace(re15, '');
+      re16.exec('qvfcynl');
+      re13.exec('uggc://cebsvyr.zlfcnpr.pbz/vaqrk.psz');
+    }
+  }
+  var re17 = /(^|[^\\])\"\\\/Qngr\((-?[0-9]+)\)\\\/\"/g;
+  var str2 = '{"anzr":"","ahzoreSbezng":{"PheeraplQrpvznyQvtvgf":2,"PheeraplQrpvznyFrcnengbe":".","VfErnqBayl":gehr,"PheeraplTebhcFvmrf":[3],"AhzoreTebhcFvmrf":[3],"CrepragTebhcFvmrf":[3],"PheeraplTebhcFrcnengbe":",","PheeraplFlzoby":"\xa4","AnAFlzoby":"AnA","PheeraplArtngvirCnggrea":0,"AhzoreArtngvirCnggrea":1,"CrepragCbfvgvirCnggrea":0,"CrepragArtngvirCnggrea":0,"ArtngvirVasvavglFlzoby":"-Vasvavgl","ArtngvirFvta":"-","AhzoreQrpvznyQvtvgf":2,"AhzoreQrpvznyFrcnengbe":".","AhzoreTebhcFrcnengbe":",","PheeraplCbfvgvirCnggrea":0,"CbfvgvirVasvavglFlzoby":"Vasvavgl","CbfvgvirFvta":"+","CrepragQrpvznyQvtvgf":2,"CrepragQrpvznyFrcnengbe":".","CrepragTebhcFrcnengbe":",","CrepragFlzoby":"%","CreZvyyrFlzoby":"\u2030","AngvirQvtvgf":["0","1","2","3","4","5","6","7","8","9"],"QvtvgFhofgvghgvba":1},"qngrGvzrSbezng":{"NZQrfvtangbe":"NZ","Pnyraqne":{"ZvaFhccbegrqQngrGvzr":"@-62135568000000@","ZnkFhccbegrqQngrGvzr":"@253402300799999@","NytbevguzGlcr":1,"PnyraqneGlcr":1,"Renf":[1],"GjbQvtvgLrneZnk":2029,"VfErnqBayl":gehr},"QngrFrcnengbe":"/","SvefgQnlBsJrrx":0,"PnyraqneJrrxEhyr":0,"ShyyQngrGvzrCnggrea":"qqqq, qq ZZZZ llll UU:zz:ff","YbatQngrCnggrea":"qqqq, qq ZZZZ llll","YbatGvzrCnggrea":"UU:zz:ff","ZbaguQnlCnggrea":"ZZZZ qq","CZQrfvtangbe":"CZ","ESP1123Cnggrea":"qqq, qq ZZZ llll UU\':\'zz\':\'ff \'TZG\'","FubegQngrCnggrea":"ZZ/qq/llll","FubegGvzrCnggrea":"UU:zz","FbegnoyrQngrGvzrCnggrea":"llll\'-\'ZZ\'-\'qq\'G\'UU\':\'zz\':\'ff","GvzrFrcnengbe":":","HavirefnyFbegnoyrQngrGvzrCnggrea":"llll\'-\'ZZ\'-\'qq UU\':\'zz\':\'ff\'M\'","LrneZbaguCnggrea":"llll ZZZZ","NooerivngrqQnlAnzrf":["Fha","Zba","Ghr","Jrq","Guh","Sev","Fng"],"FubegrfgQnlAnzrf":["Fh","Zb","Gh","Jr","Gu","Se","Fn"],"QnlAnzrf":["Fhaqnl","Zbaqnl","Ghrfqnl","Jrqarfqnl","Guhefqnl","Sevqnl","Fngheqnl"],"NooerivngrqZbaguAnzrf":["Wna","Sro","Zne","Nce","Znl","Wha","Why","Nht","Frc","Bpg","Abi","Qrp",""],"ZbaguAnzrf":["Wnahnel","Sroehnel","Znepu","Ncevy","Znl","Whar","Whyl","Nhthfg","Frcgrzore","Bpgbore","Abirzore","Qrprzore",""],"VfErnqBayl":gehr,"AngvirPnyraqneAnzr":"Tertbevna Pnyraqne","NooerivngrqZbaguTravgvirAnzrf":["Wna","Sro","Zne","Nce","Znl","Wha","Why","Nht","Frc","Bpg","Abi","Qrp",""],"ZbaguTravgvirAnzrf":["Wnahnel","Sroehnel","Znepu","Ncevy","Znl","Whar","Whyl","Nhthfg","Frcgrzore","Bpgbore","Abirzore","Qrprzore",""]}}';
+  var str3 = '{"anzr":"ra-HF","ahzoreSbezng":{"PheeraplQrpvznyQvtvgf":2,"PheeraplQrpvznyFrcnengbe":".","VfErnqBayl":snyfr,"PheeraplTebhcFvmrf":[3],"AhzoreTebhcFvmrf":[3],"CrepragTebhcFvmrf":[3],"PheeraplTebhcFrcnengbe":",","PheeraplFlzoby":"$","AnAFlzoby":"AnA","PheeraplArtngvirCnggrea":0,"AhzoreArtngvirCnggrea":1,"CrepragCbfvgvirCnggrea":0,"CrepragArtngvirCnggrea":0,"ArtngvirVasvavglFlzoby":"-Vasvavgl","ArtngvirFvta":"-","AhzoreQrpvznyQvtvgf":2,"AhzoreQrpvznyFrcnengbe":".","AhzoreTebhcFrcnengbe":",","PheeraplCbfvgvirCnggrea":0,"CbfvgvirVasvavglFlzoby":"Vasvavgl","CbfvgvirFvta":"+","CrepragQrpvznyQvtvgf":2,"CrepragQrpvznyFrcnengbe":".","CrepragTebhcFrcnengbe":",","CrepragFlzoby":"%","CreZvyyrFlzoby":"\u2030","AngvirQvtvgf":["0","1","2","3","4","5","6","7","8","9"],"QvtvgFhofgvghgvba":1},"qngrGvzrSbezng":{"NZQrfvtangbe":"NZ","Pnyraqne":{"ZvaFhccbegrqQngrGvzr":"@-62135568000000@","ZnkFhccbegrqQngrGvzr":"@253402300799999@","NytbevguzGlcr":1,"PnyraqneGlcr":1,"Renf":[1],"GjbQvtvgLrneZnk":2029,"VfErnqBayl":snyfr},"QngrFrcnengbe":"/","SvefgQnlBsJrrx":0,"PnyraqneJrrxEhyr":0,"ShyyQngrGvzrCnggrea":"qqqq, ZZZZ qq, llll u:zz:ff gg","YbatQngrCnggrea":"qqqq, ZZZZ qq, llll","YbatGvzrCnggrea":"u:zz:ff gg","ZbaguQnlCnggrea":"ZZZZ qq","CZQrfvtangbe":"CZ","ESP1123Cnggrea":"qqq, qq ZZZ llll UU\':\'zz\':\'ff \'TZG\'","FubegQngrCnggrea":"Z/q/llll","FubegGvzrCnggrea":"u:zz gg","FbegnoyrQngrGvzrCnggrea":"llll\'-\'ZZ\'-\'qq\'G\'UU\':\'zz\':\'ff","GvzrFrcnengbe":":","HavirefnyFbegnoyrQngrGvzrCnggrea":"llll\'-\'ZZ\'-\'qq UU\':\'zz\':\'ff\'M\'","LrneZbaguCnggrea":"ZZZZ, llll","NooerivngrqQnlAnzrf":["Fha","Zba","Ghr","Jrq","Guh","Sev","Fng"],"FubegrfgQnlAnzrf":["Fh","Zb","Gh","Jr","Gu","Se","Fn"],"QnlAnzrf":["Fhaqnl","Zbaqnl","Ghrfqnl","Jrqarfqnl","Guhefqnl","Sevqnl","Fngheqnl"],"NooerivngrqZbaguAnzrf":["Wna","Sro","Zne","Nce","Znl","Wha","Why","Nht","Frc","Bpg","Abi","Qrp",""],"ZbaguAnzrf":["Wnahnel","Sroehnel","Znepu","Ncevy","Znl","Whar","Whyl","Nhthfg","Frcgrzore","Bpgbore","Abirzore","Qrprzore",""],"VfErnqBayl":snyfr,"AngvirPnyraqneAnzr":"Tertbevna Pnyraqne","NooerivngrqZbaguTravgvirAnzrf":["Wna","Sro","Zne","Nce","Znl","Wha","Why","Nht","Frc","Bpg","Abi","Qrp",""],"ZbaguTravgvirAnzrf":["Wnahnel","Sroehnel","Znepu","Ncevy","Znl","Whar","Whyl","Nhthfg","Frcgrzore","Bpgbore","Abirzore","Qrprzore",""]}}';
+  var str4 = 'HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q';
+  var str5 = 'HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=';
+  var re18 = /^\s+|\s+$/g;
+  var str6 = 'uggc://jjj.snprobbx.pbz/vaqrk.cuc';
+  var re19 = /(?:^|\s+)ba(?:\s+|$)/;
+  var re20 = /[+, ]/;
+  var re21 = /ybnqrq|pbzcyrgr/;
+  var str7 = ';;jvaqbj.IjPurpxZbhfrCbfvgvbaNQ_VQ=shapgvba(r){vs(!r)ine r=jvaqbj.rirag;ine c=-1;vs(d1)c=d1.EbyybssCnary;ine bo=IjTrgBow("IjCnayNQ_VQ_"+c);vs(bo&&bo.fglyr.ivfvovyvgl=="ivfvoyr"){ine fns=IjFns?8:0;ine pheK=r.pyvragK+IjBOFpe("U")+fns,pheL=r.pyvragL+IjBOFpe("I")+fns;ine y=IjBOEC(NQ_VQ,bo,"Y"),g=IjBOEC(NQ_VQ,bo,"G");ine e=y+d1.Cnaryf[c].Jvqgu,o=g+d1.Cnaryf[c].Urvtug;vs((pheK<y)||(pheK>e)||(pheL<g)||(pheL>o)){vs(jvaqbj.IjBaEbyybssNQ_VQ)IjBaEbyybssNQ_VQ(c);ryfr IjPybfrNq(NQ_VQ,c,gehr,"");}ryfr erghea;}IjPnapryZbhfrYvfgrareNQ_VQ();};;jvaqbj.IjFrgEbyybssCnaryNQ_VQ=shapgvba(c){ine z="zbhfrzbir",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;c=IjTc(NQ_VQ,c);vs(d1&&d1.EbyybssCnary>-1)IjPnapryZbhfrYvfgrareNQ_VQ();vs(d1)d1.EbyybssCnary=c;gel{vs(q.nqqRiragYvfgrare)q.nqqRiragYvfgrare(z,s,snyfr);ryfr vs(q.nggnpuRirag)q.nggnpuRirag("ba"+z,s);}pngpu(r){}};;jvaqbj.IjPnapryZbhfrYvfgrareNQ_VQ=shapgvba(){ine z="zbhfrzbir",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;vs(d1)d1.EbyybssCnary=-1;gel{vs(q.erzbirRiragYvfgrare)q.erzbirRiragYvfgrare(z,s,snyfr);ryfr vs(q.qrgnpuRirag)q.qrgnpuRirag("ba"+z,s);}pngpu(r){}};;d1.IjTc=d2(n,c){ine nq=d1;vs(vfAnA(c)){sbe(ine v=0;v<nq.Cnaryf.yratgu;v++)vs(nq.Cnaryf[v].Anzr==c)erghea v;erghea 0;}erghea c;};;d1.IjTpy=d2(n,c,p){ine cn=d1.Cnaryf[IjTc(n,c)];vs(!cn)erghea 0;vs(vfAnA(p)){sbe(ine v=0;v<cn.Pyvpxguehf.yratgu;v++)vs(cn.Pyvpxguehf[v].Anzr==p)erghea v;erghea 0;}erghea p;};;d1.IjGenpr=d2(n,f){gel{vs(jvaqbj["Ij"+"QtQ"])jvaqbj["Ij"+"QtQ"](n,1,f);}pngpu(r){}};;d1.IjYvzvg1=d2(n,f){ine nq=d1,vh=f.fcyvg("/");sbe(ine v=0,p=0;v<vh.yratgu;v++){vs(vh[v].yratgu>0){vs(nq.FzV.yratgu>0)nq.FzV+="/";nq.FzV+=vh[v];nq.FtZ[nq.FtZ.yratgu]=snyfr;}}};;d1.IjYvzvg0=d2(n,f){ine nq=d1,vh=f.fcyvg("/");sbe(ine v=0;v<vh.yratgu;v++){vs(vh[v].yratgu>0){vs(nq.OvC.yratgu>0)nq.OvC+="/";nq.OvC+=vh[v];}}};;d1.IjRVST=d2(n,c){jvaqbj["IjCnayNQ_VQ_"+c+"_Bow"]=IjTrgBow("IjCnayNQ_VQ_"+c+"_Bow");vs(jvaqbj["IjCnayNQ_VQ_"+c+"_Bow"]==ahyy)frgGvzrbhg("IjRVST(NQ_VQ,"+c+")",d1.rvsg);};;d1.IjNavzSHC=d2(n,c){ine nq=d1;vs(c>nq.Cnaryf.yratgu)erghea;ine cna=nq.Cnaryf[c],nn=gehr,on=gehr,yn=gehr,en=gehr,cn=nq.Cnaryf[0],sf=nq.ShF,j=cn.Jvqgu,u=cn.Urvtug;vs(j=="100%"){j=sf;en=snyfr;yn=snyfr;}vs(u=="100%"){u=sf;nn=snyfr;on=snyfr;}vs(cn.YnY=="Y")yn=snyfr;vs(cn.YnY=="E")en=snyfr;vs(cn.GnY=="G")nn=snyfr;vs(cn.GnY=="O")on=snyfr;ine k=0,l=0;fjvgpu(nq.NshP%8){pnfr 0:oernx;pnfr 1:vs(nn)l=-sf;oernx;pnfr 2:k=j-sf;oernx;pnfr 3:vs(en)k=j;oernx;pnfr 4:k=j-sf;l=u-sf;oernx;pnfr 5:k=j-sf;vs(on)l=u;oernx;pnfr 6:l=u-sf;oernx;pnfr 7:vs(yn)k=-sf;l=u-sf;oernx;}vs(nq.NshP++ <nq.NshG)frgGvzrbhg(("IjNavzSHC(NQ_VQ,"+c+")"),nq.NshC);ryfr{k=-1000;l=k;}cna.YrsgBssfrg=k;cna.GbcBssfrg=l;IjNhErcb(n,c);};;d1.IjTrgErnyCbfvgvba=d2(n,b,j){erghea IjBOEC.nccyl(guvf,nethzragf);};;d1.IjPnapryGvzrbhg=d2(n,c){c=IjTc(n,c);ine cay=d1.Cnaryf[c];vs(cay&&cay.UgU!=""){pyrneGvzrbhg(cay.UgU);}};;d1.IjPnapryNyyGvzrbhgf=d2(n){vs(d1.YbpxGvzrbhgPunatrf)erghea;sbe(ine c=0;c<d1.bac;c++)IjPnapryGvzrbhg(n,c);};;d1.IjFgnegGvzrbhg=d2(n,c,bG){c=IjTc(n,c);ine cay=d1.Cnaryf[c];vs(cay&&((cay.UvqrGvzrbhgInyhr>0)||(nethzragf.yratgu==3&&bG>0))){pyrneGvzrbhg(cay.UgU);cay.UgU=frgGvzrbhg(cay.UvqrNpgvba,(nethzragf.yratgu==3?bG:cay.UvqrGvzrbhgInyhr));}};;d1.IjErfrgGvzrbhg=d2(n,c,bG){c=IjTc(n,c);IjPnapryGvzrbhg(n,c);riny("IjFgnegGvzrbhg(NQ_VQ,c"+(nethzragf.yratgu==3?",bG":"")+")");};;d1.IjErfrgNyyGvzrbhgf=d2(n){sbe(ine c=0;c<d1.bac;c++)IjErfrgGvzrbhg(n,c);};;d1.IjQrgnpure=d2(n,rig,sap){gel{vs(IjQVR5)riny("jvaqbj.qrgnpuRirag(\'ba"+rig+"\',"+sap+"NQ_VQ)");ryfr vs(!IjQVRZnp)riny("jvaqbj.erzbirRiragYvfgrare(\'"+rig+"\',"+sap+"NQ_VQ,snyfr)");}pngpu(r){}};;d1.IjPyrnaHc=d2(n){IjCvat(n,"G");ine nq=d1;sbe(ine v=0;v<nq.Cnaryf.yratgu;v++){IjUvqrCnary(n,v,gehr);}gel{IjTrgBow(nq.gya).vaareUGZY="";}pngpu(r){}vs(nq.gya!=nq.gya2)gel{IjTrgBow(nq.gya2).vaareUGZY="";}pngpu(r){}gel{d1=ahyy;}pngpu(r){}gel{IjQrgnpure(n,"haybnq","IjHayNQ_VQ");}pngpu(r){}gel{jvaqbj.IjHayNQ_VQ=ahyy;}pngpu(r){}gel{IjQrgnpure(n,"fpebyy","IjFeNQ_VQ");}pngpu(r){}gel{jvaqbj.IjFeNQ_VQ=ahyy;}pngpu(r){}gel{IjQrgnpure(n,"erfvmr","IjEmNQ_VQ");}pngpu(r){}gel{jvaqbj.IjEmNQ_VQ=ahyy;}pngpu(r){}gel{IjQrgnpure(n';
+  var str8 = ';;jvaqbj.IjPurpxZbhfrCbfvgvbaNQ_VQ=shapgvba(r){vs(!r)ine r=jvaqbj.rirag;ine c=-1;vs(jvaqbj.IjNqNQ_VQ)c=jvaqbj.IjNqNQ_VQ.EbyybssCnary;ine bo=IjTrgBow("IjCnayNQ_VQ_"+c);vs(bo&&bo.fglyr.ivfvovyvgl=="ivfvoyr"){ine fns=IjFns?8:0;ine pheK=r.pyvragK+IjBOFpe("U")+fns,pheL=r.pyvragL+IjBOFpe("I")+fns;ine y=IjBOEC(NQ_VQ,bo,"Y"),g=IjBOEC(NQ_VQ,bo,"G");ine e=y+jvaqbj.IjNqNQ_VQ.Cnaryf[c].Jvqgu,o=g+jvaqbj.IjNqNQ_VQ.Cnaryf[c].Urvtug;vs((pheK<y)||(pheK>e)||(pheL<g)||(pheL>o)){vs(jvaqbj.IjBaEbyybssNQ_VQ)IjBaEbyybssNQ_VQ(c);ryfr IjPybfrNq(NQ_VQ,c,gehr,"");}ryfr erghea;}IjPnapryZbhfrYvfgrareNQ_VQ();};;jvaqbj.IjFrgEbyybssCnaryNQ_VQ=shapgvba(c){ine z="zbhfrzbir",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;c=IjTc(NQ_VQ,c);vs(jvaqbj.IjNqNQ_VQ&&jvaqbj.IjNqNQ_VQ.EbyybssCnary>-1)IjPnapryZbhfrYvfgrareNQ_VQ();vs(jvaqbj.IjNqNQ_VQ)jvaqbj.IjNqNQ_VQ.EbyybssCnary=c;gel{vs(q.nqqRiragYvfgrare)q.nqqRiragYvfgrare(z,s,snyfr);ryfr vs(q.nggnpuRirag)q.nggnpuRirag("ba"+z,s);}pngpu(r){}};;jvaqbj.IjPnapryZbhfrYvfgrareNQ_VQ=shapgvba(){ine z="zbhfrzbir",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;vs(jvaqbj.IjNqNQ_VQ)jvaqbj.IjNqNQ_VQ.EbyybssCnary=-1;gel{vs(q.erzbirRiragYvfgrare)q.erzbirRiragYvfgrare(z,s,snyfr);ryfr vs(q.qrgnpuRirag)q.qrgnpuRirag("ba"+z,s);}pngpu(r){}};;jvaqbj.IjNqNQ_VQ.IjTc=shapgvba(n,c){ine nq=jvaqbj.IjNqNQ_VQ;vs(vfAnA(c)){sbe(ine v=0;v<nq.Cnaryf.yratgu;v++)vs(nq.Cnaryf[v].Anzr==c)erghea v;erghea 0;}erghea c;};;jvaqbj.IjNqNQ_VQ.IjTpy=shapgvba(n,c,p){ine cn=jvaqbj.IjNqNQ_VQ.Cnaryf[IjTc(n,c)];vs(!cn)erghea 0;vs(vfAnA(p)){sbe(ine v=0;v<cn.Pyvpxguehf.yratgu;v++)vs(cn.Pyvpxguehf[v].Anzr==p)erghea v;erghea 0;}erghea p;};;jvaqbj.IjNqNQ_VQ.IjGenpr=shapgvba(n,f){gel{vs(jvaqbj["Ij"+"QtQ"])jvaqbj["Ij"+"QtQ"](n,1,f);}pngpu(r){}};;jvaqbj.IjNqNQ_VQ.IjYvzvg1=shapgvba(n,f){ine nq=jvaqbj.IjNqNQ_VQ,vh=f.fcyvg("/");sbe(ine v=0,p=0;v<vh.yratgu;v++){vs(vh[v].yratgu>0){vs(nq.FzV.yratgu>0)nq.FzV+="/";nq.FzV+=vh[v];nq.FtZ[nq.FtZ.yratgu]=snyfr;}}};;jvaqbj.IjNqNQ_VQ.IjYvzvg0=shapgvba(n,f){ine nq=jvaqbj.IjNqNQ_VQ,vh=f.fcyvg("/");sbe(ine v=0;v<vh.yratgu;v++){vs(vh[v].yratgu>0){vs(nq.OvC.yratgu>0)nq.OvC+="/";nq.OvC+=vh[v];}}};;jvaqbj.IjNqNQ_VQ.IjRVST=shapgvba(n,c){jvaqbj["IjCnayNQ_VQ_"+c+"_Bow"]=IjTrgBow("IjCnayNQ_VQ_"+c+"_Bow");vs(jvaqbj["IjCnayNQ_VQ_"+c+"_Bow"]==ahyy)frgGvzrbhg("IjRVST(NQ_VQ,"+c+")",jvaqbj.IjNqNQ_VQ.rvsg);};;jvaqbj.IjNqNQ_VQ.IjNavzSHC=shapgvba(n,c){ine nq=jvaqbj.IjNqNQ_VQ;vs(c>nq.Cnaryf.yratgu)erghea;ine cna=nq.Cnaryf[c],nn=gehr,on=gehr,yn=gehr,en=gehr,cn=nq.Cnaryf[0],sf=nq.ShF,j=cn.Jvqgu,u=cn.Urvtug;vs(j=="100%"){j=sf;en=snyfr;yn=snyfr;}vs(u=="100%"){u=sf;nn=snyfr;on=snyfr;}vs(cn.YnY=="Y")yn=snyfr;vs(cn.YnY=="E")en=snyfr;vs(cn.GnY=="G")nn=snyfr;vs(cn.GnY=="O")on=snyfr;ine k=0,l=0;fjvgpu(nq.NshP%8){pnfr 0:oernx;pnfr 1:vs(nn)l=-sf;oernx;pnfr 2:k=j-sf;oernx;pnfr 3:vs(en)k=j;oernx;pnfr 4:k=j-sf;l=u-sf;oernx;pnfr 5:k=j-sf;vs(on)l=u;oernx;pnfr 6:l=u-sf;oernx;pnfr 7:vs(yn)k=-sf;l=u-sf;oernx;}vs(nq.NshP++ <nq.NshG)frgGvzrbhg(("IjNavzSHC(NQ_VQ,"+c+")"),nq.NshC);ryfr{k=-1000;l=k;}cna.YrsgBssfrg=k;cna.GbcBssfrg=l;IjNhErcb(n,c);};;jvaqbj.IjNqNQ_VQ.IjTrgErnyCbfvgvba=shapgvba(n,b,j){erghea IjBOEC.nccyl(guvf,nethzragf);};;jvaqbj.IjNqNQ_VQ.IjPnapryGvzrbhg=shapgvba(n,c){c=IjTc(n,c);ine cay=jvaqbj.IjNqNQ_VQ.Cnaryf[c];vs(cay&&cay.UgU!=""){pyrneGvzrbhg(cay.UgU);}};;jvaqbj.IjNqNQ_VQ.IjPnapryNyyGvzrbhgf=shapgvba(n){vs(jvaqbj.IjNqNQ_VQ.YbpxGvzrbhgPunatrf)erghea;sbe(ine c=0;c<jvaqbj.IjNqNQ_VQ.bac;c++)IjPnapryGvzrbhg(n,c);};;jvaqbj.IjNqNQ_VQ.IjFgnegGvzrbhg=shapgvba(n,c,bG){c=IjTc(n,c);ine cay=jvaqbj.IjNqNQ_VQ.Cnaryf[c];vs(cay&&((cay.UvqrGvzrbhgInyhr>0)||(nethzragf.yratgu==3&&bG>0))){pyrneGvzrbhg(cay.UgU);cay.UgU=frgGvzrbhg(cay.UvqrNpgvba,(nethzragf.yratgu==3?bG:cay.UvqrGvzrbhgInyhr));}};;jvaqbj.IjNqNQ_VQ.IjErfrgGvzrbhg=shapgvba(n,c,bG){c=IjTc(n,c);IjPnapryGvzrbhg(n,c);riny("IjFgnegGvzrbhg(NQ_VQ,c"+(nethzragf.yratgu==3?",bG":"")+")");};;jvaqbj.IjNqNQ_VQ.IjErfrgNyyGvzrbhgf=shapgvba(n){sbe(ine c=0;c<jvaqbj.IjNqNQ_VQ.bac;c++)IjErfrgGvzrbhg(n,c);};;jvaqbj.IjNqNQ_VQ.IjQrgnpure=shapgvba(n,rig,sap){gel{vs(IjQVR5)riny("jvaqbj.qrgnpuRirag(\'ba"+rig+"\',"+sap+"NQ_VQ)");ryfr vs(!IjQVRZnp)riny("jvaqbj.erzbir';
+  var str9 = ';;jvaqbj.IjPurpxZbhfrCbfvgvbaNQ_VQ=shapgvba(r){vs(!r)ine r=jvaqbj.rirag;ine c=-1;vs(jvaqbj.IjNqNQ_VQ)c=jvaqbj.IjNqNQ_VQ.EbyybssCnary;ine bo=IjTrgBow("IjCnayNQ_VQ_"+c);vs(bo&&bo.fglyr.ivfvovyvgl=="ivfvoyr"){ine fns=IjFns?8:0;ine pheK=r.pyvragK+IjBOFpe("U")+fns,pheL=r.pyvragL+IjBOFpe("I")+fns;ine y=IjBOEC(NQ_VQ,bo,"Y"),g=IjBOEC(NQ_VQ,bo,"G");ine e=y+jvaqbj.IjNqNQ_VQ.Cnaryf[c].Jvqgu,o=g+jvaqbj.IjNqNQ_VQ.Cnaryf[c].Urvtug;vs((pheK<y)||(pheK>e)||(pheL<g)||(pheL>o)){vs(jvaqbj.IjBaEbyybssNQ_VQ)IjBaEbyybssNQ_VQ(c);ryfr IjPybfrNq(NQ_VQ,c,gehr,"");}ryfr erghea;}IjPnapryZbhfrYvfgrareNQ_VQ();};;jvaqbj.IjFrgEbyybssCnaryNQ_VQ=shapgvba(c){ine z="zbhfrzbir",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;c=IjTc(NQ_VQ,c);vs(jvaqbj.IjNqNQ_VQ&&jvaqbj.IjNqNQ_VQ.EbyybssCnary>-1)IjPnapryZbhfrYvfgrareNQ_VQ();vs(jvaqbj.IjNqNQ_VQ)jvaqbj.IjNqNQ_VQ.EbyybssCnary=c;gel{vs(q.nqqRiragYvfgrare)q.nqqRiragYvfgrare(z,s,snyfr);ryfr vs(q.nggnpuRirag)q.nggnpuRirag("ba"+z,s);}pngpu(r){}};;jvaqbj.IjPnapryZbhfrYvfgrareNQ_VQ=shapgvba(){ine z="zbhfrzbir",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;vs(jvaqbj.IjNqNQ_VQ)jvaqbj.IjNqNQ_VQ.EbyybssCnary=-1;gel{vs(q.erzbirRiragYvfgrare)q.erzbirRiragYvfgrare(z,s,snyfr);ryfr vs(q.qrgnpuRirag)q.qrgnpuRirag("ba"+z,s);}pngpu(r){}};;jvaqbj.IjNqNQ_VQ.IjTc=d2(n,c){ine nq=jvaqbj.IjNqNQ_VQ;vs(vfAnA(c)){sbe(ine v=0;v<nq.Cnaryf.yratgu;v++)vs(nq.Cnaryf[v].Anzr==c)erghea v;erghea 0;}erghea c;};;jvaqbj.IjNqNQ_VQ.IjTpy=d2(n,c,p){ine cn=jvaqbj.IjNqNQ_VQ.Cnaryf[IjTc(n,c)];vs(!cn)erghea 0;vs(vfAnA(p)){sbe(ine v=0;v<cn.Pyvpxguehf.yratgu;v++)vs(cn.Pyvpxguehf[v].Anzr==p)erghea v;erghea 0;}erghea p;};;jvaqbj.IjNqNQ_VQ.IjGenpr=d2(n,f){gel{vs(jvaqbj["Ij"+"QtQ"])jvaqbj["Ij"+"QtQ"](n,1,f);}pngpu(r){}};;jvaqbj.IjNqNQ_VQ.IjYvzvg1=d2(n,f){ine nq=jvaqbj.IjNqNQ_VQ,vh=f.fcyvg("/");sbe(ine v=0,p=0;v<vh.yratgu;v++){vs(vh[v].yratgu>0){vs(nq.FzV.yratgu>0)nq.FzV+="/";nq.FzV+=vh[v];nq.FtZ[nq.FtZ.yratgu]=snyfr;}}};;jvaqbj.IjNqNQ_VQ.IjYvzvg0=d2(n,f){ine nq=jvaqbj.IjNqNQ_VQ,vh=f.fcyvg("/");sbe(ine v=0;v<vh.yratgu;v++){vs(vh[v].yratgu>0){vs(nq.OvC.yratgu>0)nq.OvC+="/";nq.OvC+=vh[v];}}};;jvaqbj.IjNqNQ_VQ.IjRVST=d2(n,c){jvaqbj["IjCnayNQ_VQ_"+c+"_Bow"]=IjTrgBow("IjCnayNQ_VQ_"+c+"_Bow");vs(jvaqbj["IjCnayNQ_VQ_"+c+"_Bow"]==ahyy)frgGvzrbhg("IjRVST(NQ_VQ,"+c+")",jvaqbj.IjNqNQ_VQ.rvsg);};;jvaqbj.IjNqNQ_VQ.IjNavzSHC=d2(n,c){ine nq=jvaqbj.IjNqNQ_VQ;vs(c>nq.Cnaryf.yratgu)erghea;ine cna=nq.Cnaryf[c],nn=gehr,on=gehr,yn=gehr,en=gehr,cn=nq.Cnaryf[0],sf=nq.ShF,j=cn.Jvqgu,u=cn.Urvtug;vs(j=="100%"){j=sf;en=snyfr;yn=snyfr;}vs(u=="100%"){u=sf;nn=snyfr;on=snyfr;}vs(cn.YnY=="Y")yn=snyfr;vs(cn.YnY=="E")en=snyfr;vs(cn.GnY=="G")nn=snyfr;vs(cn.GnY=="O")on=snyfr;ine k=0,l=0;fjvgpu(nq.NshP%8){pnfr 0:oernx;pnfr 1:vs(nn)l=-sf;oernx;pnfr 2:k=j-sf;oernx;pnfr 3:vs(en)k=j;oernx;pnfr 4:k=j-sf;l=u-sf;oernx;pnfr 5:k=j-sf;vs(on)l=u;oernx;pnfr 6:l=u-sf;oernx;pnfr 7:vs(yn)k=-sf;l=u-sf;oernx;}vs(nq.NshP++ <nq.NshG)frgGvzrbhg(("IjNavzSHC(NQ_VQ,"+c+")"),nq.NshC);ryfr{k=-1000;l=k;}cna.YrsgBssfrg=k;cna.GbcBssfrg=l;IjNhErcb(n,c);};;jvaqbj.IjNqNQ_VQ.IjTrgErnyCbfvgvba=d2(n,b,j){erghea IjBOEC.nccyl(guvf,nethzragf);};;jvaqbj.IjNqNQ_VQ.IjPnapryGvzrbhg=d2(n,c){c=IjTc(n,c);ine cay=jvaqbj.IjNqNQ_VQ.Cnaryf[c];vs(cay&&cay.UgU!=""){pyrneGvzrbhg(cay.UgU);}};;jvaqbj.IjNqNQ_VQ.IjPnapryNyyGvzrbhgf=d2(n){vs(jvaqbj.IjNqNQ_VQ.YbpxGvzrbhgPunatrf)erghea;sbe(ine c=0;c<jvaqbj.IjNqNQ_VQ.bac;c++)IjPnapryGvzrbhg(n,c);};;jvaqbj.IjNqNQ_VQ.IjFgnegGvzrbhg=d2(n,c,bG){c=IjTc(n,c);ine cay=jvaqbj.IjNqNQ_VQ.Cnaryf[c];vs(cay&&((cay.UvqrGvzrbhgInyhr>0)||(nethzragf.yratgu==3&&bG>0))){pyrneGvzrbhg(cay.UgU);cay.UgU=frgGvzrbhg(cay.UvqrNpgvba,(nethzragf.yratgu==3?bG:cay.UvqrGvzrbhgInyhr));}};;jvaqbj.IjNqNQ_VQ.IjErfrgGvzrbhg=d2(n,c,bG){c=IjTc(n,c);IjPnapryGvzrbhg(n,c);riny("IjFgnegGvzrbhg(NQ_VQ,c"+(nethzragf.yratgu==3?",bG":"")+")");};;jvaqbj.IjNqNQ_VQ.IjErfrgNyyGvzrbhgf=d2(n){sbe(ine c=0;c<jvaqbj.IjNqNQ_VQ.bac;c++)IjErfrgGvzrbhg(n,c);};;jvaqbj.IjNqNQ_VQ.IjQrgnpure=d2(n,rig,sap){gel{vs(IjQVR5)riny("jvaqbj.qrgnpuRirag(\'ba"+rig+"\',"+sap+"NQ_VQ)");ryfr vs(!IjQVRZnp)riny("jvaqbj.erzbirRiragYvfgrare(\'"+rig+"\',"+sap+"NQ_VQ,snyfr)");}pngpu(r){}};;jvaqbj.IjNqNQ_VQ.IjPyrna';
+  function runBlock1() {
+    for (var i = 0; i < 81; i++) {
+      re8.exec('VC=74.125.75.1');
+    }
+    for (var i = 0; i < 78; i++) {
+      '9.0  e115'.replace(/(\s)+e/, '');
+      'k'.replace(/./, '');
+      str2.replace(re17, '');
+      str3.replace(re17, '');
+      re8.exec('144631658');
+      re8.exec('Pbhagel=IIZ%3Q');
+      re8.exec('Pbhagel=IIZ=');
+      re8.exec('CersreerqPhygherCraqvat=');
+      re8.exec(str4);
+      re8.exec(str5);
+      re8.exec('__hgzp=144631658');
+      re8.exec('gvzrMbar=-8');
+      re8.exec('gvzrMbar=0');
+      /Fnsnev\/(\d+\.\d+)/.exec(str0);
+      re3.exec('vachggrkg  QBZPbageby_cynprubyqre');
+      re0.exec('xrlqbja');
+      re0.exec('xrlhc');
+    }
+    for (var i = 0; i < 77; i++) {
+      'uggc://zrffntvat.zlfcnpr.pbz/vaqrk.psz'.replace(re12, '');
+      re13.exec('uggc://zrffntvat.zlfcnpr.pbz/vaqrk.psz');
+    }
+    for (var i = 0; i < 73; i++) {
+      'FrffvbaFgbentr=%7O%22GnoThvq%22%3N%7O%22thvq%22%3N1231367125017%7Q%7Q'.replace(re18, '');
+    }
+    for (var i = 0; i < 72; i++) {
+      re1.exec(str6);
+    }
+    for (var i = 0; i < 71; i++) {
+      re19.exec('');
+    }
+    for (var i = 0; i < 70; i++) {
+      '3.5.0.0'.replace(re11, '');
+      str7.replace(/d1/g, '');
+      str8.replace(/NQ_VQ/g, '');
+      str9.replace(/d2/g, '');
+      'NI%3Q1_CI%3Q1_PI%3Q1_EI%3Q1_HI%3Q1_HP%3Q1_IC%3Q0.0.0.0_IH%3Q0'.replace(/_/g, '');
+      'svz_zlfcnpr_ubzrcntr_abgybttrqva,svz_zlfcnpr_aba_HTP,svz_zlfcnpr_havgrq-fgngrf'.split(re20);
+      re21.exec('ybnqvat');
+    }
+    for (var i = 0; i < 68; i++) {
+      re1.exec('#');
+      /(?:ZFVR.(\d+\.\d+))|(?:(?:Sversbk|TenaCnenqvfb|Vprjrnfry).(\d+\.\d+))|(?:Bcren.(\d+\.\d+))|(?:NccyrJroXvg.(\d+(?:\.\d+)?))/.exec(str0);
+      /(Znp BF K)|(Jvaqbjf;)/.exec(str0);
+      /Trpxb\/([0-9]+)/.exec(str0);
+      re21.exec('ybnqrq');
+    }
+    for (var i = 0; i < 49; i++) {
+      re16.exec('pbybe');
+    }
+    for (var i = 0; i < 44; i++) {
+      'uggc://sevraqf.zlfcnpr.pbz/vaqrk.psz'.replace(re12, '');
+      re13.exec('uggc://sevraqf.zlfcnpr.pbz/vaqrk.psz');
+    }
+  }
+  var re22 = /\bso_zrah\b/;
+  var re23 = /^(?:(?:[^:\/?#]+):)?(?:\/\/(?:[^\/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?/;
+  var re24 = /uggcf?:\/\/([^\/]+\.)?snprobbx\.pbz\//;
+  var re25 = /"/g;
+  var re26 = /^([^?#]+)(?:\?([^#]*))?(#.*)?/;
+  function runBlock2() {
+    for (var i = 0; i < 40; i++) {
+      'fryrpgrq'.replace(re14, '');
+      'fryrpgrq'.replace(re15, '');
+    }
+    for (var i = 0; i < 39; i++) {
+      'vachggrkg uvqqra_ryrz'.replace(/\buvqqra_ryrz\b/g, '');
+      re3.exec('vachggrkg ');
+      re3.exec('vachggrkg');
+      re22.exec('HVYvaxOhggba');
+      re22.exec('HVYvaxOhggba_E');
+      re22.exec('HVYvaxOhggba_EJ');
+      re22.exec('zrah_ybtva_pbagnvare');
+      /\buvqqra_ryrz\b/.exec('vachgcnffjbeq');
+    }
+    for (var i = 0; i < 37; i++) {
+      re8.exec('111soqs57qo8o8480qo18sor2011r3n591q7s6s37r120904');
+      re8.exec('SbeprqRkcvengvba=633669315660164980');
+      re8.exec('FrffvbaQQS2=111soqs57qo8o8480qo18sor2011r3n591q7s6s37r120904');
+    }
+    for (var i = 0; i < 35; i++) {
+      'puvyq p1 svefg'.replace(re14, '');
+      'puvyq p1 svefg'.replace(re15, '');
+      'sylbhg pybfrq'.replace(re14, '');
+      'sylbhg pybfrq'.replace(re15, '');
+    }
+    for (var i = 0; i < 34; i++) {
+      re19.exec('gno2');
+      re19.exec('gno3');
+      re8.exec('44132r503660');
+      re8.exec('SbeprqRkcvengvba=633669316860113296');
+      re8.exec('AFP_zp_dfctwzs-aowb_80=44132r503660');
+      re8.exec('FrffvbaQQS2=s6r4579npn4rn2135s904r0s75pp1o5334p6s6pospo12696');
+      re8.exec('s6r4579npn4rn2135s904r0s75pp1o5334p6s6pospo12696');
+    }
+    for (var i = 0; i < 32; i++) {
+      /puebzr/i.exec(str0);
+    }
+    for (var i = 0; i < 31; i++) {
+      'uggc://jjj.snprobbx.pbz/'.replace(re23, '');
+      re8.exec('SbeprqRkcvengvba=633669358527244818');
+      re8.exec('VC=66.249.85.130');
+      re8.exec('FrffvbaQQS2=s15q53p9n372sn76npr13o271n4s3p5r29p235746p908p58');
+      re8.exec('s15q53p9n372sn76npr13o271n4s3p5r29p235746p908p58');
+      re24.exec('uggc://jjj.snprobbx.pbz/');
+    }
+    for (var i = 0; i < 30; i++) {
+      '419'.replace(re6, '');
+      /(?:^|\s+)gvzrfgnzc(?:\s+|$)/.exec('gvzrfgnzc');
+      re7.exec('419');
+    }
+    for (var i = 0; i < 29; i++) {
+      'uggc://jjj.snprobbx.pbz/ybtva.cuc'.replace(re23, '');
+    }
+    for (var i = 0; i < 28; i++) {
+      'Funer guvf tnqtrg'.replace(re25, '');
+      'Funer guvf tnqtrg'.replace(re12, '');
+      re26.exec('uggc://jjj.tbbtyr.pbz/vt/qverpgbel');
+    }
+  }
+  var re27 = /-\D/g;
+  var re28 = /\bnpgvingr\b/;
+  var re29 = /%2R/gi;
+  var re30 = /%2S/gi;
+  var re31 = /^(mu-(PA|GJ)|wn|xb)$/;
+  var re32 = /\s?;\s?/;
+  var re33 = /%\w?$/;
+  var re34 = /TNQP=([^;]*)/i;
+  var str10 = 'FrffvbaQQS2=111soqs57qo8o8480qo18sor2011r3n591q7s6s37r120904; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669315660164980&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=';
+  var str11 = 'FrffvbaQQS2=111soqs57qo8o8480qo18sor2011r3n591q7s6s37r120904; __hgzm=144631658.1231363570.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.3426875219718084000.1231363570.1231363570.1231363570.1; __hgzo=144631658.0.10.1231363570; __hgzp=144631658; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669315660164980&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q';
+  var str12 = 'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231363514065&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231363514065&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Subzr.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1326469221.1231363557&tn_fvq=1231363557&tn_uvq=1114636509&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22';
+  var str13 = 'ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669315660164980&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q';
+  var str14 = 'ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669315660164980&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=';
+  var re35 = /[<>]/g;
+  var str15 = 'FrffvbaQQS2=s6r4579npn4rn2135s904r0s75pp1o5334p6s6pospo12696; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669316860113296&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_dfctwzs-aowb_80=44132r503660';
+  var str16 = 'FrffvbaQQS2=s6r4579npn4rn2135s904r0s75pp1o5334p6s6pospo12696; AFP_zp_dfctwzs-aowb_80=44132r503660; __hgzm=144631658.1231363638.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.965867047679498800.1231363638.1231363638.1231363638.1; __hgzo=144631658.0.10.1231363638; __hgzp=144631658; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669316860113296&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q';
+  var str17 = 'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231363621014&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231363621014&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Scebsvyr.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=348699119.1231363624&tn_fvq=1231363624&tn_uvq=895511034&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22';
+  var str18 = 'uggc://jjj.yrobapbva.se/yv';
+  var str19 = 'ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669316860113296&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q';
+  var str20 = 'ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669316860113296&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=';
+  function runBlock3() {
+    for (var i = 0; i < 27; i++) {
+      'e115'.replace(/[A-Za-z]/g, '');
+    }
+    for (var i = 0; i < 23; i++) {
+      'qvfcynl'.replace(re27, '');
+      'cbfvgvba'.replace(re27, '');
+    }
+    for (var i = 0; i < 22; i++) {
+      'unaqyr'.replace(re14, '');
+      'unaqyr'.replace(re15, '');
+      'yvar'.replace(re14, '');
+      'yvar'.replace(re15, '');
+      'cnerag puebzr6 fvatyr1 gno'.replace(re14, '');
+      'cnerag puebzr6 fvatyr1 gno'.replace(re15, '');
+      'fyvqre'.replace(re14, '');
+      'fyvqre'.replace(re15, '');
+      re28.exec('');
+    }
+    for (var i = 0; i < 21; i++) {
+      'uggc://jjj.zlfcnpr.pbz/'.replace(re12, '');
+      re13.exec('uggc://jjj.zlfcnpr.pbz/');
+    }
+    for (var i = 0; i < 20; i++) {
+      'cntrivrj'.replace(re29, '');
+      'cntrivrj'.replace(re30, '');
+      re19.exec('ynfg');
+      re19.exec('ba svefg');
+      re8.exec('VC=74.125.75.3');
+    }
+    for (var i = 0; i < 19; i++) {
+      re31.exec('ra');
+    }
+    for (var i = 0; i < 18; i++) {
+      str10.split(re32);
+      str11.split(re32);
+      str12.replace(re33, '');
+      re8.exec('144631658.0.10.1231363570');
+      re8.exec('144631658.1231363570.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)');
+      re8.exec('144631658.3426875219718084000.1231363570.1231363570.1231363570.1');
+      re8.exec(str13);
+      re8.exec(str14);
+      re8.exec('__hgzn=144631658.3426875219718084000.1231363570.1231363570.1231363570.1');
+      re8.exec('__hgzo=144631658.0.10.1231363570');
+      re8.exec('__hgzm=144631658.1231363570.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)');
+      re34.exec(str10);
+      re34.exec(str11);
+    }
+    for (var i = 0; i < 17; i++) {
+      str0.match(/zfvr/gi);
+      str0.match(/bcren/gi);
+      str15.split(re32);
+      str16.split(re32);
+      'ohggba'.replace(re14, '');
+      'ohggba'.replace(re15, '');
+      'puvyq p1 svefg sylbhg pybfrq'.replace(re14, '');
+      'puvyq p1 svefg sylbhg pybfrq'.replace(re15, '');
+      'pvgvrf'.replace(re14, '');
+      'pvgvrf'.replace(re15, '');
+      'pybfrq'.replace(re14, '');
+      'pybfrq'.replace(re15, '');
+      'qry'.replace(re14, '');
+      'qry'.replace(re15, '');
+      'uqy_zba'.replace(re14, '');
+      'uqy_zba'.replace(re15, '');
+      str17.replace(re33, '');
+      str18.replace(/%3P/g, '');
+      str18.replace(/%3R/g, '');
+      str18.replace(/%3q/g, '');
+      str18.replace(re35, '');
+      'yvaxyvfg16'.replace(re14, '');
+      'yvaxyvfg16'.replace(re15, '');
+      'zvahf'.replace(re14, '');
+      'zvahf'.replace(re15, '');
+      'bcra'.replace(re14, '');
+      'bcra'.replace(re15, '');
+      'cnerag puebzr5 fvatyr1 ps NU'.replace(re14, '');
+      'cnerag puebzr5 fvatyr1 ps NU'.replace(re15, '');
+      'cynlre'.replace(re14, '');
+      'cynlre'.replace(re15, '');
+      'cyhf'.replace(re14, '');
+      'cyhf'.replace(re15, '');
+      'cb_uqy'.replace(re14, '');
+      'cb_uqy'.replace(re15, '');
+      'hyJVzt'.replace(re14, '');
+      'hyJVzt'.replace(re15, '');
+      re8.exec('144631658.0.10.1231363638');
+      re8.exec('144631658.1231363638.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)');
+      re8.exec('144631658.965867047679498800.1231363638.1231363638.1231363638.1');
+      re8.exec('4413268q3660');
+      re8.exec('4ss747o77904333q374or84qrr1s9r0nprp8r5q81534o94n');
+      re8.exec('SbeprqRkcvengvba=633669321699093060');
+      re8.exec('VC=74.125.75.20');
+      re8.exec(str19);
+      re8.exec(str20);
+      re8.exec('AFP_zp_tfwsbrg-aowb_80=4413268q3660');
+      re8.exec('FrffvbaQQS2=4ss747o77904333q374or84qrr1s9r0nprp8r5q81534o94n');
+      re8.exec('__hgzn=144631658.965867047679498800.1231363638.1231363638.1231363638.1');
+      re8.exec('__hgzo=144631658.0.10.1231363638');
+      re8.exec('__hgzm=144631658.1231363638.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)');
+      re34.exec(str15);
+      re34.exec(str16);
+    }
+  }
+  var re36 = /uers|fep|fryrpgrq/;
+  var re37 = /\s*([+>~\s])\s*([a-zA-Z#.*:\[])/g;
+  var re38 = /^(\w+|\*)$/;
+  var str21 = 'FrffvbaQQS2=s15q53p9n372sn76npr13o271n4s3p5r29p235746p908p58; ZFPhygher=VC=66.249.85.130&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669358527244818&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=';
+  var str22 = 'FrffvbaQQS2=s15q53p9n372sn76npr13o271n4s3p5r29p235746p908p58; __hgzm=144631658.1231367822.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.4127520630321984500.1231367822.1231367822.1231367822.1; __hgzo=144631658.0.10.1231367822; __hgzp=144631658; ZFPhygher=VC=66.249.85.130&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669358527244818&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q';
+  var str23 = 'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231367803797&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231367803797&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Szrffntvat.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1192552091.1231367807&tn_fvq=1231367807&tn_uvq=1155446857&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22';
+  var str24 = 'ZFPhygher=VC=66.249.85.130&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669358527244818&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q';
+  var str25 = 'ZFPhygher=VC=66.249.85.130&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669358527244818&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=';
+  var str26 = 'hy.ynat-fryrpgbe';
+  var re39 = /\\/g;
+  var re40 = / /g;
+  var re41 = /\/\xc4\/t/;
+  var re42 = /\/\xd6\/t/;
+  var re43 = /\/\xdc\/t/;
+  var re44 = /\/\xdf\/t/;
+  var re45 = /\/\xe4\/t/;
+  var re46 = /\/\xf6\/t/;
+  var re47 = /\/\xfc\/t/;
+  var re48 = /\W/g;
+  var re49 = /uers|fep|fglyr/;
+  function runBlock4() {
+    for (var i = 0; i < 16; i++) {
+      ''.replace(/\*/g, '');
+      /\bnpgvir\b/.exec('npgvir');
+      /sversbk/i.exec(str0);
+      re36.exec('glcr');
+      /zfvr/i.exec(str0);
+      /bcren/i.exec(str0);
+    }
+    for (var i = 0; i < 15; i++) {
+      str21.split(re32);
+      str22.split(re32);
+      'uggc://ohyyrgvaf.zlfcnpr.pbz/vaqrk.psz'.replace(re12, '');
+      str23.replace(re33, '');
+      'yv'.replace(re37, '');
+      'yv'.replace(re18, '');
+      re8.exec('144631658.0.10.1231367822');
+      re8.exec('144631658.1231367822.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)');
+      re8.exec('144631658.4127520630321984500.1231367822.1231367822.1231367822.1');
+      re8.exec(str24);
+      re8.exec(str25);
+      re8.exec('__hgzn=144631658.4127520630321984500.1231367822.1231367822.1231367822.1');
+      re8.exec('__hgzo=144631658.0.10.1231367822');
+      re8.exec('__hgzm=144631658.1231367822.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)');
+      re34.exec(str21);
+      re34.exec(str22);
+      /\.([\w-]+)|\[(\w+)(?:([!*^$~|]?=)["']?(.*?)["']?)?\]|:([\w-]+)(?:\(["']?(.*?)?["']?\)|$)/g.exec(str26);
+      re13.exec('uggc://ohyyrgvaf.zlfcnpr.pbz/vaqrk.psz');
+      re38.exec('yv');
+    }
+    for (var i = 0; i < 14; i++) {
+      ''.replace(re18, '');
+      '9.0  e115'.replace(/(\s+e|\s+o[0-9]+)/, '');
+      'Funer guvf tnqtrg'.replace(/</g, '');
+      'Funer guvf tnqtrg'.replace(/>/g, '');
+      'Funer guvf tnqtrg'.replace(re39, '');
+      'uggc://cebsvyrrqvg.zlfcnpr.pbz/vaqrk.psz'.replace(re12, '');
+      'grnfre'.replace(re40, '');
+      'grnfre'.replace(re41, '');
+      'grnfre'.replace(re42, '');
+      'grnfre'.replace(re43, '');
+      'grnfre'.replace(re44, '');
+      'grnfre'.replace(re45, '');
+      'grnfre'.replace(re46, '');
+      'grnfre'.replace(re47, '');
+      'grnfre'.replace(re48, '');
+      re16.exec('znetva-gbc');
+      re16.exec('cbfvgvba');
+      re19.exec('gno1');
+      re9.exec('qz');
+      re9.exec('qg');
+      re9.exec('zbqobk');
+      re9.exec('zbqobkva');
+      re9.exec('zbqgvgyr');
+      re13.exec('uggc://cebsvyrrqvg.zlfcnpr.pbz/vaqrk.psz');
+      re26.exec('/vt/znvytnqtrg');
+      re49.exec('glcr');
+    }
+  }
+  var re50 = /(?:^|\s+)fryrpgrq(?:\s+|$)/;
+  var re51 = /\&/g;
+  var re52 = /\+/g;
+  var re53 = /\?/g;
+  var re54 = /\t/g;
+  var re55 = /(\$\{nqiHey\})|(\$nqiHey\b)/g;
+  var re56 = /(\$\{cngu\})|(\$cngu\b)/g;
+  function runBlock5() {
+    for (var i = 0; i < 13; i++) {
+      'purpx'.replace(re14, '');
+      'purpx'.replace(re15, '');
+      'pvgl'.replace(re14, '');
+      'pvgl'.replace(re15, '');
+      'qrpe fyvqrgrkg'.replace(re14, '');
+      'qrpe fyvqrgrkg'.replace(re15, '');
+      'svefg fryrpgrq'.replace(re14, '');
+      'svefg fryrpgrq'.replace(re15, '');
+      'uqy_rag'.replace(re14, '');
+      'uqy_rag'.replace(re15, '');
+      'vape fyvqrgrkg'.replace(re14, '');
+      'vape fyvqrgrkg'.replace(re15, '');
+      'vachggrkg QBZPbageby_cynprubyqre'.replace(re5, '');
+      'cnerag puebzr6 fvatyr1 gno fryrpgrq'.replace(re14, '');
+      'cnerag puebzr6 fvatyr1 gno fryrpgrq'.replace(re15, '');
+      'cb_guz'.replace(re14, '');
+      'cb_guz'.replace(re15, '');
+      'fhozvg'.replace(re14, '');
+      'fhozvg'.replace(re15, '');
+      re50.exec('');
+      /NccyrJroXvg\/([^\s]*)/.exec(str0);
+      /XUGZY/.exec(str0);
+    }
+    for (var i = 0; i < 12; i++) {
+      '${cebg}://${ubfg}${cngu}/${dz}'.replace(/(\$\{cebg\})|(\$cebg\b)/g, '');
+      '1'.replace(re40, '');
+      '1'.replace(re10, '');
+      '1'.replace(re51, '');
+      '1'.replace(re52, '');
+      '1'.replace(re53, '');
+      '1'.replace(re39, '');
+      '1'.replace(re54, '');
+      '9.0  e115'.replace(/^(.*)\..*$/, '');
+      '9.0  e115'.replace(/^.*e(.*)$/, '');
+      '<!-- ${nqiHey} -->'.replace(re55, '');
+      '<fpevcg glcr="grkg/wninfpevcg" fep="${nqiHey}"></fpevcg>'.replace(re55, '');
+      str1.replace(/^.*\s+(\S+\s+\S+$)/, '');
+      'tzk%2Subzrcntr%2Sfgneg%2Sqr%2S'.replace(re30, '');
+      'tzk'.replace(re30, '');
+      'uggc://${ubfg}${cngu}/${dz}'.replace(/(\$\{ubfg\})|(\$ubfg\b)/g, '');
+      'uggc://nqpyvrag.hvzfrei.arg${cngu}/${dz}'.replace(re56, '');
+      'uggc://nqpyvrag.hvzfrei.arg/wf.at/${dz}'.replace(/(\$\{dz\})|(\$dz\b)/g, '');
+      'frpgvba'.replace(re29, '');
+      'frpgvba'.replace(re30, '');
+      'fvgr'.replace(re29, '');
+      'fvgr'.replace(re30, '');
+      'fcrpvny'.replace(re29, '');
+      'fcrpvny'.replace(re30, '');
+      re36.exec('anzr');
+      /e/.exec('9.0  e115');
+    }
+  }
+  var re57 = /##yv4##/gi;
+  var re58 = /##yv16##/gi;
+  var re59 = /##yv19##/gi;
+  var str27 = '<hy pynff="nqi">##yv4##Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.##yv19##Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.##yv16##Ybgf bs fgbentr &#40;5 TO&#41; - zber pbby fghss ba gur jnl.##OE## ##OE## ##N##Yrnea zber##/N##</hy>';
+  var str28 = '<hy pynff="nqi"><yv vq="YvOYG4" fglyr="onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg4.cat)">Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.##yv19##Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.##yv16##Ybgf bs fgbentr &#40;5 TO&#41; - zber pbby fghss ba gur jnl.##OE## ##OE## ##N##Yrnea zber##/N##</hy>';
+  var str29 = '<hy pynff="nqi"><yv vq="YvOYG4" fglyr="onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg4.cat)">Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.##yv19##Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.<yv vq="YvOYG16" fglyr="onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg16.cat)">Ybgf bs fgbentr &#40;5 TO&#41; - zber pbby fghss ba gur jnl.##OE## ##OE## ##N##Yrnea zber##/N##</hy>';
+  var str30 = '<hy pynff="nqi"><yv vq="YvOYG4" fglyr="onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg4.cat)">Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.<yv vq="YvOYG19" fglyr="onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg19.cat)">Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.<yv vq="YvOYG16" fglyr="onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg16.cat)">Ybgf bs fgbentr &#40;5 TO&#41; - zber pbby fghss ba gur jnl.##OE## ##OE## ##N##Yrnea zber##/N##</hy>';
+  var str31 = '<hy pynff="nqi"><yv vq="YvOYG4" fglyr="onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg4.cat)">Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.<yv vq="YvOYG19" fglyr="onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg19.cat)">Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.<yv vq="YvOYG16" fglyr="onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg16.cat)">Ybgf bs fgbentr &#40;5 TO&#41; - zber pbby fghss ba gur jnl.<oe> <oe> ##N##Yrnea zber##/N##</hy>';
+  var str32 = '<hy pynff="nqi"><yv vq="YvOYG4" fglyr="onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg4.cat)">Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.<yv vq="YvOYG19" fglyr="onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg19.cat)">Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.<yv vq="YvOYG16" fglyr="onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg16.cat)">Ybgf bs fgbentr &#40;5 TO&#41; - zber pbby fghss ba gur jnl.<oe> <oe> <n uers="uggc://znvy.yvir.pbz/znvy/nobhg.nfck" gnetrg="_oynax">Yrnea zber##/N##</hy>';
+  var str33 = 'Bar Jvaqbjf Yvir VQ trgf lbh vagb <o>Ubgznvy</o>, <o>Zrffratre</o>, <o>Kobk YVIR</o> \u2014 naq bgure cynprf lbh frr #~#argjbexybtb#~#';
+  var re60 = /(?:^|\s+)bss(?:\s+|$)/;
+  var re61 = /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/;
+  var re62 = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;
+  var str34 = '${1}://${2}${3}${4}${5}';
+  var str35 = ' O=6gnyg0g4znrrn&o=3&f=gc; Q=_lyu=K3bQZGSxnT4lZzD3OS9GNmV3ZGLkAQxRpTyxNmRlZmRmAmNkAQLRqTImqNZjOUEgpTjQnJ5xMKtgoN--; SCF=qy';
+  function runBlock6() {
+    for (var i = 0; i < 11; i++) {
+      str27.replace(/##yv0##/gi, '');
+      str27.replace(re57, '');
+      str28.replace(re58, '');
+      str29.replace(re59, '');
+      str30.replace(/##\/o##/gi, '');
+      str30.replace(/##\/v##/gi, '');
+      str30.replace(/##\/h##/gi, '');
+      str30.replace(/##o##/gi, '');
+      str30.replace(/##oe##/gi, '');
+      str30.replace(/##v##/gi, '');
+      str30.replace(/##h##/gi, '');
+      str31.replace(/##n##/gi, '');
+      str32.replace(/##\/n##/gi, '');
+      str33.replace(/#~#argjbexybtb#~#/g, '');
+      / Zbovyr\//.exec(str0);
+      /##yv1##/gi.exec(str27);
+      /##yv10##/gi.exec(str28);
+      /##yv11##/gi.exec(str28);
+      /##yv12##/gi.exec(str28);
+      /##yv13##/gi.exec(str28);
+      /##yv14##/gi.exec(str28);
+      /##yv15##/gi.exec(str28);
+      re58.exec(str28);
+      /##yv17##/gi.exec(str29);
+      /##yv18##/gi.exec(str29);
+      re59.exec(str29);
+      /##yv2##/gi.exec(str27);
+      /##yv20##/gi.exec(str30);
+      /##yv21##/gi.exec(str30);
+      /##yv22##/gi.exec(str30);
+      /##yv23##/gi.exec(str30);
+      /##yv3##/gi.exec(str27);
+      re57.exec(str27);
+      /##yv5##/gi.exec(str28);
+      /##yv6##/gi.exec(str28);
+      /##yv7##/gi.exec(str28);
+      /##yv8##/gi.exec(str28);
+      /##yv9##/gi.exec(str28);
+      re8.exec('473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29');
+      re8.exec('SbeprqRkcvengvba=633669325184628362');
+      re8.exec('FrffvbaQQS2=473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29');
+      /AbxvnA[^\/]*/.exec(str0);
+    }
+    for (var i = 0; i < 10; i++) {
+      ' bss'.replace(/(?:^|\s+)bss(?:\s+|$)/g, '');
+      str34.replace(/(\$\{0\})|(\$0\b)/g, '');
+      str34.replace(/(\$\{1\})|(\$1\b)/g, '');
+      str34.replace(/(\$\{pbzcyrgr\})|(\$pbzcyrgr\b)/g, '');
+      str34.replace(/(\$\{sentzrag\})|(\$sentzrag\b)/g, '');
+      str34.replace(/(\$\{ubfgcbeg\})|(\$ubfgcbeg\b)/g, '');
+      str34.replace(re56, '');
+      str34.replace(/(\$\{cebgbpby\})|(\$cebgbpby\b)/g, '');
+      str34.replace(/(\$\{dhrel\})|(\$dhrel\b)/g, '');
+      'nqfvmr'.replace(re29, '');
+      'nqfvmr'.replace(re30, '');
+      'uggc://${2}${3}${4}${5}'.replace(/(\$\{2\})|(\$2\b)/g, '');
+      'uggc://wf.hv-cbegny.qr${3}${4}${5}'.replace(/(\$\{3\})|(\$3\b)/g, '');
+      'arjf'.replace(re40, '');
+      'arjf'.replace(re41, '');
+      'arjf'.replace(re42, '');
+      'arjf'.replace(re43, '');
+      'arjf'.replace(re44, '');
+      'arjf'.replace(re45, '');
+      'arjf'.replace(re46, '');
+      'arjf'.replace(re47, '');
+      'arjf'.replace(re48, '');
+      / PC=i=(\d+)&oe=(.)/.exec(str35);
+      re60.exec(' ');
+      re60.exec(' bss');
+      re60.exec('');
+      re19.exec(' ');
+      re19.exec('svefg ba');
+      re19.exec('ynfg vtaber');
+      re19.exec('ba');
+      re9.exec('scnq so ');
+      re9.exec('zrqvgobk');
+      re9.exec('hsgy');
+      re9.exec('lhv-h');
+      /Fnsnev|Xbadhrebe|XUGZY/gi.exec(str0);
+      re61.exec('uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/onfr.wf');
+      re62.exec('#Ybtva_rznvy');
+    }
+  }
+  var re63 = /\{0\}/g;
+  var str36 = 'FrffvbaQQS2=4ss747o77904333q374or84qrr1s9r0nprp8r5q81534o94n; ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669321699093060&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_tfwsbrg-aowb_80=4413268q3660';
+  var str37 = 'FrffvbaQQS2=4ss747o77904333q374or84qrr1s9r0nprp8r5q81534o94n; AFP_zp_tfwsbrg-aowb_80=4413268q3660; __hgzm=144631658.1231364074.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.2294274870215848400.1231364074.1231364074.1231364074.1; __hgzo=144631658.0.10.1231364074; __hgzp=144631658; ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669321699093060&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q';
+  var str38 = 'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231364057761&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231364057761&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Ssevraqf.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1667363813.1231364061&tn_fvq=1231364061&tn_uvq=1917563877&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22';
+  var str39 = 'ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669321699093060&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q';
+  var str40 = 'ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669321699093060&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=';
+  function runBlock7() {
+    for (var i = 0; i < 9; i++) {
+      '0'.replace(re40, '');
+      '0'.replace(re10, '');
+      '0'.replace(re51, '');
+      '0'.replace(re52, '');
+      '0'.replace(re53, '');
+      '0'.replace(re39, '');
+      '0'.replace(re54, '');
+      'Lrf'.replace(re40, '');
+      'Lrf'.replace(re10, '');
+      'Lrf'.replace(re51, '');
+      'Lrf'.replace(re52, '');
+      'Lrf'.replace(re53, '');
+      'Lrf'.replace(re39, '');
+      'Lrf'.replace(re54, '');
+    }
+    for (var i = 0; i < 8; i++) {
+      'Pybfr {0}'.replace(re63, '');
+      'Bcra {0}'.replace(re63, '');
+      str36.split(re32);
+      str37.split(re32);
+      'puvyq p1 svefg gnournqref'.replace(re14, '');
+      'puvyq p1 svefg gnournqref'.replace(re15, '');
+      'uqy_fcb'.replace(re14, '');
+      'uqy_fcb'.replace(re15, '');
+      'uvag'.replace(re14, '');
+      'uvag'.replace(re15, '');
+      str38.replace(re33, '');
+      'yvfg'.replace(re14, '');
+      'yvfg'.replace(re15, '');
+      'at_bhgre'.replace(re30, '');
+      'cnerag puebzr5 qbhoyr2 NU'.replace(re14, '');
+      'cnerag puebzr5 qbhoyr2 NU'.replace(re15, '');
+      'cnerag puebzr5 dhnq5 ps NU osyvax zbarl'.replace(re14, '');
+      'cnerag puebzr5 dhnq5 ps NU osyvax zbarl'.replace(re15, '');
+      'cnerag puebzr6 fvatyr1'.replace(re14, '');
+      'cnerag puebzr6 fvatyr1'.replace(re15, '');
+      'cb_qrs'.replace(re14, '');
+      'cb_qrs'.replace(re15, '');
+      'gnopbagrag'.replace(re14, '');
+      'gnopbagrag'.replace(re15, '');
+      'iv_svefg_gvzr'.replace(re30, '');
+      /(^|.)(ronl|qri-ehf3.wbg)(|fgberf|zbgbef|yvirnhpgvbaf|jvxv|rkcerff|punggre).(pbz(|.nh|.pa|.ux|.zl|.ft|.oe|.zk)|pb(.hx|.xe|.am)|pn|qr|se|vg|ay|or|ng|pu|vr|va|rf|cy|cu|fr)$/i.exec('cntrf.ronl.pbz');
+      re8.exec('144631658.0.10.1231364074');
+      re8.exec('144631658.1231364074.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)');
+      re8.exec('144631658.2294274870215848400.1231364074.1231364074.1231364074.1');
+      re8.exec('4413241q3660');
+      re8.exec('SbeprqRkcvengvba=633669357391353591');
+      re8.exec(str39);
+      re8.exec(str40);
+      re8.exec('AFP_zp_kkk-gdzogv_80=4413241q3660');
+      re8.exec('FrffvbaQQS2=p98s8o9q42nr21or1r61pqorn1n002nsss569635984s6qp7');
+      re8.exec('__hgzn=144631658.2294274870215848400.1231364074.1231364074.1231364074.1');
+      re8.exec('__hgzo=144631658.0.10.1231364074');
+      re8.exec('__hgzm=144631658.1231364074.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)');
+      re8.exec('p98s8o9q42nr21or1r61pqorn1n002nsss569635984s6qp7');
+      re34.exec(str36);
+      re34.exec(str37);
+    }
+  }
+  var re64 = /\b[a-z]/g;
+  var re65 = /^uggc:\/\//;
+  var re66 = /(?:^|\s+)qvfnoyrq(?:\s+|$)/;
+  var str41 = 'uggc://cebsvyr.zlfcnpr.pbz/Zbqhyrf/Nccyvpngvbaf/Cntrf/Pnainf.nfck';
+  function runBlock8() {
+    for (var i = 0; i < 7; i++) {
+      str1.match(/\d+/g);
+      'nsgre'.replace(re64, '');
+      'orsber'.replace(re64, '');
+      'obggbz'.replace(re64, '');
+      'ohvygva_jrngure.kzy'.replace(re65, '');
+      'ohggba'.replace(re37, '');
+      'ohggba'.replace(re18, '');
+      'qngrgvzr.kzy'.replace(re65, '');
+      'uggc://eff.paa.pbz/eff/paa_gbcfgbevrf.eff'.replace(re65, '');
+      'vachg'.replace(re37, '');
+      'vachg'.replace(re18, '');
+      'vafvqr'.replace(re64, '');
+      'cbvagre'.replace(re27, '');
+      'cbfvgvba'.replace(/[A-Z]/g, '');
+      'gbc'.replace(re27, '');
+      'gbc'.replace(re64, '');
+      'hy'.replace(re37, '');
+      'hy'.replace(re18, '');
+      str26.replace(re37, '');
+      str26.replace(re18, '');
+      'lbhghor_vtbbtyr/i2/lbhghor.kzy'.replace(re65, '');
+      'm-vaqrk'.replace(re27, '');
+      /#([\w-]+)/.exec(str26);
+      re16.exec('urvtug');
+      re16.exec('znetvaGbc');
+      re16.exec('jvqgu');
+      re19.exec('gno0 svefg ba');
+      re19.exec('gno0 ba');
+      re19.exec('gno4 ynfg');
+      re19.exec('gno4');
+      re19.exec('gno5');
+      re19.exec('gno6');
+      re19.exec('gno7');
+      re19.exec('gno8');
+      /NqborNVE\/([^\s]*)/.exec(str0);
+      /NccyrJroXvg\/([^ ]*)/.exec(str0);
+      /XUGZY/gi.exec(str0);
+      /^(?:obql|ugzy)$/i.exec('YV');
+      re38.exec('ohggba');
+      re38.exec('vachg');
+      re38.exec('hy');
+      re38.exec(str26);
+      /^(\w+|\*)/.exec(str26);
+      /znp|jva|yvahk/i.exec('Jva32');
+      /eton?\([\d\s,]+\)/.exec('fgngvp');
+    }
+    for (var i = 0; i < 6; i++) {
+      ''.replace(/\r/g, '');
+      '/'.replace(re40, '');
+      '/'.replace(re10, '');
+      '/'.replace(re51, '');
+      '/'.replace(re52, '');
+      '/'.replace(re53, '');
+      '/'.replace(re39, '');
+      '/'.replace(re54, '');
+      'uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/{0}?[NDO]&{1}&{2}&[NDR]'.replace(re63, '');
+      str41.replace(re12, '');
+      'uggc://jjj.snprobbx.pbz/fepu.cuc'.replace(re23, '');
+      'freivpr'.replace(re40, '');
+      'freivpr'.replace(re41, '');
+      'freivpr'.replace(re42, '');
+      'freivpr'.replace(re43, '');
+      'freivpr'.replace(re44, '');
+      'freivpr'.replace(re45, '');
+      'freivpr'.replace(re46, '');
+      'freivpr'.replace(re47, '');
+      'freivpr'.replace(re48, '');
+      /((ZFVR\s+([6-9]|\d\d)\.))/.exec(str0);
+      re66.exec('');
+      re50.exec('fryrpgrq');
+      re8.exec('8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn');
+      re8.exec('SbeprqRkcvengvba=633669340386893867');
+      re8.exec('VC=74.125.75.17');
+      re8.exec('FrffvbaQQS2=8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn');
+      /Xbadhrebe|Fnsnev|XUGZY/.exec(str0);
+      re13.exec(str41);
+      re49.exec('unfsbphf');
+    }
+  }
+  var re67 = /zrah_byq/g;
+  var str42 = 'FrffvbaQQS2=473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29; ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669325184628362&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=';
+  var str43 = 'FrffvbaQQS2=473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29; __hgzm=144631658.1231364380.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.3931862196947939300.1231364380.1231364380.1231364380.1; __hgzo=144631658.0.10.1231364380; __hgzp=144631658; ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669325184628362&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q';
+  var str44 = 'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_vzntrf_wf&qg=1231364373088&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231364373088&punaary=svz_zlfcnpr_hfre-ivrj-pbzzragf%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Spbzzrag.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1158737789.1231364375&tn_fvq=1231364375&tn_uvq=415520832&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22';
+  var str45 = 'ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669325184628362&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q';
+  var str46 = 'ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669325184628362&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=';
+  var re68 = /^([#.]?)((?:[\w\u0128-\uffff*_-]|\\.)*)/;
+  var re69 = /\{1\}/g;
+  var re70 = /\s+/;
+  var re71 = /(\$\{4\})|(\$4\b)/g;
+  var re72 = /(\$\{5\})|(\$5\b)/g;
+  var re73 = /\{2\}/g;
+  var re74 = /[^+>] [^+>]/;
+  var re75 = /\bucpyv\s*=\s*([^;]*)/i;
+  var re76 = /\bucuvqr\s*=\s*([^;]*)/i;
+  var re77 = /\bucfie\s*=\s*([^;]*)/i;
+  var re78 = /\bhfucjrn\s*=\s*([^;]*)/i;
+  var re79 = /\bmvc\s*=\s*([^;]*)/i;
+  var re80 = /^((?:[\w\u0128-\uffff*_-]|\\.)+)(#)((?:[\w\u0128-\uffff*_-]|\\.)+)/;
+  var re81 = /^([>+~])\s*(\w*)/i;
+  var re82 = /^>\s*((?:[\w\u0128-\uffff*_-]|\\.)+)/;
+  var re83 = /^[\s[]?shapgvba/;
+  var re84 = /v\/g.tvs#(.*)/i;
+  var str47 = '#Zbq-Vasb-Vasb-WninFpevcgUvag';
+  var str48 = ',n.svryqOgaPnapry';
+  var str49 = 'FrffvbaQQS2=p98s8o9q42nr21or1r61pqorn1n002nsss569635984s6qp7; ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669357391353591&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_kkk-gdzogv_80=4413241q3660';
+  var str50 = 'FrffvbaQQS2=p98s8o9q42nr21or1r61pqorn1n002nsss569635984s6qp7; AFP_zp_kkk-gdzogv_80=4413241q3660; AFP_zp_kkk-aowb_80=4413235p3660; __hgzm=144631658.1231367708.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.2770915348920628700.1231367708.1231367708.1231367708.1; __hgzo=144631658.0.10.1231367708; __hgzp=144631658; ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669357391353591&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q';
+  var str51 = 'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231367691141&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231367691141&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Sjjj.zlfcnpr.pbz%2S&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=320757904.1231367694&tn_fvq=1231367694&tn_uvq=1758792003&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22';
+  var str52 = 'uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/f55332979829981?[NDO]&aqu=1&g=7%2S0%2S2009%2014%3N38%3N42%203%20480&af=zfacbegny&cntrAnzr=HF%20UCZFSGJ&t=uggc%3N%2S%2Sjjj.zfa.pbz%2S&f=1024k768&p=24&x=L&oj=994&ou=634&uc=A&{2}&[NDR]';
+  var str53 = 'cnerag puebzr6 fvatyr1 gno fryrpgrq ovaq qbhoyr2 ps';
+  var str54 = 'ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669357391353591&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q';
+  var str55 = 'ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669357391353591&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=';
+  var str56 = 'ne;ng;nh;or;oe;pn;pu;py;pa;qr;qx;rf;sv;se;to;ux;vq;vr;va;vg;wc;xe;zk;zl;ay;ab;am;cu;cy;cg;eh;fr;ft;gu;ge;gj;mn;';
+  var str57 = 'ZP1=I=3&THVQ=6nnpr9q661804s33nnop45nosqp17q85; zu=ZFSG; PHYGHER=RA-HF; SyvtugTebhcVq=97; SyvtugVq=OnfrCntr; ucfie=Z:5|S:5|G:5|R:5|Q:oyh|J:S; ucpyv=J.U|Y.|F.|E.|H.Y|P.|U.; hfucjrn=jp:HFPN0746; ZHVQ=Q783SN9O14054831N4869R51P0SO8886&GHVQ=1';
+  var str58 = 'ZP1=I=3&THVQ=6nnpr9q661804s33nnop45nosqp17q85; zu=ZFSG; PHYGHER=RA-HF; SyvtugTebhcVq=97; SyvtugVq=OnfrCntr; ucfie=Z:5|S:5|G:5|R:5|Q:oyh|J:S; ucpyv=J.U|Y.|F.|E.|H.Y|P.|U.; hfucjrn=jp:HFPN0746; ZHVQ=Q783SN9O14054831N4869R51P0SO8886';
+  var str59 = 'ZP1=I=3&THVQ=6nnpr9q661804s33nnop45nosqp17q85; zu=ZFSG; PHYGHER=RA-HF; SyvtugTebhcVq=97; SyvtugVq=OnfrCntr; ucfie=Z:5|S:5|G:5|R:5|Q:oyh|J:S; ucpyv=J.U|Y.|F.|E.|H.Y|P.|U.; hfucjrn=jp:HFPN0746; ZHVQ=Q783SN9O14054831N4869R51P0SO8886; mvc=m:94043|yn:37.4154|yb:-122.0585|p:HF|ue:1';
+  var str60 = 'ZP1=I=3&THVQ=6nnpr9q661804s33nnop45nosqp17q85; zu=ZFSG; PHYGHER=RA-HF; SyvtugTebhcVq=97; SyvtugVq=OnfrCntr; ucfie=Z:5|S:5|G:5|R:5|Q:oyh|J:S; ucpyv=J.U|Y.|F.|E.|H.Y|P.|U.; hfucjrn=jp:HFPN0746; ZHVQ=Q783SN9O14054831N4869R51P0SO8886; mvc=m:94043|yn:37.4154|yb:-122.0585|p:HF';
+  var str61 = 'uggc://gx2.fgp.f-zfa.pbz/oe/uc/11/ra-hf/pff/v/g.tvs#uggc://gx2.fgo.f-zfa.pbz/v/29/4RQP4969777N048NPS4RRR3PO2S7S.wct';
+  var str62 = 'uggc://gx2.fgp.f-zfa.pbz/oe/uc/11/ra-hf/pff/v/g.tvs#uggc://gx2.fgo.f-zfa.pbz/v/OQ/63NP9O94NS5OQP1249Q9S1ROP7NS3.wct';
+  var str63 = 'zbmvyyn/5.0 (jvaqbjf; h; jvaqbjf ag 5.1; ra-hf) nccyrjroxvg/528.9 (xugzy, yvxr trpxb) puebzr/2.0.157.0 fnsnev/528.9';
+  function runBlock9() {
+    for (var i = 0; i < 5; i++) {
+      str42.split(re32);
+      str43.split(re32);
+      'svz_zlfcnpr_hfre-ivrj-pbzzragf,svz_zlfcnpr_havgrq-fgngrf'.split(re20);
+      str44.replace(re33, '');
+      'zrah_arj zrah_arj_gbttyr zrah_gbttyr'.replace(re67, '');
+      'zrah_byq zrah_byq_gbttyr zrah_gbttyr'.replace(re67, '');
+      re8.exec('102n9o0o9pq60132qn0337rr867p75953502q2s27s2s5r98');
+      re8.exec('144631658.0.10.1231364380');
+      re8.exec('144631658.1231364380.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)');
+      re8.exec('144631658.3931862196947939300.1231364380.1231364380.1231364380.1');
+      re8.exec('441326q33660');
+      re8.exec('SbeprqRkcvengvba=633669341278771470');
+      re8.exec(str45);
+      re8.exec(str46);
+      re8.exec('AFP_zp_dfctwzssrwh-aowb_80=441326q33660');
+      re8.exec('FrffvbaQQS2=102n9o0o9pq60132qn0337rr867p75953502q2s27s2s5r98');
+      re8.exec('__hgzn=144631658.3931862196947939300.1231364380.1231364380.1231364380.1');
+      re8.exec('__hgzo=144631658.0.10.1231364380');
+      re8.exec('__hgzm=144631658.1231364380.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)');
+    }
+    for (var i = 0; i < 4; i++) {
+      ' yvfg1'.replace(re14, '');
+      ' yvfg1'.replace(re15, '');
+      ' yvfg2'.replace(re14, '');
+      ' yvfg2'.replace(re15, '');
+      ' frneputebhc1'.replace(re14, '');
+      ' frneputebhc1'.replace(re15, '');
+      str47.replace(re68, '');
+      str47.replace(re18, '');
+      ''.replace(/&/g, '');
+      ''.replace(re35, '');
+      '(..-{0})(\|(\d+)|)'.replace(re63, '');
+      str48.replace(re18, '');
+      '//vzt.jro.qr/vij/FC/${cngu}/${anzr}/${inyhr}?gf=${abj}'.replace(re56, '');
+      '//vzt.jro.qr/vij/FC/tzk_uc/${anzr}/${inyhr}?gf=${abj}'.replace(/(\$\{anzr\})|(\$anzr\b)/g, '');
+      '<fcna pynff="urnq"><o>Jvaqbjf Yvir Ubgznvy</o></fcna><fcna pynff="zft">{1}</fcna>'.replace(re69, '');
+      '<fcna pynff="urnq"><o>{0}</o></fcna><fcna pynff="zft">{1}</fcna>'.replace(re63, '');
+      '<fcna pynff="fvtahc"><n uers=uggc://jjj.ubgznvy.pbz><o>{1}</o></n></fcna>'.replace(re69, '');
+      '<fcna pynff="fvtahc"><n uers={0}><o>{1}</o></n></fcna>'.replace(re63, '');
+      'Vzntrf'.replace(re15, '');
+      'ZFA'.replace(re15, '');
+      'Zncf'.replace(re15, '');
+      'Zbq-Vasb-Vasb-WninFpevcgUvag'.replace(re39, '');
+      'Arjf'.replace(re15, '');
+      str49.split(re32);
+      str50.split(re32);
+      'Ivqrb'.replace(re15, '');
+      'Jro'.replace(re15, '');
+      'n'.replace(re39, '');
+      'nwnkFgneg'.split(re70);
+      'nwnkFgbc'.split(re70);
+      'ovaq'.replace(re14, '');
+      'ovaq'.replace(re15, '');
+      'oevatf lbh zber. Zber fcnpr (5TO), zber frphevgl, fgvyy serr.'.replace(re63, '');
+      'puvyq p1 svefg qrpx'.replace(re14, '');
+      'puvyq p1 svefg qrpx'.replace(re15, '');
+      'puvyq p1 svefg qbhoyr2'.replace(re14, '');
+      'puvyq p1 svefg qbhoyr2'.replace(re15, '');
+      'puvyq p2 ynfg'.replace(re14, '');
+      'puvyq p2 ynfg'.replace(re15, '');
+      'puvyq p2'.replace(re14, '');
+      'puvyq p2'.replace(re15, '');
+      'puvyq p3'.replace(re14, '');
+      'puvyq p3'.replace(re15, '');
+      'puvyq p4 ynfg'.replace(re14, '');
+      'puvyq p4 ynfg'.replace(re15, '');
+      'pbclevtug'.replace(re14, '');
+      'pbclevtug'.replace(re15, '');
+      'qZFAZR_1'.replace(re14, '');
+      'qZFAZR_1'.replace(re15, '');
+      'qbhoyr2 ps'.replace(re14, '');
+      'qbhoyr2 ps'.replace(re15, '');
+      'qbhoyr2'.replace(re14, '');
+      'qbhoyr2'.replace(re15, '');
+      'uqy_arj'.replace(re14, '');
+      'uqy_arj'.replace(re15, '');
+      'uc_fubccvatobk'.replace(re30, '');
+      'ugzy%2Rvq'.replace(re29, '');
+      'ugzy%2Rvq'.replace(re30, '');
+      str51.replace(re33, '');
+      'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/cebgbglcr.wf${4}${5}'.replace(re71, '');
+      'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/cebgbglcr.wf${5}'.replace(re72, '');
+      str52.replace(re73, '');
+      'uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/f55332979829981?[NDO]&{1}&{2}&[NDR]'.replace(re69, '');
+      'vztZFSG'.replace(re14, '');
+      'vztZFSG'.replace(re15, '');
+      'zfasbbg1 ps'.replace(re14, '');
+      'zfasbbg1 ps'.replace(re15, '');
+      str53.replace(re14, '');
+      str53.replace(re15, '');
+      'cnerag puebzr6 fvatyr1 gno fryrpgrq ovaq'.replace(re14, '');
+      'cnerag puebzr6 fvatyr1 gno fryrpgrq ovaq'.replace(re15, '');
+      'cevznel'.replace(re14, '');
+      'cevznel'.replace(re15, '');
+      'erpgnatyr'.replace(re30, '');
+      'frpbaqnel'.replace(re14, '');
+      'frpbaqnel'.replace(re15, '');
+      'haybnq'.split(re70);
+      '{0}{1}1'.replace(re63, '');
+      '|{1}1'.replace(re69, '');
+      /(..-HF)(\|(\d+)|)/i.exec('xb-xe,ra-va,gu-gu');
+      re4.exec('/ZlFcnprNccf/NccPnainf,45000012');
+      re8.exec('144631658.0.10.1231367708');
+      re8.exec('144631658.1231367708.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)');
+      re8.exec('144631658.2770915348920628700.1231367708.1231367708.1231367708.1');
+      re8.exec('4413235p3660');
+      re8.exec('441327q73660');
+      re8.exec('9995p6rp12rrnr893334ro7nq70o7p64p69rqn844prs1473');
+      re8.exec('SbeprqRkcvengvba=633669350559478880');
+      re8.exec(str54);
+      re8.exec(str55);
+      re8.exec('AFP_zp_dfctwzs-aowb_80=441327q73660');
+      re8.exec('AFP_zp_kkk-aowb_80=4413235p3660');
+      re8.exec('FrffvbaQQS2=9995p6rp12rrnr893334ro7nq70o7p64p69rqn844prs1473');
+      re8.exec('__hgzn=144631658.2770915348920628700.1231367708.1231367708.1231367708.1');
+      re8.exec('__hgzo=144631658.0.10.1231367708');
+      re8.exec('__hgzm=144631658.1231367708.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)');
+      re34.exec(str49);
+      re34.exec(str50);
+      /ZFVR\s+5[.]01/.exec(str0);
+      /HF(?=;)/i.exec(str56);
+      re74.exec(str47);
+      re28.exec('svefg npgvir svefgNpgvir');
+      re28.exec('ynfg');
+      /\bp:(..)/i.exec('m:94043|yn:37.4154|yb:-122.0585|p:HF');
+      re75.exec(str57);
+      re75.exec(str58);
+      re76.exec(str57);
+      re76.exec(str58);
+      re77.exec(str57);
+      re77.exec(str58);
+      /\bhfucce\s*=\s*([^;]*)/i.exec(str59);
+      re78.exec(str57);
+      re78.exec(str58);
+      /\bjci\s*=\s*([^;]*)/i.exec(str59);
+      re79.exec(str58);
+      re79.exec(str60);
+      re79.exec(str59);
+      /\|p:([a-z]{2})/i.exec('m:94043|yn:37.4154|yb:-122.0585|p:HF|ue:1');
+      re80.exec(str47);
+      re61.exec('cebgbglcr.wf');
+      re68.exec(str47);
+      re81.exec(str47);
+      re82.exec(str47);
+      /^Fubpxjnir Synfu (\d)/.exec(str1);
+      /^Fubpxjnir Synfu (\d+)/.exec(str1);
+      re83.exec('[bowrpg tybony]');
+      re62.exec(str47);
+      re84.exec(str61);
+      re84.exec(str62);
+      /jroxvg/.exec(str63);
+    }
+  }
+  var re85 = /eaq_zbqobkva/;
+  var str64 = '1231365729213';
+  var str65 = '74.125.75.3-1057165600.29978900';
+  var str66 = '74.125.75.3-1057165600.29978900.1231365730214';
+  var str67 = 'Frnepu%20Zvpebfbsg.pbz';
+  var str68 = 'FrffvbaQQS2=8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn; ZFPhygher=VC=74.125.75.17&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669340386893867&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=';
+  var str69 = 'FrffvbaQQS2=8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn; __hgzm=144631658.1231365779.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.1877536177953918500.1231365779.1231365779.1231365779.1; __hgzo=144631658.0.10.1231365779; __hgzp=144631658; ZFPhygher=VC=74.125.75.17&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669340386893867&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q';
+  var str70 = 'I=3%26THVQ=757q3ss871q44o7o805n8113n5p72q52';
+  var str71 = 'I=3&THVQ=757q3ss871q44o7o805n8113n5p72q52';
+  var str72 = 'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231365765292&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231365765292&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Sohyyrgvaf.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1579793869.1231365768&tn_fvq=1231365768&tn_uvq=2056210897&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22';
+  var str73 = 'frnepu.zvpebfbsg.pbz';
+  var str74 = 'frnepu.zvpebfbsg.pbz/';
+  var str75 = 'ZFPhygher=VC=74.125.75.17&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669340386893867&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q';
+  var str76 = 'ZFPhygher=VC=74.125.75.17&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669340386893867&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=';
+  function runBlock10() {
+    for (var i = 0; i < 3; i++) {
+      '%3Szxg=ra-HF'.replace(re39, '');
+      '-8'.replace(re40, '');
+      '-8'.replace(re10, '');
+      '-8'.replace(re51, '');
+      '-8'.replace(re52, '');
+      '-8'.replace(re53, '');
+      '-8'.replace(re39, '');
+      '-8'.replace(re54, '');
+      '1.5'.replace(re40, '');
+      '1.5'.replace(re10, '');
+      '1.5'.replace(re51, '');
+      '1.5'.replace(re52, '');
+      '1.5'.replace(re53, '');
+      '1.5'.replace(re39, '');
+      '1.5'.replace(re54, '');
+      '1024k768'.replace(re40, '');
+      '1024k768'.replace(re10, '');
+      '1024k768'.replace(re51, '');
+      '1024k768'.replace(re52, '');
+      '1024k768'.replace(re53, '');
+      '1024k768'.replace(re39, '');
+      '1024k768'.replace(re54, '');
+      str64.replace(re40, '');
+      str64.replace(re10, '');
+      str64.replace(re51, '');
+      str64.replace(re52, '');
+      str64.replace(re53, '');
+      str64.replace(re39, '');
+      str64.replace(re54, '');
+      '14'.replace(re40, '');
+      '14'.replace(re10, '');
+      '14'.replace(re51, '');
+      '14'.replace(re52, '');
+      '14'.replace(re53, '');
+      '14'.replace(re39, '');
+      '14'.replace(re54, '');
+      '24'.replace(re40, '');
+      '24'.replace(re10, '');
+      '24'.replace(re51, '');
+      '24'.replace(re52, '');
+      '24'.replace(re53, '');
+      '24'.replace(re39, '');
+      '24'.replace(re54, '');
+      str65.replace(re40, '');
+      str65.replace(re10, '');
+      str65.replace(re51, '');
+      str65.replace(re52, '');
+      str65.replace(re53, '');
+      str65.replace(re39, '');
+      str65.replace(re54, '');
+      str66.replace(re40, '');
+      str66.replace(re10, '');
+      str66.replace(re51, '');
+      str66.replace(re52, '');
+      str66.replace(re53, '');
+      str66.replace(re39, '');
+      str66.replace(re54, '');
+      '9.0'.replace(re40, '');
+      '9.0'.replace(re10, '');
+      '9.0'.replace(re51, '');
+      '9.0'.replace(re52, '');
+      '9.0'.replace(re53, '');
+      '9.0'.replace(re39, '');
+      '9.0'.replace(re54, '');
+      '994k634'.replace(re40, '');
+      '994k634'.replace(re10, '');
+      '994k634'.replace(re51, '');
+      '994k634'.replace(re52, '');
+      '994k634'.replace(re53, '');
+      '994k634'.replace(re39, '');
+      '994k634'.replace(re54, '');
+      '?zxg=ra-HF'.replace(re40, '');
+      '?zxg=ra-HF'.replace(re10, '');
+      '?zxg=ra-HF'.replace(re51, '');
+      '?zxg=ra-HF'.replace(re52, '');
+      '?zxg=ra-HF'.replace(re53, '');
+      '?zxg=ra-HF'.replace(re54, '');
+      'PAA.pbz'.replace(re25, '');
+      'PAA.pbz'.replace(re12, '');
+      'PAA.pbz'.replace(re39, '');
+      'Qngr & Gvzr'.replace(re25, '');
+      'Qngr & Gvzr'.replace(re12, '');
+      'Qngr & Gvzr'.replace(re39, '');
+      'Frnepu Zvpebfbsg.pbz'.replace(re40, '');
+      'Frnepu Zvpebfbsg.pbz'.replace(re54, '');
+      str67.replace(re10, '');
+      str67.replace(re51, '');
+      str67.replace(re52, '');
+      str67.replace(re53, '');
+      str67.replace(re39, '');
+      str68.split(re32);
+      str69.split(re32);
+      str70.replace(re52, '');
+      str70.replace(re53, '');
+      str70.replace(re39, '');
+      str71.replace(re40, '');
+      str71.replace(re10, '');
+      str71.replace(re51, '');
+      str71.replace(re54, '');
+      'Jrngure'.replace(re25, '');
+      'Jrngure'.replace(re12, '');
+      'Jrngure'.replace(re39, '');
+      'LbhGhor'.replace(re25, '');
+      'LbhGhor'.replace(re12, '');
+      'LbhGhor'.replace(re39, '');
+      str72.replace(re33, '');
+      'erzbgr_vsenzr_1'.replace(/^erzbgr_vsenzr_/, '');
+      str73.replace(re40, '');
+      str73.replace(re10, '');
+      str73.replace(re51, '');
+      str73.replace(re52, '');
+      str73.replace(re53, '');
+      str73.replace(re39, '');
+      str73.replace(re54, '');
+      str74.replace(re40, '');
+      str74.replace(re10, '');
+      str74.replace(re51, '');
+      str74.replace(re52, '');
+      str74.replace(re53, '');
+      str74.replace(re39, '');
+      str74.replace(re54, '');
+      'lhv-h'.replace(/\-/g, '');
+      re9.exec('p');
+      re9.exec('qz p');
+      re9.exec('zbqynory');
+      re9.exec('lhv-h svefg');
+      re8.exec('144631658.0.10.1231365779');
+      re8.exec('144631658.1231365779.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)');
+      re8.exec('144631658.1877536177953918500.1231365779.1231365779.1231365779.1');
+      re8.exec(str75);
+      re8.exec(str76);
+      re8.exec('__hgzn=144631658.1877536177953918500.1231365779.1231365779.1231365779.1');
+      re8.exec('__hgzo=144631658.0.10.1231365779');
+      re8.exec('__hgzm=144631658.1231365779.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)');
+      re34.exec(str68);
+      re34.exec(str69);
+      /^$/.exec('');
+      re31.exec('qr');
+      /^znk\d+$/.exec('');
+      /^zva\d+$/.exec('');
+      /^erfgber$/.exec('');
+      re85.exec('zbqobkva zbqobk_abcnqqvat ');
+      re85.exec('zbqgvgyr');
+      re85.exec('eaq_zbqobkva ');
+      re85.exec('eaq_zbqgvgyr ');
+      /frpgvba\d+_pbagragf/.exec('obggbz_ani');
+    }
+  }
+  var re86 = /;\s*/;
+  var re87 = /(\$\{inyhr\})|(\$inyhr\b)/g;
+  var re88 = /(\$\{abj\})|(\$abj\b)/g;
+  var re89 = /\s+$/;
+  var re90 = /^\s+/;
+  var re91 = /(\\\"|\x00-|\x1f|\x7f-|\x9f|\u00ad|\u0600-|\u0604|\u070f|\u17b4|\u17b5|\u200c-|\u200f|\u2028-|\u202f|\u2060-|\u206f|\ufeff|\ufff0-|\uffff)/g;
+  var re92 = /^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/;
+  var re93 = /^([:.#]*)((?:[\w\u0128-\uffff*_-]|\\.)+)/;
+  var re94 = /^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/;
+  var str77 = '#fubhgobk .pybfr';
+  var str78 = 'FrffvbaQQS2=102n9o0o9pq60132qn0337rr867p75953502q2s27s2s5r98; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669341278771470&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_dfctwzssrwh-aowb_80=441326q33660';
+  var str79 = 'FrffvbaQQS2=102n9o0o9pq60132qn0337rr867p75953502q2s27s2s5r98; AFP_zp_dfctwzssrwh-aowb_80=441326q33660; __hgzm=144631658.1231365869.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.1670816052019209000.1231365869.1231365869.1231365869.1; __hgzo=144631658.0.10.1231365869; __hgzp=144631658; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669341278771470&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q';
+  var str80 = 'FrffvbaQQS2=9995p6rp12rrnr893334ro7nq70o7p64p69rqn844prs1473; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669350559478880&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_dfctwzs-aowb_80=441327q73660';
+  var str81 = 'FrffvbaQQS2=9995p6rp12rrnr893334ro7nq70o7p64p69rqn844prs1473; AFP_zp_dfctwzs-aowb_80=441327q73660; __hgzm=144631658.1231367054.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.1796080716621419500.1231367054.1231367054.1231367054.1; __hgzo=144631658.0.10.1231367054; __hgzp=144631658; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669350559478880&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q';
+  var str82 = '[glcr=fhozvg]';
+  var str83 = 'n.svryqOga,n.svryqOgaPnapry';
+  var str84 = 'n.svryqOgaPnapry';
+  var str85 = 'oyvpxchaxg';
+  var str86 = 'qvi.bow-nppbeqvba qg';
+  var str87 = 'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_nccf_wf&qg=1231367052227&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231367052227&punaary=svz_zlfcnpr_nccf-pnainf%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Scebsvyr.zlfcnpr.pbz%2SZbqhyrf%2SNccyvpngvbaf%2SCntrf%2SPnainf.nfck&nq_glcr=grkg&rvq=6083027&rn=0&sez=1&tn_ivq=716357910.1231367056&tn_fvq=1231367056&tn_uvq=1387206491&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22';
+  var str88 = 'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231365851658&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231365851658&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Scebsvyrrqvg.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1979828129.1231365855&tn_fvq=1231365855&tn_uvq=2085229649&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22';
+  var str89 = 'uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/f55023338617756?[NDO]&aqu=1&g=7%2S0%2S2009%2014%3N12%3N47%203%20480&af=zfacbegny&cntrAnzr=HF%20UCZFSGJ&t=uggc%3N%2S%2Sjjj.zfa.pbz%2S&f=0k0&p=43835816&x=A&oj=994&ou=634&uc=A&{2}&[NDR]';
+  var str90 = 'zrgn[anzr=nwnkHey]';
+  var str91 = 'anpuevpugra';
+  var str92 = 'b oS={\'oT\':1.1};x $8n(B){z(B!=o9)};x $S(B){O(!$8n(B))z A;O(B.4L)z\'T\';b S=7t B;O(S==\'2P\'&&B.p4){23(B.7f){12 1:z\'T\';12 3:z/\S/.2g(B.8M)?\'ox\':\'oh\'}}O(S==\'2P\'||S==\'x\'){23(B.nE){12 2V:z\'1O\';12 7I:z\'5a\';12 18:z\'4B\'}O(7t B.I==\'4F\'){O(B.3u)z\'pG\';O(B.8e)z\'1p\'}}z S};x $2p(){b 4E={};Z(b v=0;v<1p.I;v++){Z(b X 1o 1p[v]){b nc=1p[v][X];b 6E=4E[X];O(6E&&$S(nc)==\'2P\'&&$S(6E)==\'2P\')4E[X]=$2p(6E,nc);17 4E[X]=nc}}z 4E};b $E=7p.E=x(){b 1d=1p;O(!1d[1])1d=[p,1d[0]];Z(b X 1o 1d[1])1d[0][X]=1d[1][X];z 1d[0]};b $4D=7p.pJ=x(){Z(b v=0,y=1p.I;v<y;v++){1p[v].E=x(1J){Z(b 1I 1o 1J){O(!p.1Y[1I])p.1Y[1I]=1J[1I];O(!p[1I])p[1I]=$4D.6C(1I)}}}};$4D.6C=x(1I){z x(L){z p.1Y[1I].3H(L,2V.1Y.nV.1F(1p,1))}};$4D(7F,2V,6J,nb);b 3l=x(B){B=B||{};B.E=$E;z B};b pK=Y 3l(H);b pZ=Y 3l(C);C.6f=C.35(\'6f\')[0];x $2O(B){z!!(B||B===0)};x $5S(B,n8){z $8n(B)?B:n8};x $7K(3c,1m){z 1q.na(1q.7K()*(1m-3c+1)+3c)};x $3N(){z Y 97().os()};x $4M(1U){pv(1U);pa(1U);z 1S};H.43=!!(C.5Z);O(H.nB)H.31=H[H.7q?\'py\':\'nL\']=1r;17 O(C.9N&&!C.om&&!oy.oZ)H.pF=H.4Z=H[H.43?\'pt\':\'65\']=1r;17 O(C.po!=1S)H.7J=1r;O(7t 5B==\'o9\'){b 5B=x(){};O(H.4Z)C.nd("pW");5B.1Y=(H.4Z)?H["[[oN.1Y]]"]:{}}5B.1Y.4L=1r;O(H.nL)5s{C.oX("pp",A,1r)}4K(r){};b 18=x(1X){b 63=x(){z(1p[0]!==1S&&p.1w&&$S(p.1w)==\'x\')?p.1w.3H(p,1p):p};$E(63,p);63.1Y=1X;63.nE=18;z 63};18.1z=x(){};18.1Y={E:x(1X){b 7x=Y p(1S);Z(b X 1o 1X){b nC=7x[X];7x[X]=18.nY(nC,1X[X])}z Y 18(7x)},3d:x(){Z(b v=0,y=1p.I;v<y;v++)$E(p.1Y,1p[v])}};18.nY=x(2b,2n){O(2b&&2b!=2n){b S=$S(2n);O(S!=$S(2b))z 2n;23(S){12\'x\':b 7R=x(){p.1e=1p.8e.1e;z 2n.3H(p,1p)};7R.1e=2b;z 7R;12\'2P\':z $2p(2b,2n)}}z 2n};b 8o=Y 18({oQ:x(J){p.4w=p.4w||[];p.4w.1x(J);z p},7g:x(){O(p.4w&&p.4w.I)p.4w.9J().2x(10,p)},oP:x(){p.4w=[]}});b 2d=Y 18({1V:x(S,J){O(J!=18.1z){p.$19=p.$19||{};p.$19[S]=p.$19[S]||[];p.$19[S].5j(J)}z p},1v:x(S,1d,2x){O(p.$19&&p.$19[S]){p.$19[S].1b(x(J){J.3n({\'L\':p,\'2x\':2x,\'1p\':1d})()},p)}z p},3M:x(S,J){O(p.$19&&p.$19[S])p.$19[S].2U(J);z p}});b 4v=Y 18({2H:x(){p.P=$2p.3H(1S,[p.P].E(1p));O(!p.1V)z p;Z(b 3O 1o p.P){O($S(p.P[3O]==\'x\')&&3O.2g(/^5P[N-M]/))p.1V(3O,p.P[3O])}z p}});2V.E({7y:x(J,L){Z(b v=0,w=p.I;v<w;v++)J.1F(L,p[v],v,p)},3s:x(J,L){b 54=[];Z(b v=0,w=p.I;v<w;v++){O(J.1F(L,p[v],v,p))54.1x(p[v])}z 54},2X:x(J,L){b 54=[];Z(b v=0,w=p.I;v<w;v++)54[v]=J.1F(L,p[v],v,p);z 54},4i:x(J,L){Z(b v=0,w=p.I;v<w;v++){O(!J.1F(L,p[v],v,p))z A}z 1r},ob:x(J,L){Z(b v=0,w=p.I;v<w;v++){O(J.1F(L,p[v],v,p))z 1r}z A},3F:x(3u,15){b 3A=p.I;Z(b v=(15<0)?1q.1m(0,3A+15):15||0;v<3A;v++){O(p[v]===3u)z v}z-1},8z:x(1u,I){1u=1u||0;O(1u<0)1u=p.I+1u;I=I||(p.I-1u);b 89=[];Z(b v=0;v<I;v++)89[v]=p[1u++];z 89},2U:x(3u){b v=0;b 3A=p.I;6L(v<3A){O(p[v]===3u){p.6l(v,1);3A--}17{v++}}z p},1y:x(3u,15){z p.3F(3u,15)!=-1},oz:x(1C){b B={},I=1q.3c(p.I,1C.I);Z(b v=0;v<I;v++)B[1C[v]]=p[v];z B},E:x(1O){Z(b v=0,w=1O.I;v<w;v++)p.1x(1O[v]);z p},2p:x(1O){Z(b v=0,y=1O.I;v<y;v++)p.5j(1O[v]);z p},5j:x(3u){O(!p.1y(3u))p.1x(3u);z p},oc:x(){z p[$7K(0,p.I-1)]||A},7L:x(){z p[p.I-1]||A}});2V.1Y.1b=2V.1Y.7y;2V.1Y.2g=2V.1Y.1y;x $N(1O){z 2V.8z(1O)};x $1b(3J,J,L){O(3J&&7t 3J.I==\'4F\'&&$S(3J)!=\'2P\')2V.7y(3J,J,L);17 Z(b 1j 1o 3J)J.1F(L||3J,3J[1j],1j)};6J.E({2g:x(6b,2F){z(($S(6b)==\'2R\')?Y 7I(6b,2F):6b).2g(p)},3p:x(){z 5K(p,10)},o4:x(){z 69(p)},7A:x(){z p.3y(/-\D/t,x(2G){z 2G.7G(1).nW()})},9b:x(){z p.3y(/\w[N-M]/t,x(2G){z(2G.7G(0)+\'-\'+2G.7G(1).5O())})},8V:x(){z p.3y(/\b[n-m]/t,x(2G){z 2G.nW()})},5L:x(){z p.3y(/^\s+|\s+$/t,\'\')},7j:x(){z p.3y(/\s{2,}/t,\' \').5L()},5V:x(1O){b 1i=p.2G(/\d{1,3}/t);z(1i)?1i.5V(1O):A},5U:x(1O){b 3P=p.2G(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);z(3P)?3P.nV(1).5U(1O):A},1y:x(2R,f){z(f)?(f+p+f).3F(f+2R+f)>-1:p.3F(2R)>-1},nX:x(){z p.3y(/([.*+?^${}()|[\]\/\\])/t,\'\\$1\')}});2V.E({5V:x(1O){O(p.I<3)z A;O(p.I==4&&p[3]==0&&!1O)z\'p5\';b 3P=[];Z(b v=0;v<3;v++){b 52=(p[v]-0).4h(16);3P.1x((52.I==1)?\'0\'+52:52)}z 1O?3P:\'#\'+3P.2u(\'\')},5U:x(1O){O(p.I!=3)z A;b 1i=[];Z(b v=0;v<3;v++){1i.1x(5K((p[v].I==1)?p[v]+p[v]:p[v],16))}z 1O?1i:\'1i(\'+1i.2u(\',\')+\')\'}});7F.E({3n:x(P){b J=p;P=$2p({\'L\':J,\'V\':A,\'1p\':1S,\'2x\':A,\'4s\':A,\'6W\':A},P);O($2O(P.1p)&&$S(P.1p)!=\'1O\')P.1p=[P.1p];z x(V){b 1d;O(P.V){V=V||H.V;1d=[(P.V===1r)?V:Y P.V(V)];O(P.1p)1d.E(P.1p)}17 1d=P.1p||1p;b 3C=x(){z J.3H($5S(P';
+  var str93 = 'hagreunyghat';
+  var str94 = 'ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669341278771470&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q';
+  var str95 = 'ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669350559478880&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q';
+  var str96 = 'ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669341278771470&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=';
+  var str97 = 'ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669350559478880&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=';
+  var str98 = 'shapgvba (){Cuk.Nccyvpngvba.Frghc.Pber();Cuk.Nccyvpngvba.Frghc.Nwnk();Cuk.Nccyvpngvba.Frghc.Synfu();Cuk.Nccyvpngvba.Frghc.Zbqhyrf()}';
+  function runBlock11() {
+    for (var i = 0; i < 2; i++) {
+      ' .pybfr'.replace(re18, '');
+      ' n.svryqOgaPnapry'.replace(re18, '');
+      ' qg'.replace(re18, '');
+      str77.replace(re68, '');
+      str77.replace(re18, '');
+      ''.replace(re39, '');
+      ''.replace(/^/, '');
+      ''.split(re86);
+      '*'.replace(re39, '');
+      '*'.replace(re68, '');
+      '*'.replace(re18, '');
+      '.pybfr'.replace(re68, '');
+      '.pybfr'.replace(re18, '');
+      '//vzt.jro.qr/vij/FC/tzk_uc/fperra/${inyhr}?gf=${abj}'.replace(re87, '');
+      '//vzt.jro.qr/vij/FC/tzk_uc/fperra/1024?gf=${abj}'.replace(re88, '');
+      '//vzt.jro.qr/vij/FC/tzk_uc/jvafvmr/${inyhr}?gf=${abj}'.replace(re87, '');
+      '//vzt.jro.qr/vij/FC/tzk_uc/jvafvmr/992/608?gf=${abj}'.replace(re88, '');
+      '300k120'.replace(re30, '');
+      '300k250'.replace(re30, '');
+      '310k120'.replace(re30, '');
+      '310k170'.replace(re30, '');
+      '310k250'.replace(re30, '');
+      '9.0  e115'.replace(/^.*\.(.*)\s.*$/, '');
+      'Nppbeqvba'.replace(re2, '');
+      'Nxghryy\x0a'.replace(re89, '');
+      'Nxghryy\x0a'.replace(re90, '');
+      'Nccyvpngvba'.replace(re2, '');
+      'Oyvpxchaxg\x0a'.replace(re89, '');
+      'Oyvpxchaxg\x0a'.replace(re90, '');
+      'Svanamra\x0a'.replace(re89, '');
+      'Svanamra\x0a'.replace(re90, '');
+      'Tnzrf\x0a'.replace(re89, '');
+      'Tnzrf\x0a'.replace(re90, '');
+      'Ubebfxbc\x0a'.replace(re89, '');
+      'Ubebfxbc\x0a'.replace(re90, '');
+      'Xvab\x0a'.replace(re89, '');
+      'Xvab\x0a'.replace(re90, '');
+      'Zbqhyrf'.replace(re2, '');
+      'Zhfvx\x0a'.replace(re89, '');
+      'Zhfvx\x0a'.replace(re90, '');
+      'Anpuevpugra\x0a'.replace(re89, '');
+      'Anpuevpugra\x0a'.replace(re90, '');
+      'Cuk'.replace(re2, '');
+      'ErdhrfgSvavfu'.split(re70);
+      'ErdhrfgSvavfu.NWNK.Cuk'.split(re70);
+      'Ebhgr\x0a'.replace(re89, '');
+      'Ebhgr\x0a'.replace(re90, '');
+      str78.split(re32);
+      str79.split(re32);
+      str80.split(re32);
+      str81.split(re32);
+      'Fcbeg\x0a'.replace(re89, '');
+      'Fcbeg\x0a'.replace(re90, '');
+      'GI-Fcbg\x0a'.replace(re89, '');
+      'GI-Fcbg\x0a'.replace(re90, '');
+      'Gbhe\x0a'.replace(re89, '');
+      'Gbhe\x0a'.replace(re90, '');
+      'Hagreunyghat\x0a'.replace(re89, '');
+      'Hagreunyghat\x0a'.replace(re90, '');
+      'Ivqrb\x0a'.replace(re89, '');
+      'Ivqrb\x0a'.replace(re90, '');
+      'Jrggre\x0a'.replace(re89, '');
+      'Jrggre\x0a'.replace(re90, '');
+      str82.replace(re68, '');
+      str82.replace(re18, '');
+      str83.replace(re68, '');
+      str83.replace(re18, '');
+      str84.replace(re68, '');
+      str84.replace(re18, '');
+      'nqiFreivprObk'.replace(re30, '');
+      'nqiFubccvatObk'.replace(re30, '');
+      'nwnk'.replace(re39, '');
+      'nxghryy'.replace(re40, '');
+      'nxghryy'.replace(re41, '');
+      'nxghryy'.replace(re42, '');
+      'nxghryy'.replace(re43, '');
+      'nxghryy'.replace(re44, '');
+      'nxghryy'.replace(re45, '');
+      'nxghryy'.replace(re46, '');
+      'nxghryy'.replace(re47, '');
+      'nxghryy'.replace(re48, '');
+      str85.replace(re40, '');
+      str85.replace(re41, '');
+      str85.replace(re42, '');
+      str85.replace(re43, '');
+      str85.replace(re44, '');
+      str85.replace(re45, '');
+      str85.replace(re46, '');
+      str85.replace(re47, '');
+      str85.replace(re48, '');
+      'pngrtbel'.replace(re29, '');
+      'pngrtbel'.replace(re30, '');
+      'pybfr'.replace(re39, '');
+      'qvi'.replace(re39, '');
+      str86.replace(re68, '');
+      str86.replace(re18, '');
+      'qg'.replace(re39, '');
+      'qg'.replace(re68, '');
+      'qg'.replace(re18, '');
+      'rzorq'.replace(re39, '');
+      'rzorq'.replace(re68, '');
+      'rzorq'.replace(re18, '');
+      'svryqOga'.replace(re39, '');
+      'svryqOgaPnapry'.replace(re39, '');
+      'svz_zlfcnpr_nccf-pnainf,svz_zlfcnpr_havgrq-fgngrf'.split(re20);
+      'svanamra'.replace(re40, '');
+      'svanamra'.replace(re41, '');
+      'svanamra'.replace(re42, '');
+      'svanamra'.replace(re43, '');
+      'svanamra'.replace(re44, '');
+      'svanamra'.replace(re45, '');
+      'svanamra'.replace(re46, '');
+      'svanamra'.replace(re47, '');
+      'svanamra'.replace(re48, '');
+      'sbphf'.split(re70);
+      'sbphf.gno sbphfva.gno'.split(re70);
+      'sbphfva'.split(re70);
+      'sbez'.replace(re39, '');
+      'sbez.nwnk'.replace(re68, '');
+      'sbez.nwnk'.replace(re18, '');
+      'tnzrf'.replace(re40, '');
+      'tnzrf'.replace(re41, '');
+      'tnzrf'.replace(re42, '');
+      'tnzrf'.replace(re43, '');
+      'tnzrf'.replace(re44, '');
+      'tnzrf'.replace(re45, '');
+      'tnzrf'.replace(re46, '');
+      'tnzrf'.replace(re47, '');
+      'tnzrf'.replace(re48, '');
+      'ubzrcntr'.replace(re30, '');
+      'ubebfxbc'.replace(re40, '');
+      'ubebfxbc'.replace(re41, '');
+      'ubebfxbc'.replace(re42, '');
+      'ubebfxbc'.replace(re43, '');
+      'ubebfxbc'.replace(re44, '');
+      'ubebfxbc'.replace(re45, '');
+      'ubebfxbc'.replace(re46, '');
+      'ubebfxbc'.replace(re47, '');
+      'ubebfxbc'.replace(re48, '');
+      'uc_cebzbobk_ugzy%2Puc_cebzbobk_vzt'.replace(re30, '');
+      'uc_erpgnatyr'.replace(re30, '');
+      str87.replace(re33, '');
+      str88.replace(re33, '');
+      'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/onfr.wf${4}${5}'.replace(re71, '');
+      'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/onfr.wf${5}'.replace(re72, '');
+      'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/qlaYvo.wf${4}${5}'.replace(re71, '');
+      'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/qlaYvo.wf${5}'.replace(re72, '');
+      'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/rssrpgYvo.wf${4}${5}'.replace(re71, '');
+      'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/rssrpgYvo.wf${5}'.replace(re72, '');
+      str89.replace(re73, '');
+      'uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/f55023338617756?[NDO]&{1}&{2}&[NDR]'.replace(re69, '');
+      str6.replace(re23, '');
+      'xvab'.replace(re40, '');
+      'xvab'.replace(re41, '');
+      'xvab'.replace(re42, '');
+      'xvab'.replace(re43, '');
+      'xvab'.replace(re44, '');
+      'xvab'.replace(re45, '');
+      'xvab'.replace(re46, '');
+      'xvab'.replace(re47, '');
+      'xvab'.replace(re48, '');
+      'ybnq'.split(re70);
+      'zrqvnzbqgno lhv-anifrg lhv-anifrg-gbc'.replace(re18, '');
+      'zrgn'.replace(re39, '');
+      str90.replace(re68, '');
+      str90.replace(re18, '');
+      'zbhfrzbir'.split(re70);
+      'zbhfrzbir.gno'.split(re70);
+      str63.replace(/^.*jroxvg\/(\d+(\.\d+)?).*$/, '');
+      'zhfvx'.replace(re40, '');
+      'zhfvx'.replace(re41, '');
+      'zhfvx'.replace(re42, '');
+      'zhfvx'.replace(re43, '');
+      'zhfvx'.replace(re44, '');
+      'zhfvx'.replace(re45, '');
+      'zhfvx'.replace(re46, '');
+      'zhfvx'.replace(re47, '');
+      'zhfvx'.replace(re48, '');
+      'zlfcnpr_nccf_pnainf'.replace(re52, '');
+      str91.replace(re40, '');
+      str91.replace(re41, '');
+      str91.replace(re42, '');
+      str91.replace(re43, '');
+      str91.replace(re44, '');
+      str91.replace(re45, '');
+      str91.replace(re46, '');
+      str91.replace(re47, '');
+      str91.replace(re48, '');
+      'anzr'.replace(re39, '');
+      str92.replace(/\b\w+\b/g, '');
+      'bow-nppbeqvba'.replace(re39, '');
+      'bowrpg'.replace(re39, '');
+      'bowrpg'.replace(re68, '');
+      'bowrpg'.replace(re18, '');
+      'cnenzf%2Rfglyrf'.replace(re29, '');
+      'cnenzf%2Rfglyrf'.replace(re30, '');
+      'cbchc'.replace(re30, '');
+      'ebhgr'.replace(re40, '');
+      'ebhgr'.replace(re41, '');
+      'ebhgr'.replace(re42, '');
+      'ebhgr'.replace(re43, '');
+      'ebhgr'.replace(re44, '');
+      'ebhgr'.replace(re45, '');
+      'ebhgr'.replace(re46, '');
+      'ebhgr'.replace(re47, '');
+      'ebhgr'.replace(re48, '');
+      'freivprobk_uc'.replace(re30, '');
+      'fubccvatobk_uc'.replace(re30, '');
+      'fubhgobk'.replace(re39, '');
+      'fcbeg'.replace(re40, '');
+      'fcbeg'.replace(re41, '');
+      'fcbeg'.replace(re42, '');
+      'fcbeg'.replace(re43, '');
+      'fcbeg'.replace(re44, '');
+      'fcbeg'.replace(re45, '');
+      'fcbeg'.replace(re46, '');
+      'fcbeg'.replace(re47, '');
+      'fcbeg'.replace(re48, '');
+      'gbhe'.replace(re40, '');
+      'gbhe'.replace(re41, '');
+      'gbhe'.replace(re42, '');
+      'gbhe'.replace(re43, '');
+      'gbhe'.replace(re44, '');
+      'gbhe'.replace(re45, '');
+      'gbhe'.replace(re46, '');
+      'gbhe'.replace(re47, '');
+      'gbhe'.replace(re48, '');
+      'gi-fcbg'.replace(re40, '');
+      'gi-fcbg'.replace(re41, '');
+      'gi-fcbg'.replace(re42, '');
+      'gi-fcbg'.replace(re43, '');
+      'gi-fcbg'.replace(re44, '');
+      'gi-fcbg'.replace(re45, '');
+      'gi-fcbg'.replace(re46, '');
+      'gi-fcbg'.replace(re47, '');
+      'gi-fcbg'.replace(re48, '');
+      'glcr'.replace(re39, '');
+      'haqrsvarq'.replace(/\//g, '');
+      str93.replace(re40, '');
+      str93.replace(re41, '');
+      str93.replace(re42, '');
+      str93.replace(re43, '');
+      str93.replace(re44, '');
+      str93.replace(re45, '');
+      str93.replace(re46, '');
+      str93.replace(re47, '');
+      str93.replace(re48, '');
+      'ivqrb'.replace(re40, '');
+      'ivqrb'.replace(re41, '');
+      'ivqrb'.replace(re42, '');
+      'ivqrb'.replace(re43, '');
+      'ivqrb'.replace(re44, '');
+      'ivqrb'.replace(re45, '');
+      'ivqrb'.replace(re46, '');
+      'ivqrb'.replace(re47, '');
+      'ivqrb'.replace(re48, '');
+      'ivfvgf=1'.split(re86);
+      'jrggre'.replace(re40, '');
+      'jrggre'.replace(re41, '');
+      'jrggre'.replace(re42, '');
+      'jrggre'.replace(re43, '');
+      'jrggre'.replace(re44, '');
+      'jrggre'.replace(re45, '');
+      'jrggre'.replace(re46, '');
+      'jrggre'.replace(re47, '');
+      'jrggre'.replace(re48, '');
+      /#[a-z0-9]+$/i.exec('uggc://jjj.fpuhryreim.arg/Qrsnhyg');
+      re66.exec('fryrpgrq');
+      /(?:^|\s+)lhv-ani(?:\s+|$)/.exec('sff lhv-ani');
+      /(?:^|\s+)lhv-anifrg(?:\s+|$)/.exec('zrqvnzbqgno lhv-anifrg');
+      /(?:^|\s+)lhv-anifrg-gbc(?:\s+|$)/.exec('zrqvnzbqgno lhv-anifrg');
+      re91.exec('GnoThvq');
+      re91.exec('thvq');
+      /(pbzcngvoyr|jroxvg)/.exec(str63);
+      /.+(?:ei|vg|en|vr)[\/: ]([\d.]+)/.exec(str63);
+      re8.exec('144631658.0.10.1231365869');
+      re8.exec('144631658.0.10.1231367054');
+      re8.exec('144631658.1231365869.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)');
+      re8.exec('144631658.1231367054.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)');
+      re8.exec('144631658.1670816052019209000.1231365869.1231365869.1231365869.1');
+      re8.exec('144631658.1796080716621419500.1231367054.1231367054.1231367054.1');
+      re8.exec(str94);
+      re8.exec(str95);
+      re8.exec(str96);
+      re8.exec(str97);
+      re8.exec('__hgzn=144631658.1670816052019209000.1231365869.1231365869.1231365869.1');
+      re8.exec('__hgzn=144631658.1796080716621419500.1231367054.1231367054.1231367054.1');
+      re8.exec('__hgzo=144631658.0.10.1231365869');
+      re8.exec('__hgzo=144631658.0.10.1231367054');
+      re8.exec('__hgzm=144631658.1231365869.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)');
+      re8.exec('__hgzm=144631658.1231367054.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)');
+      re34.exec(str78);
+      re34.exec(str79);
+      re34.exec(str81);
+      re74.exec(str77);
+      re74.exec('*');
+      re74.exec(str82);
+      re74.exec(str83);
+      re74.exec(str86);
+      re74.exec('rzorq');
+      re74.exec('sbez.nwnk');
+      re74.exec(str90);
+      re74.exec('bowrpg');
+      /\/onfr.wf(\?.+)?$/.exec('/uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/onfr.wf');
+      re28.exec('uvag ynfgUvag ynfg');
+      re75.exec('');
+      re76.exec('');
+      re77.exec('');
+      re78.exec('');
+      re80.exec(str77);
+      re80.exec('*');
+      re80.exec('.pybfr');
+      re80.exec(str82);
+      re80.exec(str83);
+      re80.exec(str84);
+      re80.exec(str86);
+      re80.exec('qg');
+      re80.exec('rzorq');
+      re80.exec('sbez.nwnk');
+      re80.exec(str90);
+      re80.exec('bowrpg');
+      re61.exec('qlaYvo.wf');
+      re61.exec('rssrpgYvo.wf');
+      re61.exec('uggc://jjj.tzk.arg/qr/?fgnghf=uvajrvf');
+      re92.exec(' .pybfr');
+      re92.exec(' n.svryqOgaPnapry');
+      re92.exec(' qg');
+      re92.exec(str48);
+      re92.exec('.nwnk');
+      re92.exec('.svryqOga,n.svryqOgaPnapry');
+      re92.exec('.svryqOgaPnapry');
+      re92.exec('.bow-nppbeqvba qg');
+      re68.exec(str77);
+      re68.exec('*');
+      re68.exec('.pybfr');
+      re68.exec(str82);
+      re68.exec(str83);
+      re68.exec(str84);
+      re68.exec(str86);
+      re68.exec('qg');
+      re68.exec('rzorq');
+      re68.exec('sbez.nwnk');
+      re68.exec(str90);
+      re68.exec('bowrpg');
+      re93.exec(' .pybfr');
+      re93.exec(' n.svryqOgaPnapry');
+      re93.exec(' qg');
+      re93.exec(str48);
+      re93.exec('.nwnk');
+      re93.exec('.svryqOga,n.svryqOgaPnapry');
+      re93.exec('.svryqOgaPnapry');
+      re93.exec('.bow-nppbeqvba qg');
+      re81.exec(str77);
+      re81.exec('*');
+      re81.exec(str48);
+      re81.exec('.pybfr');
+      re81.exec(str82);
+      re81.exec(str83);
+      re81.exec(str84);
+      re81.exec(str86);
+      re81.exec('qg');
+      re81.exec('rzorq');
+      re81.exec('sbez.nwnk');
+      re81.exec(str90);
+      re81.exec('bowrpg');
+      re94.exec(' .pybfr');
+      re94.exec(' n.svryqOgaPnapry');
+      re94.exec(' qg');
+      re94.exec(str48);
+      re94.exec('.nwnk');
+      re94.exec('.svryqOga,n.svryqOgaPnapry');
+      re94.exec('.svryqOgaPnapry');
+      re94.exec('.bow-nppbeqvba qg');
+      re94.exec('[anzr=nwnkHey]');
+      re94.exec(str82);
+      re31.exec('rf');
+      re31.exec('wn');
+      re82.exec(str77);
+      re82.exec('*');
+      re82.exec(str48);
+      re82.exec('.pybfr');
+      re82.exec(str82);
+      re82.exec(str83);
+      re82.exec(str84);
+      re82.exec(str86);
+      re82.exec('qg');
+      re82.exec('rzorq');
+      re82.exec('sbez.nwnk');
+      re82.exec(str90);
+      re82.exec('bowrpg');
+      re83.exec(str98);
+      re83.exec('shapgvba sbphf() { [angvir pbqr] }');
+      re62.exec('#Ybtva');
+      re62.exec('#Ybtva_cnffjbeq');
+      re62.exec(str77);
+      re62.exec('#fubhgobkWf');
+      re62.exec('#fubhgobkWfReebe');
+      re62.exec('#fubhgobkWfFhpprff');
+      re62.exec('*');
+      re62.exec(str82);
+      re62.exec(str83);
+      re62.exec(str86);
+      re62.exec('rzorq');
+      re62.exec('sbez.nwnk');
+      re62.exec(str90);
+      re62.exec('bowrpg');
+      re49.exec('pbagrag');
+      re24.exec(str6);
+      /xbadhrebe/.exec(str63);
+      /znp/.exec('jva32');
+      /zbmvyyn/.exec(str63);
+      /zfvr/.exec(str63);
+      /ag\s5\.1/.exec(str63);
+      /bcren/.exec(str63);
+      /fnsnev/.exec(str63);
+      /jva/.exec('jva32');
+      /jvaqbjf/.exec(str63);
+    }
+  }
+  for (var i = 0; i < 5; i++) {
+    runBlock0();
+    runBlock1();
+    runBlock2();
+    runBlock3();
+    runBlock4();
+    runBlock5();
+    runBlock6();
+    runBlock7();
+    runBlock8();
+    runBlock9();
+    runBlock10();
+    runBlock11();
+  }
+}
diff --git a/deps/v8/benchmarks/revisions.html b/deps/v8/benchmarks/revisions.html
new file mode 100644
index 0000000..bba53dc
--- /dev/null
+++ b/deps/v8/benchmarks/revisions.html
@@ -0,0 +1,62 @@
+<html>
+<head>
+<title>V8 Benchmark Suite Revisions</title>
+<link type="text/css" rel="stylesheet" href="style.css"></link>
+</head>
+<body>
+<div>
+  <div class="title"><h1>V8 Benchmark Suite Revisions</h1></div>
+  <table>
+    <tr>
+      <td class="contents">
+
+<p>
+
+The V8 benchmark suite is changed from time to time as we fix bugs or
+expand the scope of the benchmarks.  Here is a list of revisions, with
+a description of the changes made.  Note that benchmark results are
+not comparable unless both results are run with the same revision of
+the benchmark suite.
+
+</p>
+
+<div class="subtitle"><h3>Version 3 (<a href="http://v8.googlecode.com/svn/data/benchmarks/v3/run.html">link</a>)</h3></div>
+
+<p>Version 3 adds a new benchmark, <i>RegExp</i>.  The RegExp
+benchmark is generated by loading 50 of the most popular pages on the
+web and logging all regexp operations performed.  Each operation is
+given a weight that is calculated from an estimate of the popularity
+of the pages where it occurs and the number of times it is executed
+while loading each page.  Finally the literal letters in the data are
+encoded using ROT13 in a way that does not affect how the regexps
+match their input.
+</p>
+
+<div class="subtitle"><h3>Version 2 (<a href="http://v8.googlecode.com/svn/data/benchmarks/v2/run.html">link</a>)</h3></div>
+
+<p>For version 2 the crypto benchmark was fixed.  Previously, the
+decryption stage was given plaintext as input, which resulted in an
+error.  Now, the decryption stage is given the output of the
+encryption stage as input.  The result is checked against the original
+plaintext.  For this to give the correct results the crypto objects
+are reset for each iteration of the benchmark.  In addition, the size
+of the plain text has been increased a little and the use of
+Math.random() and new Date() to build an RNG pool has been
+removed. </p>
+
+<p>Other benchmarks were fixed to do elementary verification of the
+results of their calculations.  This is to avoid accidentally
+obtaining scores that are the result of an incorrect JavaScript engine
+optimization.</p>
+
+<div class="subtitle"><h3>Version 1 (<a href="http://v8.googlecode.com/svn/data/benchmarks/v1/run.html">link</a>)</h3></div>
+
+<p>Initial release.</p>
+
+</td><td style="text-align: center">
+</td></tr></table>
+
+</div>
+
+</body>
+</html>
diff --git a/deps/v8/benchmarks/richards.js b/deps/v8/benchmarks/richards.js
new file mode 100644
index 0000000..bb88623
--- /dev/null
+++ b/deps/v8/benchmarks/richards.js
@@ -0,0 +1,539 @@
+// 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.
+
+
+// This is a JavaScript implementation of the Richards
+// benchmark from:
+//
+//    http://www.cl.cam.ac.uk/~mr10/Bench.html
+// 
+// The benchmark was originally implemented in BCPL by
+// Martin Richards.
+
+
+var Richards = new BenchmarkSuite('Richards', 34886, [
+  new Benchmark("Richards", runRichards)
+]);
+
+
+/**
+ * The Richards benchmark simulates the task dispatcher of an
+ * operating system.
+ **/
+function runRichards() {
+  var scheduler = new Scheduler();
+  scheduler.addIdleTask(ID_IDLE, 0, null, COUNT);
+
+  var queue = new Packet(null, ID_WORKER, KIND_WORK);
+  queue = new Packet(queue,  ID_WORKER, KIND_WORK);
+  scheduler.addWorkerTask(ID_WORKER, 1000, queue);
+
+  queue = new Packet(null, ID_DEVICE_A, KIND_DEVICE);
+  queue = new Packet(queue,  ID_DEVICE_A, KIND_DEVICE);
+  queue = new Packet(queue,  ID_DEVICE_A, KIND_DEVICE);
+  scheduler.addHandlerTask(ID_HANDLER_A, 2000, queue);
+
+  queue = new Packet(null, ID_DEVICE_B, KIND_DEVICE);
+  queue = new Packet(queue,  ID_DEVICE_B, KIND_DEVICE);
+  queue = new Packet(queue,  ID_DEVICE_B, KIND_DEVICE);
+  scheduler.addHandlerTask(ID_HANDLER_B, 3000, queue);
+
+  scheduler.addDeviceTask(ID_DEVICE_A, 4000, null);
+
+  scheduler.addDeviceTask(ID_DEVICE_B, 5000, null);
+
+  scheduler.schedule();
+
+  if (scheduler.queueCount != EXPECTED_QUEUE_COUNT ||
+      scheduler.holdCount != EXPECTED_HOLD_COUNT) {
+    var msg =
+        "Error during execution: queueCount = " + scheduler.queueCount +
+        ", holdCount = " + scheduler.holdCount + ".";
+    throw new Error(msg);
+  }
+}
+
+var COUNT = 1000;
+
+/**
+ * These two constants specify how many times a packet is queued and
+ * how many times a task is put on hold in a correct run of richards.
+ * They don't have any meaning a such but are characteristic of a
+ * correct run so if the actual queue or hold count is different from
+ * the expected there must be a bug in the implementation.
+ **/
+var EXPECTED_QUEUE_COUNT = 2322;
+var EXPECTED_HOLD_COUNT = 928;
+
+
+/**
+ * A scheduler can be used to schedule a set of tasks based on their relative
+ * priorities.  Scheduling is done by maintaining a list of task control blocks
+ * which holds tasks and the data queue they are processing.
+ * @constructor
+ */
+function Scheduler() {
+  this.queueCount = 0;
+  this.holdCount = 0;
+  this.blocks = new Array(NUMBER_OF_IDS);
+  this.list = null;
+  this.currentTcb = null;
+  this.currentId = null;
+}
+
+var ID_IDLE       = 0;
+var ID_WORKER     = 1;
+var ID_HANDLER_A  = 2;
+var ID_HANDLER_B  = 3;
+var ID_DEVICE_A   = 4;
+var ID_DEVICE_B   = 5;
+var NUMBER_OF_IDS = 6;
+
+var KIND_DEVICE   = 0;
+var KIND_WORK     = 1;
+
+/**
+ * Add an idle task to this scheduler.
+ * @param {int} id the identity of the task
+ * @param {int} priority the task's priority
+ * @param {Packet} queue the queue of work to be processed by the task
+ * @param {int} count the number of times to schedule the task
+ */
+Scheduler.prototype.addIdleTask = function (id, priority, queue, count) {
+  this.addRunningTask(id, priority, queue, new IdleTask(this, 1, count));
+};
+
+/**
+ * Add a work task to this scheduler.
+ * @param {int} id the identity of the task
+ * @param {int} priority the task's priority
+ * @param {Packet} queue the queue of work to be processed by the task
+ */
+Scheduler.prototype.addWorkerTask = function (id, priority, queue) {
+  this.addTask(id, priority, queue, new WorkerTask(this, ID_HANDLER_A, 0));
+};
+
+/**
+ * Add a handler task to this scheduler.
+ * @param {int} id the identity of the task
+ * @param {int} priority the task's priority
+ * @param {Packet} queue the queue of work to be processed by the task
+ */
+Scheduler.prototype.addHandlerTask = function (id, priority, queue) {
+  this.addTask(id, priority, queue, new HandlerTask(this));
+};
+
+/**
+ * Add a handler task to this scheduler.
+ * @param {int} id the identity of the task
+ * @param {int} priority the task's priority
+ * @param {Packet} queue the queue of work to be processed by the task
+ */
+Scheduler.prototype.addDeviceTask = function (id, priority, queue) {
+  this.addTask(id, priority, queue, new DeviceTask(this))
+};
+
+/**
+ * Add the specified task and mark it as running.
+ * @param {int} id the identity of the task
+ * @param {int} priority the task's priority
+ * @param {Packet} queue the queue of work to be processed by the task
+ * @param {Task} task the task to add
+ */
+Scheduler.prototype.addRunningTask = function (id, priority, queue, task) {
+  this.addTask(id, priority, queue, task);
+  this.currentTcb.setRunning();
+};
+
+/**
+ * Add the specified task to this scheduler.
+ * @param {int} id the identity of the task
+ * @param {int} priority the task's priority
+ * @param {Packet} queue the queue of work to be processed by the task
+ * @param {Task} task the task to add
+ */
+Scheduler.prototype.addTask = function (id, priority, queue, task) {
+  this.currentTcb = new TaskControlBlock(this.list, id, priority, queue, task);
+  this.list = this.currentTcb;
+  this.blocks[id] = this.currentTcb;
+};
+
+/**
+ * Execute the tasks managed by this scheduler.
+ */
+Scheduler.prototype.schedule = function () {
+  this.currentTcb = this.list;
+  while (this.currentTcb != null) {
+    if (this.currentTcb.isHeldOrSuspended()) {
+      this.currentTcb = this.currentTcb.link;
+    } else {
+      this.currentId = this.currentTcb.id;
+      this.currentTcb = this.currentTcb.run();
+    }
+  }
+};
+
+/**
+ * Release a task that is currently blocked and return the next block to run.
+ * @param {int} id the id of the task to suspend
+ */
+Scheduler.prototype.release = function (id) {
+  var tcb = this.blocks[id];
+  if (tcb == null) return tcb;
+  tcb.markAsNotHeld();
+  if (tcb.priority > this.currentTcb.priority) {
+    return tcb;
+  } else {
+    return this.currentTcb;
+  }
+};
+
+/**
+ * Block the currently executing task and return the next task control block
+ * to run.  The blocked task will not be made runnable until it is explicitly
+ * released, even if new work is added to it.
+ */
+Scheduler.prototype.holdCurrent = function () {
+  this.holdCount++;
+  this.currentTcb.markAsHeld();
+  return this.currentTcb.link;
+};
+
+/**
+ * Suspend the currently executing task and return the next task control block
+ * to run.  If new work is added to the suspended task it will be made runnable.
+ */
+Scheduler.prototype.suspendCurrent = function () {
+  this.currentTcb.markAsSuspended();
+  return this.currentTcb;
+};
+
+/**
+ * Add the specified packet to the end of the worklist used by the task
+ * associated with the packet and make the task runnable if it is currently
+ * suspended.
+ * @param {Packet} packet the packet to add
+ */
+Scheduler.prototype.queue = function (packet) {
+  var t = this.blocks[packet.id];
+  if (t == null) return t;
+  this.queueCount++;
+  packet.link = null;
+  packet.id = this.currentId;
+  return t.checkPriorityAdd(this.currentTcb, packet);
+};
+
+/**
+ * A task control block manages a task and the queue of work packages associated
+ * with it.
+ * @param {TaskControlBlock} link the preceding block in the linked block list
+ * @param {int} id the id of this block
+ * @param {int} priority the priority of this block
+ * @param {Packet} queue the queue of packages to be processed by the task
+ * @param {Task} task the task
+ * @constructor
+ */
+function TaskControlBlock(link, id, priority, queue, task) {
+  this.link = link;
+  this.id = id;
+  this.priority = priority;
+  this.queue = queue;
+  this.task = task;
+  if (queue == null) {
+    this.state = STATE_SUSPENDED;
+  } else {
+    this.state = STATE_SUSPENDED_RUNNABLE;
+  }
+}
+
+/**
+ * The task is running and is currently scheduled.
+ */
+var STATE_RUNNING = 0;
+
+/**
+ * The task has packets left to process.
+ */
+var STATE_RUNNABLE = 1;
+
+/**
+ * The task is not currently running.  The task is not blocked as such and may
+* be started by the scheduler.
+ */
+var STATE_SUSPENDED = 2;
+
+/**
+ * The task is blocked and cannot be run until it is explicitly released.
+ */
+var STATE_HELD = 4;
+
+var STATE_SUSPENDED_RUNNABLE = STATE_SUSPENDED | STATE_RUNNABLE;
+var STATE_NOT_HELD = ~STATE_HELD;
+
+TaskControlBlock.prototype.setRunning = function () {
+  this.state = STATE_RUNNING;
+};
+
+TaskControlBlock.prototype.markAsNotHeld = function () {
+  this.state = this.state & STATE_NOT_HELD;
+};
+
+TaskControlBlock.prototype.markAsHeld = function () {
+  this.state = this.state | STATE_HELD;
+};
+
+TaskControlBlock.prototype.isHeldOrSuspended = function () {
+  return (this.state & STATE_HELD) != 0 || (this.state == STATE_SUSPENDED);
+};
+
+TaskControlBlock.prototype.markAsSuspended = function () {
+  this.state = this.state | STATE_SUSPENDED;
+};
+
+TaskControlBlock.prototype.markAsRunnable = function () {
+  this.state = this.state | STATE_RUNNABLE;
+};
+
+/**
+ * Runs this task, if it is ready to be run, and returns the next task to run.
+ */
+TaskControlBlock.prototype.run = function () {
+  var packet;
+  if (this.state == STATE_SUSPENDED_RUNNABLE) {
+    packet = this.queue;
+    this.queue = packet.link;
+    if (this.queue == null) {
+      this.state = STATE_RUNNING;
+    } else {
+      this.state = STATE_RUNNABLE;
+    }
+  } else {
+    packet = null;
+  }
+  return this.task.run(packet);
+};
+
+/**
+ * Adds a packet to the worklist of this block's task, marks this as runnable if
+ * necessary, and returns the next runnable object to run (the one
+ * with the highest priority).
+ */
+TaskControlBlock.prototype.checkPriorityAdd = function (task, packet) {
+  if (this.queue == null) {
+    this.queue = packet;
+    this.markAsRunnable();
+    if (this.priority > task.priority) return this;
+  } else {
+    this.queue = packet.addTo(this.queue);
+  }
+  return task;
+};
+
+TaskControlBlock.prototype.toString = function () {
+  return "tcb { " + this.task + "@" + this.state + " }";
+};
+
+/**
+ * An idle task doesn't do any work itself but cycles control between the two
+ * device tasks.
+ * @param {Scheduler} scheduler the scheduler that manages this task
+ * @param {int} v1 a seed value that controls how the device tasks are scheduled
+ * @param {int} count the number of times this task should be scheduled
+ * @constructor
+ */
+function IdleTask(scheduler, v1, count) {
+  this.scheduler = scheduler;
+  this.v1 = v1;
+  this.count = count;
+}
+
+IdleTask.prototype.run = function (packet) {
+  this.count--;
+  if (this.count == 0) return this.scheduler.holdCurrent();
+  if ((this.v1 & 1) == 0) {
+    this.v1 = this.v1 >> 1;
+    return this.scheduler.release(ID_DEVICE_A);
+  } else {
+    this.v1 = (this.v1 >> 1) ^ 0xD008;
+    return this.scheduler.release(ID_DEVICE_B);
+  }
+};
+
+IdleTask.prototype.toString = function () {
+  return "IdleTask"
+};
+
+/**
+ * A task that suspends itself after each time it has been run to simulate
+ * waiting for data from an external device.
+ * @param {Scheduler} scheduler the scheduler that manages this task
+ * @constructor
+ */
+function DeviceTask(scheduler) {
+  this.scheduler = scheduler;
+  this.v1 = null;
+}
+
+DeviceTask.prototype.run = function (packet) {
+  if (packet == null) {
+    if (this.v1 == null) return this.scheduler.suspendCurrent();
+    var v = this.v1;
+    this.v1 = null;
+    return this.scheduler.queue(v);
+  } else {
+    this.v1 = packet;
+    return this.scheduler.holdCurrent();
+  }
+};
+
+DeviceTask.prototype.toString = function () {
+  return "DeviceTask";
+};
+
+/**
+ * A task that manipulates work packets.
+ * @param {Scheduler} scheduler the scheduler that manages this task
+ * @param {int} v1 a seed used to specify how work packets are manipulated
+ * @param {int} v2 another seed used to specify how work packets are manipulated
+ * @constructor
+ */
+function WorkerTask(scheduler, v1, v2) {
+  this.scheduler = scheduler;
+  this.v1 = v1;
+  this.v2 = v2;
+}
+
+WorkerTask.prototype.run = function (packet) {
+  if (packet == null) {
+    return this.scheduler.suspendCurrent();
+  } else {
+    if (this.v1 == ID_HANDLER_A) {
+      this.v1 = ID_HANDLER_B;
+    } else {
+      this.v1 = ID_HANDLER_A;
+    }
+    packet.id = this.v1;
+    packet.a1 = 0;
+    for (var i = 0; i < DATA_SIZE; i++) {
+      this.v2++;
+      if (this.v2 > 26) this.v2 = 1;
+      packet.a2[i] = this.v2;
+    }
+    return this.scheduler.queue(packet);
+  }
+};
+
+WorkerTask.prototype.toString = function () {
+  return "WorkerTask";
+};
+
+/**
+ * A task that manipulates work packets and then suspends itself.
+ * @param {Scheduler} scheduler the scheduler that manages this task
+ * @constructor
+ */
+function HandlerTask(scheduler) {
+  this.scheduler = scheduler;
+  this.v1 = null;
+  this.v2 = null;
+}
+
+HandlerTask.prototype.run = function (packet) {
+  if (packet != null) {
+    if (packet.kind == KIND_WORK) {
+      this.v1 = packet.addTo(this.v1);
+    } else {
+      this.v2 = packet.addTo(this.v2);
+    }
+  }
+  if (this.v1 != null) {
+    var count = this.v1.a1;
+    var v;
+    if (count < DATA_SIZE) {
+      if (this.v2 != null) {
+        v = this.v2;
+        this.v2 = this.v2.link;
+        v.a1 = this.v1.a2[count];
+        this.v1.a1 = count + 1;
+        return this.scheduler.queue(v);
+      }
+    } else {
+      v = this.v1;
+      this.v1 = this.v1.link;
+      return this.scheduler.queue(v);
+    }
+  }
+  return this.scheduler.suspendCurrent();
+};
+
+HandlerTask.prototype.toString = function () {
+  return "HandlerTask";
+};
+
+/* --- *
+ * P a c k e t
+ * --- */
+
+var DATA_SIZE = 4;
+
+/**
+ * A simple package of data that is manipulated by the tasks.  The exact layout
+ * of the payload data carried by a packet is not importaint, and neither is the
+ * nature of the work performed on packets by the tasks.
+ *
+ * Besides carrying data, packets form linked lists and are hence used both as
+ * data and worklists.
+ * @param {Packet} link the tail of the linked list of packets
+ * @param {int} id an ID for this packet
+ * @param {int} kind the type of this packet
+ * @constructor
+ */
+function Packet(link, id, kind) {
+  this.link = link;
+  this.id = id;
+  this.kind = kind;
+  this.a1 = 0;
+  this.a2 = new Array(DATA_SIZE);
+}
+
+/**
+ * Add this packet to the end of a worklist, and return the worklist.
+ * @param {Packet} queue the worklist to add this packet to
+ */
+Packet.prototype.addTo = function (queue) {
+  this.link = null;
+  if (queue == null) return this;
+  var peek, next = queue;
+  while ((peek = next.link) != null)
+    next = peek;
+  next.link = this;
+  return queue;
+};
+
+Packet.prototype.toString = function () {
+  return "Packet";
+};
diff --git a/deps/v8/benchmarks/run.html b/deps/v8/benchmarks/run.html
new file mode 100644
index 0000000..8663cf1
--- /dev/null
+++ b/deps/v8/benchmarks/run.html
@@ -0,0 +1,102 @@
+<html>
+<head>
+<title>V8 Benchmark Suite</title>
+<script type="text/javascript" src="base.js"></script>
+<script type="text/javascript" src="richards.js"></script>
+<script type="text/javascript" src="deltablue.js"></script>
+<script type="text/javascript" src="crypto.js"></script>
+<script type="text/javascript" src="raytrace.js"></script>
+<script type="text/javascript" src="earley-boyer.js"></script>
+<script type="text/javascript" src="regexp.js"></script>
+<link type="text/css" rel="stylesheet" href="style.css"></link>
+<script type="text/javascript">
+var completed = 0;
+var benchmarks = BenchmarkSuite.CountBenchmarks();
+var success = true;
+
+function ShowProgress(name) {
+  var status = document.getElementById("status");
+  var percentage = ((++completed) / benchmarks) * 100;
+  status.innerHTML = "Running: " + Math.round(percentage) + "% completed.";
+}
+
+
+function AddResult(name, result) {
+  var text = name + ': ' + result;
+  var results = document.getElementById("results");
+  results.innerHTML += (text + "<br/>");  
+}
+
+
+function AddError(name, error) {
+  AddResult(name, '<b>error</b>');
+  success = false;
+}
+
+
+function AddScore(score) {
+  var status = document.getElementById("status");
+  if (success) {
+    status.innerHTML = "Score: " + score;
+  }
+}
+
+
+function Run() {
+  BenchmarkSuite.RunSuites({ NotifyStep: ShowProgress,
+                             NotifyError: AddError,
+                             NotifyResult: AddResult,
+                             NotifyScore: AddScore }); 
+}
+
+function Load() {
+  var version = BenchmarkSuite.version;
+  document.getElementById("version").innerHTML = version;
+  window.setTimeout(Run, 200);
+}
+</script>
+</head>
+<body onLoad="Load()">
+<div>
+  <div class="title"><h1>V8 Benchmark Suite - version <span id="version">?</span></h1></div>
+  <table>
+    <tr>
+      <td class="contents">
+This page contains a suite of pure JavaScript benchmarks that we have
+used to tune V8. The final score is computed as the geometric mean of
+the individual results to make it independent of the running times of
+the individual benchmarks and of a reference system (score
+100). Scores are not comparable across benchmark suite versions and
+higher scores means better performance: <em>Bigger is better!</em>
+
+<ul>
+<li><b>Richards</b><br/>OS kernel simulation benchmark, originally written in BCPL by Martin Richards (<i>539 lines</i>).</li>
+<li><b>DeltaBlue</b><br/>One-way constraint solver, originally written in Smalltalk by John Maloney and Mario Wolczko (<i>880 lines</i>).</li>
+<li><b>Crypto</b><br/>Encryption and decryption benchmark based on code by Tom Wu (<i>1689 lines</i>).</li>
+<li><b>RayTrace</b><br/>Ray tracer benchmark based on code by <a href="http://flog.co.nz/">Adam Burmister</a> (<i>3418 lines</i>).</li>
+<li><b>EarleyBoyer</b><br/>Classic Scheme benchmarks, translated to JavaScript by Florian Loitsch's Scheme2Js compiler (<i>4682 lines</i>).</li>
+<li><b>RegExp</b><br/>Regular expression benchmark generated by extracting regular expression operations from 50 of the most popular web pages
+(<i>4758 lines</i>).
+</li>
+</ul>
+
+<p>
+Note that benchmark results are not comparable unless both results are
+run with the same revision of the benchmark suite.  We will be making
+revisions from time to time in order to fix bugs or expand the scope
+of the benchmark suite.  For previous revisions and the change log see
+the <a href="http://v8.googlecode.com/svn/data/benchmarks/current/revisions.html">revisions</a> page.
+</p>
+
+</td><td style="text-align: center">
+<div class="run">
+  <div id="status" style="text-align: center; margin-top: 60px; font-size: 120%; font-weight: bold;">Starting...</div>
+  <div style="text-align: left; margin: 30px 0 0 90px;" id="results">
+  <div>
+</div>
+</td></tr></table>
+
+</div>
+
+</body>
+</html>
diff --git a/deps/v8/benchmarks/run.js b/deps/v8/benchmarks/run.js
new file mode 100644
index 0000000..bdf1fb1
--- /dev/null
+++ b/deps/v8/benchmarks/run.js
@@ -0,0 +1,60 @@
+// Copyright 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.
+
+
+load('base.js');
+load('richards.js');
+load('deltablue.js');
+load('crypto.js');
+load('raytrace.js');
+load('earley-boyer.js');
+load('regexp.js');
+
+var success = true;
+
+function PrintResult(name, result) {
+  print(name + ': ' + result);
+}
+
+
+function PrintError(name, error) {
+  PrintResult(name, error);
+  success = false;
+}
+
+
+function PrintScore(score) {
+  if (success) {
+    print('----');
+    print('Score (version ' + BenchmarkSuite.version + '): ' + score);
+  }
+}
+
+
+BenchmarkSuite.RunSuites({ NotifyResult: PrintResult,
+                           NotifyError: PrintError,
+                           NotifyScore: PrintScore });
diff --git a/deps/v8/benchmarks/style.css b/deps/v8/benchmarks/style.css
new file mode 100644
index 0000000..d976cdd
--- /dev/null
+++ b/deps/v8/benchmarks/style.css
@@ -0,0 +1,70 @@
+body {
+  font-family: sans-serif;
+}
+
+hr{
+  border: 1px solid;
+  border-color: #36C;
+  margin: 1em 0
+}
+
+h1, h2, h3, h4 {
+  margin: 0;
+  margin-bottom: 0;
+}
+
+h1 {
+  font-size: 190%;
+  height: 1.2em;
+}
+
+
+h2{
+  font-size: 140%;
+  height: 1.2em;
+}
+
+h3{
+  font-size: 100%;
+}
+
+li{
+  margin: .3em 0 1em 0;
+}
+
+body{
+  font-family: Helvetica,Arial,sans-serif;
+  font-size: small;
+  color: #000;
+  background-color: #fff;
+}
+
+div.title {
+  background-color: rgb(229, 236, 249);
+  border-top: 1px solid rgb(51, 102, 204);
+  text-align: center;
+  padding-top: 0.2em;
+  padding-bottom: 0.2em;
+  margin-bottom: 20px;
+}
+
+div.subtitle {
+  border-bottom: 1px solid rgb(51, 102, 204);
+  margin-top: 2em;
+}
+
+td.contents {
+  text-align: start;
+}
+
+div.run {
+  margin: 20px;
+  width: 300px;
+  height: 300px;
+  float: right;
+  background-color: rgb(229, 236, 249);
+  background-image: url(v8-logo.png);
+  background-position: center center;
+  background-repeat: no-repeat;
+  border: 1px solid rgb(51, 102, 204);
+}
diff --git a/deps/v8/benchmarks/v8-logo.png b/deps/v8/benchmarks/v8-logo.png
new file mode 100644
index 0000000..9186765
Binary files /dev/null and b/deps/v8/benchmarks/v8-logo.png differ
diff --git a/deps/v8/include/v8-debug.h b/deps/v8/include/v8-debug.h
new file mode 100644
index 0000000..4c639c1
--- /dev/null
+++ b/deps/v8/include/v8-debug.h
@@ -0,0 +1,179 @@
+// Copyright 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_DEBUG_H_
+#define V8_DEBUG_H_
+
+#include "v8.h"
+
+#ifdef _WIN32
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef unsigned short uint16_t;  // NOLINT
+typedef long long int64_t;  // NOLINT
+
+// Setup for Windows DLL export/import. See v8.h in this directory for
+// information on how to build/use V8 as a DLL.
+#if defined(BUILDING_V8_SHARED) && defined(USING_V8_SHARED)
+#error both BUILDING_V8_SHARED and USING_V8_SHARED are set - please check the\
+  build configuration to ensure that at most one of these is set
+#endif
+
+#ifdef BUILDING_V8_SHARED
+#define EXPORT __declspec(dllexport)
+#elif USING_V8_SHARED
+#define EXPORT __declspec(dllimport)
+#else
+#define EXPORT
+#endif
+
+#else  // _WIN32
+
+// Setup for Linux shared library export. See v8.h in this directory for
+// information on how to build/use V8 as shared library.
+#if defined(__GNUC__) && (__GNUC__ >= 4)
+#define EXPORT __attribute__ ((visibility("default")))
+#else  // defined(__GNUC__) && (__GNUC__ >= 4)
+#define EXPORT
+#endif  // defined(__GNUC__) && (__GNUC__ >= 4)
+
+#endif  // _WIN32
+
+
+/**
+ * Debugger support for the V8 JavaScript engine.
+ */
+namespace v8 {
+
+// Debug events which can occur in the V8 JavaScript engine.
+enum DebugEvent {
+  Break = 1,
+  Exception = 2,
+  NewFunction = 3,
+  BeforeCompile = 4,
+  AfterCompile  = 5
+};
+
+
+/**
+ * Debug event callback function.
+ *
+ * \param event the type of the debug event that triggered the callback
+ *   (enum DebugEvent)
+ * \param exec_state execution state (JavaScript object)
+ * \param event_data event specific data (JavaScript object)
+ * \param data value passed by the user to SetDebugEventListener
+ */
+typedef void (*DebugEventCallback)(DebugEvent event,
+                                   Handle<Object> exec_state,
+                                   Handle<Object> event_data,
+                                   Handle<Value> data);
+
+
+/**
+ * Debug message callback function.
+ *
+ * \param message the debug message
+ * \param length length of the message
+ * \param data the data value passed when registering the message handler
+ * A DebugMessageHandler does not take posession of the message string,
+ * and must not rely on the data persisting after the handler returns.
+ */
+typedef void (*DebugMessageHandler)(const uint16_t* message, int length,
+                                    void* data);
+
+/**
+ * Debug host dispatch callback function.
+ *
+ * \param dispatch the dispatch value
+ * \param data the data value passed when registering the dispatch handler
+ */
+typedef void (*DebugHostDispatchHandler)(void* dispatch,
+                                         void* data);
+
+
+
+class EXPORT Debug {
+ public:
+  // Set a C debug event listener.
+  static bool SetDebugEventListener(DebugEventCallback that,
+                                    Handle<Value> data = Handle<Value>());
+
+  // Set a JavaScript debug event listener.
+  static bool SetDebugEventListener(v8::Handle<v8::Object> that,
+                                    Handle<Value> data = Handle<Value>());
+
+  // Break execution of JavaScript.
+  static void DebugBreak();
+
+  // Message based interface. The message protocol is JSON.
+  static void SetMessageHandler(DebugMessageHandler handler, void* data = NULL,
+                                bool message_handler_thread = true);
+  static void SendCommand(const uint16_t* command, int length);
+
+  // Dispatch interface.
+  static void SetHostDispatchHandler(DebugHostDispatchHandler handler,
+                                     void* data = NULL);
+  static void SendHostDispatch(void* dispatch);
+
+ /**
+  * Run a JavaScript function in the debugger.
+  * \param fun the function to call
+  * \param data passed as second argument to the function
+  * With this call the debugger is entered and the function specified is called
+  * with the execution state as the first argument. This makes it possible to
+  * get access to information otherwise not available during normal JavaScript
+  * execution e.g. details on stack frames. The following example show a
+  * JavaScript function which when passed to v8::Debug::Call will return the
+  * current line of JavaScript execution.
+  *
+  * \code
+  *   function frame_source_line(exec_state) {
+  *     return exec_state.frame(0).sourceLine();
+  *   }
+  * \endcode
+  */
+  static Handle<Value> Call(v8::Handle<v8::Function> fun,
+                            Handle<Value> data = Handle<Value>());
+
+ /**
+  * Enable the V8 builtin debug agent. The debugger agent will listen on the
+  * supplied TCP/IP port for remote debugger connection.
+  * \param name the name of the embedding application
+  * \param port the TCP/IP port to listen on
+  */
+  static bool EnableAgent(const char* name, int port);
+};
+
+
+}  // namespace v8
+
+
+#undef EXPORT
+
+
+#endif  // V8_DEBUG_H_
diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h
new file mode 100644
index 0000000..1ddaee0
--- /dev/null
+++ b/deps/v8/include/v8.h
@@ -0,0 +1,2538 @@
+// 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.
+
+/** \mainpage V8 API Reference Guide
+ *
+ * V8 is Google's open source JavaScript engine.
+ *
+ * This set of documents provides reference material generated from the
+ * V8 header file, include/v8.h.
+ *
+ * For other documentation see http://code.google.com/apis/v8/
+ */
+
+#ifndef V8_H_
+#define V8_H_
+
+#include <stdio.h>
+
+#ifdef _WIN32
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef unsigned short uint16_t;  // NOLINT
+typedef long long int64_t;  // NOLINT
+
+// Setup for Windows DLL export/import. When building the V8 DLL the
+// BUILDING_V8_SHARED needs to be defined. When building a program which uses
+// the V8 DLL USING_V8_SHARED needs to be defined. When either building the V8
+// static library or building a program which uses the V8 static library neither
+// BUILDING_V8_SHARED nor USING_V8_SHARED should be defined.
+// The reason for having both V8EXPORT and V8EXPORT_INLINE is that classes which
+// have their code inside this header file need to have __declspec(dllexport)
+// when building the DLL but cannot have __declspec(dllimport) when building
+// a program which uses the DLL.
+#if defined(BUILDING_V8_SHARED) && defined(USING_V8_SHARED)
+#error both BUILDING_V8_SHARED and USING_V8_SHARED are set - please check the\
+  build configuration to ensure that at most one of these is set
+#endif
+
+#ifdef BUILDING_V8_SHARED
+#define V8EXPORT __declspec(dllexport)
+#define V8EXPORT_INLINE __declspec(dllexport)
+#elif USING_V8_SHARED
+#define V8EXPORT __declspec(dllimport)
+#define V8EXPORT_INLINE
+#else
+#define V8EXPORT
+#define V8EXPORT_INLINE
+#endif  // BUILDING_V8_SHARED
+
+#else  // _WIN32
+
+#include <stdint.h>
+
+// Setup for Linux shared library export. There is no need to destinguish
+// neither between building or using the V8 shared library nor between using
+// the shared or static V8 library as there is on Windows. Therefore there is
+// no checking of BUILDING_V8_SHARED and USING_V8_SHARED.
+#if defined(__GNUC__) && (__GNUC__ >= 4)
+#define V8EXPORT __attribute__ ((visibility("default")))
+#define V8EXPORT_INLINE __attribute__ ((visibility("default")))
+#else  // defined(__GNUC__) && (__GNUC__ >= 4)
+#define V8EXPORT
+#define V8EXPORT_INLINE
+#endif  // defined(__GNUC__) && (__GNUC__ >= 4)
+
+#endif  // _WIN32
+
+/**
+ * The v8 JavaScript engine.
+ */
+namespace v8 {
+
+class Context;
+class String;
+class Value;
+class Utils;
+class Number;
+class Object;
+class Array;
+class Int32;
+class Uint32;
+class External;
+class Primitive;
+class Boolean;
+class Integer;
+class Function;
+class Date;
+class ImplementationUtilities;
+class Signature;
+template <class T> class Handle;
+template <class T> class Local;
+template <class T> class Persistent;
+class FunctionTemplate;
+class ObjectTemplate;
+class Data;
+
+
+// --- W e a k  H a n d l e s
+
+
+/**
+ * A weak reference callback function.
+ *
+ * \param object the weak global object to be reclaimed by the garbage collector
+ * \param parameter the value passed in when making the weak global object
+ */
+typedef void (*WeakReferenceCallback)(Persistent<Value> object,
+                                      void* parameter);
+
+
+// --- H a n d l e s ---
+
+#define TYPE_CHECK(T, S)                              \
+  while (false) {                                     \
+    *(static_cast<T**>(0)) = static_cast<S*>(0);      \
+  }
+
+/**
+ * An object reference managed by the v8 garbage collector.
+ *
+ * All objects returned from v8 have to be tracked by the garbage
+ * collector so that it knows that the objects are still alive.  Also,
+ * because the garbage collector may move objects, it is unsafe to
+ * point directly to an object.  Instead, all objects are stored in
+ * handles which are known by the garbage collector and updated
+ * whenever an object moves.  Handles should always be passed by value
+ * (except in cases like out-parameters) and they should never be
+ * allocated on the heap.
+ *
+ * There are two types of handles: local and persistent handles.
+ * Local handles are light-weight and transient and typically used in
+ * local operations.  They are managed by HandleScopes.  Persistent
+ * handles can be used when storing objects across several independent
+ * operations and have to be explicitly deallocated when they're no
+ * longer used.
+ *
+ * It is safe to extract the object stored in the handle by
+ * dereferencing the handle (for instance, to extract the Object* from
+ * an Handle<Object>); the value will still be governed by a handle
+ * behind the scenes and the same rules apply to these values as to
+ * their handles.
+ */
+template <class T> class V8EXPORT_INLINE Handle {
+ public:
+
+  /**
+   * Creates an empty handle.
+   */
+  Handle();
+
+  /**
+   * Creates a new handle for the specified value.
+   */
+  explicit Handle(T* val) : val_(val) { }
+
+  /**
+   * Creates a handle for the contents of the specified handle.  This
+   * constructor allows you to pass handles as arguments by value and
+   * to assign between handles.  However, if you try to assign between
+   * incompatible handles, for instance from a Handle<String> to a
+   * Handle<Number> it will cause a compiletime error.  Assigning
+   * between compatible handles, for instance assigning a
+   * Handle<String> to a variable declared as Handle<Value>, is legal
+   * because String is a subclass of Value.
+   */
+  template <class S> inline Handle(Handle<S> that)
+      : val_(reinterpret_cast<T*>(*that)) {
+    /**
+     * This check fails when trying to convert between incompatible
+     * handles. For example, converting from a Handle<String> to a
+     * Handle<Number>.
+     */
+    TYPE_CHECK(T, S);
+  }
+
+  /**
+   * Returns true if the handle is empty.
+   */
+  bool IsEmpty() const { return val_ == 0; }
+
+  T* operator->() const;
+
+  T* operator*() const;
+
+  /**
+   * Sets the handle to be empty. IsEmpty() will then return true.
+   */
+  void Clear() { this->val_ = 0; }
+
+  /**
+   * Checks whether two handles are the same.
+   * Returns true if both are empty, or if the objects
+   * to which they refer are identical.
+   * The handles' references are not checked.
+   */
+  template <class S> bool operator==(Handle<S> that) const {
+    void** a = reinterpret_cast<void**>(**this);
+    void** b = reinterpret_cast<void**>(*that);
+    if (a == 0) return b == 0;
+    if (b == 0) return false;
+    return *a == *b;
+  }
+
+  /**
+   * Checks whether two handles are different.
+   * Returns true if only one of the handles is empty, or if
+   * the objects to which they refer are different.
+   * The handles' references are not checked.
+   */
+  template <class S> bool operator!=(Handle<S> that) const {
+    return !operator==(that);
+  }
+
+  template <class S> static inline Handle<T> Cast(Handle<S> that) {
+    if (that.IsEmpty()) return Handle<T>();
+    return Handle<T>(T::Cast(*that));
+  }
+
+ private:
+  T* val_;
+};
+
+
+/**
+ * A light-weight stack-allocated object handle.  All operations
+ * that return objects from within v8 return them in local handles.  They
+ * are created within HandleScopes, and all local handles allocated within a
+ * handle scope are destroyed when the handle scope is destroyed.  Hence it
+ * is not necessary to explicitly deallocate local handles.
+ */
+template <class T> class V8EXPORT_INLINE Local : public Handle<T> {
+ public:
+  Local();
+  template <class S> inline Local(Local<S> that)
+      : Handle<T>(reinterpret_cast<T*>(*that)) {
+    /**
+     * This check fails when trying to convert between incompatible
+     * handles. For example, converting from a Handle<String> to a
+     * Handle<Number>.
+     */
+    TYPE_CHECK(T, S);
+  }
+  template <class S> inline Local(S* that) : Handle<T>(that) { }
+  template <class S> static inline Local<T> Cast(Local<S> that) {
+    if (that.IsEmpty()) return Local<T>();
+    return Local<T>(T::Cast(*that));
+  }
+
+  /** Create a local handle for the content of another handle.
+   *  The referee is kept alive by the local handle even when
+   *  the original handle is destroyed/disposed.
+   */
+  static Local<T> New(Handle<T> that);
+};
+
+
+/**
+ * An object reference that is independent of any handle scope.  Where
+ * a Local handle only lives as long as the HandleScope in which it was
+ * allocated, a Persistent handle remains valid until it is explicitly
+ * disposed.
+ *
+ * A persistent handle contains a reference to a storage cell within
+ * the v8 engine which holds an object value and which is updated by
+ * the garbage collector whenever the object is moved.  A new storage
+ * cell can be created using Persistent::New and existing handles can
+ * be disposed using Persistent::Dispose.  Since persistent handles
+ * are passed by value you may have many persistent handle objects
+ * that point to the same storage cell.  For instance, if you pass a
+ * persistent handle as an argument to a function you will not get two
+ * different storage cells but rather two references to the same
+ * storage cell.
+ */
+template <class T> class V8EXPORT_INLINE Persistent : public Handle<T> {
+ public:
+
+  /**
+   * Creates an empty persistent handle that doesn't point to any
+   * storage cell.
+   */
+  Persistent();
+
+  /**
+   * Creates a persistent handle for the same storage cell as the
+   * specified handle.  This constructor allows you to pass persistent
+   * handles as arguments by value and to assign between persistent
+   * handles.  However, attempting to assign between incompatible
+   * persistent handles, for instance from a Persistent<String> to a
+   * Persistent<Number> will cause a compiletime error.  Assigning
+   * between compatible persistent handles, for instance assigning a
+   * Persistent<String> to a variable declared as Persistent<Value>,
+   * is allowed as String is a subclass of Value.
+   */
+  template <class S> inline Persistent(Persistent<S> that)
+      : Handle<T>(reinterpret_cast<T*>(*that)) {
+    /**
+     * This check fails when trying to convert between incompatible
+     * handles. For example, converting from a Handle<String> to a
+     * Handle<Number>.
+     */
+    TYPE_CHECK(T, S);
+  }
+
+  template <class S> inline Persistent(S* that) : Handle<T>(that) { }
+
+  /**
+   * "Casts" a plain handle which is known to be a persistent handle
+   * to a persistent handle.
+   */
+  template <class S> explicit inline Persistent(Handle<S> that)
+      : Handle<T>(*that) { }
+
+  template <class S> static inline Persistent<T> Cast(Persistent<S> that) {
+    if (that.IsEmpty()) return Persistent<T>();
+    return Persistent<T>(T::Cast(*that));
+  }
+
+  /**
+   * Creates a new persistent handle for an existing local or
+   * persistent handle.
+   */
+  static Persistent<T> New(Handle<T> that);
+
+  /**
+   * Releases the storage cell referenced by this persistent handle.
+   * Does not remove the reference to the cell from any handles.
+   * This handle's reference, and any any other references to the storage
+   * cell remain and IsEmpty will still return false.
+   */
+  void Dispose();
+
+  /**
+   * Make the reference to this object weak.  When only weak handles
+   * refer to the object, the garbage collector will perform a
+   * callback to the given V8::WeakReferenceCallback function, passing
+   * it the object reference and the given parameters.
+   */
+  void MakeWeak(void* parameters, WeakReferenceCallback callback);
+
+  /** Clears the weak reference to this object.*/
+  void ClearWeak();
+
+  /**
+   *Checks if the handle holds the only reference to an object.
+   */
+  bool IsNearDeath() const;
+
+  /**
+   * Returns true if the handle's reference is weak.
+   */
+  bool IsWeak() const;
+
+ private:
+  friend class ImplementationUtilities;
+  friend class ObjectTemplate;
+};
+
+
+ /**
+ * A stack-allocated class that governs a number of local handles.
+ * After a handle scope has been created, all local handles will be
+ * allocated within that handle scope until either the handle scope is
+ * deleted or another handle scope is created.  If there is already a
+ * handle scope and a new one is created, all allocations will take
+ * place in the new handle scope until it is deleted.  After that,
+ * new handles will again be allocated in the original handle scope.
+ *
+ * After the handle scope of a local handle has been deleted the
+ * garbage collector will no longer track the object stored in the
+ * handle and may deallocate it.  The behavior of accessing a handle
+ * for which the handle scope has been deleted is undefined.
+ */
+class V8EXPORT HandleScope {
+ public:
+  HandleScope();
+
+  ~HandleScope();
+
+  /**
+   * Closes the handle scope and returns the value as a handle in the
+   * previous scope, which is the new current scope after the call.
+   */
+  template <class T> Local<T> Close(Handle<T> value);
+
+  /**
+   * Counts the number of allocated handles.
+   */
+  static int NumberOfHandles();
+
+  /**
+   * Creates a new handle with the given value.
+   */
+  static void** CreateHandle(void* value);
+
+ private:
+  // Make it impossible to create heap-allocated or illegal handle
+  // scopes by disallowing certain operations.
+  HandleScope(const HandleScope&);
+  void operator=(const HandleScope&);
+  void* operator new(size_t size);
+  void operator delete(void*, size_t);
+
+  // This Data class is accessible internally through a typedef in the
+  // ImplementationUtilities class.
+  class V8EXPORT Data {
+   public:
+    int extensions;
+    void** next;
+    void** limit;
+    inline void Initialize() {
+      extensions = -1;
+      next = limit = NULL;
+    }
+  };
+
+  Data previous_;
+
+  // Allow for the active closing of HandleScopes which allows to pass a handle
+  // from the HandleScope being closed to the next top most HandleScope.
+  bool is_closed_;
+  void** RawClose(void** value);
+
+  friend class ImplementationUtilities;
+};
+
+
+// --- S p e c i a l   o b j e c t s ---
+
+
+/**
+ * The superclass of values and API object templates.
+ */
+class V8EXPORT Data {
+ private:
+  Data();
+};
+
+
+/**
+ * Pre-compilation data that can be associated with a script.  This
+ * data can be calculated for a script in advance of actually
+ * compiling it, and can be stored between compilations.  When script
+ * data is given to the compile method compilation will be faster.
+ */
+class V8EXPORT ScriptData {  // NOLINT
+ public:
+  virtual ~ScriptData() { }
+  static ScriptData* PreCompile(const char* input, int length);
+  static ScriptData* New(unsigned* data, int length);
+
+  virtual int Length() = 0;
+  virtual unsigned* Data() = 0;
+};
+
+
+/**
+ * The origin, within a file, of a script.
+ */
+class V8EXPORT ScriptOrigin {
+ public:
+  ScriptOrigin(Handle<Value> resource_name,
+               Handle<Integer> resource_line_offset = Handle<Integer>(),
+               Handle<Integer> resource_column_offset = Handle<Integer>())
+      : resource_name_(resource_name),
+        resource_line_offset_(resource_line_offset),
+        resource_column_offset_(resource_column_offset) { }
+  inline Handle<Value> ResourceName() const;
+  inline Handle<Integer> ResourceLineOffset() const;
+  inline Handle<Integer> ResourceColumnOffset() const;
+ private:
+  Handle<Value> resource_name_;
+  Handle<Integer> resource_line_offset_;
+  Handle<Integer> resource_column_offset_;
+};
+
+
+/**
+ * A compiled JavaScript script.
+ */
+class V8EXPORT Script {
+ public:
+
+  /**
+   * Compiles the specified script. The ScriptOrigin* and ScriptData*
+   * parameters are owned by the caller of Script::Compile. No
+   * references to these objects are kept after compilation finishes.
+   */
+  static Local<Script> Compile(Handle<String> source,
+                               ScriptOrigin* origin = NULL,
+                               ScriptData* pre_data = NULL);
+
+  /**
+   * Compiles the specified script using the specified file name
+   * object (typically a string) as the script's origin.
+   */
+  static Local<Script> Compile(Handle<String> source,
+                               Handle<Value> file_name);
+
+  /**
+   * Runs the script returning the resulting value.
+   */
+  Local<Value> Run();
+
+  /**
+   * Returns the script id value.
+   */
+  Local<Value> Id();
+};
+
+
+/**
+ * An error message.
+ */
+class V8EXPORT Message {
+ public:
+  Local<String> Get() const;
+  Local<String> GetSourceLine() const;
+
+  Handle<Value> GetScriptResourceName() const;
+
+  /**
+   * Returns the number, 1-based, of the line where the error occurred.
+   */
+  int GetLineNumber() const;
+
+  /**
+   * Returns the index within the script of the first character where
+   * the error occurred.
+   */
+  int GetStartPosition() const;
+
+  /**
+   * Returns the index within the script of the last character where
+   * the error occurred.
+   */
+  int GetEndPosition() const;
+
+  /**
+   * Returns the index within the line of the first character where
+   * the error occurred.
+   */
+  int GetStartColumn() const;
+
+  /**
+   * Returns the index within the line of the last character where
+   * the error occurred.
+   */
+  int GetEndColumn() const;
+
+  // TODO(1245381): Print to a string instead of on a FILE.
+  static void PrintCurrentStackTrace(FILE* out);
+};
+
+
+// --- V a l u e ---
+
+
+/**
+ * The superclass of all JavaScript values and objects.
+ */
+class V8EXPORT Value : public Data {
+ public:
+
+  /**
+   * Returns true if this value is the undefined value.  See ECMA-262
+   * 4.3.10.
+   */
+  bool IsUndefined() const;
+
+  /**
+   * Returns true if this value is the null value.  See ECMA-262
+   * 4.3.11.
+   */
+  bool IsNull() const;
+
+   /**
+   * Returns true if this value is true.
+   */
+  bool IsTrue() const;
+
+  /**
+   * Returns true if this value is false.
+   */
+  bool IsFalse() const;
+
+  /**
+   * Returns true if this value is an instance of the String type.
+   * See ECMA-262 8.4.
+   */
+  bool IsString() const;
+
+  /**
+   * Returns true if this value is a function.
+   */
+  bool IsFunction() const;
+
+  /**
+   * Returns true if this value is an array.
+   */
+  bool IsArray() const;
+
+  /**
+   * Returns true if this value is an object.
+   */
+  bool IsObject() const;
+
+  /**
+   * Returns true if this value is boolean.
+   */
+  bool IsBoolean() const;
+
+  /**
+   * Returns true if this value is a number.
+   */
+  bool IsNumber() const;
+
+  /**
+   * Returns true if this value is external.
+   */
+  bool IsExternal() const;
+
+  /**
+   * Returns true if this value is a 32-bit signed integer.
+   */
+  bool IsInt32() const;
+
+  /**
+   * Returns true if this value is a Date.
+   */
+  bool IsDate() const;
+
+  Local<Boolean> ToBoolean() const;
+  Local<Number> ToNumber() const;
+  Local<String> ToString() const;
+  Local<String> ToDetailString() const;
+  Local<Object> ToObject() const;
+  Local<Integer> ToInteger() const;
+  Local<Uint32> ToUint32() const;
+  Local<Int32> ToInt32() const;
+
+  /**
+   * Attempts to convert a string to an array index.
+   * Returns an empty handle if the conversion fails.
+   */
+  Local<Uint32> ToArrayIndex() const;
+
+  bool BooleanValue() const;
+  double NumberValue() const;
+  int64_t IntegerValue() const;
+  uint32_t Uint32Value() const;
+  int32_t Int32Value() const;
+
+  /** JS == */
+  bool Equals(Handle<Value> that) const;
+  bool StrictEquals(Handle<Value> that) const;
+};
+
+
+/**
+ * The superclass of primitive values.  See ECMA-262 4.3.2.
+ */
+class V8EXPORT Primitive : public Value { };
+
+
+/**
+ * A primitive boolean value (ECMA-262, 4.3.14).  Either the true
+ * or false value.
+ */
+class V8EXPORT Boolean : public Primitive {
+ public:
+  bool Value() const;
+  static inline Handle<Boolean> New(bool value);
+};
+
+
+/**
+ * A JavaScript string value (ECMA-262, 4.3.17).
+ */
+class V8EXPORT String : public Primitive {
+ public:
+
+  /**
+   * Returns the number of characters in this string.
+   */
+  int Length() const;
+
+  /**
+   * Returns the number of bytes in the UTF-8 encoded
+   * representation of this string.
+   */
+  int Utf8Length() const;
+
+  /**
+   * Write the contents of the string to an external buffer.
+   * If no arguments are given, expects the buffer to be large
+   * enough to hold the entire string and NULL terminator. Copies
+   * the contents of the string and the NULL terminator into the
+   * buffer.
+   *
+   * Copies up to length characters into the output buffer.
+   * Only null-terminates if there is enough space in the buffer.
+   *
+   * \param buffer The buffer into which the string will be copied.
+   * \param start The starting position within the string at which
+   * copying begins.
+   * \param length The number of bytes to copy from the string.
+   * \return The number of characters copied to the buffer
+   * excluding the NULL terminator.
+   */
+  int Write(uint16_t* buffer, int start = 0, int length = -1) const;  // UTF-16
+  int WriteAscii(char* buffer, int start = 0, int length = -1) const;  // ASCII
+  int WriteUtf8(char* buffer, int length = -1) const; // UTF-8
+
+  /**
+   * A zero length string.
+   */
+  static v8::Local<v8::String> Empty();
+
+  /**
+   * Returns true if the string is external
+   */
+  bool IsExternal() const;
+
+  /**
+   * Returns true if the string is both external and ascii
+   */
+  bool IsExternalAscii() const;
+  /**
+   * An ExternalStringResource is a wrapper around a two-byte string
+   * buffer that resides outside V8's heap. Implement an
+   * ExternalStringResource to manage the life cycle of the underlying
+   * buffer.  Note that the string data must be immutable.
+   */
+  class V8EXPORT ExternalStringResource {  // NOLINT
+   public:
+    /**
+     * Override the destructor to manage the life cycle of the underlying
+     * buffer.
+     */
+    virtual ~ExternalStringResource() {}
+    /** The string data from the underlying buffer.*/
+    virtual const uint16_t* data() const = 0;
+    /** The length of the string. That is, the number of two-byte characters.*/
+    virtual size_t length() const = 0;
+   protected:
+    ExternalStringResource() {}
+   private:
+    // Disallow copying and assigning.
+    ExternalStringResource(const ExternalStringResource&);
+    void operator=(const ExternalStringResource&);
+  };
+
+  /**
+   * An ExternalAsciiStringResource is a wrapper around an ascii
+   * string buffer that resides outside V8's heap. Implement an
+   * ExternalAsciiStringResource to manage the life cycle of the
+   * underlying buffer.  Note that the string data must be immutable
+   * and that the data must be strict 7-bit ASCII, not Latin1 or
+   * UTF-8, which would require special treatment internally in the
+   * engine and, in the case of UTF-8, do not allow efficient indexing.
+   * Use String::New or convert to 16 bit data for non-ASCII.
+   */
+
+  class V8EXPORT ExternalAsciiStringResource {  // NOLINT
+   public:
+    /**
+     * Override the destructor to manage the life cycle of the underlying
+     * buffer.
+     */
+    virtual ~ExternalAsciiStringResource() {}
+    /** The string data from the underlying buffer.*/
+    virtual const char* data() const = 0;
+    /** The number of ascii characters in the string.*/
+    virtual size_t length() const = 0;
+   protected:
+    ExternalAsciiStringResource() {}
+   private:
+    // Disallow copying and assigning.
+    ExternalAsciiStringResource(const ExternalAsciiStringResource&);
+    void operator=(const ExternalAsciiStringResource&);
+  };
+
+  /**
+   * Get the ExternalStringResource for an external string.  Only
+   * valid if IsExternal() returns true.
+   */
+  ExternalStringResource* GetExternalStringResource() const;
+
+  /**
+   * Get the ExternalAsciiStringResource for an external ascii string.
+   * Only valid if IsExternalAscii() returns true.
+   */
+  ExternalAsciiStringResource* GetExternalAsciiStringResource() const;
+
+  static String* Cast(v8::Value* obj);
+
+  /**
+   * Allocates a new string from either utf-8 encoded or ascii data.
+   * The second parameter 'length' gives the buffer length.
+   * If the data is utf-8 encoded, the caller must
+   * be careful to supply the length parameter.
+   * If it is not given, the function calls
+   * 'strlen' to determine the buffer length, it might be
+   * wrong if 'data' contains a null character.
+   */
+  static Local<String> New(const char* data, int length = -1);
+
+  /** Allocates a new string from utf16 data.*/
+  static Local<String> New(const uint16_t* data, int length = -1);
+
+  /** Creates a symbol. Returns one if it exists already.*/
+  static Local<String> NewSymbol(const char* data, int length = -1);
+
+  /**
+   * Creates a new external string using the data defined in the given
+   * resource. The resource is deleted when the external string is no
+   * longer live on V8's heap. The caller of this function should not
+   * delete or modify the resource. Neither should the underlying buffer be
+   * deallocated or modified except through the destructor of the
+   * external string resource.
+   */
+  static Local<String> NewExternal(ExternalStringResource* resource);
+
+  /**
+   * Associate an external string resource with this string by transforming it
+   * in place so that existing references to this string in the JavaScript heap
+   * will use the external string resource. The external string resource's
+   * character contents needs to be equivalent to this string.
+   * Returns true if the string has been changed to be an external string.
+   * The string is not modified if the operation fails.
+   */
+  bool MakeExternal(ExternalStringResource* resource);
+
+  /**
+   * Creates a new external string using the ascii data defined in the given
+   * resource. The resource is deleted when the external string is no
+   * longer live on V8's heap. The caller of this function should not
+   * delete or modify the resource. Neither should the underlying buffer be
+   * deallocated or modified except through the destructor of the
+   * external string resource.
+   */
+  static Local<String> NewExternal(ExternalAsciiStringResource* resource);
+
+  /**
+   * Associate an external string resource with this string by transforming it
+   * in place so that existing references to this string in the JavaScript heap
+   * will use the external string resource. The external string resource's
+   * character contents needs to be equivalent to this string.
+   * Returns true if the string has been changed to be an external string.
+   * The string is not modified if the operation fails.
+   */
+  bool MakeExternal(ExternalAsciiStringResource* resource);
+
+  /** Creates an undetectable string from the supplied ascii or utf-8 data.*/
+  static Local<String> NewUndetectable(const char* data, int length = -1);
+
+  /** Creates an undetectable string from the supplied utf-16 data.*/
+  static Local<String> NewUndetectable(const uint16_t* data, int length = -1);
+
+  /**
+   * Converts an object to a utf8-encoded character array.  Useful if
+   * you want to print the object.  If conversion to a string fails
+   * (eg. due to an exception in the toString() method of the object)
+   * then the length() method returns 0 and the * operator returns
+   * NULL.
+   */
+  class V8EXPORT Utf8Value {
+   public:
+    explicit Utf8Value(Handle<v8::Value> obj);
+    ~Utf8Value();
+    char* operator*() const { return str_; }
+    int length() { return length_; }
+   private:
+    char* str_;
+    int length_;
+
+    // Disallow copying and assigning.
+    Utf8Value(const Utf8Value&);
+    void operator=(const Utf8Value&);
+  };
+
+  /**
+   * Converts an object to an ascii string.
+   * Useful if you want to print the object.
+   * If conversion to a string fails (eg. due to an exception in the toString()
+   * method of the object) then the length() method returns 0 and the * operator
+   * returns NULL.
+   */
+  class V8EXPORT AsciiValue {
+   public:
+    explicit AsciiValue(Handle<v8::Value> obj);
+    ~AsciiValue();
+    char* operator*() const { return str_; }
+    int length() { return length_; }
+   private:
+    char* str_;
+    int length_;
+
+    // Disallow copying and assigning.
+    AsciiValue(const AsciiValue&);
+    void operator=(const AsciiValue&);
+  };
+
+  /**
+   * Converts an object to a two-byte string.
+   * If conversion to a string fails (eg. due to an exception in the toString()
+   * method of the object) then the length() method returns 0 and the * operator
+   * returns NULL.
+   */
+  class V8EXPORT Value {
+   public:
+    explicit Value(Handle<v8::Value> obj);
+    ~Value();
+    uint16_t* operator*() const { return str_; }
+    int length() { return length_; }
+   private:
+    uint16_t* str_;
+    int length_;
+
+    // Disallow copying and assigning.
+    Value(const Value&);
+    void operator=(const Value&);
+  };
+};
+
+
+/**
+ * A JavaScript number value (ECMA-262, 4.3.20)
+ */
+class V8EXPORT Number : public Primitive {
+ public:
+  double Value() const;
+  static Local<Number> New(double value);
+  static Number* Cast(v8::Value* obj);
+ private:
+  Number();
+};
+
+
+/**
+ * A JavaScript value representing a signed integer.
+ */
+class V8EXPORT Integer : public Number {
+ public:
+  static Local<Integer> New(int32_t value);
+  int64_t Value() const;
+  static Integer* Cast(v8::Value* obj);
+ private:
+  Integer();
+};
+
+
+/**
+ * A JavaScript value representing a 32-bit signed integer.
+ */
+class V8EXPORT Int32 : public Integer {
+ public:
+  int32_t Value() const;
+ private:
+  Int32();
+};
+
+
+/**
+ * A JavaScript value representing a 32-bit unsigned integer.
+ */
+class V8EXPORT Uint32 : public Integer {
+ public:
+  uint32_t Value() const;
+ private:
+  Uint32();
+};
+
+
+/**
+ * An instance of the built-in Date constructor (ECMA-262, 15.9).
+ */
+class V8EXPORT Date : public Value {
+ public:
+  static Local<Value> New(double time);
+
+  /**
+   * A specialization of Value::NumberValue that is more efficient
+   * because we know the structure of this object.
+   */
+  double NumberValue() const;
+
+  static Date* Cast(v8::Value* obj);
+};
+
+
+enum PropertyAttribute {
+  None       = 0,
+  ReadOnly   = 1 << 0,
+  DontEnum   = 1 << 1,
+  DontDelete = 1 << 2
+};
+
+/**
+ * A JavaScript object (ECMA-262, 4.3.3)
+ */
+class V8EXPORT Object : public Value {
+ public:
+  bool Set(Handle<Value> key,
+           Handle<Value> value,
+           PropertyAttribute attribs = None);
+  Local<Value> Get(Handle<Value> key);
+
+  // TODO(1245389): Replace the type-specific versions of these
+  // functions with generic ones that accept a Handle<Value> key.
+  bool Has(Handle<String> key);
+  bool Delete(Handle<String> key);
+  bool Has(uint32_t index);
+  bool Delete(uint32_t index);
+
+  /**
+   * Returns an array containing the names of the enumerable properties
+   * of this object, including properties from prototype objects.  The
+   * array returned by this method contains the same values as would
+   * be enumerated by a for-in statement over this object.
+   */
+  Local<Array> GetPropertyNames();
+
+  /**
+   * Get the prototype object.  This does not skip objects marked to
+   * be skipped by __proto__ and it does not consult the security
+   * handler.
+   */
+  Local<Value> GetPrototype();
+
+  /**
+   * Call builtin Object.prototype.toString on this object.
+   * This is different from Value::ToString() that may call
+   * user-defined toString function. This one does not.
+   */
+  Local<String> ObjectProtoToString();
+
+  /** Gets the number of internal fields for this Object. */
+  int InternalFieldCount();
+  /** Gets the value in an internal field. */
+  Local<Value> GetInternalField(int index);
+  /** Sets the value in an internal field. */
+  void SetInternalField(int index, Handle<Value> value);
+
+  // Testers for local properties.
+  bool HasRealNamedProperty(Handle<String> key);
+  bool HasRealIndexedProperty(uint32_t index);
+  bool HasRealNamedCallbackProperty(Handle<String> key);
+
+  /**
+   * If result.IsEmpty() no real property was located in the prototype chain.
+   * This means interceptors in the prototype chain are not called.
+   */
+  Handle<Value> GetRealNamedPropertyInPrototypeChain(Handle<String> key);
+
+  /** Tests for a named lookup interceptor.*/
+  bool HasNamedLookupInterceptor();
+
+  /** Tests for an index lookup interceptor.*/
+  bool HasIndexedLookupInterceptor();
+
+  /**
+   * Turns on access check on the object if the object is an instance of
+   * a template that has access check callbacks. If an object has no
+   * access check info, the object cannot be accessed by anyone.
+   */
+  void TurnOnAccessCheck();
+
+  /**
+   * Returns the identity hash for this object. The current implemenation uses
+   * a hidden property on the object to store the identity hash.
+   */
+  int GetIdentityHash();
+
+  /**
+   * Access hidden properties on JavaScript objects. These properties are
+   * hidden from the executing JavaScript and only accessible through the V8
+   * C++ API. Hidden properties introduced by V8 internally (for example the
+   * identity hash) are prefixed with "v8::".
+   */
+  bool SetHiddenValue(Handle<String> key, Handle<Value> value);
+  Local<Value> GetHiddenValue(Handle<String> key);
+  bool DeleteHiddenValue(Handle<String> key);
+
+  /**
+   * Clone this object with a fast but shallow copy.  Values will point
+   * to the same values as the original object.
+   */
+  Local<Object> Clone();
+
+  static Local<Object> New();
+  static Object* Cast(Value* obj);
+ private:
+  Object();
+};
+
+
+/**
+ * An instance of the built-in array constructor (ECMA-262, 15.4.2).
+ */
+class V8EXPORT Array : public Object {
+ public:
+  uint32_t Length() const;
+
+  static Local<Array> New(int length = 0);
+  static Array* Cast(Value* obj);
+ private:
+  Array();
+};
+
+
+/**
+ * A JavaScript function object (ECMA-262, 15.3).
+ */
+class V8EXPORT Function : public Object {
+ public:
+  Local<Object> NewInstance() const;
+  Local<Object> NewInstance(int argc, Handle<Value> argv[]) const;
+  Local<Value> Call(Handle<Object> recv, int argc, Handle<Value> argv[]);
+  void SetName(Handle<String> name);
+  Handle<Value> GetName() const;
+  static Function* Cast(Value* obj);
+ private:
+  Function();
+};
+
+
+/**
+ * A JavaScript value that wraps a C++ void*.  This type of value is
+ * mainly used to associate C++ data structures with JavaScript
+ * objects.
+ *
+ * The Wrap function V8 will return the most optimal Value object wrapping the
+ * C++ void*. The type of the value is not guaranteed to be an External object
+ * and no assumptions about its type should be made. To access the wrapped
+ * value Unwrap should be used, all other operations on that object will lead
+ * to unpredictable results.
+ */
+class V8EXPORT External : public Value {
+ public:
+  static Local<Value> Wrap(void* data);
+  static void* Unwrap(Handle<Value> obj);
+
+  static Local<External> New(void* value);
+  static External* Cast(Value* obj);
+  void* Value() const;
+ private:
+  External();
+};
+
+
+// --- T e m p l a t e s ---
+
+
+/**
+ * The superclass of object and function templates.
+ */
+class V8EXPORT Template : public Data {
+ public:
+  /** Adds a property to each instance created by this template.*/
+  void Set(Handle<String> name, Handle<Data> value,
+           PropertyAttribute attributes = None);
+  inline void Set(const char* name, Handle<Data> value);
+ private:
+  Template();
+
+  friend class ObjectTemplate;
+  friend class FunctionTemplate;
+};
+
+
+/**
+ * The argument information given to function call callbacks.  This
+ * class provides access to information about the context of the call,
+ * including the receiver, the number and values of arguments, and
+ * the holder of the function.
+ */
+class V8EXPORT Arguments {
+ public:
+  inline int Length() const;
+  inline Local<Value> operator[](int i) const;
+  inline Local<Function> Callee() const;
+  inline Local<Object> This() const;
+  inline Local<Object> Holder() const;
+  inline bool IsConstructCall() const;
+  inline Local<Value> Data() const;
+ private:
+  Arguments();
+  friend class ImplementationUtilities;
+  inline Arguments(Local<Value> data,
+                   Local<Object> holder,
+                   Local<Function> callee,
+                   bool is_construct_call,
+                   void** values, int length);
+  Local<Value> data_;
+  Local<Object> holder_;
+  Local<Function> callee_;
+  bool is_construct_call_;
+  void** values_;
+  int length_;
+};
+
+
+/**
+ * The information passed to an accessor callback about the context
+ * of the property access.
+ */
+class V8EXPORT AccessorInfo {
+ public:
+  inline AccessorInfo(Local<Object> self,
+                      Local<Value> data,
+                      Local<Object> holder)
+      : self_(self), data_(data), holder_(holder) { }
+  inline Local<Value> Data() const;
+  inline Local<Object> This() const;
+  inline Local<Object> Holder() const;
+ private:
+  Local<Object> self_;
+  Local<Value> data_;
+  Local<Object> holder_;
+};
+
+
+typedef Handle<Value> (*InvocationCallback)(const Arguments& args);
+
+typedef int (*LookupCallback)(Local<Object> self, Local<String> name);
+
+/**
+ * Accessor[Getter|Setter] are used as callback functions when
+ * setting|getting a particular property. See objectTemplate::SetAccessor.
+ */
+typedef Handle<Value> (*AccessorGetter)(Local<String> property,
+                                        const AccessorInfo& info);
+
+
+typedef void (*AccessorSetter)(Local<String> property,
+                               Local<Value> value,
+                               const AccessorInfo& info);
+
+
+/**
+ * NamedProperty[Getter|Setter] are used as interceptors on object.
+ * See ObjectTemplate::SetNamedPropertyHandler.
+ */
+typedef Handle<Value> (*NamedPropertyGetter)(Local<String> property,
+                                             const AccessorInfo& info);
+
+
+/**
+ * Returns the value if the setter intercepts the request.
+ * Otherwise, returns an empty handle.
+ */
+typedef Handle<Value> (*NamedPropertySetter)(Local<String> property,
+                                             Local<Value> value,
+                                             const AccessorInfo& info);
+
+
+/**
+ * Returns a non-empty handle if the interceptor intercepts the request.
+ * The result is true if the property exists and false otherwise.
+ */
+typedef Handle<Boolean> (*NamedPropertyQuery)(Local<String> property,
+                                              const AccessorInfo& info);
+
+
+/**
+ * Returns a non-empty handle if the deleter intercepts the request.
+ * The return value is true if the property could be deleted and false
+ * otherwise.
+ */
+typedef Handle<Boolean> (*NamedPropertyDeleter)(Local<String> property,
+                                                const AccessorInfo& info);
+
+/**
+ * Returns an array containing the names of the properties the named
+ * property getter intercepts.
+ */
+typedef Handle<Array> (*NamedPropertyEnumerator)(const AccessorInfo& info);
+
+
+/**
+ * Returns the value of the property if the getter intercepts the
+ * request.  Otherwise, returns an empty handle.
+ */
+typedef Handle<Value> (*IndexedPropertyGetter)(uint32_t index,
+                                               const AccessorInfo& info);
+
+
+/**
+ * Returns the value if the setter intercepts the request.
+ * Otherwise, returns an empty handle.
+ */
+typedef Handle<Value> (*IndexedPropertySetter)(uint32_t index,
+                                               Local<Value> value,
+                                               const AccessorInfo& info);
+
+
+/**
+ * Returns a non-empty handle if the interceptor intercepts the request.
+ * The result is true if the property exists and false otherwise.
+ */
+typedef Handle<Boolean> (*IndexedPropertyQuery)(uint32_t index,
+                                                const AccessorInfo& info);
+
+/**
+ * Returns a non-empty handle if the deleter intercepts the request.
+ * The return value is true if the property could be deleted and false
+ * otherwise.
+ */
+typedef Handle<Boolean> (*IndexedPropertyDeleter)(uint32_t index,
+                                                  const AccessorInfo& info);
+
+/**
+ * Returns an array containing the indices of the properties the
+ * indexed property getter intercepts.
+ */
+typedef Handle<Array> (*IndexedPropertyEnumerator)(const AccessorInfo& info);
+
+
+/**
+ * Access control specifications.
+ *
+ * Some accessors should be accessible across contexts.  These
+ * accessors have an explicit access control parameter which specifies
+ * the kind of cross-context access that should be allowed.
+ *
+ * Additionally, for security, accessors can prohibit overwriting by
+ * accessors defined in JavaScript.  For objects that have such
+ * accessors either locally or in their prototype chain it is not
+ * possible to overwrite the accessor by using __defineGetter__ or
+ * __defineSetter__ from JavaScript code.
+ */
+enum AccessControl {
+  DEFAULT               = 0,
+  ALL_CAN_READ          = 1,
+  ALL_CAN_WRITE         = 1 << 1,
+  PROHIBITS_OVERWRITING = 1 << 2
+};
+
+
+/**
+ * Access type specification.
+ */
+enum AccessType {
+  ACCESS_GET,
+  ACCESS_SET,
+  ACCESS_HAS,
+  ACCESS_DELETE,
+  ACCESS_KEYS
+};
+
+
+/**
+ * Returns true if cross-context access should be allowed to the named
+ * property with the given key on the global object.
+ */
+typedef bool (*NamedSecurityCallback)(Local<Object> global,
+                                      Local<Value> key,
+                                      AccessType type,
+                                      Local<Value> data);
+
+
+/**
+ * Returns true if cross-context access should be allowed to the indexed
+ * property with the given index on the global object.
+ */
+typedef bool (*IndexedSecurityCallback)(Local<Object> global,
+                                        uint32_t index,
+                                        AccessType type,
+                                        Local<Value> data);
+
+
+/**
+ * A FunctionTemplate is used to create functions at runtime. There
+ * can only be one function created from a FunctionTemplate in a
+ * context.
+ *
+ * A FunctionTemplate can have properties, these properties are added to the
+ * function object when it is created.
+ *
+ * A FunctionTemplate has a corresponding instance template which is
+ * used to create object instances when the function is used as a
+ * constructor. Properties added to the instance template are added to
+ * each object instance.
+ *
+ * A FunctionTemplate can have a prototype template. The prototype template
+ * is used to create the prototype object of the function.
+ *
+ * The following example shows how to use a FunctionTemplate:
+ *
+ * \code
+ *    v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
+ *    t->Set("func_property", v8::Number::New(1));
+ *
+ *    v8::Local<v8::Template> proto_t = t->PrototypeTemplate();
+ *    proto_t->Set("proto_method", v8::FunctionTemplate::New(InvokeCallback));
+ *    proto_t->Set("proto_const", v8::Number::New(2));
+ *
+ *    v8::Local<v8::ObjectTemplate> instance_t = t->InstanceTemplate();
+ *    instance_t->SetAccessor("instance_accessor", InstanceAccessorCallback);
+ *    instance_t->SetNamedPropertyHandler(PropertyHandlerCallback, ...);
+ *    instance_t->Set("instance_property", Number::New(3));
+ *
+ *    v8::Local<v8::Function> function = t->GetFunction();
+ *    v8::Local<v8::Object> instance = function->NewInstance();
+ * \endcode
+ *
+ * Let's use "function" as the JS variable name of the function object
+ * and "instance" for the instance object created above.  The function
+ * and the instance will have the following properties:
+ *
+ * \code
+ *   func_property in function == true;
+ *   function.func_property == 1;
+ *
+ *   function.prototype.proto_method() invokes 'InvokeCallback'
+ *   function.prototype.proto_const == 2;
+ *
+ *   instance instanceof function == true;
+ *   instance.instance_accessor calls 'InstanceAccessorCallback'
+ *   instance.instance_property == 3;
+ * \endcode
+ *
+ * A FunctionTemplate can inherit from another one by calling the
+ * FunctionTemplate::Inherit method.  The following graph illustrates
+ * the semantics of inheritance:
+ *
+ * \code
+ *   FunctionTemplate Parent  -> Parent() . prototype -> { }
+ *     ^                                                  ^
+ *     | Inherit(Parent)                                  | .__proto__
+ *     |                                                  |
+ *   FunctionTemplate Child   -> Child()  . prototype -> { }
+ * \endcode
+ *
+ * A FunctionTemplate 'Child' inherits from 'Parent', the prototype
+ * object of the Child() function has __proto__ pointing to the
+ * Parent() function's prototype object. An instance of the Child
+ * function has all properties on Parent's instance templates.
+ *
+ * Let Parent be the FunctionTemplate initialized in the previous
+ * section and create a Child FunctionTemplate by:
+ *
+ * \code
+ *   Local<FunctionTemplate> parent = t;
+ *   Local<FunctionTemplate> child = FunctionTemplate::New();
+ *   child->Inherit(parent);
+ *
+ *   Local<Function> child_function = child->GetFunction();
+ *   Local<Object> child_instance = child_function->NewInstance();
+ * \endcode
+ *
+ * The Child function and Child instance will have the following
+ * properties:
+ *
+ * \code
+ *   child_func.prototype.__proto__ == function.prototype;
+ *   child_instance.instance_accessor calls 'InstanceAccessorCallback'
+ *   child_instance.instance_property == 3;
+ * \endcode
+ */
+class V8EXPORT FunctionTemplate : public Template {
+ public:
+  /** Creates a function template.*/
+  static Local<FunctionTemplate> New(
+      InvocationCallback callback = 0,
+      Handle<Value> data = Handle<Value>(),
+      Handle<Signature> signature = Handle<Signature>());
+  /** Returns the unique function instance in the current execution context.*/
+  Local<Function> GetFunction();
+
+  /**
+   * Set the call-handler callback for a FunctionTemplate.  This
+   * callback is called whenever the function created from this
+   * FunctionTemplate is called.
+   */
+  void SetCallHandler(InvocationCallback callback,
+                      Handle<Value> data = Handle<Value>());
+
+  /** Get the InstanceTemplate. */
+  Local<ObjectTemplate> InstanceTemplate();
+
+  /** Causes the function template to inherit from a parent function template.*/
+  void Inherit(Handle<FunctionTemplate> parent);
+
+  /**
+   * A PrototypeTemplate is the template used to create the prototype object
+   * of the function created by this template.
+   */
+  Local<ObjectTemplate> PrototypeTemplate();
+
+
+  /**
+   * Set the class name of the FunctionTemplate.  This is used for
+   * printing objects created with the function created from the
+   * FunctionTemplate as its constructor.
+   */
+  void SetClassName(Handle<String> name);
+
+  /**
+   * Determines whether the __proto__ accessor ignores instances of
+   * the function template.  If instances of the function template are
+   * ignored, __proto__ skips all instances and instead returns the
+   * next object in the prototype chain.
+   *
+   * Call with a value of true to make the __proto__ accessor ignore
+   * instances of the function template.  Call with a value of false
+   * to make the __proto__ accessor not ignore instances of the
+   * function template.  By default, instances of a function template
+   * are not ignored.
+   */
+  void SetHiddenPrototype(bool value);
+
+  /**
+   * Returns true if the given object is an instance of this function
+   * template.
+   */
+  bool HasInstance(Handle<Value> object);
+
+ private:
+  FunctionTemplate();
+  void AddInstancePropertyAccessor(Handle<String> name,
+                                   AccessorGetter getter,
+                                   AccessorSetter setter,
+                                   Handle<Value> data,
+                                   AccessControl settings,
+                                   PropertyAttribute attributes);
+  void SetNamedInstancePropertyHandler(NamedPropertyGetter getter,
+                                       NamedPropertySetter setter,
+                                       NamedPropertyQuery query,
+                                       NamedPropertyDeleter remover,
+                                       NamedPropertyEnumerator enumerator,
+                                       Handle<Value> data);
+  void SetIndexedInstancePropertyHandler(IndexedPropertyGetter getter,
+                                         IndexedPropertySetter setter,
+                                         IndexedPropertyQuery query,
+                                         IndexedPropertyDeleter remover,
+                                         IndexedPropertyEnumerator enumerator,
+                                         Handle<Value> data);
+  void SetInstanceCallAsFunctionHandler(InvocationCallback callback,
+                                        Handle<Value> data);
+
+  friend class Context;
+  friend class ObjectTemplate;
+};
+
+
+/**
+ * An ObjectTemplate is used to create objects at runtime.
+ *
+ * Properties added to an ObjectTemplate are added to each object
+ * created from the ObjectTemplate.
+ */
+class V8EXPORT ObjectTemplate : public Template {
+ public:
+  /** Creates an ObjectTemplate. */
+  static Local<ObjectTemplate> New();
+
+  /** Creates a new instance of this template.*/
+  Local<Object> NewInstance();
+
+  /**
+   * Sets an accessor on the object template.
+   *
+   * Whenever the property with the given name is accessed on objects
+   * created from this ObjectTemplate the getter and setter callbacks
+   * are called instead of getting and setting the property directly
+   * on the JavaScript object.
+   *
+   * \param name The name of the property for which an accessor is added.
+   * \param getter The callback to invoke when getting the property.
+   * \param setter The callback to invoke when setting the property.
+   * \param data A piece of data that will be passed to the getter and setter
+   *   callbacks whenever they are invoked.
+   * \param settings Access control settings for the accessor. This is a bit
+   *   field consisting of one of more of
+   *   DEFAULT = 0, ALL_CAN_READ = 1, or ALL_CAN_WRITE = 2.
+   *   The default is to not allow cross-context access.
+   *   ALL_CAN_READ means that all cross-context reads are allowed.
+   *   ALL_CAN_WRITE means that all cross-context writes are allowed.
+   *   The combination ALL_CAN_READ | ALL_CAN_WRITE can be used to allow all
+   *   cross-context access.
+   * \param attribute The attributes of the property for which an accessor
+   *   is added.
+   */
+  void SetAccessor(Handle<String> name,
+                   AccessorGetter getter,
+                   AccessorSetter setter = 0,
+                   Handle<Value> data = Handle<Value>(),
+                   AccessControl settings = DEFAULT,
+                   PropertyAttribute attribute = None);
+
+  /**
+   * Sets a named property handler on the object template.
+   *
+   * Whenever a named property is accessed on objects created from
+   * this object template, the provided callback is invoked instead of
+   * accessing the property directly on the JavaScript object.
+   *
+   * \param getter The callback to invoke when getting a property.
+   * \param setter The callback to invoke when setting a property.
+   * \param query The callback to invoke to check is an object has a property.
+   * \param deleter The callback to invoke when deleting a property.
+   * \param enumerator The callback to invoke to enumerate all the named
+   *   properties of an object.
+   * \param data A piece of data that will be passed to the callbacks
+   *   whenever they are invoked.
+   */
+  void SetNamedPropertyHandler(NamedPropertyGetter getter,
+                               NamedPropertySetter setter = 0,
+                               NamedPropertyQuery query = 0,
+                               NamedPropertyDeleter deleter = 0,
+                               NamedPropertyEnumerator enumerator = 0,
+                               Handle<Value> data = Handle<Value>());
+
+  /**
+   * Sets an indexed property handler on the object template.
+   *
+   * Whenever an indexed property is accessed on objects created from
+   * this object template, the provided callback is invoked instead of
+   * accessing the property directly on the JavaScript object.
+   *
+   * \param getter The callback to invoke when getting a property.
+   * \param setter The callback to invoke when setting a property.
+   * \param query The callback to invoke to check is an object has a property.
+   * \param deleter The callback to invoke when deleting a property.
+   * \param enumerator The callback to invoke to enumerate all the indexed
+   *   properties of an object.
+   * \param data A piece of data that will be passed to the callbacks
+   *   whenever they are invoked.
+   */
+  void SetIndexedPropertyHandler(IndexedPropertyGetter getter,
+                                 IndexedPropertySetter setter = 0,
+                                 IndexedPropertyQuery query = 0,
+                                 IndexedPropertyDeleter deleter = 0,
+                                 IndexedPropertyEnumerator enumerator = 0,
+                                 Handle<Value> data = Handle<Value>());
+  /**
+   * Sets the callback to be used when calling instances created from
+   * this template as a function.  If no callback is set, instances
+   * behave like normal JavaScript objects that cannot be called as a
+   * function.
+   */
+  void SetCallAsFunctionHandler(InvocationCallback callback,
+                                Handle<Value> data = Handle<Value>());
+
+  /**
+   * Mark object instances of the template as undetectable.
+   *
+   * In many ways, undetectable objects behave as though they are not
+   * there.  They behave like 'undefined' in conditionals and when
+   * printed.  However, properties can be accessed and called as on
+   * normal objects.
+   */
+  void MarkAsUndetectable();
+
+  /**
+   * Sets access check callbacks on the object template.
+   *
+   * When accessing properties on instances of this object template,
+   * the access check callback will be called to determine whether or
+   * not to allow cross-context access to the properties.
+   * The last parameter specifies whether access checks are turned
+   * on by default on instances. If access checks are off by default,
+   * they can be turned on on individual instances by calling
+   * Object::TurnOnAccessCheck().
+   */
+  void SetAccessCheckCallbacks(NamedSecurityCallback named_handler,
+                               IndexedSecurityCallback indexed_handler,
+                               Handle<Value> data = Handle<Value>(),
+                               bool turned_on_by_default = true);
+
+  /**
+   * Gets the number of internal fields for objects generated from
+   * this template.
+   */
+  int InternalFieldCount();
+
+  /**
+   * Sets the number of internal fields for objects generated from
+   * this template.
+   */
+  void SetInternalFieldCount(int value);
+
+ private:
+  ObjectTemplate();
+  static Local<ObjectTemplate> New(Handle<FunctionTemplate> constructor);
+  friend class FunctionTemplate;
+};
+
+
+/**
+ * A Signature specifies which receivers and arguments a function can
+ * legally be called with.
+ */
+class V8EXPORT Signature : public Data {
+ public:
+  static Local<Signature> New(Handle<FunctionTemplate> receiver =
+                                  Handle<FunctionTemplate>(),
+                              int argc = 0,
+                              Handle<FunctionTemplate> argv[] = 0);
+ private:
+  Signature();
+};
+
+
+/**
+ * A utility for determining the type of objects based on the template
+ * they were constructed from.
+ */
+class V8EXPORT TypeSwitch : public Data {
+ public:
+  static Local<TypeSwitch> New(Handle<FunctionTemplate> type);
+  static Local<TypeSwitch> New(int argc, Handle<FunctionTemplate> types[]);
+  int match(Handle<Value> value);
+ private:
+  TypeSwitch();
+};
+
+
+// --- E x t e n s i o n s ---
+
+
+/**
+ * Ignore
+ */
+class V8EXPORT Extension {  // NOLINT
+ public:
+  Extension(const char* name,
+            const char* source = 0,
+            int dep_count = 0,
+            const char** deps = 0);
+  virtual ~Extension() { }
+  virtual v8::Handle<v8::FunctionTemplate>
+      GetNativeFunction(v8::Handle<v8::String> name) {
+    return v8::Handle<v8::FunctionTemplate>();
+  }
+
+  const char* name() { return name_; }
+  const char* source() { return source_; }
+  int dependency_count() { return dep_count_; }
+  const char** dependencies() { return deps_; }
+  void set_auto_enable(bool value) { auto_enable_ = value; }
+  bool auto_enable() { return auto_enable_; }
+
+ private:
+  const char* name_;
+  const char* source_;
+  int dep_count_;
+  const char** deps_;
+  bool auto_enable_;
+
+  // Disallow copying and assigning.
+  Extension(const Extension&);
+  void operator=(const Extension&);
+};
+
+
+void V8EXPORT RegisterExtension(Extension* extension);
+
+
+/**
+ * Ignore
+ */
+class V8EXPORT DeclareExtension {
+ public:
+  inline DeclareExtension(Extension* extension) {
+    RegisterExtension(extension);
+  }
+};
+
+
+// --- S t a t i c s ---
+
+
+Handle<Primitive> V8EXPORT Undefined();
+Handle<Primitive> V8EXPORT Null();
+Handle<Boolean> V8EXPORT True();
+Handle<Boolean> V8EXPORT False();
+
+
+/**
+ * A set of constraints that specifies the limits of the runtime's
+ * memory use.
+ */
+class V8EXPORT ResourceConstraints {
+ public:
+  ResourceConstraints();
+  int max_young_space_size() const { return max_young_space_size_; }
+  void set_max_young_space_size(int value) { max_young_space_size_ = value; }
+  int max_old_space_size() const { return max_old_space_size_; }
+  void set_max_old_space_size(int value) { max_old_space_size_ = value; }
+  uint32_t* stack_limit() const { return stack_limit_; }
+  void set_stack_limit(uint32_t* value) { stack_limit_ = value; }
+ private:
+  int max_young_space_size_;
+  int max_old_space_size_;
+  uint32_t* stack_limit_;
+};
+
+
+bool SetResourceConstraints(ResourceConstraints* constraints);
+
+
+// --- E x c e p t i o n s ---
+
+
+typedef void (*FatalErrorCallback)(const char* location, const char* message);
+
+
+typedef void (*MessageCallback)(Handle<Message> message, Handle<Value> data);
+
+
+/**
+ * Schedules an exception to be thrown when returning to JavaScript.  When an
+ * exception has been scheduled it is illegal to invoke any JavaScript
+ * operation; the caller must return immediately and only after the exception
+ * has been handled does it become legal to invoke JavaScript operations.
+ */
+Handle<Value> V8EXPORT ThrowException(Handle<Value> exception);
+
+/**
+ * Create new error objects by calling the corresponding error object
+ * constructor with the message.
+ */
+class V8EXPORT Exception {
+ public:
+  static Local<Value> RangeError(Handle<String> message);
+  static Local<Value> ReferenceError(Handle<String> message);
+  static Local<Value> SyntaxError(Handle<String> message);
+  static Local<Value> TypeError(Handle<String> message);
+  static Local<Value> Error(Handle<String> message);
+};
+
+
+// --- C o u n t e r s  C a l l b a c k s ---
+
+typedef int* (*CounterLookupCallback)(const char* name);
+
+typedef void* (*CreateHistogramCallback)(const char* name,
+                                         int min,
+                                         int max,
+                                         size_t buckets);
+
+typedef void (*AddHistogramSampleCallback)(void* histogram, int sample);
+
+// --- F a i l e d A c c e s s C h e c k C a l l b a c k ---
+typedef void (*FailedAccessCheckCallback)(Local<Object> target,
+                                          AccessType type,
+                                          Local<Value> data);
+
+// --- G a r b a g e C o l l e c t i o n  C a l l b a c k s
+
+/**
+ * Applications can register a callback function which is called
+ * before and after a major garbage collection.  Allocations are not
+ * allowed in the callback function, you therefore cannot manipulate
+ * objects (set or delete properties for example) since it is possible
+ * such operations will result in the allocation of objects.
+ */
+typedef void (*GCCallback)();
+
+
+// --- C o n t e x t  G e n e r a t o r ---
+
+/**
+ * Applications must provide a callback function which is called to generate
+ * a context if a context was not deserialized from the snapshot.
+ */
+typedef Persistent<Context> (*ContextGenerator)();
+
+
+/**
+ * Container class for static utility functions.
+ */
+class V8EXPORT V8 {
+ public:
+  /** Set the callback to invoke in case of fatal errors. */
+  static void SetFatalErrorHandler(FatalErrorCallback that);
+
+  /**
+   * Ignore out-of-memory exceptions.
+   *
+   * V8 running out of memory is treated as a fatal error by default.
+   * This means that the fatal error handler is called and that V8 is
+   * terminated.
+   *
+   * IgnoreOutOfMemoryException can be used to not treat a
+   * out-of-memory situation as a fatal error.  This way, the contexts
+   * that did not cause the out of memory problem might be able to
+   * continue execution.
+   */
+  static void IgnoreOutOfMemoryException();
+
+  /**
+   * Check if V8 is dead and therefore unusable.  This is the case after
+   * fatal errors such as out-of-memory situations.
+   */
+  static bool IsDead();
+
+  /**
+   * Adds a message listener.
+   *
+   * The same message listener can be added more than once and it that
+   * case it will be called more than once for each message.
+   */
+  static bool AddMessageListener(MessageCallback that,
+                                 Handle<Value> data = Handle<Value>());
+
+  /**
+   * Remove all message listeners from the specified callback function.
+   */
+  static void RemoveMessageListeners(MessageCallback that);
+
+  /**
+   * Sets V8 flags from a string.
+   */
+  static void SetFlagsFromString(const char* str, int length);
+
+  /**
+   * Sets V8 flags from the command line.
+   */
+  static void SetFlagsFromCommandLine(int* argc,
+                                      char** argv,
+                                      bool remove_flags);
+
+  /** Get the version string. */
+  static const char* GetVersion();
+
+  /**
+   * Enables the host application to provide a mechanism for recording
+   * statistics counters.
+   */
+  static void SetCounterFunction(CounterLookupCallback);
+
+  /**
+   * Enables the host application to provide a mechanism for recording
+   * histograms. The CreateHistogram function returns a
+   * histogram which will later be passed to the AddHistogramSample
+   * function.
+   */
+  static void SetCreateHistogramFunction(CreateHistogramCallback);
+  static void SetAddHistogramSampleFunction(AddHistogramSampleCallback);
+
+  /**
+   * Enables the computation of a sliding window of states. The sliding
+   * window information is recorded in statistics counters.
+   */
+  static void EnableSlidingStateWindow();
+
+  /** Callback function for reporting failed access checks.*/
+  static void SetFailedAccessCheckCallbackFunction(FailedAccessCheckCallback);
+
+  /**
+   * Enables the host application to receive a notification before a
+   * major garbage colletion.  Allocations are not allowed in the
+   * callback function, you therefore cannot manipulate objects (set
+   * or delete properties for example) since it is possible such
+   * operations will result in the allocation of objects.
+   */
+  static void SetGlobalGCPrologueCallback(GCCallback);
+
+  /**
+   * Enables the host application to receive a notification after a
+   * major garbage collection.  Allocations are not allowed in the
+   * callback function, you therefore cannot manipulate objects (set
+   * or delete properties for example) since it is possible such
+   * operations will result in the allocation of objects.
+   */
+  static void SetGlobalGCEpilogueCallback(GCCallback);
+
+  /**
+   * Allows the host application to group objects together. If one
+   * object in the group is alive, all objects in the group are alive.
+   * After each garbage collection, object groups are removed. It is
+   * intended to be used in the before-garbage-collection callback
+   * function, for instance to simulate DOM tree connections among JS
+   * wrapper objects.
+   */
+  static void AddObjectGroup(Persistent<Value>* objects, size_t length);
+
+  /**
+   * Initializes from snapshot if possible. Otherwise, attempts to
+   * initialize from scratch.
+   */
+  static bool Initialize();
+
+  /**
+   * Adjusts the amount of registered external memory.  Used to give
+   * V8 an indication of the amount of externally allocated memory
+   * that is kept alive by JavaScript objects.  V8 uses this to decide
+   * when to perform global garbage collections.  Registering
+   * externally allocated memory will trigger global garbage
+   * collections more often than otherwise in an attempt to garbage
+   * collect the JavaScript objects keeping the externally allocated
+   * memory alive.
+   *
+   * \param change_in_bytes the change in externally allocated memory
+   *   that is kept alive by JavaScript objects.
+   * \returns the adjusted value.
+   */
+  static int AdjustAmountOfExternalAllocatedMemory(int change_in_bytes);
+
+  /**
+   * Suspends recording of tick samples in the profiler.
+   * When the V8 profiling mode is enabled (usually via command line
+   * switches) this function suspends recording of tick samples.
+   * Profiling ticks are discarded until ResumeProfiler() is called.
+   *
+   * See also the --prof and --prof_auto command line switches to
+   * enable V8 profiling.
+   */
+  static void PauseProfiler();
+
+  /**
+   * Resumes recording of tick samples in the profiler.
+   * See also PauseProfiler().
+   */
+  static void ResumeProfiler();
+
+  /**
+   * Releases any resources used by v8 and stops any utility threads
+   * that may be running.  Note that disposing v8 is permanent, it
+   * cannot be reinitialized.
+   *
+   * It should generally not be necessary to dispose v8 before exiting
+   * a process, this should happen automatically.  It is only necessary
+   * to use if the process needs the resources taken up by v8.
+   */
+  static bool Dispose();
+
+ private:
+  V8();
+
+  static void** GlobalizeReference(void** handle);
+  static void DisposeGlobal(void** global_handle);
+  static void MakeWeak(void** global_handle, void* data, WeakReferenceCallback);
+  static void ClearWeak(void** global_handle);
+  static bool IsGlobalNearDeath(void** global_handle);
+  static bool IsGlobalWeak(void** global_handle);
+
+  template <class T> friend class Handle;
+  template <class T> friend class Local;
+  template <class T> friend class Persistent;
+  friend class Context;
+};
+
+
+/**
+ * An external exception handler.
+ */
+class V8EXPORT TryCatch {
+ public:
+
+  /**
+   * Creates a new try/catch block and registers it with v8.
+   */
+  TryCatch();
+
+  /**
+   * Unregisters and deletes this try/catch block.
+   */
+  ~TryCatch();
+
+  /**
+   * Returns true if an exception has been caught by this try/catch block.
+   */
+  bool HasCaught() const;
+
+  /**
+   * Returns the exception caught by this try/catch block.  If no exception has
+   * been caught an empty handle is returned.
+   *
+   * The returned handle is valid until this TryCatch block has been destroyed.
+   */
+  Local<Value> Exception() const;
+
+  /**
+   * Returns the message associated with this exception.  If there is
+   * no message associated an empty handle is returned.
+   *
+   * The returned handle is valid until this TryCatch block has been
+   * destroyed.
+   */
+  Local<v8::Message> Message() const;
+
+  /**
+   * Clears any exceptions that may have been caught by this try/catch block.
+   * After this method has been called, HasCaught() will return false.
+   *
+   * It is not necessary to clear a try/catch block before using it again; if
+   * another exception is thrown the previously caught exception will just be
+   * overwritten.  However, it is often a good idea since it makes it easier
+   * to determine which operation threw a given exception.
+   */
+  void Reset();
+
+  /**
+   * Set verbosity of the external exception handler.
+   *
+   * By default, exceptions that are caught by an external exception
+   * handler are not reported.  Call SetVerbose with true on an
+   * external exception handler to have exceptions caught by the
+   * handler reported as if they were not caught.
+   */
+  void SetVerbose(bool value);
+
+  /**
+   * Set whether or not this TryCatch should capture a Message object
+   * which holds source information about where the exception
+   * occurred.  True by default.
+   */
+  void SetCaptureMessage(bool value);
+
+ public:
+  TryCatch* next_;
+  void* exception_;
+  void* message_;
+  bool is_verbose_;
+  bool capture_message_;
+  void* js_handler_;
+};
+
+
+// --- C o n t e x t ---
+
+
+/**
+ * Ignore
+ */
+class V8EXPORT ExtensionConfiguration {
+ public:
+  ExtensionConfiguration(int name_count, const char* names[])
+      : name_count_(name_count), names_(names) { }
+ private:
+  friend class ImplementationUtilities;
+  int name_count_;
+  const char** names_;
+};
+
+
+/**
+ * A sandboxed execution context with its own set of built-in objects
+ * and functions.
+ */
+class V8EXPORT Context {
+ public:
+  /** Returns the global object of the context. */
+  Local<Object> Global();
+
+  /**
+   * Detaches the global object from its context before
+   * the global object can be reused to create a new context.
+   */
+  void DetachGlobal();
+
+  /** Creates a new context. */
+  static Persistent<Context> New(
+      ExtensionConfiguration* extensions = 0,
+      Handle<ObjectTemplate> global_template = Handle<ObjectTemplate>(),
+      Handle<Value> global_object = Handle<Value>());
+
+  /** Returns the last entered context. */
+  static Local<Context> GetEntered();
+
+  /** Returns the context that is on the top of the stack. */
+  static Local<Context> GetCurrent();
+
+  /**
+   * Sets the security token for the context.  To access an object in
+   * another context, the security tokens must match.
+   */
+  void SetSecurityToken(Handle<Value> token);
+
+  /** Restores the security token to the default value. */
+  void UseDefaultSecurityToken();
+
+  /** Returns the security token of this context.*/
+  Handle<Value> GetSecurityToken();
+
+  /**
+   * Enter this context.  After entering a context, all code compiled
+   * and run is compiled and run in this context.  If another context
+   * is already entered, this old context is saved so it can be
+   * restored when the new context is exited.
+   */
+  void Enter();
+
+  /**
+   * Exit this context.  Exiting the current context restores the
+   * context that was in place when entering the current context.
+   */
+  void Exit();
+
+  /** Returns true if the context has experienced an out of memory situation. */
+  bool HasOutOfMemoryException();
+
+  /** Returns true if V8 has a current context. */
+  static bool InContext();
+
+  /**
+   * Stack-allocated class which sets the execution context for all
+   * operations executed within a local scope.
+   */
+  class V8EXPORT Scope {
+   public:
+    inline Scope(Handle<Context> context) : context_(context) {
+      context_->Enter();
+    }
+    inline ~Scope() { context_->Exit(); }
+   private:
+    Handle<Context> context_;
+  };
+
+ private:
+  friend class Value;
+  friend class Script;
+  friend class Object;
+  friend class Function;
+};
+
+
+/**
+ * Multiple threads in V8 are allowed, but only one thread at a time
+ * is allowed to use V8.  The definition of 'using V8' includes
+ * accessing handles or holding onto object pointers obtained from V8
+ * handles.  It is up to the user of V8 to ensure (perhaps with
+ * locking) that this constraint is not violated.
+ *
+ * If you wish to start using V8 in a thread you can do this by constructing
+ * a v8::Locker object.  After the code using V8 has completed for the
+ * current thread you can call the destructor.  This can be combined
+ * with C++ scope-based construction as follows:
+ *
+ * \code
+ * ...
+ * {
+ *   v8::Locker locker;
+ *   ...
+ *   // Code using V8 goes here.
+ *   ...
+ * } // Destructor called here
+ * \endcode
+ *
+ * If you wish to stop using V8 in a thread A you can do this by either
+ * by destroying the v8::Locker object as above or by constructing a
+ * v8::Unlocker object:
+ *
+ * \code
+ * {
+ *   v8::Unlocker unlocker;
+ *   ...
+ *   // Code not using V8 goes here while V8 can run in another thread.
+ *   ...
+ * } // Destructor called here.
+ * \endcode
+ *
+ * The Unlocker object is intended for use in a long-running callback
+ * from V8, where you want to release the V8 lock for other threads to
+ * use.
+ *
+ * The v8::Locker is a recursive lock.  That is, you can lock more than
+ * once in a given thread.  This can be useful if you have code that can
+ * be called either from code that holds the lock or from code that does
+ * not.  The Unlocker is not recursive so you can not have several
+ * Unlockers on the stack at once, and you can not use an Unlocker in a
+ * thread that is not inside a Locker's scope.
+ *
+ * An unlocker will unlock several lockers if it has to and reinstate
+ * the correct depth of locking on its destruction. eg.:
+ *
+ * \code
+ * // V8 not locked.
+ * {
+ *   v8::Locker locker;
+ *   // V8 locked.
+ *   {
+ *     v8::Locker another_locker;
+ *     // V8 still locked (2 levels).
+ *     {
+ *       v8::Unlocker unlocker;
+ *       // V8 not locked.
+ *     }
+ *     // V8 locked again (2 levels).
+ *   }
+ *   // V8 still locked (1 level).
+ * }
+ * // V8 Now no longer locked.
+ * \endcode
+ */
+class V8EXPORT Unlocker {
+ public:
+  Unlocker();
+  ~Unlocker();
+};
+
+
+class V8EXPORT Locker {
+ public:
+  Locker();
+  ~Locker();
+
+  /**
+   * Start preemption.
+   *
+   * When preemption is started, a timer is fired every n milli seconds
+   * that will switch between multiple threads that are in contention
+   * for the V8 lock.
+   */
+  static void StartPreemption(int every_n_ms);
+
+  /**
+   * Stop preemption.
+   */
+  static void StopPreemption();
+
+  /**
+   * Returns whether or not the locker is locked by the current thread.
+   */
+  static bool IsLocked();
+
+  /**
+   * Returns whether v8::Locker is being used by this V8 instance.
+   */
+  static bool IsActive() { return active_; }
+
+ private:
+  bool has_lock_;
+  bool top_level_;
+
+  static bool active_;
+
+  // Disallow copying and assigning.
+  Locker(const Locker&);
+  void operator=(const Locker&);
+};
+
+
+
+// --- I m p l e m e n t a t i o n ---
+
+template <class T>
+Handle<T>::Handle() : val_(0) { }
+
+
+template <class T>
+Local<T>::Local() : Handle<T>() { }
+
+
+template <class T>
+Local<T> Local<T>::New(Handle<T> that) {
+  if (that.IsEmpty()) return Local<T>();
+  void** p = reinterpret_cast<void**>(*that);
+  return Local<T>(reinterpret_cast<T*>(HandleScope::CreateHandle(*p)));
+}
+
+
+template <class T>
+Persistent<T> Persistent<T>::New(Handle<T> that) {
+  if (that.IsEmpty()) return Persistent<T>();
+  void** p = reinterpret_cast<void**>(*that);
+  return Persistent<T>(reinterpret_cast<T*>(V8::GlobalizeReference(p)));
+}
+
+
+template <class T>
+bool Persistent<T>::IsNearDeath() const {
+  if (this->IsEmpty()) return false;
+  return V8::IsGlobalNearDeath(reinterpret_cast<void**>(**this));
+}
+
+
+template <class T>
+bool Persistent<T>::IsWeak() const {
+  if (this->IsEmpty()) return false;
+  return V8::IsGlobalWeak(reinterpret_cast<void**>(**this));
+}
+
+
+template <class T>
+void Persistent<T>::Dispose() {
+  if (this->IsEmpty()) return;
+  V8::DisposeGlobal(reinterpret_cast<void**>(**this));
+}
+
+
+template <class T>
+Persistent<T>::Persistent() : Handle<T>() { }
+
+template <class T>
+void Persistent<T>::MakeWeak(void* parameters, WeakReferenceCallback callback) {
+  V8::MakeWeak(reinterpret_cast<void**>(**this), parameters, callback);
+}
+
+template <class T>
+void Persistent<T>::ClearWeak() {
+  V8::ClearWeak(reinterpret_cast<void**>(**this));
+}
+
+template <class T>
+T* Handle<T>::operator->() const {
+  return val_;
+}
+
+
+template <class T>
+T* Handle<T>::operator*() const {
+  return val_;
+}
+
+
+Local<Value> Arguments::operator[](int i) const {
+  if (i < 0 || length_ <= i) return Local<Value>(*Undefined());
+  return Local<Value>(reinterpret_cast<Value*>(values_ - i));
+}
+
+
+Local<Function> Arguments::Callee() const {
+  return callee_;
+}
+
+
+Local<Object> Arguments::This() const {
+  return Local<Object>(reinterpret_cast<Object*>(values_ + 1));
+}
+
+
+Local<Object> Arguments::Holder() const {
+  return holder_;
+}
+
+
+Local<Value> Arguments::Data() const {
+  return data_;
+}
+
+
+bool Arguments::IsConstructCall() const {
+  return is_construct_call_;
+}
+
+
+int Arguments::Length() const {
+  return length_;
+}
+
+
+Local<Value> AccessorInfo::Data() const {
+  return data_;
+}
+
+
+Local<Object> AccessorInfo::This() const {
+  return self_;
+}
+
+
+Local<Object> AccessorInfo::Holder() const {
+  return holder_;
+}
+
+
+template <class T>
+Local<T> HandleScope::Close(Handle<T> value) {
+  void** after = RawClose(reinterpret_cast<void**>(*value));
+  return Local<T>(reinterpret_cast<T*>(after));
+}
+
+Handle<Value> ScriptOrigin::ResourceName() const {
+  return resource_name_;
+}
+
+
+Handle<Integer> ScriptOrigin::ResourceLineOffset() const {
+  return resource_line_offset_;
+}
+
+
+Handle<Integer> ScriptOrigin::ResourceColumnOffset() const {
+  return resource_column_offset_;
+}
+
+
+Handle<Boolean> Boolean::New(bool value) {
+  return value ? True() : False();
+}
+
+
+void Template::Set(const char* name, v8::Handle<Data> value) {
+  Set(v8::String::New(name), value);
+}
+
+
+/**
+ * \example shell.cc
+ * A simple shell that takes a list of expressions on the
+ * command-line and executes them.
+ */
+
+
+/**
+ * \example process.cc
+ */
+
+
+}  // namespace v8
+
+
+#undef V8EXPORT
+#undef V8EXPORT_INLINE
+#undef TYPE_CHECK
+
+
+#endif  // V8_H_
diff --git a/deps/v8/samples/SConscript b/deps/v8/samples/SConscript
new file mode 100644
index 0000000..31990b6
--- /dev/null
+++ b/deps/v8/samples/SConscript
@@ -0,0 +1,38 @@
+# Copyright 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.
+
+from os.path import join
+Import('sample context')
+
+def ConfigureObjectFiles():
+  env = Environment()
+  env.Replace(**context.flags['sample'])
+  context.ApplyEnvOverrides(env)
+  return env.Object(sample + '.cc')
+
+sample_object = ConfigureObjectFiles()
+Return('sample_object')
diff --git a/deps/v8/samples/count-hosts.js b/deps/v8/samples/count-hosts.js
new file mode 100644
index 0000000..bea6553
--- /dev/null
+++ b/deps/v8/samples/count-hosts.js
@@ -0,0 +1,42 @@
+// Copyright 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.
+
+function Initialize() { }
+
+function Process(request) {
+  if (options.verbose) {
+    log("Processing " + request.host + request.path +
+        " from " + request.referrer + "@" + request.userAgent);
+  }
+  if (!output[request.host]) {
+    output[request.host] = 1;
+  } else {
+    output[request.host]++
+  }
+}
+
+Initialize();
diff --git a/deps/v8/samples/process.cc b/deps/v8/samples/process.cc
new file mode 100644
index 0000000..511e21a
--- /dev/null
+++ b/deps/v8/samples/process.cc
@@ -0,0 +1,622 @@
+// Copyright 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.
+
+#include <v8.h>
+
+#include <string>
+#include <map>
+
+using namespace std;
+using namespace v8;
+
+// These interfaces represent an existing request processing interface.
+// The idea is to imagine a real application that uses these interfaces
+// and then add scripting capabilities that allow you to interact with
+// the objects through JavaScript.
+
+/**
+ * A simplified http request.
+ */
+class HttpRequest {
+ public:
+  virtual ~HttpRequest() { }
+  virtual const string& Path() = 0;
+  virtual const string& Referrer() = 0;
+  virtual const string& Host() = 0;
+  virtual const string& UserAgent() = 0;
+};
+
+/**
+ * The abstract superclass of http request processors.
+ */
+class HttpRequestProcessor {
+ public:
+  virtual ~HttpRequestProcessor() { }
+
+  // Initialize this processor.  The map contains options that control
+  // how requests should be processed.
+  virtual bool Initialize(map<string, string>* options,
+                          map<string, string>* output) = 0;
+
+  // Process a single request.
+  virtual bool Process(HttpRequest* req) = 0;
+
+  static void Log(const char* event);
+};
+
+/**
+ * An http request processor that is scriptable using JavaScript.
+ */
+class JsHttpRequestProcessor : public HttpRequestProcessor {
+ public:
+
+  // Creates a new processor that processes requests by invoking the
+  // Process function of the JavaScript script given as an argument.
+  explicit JsHttpRequestProcessor(Handle<String> script) : script_(script) { }
+  virtual ~JsHttpRequestProcessor();
+
+  virtual bool Initialize(map<string, string>* opts,
+                          map<string, string>* output);
+  virtual bool Process(HttpRequest* req);
+
+ private:
+
+  // Execute the script associated with this processor and extract the
+  // Process function.  Returns true if this succeeded, otherwise false.
+  bool ExecuteScript(Handle<String> script);
+
+  // Wrap the options and output map in a JavaScript objects and
+  // install it in the global namespace as 'options' and 'output'.
+  bool InstallMaps(map<string, string>* opts, map<string, string>* output);
+
+  // Constructs the template that describes the JavaScript wrapper
+  // type for requests.
+  static Handle<ObjectTemplate> MakeRequestTemplate();
+  static Handle<ObjectTemplate> MakeMapTemplate();
+
+  // Callbacks that access the individual fields of request objects.
+  static Handle<Value> GetPath(Local<String> name, const AccessorInfo& info);
+  static Handle<Value> GetReferrer(Local<String> name,
+                                   const AccessorInfo& info);
+  static Handle<Value> GetHost(Local<String> name, const AccessorInfo& info);
+  static Handle<Value> GetUserAgent(Local<String> name,
+                                    const AccessorInfo& info);
+
+  // Callbacks that access maps
+  static Handle<Value> MapGet(Local<String> name, const AccessorInfo& info);
+  static Handle<Value> MapSet(Local<String> name,
+                              Local<Value> value,
+                              const AccessorInfo& info);
+
+  // Utility methods for wrapping C++ objects as JavaScript objects,
+  // and going back again.
+  static Handle<Object> WrapMap(map<string, string>* obj);
+  static map<string, string>* UnwrapMap(Handle<Object> obj);
+  static Handle<Object> WrapRequest(HttpRequest* obj);
+  static HttpRequest* UnwrapRequest(Handle<Object> obj);
+
+  Handle<String> script_;
+  Persistent<Context> context_;
+  Persistent<Function> process_;
+  static Persistent<ObjectTemplate> request_template_;
+  static Persistent<ObjectTemplate> map_template_;
+};
+
+// -------------------------
+// --- P r o c e s s o r ---
+// -------------------------
+
+
+static Handle<Value> LogCallback(const Arguments& args) {
+  if (args.Length() < 1) return v8::Undefined();
+  HandleScope scope;
+  Handle<Value> arg = args[0];
+  String::Utf8Value value(arg);
+  HttpRequestProcessor::Log(*value);
+  return v8::Undefined();
+}
+
+
+// Execute the script and fetch the Process method.
+bool JsHttpRequestProcessor::Initialize(map<string, string>* opts,
+                                        map<string, string>* output) {
+  // Create a handle scope to hold the temporary references.
+  HandleScope handle_scope;
+
+  // Create a template for the global object where we set the
+  // built-in global functions.
+  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);
+
+  // Enter the new context so all the following operations take place
+  // within it.
+  Context::Scope context_scope(context);
+
+  // Make the options mapping available within the context
+  if (!InstallMaps(opts, output))
+    return false;
+
+  // Compile and run the script
+  if (!ExecuteScript(script_))
+    return false;
+
+  // 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);
+
+  // If there is no Process function, or if it is not a function,
+  // bail out
+  if (!process_val->IsFunction()) return false;
+
+  // It is a function; cast it to a Function
+  Handle<Function> process_fun = Handle<Function>::Cast(process_val);
+
+  // Store the function in a Persistent handle, since we also want
+  // that to remain after this call returns
+  process_ = Persistent<Function>::New(process_fun);
+
+  // All done; all went well
+  return true;
+}
+
+
+bool JsHttpRequestProcessor::ExecuteScript(Handle<String> script) {
+  HandleScope handle_scope;
+
+  // We're just about to compile the script; set up an error handler to
+  // catch any exceptions the script might throw.
+  TryCatch try_catch;
+
+  // Compile the script and check for errors.
+  Handle<Script> compiled_script = Script::Compile(script);
+  if (compiled_script.IsEmpty()) {
+    String::Utf8Value error(try_catch.Exception());
+    Log(*error);
+    // The script failed to compile; bail out.
+    return false;
+  }
+
+  // Run the script!
+  Handle<Value> result = compiled_script->Run();
+  if (result.IsEmpty()) {
+    // The TryCatch above is still in effect and will have caught the error.
+    String::Utf8Value error(try_catch.Exception());
+    Log(*error);
+    // Running the script failed; bail out.
+    return false;
+  }
+  return true;
+}
+
+
+bool JsHttpRequestProcessor::InstallMaps(map<string, string>* opts,
+                                         map<string, string>* output) {
+  HandleScope handle_scope;
+
+  // Wrap the map object in a JavaScript wrapper
+  Handle<Object> opts_obj = WrapMap(opts);
+
+  // Set the options object as a property on the global object.
+  context_->Global()->Set(String::New("options"), opts_obj);
+
+  Handle<Object> output_obj = WrapMap(output);
+  context_->Global()->Set(String::New("output"), output_obj);
+
+  return true;
+}
+
+
+bool JsHttpRequestProcessor::Process(HttpRequest* request) {
+  // Create a handle scope to keep the temporary object references.
+  HandleScope handle_scope;
+
+  // Enter this processor's context so all the remaining operations
+  // take place there
+  Context::Scope context_scope(context_);
+
+  // Wrap the C++ request object in a JavaScript wrapper
+  Handle<Object> request_obj = WrapRequest(request);
+
+  // Set up an exception handler before calling the Process function
+  TryCatch try_catch;
+
+  // Invoke the process function, giving the global object as 'this'
+  // and one argument, the request.
+  const int argc = 1;
+  Handle<Value> argv[argc] = { request_obj };
+  Handle<Value> result = process_->Call(context_->Global(), argc, argv);
+  if (result.IsEmpty()) {
+    String::Utf8Value error(try_catch.Exception());
+    Log(*error);
+    return false;
+  } else {
+    return true;
+  }
+}
+
+
+JsHttpRequestProcessor::~JsHttpRequestProcessor() {
+  // Dispose the persistent handles.  When noone else has any
+  // references to the objects stored in the handles they will be
+  // automatically reclaimed.
+  context_.Dispose();
+  process_.Dispose();
+}
+
+
+Persistent<ObjectTemplate> JsHttpRequestProcessor::request_template_;
+Persistent<ObjectTemplate> JsHttpRequestProcessor::map_template_;
+
+
+// -----------------------------------
+// --- A c c e s s i n g   M a p s ---
+// -----------------------------------
+
+// Utility function that wraps a C++ http request object in a
+// JavaScript object.
+Handle<Object> JsHttpRequestProcessor::WrapMap(map<string, string>* obj) {
+  // Handle scope for temporary handles.
+  HandleScope handle_scope;
+
+  // Fetch the template for creating JavaScript map wrappers.
+  // It only has to be created once, which we do on demand.
+  if (request_template_.IsEmpty()) {
+    Handle<ObjectTemplate> raw_template = MakeMapTemplate();
+    map_template_ = Persistent<ObjectTemplate>::New(raw_template);
+  }
+  Handle<ObjectTemplate> templ = map_template_;
+
+  // Create an empty map wrapper.
+  Handle<Object> result = templ->NewInstance();
+
+  // Wrap the raw C++ pointer in an External so it can be referenced
+  // from within JavaScript.
+  Handle<External> map_ptr = External::New(obj);
+
+  // Store the map pointer in the JavaScript wrapper.
+  result->SetInternalField(0, map_ptr);
+
+  // Return the result through the current handle scope.  Since each
+  // of these handles will go away when the handle scope is deleted
+  // we need to call Close to let one, the result, escape into the
+  // outer handle scope.
+  return handle_scope.Close(result);
+}
+
+
+// Utility function that extracts the C++ map pointer from a wrapper
+// object.
+map<string, string>* JsHttpRequestProcessor::UnwrapMap(Handle<Object> obj) {
+  Handle<External> field = Handle<External>::Cast(obj->GetInternalField(0));
+  void* ptr = field->Value();
+  return static_cast<map<string, string>*>(ptr);
+}
+
+
+// Convert a JavaScript string to a std::string.  To not bother too
+// much with string encodings we just use ascii.
+string ObjectToString(Local<Value> value) {
+  String::Utf8Value utf8_value(value);
+  return string(*utf8_value);
+}
+
+
+Handle<Value> JsHttpRequestProcessor::MapGet(Local<String> name,
+                                             const AccessorInfo& info) {
+  // Fetch the map wrapped by this object.
+  map<string, string>* obj = UnwrapMap(info.Holder());
+
+  // Convert the JavaScript string to a std::string.
+  string key = ObjectToString(name);
+
+  // Look up the value if it exists using the standard STL ideom.
+  map<string, string>::iterator iter = obj->find(key);
+
+  // If the key is not present return an empty handle as signal
+  if (iter == obj->end()) return Handle<Value>();
+
+  // Otherwise fetch the value and wrap it in a JavaScript string
+  const string& value = (*iter).second;
+  return String::New(value.c_str(), value.length());
+}
+
+
+Handle<Value> JsHttpRequestProcessor::MapSet(Local<String> name,
+                                             Local<Value> value_obj,
+                                             const AccessorInfo& info) {
+  // Fetch the map wrapped by this object.
+  map<string, string>* obj = UnwrapMap(info.Holder());
+
+  // Convert the key and value to std::strings.
+  string key = ObjectToString(name);
+  string value = ObjectToString(value_obj);
+
+  // Update the map.
+  (*obj)[key] = value;
+
+  // Return the value; any non-empty handle will work.
+  return value_obj;
+}
+
+
+Handle<ObjectTemplate> JsHttpRequestProcessor::MakeMapTemplate() {
+  HandleScope handle_scope;
+
+  Handle<ObjectTemplate> result = ObjectTemplate::New();
+  result->SetInternalFieldCount(1);
+  result->SetNamedPropertyHandler(MapGet, MapSet);
+
+  // Again, return the result through the current handle scope.
+  return handle_scope.Close(result);
+}
+
+
+// -------------------------------------------
+// --- A c c e s s i n g   R e q u e s t s ---
+// -------------------------------------------
+
+/**
+ * Utility function that wraps a C++ http request object in a
+ * JavaScript object.
+ */
+Handle<Object> JsHttpRequestProcessor::WrapRequest(HttpRequest* request) {
+  // Handle scope for temporary handles.
+  HandleScope handle_scope;
+
+  // Fetch the template for creating JavaScript http request wrappers.
+  // It only has to be created once, which we do on demand.
+  if (request_template_.IsEmpty()) {
+    Handle<ObjectTemplate> raw_template = MakeRequestTemplate();
+    request_template_ = Persistent<ObjectTemplate>::New(raw_template);
+  }
+  Handle<ObjectTemplate> templ = request_template_;
+
+  // Create an empty http request wrapper.
+  Handle<Object> result = templ->NewInstance();
+
+  // Wrap the raw C++ pointer in an External so it can be referenced
+  // from within JavaScript.
+  Handle<External> request_ptr = External::New(request);
+
+  // Store the request pointer in the JavaScript wrapper.
+  result->SetInternalField(0, request_ptr);
+
+  // Return the result through the current handle scope.  Since each
+  // of these handles will go away when the handle scope is deleted
+  // we need to call Close to let one, the result, escape into the
+  // outer handle scope.
+  return handle_scope.Close(result);
+}
+
+
+/**
+ * Utility function that extracts the C++ http request object from a
+ * wrapper object.
+ */
+HttpRequest* JsHttpRequestProcessor::UnwrapRequest(Handle<Object> obj) {
+  Handle<External> field = Handle<External>::Cast(obj->GetInternalField(0));
+  void* ptr = field->Value();
+  return static_cast<HttpRequest*>(ptr);
+}
+
+
+Handle<Value> JsHttpRequestProcessor::GetPath(Local<String> name,
+                                              const AccessorInfo& info) {
+  // Extract the C++ request object from the JavaScript wrapper.
+  HttpRequest* request = UnwrapRequest(info.Holder());
+
+  // Fetch the path.
+  const string& path = request->Path();
+
+  // Wrap the result in a JavaScript string and return it.
+  return String::New(path.c_str(), path.length());
+}
+
+
+Handle<Value> JsHttpRequestProcessor::GetReferrer(Local<String> name,
+                                                  const AccessorInfo& info) {
+  HttpRequest* request = UnwrapRequest(info.Holder());
+  const string& path = request->Referrer();
+  return String::New(path.c_str(), path.length());
+}
+
+
+Handle<Value> JsHttpRequestProcessor::GetHost(Local<String> name,
+                                              const AccessorInfo& info) {
+  HttpRequest* request = UnwrapRequest(info.Holder());
+  const string& path = request->Host();
+  return String::New(path.c_str(), path.length());
+}
+
+
+Handle<Value> JsHttpRequestProcessor::GetUserAgent(Local<String> name,
+                                                   const AccessorInfo& info) {
+  HttpRequest* request = UnwrapRequest(info.Holder());
+  const string& path = request->UserAgent();
+  return String::New(path.c_str(), path.length());
+}
+
+
+Handle<ObjectTemplate> JsHttpRequestProcessor::MakeRequestTemplate() {
+  HandleScope handle_scope;
+
+  Handle<ObjectTemplate> result = ObjectTemplate::New();
+  result->SetInternalFieldCount(1);
+
+  // Add accessors for each of the fields of the request.
+  result->SetAccessor(String::NewSymbol("path"), GetPath);
+  result->SetAccessor(String::NewSymbol("referrer"), GetReferrer);
+  result->SetAccessor(String::NewSymbol("host"), GetHost);
+  result->SetAccessor(String::NewSymbol("userAgent"), GetUserAgent);
+
+  // Again, return the result through the current handle scope.
+  return handle_scope.Close(result);
+}
+
+
+// --- Test ---
+
+
+void HttpRequestProcessor::Log(const char* event) {
+  printf("Logged: %s\n", event);
+}
+
+
+/**
+ * A simplified http request.
+ */
+class StringHttpRequest : public HttpRequest {
+ public:
+  StringHttpRequest(const string& path,
+                    const string& referrer,
+                    const string& host,
+                    const string& user_agent);
+  virtual const string& Path() { return path_; }
+  virtual const string& Referrer() { return referrer_; }
+  virtual const string& Host() { return host_; }
+  virtual const string& UserAgent() { return user_agent_; }
+ private:
+  string path_;
+  string referrer_;
+  string host_;
+  string user_agent_;
+};
+
+
+StringHttpRequest::StringHttpRequest(const string& path,
+                                     const string& referrer,
+                                     const string& host,
+                                     const string& user_agent)
+    : path_(path),
+      referrer_(referrer),
+      host_(host),
+      user_agent_(user_agent) { }
+
+
+void ParseOptions(int argc,
+                  char* argv[],
+                  map<string, string>& options,
+                  string* file) {
+  for (int i = 1; i < argc; i++) {
+    string arg = argv[i];
+    int index = arg.find('=', 0);
+    if (index == string::npos) {
+      *file = arg;
+    } else {
+      string key = arg.substr(0, index);
+      string value = arg.substr(index+1);
+      options[key] = value;
+    }
+  }
+}
+
+
+// Reads a file into a v8 string.
+Handle<String> ReadFile(const string& name) {
+  FILE* file = fopen(name.c_str(), "rb");
+  if (file == NULL) return Handle<String>();
+
+  fseek(file, 0, SEEK_END);
+  int size = ftell(file);
+  rewind(file);
+
+  char* chars = new char[size + 1];
+  chars[size] = '\0';
+  for (int i = 0; i < size;) {
+    int read = fread(&chars[i], 1, size - i, file);
+    i += read;
+  }
+  fclose(file);
+  Handle<String> result = String::New(chars, size);
+  delete[] chars;
+  return result;
+}
+
+
+const int kSampleSize = 6;
+StringHttpRequest kSampleRequests[kSampleSize] = {
+  StringHttpRequest("/process.cc", "localhost", "google.com", "firefox"),
+  StringHttpRequest("/", "localhost", "google.net", "firefox"),
+  StringHttpRequest("/", "localhost", "google.org", "safari"),
+  StringHttpRequest("/", "localhost", "yahoo.com", "ie"),
+  StringHttpRequest("/", "localhost", "yahoo.com", "safari"),
+  StringHttpRequest("/", "localhost", "yahoo.com", "firefox")
+};
+
+
+bool ProcessEntries(HttpRequestProcessor* processor, int count,
+                    StringHttpRequest* reqs) {
+  for (int i = 0; i < count; i++) {
+    if (!processor->Process(&reqs[i]))
+      return false;
+  }
+  return true;
+}
+
+
+void PrintMap(map<string, string>* m) {
+  for (map<string, string>::iterator i = m->begin(); i != m->end(); i++) {
+    pair<string, string> entry = *i;
+    printf("%s: %s\n", entry.first.c_str(), entry.second.c_str());
+  }
+}
+
+
+int main(int argc, char* argv[]) {
+  map<string, string> options;
+  string file;
+  ParseOptions(argc, argv, options, &file);
+  if (file.empty()) {
+    fprintf(stderr, "No script was specified.\n");
+    return 1;
+  }
+  HandleScope scope;
+  Handle<String> source = ReadFile(file);
+  if (source.IsEmpty()) {
+    fprintf(stderr, "Error reading '%s'.\n", file.c_str());
+    return 1;
+  }
+  JsHttpRequestProcessor processor(source);
+  map<string, string> output;
+  if (!processor.Initialize(&options, &output)) {
+    fprintf(stderr, "Error initializing processor.\n");
+    return 1;
+  }
+  if (!ProcessEntries(&processor, kSampleSize, kSampleRequests))
+    return 1;
+  PrintMap(&output);
+}
diff --git a/deps/v8/samples/shell.cc b/deps/v8/samples/shell.cc
new file mode 100644
index 0000000..087d4fd
--- /dev/null
+++ b/deps/v8/samples/shell.cc
@@ -0,0 +1,281 @@
+// 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.
+
+#include <v8.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+void RunShell(v8::Handle<v8::Context> context);
+bool ExecuteString(v8::Handle<v8::String> source,
+                   v8::Handle<v8::Value> name,
+                   bool print_result,
+                   bool report_exceptions);
+v8::Handle<v8::Value> Print(const v8::Arguments& args);
+v8::Handle<v8::Value> Load(const v8::Arguments& args);
+v8::Handle<v8::Value> Quit(const v8::Arguments& args);
+v8::Handle<v8::Value> Version(const v8::Arguments& args);
+v8::Handle<v8::String> ReadFile(const char* name);
+void ReportException(v8::TryCatch* handler);
+
+
+int RunMain(int argc, char* argv[]) {
+  v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
+  v8::HandleScope handle_scope;
+  // Create a template for the global object.
+  v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
+  // Bind the global 'print' function to the C++ Print callback.
+  global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print));
+  // Bind the global 'load' function to the C++ Load callback.
+  global->Set(v8::String::New("load"), v8::FunctionTemplate::New(Load));
+  // Bind the 'quit' function
+  global->Set(v8::String::New("quit"), v8::FunctionTemplate::New(Quit));
+  // Bind the 'version' function
+  global->Set(v8::String::New("version"), v8::FunctionTemplate::New(Version));
+  // Create a new execution environment containing the built-in
+  // functions
+  v8::Handle<v8::Context> context = v8::Context::New(NULL, global);
+  // Enter the newly created execution environment.
+  v8::Context::Scope context_scope(context);
+  bool run_shell = (argc == 1);
+  for (int i = 1; i < argc; i++) {
+    const char* str = argv[i];
+    if (strcmp(str, "--shell") == 0) {
+      run_shell = true;
+    } else if (strcmp(str, "-f") == 0) {
+      // Ignore any -f flags for compatibility with the other stand-
+      // alone JavaScript engines.
+      continue;
+    } else if (strncmp(str, "--", 2) == 0) {
+      printf("Warning: unknown flag %s.\nTry --help for options\n", str);
+    } else if (strcmp(str, "-e") == 0 && i + 1 < argc) {
+      // Execute argument given to -e option directly
+      v8::HandleScope handle_scope;
+      v8::Handle<v8::String> file_name = v8::String::New("unnamed");
+      v8::Handle<v8::String> source = v8::String::New(argv[i + 1]);
+      if (!ExecuteString(source, file_name, false, true))
+        return 1;
+      i++;
+    } else {
+      // Use all other arguments as names of files to load and run.
+      v8::HandleScope handle_scope;
+      v8::Handle<v8::String> file_name = v8::String::New(str);
+      v8::Handle<v8::String> source = ReadFile(str);
+      if (source.IsEmpty()) {
+        printf("Error reading '%s'\n", str);
+        return 1;
+      }
+      if (!ExecuteString(source, file_name, false, true))
+        return 1;
+    }
+  }
+  if (run_shell) RunShell(context);
+  return 0;
+}
+
+
+int main(int argc, char* argv[]) {
+  int result = RunMain(argc, argv);
+  v8::V8::Dispose();
+  return result;
+}
+
+
+// Extracts a C string from a V8 Utf8Value.
+const char* ToCString(const v8::String::Utf8Value& value) {
+  return *value ? *value : "<string conversion failed>";
+}
+
+
+// The callback that is invoked by v8 whenever the JavaScript 'print'
+// function is called.  Prints its arguments on stdout separated by
+// spaces and ending with a newline.
+v8::Handle<v8::Value> Print(const v8::Arguments& args) {
+  bool first = true;
+  for (int i = 0; i < args.Length(); i++) {
+    v8::HandleScope handle_scope;
+    if (first) {
+      first = false;
+    } else {
+      printf(" ");
+    }
+    v8::String::Utf8Value str(args[i]);
+    const char* cstr = ToCString(str);
+    printf("%s", cstr);
+  }
+  printf("\n");
+  fflush(stdout);
+  return v8::Undefined();
+}
+
+
+// The callback that is invoked by v8 whenever the JavaScript 'load'
+// function is called.  Loads, compiles and executes its argument
+// JavaScript file.
+v8::Handle<v8::Value> Load(const v8::Arguments& args) {
+  for (int i = 0; i < args.Length(); i++) {
+    v8::HandleScope handle_scope;
+    v8::String::Utf8Value file(args[i]);
+    if (*file == NULL) {
+      return v8::ThrowException(v8::String::New("Error loading file"));
+    }
+    v8::Handle<v8::String> source = ReadFile(*file);
+    if (source.IsEmpty()) {
+      return v8::ThrowException(v8::String::New("Error loading file"));
+    }
+    if (!ExecuteString(source, v8::String::New(*file), false, false)) {
+      return v8::ThrowException(v8::String::New("Error executing file"));
+    }
+  }
+  return v8::Undefined();
+}
+
+
+// The callback that is invoked by v8 whenever the JavaScript 'quit'
+// function is called.  Quits.
+v8::Handle<v8::Value> Quit(const v8::Arguments& args) {
+  // If not arguments are given args[0] will yield undefined which
+  // converts to the integer value 0.
+  int exit_code = args[0]->Int32Value();
+  exit(exit_code);
+  return v8::Undefined();
+}
+
+
+v8::Handle<v8::Value> Version(const v8::Arguments& args) {
+  return v8::String::New(v8::V8::GetVersion());
+}
+
+
+// Reads a file into a v8 string.
+v8::Handle<v8::String> ReadFile(const char* name) {
+  FILE* file = fopen(name, "rb");
+  if (file == NULL) return v8::Handle<v8::String>();
+
+  fseek(file, 0, SEEK_END);
+  int size = ftell(file);
+  rewind(file);
+
+  char* chars = new char[size + 1];
+  chars[size] = '\0';
+  for (int i = 0; i < size;) {
+    int read = fread(&chars[i], 1, size - i, file);
+    i += read;
+  }
+  fclose(file);
+  v8::Handle<v8::String> result = v8::String::New(chars, size);
+  delete[] chars;
+  return result;
+}
+
+
+// The read-eval-execute loop of the shell.
+void RunShell(v8::Handle<v8::Context> context) {
+  printf("V8 version %s\n", v8::V8::GetVersion());
+  static const int kBufferSize = 256;
+  while (true) {
+    char buffer[kBufferSize];
+    printf("> ");
+    char* str = fgets(buffer, kBufferSize, stdin);
+    if (str == NULL) break;
+    v8::HandleScope handle_scope;
+    ExecuteString(v8::String::New(str),
+                  v8::String::New("(shell)"),
+                  true,
+                  true);
+  }
+  printf("\n");
+}
+
+
+// Executes a string within the current v8 context.
+bool ExecuteString(v8::Handle<v8::String> source,
+                   v8::Handle<v8::Value> name,
+                   bool print_result,
+                   bool report_exceptions) {
+  v8::HandleScope handle_scope;
+  v8::TryCatch try_catch;
+  v8::Handle<v8::Script> script = v8::Script::Compile(source, name);
+  if (script.IsEmpty()) {
+    // Print errors that happened during compilation.
+    if (report_exceptions)
+      ReportException(&try_catch);
+    return false;
+  } else {
+    v8::Handle<v8::Value> result = script->Run();
+    if (result.IsEmpty()) {
+      // Print errors that happened during execution.
+      if (report_exceptions)
+        ReportException(&try_catch);
+      return false;
+    } else {
+      if (print_result && !result->IsUndefined()) {
+        // If all went well and the result wasn't undefined then print
+        // the returned value.
+        v8::String::Utf8Value str(result);
+        const char* cstr = ToCString(str);
+        printf("%s\n", cstr);
+      }
+      return true;
+    }
+  }
+}
+
+
+void ReportException(v8::TryCatch* try_catch) {
+  v8::HandleScope handle_scope;
+  v8::String::Utf8Value exception(try_catch->Exception());
+  const char* exception_string = ToCString(exception);
+  v8::Handle<v8::Message> message = try_catch->Message();
+  if (message.IsEmpty()) {
+    // V8 didn't provide any extra information about this error; just
+    // print the exception.
+    printf("%s\n", exception_string);
+  } else {
+    // Print (filename):(line number): (message).
+    v8::String::Utf8Value filename(message->GetScriptResourceName());
+    const char* filename_string = ToCString(filename);
+    int linenum = message->GetLineNumber();
+    printf("%s:%i: %s\n", filename_string, linenum, exception_string);
+    // Print line of source code.
+    v8::String::Utf8Value sourceline(message->GetSourceLine());
+    const char* sourceline_string = ToCString(sourceline);
+    printf("%s\n", sourceline_string);
+    // Print wavy underline (GetUnderline is deprecated).
+    int start = message->GetStartColumn();
+    for (int i = 0; i < start; i++) {
+      printf(" ");
+    }
+    int end = message->GetEndColumn();
+    for (int i = start; i < end; i++) {
+      printf("^");
+    }
+    printf("\n");
+  }
+}
diff --git a/deps/v8/scons-LICENSE b/deps/v8/scons-LICENSE
new file mode 100644
index 0000000..804ed86
--- /dev/null
+++ b/deps/v8/scons-LICENSE
@@ -0,0 +1,25 @@
+        Copyright and license for SCons - a software construction tool
+
+        This copyright and license do not apply to any other software
+        with which this software may have been included.
+
+Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/deps/v8/scons-README b/deps/v8/scons-README
new file mode 100644
index 0000000..298a221
--- /dev/null
+++ b/deps/v8/scons-README
@@ -0,0 +1,204 @@
+# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
+
+                 SCons - a software construction tool
+
+This is the scons-README file for a version of SCons packaged for local
+execution--that is, execution out of a specific local directory, without
+having to install SCons as a system-wide utility.
+
+You are likely reading this file in one of the following two situations:
+
+    1)  You have unpacked an scons-local-{version} package and are
+        examining the contents.
+
+        In this case, you are presumably interested in using this
+        package to include a local copy of SCons with some other
+        software that you package, so that you can use SCons to build
+        your software without forcing all of your users to have it fully
+        installed.  Instructions for this can be found below.
+
+        If you are not looking to use SCons in this way, then please
+        use either the scons-{version} package to install SCons on your
+        system, or the scons-src-{version} package if you want the full
+        source to SCons, including its packaging code and underlying
+        tests and testing infrastructure.
+
+    2)  This file was included in some other software package so that
+        the package could be built using SCons.
+
+        In this case, follow the instructions provided with the
+        rest of the software package for how to use SCons to build
+        and/or install the software.  The file containing build and
+        installation instructions will typically be named README or
+        INSTALL.
+
+LATEST VERSION
+==============
+
+Before going further, you can check for the latest version of the
+scons-local package, or any SCons package, at the SCons download page:
+
+        http://www.scons.org/download.html
+
+
+EXECUTION REQUIREMENTS
+======================
+
+Running SCons requires Python version 1.5.2 or later.  There should be
+no other dependencies or requirements to run SCons.
+
+The default SCons configuration assumes use of the Microsoft Visual C++
+compiler suite on WIN32 systems, and assumes a C compiler named 'cc',
+a C++ compiler named 'c++', and a Fortran compiler named 'g77' (such
+as found in the GNU C compiler suite) on any other type of system.
+You may, of course, override these default values by appropriate
+configuration of Environment construction variables.
+
+
+INSTALLATION
+============
+
+Installation of this package should be as simple as unpacking the
+archive (either .tar.gz or .zip) in any directory (top-level or a
+subdirectory) within the software package with which you want to ship
+SCons.
+
+Once you have installed this package, you should write an SConstruct
+file at the top level of your source tree to build your software as you
+see fit.
+
+Then modify the build/install instructions for your package to instruct
+your users to execute SCons as follows (if you installed this package in
+your top-level directory):
+
+        $ python scons.py
+
+Or (if, for example, you installed this package in a subdirectory named
+"scons"):
+
+        $ python scons/scons.py
+
+That should be all you have to do.  (If it isn't that simple, please let
+us know!)
+
+
+CONTENTS OF THIS PACKAGE
+========================
+
+This scons-local package consists of the following:
+
+scons-LICENSE
+        A copy of the copyright and terms under which SCons is
+        distributed (the Open Source Initiative-approved MIT license).
+
+        A disclaimer has been added to the beginning to make clear that
+        this license applies only to SCons, and not to any separate
+        software you've written with which you're planning to package
+        SCons.
+
+scons-README
+        What you're looking at right now.
+
+scons-local-{version}/
+        The SCons build engine.  This is structured as a Python
+        library.
+
+scons.py
+        The SCons script itself.  The script sets up the Python
+        sys.path variable to use the build engine found in the
+        scons-local-{version}/ directory in preference to any other
+        SCons build engine installed on your system.
+
+
+DOCUMENTATION
+=============
+
+Because this package is intended to be included with other software by
+experienced users, we have not included any SCons documentation in this
+package (other than this scons-README file you're reading right now).
+
+If, however, you need documentation about SCons, then consult any of the
+following from the corresponding scons-{version} or scons-src-{version}
+package:
+
+        The RELEASE.txt file (src/RELEASE.txt file in the
+        scons-src-{version} package), which contains notes about this
+        specific release, including known problems.
+
+        The CHANGES.txt file (src/CHANGES.txt file in the
+        scons-src-{version} package), which contains a list of changes
+        since the previous release.
+
+        The scons.1 man page (doc/man/scons.1 in the scons-src-{version}
+        package), which contains a section of small examples for getting
+        started using SCons.
+
+Additional documentation for SCons is available at:
+
+        http://www.scons.org/doc.html
+
+
+LICENSING
+=========
+
+SCons is distributed under the MIT license, a full copy of which is
+available in the scons-LICENSE file in this package. The MIT license is
+an approved Open Source license, which means:
+
+        This software is OSI Certified Open Source Software.  OSI
+        Certified is a certification mark of the Open Source Initiative.
+
+More information about OSI certifications and Open Source software is
+available at:
+
+        http://www.opensource.org/
+
+
+REPORTING BUGS
+==============
+
+You can report bugs either by following the "Tracker - Bugs" link
+on the SCons project page:
+
+        http://sourceforge.net/projects/scons/
+
+or by sending mail to the SCons developers mailing list:
+
+        scons-devel@lists.sourceforge.net
+
+
+MAILING LISTS
+=============
+
+A mailing list for users of SCons is available.  You may send questions
+or comments to the list at:
+
+        scons-users@lists.sourceforge.net
+
+You may subscribe to the scons-users mailing list at:
+
+        http://lists.sourceforge.net/lists/listinfo/scons-users
+
+
+FOR MORE INFORMATION
+====================
+
+Check the SCons web site at:
+
+        http://www.scons.org/
+
+
+AUTHOR INFO
+===========
+
+Steven Knight
+knight at baldmt dot com
+http://www.baldmt.com/~knight/
+
+With plenty of help from the SCons Development team:
+        Chad Austin
+        Charles Crain
+        Steve Leblanc
+        Anthony Roach
+        Terrel Shumway
+
diff --git a/deps/v8/scons-time.py b/deps/v8/scons-time.py
new file mode 100755
index 0000000..67b6643
--- /dev/null
+++ b/deps/v8/scons-time.py
@@ -0,0 +1,1513 @@
+#!/usr/bin/env python
+#
+# scons-time - run SCons timings and collect statistics
+#
+# A script for running a configuration through SCons with a standard
+# set of invocations to collect timing and memory statistics and to
+# capture the results in a consistent set of output files for display
+# and analysis.
+#
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+from __future__ import nested_scopes
+
+__revision__ = "src/script/scons-time.py 3842 2008/12/20 22:59:52 scons"
+
+import getopt
+import glob
+import os
+import os.path
+import re
+import shutil
+import string
+import sys
+import tempfile
+import time
+
+try:
+    False
+except NameError:
+    # Pre-2.2 Python has no False keyword.
+    import __builtin__
+    __builtin__.False = not 1
+
+try:
+    True
+except NameError:
+    # Pre-2.2 Python has no True keyword.
+    import __builtin__
+    __builtin__.True = not 0
+
+def make_temp_file(**kw):
+    try:
+        result = tempfile.mktemp(**kw)
+        try:
+            result = os.path.realpath(result)
+        except AttributeError:
+            # Python 2.1 has no os.path.realpath() method.
+            pass
+    except TypeError:
+        try:
+            save_template = tempfile.template
+            prefix = kw['prefix']
+            del kw['prefix']
+            tempfile.template = prefix
+            result = tempfile.mktemp(**kw)
+        finally:
+            tempfile.template = save_template
+    return result
+
+class Plotter:
+    def increment_size(self, largest):
+        """
+        Return the size of each horizontal increment line for a specified
+        maximum value.  This returns a value that will provide somewhere
+        between 5 and 9 horizontal lines on the graph, on some set of
+        boundaries that are multiples of 10/100/1000/etc.
+        """
+        i = largest / 5
+        if not i:
+            return largest
+        multiplier = 1
+        while i >= 10:
+            i = i / 10
+            multiplier = multiplier * 10
+        return i * multiplier
+
+    def max_graph_value(self, largest):
+        # Round up to next integer.
+        largest = int(largest) + 1
+        increment = self.increment_size(largest)
+        return ((largest + increment - 1) / increment) * increment
+
+class Line:
+    def __init__(self, points, type, title, label, comment, fmt="%s %s"):
+        self.points = points
+        self.type = type
+        self.title = title
+        self.label = label
+        self.comment = comment
+        self.fmt = fmt
+
+    def print_label(self, inx, x, y):
+        if self.label:
+            print 'set label %s "%s" at %s,%s right' % (inx, self.label, x, y)
+
+    def plot_string(self):
+        if self.title:
+            title_string = 'title "%s"' % self.title
+        else:
+            title_string = 'notitle'
+        return "'-' %s with lines lt %s" % (title_string, self.type)
+
+    def print_points(self, fmt=None):
+        if fmt is None:
+            fmt = self.fmt
+        if self.comment:
+            print '# %s' % self.comment
+        for x, y in self.points:
+            # If y is None, it usually represents some kind of break
+            # in the line's index number.  We might want to represent
+            # this some way rather than just drawing the line straight
+            # between the two points on either side.
+            if not y is None:
+                print fmt % (x, y)
+        print 'e'
+
+    def get_x_values(self):
+        return [ p[0] for p in self.points ]
+
+    def get_y_values(self):
+        return [ p[1] for p in self.points ]
+
+class Gnuplotter(Plotter):
+
+    def __init__(self, title, key_location):
+        self.lines = []
+        self.title = title
+        self.key_location = key_location
+
+    def line(self, points, type, title=None, label=None, comment=None, fmt='%s %s'):
+        if points:
+            line = Line(points, type, title, label, comment, fmt)
+            self.lines.append(line)
+
+    def plot_string(self, line):
+        return line.plot_string()
+
+    def vertical_bar(self, x, type, label, comment):
+        if self.get_min_x() <= x and x <= self.get_max_x():
+            points = [(x, 0), (x, self.max_graph_value(self.get_max_y()))]
+            self.line(points, type, label, comment)
+
+    def get_all_x_values(self):
+        result = []
+        for line in self.lines:
+            result.extend(line.get_x_values())
+        return filter(lambda r: not r is None, result)
+
+    def get_all_y_values(self):
+        result = []
+        for line in self.lines:
+            result.extend(line.get_y_values())
+        return filter(lambda r: not r is None, result)
+
+    def get_min_x(self):
+        try:
+            return self.min_x
+        except AttributeError:
+            try:
+                self.min_x = min(self.get_all_x_values())
+            except ValueError:
+                self.min_x = 0
+            return self.min_x
+
+    def get_max_x(self):
+        try:
+            return self.max_x
+        except AttributeError:
+            try:
+                self.max_x = max(self.get_all_x_values())
+            except ValueError:
+                self.max_x = 0
+            return self.max_x
+
+    def get_min_y(self):
+        try:
+            return self.min_y
+        except AttributeError:
+            try:
+                self.min_y = min(self.get_all_y_values())
+            except ValueError:
+                self.min_y = 0
+            return self.min_y
+
+    def get_max_y(self):
+        try:
+            return self.max_y
+        except AttributeError:
+            try:
+                self.max_y = max(self.get_all_y_values())
+            except ValueError:
+                self.max_y = 0
+            return self.max_y
+
+    def draw(self):
+
+        if not self.lines:
+            return
+
+        if self.title:
+            print 'set title "%s"' % self.title
+        print 'set key %s' % self.key_location
+
+        min_y = self.get_min_y()
+        max_y = self.max_graph_value(self.get_max_y())
+        range = max_y - min_y
+        incr = range / 10.0
+        start = min_y + (max_y / 2.0) + (2.0 * incr)
+        position = [ start - (i * incr) for i in xrange(5) ]
+
+        inx = 1
+        for line in self.lines:
+            line.print_label(inx, line.points[0][0]-1,
+                             position[(inx-1) % len(position)])
+            inx += 1
+
+        plot_strings = [ self.plot_string(l) for l in self.lines ]
+        print 'plot ' + ', \\\n     '.join(plot_strings)
+
+        for line in self.lines:
+            line.print_points()
+
+
+
+def untar(fname):
+    import tarfile
+    tar = tarfile.open(name=fname, mode='r')
+    for tarinfo in tar:
+        tar.extract(tarinfo)
+    tar.close()
+
+def unzip(fname):
+    import zipfile
+    zf = zipfile.ZipFile(fname, 'r')
+    for name in zf.namelist():
+        dir = os.path.dirname(name)
+        try:
+            os.makedirs(dir)
+        except:
+            pass
+        open(name, 'w').write(zf.read(name))
+
+def read_tree(dir):
+    def read_files(arg, dirname, fnames):
+        for fn in fnames:
+            fn = os.path.join(dirname, fn)
+            if os.path.isfile(fn):
+                open(fn, 'rb').read()
+    os.path.walk('.', read_files, None)
+
+def redirect_to_file(command, log):
+    return '%s > %s 2>&1' % (command, log)
+
+def tee_to_file(command, log):
+    return '%s 2>&1 | tee %s' % (command, log)
+
+
+    
+class SConsTimer:
+    """
+    Usage: scons-time SUBCOMMAND [ARGUMENTS]
+    Type "scons-time help SUBCOMMAND" for help on a specific subcommand.
+
+    Available subcommands:
+        func            Extract test-run data for a function
+        help            Provides help
+        mem             Extract --debug=memory data from test runs
+        obj             Extract --debug=count data from test runs
+        time            Extract --debug=time data from test runs
+        run             Runs a test configuration
+    """
+
+    name = 'scons-time'
+    name_spaces = ' '*len(name)
+
+    def makedict(**kw):
+        return kw
+
+    default_settings = makedict(
+        aegis               = 'aegis',
+        aegis_project       = None,
+        chdir               = None,
+        config_file         = None,
+        initial_commands    = [],
+        key_location        = 'bottom left',
+        orig_cwd            = os.getcwd(),
+        outdir              = None,
+        prefix              = '',
+        python              = '"%s"' % sys.executable,
+        redirect            = redirect_to_file,
+        scons               = None,
+        scons_flags         = '--debug=count --debug=memory --debug=time --debug=memoizer',
+        scons_lib_dir       = None,
+        scons_wrapper       = None,
+        startup_targets     = '--help',
+        subdir              = None,
+        subversion_url      = None,
+        svn                 = 'svn',
+        svn_co_flag         = '-q',
+        tar                 = 'tar',
+        targets             = '',
+        targets0            = None,
+        targets1            = None,
+        targets2            = None,
+        title               = None,
+        unzip               = 'unzip',
+        verbose             = False,
+        vertical_bars       = [],
+
+        unpack_map = {
+            '.tar.gz'       : (untar,   '%(tar)s xzf %%s'),
+            '.tgz'          : (untar,   '%(tar)s xzf %%s'),
+            '.tar'          : (untar,   '%(tar)s xf %%s'),
+            '.zip'          : (unzip,   '%(unzip)s %%s'),
+        },
+    )
+
+    run_titles = [
+        'Startup',
+        'Full build',
+        'Up-to-date build',
+    ]
+
+    run_commands = [
+        '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof0)s %(targets0)s',
+        '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof1)s %(targets1)s',
+        '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof2)s %(targets2)s',
+    ]
+
+    stages = [
+        'pre-read',
+        'post-read',
+        'pre-build',
+        'post-build',
+    ]
+
+    stage_strings = {
+        'pre-read'      : 'Memory before reading SConscript files:',
+        'post-read'     : 'Memory after reading SConscript files:',
+        'pre-build'     : 'Memory before building targets:',
+        'post-build'    : 'Memory after building targets:',
+    }
+
+    memory_string_all = 'Memory '
+
+    default_stage = stages[-1]
+
+    time_strings = {
+        'total'         : 'Total build time',
+        'SConscripts'   : 'Total SConscript file execution time',
+        'SCons'         : 'Total SCons execution time',
+        'commands'      : 'Total command execution time',
+    }
+    
+    time_string_all = 'Total .* time'
+
+    #
+
+    def __init__(self):
+        self.__dict__.update(self.default_settings)
+
+    # Functions for displaying and executing commands.
+
+    def subst(self, x, dictionary):
+        try:
+            return x % dictionary
+        except TypeError:
+            # x isn't a string (it's probably a Python function),
+            # so just return it.
+            return x
+
+    def subst_variables(self, command, dictionary):
+        """
+        Substitutes (via the format operator) the values in the specified
+        dictionary into the specified command.
+
+        The command can be an (action, string) tuple.  In all cases, we
+        perform substitution on strings and don't worry if something isn't
+        a string.  (It's probably a Python function to be executed.)
+        """
+        try:
+            command + ''
+        except TypeError:
+            action = command[0]
+            string = command[1]
+            args = command[2:]
+        else:
+            action = command
+            string = action
+            args = (())
+        action = self.subst(action, dictionary)
+        string = self.subst(string, dictionary)
+        return (action, string, args)
+
+    def _do_not_display(self, msg, *args):
+        pass
+
+    def display(self, msg, *args):
+        """
+        Displays the specified message.
+
+        Each message is prepended with a standard prefix of our name
+        plus the time.
+        """
+        if callable(msg):
+            msg = msg(*args)
+        else:
+            msg = msg % args
+        if msg is None:
+            return
+        fmt = '%s[%s]: %s\n'
+        sys.stdout.write(fmt % (self.name, time.strftime('%H:%M:%S'), msg))
+
+    def _do_not_execute(self, action, *args):
+        pass
+
+    def execute(self, action, *args):
+        """
+        Executes the specified action.
+
+        The action is called if it's a callable Python function, and
+        otherwise passed to os.system().
+        """
+        if callable(action):
+            action(*args)
+        else:
+            os.system(action % args)
+
+    def run_command_list(self, commands, dict):
+        """
+        Executes a list of commands, substituting values from the
+        specified dictionary.
+        """
+        commands = [ self.subst_variables(c, dict) for c in commands ]
+        for action, string, args in commands:
+            self.display(string, *args)
+            sys.stdout.flush()
+            status = self.execute(action, *args)
+            if status:
+                sys.exit(status)
+
+    def log_display(self, command, log):
+        command = self.subst(command, self.__dict__)
+        if log:
+            command = self.redirect(command, log)
+        return command
+
+    def log_execute(self, command, log):
+        command = self.subst(command, self.__dict__)
+        output = os.popen(command).read()
+        if self.verbose:
+            sys.stdout.write(output)
+        open(log, 'wb').write(output)
+
+    #
+
+    def archive_splitext(self, path):
+        """
+        Splits an archive name into a filename base and extension.
+
+        This is like os.path.splitext() (which it calls) except that it
+        also looks for '.tar.gz' and treats it as an atomic extensions.
+        """
+        if path.endswith('.tar.gz'):
+            return path[:-7], path[-7:]
+        else:
+            return os.path.splitext(path)
+
+    def args_to_files(self, args, tail=None):
+        """
+        Takes a list of arguments, expands any glob patterns, and
+        returns the last "tail" files from the list.
+        """
+        files = []
+        for a in args:
+            g = glob.glob(a)
+            g.sort()
+            files.extend(g)
+
+        if tail:
+            files = files[-tail:]
+
+        return files
+
+    def ascii_table(self, files, columns,
+                    line_function, file_function=lambda x: x,
+                    *args, **kw):
+
+        header_fmt = ' '.join(['%12s'] * len(columns))
+        line_fmt = header_fmt + '    %s'
+
+        print header_fmt % columns
+
+        for file in files:
+            t = line_function(file, *args, **kw)
+            if t is None:
+                t = []
+            diff = len(columns) - len(t)
+            if diff > 0:
+                t += [''] * diff
+            t.append(file_function(file))
+            print line_fmt % tuple(t)
+
+    def collect_results(self, files, function, *args, **kw):
+        results = {}
+
+        for file in files:
+            base = os.path.splitext(file)[0]
+            run, index = string.split(base, '-')[-2:]
+
+            run = int(run)
+            index = int(index)
+
+            value = function(file, *args, **kw)
+
+            try:
+                r = results[index]
+            except KeyError:
+                r = []
+                results[index] = r
+            r.append((run, value))
+
+        return results
+
+    def doc_to_help(self, obj):
+        """
+        Translates an object's __doc__ string into help text.
+
+        This strips a consistent number of spaces from each line in the
+        help text, essentially "outdenting" the text to the left-most
+        column.
+        """
+        doc = obj.__doc__
+        if doc is None:
+            return ''
+        return self.outdent(doc)
+
+    def find_next_run_number(self, dir, prefix):
+        """
+        Returns the next run number in a directory for the specified prefix.
+
+        Examines the contents the specified directory for files with the
+        specified prefix, extracts the run numbers from each file name,
+        and returns the next run number after the largest it finds.
+        """
+        x = re.compile(re.escape(prefix) + '-([0-9]+).*')
+        matches = map(lambda e, x=x: x.match(e), os.listdir(dir))
+        matches = filter(None, matches)
+        if not matches:
+            return 0
+        run_numbers = map(lambda m: int(m.group(1)), matches)
+        return int(max(run_numbers)) + 1
+
+    def gnuplot_results(self, results, fmt='%s %.3f'):
+        """
+        Prints out a set of results in Gnuplot format.
+        """
+        gp = Gnuplotter(self.title, self.key_location)
+
+        indices = results.keys()
+        indices.sort()
+
+        for i in indices:
+            try:
+                t = self.run_titles[i]
+            except IndexError:
+                t = '??? %s ???' % i
+            results[i].sort()
+            gp.line(results[i], i+1, t, None, t, fmt=fmt)
+
+        for bar_tuple in self.vertical_bars:
+            try:
+                x, type, label, comment = bar_tuple
+            except ValueError:
+                x, type, label = bar_tuple
+                comment = label
+            gp.vertical_bar(x, type, label, comment)
+
+        gp.draw()
+
+    def logfile_name(self, invocation):
+        """
+        Returns the absolute path of a log file for the specificed
+        invocation number.
+        """
+        name = self.prefix_run + '-%d.log' % invocation
+        return os.path.join(self.outdir, name)
+
+    def outdent(self, s):
+        """
+        Strip as many spaces from each line as are found at the beginning
+        of the first line in the list.
+        """
+        lines = s.split('\n')
+        if lines[0] == '':
+            lines = lines[1:]
+        spaces = re.match(' *', lines[0]).group(0)
+        def strip_initial_spaces(l, s=spaces):
+            if l.startswith(spaces):
+                l = l[len(spaces):]
+            return l
+        return '\n'.join([ strip_initial_spaces(l) for l in lines ]) + '\n'
+
+    def profile_name(self, invocation):
+        """
+        Returns the absolute path of a profile file for the specified
+        invocation number.
+        """
+        name = self.prefix_run + '-%d.prof' % invocation
+        return os.path.join(self.outdir, name)
+
+    def set_env(self, key, value):
+        os.environ[key] = value
+
+    #
+
+    def get_debug_times(self, file, time_string=None):
+        """
+        Fetch times from the --debug=time strings in the specified file.
+        """
+        if time_string is None:
+            search_string = self.time_string_all
+        else:
+            search_string = time_string
+        contents = open(file).read()
+        if not contents:
+            sys.stderr.write('file %s has no contents!\n' % repr(file))
+            return None
+        result = re.findall(r'%s: ([\d\.]*)' % search_string, contents)[-4:]
+        result = [ float(r) for r in result ]
+        if not time_string is None:
+            try:
+                result = result[0]
+            except IndexError:
+                sys.stderr.write('file %s has no results!\n' % repr(file))
+                return None
+        return result
+
+    def get_function_profile(self, file, function):
+        """
+        Returns the file, line number, function name, and cumulative time.
+        """
+        try:
+            import pstats
+        except ImportError, e:
+            sys.stderr.write('%s: func: %s\n' % (self.name, e))
+            sys.stderr.write('%s  This version of Python is missing the profiler.\n' % self.name_spaces)
+            sys.stderr.write('%s  Cannot use the "func" subcommand.\n' % self.name_spaces)
+            sys.exit(1)
+        statistics = pstats.Stats(file).stats
+        matches = [ e for e in statistics.items() if e[0][2] == function ]
+        r = matches[0]
+        return r[0][0], r[0][1], r[0][2], r[1][3]
+
+    def get_function_time(self, file, function):
+        """
+        Returns just the cumulative time for the specified function.
+        """
+        return self.get_function_profile(file, function)[3]
+
+    def get_memory(self, file, memory_string=None):
+        """
+        Returns a list of integers of the amount of memory used.  The
+        default behavior is to return all the stages.
+        """
+        if memory_string is None:
+            search_string = self.memory_string_all
+        else:
+            search_string = memory_string
+        lines = open(file).readlines()
+        lines = [ l for l in lines if l.startswith(search_string) ][-4:]
+        result = [ int(l.split()[-1]) for l in lines[-4:] ]
+        if len(result) == 1:
+            result = result[0]
+        return result
+
+    def get_object_counts(self, file, object_name, index=None):
+        """
+        Returns the counts of the specified object_name.
+        """
+        object_string = ' ' + object_name + '\n'
+        lines = open(file).readlines()
+        line = [ l for l in lines if l.endswith(object_string) ][0]
+        result = [ int(field) for field in line.split()[:4] ]
+        if not index is None:
+            result = result[index]
+        return result
+
+    #
+
+    command_alias = {}
+
+    def execute_subcommand(self, argv):
+        """
+        Executes the do_*() function for the specified subcommand (argv[0]).
+        """
+        if not argv:
+            return
+        cmdName = self.command_alias.get(argv[0], argv[0])
+        try:
+            func = getattr(self, 'do_' + cmdName)
+        except AttributeError:
+            return self.default(argv)
+        try:
+            return func(argv)
+        except TypeError, e:
+            sys.stderr.write("%s %s: %s\n" % (self.name, cmdName, e))
+            import traceback
+            traceback.print_exc(file=sys.stderr)
+            sys.stderr.write("Try '%s help %s'\n" % (self.name, cmdName))
+
+    def default(self, argv):
+        """
+        The default behavior for an unknown subcommand.  Prints an
+        error message and exits.
+        """
+        sys.stderr.write('%s: Unknown subcommand "%s".\n' % (self.name, argv[0]))
+        sys.stderr.write('Type "%s help" for usage.\n' % self.name)
+        sys.exit(1)
+
+    #
+
+    def do_help(self, argv):
+        """
+        """
+        if argv[1:]:
+            for arg in argv[1:]:
+                try:
+                    func = getattr(self, 'do_' + arg)
+                except AttributeError:
+                    sys.stderr.write('%s: No help for "%s"\n' % (self.name, arg))
+                else:
+                    try:
+                        help = getattr(self, 'help_' + arg)
+                    except AttributeError:
+                        sys.stdout.write(self.doc_to_help(func))
+                        sys.stdout.flush()
+                    else:
+                        help()
+        else:
+            doc = self.doc_to_help(self.__class__)
+            if doc:
+                sys.stdout.write(doc)
+            sys.stdout.flush()
+            return None
+
+    #
+
+    def help_func(self):
+        help = """\
+        Usage: scons-time func [OPTIONS] FILE [...]
+
+          -C DIR, --chdir=DIR           Change to DIR before looking for files
+          -f FILE, --file=FILE          Read configuration from specified FILE
+          --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT
+          --func=NAME, --function=NAME  Report time for function NAME
+          -h, --help                    Print this help and exit
+          -p STRING, --prefix=STRING    Use STRING as log file/profile prefix
+          -t NUMBER, --tail=NUMBER      Only report the last NUMBER files
+          --title=TITLE                 Specify the output plot TITLE
+        """
+        sys.stdout.write(self.outdent(help))
+        sys.stdout.flush()
+
+    def do_func(self, argv):
+        """
+        """
+        format = 'ascii'
+        function_name = '_main'
+        tail = None
+
+        short_opts = '?C:f:hp:t:'
+
+        long_opts = [
+            'chdir=',
+            'file=',
+            'fmt=',
+            'format=',
+            'func=',
+            'function=',
+            'help',
+            'prefix=',
+            'tail=',
+            'title=',
+        ]
+
+        opts, args = getopt.getopt(argv[1:], short_opts, long_opts)
+
+        for o, a in opts:
+            if o in ('-C', '--chdir'):
+                self.chdir = a
+            elif o in ('-f', '--file'):
+                self.config_file = a
+            elif o in ('--fmt', '--format'):
+                format = a
+            elif o in ('--func', '--function'):
+                function_name = a
+            elif o in ('-?', '-h', '--help'):
+                self.do_help(['help', 'func'])
+                sys.exit(0)
+            elif o in ('--max',):
+                max_time = int(a)
+            elif o in ('-p', '--prefix'):
+                self.prefix = a
+            elif o in ('-t', '--tail'):
+                tail = int(a)
+            elif o in ('--title',):
+                self.title = a
+
+        if self.config_file:
+            execfile(self.config_file, self.__dict__)
+
+        if self.chdir:
+            os.chdir(self.chdir)
+
+        if not args:
+
+            pattern = '%s*.prof' % self.prefix
+            args = self.args_to_files([pattern], tail)
+
+            if not args:
+                if self.chdir:
+                    directory = self.chdir
+                else:
+                    directory = os.getcwd()
+
+                sys.stderr.write('%s: func: No arguments specified.\n' % self.name)
+                sys.stderr.write('%s  No %s*.prof files found in "%s".\n' % (self.name_spaces, self.prefix, directory))
+                sys.stderr.write('%s  Type "%s help func" for help.\n' % (self.name_spaces, self.name))
+                sys.exit(1)
+
+        else:
+
+            args = self.args_to_files(args, tail)
+
+        cwd_ = os.getcwd() + os.sep
+
+        if format == 'ascii':
+
+            def print_function_timing(file, func):
+                try:
+                    f, line, func, time = self.get_function_profile(file, func)
+                except ValueError, e:
+                    sys.stderr.write("%s: func: %s: %s\n" % (self.name, file, e))
+                else:
+                    if f.startswith(cwd_):
+                        f = f[len(cwd_):]
+                    print "%.3f %s:%d(%s)" % (time, f, line, func)
+
+            for file in args:
+                print_function_timing(file, function_name)
+
+        elif format == 'gnuplot':
+
+            results = self.collect_results(args, self.get_function_time,
+                                           function_name)
+
+            self.gnuplot_results(results)
+
+        else:
+
+            sys.stderr.write('%s: func: Unknown format "%s".\n' % (self.name, format))
+            sys.exit(1)
+
+    #
+
+    def help_mem(self):
+        help = """\
+        Usage: scons-time mem [OPTIONS] FILE [...]
+
+          -C DIR, --chdir=DIR           Change to DIR before looking for files
+          -f FILE, --file=FILE          Read configuration from specified FILE
+          --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT
+          -h, --help                    Print this help and exit
+          -p STRING, --prefix=STRING    Use STRING as log file/profile prefix
+          --stage=STAGE                 Plot memory at the specified stage:
+                                          pre-read, post-read, pre-build,
+                                          post-build (default: post-build)
+          -t NUMBER, --tail=NUMBER      Only report the last NUMBER files
+          --title=TITLE                 Specify the output plot TITLE
+        """
+        sys.stdout.write(self.outdent(help))
+        sys.stdout.flush()
+
+    def do_mem(self, argv):
+
+        format = 'ascii'
+        logfile_path = lambda x: x
+        stage = self.default_stage
+        tail = None
+
+        short_opts = '?C:f:hp:t:'
+
+        long_opts = [
+            'chdir=',
+            'file=',
+            'fmt=',
+            'format=',
+            'help',
+            'prefix=',
+            'stage=',
+            'tail=',
+            'title=',
+        ]
+
+        opts, args = getopt.getopt(argv[1:], short_opts, long_opts)
+
+        for o, a in opts:
+            if o in ('-C', '--chdir'):
+                self.chdir = a
+            elif o in ('-f', '--file'):
+                self.config_file = a
+            elif o in ('--fmt', '--format'):
+                format = a
+            elif o in ('-?', '-h', '--help'):
+                self.do_help(['help', 'mem'])
+                sys.exit(0)
+            elif o in ('-p', '--prefix'):
+                self.prefix = a
+            elif o in ('--stage',):
+                if not a in self.stages:
+                    sys.stderr.write('%s: mem: Unrecognized stage "%s".\n' % (self.name, a))
+                    sys.exit(1)
+                stage = a
+            elif o in ('-t', '--tail'):
+                tail = int(a)
+            elif o in ('--title',):
+                self.title = a
+
+        if self.config_file:
+            execfile(self.config_file, self.__dict__)
+
+        if self.chdir:
+            os.chdir(self.chdir)
+            logfile_path = lambda x, c=self.chdir: os.path.join(c, x)
+
+        if not args:
+
+            pattern = '%s*.log' % self.prefix
+            args = self.args_to_files([pattern], tail)
+
+            if not args:
+                if self.chdir:
+                    directory = self.chdir
+                else:
+                    directory = os.getcwd()
+
+                sys.stderr.write('%s: mem: No arguments specified.\n' % self.name)
+                sys.stderr.write('%s  No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory))
+                sys.stderr.write('%s  Type "%s help mem" for help.\n' % (self.name_spaces, self.name))
+                sys.exit(1)
+
+        else:
+
+            args = self.args_to_files(args, tail)
+
+        cwd_ = os.getcwd() + os.sep
+
+        if format == 'ascii':
+
+            self.ascii_table(args, tuple(self.stages), self.get_memory, logfile_path)
+
+        elif format == 'gnuplot':
+
+            results = self.collect_results(args, self.get_memory,
+                                           self.stage_strings[stage])
+
+            self.gnuplot_results(results)
+
+        else:
+
+            sys.stderr.write('%s: mem: Unknown format "%s".\n' % (self.name, format))
+            sys.exit(1)
+
+        return 0
+
+    #
+
+    def help_obj(self):
+        help = """\
+        Usage: scons-time obj [OPTIONS] OBJECT FILE [...]
+
+          -C DIR, --chdir=DIR           Change to DIR before looking for files
+          -f FILE, --file=FILE          Read configuration from specified FILE
+          --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT
+          -h, --help                    Print this help and exit
+          -p STRING, --prefix=STRING    Use STRING as log file/profile prefix
+          --stage=STAGE                 Plot memory at the specified stage:
+                                          pre-read, post-read, pre-build,
+                                          post-build (default: post-build)
+          -t NUMBER, --tail=NUMBER      Only report the last NUMBER files
+          --title=TITLE                 Specify the output plot TITLE
+        """
+        sys.stdout.write(self.outdent(help))
+        sys.stdout.flush()
+
+    def do_obj(self, argv):
+
+        format = 'ascii'
+        logfile_path = lambda x: x
+        stage = self.default_stage
+        tail = None
+
+        short_opts = '?C:f:hp:t:'
+
+        long_opts = [
+            'chdir=',
+            'file=',
+            'fmt=',
+            'format=',
+            'help',
+            'prefix=',
+            'stage=',
+            'tail=',
+            'title=',
+        ]
+
+        opts, args = getopt.getopt(argv[1:], short_opts, long_opts)
+
+        for o, a in opts:
+            if o in ('-C', '--chdir'):
+                self.chdir = a
+            elif o in ('-f', '--file'):
+                self.config_file = a
+            elif o in ('--fmt', '--format'):
+                format = a
+            elif o in ('-?', '-h', '--help'):
+                self.do_help(['help', 'obj'])
+                sys.exit(0)
+            elif o in ('-p', '--prefix'):
+                self.prefix = a
+            elif o in ('--stage',):
+                if not a in self.stages:
+                    sys.stderr.write('%s: obj: Unrecognized stage "%s".\n' % (self.name, a))
+                    sys.stderr.write('%s       Type "%s help obj" for help.\n' % (self.name_spaces, self.name))
+                    sys.exit(1)
+                stage = a
+            elif o in ('-t', '--tail'):
+                tail = int(a)
+            elif o in ('--title',):
+                self.title = a
+
+        if not args:
+            sys.stderr.write('%s: obj: Must specify an object name.\n' % self.name)
+            sys.stderr.write('%s       Type "%s help obj" for help.\n' % (self.name_spaces, self.name))
+            sys.exit(1)
+
+        object_name = args.pop(0)
+
+        if self.config_file:
+            execfile(self.config_file, self.__dict__)
+
+        if self.chdir:
+            os.chdir(self.chdir)
+            logfile_path = lambda x, c=self.chdir: os.path.join(c, x)
+
+        if not args:
+
+            pattern = '%s*.log' % self.prefix
+            args = self.args_to_files([pattern], tail)
+
+            if not args:
+                if self.chdir:
+                    directory = self.chdir
+                else:
+                    directory = os.getcwd()
+
+                sys.stderr.write('%s: obj: No arguments specified.\n' % self.name)
+                sys.stderr.write('%s  No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory))
+                sys.stderr.write('%s  Type "%s help obj" for help.\n' % (self.name_spaces, self.name))
+                sys.exit(1)
+
+        else:
+
+            args = self.args_to_files(args, tail)
+
+        cwd_ = os.getcwd() + os.sep
+
+        if format == 'ascii':
+
+            self.ascii_table(args, tuple(self.stages), self.get_object_counts, logfile_path, object_name)
+
+        elif format == 'gnuplot':
+
+            stage_index = 0
+            for s in self.stages:
+                if stage == s:
+                    break
+                stage_index = stage_index + 1
+
+            results = self.collect_results(args, self.get_object_counts,
+                                           object_name, stage_index)
+
+            self.gnuplot_results(results)
+
+        else:
+
+            sys.stderr.write('%s: obj: Unknown format "%s".\n' % (self.name, format))
+            sys.exit(1)
+
+        return 0
+
+    #
+
+    def help_run(self):
+        help = """\
+        Usage: scons-time run [OPTIONS] [FILE ...]
+
+          --aegis=PROJECT               Use SCons from the Aegis PROJECT
+          --chdir=DIR                   Name of unpacked directory for chdir
+          -f FILE, --file=FILE          Read configuration from specified FILE
+          -h, --help                    Print this help and exit
+          -n, --no-exec                 No execute, just print command lines
+          --number=NUMBER               Put output in files for run NUMBER
+          --outdir=OUTDIR               Put output files in OUTDIR
+          -p STRING, --prefix=STRING    Use STRING as log file/profile prefix
+          --python=PYTHON               Time using the specified PYTHON
+          -q, --quiet                   Don't print command lines
+          --scons=SCONS                 Time using the specified SCONS
+          --svn=URL, --subversion=URL   Use SCons from Subversion URL
+          -v, --verbose                 Display output of commands
+        """
+        sys.stdout.write(self.outdent(help))
+        sys.stdout.flush()
+
+    def do_run(self, argv):
+        """
+        """
+        run_number_list = [None]
+
+        short_opts = '?f:hnp:qs:v'
+
+        long_opts = [
+            'aegis=',
+            'file=',
+            'help',
+            'no-exec',
+            'number=',
+            'outdir=',
+            'prefix=',
+            'python=',
+            'quiet',
+            'scons=',
+            'svn=',
+            'subdir=',
+            'subversion=',
+            'verbose',
+        ]
+
+        opts, args = getopt.getopt(argv[1:], short_opts, long_opts)
+
+        for o, a in opts:
+            if o in ('--aegis',):
+                self.aegis_project = a
+            elif o in ('-f', '--file'):
+                self.config_file = a
+            elif o in ('-?', '-h', '--help'):
+                self.do_help(['help', 'run'])
+                sys.exit(0)
+            elif o in ('-n', '--no-exec'):
+                self.execute = self._do_not_execute
+            elif o in ('--number',):
+                run_number_list = self.split_run_numbers(a)
+            elif o in ('--outdir',):
+                self.outdir = a
+            elif o in ('-p', '--prefix'):
+                self.prefix = a
+            elif o in ('--python',):
+                self.python = a
+            elif o in ('-q', '--quiet'):
+                self.display = self._do_not_display
+            elif o in ('-s', '--subdir'):
+                self.subdir = a
+            elif o in ('--scons',):
+                self.scons = a
+            elif o in ('--svn', '--subversion'):
+                self.subversion_url = a
+            elif o in ('-v', '--verbose'):
+                self.redirect = tee_to_file
+                self.verbose = True
+                self.svn_co_flag = ''
+
+        if not args and not self.config_file:
+            sys.stderr.write('%s: run: No arguments or -f config file specified.\n' % self.name)
+            sys.stderr.write('%s  Type "%s help run" for help.\n' % (self.name_spaces, self.name))
+            sys.exit(1)
+
+        if self.config_file:
+            execfile(self.config_file, self.__dict__)
+
+        if args:
+            self.archive_list = args
+
+        archive_file_name = os.path.split(self.archive_list[0])[1]
+
+        if not self.subdir:
+            self.subdir = self.archive_splitext(archive_file_name)[0]
+
+        if not self.prefix:
+            self.prefix = self.archive_splitext(archive_file_name)[0]
+
+        prepare = None
+        if self.subversion_url:
+            prepare = self.prep_subversion_run
+        elif self.aegis_project:
+            prepare = self.prep_aegis_run
+
+        for run_number in run_number_list:
+            self.individual_run(run_number, self.archive_list, prepare)
+
+    def split_run_numbers(self, s):
+        result = []
+        for n in s.split(','):
+            try:
+                x, y = n.split('-')
+            except ValueError:
+                result.append(int(n))
+            else:
+                result.extend(range(int(x), int(y)+1))
+        return result
+
+    def scons_path(self, dir):
+        return os.path.join(dir, 'src', 'script', 'scons.py')
+
+    def scons_lib_dir_path(self, dir):
+        return os.path.join(dir, 'src', 'engine')
+
+    def prep_aegis_run(self, commands, removals):
+        self.aegis_tmpdir = make_temp_file(prefix = self.name + '-aegis-')
+        removals.append((shutil.rmtree, 'rm -rf %%s', self.aegis_tmpdir))
+
+        self.aegis_parent_project = os.path.splitext(self.aegis_project)[0]
+        self.scons = self.scons_path(self.aegis_tmpdir)
+        self.scons_lib_dir = self.scons_lib_dir_path(self.aegis_tmpdir)
+
+        commands.extend([
+            'mkdir %(aegis_tmpdir)s',
+            (lambda: os.chdir(self.aegis_tmpdir), 'cd %(aegis_tmpdir)s'),
+            '%(aegis)s -cp -ind -p %(aegis_parent_project)s .',
+            '%(aegis)s -cp -ind -p %(aegis_project)s -delta %(run_number)s .',
+        ])
+
+    def prep_subversion_run(self, commands, removals):
+        self.svn_tmpdir = make_temp_file(prefix = self.name + '-svn-')
+        removals.append((shutil.rmtree, 'rm -rf %%s', self.svn_tmpdir))
+
+        self.scons = self.scons_path(self.svn_tmpdir)
+        self.scons_lib_dir = self.scons_lib_dir_path(self.svn_tmpdir)
+
+        commands.extend([
+            'mkdir %(svn_tmpdir)s',
+            '%(svn)s co %(svn_co_flag)s -r %(run_number)s %(subversion_url)s %(svn_tmpdir)s',
+        ])
+
+    def individual_run(self, run_number, archive_list, prepare=None):
+        """
+        Performs an individual run of the default SCons invocations.
+        """
+
+        commands = []
+        removals = []
+
+        if prepare:
+            prepare(commands, removals)
+
+        save_scons              = self.scons
+        save_scons_wrapper      = self.scons_wrapper
+        save_scons_lib_dir      = self.scons_lib_dir
+
+        if self.outdir is None:
+            self.outdir = self.orig_cwd
+        elif not os.path.isabs(self.outdir):
+            self.outdir = os.path.join(self.orig_cwd, self.outdir)
+
+        if self.scons is None:
+            self.scons = self.scons_path(self.orig_cwd)
+
+        if self.scons_lib_dir is None:
+            self.scons_lib_dir = self.scons_lib_dir_path(self.orig_cwd)
+
+        if self.scons_wrapper is None:
+            self.scons_wrapper = self.scons
+
+        if not run_number:
+            run_number = self.find_next_run_number(self.outdir, self.prefix)
+
+        self.run_number = str(run_number)
+
+        self.prefix_run = self.prefix + '-%03d' % run_number
+
+        if self.targets0 is None:
+            self.targets0 = self.startup_targets
+        if self.targets1 is None:
+            self.targets1 = self.targets
+        if self.targets2 is None:
+            self.targets2 = self.targets
+
+        self.tmpdir = make_temp_file(prefix = self.name + '-')
+
+        commands.extend([
+            'mkdir %(tmpdir)s',
+
+            (os.chdir, 'cd %%s', self.tmpdir),
+        ])
+
+        for archive in archive_list:
+            if not os.path.isabs(archive):
+                archive = os.path.join(self.orig_cwd, archive)
+            if os.path.isdir(archive):
+                dest = os.path.split(archive)[1]
+                commands.append((shutil.copytree, 'cp -r %%s %%s', archive, dest))
+            else:
+                suffix = self.archive_splitext(archive)[1]
+                unpack_command = self.unpack_map.get(suffix)
+                if not unpack_command:
+                    dest = os.path.split(archive)[1]
+                    commands.append((shutil.copyfile, 'cp %%s %%s', archive, dest))
+                else:
+                    commands.append(unpack_command + (archive,))
+
+        commands.extend([
+            (os.chdir, 'cd %%s', self.subdir),
+        ])
+
+        commands.extend(self.initial_commands)
+
+        commands.extend([
+            (lambda: read_tree('.'),
+            'find * -type f | xargs cat > /dev/null'),
+
+            (self.set_env, 'export %%s=%%s',
+             'SCONS_LIB_DIR', self.scons_lib_dir),
+
+            '%(python)s %(scons_wrapper)s --version',
+        ])
+
+        index = 0
+        for run_command in self.run_commands:
+            setattr(self, 'prof%d' % index, self.profile_name(index))
+            c = (
+                self.log_execute,
+                self.log_display,
+                run_command,
+                self.logfile_name(index),
+            )
+            commands.append(c)
+            index = index + 1
+
+        commands.extend([
+            (os.chdir, 'cd %%s', self.orig_cwd),
+        ])
+
+        if not os.environ.get('PRESERVE'):
+            commands.extend(removals)
+
+            commands.append((shutil.rmtree, 'rm -rf %%s', self.tmpdir))
+
+        self.run_command_list(commands, self.__dict__)
+
+        self.scons              = save_scons
+        self.scons_lib_dir      = save_scons_lib_dir
+        self.scons_wrapper      = save_scons_wrapper
+
+    #
+
+    def help_time(self):
+        help = """\
+        Usage: scons-time time [OPTIONS] FILE [...]
+
+          -C DIR, --chdir=DIR           Change to DIR before looking for files
+          -f FILE, --file=FILE          Read configuration from specified FILE
+          --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT
+          -h, --help                    Print this help and exit
+          -p STRING, --prefix=STRING    Use STRING as log file/profile prefix
+          -t NUMBER, --tail=NUMBER      Only report the last NUMBER files
+          --which=TIMER                 Plot timings for TIMER:  total,
+                                          SConscripts, SCons, commands.
+        """
+        sys.stdout.write(self.outdent(help))
+        sys.stdout.flush()
+
+    def do_time(self, argv):
+
+        format = 'ascii'
+        logfile_path = lambda x: x
+        tail = None
+        which = 'total'
+
+        short_opts = '?C:f:hp:t:'
+
+        long_opts = [
+            'chdir=',
+            'file=',
+            'fmt=',
+            'format=',
+            'help',
+            'prefix=',
+            'tail=',
+            'title=',
+            'which=',
+        ]
+
+        opts, args = getopt.getopt(argv[1:], short_opts, long_opts)
+
+        for o, a in opts:
+            if o in ('-C', '--chdir'):
+                self.chdir = a
+            elif o in ('-f', '--file'):
+                self.config_file = a
+            elif o in ('--fmt', '--format'):
+                format = a
+            elif o in ('-?', '-h', '--help'):
+                self.do_help(['help', 'time'])
+                sys.exit(0)
+            elif o in ('-p', '--prefix'):
+                self.prefix = a
+            elif o in ('-t', '--tail'):
+                tail = int(a)
+            elif o in ('--title',):
+                self.title = a
+            elif o in ('--which',):
+                if not a in self.time_strings.keys():
+                    sys.stderr.write('%s: time: Unrecognized timer "%s".\n' % (self.name, a))
+                    sys.stderr.write('%s  Type "%s help time" for help.\n' % (self.name_spaces, self.name))
+                    sys.exit(1)
+                which = a
+
+        if self.config_file:
+            execfile(self.config_file, self.__dict__)
+
+        if self.chdir:
+            os.chdir(self.chdir)
+            logfile_path = lambda x, c=self.chdir: os.path.join(c, x)
+
+        if not args:
+
+            pattern = '%s*.log' % self.prefix
+            args = self.args_to_files([pattern], tail)
+
+            if not args:
+                if self.chdir:
+                    directory = self.chdir
+                else:
+                    directory = os.getcwd()
+
+                sys.stderr.write('%s: time: No arguments specified.\n' % self.name)
+                sys.stderr.write('%s  No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory))
+                sys.stderr.write('%s  Type "%s help time" for help.\n' % (self.name_spaces, self.name))
+                sys.exit(1)
+
+        else:
+
+            args = self.args_to_files(args, tail)
+
+        cwd_ = os.getcwd() + os.sep
+
+        if format == 'ascii':
+
+            columns = ("Total", "SConscripts", "SCons", "commands")
+            self.ascii_table(args, columns, self.get_debug_times, logfile_path)
+
+        elif format == 'gnuplot':
+
+            results = self.collect_results(args, self.get_debug_times,
+                                           self.time_strings[which])
+
+            self.gnuplot_results(results, fmt='%s %.6f')
+
+        else:
+
+            sys.stderr.write('%s: time: Unknown format "%s".\n' % (self.name, format))
+            sys.exit(1)
+
+if __name__ == '__main__':
+    opts, args = getopt.getopt(sys.argv[1:], 'h?V', ['help', 'version'])
+
+    ST = SConsTimer()
+
+    for o, a in opts:
+        if o in ('-?', '-h', '--help'):
+            ST.do_help(['help'])
+            sys.exit(0)
+        elif o in ('-V', '--version'):
+            sys.stdout.write('scons-time version\n')
+            sys.exit(0)
+
+    if not args:
+        sys.stderr.write('Type "%s help" for usage.\n' % ST.name)
+        sys.exit(1)
+
+    ST.execute_subcommand(args)
diff --git a/deps/v8/scons.py b/deps/v8/scons.py
new file mode 100755
index 0000000..88276a4
--- /dev/null
+++ b/deps/v8/scons.py
@@ -0,0 +1,165 @@
+#! /usr/bin/env python
+#
+# SCons - a Software Constructor
+#
+# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "src/script/scons.py 3842 2008/12/20 22:59:52 scons"
+
+__version__ = "1.2.0"
+
+__build__ = "r3842"
+
+__buildsys__ = "scons-dev"
+
+__date__ = "2008/12/20 22:59:52"
+
+__developer__ = "scons"
+
+import os
+import os.path
+import sys
+
+##############################################################################
+# BEGIN STANDARD SCons SCRIPT HEADER
+#
+# This is the cut-and-paste logic so that a self-contained script can
+# interoperate correctly with different SCons versions and installation
+# locations for the engine.  If you modify anything in this section, you
+# should also change other scripts that use this same header.
+##############################################################################
+
+# Strip the script directory from sys.path() so on case-insensitive
+# (WIN32) systems Python doesn't think that the "scons" script is the
+# "SCons" package.  Replace it with our own library directories
+# (version-specific first, in case they installed by hand there,
+# followed by generic) so we pick up the right version of the build
+# engine modules if they're in either directory.
+
+script_dir = sys.path[0]
+
+if script_dir in sys.path:
+    sys.path.remove(script_dir)
+
+libs = []
+
+if os.environ.has_key("SCONS_LIB_DIR"):
+    libs.append(os.environ["SCONS_LIB_DIR"])
+
+local_version = 'scons-local-' + __version__
+local = 'scons-local'
+if script_dir:
+    local_version = os.path.join(script_dir, local_version)
+    local = os.path.join(script_dir, local)
+libs.append(os.path.abspath(local_version))
+libs.append(os.path.abspath(local))
+
+scons_version = 'scons-%s' % __version__
+
+prefs = []
+
+if sys.platform == 'win32':
+    # sys.prefix is (likely) C:\Python*;
+    # check only C:\Python*.
+    prefs.append(sys.prefix)
+    prefs.append(os.path.join(sys.prefix, 'Lib', 'site-packages'))
+else:
+    # On other (POSIX) platforms, things are more complicated due to
+    # the variety of path names and library locations.  Try to be smart
+    # about it.
+    if script_dir == 'bin':
+        # script_dir is `pwd`/bin;
+        # check `pwd`/lib/scons*.
+        prefs.append(os.getcwd())
+    else:
+        if script_dir == '.' or script_dir == '':
+            script_dir = os.getcwd()
+        head, tail = os.path.split(script_dir)
+        if tail == "bin":
+            # script_dir is /foo/bin;
+            # check /foo/lib/scons*.
+            prefs.append(head)
+
+    head, tail = os.path.split(sys.prefix)
+    if tail == "usr":
+        # sys.prefix is /foo/usr;
+        # check /foo/usr/lib/scons* first,
+        # then /foo/usr/local/lib/scons*.
+        prefs.append(sys.prefix)
+        prefs.append(os.path.join(sys.prefix, "local"))
+    elif tail == "local":
+        h, t = os.path.split(head)
+        if t == "usr":
+            # sys.prefix is /foo/usr/local;
+            # check /foo/usr/local/lib/scons* first,
+            # then /foo/usr/lib/scons*.
+            prefs.append(sys.prefix)
+            prefs.append(head)
+        else:
+            # sys.prefix is /foo/local;
+            # check only /foo/local/lib/scons*.
+            prefs.append(sys.prefix)
+    else:
+        # sys.prefix is /foo (ends in neither /usr or /local);
+        # check only /foo/lib/scons*.
+        prefs.append(sys.prefix)
+
+    temp = map(lambda x: os.path.join(x, 'lib'), prefs)
+    temp.extend(map(lambda x: os.path.join(x,
+                                           'lib',
+                                           'python' + sys.version[:3],
+                                           'site-packages'),
+                           prefs))
+    prefs = temp
+
+    # Add the parent directory of the current python's library to the
+    # preferences.  On SuSE-91/AMD64, for example, this is /usr/lib64,
+    # not /usr/lib.
+    try:
+        libpath = os.__file__
+    except AttributeError:
+        pass
+    else:
+        # Split /usr/libfoo/python*/os.py to /usr/libfoo/python*.
+        libpath, tail = os.path.split(libpath)
+        # Split /usr/libfoo/python* to /usr/libfoo
+        libpath, tail = os.path.split(libpath)
+        # Check /usr/libfoo/scons*.
+        prefs.append(libpath)
+
+# Look first for 'scons-__version__' in all of our preference libs,
+# then for 'scons'.
+libs.extend(map(lambda x: os.path.join(x, scons_version), prefs))
+libs.extend(map(lambda x: os.path.join(x, 'scons'), prefs))
+
+sys.path = libs + sys.path
+
+##############################################################################
+# END STANDARD SCons SCRIPT HEADER
+##############################################################################
+
+if __name__ == "__main__":
+    import SCons.Script
+    # this does all the work, and calls sys.exit
+    # with the proper exit status when done.
+    SCons.Script.main()
diff --git a/deps/v8/sconsign.py b/deps/v8/sconsign.py
new file mode 100755
index 0000000..a33b7b4
--- /dev/null
+++ b/deps/v8/sconsign.py
@@ -0,0 +1,502 @@
+#! /usr/bin/env python
+#
+# SCons - a Software Constructor
+#
+# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "src/script/sconsign.py 3842 2008/12/20 22:59:52 scons"
+
+__version__ = "1.2.0"
+
+__build__ = "r3842"
+
+__buildsys__ = "scons-dev"
+
+__date__ = "2008/12/20 22:59:52"
+
+__developer__ = "scons"
+
+import os
+import os.path
+import sys
+import time
+
+##############################################################################
+# BEGIN STANDARD SCons SCRIPT HEADER
+#
+# This is the cut-and-paste logic so that a self-contained script can
+# interoperate correctly with different SCons versions and installation
+# locations for the engine.  If you modify anything in this section, you
+# should also change other scripts that use this same header.
+##############################################################################
+
+# Strip the script directory from sys.path() so on case-insensitive
+# (WIN32) systems Python doesn't think that the "scons" script is the
+# "SCons" package.  Replace it with our own library directories
+# (version-specific first, in case they installed by hand there,
+# followed by generic) so we pick up the right version of the build
+# engine modules if they're in either directory.
+
+script_dir = sys.path[0]
+
+if script_dir in sys.path:
+    sys.path.remove(script_dir)
+
+libs = []
+
+if os.environ.has_key("SCONS_LIB_DIR"):
+    libs.append(os.environ["SCONS_LIB_DIR"])
+
+local_version = 'scons-local-' + __version__
+local = 'scons-local'
+if script_dir:
+    local_version = os.path.join(script_dir, local_version)
+    local = os.path.join(script_dir, local)
+libs.append(os.path.abspath(local_version))
+libs.append(os.path.abspath(local))
+
+scons_version = 'scons-%s' % __version__
+
+prefs = []
+
+if sys.platform == 'win32':
+    # sys.prefix is (likely) C:\Python*;
+    # check only C:\Python*.
+    prefs.append(sys.prefix)
+    prefs.append(os.path.join(sys.prefix, 'Lib', 'site-packages'))
+else:
+    # On other (POSIX) platforms, things are more complicated due to
+    # the variety of path names and library locations.  Try to be smart
+    # about it.
+    if script_dir == 'bin':
+        # script_dir is `pwd`/bin;
+        # check `pwd`/lib/scons*.
+        prefs.append(os.getcwd())
+    else:
+        if script_dir == '.' or script_dir == '':
+            script_dir = os.getcwd()
+        head, tail = os.path.split(script_dir)
+        if tail == "bin":
+            # script_dir is /foo/bin;
+            # check /foo/lib/scons*.
+            prefs.append(head)
+
+    head, tail = os.path.split(sys.prefix)
+    if tail == "usr":
+        # sys.prefix is /foo/usr;
+        # check /foo/usr/lib/scons* first,
+        # then /foo/usr/local/lib/scons*.
+        prefs.append(sys.prefix)
+        prefs.append(os.path.join(sys.prefix, "local"))
+    elif tail == "local":
+        h, t = os.path.split(head)
+        if t == "usr":
+            # sys.prefix is /foo/usr/local;
+            # check /foo/usr/local/lib/scons* first,
+            # then /foo/usr/lib/scons*.
+            prefs.append(sys.prefix)
+            prefs.append(head)
+        else:
+            # sys.prefix is /foo/local;
+            # check only /foo/local/lib/scons*.
+            prefs.append(sys.prefix)
+    else:
+        # sys.prefix is /foo (ends in neither /usr or /local);
+        # check only /foo/lib/scons*.
+        prefs.append(sys.prefix)
+
+    temp = map(lambda x: os.path.join(x, 'lib'), prefs)
+    temp.extend(map(lambda x: os.path.join(x,
+                                           'lib',
+                                           'python' + sys.version[:3],
+                                           'site-packages'),
+                           prefs))
+    prefs = temp
+
+    # Add the parent directory of the current python's library to the
+    # preferences.  On SuSE-91/AMD64, for example, this is /usr/lib64,
+    # not /usr/lib.
+    try:
+        libpath = os.__file__
+    except AttributeError:
+        pass
+    else:
+        # Split /usr/libfoo/python*/os.py to /usr/libfoo/python*.
+        libpath, tail = os.path.split(libpath)
+        # Split /usr/libfoo/python* to /usr/libfoo
+        libpath, tail = os.path.split(libpath)
+        # Check /usr/libfoo/scons*.
+        prefs.append(libpath)
+
+# Look first for 'scons-__version__' in all of our preference libs,
+# then for 'scons'.
+libs.extend(map(lambda x: os.path.join(x, scons_version), prefs))
+libs.extend(map(lambda x: os.path.join(x, 'scons'), prefs))
+
+sys.path = libs + sys.path
+
+##############################################################################
+# END STANDARD SCons SCRIPT HEADER
+##############################################################################
+
+import cPickle
+import imp
+import string
+import whichdb
+
+import SCons.SConsign
+
+def my_whichdb(filename):
+    if filename[-7:] == ".dblite":
+        return "SCons.dblite"
+    try:
+        f = open(filename + ".dblite", "rb")
+        f.close()
+        return "SCons.dblite"
+    except IOError:
+        pass
+    return _orig_whichdb(filename)
+
+_orig_whichdb = whichdb.whichdb
+whichdb.whichdb = my_whichdb
+
+def my_import(mname):
+    if '.' in mname:
+        i = string.rfind(mname, '.')
+        parent = my_import(mname[:i])
+        fp, pathname, description = imp.find_module(mname[i+1:],
+                                                    parent.__path__)
+    else:
+        fp, pathname, description = imp.find_module(mname)
+    return imp.load_module(mname, fp, pathname, description)
+
+class Flagger:
+    default_value = 1
+    def __setitem__(self, item, value):
+        self.__dict__[item] = value
+        self.default_value = 0
+    def __getitem__(self, item):
+        return self.__dict__.get(item, self.default_value)
+
+Do_Call = None
+Print_Directories = []
+Print_Entries = []
+Print_Flags = Flagger()
+Verbose = 0
+Readable = 0
+
+def default_mapper(entry, name):
+    try:
+        val = eval("entry."+name)
+    except:
+        val = None
+    return str(val)
+
+def map_action(entry, name):
+    try:
+        bact = entry.bact
+        bactsig = entry.bactsig
+    except AttributeError:
+        return None
+    return '%s [%s]' % (bactsig, bact)
+
+def map_timestamp(entry, name):
+    try:
+        timestamp = entry.timestamp
+    except AttributeError:
+        timestamp = None
+    if Readable and timestamp:
+        return "'" + time.ctime(timestamp) + "'"
+    else:
+        return str(timestamp)
+
+def map_bkids(entry, name):
+    try:
+        bkids = entry.bsources + entry.bdepends + entry.bimplicit
+        bkidsigs = entry.bsourcesigs + entry.bdependsigs + entry.bimplicitsigs
+    except AttributeError:
+        return None
+    result = []
+    for i in xrange(len(bkids)):
+        result.append(nodeinfo_string(bkids[i], bkidsigs[i], "        "))
+    if result == []:
+        return None
+    return string.join(result, "\n        ")
+
+map_field = {
+    'action'    : map_action,
+    'timestamp' : map_timestamp,
+    'bkids'     : map_bkids,
+}
+
+map_name = {
+    'implicit'  : 'bkids',
+}
+
+def field(name, entry, verbose=Verbose):
+    if not Print_Flags[name]:
+        return None
+    fieldname = map_name.get(name, name)
+    mapper = map_field.get(fieldname, default_mapper)
+    val = mapper(entry, name)
+    if verbose:
+        val = name + ": " + val
+    return val
+
+def nodeinfo_raw(name, ninfo, prefix=""):
+    # This just formats the dictionary, which we would normally use str()
+    # to do, except that we want the keys sorted for deterministic output.
+    d = ninfo.__dict__
+    try:
+        keys = ninfo.field_list + ['_version_id']
+    except AttributeError:
+        keys = d.keys()
+        keys.sort()
+    l = []
+    for k in keys:
+        l.append('%s: %s' % (repr(k), repr(d.get(k))))
+    if '\n' in name:
+        name = repr(name)
+    return name + ': {' + string.join(l, ', ') + '}'
+
+def nodeinfo_cooked(name, ninfo, prefix=""):
+    try:
+        field_list = ninfo.field_list
+    except AttributeError:
+        field_list = []
+    f = lambda x, ni=ninfo, v=Verbose: field(x, ni, v)
+    if '\n' in name:
+        name = repr(name)
+    outlist = [name+':'] + filter(None, map(f, field_list))
+    if Verbose:
+        sep = '\n    ' + prefix
+    else:
+        sep = ' '
+    return string.join(outlist, sep)
+
+nodeinfo_string = nodeinfo_cooked
+
+def printfield(name, entry, prefix=""):
+    outlist = field("implicit", entry, 0)
+    if outlist:
+        if Verbose:
+            print "    implicit:"
+        print "        " + outlist
+    outact = field("action", entry, 0)
+    if outact:
+        if Verbose:
+            print "    action: " + outact
+        else:
+            print "        " + outact
+
+def printentries(entries, location):
+    if Print_Entries:
+        for name in Print_Entries:
+            try:
+                entry = entries[name]
+            except KeyError:
+                sys.stderr.write("sconsign: no entry `%s' in `%s'\n" % (name, location))
+            else:
+                try:
+                    ninfo = entry.ninfo
+                except AttributeError:
+                    print name + ":"
+                else:
+                    print nodeinfo_string(name, entry.ninfo)
+                printfield(name, entry.binfo)
+    else:
+        names = entries.keys()
+        names.sort()
+        for name in names:
+            entry = entries[name]
+            try:
+                ninfo = entry.ninfo
+            except AttributeError:
+                print name + ":"
+            else:
+                print nodeinfo_string(name, entry.ninfo)
+            printfield(name, entry.binfo)
+
+class Do_SConsignDB:
+    def __init__(self, dbm_name, dbm):
+        self.dbm_name = dbm_name
+        self.dbm = dbm
+
+    def __call__(self, fname):
+        # The *dbm modules stick their own file suffixes on the names
+        # that are passed in.  This is causes us to jump through some
+        # hoops here to be able to allow the user
+        try:
+            # Try opening the specified file name.  Example:
+            #   SPECIFIED                  OPENED BY self.dbm.open()
+            #   ---------                  -------------------------
+            #   .sconsign               => .sconsign.dblite
+            #   .sconsign.dblite        => .sconsign.dblite.dblite
+            db = self.dbm.open(fname, "r")
+        except (IOError, OSError), e:
+            print_e = e
+            try:
+                # That didn't work, so try opening the base name,
+                # so that if the actually passed in 'sconsign.dblite'
+                # (for example), the dbm module will put the suffix back
+                # on for us and open it anyway.
+                db = self.dbm.open(os.path.splitext(fname)[0], "r")
+            except (IOError, OSError):
+                # That didn't work either.  See if the file name
+                # they specified just exists (independent of the dbm
+                # suffix-mangling).
+                try:
+                    open(fname, "r")
+                except (IOError, OSError), e:
+                    # Nope, that file doesn't even exist, so report that
+                    # fact back.
+                    print_e = e
+                sys.stderr.write("sconsign: %s\n" % (print_e))
+                return
+        except KeyboardInterrupt:
+            raise
+        except cPickle.UnpicklingError:
+            sys.stderr.write("sconsign: ignoring invalid `%s' file `%s'\n" % (self.dbm_name, fname))
+            return
+        except Exception, e:
+            sys.stderr.write("sconsign: ignoring invalid `%s' file `%s': %s\n" % (self.dbm_name, fname, e))
+            return
+
+        if Print_Directories:
+            for dir in Print_Directories:
+                try:
+                    val = db[dir]
+                except KeyError:
+                    sys.stderr.write("sconsign: no dir `%s' in `%s'\n" % (dir, args[0]))
+                else:
+                    self.printentries(dir, val)
+        else:
+            keys = db.keys()
+            keys.sort()
+            for dir in keys:
+                self.printentries(dir, db[dir])
+
+    def printentries(self, dir, val):
+        print '=== ' + dir + ':'
+        printentries(cPickle.loads(val), dir)
+
+def Do_SConsignDir(name):
+    try:
+        fp = open(name, 'rb')
+    except (IOError, OSError), e:
+        sys.stderr.write("sconsign: %s\n" % (e))
+        return
+    try:
+        sconsign = SCons.SConsign.Dir(fp)
+    except KeyboardInterrupt:
+        raise
+    except cPickle.UnpicklingError:
+        sys.stderr.write("sconsign: ignoring invalid .sconsign file `%s'\n" % (name))
+        return
+    except Exception, e:
+        sys.stderr.write("sconsign: ignoring invalid .sconsign file `%s': %s\n" % (name, e))
+        return
+    printentries(sconsign.entries, args[0])
+
+##############################################################################
+
+import getopt
+
+helpstr = """\
+Usage: sconsign [OPTIONS] FILE [...]
+Options:
+  -a, --act, --action         Print build action information.
+  -c, --csig                  Print content signature information.
+  -d DIR, --dir=DIR           Print only info about DIR.
+  -e ENTRY, --entry=ENTRY     Print only info about ENTRY.
+  -f FORMAT, --format=FORMAT  FILE is in the specified FORMAT.
+  -h, --help                  Print this message and exit.
+  -i, --implicit              Print implicit dependency information.
+  -r, --readable              Print timestamps in human-readable form.
+  --raw                       Print raw Python object representations.
+  -s, --size                  Print file sizes.
+  -t, --timestamp             Print timestamp information.
+  -v, --verbose               Verbose, describe each field.
+"""
+
+opts, args = getopt.getopt(sys.argv[1:], "acd:e:f:hirstv",
+                            ['act', 'action',
+                             'csig', 'dir=', 'entry=',
+                             'format=', 'help', 'implicit',
+                             'raw', 'readable',
+                             'size', 'timestamp', 'verbose'])
+
+
+for o, a in opts:
+    if o in ('-a', '--act', '--action'):
+        Print_Flags['action'] = 1
+    elif o in ('-c', '--csig'):
+        Print_Flags['csig'] = 1
+    elif o in ('-d', '--dir'):
+        Print_Directories.append(a)
+    elif o in ('-e', '--entry'):
+        Print_Entries.append(a)
+    elif o in ('-f', '--format'):
+        Module_Map = {'dblite'   : 'SCons.dblite',
+                      'sconsign' : None}
+        dbm_name = Module_Map.get(a, a)
+        if dbm_name:
+            try:
+                dbm = my_import(dbm_name)
+            except:
+                sys.stderr.write("sconsign: illegal file format `%s'\n" % a)
+                print helpstr
+                sys.exit(2)
+            Do_Call = Do_SConsignDB(a, dbm)
+        else:
+            Do_Call = Do_SConsignDir
+    elif o in ('-h', '--help'):
+        print helpstr
+        sys.exit(0)
+    elif o in ('-i', '--implicit'):
+        Print_Flags['implicit'] = 1
+    elif o in ('--raw',):
+        nodeinfo_string = nodeinfo_raw
+    elif o in ('-r', '--readable'):
+        Readable = 1
+    elif o in ('-s', '--size'):
+        Print_Flags['size'] = 1
+    elif o in ('-t', '--timestamp'):
+        Print_Flags['timestamp'] = 1
+    elif o in ('-v', '--verbose'):
+        Verbose = 1
+
+if Do_Call:
+    for a in args:
+        Do_Call(a)
+else:
+    for a in args:
+        dbm_name = whichdb.whichdb(a)
+        if dbm_name:
+            Map_Module = {'SCons.dblite' : 'dblite'}
+            dbm = my_import(dbm_name)
+            Do_SConsignDB(Map_Module.get(dbm_name, dbm_name), dbm)(a)
+        else:
+            Do_SConsignDir(a)
+
+sys.exit(0)
diff --git a/deps/v8/src/SConscript b/deps/v8/src/SConscript
new file mode 100644
index 0000000..97fb7d6
--- /dev/null
+++ b/deps/v8/src/SConscript
@@ -0,0 +1,183 @@
+# Copyright 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.
+
+import sys
+from os.path import join, dirname, abspath
+root_dir = dirname(File('SConstruct').rfile().abspath)
+sys.path.append(join(root_dir, 'tools'))
+import js2c
+Import('context')
+
+
+SOURCES = {
+  'all': [
+    'accessors.cc', 'allocation.cc', 'api.cc', 'assembler.cc', 'ast.cc',
+    'bootstrapper.cc', 'builtins.cc', 'checks.cc', 'code-stubs.cc',
+    'codegen.cc', 'compilation-cache.cc', 'compiler.cc', 'contexts.cc',
+    'conversions.cc', 'counters.cc', 'dateparser.cc', 'debug.cc',
+    'debug-agent.cc', 'disassembler.cc', 'execution.cc', 'factory.cc',
+    'flags.cc', 'frames.cc', 'func-name-inferrer.cc',
+    'global-handles.cc', 'handles.cc', 'hashmap.cc',
+    'heap.cc', 'ic.cc', 'interpreter-irregexp.cc', 'jsregexp.cc',
+    'jump-target.cc', 'log.cc', 'mark-compact.cc', 'messages.cc', 'objects.cc',
+    'oprofile-agent.cc', 'parser.cc', 'property.cc', 'regexp-macro-assembler.cc',
+    'regexp-macro-assembler-irregexp.cc', 'regexp-stack.cc',
+    'register-allocator.cc', 'rewriter.cc', 'runtime.cc', 'scanner.cc',
+    'scopeinfo.cc', 'scopes.cc', 'serialize.cc', 'snapshot-common.cc',
+    'spaces.cc', 'string-stream.cc', 'stub-cache.cc', 'token.cc', 'top.cc',
+    'unicode.cc', 'usage-analyzer.cc', 'utils.cc', 'v8-counters.cc',
+    'v8.cc', 'v8threads.cc', 'variables.cc', 'virtual-frame.cc', 'zone.cc'
+  ],
+  'arch:arm': [
+    'assembler-arm.cc', 'builtins-arm.cc', 'codegen-arm.cc', 'cpu-arm.cc',
+    'disasm-arm.cc', 'debug-arm.cc', 'frames-arm.cc', 'ic-arm.cc',
+    'jump-target-arm.cc', 'macro-assembler-arm.cc',
+    'regexp-macro-assembler-arm.cc', 'register-allocator-arm.cc',
+    'stub-cache-arm.cc', 'virtual-frame-arm.cc'
+  ],
+  'arch:ia32': [
+    'assembler-ia32.cc', 'builtins-ia32.cc', 'codegen-ia32.cc',
+    'cpu-ia32.cc', 'disasm-ia32.cc', 'debug-ia32.cc', 'frames-ia32.cc',
+    'ic-ia32.cc', 'jump-target-ia32.cc', 'macro-assembler-ia32.cc',
+    'regexp-macro-assembler-ia32.cc', 'register-allocator-ia32.cc',
+    'stub-cache-ia32.cc', 'virtual-frame-ia32.cc'
+  ],
+  'simulator:arm': ['simulator-arm.cc'],
+  'os:freebsd': ['platform-freebsd.cc', 'platform-posix.cc'],
+  'os:linux':   ['platform-linux.cc', 'platform-posix.cc'],
+  'os:android': ['platform-linux.cc', 'platform-posix.cc'],
+  'os:macos':   ['platform-macos.cc', 'platform-posix.cc'],
+  'os:nullos':  ['platform-nullos.cc'],
+  'os:win32':   ['platform-win32.cc'],
+  'mode:release': [],
+  'mode:debug': [
+    'objects-debug.cc', 'prettyprinter.cc', 'regexp-macro-assembler-tracer.cc'
+  ]
+}
+
+
+D8_FILES = {
+  'all': [
+    'd8.cc', 'd8-debug.cc'
+  ],
+  'os:linux': [
+    'd8-posix.cc'
+  ],
+  'os:macos': [
+    'd8-posix.cc'
+  ],
+  'os:android': [
+    'd8-posix.cc'
+  ],
+  'os:freebsd': [
+    'd8-posix.cc'
+  ],
+  'os:win32': [
+    'd8-windows.cc'
+  ],
+  'os:nullos': [
+    'd8-windows.cc'   # Empty implementation at the moment.
+  ],
+  'console:readline': [
+    'd8-readline.cc'
+  ]
+}
+
+
+LIBRARY_FILES = '''
+runtime.js
+v8natives.js
+array.js
+string.js
+uri.js
+math.js
+messages.js
+apinatives.js
+debug-delay.js
+mirror-delay.js
+date-delay.js
+regexp-delay.js
+'''.split()
+
+
+def Abort(message):
+  print message
+  sys.exit(1)
+
+
+def ConfigureObjectFiles():
+  env = Environment()
+  env.Replace(**context.flags['v8'])
+  context.ApplyEnvOverrides(env)
+  env['BUILDERS']['JS2C'] = Builder(action=js2c.JS2C)
+  env['BUILDERS']['Snapshot'] = Builder(action='$SOURCE $TARGET --logfile "$LOGFILE"')
+
+  # Build the standard platform-independent source files.
+  source_files = context.GetRelevantSources(SOURCES)
+
+  d8_files = context.GetRelevantSources(D8_FILES)
+  d8_js = env.JS2C('d8-js.cc', 'd8.js', TYPE='D8')
+  d8_js_obj = context.ConfigureObject(env, d8_js, CPPPATH=['.'])
+  d8_objs = [context.ConfigureObject(env, [d8_files]), d8_js_obj]
+
+  # Combine the JavaScript library files into a single C++ file and
+  # compile it.
+  library_files = [s for s in LIBRARY_FILES]
+  library_files.append('macros.py')
+  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]
+
+  # Create snapshot if necessary.
+  empty_snapshot_obj = context.ConfigureObject(env, 'snapshot-empty.cc')
+  mksnapshot_env = env.Copy()
+  mksnapshot_env.Replace(**context.flags['mksnapshot'])
+  mksnapshot_src = 'mksnapshot.cc'
+  mksnapshot = mksnapshot_env.Program('mksnapshot', [mksnapshot_src, libraries_obj, non_snapshot_files, empty_snapshot_obj], PDB='mksnapshot.exe.pdb')
+  if context.use_snapshot:
+    if context.build_snapshot:
+      snapshot_cc = env.Snapshot('snapshot.cc', mksnapshot, LOGFILE=File('snapshot.log').abspath)
+    else:
+      snapshot_cc = Command('snapshot.cc', [], [])
+    snapshot_obj = context.ConfigureObject(env, snapshot_cc, CPPPATH=['.'])
+    libraries_obj = context.ConfigureObject(env, libraries_empty_src, CPPPATH=['.'])
+  else:
+    snapshot_obj = empty_snapshot_obj
+  library_objs = [non_snapshot_files, libraries_obj, snapshot_obj]
+  return (library_objs, d8_objs, [mksnapshot])
+
+
+(library_objs, d8_objs, mksnapshot) = ConfigureObjectFiles()
+Return('library_objs d8_objs mksnapshot')
diff --git a/deps/v8/src/accessors.cc b/deps/v8/src/accessors.cc
new file mode 100644
index 0000000..d779eb2
--- /dev/null
+++ b/deps/v8/src/accessors.cc
@@ -0,0 +1,548 @@
+// 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.
+
+#include "v8.h"
+
+#include "accessors.h"
+#include "execution.h"
+#include "factory.h"
+#include "scopeinfo.h"
+#include "top.h"
+#include "zone-inl.h"
+
+namespace v8 { namespace internal {
+
+
+template <class C>
+static C* FindInPrototypeChain(Object* obj, bool* found_it) {
+  ASSERT(!*found_it);
+  while (!Is<C>(obj)) {
+    if (obj == Heap::null_value()) return NULL;
+    obj = obj->GetPrototype();
+  }
+  *found_it = true;
+  return C::cast(obj);
+}
+
+
+// Entry point that never should be called.
+Object* Accessors::IllegalSetter(JSObject*, Object*, void*) {
+  UNREACHABLE();
+  return NULL;
+}
+
+
+Object* Accessors::IllegalGetAccessor(Object* object, void*) {
+  UNREACHABLE();
+  return object;
+}
+
+
+Object* Accessors::ReadOnlySetAccessor(JSObject*, Object* value, void*) {
+  // According to ECMA-262, section 8.6.2.2, page 28, setting
+  // read-only properties must be silently ignored.
+  return value;
+}
+
+
+//
+// Accessors::ArrayLength
+//
+
+
+Object* Accessors::ArrayGetLength(Object* object, void*) {
+  // Traverse the prototype chain until we reach an array.
+  bool found_it = false;
+  JSArray* holder = FindInPrototypeChain<JSArray>(object, &found_it);
+  if (!found_it) return Smi::FromInt(0);
+  return holder->length();
+}
+
+
+// The helper function will 'flatten' Number objects.
+Object* Accessors::FlattenNumber(Object* value) {
+  if (value->IsNumber() || !value->IsJSValue()) return value;
+  JSValue* wrapper = JSValue::cast(value);
+  ASSERT(
+      Top::context()->global_context()->number_function()->has_initial_map());
+  Map* number_map =
+      Top::context()->global_context()->number_function()->initial_map();
+  if (wrapper->map() == number_map) return wrapper->value();
+  return value;
+}
+
+
+Object* Accessors::ArraySetLength(JSObject* object, Object* value, void*) {
+  value = FlattenNumber(value);
+
+  // Need to call methods that may trigger GC.
+  HandleScope scope;
+
+  // Protect raw pointers.
+  Handle<JSObject> object_handle(object);
+  Handle<Object> value_handle(value);
+
+  bool has_exception;
+  Handle<Object> uint32_v = Execution::ToUint32(value_handle, &has_exception);
+  if (has_exception) return Failure::Exception();
+  Handle<Object> number_v = Execution::ToNumber(value_handle, &has_exception);
+  if (has_exception) return Failure::Exception();
+
+  // Restore raw pointers,
+  object = *object_handle;
+  value = *value_handle;
+
+  if (uint32_v->Number() == number_v->Number()) {
+    if (object->IsJSArray()) {
+      return JSArray::cast(object)->SetElementsLength(*uint32_v);
+    } else {
+      // This means one of the object's prototypes is a JSArray and
+      // the object does not have a 'length' property.
+      // Calling SetProperty causes an infinite loop.
+      return object->IgnoreAttributesAndSetLocalProperty(Heap::length_symbol(),
+                                                         value, NONE);
+    }
+  }
+  return Top::Throw(*Factory::NewRangeError("invalid_array_length",
+                                            HandleVector<Object>(NULL, 0)));
+}
+
+
+const AccessorDescriptor Accessors::ArrayLength = {
+  ArrayGetLength,
+  ArraySetLength,
+  0
+};
+
+
+//
+// Accessors::StringLength
+//
+
+
+Object* Accessors::StringGetLength(Object* object, void*) {
+  Object* value = object;
+  if (object->IsJSValue()) value = JSValue::cast(object)->value();
+  if (value->IsString()) return Smi::FromInt(String::cast(value)->length());
+  // If object is not a string we return 0 to be compatible with WebKit.
+  // Note: Firefox returns the length of ToString(object).
+  return Smi::FromInt(0);
+}
+
+
+const AccessorDescriptor Accessors::StringLength = {
+  StringGetLength,
+  IllegalSetter,
+  0
+};
+
+
+//
+// Accessors::ScriptSource
+//
+
+
+Object* Accessors::ScriptGetSource(Object* object, void*) {
+  Object* script = JSValue::cast(object)->value();
+  return Script::cast(script)->source();
+}
+
+
+const AccessorDescriptor Accessors::ScriptSource = {
+  ScriptGetSource,
+  IllegalSetter,
+  0
+};
+
+
+//
+// Accessors::ScriptName
+//
+
+
+Object* Accessors::ScriptGetName(Object* object, void*) {
+  Object* script = JSValue::cast(object)->value();
+  return Script::cast(script)->name();
+}
+
+
+const AccessorDescriptor Accessors::ScriptName = {
+  ScriptGetName,
+  IllegalSetter,
+  0
+};
+
+
+//
+// Accessors::ScriptId
+//
+
+
+Object* Accessors::ScriptGetId(Object* object, void*) {
+  Object* script = JSValue::cast(object)->value();
+  return Script::cast(script)->id();
+}
+
+
+const AccessorDescriptor Accessors::ScriptId = {
+  ScriptGetId,
+  IllegalSetter,
+  0
+};
+
+
+//
+// Accessors::ScriptLineOffset
+//
+
+
+Object* Accessors::ScriptGetLineOffset(Object* object, void*) {
+  Object* script = JSValue::cast(object)->value();
+  return Script::cast(script)->line_offset();
+}
+
+
+const AccessorDescriptor Accessors::ScriptLineOffset = {
+  ScriptGetLineOffset,
+  IllegalSetter,
+  0
+};
+
+
+//
+// Accessors::ScriptColumnOffset
+//
+
+
+Object* Accessors::ScriptGetColumnOffset(Object* object, void*) {
+  Object* script = JSValue::cast(object)->value();
+  return Script::cast(script)->column_offset();
+}
+
+
+const AccessorDescriptor Accessors::ScriptColumnOffset = {
+  ScriptGetColumnOffset,
+  IllegalSetter,
+  0
+};
+
+
+//
+// Accessors::ScriptType
+//
+
+
+Object* Accessors::ScriptGetType(Object* object, void*) {
+  Object* script = JSValue::cast(object)->value();
+  return Script::cast(script)->type();
+}
+
+
+const AccessorDescriptor Accessors::ScriptType = {
+  ScriptGetType,
+  IllegalSetter,
+  0
+};
+
+
+//
+// Accessors::ScriptGetLineEnds
+//
+
+
+Object* Accessors::ScriptGetLineEnds(Object* object, void*) {
+  HandleScope scope;
+  Handle<Script> script(Script::cast(JSValue::cast(object)->value()));
+  InitScriptLineEnds(script);
+  return script->line_ends();
+}
+
+
+const AccessorDescriptor Accessors::ScriptLineEnds = {
+  ScriptGetLineEnds,
+  IllegalSetter,
+  0
+};
+
+
+//
+// Accessors::FunctionPrototype
+//
+
+
+Object* Accessors::FunctionGetPrototype(Object* object, void*) {
+  bool found_it = false;
+  JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it);
+  if (!found_it) return Heap::undefined_value();
+  if (!function->has_prototype()) {
+    Object* prototype = Heap::AllocateFunctionPrototype(function);
+    if (prototype->IsFailure()) return prototype;
+    Object* result = function->SetPrototype(prototype);
+    if (result->IsFailure()) return result;
+  }
+  return function->prototype();
+}
+
+
+Object* Accessors::FunctionSetPrototype(JSObject* object,
+                                        Object* value,
+                                        void*) {
+  bool found_it = false;
+  JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it);
+  if (!found_it) return Heap::undefined_value();
+  if (function->has_initial_map()) {
+    // If the function has allocated the initial map
+    // replace it with a copy containing the new prototype.
+    Object* new_map = function->initial_map()->CopyDropTransitions();
+    if (new_map->IsFailure()) return new_map;
+    function->set_initial_map(Map::cast(new_map));
+  }
+  Object* prototype = function->SetPrototype(value);
+  if (prototype->IsFailure()) return prototype;
+  ASSERT(function->prototype() == value);
+  return function;
+}
+
+
+const AccessorDescriptor Accessors::FunctionPrototype = {
+  FunctionGetPrototype,
+  FunctionSetPrototype,
+  0
+};
+
+
+//
+// Accessors::FunctionLength
+//
+
+
+Object* Accessors::FunctionGetLength(Object* object, void*) {
+  bool found_it = false;
+  JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it);
+  if (!found_it) return Smi::FromInt(0);
+  // Check if already compiled.
+  if (!function->is_compiled()) {
+    // If the function isn't compiled yet, the length is not computed
+    // correctly yet. Compile it now and return the right length.
+    HandleScope scope;
+    Handle<JSFunction> function_handle(function);
+    if (!CompileLazy(function_handle, KEEP_EXCEPTION)) {
+      return Failure::Exception();
+    }
+    return Smi::FromInt(function_handle->shared()->length());
+  } else {
+    return Smi::FromInt(function->shared()->length());
+  }
+}
+
+
+const AccessorDescriptor Accessors::FunctionLength = {
+  FunctionGetLength,
+  ReadOnlySetAccessor,
+  0
+};
+
+
+//
+// Accessors::FunctionName
+//
+
+
+Object* Accessors::FunctionGetName(Object* object, void*) {
+  bool found_it = false;
+  JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it);
+  if (!found_it) return Heap::undefined_value();
+  return holder->shared()->name();
+}
+
+
+const AccessorDescriptor Accessors::FunctionName = {
+  FunctionGetName,
+  ReadOnlySetAccessor,
+  0
+};
+
+
+//
+// Accessors::FunctionArguments
+//
+
+
+Object* Accessors::FunctionGetArguments(Object* object, void*) {
+  HandleScope scope;
+  bool found_it = false;
+  JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it);
+  if (!found_it) return Heap::undefined_value();
+  Handle<JSFunction> function(holder);
+
+  // Find the top invocation of the function by traversing frames.
+  for (JavaScriptFrameIterator it; !it.done(); it.Advance()) {
+    // Skip all frames that aren't invocations of the given function.
+    JavaScriptFrame* frame = it.frame();
+    if (frame->function() != *function) continue;
+
+    // If there is an arguments variable in the stack, we return that.
+    int index = ScopeInfo<>::StackSlotIndex(frame->code(),
+                                            Heap::arguments_symbol());
+    if (index >= 0) return frame->GetExpression(index);
+
+    // If there isn't an arguments variable in the stack, we need to
+    // find the frame that holds the actual arguments passed to the
+    // function on the stack.
+    it.AdvanceToArgumentsFrame();
+    frame = it.frame();
+
+    // Get the number of arguments and construct an arguments object
+    // mirror for the right frame.
+    const int length = frame->GetProvidedParametersCount();
+    Handle<JSObject> arguments = Factory::NewArgumentsObject(function, length);
+    Handle<FixedArray> array = Factory::NewFixedArray(length);
+
+    // Copy the parameters to the arguments object.
+    ASSERT(array->length() == length);
+    for (int i = 0; i < length; i++) array->set(i, frame->GetParameter(i));
+    arguments->set_elements(*array);
+
+    // Return the freshly allocated arguments object.
+    return *arguments;
+  }
+
+  // No frame corresponding to the given function found. Return null.
+  return Heap::null_value();
+}
+
+
+const AccessorDescriptor Accessors::FunctionArguments = {
+  FunctionGetArguments,
+  ReadOnlySetAccessor,
+  0
+};
+
+
+//
+// Accessors::FunctionCaller
+//
+
+
+Object* Accessors::FunctionGetCaller(Object* object, void*) {
+  HandleScope scope;
+  bool found_it = false;
+  JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it);
+  if (!found_it) return Heap::undefined_value();
+  Handle<JSFunction> function(holder);
+
+  // Find the top invocation of the function by traversing frames.
+  for (JavaScriptFrameIterator it; !it.done(); it.Advance()) {
+    // Skip all frames that aren't invocations of the given function.
+    if (it.frame()->function() != *function) continue;
+    // Once we have found the frame, we need to go to the caller
+    // frame. This may require skipping through a number of top-level
+    // frames, e.g. frames for scripts not functions.
+    while (true) {
+      it.Advance();
+      if (it.done()) return Heap::null_value();
+      JSFunction* caller = JSFunction::cast(it.frame()->function());
+      if (!caller->shared()->is_toplevel()) return caller;
+    }
+  }
+
+  // No frame corresponding to the given function found. Return null.
+  return Heap::null_value();
+}
+
+
+const AccessorDescriptor Accessors::FunctionCaller = {
+  FunctionGetCaller,
+  ReadOnlySetAccessor,
+  0
+};
+
+
+//
+// Accessors::ObjectPrototype
+//
+
+
+Object* Accessors::ObjectGetPrototype(Object* receiver, void*) {
+  Object* current = receiver->GetPrototype();
+  while (current->IsJSObject() &&
+         JSObject::cast(current)->map()->is_hidden_prototype()) {
+    current = current->GetPrototype();
+  }
+  return current;
+}
+
+
+Object* Accessors::ObjectSetPrototype(JSObject* receiver,
+                                      Object* value,
+                                      void*) {
+  // Before we can set the prototype we need to be sure
+  // prototype cycles are prevented.
+  // It is sufficient to validate that the receiver is not in the new prototype
+  // chain.
+
+  // Silently ignore the change if value is not a JSObject or null.
+  // SpiderMonkey behaves this way.
+  if (!value->IsJSObject() && !value->IsNull()) return value;
+
+  for (Object* pt = value; pt != Heap::null_value(); pt = pt->GetPrototype()) {
+    if (JSObject::cast(pt) == receiver) {
+      // Cycle detected.
+      HandleScope scope;
+      return Top::Throw(*Factory::NewError("cyclic_proto",
+                                           HandleVector<Object>(NULL, 0)));
+    }
+  }
+
+  // Find the first object in the chain whose prototype object is not
+  // hidden and set the new prototype on that object.
+  JSObject* current = receiver;
+  Object* current_proto = receiver->GetPrototype();
+  while (current_proto->IsJSObject() &&
+         JSObject::cast(current_proto)->map()->is_hidden_prototype()) {
+    current = JSObject::cast(current_proto);
+    current_proto = current_proto->GetPrototype();
+  }
+
+  // Set the new prototype of the object.
+  Object* new_map = current->map()->CopyDropTransitions();
+  if (new_map->IsFailure()) return new_map;
+  Map::cast(new_map)->set_prototype(value);
+  current->set_map(Map::cast(new_map));
+
+  // To be consistent with other Set functions, return the value.
+  return value;
+}
+
+
+const AccessorDescriptor Accessors::ObjectPrototype = {
+  ObjectGetPrototype,
+  ObjectSetPrototype,
+  0
+};
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/accessors.h b/deps/v8/src/accessors.h
new file mode 100644
index 0000000..938b014
--- /dev/null
+++ b/deps/v8/src/accessors.h
@@ -0,0 +1,101 @@
+// 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_ACCESSORS_H_
+#define V8_ACCESSORS_H_
+
+namespace v8 { namespace internal {
+
+// The list of accessor descriptors. This is a second-order macro
+// taking a macro to be applied to all accessor descriptor names.
+#define ACCESSOR_DESCRIPTOR_LIST(V) \
+  V(FunctionPrototype)   \
+  V(FunctionLength)      \
+  V(FunctionName)        \
+  V(FunctionArguments)   \
+  V(FunctionCaller)      \
+  V(ArrayLength)         \
+  V(StringLength)        \
+  V(ScriptSource)        \
+  V(ScriptName)          \
+  V(ScriptId)            \
+  V(ScriptLineOffset)    \
+  V(ScriptColumnOffset)  \
+  V(ScriptType)          \
+  V(ScriptLineEnds)      \
+  V(ObjectPrototype)
+
+// Accessors contains all predefined proxy accessors.
+
+class Accessors : public AllStatic {
+ public:
+  // Accessor descriptors.
+#define ACCESSOR_DESCRIPTOR_DECLARATION(name) \
+  static const AccessorDescriptor name;
+  ACCESSOR_DESCRIPTOR_LIST(ACCESSOR_DESCRIPTOR_DECLARATION)
+#undef ACCESSOR_DESCRIPTOR_DECLARATION
+
+  enum DescriptorId {
+#define ACCESSOR_DESCRIPTOR_DECLARATION(name) \
+    k##name,
+  ACCESSOR_DESCRIPTOR_LIST(ACCESSOR_DESCRIPTOR_DECLARATION)
+#undef ACCESSOR_DESCRIPTOR_DECLARATION
+    descriptorCount
+  };
+
+  // Accessor functions called directly from the runtime system.
+  static Object* FunctionGetPrototype(Object* object, void*);
+  static Object* FunctionSetPrototype(JSObject* object, Object* value, void*);
+ private:
+  // Accessor functions only used through the descriptor.
+  static Object* FunctionGetLength(Object* object, void*);
+  static Object* FunctionGetName(Object* object, void*);
+  static Object* FunctionGetArguments(Object* object, void*);
+  static Object* FunctionGetCaller(Object* object, void*);
+  static Object* ArraySetLength(JSObject* object, Object* value, void*);
+  static Object* ArrayGetLength(Object* object, void*);
+  static Object* StringGetLength(Object* object, void*);
+  static Object* ScriptGetName(Object* object, void*);
+  static Object* ScriptGetId(Object* object, void*);
+  static Object* ScriptGetSource(Object* object, void*);
+  static Object* ScriptGetLineOffset(Object* object, void*);
+  static Object* ScriptGetColumnOffset(Object* object, void*);
+  static Object* ScriptGetType(Object* object, void*);
+  static Object* ScriptGetLineEnds(Object* object, void*);
+  static Object* ObjectGetPrototype(Object* receiver, void*);
+  static Object* ObjectSetPrototype(JSObject* receiver, Object* value, void*);
+
+  // Helper functions.
+  static Object* FlattenNumber(Object* value);
+  static Object* IllegalSetter(JSObject*, Object*, void*);
+  static Object* IllegalGetAccessor(Object* object, void*);
+  static Object* ReadOnlySetAccessor(JSObject*, Object* value, void*);
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_ACCESSORS_H_
diff --git a/deps/v8/src/allocation.cc b/deps/v8/src/allocation.cc
new file mode 100644
index 0000000..3d26123
--- /dev/null
+++ b/deps/v8/src/allocation.cc
@@ -0,0 +1,197 @@
+// Copyright 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.
+
+#include <stdlib.h>
+
+#include "v8.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");
+  return result;
+}
+
+
+void Malloced::Delete(void* p) {
+  free(p);
+}
+
+
+void Malloced::FatalProcessOutOfMemory() {
+  V8::FatalProcessOutOfMemory("Out of memory");
+}
+
+
+#ifdef DEBUG
+
+static void* invalid = static_cast<void*>(NULL);
+
+void* Embedded::operator new(size_t size) {
+  UNREACHABLE();
+  return invalid;
+}
+
+
+void Embedded::operator delete(void* p) {
+  UNREACHABLE();
+}
+
+
+void* AllStatic::operator new(size_t size) {
+  UNREACHABLE();
+  return invalid;
+}
+
+
+void AllStatic::operator delete(void* p) {
+  UNREACHABLE();
+}
+
+#endif
+
+
+char* StrDup(const char* str) {
+  int length = strlen(str);
+  char* result = NewArray<char>(length + 1);
+  memcpy(result, str, length * kCharSize);
+  result[length] = '\0';
+  return result;
+}
+
+
+char* StrNDup(const char* str, size_t n) {
+  size_t length = strlen(str);
+  if (n < length) length = n;
+  char* result = NewArray<char>(length + 1);
+  memcpy(result, str, length * kCharSize);
+  result[length] = '\0';
+  return result;
+}
+
+
+int NativeAllocationChecker::allocation_disallowed_ = 0;
+
+
+PreallocatedStorage PreallocatedStorage::in_use_list_(0);
+PreallocatedStorage PreallocatedStorage::free_list_(0);
+bool PreallocatedStorage::preallocated_ = false;
+
+
+void PreallocatedStorage::Init(size_t size) {
+  ASSERT(free_list_.next_ == &free_list_);
+  ASSERT(free_list_.previous_ == &free_list_);
+  PreallocatedStorage* free_chunk =
+      reinterpret_cast<PreallocatedStorage*>(new char[size]);
+  free_list_.next_ = free_list_.previous_ = free_chunk;
+  free_chunk->next_ = free_chunk->previous_ = &free_list_;
+  free_chunk->size_ = size - sizeof(PreallocatedStorage);
+  preallocated_ = true;
+}
+
+
+void* PreallocatedStorage::New(size_t size) {
+  if (!preallocated_) {
+    return FreeStoreAllocationPolicy::New(size);
+  }
+  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_;
+       storage != &free_list_;
+       storage = storage->next_) {
+    if (storage->size_ == size) {
+      storage->Unlink();
+      storage->LinkTo(&in_use_list_);
+      return reinterpret_cast<void*>(storage + 1);
+    }
+  }
+  // Search for first fit.
+  for (PreallocatedStorage* storage = free_list_.next_;
+       storage != &free_list_;
+       storage = storage->next_) {
+    if (storage->size_ >= size + sizeof(PreallocatedStorage)) {
+      storage->Unlink();
+      storage->LinkTo(&in_use_list_);
+      PreallocatedStorage* left_over =
+          reinterpret_cast<PreallocatedStorage*>(
+              reinterpret_cast<char*>(storage + 1) + size);
+      left_over->size_ = storage->size_ - size - sizeof(PreallocatedStorage);
+      ASSERT(size + left_over->size_ + sizeof(PreallocatedStorage) ==
+             storage->size_);
+      storage->size_ = size;
+      left_over->LinkTo(&free_list_);
+      return reinterpret_cast<void*>(storage + 1);
+    }
+  }
+  // Allocation failure.
+  ASSERT(false);
+  return NULL;
+}
+
+
+// We don't attempt to coalesce.
+void PreallocatedStorage::Delete(void* p) {
+  if (p == NULL) {
+    return;
+  }
+  if (!preallocated_) {
+    FreeStoreAllocationPolicy::Delete(p);
+    return;
+  }
+  PreallocatedStorage* storage = reinterpret_cast<PreallocatedStorage*>(p) - 1;
+  ASSERT(storage->next_->previous_ == storage);
+  ASSERT(storage->previous_->next_ == storage);
+  storage->Unlink();
+  storage->LinkTo(&free_list_);
+}
+
+
+void PreallocatedStorage::LinkTo(PreallocatedStorage* other) {
+  next_ = other->next_;
+  other->next_->previous_ = this;
+  previous_ = other;
+  other->next_ = this;
+}
+
+
+void PreallocatedStorage::Unlink() {
+  next_->previous_ = previous_;
+  previous_->next_ = next_;
+}
+
+
+PreallocatedStorage::PreallocatedStorage(size_t size)
+  : size_(size) {
+  previous_ = next_ = this;
+}
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/allocation.h b/deps/v8/src/allocation.h
new file mode 100644
index 0000000..a690f08
--- /dev/null
+++ b/deps/v8/src/allocation.h
@@ -0,0 +1,168 @@
+// Copyright 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_ALLOCATION_H_
+#define V8_ALLOCATION_H_
+
+namespace v8 { namespace internal {
+
+
+// A class that controls whether allocation is allowed.  This is for
+// the C++ heap only!
+class NativeAllocationChecker {
+ public:
+  typedef enum { ALLOW, DISALLOW } NativeAllocationAllowed;
+  explicit inline NativeAllocationChecker(NativeAllocationAllowed allowed)
+      : allowed_(allowed) {
+#ifdef DEBUG
+    if (allowed == DISALLOW) {
+      allocation_disallowed_++;
+    }
+#endif
+  }
+  ~NativeAllocationChecker() {
+#ifdef DEBUG
+    if (allowed_ == DISALLOW) {
+      allocation_disallowed_--;
+    }
+#endif
+    ASSERT(allocation_disallowed_ >= 0);
+  }
+  static inline bool allocation_allowed() {
+    return allocation_disallowed_ == 0;
+  }
+ private:
+  // This static counter ensures that NativeAllocationCheckers can be nested.
+  static int allocation_disallowed_;
+  // This flag applies to this particular instance.
+  NativeAllocationAllowed allowed_;
+};
+
+
+// Superclass for classes managed with new & delete.
+class Malloced {
+ public:
+  void* operator new(size_t size) { return New(size); }
+  void  operator delete(void* p) { Delete(p); }
+
+  static void FatalProcessOutOfMemory();
+  static void* New(size_t size);
+  static void Delete(void* p);
+};
+
+
+// A macro is used for defining the base class used for embedded instances.
+// The reason is some compilers allocate a minimum of one word for the
+// superclass. The macro prevents the use of new & delete in debug mode.
+// In release mode we are not willing to pay this overhead.
+
+#ifdef DEBUG
+// Superclass for classes with instances allocated inside stack
+// activations or inside other objects.
+class Embedded {
+ public:
+  void* operator new(size_t size);
+  void  operator delete(void* p);
+};
+#define BASE_EMBEDDED : public Embedded
+#else
+#define BASE_EMBEDDED
+#endif
+
+
+// Superclass for classes only using statics.
+class AllStatic {
+#ifdef DEBUG
+ public:
+  void* operator new(size_t size);
+  void operator delete(void* p);
+#endif
+};
+
+
+template <typename T>
+static T* NewArray(int size) {
+  ASSERT(NativeAllocationChecker::allocation_allowed());
+  T* result = new T[size];
+  if (result == NULL) Malloced::FatalProcessOutOfMemory();
+  return result;
+}
+
+
+template <typename T>
+static void DeleteArray(T* array) {
+  delete[] array;
+}
+
+
+// The normal strdup functions use malloc.  These versions of StrDup
+// and StrNDup uses new and calls the FatalProcessOutOfMemory handler
+// if allocation fails.
+char* StrDup(const char* str);
+char* StrNDup(const char* str, size_t n);
+
+
+// Allocation policy for allocating in the C free store using malloc
+// and free. Used as the default policy for lists.
+class FreeStoreAllocationPolicy {
+ public:
+  INLINE(static void* New(size_t size)) { return Malloced::New(size); }
+  INLINE(static void Delete(void* p)) { Malloced::Delete(p); }
+};
+
+
+// Allocation policy for allocating in preallocated space.
+// Used as an allocation policy for ScopeInfo when generating
+// stack traces.
+class PreallocatedStorage : public AllStatic {
+ public:
+  explicit PreallocatedStorage(size_t size);
+  size_t size() { return size_; }
+  static void* New(size_t size);
+  static void Delete(void* p);
+
+  // Preallocate a set number of bytes.
+  static void Init(size_t size);
+
+ private:
+  size_t size_;
+  PreallocatedStorage* previous_;
+  PreallocatedStorage* next_;
+  static bool preallocated_;
+
+  static PreallocatedStorage in_use_list_;
+  static PreallocatedStorage free_list_;
+
+  void LinkTo(PreallocatedStorage* other);
+  void Unlink();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(PreallocatedStorage);
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_ALLOCATION_H_
diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc
new file mode 100644
index 0000000..a190b9c
--- /dev/null
+++ b/deps/v8/src/api.cc
@@ -0,0 +1,3348 @@
+// 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.
+
+#include "v8.h"
+
+#include "api.h"
+#include "bootstrapper.h"
+#include "compiler.h"
+#include "debug.h"
+#include "execution.h"
+#include "global-handles.h"
+#include "platform.h"
+#include "serialize.h"
+#include "snapshot.h"
+#include "v8threads.h"
+
+
+#define LOG_API(expr) LOG(ApiEntryCall(expr))
+
+#ifdef ENABLE_HEAP_PROTECTION
+#define ENTER_V8 i::VMState __state__(i::OTHER)
+#define LEAVE_V8 i::VMState __state__(i::EXTERNAL)
+#else
+#define ENTER_V8 ((void) 0)
+#define LEAVE_V8 ((void) 0)
+#endif
+
+namespace v8 {
+
+
+#define ON_BAILOUT(location, code)              \
+  if (IsDeadCheck(location)) {                  \
+    code;                                       \
+    UNREACHABLE();                              \
+  }
+
+
+#define EXCEPTION_PREAMBLE()                                      \
+  thread_local.IncrementCallDepth();                              \
+  ASSERT(!i::Top::external_caught_exception());                   \
+  bool has_pending_exception = false
+
+
+#define EXCEPTION_BAILOUT_CHECK(value)                                         \
+  do {                                                                         \
+    thread_local.DecrementCallDepth();                                         \
+    if (has_pending_exception) {                                               \
+      if (thread_local.CallDepthIsZero() && i::Top::is_out_of_memory()) {      \
+        if (!thread_local.IgnoreOutOfMemory())                                 \
+          i::V8::FatalProcessOutOfMemory(NULL);                                \
+      }                                                                        \
+      bool call_depth_is_zero = thread_local.CallDepthIsZero();                \
+      i::Top::optional_reschedule_exception(call_depth_is_zero);               \
+      return value;                                                            \
+    }                                                                          \
+  } while (false)
+
+
+#define API_ENTRY_CHECK(msg)                                                   \
+  do {                                                                         \
+    if (v8::Locker::IsActive()) {                                              \
+      ApiCheck(i::ThreadManager::IsLockedByCurrentThread(),                    \
+               msg,                                                            \
+               "Entering the V8 API without proper locking in place");         \
+    }                                                                          \
+  } while (false)
+
+// --- D a t a   t h a t   i s   s p e c i f i c   t o   a   t h r e a d ---
+
+
+static i::HandleScopeImplementer thread_local;
+
+
+// --- E x c e p t i o n   B e h a v i o r ---
+
+
+static bool has_shut_down = false;
+static FatalErrorCallback exception_behavior = NULL;
+
+
+static void DefaultFatalErrorHandler(const char* location,
+                                     const char* message) {
+  ENTER_V8;
+  API_Fatal(location, message);
+}
+
+
+
+static FatalErrorCallback& GetFatalErrorHandler() {
+  if (exception_behavior == NULL) {
+    exception_behavior = DefaultFatalErrorHandler;
+  }
+  return exception_behavior;
+}
+
+
+
+// When V8 cannot allocated memory FatalProcessOutOfMemory is called.
+// The default fatal error handler is called and execution is stopped.
+void i::V8::FatalProcessOutOfMemory(const char* location) {
+  has_shut_down = true;
+  FatalErrorCallback callback = GetFatalErrorHandler();
+  {
+    LEAVE_V8;
+    callback(location, "Allocation failed - process out of memory");
+  }
+  // If the callback returns, we stop execution.
+  UNREACHABLE();
+}
+
+
+void V8::SetFatalErrorHandler(FatalErrorCallback that) {
+  exception_behavior = that;
+}
+
+
+bool Utils::ReportApiFailure(const char* location, const char* message) {
+  FatalErrorCallback callback = GetFatalErrorHandler();
+  callback(location, message);
+  has_shut_down = true;
+  return false;
+}
+
+
+bool V8::IsDead() {
+  return has_shut_down;
+}
+
+
+static inline bool ApiCheck(bool condition,
+                            const char* location,
+                            const char* message) {
+  return condition ? true : Utils::ReportApiFailure(location, message);
+}
+
+
+static bool ReportV8Dead(const char* location) {
+  FatalErrorCallback callback = GetFatalErrorHandler();
+  callback(location, "V8 is no longer usable");
+  return true;
+}
+
+
+static bool ReportEmptyHandle(const char* location) {
+  FatalErrorCallback callback = GetFatalErrorHandler();
+  callback(location, "Reading from empty handle");
+  return true;
+}
+
+
+/**
+ * IsDeadCheck checks that the vm is usable.  If, for instance, the vm has been
+ * out of memory at some point this check will fail.  It should be called on
+ * entry to all methods that touch anything in the heap, except destructors
+ * which you sometimes can't avoid calling after the vm has crashed.  Functions
+ * that call EnsureInitialized or ON_BAILOUT don't have to also call
+ * IsDeadCheck.  ON_BAILOUT has the advantage over EnsureInitialized that you
+ * can arrange to return if the VM is dead.  This is needed to ensure that no VM
+ * heap allocations are attempted on a dead VM.  EnsureInitialized has the
+ * advantage over ON_BAILOUT that it actually initializes the VM if this has not
+ * yet been done.
+ */
+static inline bool IsDeadCheck(const char* location) {
+  return has_shut_down ? ReportV8Dead(location) : false;
+}
+
+
+static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) {
+  return obj.IsEmpty() ? ReportEmptyHandle(location) : false;
+}
+
+
+static inline bool EmptyCheck(const char* location, const v8::Data* obj) {
+  return (obj == 0) ? ReportEmptyHandle(location) : false;
+}
+
+// --- S t a t i c s ---
+
+
+static i::StringInputBuffer write_input_buffer;
+
+
+static void EnsureInitialized(const char* location) {
+  if (IsDeadCheck(location)) return;
+  ApiCheck(v8::V8::Initialize(), location, "Error initializing V8");
+}
+
+
+ImplementationUtilities::HandleScopeData*
+    ImplementationUtilities::CurrentHandleScope() {
+  return &i::HandleScope::current_;
+}
+
+
+#ifdef DEBUG
+void ImplementationUtilities::ZapHandleRange(void** begin, void** end) {
+  i::HandleScope::ZapRange(begin, end);
+}
+#endif
+
+
+v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() {
+  if (IsDeadCheck("v8::Undefined()")) return v8::Handle<v8::Primitive>();
+  EnsureInitialized("v8::Undefined()");
+  return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::undefined_value()));
+}
+
+
+v8::Handle<v8::Primitive> ImplementationUtilities::Null() {
+  if (IsDeadCheck("v8::Null()")) return v8::Handle<v8::Primitive>();
+  EnsureInitialized("v8::Null()");
+  return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::null_value()));
+}
+
+
+v8::Handle<v8::Boolean> ImplementationUtilities::True() {
+  if (IsDeadCheck("v8::True()")) return v8::Handle<v8::Boolean>();
+  EnsureInitialized("v8::True()");
+  return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::true_value()));
+}
+
+
+v8::Handle<v8::Boolean> ImplementationUtilities::False() {
+  if (IsDeadCheck("v8::False()")) return v8::Handle<v8::Boolean>();
+  EnsureInitialized("v8::False()");
+  return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::false_value()));
+}
+
+
+void V8::SetFlagsFromString(const char* str, int length) {
+  i::FlagList::SetFlagsFromString(str, length);
+}
+
+
+void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
+  i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
+}
+
+
+v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) {
+  if (IsDeadCheck("v8::ThrowException()")) return v8::Handle<Value>();
+  ENTER_V8;
+  // If we're passed an empty handle, we throw an undefined exception
+  // to deal more gracefully with out of memory situations.
+  if (value.IsEmpty()) {
+    i::Top::ScheduleThrow(i::Heap::undefined_value());
+  } else {
+    i::Top::ScheduleThrow(*Utils::OpenHandle(*value));
+  }
+  return v8::Undefined();
+}
+
+
+RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
+
+
+RegisteredExtension::RegisteredExtension(Extension* extension)
+    : extension_(extension), state_(UNVISITED) { }
+
+
+void RegisteredExtension::Register(RegisteredExtension* that) {
+  that->next_ = RegisteredExtension::first_extension_;
+  RegisteredExtension::first_extension_ = that;
+}
+
+
+void RegisterExtension(Extension* that) {
+  RegisteredExtension* extension = new RegisteredExtension(that);
+  RegisteredExtension::Register(extension);
+}
+
+
+Extension::Extension(const char* name,
+                     const char* source,
+                     int dep_count,
+                     const char** deps)
+    : name_(name),
+      source_(source),
+      dep_count_(dep_count),
+      deps_(deps),
+      auto_enable_(false) { }
+
+
+v8::Handle<Primitive> Undefined() {
+  LOG_API("Undefined");
+  return ImplementationUtilities::Undefined();
+}
+
+
+v8::Handle<Primitive> Null() {
+  LOG_API("Null");
+  return ImplementationUtilities::Null();
+}
+
+
+v8::Handle<Boolean> True() {
+  LOG_API("True");
+  return ImplementationUtilities::True();
+}
+
+
+v8::Handle<Boolean> False() {
+  LOG_API("False");
+  return ImplementationUtilities::False();
+}
+
+
+ResourceConstraints::ResourceConstraints()
+  : max_young_space_size_(0),
+    max_old_space_size_(0),
+    stack_limit_(NULL) { }
+
+
+bool SetResourceConstraints(ResourceConstraints* constraints) {
+  bool result = i::Heap::ConfigureHeap(constraints->max_young_space_size(),
+                                       constraints->max_old_space_size());
+  if (!result) return false;
+  if (constraints->stack_limit() != NULL) {
+    uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
+    i::StackGuard::SetStackLimit(limit);
+  }
+  return true;
+}
+
+
+void** V8::GlobalizeReference(void** obj) {
+  if (IsDeadCheck("V8::Persistent::New")) return NULL;
+  LOG_API("Persistent::New");
+  i::Handle<i::Object> result =
+      i::GlobalHandles::Create(*reinterpret_cast<i::Object**>(obj));
+  return reinterpret_cast<void**>(result.location());
+}
+
+
+void V8::MakeWeak(void** object, void* parameters,
+                  WeakReferenceCallback callback) {
+  LOG_API("MakeWeak");
+  i::GlobalHandles::MakeWeak(reinterpret_cast<i::Object**>(object), parameters,
+      callback);
+}
+
+
+void V8::ClearWeak(void** obj) {
+  LOG_API("ClearWeak");
+  i::GlobalHandles::ClearWeakness(reinterpret_cast<i::Object**>(obj));
+}
+
+
+bool V8::IsGlobalNearDeath(void** obj) {
+  LOG_API("IsGlobalNearDeath");
+  if (has_shut_down) return false;
+  return i::GlobalHandles::IsNearDeath(reinterpret_cast<i::Object**>(obj));
+}
+
+
+bool V8::IsGlobalWeak(void** obj) {
+  LOG_API("IsGlobalWeak");
+  if (has_shut_down) return false;
+  return i::GlobalHandles::IsWeak(reinterpret_cast<i::Object**>(obj));
+}
+
+
+void V8::DisposeGlobal(void** obj) {
+  LOG_API("DisposeGlobal");
+  if (has_shut_down) return;
+  i::Object** ptr = reinterpret_cast<i::Object**>(obj);
+  if ((*ptr)->IsGlobalContext()) i::Heap::NotifyContextDisposed();
+  i::GlobalHandles::Destroy(ptr);
+}
+
+// --- H a n d l e s ---
+
+
+HandleScope::HandleScope() : is_closed_(false) {
+  API_ENTRY_CHECK("HandleScope::HandleScope");
+  i::HandleScope::Enter(&previous_);
+}
+
+
+HandleScope::~HandleScope() {
+  if (!is_closed_) {
+    i::HandleScope::Leave(&previous_);
+  }
+}
+
+
+int HandleScope::NumberOfHandles() {
+  return i::HandleScope::NumberOfHandles();
+}
+
+
+void** v8::HandleScope::CreateHandle(void* value) {
+  return i::HandleScope::CreateHandle(value);
+}
+
+
+void Context::Enter() {
+  if (IsDeadCheck("v8::Context::Enter()")) return;
+  ENTER_V8;
+  i::Handle<i::Context> env = Utils::OpenHandle(this);
+  thread_local.EnterContext(env);
+
+  thread_local.SaveContext(i::GlobalHandles::Create(i::Top::context()));
+  i::Top::set_context(*env);
+}
+
+
+void Context::Exit() {
+  if (has_shut_down) return;
+  if (!ApiCheck(thread_local.LeaveLastContext(),
+                "v8::Context::Exit()",
+                "Cannot exit non-entered context")) {
+    return;
+  }
+
+  // Content of 'last_context' could be NULL.
+  i::Handle<i::Object> last_context = thread_local.RestoreContext();
+  i::Top::set_context(static_cast<i::Context*>(*last_context));
+  i::GlobalHandles::Destroy(last_context.location());
+}
+
+
+void** v8::HandleScope::RawClose(void** value) {
+  if (!ApiCheck(!is_closed_,
+                "v8::HandleScope::Close()",
+                "Local scope has already been closed")) {
+    return 0;
+  }
+  LOG_API("CloseHandleScope");
+
+  // Read the result before popping the handle block.
+  i::Object* result = reinterpret_cast<i::Object*>(*value);
+  is_closed_ = true;
+  i::HandleScope::Leave(&previous_);
+
+  // Allocate a new handle on the previous handle block.
+  i::Handle<i::Object> handle(result);
+  return reinterpret_cast<void**>(handle.location());
+}
+
+
+// --- N e a n d e r ---
+
+
+// A constructor cannot easily return an error value, therefore it is necessary
+// to check for a dead VM with ON_BAILOUT before constructing any Neander
+// objects.  To remind you about this there is no HandleScope in the
+// NeanderObject constructor.  When you add one to the site calling the
+// constructor you should check that you ensured the VM was not dead first.
+NeanderObject::NeanderObject(int size) {
+  EnsureInitialized("v8::Nowhere");
+  ENTER_V8;
+  value_ = i::Factory::NewNeanderObject();
+  i::Handle<i::FixedArray> elements = i::Factory::NewFixedArray(size);
+  value_->set_elements(*elements);
+}
+
+
+int NeanderObject::size() {
+  return i::FixedArray::cast(value_->elements())->length();
+}
+
+
+NeanderArray::NeanderArray() : obj_(2) {
+  obj_.set(0, i::Smi::FromInt(0));
+}
+
+
+int NeanderArray::length() {
+  return i::Smi::cast(obj_.get(0))->value();
+}
+
+
+i::Object* NeanderArray::get(int offset) {
+  ASSERT(0 <= offset);
+  ASSERT(offset < length());
+  return obj_.get(offset + 1);
+}
+
+
+// This method cannot easily return an error value, therefore it is necessary
+// to check for a dead VM with ON_BAILOUT before calling it.  To remind you
+// about this there is no HandleScope in this method.  When you add one to the
+// site calling this method you should check that you ensured the VM was not
+// dead first.
+void NeanderArray::add(i::Handle<i::Object> value) {
+  int length = this->length();
+  int size = obj_.size();
+  if (length == size - 1) {
+    i::Handle<i::FixedArray> new_elms = i::Factory::NewFixedArray(2 * size);
+    for (int i = 0; i < length; i++)
+      new_elms->set(i + 1, get(i));
+    obj_.value()->set_elements(*new_elms);
+  }
+  obj_.set(length + 1, *value);
+  obj_.set(0, i::Smi::FromInt(length + 1));
+}
+
+
+void NeanderArray::set(int index, i::Object* value) {
+  if (index < 0 || index >= this->length()) return;
+  obj_.set(index + 1, value);
+}
+
+
+// --- T e m p l a t e ---
+
+
+static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
+  that->set_tag(i::Smi::FromInt(type));
+}
+
+
+void Template::Set(v8::Handle<String> name, v8::Handle<Data> value,
+                   v8::PropertyAttribute attribute) {
+  if (IsDeadCheck("v8::Template::SetProperty()")) return;
+  ENTER_V8;
+  HandleScope scope;
+  i::Handle<i::Object> list(Utils::OpenHandle(this)->property_list());
+  if (list->IsUndefined()) {
+    list = NeanderArray().value();
+    Utils::OpenHandle(this)->set_property_list(*list);
+  }
+  NeanderArray array(list);
+  array.add(Utils::OpenHandle(*name));
+  array.add(Utils::OpenHandle(*value));
+  array.add(Utils::OpenHandle(*v8::Integer::New(attribute)));
+}
+
+
+// --- F u n c t i o n   T e m p l a t e ---
+static void InitializeFunctionTemplate(
+      i::Handle<i::FunctionTemplateInfo> info) {
+  info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
+  info->set_flag(0);
+}
+
+
+Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
+  if (IsDeadCheck("v8::FunctionTemplate::PrototypeTemplate()")) {
+    return Local<ObjectTemplate>();
+  }
+  ENTER_V8;
+  i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template());
+  if (result->IsUndefined()) {
+    result = Utils::OpenHandle(*ObjectTemplate::New());
+    Utils::OpenHandle(this)->set_prototype_template(*result);
+  }
+  return Local<ObjectTemplate>(ToApi<ObjectTemplate>(result));
+}
+
+
+void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
+  if (IsDeadCheck("v8::FunctionTemplate::Inherit()")) return;
+  ENTER_V8;
+  Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
+}
+
+
+// To distinguish the function templates, so that we can find them in the
+// function cache of the global context.
+static int next_serial_number = 0;
+
+
+Local<FunctionTemplate> FunctionTemplate::New(InvocationCallback callback,
+    v8::Handle<Value> data, v8::Handle<Signature> signature) {
+  EnsureInitialized("v8::FunctionTemplate::New()");
+  LOG_API("FunctionTemplate::New");
+  ENTER_V8;
+  i::Handle<i::Struct> struct_obj =
+      i::Factory::NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
+  i::Handle<i::FunctionTemplateInfo> obj =
+      i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
+  InitializeFunctionTemplate(obj);
+  obj->set_serial_number(i::Smi::FromInt(next_serial_number++));
+  if (callback != 0) {
+    if (data.IsEmpty()) data = v8::Undefined();
+    Utils::ToLocal(obj)->SetCallHandler(callback, data);
+  }
+  obj->set_undetectable(false);
+  obj->set_needs_access_check(false);
+
+  if (!signature.IsEmpty())
+    obj->set_signature(*Utils::OpenHandle(*signature));
+  return Utils::ToLocal(obj);
+}
+
+
+Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
+      int argc, Handle<FunctionTemplate> argv[]) {
+  EnsureInitialized("v8::Signature::New()");
+  LOG_API("Signature::New");
+  ENTER_V8;
+  i::Handle<i::Struct> struct_obj =
+      i::Factory::NewStruct(i::SIGNATURE_INFO_TYPE);
+  i::Handle<i::SignatureInfo> obj =
+      i::Handle<i::SignatureInfo>::cast(struct_obj);
+  if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
+  if (argc > 0) {
+    i::Handle<i::FixedArray> args = i::Factory::NewFixedArray(argc);
+    for (int i = 0; i < argc; i++) {
+      if (!argv[i].IsEmpty())
+        args->set(i, *Utils::OpenHandle(*argv[i]));
+    }
+    obj->set_args(*args);
+  }
+  return Utils::ToLocal(obj);
+}
+
+
+Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
+  Handle<FunctionTemplate> types[1] = { type };
+  return TypeSwitch::New(1, types);
+}
+
+
+Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
+  EnsureInitialized("v8::TypeSwitch::New()");
+  LOG_API("TypeSwitch::New");
+  ENTER_V8;
+  i::Handle<i::FixedArray> vector = i::Factory::NewFixedArray(argc);
+  for (int i = 0; i < argc; i++)
+    vector->set(i, *Utils::OpenHandle(*types[i]));
+  i::Handle<i::Struct> struct_obj =
+      i::Factory::NewStruct(i::TYPE_SWITCH_INFO_TYPE);
+  i::Handle<i::TypeSwitchInfo> obj =
+      i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
+  obj->set_types(*vector);
+  return Utils::ToLocal(obj);
+}
+
+
+int TypeSwitch::match(v8::Handle<Value> value) {
+  LOG_API("TypeSwitch::match");
+  i::Handle<i::Object> obj = Utils::OpenHandle(*value);
+  i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
+  i::FixedArray* types = i::FixedArray::cast(info->types());
+  for (int i = 0; i < types->length(); i++) {
+    if (obj->IsInstanceOf(i::FunctionTemplateInfo::cast(types->get(i))))
+      return i + 1;
+  }
+  return 0;
+}
+
+
+void FunctionTemplate::SetCallHandler(InvocationCallback callback,
+                                      v8::Handle<Value> data) {
+  if (IsDeadCheck("v8::FunctionTemplate::SetCallHandler()")) return;
+  ENTER_V8;
+  HandleScope scope;
+  i::Handle<i::Struct> struct_obj =
+      i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
+  i::Handle<i::CallHandlerInfo> obj =
+      i::Handle<i::CallHandlerInfo>::cast(struct_obj);
+  obj->set_callback(*FromCData(callback));
+  if (data.IsEmpty()) data = v8::Undefined();
+  obj->set_data(*Utils::OpenHandle(*data));
+  Utils::OpenHandle(this)->set_call_code(*obj);
+}
+
+
+void FunctionTemplate::AddInstancePropertyAccessor(
+      v8::Handle<String> name,
+      AccessorGetter getter,
+      AccessorSetter setter,
+      v8::Handle<Value> data,
+      v8::AccessControl settings,
+      v8::PropertyAttribute attributes) {
+  if (IsDeadCheck("v8::FunctionTemplate::AddInstancePropertyAccessor()")) {
+    return;
+  }
+  ENTER_V8;
+  HandleScope scope;
+  i::Handle<i::AccessorInfo> obj = i::Factory::NewAccessorInfo();
+  ASSERT(getter != NULL);
+  obj->set_getter(*FromCData(getter));
+  obj->set_setter(*FromCData(setter));
+  if (data.IsEmpty()) data = v8::Undefined();
+  obj->set_data(*Utils::OpenHandle(*data));
+  obj->set_name(*Utils::OpenHandle(*name));
+  if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
+  if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
+  if (settings & PROHIBITS_OVERWRITING) obj->set_prohibits_overwriting(true);
+  obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
+
+  i::Handle<i::Object> list(Utils::OpenHandle(this)->property_accessors());
+  if (list->IsUndefined()) {
+    list = NeanderArray().value();
+    Utils::OpenHandle(this)->set_property_accessors(*list);
+  }
+  NeanderArray array(list);
+  array.add(obj);
+}
+
+
+Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
+  if (IsDeadCheck("v8::FunctionTemplate::InstanceTemplate()")
+      || EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this))
+    return Local<ObjectTemplate>();
+  ENTER_V8;
+  if (Utils::OpenHandle(this)->instance_template()->IsUndefined()) {
+    Local<ObjectTemplate> templ =
+        ObjectTemplate::New(v8::Handle<FunctionTemplate>(this));
+    Utils::OpenHandle(this)->set_instance_template(*Utils::OpenHandle(*templ));
+  }
+  i::Handle<i::ObjectTemplateInfo> result(i::ObjectTemplateInfo::cast(
+        Utils::OpenHandle(this)->instance_template()));
+  return Utils::ToLocal(result);
+}
+
+
+void FunctionTemplate::SetClassName(Handle<String> name) {
+  if (IsDeadCheck("v8::FunctionTemplate::SetClassName()")) return;
+  ENTER_V8;
+  Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
+}
+
+
+void FunctionTemplate::SetHiddenPrototype(bool value) {
+  if (IsDeadCheck("v8::FunctionTemplate::SetHiddenPrototype()")) return;
+  ENTER_V8;
+  Utils::OpenHandle(this)->set_hidden_prototype(value);
+}
+
+
+void FunctionTemplate::SetNamedInstancePropertyHandler(
+      NamedPropertyGetter getter,
+      NamedPropertySetter setter,
+      NamedPropertyQuery query,
+      NamedPropertyDeleter remover,
+      NamedPropertyEnumerator enumerator,
+      Handle<Value> data) {
+  if (IsDeadCheck("v8::FunctionTemplate::SetNamedInstancePropertyHandler()")) {
+    return;
+  }
+  ENTER_V8;
+  HandleScope scope;
+  i::Handle<i::Struct> struct_obj =
+      i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
+  i::Handle<i::InterceptorInfo> obj =
+      i::Handle<i::InterceptorInfo>::cast(struct_obj);
+  if (getter != 0) obj->set_getter(*FromCData(getter));
+  if (setter != 0) obj->set_setter(*FromCData(setter));
+  if (query != 0) obj->set_query(*FromCData(query));
+  if (remover != 0) obj->set_deleter(*FromCData(remover));
+  if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
+  if (data.IsEmpty()) data = v8::Undefined();
+  obj->set_data(*Utils::OpenHandle(*data));
+  Utils::OpenHandle(this)->set_named_property_handler(*obj);
+}
+
+
+void FunctionTemplate::SetIndexedInstancePropertyHandler(
+      IndexedPropertyGetter getter,
+      IndexedPropertySetter setter,
+      IndexedPropertyQuery query,
+      IndexedPropertyDeleter remover,
+      IndexedPropertyEnumerator enumerator,
+      Handle<Value> data) {
+  if (IsDeadCheck(
+        "v8::FunctionTemplate::SetIndexedInstancePropertyHandler()")) {
+    return;
+  }
+  ENTER_V8;
+  HandleScope scope;
+  i::Handle<i::Struct> struct_obj =
+      i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
+  i::Handle<i::InterceptorInfo> obj =
+      i::Handle<i::InterceptorInfo>::cast(struct_obj);
+  if (getter != 0) obj->set_getter(*FromCData(getter));
+  if (setter != 0) obj->set_setter(*FromCData(setter));
+  if (query != 0) obj->set_query(*FromCData(query));
+  if (remover != 0) obj->set_deleter(*FromCData(remover));
+  if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
+  if (data.IsEmpty()) data = v8::Undefined();
+  obj->set_data(*Utils::OpenHandle(*data));
+  Utils::OpenHandle(this)->set_indexed_property_handler(*obj);
+}
+
+
+void FunctionTemplate::SetInstanceCallAsFunctionHandler(
+      InvocationCallback callback,
+      Handle<Value> data) {
+  if (IsDeadCheck("v8::FunctionTemplate::SetInstanceCallAsFunctionHandler()")) {
+    return;
+  }
+  ENTER_V8;
+  HandleScope scope;
+  i::Handle<i::Struct> struct_obj =
+      i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
+  i::Handle<i::CallHandlerInfo> obj =
+      i::Handle<i::CallHandlerInfo>::cast(struct_obj);
+  obj->set_callback(*FromCData(callback));
+  if (data.IsEmpty()) data = v8::Undefined();
+  obj->set_data(*Utils::OpenHandle(*data));
+  Utils::OpenHandle(this)->set_instance_call_handler(*obj);
+}
+
+
+// --- O b j e c t T e m p l a t e ---
+
+
+Local<ObjectTemplate> ObjectTemplate::New() {
+  return New(Local<FunctionTemplate>());
+}
+
+
+Local<ObjectTemplate> ObjectTemplate::New(
+      v8::Handle<FunctionTemplate> constructor) {
+  if (IsDeadCheck("v8::ObjectTemplate::New()")) return Local<ObjectTemplate>();
+  EnsureInitialized("v8::ObjectTemplate::New()");
+  LOG_API("ObjectTemplate::New");
+  ENTER_V8;
+  i::Handle<i::Struct> struct_obj =
+      i::Factory::NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
+  i::Handle<i::ObjectTemplateInfo> obj =
+      i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
+  InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
+  if (!constructor.IsEmpty())
+    obj->set_constructor(*Utils::OpenHandle(*constructor));
+  obj->set_internal_field_count(i::Smi::FromInt(0));
+  return Utils::ToLocal(obj);
+}
+
+
+// Ensure that the object template has a constructor.  If no
+// constructor is available we create one.
+static void EnsureConstructor(ObjectTemplate* object_template) {
+  if (Utils::OpenHandle(object_template)->constructor()->IsUndefined()) {
+    Local<FunctionTemplate> templ = FunctionTemplate::New();
+    i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
+    constructor->set_instance_template(*Utils::OpenHandle(object_template));
+    Utils::OpenHandle(object_template)->set_constructor(*constructor);
+  }
+}
+
+
+void ObjectTemplate::SetAccessor(v8::Handle<String> name,
+                                 AccessorGetter getter,
+                                 AccessorSetter setter,
+                                 v8::Handle<Value> data,
+                                 AccessControl settings,
+                                 PropertyAttribute attribute) {
+  if (IsDeadCheck("v8::ObjectTemplate::SetAccessor()")) return;
+  ENTER_V8;
+  HandleScope scope;
+  EnsureConstructor(this);
+  i::FunctionTemplateInfo* constructor =
+      i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
+  i::Handle<i::FunctionTemplateInfo> cons(constructor);
+  Utils::ToLocal(cons)->AddInstancePropertyAccessor(name,
+                                                    getter,
+                                                    setter,
+                                                    data,
+                                                    settings,
+                                                    attribute);
+}
+
+
+void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
+                                             NamedPropertySetter setter,
+                                             NamedPropertyQuery query,
+                                             NamedPropertyDeleter remover,
+                                             NamedPropertyEnumerator enumerator,
+                                             Handle<Value> data) {
+  if (IsDeadCheck("v8::ObjectTemplate::SetNamedPropertyHandler()")) return;
+  ENTER_V8;
+  HandleScope scope;
+  EnsureConstructor(this);
+  i::FunctionTemplateInfo* constructor =
+      i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
+  i::Handle<i::FunctionTemplateInfo> cons(constructor);
+  Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter,
+                                                        setter,
+                                                        query,
+                                                        remover,
+                                                        enumerator,
+                                                        data);
+}
+
+
+void ObjectTemplate::MarkAsUndetectable() {
+  if (IsDeadCheck("v8::ObjectTemplate::MarkAsUndetectable()")) return;
+  ENTER_V8;
+  HandleScope scope;
+  EnsureConstructor(this);
+  i::FunctionTemplateInfo* constructor =
+      i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
+  i::Handle<i::FunctionTemplateInfo> cons(constructor);
+  cons->set_undetectable(true);
+}
+
+
+void ObjectTemplate::SetAccessCheckCallbacks(
+      NamedSecurityCallback named_callback,
+      IndexedSecurityCallback indexed_callback,
+      Handle<Value> data,
+      bool turned_on_by_default) {
+  if (IsDeadCheck("v8::ObjectTemplate::SetAccessCheckCallbacks()")) return;
+  ENTER_V8;
+  HandleScope scope;
+  EnsureConstructor(this);
+
+  i::Handle<i::Struct> struct_info =
+      i::Factory::NewStruct(i::ACCESS_CHECK_INFO_TYPE);
+  i::Handle<i::AccessCheckInfo> info =
+      i::Handle<i::AccessCheckInfo>::cast(struct_info);
+  info->set_named_callback(*FromCData(named_callback));
+  info->set_indexed_callback(*FromCData(indexed_callback));
+  if (data.IsEmpty()) data = v8::Undefined();
+  info->set_data(*Utils::OpenHandle(*data));
+
+  i::FunctionTemplateInfo* constructor =
+      i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
+  i::Handle<i::FunctionTemplateInfo> cons(constructor);
+  cons->set_access_check_info(*info);
+  cons->set_needs_access_check(turned_on_by_default);
+}
+
+
+void ObjectTemplate::SetIndexedPropertyHandler(
+      IndexedPropertyGetter getter,
+      IndexedPropertySetter setter,
+      IndexedPropertyQuery query,
+      IndexedPropertyDeleter remover,
+      IndexedPropertyEnumerator enumerator,
+      Handle<Value> data) {
+  if (IsDeadCheck("v8::ObjectTemplate::SetIndexedPropertyHandler()")) return;
+  ENTER_V8;
+  HandleScope scope;
+  EnsureConstructor(this);
+  i::FunctionTemplateInfo* constructor =
+      i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
+  i::Handle<i::FunctionTemplateInfo> cons(constructor);
+  Utils::ToLocal(cons)->SetIndexedInstancePropertyHandler(getter,
+                                                          setter,
+                                                          query,
+                                                          remover,
+                                                          enumerator,
+                                                          data);
+}
+
+
+void ObjectTemplate::SetCallAsFunctionHandler(InvocationCallback callback,
+                                              Handle<Value> data) {
+  if (IsDeadCheck("v8::ObjectTemplate::SetCallAsFunctionHandler()")) return;
+  ENTER_V8;
+  HandleScope scope;
+  EnsureConstructor(this);
+  i::FunctionTemplateInfo* constructor =
+      i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
+  i::Handle<i::FunctionTemplateInfo> cons(constructor);
+  Utils::ToLocal(cons)->SetInstanceCallAsFunctionHandler(callback, data);
+}
+
+
+int ObjectTemplate::InternalFieldCount() {
+  if (IsDeadCheck("v8::ObjectTemplate::InternalFieldCount()")) {
+    return 0;
+  }
+  return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
+}
+
+
+void ObjectTemplate::SetInternalFieldCount(int value) {
+  if (IsDeadCheck("v8::ObjectTemplate::SetInternalFieldCount()")) return;
+  if (!ApiCheck(i::Smi::IsValid(value),
+                "v8::ObjectTemplate::SetInternalFieldCount()",
+                "Invalid internal field count")) {
+    return;
+  }
+  ENTER_V8;
+  if (value > 0) {
+    // The internal field count is set by the constructor function's
+    // construct code, so we ensure that there is a constructor
+    // function to do the setting.
+    EnsureConstructor(this);
+  }
+  Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
+}
+
+
+// --- S c r i p t D a t a ---
+
+
+ScriptData* ScriptData::PreCompile(const char* input, int length) {
+  unibrow::Utf8InputBuffer<> buf(input, length);
+  return i::PreParse(&buf, NULL);
+}
+
+
+ScriptData* ScriptData::New(unsigned* data, int length) {
+  return new i::ScriptDataImpl(i::Vector<unsigned>(data, length));
+}
+
+
+// --- S c r i p t ---
+
+
+Local<Script> Script::Compile(v8::Handle<String> source,
+                              v8::ScriptOrigin* origin,
+                              v8::ScriptData* script_data) {
+  ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
+  LOG_API("Script::Compile");
+  ENTER_V8;
+  i::Handle<i::String> str = Utils::OpenHandle(*source);
+  i::Handle<i::Object> name_obj;
+  int line_offset = 0;
+  int column_offset = 0;
+  if (origin != NULL) {
+    if (!origin->ResourceName().IsEmpty()) {
+      name_obj = Utils::OpenHandle(*origin->ResourceName());
+    }
+    if (!origin->ResourceLineOffset().IsEmpty()) {
+      line_offset = static_cast<int>(origin->ResourceLineOffset()->Value());
+    }
+    if (!origin->ResourceColumnOffset().IsEmpty()) {
+      column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value());
+    }
+  }
+  EXCEPTION_PREAMBLE();
+  i::ScriptDataImpl* pre_data = static_cast<i::ScriptDataImpl*>(script_data);
+  // We assert that the pre-data is sane, even though we can actually
+  // handle it if it turns out not to be in release mode.
+  ASSERT(pre_data == NULL || pre_data->SanityCheck());
+  // If the pre-data isn't sane we simply ignore it
+  if (pre_data != NULL && !pre_data->SanityCheck())
+    pre_data = NULL;
+  i::Handle<i::JSFunction> boilerplate = i::Compiler::Compile(str,
+                                                              name_obj,
+                                                              line_offset,
+                                                              column_offset,
+                                                              NULL,
+                                                              pre_data);
+  has_pending_exception = boilerplate.is_null();
+  EXCEPTION_BAILOUT_CHECK(Local<Script>());
+  i::Handle<i::JSFunction> result =
+      i::Factory::NewFunctionFromBoilerplate(boilerplate,
+                                             i::Top::global_context());
+  return Local<Script>(ToApi<Script>(result));
+}
+
+
+Local<Script> Script::Compile(v8::Handle<String> source,
+                              v8::Handle<Value> file_name) {
+  ScriptOrigin origin(file_name);
+  return Compile(source, &origin);
+}
+
+
+Local<Value> Script::Run() {
+  ON_BAILOUT("v8::Script::Run()", return Local<Value>());
+  LOG_API("Script::Run");
+  ENTER_V8;
+  i::Object* raw_result = NULL;
+  {
+    HandleScope scope;
+    i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
+    EXCEPTION_PREAMBLE();
+    i::Handle<i::Object> receiver(i::Top::context()->global_proxy());
+    i::Handle<i::Object> result =
+        i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
+    EXCEPTION_BAILOUT_CHECK(Local<Value>());
+    raw_result = *result;
+  }
+  i::Handle<i::Object> result(raw_result);
+  return Utils::ToLocal(result);
+}
+
+
+Local<Value> Script::Id() {
+  ON_BAILOUT("v8::Script::Id()", return Local<Value>());
+  LOG_API("Script::Id");
+  i::Object* raw_id = NULL;
+  {
+    HandleScope scope;
+    i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
+    i::Handle<i::Script> script(i::Script::cast(fun->shared()->script()));
+    i::Handle<i::Object> id(script->id());
+    raw_id = *id;
+  }
+  i::Handle<i::Object> id(raw_id);
+  return Utils::ToLocal(id);
+}
+
+
+// --- E x c e p t i o n s ---
+
+
+v8::TryCatch::TryCatch()
+    : next_(i::Top::try_catch_handler()),
+      exception_(i::Heap::the_hole_value()),
+      message_(i::Smi::FromInt(0)),
+      is_verbose_(false),
+      capture_message_(true),
+      js_handler_(NULL) {
+  i::Top::RegisterTryCatchHandler(this);
+}
+
+
+v8::TryCatch::~TryCatch() {
+  i::Top::UnregisterTryCatchHandler(this);
+}
+
+
+bool v8::TryCatch::HasCaught() const {
+  return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
+}
+
+
+v8::Local<Value> v8::TryCatch::Exception() const {
+  if (HasCaught()) {
+    // Check for out of memory exception.
+    i::Object* exception = reinterpret_cast<i::Object*>(exception_);
+    return v8::Utils::ToLocal(i::Handle<i::Object>(exception));
+  } else {
+    return v8::Local<Value>();
+  }
+}
+
+
+v8::Local<v8::Message> v8::TryCatch::Message() const {
+  if (HasCaught() && message_ != i::Smi::FromInt(0)) {
+    i::Object* message = reinterpret_cast<i::Object*>(message_);
+    return v8::Utils::MessageToLocal(i::Handle<i::Object>(message));
+  } else {
+    return v8::Local<v8::Message>();
+  }
+}
+
+
+void v8::TryCatch::Reset() {
+  exception_ = i::Heap::the_hole_value();
+  message_ = i::Smi::FromInt(0);
+}
+
+
+void v8::TryCatch::SetVerbose(bool value) {
+  is_verbose_ = value;
+}
+
+
+void v8::TryCatch::SetCaptureMessage(bool value) {
+  capture_message_ = value;
+}
+
+
+// --- M e s s a g e ---
+
+
+Local<String> Message::Get() const {
+  ON_BAILOUT("v8::Message::Get()", return Local<String>());
+  ENTER_V8;
+  HandleScope scope;
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(obj);
+  Local<String> result = Utils::ToLocal(raw_result);
+  return scope.Close(result);
+}
+
+
+v8::Handle<Value> Message::GetScriptResourceName() const {
+  if (IsDeadCheck("v8::Message::GetScriptResourceName()")) {
+    return Local<String>();
+  }
+  ENTER_V8;
+  HandleScope scope;
+  i::Handle<i::JSObject> obj =
+      i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
+  // Return this.script.name.
+  i::Handle<i::JSValue> script =
+      i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
+  i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name());
+  return scope.Close(Utils::ToLocal(resource_name));
+}
+
+
+static i::Handle<i::Object> CallV8HeapFunction(const char* name,
+                                               i::Handle<i::Object> recv,
+                                               int argc,
+                                               i::Object** argv[],
+                                               bool* has_pending_exception) {
+  i::Handle<i::String> fmt_str = i::Factory::LookupAsciiSymbol(name);
+  i::Object* object_fun = i::Top::builtins()->GetProperty(*fmt_str);
+  i::Handle<i::JSFunction> fun =
+      i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
+  i::Handle<i::Object> value =
+      i::Execution::Call(fun, recv, argc, argv, has_pending_exception);
+  return value;
+}
+
+
+static i::Handle<i::Object> CallV8HeapFunction(const char* name,
+                                               i::Handle<i::Object> data,
+                                               bool* has_pending_exception) {
+  i::Object** argv[1] = { data.location() };
+  return CallV8HeapFunction(name,
+                            i::Top::builtins(),
+                            1,
+                            argv,
+                            has_pending_exception);
+}
+
+
+int Message::GetLineNumber() const {
+  ON_BAILOUT("v8::Message::GetLineNumber()", return -1);
+  ENTER_V8;
+  HandleScope scope;
+  EXCEPTION_PREAMBLE();
+  i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
+                                                   Utils::OpenHandle(this),
+                                                   &has_pending_exception);
+  EXCEPTION_BAILOUT_CHECK(0);
+  return static_cast<int>(result->Number());
+}
+
+
+int Message::GetStartPosition() const {
+  if (IsDeadCheck("v8::Message::GetStartPosition()")) return 0;
+  ENTER_V8;
+  HandleScope scope;
+
+  i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
+  return static_cast<int>(GetProperty(data_obj, "startPos")->Number());
+}
+
+
+int Message::GetEndPosition() const {
+  if (IsDeadCheck("v8::Message::GetEndPosition()")) return 0;
+  ENTER_V8;
+  HandleScope scope;
+  i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
+  return static_cast<int>(GetProperty(data_obj, "endPos")->Number());
+}
+
+
+int Message::GetStartColumn() const {
+  if (IsDeadCheck("v8::Message::GetStartColumn()")) return 0;
+  ENTER_V8;
+  HandleScope scope;
+  i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
+  EXCEPTION_PREAMBLE();
+  i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
+      "GetPositionInLine",
+      data_obj,
+      &has_pending_exception);
+  EXCEPTION_BAILOUT_CHECK(0);
+  return static_cast<int>(start_col_obj->Number());
+}
+
+
+int Message::GetEndColumn() const {
+  if (IsDeadCheck("v8::Message::GetEndColumn()")) return 0;
+  ENTER_V8;
+  HandleScope scope;
+  i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
+  EXCEPTION_PREAMBLE();
+  i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
+      "GetPositionInLine",
+      data_obj,
+      &has_pending_exception);
+  EXCEPTION_BAILOUT_CHECK(0);
+  int start = static_cast<int>(GetProperty(data_obj, "startPos")->Number());
+  int end = static_cast<int>(GetProperty(data_obj, "endPos")->Number());
+  return static_cast<int>(start_col_obj->Number()) + (end - start);
+}
+
+
+Local<String> Message::GetSourceLine() const {
+  ON_BAILOUT("v8::Message::GetSourceLine()", return Local<String>());
+  ENTER_V8;
+  HandleScope scope;
+  EXCEPTION_PREAMBLE();
+  i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
+                                                   Utils::OpenHandle(this),
+                                                   &has_pending_exception);
+  EXCEPTION_BAILOUT_CHECK(Local<v8::String>());
+  if (result->IsString()) {
+    return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result)));
+  } else {
+    return Local<String>();
+  }
+}
+
+
+void Message::PrintCurrentStackTrace(FILE* out) {
+  if (IsDeadCheck("v8::Message::PrintCurrentStackTrace()")) return;
+  ENTER_V8;
+  i::Top::PrintCurrentStackTrace(out);
+}
+
+
+// --- D a t a ---
+
+bool Value::IsUndefined() const {
+  if (IsDeadCheck("v8::Value::IsUndefined()")) return false;
+  return Utils::OpenHandle(this)->IsUndefined();
+}
+
+
+bool Value::IsNull() const {
+  if (IsDeadCheck("v8::Value::IsNull()")) return false;
+  return Utils::OpenHandle(this)->IsNull();
+}
+
+
+bool Value::IsTrue() const {
+  if (IsDeadCheck("v8::Value::IsTrue()")) return false;
+  return Utils::OpenHandle(this)->IsTrue();
+}
+
+
+bool Value::IsFalse() const {
+  if (IsDeadCheck("v8::Value::IsFalse()")) return false;
+  return Utils::OpenHandle(this)->IsFalse();
+}
+
+
+bool Value::IsFunction() const {
+  if (IsDeadCheck("v8::Value::IsFunction()")) return false;
+  return Utils::OpenHandle(this)->IsJSFunction();
+}
+
+
+bool Value::IsString() const {
+  if (IsDeadCheck("v8::Value::IsString()")) return false;
+  return Utils::OpenHandle(this)->IsString();
+}
+
+
+bool Value::IsArray() const {
+  if (IsDeadCheck("v8::Value::IsArray()")) return false;
+  return Utils::OpenHandle(this)->IsJSArray();
+}
+
+
+bool Value::IsObject() const {
+  if (IsDeadCheck("v8::Value::IsObject()")) return false;
+  return Utils::OpenHandle(this)->IsJSObject();
+}
+
+
+bool Value::IsNumber() const {
+  if (IsDeadCheck("v8::Value::IsNumber()")) return false;
+  return Utils::OpenHandle(this)->IsNumber();
+}
+
+
+bool Value::IsBoolean() const {
+  if (IsDeadCheck("v8::Value::IsBoolean()")) return false;
+  return Utils::OpenHandle(this)->IsBoolean();
+}
+
+
+bool Value::IsExternal() const {
+  if (IsDeadCheck("v8::Value::IsExternal()")) return false;
+  return Utils::OpenHandle(this)->IsProxy();
+}
+
+
+bool Value::IsInt32() const {
+  if (IsDeadCheck("v8::Value::IsInt32()")) return false;
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  if (obj->IsSmi()) return true;
+  if (obj->IsNumber()) {
+    double value = obj->Number();
+    return i::FastI2D(i::FastD2I(value)) == value;
+  }
+  return false;
+}
+
+
+bool Value::IsDate() const {
+  if (IsDeadCheck("v8::Value::IsDate()")) return false;
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  return obj->HasSpecificClassOf(i::Heap::Date_symbol());
+}
+
+
+Local<String> Value::ToString() const {
+  if (IsDeadCheck("v8::Value::ToString()")) return Local<String>();
+  LOG_API("ToString");
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  i::Handle<i::Object> str;
+  if (obj->IsString()) {
+    str = obj;
+  } else {
+    ENTER_V8;
+    EXCEPTION_PREAMBLE();
+    str = i::Execution::ToString(obj, &has_pending_exception);
+    EXCEPTION_BAILOUT_CHECK(Local<String>());
+  }
+  return Local<String>(ToApi<String>(str));
+}
+
+
+Local<String> Value::ToDetailString() const {
+  if (IsDeadCheck("v8::Value::ToDetailString()")) return Local<String>();
+  LOG_API("ToDetailString");
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  i::Handle<i::Object> str;
+  if (obj->IsString()) {
+    str = obj;
+  } else {
+    ENTER_V8;
+    EXCEPTION_PREAMBLE();
+    str = i::Execution::ToDetailString(obj, &has_pending_exception);
+    EXCEPTION_BAILOUT_CHECK(Local<String>());
+  }
+  return Local<String>(ToApi<String>(str));
+}
+
+
+Local<v8::Object> Value::ToObject() const {
+  if (IsDeadCheck("v8::Value::ToObject()")) return Local<v8::Object>();
+  LOG_API("ToObject");
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  i::Handle<i::Object> val;
+  if (obj->IsJSObject()) {
+    val = obj;
+  } else {
+    ENTER_V8;
+    EXCEPTION_PREAMBLE();
+    val = i::Execution::ToObject(obj, &has_pending_exception);
+    EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
+  }
+  return Local<v8::Object>(ToApi<Object>(val));
+}
+
+
+Local<Boolean> Value::ToBoolean() const {
+  if (IsDeadCheck("v8::Value::ToBoolean()")) return Local<Boolean>();
+  LOG_API("ToBoolean");
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  if (obj->IsBoolean()) {
+    return Local<Boolean>(ToApi<Boolean>(obj));
+  } else {
+    ENTER_V8;
+    i::Handle<i::Object> val = i::Execution::ToBoolean(obj);
+    return Local<Boolean>(ToApi<Boolean>(val));
+  }
+}
+
+
+Local<Number> Value::ToNumber() const {
+  if (IsDeadCheck("v8::Value::ToNumber()")) return Local<Number>();
+  LOG_API("ToNumber");
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  i::Handle<i::Object> num;
+  if (obj->IsNumber()) {
+    num = obj;
+  } else {
+    ENTER_V8;
+    EXCEPTION_PREAMBLE();
+    num = i::Execution::ToNumber(obj, &has_pending_exception);
+    EXCEPTION_BAILOUT_CHECK(Local<Number>());
+  }
+  return Local<Number>(ToApi<Number>(num));
+}
+
+
+Local<Integer> Value::ToInteger() const {
+  if (IsDeadCheck("v8::Value::ToInteger()")) return Local<Integer>();
+  LOG_API("ToInteger");
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  i::Handle<i::Object> num;
+  if (obj->IsSmi()) {
+    num = obj;
+  } else {
+    ENTER_V8;
+    EXCEPTION_PREAMBLE();
+    num = i::Execution::ToInteger(obj, &has_pending_exception);
+    EXCEPTION_BAILOUT_CHECK(Local<Integer>());
+  }
+  return Local<Integer>(ToApi<Integer>(num));
+}
+
+
+External* External::Cast(v8::Value* that) {
+  if (IsDeadCheck("v8::External::Cast()")) return 0;
+  i::Handle<i::Object> obj = Utils::OpenHandle(that);
+  ApiCheck(obj->IsProxy(),
+           "v8::External::Cast()",
+           "Could not convert to external");
+  return static_cast<External*>(that);
+}
+
+
+v8::Object* v8::Object::Cast(Value* that) {
+  if (IsDeadCheck("v8::Object::Cast()")) return 0;
+  i::Handle<i::Object> obj = Utils::OpenHandle(that);
+  ApiCheck(obj->IsJSObject(),
+           "v8::Object::Cast()",
+           "Could not convert to object");
+  return static_cast<v8::Object*>(that);
+}
+
+
+v8::Function* v8::Function::Cast(Value* that) {
+  if (IsDeadCheck("v8::Function::Cast()")) return 0;
+  i::Handle<i::Object> obj = Utils::OpenHandle(that);
+  ApiCheck(obj->IsJSFunction(),
+           "v8::Function::Cast()",
+           "Could not convert to function");
+  return static_cast<v8::Function*>(that);
+}
+
+
+v8::String* v8::String::Cast(v8::Value* that) {
+  if (IsDeadCheck("v8::String::Cast()")) return 0;
+  i::Handle<i::Object> obj = Utils::OpenHandle(that);
+  ApiCheck(obj->IsString(),
+           "v8::String::Cast()",
+           "Could not convert to string");
+  return static_cast<v8::String*>(that);
+}
+
+
+v8::Number* v8::Number::Cast(v8::Value* that) {
+  if (IsDeadCheck("v8::Number::Cast()")) return 0;
+  i::Handle<i::Object> obj = Utils::OpenHandle(that);
+  ApiCheck(obj->IsNumber(),
+           "v8::Number::Cast()",
+           "Could not convert to number");
+  return static_cast<v8::Number*>(that);
+}
+
+
+v8::Integer* v8::Integer::Cast(v8::Value* that) {
+  if (IsDeadCheck("v8::Integer::Cast()")) return 0;
+  i::Handle<i::Object> obj = Utils::OpenHandle(that);
+  ApiCheck(obj->IsNumber(),
+           "v8::Integer::Cast()",
+           "Could not convert to number");
+  return static_cast<v8::Integer*>(that);
+}
+
+
+v8::Array* v8::Array::Cast(Value* that) {
+  if (IsDeadCheck("v8::Array::Cast()")) return 0;
+  i::Handle<i::Object> obj = Utils::OpenHandle(that);
+  ApiCheck(obj->IsJSArray(),
+           "v8::Array::Cast()",
+           "Could not convert to array");
+  return static_cast<v8::Array*>(that);
+}
+
+
+v8::Date* v8::Date::Cast(v8::Value* that) {
+  if (IsDeadCheck("v8::Date::Cast()")) return 0;
+  i::Handle<i::Object> obj = Utils::OpenHandle(that);
+  ApiCheck(obj->HasSpecificClassOf(i::Heap::Date_symbol()),
+           "v8::Date::Cast()",
+           "Could not convert to date");
+  return static_cast<v8::Date*>(that);
+}
+
+
+bool Value::BooleanValue() const {
+  if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
+  LOG_API("BooleanValue");
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  if (obj->IsBoolean()) {
+    return obj->IsTrue();
+  } else {
+    ENTER_V8;
+    i::Handle<i::Object> value = i::Execution::ToBoolean(obj);
+    return value->IsTrue();
+  }
+}
+
+
+double Value::NumberValue() const {
+  if (IsDeadCheck("v8::Value::NumberValue()")) return i::OS::nan_value();
+  LOG_API("NumberValue");
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  i::Handle<i::Object> num;
+  if (obj->IsNumber()) {
+    num = obj;
+  } else {
+    ENTER_V8;
+    EXCEPTION_PREAMBLE();
+    num = i::Execution::ToNumber(obj, &has_pending_exception);
+    EXCEPTION_BAILOUT_CHECK(i::OS::nan_value());
+  }
+  return num->Number();
+}
+
+
+int64_t Value::IntegerValue() const {
+  if (IsDeadCheck("v8::Value::IntegerValue()")) return 0;
+  LOG_API("IntegerValue");
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  i::Handle<i::Object> num;
+  if (obj->IsNumber()) {
+    num = obj;
+  } else {
+    ENTER_V8;
+    EXCEPTION_PREAMBLE();
+    num = i::Execution::ToInteger(obj, &has_pending_exception);
+    EXCEPTION_BAILOUT_CHECK(0);
+  }
+  if (num->IsSmi()) {
+    return i::Smi::cast(*num)->value();
+  } else {
+    return static_cast<int64_t>(num->Number());
+  }
+}
+
+
+Local<Int32> Value::ToInt32() const {
+  if (IsDeadCheck("v8::Value::ToInt32()")) return Local<Int32>();
+  LOG_API("ToInt32");
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  i::Handle<i::Object> num;
+  if (obj->IsSmi()) {
+    num = obj;
+  } else {
+    ENTER_V8;
+    EXCEPTION_PREAMBLE();
+    num = i::Execution::ToInt32(obj, &has_pending_exception);
+    EXCEPTION_BAILOUT_CHECK(Local<Int32>());
+  }
+  return Local<Int32>(ToApi<Int32>(num));
+}
+
+
+Local<Uint32> Value::ToUint32() const {
+  if (IsDeadCheck("v8::Value::ToUint32()")) return Local<Uint32>();
+  LOG_API("ToUInt32");
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  i::Handle<i::Object> num;
+  if (obj->IsSmi()) {
+    num = obj;
+  } else {
+    ENTER_V8;
+    EXCEPTION_PREAMBLE();
+    num = i::Execution::ToUint32(obj, &has_pending_exception);
+    EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
+  }
+  return Local<Uint32>(ToApi<Uint32>(num));
+}
+
+
+Local<Uint32> Value::ToArrayIndex() const {
+  if (IsDeadCheck("v8::Value::ToArrayIndex()")) return Local<Uint32>();
+  LOG_API("ToArrayIndex");
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  if (obj->IsSmi()) {
+    if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
+    return Local<Uint32>();
+  }
+  ENTER_V8;
+  EXCEPTION_PREAMBLE();
+  i::Handle<i::Object> string_obj =
+      i::Execution::ToString(obj, &has_pending_exception);
+  EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
+  i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
+  uint32_t index;
+  if (str->AsArrayIndex(&index)) {
+    i::Handle<i::Object> value;
+    if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
+      value = i::Handle<i::Object>(i::Smi::FromInt(index));
+    } else {
+      value = i::Factory::NewNumber(index);
+    }
+    return Utils::Uint32ToLocal(value);
+  }
+  return Local<Uint32>();
+}
+
+
+int32_t Value::Int32Value() const {
+  if (IsDeadCheck("v8::Value::Int32Value()")) return 0;
+  LOG_API("Int32Value");
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  if (obj->IsSmi()) {
+    return i::Smi::cast(*obj)->value();
+  } else {
+    LOG_API("Int32Value (slow)");
+    ENTER_V8;
+    EXCEPTION_PREAMBLE();
+    i::Handle<i::Object> num =
+        i::Execution::ToInt32(obj, &has_pending_exception);
+    EXCEPTION_BAILOUT_CHECK(0);
+    if (num->IsSmi()) {
+      return i::Smi::cast(*num)->value();
+    } else {
+      return static_cast<int32_t>(num->Number());
+    }
+  }
+}
+
+
+bool Value::Equals(Handle<Value> that) const {
+  if (IsDeadCheck("v8::Value::Equals()")
+      || EmptyCheck("v8::Value::Equals()", this)
+      || EmptyCheck("v8::Value::Equals()", that)) {
+    return false;
+  }
+  LOG_API("Equals");
+  ENTER_V8;
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  i::Handle<i::Object> other = Utils::OpenHandle(*that);
+  i::Object** args[1] = { other.location() };
+  EXCEPTION_PREAMBLE();
+  i::Handle<i::Object> result =
+      CallV8HeapFunction("EQUALS", obj, 1, args, &has_pending_exception);
+  EXCEPTION_BAILOUT_CHECK(false);
+  return *result == i::Smi::FromInt(i::EQUAL);
+}
+
+
+bool Value::StrictEquals(Handle<Value> that) const {
+  if (IsDeadCheck("v8::Value::StrictEquals()")
+      || EmptyCheck("v8::Value::StrictEquals()", this)
+      || EmptyCheck("v8::Value::StrictEquals()", that)) {
+    return false;
+  }
+  LOG_API("StrictEquals");
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  i::Handle<i::Object> other = Utils::OpenHandle(*that);
+  // Must check HeapNumber first, since NaN !== NaN.
+  if (obj->IsHeapNumber()) {
+    if (!other->IsNumber()) return false;
+    double x = obj->Number();
+    double y = other->Number();
+    // Must check explicitly for NaN:s on Windows, but -0 works fine.
+    return x == y && !isnan(x) && !isnan(y);
+  } else if (*obj == *other) {  // Also covers Booleans.
+    return true;
+  } else if (obj->IsSmi()) {
+    return other->IsNumber() && obj->Number() == other->Number();
+  } else if (obj->IsString()) {
+    return other->IsString() &&
+      i::String::cast(*obj)->Equals(i::String::cast(*other));
+  } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
+    return other->IsUndefined() || other->IsUndetectableObject();
+  } else {
+    return false;
+  }
+}
+
+
+uint32_t Value::Uint32Value() const {
+  if (IsDeadCheck("v8::Value::Uint32Value()")) return 0;
+  LOG_API("Uint32Value");
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  if (obj->IsSmi()) {
+    return i::Smi::cast(*obj)->value();
+  } else {
+    ENTER_V8;
+    EXCEPTION_PREAMBLE();
+    i::Handle<i::Object> num =
+        i::Execution::ToUint32(obj, &has_pending_exception);
+    EXCEPTION_BAILOUT_CHECK(0);
+    if (num->IsSmi()) {
+      return i::Smi::cast(*num)->value();
+    } else {
+      return static_cast<uint32_t>(num->Number());
+    }
+  }
+}
+
+
+bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
+                     v8::PropertyAttribute attribs) {
+  ON_BAILOUT("v8::Object::Set()", return false);
+  ENTER_V8;
+  i::Handle<i::Object> self = Utils::OpenHandle(this);
+  i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
+  i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
+  EXCEPTION_PREAMBLE();
+  i::Handle<i::Object> obj = i::SetProperty(
+      self,
+      key_obj,
+      value_obj,
+      static_cast<PropertyAttributes>(attribs));
+  has_pending_exception = obj.is_null();
+  EXCEPTION_BAILOUT_CHECK(false);
+  return true;
+}
+
+
+Local<Value> v8::Object::Get(v8::Handle<Value> key) {
+  ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
+  ENTER_V8;
+  i::Handle<i::Object> self = Utils::OpenHandle(this);
+  i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
+  EXCEPTION_PREAMBLE();
+  i::Handle<i::Object> result = i::GetProperty(self, key_obj);
+  has_pending_exception = result.is_null();
+  EXCEPTION_BAILOUT_CHECK(Local<Value>());
+  return Utils::ToLocal(result);
+}
+
+
+Local<Value> v8::Object::GetPrototype() {
+  ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>());
+  ENTER_V8;
+  i::Handle<i::Object> self = Utils::OpenHandle(this);
+  i::Handle<i::Object> result = i::GetPrototype(self);
+  return Utils::ToLocal(result);
+}
+
+
+Local<Array> v8::Object::GetPropertyNames() {
+  ON_BAILOUT("v8::Object::GetPropertyNames()", return Local<v8::Array>());
+  ENTER_V8;
+  v8::HandleScope scope;
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::FixedArray> value = i::GetKeysInFixedArrayFor(self);
+  // Because we use caching to speed up enumeration it is important
+  // to never change the result of the basic enumeration function so
+  // we clone the result.
+  i::Handle<i::FixedArray> elms = i::Factory::CopyFixedArray(value);
+  i::Handle<i::JSArray> result = i::Factory::NewJSArrayWithElements(elms);
+  return scope.Close(Utils::ToLocal(result));
+}
+
+
+Local<String> v8::Object::ObjectProtoToString() {
+  ON_BAILOUT("v8::Object::ObjectProtoToString()", return Local<v8::String>());
+  ENTER_V8;
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+
+  i::Handle<i::Object> name(self->class_name());
+
+  // Native implementation of Object.prototype.toString (v8natives.js):
+  //   var c = %ClassOf(this);
+  //   if (c === 'Arguments') c  = 'Object';
+  //   return "[object " + c + "]";
+
+  if (!name->IsString()) {
+    return v8::String::New("[object ]");
+
+  } else {
+    i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
+    if (class_name->IsEqualTo(i::CStrVector("Arguments"))) {
+      return v8::String::New("[object Object]");
+
+    } else {
+      const char* prefix = "[object ";
+      Local<String> str = Utils::ToLocal(class_name);
+      const char* postfix = "]";
+
+      size_t prefix_len = strlen(prefix);
+      size_t str_len = str->Length();
+      size_t postfix_len = strlen(postfix);
+
+      size_t buf_len = prefix_len + str_len + postfix_len;
+      char* buf = i::NewArray<char>(buf_len);
+
+      // Write prefix.
+      char* ptr = buf;
+      memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize);
+      ptr += prefix_len;
+
+      // Write real content.
+      str->WriteAscii(ptr, 0, str_len);
+      ptr += str_len;
+
+      // Write postfix.
+      memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize);
+
+      // Copy the buffer into a heap-allocated string and return it.
+      Local<String> result = v8::String::New(buf, buf_len);
+      i::DeleteArray(buf);
+      return result;
+    }
+  }
+}
+
+
+bool v8::Object::Delete(v8::Handle<String> key) {
+  ON_BAILOUT("v8::Object::Delete()", return false);
+  ENTER_V8;
+  HandleScope scope;
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
+  return i::DeleteProperty(self, key_obj)->IsTrue();
+}
+
+
+bool v8::Object::Has(v8::Handle<String> key) {
+  ON_BAILOUT("v8::Object::Has()", return false);
+  ENTER_V8;
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
+  return self->HasProperty(*key_obj);
+}
+
+
+bool v8::Object::Delete(uint32_t index) {
+  ON_BAILOUT("v8::Object::DeleteProperty()", return false);
+  ENTER_V8;
+  HandleScope scope;
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  return i::DeleteElement(self, index)->IsTrue();
+}
+
+
+bool v8::Object::Has(uint32_t index) {
+  ON_BAILOUT("v8::Object::HasProperty()", return false);
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  return self->HasElement(index);
+}
+
+
+bool v8::Object::HasRealNamedProperty(Handle<String> key) {
+  ON_BAILOUT("v8::Object::HasRealNamedProperty()", return false);
+  return Utils::OpenHandle(this)->HasRealNamedProperty(
+      *Utils::OpenHandle(*key));
+}
+
+
+bool v8::Object::HasRealIndexedProperty(uint32_t index) {
+  ON_BAILOUT("v8::Object::HasRealIndexedProperty()", return false);
+  return Utils::OpenHandle(this)->HasRealElementProperty(index);
+}
+
+
+bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
+  ON_BAILOUT("v8::Object::HasRealNamedCallbackProperty()", return false);
+  ENTER_V8;
+  return Utils::OpenHandle(this)->HasRealNamedCallbackProperty(
+      *Utils::OpenHandle(*key));
+}
+
+
+bool v8::Object::HasNamedLookupInterceptor() {
+  ON_BAILOUT("v8::Object::HasNamedLookupInterceptor()", return false);
+  return Utils::OpenHandle(this)->HasNamedInterceptor();
+}
+
+
+bool v8::Object::HasIndexedLookupInterceptor() {
+  ON_BAILOUT("v8::Object::HasIndexedLookupInterceptor()", return false);
+  return Utils::OpenHandle(this)->HasIndexedInterceptor();
+}
+
+
+Handle<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
+      Handle<String> key) {
+  ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()",
+             return Local<Value>());
+  ENTER_V8;
+  i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
+  i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
+  i::LookupResult lookup;
+  self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
+  if (lookup.IsValid()) {
+    PropertyAttributes attributes;
+    i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
+                                                      &lookup,
+                                                      *key_obj,
+                                                      &attributes));
+    return Utils::ToLocal(result);
+  }
+  return Local<Value>();  // No real property was found in prototype chain.
+}
+
+
+// Turns on access checks by copying the map and setting the check flag.
+// Because the object gets a new map, existing inline cache caching
+// the old map of this object will fail.
+void v8::Object::TurnOnAccessCheck() {
+  ON_BAILOUT("v8::Object::TurnOnAccessCheck()", return);
+  ENTER_V8;
+  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
+
+  i::Handle<i::Map> new_map =
+    i::Factory::CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
+  new_map->set_is_access_check_needed(true);
+  obj->set_map(*new_map);
+}
+
+
+Local<v8::Object> v8::Object::Clone() {
+  ON_BAILOUT("v8::Object::Clone()", return Local<Object>());
+  ENTER_V8;
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  EXCEPTION_PREAMBLE();
+  i::Handle<i::JSObject> result = i::Copy(self);
+  has_pending_exception = result.is_null();
+  EXCEPTION_BAILOUT_CHECK(Local<Object>());
+  return Utils::ToLocal(result);
+}
+
+
+int v8::Object::GetIdentityHash() {
+  ON_BAILOUT("v8::Object::GetIdentityHash()", return 0);
+  ENTER_V8;
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
+  i::Handle<i::Object> hash_symbol = i::Factory::identity_hash_symbol();
+  i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
+  int hash_value;
+  if (hash->IsSmi()) {
+    hash_value = i::Smi::cast(*hash)->value();
+  } else {
+    hash_value = random() & i::Smi::kMaxValue;  // Limit range to fit a smi.
+    i::SetProperty(hidden_props,
+                   hash_symbol,
+                   i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
+                   static_cast<PropertyAttributes>(None));
+  }
+  return hash_value;
+}
+
+
+bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
+                                v8::Handle<v8::Value> value) {
+  ON_BAILOUT("v8::Object::SetHiddenValue()", return false);
+  ENTER_V8;
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
+  i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
+  i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
+  EXCEPTION_PREAMBLE();
+  i::Handle<i::Object> obj = i::SetProperty(
+      hidden_props,
+      key_obj,
+      value_obj,
+      static_cast<PropertyAttributes>(None));
+  has_pending_exception = obj.is_null();
+  EXCEPTION_BAILOUT_CHECK(false);
+  return true;
+}
+
+
+v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
+  ON_BAILOUT("v8::Object::GetHiddenValue()", return Local<v8::Value>());
+  ENTER_V8;
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
+  if (hidden_props->IsUndefined()) {
+    return v8::Local<v8::Value>();
+  }
+  i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
+  EXCEPTION_PREAMBLE();
+  i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj);
+  has_pending_exception = result.is_null();
+  EXCEPTION_BAILOUT_CHECK(v8::Local<v8::Value>());
+  if (result->IsUndefined()) {
+    return v8::Local<v8::Value>();
+  }
+  return Utils::ToLocal(result);
+}
+
+
+bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
+  ON_BAILOUT("v8::DeleteHiddenValue()", return false);
+  ENTER_V8;
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
+  if (hidden_props->IsUndefined()) {
+    return true;
+  }
+  i::Handle<i::JSObject> js_obj(i::JSObject::cast(*hidden_props));
+  i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
+  return i::DeleteProperty(js_obj, key_obj)->IsTrue();
+}
+
+
+Local<v8::Object> Function::NewInstance() const {
+  return NewInstance(0, NULL);
+}
+
+
+Local<v8::Object> Function::NewInstance(int argc,
+                                        v8::Handle<v8::Value> argv[]) const {
+  ON_BAILOUT("v8::Function::NewInstance()", return Local<v8::Object>());
+  LOG_API("Function::NewInstance");
+  ENTER_V8;
+  HandleScope scope;
+  i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
+  STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
+  i::Object*** args = reinterpret_cast<i::Object***>(argv);
+  EXCEPTION_PREAMBLE();
+  i::Handle<i::Object> returned =
+      i::Execution::New(function, argc, args, &has_pending_exception);
+  EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
+  return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
+}
+
+
+Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
+                                v8::Handle<v8::Value> argv[]) {
+  ON_BAILOUT("v8::Function::Call()", return Local<v8::Value>());
+  LOG_API("Function::Call");
+  ENTER_V8;
+  i::Object* raw_result = NULL;
+  {
+    HandleScope scope;
+    i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
+    i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
+    STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
+    i::Object*** args = reinterpret_cast<i::Object***>(argv);
+    EXCEPTION_PREAMBLE();
+    i::Handle<i::Object> returned =
+        i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
+    EXCEPTION_BAILOUT_CHECK(Local<Object>());
+    raw_result = *returned;
+  }
+  i::Handle<i::Object> result(raw_result);
+  return Utils::ToLocal(result);
+}
+
+
+void Function::SetName(v8::Handle<v8::String> name) {
+  ENTER_V8;
+  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
+  func->shared()->set_name(*Utils::OpenHandle(*name));
+}
+
+
+Handle<Value> Function::GetName() const {
+  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
+  return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name()));
+}
+
+
+int String::Length() const {
+  if (IsDeadCheck("v8::String::Length()")) return 0;
+  return Utils::OpenHandle(this)->length();
+}
+
+
+int String::Utf8Length() const {
+  if (IsDeadCheck("v8::String::Utf8Length()")) return 0;
+  return Utils::OpenHandle(this)->Utf8Length();
+}
+
+
+int String::WriteUtf8(char* buffer, int capacity) const {
+  if (IsDeadCheck("v8::String::WriteUtf8()")) return 0;
+  LOG_API("String::WriteUtf8");
+  ENTER_V8;
+  i::Handle<i::String> str = Utils::OpenHandle(this);
+  write_input_buffer.Reset(0, *str);
+  int len = str->length();
+  // Encode the first K - 3 bytes directly into the buffer since we
+  // know there's room for them.  If no capacity is given we copy all
+  // of them here.
+  int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
+  int i;
+  int pos = 0;
+  for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) {
+    i::uc32 c = write_input_buffer.GetNext();
+    int written = unibrow::Utf8::Encode(buffer + pos, c);
+    pos += written;
+  }
+  if (i < len) {
+    // For the last characters we need to check the length for each one
+    // because they may be longer than the remaining space in the
+    // buffer.
+    char intermediate[unibrow::Utf8::kMaxEncodedSize];
+    for (; i < len && pos < capacity; i++) {
+      i::uc32 c = write_input_buffer.GetNext();
+      int written = unibrow::Utf8::Encode(intermediate, c);
+      if (pos + written <= capacity) {
+        for (int j = 0; j < written; j++)
+          buffer[pos + j] = intermediate[j];
+        pos += written;
+      } else {
+        // We've reached the end of the buffer
+        break;
+      }
+    }
+  }
+  if (i == len && (capacity == -1 || pos < capacity))
+    buffer[pos++] = '\0';
+  return pos;
+}
+
+
+int String::WriteAscii(char* buffer, int start, int length) const {
+  if (IsDeadCheck("v8::String::WriteAscii()")) return 0;
+  LOG_API("String::WriteAscii");
+  ENTER_V8;
+  ASSERT(start >= 0 && length >= -1);
+  i::Handle<i::String> str = Utils::OpenHandle(this);
+  // Flatten the string for efficiency.  This applies whether we are
+  // using StringInputBuffer or Get(i) to access the characters.
+  str->TryFlattenIfNotFlat();
+  int end = length;
+  if ( (length == -1) || (length > str->length() - start) )
+    end = str->length() - start;
+  if (end < 0) return 0;
+  write_input_buffer.Reset(start, *str);
+  int i;
+  for (i = 0; i < end; i++) {
+    char c = static_cast<char>(write_input_buffer.GetNext());
+    if (c == '\0') c = ' ';
+    buffer[i] = c;
+  }
+  if (length == -1 || i < length)
+    buffer[i] = '\0';
+  return i;
+}
+
+
+int String::Write(uint16_t* buffer, int start, int length) const {
+  if (IsDeadCheck("v8::String::Write()")) return 0;
+  LOG_API("String::Write");
+  ENTER_V8;
+  ASSERT(start >= 0 && length >= -1);
+  i::Handle<i::String> str = Utils::OpenHandle(this);
+  // Flatten the string for efficiency.  This applies whether we are
+  // using StringInputBuffer or Get(i) to access the characters.
+  str->TryFlattenIfNotFlat();
+  int end = length;
+  if ( (length == -1) || (length > str->length() - start) )
+    end = str->length() - start;
+  if (end < 0) return 0;
+  write_input_buffer.Reset(start, *str);
+  int i;
+  for (i = 0; i < end; i++)
+    buffer[i] = write_input_buffer.GetNext();
+  if (length == -1 || i < length)
+    buffer[i] = '\0';
+  return i;
+}
+
+
+bool v8::String::IsExternal() const {
+  EnsureInitialized("v8::String::IsExternal()");
+  i::Handle<i::String> str = Utils::OpenHandle(this);
+  return i::StringShape(*str).IsExternalTwoByte();
+}
+
+
+bool v8::String::IsExternalAscii() const {
+  EnsureInitialized("v8::String::IsExternalAscii()");
+  i::Handle<i::String> str = Utils::OpenHandle(this);
+  return i::StringShape(*str).IsExternalAscii();
+}
+
+
+v8::String::ExternalStringResource*
+v8::String::GetExternalStringResource() const {
+  EnsureInitialized("v8::String::GetExternalStringResource()");
+  i::Handle<i::String> str = Utils::OpenHandle(this);
+  ASSERT(str->IsExternalTwoByteString());
+  void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
+  return reinterpret_cast<ExternalStringResource*>(resource);
+}
+
+
+v8::String::ExternalAsciiStringResource*
+      v8::String::GetExternalAsciiStringResource() const {
+  EnsureInitialized("v8::String::GetExternalAsciiStringResource()");
+  i::Handle<i::String> str = Utils::OpenHandle(this);
+  ASSERT(str->IsExternalAsciiString());
+  void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
+  return reinterpret_cast<ExternalAsciiStringResource*>(resource);
+}
+
+
+double Number::Value() const {
+  if (IsDeadCheck("v8::Number::Value()")) return 0;
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  return obj->Number();
+}
+
+
+bool Boolean::Value() const {
+  if (IsDeadCheck("v8::Boolean::Value()")) return false;
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  return obj->IsTrue();
+}
+
+
+int64_t Integer::Value() const {
+  if (IsDeadCheck("v8::Integer::Value()")) return 0;
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  if (obj->IsSmi()) {
+    return i::Smi::cast(*obj)->value();
+  } else {
+    return static_cast<int64_t>(obj->Number());
+  }
+}
+
+
+int32_t Int32::Value() const {
+  if (IsDeadCheck("v8::Int32::Value()")) return 0;
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  if (obj->IsSmi()) {
+    return i::Smi::cast(*obj)->value();
+  } else {
+    return static_cast<int32_t>(obj->Number());
+  }
+}
+
+
+int v8::Object::InternalFieldCount() {
+  if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0;
+  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
+  return obj->GetInternalFieldCount();
+}
+
+
+Local<Value> v8::Object::GetInternalField(int index) {
+  if (IsDeadCheck("v8::Object::GetInternalField()")) return Local<Value>();
+  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
+  if (!ApiCheck(index < obj->GetInternalFieldCount(),
+                "v8::Object::GetInternalField()",
+                "Reading internal field out of bounds")) {
+    return Local<Value>();
+  }
+  i::Handle<i::Object> value(obj->GetInternalField(index));
+  return Utils::ToLocal(value);
+}
+
+
+void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
+  if (IsDeadCheck("v8::Object::SetInternalField()")) return;
+  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
+  if (!ApiCheck(index < obj->GetInternalFieldCount(),
+                "v8::Object::SetInternalField()",
+                "Writing internal field out of bounds")) {
+    return;
+  }
+  ENTER_V8;
+  i::Handle<i::Object> val = Utils::OpenHandle(*value);
+  obj->SetInternalField(index, *val);
+}
+
+
+// --- E n v i r o n m e n t ---
+
+bool v8::V8::Initialize() {
+  if (i::V8::HasBeenSetup()) return true;
+  ENTER_V8;
+  HandleScope scope;
+  if (i::Snapshot::Initialize()) {
+    return true;
+  } else {
+    return i::V8::Initialize(NULL);
+  }
+}
+
+
+bool v8::V8::Dispose() {
+  i::V8::TearDown();
+  return true;
+}
+
+
+const char* v8::V8::GetVersion() {
+  return "1.1.10.4";
+}
+
+
+static i::Handle<i::FunctionTemplateInfo>
+    EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
+  if (templ->constructor()->IsUndefined()) {
+    Local<FunctionTemplate> constructor = FunctionTemplate::New();
+    Utils::OpenHandle(*constructor)->set_instance_template(*templ);
+    templ->set_constructor(*Utils::OpenHandle(*constructor));
+  }
+  return i::Handle<i::FunctionTemplateInfo>(
+    i::FunctionTemplateInfo::cast(templ->constructor()));
+}
+
+
+Persistent<Context> v8::Context::New(
+    v8::ExtensionConfiguration* extensions,
+    v8::Handle<ObjectTemplate> global_template,
+    v8::Handle<Value> global_object) {
+  EnsureInitialized("v8::Context::New()");
+  LOG_API("Context::New");
+  ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
+
+  // Enter V8 via an ENTER_V8 scope.
+  i::Handle<i::Context> env;
+  {
+    ENTER_V8;
+    // Give the heap a chance to cleanup if we've disposed contexts.
+    i::Heap::CollectAllGarbageIfContextDisposed();
+
+    v8::Handle<ObjectTemplate> proxy_template = global_template;
+    i::Handle<i::FunctionTemplateInfo> proxy_constructor;
+    i::Handle<i::FunctionTemplateInfo> global_constructor;
+
+    if (!global_template.IsEmpty()) {
+      // Make sure that the global_template has a constructor.
+      global_constructor =
+          EnsureConstructor(Utils::OpenHandle(*global_template));
+
+      // Create a fresh template for the global proxy object.
+      proxy_template = ObjectTemplate::New();
+      proxy_constructor =
+          EnsureConstructor(Utils::OpenHandle(*proxy_template));
+
+      // Set the global template to be the prototype template of
+      // global proxy template.
+      proxy_constructor->set_prototype_template(
+          *Utils::OpenHandle(*global_template));
+
+      // Migrate security handlers from global_template to
+      // proxy_template.  Temporarily removing access check
+      // information from the global template.
+      if (!global_constructor->access_check_info()->IsUndefined()) {
+        proxy_constructor->set_access_check_info(
+            global_constructor->access_check_info());
+        proxy_constructor->set_needs_access_check(
+            global_constructor->needs_access_check());
+        global_constructor->set_needs_access_check(false);
+        global_constructor->set_access_check_info(i::Heap::undefined_value());
+      }
+    }
+
+    // Create the environment.
+    env = i::Bootstrapper::CreateEnvironment(
+        Utils::OpenHandle(*global_object),
+        proxy_template,
+        extensions);
+
+    // Restore the access check info on the global template.
+    if (!global_template.IsEmpty()) {
+      ASSERT(!global_constructor.is_null());
+      ASSERT(!proxy_constructor.is_null());
+      global_constructor->set_access_check_info(
+          proxy_constructor->access_check_info());
+      global_constructor->set_needs_access_check(
+          proxy_constructor->needs_access_check());
+    }
+  }
+  // Leave V8.
+
+  if (!ApiCheck(!env.is_null(),
+                "v8::Context::New()",
+                "Could not initialize environment"))
+    return Persistent<Context>();
+  return Persistent<Context>(Utils::ToLocal(env));
+}
+
+
+void v8::Context::SetSecurityToken(Handle<Value> token) {
+  if (IsDeadCheck("v8::Context::SetSecurityToken()")) return;
+  ENTER_V8;
+  i::Handle<i::Context> env = Utils::OpenHandle(this);
+  i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
+  env->set_security_token(*token_handle);
+}
+
+
+void v8::Context::UseDefaultSecurityToken() {
+  if (IsDeadCheck("v8::Context::UseDefaultSecurityToken()")) return;
+  ENTER_V8;
+  i::Handle<i::Context> env = Utils::OpenHandle(this);
+  env->set_security_token(env->global());
+}
+
+
+Handle<Value> v8::Context::GetSecurityToken() {
+  if (IsDeadCheck("v8::Context::GetSecurityToken()")) return Handle<Value>();
+  i::Handle<i::Context> env = Utils::OpenHandle(this);
+  i::Object* security_token = env->security_token();
+  i::Handle<i::Object> token_handle(security_token);
+  return Utils::ToLocal(token_handle);
+}
+
+
+bool Context::HasOutOfMemoryException() {
+  i::Handle<i::Context> env = Utils::OpenHandle(this);
+  return env->has_out_of_memory();
+}
+
+
+bool Context::InContext() {
+  return i::Top::context() != NULL;
+}
+
+
+v8::Local<v8::Context> Context::GetEntered() {
+  if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
+  i::Handle<i::Object> last = thread_local.LastEnteredContext();
+  if (last.is_null()) return Local<Context>();
+  i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
+  return Utils::ToLocal(context);
+}
+
+
+v8::Local<v8::Context> Context::GetCurrent() {
+  if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
+  i::Handle<i::Context> context(i::Top::global_context());
+  return Utils::ToLocal(context);
+}
+
+
+v8::Local<v8::Object> Context::Global() {
+  if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
+  i::Object** ctx = reinterpret_cast<i::Object**>(this);
+  i::Handle<i::Context> context =
+      i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
+  i::Handle<i::Object> global(context->global_proxy());
+  return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
+}
+
+
+void Context::DetachGlobal() {
+  if (IsDeadCheck("v8::Context::DetachGlobal()")) return;
+  ENTER_V8;
+  i::Object** ctx = reinterpret_cast<i::Object**>(this);
+  i::Handle<i::Context> context =
+      i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
+  i::Bootstrapper::DetachGlobal(context);
+}
+
+
+Local<v8::Object> ObjectTemplate::NewInstance() {
+  ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
+  LOG_API("ObjectTemplate::NewInstance");
+  ENTER_V8;
+  EXCEPTION_PREAMBLE();
+  i::Handle<i::Object> obj =
+      i::Execution::InstantiateObject(Utils::OpenHandle(this),
+                                      &has_pending_exception);
+  EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
+  return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
+}
+
+
+Local<v8::Function> FunctionTemplate::GetFunction() {
+  ON_BAILOUT("v8::FunctionTemplate::GetFunction()",
+             return Local<v8::Function>());
+  LOG_API("FunctionTemplate::GetFunction");
+  ENTER_V8;
+  EXCEPTION_PREAMBLE();
+  i::Handle<i::Object> obj =
+      i::Execution::InstantiateFunction(Utils::OpenHandle(this),
+                                        &has_pending_exception);
+  EXCEPTION_BAILOUT_CHECK(Local<v8::Function>());
+  return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
+}
+
+
+bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
+  ON_BAILOUT("v8::FunctionTemplate::HasInstanceOf()", return false);
+  i::Object* obj = *Utils::OpenHandle(*value);
+  return obj->IsInstanceOf(*Utils::OpenHandle(this));
+}
+
+
+static Local<External> ExternalNewImpl(void* data) {
+  return Utils::ToLocal(i::Factory::NewProxy(static_cast<i::Address>(data)));
+}
+
+static void* ExternalValueImpl(i::Handle<i::Object> obj) {
+  return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy());
+}
+
+
+static const intptr_t kAlignedPointerMask = 3;
+static const int kAlignedPointerShift = 2;
+
+
+Local<Value> v8::External::Wrap(void* data) {
+  STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
+  LOG_API("External::Wrap");
+  EnsureInitialized("v8::External::Wrap()");
+  ENTER_V8;
+  if ((reinterpret_cast<intptr_t>(data) & kAlignedPointerMask) == 0) {
+    uintptr_t data_ptr = reinterpret_cast<uintptr_t>(data);
+    int data_value = static_cast<int>(data_ptr >> kAlignedPointerShift);
+    STATIC_ASSERT(sizeof(data_ptr) == sizeof(data_value));
+    i::Handle<i::Object> obj(i::Smi::FromInt(data_value));
+    return Utils::ToLocal(obj);
+  }
+  return ExternalNewImpl(data);
+}
+
+
+void* v8::External::Unwrap(v8::Handle<v8::Value> value) {
+  if (IsDeadCheck("v8::External::Unwrap()")) return 0;
+  i::Handle<i::Object> obj = Utils::OpenHandle(*value);
+  if (obj->IsSmi()) {
+    // The external value was an aligned pointer.
+    uintptr_t result = i::Smi::cast(*obj)->value() << kAlignedPointerShift;
+    return reinterpret_cast<void*>(result);
+  }
+  return ExternalValueImpl(obj);
+}
+
+
+Local<External> v8::External::New(void* data) {
+  STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
+  LOG_API("External::New");
+  EnsureInitialized("v8::External::New()");
+  ENTER_V8;
+  return ExternalNewImpl(data);
+}
+
+
+void* External::Value() const {
+  if (IsDeadCheck("v8::External::Value()")) return 0;
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  return ExternalValueImpl(obj);
+}
+
+
+Local<String> v8::String::Empty() {
+  EnsureInitialized("v8::String::Empty()");
+  LOG_API("String::Empty()");
+  return Utils::ToLocal(i::Factory::empty_symbol());
+}
+
+
+Local<String> v8::String::New(const char* data, int length) {
+  EnsureInitialized("v8::String::New()");
+  LOG_API("String::New(char)");
+  if (length == 0) return Empty();
+  ENTER_V8;
+  if (length == -1) length = strlen(data);
+  i::Handle<i::String> result =
+      i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
+  return Utils::ToLocal(result);
+}
+
+
+Local<String> v8::String::NewUndetectable(const char* data, int length) {
+  EnsureInitialized("v8::String::NewUndetectable()");
+  LOG_API("String::NewUndetectable(char)");
+  ENTER_V8;
+  if (length == -1) length = strlen(data);
+  i::Handle<i::String> result =
+      i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
+  result->MarkAsUndetectable();
+  return Utils::ToLocal(result);
+}
+
+
+static int TwoByteStringLength(const uint16_t* data) {
+  int length = 0;
+  while (data[length] != '\0') length++;
+  return length;
+}
+
+
+Local<String> v8::String::New(const uint16_t* data, int length) {
+  EnsureInitialized("v8::String::New()");
+  LOG_API("String::New(uint16_)");
+  if (length == 0) return Empty();
+  ENTER_V8;
+  if (length == -1) length = TwoByteStringLength(data);
+  i::Handle<i::String> result =
+      i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
+  return Utils::ToLocal(result);
+}
+
+
+Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) {
+  EnsureInitialized("v8::String::NewUndetectable()");
+  LOG_API("String::NewUndetectable(uint16_)");
+  ENTER_V8;
+  if (length == -1) length = TwoByteStringLength(data);
+  i::Handle<i::String> result =
+      i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
+  result->MarkAsUndetectable();
+  return Utils::ToLocal(result);
+}
+
+
+i::Handle<i::String> NewExternalStringHandle(
+      v8::String::ExternalStringResource* resource) {
+  i::Handle<i::String> result =
+      i::Factory::NewExternalStringFromTwoByte(resource);
+  return result;
+}
+
+
+i::Handle<i::String> NewExternalAsciiStringHandle(
+      v8::String::ExternalAsciiStringResource* resource) {
+  i::Handle<i::String> result =
+      i::Factory::NewExternalStringFromAscii(resource);
+  return result;
+}
+
+
+static void DisposeExternalString(v8::Persistent<v8::Value> obj,
+                                  void* parameter) {
+  ENTER_V8;
+  i::ExternalTwoByteString* str =
+      i::ExternalTwoByteString::cast(*Utils::OpenHandle(*obj));
+
+  // External symbols are deleted when they are pruned out of the symbol
+  // table. Generally external symbols are not registered with the weak handle
+  // callbacks unless they are upgraded to a symbol after being externalized.
+  if (!str->IsSymbol()) {
+    v8::String::ExternalStringResource* resource =
+        reinterpret_cast<v8::String::ExternalStringResource*>(parameter);
+    if (resource != NULL) {
+      const size_t total_size = resource->length() * sizeof(*resource->data());
+      i::Counters::total_external_string_memory.Decrement(total_size);
+
+      // The object will continue to live in the JavaScript heap until the
+      // handle is entirely cleaned out by the next GC. For example the
+      // destructor for the resource below could bring it back to life again.
+      // Which is why we make sure to not have a dangling pointer here.
+      str->set_resource(NULL);
+      delete resource;
+    }
+  }
+
+  // In any case we do not need this handle any longer.
+  obj.Dispose();
+}
+
+
+static void DisposeExternalAsciiString(v8::Persistent<v8::Value> obj,
+                                       void* parameter) {
+  ENTER_V8;
+  i::ExternalAsciiString* str =
+      i::ExternalAsciiString::cast(*Utils::OpenHandle(*obj));
+
+  // External symbols are deleted when they are pruned out of the symbol
+  // table. Generally external symbols are not registered with the weak handle
+  // callbacks unless they are upgraded to a symbol after being externalized.
+  if (!str->IsSymbol()) {
+    v8::String::ExternalAsciiStringResource* resource =
+        reinterpret_cast<v8::String::ExternalAsciiStringResource*>(parameter);
+    if (resource != NULL) {
+      const size_t total_size = resource->length() * sizeof(*resource->data());
+      i::Counters::total_external_string_memory.Decrement(total_size);
+
+      // The object will continue to live in the JavaScript heap until the
+      // handle is entirely cleaned out by the next GC. For example the
+      // destructor for the resource below could bring it back to life again.
+      // Which is why we make sure to not have a dangling pointer here.
+      str->set_resource(NULL);
+      delete resource;
+    }
+  }
+
+  // In any case we do not need this handle any longer.
+  obj.Dispose();
+}
+
+
+Local<String> v8::String::NewExternal(
+      v8::String::ExternalStringResource* resource) {
+  EnsureInitialized("v8::String::NewExternal()");
+  LOG_API("String::NewExternal");
+  ENTER_V8;
+  const size_t total_size = resource->length() * sizeof(*resource->data());
+  i::Counters::total_external_string_memory.Increment(total_size);
+  i::Handle<i::String> result = NewExternalStringHandle(resource);
+  i::Handle<i::Object> handle = i::GlobalHandles::Create(*result);
+  i::GlobalHandles::MakeWeak(handle.location(),
+                             resource,
+                             &DisposeExternalString);
+  return Utils::ToLocal(result);
+}
+
+
+bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
+  if (IsDeadCheck("v8::String::MakeExternal()")) return false;
+  if (this->IsExternal()) return false;  // Already an external string.
+  ENTER_V8;
+  i::Handle <i::String> obj = Utils::OpenHandle(this);
+  bool result = obj->MakeExternal(resource);
+  if (result && !obj->IsSymbol()) {
+    // Operation was successful and the string is not a symbol. In this case
+    // we need to make sure that the we call the destructor for the external
+    // resource when no strong references to the string remain.
+    i::Handle<i::Object> handle = i::GlobalHandles::Create(*obj);
+    i::GlobalHandles::MakeWeak(handle.location(),
+                               resource,
+                               &DisposeExternalString);
+  }
+  return result;
+}
+
+
+Local<String> v8::String::NewExternal(
+      v8::String::ExternalAsciiStringResource* resource) {
+  EnsureInitialized("v8::String::NewExternal()");
+  LOG_API("String::NewExternal");
+  ENTER_V8;
+  const size_t total_size = resource->length() * sizeof(*resource->data());
+  i::Counters::total_external_string_memory.Increment(total_size);
+  i::Handle<i::String> result = NewExternalAsciiStringHandle(resource);
+  i::Handle<i::Object> handle = i::GlobalHandles::Create(*result);
+  i::GlobalHandles::MakeWeak(handle.location(),
+                             resource,
+                             &DisposeExternalAsciiString);
+  return Utils::ToLocal(result);
+}
+
+
+bool v8::String::MakeExternal(
+    v8::String::ExternalAsciiStringResource* resource) {
+  if (IsDeadCheck("v8::String::MakeExternal()")) return false;
+  if (this->IsExternal()) return false;  // Already an external string.
+  ENTER_V8;
+  i::Handle <i::String> obj = Utils::OpenHandle(this);
+  bool result = obj->MakeExternal(resource);
+  if (result && !obj->IsSymbol()) {
+    // Operation was successful and the string is not a symbol. In this case
+    // we need to make sure that the we call the destructor for the external
+    // resource when no strong references to the string remain.
+    i::Handle<i::Object> handle = i::GlobalHandles::Create(*obj);
+    i::GlobalHandles::MakeWeak(handle.location(),
+                               resource,
+                               &DisposeExternalAsciiString);
+  }
+  return result;
+}
+
+
+Local<v8::Object> v8::Object::New() {
+  EnsureInitialized("v8::Object::New()");
+  LOG_API("Object::New");
+  ENTER_V8;
+  i::Handle<i::JSObject> obj =
+      i::Factory::NewJSObject(i::Top::object_function());
+  return Utils::ToLocal(obj);
+}
+
+
+Local<v8::Value> v8::Date::New(double time) {
+  EnsureInitialized("v8::Date::New()");
+  LOG_API("Date::New");
+  ENTER_V8;
+  EXCEPTION_PREAMBLE();
+  i::Handle<i::Object> obj =
+      i::Execution::NewDate(time, &has_pending_exception);
+  EXCEPTION_BAILOUT_CHECK(Local<v8::Value>());
+  return Utils::ToLocal(obj);
+}
+
+
+double v8::Date::NumberValue() const {
+  if (IsDeadCheck("v8::Date::NumberValue()")) return 0;
+  LOG_API("Date::NumberValue");
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
+  return jsvalue->value()->Number();
+}
+
+
+Local<v8::Array> v8::Array::New(int length) {
+  EnsureInitialized("v8::Array::New()");
+  LOG_API("Array::New");
+  ENTER_V8;
+  i::Handle<i::JSArray> obj = i::Factory::NewJSArray(length);
+  return Utils::ToLocal(obj);
+}
+
+
+uint32_t v8::Array::Length() const {
+  if (IsDeadCheck("v8::Array::Length()")) return 0;
+  i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
+  i::Object* length = obj->length();
+  if (length->IsSmi()) {
+    return i::Smi::cast(length)->value();
+  } else {
+    return static_cast<uint32_t>(length->Number());
+  }
+}
+
+
+Local<String> v8::String::NewSymbol(const char* data, int length) {
+  EnsureInitialized("v8::String::NewSymbol()");
+  LOG_API("String::NewSymbol(char)");
+  ENTER_V8;
+  if (length == -1) length = strlen(data);
+  i::Handle<i::String> result =
+      i::Factory::LookupSymbol(i::Vector<const char>(data, length));
+  return Utils::ToLocal(result);
+}
+
+
+Local<Number> v8::Number::New(double value) {
+  EnsureInitialized("v8::Number::New()");
+  ENTER_V8;
+  i::Handle<i::Object> result = i::Factory::NewNumber(value);
+  return Utils::NumberToLocal(result);
+}
+
+
+Local<Integer> v8::Integer::New(int32_t value) {
+  EnsureInitialized("v8::Integer::New()");
+  if (i::Smi::IsValid(value)) {
+    return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value)));
+  }
+  ENTER_V8;
+  i::Handle<i::Object> result = i::Factory::NewNumber(value);
+  return Utils::IntegerToLocal(result);
+}
+
+
+void V8::IgnoreOutOfMemoryException() {
+  thread_local.SetIgnoreOutOfMemory(true);
+}
+
+
+bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
+  EnsureInitialized("v8::V8::AddMessageListener()");
+  ON_BAILOUT("v8::V8::AddMessageListener()", return false);
+  ENTER_V8;
+  HandleScope scope;
+  NeanderArray listeners(i::Factory::message_listeners());
+  NeanderObject obj(2);
+  obj.set(0, *i::Factory::NewProxy(FUNCTION_ADDR(that)));
+  obj.set(1, data.IsEmpty() ?
+             i::Heap::undefined_value() :
+             *Utils::OpenHandle(*data));
+  listeners.add(obj.value());
+  return true;
+}
+
+
+void V8::RemoveMessageListeners(MessageCallback that) {
+  EnsureInitialized("v8::V8::RemoveMessageListener()");
+  ON_BAILOUT("v8::V8::RemoveMessageListeners()", return);
+  ENTER_V8;
+  HandleScope scope;
+  NeanderArray listeners(i::Factory::message_listeners());
+  for (int i = 0; i < listeners.length(); i++) {
+    if (listeners.get(i)->IsUndefined()) continue;  // skip deleted ones
+
+    NeanderObject listener(i::JSObject::cast(listeners.get(i)));
+    i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0)));
+    if (callback_obj->proxy() == FUNCTION_ADDR(that)) {
+      listeners.set(i, i::Heap::undefined_value());
+    }
+  }
+}
+
+
+void V8::SetCounterFunction(CounterLookupCallback callback) {
+  if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
+  i::StatsTable::SetCounterFunction(callback);
+}
+
+void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
+  if (IsDeadCheck("v8::V8::SetCreateHistogramFunction()")) return;
+  i::StatsTable::SetCreateHistogramFunction(callback);
+}
+
+void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
+  if (IsDeadCheck("v8::V8::SetAddHistogramSampleFunction()")) return;
+  i::StatsTable::SetAddHistogramSampleFunction(callback);
+}
+
+void V8::EnableSlidingStateWindow() {
+  if (IsDeadCheck("v8::V8::EnableSlidingStateWindow()")) return;
+  i::Logger::EnableSlidingStateWindow();
+}
+
+
+void V8::SetFailedAccessCheckCallbackFunction(
+      FailedAccessCheckCallback callback) {
+  if (IsDeadCheck("v8::V8::SetFailedAccessCheckCallbackFunction()")) return;
+  i::Top::SetFailedAccessCheckCallback(callback);
+}
+
+
+void V8::AddObjectGroup(Persistent<Value>* objects, size_t length) {
+  if (IsDeadCheck("v8::V8::AddObjectGroup()")) return;
+  STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
+  i::GlobalHandles::AddGroup(reinterpret_cast<i::Object***>(objects), length);
+}
+
+
+int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
+  if (IsDeadCheck("v8::V8::AdjustAmountOfExternalAllocatedMemory()")) return 0;
+  return i::Heap::AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
+}
+
+
+void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
+  if (IsDeadCheck("v8::V8::SetGlobalGCPrologueCallback()")) return;
+  i::Heap::SetGlobalGCPrologueCallback(callback);
+}
+
+
+void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
+  if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return;
+  i::Heap::SetGlobalGCEpilogueCallback(callback);
+}
+
+
+void V8::PauseProfiler() {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  i::Logger::PauseProfiler();
+#endif
+}
+
+void V8::ResumeProfiler() {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  i::Logger::ResumeProfiler();
+#endif
+}
+
+
+String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
+  EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
+  if (obj.IsEmpty()) {
+    str_ = NULL;
+    length_ = 0;
+    return;
+  }
+  ENTER_V8;
+  HandleScope scope;
+  TryCatch try_catch;
+  Handle<String> str = obj->ToString();
+  if (str.IsEmpty()) {
+    str_ = NULL;
+    length_ = 0;
+  } else {
+    length_ = str->Utf8Length();
+    str_ = i::NewArray<char>(length_ + 1);
+    str->WriteUtf8(str_);
+  }
+}
+
+
+String::Utf8Value::~Utf8Value() {
+  i::DeleteArray(str_);
+}
+
+
+String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) {
+  EnsureInitialized("v8::String::AsciiValue::AsciiValue()");
+  if (obj.IsEmpty()) {
+    str_ = NULL;
+    length_ = 0;
+    return;
+  }
+  ENTER_V8;
+  HandleScope scope;
+  TryCatch try_catch;
+  Handle<String> str = obj->ToString();
+  if (str.IsEmpty()) {
+    str_ = NULL;
+    length_ = 0;
+  } else {
+    length_ = str->Length();
+    str_ = i::NewArray<char>(length_ + 1);
+    str->WriteAscii(str_);
+  }
+}
+
+
+String::AsciiValue::~AsciiValue() {
+  i::DeleteArray(str_);
+}
+
+
+String::Value::Value(v8::Handle<v8::Value> obj) {
+  EnsureInitialized("v8::String::Value::Value()");
+  if (obj.IsEmpty()) {
+    str_ = NULL;
+    length_ = 0;
+    return;
+  }
+  ENTER_V8;
+  HandleScope scope;
+  TryCatch try_catch;
+  Handle<String> str = obj->ToString();
+  if (str.IsEmpty()) {
+    str_ = NULL;
+    length_ = 0;
+  } else {
+    length_ = str->Length();
+    str_ = i::NewArray<uint16_t>(length_ + 1);
+    str->Write(str_);
+  }
+}
+
+
+String::Value::~Value() {
+  i::DeleteArray(str_);
+}
+
+Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
+  LOG_API("RangeError");
+  ON_BAILOUT("v8::Exception::RangeError()", return Local<Value>());
+  ENTER_V8;
+  i::Object* error;
+  {
+    HandleScope scope;
+    i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
+    i::Handle<i::Object> result = i::Factory::NewRangeError(message);
+    error = *result;
+  }
+  i::Handle<i::Object> result(error);
+  return Utils::ToLocal(result);
+}
+
+Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
+  LOG_API("ReferenceError");
+  ON_BAILOUT("v8::Exception::ReferenceError()", return Local<Value>());
+  ENTER_V8;
+  i::Object* error;
+  {
+    HandleScope scope;
+    i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
+    i::Handle<i::Object> result = i::Factory::NewReferenceError(message);
+    error = *result;
+  }
+  i::Handle<i::Object> result(error);
+  return Utils::ToLocal(result);
+}
+
+Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
+  LOG_API("SyntaxError");
+  ON_BAILOUT("v8::Exception::SyntaxError()", return Local<Value>());
+  ENTER_V8;
+  i::Object* error;
+  {
+    HandleScope scope;
+    i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
+    i::Handle<i::Object> result = i::Factory::NewSyntaxError(message);
+    error = *result;
+  }
+  i::Handle<i::Object> result(error);
+  return Utils::ToLocal(result);
+}
+
+Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
+  LOG_API("TypeError");
+  ON_BAILOUT("v8::Exception::TypeError()", return Local<Value>());
+  ENTER_V8;
+  i::Object* error;
+  {
+    HandleScope scope;
+    i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
+    i::Handle<i::Object> result = i::Factory::NewTypeError(message);
+    error = *result;
+  }
+  i::Handle<i::Object> result(error);
+  return Utils::ToLocal(result);
+}
+
+Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
+  LOG_API("Error");
+  ON_BAILOUT("v8::Exception::Error()", return Local<Value>());
+  ENTER_V8;
+  i::Object* error;
+  {
+    HandleScope scope;
+    i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
+    i::Handle<i::Object> result = i::Factory::NewError(message);
+    error = *result;
+  }
+  i::Handle<i::Object> result(error);
+  return Utils::ToLocal(result);
+}
+
+
+// --- D e b u g   S u p p o r t ---
+
+
+bool Debug::SetDebugEventListener(DebugEventCallback that, Handle<Value> data) {
+  EnsureInitialized("v8::Debug::SetDebugEventListener()");
+  ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
+  ENTER_V8;
+  HandleScope scope;
+  i::Handle<i::Object> proxy = i::Factory::undefined_value();
+  if (that != NULL) {
+    proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
+  }
+  i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
+  return true;
+}
+
+
+bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
+                                  Handle<Value> data) {
+  ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
+  ENTER_V8;
+  i::Debugger::SetEventListener(Utils::OpenHandle(*that),
+                                Utils::OpenHandle(*data));
+  return true;
+}
+
+
+void Debug::DebugBreak() {
+  if (!i::V8::HasBeenSetup()) return;
+  i::StackGuard::DebugBreak();
+}
+
+
+void Debug::SetMessageHandler(v8::DebugMessageHandler handler, void* data,
+                              bool message_handler_thread) {
+  EnsureInitialized("v8::Debug::SetMessageHandler");
+  ENTER_V8;
+  i::Debugger::SetMessageHandler(handler, data, message_handler_thread);
+}
+
+
+void Debug::SendCommand(const uint16_t* command, int length) {
+  if (!i::V8::HasBeenSetup()) return;
+  i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length));
+}
+
+
+void Debug::SetHostDispatchHandler(v8::DebugHostDispatchHandler handler,
+                                   void* data) {
+  EnsureInitialized("v8::Debug::SetHostDispatchHandler");
+  ENTER_V8;
+  i::Debugger::SetHostDispatchHandler(handler, data);
+}
+
+
+void Debug::SendHostDispatch(void* dispatch) {
+  if (!i::V8::HasBeenSetup()) return;
+  i::Debugger::ProcessHostDispatch(dispatch);
+}
+
+
+Handle<Value> Debug::Call(v8::Handle<v8::Function> fun,
+                          v8::Handle<v8::Value> data) {
+  if (!i::V8::HasBeenSetup()) return Handle<Value>();
+  ON_BAILOUT("v8::Debug::Call()", return Handle<Value>());
+  ENTER_V8;
+  i::Handle<i::Object> result;
+  EXCEPTION_PREAMBLE();
+  if (data.IsEmpty()) {
+    result = i::Debugger::Call(Utils::OpenHandle(*fun),
+                               i::Factory::undefined_value(),
+                               &has_pending_exception);
+  } else {
+    result = i::Debugger::Call(Utils::OpenHandle(*fun),
+                               Utils::OpenHandle(*data),
+                               &has_pending_exception);
+  }
+  EXCEPTION_BAILOUT_CHECK(Local<Value>());
+  return Utils::ToLocal(result);
+}
+
+
+bool Debug::EnableAgent(const char* name, int port) {
+  return i::Debugger::StartAgent(name, port);
+}
+
+
+namespace internal {
+
+
+HandleScopeImplementer* HandleScopeImplementer::instance() {
+  return &thread_local;
+}
+
+
+char* HandleScopeImplementer::ArchiveThread(char* storage) {
+  return thread_local.ArchiveThreadHelper(storage);
+}
+
+
+char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) {
+  v8::ImplementationUtilities::HandleScopeData* current =
+      v8::ImplementationUtilities::CurrentHandleScope();
+  handle_scope_data_ = *current;
+  memcpy(storage, this, sizeof(*this));
+
+  Initialize();
+  current->Initialize();
+
+  return storage + ArchiveSpacePerThread();
+}
+
+
+int HandleScopeImplementer::ArchiveSpacePerThread() {
+  return sizeof(thread_local);
+}
+
+
+char* HandleScopeImplementer::RestoreThread(char* storage) {
+  return thread_local.RestoreThreadHelper(storage);
+}
+
+
+char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
+  memcpy(this, storage, sizeof(*this));
+  *v8::ImplementationUtilities::CurrentHandleScope() = handle_scope_data_;
+  return storage + ArchiveSpacePerThread();
+}
+
+
+void HandleScopeImplementer::Iterate(
+    ObjectVisitor* v,
+    List<void**>* blocks,
+    v8::ImplementationUtilities::HandleScopeData* handle_data) {
+  // Iterate over all handles in the blocks except for the last.
+  for (int i = blocks->length() - 2; i >= 0; --i) {
+    Object** block =
+        reinterpret_cast<Object**>(blocks->at(i));
+    v->VisitPointers(block, &block[kHandleBlockSize]);
+  }
+
+  // Iterate over live handles in the last block (if any).
+  if (!blocks->is_empty()) {
+    v->VisitPointers(reinterpret_cast<Object**>(blocks->last()),
+       reinterpret_cast<Object**>(handle_data->next));
+  }
+}
+
+
+void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
+  v8::ImplementationUtilities::HandleScopeData* current =
+      v8::ImplementationUtilities::CurrentHandleScope();
+  Iterate(v, thread_local.Blocks(), current);
+}
+
+
+char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
+  HandleScopeImplementer* thread_local =
+      reinterpret_cast<HandleScopeImplementer*>(storage);
+  List<void**>* blocks_of_archived_thread = thread_local->Blocks();
+  v8::ImplementationUtilities::HandleScopeData* handle_data_of_archived_thread =
+      &thread_local->handle_scope_data_;
+  Iterate(v, blocks_of_archived_thread, handle_data_of_archived_thread);
+
+  return storage + ArchiveSpacePerThread();
+}
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/api.h b/deps/v8/src/api.h
new file mode 100644
index 0000000..85b13ec
--- /dev/null
+++ b/deps/v8/src/api.h
@@ -0,0 +1,454 @@
+// Copyright 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_API_H_
+#define V8_API_H_
+
+#include "apiutils.h"
+#include "factory.h"
+
+namespace v8 {
+
+// Constants used in the implementation of the API.  The most natural thing
+// would usually be to place these with the classes that use them, but
+// we want to keep them out of v8.h because it is an externally
+// visible file.
+class Consts {
+ public:
+  enum TemplateType {
+    FUNCTION_TEMPLATE = 0,
+    OBJECT_TEMPLATE = 1
+  };
+};
+
+
+// Utilities for working with neander-objects, primitive
+// env-independent JSObjects used by the api.
+class NeanderObject {
+ public:
+  explicit NeanderObject(int size);
+  inline NeanderObject(v8::internal::Handle<v8::internal::Object> obj);
+  inline NeanderObject(v8::internal::Object* obj);
+  inline v8::internal::Object* get(int index);
+  inline void set(int index, v8::internal::Object* value);
+  inline v8::internal::Handle<v8::internal::JSObject> value() { return value_; }
+  int size();
+ private:
+  v8::internal::Handle<v8::internal::JSObject> value_;
+};
+
+
+// Utilities for working with neander-arrays, a simple extensible
+// array abstraction built on neander-objects.
+class NeanderArray {
+ public:
+  NeanderArray();
+  inline NeanderArray(v8::internal::Handle<v8::internal::Object> obj);
+  inline v8::internal::Handle<v8::internal::JSObject> value() {
+    return obj_.value();
+  }
+
+  void add(v8::internal::Handle<v8::internal::Object> value);
+
+  int length();
+
+  v8::internal::Object* get(int index);
+  // Change the value at an index to undefined value. If the index is
+  // out of bounds, the request is ignored. Returns the old value.
+  void set(int index, v8::internal::Object* value);
+ private:
+  NeanderObject obj_;
+};
+
+
+NeanderObject::NeanderObject(v8::internal::Handle<v8::internal::Object> obj)
+    : value_(v8::internal::Handle<v8::internal::JSObject>::cast(obj)) { }
+
+
+NeanderObject::NeanderObject(v8::internal::Object* obj)
+    : value_(v8::internal::Handle<v8::internal::JSObject>(
+        v8::internal::JSObject::cast(obj))) { }
+
+
+NeanderArray::NeanderArray(v8::internal::Handle<v8::internal::Object> obj)
+    : obj_(obj) { }
+
+
+v8::internal::Object* NeanderObject::get(int offset) {
+  ASSERT(value()->HasFastElements());
+  return v8::internal::FixedArray::cast(value()->elements())->get(offset);
+}
+
+
+void NeanderObject::set(int offset, v8::internal::Object* value) {
+  ASSERT(value_->HasFastElements());
+  v8::internal::FixedArray::cast(value_->elements())->set(offset, value);
+}
+
+
+template <typename T> static inline T ToCData(v8::internal::Object* obj) {
+  STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address));
+  return reinterpret_cast<T>(
+      reinterpret_cast<intptr_t>(v8::internal::Proxy::cast(obj)->proxy()));
+}
+
+
+template <typename T>
+static inline v8::internal::Handle<v8::internal::Object> FromCData(T obj) {
+  STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address));
+  return v8::internal::Factory::NewProxy(
+      reinterpret_cast<v8::internal::Address>(reinterpret_cast<intptr_t>(obj)));
+}
+
+
+v8::Arguments::Arguments(v8::Local<v8::Value> data,
+                         v8::Local<v8::Object> holder,
+                         v8::Local<v8::Function> callee,
+                         bool is_construct_call,
+                         void** values, int length)
+    : data_(data), holder_(holder), callee_(callee),
+      is_construct_call_(is_construct_call),
+      values_(values), length_(length) { }
+
+
+enum ExtensionTraversalState {
+  UNVISITED, VISITED, INSTALLED
+};
+
+
+class RegisteredExtension {
+ public:
+  explicit RegisteredExtension(Extension* extension);
+  static void Register(RegisteredExtension* that);
+  Extension* extension() { return extension_; }
+  RegisteredExtension* next() { return next_; }
+  RegisteredExtension* next_auto() { return next_auto_; }
+  ExtensionTraversalState state() { return state_; }
+  void set_state(ExtensionTraversalState value) { state_ = value; }
+  static RegisteredExtension* first_extension() { return first_extension_; }
+ private:
+  Extension* extension_;
+  RegisteredExtension* next_;
+  RegisteredExtension* next_auto_;
+  ExtensionTraversalState state_;
+  static RegisteredExtension* first_extension_;
+  static RegisteredExtension* first_auto_extension_;
+};
+
+
+class Utils {
+ public:
+  static bool ReportApiFailure(const char* location, const char* message);
+
+  static Local<FunctionTemplate> ToFunctionTemplate(NeanderObject obj);
+  static Local<ObjectTemplate> ToObjectTemplate(NeanderObject obj);
+
+  static inline Local<Context> ToLocal(
+      v8::internal::Handle<v8::internal::Context> obj);
+  static inline Local<Value> ToLocal(
+      v8::internal::Handle<v8::internal::Object> obj);
+  static inline Local<Function> ToLocal(
+      v8::internal::Handle<v8::internal::JSFunction> obj);
+  static inline Local<String> ToLocal(
+      v8::internal::Handle<v8::internal::String> obj);
+  static inline Local<Object> ToLocal(
+      v8::internal::Handle<v8::internal::JSObject> obj);
+  static inline Local<Array> ToLocal(
+      v8::internal::Handle<v8::internal::JSArray> obj);
+  static inline Local<External> ToLocal(
+      v8::internal::Handle<v8::internal::Proxy> obj);
+  static inline Local<Message> MessageToLocal(
+      v8::internal::Handle<v8::internal::Object> obj);
+  static inline Local<Number> NumberToLocal(
+      v8::internal::Handle<v8::internal::Object> obj);
+  static inline Local<Integer> IntegerToLocal(
+      v8::internal::Handle<v8::internal::Object> obj);
+  static inline Local<Uint32> Uint32ToLocal(
+      v8::internal::Handle<v8::internal::Object> obj);
+  static inline Local<FunctionTemplate> ToLocal(
+      v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj);
+  static inline Local<ObjectTemplate> ToLocal(
+      v8::internal::Handle<v8::internal::ObjectTemplateInfo> obj);
+  static inline Local<Signature> ToLocal(
+      v8::internal::Handle<v8::internal::SignatureInfo> obj);
+  static inline Local<TypeSwitch> ToLocal(
+      v8::internal::Handle<v8::internal::TypeSwitchInfo> obj);
+
+  static inline v8::internal::Handle<v8::internal::TemplateInfo>
+      OpenHandle(const Template* that);
+  static inline v8::internal::Handle<v8::internal::FunctionTemplateInfo>
+      OpenHandle(const FunctionTemplate* that);
+  static inline v8::internal::Handle<v8::internal::ObjectTemplateInfo>
+      OpenHandle(const ObjectTemplate* that);
+  static inline v8::internal::Handle<v8::internal::Object>
+      OpenHandle(const Data* data);
+  static inline v8::internal::Handle<v8::internal::JSObject>
+      OpenHandle(const v8::Object* data);
+  static inline v8::internal::Handle<v8::internal::JSArray>
+      OpenHandle(const v8::Array* data);
+  static inline v8::internal::Handle<v8::internal::String>
+      OpenHandle(const String* data);
+  static inline v8::internal::Handle<v8::internal::JSFunction>
+      OpenHandle(const Script* data);
+  static inline v8::internal::Handle<v8::internal::JSFunction>
+      OpenHandle(const Function* data);
+  static inline v8::internal::Handle<v8::internal::JSObject>
+      OpenHandle(const Message* message);
+  static inline v8::internal::Handle<v8::internal::Context>
+      OpenHandle(const v8::Context* context);
+  static inline v8::internal::Handle<v8::internal::SignatureInfo>
+      OpenHandle(const v8::Signature* sig);
+  static inline v8::internal::Handle<v8::internal::TypeSwitchInfo>
+      OpenHandle(const v8::TypeSwitch* that);
+  static inline v8::internal::Handle<v8::internal::Proxy>
+      OpenHandle(const v8::External* that);
+};
+
+
+template <class T>
+static inline T* ToApi(v8::internal::Handle<v8::internal::Object> obj) {
+  return reinterpret_cast<T*>(obj.location());
+}
+
+
+template <class T>
+v8::internal::Handle<T> v8::internal::Handle<T>::EscapeFrom(
+    v8::HandleScope* scope) {
+  return Utils::OpenHandle(*scope->Close(Utils::ToLocal(*this)));
+}
+
+
+// Implementations of ToLocal
+
+#define MAKE_TO_LOCAL(Name, From, To) \
+  Local<v8::To> Utils::Name(v8::internal::Handle<v8::internal::From> obj) { \
+    return Local<To>(reinterpret_cast<To*>(obj.location())); \
+  }
+
+MAKE_TO_LOCAL(ToLocal, Context, Context)
+MAKE_TO_LOCAL(ToLocal, Object, Value)
+MAKE_TO_LOCAL(ToLocal, JSFunction, Function)
+MAKE_TO_LOCAL(ToLocal, String, String)
+MAKE_TO_LOCAL(ToLocal, JSObject, Object)
+MAKE_TO_LOCAL(ToLocal, JSArray, Array)
+MAKE_TO_LOCAL(ToLocal, Proxy, External)
+MAKE_TO_LOCAL(ToLocal, FunctionTemplateInfo, FunctionTemplate)
+MAKE_TO_LOCAL(ToLocal, ObjectTemplateInfo, ObjectTemplate)
+MAKE_TO_LOCAL(ToLocal, SignatureInfo, Signature)
+MAKE_TO_LOCAL(ToLocal, TypeSwitchInfo, TypeSwitch)
+MAKE_TO_LOCAL(MessageToLocal, Object, Message)
+MAKE_TO_LOCAL(NumberToLocal, Object, Number)
+MAKE_TO_LOCAL(IntegerToLocal, Object, Integer)
+MAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32)
+
+#undef MAKE_TO_LOCAL
+
+
+// Implementations of OpenHandle
+
+#define MAKE_OPEN_HANDLE(From, To) \
+  v8::internal::Handle<v8::internal::To> Utils::OpenHandle(\
+    const v8::From* that) { \
+    return v8::internal::Handle<v8::internal::To>( \
+        reinterpret_cast<v8::internal::To**>(const_cast<v8::From*>(that))); \
+  }
+
+MAKE_OPEN_HANDLE(Template, TemplateInfo)
+MAKE_OPEN_HANDLE(FunctionTemplate, FunctionTemplateInfo)
+MAKE_OPEN_HANDLE(ObjectTemplate, ObjectTemplateInfo)
+MAKE_OPEN_HANDLE(Signature, SignatureInfo)
+MAKE_OPEN_HANDLE(TypeSwitch, TypeSwitchInfo)
+MAKE_OPEN_HANDLE(Data, Object)
+MAKE_OPEN_HANDLE(Object, JSObject)
+MAKE_OPEN_HANDLE(Array, JSArray)
+MAKE_OPEN_HANDLE(String, String)
+MAKE_OPEN_HANDLE(Script, JSFunction)
+MAKE_OPEN_HANDLE(Function, JSFunction)
+MAKE_OPEN_HANDLE(Message, JSObject)
+MAKE_OPEN_HANDLE(Context, Context)
+MAKE_OPEN_HANDLE(External, Proxy)
+
+#undef MAKE_OPEN_HANDLE
+
+
+namespace internal {
+
+// This class is here in order to be able to declare it a friend of
+// HandleScope.  Moving these methods to be members of HandleScope would be
+// neat in some ways, but it would expose external implementation details in
+// our public header file, which is undesirable.
+//
+// There is a singleton instance of this class to hold the per-thread data.
+// For multithreaded V8 programs this data is copied in and out of storage
+// so that the currently executing thread always has its own copy of this
+// data.
+class HandleScopeImplementer {
+ public:
+
+  HandleScopeImplementer()
+      : blocks(0),
+        entered_contexts_(0),
+        saved_contexts_(0) {
+    Initialize();
+  }
+
+  void Initialize() {
+    blocks.Initialize(0);
+    entered_contexts_.Initialize(0);
+    saved_contexts_.Initialize(0);
+    spare = NULL;
+    ignore_out_of_memory = false;
+    call_depth = 0;
+  }
+
+  static HandleScopeImplementer* instance();
+
+  // Threading support for handle data.
+  static int ArchiveSpacePerThread();
+  static char* RestoreThread(char* from);
+  static char* ArchiveThread(char* to);
+
+  // Garbage collection support.
+  static void Iterate(v8::internal::ObjectVisitor* v);
+  static char* Iterate(v8::internal::ObjectVisitor* v, char* data);
+
+
+  inline void** GetSpareOrNewBlock();
+  inline void DeleteExtensions(int extensions);
+
+  inline void IncrementCallDepth() {call_depth++;}
+  inline void DecrementCallDepth() {call_depth--;}
+  inline bool CallDepthIsZero() { return call_depth == 0; }
+
+  inline void EnterContext(Handle<Object> context);
+  inline bool LeaveLastContext();
+
+  // Returns the last entered context or an empty handle if no
+  // contexts have been entered.
+  inline Handle<Object> LastEnteredContext();
+
+  inline void SaveContext(Handle<Object> context);
+  inline Handle<Object> RestoreContext();
+  inline bool HasSavedContexts();
+
+  inline List<void**>* Blocks() { return &blocks; }
+
+  inline bool IgnoreOutOfMemory() { return ignore_out_of_memory; }
+  inline void SetIgnoreOutOfMemory(bool value) { ignore_out_of_memory = value; }
+
+ private:
+  List<void**> blocks;
+  Object** spare;
+  int call_depth;
+  // Used as a stack to keep track of entered contexts.
+  List<Handle<Object> > entered_contexts_;
+  // Used as a stack to keep track of saved contexts.
+  List<Handle<Object> > saved_contexts_;
+  bool ignore_out_of_memory;
+  // This is only used for threading support.
+  v8::ImplementationUtilities::HandleScopeData handle_scope_data_;
+
+  static void Iterate(ObjectVisitor* v,
+      List<void**>* blocks,
+      v8::ImplementationUtilities::HandleScopeData* handle_data);
+  char* RestoreThreadHelper(char* from);
+  char* ArchiveThreadHelper(char* to);
+
+  DISALLOW_COPY_AND_ASSIGN(HandleScopeImplementer);
+};
+
+
+static const int kHandleBlockSize = v8::internal::KB - 2;  // fit in one page
+
+
+void HandleScopeImplementer::SaveContext(Handle<Object> context) {
+  saved_contexts_.Add(context);
+}
+
+
+Handle<Object> HandleScopeImplementer::RestoreContext() {
+  return saved_contexts_.RemoveLast();
+}
+
+
+bool HandleScopeImplementer::HasSavedContexts() {
+  return !saved_contexts_.is_empty();
+}
+
+
+void HandleScopeImplementer::EnterContext(Handle<Object> context) {
+  entered_contexts_.Add(context);
+}
+
+
+bool HandleScopeImplementer::LeaveLastContext() {
+  if (entered_contexts_.is_empty()) return false;
+  entered_contexts_.RemoveLast();
+  return true;
+}
+
+
+Handle<Object> HandleScopeImplementer::LastEnteredContext() {
+  if (entered_contexts_.is_empty()) return Handle<Object>::null();
+  return entered_contexts_.last();
+}
+
+
+// If there's a spare block, use it for growing the current scope.
+void** HandleScopeImplementer::GetSpareOrNewBlock() {
+  void** block = (spare != NULL) ?
+      reinterpret_cast<void**>(spare) :
+      NewArray<void*>(kHandleBlockSize);
+  spare = NULL;
+  return block;
+}
+
+
+void HandleScopeImplementer::DeleteExtensions(int extensions) {
+  if (spare != NULL) {
+    DeleteArray(spare);
+    spare = NULL;
+  }
+  for (int i = extensions; i > 1; --i) {
+    void** block = blocks.RemoveLast();
+#ifdef DEBUG
+    v8::ImplementationUtilities::ZapHandleRange(block,
+                                                &block[kHandleBlockSize]);
+#endif
+    DeleteArray(block);
+  }
+  spare = reinterpret_cast<Object**>(blocks.RemoveLast());
+#ifdef DEBUG
+  v8::ImplementationUtilities::ZapHandleRange(
+      reinterpret_cast<void**>(spare),
+      reinterpret_cast<void**>(&spare[kHandleBlockSize]));
+#endif
+}
+
+} }  // namespace v8::internal
+
+#endif  // V8_API_H_
diff --git a/deps/v8/src/apinatives.js b/deps/v8/src/apinatives.js
new file mode 100644
index 0000000..2981eec
--- /dev/null
+++ b/deps/v8/src/apinatives.js
@@ -0,0 +1,109 @@
+// 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.
+
+// This file contains infrastructure used by the API.  See
+// v8natives.js for an explanation of these files are processed and
+// loaded.
+
+
+function CreateDate(time) {
+  var date = new ORIGINAL_DATE();
+  date.setTime(time);
+  return date;
+}
+
+
+const kApiFunctionCache = {};
+const functionCache = kApiFunctionCache;
+
+
+function Instantiate(data, name) {
+  if (!%IsTemplate(data)) return data;
+  var tag = %GetTemplateField(data, kApiTagOffset);
+  switch (tag) {
+    case kFunctionTag:
+      return InstantiateFunction(data, name);
+    case kNewObjectTag:
+      var Constructor = %GetTemplateField(data, kApiConstructorOffset);
+      var result = Constructor ? new (Instantiate(Constructor))() : {};
+      ConfigureTemplateInstance(result, data);
+      return result;
+    default:
+      throw 'Unknown API tag <' + tag + '>';
+  }
+}
+
+
+function InstantiateFunction(data, name) {
+  // We need a reference to kApiFunctionCache in the stack frame
+  // if we need to bail out from a stack overflow.
+  var cache = kApiFunctionCache;
+  var serialNumber = %GetTemplateField(data, kApiSerialNumberOffset);
+  var isFunctionCached =
+   (serialNumber in cache) && (cache[serialNumber] != kUninitialized);
+  if (!isFunctionCached) {
+    try {
+      cache[serialNumber] = null;
+      var fun = %CreateApiFunction(data);
+      if (name) %FunctionSetName(fun, name);
+      cache[serialNumber] = fun;
+      var prototype = %GetTemplateField(data, kApiPrototypeTemplateOffset);
+      fun.prototype = prototype ? Instantiate(prototype) : {};
+      %SetProperty(fun.prototype, "constructor", fun, DONT_ENUM);
+      var parent = %GetTemplateField(data, kApiParentTemplateOffset);
+      if (parent) {
+        var parent_fun = Instantiate(parent);
+        fun.prototype.__proto__ = parent_fun.prototype;
+      }
+      ConfigureTemplateInstance(fun, data);
+    } catch (e) {
+      cache[serialNumber] = kUninitialized;
+      throw e;
+    }
+  }
+  return cache[serialNumber];
+}
+
+
+function ConfigureTemplateInstance(obj, data) {
+  var properties = %GetTemplateField(data, kApiPropertyListOffset);
+  if (properties) {
+    // Disable access checks while instantiating the object.
+    var requires_access_checks = %DisableAccessChecks(obj);
+    try {
+      for (var i = 0; i < properties[0]; i += 3) {
+        var name = properties[i + 1];
+        var prop_data = properties[i + 2];
+        var attributes = properties[i + 3];
+        var value = Instantiate(prop_data, name);
+        %SetProperty(obj, name, value, attributes);
+      }
+    } finally {
+      if (requires_access_checks) %EnableAccessChecks(obj);
+    }
+  }
+}
diff --git a/deps/v8/src/apiutils.h b/deps/v8/src/apiutils.h
new file mode 100644
index 0000000..5745343
--- /dev/null
+++ b/deps/v8/src/apiutils.h
@@ -0,0 +1,69 @@
+// 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.
+
+#ifndef V8_APIUTILS_H_
+#define V8_APIUTILS_H_
+
+namespace v8 {
+
+class ImplementationUtilities {
+ public:
+  static v8::Handle<v8::Primitive> Undefined();
+  static v8::Handle<v8::Primitive> Null();
+  static v8::Handle<v8::Boolean> True();
+  static v8::Handle<v8::Boolean> False();
+
+  static int GetNameCount(ExtensionConfiguration* that) {
+    return that->name_count_;
+  }
+
+  static const char** GetNames(ExtensionConfiguration* that) {
+    return that->names_;
+  }
+
+  static v8::Arguments NewArguments(Local<Value> data,
+                                    Local<Object> holder,
+                                    Local<Function> callee,
+                                    bool is_construct_call,
+                                    void** argv, int argc) {
+    return v8::Arguments(data, holder, callee, is_construct_call, argv, argc);
+  }
+
+  // Introduce an alias for the handle scope data to allow non-friends
+  // to access the HandleScope data.
+  typedef v8::HandleScope::Data HandleScopeData;
+
+  static HandleScopeData* CurrentHandleScope();
+
+#ifdef DEBUG
+  static void ZapHandleRange(void** begin, void** end);
+#endif
+};
+
+}  // namespace v8
+
+#endif  // V8_APIUTILS_H_
diff --git a/deps/v8/src/arguments.h b/deps/v8/src/arguments.h
new file mode 100644
index 0000000..2ec68ed
--- /dev/null
+++ b/deps/v8/src/arguments.h
@@ -0,0 +1,70 @@
+// 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_ARGUMENTS_H_
+#define V8_ARGUMENTS_H_
+
+namespace v8 { namespace internal {
+
+// Arguments provides access to runtime call parameters.
+//
+// It uses the fact that the instance fields of Arguments
+// (length_, arguments_) are "overlayed" with the parameters
+// (no. of parameters, and the parameter pointer) passed so
+// that inside the C++ function, the parameters passed can
+// be accessed conveniently:
+//
+//   Object* Runtime_function(Arguments args) {
+//     ... use args[i] here ...
+//   }
+
+class Arguments BASE_EMBEDDED {
+ public:
+  Object*& operator[] (int index) {
+    ASSERT(0 <= index && index < length_);
+    return arguments_[-index];
+  }
+
+  template <class S> Handle<S> at(int index) {
+    Object** value = &((*this)[index]);
+    // This cast checks that the object we're accessing does indeed have the
+    // expected type.
+    S::cast(*value);
+    return Handle<S>(reinterpret_cast<S**>(value));
+  }
+
+  // Get the total number of arguments including the receiver.
+  int length() const { return length_; }
+
+ private:
+  int length_;
+  Object** arguments_;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_ARGUMENTS_H_
diff --git a/deps/v8/src/array.js b/deps/v8/src/array.js
new file mode 100644
index 0000000..d30a989
--- /dev/null
+++ b/deps/v8/src/array.js
@@ -0,0 +1,938 @@
+// 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.
+
+// This file relies on the fact that the following declarations have been made
+// in runtime.js:
+// const $Array = global.Array;
+
+// -------------------------------------------------------------------
+
+// Global list of arrays visited during toString, toLocaleString and
+// join invocations.
+var visited_arrays = new $Array();
+
+
+// Gets a sorted array of array keys.  Useful for operations on sparse
+// arrays.  Dupes have not been removed.
+function GetSortedArrayKeys(array, intervals) {
+  var length = intervals.length;
+  var keys = [];
+  for (var k = 0; k < length; k++) {
+    var key = intervals[k];
+    if (key < 0) {
+      var j = -1 - key;
+      var limit = j + intervals[++k];
+      for (; j < limit; j++) {
+        var e = array[j];
+        if (!IS_UNDEFINED(e) || j in array) {
+          keys.push(j);
+        }
+      }
+    } else {
+      // The case where key is undefined also ends here.
+      if (!IS_UNDEFINED(key)) {
+        var e = array[key];
+        if (!IS_UNDEFINED(e) || key in array) {
+          keys.push(key);
+        }
+      }
+    }
+  }
+  keys.sort(function(a, b) { return a - b; });
+  return keys;
+}
+
+
+// Optimized for sparse arrays if separator is ''.
+function SparseJoin(array, len, convert) {
+  var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len));
+  var builder = new StringBuilder();
+  var last_key = -1;
+  var keys_length = keys.length;
+  for (var i = 0; i < keys_length; i++) {
+    var key = keys[i];
+    if (key != last_key) {
+      var e = array[key];
+      builder.add(convert(e));
+      last_key = key;
+    }
+  }
+  return builder.generate();
+}
+
+
+function UseSparseVariant(object, length, is_array) {
+   return is_array &&
+       length > 1000 &&
+       (!%_IsSmi(length) ||
+        %EstimateNumberOfElements(object) < (length >> 2));
+}
+
+
+function Join(array, length, separator, convert) {
+  if (length == 0) return '';
+
+  var is_array = IS_ARRAY(array);
+
+  if (is_array) {
+    // If the array is cyclic, return the empty string for already
+    // visited arrays.
+    if (!%PushIfAbsent(visited_arrays, array)) return '';
+  }
+
+  // Attempt to convert the elements.
+  try {
+    if (UseSparseVariant(array, length, is_array) && separator === '') {
+      return SparseJoin(array, length, convert);
+    }
+
+    // Fast case for one-element arrays.
+    if (length == 1) {
+      var e = array[0];
+      if (!IS_UNDEFINED(e) || (0 in array)) {
+        return convert(e);
+      }
+    }
+
+    var builder = new StringBuilder();
+
+    for (var i = 0; i < length; i++) {
+      var e = array[i];
+      if (i != 0) builder.add(separator);
+      if (!IS_UNDEFINED(e) || (i in array)) {
+        builder.add(convert(e));
+      }
+    }
+    return builder.generate();
+  } finally {
+    // Make sure to pop the visited array no matter what happens.
+    if (is_array) visited_arrays.pop();
+  }
+}
+
+
+function ConvertToString(e) {
+  if (e == null) return '';
+  else return ToString(e);
+}
+
+
+function ConvertToLocaleString(e) {
+  if (e == null) return '';
+  else {
+    // e_obj's toLocaleString might be overwritten, check if it is a function.
+    // Call ToString if toLocaleString is not a function.
+    // See issue 877615.
+    var e_obj = ToObject(e);
+    if (IS_FUNCTION(e_obj.toLocaleString))
+      return e_obj.toLocaleString();
+    else
+      return ToString(e);
+  }
+}
+
+
+// This function implements the optimized splice implementation that can use
+// special array operations to handle sparse arrays in a sensible fashion.
+function SmartSlice(array, start_i, del_count, len, deleted_elements) {
+  // Move deleted elements to a new array (the return value from splice).
+  // Intervals array can contain keys and intervals.  See comment in Concat.
+  var intervals = %GetArrayKeys(array, start_i + del_count);
+  var length = intervals.length;
+  for (var k = 0; k < length; k++) {
+    var key = intervals[k];
+    if (key < 0) {
+      var j = -1 - key;
+      var interval_limit = j + intervals[++k];
+      if (j < start_i) {
+        j = start_i;
+      }
+      for (; j < interval_limit; j++) {
+        // ECMA-262 15.4.4.12 line 10.  The spec could also be
+        // interpreted such that %HasLocalProperty would be the
+        // appropriate test.  We follow KJS in consulting the
+        // prototype.
+        var current = array[j];
+        if (!IS_UNDEFINED(current) || j in array) {
+          deleted_elements[j - start_i] = current;
+        }
+      }
+    } else {
+      if (!IS_UNDEFINED(key)) {
+        if (key >= start_i) {
+          // ECMA-262 15.4.4.12 line 10.  The spec could also be
+          // interpreted such that %HasLocalProperty would be the
+          // appropriate test.  We follow KJS in consulting the
+          // prototype.
+          var current = array[key];
+          if (!IS_UNDEFINED(current) || key in array) {
+            deleted_elements[key - start_i] = current;
+          }
+        }
+      }
+    }
+  }
+}
+
+
+// This function implements the optimized splice implementation that can use
+// special array operations to handle sparse arrays in a sensible fashion.
+function SmartMove(array, start_i, del_count, len, num_additional_args) {
+  // Move data to new array.
+  var new_array = new $Array(len - del_count + num_additional_args);
+  var intervals = %GetArrayKeys(array, len);
+  var length = intervals.length;
+  for (var k = 0; k < length; k++) {
+    var key = intervals[k];
+    if (key < 0) {
+      var j = -1 - key;
+      var interval_limit = j + intervals[++k];
+      while (j < start_i && j < interval_limit) {
+        // The spec could also be interpreted such that
+        // %HasLocalProperty would be the appropriate test.  We follow
+        // KJS in consulting the prototype.
+        var current = array[j];
+        if (!IS_UNDEFINED(current) || j in array) {
+          new_array[j] = current;
+        }
+        j++;
+      }
+      j = start_i + del_count;
+      while (j < interval_limit) {
+        // ECMA-262 15.4.4.12 lines 24 and 41.  The spec could also be
+        // interpreted such that %HasLocalProperty would be the
+        // appropriate test.  We follow KJS in consulting the
+        // prototype.
+        var current = array[j];
+        if (!IS_UNDEFINED(current) || j in array) {
+          new_array[j - del_count + num_additional_args] = current;
+        }
+        j++;
+      }
+    } else {
+      if (!IS_UNDEFINED(key)) {
+        if (key < start_i) {
+          // The spec could also be interpreted such that
+          // %HasLocalProperty would be the appropriate test.  We follow
+          // KJS in consulting the prototype.
+          var current = array[key];
+          if (!IS_UNDEFINED(current) || key in array) {
+            new_array[key] = current;
+          }
+        } else if (key >= start_i + del_count) {
+          // ECMA-262 15.4.4.12 lines 24 and 41.  The spec could also
+          // be interpreted such that %HasLocalProperty would be the
+          // appropriate test.  We follow KJS in consulting the
+          // prototype.
+          var current = array[key];
+          if (!IS_UNDEFINED(current) || key in array) {
+            new_array[key - del_count + num_additional_args] = current;
+          }
+        }
+      }
+    }
+  }
+  // Move contents of new_array into this array
+  %MoveArrayContents(new_array, array);
+}
+
+
+// This is part of the old simple-minded splice.  We are using it either
+// because the receiver is not an array (so we have no choice) or because we
+// know we are not deleting or moving a lot of elements.
+function SimpleSlice(array, start_i, del_count, len, deleted_elements) {
+  for (var i = 0; i < del_count; i++) {
+    var index = start_i + i;
+    // The spec could also be interpreted such that %HasLocalProperty
+    // would be the appropriate test.  We follow KJS in consulting the
+    // prototype.
+    var current = array[index];
+    if (!IS_UNDEFINED(current) || index in array)
+      deleted_elements[i] = current;
+  }
+}
+
+
+function SimpleMove(array, start_i, del_count, len, num_additional_args) {
+  if (num_additional_args !== del_count) {
+    // Move the existing elements after the elements to be deleted
+    // to the right position in the resulting array.
+    if (num_additional_args > del_count) {
+      for (var i = len - del_count; i > start_i; i--) {
+        var from_index = i + del_count - 1;
+        var to_index = i + num_additional_args - 1;
+        // The spec could also be interpreted such that
+        // %HasLocalProperty would be the appropriate test.  We follow
+        // KJS in consulting the prototype.
+        var current = array[from_index];
+        if (!IS_UNDEFINED(current) || from_index in array) {
+          array[to_index] = current;
+        } else {
+          delete array[to_index];
+        }
+      }
+    } else {
+      for (var i = start_i; i < len - del_count; i++) {
+        var from_index = i + del_count;
+        var to_index = i + num_additional_args;
+        // The spec could also be interpreted such that
+        // %HasLocalProperty would be the appropriate test.  We follow
+        // KJS in consulting the prototype.
+        var current = array[from_index];
+        if (!IS_UNDEFINED(current) || from_index in array) {
+          array[to_index] = current;
+        } else {
+          delete array[to_index];
+        }
+      }
+      for (var i = len; i > len - del_count + num_additional_args; i--) {
+        delete array[i - 1];
+      }
+    }
+  }
+}
+
+
+// -------------------------------------------------------------------
+
+
+function ArrayToString() {
+  if (!IS_ARRAY(this)) {
+    throw new $TypeError('Array.prototype.toString is not generic');
+  }
+  return Join(this, this.length, ',', ConvertToString);
+}
+
+
+function ArrayToLocaleString() {
+  if (!IS_ARRAY(this)) {
+    throw new $TypeError('Array.prototype.toString is not generic');
+  }
+  return Join(this, this.length, ',', ConvertToLocaleString);
+}
+
+
+function ArrayJoin(separator) {
+  if (IS_UNDEFINED(separator)) separator = ',';
+  else separator = ToString(separator);
+  return Join(this, ToUint32(this.length), separator, ConvertToString);
+}
+
+
+// Removes the last element from the array and returns it. See
+// ECMA-262, section 15.4.4.6.
+function ArrayPop() {
+  var n = ToUint32(this.length);
+  if (n == 0) {
+    this.length = n;
+    return;
+  }
+  n--;
+  var value = this[n];
+  this.length = n;
+  delete this[n];
+  return value;
+}
+
+
+// Appends the arguments to the end of the array and returns the new
+// length of the array. See ECMA-262, section 15.4.4.7.
+function ArrayPush() {
+  var n = ToUint32(this.length);
+  var m = %_ArgumentsLength();
+  for (var i = 0; i < m; i++) {
+    this[i+n] = %_Arguments(i);
+  }
+  this.length = n + m;
+  return this.length;
+}
+
+
+function ArrayConcat(arg1) {  // length == 1
+  // TODO: can we just use arguments?
+  var arg_count = %_ArgumentsLength();
+  var arrays = new $Array(1 + arg_count);
+  arrays[0] = this;
+  for (var i = 0; i < arg_count; i++) {
+    arrays[i + 1] = %_Arguments(i);
+  }
+
+  return %ArrayConcat(arrays);
+}
+
+
+// For implementing reverse() on large, sparse arrays.
+function SparseReverse(array, len) {
+  var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len));
+  var high_counter = keys.length - 1;
+  var low_counter = 0;
+  while (low_counter <= high_counter) {
+    var i = keys[low_counter];
+    var j = keys[high_counter];
+
+    var j_complement = len - j - 1;
+    var low, high;
+
+    if (j_complement <= i) {
+      high = j;
+      while (keys[--high_counter] == j);
+      low = j_complement;
+    }
+    if (j_complement >= i) {
+      low = i;
+      while (keys[++low_counter] == i);
+      high = len - i - 1;
+    }
+
+    var current_i = array[low];
+    if (!IS_UNDEFINED(current_i) || low in array) {
+      var current_j = array[high];
+      if (!IS_UNDEFINED(current_j) || high in array) {
+        array[low] = current_j;
+        array[high] = current_i;
+      } else {
+        array[high] = current_i;
+        delete array[low];
+      }
+    } else {
+      var current_j = array[high];
+      if (!IS_UNDEFINED(current_j) || high in array) {
+        array[low] = current_j;
+        delete array[high];
+      }
+    }
+  }
+}
+
+
+function ArrayReverse() {
+  var j = ToUint32(this.length) - 1;
+
+  if (UseSparseVariant(this, j, IS_ARRAY(this))) {
+    SparseReverse(this, j+1);
+    return this;
+  }
+
+  for (var i = 0; i < j; i++, j--) {
+    var current_i = this[i];
+    if (!IS_UNDEFINED(current_i) || i in this) {
+      var current_j = this[j];
+      if (!IS_UNDEFINED(current_j) || j in this) {
+        this[i] = current_j;
+        this[j] = current_i;
+      } else {
+        this[j] = current_i;
+        delete this[i];
+      }
+    } else {
+      var current_j = this[j];
+      if (!IS_UNDEFINED(current_j) || j in this) {
+        this[i] = current_j;
+        delete this[j];
+      }
+    }
+  }
+  return this;
+}
+
+
+function ArrayShift() {
+  var len = ToUint32(this.length);
+
+  if (len === 0) {
+    this.length = 0;
+    return;
+  }
+
+  var first = this[0];
+
+  if (IS_ARRAY(this))
+    SmartMove(this, 0, 1, len, 0);
+  else
+    SimpleMove(this, 0, 1, len, 0);
+
+  this.length = len - 1;
+
+  return first;
+}
+
+
+function ArrayUnshift(arg1) {  // length == 1
+  var len = ToUint32(this.length);
+  var num_arguments = %_ArgumentsLength();
+
+  if (IS_ARRAY(this))
+    SmartMove(this, 0, 0, len, num_arguments);
+  else
+    SimpleMove(this, 0, 0, len, num_arguments);
+
+  for (var i = 0; i < num_arguments; i++) {
+    this[i] = %_Arguments(i);
+  }
+
+  this.length = len + num_arguments;
+
+  return len + num_arguments;
+}
+
+
+function ArraySlice(start, end) {
+  var len = ToUint32(this.length);
+  var start_i = TO_INTEGER(start);
+  var end_i = len;
+
+  if (end !== void 0) end_i = TO_INTEGER(end);
+
+  if (start_i < 0) {
+    start_i += len;
+    if (start_i < 0) start_i = 0;
+  } else {
+    if (start_i > len) start_i = len;
+  }
+
+  if (end_i < 0) {
+    end_i += len;
+    if (end_i < 0) end_i = 0;
+  } else {
+    if (end_i > len) end_i = len;
+  }
+
+  var result = [];
+
+  if (end_i < start_i) return result;
+
+  if (IS_ARRAY(this)) {
+    SmartSlice(this, start_i, end_i - start_i, len, result);
+  } else {
+    SimpleSlice(this, start_i, end_i - start_i, len, result);
+  }
+
+  result.length = end_i - start_i;
+
+  return result;
+}
+
+
+function ArraySplice(start, delete_count) {
+  var num_arguments = %_ArgumentsLength();
+
+  // SpiderMonkey and KJS return undefined in the case where no
+  // arguments are given instead of using the implicit undefined
+  // arguments.  This does not follow ECMA-262, but we do the same for
+  // compatibility.
+  if (num_arguments == 0) return;
+
+  var len = ToUint32(this.length);
+  var start_i = TO_INTEGER(start);
+
+  if (start_i < 0) {
+    start_i += len;
+    if (start_i < 0) start_i = 0;
+  } else {
+    if (start_i > len) start_i = len;
+  }
+
+  // SpiderMonkey and KJS treat the case where no delete count is
+  // given differently from when an undefined delete count is given.
+  // This does not follow ECMA-262, but we do the same for
+  // compatibility.
+  var del_count = 0;
+  if (num_arguments > 1) {
+    del_count = TO_INTEGER(delete_count);
+    if (del_count < 0) del_count = 0;
+    if (del_count > len - start_i) del_count = len - start_i;
+  } else {
+    del_count = len - start_i;
+  }
+
+  var deleted_elements = [];
+  deleted_elements.length = del_count;
+
+  // Number of elements to add.
+  var num_additional_args = 0;
+  if (num_arguments > 2) {
+    num_additional_args = num_arguments - 2;
+  }
+
+  var use_simple_splice = true;
+
+  if (IS_ARRAY(this) && num_additional_args !== del_count) {
+    // If we are only deleting/moving a few things near the end of the
+    // array then the simple version is going to be faster, because it
+    // doesn't touch most of the array.
+    var estimated_non_hole_elements = %EstimateNumberOfElements(this);
+    if (len > 20 && (estimated_non_hole_elements >> 2) < (len - start_i)) {
+      use_simple_splice = false;
+    }
+  }
+
+  if (use_simple_splice) {
+    SimpleSlice(this, start_i, del_count, len, deleted_elements);
+    SimpleMove(this, start_i, del_count, len, num_additional_args);
+  } else {
+    SmartSlice(this, start_i, del_count, len, deleted_elements);
+    SmartMove(this, start_i, del_count, len, num_additional_args);
+  }
+
+  // Insert the arguments into the resulting array in
+  // place of the deleted elements.
+  var i = start_i;
+  var arguments_index = 2;
+  var arguments_length = %_ArgumentsLength();
+  while (arguments_index < arguments_length) {
+    this[i++] = %_Arguments(arguments_index++);
+  }
+  this.length = len - del_count + num_additional_args;
+
+  // Return the deleted elements.
+  return deleted_elements;
+}
+
+
+function ArraySort(comparefn) {
+  // In-place QuickSort algorithm.
+  // For short (length <= 22) arrays, insertion sort is used for efficiency.
+
+  var custom_compare = IS_FUNCTION(comparefn);
+
+  function Compare(x,y) {
+    // Assume the comparefn, if any, is a consistent comparison function.
+    // If it isn't, we are allowed arbitrary behavior by ECMA 15.4.4.11.
+    if (x === y) return 0;
+    if (custom_compare) {
+      // Don't call directly to avoid exposing the builtin's global object.
+      return comparefn.call(null, x, y);
+    }
+    if (%_IsSmi(x) && %_IsSmi(y)) {
+      return %SmiLexicographicCompare(x, y);
+    }
+    x = ToString(x);
+    y = ToString(y);
+    if (x == y) return 0;
+    else return x < y ? -1 : 1;
+  };
+
+  function InsertionSort(a, from, to) {
+    for (var i = from + 1; i < to; i++) {
+      var element = a[i];
+      // Pre-convert the element to a string for comparison if we know
+      // it will happen on each compare anyway.
+      var key =
+          (custom_compare || %_IsSmi(element)) ? element : ToString(element);
+      // place element in a[from..i[
+      // binary search
+      var min = from;
+      var max = i;
+      // The search interval is a[min..max[
+      while (min < max) {
+        var mid = min + ((max - min) >> 1);
+        var order = Compare(a[mid], key);
+        if (order == 0) {
+          min = max = mid;
+          break;
+        }
+        if (order < 0) {
+          min = mid + 1;
+        } else {
+          max = mid;
+        }
+      }
+      // place element at position min==max.
+      for (var j = i; j > min; j--) {
+        a[j] = a[j - 1];
+      }
+      a[min] = element;
+    }
+  }
+
+  function QuickSort(a, from, to) {
+    // Insertion sort is faster for short arrays.
+    if (to - from <= 22) {
+      InsertionSort(a, from, to);
+      return;
+    }
+    var pivot_index = $floor($random() * (to - from)) + from;
+    var pivot = a[pivot_index];
+    // Pre-convert the element to a string for comparison if we know
+    // it will happen on each compare anyway.
+    var pivot_key =
+      (custom_compare || %_IsSmi(pivot)) ? pivot : ToString(pivot);
+    // Issue 95: Keep the pivot element out of the comparisons to avoid
+    // infinite recursion if comparefn(pivot, pivot) != 0.
+    a[pivot_index] = a[from];
+    a[from] = pivot;
+    var low_end = from;   // Upper bound of the elements lower than pivot.
+    var high_start = to;  // Lower bound of the elements greater than pivot.
+    // From low_end to i are elements equal to pivot.
+    // From i to high_start are elements that haven't been compared yet.
+    for (var i = from + 1; i < high_start; ) {
+      var element = a[i];
+      var order = Compare(element, pivot_key);
+      if (order < 0) {
+        a[i] = a[low_end];
+        a[low_end] = element;
+        i++;
+        low_end++;
+      } else if (order > 0) {
+        high_start--;
+        a[i] = a[high_start];
+        a[high_start] = element;
+      } else {  // order == 0
+        i++;
+      }
+    }
+    QuickSort(a, from, low_end);
+    QuickSort(a, high_start, to);
+  }
+
+  var old_length = ToUint32(this.length);
+  if (old_length < 2) return this;
+
+  %RemoveArrayHoles(this);
+
+  var length = ToUint32(this.length);
+
+  // Move undefined elements to the end of the array.
+  for (var i = 0; i < length; ) {
+    if (IS_UNDEFINED(this[i])) {
+      length--;
+      this[i] = this[length];
+      this[length] = void 0;
+    } else {
+      i++;
+    }
+  }
+
+  QuickSort(this, 0, length);
+
+  // We only changed the length of the this object (in
+  // RemoveArrayHoles) if it was an array.  We are not allowed to set
+  // the length of the this object if it is not an array because this
+  // might introduce a new length property.
+  if (IS_ARRAY(this)) {
+    this.length = old_length;
+  }
+
+  return this;
+}
+
+
+// The following functions cannot be made efficient on sparse arrays while
+// preserving the semantics, since the calls to the receiver function can add
+// or delete elements from the array.
+function ArrayFilter(f, receiver) {
+  if (!IS_FUNCTION(f)) {
+    throw MakeTypeError('called_non_callable', [ f ]);
+  }
+  // Pull out the length so that modifications to the length in the
+  // loop will not affect the looping.
+  var length = this.length;
+  var result = [];
+  var result_length = 0;
+  for (var i = 0; i < length; i++) {
+    var current = this[i];
+    if (!IS_UNDEFINED(current) || i in this) {
+      if (f.call(receiver, current, i, this)) result[result_length++] = current;
+    }
+  }
+  return result;
+}
+
+
+function ArrayForEach(f, receiver) {
+  if (!IS_FUNCTION(f)) {
+    throw MakeTypeError('called_non_callable', [ f ]);
+  }
+  // Pull out the length so that modifications to the length in the
+  // loop will not affect the looping.
+  var length = this.length;
+  for (var i = 0; i < length; i++) {
+    var current = this[i];
+    if (!IS_UNDEFINED(current) || i in this) {
+      f.call(receiver, current, i, this);
+    }
+  }
+}
+
+
+// Executes the function once for each element present in the
+// array until it finds one where callback returns true.
+function ArraySome(f, receiver) {
+  if (!IS_FUNCTION(f)) {
+    throw MakeTypeError('called_non_callable', [ f ]);
+  }
+  // Pull out the length so that modifications to the length in the
+  // loop will not affect the looping.
+  var length = this.length;
+  for (var i = 0; i < length; i++) {
+    var current = this[i];
+    if (!IS_UNDEFINED(current) || i in this) {
+      if (f.call(receiver, current, i, this)) return true;
+    }
+  }
+  return false;
+}
+
+
+function ArrayEvery(f, receiver) {
+  if (!IS_FUNCTION(f)) {
+    throw MakeTypeError('called_non_callable', [ f ]);
+  }
+  // Pull out the length so that modifications to the length in the
+  // loop will not affect the looping.
+  var length = this.length;
+  for (var i = 0; i < length; i++) {
+    var current = this[i];
+    if (!IS_UNDEFINED(current) || i in this) {
+      if (!f.call(receiver, current, i, this)) return false;
+    }
+  }
+
+  return true;
+}
+
+
+function ArrayMap(f, receiver) {
+  if (!IS_FUNCTION(f)) {
+    throw MakeTypeError('called_non_callable', [ f ]);
+  }
+  // Pull out the length so that modifications to the length in the
+  // loop will not affect the looping.
+  var length = this.length;
+  var result = new $Array(length);
+  for (var i = 0; i < length; i++) {
+    var current = this[i];
+    if (!IS_UNDEFINED(current) || i in this) {
+      result[i] = f.call(receiver, current, i, this);
+    }
+  }
+  return result;
+}
+
+
+function ArrayIndexOf(element, index) {
+  var length = this.length;
+  if (index == null) {
+    index = 0;
+  } else {
+    index = TO_INTEGER(index);
+    // If index is negative, index from the end of the array.
+    if (index < 0) index = length + index;
+    // If index is still negative, search the entire array.
+    if (index < 0) index = 0;
+  }
+  // Lookup through the array.
+  for (var i = index; i < length; i++) {
+    var current = this[i];
+    if (!IS_UNDEFINED(current) || i in this) {
+      if (current === element) return i;
+    }
+  }
+  return -1;
+}
+
+
+function ArrayLastIndexOf(element, index) {
+  var length = this.length;
+  if (index == null) {
+    index = length - 1;
+  } else {
+    index = TO_INTEGER(index);
+    // If index is negative, index from end of the array.
+    if (index < 0) index = length + index;
+    // If index is still negative, do not search the array.
+    if (index < 0) index = -1;
+    else if (index >= length) index = length - 1;
+  }
+  // Lookup through the array.
+  for (var i = index; i >= 0; i--) {
+    var current = this[i];
+    if (!IS_UNDEFINED(current) || i in this) {
+      if (current === element) return i;
+    }
+  }
+  return -1;
+}
+
+
+// -------------------------------------------------------------------
+
+
+function UpdateFunctionLengths(lengths) {
+  for (var key in lengths) {
+    %FunctionSetLength(this[key], lengths[key]);
+  }
+}
+
+
+// -------------------------------------------------------------------
+
+function SetupArray() {
+  // Setup non-enumerable constructor property on the Array.prototype
+  // object.
+  %SetProperty($Array.prototype, "constructor", $Array, DONT_ENUM);
+
+  // Setup non-enumerable functions of the Array.prototype object and
+  // set their names.
+  InstallFunctions($Array.prototype, DONT_ENUM, $Array(
+    "toString", ArrayToString,
+    "toLocaleString", ArrayToLocaleString,
+    "join", ArrayJoin,
+    "pop", ArrayPop,
+    "push", ArrayPush,
+    "concat", ArrayConcat,
+    "reverse", ArrayReverse,
+    "shift", ArrayShift,
+    "unshift", ArrayUnshift,
+    "slice", ArraySlice,
+    "splice", ArraySplice,
+    "sort", ArraySort,
+    "filter", ArrayFilter,
+    "forEach", ArrayForEach,
+    "some", ArraySome,
+    "every", ArrayEvery,
+    "map", ArrayMap,
+    "indexOf", ArrayIndexOf,
+    "lastIndexOf", ArrayLastIndexOf
+  ));
+
+  // Manipulate the length of some of the functions to meet
+  // expectations set by ECMA-262 or Mozilla.
+  UpdateFunctionLengths({
+    ArrayFilter: 1,
+    ArrayForEach: 1,
+    ArraySome: 1,
+    ArrayEvery: 1,
+    ArrayMap: 1,
+    ArrayIndexOf: 1,
+    ArrayLastIndexOf: 1,
+    ArrayPush: 1
+  });
+}
+
+
+SetupArray();
diff --git a/deps/v8/src/assembler-arm-inl.h b/deps/v8/src/assembler-arm-inl.h
new file mode 100644
index 0000000..315605e
--- /dev/null
+++ b/deps/v8/src/assembler-arm-inl.h
@@ -0,0 +1,249 @@
+// Copyright (c) 1994-2006 Sun Microsystems Inc.
+// 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.
+//
+// - Redistribution 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 Sun Microsystems or the names of 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.
+
+// The original source code covered by the above license above has been modified
+// significantly by Google Inc.
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+
+#ifndef V8_ASSEMBLER_ARM_INL_H_
+#define V8_ASSEMBLER_ARM_INL_H_
+
+#include "assembler-arm.h"
+#include "cpu.h"
+
+
+namespace v8 { namespace internal {
+
+Condition NegateCondition(Condition cc) {
+  ASSERT(cc != al);
+  return static_cast<Condition>(cc ^ ne);
+}
+
+
+void RelocInfo::apply(int delta) {
+  if (RelocInfo::IsInternalReference(rmode_)) {
+    // absolute code pointer inside code object moves with the code object.
+    int32_t* p = reinterpret_cast<int32_t*>(pc_);
+    *p += delta;  // relocate entry
+  }
+  // We do not use pc relative addressing on ARM, so there is
+  // nothing else to do.
+}
+
+
+Address RelocInfo::target_address() {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
+  return Assembler::target_address_at(pc_);
+}
+
+
+Address RelocInfo::target_address_address() {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
+  return reinterpret_cast<Address>(Assembler::target_address_address_at(pc_));
+}
+
+
+void RelocInfo::set_target_address(Address target) {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
+  Assembler::set_target_address_at(pc_, target);
+}
+
+
+Object* RelocInfo::target_object() {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
+  return reinterpret_cast<Object*>(Assembler::target_address_at(pc_));
+}
+
+
+Object** RelocInfo::target_object_address() {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
+  return reinterpret_cast<Object**>(Assembler::target_address_address_at(pc_));
+}
+
+
+void RelocInfo::set_target_object(Object* target) {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
+  Assembler::set_target_address_at(pc_, reinterpret_cast<Address>(target));
+}
+
+
+Address* RelocInfo::target_reference_address() {
+  ASSERT(rmode_ == EXTERNAL_REFERENCE);
+  return reinterpret_cast<Address*>(Assembler::target_address_address_at(pc_));
+}
+
+
+Address RelocInfo::call_address() {
+  ASSERT(IsCallInstruction());
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void RelocInfo::set_call_address(Address target) {
+  ASSERT(IsCallInstruction());
+  UNIMPLEMENTED();
+}
+
+
+Object* RelocInfo::call_object() {
+  ASSERT(IsCallInstruction());
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+Object** RelocInfo::call_object_address() {
+  ASSERT(IsCallInstruction());
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void RelocInfo::set_call_object(Object* target) {
+  ASSERT(IsCallInstruction());
+  UNIMPLEMENTED();
+}
+
+
+bool RelocInfo::IsCallInstruction() {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+Operand::Operand(int32_t immediate, RelocInfo::Mode rmode)  {
+  rm_ = no_reg;
+  imm32_ = immediate;
+  rmode_ = rmode;
+}
+
+
+Operand::Operand(const char* s) {
+  rm_ = no_reg;
+  imm32_ = reinterpret_cast<int32_t>(s);
+  rmode_ = RelocInfo::EMBEDDED_STRING;
+}
+
+
+Operand::Operand(const ExternalReference& f)  {
+  rm_ = no_reg;
+  imm32_ = reinterpret_cast<int32_t>(f.address());
+  rmode_ = RelocInfo::EXTERNAL_REFERENCE;
+}
+
+
+Operand::Operand(Object** opp) {
+  rm_ = no_reg;
+  imm32_ = reinterpret_cast<int32_t>(opp);
+  rmode_ = RelocInfo::NONE;
+}
+
+
+Operand::Operand(Context** cpp) {
+  rm_ = no_reg;
+  imm32_ = reinterpret_cast<int32_t>(cpp);
+  rmode_ = RelocInfo::NONE;
+}
+
+
+Operand::Operand(Smi* value) {
+  rm_ = no_reg;
+  imm32_ =  reinterpret_cast<intptr_t>(value);
+  rmode_ = RelocInfo::NONE;
+}
+
+
+Operand::Operand(Register rm) {
+  rm_ = rm;
+  rs_ = no_reg;
+  shift_op_ = LSL;
+  shift_imm_ = 0;
+}
+
+
+bool Operand::is_reg() const {
+  return rm_.is_valid() &&
+         rs_.is(no_reg) &&
+         shift_op_ == LSL &&
+         shift_imm_ == 0;
+}
+
+
+void Assembler::CheckBuffer() {
+  if (buffer_space() <= kGap) {
+    GrowBuffer();
+  }
+  if (pc_offset() > next_buffer_check_) {
+    CheckConstPool(false, true);
+  }
+}
+
+
+void Assembler::emit(Instr x) {
+  CheckBuffer();
+  *reinterpret_cast<Instr*>(pc_) = x;
+  pc_ += kInstrSize;
+}
+
+
+Address Assembler::target_address_address_at(Address pc) {
+  Instr instr = Memory::int32_at(pc);
+  // Verify that the instruction at pc is a ldr<cond> <Rd>, [pc +/- offset_12].
+  ASSERT((instr & 0x0f7f0000) == 0x051f0000);
+  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.
+  ASSERT(offset >= -4);
+  return pc + offset + 8;
+}
+
+
+Address Assembler::target_address_at(Address pc) {
+  return Memory::Address_at(target_address_address_at(pc));
+}
+
+
+void Assembler::set_target_address_at(Address pc, Address target) {
+  Memory::Address_at(target_address_address_at(pc)) = target;
+  // Intuitively, we would think it is necessary to flush the instruction cache
+  // after patching a target address in the code as follows:
+  //   CPU::FlushICache(pc, sizeof(target));
+  // However, on ARM, no instruction was actually patched by the assignment
+  // above; the target address is not part of an instruction, it is patched in
+  // the constant pool and is read via a data access; the instruction accessing
+  // this address in the constant pool remains unchanged.
+}
+
+} }  // namespace v8::internal
+
+#endif  // V8_ASSEMBLER_ARM_INL_H_
diff --git a/deps/v8/src/assembler-arm.cc b/deps/v8/src/assembler-arm.cc
new file mode 100644
index 0000000..ba7638e
--- /dev/null
+++ b/deps/v8/src/assembler-arm.cc
@@ -0,0 +1,1471 @@
+// Copyright (c) 1994-2006 Sun Microsystems Inc.
+// 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.
+//
+// - Redistribution 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 Sun Microsystems or the names of 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.
+
+// The original source code covered by the above license above has been modified
+// significantly by Google Inc.
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+
+#include "v8.h"
+
+#include "assembler-arm-inl.h"
+#include "serialize.h"
+
+namespace v8 { namespace internal {
+
+// -----------------------------------------------------------------------------
+// Implementation of Register and CRegister
+
+Register no_reg = { -1 };
+
+Register r0  = {  0 };
+Register r1  = {  1 };
+Register r2  = {  2 };
+Register r3  = {  3 };
+Register r4  = {  4 };
+Register r5  = {  5 };
+Register r6  = {  6 };
+Register r7  = {  7 };
+Register r8  = {  8 };
+Register r9  = {  9 };
+Register r10 = { 10 };
+Register fp  = { 11 };
+Register ip  = { 12 };
+Register sp  = { 13 };
+Register lr  = { 14 };
+Register pc  = { 15 };
+
+
+CRegister no_creg = { -1 };
+
+CRegister cr0  = {  0 };
+CRegister cr1  = {  1 };
+CRegister cr2  = {  2 };
+CRegister cr3  = {  3 };
+CRegister cr4  = {  4 };
+CRegister cr5  = {  5 };
+CRegister cr6  = {  6 };
+CRegister cr7  = {  7 };
+CRegister cr8  = {  8 };
+CRegister cr9  = {  9 };
+CRegister cr10 = { 10 };
+CRegister cr11 = { 11 };
+CRegister cr12 = { 12 };
+CRegister cr13 = { 13 };
+CRegister cr14 = { 14 };
+CRegister cr15 = { 15 };
+
+
+// -----------------------------------------------------------------------------
+// Implementation of RelocInfo
+
+const int RelocInfo::kApplyMask = 0;
+
+
+void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
+  // Patch the code at the current address with the supplied instructions.
+  UNIMPLEMENTED();
+}
+
+
+// Patch the code at the current PC with a call to the target address.
+// Additional guard instructions can be added if required.
+void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
+  // Patch the code at the current address with a call to the target.
+  UNIMPLEMENTED();
+}
+
+
+// -----------------------------------------------------------------------------
+// Implementation of Operand and MemOperand
+// See assembler-arm-inl.h for inlined constructors
+
+Operand::Operand(Handle<Object> handle) {
+  rm_ = no_reg;
+  // Verify all Objects referred by code are NOT in new space.
+  Object* obj = *handle;
+  ASSERT(!Heap::InNewSpace(obj));
+  if (obj->IsHeapObject()) {
+    imm32_ = reinterpret_cast<intptr_t>(handle.location());
+    rmode_ = RelocInfo::EMBEDDED_OBJECT;
+  } else {
+    // no relocation needed
+    imm32_ =  reinterpret_cast<intptr_t>(obj);
+    rmode_ = RelocInfo::NONE;
+  }
+}
+
+
+Operand::Operand(Register rm, ShiftOp shift_op, int shift_imm) {
+  ASSERT(is_uint5(shift_imm));
+  ASSERT(shift_op != ROR || shift_imm != 0);  // use RRX if you mean it
+  rm_ = rm;
+  rs_ = no_reg;
+  shift_op_ = shift_op;
+  shift_imm_ = shift_imm & 31;
+  if (shift_op == RRX) {
+    // encoded as ROR with shift_imm == 0
+    ASSERT(shift_imm == 0);
+    shift_op_ = ROR;
+    shift_imm_ = 0;
+  }
+}
+
+
+Operand::Operand(Register rm, ShiftOp shift_op, Register rs) {
+  ASSERT(shift_op != RRX);
+  rm_ = rm;
+  rs_ = no_reg;
+  shift_op_ = shift_op;
+  rs_ = rs;
+}
+
+
+MemOperand::MemOperand(Register rn, int32_t offset, AddrMode am) {
+  rn_ = rn;
+  rm_ = no_reg;
+  offset_ = offset;
+  am_ = am;
+}
+
+MemOperand::MemOperand(Register rn, Register rm, AddrMode am) {
+  rn_ = rn;
+  rm_ = rm;
+  shift_op_ = LSL;
+  shift_imm_ = 0;
+  am_ = am;
+}
+
+
+MemOperand::MemOperand(Register rn, Register rm,
+                       ShiftOp shift_op, int shift_imm, AddrMode am) {
+  ASSERT(is_uint5(shift_imm));
+  rn_ = rn;
+  rm_ = rm;
+  shift_op_ = shift_op;
+  shift_imm_ = shift_imm & 31;
+  am_ = am;
+}
+
+
+// -----------------------------------------------------------------------------
+// Implementation of Assembler
+
+// Instruction encoding bits
+enum {
+  H   = 1 << 5,   // halfword (or byte)
+  S6  = 1 << 6,   // signed (or unsigned)
+  L   = 1 << 20,  // load (or store)
+  S   = 1 << 20,  // set condition code (or leave unchanged)
+  W   = 1 << 21,  // writeback base register (or leave unchanged)
+  A   = 1 << 21,  // accumulate in multiply instruction (or not)
+  B   = 1 << 22,  // unsigned byte (or word)
+  N   = 1 << 22,  // long (or short)
+  U   = 1 << 23,  // positive (or negative) offset/index
+  P   = 1 << 24,  // offset/pre-indexed addressing (or post-indexed addressing)
+  I   = 1 << 25,  // immediate shifter operand (or not)
+
+  B4  = 1 << 4,
+  B5  = 1 << 5,
+  B7  = 1 << 7,
+  B8  = 1 << 8,
+  B12 = 1 << 12,
+  B16 = 1 << 16,
+  B20 = 1 << 20,
+  B21 = 1 << 21,
+  B22 = 1 << 22,
+  B23 = 1 << 23,
+  B24 = 1 << 24,
+  B25 = 1 << 25,
+  B26 = 1 << 26,
+  B27 = 1 << 27,
+
+  // Instruction bit masks
+  RdMask     = 15 << 12,  // in str instruction
+  CondMask   = 15 << 28,
+  OpCodeMask = 15 << 21,  // in data-processing instructions
+  Imm24Mask  = (1 << 24) - 1,
+  Off12Mask  = (1 << 12) - 1,
+  // Reserved condition
+  nv = 15 << 28
+};
+
+
+// add(sp, sp, 4) instruction (aka Pop())
+static const Instr kPopInstruction =
+    al | 4 * B21 | 4 | LeaveCC | I | sp.code() * B16 | sp.code() * B12;
+// str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r))
+// register r is not encoded.
+static const Instr kPushRegPattern =
+    al | B26 | 4 | NegPreIndex | sp.code() * B16;
+// ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r))
+// register r is not encoded.
+static const Instr kPopRegPattern =
+    al | B26 | L | 4 | PostIndex | sp.code() * B16;
+
+// spare_buffer_
+static const int kMinimalBufferSize = 4*KB;
+static byte* spare_buffer_ = NULL;
+
+Assembler::Assembler(void* buffer, int buffer_size) {
+  if (buffer == NULL) {
+    // do our own buffer management
+    if (buffer_size <= kMinimalBufferSize) {
+      buffer_size = kMinimalBufferSize;
+
+      if (spare_buffer_ != NULL) {
+        buffer = spare_buffer_;
+        spare_buffer_ = NULL;
+      }
+    }
+    if (buffer == NULL) {
+      buffer_ = NewArray<byte>(buffer_size);
+    } else {
+      buffer_ = static_cast<byte*>(buffer);
+    }
+    buffer_size_ = buffer_size;
+    own_buffer_ = true;
+
+  } else {
+    // use externally provided buffer instead
+    ASSERT(buffer_size > 0);
+    buffer_ = static_cast<byte*>(buffer);
+    buffer_size_ = buffer_size;
+    own_buffer_ = false;
+  }
+
+  // setup buffer pointers
+  ASSERT(buffer_ != NULL);
+  pc_ = buffer_;
+  reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
+  num_prinfo_ = 0;
+  next_buffer_check_ = 0;
+  no_const_pool_before_ = 0;
+  last_const_pool_end_ = 0;
+  last_bound_pos_ = 0;
+  current_statement_position_ = RelocInfo::kNoPosition;
+  current_position_ = RelocInfo::kNoPosition;
+  written_statement_position_ = current_statement_position_;
+  written_position_ = current_position_;
+}
+
+
+Assembler::~Assembler() {
+  if (own_buffer_) {
+    if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
+      spare_buffer_ = buffer_;
+    } else {
+      DeleteArray(buffer_);
+    }
+  }
+}
+
+
+void Assembler::GetCode(CodeDesc* desc) {
+  // emit constant pool if necessary
+  CheckConstPool(true, false);
+  ASSERT(num_prinfo_ == 0);
+
+  // setup desc
+  desc->buffer = buffer_;
+  desc->buffer_size = buffer_size_;
+  desc->instr_size = pc_offset();
+  desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
+}
+
+
+void Assembler::Align(int m) {
+  ASSERT(m >= 4 && IsPowerOf2(m));
+  while ((pc_offset() & (m - 1)) != 0) {
+    nop();
+  }
+}
+
+
+// Labels refer to positions in the (to be) generated code.
+// There are bound, linked, and unused labels.
+//
+// Bound labels refer to known positions in the already
+// generated code. pos() is the position the label refers to.
+//
+// Linked labels refer to unknown positions in the code
+// to be generated; pos() is the position of the last
+// instruction using the label.
+
+
+// The link chain is terminated by a negative code position (must be aligned)
+const int kEndOfChain = -4;
+
+
+int Assembler::target_at(int pos)  {
+  Instr instr = instr_at(pos);
+  ASSERT((instr & 7*B25) == 5*B25);  // b, bl, or blx imm24
+  int imm26 = ((instr & Imm24Mask) << 8) >> 6;
+  if ((instr & CondMask) == nv && (instr & B24) != 0)
+    // blx uses bit 24 to encode bit 2 of imm26
+    imm26 += 2;
+
+  return pos + 8 + imm26;
+}
+
+
+void Assembler::target_at_put(int pos, int target_pos) {
+  int imm26 = target_pos - pos - 8;
+  Instr instr = instr_at(pos);
+  ASSERT((instr & 7*B25) == 5*B25);  // b, bl, or blx imm24
+  if ((instr & CondMask) == nv) {
+    // blx uses bit 24 to encode bit 2 of imm26
+    ASSERT((imm26 & 1) == 0);
+    instr = (instr & ~(B24 | Imm24Mask)) | ((imm26 & 2) >> 1)*B24;
+  } else {
+    ASSERT((imm26 & 3) == 0);
+    instr &= ~Imm24Mask;
+  }
+  int imm24 = imm26 >> 2;
+  ASSERT(is_int24(imm24));
+  instr_at_put(pos, instr | (imm24 & Imm24Mask));
+}
+
+
+void Assembler::print(Label* L) {
+  if (L->is_unused()) {
+    PrintF("unused label\n");
+  } else if (L->is_bound()) {
+    PrintF("bound label to %d\n", L->pos());
+  } else if (L->is_linked()) {
+    Label l = *L;
+    PrintF("unbound label");
+    while (l.is_linked()) {
+      PrintF("@ %d ", l.pos());
+      Instr instr = instr_at(l.pos());
+      ASSERT((instr & 7*B25) == 5*B25);  // b, bl, or blx
+      int cond = instr & CondMask;
+      const char* b;
+      const char* c;
+      if (cond == nv) {
+        b = "blx";
+        c = "";
+      } else {
+        if ((instr & B24) != 0)
+          b = "bl";
+        else
+          b = "b";
+
+        switch (cond) {
+          case eq: c = "eq"; break;
+          case ne: c = "ne"; break;
+          case hs: c = "hs"; break;
+          case lo: c = "lo"; break;
+          case mi: c = "mi"; break;
+          case pl: c = "pl"; break;
+          case vs: c = "vs"; break;
+          case vc: c = "vc"; break;
+          case hi: c = "hi"; break;
+          case ls: c = "ls"; break;
+          case ge: c = "ge"; break;
+          case lt: c = "lt"; break;
+          case gt: c = "gt"; break;
+          case le: c = "le"; break;
+          case al: c = ""; break;
+          default:
+            c = "";
+            UNREACHABLE();
+        }
+      }
+      PrintF("%s%s\n", b, c);
+      next(&l);
+    }
+  } else {
+    PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
+  }
+}
+
+
+void Assembler::bind_to(Label* L, int pos) {
+  ASSERT(0 <= pos && pos <= pc_offset());  // must have a valid binding position
+  while (L->is_linked()) {
+    int fixup_pos = L->pos();
+    next(L);  // call next before overwriting link with target at fixup_pos
+    target_at_put(fixup_pos, pos);
+  }
+  L->bind_to(pos);
+
+  // Keep track of the last bound label so we don't eliminate any instructions
+  // before a bound label.
+  if (pos > last_bound_pos_)
+    last_bound_pos_ = pos;
+}
+
+
+void Assembler::link_to(Label* L, Label* appendix) {
+  if (appendix->is_linked()) {
+    if (L->is_linked()) {
+      // append appendix to L's list
+      int fixup_pos;
+      int link = L->pos();
+      do {
+        fixup_pos = link;
+        link = target_at(fixup_pos);
+      } while (link > 0);
+      ASSERT(link == kEndOfChain);
+      target_at_put(fixup_pos, appendix->pos());
+    } else {
+      // L is empty, simply use appendix
+      *L = *appendix;
+    }
+  }
+  appendix->Unuse();  // appendix should not be used anymore
+}
+
+
+void Assembler::bind(Label* L) {
+  ASSERT(!L->is_bound());  // label can only be bound once
+  bind_to(L, pc_offset());
+}
+
+
+void Assembler::next(Label* L) {
+  ASSERT(L->is_linked());
+  int link = target_at(L->pos());
+  if (link > 0) {
+    L->link_to(link);
+  } else {
+    ASSERT(link == kEndOfChain);
+    L->Unuse();
+  }
+}
+
+
+// Low-level code emission routines depending on the addressing mode
+static bool fits_shifter(uint32_t imm32,
+                         uint32_t* rotate_imm,
+                         uint32_t* immed_8,
+                         Instr* instr) {
+  // imm32 must be unsigned
+  for (int rot = 0; rot < 16; rot++) {
+    uint32_t imm8 = (imm32 << 2*rot) | (imm32 >> (32 - 2*rot));
+    if ((imm8 <= 0xff)) {
+      *rotate_imm = rot;
+      *immed_8 = imm8;
+      return true;
+    }
+  }
+  // if the opcode is mov or mvn and if ~imm32 fits, change the opcode
+  if (instr != NULL && (*instr & 0xd*B21) == 0xd*B21) {
+    if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) {
+      *instr ^= 0x2*B21;
+      return true;
+    }
+  }
+  return false;
+}
+
+
+void Assembler::addrmod1(Instr instr,
+                         Register rn,
+                         Register rd,
+                         const Operand& x) {
+  CheckBuffer();
+  ASSERT((instr & ~(CondMask | OpCodeMask | S)) == 0);
+  if (!x.rm_.is_valid()) {
+    // immediate
+    uint32_t rotate_imm;
+    uint32_t immed_8;
+    if ((x.rmode_ != RelocInfo::NONE &&
+         x.rmode_ != RelocInfo::EXTERNAL_REFERENCE) ||
+        !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) {
+      // The immediate operand cannot be encoded as a shifter operand, so load
+      // it first to register ip and change the original instruction to use ip.
+      // However, if the original instruction is a 'mov rd, x' (not setting the
+      // condition code), then replace it with a 'ldr rd, [pc]'
+      RecordRelocInfo(x.rmode_, x.imm32_);
+      CHECK(!rn.is(ip));  // rn should never be ip, or will be trashed
+      Condition cond = static_cast<Condition>(instr & CondMask);
+      if ((instr & ~CondMask) == 13*B21) {  // mov, S not set
+        ldr(rd, MemOperand(pc, 0), cond);
+      } else {
+        ldr(ip, MemOperand(pc, 0), cond);
+        addrmod1(instr, rn, rd, Operand(ip));
+      }
+      return;
+    }
+    instr |= I | rotate_imm*B8 | immed_8;
+  } else if (!x.rs_.is_valid()) {
+    // immediate shift
+    instr |= x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
+  } else {
+    // register shift
+    ASSERT(!rn.is(pc) && !rd.is(pc) && !x.rm_.is(pc) && !x.rs_.is(pc));
+    instr |= x.rs_.code()*B8 | x.shift_op_ | B4 | x.rm_.code();
+  }
+  emit(instr | rn.code()*B16 | rd.code()*B12);
+  if (rn.is(pc) || x.rm_.is(pc))
+    // block constant pool emission for one instruction after reading pc
+    BlockConstPoolBefore(pc_offset() + kInstrSize);
+}
+
+
+void Assembler::addrmod2(Instr instr, Register rd, const MemOperand& x) {
+  ASSERT((instr & ~(CondMask | B | L)) == B26);
+  int am = x.am_;
+  if (!x.rm_.is_valid()) {
+    // immediate offset
+    int offset_12 = x.offset_;
+    if (offset_12 < 0) {
+      offset_12 = -offset_12;
+      am ^= U;
+    }
+    if (!is_uint12(offset_12)) {
+      // immediate offset cannot be encoded, load it first to register ip
+      // rn (and rd in a load) should never be ip, or will be trashed
+      ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
+      mov(ip, Operand(x.offset_), LeaveCC,
+          static_cast<Condition>(instr & CondMask));
+      addrmod2(instr, rd, MemOperand(x.rn_, ip, x.am_));
+      return;
+    }
+    ASSERT(offset_12 >= 0);  // no masking needed
+    instr |= offset_12;
+  } else {
+    // register offset (shift_imm_ and shift_op_ are 0) or scaled
+    // register offset the constructors make sure than both shift_imm_
+    // and shift_op_ are initialized
+    ASSERT(!x.rm_.is(pc));
+    instr |= B25 | x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
+  }
+  ASSERT((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
+  emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
+}
+
+
+void Assembler::addrmod3(Instr instr, Register rd, const MemOperand& x) {
+  ASSERT((instr & ~(CondMask | L | S6 | H)) == (B4 | B7));
+  ASSERT(x.rn_.is_valid());
+  int am = x.am_;
+  if (!x.rm_.is_valid()) {
+    // immediate offset
+    int offset_8 = x.offset_;
+    if (offset_8 < 0) {
+      offset_8 = -offset_8;
+      am ^= U;
+    }
+    if (!is_uint8(offset_8)) {
+      // immediate offset cannot be encoded, load it first to register ip
+      // rn (and rd in a load) should never be ip, or will be trashed
+      ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
+      mov(ip, Operand(x.offset_), LeaveCC,
+          static_cast<Condition>(instr & CondMask));
+      addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
+      return;
+    }
+    ASSERT(offset_8 >= 0);  // no masking needed
+    instr |= B | (offset_8 >> 4)*B8 | (offset_8 & 0xf);
+  } else if (x.shift_imm_ != 0) {
+    // scaled register offset not supported, load index first
+    // rn (and rd in a load) should never be ip, or will be trashed
+    ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
+    mov(ip, Operand(x.rm_, x.shift_op_, x.shift_imm_), LeaveCC,
+        static_cast<Condition>(instr & CondMask));
+    addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
+    return;
+  } else {
+    // register offset
+    ASSERT((am & (P|W)) == P || !x.rm_.is(pc));  // no pc index with writeback
+    instr |= x.rm_.code();
+  }
+  ASSERT((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
+  emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
+}
+
+
+void Assembler::addrmod4(Instr instr, Register rn, RegList rl) {
+  ASSERT((instr & ~(CondMask | P | U | W | L)) == B27);
+  ASSERT(rl != 0);
+  ASSERT(!rn.is(pc));
+  emit(instr | rn.code()*B16 | rl);
+}
+
+
+void Assembler::addrmod5(Instr instr, CRegister crd, const MemOperand& x) {
+  // unindexed addressing is not encoded by this function
+  ASSERT((instr & ~(CondMask | P | U | N | W | L)) == (B27 | B26));
+  ASSERT(x.rn_.is_valid() && !x.rm_.is_valid());
+  int am = x.am_;
+  int offset_8 = x.offset_;
+  ASSERT((offset_8 & 3) == 0);  // offset must be an aligned word offset
+  offset_8 >>= 2;
+  if (offset_8 < 0) {
+    offset_8 = -offset_8;
+    am ^= U;
+  }
+  ASSERT(is_uint8(offset_8));  // unsigned word offset must fit in a byte
+  ASSERT((am & (P|W)) == P || !x.rn_.is(pc));  // no pc base with writeback
+
+  // post-indexed addressing requires W == 1; different than in addrmod2/3
+  if ((am & P) == 0)
+    am |= W;
+
+  ASSERT(offset_8 >= 0);  // no masking needed
+  emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8);
+}
+
+
+int Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
+  int target_pos;
+  if (L->is_bound()) {
+    target_pos = L->pos();
+  } else {
+    if (L->is_linked()) {
+      target_pos = L->pos();  // L's link
+    } else {
+      target_pos = kEndOfChain;
+    }
+    L->link_to(pc_offset());
+  }
+
+  // Block the emission of the constant pool, since the branch instruction must
+  // be emitted at the pc offset recorded by the label
+  BlockConstPoolBefore(pc_offset() + kInstrSize);
+
+  return target_pos - pc_offset() - 8;
+}
+
+
+// Branch instructions
+void Assembler::b(int branch_offset, Condition cond) {
+  ASSERT((branch_offset & 3) == 0);
+  int imm24 = branch_offset >> 2;
+  ASSERT(is_int24(imm24));
+  emit(cond | B27 | B25 | (imm24 & Imm24Mask));
+
+  if (cond == al)
+    // dead code is a good location to emit the constant pool
+    CheckConstPool(false, false);
+}
+
+
+void Assembler::bl(int branch_offset, Condition cond) {
+  ASSERT((branch_offset & 3) == 0);
+  int imm24 = branch_offset >> 2;
+  ASSERT(is_int24(imm24));
+  emit(cond | B27 | B25 | B24 | (imm24 & Imm24Mask));
+}
+
+
+void Assembler::blx(int branch_offset) {  // v5 and above
+  ASSERT((branch_offset & 1) == 0);
+  int h = ((branch_offset & 2) >> 1)*B24;
+  int imm24 = branch_offset >> 2;
+  ASSERT(is_int24(imm24));
+  emit(15 << 28 | B27 | B25 | h | (imm24 & Imm24Mask));
+}
+
+
+void Assembler::blx(Register target, Condition cond) {  // v5 and above
+  ASSERT(!target.is(pc));
+  emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | 3*B4 | target.code());
+}
+
+
+void Assembler::bx(Register target, Condition cond) {  // v5 and above, plus v4t
+  ASSERT(!target.is(pc));  // use of pc is actually allowed, but discouraged
+  emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | B4 | target.code());
+}
+
+
+// Data-processing instructions
+void Assembler::and_(Register dst, Register src1, const Operand& src2,
+                     SBit s, Condition cond) {
+  addrmod1(cond | 0*B21 | s, src1, dst, src2);
+}
+
+
+void Assembler::eor(Register dst, Register src1, const Operand& src2,
+                    SBit s, Condition cond) {
+  addrmod1(cond | 1*B21 | s, src1, dst, src2);
+}
+
+
+void Assembler::sub(Register dst, Register src1, const Operand& src2,
+                    SBit s, Condition cond) {
+  addrmod1(cond | 2*B21 | s, src1, dst, src2);
+}
+
+
+void Assembler::rsb(Register dst, Register src1, const Operand& src2,
+                    SBit s, Condition cond) {
+  addrmod1(cond | 3*B21 | s, src1, dst, src2);
+}
+
+
+void Assembler::add(Register dst, Register src1, const Operand& src2,
+                    SBit s, Condition cond) {
+  addrmod1(cond | 4*B21 | s, src1, dst, src2);
+
+  // Eliminate pattern: push(r), pop()
+  //   str(src, MemOperand(sp, 4, NegPreIndex), al);
+  //   add(sp, sp, Operand(kPointerSize));
+  // Both instructions can be eliminated.
+  int pattern_size = 2 * kInstrSize;
+  if (FLAG_push_pop_elimination &&
+      last_bound_pos_ <= (pc_offset() - pattern_size) &&
+      reloc_info_writer.last_pc() <= (pc_ - pattern_size) &&
+      // pattern
+      instr_at(pc_ - 1 * kInstrSize) == kPopInstruction &&
+      (instr_at(pc_ - 2 * kInstrSize) & ~RdMask) == kPushRegPattern) {
+    pc_ -= 2 * kInstrSize;
+    if (FLAG_print_push_pop_elimination) {
+      PrintF("%x push(reg)/pop() eliminated\n", pc_offset());
+    }
+  }
+}
+
+
+void Assembler::adc(Register dst, Register src1, const Operand& src2,
+                    SBit s, Condition cond) {
+  addrmod1(cond | 5*B21 | s, src1, dst, src2);
+}
+
+
+void Assembler::sbc(Register dst, Register src1, const Operand& src2,
+                    SBit s, Condition cond) {
+  addrmod1(cond | 6*B21 | s, src1, dst, src2);
+}
+
+
+void Assembler::rsc(Register dst, Register src1, const Operand& src2,
+                    SBit s, Condition cond) {
+  addrmod1(cond | 7*B21 | s, src1, dst, src2);
+}
+
+
+void Assembler::tst(Register src1, const Operand& src2, Condition cond) {
+  addrmod1(cond | 8*B21 | S, src1, r0, src2);
+}
+
+
+void Assembler::teq(Register src1, const Operand& src2, Condition cond) {
+  addrmod1(cond | 9*B21 | S, src1, r0, src2);
+}
+
+
+void Assembler::cmp(Register src1, const Operand& src2, Condition cond) {
+  addrmod1(cond | 10*B21 | S, src1, r0, src2);
+}
+
+
+void Assembler::cmn(Register src1, const Operand& src2, Condition cond) {
+  addrmod1(cond | 11*B21 | S, src1, r0, src2);
+}
+
+
+void Assembler::orr(Register dst, Register src1, const Operand& src2,
+                    SBit s, Condition cond) {
+  addrmod1(cond | 12*B21 | s, src1, dst, src2);
+}
+
+
+void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) {
+  addrmod1(cond | 13*B21 | s, r0, dst, src);
+}
+
+
+void Assembler::bic(Register dst, Register src1, const Operand& src2,
+                    SBit s, Condition cond) {
+  addrmod1(cond | 14*B21 | s, src1, dst, src2);
+}
+
+
+void Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) {
+  addrmod1(cond | 15*B21 | s, r0, dst, src);
+}
+
+
+// Multiply instructions
+void Assembler::mla(Register dst, Register src1, Register src2, Register srcA,
+                    SBit s, Condition cond) {
+  ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
+  ASSERT(!dst.is(src1));
+  emit(cond | A | s | dst.code()*B16 | srcA.code()*B12 |
+       src2.code()*B8 | B7 | B4 | src1.code());
+}
+
+
+void Assembler::mul(Register dst, Register src1, Register src2,
+                    SBit s, Condition cond) {
+  ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
+  ASSERT(!dst.is(src1));
+  emit(cond | s | dst.code()*B16 | src2.code()*B8 | B7 | B4 | src1.code());
+}
+
+
+void Assembler::smlal(Register dstL,
+                      Register dstH,
+                      Register src1,
+                      Register src2,
+                      SBit s,
+                      Condition cond) {
+  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
+  ASSERT(!dstL.is(dstH) && !dstH.is(src1) && !src1.is(dstL));
+  emit(cond | B23 | B22 | A | s | dstH.code()*B16 | dstL.code()*B12 |
+       src2.code()*B8 | B7 | B4 | src1.code());
+}
+
+
+void Assembler::smull(Register dstL,
+                      Register dstH,
+                      Register src1,
+                      Register src2,
+                      SBit s,
+                      Condition cond) {
+  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
+  ASSERT(!dstL.is(dstH) && !dstH.is(src1) && !src1.is(dstL));
+  emit(cond | B23 | B22 | s | dstH.code()*B16 | dstL.code()*B12 |
+       src2.code()*B8 | B7 | B4 | src1.code());
+}
+
+
+void Assembler::umlal(Register dstL,
+                      Register dstH,
+                      Register src1,
+                      Register src2,
+                      SBit s,
+                      Condition cond) {
+  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
+  ASSERT(!dstL.is(dstH) && !dstH.is(src1) && !src1.is(dstL));
+  emit(cond | B23 | A | s | dstH.code()*B16 | dstL.code()*B12 |
+       src2.code()*B8 | B7 | B4 | src1.code());
+}
+
+
+void Assembler::umull(Register dstL,
+                      Register dstH,
+                      Register src1,
+                      Register src2,
+                      SBit s,
+                      Condition cond) {
+  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
+  ASSERT(!dstL.is(dstH) && !dstH.is(src1) && !src1.is(dstL));
+  emit(cond | B23 | s | dstH.code()*B16 | dstL.code()*B12 |
+       src2.code()*B8 | B7 | B4 | src1.code());
+}
+
+
+// Miscellaneous arithmetic instructions
+void Assembler::clz(Register dst, Register src, Condition cond) {
+  // v5 and above.
+  ASSERT(!dst.is(pc) && !src.is(pc));
+  emit(cond | B24 | B22 | B21 | 15*B16 | dst.code()*B12 |
+       15*B8 | B4 | src.code());
+}
+
+
+// Status register access instructions
+void Assembler::mrs(Register dst, SRegister s, Condition cond) {
+  ASSERT(!dst.is(pc));
+  emit(cond | B24 | s | 15*B16 | dst.code()*B12);
+}
+
+
+void Assembler::msr(SRegisterFieldMask fields, const Operand& src,
+                    Condition cond) {
+  ASSERT(fields >= B16 && fields < B20);  // at least one field set
+  Instr instr;
+  if (!src.rm_.is_valid()) {
+    // immediate
+    uint32_t rotate_imm;
+    uint32_t immed_8;
+    if ((src.rmode_ != RelocInfo::NONE &&
+         src.rmode_ != RelocInfo::EXTERNAL_REFERENCE)||
+        !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) {
+      // immediate operand cannot be encoded, load it first to register ip
+      RecordRelocInfo(src.rmode_, src.imm32_);
+      ldr(ip, MemOperand(pc, 0), cond);
+      msr(fields, Operand(ip), cond);
+      return;
+    }
+    instr = I | rotate_imm*B8 | immed_8;
+  } else {
+    ASSERT(!src.rs_.is_valid() && src.shift_imm_ == 0);  // only rm allowed
+    instr = src.rm_.code();
+  }
+  emit(cond | instr | B24 | B21 | fields | 15*B12);
+}
+
+
+// Load/Store instructions
+void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
+  addrmod2(cond | B26 | L, dst, src);
+
+  // Eliminate pattern: push(r), pop(r)
+  //   str(r, MemOperand(sp, 4, NegPreIndex), al)
+  //   ldr(r, MemOperand(sp, 4, PostIndex), al)
+  // Both instructions can be eliminated.
+  int pattern_size = 2 * kInstrSize;
+  if (FLAG_push_pop_elimination &&
+      last_bound_pos_ <= (pc_offset() - pattern_size) &&
+      reloc_info_writer.last_pc() <= (pc_ - pattern_size) &&
+      // pattern
+      instr_at(pc_ - 1 * kInstrSize) == (kPopRegPattern | dst.code() * B12) &&
+      instr_at(pc_ - 2 * kInstrSize) == (kPushRegPattern | dst.code() * B12)) {
+    pc_ -= 2 * kInstrSize;
+    if (FLAG_print_push_pop_elimination) {
+      PrintF("%x push/pop (same reg) eliminated\n", pc_offset());
+    }
+  }
+}
+
+
+void Assembler::str(Register src, const MemOperand& dst, Condition cond) {
+  addrmod2(cond | B26, src, dst);
+
+  // Eliminate pattern: pop(), push(r)
+  //     add sp, sp, #4 LeaveCC, al; str r, [sp, #-4], al
+  // ->  str r, [sp, 0], al
+  int pattern_size = 2 * kInstrSize;
+  if (FLAG_push_pop_elimination &&
+     last_bound_pos_ <= (pc_offset() - pattern_size) &&
+     reloc_info_writer.last_pc() <= (pc_ - pattern_size) &&
+     instr_at(pc_ - 1 * kInstrSize) == (kPushRegPattern | src.code() * B12) &&
+     instr_at(pc_ - 2 * kInstrSize) == kPopInstruction) {
+    pc_ -= 2 * kInstrSize;
+    emit(al | B26 | 0 | Offset | sp.code() * B16 | src.code() * B12);
+    if (FLAG_print_push_pop_elimination) {
+      PrintF("%x pop()/push(reg) eliminated\n", pc_offset());
+    }
+  }
+}
+
+
+void Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) {
+  addrmod2(cond | B26 | B | L, dst, src);
+}
+
+
+void Assembler::strb(Register src, const MemOperand& dst, Condition cond) {
+  addrmod2(cond | B26 | B, src, dst);
+}
+
+
+void Assembler::ldrh(Register dst, const MemOperand& src, Condition cond) {
+  addrmod3(cond | L | B7 | H | B4, dst, src);
+}
+
+
+void Assembler::strh(Register src, const MemOperand& dst, Condition cond) {
+  addrmod3(cond | B7 | H | B4, src, dst);
+}
+
+
+void Assembler::ldrsb(Register dst, const MemOperand& src, Condition cond) {
+  addrmod3(cond | L | B7 | S6 | B4, dst, src);
+}
+
+
+void Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) {
+  addrmod3(cond | L | B7 | S6 | H | B4, dst, src);
+}
+
+
+// Load/Store multiple instructions
+void Assembler::ldm(BlockAddrMode am,
+                    Register base,
+                    RegList dst,
+                    Condition cond) {
+  // ABI stack constraint: ldmxx base, {..sp..}  base != sp  is not restartable
+  ASSERT(base.is(sp) || (dst & sp.bit()) == 0);
+
+  addrmod4(cond | B27 | am | L, base, dst);
+
+  // emit the constant pool after a function return implemented by ldm ..{..pc}
+  if (cond == al && (dst & pc.bit()) != 0) {
+    // There is a slight chance that the ldm instruction was actually a call,
+    // in which case it would be wrong to return into the constant pool; we
+    // recognize this case by checking if the emission of the pool was blocked
+    // at the pc of the ldm instruction by a mov lr, pc instruction; if this is
+    // the case, we emit a jump over the pool.
+    CheckConstPool(true, no_const_pool_before_ == pc_offset() - kInstrSize);
+  }
+}
+
+
+void Assembler::stm(BlockAddrMode am,
+                    Register base,
+                    RegList src,
+                    Condition cond) {
+  addrmod4(cond | B27 | am, base, src);
+}
+
+
+// Semaphore instructions
+void Assembler::swp(Register dst, Register src, Register base, Condition cond) {
+  ASSERT(!dst.is(pc) && !src.is(pc) && !base.is(pc));
+  ASSERT(!dst.is(base) && !src.is(base));
+  emit(cond | P | base.code()*B16 | dst.code()*B12 |
+       B7 | B4 | src.code());
+}
+
+
+void Assembler::swpb(Register dst,
+                     Register src,
+                     Register base,
+                     Condition cond) {
+  ASSERT(!dst.is(pc) && !src.is(pc) && !base.is(pc));
+  ASSERT(!dst.is(base) && !src.is(base));
+  emit(cond | P | B | base.code()*B16 | dst.code()*B12 |
+       B7 | B4 | src.code());
+}
+
+
+// Exception-generating instructions and debugging support
+void Assembler::stop(const char* msg) {
+#if !defined(__arm__)
+  // The simulator handles these special instructions and stops execution.
+  emit(15 << 28 | ((intptr_t) msg));
+#else
+  // Just issue a simple break instruction for now. Alternatively we could use
+  // the swi(0x9f0001) instruction on Linux.
+  bkpt(0);
+#endif
+}
+
+
+void Assembler::bkpt(uint32_t imm16) {  // v5 and above
+  ASSERT(is_uint16(imm16));
+  emit(al | B24 | B21 | (imm16 >> 4)*B8 | 7*B4 | (imm16 & 0xf));
+}
+
+
+void Assembler::swi(uint32_t imm24, Condition cond) {
+  ASSERT(is_uint24(imm24));
+  emit(cond | 15*B24 | imm24);
+}
+
+
+// Coprocessor instructions
+void Assembler::cdp(Coprocessor coproc,
+                    int opcode_1,
+                    CRegister crd,
+                    CRegister crn,
+                    CRegister crm,
+                    int opcode_2,
+                    Condition cond) {
+  ASSERT(is_uint4(opcode_1) && is_uint3(opcode_2));
+  emit(cond | B27 | B26 | B25 | (opcode_1 & 15)*B20 | crn.code()*B16 |
+       crd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | crm.code());
+}
+
+
+void Assembler::cdp2(Coprocessor coproc,
+                     int opcode_1,
+                     CRegister crd,
+                     CRegister crn,
+                     CRegister crm,
+                     int opcode_2) {  // v5 and above
+  cdp(coproc, opcode_1, crd, crn, crm, opcode_2, static_cast<Condition>(nv));
+}
+
+
+void Assembler::mcr(Coprocessor coproc,
+                    int opcode_1,
+                    Register rd,
+                    CRegister crn,
+                    CRegister crm,
+                    int opcode_2,
+                    Condition cond) {
+  ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2));
+  emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | crn.code()*B16 |
+       rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
+}
+
+
+void Assembler::mcr2(Coprocessor coproc,
+                     int opcode_1,
+                     Register rd,
+                     CRegister crn,
+                     CRegister crm,
+                     int opcode_2) {  // v5 and above
+  mcr(coproc, opcode_1, rd, crn, crm, opcode_2, static_cast<Condition>(nv));
+}
+
+
+void Assembler::mrc(Coprocessor coproc,
+                    int opcode_1,
+                    Register rd,
+                    CRegister crn,
+                    CRegister crm,
+                    int opcode_2,
+                    Condition cond) {
+  ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2));
+  emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | L | crn.code()*B16 |
+       rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
+}
+
+
+void Assembler::mrc2(Coprocessor coproc,
+                     int opcode_1,
+                     Register rd,
+                     CRegister crn,
+                     CRegister crm,
+                     int opcode_2) {  // v5 and above
+  mrc(coproc, opcode_1, rd, crn, crm, opcode_2, static_cast<Condition>(nv));
+}
+
+
+void Assembler::ldc(Coprocessor coproc,
+                    CRegister crd,
+                    const MemOperand& src,
+                    LFlag l,
+                    Condition cond) {
+  addrmod5(cond | B27 | B26 | l | L | coproc*B8, crd, src);
+}
+
+
+void Assembler::ldc(Coprocessor coproc,
+                    CRegister crd,
+                    Register rn,
+                    int option,
+                    LFlag l,
+                    Condition cond) {
+  // unindexed addressing
+  ASSERT(is_uint8(option));
+  emit(cond | B27 | B26 | U | l | L | rn.code()*B16 | crd.code()*B12 |
+       coproc*B8 | (option & 255));
+}
+
+
+void Assembler::ldc2(Coprocessor coproc,
+                     CRegister crd,
+                     const MemOperand& src,
+                     LFlag l) {  // v5 and above
+  ldc(coproc, crd, src, l, static_cast<Condition>(nv));
+}
+
+
+void Assembler::ldc2(Coprocessor coproc,
+                     CRegister crd,
+                     Register rn,
+                     int option,
+                     LFlag l) {  // v5 and above
+  ldc(coproc, crd, rn, option, l, static_cast<Condition>(nv));
+}
+
+
+void Assembler::stc(Coprocessor coproc,
+                    CRegister crd,
+                    const MemOperand& dst,
+                    LFlag l,
+                    Condition cond) {
+  addrmod5(cond | B27 | B26 | l | coproc*B8, crd, dst);
+}
+
+
+void Assembler::stc(Coprocessor coproc,
+                    CRegister crd,
+                    Register rn,
+                    int option,
+                    LFlag l,
+                    Condition cond) {
+  // unindexed addressing
+  ASSERT(is_uint8(option));
+  emit(cond | B27 | B26 | U | l | rn.code()*B16 | crd.code()*B12 |
+       coproc*B8 | (option & 255));
+}
+
+
+void Assembler::stc2(Coprocessor
+                     coproc, CRegister crd,
+                     const MemOperand& dst,
+                     LFlag l) {  // v5 and above
+  stc(coproc, crd, dst, l, static_cast<Condition>(nv));
+}
+
+
+void Assembler::stc2(Coprocessor coproc,
+                     CRegister crd,
+                     Register rn,
+                     int option,
+                     LFlag l) {  // v5 and above
+  stc(coproc, crd, rn, option, l, static_cast<Condition>(nv));
+}
+
+
+// Pseudo instructions
+void Assembler::lea(Register dst,
+                    const MemOperand& x,
+                    SBit s,
+                    Condition cond) {
+  int am = x.am_;
+  if (!x.rm_.is_valid()) {
+    // immediate offset
+    if ((am & P) == 0)  // post indexing
+      mov(dst, Operand(x.rn_), s, cond);
+    else if ((am & U) == 0)  // negative indexing
+      sub(dst, x.rn_, Operand(x.offset_), s, cond);
+    else
+      add(dst, x.rn_, Operand(x.offset_), s, cond);
+  } else {
+    // Register offset (shift_imm_ and shift_op_ are 0) or scaled
+    // register offset the constructors make sure than both shift_imm_
+    // and shift_op_ are initialized.
+    ASSERT(!x.rm_.is(pc));
+    if ((am & P) == 0)  // post indexing
+      mov(dst, Operand(x.rn_), s, cond);
+    else if ((am & U) == 0)  // negative indexing
+      sub(dst, x.rn_, Operand(x.rm_, x.shift_op_, x.shift_imm_), s, cond);
+    else
+      add(dst, x.rn_, Operand(x.rm_, x.shift_op_, x.shift_imm_), s, cond);
+  }
+}
+
+
+// Debugging
+void Assembler::RecordComment(const char* msg) {
+  if (FLAG_debug_code) {
+    CheckBuffer();
+    RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
+  }
+}
+
+
+void Assembler::RecordPosition(int pos) {
+  if (pos == RelocInfo::kNoPosition) return;
+  ASSERT(pos >= 0);
+  current_position_ = pos;
+  WriteRecordedPositions();
+}
+
+
+void Assembler::RecordStatementPosition(int pos) {
+  if (pos == RelocInfo::kNoPosition) return;
+  ASSERT(pos >= 0);
+  current_statement_position_ = pos;
+  WriteRecordedPositions();
+}
+
+
+void Assembler::WriteRecordedPositions() {
+  // Write the statement position if it is different from what was written last
+  // time.
+  if (current_statement_position_ != written_statement_position_) {
+    CheckBuffer();
+    RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_);
+    written_statement_position_ = current_statement_position_;
+  }
+
+  // Write the position if it is different from what was written last time and
+  // also different from the written statement position.
+  if (current_position_ != written_position_ &&
+      current_position_ != written_statement_position_) {
+    CheckBuffer();
+    RecordRelocInfo(RelocInfo::POSITION, current_position_);
+    written_position_ = current_position_;
+  }
+}
+
+
+void Assembler::GrowBuffer() {
+  if (!own_buffer_) FATAL("external code buffer is too small");
+
+  // compute new buffer size
+  CodeDesc desc;  // the new buffer
+  if (buffer_size_ < 4*KB) {
+    desc.buffer_size = 4*KB;
+  } else if (buffer_size_ < 1*MB) {
+    desc.buffer_size = 2*buffer_size_;
+  } else {
+    desc.buffer_size = buffer_size_ + 1*MB;
+  }
+  CHECK_GT(desc.buffer_size, 0);  // no overflow
+
+  // setup new buffer
+  desc.buffer = NewArray<byte>(desc.buffer_size);
+
+  desc.instr_size = pc_offset();
+  desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
+
+  // copy the data
+  int pc_delta = desc.buffer - buffer_;
+  int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
+  memmove(desc.buffer, buffer_, desc.instr_size);
+  memmove(reloc_info_writer.pos() + rc_delta,
+          reloc_info_writer.pos(), desc.reloc_size);
+
+  // switch buffers
+  DeleteArray(buffer_);
+  buffer_ = desc.buffer;
+  buffer_size_ = desc.buffer_size;
+  pc_ += pc_delta;
+  reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
+                               reloc_info_writer.last_pc() + pc_delta);
+
+  // none of our relocation types are pc relative pointing outside the code
+  // buffer nor pc absolute pointing inside the code buffer, so there is no need
+  // to relocate any emitted relocation entries
+
+  // relocate pending relocation entries
+  for (int i = 0; i < num_prinfo_; i++) {
+    RelocInfo& rinfo = prinfo_[i];
+    ASSERT(rinfo.rmode() != RelocInfo::COMMENT &&
+           rinfo.rmode() != RelocInfo::POSITION);
+    rinfo.set_pc(rinfo.pc() + pc_delta);
+  }
+}
+
+
+void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
+  RelocInfo rinfo(pc_, rmode, data);  // we do not try to reuse pool constants
+  if (rmode >= RelocInfo::COMMENT && rmode <= RelocInfo::STATEMENT_POSITION) {
+    // adjust code for new modes
+    ASSERT(RelocInfo::IsComment(rmode) || RelocInfo::IsPosition(rmode));
+    // these modes do not need an entry in the constant pool
+  } else {
+    ASSERT(num_prinfo_ < kMaxNumPRInfo);
+    prinfo_[num_prinfo_++] = rinfo;
+    // Make sure the constant pool is not emitted in place of the next
+    // instruction for which we just recorded relocation info
+    BlockConstPoolBefore(pc_offset() + kInstrSize);
+  }
+  if (rinfo.rmode() != RelocInfo::NONE) {
+    // Don't record external references unless the heap will be serialized.
+    if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
+        !Serializer::enabled() &&
+        !FLAG_debug_code) {
+      return;
+    }
+    ASSERT(buffer_space() >= kMaxRelocSize);  // too late to grow buffer here
+    reloc_info_writer.Write(&rinfo);
+  }
+}
+
+
+void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
+  // Calculate the offset of the next check. It will be overwritten
+  // when a const pool is generated or when const pools are being
+  // blocked for a specific range.
+  next_buffer_check_ = pc_offset() + kCheckConstInterval;
+
+  // There is nothing to do if there are no pending relocation info entries
+  if (num_prinfo_ == 0) return;
+
+  // We emit a constant pool at regular intervals of about kDistBetweenPools
+  // or when requested by parameter force_emit (e.g. after each function).
+  // We prefer not to emit a jump unless the max distance is reached or if we
+  // are running low on slots, which can happen if a lot of constants are being
+  // emitted (e.g. --debug-code and many static references).
+  int dist = pc_offset() - last_const_pool_end_;
+  if (!force_emit && dist < kMaxDistBetweenPools &&
+      (require_jump || dist < kDistBetweenPools) &&
+      // TODO(1236125): Cleanup the "magic" number below. We know that
+      // the code generation will test every kCheckConstIntervalInst.
+      // Thus we are safe as long as we generate less than 7 constant
+      // entries per instruction.
+      (num_prinfo_ < (kMaxNumPRInfo - (7 * kCheckConstIntervalInst)))) {
+    return;
+  }
+
+  // If we did not return by now, we need to emit the constant pool soon.
+
+  // However, some small sequences of instructions must not be broken up by the
+  // insertion of a constant pool; such sequences are protected by setting
+  // no_const_pool_before_, which is checked here. Also, recursive calls to
+  // CheckConstPool are blocked by no_const_pool_before_.
+  if (pc_offset() < no_const_pool_before_) {
+    // Emission is currently blocked; make sure we try again as soon as possible
+    next_buffer_check_ = no_const_pool_before_;
+
+    // Something is wrong if emission is forced and blocked at the same time
+    ASSERT(!force_emit);
+    return;
+  }
+
+  int jump_instr = require_jump ? kInstrSize : 0;
+
+  // Check that the code buffer is large enough before emitting the constant
+  // pool and relocation information (include the jump over the pool and the
+  // constant pool marker).
+  int max_needed_space =
+      jump_instr + kInstrSize + num_prinfo_*(kInstrSize + kMaxRelocSize);
+  while (buffer_space() <= (max_needed_space + kGap)) GrowBuffer();
+
+  // Block recursive calls to CheckConstPool
+  BlockConstPoolBefore(pc_offset() + jump_instr + kInstrSize +
+                       num_prinfo_*kInstrSize);
+  // Don't bother to check for the emit calls below.
+  next_buffer_check_ = no_const_pool_before_;
+
+  // Emit jump over constant pool if necessary
+  Label after_pool;
+  if (require_jump) b(&after_pool);
+
+  RecordComment("[ Constant Pool");
+
+  // Put down constant pool marker
+  // "Undefined instruction" as specified by A3.1 Instruction set encoding
+  emit(0x03000000 | num_prinfo_);
+
+  // Emit constant pool entries
+  for (int i = 0; i < num_prinfo_; i++) {
+    RelocInfo& rinfo = prinfo_[i];
+    ASSERT(rinfo.rmode() != RelocInfo::COMMENT &&
+           rinfo.rmode() != RelocInfo::POSITION &&
+           rinfo.rmode() != RelocInfo::STATEMENT_POSITION);
+    Instr instr = instr_at(rinfo.pc());
+    // Instruction to patch must be a ldr/str [pc, #offset]
+    // P and U set, B and W clear, Rn == pc, offset12 still 0
+    ASSERT((instr & (7*B25 | P | U | B | W | 15*B16 | Off12Mask)) ==
+           (2*B25 | P | U | pc.code()*B16));
+    int delta = pc_ - rinfo.pc() - 8;
+    ASSERT(delta >= -4);  // instr could be ldr pc, [pc, #-4] followed by targ32
+    if (delta < 0) {
+      instr &= ~U;
+      delta = -delta;
+    }
+    ASSERT(is_uint12(delta));
+    instr_at_put(rinfo.pc(), instr + delta);
+    emit(rinfo.data());
+  }
+  num_prinfo_ = 0;
+  last_const_pool_end_ = pc_offset();
+
+  RecordComment("]");
+
+  if (after_pool.is_linked()) {
+    bind(&after_pool);
+  }
+
+  // Since a constant pool was just emitted, move the check offset forward by
+  // the standard interval.
+  next_buffer_check_ = pc_offset() + kCheckConstInterval;
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/assembler-arm.h b/deps/v8/src/assembler-arm.h
new file mode 100644
index 0000000..f965ebd
--- /dev/null
+++ b/deps/v8/src/assembler-arm.h
@@ -0,0 +1,789 @@
+// Copyright (c) 1994-2006 Sun Microsystems Inc.
+// 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.
+//
+// - Redistribution 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 Sun Microsystems or the names of 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.
+
+// The original source code covered by the above license above has been modified
+// significantly by Google Inc.
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+
+// A light-weight ARM Assembler
+// Generates user mode instructions for the ARM architecture up to version 5
+
+#ifndef V8_ASSEMBLER_ARM_H_
+#define V8_ASSEMBLER_ARM_H_
+
+#include "assembler.h"
+
+namespace v8 { namespace internal {
+
+// CPU Registers.
+//
+// 1) We would prefer to use an enum, but enum values are assignment-
+// compatible with int, which has caused code-generation bugs.
+//
+// 2) We would prefer to use a class instead of a struct but we don't like
+// the register initialization to depend on the particular initialization
+// order (which appears to be different on OS X, Linux, and Windows for the
+// installed versions of C++ we tried). Using a struct permits C-style
+// "initialization". Also, the Register objects cannot be const as this
+// forces initialization stubs in MSVC, making us dependent on initialization
+// order.
+//
+// 3) By not using an enum, we are possibly preventing the compiler from
+// doing certain constant folds, which may significantly reduce the
+// code generated for some assembly instructions (because they boil down
+// to a few constants). If this is a problem, we could change the code
+// such that we use an enum in optimized mode, and the struct in debug
+// mode. This way we get the compile-time error checking in debug mode
+// and best performance in optimized code.
+//
+// Core register
+struct Register {
+  bool is_valid() const  { return 0 <= code_ && code_ < 16; }
+  bool is(Register reg) const  { return code_ == reg.code_; }
+  int code() const  {
+    ASSERT(is_valid());
+    return code_;
+  }
+  int bit() const  {
+    ASSERT(is_valid());
+    return 1 << code_;
+  }
+
+  // (unfortunately we can't make this private in a struct)
+  int code_;
+};
+
+
+const int kNumRegisters = 16;
+
+extern Register no_reg;
+extern Register r0;
+extern Register r1;
+extern Register r2;
+extern Register r3;
+extern Register r4;
+extern Register r5;
+extern Register r6;
+extern Register r7;
+extern Register r8;
+extern Register r9;
+extern Register r10;
+extern Register fp;
+extern Register ip;
+extern Register sp;
+extern Register lr;
+extern Register pc;
+
+
+// Coprocessor register
+struct CRegister {
+  bool is_valid() const  { return 0 <= code_ && code_ < 16; }
+  bool is(CRegister creg) const  { return code_ == creg.code_; }
+  int code() const  {
+    ASSERT(is_valid());
+    return code_;
+  }
+  int bit() const  {
+    ASSERT(is_valid());
+    return 1 << code_;
+  }
+
+  // (unfortunately we can't make this private in a struct)
+  int code_;
+};
+
+
+extern CRegister no_creg;
+extern CRegister cr0;
+extern CRegister cr1;
+extern CRegister cr2;
+extern CRegister cr3;
+extern CRegister cr4;
+extern CRegister cr5;
+extern CRegister cr6;
+extern CRegister cr7;
+extern CRegister cr8;
+extern CRegister cr9;
+extern CRegister cr10;
+extern CRegister cr11;
+extern CRegister cr12;
+extern CRegister cr13;
+extern CRegister cr14;
+extern CRegister cr15;
+
+
+// Coprocessor number
+enum Coprocessor {
+  p0  = 0,
+  p1  = 1,
+  p2  = 2,
+  p3  = 3,
+  p4  = 4,
+  p5  = 5,
+  p6  = 6,
+  p7  = 7,
+  p8  = 8,
+  p9  = 9,
+  p10 = 10,
+  p11 = 11,
+  p12 = 12,
+  p13 = 13,
+  p14 = 14,
+  p15 = 15
+};
+
+
+// Condition field in instructions
+enum Condition {
+  eq =  0 << 28,
+  ne =  1 << 28,
+  cs =  2 << 28,
+  hs =  2 << 28,
+  cc =  3 << 28,
+  lo =  3 << 28,
+  mi =  4 << 28,
+  pl =  5 << 28,
+  vs =  6 << 28,
+  vc =  7 << 28,
+  hi =  8 << 28,
+  ls =  9 << 28,
+  ge = 10 << 28,
+  lt = 11 << 28,
+  gt = 12 << 28,
+  le = 13 << 28,
+  al = 14 << 28
+};
+
+
+// Returns the equivalent of !cc.
+INLINE(Condition NegateCondition(Condition cc));
+
+
+// Corresponds to transposing the operands of a comparison.
+inline Condition ReverseCondition(Condition cc) {
+  switch (cc) {
+    case lo:
+      return hi;
+    case hi:
+      return lo;
+    case hs:
+      return ls;
+    case ls:
+      return hs;
+    case lt:
+      return gt;
+    case gt:
+      return lt;
+    case ge:
+      return le;
+    case le:
+      return ge;
+    default:
+      return cc;
+  };
+}
+
+
+// Branch hints are not used on the ARM.  They are defined so that they can
+// appear in shared function signatures, but will be ignored in ARM
+// implementations.
+enum Hint { no_hint };
+
+// Hints are not used on the arm.  Negating is trivial.
+inline Hint NegateHint(Hint ignored) { return no_hint; }
+
+
+// -----------------------------------------------------------------------------
+// Addressing modes and instruction variants
+
+// Shifter operand shift operation
+enum ShiftOp {
+  LSL = 0 << 5,
+  LSR = 1 << 5,
+  ASR = 2 << 5,
+  ROR = 3 << 5,
+  RRX = -1
+};
+
+
+// Condition code updating mode
+enum SBit {
+  SetCC   = 1 << 20,  // set condition code
+  LeaveCC = 0 << 20   // leave condition code unchanged
+};
+
+
+// Status register selection
+enum SRegister {
+  CPSR = 0 << 22,
+  SPSR = 1 << 22
+};
+
+
+// Status register fields
+enum SRegisterField {
+  CPSR_c = CPSR | 1 << 16,
+  CPSR_x = CPSR | 1 << 17,
+  CPSR_s = CPSR | 1 << 18,
+  CPSR_f = CPSR | 1 << 19,
+  SPSR_c = SPSR | 1 << 16,
+  SPSR_x = SPSR | 1 << 17,
+  SPSR_s = SPSR | 1 << 18,
+  SPSR_f = SPSR | 1 << 19
+};
+
+// Status register field mask (or'ed SRegisterField enum values)
+typedef uint32_t SRegisterFieldMask;
+
+
+// Memory operand addressing mode
+enum AddrMode {
+  // bit encoding P U W
+  Offset       = (8|4|0) << 21,  // offset (without writeback to base)
+  PreIndex     = (8|4|1) << 21,  // pre-indexed addressing with writeback
+  PostIndex    = (0|4|0) << 21,  // post-indexed addressing with writeback
+  NegOffset    = (8|0|0) << 21,  // negative offset (without writeback to base)
+  NegPreIndex  = (8|0|1) << 21,  // negative pre-indexed with writeback
+  NegPostIndex = (0|0|0) << 21   // negative post-indexed with writeback
+};
+
+
+// Load/store multiple addressing mode
+enum BlockAddrMode {
+  // bit encoding P U W
+  da           = (0|0|0) << 21,  // decrement after
+  ia           = (0|4|0) << 21,  // increment after
+  db           = (8|0|0) << 21,  // decrement before
+  ib           = (8|4|0) << 21,  // increment before
+  da_w         = (0|0|1) << 21,  // decrement after with writeback to base
+  ia_w         = (0|4|1) << 21,  // increment after with writeback to base
+  db_w         = (8|0|1) << 21,  // decrement before with writeback to base
+  ib_w         = (8|4|1) << 21   // increment before with writeback to base
+};
+
+
+// Coprocessor load/store operand size
+enum LFlag {
+  Long  = 1 << 22,  // long load/store coprocessor
+  Short = 0 << 22   // short load/store coprocessor
+};
+
+
+// -----------------------------------------------------------------------------
+// Machine instruction Operands
+
+// Class Operand represents a shifter operand in data processing instructions
+class Operand BASE_EMBEDDED {
+ public:
+  // immediate
+  INLINE(explicit Operand(int32_t immediate,
+         RelocInfo::Mode rmode = RelocInfo::NONE));
+  INLINE(explicit Operand(const ExternalReference& f));
+  INLINE(explicit Operand(const char* s));
+  INLINE(explicit Operand(Object** opp));
+  INLINE(explicit Operand(Context** cpp));
+  explicit Operand(Handle<Object> handle);
+  INLINE(explicit Operand(Smi* value));
+
+  // rm
+  INLINE(explicit Operand(Register rm));
+
+  // rm <shift_op> shift_imm
+  explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
+
+  // rm <shift_op> rs
+  explicit Operand(Register rm, ShiftOp shift_op, Register rs);
+
+  // Return true if this is a register operand.
+  INLINE(bool is_reg() const);
+
+  Register rm() const { return rm_; }
+
+ private:
+  Register rm_;
+  Register rs_;
+  ShiftOp shift_op_;
+  int shift_imm_;  // valid if rm_ != no_reg && rs_ == no_reg
+  int32_t imm32_;  // valid if rm_ == no_reg
+  RelocInfo::Mode rmode_;
+
+  friend class Assembler;
+};
+
+
+// Class MemOperand represents a memory operand in load and store instructions
+class MemOperand BASE_EMBEDDED {
+ public:
+  // [rn +/- offset]      Offset/NegOffset
+  // [rn +/- offset]!     PreIndex/NegPreIndex
+  // [rn], +/- offset     PostIndex/NegPostIndex
+  // offset is any signed 32-bit value; offset is first loaded to register ip if
+  // it does not fit the addressing mode (12-bit unsigned and sign bit)
+  explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
+
+  // [rn +/- rm]          Offset/NegOffset
+  // [rn +/- rm]!         PreIndex/NegPreIndex
+  // [rn], +/- rm         PostIndex/NegPostIndex
+  explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
+
+  // [rn +/- rm <shift_op> shift_imm]      Offset/NegOffset
+  // [rn +/- rm <shift_op> shift_imm]!     PreIndex/NegPreIndex
+  // [rn], +/- rm <shift_op> shift_imm     PostIndex/NegPostIndex
+  explicit MemOperand(Register rn, Register rm,
+                      ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
+
+ private:
+  Register rn_;  // base
+  Register rm_;  // register offset
+  int32_t offset_;  // valid if rm_ == no_reg
+  ShiftOp shift_op_;
+  int shift_imm_;  // valid if rm_ != no_reg && rs_ == no_reg
+  AddrMode am_;  // bits P, U, and W
+
+  friend class Assembler;
+};
+
+
+typedef int32_t Instr;
+
+
+class Assembler : public Malloced {
+ public:
+  // Create an assembler. Instructions and relocation information are emitted
+  // into a buffer, with the instructions starting from the beginning and the
+  // relocation information starting from the end of the buffer. See CodeDesc
+  // for a detailed comment on the layout (globals.h).
+  //
+  // If the provided buffer is NULL, the assembler allocates and grows its own
+  // buffer, and buffer_size determines the initial buffer size. The buffer is
+  // owned by the assembler and deallocated upon destruction of the assembler.
+  //
+  // If the provided buffer is not NULL, the assembler uses the provided buffer
+  // for code generation and assumes its size to be buffer_size. If the buffer
+  // is too small, a fatal error occurs. No deallocation of the buffer is done
+  // upon destruction of the assembler.
+  Assembler(void* buffer, int buffer_size);
+  ~Assembler();
+
+  // GetCode emits any pending (non-emitted) code and fills the descriptor
+  // desc. GetCode() is idempotent; it returns the same result if no other
+  // Assembler functions are invoked in between GetCode() calls.
+  void GetCode(CodeDesc* desc);
+
+  // Label operations & relative jumps (PPUM Appendix D)
+  //
+  // Takes a branch opcode (cc) and a label (L) and generates
+  // either a backward branch or a forward branch and links it
+  // to the label fixup chain. Usage:
+  //
+  // Label L;    // unbound label
+  // j(cc, &L);  // forward branch to unbound label
+  // bind(&L);   // bind label to the current pc
+  // j(cc, &L);  // backward branch to bound label
+  // bind(&L);   // illegal: a label may be bound only once
+  //
+  // Note: The same Label can be used for forward and backward branches
+  // but it may be bound only once.
+
+  void bind(Label* L);  // binds an unbound label L to the current code position
+
+  // Returns the branch offset to the given label from the current code position
+  // Links the label to the current position if it is still unbound
+  // Manages the jump elimination optimization if the second parameter is true.
+  int branch_offset(Label* L, bool jump_elimination_allowed);
+
+  // Return the address in the constant pool of the code target address used by
+  // the branch/call instruction at pc.
+  INLINE(static Address target_address_address_at(Address pc));
+
+  // Read/Modify the code target address in the branch/call instruction at pc.
+  INLINE(static Address target_address_at(Address pc));
+  INLINE(static void set_target_address_at(Address pc, Address target));
+
+  // Distance between the instruction referring to the address of the call
+  // target (ldr pc, [target addr in const pool]) and the return address
+  static const int kTargetAddrToReturnAddrDist = sizeof(Instr);
+
+
+  // ---------------------------------------------------------------------------
+  // Code generation
+
+  // Insert the smallest number of nop instructions
+  // possible to align the pc offset to a multiple
+  // of m. m must be a power of 2 (>= 4).
+  void Align(int m);
+
+  // Branch instructions
+  void b(int branch_offset, Condition cond = al);
+  void bl(int branch_offset, Condition cond = al);
+  void blx(int branch_offset);  // v5 and above
+  void blx(Register target, Condition cond = al);  // v5 and above
+  void bx(Register target, Condition cond = al);  // v5 and above, plus v4t
+
+  // Convenience branch instructions using labels
+  void b(Label* L, Condition cond = al)  {
+    b(branch_offset(L, cond == al), cond);
+  }
+  void b(Condition cond, Label* L)  { b(branch_offset(L, cond == al), cond); }
+  void bl(Label* L, Condition cond = al)  { bl(branch_offset(L, false), cond); }
+  void bl(Condition cond, Label* L)  { bl(branch_offset(L, false), cond); }
+  void blx(Label* L)  { blx(branch_offset(L, false)); }  // v5 and above
+
+  // Data-processing instructions
+  void and_(Register dst, Register src1, const Operand& src2,
+            SBit s = LeaveCC, Condition cond = al);
+
+  void eor(Register dst, Register src1, const Operand& src2,
+           SBit s = LeaveCC, Condition cond = al);
+
+  void sub(Register dst, Register src1, const Operand& src2,
+           SBit s = LeaveCC, Condition cond = al);
+  void sub(Register dst, Register src1, Register src2,
+           SBit s = LeaveCC, Condition cond = al) {
+    sub(dst, src1, Operand(src2), s, cond);
+  }
+
+  void rsb(Register dst, Register src1, const Operand& src2,
+           SBit s = LeaveCC, Condition cond = al);
+
+  void add(Register dst, Register src1, const Operand& src2,
+           SBit s = LeaveCC, Condition cond = al);
+
+  void adc(Register dst, Register src1, const Operand& src2,
+           SBit s = LeaveCC, Condition cond = al);
+
+  void sbc(Register dst, Register src1, const Operand& src2,
+           SBit s = LeaveCC, Condition cond = al);
+
+  void rsc(Register dst, Register src1, const Operand& src2,
+           SBit s = LeaveCC, Condition cond = al);
+
+  void tst(Register src1, const Operand& src2, Condition cond = al);
+  void tst(Register src1, Register src2, Condition cond = al) {
+    tst(src1, Operand(src2), cond);
+  }
+
+  void teq(Register src1, const Operand& src2, Condition cond = al);
+
+  void cmp(Register src1, const Operand& src2, Condition cond = al);
+  void cmp(Register src1, Register src2, Condition cond = al) {
+    cmp(src1, Operand(src2), cond);
+  }
+
+  void cmn(Register src1, const Operand& src2, Condition cond = al);
+
+  void orr(Register dst, Register src1, const Operand& src2,
+           SBit s = LeaveCC, Condition cond = al);
+  void orr(Register dst, Register src1, Register src2,
+           SBit s = LeaveCC, Condition cond = al) {
+    orr(dst, src1, Operand(src2), s, cond);
+  }
+
+  void mov(Register dst, const Operand& src,
+           SBit s = LeaveCC, Condition cond = al);
+  void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
+    mov(dst, Operand(src), s, cond);
+  }
+
+  void bic(Register dst, Register src1, const Operand& src2,
+           SBit s = LeaveCC, Condition cond = al);
+
+  void mvn(Register dst, const Operand& src,
+           SBit s = LeaveCC, Condition cond = al);
+
+  // Multiply instructions
+
+  void mla(Register dst, Register src1, Register src2, Register srcA,
+           SBit s = LeaveCC, Condition cond = al);
+
+  void mul(Register dst, Register src1, Register src2,
+           SBit s = LeaveCC, Condition cond = al);
+
+  void smlal(Register dstL, Register dstH, Register src1, Register src2,
+             SBit s = LeaveCC, Condition cond = al);
+
+  void smull(Register dstL, Register dstH, Register src1, Register src2,
+             SBit s = LeaveCC, Condition cond = al);
+
+  void umlal(Register dstL, Register dstH, Register src1, Register src2,
+             SBit s = LeaveCC, Condition cond = al);
+
+  void umull(Register dstL, Register dstH, Register src1, Register src2,
+             SBit s = LeaveCC, Condition cond = al);
+
+  // Miscellaneous arithmetic instructions
+
+  void clz(Register dst, Register src, Condition cond = al);  // v5 and above
+
+  // Status register access instructions
+
+  void mrs(Register dst, SRegister s, Condition cond = al);
+  void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
+
+  // Load/Store instructions
+  void ldr(Register dst, const MemOperand& src, Condition cond = al);
+  void str(Register src, const MemOperand& dst, Condition cond = al);
+  void ldrb(Register dst, const MemOperand& src, Condition cond = al);
+  void strb(Register src, const MemOperand& dst, Condition cond = al);
+  void ldrh(Register dst, const MemOperand& src, Condition cond = al);
+  void strh(Register src, const MemOperand& dst, Condition cond = al);
+  void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
+  void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
+
+  // Load/Store multiple instructions
+  void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
+  void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
+
+  // Semaphore instructions
+  void swp(Register dst, Register src, Register base, Condition cond = al);
+  void swpb(Register dst, Register src, Register base, Condition cond = al);
+
+  // Exception-generating instructions and debugging support
+  void stop(const char* msg);
+
+  void bkpt(uint32_t imm16);  // v5 and above
+  void swi(uint32_t imm24, Condition cond = al);
+
+  // Coprocessor instructions
+
+  void cdp(Coprocessor coproc, int opcode_1,
+           CRegister crd, CRegister crn, CRegister crm,
+           int opcode_2, Condition cond = al);
+
+  void cdp2(Coprocessor coproc, int opcode_1,
+            CRegister crd, CRegister crn, CRegister crm,
+            int opcode_2);  // v5 and above
+
+  void mcr(Coprocessor coproc, int opcode_1,
+           Register rd, CRegister crn, CRegister crm,
+           int opcode_2 = 0, Condition cond = al);
+
+  void mcr2(Coprocessor coproc, int opcode_1,
+            Register rd, CRegister crn, CRegister crm,
+            int opcode_2 = 0);  // v5 and above
+
+  void mrc(Coprocessor coproc, int opcode_1,
+           Register rd, CRegister crn, CRegister crm,
+           int opcode_2 = 0, Condition cond = al);
+
+  void mrc2(Coprocessor coproc, int opcode_1,
+            Register rd, CRegister crn, CRegister crm,
+            int opcode_2 = 0);  // v5 and above
+
+  void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
+           LFlag l = Short, Condition cond = al);
+  void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
+           LFlag l = Short, Condition cond = al);
+
+  void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
+            LFlag l = Short);  // v5 and above
+  void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
+            LFlag l = Short);  // v5 and above
+
+  void stc(Coprocessor coproc, CRegister crd, const MemOperand& dst,
+           LFlag l = Short, Condition cond = al);
+  void stc(Coprocessor coproc, CRegister crd, Register base, int option,
+           LFlag l = Short, Condition cond = al);
+
+  void stc2(Coprocessor coproc, CRegister crd, const MemOperand& dst,
+            LFlag l = Short);  // v5 and above
+  void stc2(Coprocessor coproc, CRegister crd, Register base, int option,
+            LFlag l = Short);  // v5 and above
+
+  // Pseudo instructions
+  void nop()  { mov(r0, Operand(r0)); }
+
+  void push(Register src) {
+    str(src, MemOperand(sp, 4, NegPreIndex), al);
+  }
+
+  void pop(Register dst) {
+    ldr(dst, MemOperand(sp, 4, PostIndex), al);
+  }
+
+  void pop() {
+    add(sp, sp, Operand(kPointerSize));
+  }
+
+  // Load effective address of memory operand x into register dst
+  void lea(Register dst, const MemOperand& x,
+           SBit s = LeaveCC, Condition cond = al);
+
+  // Jump unconditionally to given label.
+  void jmp(Label* L) { b(L, al); }
+
+
+  // Debugging
+
+  // Record a comment relocation entry that can be used by a disassembler.
+  // Use --debug_code to enable.
+  void RecordComment(const char* msg);
+
+  void RecordPosition(int pos);
+  void RecordStatementPosition(int pos);
+  void WriteRecordedPositions();
+
+  int pc_offset() const { return pc_ - buffer_; }
+  int current_position() const { return current_position_; }
+  int current_statement_position() const { return current_position_; }
+
+ protected:
+  int buffer_space() const { return reloc_info_writer.pos() - pc_; }
+
+  // Read/patch instructions
+  Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
+  void instr_at_put(byte* pc, Instr instr) {
+    *reinterpret_cast<Instr*>(pc) = instr;
+  }
+  Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
+  void instr_at_put(int pos, Instr instr) {
+    *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
+  }
+
+  // Decode branch instruction at pos and return branch target pos
+  int target_at(int pos);
+
+  // Patch branch instruction at pos to branch to given branch target pos
+  void target_at_put(int pos, int target_pos);
+
+  // Check if is time to emit a constant pool for pending reloc info entries
+  void CheckConstPool(bool force_emit, bool require_jump);
+
+  // Block the emission of the constant pool before pc_offset
+  void BlockConstPoolBefore(int pc_offset) {
+    if (no_const_pool_before_ < pc_offset) no_const_pool_before_ = pc_offset;
+  }
+
+ private:
+  // Code buffer:
+  // The buffer into which code and relocation info are generated.
+  byte* buffer_;
+  int buffer_size_;
+  // True if the assembler owns the buffer, false if buffer is external.
+  bool own_buffer_;
+
+  // Buffer size and constant pool distance are checked together at regular
+  // intervals of kBufferCheckInterval emitted bytes
+  static const int kBufferCheckInterval = 1*KB/2;
+  int next_buffer_check_;  // pc offset of next buffer check
+
+  // Code generation
+  static const int kInstrSize = sizeof(Instr);  // signed size
+  // The relocation writer's position is at least kGap bytes below the end of
+  // the generated instructions. This is so that multi-instruction sequences do
+  // not have to check for overflow. The same is true for writes of large
+  // relocation info entries.
+  static const int kGap = 32;
+  byte* pc_;  // the program counter; moves forward
+
+  // Constant pool generation
+  // Pools are emitted in the instruction stream, preferably after unconditional
+  // jumps or after returns from functions (in dead code locations).
+  // If a long code sequence does not contain unconditional jumps, it is
+  // necessary to emit the constant pool before the pool gets too far from the
+  // location it is accessed from. In this case, we emit a jump over the emitted
+  // constant pool.
+  // Constants in the pool may be addresses of functions that gets relocated;
+  // if so, a relocation info entry is associated to the constant pool entry.
+
+  // Repeated checking whether the constant pool should be emitted is rather
+  // expensive. By default we only check again once a number of instructions
+  // has been generated. That also means that the sizing of the buffers is not
+  // an exact science, and that we rely on some slop to not overrun buffers.
+  static const int kCheckConstIntervalInst = 32;
+  static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize;
+
+
+  // Pools are emitted after function return and in dead code at (more or less)
+  // regular intervals of kDistBetweenPools bytes
+  static const int kDistBetweenPools = 1*KB;
+
+  // Constants in pools are accessed via pc relative addressing, which can
+  // reach +/-4KB thereby defining a maximum distance between the instruction
+  // and the accessed constant. We satisfy this constraint by limiting the
+  // distance between pools.
+  static const int kMaxDistBetweenPools = 4*KB - 2*kBufferCheckInterval;
+
+  // Emission of the constant pool may be blocked in some code sequences
+  int no_const_pool_before_;  // block emission before this pc offset
+
+  // Keep track of the last emitted pool to guarantee a maximal distance
+  int last_const_pool_end_;  // pc offset following the last constant pool
+
+  // Relocation info generation
+  // Each relocation is encoded as a variable size value
+  static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
+  RelocInfoWriter reloc_info_writer;
+  // Relocation info records are also used during code generation as temporary
+  // containers for constants and code target addresses until they are emitted
+  // to the constant pool. These pending relocation info records are temporarily
+  // stored in a separate buffer until a constant pool is emitted.
+  // If every instruction in a long sequence is accessing the pool, we need one
+  // pending relocation entry per instruction.
+  static const int kMaxNumPRInfo = kMaxDistBetweenPools/kInstrSize;
+  RelocInfo prinfo_[kMaxNumPRInfo];  // the buffer of pending relocation info
+  int num_prinfo_;  // number of pending reloc info entries in the buffer
+
+  // The bound position, before this we cannot do instruction elimination.
+  int last_bound_pos_;
+
+  // source position information
+  int current_position_;
+  int current_statement_position_;
+  int written_position_;
+  int written_statement_position_;
+
+  // Code emission
+  inline void CheckBuffer();
+  void GrowBuffer();
+  inline void emit(Instr x);
+
+  // Instruction generation
+  void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
+  void addrmod2(Instr instr, Register rd, const MemOperand& x);
+  void addrmod3(Instr instr, Register rd, const MemOperand& x);
+  void addrmod4(Instr instr, Register rn, RegList rl);
+  void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
+
+  // Labels
+  void print(Label* L);
+  void bind_to(Label* L, int pos);
+  void link_to(Label* L, Label* appendix);
+  void next(Label* L);
+
+  // Record reloc info for current pc_
+  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_ASSEMBLER_ARM_H_
diff --git a/deps/v8/src/assembler-ia32-inl.h b/deps/v8/src/assembler-ia32-inl.h
new file mode 100644
index 0000000..c5213a7
--- /dev/null
+++ b/deps/v8/src/assembler-ia32-inl.h
@@ -0,0 +1,302 @@
+// Copyright (c) 1994-2006 Sun Microsystems Inc.
+// 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.
+//
+// - Redistribution 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 Sun Microsystems or the names of 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.
+
+// The original source code covered by the above license above has been
+// modified significantly by Google Inc.
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+
+// A light-weight IA32 Assembler.
+
+#ifndef V8_ASSEMBLER_IA32_INL_H_
+#define V8_ASSEMBLER_IA32_INL_H_
+
+#include "cpu.h"
+
+namespace v8 { namespace internal {
+
+Condition NegateCondition(Condition cc) {
+  return static_cast<Condition>(cc ^ 1);
+}
+
+
+// The modes possibly affected by apply must be in kApplyMask.
+void RelocInfo::apply(int delta) {
+  if (rmode_ == RUNTIME_ENTRY || IsCodeTarget(rmode_)) {
+    int32_t* p = reinterpret_cast<int32_t*>(pc_);
+    *p -= delta;  // relocate entry
+  } else if (rmode_ == JS_RETURN && IsCallInstruction()) {
+    // Special handling of js_return when a break point is set (call
+    // instruction has been inserted).
+    int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1);
+    *p -= delta;  // relocate entry
+  } else if (IsInternalReference(rmode_)) {
+    // absolute code pointer inside code object moves with the code object.
+    int32_t* p = reinterpret_cast<int32_t*>(pc_);
+    *p += delta;  // relocate entry
+  }
+}
+
+
+Address RelocInfo::target_address() {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
+  return Assembler::target_address_at(pc_);
+}
+
+
+Address RelocInfo::target_address_address() {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
+  return reinterpret_cast<Address>(pc_);
+}
+
+
+void RelocInfo::set_target_address(Address target) {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
+  Assembler::set_target_address_at(pc_, target);
+}
+
+
+Object* RelocInfo::target_object() {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
+  return *reinterpret_cast<Object**>(pc_);
+}
+
+
+Object** RelocInfo::target_object_address() {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
+  return reinterpret_cast<Object**>(pc_);
+}
+
+
+void RelocInfo::set_target_object(Object* target) {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
+  *reinterpret_cast<Object**>(pc_) = target;
+}
+
+
+Address* RelocInfo::target_reference_address() {
+  ASSERT(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
+  return reinterpret_cast<Address*>(pc_);
+}
+
+
+Address RelocInfo::call_address() {
+  ASSERT(IsCallInstruction());
+  return Assembler::target_address_at(pc_ + 1);
+}
+
+
+void RelocInfo::set_call_address(Address target) {
+  ASSERT(IsCallInstruction());
+  Assembler::set_target_address_at(pc_ + 1, target);
+}
+
+
+Object* RelocInfo::call_object() {
+  ASSERT(IsCallInstruction());
+  return *call_object_address();
+}
+
+
+Object** RelocInfo::call_object_address() {
+  ASSERT(IsCallInstruction());
+  return reinterpret_cast<Object**>(pc_ + 1);
+}
+
+
+void RelocInfo::set_call_object(Object* target) {
+  ASSERT(IsCallInstruction());
+  *call_object_address() = target;
+}
+
+
+bool RelocInfo::IsCallInstruction() {
+  return *pc_ == 0xE8;
+}
+
+
+Immediate::Immediate(int x)  {
+  x_ = x;
+  rmode_ = RelocInfo::NONE;
+}
+
+
+Immediate::Immediate(const ExternalReference& ext) {
+  x_ = reinterpret_cast<int32_t>(ext.address());
+  rmode_ = RelocInfo::EXTERNAL_REFERENCE;
+}
+
+Immediate::Immediate(const char* s) {
+  x_ = reinterpret_cast<int32_t>(s);
+  rmode_ = RelocInfo::EMBEDDED_STRING;
+}
+
+
+Immediate::Immediate(Label *internal_offset) {
+  x_ = reinterpret_cast<int32_t>(internal_offset);
+  rmode_ = RelocInfo::INTERNAL_REFERENCE;
+}
+
+
+Immediate::Immediate(Handle<Object> handle) {
+  // Verify all Objects referred by code are NOT in new space.
+  Object* obj = *handle;
+  ASSERT(!Heap::InNewSpace(obj));
+  if (obj->IsHeapObject()) {
+    x_ = reinterpret_cast<intptr_t>(handle.location());
+    rmode_ = RelocInfo::EMBEDDED_OBJECT;
+  } else {
+    // no relocation needed
+    x_ =  reinterpret_cast<intptr_t>(obj);
+    rmode_ = RelocInfo::NONE;
+  }
+}
+
+
+Immediate::Immediate(Smi* value) {
+  x_ = reinterpret_cast<intptr_t>(value);
+  rmode_ = RelocInfo::NONE;
+}
+
+
+void Assembler::emit(uint32_t x) {
+  *reinterpret_cast<uint32_t*>(pc_) = x;
+  pc_ += sizeof(uint32_t);
+}
+
+
+void Assembler::emit(Handle<Object> handle) {
+  // Verify all Objects referred by code are NOT in new space.
+  Object* obj = *handle;
+  ASSERT(!Heap::InNewSpace(obj));
+  if (obj->IsHeapObject()) {
+    emit(reinterpret_cast<intptr_t>(handle.location()),
+         RelocInfo::EMBEDDED_OBJECT);
+  } else {
+    // no relocation needed
+    emit(reinterpret_cast<intptr_t>(obj));
+  }
+}
+
+
+void Assembler::emit(uint32_t x, RelocInfo::Mode rmode) {
+  if (rmode != RelocInfo::NONE) RecordRelocInfo(rmode);
+  emit(x);
+}
+
+
+void Assembler::emit(const Immediate& x) {
+  if (x.rmode_ == RelocInfo::INTERNAL_REFERENCE) {
+    Label* label = reinterpret_cast<Label*>(x.x_);
+    emit_code_relative_offset(label);
+    return;
+  }
+  if (x.rmode_ != RelocInfo::NONE) RecordRelocInfo(x.rmode_);
+  emit(x.x_);
+}
+
+
+void Assembler::emit_code_relative_offset(Label* label) {
+  if (label->is_bound()) {
+    int32_t pos;
+    pos = label->pos() + Code::kHeaderSize - kHeapObjectTag;
+    emit(pos);
+  } else {
+    emit_disp(label, Displacement::CODE_RELATIVE);
+  }
+}
+
+
+void Assembler::emit_w(const Immediate& x) {
+  ASSERT(x.rmode_ == RelocInfo::NONE);
+  uint16_t value = static_cast<uint16_t>(x.x_);
+  reinterpret_cast<uint16_t*>(pc_)[0] = value;
+  pc_ += sizeof(uint16_t);
+}
+
+
+Address Assembler::target_address_at(Address pc) {
+  return pc + sizeof(int32_t) + *reinterpret_cast<int32_t*>(pc);
+}
+
+
+void Assembler::set_target_address_at(Address pc, Address target) {
+  int32_t* p = reinterpret_cast<int32_t*>(pc);
+  *p = target - (pc + sizeof(int32_t));
+  CPU::FlushICache(p, sizeof(int32_t));
+}
+
+
+Displacement Assembler::disp_at(Label* L) {
+  return Displacement(long_at(L->pos()));
+}
+
+
+void Assembler::disp_at_put(Label* L, Displacement disp) {
+  long_at_put(L->pos(), disp.data());
+}
+
+
+void Assembler::emit_disp(Label* L, Displacement::Type type) {
+  Displacement disp(L, type);
+  L->link_to(pc_offset());
+  emit(static_cast<int>(disp.data()));
+}
+
+
+void Operand::set_modrm(int mod, Register rm) {
+  ASSERT((mod & -4) == 0);
+  buf_[0] = mod << 6 | rm.code();
+  len_ = 1;
+}
+
+
+void Operand::set_dispr(int32_t disp, RelocInfo::Mode rmode) {
+  ASSERT(len_ == 1 || len_ == 2);
+  int32_t* p = reinterpret_cast<int32_t*>(&buf_[len_]);
+  *p = disp;
+  len_ += sizeof(int32_t);
+  rmode_ = rmode;
+}
+
+Operand::Operand(Register reg) {
+  // reg
+  set_modrm(3, reg);
+}
+
+
+Operand::Operand(int32_t disp, RelocInfo::Mode rmode) {
+  // [disp/r]
+  set_modrm(0, ebp);
+  set_dispr(disp, rmode);
+}
+
+} }  // namespace v8::internal
+
+#endif  // V8_ASSEMBLER_IA32_INL_H_
diff --git a/deps/v8/src/assembler-ia32.cc b/deps/v8/src/assembler-ia32.cc
new file mode 100644
index 0000000..8549261
--- /dev/null
+++ b/deps/v8/src/assembler-ia32.cc
@@ -0,0 +1,2205 @@
+// Copyright (c) 1994-2006 Sun Microsystems Inc.
+// 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.
+//
+// - Redistribution 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 Sun Microsystems or the names of 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.
+
+// The original source code covered by the above license above has been modified
+// significantly by Google Inc.
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+
+#include "v8.h"
+
+#include "disassembler.h"
+#include "macro-assembler.h"
+#include "serialize.h"
+
+namespace v8 { namespace internal {
+
+// -----------------------------------------------------------------------------
+// Implementation of Register
+
+Register eax = { 0 };
+Register ecx = { 1 };
+Register edx = { 2 };
+Register ebx = { 3 };
+Register esp = { 4 };
+Register ebp = { 5 };
+Register esi = { 6 };
+Register edi = { 7 };
+Register no_reg = { -1 };
+
+XMMRegister xmm0 = { 0 };
+XMMRegister xmm1 = { 1 };
+XMMRegister xmm2 = { 2 };
+XMMRegister xmm3 = { 3 };
+XMMRegister xmm4 = { 4 };
+XMMRegister xmm5 = { 5 };
+XMMRegister xmm6 = { 6 };
+XMMRegister xmm7 = { 7 };
+
+
+// -----------------------------------------------------------------------------
+// Implementation of CpuFeatures
+
+// Safe default is no features.
+uint64_t CpuFeatures::supported_ = 0;
+uint64_t CpuFeatures::enabled_ = 0;
+
+
+// The Probe method needs executable memory, so it uses Heap::CreateCode.
+// Allocation failure is silent and leads to safe default.
+void CpuFeatures::Probe() {
+  ASSERT(Heap::HasBeenSetup());
+  ASSERT(supported_ == 0);
+  if (Serializer::enabled()) return;  // No features if we might serialize.
+
+  Assembler assm(NULL, 0);
+  Label cpuid, done;
+#define __ assm.
+  // Save old esp, since we are going to modify the stack.
+  __ push(ebp);
+  __ pushfd();
+  __ push(ecx);
+  __ push(ebx);
+  __ mov(ebp, Operand(esp));
+
+  // If we can modify bit 21 of the EFLAGS register, then CPUID is supported.
+  __ pushfd();
+  __ pop(eax);
+  __ mov(edx, Operand(eax));
+  __ xor_(eax, 0x200000);  // Flip bit 21.
+  __ push(eax);
+  __ popfd();
+  __ pushfd();
+  __ pop(eax);
+  __ xor_(eax, Operand(edx));  // Different if CPUID is supported.
+  __ j(not_zero, &cpuid);
+
+  // CPUID not supported. Clear the supported features in edx:eax.
+  __ xor_(eax, Operand(eax));
+  __ xor_(edx, Operand(edx));
+  __ jmp(&done);
+
+  // Invoke CPUID with 1 in eax to get feature information in
+  // ecx:edx. Temporarily enable CPUID support because we know it's
+  // safe here.
+  __ bind(&cpuid);
+  __ mov(eax, 1);
+  supported_ = (1 << CPUID);
+  { Scope fscope(CPUID);
+    __ cpuid();
+  }
+  supported_ = 0;
+
+  // Move the result from ecx:edx to edx:eax and make sure to mark the
+  // CPUID feature as supported.
+  __ mov(eax, Operand(edx));
+  __ or_(eax, 1 << CPUID);
+  __ mov(edx, Operand(ecx));
+
+  // Done.
+  __ bind(&done);
+  __ mov(esp, Operand(ebp));
+  __ pop(ebx);
+  __ pop(ecx);
+  __ popfd();
+  __ pop(ebp);
+  __ ret(0);
+#undef __
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code =
+      Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB), NULL);
+  if (!code->IsCode()) return;
+  LOG(CodeCreateEvent("Builtin", Code::cast(code), "CpuFeatures::Probe"));
+  typedef uint64_t (*F0)();
+  F0 probe = FUNCTION_CAST<F0>(Code::cast(code)->entry());
+  supported_ = probe();
+}
+
+
+// -----------------------------------------------------------------------------
+// Implementation of Displacement
+
+void Displacement::init(Label* L, Type type) {
+  ASSERT(!L->is_bound());
+  int next = 0;
+  if (L->is_linked()) {
+    next = L->pos();
+    ASSERT(next > 0);  // Displacements must be at positions > 0
+  }
+  // Ensure that we _never_ overflow the next field.
+  ASSERT(NextField::is_valid(Assembler::kMaximalBufferSize));
+  data_ = NextField::encode(next) | TypeField::encode(type);
+}
+
+
+// -----------------------------------------------------------------------------
+// Implementation of RelocInfo
+
+
+const int RelocInfo::kApplyMask =
+  RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY |
+    1 << RelocInfo::JS_RETURN | 1 << RelocInfo::INTERNAL_REFERENCE;
+
+
+void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
+  // Patch the code at the current address with the supplied instructions.
+  for (int i = 0; i < instruction_count; i++) {
+    *(pc_ + i) = *(instructions + i);
+  }
+}
+
+
+// Patch the code at the current PC with a call to the target address.
+// Additional guard int3 instructions can be added if required.
+void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
+  // Call instruction takes up 5 bytes and int3 takes up one byte.
+  int code_size = 5 + guard_bytes;
+
+  // Patch the code.
+  CodePatcher patcher(pc_, code_size);
+  patcher.masm()->call(target, RelocInfo::NONE);
+
+  // Add the requested number of int3 instructions after the call.
+  for (int i = 0; i < guard_bytes; i++) {
+    patcher.masm()->int3();
+  }
+}
+
+
+// -----------------------------------------------------------------------------
+// Implementation of Operand
+
+Operand::Operand(Register base, int32_t disp, RelocInfo::Mode rmode) {
+  // [base + disp/r]
+  if (disp == 0 && rmode == RelocInfo::NONE && !base.is(ebp)) {
+    // [base]
+    set_modrm(0, base);
+    if (base.is(esp)) set_sib(times_1, esp, base);
+  } else if (is_int8(disp) && rmode == RelocInfo::NONE) {
+    // [base + disp8]
+    set_modrm(1, base);
+    if (base.is(esp)) set_sib(times_1, esp, base);
+    set_disp8(disp);
+  } else {
+    // [base + disp/r]
+    set_modrm(2, base);
+    if (base.is(esp)) set_sib(times_1, esp, base);
+    set_dispr(disp, rmode);
+  }
+}
+
+
+Operand::Operand(Register base,
+                 Register index,
+                 ScaleFactor scale,
+                 int32_t disp,
+                 RelocInfo::Mode rmode) {
+  ASSERT(!index.is(esp));  // illegal addressing mode
+  // [base + index*scale + disp/r]
+  if (disp == 0 && rmode == RelocInfo::NONE && !base.is(ebp)) {
+    // [base + index*scale]
+    set_modrm(0, esp);
+    set_sib(scale, index, base);
+  } else if (is_int8(disp) && rmode == RelocInfo::NONE) {
+    // [base + index*scale + disp8]
+    set_modrm(1, esp);
+    set_sib(scale, index, base);
+    set_disp8(disp);
+  } else {
+    // [base + index*scale + disp/r]
+    set_modrm(2, esp);
+    set_sib(scale, index, base);
+    set_dispr(disp, rmode);
+  }
+}
+
+
+Operand::Operand(Register index,
+                 ScaleFactor scale,
+                 int32_t disp,
+                 RelocInfo::Mode rmode) {
+  ASSERT(!index.is(esp));  // illegal addressing mode
+  // [index*scale + disp/r]
+  set_modrm(0, esp);
+  set_sib(scale, index, ebp);
+  set_dispr(disp, rmode);
+}
+
+
+void Operand::set_sib(ScaleFactor scale, Register index, Register base) {
+  ASSERT(len_ == 1);
+  ASSERT((scale & -4) == 0);
+  buf_[1] = scale << 6 | index.code() << 3 | base.code();
+  len_ = 2;
+}
+
+
+void Operand::set_disp8(int8_t disp) {
+  ASSERT(len_ == 1 || len_ == 2);
+  *reinterpret_cast<int8_t*>(&buf_[len_++]) = disp;
+}
+
+
+bool Operand::is_reg(Register reg) const {
+  return ((buf_[0] & 0xF8) == 0xC0)  // addressing mode is register only.
+      && ((buf_[0] & 0x07) == reg.code());  // register codes match.
+}
+
+// -----------------------------------------------------------------------------
+// Implementation of Assembler
+
+// Emit a single byte. Must always be inlined.
+#define EMIT(x)                                 \
+  *pc_++ = (x)
+
+
+// spare_buffer_
+static byte* spare_buffer_ = NULL;
+
+Assembler::Assembler(void* buffer, int buffer_size) {
+  if (buffer == NULL) {
+    // do our own buffer management
+    if (buffer_size <= kMinimalBufferSize) {
+      buffer_size = kMinimalBufferSize;
+
+      if (spare_buffer_ != NULL) {
+        buffer = spare_buffer_;
+        spare_buffer_ = NULL;
+      }
+    }
+    if (buffer == NULL) {
+      buffer_ = NewArray<byte>(buffer_size);
+    } else {
+      buffer_ = static_cast<byte*>(buffer);
+    }
+    buffer_size_ = buffer_size;
+    own_buffer_ = true;
+  } else {
+    // use externally provided buffer instead
+    ASSERT(buffer_size > 0);
+    buffer_ = static_cast<byte*>(buffer);
+    buffer_size_ = buffer_size;
+    own_buffer_ = false;
+  }
+
+  // Clear the buffer in debug mode unless it was provided by the
+  // caller in which case we can't be sure it's okay to overwrite
+  // existing code in it; see CodePatcher::CodePatcher(...).
+  if (kDebug && own_buffer_) {
+    memset(buffer_, 0xCC, buffer_size);  // int3
+  }
+
+  // setup buffer pointers
+  ASSERT(buffer_ != NULL);
+  pc_ = buffer_;
+  reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
+
+  last_pc_ = NULL;
+  current_statement_position_ = RelocInfo::kNoPosition;
+  current_position_ = RelocInfo::kNoPosition;
+  written_statement_position_ = current_statement_position_;
+  written_position_ = current_position_;
+}
+
+
+Assembler::~Assembler() {
+  if (own_buffer_) {
+    if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
+      spare_buffer_ = buffer_;
+    } else {
+      DeleteArray(buffer_);
+    }
+  }
+}
+
+
+void Assembler::GetCode(CodeDesc* desc) {
+  // finalize code
+  // (at this point overflow() may be true, but the gap ensures that
+  // we are still not overlapping instructions and relocation info)
+  ASSERT(pc_ <= reloc_info_writer.pos());  // no overlap
+  // setup desc
+  desc->buffer = buffer_;
+  desc->buffer_size = buffer_size_;
+  desc->instr_size = pc_offset();
+  desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
+  desc->origin = this;
+
+  Counters::reloc_info_size.Increment(desc->reloc_size);
+}
+
+
+void Assembler::Align(int m) {
+  ASSERT(IsPowerOf2(m));
+  while ((pc_offset() & (m - 1)) != 0) {
+    nop();
+  }
+}
+
+
+void Assembler::cpuid() {
+  ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CPUID));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x0F);
+  EMIT(0xA2);
+}
+
+
+void Assembler::pushad() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x60);
+}
+
+
+void Assembler::popad() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x61);
+}
+
+
+void Assembler::pushfd() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x9C);
+}
+
+
+void Assembler::popfd() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x9D);
+}
+
+
+void Assembler::push(const Immediate& x) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  if (x.is_int8()) {
+    EMIT(0x6a);
+    EMIT(x.x_);
+  } else {
+    EMIT(0x68);
+    emit(x);
+  }
+}
+
+
+void Assembler::push(Register src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x50 | src.code());
+}
+
+
+void Assembler::push(const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xFF);
+  emit_operand(esi, src);
+}
+
+
+void Assembler::pop(Register dst) {
+  ASSERT(reloc_info_writer.last_pc() != NULL);
+  if (FLAG_push_pop_elimination && (reloc_info_writer.last_pc() <= last_pc_)) {
+    // (last_pc_ != NULL) is rolled into the above check
+    // If a last_pc_ is set, we need to make sure that there has not been any
+    // relocation information generated between the last instruction and this
+    // pop instruction.
+    byte instr = last_pc_[0];
+    if ((instr & ~0x7) == 0x50) {
+      int push_reg_code = instr & 0x7;
+      if (push_reg_code == dst.code()) {
+        pc_ = last_pc_;
+        if (FLAG_print_push_pop_elimination) {
+          PrintF("%d push/pop (same reg) eliminated\n", pc_offset());
+        }
+      } else {
+        // Convert 'push src; pop dst' to 'mov dst, src'.
+        last_pc_[0] = 0x8b;
+        Register src = { push_reg_code };
+        EnsureSpace ensure_space(this);
+        emit_operand(dst, Operand(src));
+        if (FLAG_print_push_pop_elimination) {
+          PrintF("%d push/pop (reg->reg) eliminated\n", pc_offset());
+        }
+      }
+      last_pc_ = NULL;
+      return;
+    } else if (instr == 0xff) {  // push of an operand, convert to a move
+      byte op1 = last_pc_[1];
+      // Check if the operation is really a push
+      if ((op1 & 0x38) == (6 << 3)) {
+        op1 = (op1 & ~0x38) | static_cast<byte>(dst.code() << 3);
+        last_pc_[0] = 0x8b;
+        last_pc_[1] = op1;
+        last_pc_ = NULL;
+        if (FLAG_print_push_pop_elimination) {
+          PrintF("%d push/pop (op->reg) eliminated\n", pc_offset());
+        }
+        return;
+      }
+    } else if ((instr == 0x89) &&
+               (last_pc_[1] == 0x04) &&
+               (last_pc_[2] == 0x24)) {
+      // 0x71283c   396  890424         mov [esp],eax
+      // 0x71283f   399  58             pop eax
+      if (dst.is(eax)) {
+        // change to
+        // 0x710fac   216  83c404         add esp,0x4
+        last_pc_[0] = 0x83;
+        last_pc_[1] = 0xc4;
+        last_pc_[2] = 0x04;
+        last_pc_ = NULL;
+        if (FLAG_print_push_pop_elimination) {
+          PrintF("%d push/pop (mov-pop) eliminated\n", pc_offset());
+        }
+        return;
+      }
+    } else if (instr == 0x6a && dst.is(eax)) {  // push of immediate 8 bit
+      byte imm8 = last_pc_[1];
+      if (imm8 == 0) {
+        // 6a00         push 0x0
+        // 58           pop eax
+        last_pc_[0] = 0x31;
+        last_pc_[1] = 0xc0;
+        // change to
+        // 31c0         xor eax,eax
+        last_pc_ = NULL;
+        if (FLAG_print_push_pop_elimination) {
+          PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
+        }
+        return;
+      } else {
+        // 6a00         push 0xXX
+        // 58           pop eax
+        last_pc_[0] = 0xb8;
+        EnsureSpace ensure_space(this);
+        if ((imm8 & 0x80) != 0) {
+          EMIT(0xff);
+          EMIT(0xff);
+          EMIT(0xff);
+          // change to
+          // b8XXffffff   mov eax,0xffffffXX
+        } else {
+          EMIT(0x00);
+          EMIT(0x00);
+          EMIT(0x00);
+          // change to
+          // b8XX000000   mov eax,0x000000XX
+        }
+        last_pc_ = NULL;
+        if (FLAG_print_push_pop_elimination) {
+          PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
+        }
+        return;
+      }
+    } else if (instr == 0x68 && dst.is(eax)) {  // push of immediate 32 bit
+      // 68XXXXXXXX   push 0xXXXXXXXX
+      // 58           pop eax
+      last_pc_[0] = 0xb8;
+      last_pc_ = NULL;
+      // change to
+      // b8XXXXXXXX   mov eax,0xXXXXXXXX
+      if (FLAG_print_push_pop_elimination) {
+        PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
+      }
+      return;
+    }
+
+    // Other potential patterns for peephole:
+    // 0x712716   102  890424         mov [esp], eax
+    // 0x712719   105  8b1424         mov edx, [esp]
+  }
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x58 | dst.code());
+}
+
+
+void Assembler::pop(const Operand& dst) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x8F);
+  emit_operand(eax, dst);
+}
+
+
+void Assembler::enter(const Immediate& size) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xC8);
+  emit_w(size);
+  EMIT(0);
+}
+
+
+void Assembler::leave() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xC9);
+}
+
+
+void Assembler::mov_b(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x8A);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::mov_b(const Operand& dst, int8_t imm8) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xC6);
+  emit_operand(eax, dst);
+  EMIT(imm8);
+}
+
+
+void Assembler::mov_b(const Operand& dst, Register src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x88);
+  emit_operand(src, dst);
+}
+
+
+void Assembler::mov_w(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x66);
+  EMIT(0x8B);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::mov_w(const Operand& dst, Register src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x66);
+  EMIT(0x89);
+  emit_operand(src, dst);
+}
+
+
+void Assembler::mov(Register dst, int32_t imm32) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xB8 | dst.code());
+  emit(imm32);
+}
+
+
+void Assembler::mov(Register dst, const Immediate& x) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xB8 | dst.code());
+  emit(x);
+}
+
+
+void Assembler::mov(Register dst, Handle<Object> handle) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xB8 | dst.code());
+  emit(handle);
+}
+
+
+void Assembler::mov(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x8B);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::mov(Register dst, Register src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x89);
+  EMIT(0xC0 | src.code() << 3 | dst.code());
+}
+
+
+void Assembler::mov(const Operand& dst, const Immediate& x) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xC7);
+  emit_operand(eax, dst);
+  emit(x);
+}
+
+
+void Assembler::mov(const Operand& dst, Handle<Object> handle) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xC7);
+  emit_operand(eax, dst);
+  emit(handle);
+}
+
+
+void Assembler::mov(const Operand& dst, Register src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x89);
+  emit_operand(src, dst);
+}
+
+
+void Assembler::movsx_b(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x0F);
+  EMIT(0xBE);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::movsx_w(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x0F);
+  EMIT(0xBF);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::movzx_b(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x0F);
+  EMIT(0xB6);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::movzx_w(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x0F);
+  EMIT(0xB7);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::cmov(Condition cc, Register dst, int32_t imm32) {
+  ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CMOV));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  UNIMPLEMENTED();
+  USE(cc);
+  USE(dst);
+  USE(imm32);
+}
+
+
+void Assembler::cmov(Condition cc, Register dst, Handle<Object> handle) {
+  ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CMOV));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  UNIMPLEMENTED();
+  USE(cc);
+  USE(dst);
+  USE(handle);
+}
+
+
+void Assembler::cmov(Condition cc, Register dst, const Operand& src) {
+  ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CMOV));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  UNIMPLEMENTED();
+  USE(cc);
+  USE(dst);
+  USE(src);
+}
+
+
+void Assembler::xchg(Register dst, Register src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  if (src.is(eax) || dst.is(eax)) {  // Single-byte encoding
+    EMIT(0x90 | (src.is(eax) ? dst.code() : src.code()));
+  } else {
+    EMIT(0x87);
+    EMIT(0xC0 | src.code() << 3 | dst.code());
+  }
+}
+
+
+void Assembler::adc(Register dst, int32_t imm32) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_arith(2, Operand(dst), Immediate(imm32));
+}
+
+
+void Assembler::adc(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x13);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::add(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x03);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::add(const Operand& dst, const Immediate& x) {
+  ASSERT(reloc_info_writer.last_pc() != NULL);
+  if (FLAG_push_pop_elimination && (reloc_info_writer.last_pc() <= last_pc_)) {
+    byte instr = last_pc_[0];
+    if ((instr & 0xf8) == 0x50) {
+      // Last instruction was a push. Check whether this is a pop without a
+      // result.
+      if ((dst.is_reg(esp)) &&
+          (x.x_ == kPointerSize) && (x.rmode_ == RelocInfo::NONE)) {
+        pc_ = last_pc_;
+        last_pc_ = NULL;
+        if (FLAG_print_push_pop_elimination) {
+          PrintF("%d push/pop(noreg) eliminated\n", pc_offset());
+        }
+        return;
+      }
+    }
+  }
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_arith(0, dst, x);
+}
+
+
+void Assembler::and_(Register dst, int32_t imm32) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_arith(4, Operand(dst), Immediate(imm32));
+}
+
+
+void Assembler::and_(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x23);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::and_(const Operand& dst, const Immediate& x) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_arith(4, dst, x);
+}
+
+
+void Assembler::and_(const Operand& dst, Register src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x21);
+  emit_operand(src, dst);
+}
+
+
+void Assembler::cmpb(const Operand& op, int8_t imm8) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x80);
+  emit_operand(edi, op);  // edi == 7
+  EMIT(imm8);
+}
+
+
+void Assembler::cmpw(const Operand& op, Immediate imm16) {
+  ASSERT(imm16.is_int16());
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x66);
+  EMIT(0x81);
+  emit_operand(edi, op);
+  emit_w(imm16);
+}
+
+
+void Assembler::cmp(Register reg, int32_t imm32) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_arith(7, Operand(reg), Immediate(imm32));
+}
+
+
+void Assembler::cmp(Register reg, Handle<Object> handle) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_arith(7, Operand(reg), Immediate(handle));
+}
+
+
+void Assembler::cmp(Register reg, const Operand& op) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x3B);
+  emit_operand(reg, op);
+}
+
+
+void Assembler::cmp(const Operand& op, const Immediate& imm) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_arith(7, op, imm);
+}
+
+
+void Assembler::cmpb_al(const Operand& op) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x38);  // CMP r/m8, r8
+  emit_operand(eax, op);  // eax has same code as register al.
+}
+
+
+void Assembler::cmpw_ax(const Operand& op) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x66);
+  EMIT(0x39);  // CMP r/m16, r16
+  emit_operand(eax, op);  // eax has same code as register ax.
+}
+
+
+void Assembler::dec_b(Register dst) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xFE);
+  EMIT(0xC8 | dst.code());
+}
+
+
+void Assembler::dec(Register dst) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x48 | dst.code());
+}
+
+
+void Assembler::dec(const Operand& dst) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xFF);
+  emit_operand(ecx, dst);
+}
+
+
+void Assembler::cdq() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x99);
+}
+
+
+void Assembler::idiv(Register src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xF7);
+  EMIT(0xF8 | src.code());
+}
+
+
+void Assembler::imul(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x0F);
+  EMIT(0xAF);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::imul(Register dst, Register src, int32_t imm32) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  if (is_int8(imm32)) {
+    EMIT(0x6B);
+    EMIT(0xC0 | dst.code() << 3 | src.code());
+    EMIT(imm32);
+  } else {
+    EMIT(0x69);
+    EMIT(0xC0 | dst.code() << 3 | src.code());
+    emit(imm32);
+  }
+}
+
+
+void Assembler::inc(Register dst) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x40 | dst.code());
+}
+
+
+void Assembler::inc(const Operand& dst) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xFF);
+  emit_operand(eax, dst);
+}
+
+
+void Assembler::lea(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x8D);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::mul(Register src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xF7);
+  EMIT(0xE0 | src.code());
+}
+
+
+void Assembler::neg(Register dst) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xF7);
+  EMIT(0xD8 | dst.code());
+}
+
+
+void Assembler::not_(Register dst) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xF7);
+  EMIT(0xD0 | dst.code());
+}
+
+
+void Assembler::or_(Register dst, int32_t imm32) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_arith(1, Operand(dst), Immediate(imm32));
+}
+
+
+void Assembler::or_(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x0B);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::or_(const Operand& dst, const Immediate& x) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_arith(1, dst, x);
+}
+
+
+void Assembler::or_(const Operand& dst, Register src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x09);
+  emit_operand(src, dst);
+}
+
+
+void Assembler::rcl(Register dst, uint8_t imm8) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  ASSERT(is_uint5(imm8));  // illegal shift count
+  if (imm8 == 1) {
+    EMIT(0xD1);
+    EMIT(0xD0 | dst.code());
+  } else {
+    EMIT(0xC1);
+    EMIT(0xD0 | dst.code());
+    EMIT(imm8);
+  }
+}
+
+
+void Assembler::sar(Register dst, uint8_t imm8) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  ASSERT(is_uint5(imm8));  // illegal shift count
+  if (imm8 == 1) {
+    EMIT(0xD1);
+    EMIT(0xF8 | dst.code());
+  } else {
+    EMIT(0xC1);
+    EMIT(0xF8 | dst.code());
+    EMIT(imm8);
+  }
+}
+
+
+void Assembler::sar(Register dst) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xD3);
+  EMIT(0xF8 | dst.code());
+}
+
+
+void Assembler::sbb(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x1B);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::shld(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x0F);
+  EMIT(0xA5);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::shl(Register dst, uint8_t imm8) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  ASSERT(is_uint5(imm8));  // illegal shift count
+  if (imm8 == 1) {
+    EMIT(0xD1);
+    EMIT(0xE0 | dst.code());
+  } else {
+    EMIT(0xC1);
+    EMIT(0xE0 | dst.code());
+    EMIT(imm8);
+  }
+}
+
+
+void Assembler::shl(Register dst) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xD3);
+  EMIT(0xE0 | dst.code());
+}
+
+
+void Assembler::shrd(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x0F);
+  EMIT(0xAD);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::shr(Register dst, uint8_t imm8) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  ASSERT(is_uint5(imm8));  // illegal shift count
+  EMIT(0xC1);
+  EMIT(0xE8 | dst.code());
+  EMIT(imm8);
+}
+
+
+void Assembler::shr(Register dst) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xD3);
+  EMIT(0xE8 | dst.code());
+}
+
+
+void Assembler::shr_cl(Register dst) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xD1);
+  EMIT(0xE8 | dst.code());
+}
+
+
+void Assembler::sub(const Operand& dst, const Immediate& x) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_arith(5, dst, x);
+}
+
+
+void Assembler::sub(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x2B);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::sub(const Operand& dst, Register src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x29);
+  emit_operand(src, dst);
+}
+
+
+void Assembler::test(Register reg, const Immediate& imm) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  // Only use test against byte for registers that have a byte
+  // variant: eax, ebx, ecx, and edx.
+  if (imm.rmode_ == RelocInfo::NONE && is_uint8(imm.x_) && reg.code() < 4) {
+    uint8_t imm8 = imm.x_;
+    if (reg.is(eax)) {
+      EMIT(0xA8);
+      EMIT(imm8);
+    } else {
+      emit_arith_b(0xF6, 0xC0, reg, imm8);
+    }
+  } else {
+    // This is not using emit_arith because test doesn't support
+    // sign-extension of 8-bit operands.
+    if (reg.is(eax)) {
+      EMIT(0xA9);
+    } else {
+      EMIT(0xF7);
+      EMIT(0xC0 | reg.code());
+    }
+    emit(imm);
+  }
+}
+
+
+void Assembler::test(Register reg, const Operand& op) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x85);
+  emit_operand(reg, op);
+}
+
+
+void Assembler::test(const Operand& op, const Immediate& imm) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xF7);
+  emit_operand(eax, op);
+  emit(imm);
+}
+
+
+void Assembler::xor_(Register dst, int32_t imm32) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_arith(6, Operand(dst), Immediate(imm32));
+}
+
+
+void Assembler::xor_(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x33);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::xor_(const Operand& src, Register dst) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x31);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::xor_(const Operand& dst, const Immediate& x) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_arith(6, dst, x);
+}
+
+
+void Assembler::bt(const Operand& dst, Register src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x0F);
+  EMIT(0xA3);
+  emit_operand(src, dst);
+}
+
+
+void Assembler::bts(const Operand& dst, Register src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x0F);
+  EMIT(0xAB);
+  emit_operand(src, dst);
+}
+
+
+void Assembler::hlt() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xF4);
+}
+
+
+void Assembler::int3() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xCC);
+}
+
+
+void Assembler::nop() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x90);
+}
+
+
+void Assembler::rdtsc() {
+  ASSERT(CpuFeatures::IsEnabled(CpuFeatures::RDTSC));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x0F);
+  EMIT(0x31);
+}
+
+
+void Assembler::ret(int imm16) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  ASSERT(is_uint16(imm16));
+  if (imm16 == 0) {
+    EMIT(0xC3);
+  } else {
+    EMIT(0xC2);
+    EMIT(imm16 & 0xFF);
+    EMIT((imm16 >> 8) & 0xFF);
+  }
+}
+
+
+// Labels refer to positions in the (to be) generated code.
+// There are bound, linked, and unused labels.
+//
+// Bound labels refer to known positions in the already
+// generated code. pos() is the position the label refers to.
+//
+// Linked labels refer to unknown positions in the code
+// to be generated; pos() is the position of the 32bit
+// Displacement of the last instruction using the label.
+
+
+void Assembler::print(Label* L) {
+  if (L->is_unused()) {
+    PrintF("unused label\n");
+  } else if (L->is_bound()) {
+    PrintF("bound label to %d\n", L->pos());
+  } else if (L->is_linked()) {
+    Label l = *L;
+    PrintF("unbound label");
+    while (l.is_linked()) {
+      Displacement disp = disp_at(&l);
+      PrintF("@ %d ", l.pos());
+      disp.print();
+      PrintF("\n");
+      disp.next(&l);
+    }
+  } else {
+    PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
+  }
+}
+
+
+void Assembler::bind_to(Label* L, int pos) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = NULL;
+  ASSERT(0 <= pos && pos <= pc_offset());  // must have a valid binding position
+  while (L->is_linked()) {
+    Displacement disp = disp_at(L);
+    int fixup_pos = L->pos();
+    if (disp.type() == Displacement::CODE_RELATIVE) {
+      // Relative to Code* heap object pointer.
+      long_at_put(fixup_pos, pos + Code::kHeaderSize - kHeapObjectTag);
+    } else {
+      if (disp.type() == Displacement::UNCONDITIONAL_JUMP) {
+        ASSERT(byte_at(fixup_pos - 1) == 0xE9);  // jmp expected
+      }
+      // relative address, relative to point after address
+      int imm32 = pos - (fixup_pos + sizeof(int32_t));
+      long_at_put(fixup_pos, imm32);
+    }
+    disp.next(L);
+  }
+  L->bind_to(pos);
+}
+
+
+void Assembler::link_to(Label* L, Label* appendix) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = NULL;
+  if (appendix->is_linked()) {
+    if (L->is_linked()) {
+      // append appendix to L's list
+      Label p;
+      Label q = *L;
+      do {
+        p = q;
+        Displacement disp = disp_at(&q);
+        disp.next(&q);
+      } while (q.is_linked());
+      Displacement disp = disp_at(&p);
+      disp.link_to(appendix);
+      disp_at_put(&p, disp);
+      p.Unuse();  // to avoid assertion failure in ~Label
+    } else {
+      // L is empty, simply use appendix
+      *L = *appendix;
+    }
+  }
+  appendix->Unuse();  // appendix should not be used anymore
+}
+
+
+void Assembler::bind(Label* L) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = NULL;
+  ASSERT(!L->is_bound());  // label can only be bound once
+  bind_to(L, pc_offset());
+}
+
+
+void Assembler::call(Label* L) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  if (L->is_bound()) {
+    const int long_size = 5;
+    int offs = L->pos() - pc_offset();
+    ASSERT(offs <= 0);
+    // 1110 1000 #32-bit disp
+    EMIT(0xE8);
+    emit(offs - long_size);
+  } else {
+    // 1110 1000 #32-bit disp
+    EMIT(0xE8);
+    emit_disp(L, Displacement::OTHER);
+  }
+}
+
+
+void Assembler::call(byte* entry, RelocInfo::Mode rmode) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  ASSERT(!RelocInfo::IsCodeTarget(rmode));
+  EMIT(0xE8);
+  emit(entry - (pc_ + sizeof(int32_t)), rmode);
+}
+
+
+void Assembler::call(const Operand& adr) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xFF);
+  emit_operand(edx, adr);
+}
+
+
+void Assembler::call(Handle<Code> code,  RelocInfo::Mode rmode) {
+  WriteRecordedPositions();
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  ASSERT(RelocInfo::IsCodeTarget(rmode));
+  EMIT(0xE8);
+  emit(reinterpret_cast<intptr_t>(code.location()), rmode);
+}
+
+
+void Assembler::jmp(Label* L) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  if (L->is_bound()) {
+    const int short_size = 2;
+    const int long_size  = 5;
+    int offs = L->pos() - pc_offset();
+    ASSERT(offs <= 0);
+    if (is_int8(offs - short_size)) {
+      // 1110 1011 #8-bit disp
+      EMIT(0xEB);
+      EMIT((offs - short_size) & 0xFF);
+    } else {
+      // 1110 1001 #32-bit disp
+      EMIT(0xE9);
+      emit(offs - long_size);
+    }
+  } else {
+    // 1110 1001 #32-bit disp
+    EMIT(0xE9);
+    emit_disp(L, Displacement::UNCONDITIONAL_JUMP);
+  }
+}
+
+
+void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  ASSERT(!RelocInfo::IsCodeTarget(rmode));
+  EMIT(0xE9);
+  emit(entry - (pc_ + sizeof(int32_t)), rmode);
+}
+
+
+void Assembler::jmp(const Operand& adr) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xFF);
+  emit_operand(esp, adr);
+}
+
+
+void Assembler::jmp(Handle<Code> code, RelocInfo::Mode rmode) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  ASSERT(RelocInfo::IsCodeTarget(rmode));
+  EMIT(0xE9);
+  emit(reinterpret_cast<intptr_t>(code.location()), rmode);
+}
+
+
+
+void Assembler::j(Condition cc, Label* L, Hint hint) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  ASSERT(0 <= cc && cc < 16);
+  if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
+  if (L->is_bound()) {
+    const int short_size = 2;
+    const int long_size  = 6;
+    int offs = L->pos() - pc_offset();
+    ASSERT(offs <= 0);
+    if (is_int8(offs - short_size)) {
+      // 0111 tttn #8-bit disp
+      EMIT(0x70 | cc);
+      EMIT((offs - short_size) & 0xFF);
+    } else {
+      // 0000 1111 1000 tttn #32-bit disp
+      EMIT(0x0F);
+      EMIT(0x80 | cc);
+      emit(offs - long_size);
+    }
+  } else {
+    // 0000 1111 1000 tttn #32-bit disp
+    // Note: could eliminate cond. jumps to this jump if condition
+    //       is the same however, seems to be rather unlikely case.
+    EMIT(0x0F);
+    EMIT(0x80 | cc);
+    emit_disp(L, Displacement::OTHER);
+  }
+}
+
+
+void Assembler::j(Condition cc, byte* entry, RelocInfo::Mode rmode, Hint hint) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  ASSERT((0 <= cc) && (cc < 16));
+  if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
+  // 0000 1111 1000 tttn #32-bit disp
+  EMIT(0x0F);
+  EMIT(0x80 | cc);
+  emit(entry - (pc_ + sizeof(int32_t)), rmode);
+}
+
+
+void Assembler::j(Condition cc, Handle<Code> code, Hint hint) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
+  // 0000 1111 1000 tttn #32-bit disp
+  EMIT(0x0F);
+  EMIT(0x80 | cc);
+  emit(reinterpret_cast<intptr_t>(code.location()), RelocInfo::CODE_TARGET);
+}
+
+
+// FPU instructions
+
+
+void Assembler::fld(int i) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_farith(0xD9, 0xC0, i);
+}
+
+
+void Assembler::fld1() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xD9);
+  EMIT(0xE8);
+}
+
+
+void Assembler::fldz() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xD9);
+  EMIT(0xEE);
+}
+
+
+void Assembler::fld_s(const Operand& adr) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xD9);
+  emit_operand(eax, adr);
+}
+
+
+void Assembler::fld_d(const Operand& adr) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xDD);
+  emit_operand(eax, adr);
+}
+
+
+void Assembler::fstp_s(const Operand& adr) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xD9);
+  emit_operand(ebx, adr);
+}
+
+
+void Assembler::fstp_d(const Operand& adr) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xDD);
+  emit_operand(ebx, adr);
+}
+
+
+void Assembler::fild_s(const Operand& adr) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xDB);
+  emit_operand(eax, adr);
+}
+
+
+void Assembler::fild_d(const Operand& adr) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xDF);
+  emit_operand(ebp, adr);
+}
+
+
+void Assembler::fistp_s(const Operand& adr) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xDB);
+  emit_operand(ebx, adr);
+}
+
+
+void Assembler::fisttp_s(const Operand& adr) {
+  ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE3));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xDB);
+  emit_operand(ecx, adr);
+}
+
+
+void Assembler::fist_s(const Operand& adr) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xDB);
+  emit_operand(edx, adr);
+}
+
+
+void Assembler::fistp_d(const Operand& adr) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xDF);
+  emit_operand(edi, adr);
+}
+
+
+void Assembler::fabs() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xD9);
+  EMIT(0xE1);
+}
+
+
+void Assembler::fchs() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xD9);
+  EMIT(0xE0);
+}
+
+
+void Assembler::fadd(int i) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_farith(0xDC, 0xC0, i);
+}
+
+
+void Assembler::fsub(int i) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_farith(0xDC, 0xE8, i);
+}
+
+
+void Assembler::fisub_s(const Operand& adr) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xDA);
+  emit_operand(esp, adr);
+}
+
+
+void Assembler::fmul(int i) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_farith(0xDC, 0xC8, i);
+}
+
+
+void Assembler::fdiv(int i) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_farith(0xDC, 0xF8, i);
+}
+
+
+void Assembler::faddp(int i) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_farith(0xDE, 0xC0, i);
+}
+
+
+void Assembler::fsubp(int i) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_farith(0xDE, 0xE8, i);
+}
+
+
+void Assembler::fsubrp(int i) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_farith(0xDE, 0xE0, i);
+}
+
+
+void Assembler::fmulp(int i) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_farith(0xDE, 0xC8, i);
+}
+
+
+void Assembler::fdivp(int i) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_farith(0xDE, 0xF8, i);
+}
+
+
+void Assembler::fprem() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xD9);
+  EMIT(0xF8);
+}
+
+
+void Assembler::fprem1() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xD9);
+  EMIT(0xF5);
+}
+
+
+void Assembler::fxch(int i) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_farith(0xD9, 0xC8, i);
+}
+
+
+void Assembler::fincstp() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xD9);
+  EMIT(0xF7);
+}
+
+
+void Assembler::ffree(int i) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_farith(0xDD, 0xC0, i);
+}
+
+
+void Assembler::ftst() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xD9);
+  EMIT(0xE4);
+}
+
+
+void Assembler::fucomp(int i) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_farith(0xDD, 0xE8, i);
+}
+
+
+void Assembler::fucompp() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xDA);
+  EMIT(0xE9);
+}
+
+
+void Assembler::fcompp() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xDE);
+  EMIT(0xD9);
+}
+
+
+void Assembler::fnstsw_ax() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xdF);
+  EMIT(0xE0);
+}
+
+
+void Assembler::fwait() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x9B);
+}
+
+
+void Assembler::frndint() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xD9);
+  EMIT(0xFC);
+}
+
+
+void Assembler::fnclex() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xDB);
+  EMIT(0xE2);
+}
+
+
+void Assembler::sahf() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x9E);
+}
+
+
+void Assembler::setcc(Condition cc, Register reg) {
+  ASSERT(reg.is_byte_register());
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x0F);
+  EMIT(0x90 | cc);
+  EMIT(0xC0 | reg.code());
+}
+
+
+void Assembler::cvttss2si(Register dst, const Operand& src) {
+  ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xF3);
+  EMIT(0x0F);
+  EMIT(0x2C);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::cvttsd2si(Register dst, const Operand& src) {
+  ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xF2);
+  EMIT(0x0F);
+  EMIT(0x2C);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) {
+  ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xF2);
+  EMIT(0x0F);
+  EMIT(0x2A);
+  emit_sse_operand(dst, src);
+}
+
+
+void Assembler::addsd(XMMRegister dst, XMMRegister src) {
+  ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xF2);
+  EMIT(0x0F);
+  EMIT(0x58);
+  emit_sse_operand(dst, src);
+}
+
+
+void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
+  ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xF2);
+  EMIT(0x0F);
+  EMIT(0x59);
+  emit_sse_operand(dst, src);
+}
+
+
+void Assembler::subsd(XMMRegister dst, XMMRegister src) {
+  ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xF2);
+  EMIT(0x0F);
+  EMIT(0x5C);
+  emit_sse_operand(dst, src);
+}
+
+
+void Assembler::divsd(XMMRegister dst, XMMRegister src) {
+  ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xF2);
+  EMIT(0x0F);
+  EMIT(0x5E);
+  emit_sse_operand(dst, src);
+}
+
+
+void Assembler::movdbl(XMMRegister dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  movsd(dst, src);
+}
+
+
+void Assembler::movdbl(const Operand& dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  movsd(dst, src);
+}
+
+
+void Assembler::movsd(const Operand& dst, XMMRegister src ) {
+  ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xF2);  // double
+  EMIT(0x0F);
+  EMIT(0x11);  // store
+  emit_sse_operand(src, dst);
+}
+
+
+void Assembler::movsd(XMMRegister dst, const Operand& src) {
+  ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xF2);  // double
+  EMIT(0x0F);
+  EMIT(0x10);  // load
+  emit_sse_operand(dst, src);
+}
+
+
+void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
+  Register ireg = { reg.code() };
+  emit_operand(ireg, adr);
+}
+
+
+void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
+  EMIT(0xC0 | dst.code() << 3 | src.code());
+}
+
+
+void Assembler::Print() {
+  Disassembler::Decode(stdout, buffer_, pc_);
+}
+
+
+void Assembler::RecordJSReturn() {
+  WriteRecordedPositions();
+  EnsureSpace ensure_space(this);
+  RecordRelocInfo(RelocInfo::JS_RETURN);
+}
+
+
+void Assembler::RecordComment(const char* msg) {
+  if (FLAG_debug_code) {
+    EnsureSpace ensure_space(this);
+    RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
+  }
+}
+
+
+void Assembler::RecordPosition(int pos) {
+  ASSERT(pos != RelocInfo::kNoPosition);
+  ASSERT(pos >= 0);
+  current_position_ = pos;
+}
+
+
+void Assembler::RecordStatementPosition(int pos) {
+  ASSERT(pos != RelocInfo::kNoPosition);
+  ASSERT(pos >= 0);
+  current_statement_position_ = pos;
+}
+
+
+void Assembler::WriteRecordedPositions() {
+  // Write the statement position if it is different from what was written last
+  // time.
+  if (current_statement_position_ != written_statement_position_) {
+    EnsureSpace ensure_space(this);
+    RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_);
+    written_statement_position_ = current_statement_position_;
+  }
+
+  // Write the position if it is different from what was written last time and
+  // also different from the written statement position.
+  if (current_position_ != written_position_ &&
+      current_position_ != written_statement_position_) {
+    EnsureSpace ensure_space(this);
+    RecordRelocInfo(RelocInfo::POSITION, current_position_);
+    written_position_ = current_position_;
+  }
+}
+
+
+void Assembler::GrowBuffer() {
+  ASSERT(overflow());  // should not call this otherwise
+  if (!own_buffer_) FATAL("external code buffer is too small");
+
+  // compute new buffer size
+  CodeDesc desc;  // the new buffer
+  if (buffer_size_ < 4*KB) {
+    desc.buffer_size = 4*KB;
+  } else {
+    desc.buffer_size = 2*buffer_size_;
+  }
+  // Some internal data structures overflow for very large buffers,
+  // they must ensure that kMaximalBufferSize is not too large.
+  if ((desc.buffer_size > kMaximalBufferSize) ||
+      (desc.buffer_size > Heap::OldGenerationSize())) {
+    V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
+  }
+
+  // setup new buffer
+  desc.buffer = NewArray<byte>(desc.buffer_size);
+  desc.instr_size = pc_offset();
+  desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos());
+
+  // Clear the buffer in debug mode. Use 'int3' instructions to make
+  // sure to get into problems if we ever run uninitialized code.
+  if (kDebug) {
+    memset(desc.buffer, 0xCC, desc.buffer_size);
+  }
+
+  // copy the data
+  int pc_delta = desc.buffer - buffer_;
+  int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
+  memmove(desc.buffer, buffer_, desc.instr_size);
+  memmove(rc_delta + reloc_info_writer.pos(),
+          reloc_info_writer.pos(), desc.reloc_size);
+
+  // switch buffers
+  if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
+    spare_buffer_ = buffer_;
+  } else {
+    DeleteArray(buffer_);
+  }
+  buffer_ = desc.buffer;
+  buffer_size_ = desc.buffer_size;
+  pc_ += pc_delta;
+  if (last_pc_ != NULL) {
+    last_pc_ += pc_delta;
+  }
+  reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
+                               reloc_info_writer.last_pc() + pc_delta);
+
+  // relocate runtime entries
+  for (RelocIterator it(desc); !it.done(); it.next()) {
+    RelocInfo::Mode rmode = it.rinfo()->rmode();
+    if (rmode == RelocInfo::RUNTIME_ENTRY) {
+      int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
+      *p -= pc_delta;  // relocate entry
+    } else if (rmode == RelocInfo::INTERNAL_REFERENCE) {
+      int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
+      if (*p != 0) {  // 0 means uninitialized.
+        *p += pc_delta;
+      }
+    }
+  }
+
+  ASSERT(!overflow());
+}
+
+
+void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) {
+  ASSERT(is_uint8(op1) && is_uint8(op2));  // wrong opcode
+  ASSERT(is_uint8(imm8));
+  ASSERT((op1 & 0x01) == 0);  // should be 8bit operation
+  EMIT(op1);
+  EMIT(op2 | dst.code());
+  EMIT(imm8);
+}
+
+
+void Assembler::emit_arith(int sel, Operand dst, const Immediate& x) {
+  ASSERT((0 <= sel) && (sel <= 7));
+  Register ireg = { sel };
+  if (x.is_int8()) {
+    EMIT(0x83);  // using a sign-extended 8-bit immediate.
+    emit_operand(ireg, dst);
+    EMIT(x.x_ & 0xFF);
+  } else if (dst.is_reg(eax)) {
+    EMIT((sel << 3) | 0x05);  // short form if the destination is eax.
+    emit(x);
+  } else {
+    EMIT(0x81);  // using a literal 32-bit immediate.
+    emit_operand(ireg, dst);
+    emit(x);
+  }
+}
+
+
+void Assembler::emit_operand(Register reg, const Operand& adr) {
+  const unsigned length = adr.len_;
+  ASSERT(length > 0);
+
+  // Emit updated ModRM byte containing the given register.
+  pc_[0] = (adr.buf_[0] & ~0x38) | (reg.code() << 3);
+
+  // Emit the rest of the encoded operand.
+  for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i];
+  pc_ += length;
+
+  // Emit relocation information if necessary.
+  if (length >= sizeof(int32_t) && adr.rmode_ != RelocInfo::NONE) {
+    pc_ -= sizeof(int32_t);  // pc_ must be *at* disp32
+    RecordRelocInfo(adr.rmode_);
+    pc_ += sizeof(int32_t);
+  }
+}
+
+
+void Assembler::emit_farith(int b1, int b2, int i) {
+  ASSERT(is_uint8(b1) && is_uint8(b2));  // wrong opcode
+  ASSERT(0 <= i &&  i < 8);  // illegal stack offset
+  EMIT(b1);
+  EMIT(b2 + i);
+}
+
+
+void Assembler::dd(uint32_t data, RelocInfo::Mode reloc_info) {
+  EnsureSpace ensure_space(this);
+  emit(data, reloc_info);
+}
+
+
+void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
+  ASSERT(rmode != RelocInfo::NONE);
+  // Don't record external references unless the heap will be serialized.
+  if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
+      !Serializer::enabled() &&
+      !FLAG_debug_code) {
+    return;
+  }
+  RelocInfo rinfo(pc_, rmode, data);
+  reloc_info_writer.Write(&rinfo);
+}
+
+
+void Assembler::WriteInternalReference(int position, const Label& bound_label) {
+  ASSERT(bound_label.is_bound());
+  ASSERT(0 <= position);
+  ASSERT(position + static_cast<int>(sizeof(uint32_t)) <= pc_offset());
+  ASSERT(long_at(position) == 0);  // only initialize once!
+
+  uint32_t label_loc = reinterpret_cast<uint32_t>(addr_at(bound_label.pos()));
+  long_at_put(position, label_loc);
+}
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/assembler-ia32.h b/deps/v8/src/assembler-ia32.h
new file mode 100644
index 0000000..a664093
--- /dev/null
+++ b/deps/v8/src/assembler-ia32.h
@@ -0,0 +1,863 @@
+// Copyright (c) 1994-2006 Sun Microsystems Inc.
+// 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.
+//
+// - Redistribution 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 Sun Microsystems or the names of 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.
+
+// The original source code covered by the above license above has been
+// modified significantly by Google Inc.
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+
+// A light-weight IA32 Assembler.
+
+#ifndef V8_ASSEMBLER_IA32_H_
+#define V8_ASSEMBLER_IA32_H_
+
+namespace v8 { namespace internal {
+
+// CPU Registers.
+//
+// 1) We would prefer to use an enum, but enum values are assignment-
+// compatible with int, which has caused code-generation bugs.
+//
+// 2) We would prefer to use a class instead of a struct but we don't like
+// the register initialization to depend on the particular initialization
+// order (which appears to be different on OS X, Linux, and Windows for the
+// installed versions of C++ we tried). Using a struct permits C-style
+// "initialization". Also, the Register objects cannot be const as this
+// forces initialization stubs in MSVC, making us dependent on initialization
+// order.
+//
+// 3) By not using an enum, we are possibly preventing the compiler from
+// doing certain constant folds, which may significantly reduce the
+// code generated for some assembly instructions (because they boil down
+// to a few constants). If this is a problem, we could change the code
+// such that we use an enum in optimized mode, and the struct in debug
+// mode. This way we get the compile-time error checking in debug mode
+// and best performance in optimized code.
+//
+struct Register {
+  bool is_valid() const  { return 0 <= code_ && code_ < 8; }
+  bool is(Register reg) const  { return code_ == reg.code_; }
+  // eax, ebx, ecx and edx are byte registers, the rest are not.
+  bool is_byte_register() const  { return code_ <= 3; }
+  int code() const  {
+    ASSERT(is_valid());
+    return code_;
+  }
+  int bit() const  {
+    ASSERT(is_valid());
+    return 1 << code_;
+  }
+
+  // (unfortunately we can't make this private in a struct)
+  int code_;
+};
+
+const int kNumRegisters = 8;
+
+extern Register eax;
+extern Register ecx;
+extern Register edx;
+extern Register ebx;
+extern Register esp;
+extern Register ebp;
+extern Register esi;
+extern Register edi;
+extern Register no_reg;
+
+
+struct XMMRegister {
+  bool is_valid() const  { return 0 <= code_ && code_ < 2; }  // currently
+  int code() const  {
+    ASSERT(is_valid());
+    return code_;
+  }
+
+  int code_;
+};
+
+extern XMMRegister xmm0;
+extern XMMRegister xmm1;
+extern XMMRegister xmm2;
+extern XMMRegister xmm3;
+extern XMMRegister xmm4;
+extern XMMRegister xmm5;
+extern XMMRegister xmm6;
+extern XMMRegister xmm7;
+
+enum Condition {
+  // any value < 0 is considered no_condition
+  no_condition  = -1,
+
+  overflow      =  0,
+  no_overflow   =  1,
+  below         =  2,
+  above_equal   =  3,
+  equal         =  4,
+  not_equal     =  5,
+  below_equal   =  6,
+  above         =  7,
+  negative      =  8,
+  positive      =  9,
+  parity_even   = 10,
+  parity_odd    = 11,
+  less          = 12,
+  greater_equal = 13,
+  less_equal    = 14,
+  greater       = 15,
+
+  // aliases
+  carry         = below,
+  not_carry     = above_equal,
+  zero          = equal,
+  not_zero      = not_equal,
+  sign          = negative,
+  not_sign      = positive
+};
+
+
+// Returns the equivalent of !cc.
+// Negation of the default no_condition (-1) results in a non-default
+// no_condition value (-2). As long as tests for no_condition check
+// for condition < 0, this will work as expected.
+inline Condition NegateCondition(Condition cc);
+
+// Corresponds to transposing the operands of a comparison.
+inline Condition ReverseCondition(Condition cc) {
+  switch (cc) {
+    case below:
+      return above;
+    case above:
+      return below;
+    case above_equal:
+      return below_equal;
+    case below_equal:
+      return above_equal;
+    case less:
+      return greater;
+    case greater:
+      return less;
+    case greater_equal:
+      return less_equal;
+    case less_equal:
+      return greater_equal;
+    default:
+      return cc;
+  };
+}
+
+enum Hint {
+  no_hint = 0,
+  not_taken = 0x2e,
+  taken = 0x3e
+};
+
+// The result of negating a hint is as if the corresponding condition
+// were negated by NegateCondition.  That is, no_hint is mapped to
+// itself and not_taken and taken are mapped to each other.
+inline Hint NegateHint(Hint hint) {
+  return (hint == no_hint)
+      ? no_hint
+      : ((hint == not_taken) ? taken : not_taken);
+}
+
+
+// -----------------------------------------------------------------------------
+// Machine instruction Immediates
+
+class Immediate BASE_EMBEDDED {
+ public:
+  inline explicit Immediate(int x);
+  inline explicit Immediate(const char* s);
+  inline explicit Immediate(const ExternalReference& ext);
+  inline explicit Immediate(Handle<Object> handle);
+  inline explicit Immediate(Smi* value);
+
+  static Immediate CodeRelativeOffset(Label* label) {
+    return Immediate(label);
+  }
+
+  bool is_zero() const { return x_ == 0 && rmode_ == RelocInfo::NONE; }
+  bool is_int8() const {
+    return -128 <= x_ && x_ < 128 && rmode_ == RelocInfo::NONE;
+  }
+  bool is_int16() const {
+    return -32768 <= x_ && x_ < 32768 && rmode_ == RelocInfo::NONE;
+  }
+
+ private:
+  inline explicit Immediate(Label* value);
+
+  int x_;
+  RelocInfo::Mode rmode_;
+
+  friend class Assembler;
+};
+
+
+// -----------------------------------------------------------------------------
+// Machine instruction Operands
+
+enum ScaleFactor {
+  times_1 = 0,
+  times_2 = 1,
+  times_4 = 2,
+  times_8 = 3
+};
+
+
+class Operand BASE_EMBEDDED {
+ public:
+  // reg
+  INLINE(explicit Operand(Register reg));
+
+  // [disp/r]
+  INLINE(explicit Operand(int32_t disp, RelocInfo::Mode rmode));
+  // disp only must always be relocated
+
+  // [base + disp/r]
+  explicit Operand(Register base, int32_t disp,
+                   RelocInfo::Mode rmode = RelocInfo::NONE);
+
+  // [base + index*scale + disp/r]
+  explicit Operand(Register base,
+                   Register index,
+                   ScaleFactor scale,
+                   int32_t disp,
+                   RelocInfo::Mode rmode = RelocInfo::NONE);
+
+  // [index*scale + disp/r]
+  explicit Operand(Register index,
+                   ScaleFactor scale,
+                   int32_t disp,
+                   RelocInfo::Mode rmode = RelocInfo::NONE);
+
+  static Operand StaticVariable(const ExternalReference& ext) {
+    return Operand(reinterpret_cast<int32_t>(ext.address()),
+                   RelocInfo::EXTERNAL_REFERENCE);
+  }
+
+  static Operand StaticArray(Register index,
+                             ScaleFactor scale,
+                             const ExternalReference& arr) {
+    return Operand(index, scale, reinterpret_cast<int32_t>(arr.address()),
+                   RelocInfo::EXTERNAL_REFERENCE);
+  }
+
+  // Returns true if this Operand is a wrapper for the specified register.
+  bool is_reg(Register reg) const;
+
+ private:
+  byte buf_[6];
+  // The number of bytes in buf_.
+  unsigned int len_;
+  // Only valid if len_ > 4.
+  RelocInfo::Mode rmode_;
+
+  // Set the ModRM byte without an encoded 'reg' register. The
+  // register is encoded later as part of the emit_operand operation.
+  inline void set_modrm(int mod, Register rm);
+
+  inline void set_sib(ScaleFactor scale, Register index, Register base);
+  inline void set_disp8(int8_t disp);
+  inline void set_dispr(int32_t disp, RelocInfo::Mode rmode);
+
+  friend class Assembler;
+};
+
+
+// -----------------------------------------------------------------------------
+// A Displacement describes the 32bit immediate field of an instruction which
+// may be used together with a Label in order to refer to a yet unknown code
+// position. Displacements stored in the instruction stream are used to describe
+// the instruction and to chain a list of instructions using the same Label.
+// A Displacement contains 2 different fields:
+//
+// next field: position of next displacement in the chain (0 = end of list)
+// type field: instruction type
+//
+// A next value of null (0) indicates the end of a chain (note that there can
+// be no displacement at position zero, because there is always at least one
+// instruction byte before the displacement).
+//
+// Displacement _data field layout
+//
+// |31.....2|1......0|
+// [  next  |  type  |
+
+class Displacement BASE_EMBEDDED {
+ public:
+  enum Type {
+    UNCONDITIONAL_JUMP,
+    CODE_RELATIVE,
+    OTHER
+  };
+
+  int data() const { return data_; }
+  Type type() const { return TypeField::decode(data_); }
+  void next(Label* L) const {
+    int n = NextField::decode(data_);
+    n > 0 ? L->link_to(n) : L->Unuse();
+  }
+  void link_to(Label* L) { init(L, type()); }
+
+  explicit Displacement(int data) { data_ = data; }
+
+  Displacement(Label* L, Type type) { init(L, type); }
+
+  void print() {
+    PrintF("%s (%x) ", (type() == UNCONDITIONAL_JUMP ? "jmp" : "[other]"),
+                       NextField::decode(data_));
+  }
+
+ private:
+  int data_;
+
+  class TypeField: public BitField<Type, 0, 2> {};
+  class NextField: public BitField<int,  2, 32-2> {};
+
+  void init(Label* L, Type type);
+};
+
+
+
+// CpuFeatures keeps track of which features are supported by the target CPU.
+// Supported features must be enabled by a Scope before use.
+// Example:
+//   if (CpuFeatures::IsSupported(SSE2)) {
+//     CpuFeatures::Scope fscope(SSE2);
+//     // Generate SSE2 floating point code.
+//   } else {
+//     // Generate standard x87 floating point code.
+//   }
+class CpuFeatures : public AllStatic {
+ public:
+  // 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.)
+  enum Feature { SSE3 = 32, SSE2 = 26, CMOV = 15, RDTSC = 4, CPUID = 10 };
+  // Detect features of the target CPU. Set safe defaults if the serializer
+  // is enabled (snapshots must be portable).
+  static void Probe();
+  // Check whether a feature is supported by the target CPU.
+  static bool IsSupported(Feature f) {
+    return (supported_ & (static_cast<uint64_t>(1) << f)) != 0;
+  }
+  // Check whether a feature is currently enabled.
+  static bool IsEnabled(Feature f) {
+    return (enabled_ & (static_cast<uint64_t>(1) << f)) != 0;
+  }
+  // Enable a specified feature within a scope.
+  class Scope BASE_EMBEDDED {
+#ifdef DEBUG
+   public:
+    explicit Scope(Feature f) {
+      ASSERT(CpuFeatures::IsSupported(f));
+      old_enabled_ = CpuFeatures::enabled_;
+      CpuFeatures::enabled_ |= (static_cast<uint64_t>(1) << f);
+    }
+    ~Scope() { CpuFeatures::enabled_ = old_enabled_; }
+   private:
+    uint64_t old_enabled_;
+#else
+   public:
+    explicit Scope(Feature f) {}
+#endif
+  };
+ private:
+  static uint64_t supported_;
+  static uint64_t enabled_;
+};
+
+
+class Assembler : public Malloced {
+ private:
+  // The relocation writer's position is kGap bytes below the end of
+  // the generated instructions. This leaves enough space for the
+  // longest possible ia32 instruction (17 bytes as of 9/26/06) and
+  // allows for a single, fast space check per instruction.
+  static const int kGap = 32;
+
+ public:
+  // Create an assembler. Instructions and relocation information are emitted
+  // into a buffer, with the instructions starting from the beginning and the
+  // relocation information starting from the end of the buffer. See CodeDesc
+  // for a detailed comment on the layout (globals.h).
+  //
+  // If the provided buffer is NULL, the assembler allocates and grows its own
+  // buffer, and buffer_size determines the initial buffer size. The buffer is
+  // owned by the assembler and deallocated upon destruction of the assembler.
+  //
+  // If the provided buffer is not NULL, the assembler uses the provided buffer
+  // for code generation and assumes its size to be buffer_size. If the buffer
+  // is too small, a fatal error occurs. No deallocation of the buffer is done
+  // upon destruction of the assembler.
+  Assembler(void* buffer, int buffer_size);
+  ~Assembler();
+
+  // GetCode emits any pending (non-emitted) code and fills the descriptor
+  // desc. GetCode() is idempotent; it returns the same result if no other
+  // Assembler functions are invoked in between GetCode() calls.
+  void GetCode(CodeDesc* desc);
+
+  // Read/Modify the code target in the branch/call instruction at pc.
+  inline static Address target_address_at(Address pc);
+  inline static void set_target_address_at(Address pc, Address target);
+
+  // Distance between the address of the code target in the call instruction
+  // and the return address
+  static const int kTargetAddrToReturnAddrDist = kPointerSize;
+
+
+  // ---------------------------------------------------------------------------
+  // Code generation
+  //
+  // - function names correspond one-to-one to ia32 instruction mnemonics
+  // - unless specified otherwise, instructions operate on 32bit operands
+  // - instructions on 8bit (byte) operands/registers have a trailing '_b'
+  // - instructions on 16bit (word) operands/registers have a trailing '_w'
+  // - naming conflicts with C++ keywords are resolved via a trailing '_'
+
+  // NOTE ON INTERFACE: Currently, the interface is not very consistent
+  // in the sense that some operations (e.g. mov()) can be called in more
+  // the one way to generate the same instruction: The Register argument
+  // can in some cases be replaced with an Operand(Register) argument.
+  // This should be cleaned up and made more orthogonal. The questions
+  // is: should we always use Operands instead of Registers where an
+  // Operand is possible, or should we have a Register (overloaded) form
+  // instead? We must be careful to make sure that the selected instruction
+  // is obvious from the parameters to avoid hard-to-find code generation
+  // bugs.
+
+  // Insert the smallest number of nop instructions
+  // possible to align the pc offset to a multiple
+  // of m. m must be a power of 2.
+  void Align(int m);
+
+  // Stack
+  void pushad();
+  void popad();
+
+  void pushfd();
+  void popfd();
+
+  void push(const Immediate& x);
+  void push(Register src);
+  void push(const Operand& src);
+  void push(Label* label, RelocInfo::Mode relocation_mode);
+
+  void pop(Register dst);
+  void pop(const Operand& dst);
+
+  void enter(const Immediate& size);
+  void leave();
+
+  // Moves
+  void mov_b(Register dst, const Operand& src);
+  void mov_b(const Operand& dst, int8_t imm8);
+  void mov_b(const Operand& dst, Register src);
+
+  void mov_w(Register dst, const Operand& src);
+  void mov_w(const Operand& dst, Register src);
+
+  void mov(Register dst, int32_t imm32);
+  void mov(Register dst, const Immediate& x);
+  void mov(Register dst, Handle<Object> handle);
+  void mov(Register dst, const Operand& src);
+  void mov(Register dst, Register src);
+  void mov(const Operand& dst, const Immediate& x);
+  void mov(const Operand& dst, Handle<Object> handle);
+  void mov(const Operand& dst, Register src);
+
+  void movsx_b(Register dst, const Operand& src);
+
+  void movsx_w(Register dst, const Operand& src);
+
+  void movzx_b(Register dst, const Operand& src);
+
+  void movzx_w(Register dst, const Operand& src);
+
+  // Conditional moves
+  void cmov(Condition cc, Register dst, int32_t imm32);
+  void cmov(Condition cc, Register dst, Handle<Object> handle);
+  void cmov(Condition cc, Register dst, const Operand& src);
+
+  // Exchange two registers
+  void xchg(Register dst, Register src);
+
+  // Arithmetics
+  void adc(Register dst, int32_t imm32);
+  void adc(Register dst, const Operand& src);
+
+  void add(Register dst, const Operand& src);
+  void add(const Operand& dst, const Immediate& x);
+
+  void and_(Register dst, int32_t imm32);
+  void and_(Register dst, const Operand& src);
+  void and_(const Operand& src, Register dst);
+  void and_(const Operand& dst, const Immediate& x);
+
+  void cmpb(const Operand& op, int8_t imm8);
+  void cmpb_al(const Operand& op);
+  void cmpw_ax(const Operand& op);
+  void cmpw(const Operand& op, Immediate imm16);
+  void cmp(Register reg, int32_t imm32);
+  void cmp(Register reg, Handle<Object> handle);
+  void cmp(Register reg, const Operand& op);
+  void cmp(const Operand& op, const Immediate& imm);
+
+  void dec_b(Register dst);
+
+  void dec(Register dst);
+  void dec(const Operand& dst);
+
+  void cdq();
+
+  void idiv(Register src);
+
+  void imul(Register dst, const Operand& src);
+  void imul(Register dst, Register src, int32_t imm32);
+
+  void inc(Register dst);
+  void inc(const Operand& dst);
+
+  void lea(Register dst, const Operand& src);
+
+  void mul(Register src);
+
+  void neg(Register dst);
+
+  void not_(Register dst);
+
+  void or_(Register dst, int32_t imm32);
+  void or_(Register dst, const Operand& src);
+  void or_(const Operand& dst, Register src);
+  void or_(const Operand& dst, const Immediate& x);
+
+  void rcl(Register dst, uint8_t imm8);
+
+  void sar(Register dst, uint8_t imm8);
+  void sar(Register dst);
+
+  void sbb(Register dst, const Operand& src);
+
+  void shld(Register dst, const Operand& src);
+
+  void shl(Register dst, uint8_t imm8);
+  void shl(Register dst);
+
+  void shrd(Register dst, const Operand& src);
+
+  void shr(Register dst, uint8_t imm8);
+  void shr(Register dst);
+  void shr_cl(Register dst);
+
+  void sub(const Operand& dst, const Immediate& x);
+  void sub(Register dst, const Operand& src);
+  void sub(const Operand& dst, Register src);
+
+  void test(Register reg, const Immediate& imm);
+  void test(Register reg, const Operand& op);
+  void test(const Operand& op, const Immediate& imm);
+
+  void xor_(Register dst, int32_t imm32);
+  void xor_(Register dst, const Operand& src);
+  void xor_(const Operand& src, Register dst);
+  void xor_(const Operand& dst, const Immediate& x);
+
+  // Bit operations.
+  void bt(const Operand& dst, Register src);
+  void bts(const Operand& dst, Register src);
+
+  // Miscellaneous
+  void hlt();
+  void int3();
+  void nop();
+  void rdtsc();
+  void ret(int imm16);
+
+  // Label operations & relative jumps (PPUM Appendix D)
+  //
+  // Takes a branch opcode (cc) and a label (L) and generates
+  // either a backward branch or a forward branch and links it
+  // to the label fixup chain. Usage:
+  //
+  // Label L;    // unbound label
+  // j(cc, &L);  // forward branch to unbound label
+  // bind(&L);   // bind label to the current pc
+  // j(cc, &L);  // backward branch to bound label
+  // bind(&L);   // illegal: a label may be bound only once
+  //
+  // Note: The same Label can be used for forward and backward branches
+  // but it may be bound only once.
+
+  void bind(Label* L);  // binds an unbound label L to the current code position
+
+  // Calls
+  void call(Label* L);
+  void call(byte* entry, RelocInfo::Mode rmode);
+  void call(const Operand& adr);
+  void call(Handle<Code> code, RelocInfo::Mode rmode);
+
+  // Jumps
+  void jmp(Label* L);  // unconditional jump to L
+  void jmp(byte* entry, RelocInfo::Mode rmode);
+  void jmp(const Operand& adr);
+  void jmp(Handle<Code> code, RelocInfo::Mode rmode);
+
+  // Conditional jumps
+  void j(Condition cc, Label* L, Hint hint = no_hint);
+  void j(Condition cc, byte* entry, RelocInfo::Mode rmode, Hint hint = no_hint);
+  void j(Condition cc, Handle<Code> code, Hint hint = no_hint);
+
+  // Floating-point operations
+  void fld(int i);
+
+  void fld1();
+  void fldz();
+
+  void fld_s(const Operand& adr);
+  void fld_d(const Operand& adr);
+
+  void fstp_s(const Operand& adr);
+  void fstp_d(const Operand& adr);
+
+  void fild_s(const Operand& adr);
+  void fild_d(const Operand& adr);
+
+  void fist_s(const Operand& adr);
+
+  void fistp_s(const Operand& adr);
+  void fistp_d(const Operand& adr);
+
+  void fisttp_s(const Operand& adr);
+
+  void fabs();
+  void fchs();
+
+  void fadd(int i);
+  void fsub(int i);
+  void fmul(int i);
+  void fdiv(int i);
+
+  void fisub_s(const Operand& adr);
+
+  void faddp(int i = 1);
+  void fsubp(int i = 1);
+  void fsubrp(int i = 1);
+  void fmulp(int i = 1);
+  void fdivp(int i = 1);
+  void fprem();
+  void fprem1();
+
+  void fxch(int i = 1);
+  void fincstp();
+  void ffree(int i = 0);
+
+  void ftst();
+  void fucomp(int i);
+  void fucompp();
+  void fcompp();
+  void fnstsw_ax();
+  void fwait();
+  void fnclex();
+
+  void frndint();
+
+  void sahf();
+  void setcc(Condition cc, Register reg);
+
+  void cpuid();
+
+  // SSE2 instructions
+  void cvttss2si(Register dst, const Operand& src);
+  void cvttsd2si(Register dst, const Operand& src);
+
+  void cvtsi2sd(XMMRegister dst, const Operand& src);
+
+  void addsd(XMMRegister dst, XMMRegister src);
+  void subsd(XMMRegister dst, XMMRegister src);
+  void mulsd(XMMRegister dst, XMMRegister src);
+  void divsd(XMMRegister dst, XMMRegister src);
+
+  // Use either movsd or movlpd.
+  void movdbl(XMMRegister dst, const Operand& src);
+  void movdbl(const Operand& dst, XMMRegister src);
+
+  // Debugging
+  void Print();
+
+  // Check the code size generated from label to here.
+  int SizeOfCodeGeneratedSince(Label* l) { return pc_offset() - l->pos(); }
+
+  // Mark address of the ExitJSFrame code.
+  void RecordJSReturn();
+
+  // Record a comment relocation entry that can be used by a disassembler.
+  // Use --debug_code to enable.
+  void RecordComment(const char* msg);
+
+  void RecordPosition(int pos);
+  void RecordStatementPosition(int pos);
+  void WriteRecordedPositions();
+
+  // Writes a single word of data in the code stream.
+  // Used for inline tables, e.g., jump-tables.
+  void dd(uint32_t data, RelocInfo::Mode reloc_info);
+
+  // Writes the absolute address of a bound label at the given position in
+  // the generated code. That positions should have the relocation mode
+  // internal_reference!
+  void WriteInternalReference(int position, const Label& bound_label);
+
+  int pc_offset() const  { return pc_ - buffer_; }
+  int current_statement_position() const { return current_statement_position_; }
+  int current_position() const  { return current_position_; }
+
+  // Check if there is less than kGap bytes available in the buffer.
+  // If this is the case, we need to grow the buffer before emitting
+  // an instruction or relocation information.
+  inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; }
+
+  // Get the number of bytes available in the buffer.
+  inline int available_space() const { return reloc_info_writer.pos() - pc_; }
+
+  // Avoid overflows for displacements etc.
+  static const int kMaximalBufferSize = 512*MB;
+  static const int kMinimalBufferSize = 4*KB;
+
+ protected:
+  void movsd(XMMRegister dst, const Operand& src);
+  void movsd(const Operand& dst, XMMRegister src);
+
+  void emit_sse_operand(XMMRegister reg, const Operand& adr);
+  void emit_sse_operand(XMMRegister dst, XMMRegister src);
+
+
+ private:
+  byte* addr_at(int pos)  { return buffer_ + pos; }
+  byte byte_at(int pos)  { return buffer_[pos]; }
+  uint32_t long_at(int pos)  {
+    return *reinterpret_cast<uint32_t*>(addr_at(pos));
+  }
+  void long_at_put(int pos, uint32_t x)  {
+    *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
+  }
+
+  // code emission
+  void GrowBuffer();
+  inline void emit(uint32_t x);
+  inline void emit(Handle<Object> handle);
+  inline void emit(uint32_t x, RelocInfo::Mode rmode);
+  inline void emit(const Immediate& x);
+  inline void emit_w(const Immediate& x);
+
+  // Emit the code-object-relative offset of the label's position
+  inline void emit_code_relative_offset(Label* label);
+
+  // instruction generation
+  void emit_arith_b(int op1, int op2, Register dst, int imm8);
+
+  // Emit a basic arithmetic instruction (i.e. first byte of the family is 0x81)
+  // with a given destination expression and an immediate operand.  It attempts
+  // to use the shortest encoding possible.
+  // sel specifies the /n in the modrm byte (see the Intel PRM).
+  void emit_arith(int sel, Operand dst, const Immediate& x);
+
+  void emit_operand(Register reg, const Operand& adr);
+
+  void emit_farith(int b1, int b2, int i);
+
+  // labels
+  void print(Label* L);
+  void bind_to(Label* L, int pos);
+  void link_to(Label* L, Label* appendix);
+
+  // displacements
+  inline Displacement disp_at(Label* L);
+  inline void disp_at_put(Label* L, Displacement disp);
+  inline void emit_disp(Label* L, Displacement::Type type);
+
+  // record reloc info for current pc_
+  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
+
+  friend class CodePatcher;
+  friend class EnsureSpace;
+
+  // Code buffer:
+  // The buffer into which code and relocation info are generated.
+  byte* buffer_;
+  int buffer_size_;
+  // True if the assembler owns the buffer, false if buffer is external.
+  bool own_buffer_;
+
+  // code generation
+  byte* pc_;  // the program counter; moves forward
+  RelocInfoWriter reloc_info_writer;
+
+  // push-pop elimination
+  byte* last_pc_;
+
+  // source position information
+  int current_statement_position_;
+  int current_position_;
+  int written_statement_position_;
+  int written_position_;
+};
+
+
+// Helper class that ensures that there is enough space for generating
+// instructions and relocation information.  The constructor makes
+// sure that there is enough space and (in debug mode) the destructor
+// checks that we did not generate too much.
+class EnsureSpace BASE_EMBEDDED {
+ public:
+  explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
+    if (assembler_->overflow()) assembler_->GrowBuffer();
+#ifdef DEBUG
+    space_before_ = assembler_->available_space();
+#endif
+  }
+
+#ifdef DEBUG
+  ~EnsureSpace() {
+    int bytes_generated = space_before_ - assembler_->available_space();
+    ASSERT(bytes_generated < assembler_->kGap);
+  }
+#endif
+
+ private:
+  Assembler* assembler_;
+#ifdef DEBUG
+  int space_before_;
+#endif
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_ASSEMBLER_IA32_H_
diff --git a/deps/v8/src/assembler.cc b/deps/v8/src/assembler.cc
new file mode 100644
index 0000000..ad4b24c
--- /dev/null
+++ b/deps/v8/src/assembler.cc
@@ -0,0 +1,585 @@
+// Copyright (c) 1994-2006 Sun Microsystems Inc.
+// 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.
+//
+// - Redistribution 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 Sun Microsystems or the names of 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.
+
+// The original source code covered by the above license above has been
+// modified significantly by Google Inc.
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+
+#include "v8.h"
+
+#include "arguments.h"
+#include "execution.h"
+#include "ic-inl.h"
+#include "factory.h"
+#include "runtime.h"
+#include "serialize.h"
+#include "stub-cache.h"
+#include "regexp-stack.h"
+
+namespace v8 { namespace internal {
+
+
+// -----------------------------------------------------------------------------
+// Implementation of Label
+
+int Label::pos() const {
+  if (pos_ < 0) return -pos_ - 1;
+  if (pos_ > 0) return  pos_ - 1;
+  UNREACHABLE();
+  return 0;
+}
+
+
+// -----------------------------------------------------------------------------
+// Implementation of RelocInfoWriter and RelocIterator
+//
+// Encoding
+//
+// The most common modes are given single-byte encodings.  Also, it is
+// easy to identify the type of reloc info and skip unwanted modes in
+// an iteration.
+//
+// The encoding relies on the fact that there are less than 14
+// different relocation modes.
+//
+// embedded_object:    [6 bits pc delta] 00
+//
+// code_taget:         [6 bits pc delta] 01
+//
+// position:           [6 bits pc delta] 10,
+//                     [7 bits signed data delta] 0
+//
+// statement_position: [6 bits pc delta] 10,
+//                     [7 bits signed data delta] 1
+//
+// any nondata mode:   00 [4 bits rmode] 11,  // rmode: 0..13 only
+//                     00 [6 bits pc delta]
+//
+// pc-jump:            00 1111 11,
+//                     00 [6 bits pc delta]
+//
+// pc-jump:            01 1111 11,
+// (variable length)   7 - 26 bit pc delta, written in chunks of 7
+//                     bits, the lowest 7 bits written first.
+//
+// data-jump + pos:    00 1110 11,
+//                     signed int, lowest byte written first
+//
+// data-jump + st.pos: 01 1110 11,
+//                     signed int, lowest byte written first
+//
+// data-jump + comm.:  10 1110 11,
+//                     signed int, lowest byte written first
+//
+const int kMaxRelocModes = 14;
+
+const int kTagBits = 2;
+const int kTagMask = (1 << kTagBits) - 1;
+const int kExtraTagBits = 4;
+const int kPositionTypeTagBits = 1;
+const int kSmallDataBits = kBitsPerByte - kPositionTypeTagBits;
+
+const int kEmbeddedObjectTag = 0;
+const int kCodeTargetTag = 1;
+const int kPositionTag = 2;
+const int kDefaultTag = 3;
+
+const int kPCJumpTag = (1 << kExtraTagBits) - 1;
+
+const int kSmallPCDeltaBits = kBitsPerByte - kTagBits;
+const int kSmallPCDeltaMask = (1 << kSmallPCDeltaBits) - 1;
+
+const int kVariableLengthPCJumpTopTag = 1;
+const int kChunkBits = 7;
+const int kChunkMask = (1 << kChunkBits) - 1;
+const int kLastChunkTagBits = 1;
+const int kLastChunkTagMask = 1;
+const int kLastChunkTag = 1;
+
+
+const int kDataJumpTag = kPCJumpTag - 1;
+
+const int kNonstatementPositionTag = 0;
+const int kStatementPositionTag = 1;
+const int kCommentTag = 2;
+
+
+uint32_t RelocInfoWriter::WriteVariableLengthPCJump(uint32_t pc_delta) {
+  // Return if the pc_delta can fit in kSmallPCDeltaBits bits.
+  // Otherwise write a variable length PC jump for the bits that do
+  // not fit in the kSmallPCDeltaBits bits.
+  if (is_uintn(pc_delta, kSmallPCDeltaBits)) return pc_delta;
+  WriteExtraTag(kPCJumpTag, kVariableLengthPCJumpTopTag);
+  uint32_t pc_jump = pc_delta >> kSmallPCDeltaBits;
+  ASSERT(pc_jump > 0);
+  // Write kChunkBits size chunks of the pc_jump.
+  for (; pc_jump > 0; pc_jump = pc_jump >> kChunkBits) {
+    byte b = pc_jump & kChunkMask;
+    *--pos_ = b << kLastChunkTagBits;
+  }
+  // Tag the last chunk so it can be identified.
+  *pos_ = *pos_ | kLastChunkTag;
+  // Return the remaining kSmallPCDeltaBits of the pc_delta.
+  return pc_delta & kSmallPCDeltaMask;
+}
+
+
+void RelocInfoWriter::WriteTaggedPC(uint32_t pc_delta, int tag) {
+  // Write a byte of tagged pc-delta, possibly preceded by var. length pc-jump.
+  pc_delta = WriteVariableLengthPCJump(pc_delta);
+  *--pos_ = pc_delta << kTagBits | tag;
+}
+
+
+void RelocInfoWriter::WriteTaggedData(int32_t data_delta, int tag) {
+  *--pos_ = data_delta << kPositionTypeTagBits | tag;
+}
+
+
+void RelocInfoWriter::WriteExtraTag(int extra_tag, int top_tag) {
+  *--pos_ = top_tag << (kTagBits + kExtraTagBits) |
+            extra_tag << kTagBits |
+            kDefaultTag;
+}
+
+
+void RelocInfoWriter::WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag) {
+  // Write two-byte tagged pc-delta, possibly preceded by var. length pc-jump.
+  pc_delta = WriteVariableLengthPCJump(pc_delta);
+  WriteExtraTag(extra_tag, 0);
+  *--pos_ = pc_delta;
+}
+
+
+void RelocInfoWriter::WriteExtraTaggedData(int32_t data_delta, int top_tag) {
+  WriteExtraTag(kDataJumpTag, top_tag);
+  for (int i = 0; i < kIntSize; i++) {
+    *--pos_ = data_delta;
+    data_delta = ArithmeticShiftRight(data_delta, kBitsPerByte);
+  }
+}
+
+
+void RelocInfoWriter::Write(const RelocInfo* rinfo) {
+#ifdef DEBUG
+  byte* begin_pos = pos_;
+#endif
+  Counters::reloc_info_count.Increment();
+  ASSERT(rinfo->pc() - last_pc_ >= 0);
+  ASSERT(RelocInfo::NUMBER_OF_MODES < kMaxRelocModes);
+  // Use unsigned delta-encoding for pc.
+  uint32_t pc_delta = rinfo->pc() - last_pc_;
+  RelocInfo::Mode rmode = rinfo->rmode();
+
+  // The two most common modes are given small tags, and usually fit in a byte.
+  if (rmode == RelocInfo::EMBEDDED_OBJECT) {
+    WriteTaggedPC(pc_delta, kEmbeddedObjectTag);
+  } else if (rmode == RelocInfo::CODE_TARGET) {
+    WriteTaggedPC(pc_delta, kCodeTargetTag);
+  } else if (RelocInfo::IsPosition(rmode)) {
+    // Use signed delta-encoding for data.
+    int32_t data_delta = rinfo->data() - last_data_;
+    int pos_type_tag = rmode == RelocInfo::POSITION ? kNonstatementPositionTag
+                                                    : kStatementPositionTag;
+    // Check if data is small enough to fit in a tagged byte.
+    if (is_intn(data_delta, kSmallDataBits)) {
+      WriteTaggedPC(pc_delta, kPositionTag);
+      WriteTaggedData(data_delta, pos_type_tag);
+      last_data_ = rinfo->data();
+    } else {
+      // Otherwise, use costly encoding.
+      WriteExtraTaggedPC(pc_delta, kPCJumpTag);
+      WriteExtraTaggedData(data_delta, pos_type_tag);
+      last_data_ = rinfo->data();
+    }
+  } else if (RelocInfo::IsComment(rmode)) {
+    // Comments are normally not generated, so we use the costly encoding.
+    WriteExtraTaggedPC(pc_delta, kPCJumpTag);
+    WriteExtraTaggedData(rinfo->data() - last_data_, kCommentTag);
+    last_data_ = rinfo->data();
+  } else {
+    // For all other modes we simply use the mode as the extra tag.
+    // None of these modes need a data component.
+    ASSERT(rmode < kPCJumpTag && rmode < kDataJumpTag);
+    WriteExtraTaggedPC(pc_delta, rmode);
+  }
+  last_pc_ = rinfo->pc();
+#ifdef DEBUG
+  ASSERT(begin_pos - pos_ <= kMaxSize);
+#endif
+}
+
+
+inline int RelocIterator::AdvanceGetTag() {
+  return *--pos_ & kTagMask;
+}
+
+
+inline int RelocIterator::GetExtraTag() {
+  return (*pos_ >> kTagBits) & ((1 << kExtraTagBits) - 1);
+}
+
+
+inline int RelocIterator::GetTopTag() {
+  return *pos_ >> (kTagBits + kExtraTagBits);
+}
+
+
+inline void RelocIterator::ReadTaggedPC() {
+  rinfo_.pc_ += *pos_ >> kTagBits;
+}
+
+
+inline void RelocIterator::AdvanceReadPC() {
+  rinfo_.pc_ += *--pos_;
+}
+
+
+void RelocIterator::AdvanceReadData() {
+  int32_t x = 0;
+  for (int i = 0; i < kIntSize; i++) {
+    x |= *--pos_ << i * kBitsPerByte;
+  }
+  rinfo_.data_ += x;
+}
+
+
+void RelocIterator::AdvanceReadVariableLengthPCJump() {
+  // Read the 32-kSmallPCDeltaBits most significant bits of the
+  // pc jump in kChunkBits bit chunks and shift them into place.
+  // Stop when the last chunk is encountered.
+  uint32_t pc_jump = 0;
+  for (int i = 0; i < kIntSize; i++) {
+    byte pc_jump_part = *--pos_;
+    pc_jump |= (pc_jump_part >> kLastChunkTagBits) << i * kChunkBits;
+    if ((pc_jump_part & kLastChunkTagMask) == 1) break;
+  }
+  // The least significant kSmallPCDeltaBits bits will be added
+  // later.
+  rinfo_.pc_ += pc_jump << kSmallPCDeltaBits;
+}
+
+
+inline int RelocIterator::GetPositionTypeTag() {
+  return *pos_ & ((1 << kPositionTypeTagBits) - 1);
+}
+
+
+inline void RelocIterator::ReadTaggedData() {
+  int8_t signed_b = *pos_;
+  rinfo_.data_ += ArithmeticShiftRight(signed_b, kPositionTypeTagBits);
+}
+
+
+inline RelocInfo::Mode RelocIterator::DebugInfoModeFromTag(int tag) {
+  if (tag == kStatementPositionTag) {
+    return RelocInfo::STATEMENT_POSITION;
+  } else if (tag == kNonstatementPositionTag) {
+    return RelocInfo::POSITION;
+  } else {
+    ASSERT(tag == kCommentTag);
+    return RelocInfo::COMMENT;
+  }
+}
+
+
+void RelocIterator::next() {
+  ASSERT(!done());
+  // Basically, do the opposite of RelocInfoWriter::Write.
+  // Reading of data is as far as possible avoided for unwanted modes,
+  // but we must always update the pc.
+  //
+  // We exit this loop by returning when we find a mode we want.
+  while (pos_ > end_) {
+    int tag = AdvanceGetTag();
+    if (tag == kEmbeddedObjectTag) {
+      ReadTaggedPC();
+      if (SetMode(RelocInfo::EMBEDDED_OBJECT)) return;
+    } else if (tag == kCodeTargetTag) {
+      ReadTaggedPC();
+      if (*(reinterpret_cast<int*>(rinfo_.pc())) == 0x61) {
+        tag = 0;
+      }
+      if (SetMode(RelocInfo::CODE_TARGET)) return;
+    } else if (tag == kPositionTag) {
+      ReadTaggedPC();
+      Advance();
+      // Check if we want source positions.
+      if (mode_mask_ & RelocInfo::kPositionMask) {
+        // Check if we want this type of source position.
+        if (SetMode(DebugInfoModeFromTag(GetPositionTypeTag()))) {
+          // Finally read the data before returning.
+          ReadTaggedData();
+          return;
+        }
+      }
+    } else {
+      ASSERT(tag == kDefaultTag);
+      int extra_tag = GetExtraTag();
+      if (extra_tag == kPCJumpTag) {
+        int top_tag = GetTopTag();
+        if (top_tag == kVariableLengthPCJumpTopTag) {
+          AdvanceReadVariableLengthPCJump();
+        } else {
+          AdvanceReadPC();
+        }
+      } else if (extra_tag == kDataJumpTag) {
+        // Check if we want debug modes (the only ones with data).
+        if (mode_mask_ & RelocInfo::kDebugMask) {
+          int top_tag = GetTopTag();
+          AdvanceReadData();
+          if (SetMode(DebugInfoModeFromTag(top_tag))) return;
+        } else {
+          // Otherwise, just skip over the data.
+          Advance(kIntSize);
+        }
+      } else {
+        AdvanceReadPC();
+        if (SetMode(static_cast<RelocInfo::Mode>(extra_tag))) return;
+      }
+    }
+  }
+  done_ = true;
+}
+
+
+RelocIterator::RelocIterator(Code* code, int mode_mask) {
+  rinfo_.pc_ = code->instruction_start();
+  rinfo_.data_ = 0;
+  // relocation info is read backwards
+  pos_ = code->relocation_start() + code->relocation_size();
+  end_ = code->relocation_start();
+  done_ = false;
+  mode_mask_ = mode_mask;
+  if (mode_mask_ == 0) pos_ = end_;
+  next();
+}
+
+
+RelocIterator::RelocIterator(const CodeDesc& desc, int mode_mask) {
+  rinfo_.pc_ = desc.buffer;
+  rinfo_.data_ = 0;
+  // relocation info is read backwards
+  pos_ = desc.buffer + desc.buffer_size;
+  end_ = pos_ - desc.reloc_size;
+  done_ = false;
+  mode_mask_ = mode_mask;
+  if (mode_mask_ == 0) pos_ = end_;
+  next();
+}
+
+
+// -----------------------------------------------------------------------------
+// Implementation of RelocInfo
+
+
+#ifdef ENABLE_DISASSEMBLER
+const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
+  switch (rmode) {
+    case RelocInfo::NONE:
+      return "no reloc";
+    case RelocInfo::EMBEDDED_OBJECT:
+      return "embedded object";
+    case RelocInfo::EMBEDDED_STRING:
+      return "embedded string";
+    case RelocInfo::CONSTRUCT_CALL:
+      return "code target (js construct call)";
+    case RelocInfo::CODE_TARGET_CONTEXT:
+      return "code target (context)";
+    case RelocInfo::CODE_TARGET:
+      return "code target";
+    case RelocInfo::RUNTIME_ENTRY:
+      return "runtime entry";
+    case RelocInfo::JS_RETURN:
+      return "js return";
+    case RelocInfo::COMMENT:
+      return "comment";
+    case RelocInfo::POSITION:
+      return "position";
+    case RelocInfo::STATEMENT_POSITION:
+      return "statement position";
+    case RelocInfo::EXTERNAL_REFERENCE:
+      return "external reference";
+    case RelocInfo::INTERNAL_REFERENCE:
+      return "internal reference";
+    case RelocInfo::NUMBER_OF_MODES:
+      UNREACHABLE();
+      return "number_of_modes";
+  }
+  return "unknown relocation type";
+}
+
+
+void RelocInfo::Print() {
+  PrintF("%p  %s", pc_, RelocModeName(rmode_));
+  if (IsComment(rmode_)) {
+    PrintF("  (%s)", data_);
+  } else if (rmode_ == EMBEDDED_OBJECT) {
+    PrintF("  (");
+    target_object()->ShortPrint();
+    PrintF(")");
+  } else if (rmode_ == EXTERNAL_REFERENCE) {
+    ExternalReferenceEncoder ref_encoder;
+    PrintF(" (%s)  (%p)",
+           ref_encoder.NameOfAddress(*target_reference_address()),
+           *target_reference_address());
+  } else if (IsCodeTarget(rmode_)) {
+    Code* code = Code::GetCodeFromTargetAddress(target_address());
+    PrintF(" (%s)  (%p)", Code::Kind2String(code->kind()), target_address());
+  } else if (IsPosition(rmode_)) {
+    PrintF("  (%d)", data());
+  }
+
+  PrintF("\n");
+}
+#endif  // ENABLE_DISASSEMBLER
+
+
+#ifdef DEBUG
+void RelocInfo::Verify() {
+  switch (rmode_) {
+    case EMBEDDED_OBJECT:
+      Object::VerifyPointer(target_object());
+      break;
+    case CONSTRUCT_CALL:
+    case CODE_TARGET_CONTEXT:
+    case CODE_TARGET: {
+      // convert inline target address to code object
+      Address addr = target_address();
+      ASSERT(addr != NULL);
+      // Check that we can find the right code object.
+      HeapObject* code = HeapObject::FromAddress(addr - Code::kHeaderSize);
+      Object* found = Heap::FindCodeObject(addr);
+      ASSERT(found->IsCode());
+      ASSERT(code->address() == HeapObject::cast(found)->address());
+      break;
+    }
+    case RelocInfo::EMBEDDED_STRING:
+    case RUNTIME_ENTRY:
+    case JS_RETURN:
+    case COMMENT:
+    case POSITION:
+    case STATEMENT_POSITION:
+    case EXTERNAL_REFERENCE:
+    case INTERNAL_REFERENCE:
+    case NONE:
+      break;
+    case NUMBER_OF_MODES:
+      UNREACHABLE();
+      break;
+  }
+}
+#endif  // DEBUG
+
+
+// -----------------------------------------------------------------------------
+// Implementation of ExternalReference
+
+ExternalReference::ExternalReference(Builtins::CFunctionId id)
+  : address_(Builtins::c_function_address(id)) {}
+
+
+ExternalReference::ExternalReference(Builtins::Name name)
+  : address_(Builtins::builtin_address(name)) {}
+
+
+ExternalReference::ExternalReference(Runtime::FunctionId id)
+  : address_(Runtime::FunctionForId(id)->entry) {}
+
+
+ExternalReference::ExternalReference(Runtime::Function* f)
+  : address_(f->entry) {}
+
+
+ExternalReference::ExternalReference(const IC_Utility& ic_utility)
+  : address_(ic_utility.address()) {}
+
+
+ExternalReference::ExternalReference(const Debug_Address& debug_address)
+  : address_(debug_address.address()) {}
+
+
+ExternalReference::ExternalReference(StatsCounter* counter)
+  : address_(reinterpret_cast<Address>(counter->GetInternalPointer())) {}
+
+
+ExternalReference::ExternalReference(Top::AddressId id)
+  : address_(Top::get_address_from_id(id)) {}
+
+
+ExternalReference::ExternalReference(const SCTableReference& table_ref)
+  : address_(table_ref.address()) {}
+
+
+ExternalReference ExternalReference::builtin_passed_function() {
+  return ExternalReference(&Builtins::builtin_passed_function);
+}
+
+ExternalReference ExternalReference::the_hole_value_location() {
+  return ExternalReference(Factory::the_hole_value().location());
+}
+
+
+ExternalReference ExternalReference::address_of_stack_guard_limit() {
+  return ExternalReference(StackGuard::address_of_jslimit());
+}
+
+
+ExternalReference ExternalReference::address_of_regexp_stack_limit() {
+  return ExternalReference(RegExpStack::limit_address());
+}
+
+
+ExternalReference ExternalReference::debug_break() {
+  return ExternalReference(FUNCTION_ADDR(Debug::Break));
+}
+
+
+ExternalReference ExternalReference::new_space_start() {
+  return ExternalReference(Heap::NewSpaceStart());
+}
+
+ExternalReference ExternalReference::new_space_allocation_top_address() {
+  return ExternalReference(Heap::NewSpaceAllocationTopAddress());
+}
+
+ExternalReference ExternalReference::heap_always_allocate_scope_depth() {
+  return ExternalReference(Heap::always_allocate_scope_depth_address());
+}
+
+ExternalReference ExternalReference::new_space_allocation_limit_address() {
+  return ExternalReference(Heap::NewSpaceAllocationLimitAddress());
+}
+
+ExternalReference ExternalReference::debug_step_in_fp_address() {
+  return ExternalReference(Debug::step_in_fp_addr());
+}
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/assembler.h b/deps/v8/src/assembler.h
new file mode 100644
index 0000000..49c9b90
--- /dev/null
+++ b/deps/v8/src/assembler.h
@@ -0,0 +1,456 @@
+// Copyright (c) 1994-2006 Sun Microsystems Inc.
+// 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.
+//
+// - Redistribution 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 Sun Microsystems or the names of 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.
+
+// The original source code covered by the above license above has been
+// modified significantly by Google Inc.
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+
+#ifndef V8_ASSEMBLER_H_
+#define V8_ASSEMBLER_H_
+
+#include "runtime.h"
+#include "top.h"
+#include "zone-inl.h"
+
+namespace v8 { namespace internal {
+
+
+// -----------------------------------------------------------------------------
+// Labels represent pc locations; they are typically jump or call targets.
+// After declaration, a label can be freely used to denote known or (yet)
+// unknown pc location. Assembler::bind() is used to bind a label to the
+// current pc. A label can be bound only once.
+
+class Label BASE_EMBEDDED {
+ public:
+  INLINE(Label())                 { Unuse(); }
+  INLINE(~Label())                { ASSERT(!is_linked()); }
+
+  INLINE(void Unuse())            { pos_ = 0; }
+
+  INLINE(bool is_bound()  const)  { return pos_ <  0; }
+  INLINE(bool is_unused() const)  { return pos_ == 0; }
+  INLINE(bool is_linked() const)  { return pos_ >  0; }
+
+  // Returns the position of bound or linked labels. Cannot be used
+  // for unused labels.
+  int pos() const;
+
+ private:
+  // pos_ encodes both the binding state (via its sign)
+  // and the binding position (via its value) of a label.
+  //
+  // pos_ <  0  bound label, pos() returns the jump target position
+  // pos_ == 0  unused label
+  // pos_ >  0  linked label, pos() returns the last reference position
+  int pos_;
+
+  void bind_to(int pos)  {
+    pos_ = -pos - 1;
+    ASSERT(is_bound());
+  }
+  void link_to(int pos)  {
+    pos_ =  pos + 1;
+    ASSERT(is_linked());
+  }
+
+  friend class Assembler;
+  friend class RegexpAssembler;
+  friend class Displacement;
+  friend class ShadowTarget;
+  friend class RegExpMacroAssemblerIrregexp;
+};
+
+
+// -----------------------------------------------------------------------------
+// Relocation information
+
+
+// Relocation information consists of the address (pc) of the datum
+// to which the relocation information applies, the relocation mode
+// (rmode), and an optional data field. The relocation mode may be
+// "descriptive" and not indicate a need for relocation, but simply
+// describe a property of the datum. Such rmodes are useful for GC
+// and nice disassembly output.
+
+class RelocInfo BASE_EMBEDDED {
+ public:
+  // The constant kNoPosition is used with the collecting of source positions
+  // in the relocation information. Two types of source positions are collected
+  // "position" (RelocMode position) and "statement position" (RelocMode
+  // statement_position). The "position" is collected at places in the source
+  // code which are of interest when making stack traces to pin-point the source
+  // location of a stack frame as close as possible. The "statement position" is
+  // collected at the beginning at each statement, and is used to indicate
+  // possible break locations. kNoPosition is used to indicate an
+  // invalid/uninitialized position value.
+  static const int kNoPosition = -1;
+
+  enum Mode {
+    // Please note the order is important (see IsCodeTarget, IsGCRelocMode).
+    CONSTRUCT_CALL,  // code target that is a call to a JavaScript constructor.
+    CODE_TARGET_CONTEXT,  // code target used for contextual loads.
+    CODE_TARGET,         // code target which is not any of the above.
+    EMBEDDED_OBJECT,
+    EMBEDDED_STRING,
+
+    // Everything after runtime_entry (inclusive) is not GC'ed.
+    RUNTIME_ENTRY,
+    JS_RETURN,  // Marks start of the ExitJSFrame code.
+    COMMENT,
+    POSITION,  // See comment for kNoPosition above.
+    STATEMENT_POSITION,  // See comment for kNoPosition above.
+    EXTERNAL_REFERENCE,  // The address of an external C++ function.
+    INTERNAL_REFERENCE,  // An address inside the same function.
+
+    // add more as needed
+    // Pseudo-types
+    NUMBER_OF_MODES,  // must be no greater than 14 - see RelocInfoWriter
+    NONE,  // never recorded
+    LAST_CODE_ENUM = CODE_TARGET,
+    LAST_GCED_ENUM = EMBEDDED_STRING
+  };
+
+
+  RelocInfo() {}
+  RelocInfo(byte* pc, Mode rmode, intptr_t data)
+      : pc_(pc), rmode_(rmode), data_(data) {
+  }
+
+  static inline bool IsConstructCall(Mode mode) {
+    return mode == CONSTRUCT_CALL;
+  }
+  static inline bool IsCodeTarget(Mode mode) {
+    return mode <= LAST_CODE_ENUM;
+  }
+  // Is the relocation mode affected by GC?
+  static inline bool IsGCRelocMode(Mode mode) {
+    return mode <= LAST_GCED_ENUM;
+  }
+  static inline bool IsJSReturn(Mode mode) {
+    return mode == JS_RETURN;
+  }
+  static inline bool IsComment(Mode mode) {
+    return mode == COMMENT;
+  }
+  static inline bool IsPosition(Mode mode) {
+    return mode == POSITION || mode == STATEMENT_POSITION;
+  }
+  static inline bool IsStatementPosition(Mode mode) {
+    return mode == STATEMENT_POSITION;
+  }
+  static inline bool IsExternalReference(Mode mode) {
+    return mode == EXTERNAL_REFERENCE;
+  }
+  static inline bool IsInternalReference(Mode mode) {
+    return mode == INTERNAL_REFERENCE;
+  }
+  static inline int ModeMask(Mode mode) { return 1 << mode; }
+
+  // Accessors
+  byte* pc() const  { return pc_; }
+  void set_pc(byte* pc) { pc_ = pc; }
+  Mode rmode() const {  return rmode_; }
+  intptr_t data() const  { return data_; }
+
+  // Apply a relocation by delta bytes
+  INLINE(void apply(int delta));
+
+  // Read/modify the code target in the branch/call instruction
+  // this relocation applies to;
+  // can only be called if IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY
+  INLINE(Address target_address());
+  INLINE(void set_target_address(Address target));
+  INLINE(Object* target_object());
+  INLINE(Object** target_object_address());
+  INLINE(void set_target_object(Object* target));
+
+  // Read the address of the word containing the target_address. Can only
+  // be called if IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY.
+  INLINE(Address target_address_address());
+
+  // Read/modify the reference in the instruction this relocation
+  // applies to; can only be called if rmode_ is external_reference
+  INLINE(Address* target_reference_address());
+
+  // Read/modify the address of a call instruction. This is used to relocate
+  // the break points where straight-line code is patched with a call
+  // instruction.
+  INLINE(Address call_address());
+  INLINE(void set_call_address(Address target));
+  INLINE(Object* call_object());
+  INLINE(Object** call_object_address());
+  INLINE(void set_call_object(Object* target));
+
+  // Patch the code with some other code.
+  void PatchCode(byte* instructions, int instruction_count);
+
+  // Patch the code with a call.
+  void PatchCodeWithCall(Address target, int guard_bytes);
+  INLINE(bool IsCallInstruction());
+
+#ifdef ENABLE_DISASSEMBLER
+  // Printing
+  static const char* RelocModeName(Mode rmode);
+  void Print();
+#endif  // ENABLE_DISASSEMBLER
+#ifdef DEBUG
+  // Debugging
+  void Verify();
+#endif
+
+  static const int kCodeTargetMask = (1 << (LAST_CODE_ENUM + 1)) - 1;
+  static const int kPositionMask = 1 << POSITION | 1 << STATEMENT_POSITION;
+  static const int kDebugMask = kPositionMask | 1 << COMMENT;
+  static const int kApplyMask;  // Modes affected by apply. Depends on arch.
+
+ private:
+  // On ARM, note that pc_ is the address of the constant pool entry
+  // to be relocated and not the address of the instruction
+  // referencing the constant pool entry (except when rmode_ ==
+  // comment).
+  byte* pc_;
+  Mode rmode_;
+  intptr_t data_;
+  friend class RelocIterator;
+};
+
+
+// RelocInfoWriter serializes a stream of relocation info. It writes towards
+// lower addresses.
+class RelocInfoWriter BASE_EMBEDDED {
+ public:
+  RelocInfoWriter() : pos_(NULL), last_pc_(NULL), last_data_(0) {}
+  RelocInfoWriter(byte* pos, byte* pc) : pos_(pos), last_pc_(pc),
+                                         last_data_(0) {}
+
+  byte* pos() const { return pos_; }
+  byte* last_pc() const { return last_pc_; }
+
+  void Write(const RelocInfo* rinfo);
+
+  // Update the state of the stream after reloc info buffer
+  // and/or code is moved while the stream is active.
+  void Reposition(byte* pos, byte* pc) {
+    pos_ = pos;
+    last_pc_ = pc;
+  }
+
+  // Max size (bytes) of a written RelocInfo.
+  static const int kMaxSize = 12;
+
+ private:
+  inline uint32_t WriteVariableLengthPCJump(uint32_t pc_delta);
+  inline void WriteTaggedPC(uint32_t pc_delta, int tag);
+  inline void WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag);
+  inline void WriteExtraTaggedData(int32_t data_delta, int top_tag);
+  inline void WriteTaggedData(int32_t data_delta, int tag);
+  inline void WriteExtraTag(int extra_tag, int top_tag);
+
+  byte* pos_;
+  byte* last_pc_;
+  intptr_t last_data_;
+  DISALLOW_COPY_AND_ASSIGN(RelocInfoWriter);
+};
+
+
+// A RelocIterator iterates over relocation information.
+// Typical use:
+//
+//   for (RelocIterator it(code); !it.done(); it.next()) {
+//     // do something with it.rinfo() here
+//   }
+//
+// A mask can be specified to skip unwanted modes.
+class RelocIterator: public Malloced {
+ public:
+  // Create a new iterator positioned at
+  // the beginning of the reloc info.
+  // Relocation information with mode k is included in the
+  // iteration iff bit k of mode_mask is set.
+  explicit RelocIterator(Code* code, int mode_mask = -1);
+  explicit RelocIterator(const CodeDesc& desc, int mode_mask = -1);
+
+  // Iteration
+  bool done() const  { return done_; }
+  void next();
+
+  // Return pointer valid until next next().
+  RelocInfo* rinfo() {
+    ASSERT(!done());
+    return &rinfo_;
+  }
+
+ private:
+  // Advance* moves the position before/after reading.
+  // *Read* reads from current byte(s) into rinfo_.
+  // *Get* just reads and returns info on current byte.
+  void Advance(int bytes = 1) { pos_ -= bytes; }
+  int AdvanceGetTag();
+  int GetExtraTag();
+  int GetTopTag();
+  void ReadTaggedPC();
+  void AdvanceReadPC();
+  void AdvanceReadData();
+  void AdvanceReadVariableLengthPCJump();
+  int GetPositionTypeTag();
+  void ReadTaggedData();
+
+  static RelocInfo::Mode DebugInfoModeFromTag(int tag);
+
+  // If the given mode is wanted, set it in rinfo_ and return true.
+  // Else return false. Used for efficiently skipping unwanted modes.
+  bool SetMode(RelocInfo::Mode mode) {
+    return (mode_mask_ & 1 << mode) ? (rinfo_.rmode_ = mode, true) : false;
+  }
+
+  byte* pos_;
+  byte* end_;
+  RelocInfo rinfo_;
+  bool done_;
+  int mode_mask_;
+  DISALLOW_COPY_AND_ASSIGN(RelocIterator);
+};
+
+
+// A stack-allocated code region logs a name for the code generated
+// while the region is in effect.  This information is used by the
+// profiler to categorize ticks within generated code.
+class CodeRegion BASE_EMBEDDED {
+ public:
+  inline CodeRegion(Assembler* assm, const char *name) : assm_(assm) {
+    LOG(BeginCodeRegionEvent(this, assm, name));
+  }
+  inline ~CodeRegion() {
+    LOG(EndCodeRegionEvent(this, assm_));
+  }
+ private:
+  Assembler* assm_;
+};
+
+
+//------------------------------------------------------------------------------
+// External function
+
+//----------------------------------------------------------------------------
+class IC_Utility;
+class Debug_Address;
+class SCTableReference;
+
+// An ExternalReference represents a C++ address called from the generated
+// code. All references to C++ functions and must be encapsulated in an
+// ExternalReference instance. This is done in order to track the origin of
+// all external references in the code.
+class ExternalReference BASE_EMBEDDED {
+ public:
+  explicit ExternalReference(Builtins::CFunctionId id);
+
+  explicit ExternalReference(Builtins::Name name);
+
+  explicit ExternalReference(Runtime::FunctionId id);
+
+  explicit ExternalReference(Runtime::Function* f);
+
+  explicit ExternalReference(const IC_Utility& ic_utility);
+
+  explicit ExternalReference(const Debug_Address& debug_address);
+
+  explicit ExternalReference(StatsCounter* counter);
+
+  explicit ExternalReference(Top::AddressId id);
+
+  explicit ExternalReference(const SCTableReference& table_ref);
+
+  // One-of-a-kind references. These references are not part of a general
+  // pattern. This means that they have to be added to the
+  // ExternalReferenceTable in serialize.cc manually.
+
+  static ExternalReference builtin_passed_function();
+
+  // Static variable Factory::the_hole_value.location()
+  static ExternalReference the_hole_value_location();
+
+  // Static variable StackGuard::address_of_jslimit()
+  static ExternalReference address_of_stack_guard_limit();
+
+  // Static variable RegExpStack::limit_address()
+  static ExternalReference address_of_regexp_stack_limit();
+
+  // Function Debug::Break()
+  static ExternalReference debug_break();
+
+  // Static variable Heap::NewSpaceStart()
+  static ExternalReference new_space_start();
+  static ExternalReference heap_always_allocate_scope_depth();
+
+  // Used for fast allocation in generated code.
+  static ExternalReference new_space_allocation_top_address();
+  static ExternalReference new_space_allocation_limit_address();
+
+  // Used to check if single stepping is enabled in generated code.
+  static ExternalReference debug_step_in_fp_address();
+
+  Address address() const {return address_;}
+
+ private:
+  explicit ExternalReference(void* address)
+    : address_(reinterpret_cast<Address>(address)) {}
+
+  Address address_;
+};
+
+
+// -----------------------------------------------------------------------------
+// Utility functions
+
+// Move these into inline file?
+
+static inline bool is_intn(int x, int n)  {
+  return -(1 << (n-1)) <= x && x < (1 << (n-1));
+}
+
+static inline bool is_int24(int x)  { return is_intn(x, 24); }
+static inline bool is_int8(int x)  { return is_intn(x, 8); }
+
+static inline bool is_uintn(int x, int n) {
+  return (x & -(1 << n)) == 0;
+}
+
+static inline bool is_uint3(int x)  { return is_uintn(x, 3); }
+static inline bool is_uint4(int x)  { return is_uintn(x, 4); }
+static inline bool is_uint5(int x)  { return is_uintn(x, 5); }
+static inline bool is_uint8(int x)  { return is_uintn(x, 8); }
+static inline bool is_uint12(int x)  { return is_uintn(x, 12); }
+static inline bool is_uint16(int x)  { return is_uintn(x, 16); }
+static inline bool is_uint24(int x)  { return is_uintn(x, 24); }
+
+} }  // namespace v8::internal
+
+#endif  // V8_ASSEMBLER_H_
diff --git a/deps/v8/src/ast.cc b/deps/v8/src/ast.cc
new file mode 100644
index 0000000..1a6010a
--- /dev/null
+++ b/deps/v8/src/ast.cc
@@ -0,0 +1,490 @@
+// 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.
+
+#include "v8.h"
+
+#include "ast.h"
+#include "scopes.h"
+#include "string-stream.h"
+
+namespace v8 { namespace internal {
+
+
+VariableProxySentinel VariableProxySentinel::this_proxy_(true);
+VariableProxySentinel VariableProxySentinel::identifier_proxy_(false);
+ValidLeftHandSideSentinel ValidLeftHandSideSentinel::instance_;
+Property Property::this_property_(VariableProxySentinel::this_proxy(), NULL, 0);
+Call Call::sentinel_(NULL, NULL, 0);
+CallEval CallEval::sentinel_(NULL, NULL, 0);
+
+
+// ----------------------------------------------------------------------------
+// All the Accept member functions for each syntax tree node type.
+
+#define DECL_ACCEPT(type)                \
+  void type::Accept(AstVisitor* v) {        \
+    if (v->CheckStackOverflow()) return; \
+    v->Visit##type(this);                \
+  }
+NODE_LIST(DECL_ACCEPT)
+#undef DECL_ACCEPT
+
+
+// ----------------------------------------------------------------------------
+// Implementation of other node functionality.
+
+VariableProxy::VariableProxy(Handle<String> name,
+                             bool is_this,
+                             bool inside_with)
+  : name_(name),
+    var_(NULL),
+    is_this_(is_this),
+    inside_with_(inside_with) {
+  // names must be canonicalized for fast equality checks
+  ASSERT(name->IsSymbol());
+  // at least one access, otherwise no need for a VariableProxy
+  var_uses_.RecordAccess(1);
+}
+
+
+VariableProxy::VariableProxy(bool is_this)
+  : is_this_(is_this) {
+}
+
+
+void VariableProxy::BindTo(Variable* var) {
+  ASSERT(var_ == NULL);  // must be bound only once
+  ASSERT(var != NULL);  // must bind
+  ASSERT((is_this() && var->is_this()) || name_.is_identical_to(var->name()));
+  // Ideally CONST-ness should match. However, this is very hard to achieve
+  // because we don't know the exact semantics of conflicting (const and
+  // non-const) multiple variable declarations, const vars introduced via
+  // eval() etc.  Const-ness and variable declarations are a complete mess
+  // in JS. Sigh...
+  var_ = var;
+  var->var_uses()->RecordUses(&var_uses_);
+  var->obj_uses()->RecordUses(&obj_uses_);
+}
+
+
+#ifdef DEBUG
+
+const char* LoopStatement::OperatorString() const {
+  switch (type()) {
+    case DO_LOOP: return "DO";
+    case FOR_LOOP: return "FOR";
+    case WHILE_LOOP: return "WHILE";
+  }
+  return NULL;
+}
+
+#endif  // DEBUG
+
+
+Token::Value Assignment::binary_op() const {
+  switch (op_) {
+    case Token::ASSIGN_BIT_OR: return Token::BIT_OR;
+    case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR;
+    case Token::ASSIGN_BIT_AND: return Token::BIT_AND;
+    case Token::ASSIGN_SHL: return Token::SHL;
+    case Token::ASSIGN_SAR: return Token::SAR;
+    case Token::ASSIGN_SHR: return Token::SHR;
+    case Token::ASSIGN_ADD: return Token::ADD;
+    case Token::ASSIGN_SUB: return Token::SUB;
+    case Token::ASSIGN_MUL: return Token::MUL;
+    case Token::ASSIGN_DIV: return Token::DIV;
+    case Token::ASSIGN_MOD: return Token::MOD;
+    default: UNREACHABLE();
+  }
+  return Token::ILLEGAL;
+}
+
+
+bool FunctionLiteral::AllowsLazyCompilation() {
+  return scope()->AllowsLazyCompilation();
+}
+
+
+ObjectLiteral::Property::Property(Literal* key, Expression* value) {
+  key_ = key;
+  value_ = value;
+  Object* k = *key->handle();
+  if (k->IsSymbol() && Heap::Proto_symbol()->Equals(String::cast(k))) {
+    kind_ = PROTOTYPE;
+  } else if (value_->AsMaterializedLiteral() != NULL) {
+    kind_ = MATERIALIZED_LITERAL;
+  } else if (value_->AsLiteral() != NULL) {
+    kind_ = CONSTANT;
+  } else {
+    kind_ = COMPUTED;
+  }
+}
+
+
+ObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) {
+  key_ = new Literal(value->name());
+  value_ = value;
+  kind_ = is_getter ? GETTER : SETTER;
+}
+
+
+void TargetCollector::AddTarget(BreakTarget* target) {
+  // Add the label to the collector, but discard duplicates.
+  int length = targets_->length();
+  for (int i = 0; i < length; i++) {
+    if (targets_->at(i) == target) return;
+  }
+  targets_->Add(target);
+}
+
+
+// ----------------------------------------------------------------------------
+// Implementation of AstVisitor
+
+
+void AstVisitor::VisitStatements(ZoneList<Statement*>* statements) {
+  for (int i = 0; i < statements->length(); i++) {
+    Visit(statements->at(i));
+  }
+}
+
+
+void AstVisitor::VisitExpressions(ZoneList<Expression*>* expressions) {
+  for (int i = 0; i < expressions->length(); i++) {
+    // The variable statement visiting code may pass NULL expressions
+    // to this code. Maybe this should be handled by introducing an
+    // undefined expression or literal?  Revisit this code if this
+    // changes
+    Expression* expression = expressions->at(i);
+    if (expression != NULL) Visit(expression);
+  }
+}
+
+
+// ----------------------------------------------------------------------------
+// Regular expressions
+
+#define MAKE_ACCEPT(Name)                                            \
+  void* RegExp##Name::Accept(RegExpVisitor* visitor, void* data) {   \
+    return visitor->Visit##Name(this, data);                         \
+  }
+FOR_EACH_REG_EXP_TREE_TYPE(MAKE_ACCEPT)
+#undef MAKE_ACCEPT
+
+#define MAKE_TYPE_CASE(Name)                                         \
+  RegExp##Name* RegExpTree::As##Name() {                             \
+    return NULL;                                                     \
+  }                                                                  \
+  bool RegExpTree::Is##Name() { return false; }
+FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE)
+#undef MAKE_TYPE_CASE
+
+#define MAKE_TYPE_CASE(Name)                                        \
+  RegExp##Name* RegExp##Name::As##Name() {                          \
+    return this;                                                    \
+  }                                                                 \
+  bool RegExp##Name::Is##Name() { return true; }
+FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE)
+#undef MAKE_TYPE_CASE
+
+RegExpEmpty RegExpEmpty::kInstance;
+
+
+static Interval ListCaptureRegisters(ZoneList<RegExpTree*>* children) {
+  Interval result = Interval::Empty();
+  for (int i = 0; i < children->length(); i++)
+    result = result.Union(children->at(i)->CaptureRegisters());
+  return result;
+}
+
+
+Interval RegExpAlternative::CaptureRegisters() {
+  return ListCaptureRegisters(nodes());
+}
+
+
+Interval RegExpDisjunction::CaptureRegisters() {
+  return ListCaptureRegisters(alternatives());
+}
+
+
+Interval RegExpLookahead::CaptureRegisters() {
+  return body()->CaptureRegisters();
+}
+
+
+Interval RegExpCapture::CaptureRegisters() {
+  Interval self(StartRegister(index()), EndRegister(index()));
+  return self.Union(body()->CaptureRegisters());
+}
+
+
+Interval RegExpQuantifier::CaptureRegisters() {
+  return body()->CaptureRegisters();
+}
+
+
+bool RegExpAssertion::IsAnchored() {
+  return type() == RegExpAssertion::START_OF_INPUT;
+}
+
+
+bool RegExpAlternative::IsAnchored() {
+  ZoneList<RegExpTree*>* nodes = this->nodes();
+  for (int i = 0; i < nodes->length(); i++) {
+    RegExpTree* node = nodes->at(i);
+    if (node->IsAnchored()) { return true; }
+    if (node->max_match() > 0) { return false; }
+  }
+  return false;
+}
+
+
+bool RegExpDisjunction::IsAnchored() {
+  ZoneList<RegExpTree*>* alternatives = this->alternatives();
+  for (int i = 0; i < alternatives->length(); i++) {
+    if (!alternatives->at(i)->IsAnchored())
+      return false;
+  }
+  return true;
+}
+
+
+bool RegExpLookahead::IsAnchored() {
+  return is_positive() && body()->IsAnchored();
+}
+
+
+bool RegExpCapture::IsAnchored() {
+  return body()->IsAnchored();
+}
+
+
+// Convert regular expression trees to a simple sexp representation.
+// This representation should be different from the input grammar
+// in as many cases as possible, to make it more difficult for incorrect
+// parses to look as correct ones which is likely if the input and
+// output formats are alike.
+class RegExpUnparser: public RegExpVisitor {
+ public:
+  RegExpUnparser();
+  void VisitCharacterRange(CharacterRange that);
+  SmartPointer<const char> ToString() { return stream_.ToCString(); }
+#define MAKE_CASE(Name) virtual void* Visit##Name(RegExp##Name*, void* data);
+  FOR_EACH_REG_EXP_TREE_TYPE(MAKE_CASE)
+#undef MAKE_CASE
+ private:
+  StringStream* stream() { return &stream_; }
+  HeapStringAllocator alloc_;
+  StringStream stream_;
+};
+
+
+RegExpUnparser::RegExpUnparser() : stream_(&alloc_) {
+}
+
+
+void* RegExpUnparser::VisitDisjunction(RegExpDisjunction* that, void* data) {
+  stream()->Add("(|");
+  for (int i = 0; i <  that->alternatives()->length(); i++) {
+    stream()->Add(" ");
+    that->alternatives()->at(i)->Accept(this, data);
+  }
+  stream()->Add(")");
+  return NULL;
+}
+
+
+void* RegExpUnparser::VisitAlternative(RegExpAlternative* that, void* data) {
+  stream()->Add("(:");
+  for (int i = 0; i <  that->nodes()->length(); i++) {
+    stream()->Add(" ");
+    that->nodes()->at(i)->Accept(this, data);
+  }
+  stream()->Add(")");
+  return NULL;
+}
+
+
+void RegExpUnparser::VisitCharacterRange(CharacterRange that) {
+  stream()->Add("%k", that.from());
+  if (!that.IsSingleton()) {
+    stream()->Add("-%k", that.to());
+  }
+}
+
+
+
+void* RegExpUnparser::VisitCharacterClass(RegExpCharacterClass* that,
+                                          void* data) {
+  if (that->is_negated())
+    stream()->Add("^");
+  stream()->Add("[");
+  for (int i = 0; i < that->ranges()->length(); i++) {
+    if (i > 0) stream()->Add(" ");
+    VisitCharacterRange(that->ranges()->at(i));
+  }
+  stream()->Add("]");
+  return NULL;
+}
+
+
+void* RegExpUnparser::VisitAssertion(RegExpAssertion* that, void* data) {
+  switch (that->type()) {
+    case RegExpAssertion::START_OF_INPUT:
+      stream()->Add("@^i");
+      break;
+    case RegExpAssertion::END_OF_INPUT:
+      stream()->Add("@$i");
+      break;
+    case RegExpAssertion::START_OF_LINE:
+      stream()->Add("@^l");
+      break;
+    case RegExpAssertion::END_OF_LINE:
+      stream()->Add("@$l");
+       break;
+    case RegExpAssertion::BOUNDARY:
+      stream()->Add("@b");
+      break;
+    case RegExpAssertion::NON_BOUNDARY:
+      stream()->Add("@B");
+      break;
+  }
+  return NULL;
+}
+
+
+void* RegExpUnparser::VisitAtom(RegExpAtom* that, void* data) {
+  stream()->Add("'");
+  Vector<const uc16> chardata = that->data();
+  for (int i = 0; i < chardata.length(); i++) {
+    stream()->Add("%k", chardata[i]);
+  }
+  stream()->Add("'");
+  return NULL;
+}
+
+
+void* RegExpUnparser::VisitText(RegExpText* that, void* data) {
+  if (that->elements()->length() == 1) {
+    that->elements()->at(0).data.u_atom->Accept(this, data);
+  } else {
+    stream()->Add("(!");
+    for (int i = 0; i < that->elements()->length(); i++) {
+      stream()->Add(" ");
+      that->elements()->at(i).data.u_atom->Accept(this, data);
+    }
+    stream()->Add(")");
+  }
+  return NULL;
+}
+
+
+void* RegExpUnparser::VisitQuantifier(RegExpQuantifier* that, void* data) {
+  stream()->Add("(# %i ", that->min());
+  if (that->max() == RegExpTree::kInfinity) {
+    stream()->Add("- ");
+  } else {
+    stream()->Add("%i ", that->max());
+  }
+  stream()->Add(that->is_greedy() ? "g " : "n ");
+  that->body()->Accept(this, data);
+  stream()->Add(")");
+  return NULL;
+}
+
+
+void* RegExpUnparser::VisitCapture(RegExpCapture* that, void* data) {
+  stream()->Add("(^ ");
+  that->body()->Accept(this, data);
+  stream()->Add(")");
+  return NULL;
+}
+
+
+void* RegExpUnparser::VisitLookahead(RegExpLookahead* that, void* data) {
+  stream()->Add("(-> ");
+  stream()->Add(that->is_positive() ? "+ " : "- ");
+  that->body()->Accept(this, data);
+  stream()->Add(")");
+  return NULL;
+}
+
+
+void* RegExpUnparser::VisitBackReference(RegExpBackReference* that,
+                                         void* data) {
+  stream()->Add("(<- %i)", that->index());
+  return NULL;
+}
+
+
+void* RegExpUnparser::VisitEmpty(RegExpEmpty* that, void* data) {
+  stream()->Put('%');
+  return NULL;
+}
+
+
+SmartPointer<const char> RegExpTree::ToString() {
+  RegExpUnparser unparser;
+  Accept(&unparser, NULL);
+  return unparser.ToString();
+}
+
+
+RegExpDisjunction::RegExpDisjunction(ZoneList<RegExpTree*>* alternatives)
+    : alternatives_(alternatives) {
+  ASSERT(alternatives->length() > 1);
+  RegExpTree* first_alternative = alternatives->at(0);
+  min_match_ = first_alternative->min_match();
+  max_match_ = first_alternative->max_match();
+  for (int i = 1; i < alternatives->length(); i++) {
+    RegExpTree* alternative = alternatives->at(i);
+    min_match_ = Min(min_match_, alternative->min_match());
+    max_match_ = Max(max_match_, alternative->max_match());
+  }
+}
+
+
+RegExpAlternative::RegExpAlternative(ZoneList<RegExpTree*>* nodes)
+    : nodes_(nodes) {
+  ASSERT(nodes->length() > 1);
+  min_match_ = 0;
+  max_match_ = 0;
+  for (int i = 0; i < nodes->length(); i++) {
+    RegExpTree* node = nodes->at(i);
+    min_match_ += node->min_match();
+    int node_max_match = node->max_match();
+    if (kInfinity - max_match_ < node_max_match) {
+      max_match_ = kInfinity;
+    } else {
+      max_match_ += node->max_match();
+    }
+  }
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/ast.h b/deps/v8/src/ast.h
new file mode 100644
index 0000000..b496816
--- /dev/null
+++ b/deps/v8/src/ast.h
@@ -0,0 +1,1710 @@
+// 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_AST_H_
+#define V8_AST_H_
+
+#include "execution.h"
+#include "factory.h"
+#include "runtime.h"
+#include "token.h"
+#include "variables.h"
+#include "macro-assembler.h"
+#include "jsregexp.h"
+#include "jump-target.h"
+
+namespace v8 { namespace internal {
+
+// The abstract syntax tree is an intermediate, light-weight
+// representation of the parsed JavaScript code suitable for
+// compilation to native code.
+
+// Nodes are allocated in a separate zone, which allows faster
+// allocation and constant-time deallocation of the entire syntax
+// tree.
+
+
+// ----------------------------------------------------------------------------
+// Nodes of the abstract syntax tree. Only concrete classes are
+// enumerated here.
+
+#define NODE_LIST(V)                            \
+  V(Block)                                      \
+  V(Declaration)                                \
+  V(ExpressionStatement)                        \
+  V(EmptyStatement)                             \
+  V(IfStatement)                                \
+  V(ContinueStatement)                          \
+  V(BreakStatement)                             \
+  V(ReturnStatement)                            \
+  V(WithEnterStatement)                         \
+  V(WithExitStatement)                          \
+  V(SwitchStatement)                            \
+  V(LoopStatement)                              \
+  V(ForInStatement)                             \
+  V(TryCatch)                                   \
+  V(TryFinally)                                 \
+  V(DebuggerStatement)                          \
+  V(FunctionLiteral)                            \
+  V(FunctionBoilerplateLiteral)                 \
+  V(Conditional)                                \
+  V(Slot)                                       \
+  V(VariableProxy)                              \
+  V(Literal)                                    \
+  V(RegExpLiteral)                              \
+  V(ObjectLiteral)                              \
+  V(ArrayLiteral)                               \
+  V(CatchExtensionObject)                       \
+  V(Assignment)                                 \
+  V(Throw)                                      \
+  V(Property)                                   \
+  V(Call)                                       \
+  V(CallEval)                                   \
+  V(CallNew)                                    \
+  V(CallRuntime)                                \
+  V(UnaryOperation)                             \
+  V(CountOperation)                             \
+  V(BinaryOperation)                            \
+  V(CompareOperation)                           \
+  V(ThisFunction)
+
+
+// Forward declarations
+class TargetCollector;
+class MaterializedLiteral;
+
+#define DEF_FORWARD_DECLARATION(type) class type;
+NODE_LIST(DEF_FORWARD_DECLARATION)
+#undef DEF_FORWARD_DECLARATION
+
+
+// Typedef only introduced to avoid unreadable code.
+// Please do appreciate the required space in "> >".
+typedef ZoneList<Handle<String> > ZoneStringList;
+
+
+class Node: public ZoneObject {
+ public:
+  Node(): statement_pos_(RelocInfo::kNoPosition) { }
+  virtual ~Node() { }
+  virtual void Accept(AstVisitor* v) = 0;
+
+  // Type testing & conversion.
+  virtual Statement* AsStatement() { return NULL; }
+  virtual ExpressionStatement* AsExpressionStatement() { return NULL; }
+  virtual EmptyStatement* AsEmptyStatement() { return NULL; }
+  virtual Expression* AsExpression() { return NULL; }
+  virtual Literal* AsLiteral() { return NULL; }
+  virtual Slot* AsSlot() { return NULL; }
+  virtual VariableProxy* AsVariableProxy() { return NULL; }
+  virtual Property* AsProperty() { return NULL; }
+  virtual Call* AsCall() { return NULL; }
+  virtual TargetCollector* AsTargetCollector() { return NULL; }
+  virtual BreakableStatement* AsBreakableStatement() { return NULL; }
+  virtual IterationStatement* AsIterationStatement() { return NULL; }
+  virtual UnaryOperation* AsUnaryOperation() { return NULL; }
+  virtual BinaryOperation* AsBinaryOperation() { return NULL; }
+  virtual Assignment* AsAssignment() { return NULL; }
+  virtual FunctionLiteral* AsFunctionLiteral() { return NULL; }
+  virtual MaterializedLiteral* AsMaterializedLiteral() { return NULL; }
+  virtual ObjectLiteral* AsObjectLiteral() { return NULL; }
+  virtual ArrayLiteral* AsArrayLiteral() { return NULL; }
+
+  void set_statement_pos(int statement_pos) { statement_pos_ = statement_pos; }
+  int statement_pos() const { return statement_pos_; }
+
+ private:
+  int statement_pos_;
+};
+
+
+class Statement: public Node {
+ public:
+  virtual Statement* AsStatement()  { return this; }
+  virtual ReturnStatement* AsReturnStatement() { return NULL; }
+
+  bool IsEmpty() { return AsEmptyStatement() != NULL; }
+};
+
+
+class Expression: public Node {
+ public:
+  virtual Expression* AsExpression()  { return this; }
+
+  virtual bool IsValidLeftHandSide() { return false; }
+
+  // Mark the expression as being compiled as an expression
+  // statement. This is used to transform postfix increments to
+  // (faster) prefix increments.
+  virtual void MarkAsStatement() { /* do nothing */ }
+
+  // Static type information for this expression.
+  SmiAnalysis* type() { return &type_; }
+
+ private:
+  SmiAnalysis type_;
+};
+
+
+/**
+ * A sentinel used during pre parsing that represents some expression
+ * that is a valid left hand side without having to actually build
+ * the expression.
+ */
+class ValidLeftHandSideSentinel: public Expression {
+ public:
+  virtual bool IsValidLeftHandSide() { return true; }
+  virtual void Accept(AstVisitor* v) { UNREACHABLE(); }
+  static ValidLeftHandSideSentinel* instance() { return &instance_; }
+ private:
+  static ValidLeftHandSideSentinel instance_;
+};
+
+
+class BreakableStatement: public Statement {
+ public:
+  enum Type {
+    TARGET_FOR_ANONYMOUS,
+    TARGET_FOR_NAMED_ONLY
+  };
+
+  // The labels associated with this statement. May be NULL;
+  // if it is != NULL, guaranteed to contain at least one entry.
+  ZoneStringList* labels() const { return labels_; }
+
+  // Type testing & conversion.
+  virtual BreakableStatement* AsBreakableStatement() { return this; }
+
+  // Code generation
+  BreakTarget* break_target() { return &break_target_; }
+
+  // Testers.
+  bool is_target_for_anonymous() const { return type_ == TARGET_FOR_ANONYMOUS; }
+
+ protected:
+  BreakableStatement(ZoneStringList* labels, Type type)
+      : labels_(labels), type_(type) {
+    ASSERT(labels == NULL || labels->length() > 0);
+  }
+
+ private:
+  ZoneStringList* labels_;
+  Type type_;
+  BreakTarget break_target_;
+};
+
+
+class Block: public BreakableStatement {
+ public:
+  Block(ZoneStringList* labels, int capacity, bool is_initializer_block)
+      : BreakableStatement(labels, TARGET_FOR_NAMED_ONLY),
+        statements_(capacity),
+        is_initializer_block_(is_initializer_block) { }
+
+  virtual void Accept(AstVisitor* v);
+
+  void AddStatement(Statement* statement) { statements_.Add(statement); }
+
+  ZoneList<Statement*>* statements() { return &statements_; }
+  bool is_initializer_block() const  { return is_initializer_block_; }
+
+ private:
+  ZoneList<Statement*> statements_;
+  bool is_initializer_block_;
+};
+
+
+class Declaration: public Node {
+ public:
+  Declaration(VariableProxy* proxy, Variable::Mode mode, FunctionLiteral* fun)
+      : proxy_(proxy),
+        mode_(mode),
+        fun_(fun) {
+    ASSERT(mode == Variable::VAR || mode == Variable::CONST);
+    // At the moment there are no "const functions"'s in JavaScript...
+    ASSERT(fun == NULL || mode == Variable::VAR);
+  }
+
+  virtual void Accept(AstVisitor* v);
+
+  VariableProxy* proxy() const  { return proxy_; }
+  Variable::Mode mode() const  { return mode_; }
+  FunctionLiteral* fun() const  { return fun_; }  // may be NULL
+
+ private:
+  VariableProxy* proxy_;
+  Variable::Mode mode_;
+  FunctionLiteral* fun_;
+};
+
+
+class IterationStatement: public BreakableStatement {
+ public:
+  // Type testing & conversion.
+  virtual IterationStatement* AsIterationStatement() { return this; }
+
+  Statement* body() const { return body_; }
+
+  // Code generation
+  BreakTarget* continue_target()  { return &continue_target_; }
+
+ protected:
+  explicit IterationStatement(ZoneStringList* labels)
+      : BreakableStatement(labels, TARGET_FOR_ANONYMOUS), body_(NULL) { }
+
+  void Initialize(Statement* body) {
+    body_ = body;
+  }
+
+ private:
+  Statement* body_;
+  BreakTarget continue_target_;
+};
+
+
+class LoopStatement: public IterationStatement {
+ public:
+  enum Type { DO_LOOP, FOR_LOOP, WHILE_LOOP };
+
+  LoopStatement(ZoneStringList* labels, Type type)
+      : IterationStatement(labels),
+        type_(type),
+        init_(NULL),
+        cond_(NULL),
+        next_(NULL),
+        may_have_function_literal_(true) {
+  }
+
+  void Initialize(Statement* init,
+                  Expression* cond,
+                  Statement* next,
+                  Statement* body) {
+    ASSERT(init == NULL || type_ == FOR_LOOP);
+    ASSERT(next == NULL || type_ == FOR_LOOP);
+    IterationStatement::Initialize(body);
+    init_ = init;
+    cond_ = cond;
+    next_ = next;
+  }
+
+  virtual void Accept(AstVisitor* v);
+
+  Type type() const  { return type_; }
+  Statement* init() const  { return init_; }
+  Expression* cond() const  { return cond_; }
+  Statement* next() const  { return next_; }
+  bool may_have_function_literal() const {
+    return may_have_function_literal_;
+  }
+
+#ifdef DEBUG
+  const char* OperatorString() const;
+#endif
+
+ private:
+  Type type_;
+  Statement* init_;
+  Expression* cond_;
+  Statement* next_;
+  // True if there is a function literal subexpression in the condition.
+  bool may_have_function_literal_;
+
+  friend class AstOptimizer;
+};
+
+
+class ForInStatement: public IterationStatement {
+ public:
+  explicit ForInStatement(ZoneStringList* labels)
+      : IterationStatement(labels), each_(NULL), enumerable_(NULL) { }
+
+  void Initialize(Expression* each, Expression* enumerable, Statement* body) {
+    IterationStatement::Initialize(body);
+    each_ = each;
+    enumerable_ = enumerable;
+  }
+
+  virtual void Accept(AstVisitor* v);
+
+  Expression* each() const { return each_; }
+  Expression* enumerable() const { return enumerable_; }
+
+ private:
+  Expression* each_;
+  Expression* enumerable_;
+};
+
+
+class ExpressionStatement: public Statement {
+ public:
+  explicit ExpressionStatement(Expression* expression)
+      : expression_(expression) { }
+
+  virtual void Accept(AstVisitor* v);
+
+  // Type testing & conversion.
+  virtual ExpressionStatement* AsExpressionStatement() { return this; }
+
+  void set_expression(Expression* e) { expression_ = e; }
+  Expression* expression() { return expression_; }
+
+ private:
+  Expression* expression_;
+};
+
+
+class ContinueStatement: public Statement {
+ public:
+  explicit ContinueStatement(IterationStatement* target)
+      : target_(target) { }
+
+  virtual void Accept(AstVisitor* v);
+
+  IterationStatement* target() const  { return target_; }
+
+ private:
+  IterationStatement* target_;
+};
+
+
+class BreakStatement: public Statement {
+ public:
+  explicit BreakStatement(BreakableStatement* target)
+      : target_(target) { }
+
+  virtual void Accept(AstVisitor* v);
+
+  BreakableStatement* target() const  { return target_; }
+
+ private:
+  BreakableStatement* target_;
+};
+
+
+class ReturnStatement: public Statement {
+ public:
+  explicit ReturnStatement(Expression* expression)
+      : expression_(expression) { }
+
+  virtual void Accept(AstVisitor* v);
+
+  // Type testing & conversion.
+  virtual ReturnStatement* AsReturnStatement() { return this; }
+
+  Expression* expression() { return expression_; }
+
+ private:
+  Expression* expression_;
+};
+
+
+class WithEnterStatement: public Statement {
+ public:
+  explicit WithEnterStatement(Expression* expression, bool is_catch_block)
+      : expression_(expression), is_catch_block_(is_catch_block) { }
+
+  virtual void Accept(AstVisitor* v);
+
+  Expression* expression() const  { return expression_; }
+
+  bool is_catch_block() const { return is_catch_block_; }
+
+ private:
+  Expression* expression_;
+  bool is_catch_block_;
+};
+
+
+class WithExitStatement: public Statement {
+ public:
+  WithExitStatement() { }
+
+  virtual void Accept(AstVisitor* v);
+};
+
+
+class CaseClause: public ZoneObject {
+ public:
+  CaseClause(Expression* label, ZoneList<Statement*>* statements)
+      : label_(label), statements_(statements) { }
+
+  bool is_default() const  { return label_ == NULL; }
+  Expression* label() const  {
+    CHECK(!is_default());
+    return label_;
+  }
+  JumpTarget* body_target() { return &body_target_; }
+  ZoneList<Statement*>* statements() const  { return statements_; }
+
+ private:
+  Expression* label_;
+  JumpTarget body_target_;
+  ZoneList<Statement*>* statements_;
+};
+
+
+class SwitchStatement: public BreakableStatement {
+ public:
+  explicit SwitchStatement(ZoneStringList* labels)
+      : BreakableStatement(labels, TARGET_FOR_ANONYMOUS),
+        tag_(NULL), cases_(NULL) { }
+
+  void Initialize(Expression* tag, ZoneList<CaseClause*>* cases) {
+    tag_ = tag;
+    cases_ = cases;
+  }
+
+  virtual void Accept(AstVisitor* v);
+
+  Expression* tag() const  { return tag_; }
+  ZoneList<CaseClause*>* cases() const  { return cases_; }
+
+ private:
+  Expression* tag_;
+  ZoneList<CaseClause*>* cases_;
+};
+
+
+// If-statements always have non-null references to their then- and
+// else-parts. When parsing if-statements with no explicit else-part,
+// the parser implicitly creates an empty statement. Use the
+// HasThenStatement() and HasElseStatement() functions to check if a
+// given if-statement has a then- or an else-part containing code.
+class IfStatement: public Statement {
+ public:
+  IfStatement(Expression* condition,
+              Statement* then_statement,
+              Statement* else_statement)
+      : condition_(condition),
+        then_statement_(then_statement),
+        else_statement_(else_statement) { }
+
+  virtual void Accept(AstVisitor* v);
+
+  bool HasThenStatement() const { return !then_statement()->IsEmpty(); }
+  bool HasElseStatement() const { return !else_statement()->IsEmpty(); }
+
+  Expression* condition() const { return condition_; }
+  Statement* then_statement() const { return then_statement_; }
+  Statement* else_statement() const { return else_statement_; }
+
+ private:
+  Expression* condition_;
+  Statement* then_statement_;
+  Statement* else_statement_;
+};
+
+
+// NOTE: TargetCollectors are represented as nodes to fit in the target
+// stack in the compiler; this should probably be reworked.
+class TargetCollector: public Node {
+ public:
+  explicit TargetCollector(ZoneList<BreakTarget*>* targets)
+      : targets_(targets) {
+  }
+
+  // Adds a jump target to the collector. The collector stores a pointer not
+  // a copy of the target to make binding work, so make sure not to pass in
+  // references to something on the stack.
+  void AddTarget(BreakTarget* target);
+
+  // Virtual behaviour. TargetCollectors are never part of the AST.
+  virtual void Accept(AstVisitor* v) { UNREACHABLE(); }
+  virtual TargetCollector* AsTargetCollector() { return this; }
+
+  ZoneList<BreakTarget*>* targets() { return targets_; }
+
+ private:
+  ZoneList<BreakTarget*>* targets_;
+};
+
+
+class TryStatement: public Statement {
+ public:
+  explicit TryStatement(Block* try_block)
+      : try_block_(try_block), escaping_targets_(NULL) { }
+
+  void set_escaping_targets(ZoneList<BreakTarget*>* targets) {
+    escaping_targets_ = targets;
+  }
+
+  Block* try_block() const { return try_block_; }
+  ZoneList<BreakTarget*>* escaping_targets() const { return escaping_targets_; }
+
+ private:
+  Block* try_block_;
+  ZoneList<BreakTarget*>* escaping_targets_;
+};
+
+
+class TryCatch: public TryStatement {
+ public:
+  TryCatch(Block* try_block, Expression* catch_var, Block* catch_block)
+      : TryStatement(try_block),
+        catch_var_(catch_var),
+        catch_block_(catch_block) {
+    ASSERT(catch_var->AsVariableProxy() != NULL);
+  }
+
+  virtual void Accept(AstVisitor* v);
+
+  Expression* catch_var() const  { return catch_var_; }
+  Block* catch_block() const  { return catch_block_; }
+
+ private:
+  Expression* catch_var_;
+  Block* catch_block_;
+};
+
+
+class TryFinally: public TryStatement {
+ public:
+  TryFinally(Block* try_block, Block* finally_block)
+      : TryStatement(try_block),
+        finally_block_(finally_block) { }
+
+  virtual void Accept(AstVisitor* v);
+
+  Block* finally_block() const { return finally_block_; }
+
+ private:
+  Block* finally_block_;
+};
+
+
+class DebuggerStatement: public Statement {
+ public:
+  virtual void Accept(AstVisitor* v);
+};
+
+
+class EmptyStatement: public Statement {
+ public:
+  virtual void Accept(AstVisitor* v);
+
+  // Type testing & conversion.
+  virtual EmptyStatement* AsEmptyStatement() { return this; }
+};
+
+
+class Literal: public Expression {
+ public:
+  explicit Literal(Handle<Object> handle) : handle_(handle) { }
+
+  virtual void Accept(AstVisitor* v);
+
+  // Type testing & conversion.
+  virtual Literal* AsLiteral() { return this; }
+
+  // Check if this literal is identical to the other literal.
+  bool IsIdenticalTo(const Literal* other) const {
+    return handle_.is_identical_to(other->handle_);
+  }
+
+  // Identity testers.
+  bool IsNull() const { return handle_.is_identical_to(Factory::null_value()); }
+  bool IsTrue() const { return handle_.is_identical_to(Factory::true_value()); }
+  bool IsFalse() const {
+    return handle_.is_identical_to(Factory::false_value());
+  }
+
+  Handle<Object> handle() const { return handle_; }
+
+ private:
+  Handle<Object> handle_;
+};
+
+
+// Base class for literals that needs space in the corresponding JSFunction.
+class MaterializedLiteral: public Expression {
+ public:
+  explicit MaterializedLiteral(int literal_index, bool is_simple, int depth)
+      : literal_index_(literal_index), is_simple_(is_simple), depth_(depth) {}
+
+  virtual MaterializedLiteral* AsMaterializedLiteral() { return this; }
+
+  int literal_index() { return literal_index_; }
+
+  // A materialized literal is simple if the values consist of only
+  // constants and simple object and array literals.
+  bool is_simple() const { return is_simple_; }
+
+  int depth() const { return depth_; }
+
+ private:
+  int literal_index_;
+  bool is_simple_;
+  int depth_;
+};
+
+
+// An object literal has a boilerplate object that is used
+// for minimizing the work when constructing it at runtime.
+class ObjectLiteral: public MaterializedLiteral {
+ public:
+  // Property is used for passing information
+  // about an object literal's properties from the parser
+  // to the code generator.
+  class Property: public ZoneObject {
+   public:
+
+    enum Kind {
+      CONSTANT,              // Property with constant value (compile time).
+      COMPUTED,              // Property with computed value (execution time).
+      MATERIALIZED_LITERAL,  // Property value is a materialized literal.
+      GETTER, SETTER,        // Property is an accessor function.
+      PROTOTYPE              // Property is __proto__.
+    };
+
+    Property(Literal* key, Expression* value);
+    Property(bool is_getter, FunctionLiteral* value);
+
+    Literal* key() { return key_; }
+    Expression* value() { return value_; }
+    Kind kind() { return kind_; }
+
+   private:
+    Literal* key_;
+    Expression* value_;
+    Kind kind_;
+  };
+
+  ObjectLiteral(Handle<FixedArray> constant_properties,
+                ZoneList<Property*>* properties,
+                int literal_index,
+                bool is_simple,
+                int depth)
+      : MaterializedLiteral(literal_index, is_simple, depth),
+        constant_properties_(constant_properties),
+        properties_(properties) {}
+
+  virtual ObjectLiteral* AsObjectLiteral() { return this; }
+  virtual void Accept(AstVisitor* v);
+
+  Handle<FixedArray> constant_properties() const {
+    return constant_properties_;
+  }
+  ZoneList<Property*>* properties() const { return properties_; }
+
+ private:
+  Handle<FixedArray> constant_properties_;
+  ZoneList<Property*>* properties_;
+};
+
+
+// Node for capturing a regexp literal.
+class RegExpLiteral: public MaterializedLiteral {
+ public:
+  RegExpLiteral(Handle<String> pattern,
+                Handle<String> flags,
+                int literal_index)
+      : MaterializedLiteral(literal_index, false, 1),
+        pattern_(pattern),
+        flags_(flags) {}
+
+  virtual void Accept(AstVisitor* v);
+
+  Handle<String> pattern() const { return pattern_; }
+  Handle<String> flags() const { return flags_; }
+
+ private:
+  Handle<String> pattern_;
+  Handle<String> flags_;
+};
+
+// An array literal has a literals object that is used
+// for minimizing the work when constructing it at runtime.
+class ArrayLiteral: public MaterializedLiteral {
+ public:
+  ArrayLiteral(Handle<FixedArray> literals,
+               ZoneList<Expression*>* values,
+               int literal_index,
+               bool is_simple,
+               int depth)
+      : MaterializedLiteral(literal_index, is_simple, depth),
+        literals_(literals),
+        values_(values) {}
+
+  virtual void Accept(AstVisitor* v);
+  virtual ArrayLiteral* AsArrayLiteral() { return this; }
+
+  Handle<FixedArray> literals() const { return literals_; }
+  ZoneList<Expression*>* values() const { return values_; }
+
+ private:
+  Handle<FixedArray> literals_;
+  ZoneList<Expression*>* values_;
+};
+
+
+// Node for constructing a context extension object for a catch block.
+// The catch context extension object has one property, the catch
+// variable, which should be DontDelete.
+class CatchExtensionObject: public Expression {
+ public:
+  CatchExtensionObject(Literal* key, VariableProxy* value)
+      : key_(key), value_(value) {
+  }
+
+  virtual void Accept(AstVisitor* v);
+
+  Literal* key() const { return key_; }
+  VariableProxy* value() const { return value_; }
+
+ private:
+  Literal* key_;
+  VariableProxy* value_;
+};
+
+
+class VariableProxy: public Expression {
+ public:
+  virtual void Accept(AstVisitor* v);
+
+  // Type testing & conversion
+  virtual Property* AsProperty() {
+    return var_ == NULL ? NULL : var_->AsProperty();
+  }
+  virtual VariableProxy* AsVariableProxy()  { return this; }
+
+  Variable* AsVariable() {
+    return this == NULL || var_ == NULL ? NULL : var_->AsVariable();
+  }
+  virtual bool IsValidLeftHandSide() {
+    return var_ == NULL ? true : var_->IsValidLeftHandSide();
+  }
+  bool IsVariable(Handle<String> n) {
+    return !is_this() && name().is_identical_to(n);
+  }
+
+  // If this assertion fails it means that some code has tried to
+  // treat the special "this" variable as an ordinary variable with
+  // the name "this".
+  Handle<String> name() const  { return name_; }
+  Variable* var() const  { return var_; }
+  UseCount* var_uses()  { return &var_uses_; }
+  UseCount* obj_uses()  { return &obj_uses_; }
+  bool is_this() const  { return is_this_; }
+  bool inside_with() const  { return inside_with_; }
+
+  // Bind this proxy to the variable var.
+  void BindTo(Variable* var);
+
+ protected:
+  Handle<String> name_;
+  Variable* var_;  // resolved variable, or NULL
+  bool is_this_;
+  bool inside_with_;
+
+  // VariableProxy usage info.
+  UseCount var_uses_;  // uses of the variable value
+  UseCount obj_uses_;  // uses of the object the variable points to
+
+  VariableProxy(Handle<String> name, bool is_this, bool inside_with);
+  explicit VariableProxy(bool is_this);
+
+  friend class Scope;
+};
+
+
+class VariableProxySentinel: public VariableProxy {
+ public:
+  virtual bool IsValidLeftHandSide() { return !is_this(); }
+  static VariableProxySentinel* this_proxy() { return &this_proxy_; }
+  static VariableProxySentinel* identifier_proxy() {
+    return &identifier_proxy_;
+  }
+
+ private:
+  explicit VariableProxySentinel(bool is_this) : VariableProxy(is_this) { }
+  static VariableProxySentinel this_proxy_;
+  static VariableProxySentinel identifier_proxy_;
+};
+
+
+class Slot: public Expression {
+ public:
+  enum Type {
+    // A slot in the parameter section on the stack. index() is
+    // the parameter index, counting left-to-right, starting at 0.
+    PARAMETER,
+
+    // A slot in the local section on the stack. index() is
+    // the variable index in the stack frame, starting at 0.
+    LOCAL,
+
+    // An indexed slot in a heap context. index() is the
+    // variable index in the context object on the heap,
+    // starting at 0. var()->scope() is the corresponding
+    // scope.
+    CONTEXT,
+
+    // A named slot in a heap context. var()->name() is the
+    // variable name in the context object on the heap,
+    // with lookup starting at the current context. index()
+    // is invalid.
+    LOOKUP,
+
+    // A property in the global object. var()->name() is
+    // the property name.
+    GLOBAL
+  };
+
+  Slot(Variable* var, Type type, int index)
+      : var_(var), type_(type), index_(index) {
+    ASSERT(var != NULL);
+  }
+
+  virtual void Accept(AstVisitor* v);
+
+  // Type testing & conversion
+  virtual Slot* AsSlot()  { return this; }
+
+  // Accessors
+  Variable* var() const  { return var_; }
+  Type type() const  { return type_; }
+  int index() const  { return index_; }
+
+ private:
+  Variable* var_;
+  Type type_;
+  int index_;
+};
+
+
+class Property: public Expression {
+ public:
+  // Synthetic properties are property lookups introduced by the system,
+  // to objects that aren't visible to the user. Function calls to synthetic
+  // properties should use the global object as receiver, not the base object
+  // of the resolved Reference.
+  enum Type { NORMAL, SYNTHETIC };
+  Property(Expression* obj, Expression* key, int pos, Type type = NORMAL)
+      : obj_(obj), key_(key), pos_(pos), type_(type) { }
+
+  virtual void Accept(AstVisitor* v);
+
+  // Type testing & conversion
+  virtual Property* AsProperty() { return this; }
+
+  virtual bool IsValidLeftHandSide() { return true; }
+
+  Expression* obj() const { return obj_; }
+  Expression* key() const { return key_; }
+  int position() const { return pos_; }
+  bool is_synthetic() const { return type_ == SYNTHETIC; }
+
+  // Returns a property singleton property access on 'this'.  Used
+  // during preparsing.
+  static Property* this_property() { return &this_property_; }
+
+ private:
+  Expression* obj_;
+  Expression* key_;
+  int pos_;
+  Type type_;
+
+  // Dummy property used during preparsing.
+  static Property this_property_;
+};
+
+
+class Call: public Expression {
+ public:
+  Call(Expression* expression,
+       ZoneList<Expression*>* arguments,
+       int pos)
+      : expression_(expression),
+        arguments_(arguments),
+        pos_(pos) { }
+
+  virtual void Accept(AstVisitor* v);
+
+  // Type testing and conversion.
+  virtual Call* AsCall() { return this; }
+
+  Expression* expression() const { return expression_; }
+  ZoneList<Expression*>* arguments() const { return arguments_; }
+  int position() { return pos_; }
+
+  static Call* sentinel() { return &sentinel_; }
+
+ private:
+  Expression* expression_;
+  ZoneList<Expression*>* arguments_;
+  int pos_;
+
+  static Call sentinel_;
+};
+
+
+class CallNew: public Call {
+ public:
+  CallNew(Expression* expression, ZoneList<Expression*>* arguments, int pos)
+      : Call(expression, arguments, pos) { }
+
+  virtual void Accept(AstVisitor* v);
+};
+
+
+// The CallEval class represents a call of the form 'eval(...)' where eval
+// cannot be seen to be overwritten at compile time. It is potentially a
+// direct (i.e. not aliased) eval call. The real nature of the call is
+// determined at runtime.
+class CallEval: public Call {
+ public:
+  CallEval(Expression* expression, ZoneList<Expression*>* arguments, int pos)
+      : Call(expression, arguments, pos) { }
+
+  virtual void Accept(AstVisitor* v);
+
+  static CallEval* sentinel() { return &sentinel_; }
+
+ private:
+  static CallEval sentinel_;
+};
+
+
+// The CallRuntime class does not represent any official JavaScript
+// language construct. Instead it is used to call a C or JS function
+// with a set of arguments. This is used from the builtins that are
+// implemented in JavaScript (see "v8natives.js").
+class CallRuntime: public Expression {
+ public:
+  CallRuntime(Handle<String> name,
+              Runtime::Function* function,
+              ZoneList<Expression*>* arguments)
+      : name_(name), function_(function), arguments_(arguments) { }
+
+  virtual void Accept(AstVisitor* v);
+
+  Handle<String> name() const { return name_; }
+  Runtime::Function* function() const { return function_; }
+  ZoneList<Expression*>* arguments() const { return arguments_; }
+
+ private:
+  Handle<String> name_;
+  Runtime::Function* function_;
+  ZoneList<Expression*>* arguments_;
+};
+
+
+class UnaryOperation: public Expression {
+ public:
+  UnaryOperation(Token::Value op, Expression* expression)
+      : op_(op), expression_(expression) {
+    ASSERT(Token::IsUnaryOp(op));
+  }
+
+  virtual void Accept(AstVisitor* v);
+
+  // Type testing & conversion
+  virtual UnaryOperation* AsUnaryOperation() { return this; }
+
+  Token::Value op() const { return op_; }
+  Expression* expression() const { return expression_; }
+
+ private:
+  Token::Value op_;
+  Expression* expression_;
+};
+
+
+class BinaryOperation: public Expression {
+ public:
+  BinaryOperation(Token::Value op, Expression* left, Expression* right)
+      : op_(op), left_(left), right_(right) {
+    ASSERT(Token::IsBinaryOp(op));
+  }
+
+  virtual void Accept(AstVisitor* v);
+
+  // Type testing & conversion
+  virtual BinaryOperation* AsBinaryOperation() { return this; }
+
+  // True iff the result can be safely overwritten (to avoid allocation).
+  // False for operations that can return one of their operands.
+  bool ResultOverwriteAllowed() {
+    switch (op_) {
+      case Token::COMMA:
+      case Token::OR:
+      case Token::AND:
+        return false;
+      case Token::BIT_OR:
+      case Token::BIT_XOR:
+      case Token::BIT_AND:
+      case Token::SHL:
+      case Token::SAR:
+      case Token::SHR:
+      case Token::ADD:
+      case Token::SUB:
+      case Token::MUL:
+      case Token::DIV:
+      case Token::MOD:
+        return true;
+      default:
+        UNREACHABLE();
+    }
+    return false;
+  }
+
+  Token::Value op() const { return op_; }
+  Expression* left() const { return left_; }
+  Expression* right() const { return right_; }
+
+ private:
+  Token::Value op_;
+  Expression* left_;
+  Expression* right_;
+};
+
+
+class CountOperation: public Expression {
+ public:
+  CountOperation(bool is_prefix, Token::Value op, Expression* expression)
+      : is_prefix_(is_prefix), op_(op), expression_(expression) {
+    ASSERT(Token::IsCountOp(op));
+  }
+
+  virtual void Accept(AstVisitor* v);
+
+  bool is_prefix() const { return is_prefix_; }
+  bool is_postfix() const { return !is_prefix_; }
+  Token::Value op() const { return op_; }
+  Expression* expression() const { return expression_; }
+
+  virtual void MarkAsStatement() { is_prefix_ = true; }
+
+ private:
+  bool is_prefix_;
+  Token::Value op_;
+  Expression* expression_;
+};
+
+
+class CompareOperation: public Expression {
+ public:
+  CompareOperation(Token::Value op, Expression* left, Expression* right)
+      : op_(op), left_(left), right_(right) {
+    ASSERT(Token::IsCompareOp(op));
+  }
+
+  virtual void Accept(AstVisitor* v);
+
+  Token::Value op() const { return op_; }
+  Expression* left() const { return left_; }
+  Expression* right() const { return right_; }
+
+ private:
+  Token::Value op_;
+  Expression* left_;
+  Expression* right_;
+};
+
+
+class Conditional: public Expression {
+ public:
+  Conditional(Expression* condition,
+              Expression* then_expression,
+              Expression* else_expression)
+      : condition_(condition),
+        then_expression_(then_expression),
+        else_expression_(else_expression) { }
+
+  virtual void Accept(AstVisitor* v);
+
+  Expression* condition() const { return condition_; }
+  Expression* then_expression() const { return then_expression_; }
+  Expression* else_expression() const { return else_expression_; }
+
+ private:
+  Expression* condition_;
+  Expression* then_expression_;
+  Expression* else_expression_;
+};
+
+
+class Assignment: public Expression {
+ public:
+  Assignment(Token::Value op, Expression* target, Expression* value, int pos)
+      : op_(op), target_(target), value_(value), pos_(pos),
+        block_start_(false), block_end_(false) {
+    ASSERT(Token::IsAssignmentOp(op));
+  }
+
+  virtual void Accept(AstVisitor* v);
+  virtual Assignment* AsAssignment() { return this; }
+
+  Token::Value binary_op() const;
+
+  Token::Value op() const { return op_; }
+  Expression* target() const { return target_; }
+  Expression* value() const { return value_; }
+  int position() { return pos_; }
+
+  // An initialization block is a series of statments of the form
+  // x.y.z.a = ...; x.y.z.b = ...; etc. The parser marks the beginning and
+  // ending of these blocks to allow for optimizations of initialization
+  // blocks.
+  bool starts_initialization_block() { return block_start_; }
+  bool ends_initialization_block() { return block_end_; }
+  void mark_block_start() { block_start_ = true; }
+  void mark_block_end() { block_end_ = true; }
+
+ private:
+  Token::Value op_;
+  Expression* target_;
+  Expression* value_;
+  int pos_;
+  bool block_start_;
+  bool block_end_;
+};
+
+
+class Throw: public Expression {
+ public:
+  Throw(Expression* exception, int pos)
+      : exception_(exception), pos_(pos) {}
+
+  virtual void Accept(AstVisitor* v);
+  Expression* exception() const { return exception_; }
+  int position() const { return pos_; }
+
+ private:
+  Expression* exception_;
+  int pos_;
+};
+
+
+class FunctionLiteral: public Expression {
+ public:
+  FunctionLiteral(Handle<String> name,
+                  Scope* scope,
+                  ZoneList<Statement*>* body,
+                  int materialized_literal_count,
+                  bool contains_array_literal,
+                  int expected_property_count,
+                  int num_parameters,
+                  int start_position,
+                  int end_position,
+                  bool is_expression)
+      : name_(name),
+        scope_(scope),
+        body_(body),
+        materialized_literal_count_(materialized_literal_count),
+        contains_array_literal_(contains_array_literal),
+        expected_property_count_(expected_property_count),
+        num_parameters_(num_parameters),
+        start_position_(start_position),
+        end_position_(end_position),
+        is_expression_(is_expression),
+        loop_nesting_(0),
+        function_token_position_(RelocInfo::kNoPosition),
+        inferred_name_(Heap::empty_string()) {
+#ifdef DEBUG
+    already_compiled_ = false;
+#endif
+  }
+
+  virtual void Accept(AstVisitor* v);
+
+  // Type testing & conversion
+  virtual FunctionLiteral* AsFunctionLiteral()  { return this; }
+
+  Handle<String> name() const  { return name_; }
+  Scope* scope() const  { return scope_; }
+  ZoneList<Statement*>* body() const  { return body_; }
+  void set_function_token_position(int pos) { function_token_position_ = pos; }
+  int function_token_position() const { return function_token_position_; }
+  int start_position() const { return start_position_; }
+  int end_position() const { return end_position_; }
+  bool is_expression() const { return is_expression_; }
+
+  int materialized_literal_count() { return materialized_literal_count_; }
+  bool contains_array_literal() { return contains_array_literal_; }
+  int expected_property_count() { return expected_property_count_; }
+  int num_parameters() { return num_parameters_; }
+
+  bool AllowsLazyCompilation();
+
+  bool loop_nesting() const { return loop_nesting_; }
+  void set_loop_nesting(int nesting) { loop_nesting_ = nesting; }
+
+  Handle<String> inferred_name() const  { return inferred_name_; }
+  void set_inferred_name(Handle<String> inferred_name) {
+    inferred_name_ = inferred_name;
+  }
+
+#ifdef DEBUG
+  void mark_as_compiled() {
+    ASSERT(!already_compiled_);
+    already_compiled_ = true;
+  }
+#endif
+
+ private:
+  Handle<String> name_;
+  Scope* scope_;
+  ZoneList<Statement*>* body_;
+  int materialized_literal_count_;
+  bool contains_array_literal_;
+  int expected_property_count_;
+  int num_parameters_;
+  int start_position_;
+  int end_position_;
+  bool is_expression_;
+  int loop_nesting_;
+  int function_token_position_;
+  Handle<String> inferred_name_;
+#ifdef DEBUG
+  bool already_compiled_;
+#endif
+};
+
+
+class FunctionBoilerplateLiteral: public Expression {
+ public:
+  explicit FunctionBoilerplateLiteral(Handle<JSFunction> boilerplate)
+      : boilerplate_(boilerplate) {
+    ASSERT(boilerplate->IsBoilerplate());
+  }
+
+  Handle<JSFunction> boilerplate() const { return boilerplate_; }
+
+  virtual void Accept(AstVisitor* v);
+
+ private:
+  Handle<JSFunction> boilerplate_;
+};
+
+
+class ThisFunction: public Expression {
+ public:
+  virtual void Accept(AstVisitor* v);
+};
+
+
+// ----------------------------------------------------------------------------
+// Regular expressions
+
+
+class RegExpVisitor BASE_EMBEDDED {
+ public:
+  virtual ~RegExpVisitor() { }
+#define MAKE_CASE(Name)                                              \
+  virtual void* Visit##Name(RegExp##Name*, void* data) = 0;
+  FOR_EACH_REG_EXP_TREE_TYPE(MAKE_CASE)
+#undef MAKE_CASE
+};
+
+
+class RegExpTree: public ZoneObject {
+ public:
+  static const int kInfinity = kMaxInt;
+  virtual ~RegExpTree() { }
+  virtual void* Accept(RegExpVisitor* visitor, void* data) = 0;
+  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
+                             RegExpNode* on_success) = 0;
+  virtual bool IsTextElement() { return false; }
+  virtual bool IsAnchored() { return false; }
+  virtual int min_match() = 0;
+  virtual int max_match() = 0;
+  // Returns the interval of registers used for captures within this
+  // expression.
+  virtual Interval CaptureRegisters() { return Interval::Empty(); }
+  virtual void AppendToText(RegExpText* text);
+  SmartPointer<const char> ToString();
+#define MAKE_ASTYPE(Name)                                                  \
+  virtual RegExp##Name* As##Name();                                        \
+  virtual bool Is##Name();
+  FOR_EACH_REG_EXP_TREE_TYPE(MAKE_ASTYPE)
+#undef MAKE_ASTYPE
+};
+
+
+class RegExpDisjunction: public RegExpTree {
+ public:
+  explicit RegExpDisjunction(ZoneList<RegExpTree*>* alternatives);
+  virtual void* Accept(RegExpVisitor* visitor, void* data);
+  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
+                             RegExpNode* on_success);
+  virtual RegExpDisjunction* AsDisjunction();
+  virtual Interval CaptureRegisters();
+  virtual bool IsDisjunction();
+  virtual bool IsAnchored();
+  virtual int min_match() { return min_match_; }
+  virtual int max_match() { return max_match_; }
+  ZoneList<RegExpTree*>* alternatives() { return alternatives_; }
+ private:
+  ZoneList<RegExpTree*>* alternatives_;
+  int min_match_;
+  int max_match_;
+};
+
+
+class RegExpAlternative: public RegExpTree {
+ public:
+  explicit RegExpAlternative(ZoneList<RegExpTree*>* nodes);
+  virtual void* Accept(RegExpVisitor* visitor, void* data);
+  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
+                             RegExpNode* on_success);
+  virtual RegExpAlternative* AsAlternative();
+  virtual Interval CaptureRegisters();
+  virtual bool IsAlternative();
+  virtual bool IsAnchored();
+  virtual int min_match() { return min_match_; }
+  virtual int max_match() { return max_match_; }
+  ZoneList<RegExpTree*>* nodes() { return nodes_; }
+ private:
+  ZoneList<RegExpTree*>* nodes_;
+  int min_match_;
+  int max_match_;
+};
+
+
+class RegExpAssertion: public RegExpTree {
+ public:
+  enum Type {
+    START_OF_LINE,
+    START_OF_INPUT,
+    END_OF_LINE,
+    END_OF_INPUT,
+    BOUNDARY,
+    NON_BOUNDARY
+  };
+  explicit RegExpAssertion(Type type) : type_(type) { }
+  virtual void* Accept(RegExpVisitor* visitor, void* data);
+  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
+                             RegExpNode* on_success);
+  virtual RegExpAssertion* AsAssertion();
+  virtual bool IsAssertion();
+  virtual bool IsAnchored();
+  virtual int min_match() { return 0; }
+  virtual int max_match() { return 0; }
+  Type type() { return type_; }
+ private:
+  Type type_;
+};
+
+
+class CharacterSet BASE_EMBEDDED {
+ public:
+  explicit CharacterSet(uc16 standard_set_type)
+      : ranges_(NULL),
+        standard_set_type_(standard_set_type) {}
+  explicit CharacterSet(ZoneList<CharacterRange>* ranges)
+      : ranges_(ranges),
+        standard_set_type_(0) {}
+  ZoneList<CharacterRange>* ranges();
+  uc16 standard_set_type() { return standard_set_type_; }
+  void set_standard_set_type(uc16 special_set_type) {
+    standard_set_type_ = special_set_type;
+  }
+  bool is_standard() { return standard_set_type_ != 0; }
+ private:
+  ZoneList<CharacterRange>* ranges_;
+  // If non-zero, the value represents a standard set (e.g., all whitespace
+  // characters) without having to expand the ranges.
+  uc16 standard_set_type_;
+};
+
+
+class RegExpCharacterClass: public RegExpTree {
+ public:
+  RegExpCharacterClass(ZoneList<CharacterRange>* ranges, bool is_negated)
+      : set_(ranges),
+        is_negated_(is_negated) { }
+  explicit RegExpCharacterClass(uc16 type)
+      : set_(type),
+        is_negated_(false) { }
+  virtual void* Accept(RegExpVisitor* visitor, void* data);
+  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
+                             RegExpNode* on_success);
+  virtual RegExpCharacterClass* AsCharacterClass();
+  virtual bool IsCharacterClass();
+  virtual bool IsTextElement() { return true; }
+  virtual int min_match() { return 1; }
+  virtual int max_match() { return 1; }
+  virtual void AppendToText(RegExpText* text);
+  CharacterSet character_set() { return set_; }
+  // TODO(lrn): Remove need for complex version if is_standard that
+  // recognizes a mangled standard set and just do { return set_.is_special(); }
+  bool is_standard();
+  // Returns a value representing the standard character set if is_standard()
+  // returns true.
+  // Currently used values are:
+  // s : unicode whitespace
+  // S : unicode non-whitespace
+  // w : ASCII word character (digit, letter, underscore)
+  // W : non-ASCII word character
+  // d : ASCII digit
+  // D : non-ASCII digit
+  // . : non-unicode non-newline
+  // * : All characters
+  uc16 standard_type() { return set_.standard_set_type(); }
+  ZoneList<CharacterRange>* ranges() { return set_.ranges(); }
+  bool is_negated() { return is_negated_; }
+ private:
+  CharacterSet set_;
+  bool is_negated_;
+};
+
+
+class RegExpAtom: public RegExpTree {
+ public:
+  explicit RegExpAtom(Vector<const uc16> data) : data_(data) { }
+  virtual void* Accept(RegExpVisitor* visitor, void* data);
+  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
+                             RegExpNode* on_success);
+  virtual RegExpAtom* AsAtom();
+  virtual bool IsAtom();
+  virtual bool IsTextElement() { return true; }
+  virtual int min_match() { return data_.length(); }
+  virtual int max_match() { return data_.length(); }
+  virtual void AppendToText(RegExpText* text);
+  Vector<const uc16> data() { return data_; }
+  int length() { return data_.length(); }
+ private:
+  Vector<const uc16> data_;
+};
+
+
+class RegExpText: public RegExpTree {
+ public:
+  RegExpText() : elements_(2), length_(0) {}
+  virtual void* Accept(RegExpVisitor* visitor, void* data);
+  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
+                             RegExpNode* on_success);
+  virtual RegExpText* AsText();
+  virtual bool IsText();
+  virtual bool IsTextElement() { return true; }
+  virtual int min_match() { return length_; }
+  virtual int max_match() { return length_; }
+  virtual void AppendToText(RegExpText* text);
+  void AddElement(TextElement elm)  {
+    elements_.Add(elm);
+    length_ += elm.length();
+  };
+  ZoneList<TextElement>* elements() { return &elements_; }
+ private:
+  ZoneList<TextElement> elements_;
+  int length_;
+};
+
+
+class RegExpQuantifier: public RegExpTree {
+ public:
+  RegExpQuantifier(int min, int max, bool is_greedy, RegExpTree* body)
+      : min_(min),
+        max_(max),
+        is_greedy_(is_greedy),
+        body_(body),
+        min_match_(min * body->min_match()) {
+    if (max > 0 && body->max_match() > kInfinity / max) {
+      max_match_ = kInfinity;
+    } else {
+      max_match_ = max * body->max_match();
+    }
+  }
+  virtual void* Accept(RegExpVisitor* visitor, void* data);
+  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
+                             RegExpNode* on_success);
+  static RegExpNode* ToNode(int min,
+                            int max,
+                            bool is_greedy,
+                            RegExpTree* body,
+                            RegExpCompiler* compiler,
+                            RegExpNode* on_success,
+                            bool not_at_start = false);
+  virtual RegExpQuantifier* AsQuantifier();
+  virtual Interval CaptureRegisters();
+  virtual bool IsQuantifier();
+  virtual int min_match() { return min_match_; }
+  virtual int max_match() { return max_match_; }
+  int min() { return min_; }
+  int max() { return max_; }
+  bool is_greedy() { return is_greedy_; }
+  RegExpTree* body() { return body_; }
+ private:
+  int min_;
+  int max_;
+  bool is_greedy_;
+  RegExpTree* body_;
+  int min_match_;
+  int max_match_;
+};
+
+
+enum CaptureAvailability {
+  CAPTURE_AVAILABLE,
+  CAPTURE_UNREACHABLE,
+  CAPTURE_PERMANENTLY_UNREACHABLE
+};
+
+class RegExpCapture: public RegExpTree {
+ public:
+  explicit RegExpCapture(RegExpTree* body, int index)
+      : body_(body), index_(index), available_(CAPTURE_AVAILABLE) { }
+  virtual void* Accept(RegExpVisitor* visitor, void* data);
+  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
+                             RegExpNode* on_success);
+  static RegExpNode* ToNode(RegExpTree* body,
+                            int index,
+                            RegExpCompiler* compiler,
+                            RegExpNode* on_success);
+  virtual RegExpCapture* AsCapture();
+  virtual bool IsAnchored();
+  virtual Interval CaptureRegisters();
+  virtual bool IsCapture();
+  virtual int min_match() { return body_->min_match(); }
+  virtual int max_match() { return body_->max_match(); }
+  RegExpTree* body() { return body_; }
+  int index() { return index_; }
+  inline CaptureAvailability available() { return available_; }
+  inline void set_available(CaptureAvailability availability) {
+    available_ = availability;
+  }
+  static int StartRegister(int index) { return index * 2; }
+  static int EndRegister(int index) { return index * 2 + 1; }
+ private:
+  RegExpTree* body_;
+  int index_;
+  CaptureAvailability available_;
+};
+
+
+class RegExpLookahead: public RegExpTree {
+ public:
+  RegExpLookahead(RegExpTree* body,
+                  bool is_positive,
+                  int capture_count,
+                  int capture_from)
+      : body_(body),
+        is_positive_(is_positive),
+        capture_count_(capture_count),
+        capture_from_(capture_from) { }
+
+  virtual void* Accept(RegExpVisitor* visitor, void* data);
+  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
+                             RegExpNode* on_success);
+  virtual RegExpLookahead* AsLookahead();
+  virtual Interval CaptureRegisters();
+  virtual bool IsLookahead();
+  virtual bool IsAnchored();
+  virtual int min_match() { return 0; }
+  virtual int max_match() { return 0; }
+  RegExpTree* body() { return body_; }
+  bool is_positive() { return is_positive_; }
+  int capture_count() { return capture_count_; }
+  int capture_from() { return capture_from_; }
+ private:
+  RegExpTree* body_;
+  bool is_positive_;
+  int capture_count_;
+  int capture_from_;
+};
+
+
+class RegExpBackReference: public RegExpTree {
+ public:
+  explicit RegExpBackReference(RegExpCapture* capture)
+      : capture_(capture) { }
+  virtual void* Accept(RegExpVisitor* visitor, void* data);
+  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
+                             RegExpNode* on_success);
+  virtual RegExpBackReference* AsBackReference();
+  virtual bool IsBackReference();
+  virtual int min_match() { return 0; }
+  virtual int max_match() { return capture_->max_match(); }
+  int index() { return capture_->index(); }
+  RegExpCapture* capture() { return capture_; }
+ private:
+  RegExpCapture* capture_;
+};
+
+
+class RegExpEmpty: public RegExpTree {
+ public:
+  RegExpEmpty() { }
+  virtual void* Accept(RegExpVisitor* visitor, void* data);
+  virtual RegExpNode* ToNode(RegExpCompiler* compiler,
+                             RegExpNode* on_success);
+  virtual RegExpEmpty* AsEmpty();
+  virtual bool IsEmpty();
+  virtual int min_match() { return 0; }
+  virtual int max_match() { return 0; }
+  static RegExpEmpty* GetInstance() { return &kInstance; }
+ private:
+  static RegExpEmpty kInstance;
+};
+
+
+// ----------------------------------------------------------------------------
+// Basic visitor
+// - leaf node visitors are abstract.
+
+class AstVisitor BASE_EMBEDDED {
+ public:
+  AstVisitor() : stack_overflow_(false) { }
+  virtual ~AstVisitor() { }
+
+  // Dispatch
+  void Visit(Node* node) { node->Accept(this); }
+
+  // Iteration
+  virtual void VisitStatements(ZoneList<Statement*>* statements);
+  virtual void VisitExpressions(ZoneList<Expression*>* expressions);
+
+  // Stack overflow tracking support.
+  bool HasStackOverflow() const { return stack_overflow_; }
+  bool CheckStackOverflow() {
+    if (stack_overflow_) return true;
+    StackLimitCheck check;
+    if (!check.HasOverflowed()) return false;
+    return (stack_overflow_ = true);
+  }
+
+  // If a stack-overflow exception is encountered when visiting a
+  // node, calling SetStackOverflow will make sure that the visitor
+  // bails out without visiting more nodes.
+  void SetStackOverflow() { stack_overflow_ = true; }
+
+
+  // Individual nodes
+#define DEF_VISIT(type)                         \
+  virtual void Visit##type(type* node) = 0;
+  NODE_LIST(DEF_VISIT)
+#undef DEF_VISIT
+
+ private:
+  bool stack_overflow_;
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_AST_H_
diff --git a/deps/v8/src/bootstrapper.cc b/deps/v8/src/bootstrapper.cc
new file mode 100644
index 0000000..0a0ed83
--- /dev/null
+++ b/deps/v8/src/bootstrapper.cc
@@ -0,0 +1,1528 @@
+// 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.
+
+#include "v8.h"
+
+#include "accessors.h"
+#include "api.h"
+#include "bootstrapper.h"
+#include "compiler.h"
+#include "debug.h"
+#include "execution.h"
+#include "global-handles.h"
+#include "macro-assembler.h"
+#include "natives.h"
+
+namespace v8 { namespace internal {
+
+// A SourceCodeCache uses a FixedArray to store pairs of
+// (AsciiString*, JSFunction*), mapping names of native code files
+// (runtime.js, etc.) to precompiled functions. Instead of mapping
+// names to functions it might make sense to let the JS2C tool
+// generate an index for each native JS file.
+class SourceCodeCache BASE_EMBEDDED {
+ public:
+  explicit SourceCodeCache(ScriptType type): type_(type) { }
+
+  void Initialize(bool create_heap_objects) {
+    if (create_heap_objects) {
+      cache_ = Heap::empty_fixed_array();
+    } else {
+      cache_ = NULL;
+    }
+  }
+
+  void Iterate(ObjectVisitor* v) {
+    v->VisitPointer(bit_cast<Object**, FixedArray**>(&cache_));
+  }
+
+
+  bool Lookup(Vector<const char> name, Handle<JSFunction>* handle) {
+    for (int i = 0; i < cache_->length(); i+=2) {
+      SeqAsciiString* str = SeqAsciiString::cast(cache_->get(i));
+      if (str->IsEqualTo(name)) {
+        *handle = Handle<JSFunction>(JSFunction::cast(cache_->get(i + 1)));
+        return true;
+      }
+    }
+    return false;
+  }
+
+
+  void Add(Vector<const char> name, Handle<JSFunction> fun) {
+    ASSERT(fun->IsBoilerplate());
+    HandleScope scope;
+    int length = cache_->length();
+    Handle<FixedArray> new_array =
+        Factory::NewFixedArray(length + 2, TENURED);
+    cache_->CopyTo(0, *new_array, 0, cache_->length());
+    cache_ = *new_array;
+    Handle<String> str = Factory::NewStringFromAscii(name, TENURED);
+    cache_->set(length, *str);
+    cache_->set(length + 1, *fun);
+    Script::cast(fun->shared()->script())->set_type(Smi::FromInt(type_));
+  }
+
+ private:
+  ScriptType type_;
+  FixedArray* cache_;
+  DISALLOW_COPY_AND_ASSIGN(SourceCodeCache);
+};
+
+static SourceCodeCache natives_cache(SCRIPT_TYPE_NATIVE);
+static SourceCodeCache extensions_cache(SCRIPT_TYPE_EXTENSION);
+
+
+Handle<String> Bootstrapper::NativesSourceLookup(int index) {
+  ASSERT(0 <= index && index < Natives::GetBuiltinsCount());
+  if (Heap::natives_source_cache()->get(index)->IsUndefined()) {
+    Handle<String> source_code =
+      Factory::NewStringFromAscii(Natives::GetScriptSource(index));
+    Heap::natives_source_cache()->set(index, *source_code);
+  }
+  Handle<Object> cached_source(Heap::natives_source_cache()->get(index));
+  return Handle<String>::cast(cached_source);
+}
+
+
+bool Bootstrapper::NativesCacheLookup(Vector<const char> name,
+                                      Handle<JSFunction>* handle) {
+  return natives_cache.Lookup(name, handle);
+}
+
+
+void Bootstrapper::NativesCacheAdd(Vector<const char> name,
+                                   Handle<JSFunction> fun) {
+  natives_cache.Add(name, fun);
+}
+
+
+void Bootstrapper::Initialize(bool create_heap_objects) {
+  natives_cache.Initialize(create_heap_objects);
+  extensions_cache.Initialize(create_heap_objects);
+}
+
+
+void Bootstrapper::TearDown() {
+  natives_cache.Initialize(false);  // Yes, symmetrical
+  extensions_cache.Initialize(false);
+}
+
+
+// Pending fixups are code positions that have refer to builtin code
+// objects that were not available at the time the code was generated.
+// The pending list is processed whenever an environment has been
+// created.
+class PendingFixups : public AllStatic {
+ public:
+  static void Add(Code* code, MacroAssembler* masm);
+  static bool Process(Handle<JSBuiltinsObject> builtins);
+
+  static void Iterate(ObjectVisitor* v);
+
+ private:
+  static List<Object*> code_;
+  static List<const char*> name_;
+  static List<int> pc_;
+  static List<uint32_t> flags_;
+
+  static void Clear();
+};
+
+
+List<Object*> PendingFixups::code_(0);
+List<const char*> PendingFixups::name_(0);
+List<int> PendingFixups::pc_(0);
+List<uint32_t> PendingFixups::flags_(0);
+
+
+void PendingFixups::Add(Code* code, MacroAssembler* masm) {
+  // Note this code is not only called during bootstrapping.
+  List<MacroAssembler::Unresolved>* unresolved = masm->unresolved();
+  int n = unresolved->length();
+  for (int i = 0; i < n; i++) {
+    const char* name = unresolved->at(i).name;
+    code_.Add(code);
+    name_.Add(name);
+    pc_.Add(unresolved->at(i).pc);
+    flags_.Add(unresolved->at(i).flags);
+    LOG(StringEvent("unresolved", name));
+  }
+}
+
+
+bool PendingFixups::Process(Handle<JSBuiltinsObject> builtins) {
+  HandleScope scope;
+  // NOTE: Extra fixups may be added to the list during the iteration
+  // due to lazy compilation of functions during the processing. Do not
+  // cache the result of getting the length of the code list.
+  for (int i = 0; i < code_.length(); i++) {
+    const char* name = name_[i];
+    uint32_t flags = flags_[i];
+    Handle<String> symbol = Factory::LookupAsciiSymbol(name);
+    Object* o = builtins->GetProperty(*symbol);
+#ifdef DEBUG
+    if (!o->IsJSFunction()) {
+      V8_Fatal(__FILE__, __LINE__, "Cannot resolve call to builtin %s", name);
+    }
+#endif
+    Handle<JSFunction> f = Handle<JSFunction>(JSFunction::cast(o));
+    // Make sure the number of parameters match the formal parameter count.
+    int argc = Bootstrapper::FixupFlagsArgumentsCount::decode(flags);
+    USE(argc);
+    ASSERT(f->shared()->formal_parameter_count() == argc);
+    if (!f->is_compiled()) {
+      // Do lazy compilation and check for stack overflows.
+      if (!CompileLazy(f, CLEAR_EXCEPTION)) {
+        Clear();
+        return false;
+      }
+    }
+    Code* code = Code::cast(code_[i]);
+    Address pc = code->instruction_start() + pc_[i];
+    bool is_pc_relative = Bootstrapper::FixupFlagsIsPCRelative::decode(flags);
+    bool use_code_object = Bootstrapper::FixupFlagsUseCodeObject::decode(flags);
+
+    if (use_code_object) {
+      if (is_pc_relative) {
+        Assembler::set_target_address_at(
+            pc, reinterpret_cast<Address>(f->code()));
+      } else {
+        *reinterpret_cast<Object**>(pc) = f->code();
+      }
+    } else {
+      ASSERT(is_pc_relative);
+      Assembler::set_target_address_at(pc, f->code()->instruction_start());
+    }
+
+    LOG(StringEvent("resolved", name));
+  }
+  Clear();
+
+  // TODO(1240818): We should probably try to avoid doing this for all
+  // the V8 builtin JS files. It should only happen after running
+  // runtime.js - just like there shouldn't be any fixups left after
+  // that.
+  for (int i = 0; i < Builtins::NumberOfJavaScriptBuiltins(); i++) {
+    Builtins::JavaScript id = static_cast<Builtins::JavaScript>(i);
+    Handle<String> name = Factory::LookupAsciiSymbol(Builtins::GetName(id));
+    JSFunction* function = JSFunction::cast(builtins->GetProperty(*name));
+    builtins->set_javascript_builtin(id, function);
+  }
+
+  return true;
+}
+
+
+void PendingFixups::Clear() {
+  code_.Clear();
+  name_.Clear();
+  pc_.Clear();
+  flags_.Clear();
+}
+
+
+void PendingFixups::Iterate(ObjectVisitor* v) {
+  if (!code_.is_empty()) {
+    v->VisitPointers(&code_[0], &code_[0] + code_.length());
+  }
+}
+
+
+class Genesis BASE_EMBEDDED {
+ public:
+  Genesis(Handle<Object> global_object,
+          v8::Handle<v8::ObjectTemplate> global_template,
+          v8::ExtensionConfiguration* extensions);
+  ~Genesis();
+
+  Handle<Context> result() { return result_; }
+
+  Genesis* previous() { return previous_; }
+  static Genesis* current() { return current_; }
+
+  // Support for thread preemption.
+  static int ArchiveSpacePerThread();
+  static char* ArchiveState(char* to);
+  static char* RestoreState(char* from);
+
+ private:
+  Handle<Context> global_context_;
+
+  // There may be more than one active genesis object: When GC is
+  // triggered during environment creation there may be weak handle
+  // processing callbacks which may create new environments.
+  Genesis* previous_;
+  static Genesis* current_;
+
+  Handle<Context> global_context() { return global_context_; }
+
+  void CreateRoots(v8::Handle<v8::ObjectTemplate> global_template,
+                   Handle<Object> global_object);
+  void InstallNativeFunctions();
+  bool InstallNatives();
+  bool InstallExtensions(v8::ExtensionConfiguration* extensions);
+  bool InstallExtension(const char* name);
+  bool InstallExtension(v8::RegisteredExtension* current);
+  bool InstallSpecialObjects();
+  bool ConfigureApiObject(Handle<JSObject> object,
+                          Handle<ObjectTemplateInfo> object_template);
+  bool ConfigureGlobalObjects(v8::Handle<v8::ObjectTemplate> global_template);
+
+  // Migrates all properties from the 'from' object to the 'to'
+  // object and overrides the prototype in 'to' with the one from
+  // 'from'.
+  void TransferObject(Handle<JSObject> from, Handle<JSObject> to);
+  void TransferNamedProperties(Handle<JSObject> from, Handle<JSObject> to);
+  void TransferIndexedProperties(Handle<JSObject> from, Handle<JSObject> to);
+
+  Handle<DescriptorArray> ComputeFunctionInstanceDescriptor(
+      bool make_prototype_read_only,
+      bool make_prototype_enumerable = false);
+  void MakeFunctionInstancePrototypeWritable();
+
+  void AddSpecialFunction(Handle<JSObject> prototype,
+                          const char* name,
+                          Handle<Code> code);
+
+  void BuildSpecialFunctionTable();
+
+  static bool CompileBuiltin(int index);
+  static bool CompileNative(Vector<const char> name, Handle<String> source);
+  static bool CompileScriptCached(Vector<const char> name,
+                                  Handle<String> source,
+                                  SourceCodeCache* cache,
+                                  v8::Extension* extension,
+                                  bool use_runtime_context);
+
+  Handle<Context> result_;
+};
+
+Genesis* Genesis::current_ = NULL;
+
+
+void Bootstrapper::Iterate(ObjectVisitor* v) {
+  natives_cache.Iterate(v);
+  extensions_cache.Iterate(v);
+  PendingFixups::Iterate(v);
+}
+
+
+// While setting up the environment, we collect code positions that
+// need to be patched before we can run any code in the environment.
+void Bootstrapper::AddFixup(Code* code, MacroAssembler* masm) {
+  PendingFixups::Add(code, masm);
+}
+
+
+bool Bootstrapper::IsActive() {
+  return Genesis::current() != NULL;
+}
+
+
+Handle<Context> Bootstrapper::CreateEnvironment(
+    Handle<Object> global_object,
+    v8::Handle<v8::ObjectTemplate> global_template,
+    v8::ExtensionConfiguration* extensions) {
+  Genesis genesis(global_object, global_template, extensions);
+  return genesis.result();
+}
+
+
+static void SetObjectPrototype(Handle<JSObject> object, Handle<Object> proto) {
+  // object.__proto__ = proto;
+  Handle<Map> old_to_map = Handle<Map>(object->map());
+  Handle<Map> new_to_map = Factory::CopyMapDropTransitions(old_to_map);
+  new_to_map->set_prototype(*proto);
+  object->set_map(*new_to_map);
+}
+
+
+void Bootstrapper::DetachGlobal(Handle<Context> env) {
+  JSGlobalProxy::cast(env->global_proxy())->set_context(*Factory::null_value());
+  SetObjectPrototype(Handle<JSObject>(env->global_proxy()),
+                     Factory::null_value());
+  env->set_global_proxy(env->global());
+  env->global()->set_global_receiver(env->global());
+}
+
+
+Genesis::~Genesis() {
+  ASSERT(current_ == this);
+  current_ = previous_;
+}
+
+
+static Handle<JSFunction> InstallFunction(Handle<JSObject> target,
+                                          const char* name,
+                                          InstanceType type,
+                                          int instance_size,
+                                          Handle<JSObject> prototype,
+                                          Builtins::Name call,
+                                          bool is_ecma_native) {
+  Handle<String> symbol = Factory::LookupAsciiSymbol(name);
+  Handle<Code> call_code = Handle<Code>(Builtins::builtin(call));
+  Handle<JSFunction> function =
+    Factory::NewFunctionWithPrototype(symbol,
+                                      type,
+                                      instance_size,
+                                      prototype,
+                                      call_code,
+                                      is_ecma_native);
+  SetProperty(target, symbol, function, DONT_ENUM);
+  if (is_ecma_native) {
+    function->shared()->set_instance_class_name(*symbol);
+  }
+  return function;
+}
+
+
+Handle<DescriptorArray> Genesis::ComputeFunctionInstanceDescriptor(
+    bool make_prototype_read_only,
+    bool make_prototype_enumerable) {
+  Handle<DescriptorArray> result = Factory::empty_descriptor_array();
+
+  // Add prototype.
+  PropertyAttributes attributes = static_cast<PropertyAttributes>(
+      (make_prototype_enumerable ? 0 : DONT_ENUM)
+      | DONT_DELETE
+      | (make_prototype_read_only ? READ_ONLY : 0));
+  result =
+      Factory::CopyAppendProxyDescriptor(
+          result,
+          Factory::prototype_symbol(),
+          Factory::NewProxy(&Accessors::FunctionPrototype),
+          attributes);
+
+  attributes =
+      static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
+  // Add length.
+  result =
+      Factory::CopyAppendProxyDescriptor(
+          result,
+          Factory::length_symbol(),
+          Factory::NewProxy(&Accessors::FunctionLength),
+          attributes);
+
+  // Add name.
+  result =
+      Factory::CopyAppendProxyDescriptor(
+          result,
+          Factory::name_symbol(),
+          Factory::NewProxy(&Accessors::FunctionName),
+          attributes);
+
+  // Add arguments.
+  result =
+      Factory::CopyAppendProxyDescriptor(
+          result,
+          Factory::arguments_symbol(),
+          Factory::NewProxy(&Accessors::FunctionArguments),
+          attributes);
+
+  // Add caller.
+  result =
+      Factory::CopyAppendProxyDescriptor(
+          result,
+          Factory::caller_symbol(),
+          Factory::NewProxy(&Accessors::FunctionCaller),
+          attributes);
+
+  return result;
+}
+
+
+void Genesis::CreateRoots(v8::Handle<v8::ObjectTemplate> global_template,
+                          Handle<Object> global_object) {
+  HandleScope scope;
+  // Allocate the global context FixedArray first and then patch the
+  // closure and extension object later (we need the empty function
+  // and the global object, but in order to create those, we need the
+  // global context).
+  global_context_ =
+      Handle<Context>::cast(
+          GlobalHandles::Create(*Factory::NewGlobalContext()));
+  Top::set_context(*global_context());
+
+  // Allocate the message listeners object.
+  v8::NeanderArray listeners;
+  global_context()->set_message_listeners(*listeners.value());
+
+  // Allocate the map for function instances.
+  Handle<Map> fm = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
+  global_context()->set_function_instance_map(*fm);
+  // Please note that the prototype property for function instances must be
+  // writable.
+  Handle<DescriptorArray> function_map_descriptors =
+      ComputeFunctionInstanceDescriptor(false, true);
+  fm->set_instance_descriptors(*function_map_descriptors);
+
+  // Allocate the function map first and then patch the prototype later
+  fm = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
+  global_context()->set_function_map(*fm);
+  function_map_descriptors = ComputeFunctionInstanceDescriptor(true);
+  fm->set_instance_descriptors(*function_map_descriptors);
+
+  Handle<String> object_name = Handle<String>(Heap::Object_symbol());
+
+  {  // --- O b j e c t ---
+    Handle<JSFunction> object_fun =
+        Factory::NewFunction(object_name, Factory::null_value());
+    Handle<Map> object_function_map =
+        Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
+    object_fun->set_initial_map(*object_function_map);
+    object_function_map->set_constructor(*object_fun);
+
+    global_context()->set_object_function(*object_fun);
+
+    // Allocate a new prototype for the object function.
+    Handle<JSObject> prototype = Factory::NewJSObject(Top::object_function(),
+                                                      TENURED);
+
+    global_context()->set_initial_object_prototype(*prototype);
+    SetPrototype(object_fun, prototype);
+    object_function_map->
+      set_instance_descriptors(Heap::empty_descriptor_array());
+  }
+
+  // Allocate the empty function as the prototype for function ECMAScript
+  // 262 15.3.4.
+  Handle<String> symbol = Factory::LookupAsciiSymbol("Empty");
+  Handle<JSFunction> empty_function =
+      Factory::NewFunction(symbol, Factory::null_value());
+
+  {  // --- E m p t y ---
+    Handle<Code> code =
+        Handle<Code>(Builtins::builtin(Builtins::EmptyFunction));
+    empty_function->set_code(*code);
+    Handle<String> source = Factory::NewStringFromAscii(CStrVector("() {}"));
+    Handle<Script> script = Factory::NewScript(source);
+    script->set_type(Smi::FromInt(SCRIPT_TYPE_NATIVE));
+    empty_function->shared()->set_script(*script);
+    empty_function->shared()->set_start_position(0);
+    empty_function->shared()->set_end_position(source->length());
+    empty_function->shared()->DontAdaptArguments();
+    global_context()->function_map()->set_prototype(*empty_function);
+    global_context()->function_instance_map()->set_prototype(*empty_function);
+
+    // Allocate the function map first and then patch the prototype later
+    Handle<Map> empty_fm = Factory::CopyMap(fm);
+    empty_fm->set_instance_descriptors(*function_map_descriptors);
+    empty_fm->set_prototype(global_context()->object_function()->prototype());
+    empty_function->set_map(*empty_fm);
+  }
+
+  {  // --- G l o b a l ---
+    // Step 1: create a fresh inner JSGlobalObject
+    Handle<JSGlobalObject> object;
+    {
+      Handle<JSFunction> js_global_function;
+      Handle<ObjectTemplateInfo> js_global_template;
+      if (!global_template.IsEmpty()) {
+        // Get prototype template of the global_template
+        Handle<ObjectTemplateInfo> data =
+            v8::Utils::OpenHandle(*global_template);
+        Handle<FunctionTemplateInfo> global_constructor =
+            Handle<FunctionTemplateInfo>(
+                FunctionTemplateInfo::cast(data->constructor()));
+        Handle<Object> proto_template(global_constructor->prototype_template());
+        if (!proto_template->IsUndefined()) {
+          js_global_template =
+              Handle<ObjectTemplateInfo>::cast(proto_template);
+        }
+      }
+
+      if (js_global_template.is_null()) {
+        Handle<String> name = Handle<String>(Heap::empty_symbol());
+        Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
+        js_global_function =
+            Factory::NewFunction(name, JS_GLOBAL_OBJECT_TYPE,
+                                 JSGlobalObject::kSize, code, true);
+        // Change the constructor property of the prototype of the
+        // hidden global function to refer to the Object function.
+        Handle<JSObject> prototype =
+            Handle<JSObject>(
+                JSObject::cast(js_global_function->instance_prototype()));
+        SetProperty(prototype, Factory::constructor_symbol(),
+                    Top::object_function(), NONE);
+      } else {
+        Handle<FunctionTemplateInfo> js_global_constructor(
+            FunctionTemplateInfo::cast(js_global_template->constructor()));
+        js_global_function =
+            Factory::CreateApiFunction(js_global_constructor,
+                                       Factory::InnerGlobalObject);
+      }
+
+      js_global_function->initial_map()->set_is_hidden_prototype();
+      SetExpectedNofProperties(js_global_function, 100);
+      object = Handle<JSGlobalObject>::cast(
+          Factory::NewJSObject(js_global_function, TENURED));
+    }
+
+    // Set the global context for the global object.
+    object->set_global_context(*global_context());
+
+    // Step 2: create or re-initialize the global proxy object.
+    Handle<JSGlobalProxy> global_proxy;
+    {
+      Handle<JSFunction> global_proxy_function;
+      if (global_template.IsEmpty()) {
+        Handle<String> name = Handle<String>(Heap::empty_symbol());
+        Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
+        global_proxy_function =
+            Factory::NewFunction(name, JS_GLOBAL_PROXY_TYPE,
+                                 JSGlobalProxy::kSize, code, true);
+      } else {
+        Handle<ObjectTemplateInfo> data =
+            v8::Utils::OpenHandle(*global_template);
+        Handle<FunctionTemplateInfo> global_constructor(
+                FunctionTemplateInfo::cast(data->constructor()));
+        global_proxy_function =
+            Factory::CreateApiFunction(global_constructor,
+                                       Factory::OuterGlobalObject);
+      }
+
+      Handle<String> global_name = Factory::LookupAsciiSymbol("global");
+      global_proxy_function->shared()->set_instance_class_name(*global_name);
+      global_proxy_function->initial_map()->set_is_access_check_needed(true);
+
+      // Set global_proxy.__proto__ to js_global after ConfigureGlobalObjects
+
+      if (global_object.location() != NULL) {
+        ASSERT(global_object->IsJSGlobalProxy());
+        global_proxy =
+            ReinitializeJSGlobalProxy(
+                global_proxy_function,
+                Handle<JSGlobalProxy>::cast(global_object));
+      } else {
+        global_proxy = Handle<JSGlobalProxy>::cast(
+            Factory::NewJSObject(global_proxy_function, TENURED));
+      }
+
+      // Security setup: Set the security token of the global object to
+      // its the inner global. This makes the security check between two
+      // different contexts fail by default even in case of global
+      // object reinitialization.
+      object->set_global_receiver(*global_proxy);
+      global_proxy->set_context(*global_context());
+    }
+
+    {  // --- G l o b a l   C o n t e x t ---
+      // use the empty function as closure (no scope info)
+      global_context()->set_closure(*empty_function);
+      global_context()->set_fcontext(*global_context());
+      global_context()->set_previous(NULL);
+
+      // set extension and global object
+      global_context()->set_extension(*object);
+      global_context()->set_global(*object);
+      global_context()->set_global_proxy(*global_proxy);
+      // use inner global object as security token by default
+      global_context()->set_security_token(*object);
+    }
+
+    Handle<JSObject> global = Handle<JSObject>(global_context()->global());
+    SetProperty(global, object_name, Top::object_function(), DONT_ENUM);
+  }
+
+  Handle<JSObject> global = Handle<JSObject>(global_context()->global());
+
+  // Install global Function object
+  InstallFunction(global, "Function", JS_FUNCTION_TYPE, JSFunction::kSize,
+                  empty_function, Builtins::Illegal, true);  // ECMA native.
+
+  {  // --- A r r a y ---
+    Handle<JSFunction> array_function =
+        InstallFunction(global, "Array", JS_ARRAY_TYPE, JSArray::kSize,
+                        Top::initial_object_prototype(), Builtins::ArrayCode,
+                        true);
+    array_function->shared()->DontAdaptArguments();
+
+    // This seems a bit hackish, but we need to make sure Array.length
+    // is 1.
+    array_function->shared()->set_length(1);
+    Handle<DescriptorArray> array_descriptors =
+        Factory::CopyAppendProxyDescriptor(
+            Factory::empty_descriptor_array(),
+            Factory::length_symbol(),
+            Factory::NewProxy(&Accessors::ArrayLength),
+            static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE));
+
+    // Cache the fast JavaScript array map
+    global_context()->set_js_array_map(array_function->initial_map());
+    global_context()->js_array_map()->set_instance_descriptors(
+        *array_descriptors);
+    // array_function is used internally. JS code creating array object should
+    // search for the 'Array' property on the global object and use that one
+    // as the constructor. 'Array' property on a global object can be
+    // overwritten by JS code.
+    global_context()->set_array_function(*array_function);
+  }
+
+  {  // --- N u m b e r ---
+    Handle<JSFunction> number_fun =
+        InstallFunction(global, "Number", JS_VALUE_TYPE, JSValue::kSize,
+                        Top::initial_object_prototype(), Builtins::Illegal,
+                        true);
+    global_context()->set_number_function(*number_fun);
+  }
+
+  {  // --- B o o l e a n ---
+    Handle<JSFunction> boolean_fun =
+        InstallFunction(global, "Boolean", JS_VALUE_TYPE, JSValue::kSize,
+                        Top::initial_object_prototype(), Builtins::Illegal,
+                        true);
+    global_context()->set_boolean_function(*boolean_fun);
+  }
+
+  {  // --- S t r i n g ---
+    Handle<JSFunction> string_fun =
+        InstallFunction(global, "String", JS_VALUE_TYPE, JSValue::kSize,
+                        Top::initial_object_prototype(), Builtins::Illegal,
+                        true);
+    global_context()->set_string_function(*string_fun);
+    // Add 'length' property to strings.
+    Handle<DescriptorArray> string_descriptors =
+        Factory::CopyAppendProxyDescriptor(
+            Factory::empty_descriptor_array(),
+            Factory::length_symbol(),
+            Factory::NewProxy(&Accessors::StringLength),
+            static_cast<PropertyAttributes>(DONT_ENUM |
+                                            DONT_DELETE |
+                                            READ_ONLY));
+
+    Handle<Map> string_map =
+        Handle<Map>(global_context()->string_function()->initial_map());
+    string_map->set_instance_descriptors(*string_descriptors);
+  }
+
+  {  // --- D a t e ---
+    // Builtin functions for Date.prototype.
+    Handle<JSFunction> date_fun =
+        InstallFunction(global, "Date", JS_VALUE_TYPE, JSValue::kSize,
+                        Top::initial_object_prototype(), Builtins::Illegal,
+                        true);
+
+    global_context()->set_date_function(*date_fun);
+  }
+
+
+  {  // -- R e g E x p
+    // Builtin functions for RegExp.prototype.
+    Handle<JSFunction> regexp_fun =
+        InstallFunction(global, "RegExp", JS_REGEXP_TYPE, JSRegExp::kSize,
+                        Top::initial_object_prototype(), Builtins::Illegal,
+                        true);
+
+    global_context()->set_regexp_function(*regexp_fun);
+  }
+
+  {  // --- arguments_boilerplate_
+    // Make sure we can recognize argument objects at runtime.
+    // This is done by introducing an anonymous function with
+    // class_name equals 'Arguments'.
+    Handle<String> symbol = Factory::LookupAsciiSymbol("Arguments");
+    Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
+    Handle<JSObject> prototype =
+        Handle<JSObject>(
+            JSObject::cast(global_context()->object_function()->prototype()));
+
+    Handle<JSFunction> function =
+        Factory::NewFunctionWithPrototype(symbol,
+                                          JS_OBJECT_TYPE,
+                                          JSObject::kHeaderSize,
+                                          prototype,
+                                          code,
+                                          false);
+    ASSERT(!function->has_initial_map());
+    function->shared()->set_instance_class_name(*symbol);
+    function->shared()->set_expected_nof_properties(2);
+    Handle<JSObject> result = Factory::NewJSObject(function);
+
+    global_context()->set_arguments_boilerplate(*result);
+    // Note: callee must be added as the first property and
+    //       length must be added as the second property.
+    SetProperty(result, Factory::callee_symbol(),
+                Factory::undefined_value(),
+                DONT_ENUM);
+    SetProperty(result, Factory::length_symbol(),
+                Factory::undefined_value(),
+                DONT_ENUM);
+
+#ifdef DEBUG
+    LookupResult lookup;
+    result->LocalLookup(Heap::callee_symbol(), &lookup);
+    ASSERT(lookup.IsValid() && (lookup.type() == FIELD));
+    ASSERT(lookup.GetFieldIndex() == Heap::arguments_callee_index);
+
+    result->LocalLookup(Heap::length_symbol(), &lookup);
+    ASSERT(lookup.IsValid() && (lookup.type() == FIELD));
+    ASSERT(lookup.GetFieldIndex() == Heap::arguments_length_index);
+
+    ASSERT(result->map()->inobject_properties() > Heap::arguments_callee_index);
+    ASSERT(result->map()->inobject_properties() > Heap::arguments_length_index);
+
+    // Check the state of the object.
+    ASSERT(result->HasFastProperties());
+    ASSERT(result->HasFastElements());
+#endif
+  }
+
+  {  // --- context extension
+    // Create a function for the context extension objects.
+    Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
+    Handle<JSFunction> context_extension_fun =
+        Factory::NewFunction(Factory::empty_symbol(),
+                             JS_CONTEXT_EXTENSION_OBJECT_TYPE,
+                             JSObject::kHeaderSize,
+                             code,
+                             true);
+
+    Handle<String> name = Factory::LookupAsciiSymbol("context_extension");
+    context_extension_fun->shared()->set_instance_class_name(*name);
+    global_context()->set_context_extension_function(*context_extension_fun);
+  }
+
+  // Setup the call-as-function delegate.
+  Handle<Code> code =
+      Handle<Code>(Builtins::builtin(Builtins::HandleApiCallAsFunction));
+  Handle<JSFunction> delegate =
+      Factory::NewFunction(Factory::empty_symbol(), JS_OBJECT_TYPE,
+                           JSObject::kHeaderSize, code, true);
+  global_context()->set_call_as_function_delegate(*delegate);
+  delegate->shared()->DontAdaptArguments();
+
+  global_context()->set_special_function_table(Heap::empty_fixed_array());
+
+  // Initialize the out of memory slot.
+  global_context()->set_out_of_memory(Heap::false_value());
+}
+
+
+bool Genesis::CompileBuiltin(int index) {
+  Vector<const char> name = Natives::GetScriptName(index);
+  Handle<String> source_code = Bootstrapper::NativesSourceLookup(index);
+  return CompileNative(name, source_code);
+}
+
+
+bool Genesis::CompileNative(Vector<const char> name, Handle<String> source) {
+  HandleScope scope;
+  Debugger::set_compiling_natives(true);
+  bool result =
+      CompileScriptCached(name, source, &natives_cache, NULL, true);
+  ASSERT(Top::has_pending_exception() != result);
+  if (!result) Top::clear_pending_exception();
+  Debugger::set_compiling_natives(false);
+  return result;
+}
+
+
+bool Genesis::CompileScriptCached(Vector<const char> name,
+                                  Handle<String> source,
+                                  SourceCodeCache* cache,
+                                  v8::Extension* extension,
+                                  bool use_runtime_context) {
+  HandleScope scope;
+  Handle<JSFunction> boilerplate;
+
+  // If we can't find the function in the cache, we compile a new
+  // function and insert it into the cache.
+  if (!cache->Lookup(name, &boilerplate)) {
+#ifdef DEBUG
+    ASSERT(StringShape(*source).IsAsciiRepresentation());
+#endif
+    Handle<String> script_name = Factory::NewStringFromUtf8(name);
+    boilerplate =
+        Compiler::Compile(source, script_name, 0, 0, extension, NULL);
+    if (boilerplate.is_null()) return false;
+    cache->Add(name, boilerplate);
+  }
+
+  // Setup the function context. Conceptually, we should clone the
+  // function before overwriting the context but since we're in a
+  // single-threaded environment it is not strictly necessary.
+  ASSERT(Top::context()->IsGlobalContext());
+  Handle<Context> context =
+      Handle<Context>(use_runtime_context
+                      ? Top::context()->runtime_context()
+                      : Top::context());
+  Handle<JSFunction> fun =
+      Factory::NewFunctionFromBoilerplate(boilerplate, context);
+
+  // Call function using the either the runtime object or the global
+  // object as the receiver. Provide no parameters.
+  Handle<Object> receiver =
+      Handle<Object>(use_runtime_context
+                     ? Top::context()->builtins()
+                     : Top::context()->global());
+  bool has_pending_exception;
+  Handle<Object> result =
+      Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
+  if (has_pending_exception) return false;
+  return PendingFixups::Process(
+      Handle<JSBuiltinsObject>(Top::context()->builtins()));
+}
+
+
+#define INSTALL_NATIVE(Type, name, var)                                  \
+  Handle<String> var##_name = Factory::LookupAsciiSymbol(name);          \
+  global_context()->set_##var(Type::cast(global_context()->              \
+                                           builtins()->                  \
+                                             GetProperty(*var##_name)));
+
+void Genesis::InstallNativeFunctions() {
+  HandleScope scope;
+  INSTALL_NATIVE(JSFunction, "CreateDate", create_date_fun);
+  INSTALL_NATIVE(JSFunction, "ToNumber", to_number_fun);
+  INSTALL_NATIVE(JSFunction, "ToString", to_string_fun);
+  INSTALL_NATIVE(JSFunction, "ToDetailString", to_detail_string_fun);
+  INSTALL_NATIVE(JSFunction, "ToObject", to_object_fun);
+  INSTALL_NATIVE(JSFunction, "ToInteger", to_integer_fun);
+  INSTALL_NATIVE(JSFunction, "ToUint32", to_uint32_fun);
+  INSTALL_NATIVE(JSFunction, "ToInt32", to_int32_fun);
+  INSTALL_NATIVE(JSFunction, "ToBoolean", to_boolean_fun);
+  INSTALL_NATIVE(JSFunction, "Instantiate", instantiate_fun);
+  INSTALL_NATIVE(JSFunction, "ConfigureTemplateInstance",
+                 configure_instance_fun);
+  INSTALL_NATIVE(JSFunction, "MakeMessage", make_message_fun);
+  INSTALL_NATIVE(JSFunction, "GetStackTraceLine", get_stack_trace_line_fun);
+  INSTALL_NATIVE(JSObject, "functionCache", function_cache);
+}
+
+#undef INSTALL_NATIVE
+
+
+bool Genesis::InstallNatives() {
+  HandleScope scope;
+
+  // Create a function for the builtins object. Allocate space for the
+  // JavaScript builtins, a reference to the builtins object
+  // (itself) and a reference to the global_context directly in the object.
+  Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
+  Handle<JSFunction> builtins_fun =
+      Factory::NewFunction(Factory::empty_symbol(), JS_BUILTINS_OBJECT_TYPE,
+                           JSBuiltinsObject::kSize, code, true);
+
+  Handle<String> name = Factory::LookupAsciiSymbol("builtins");
+  builtins_fun->shared()->set_instance_class_name(*name);
+  SetExpectedNofProperties(builtins_fun, 100);
+
+  // Allocate the builtins object.
+  Handle<JSBuiltinsObject> builtins =
+      Handle<JSBuiltinsObject>::cast(Factory::NewJSObject(builtins_fun,
+                                                          TENURED));
+  builtins->set_builtins(*builtins);
+  builtins->set_global_context(*global_context());
+  builtins->set_global_receiver(*builtins);
+
+  // Setup the 'global' properties of the builtins object. The
+  // 'global' property that refers to the global object is the only
+  // way to get from code running in the builtins context to the
+  // global object.
+  static const PropertyAttributes attributes =
+      static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
+  SetProperty(builtins, Factory::LookupAsciiSymbol("global"),
+              Handle<Object>(global_context()->global()), attributes);
+
+  // Setup the reference from the global object to the builtins object.
+  JSGlobalObject::cast(global_context()->global())->set_builtins(*builtins);
+
+  // Create a bridge function that has context in the global context.
+  Handle<JSFunction> bridge =
+      Factory::NewFunction(Factory::empty_symbol(), Factory::undefined_value());
+  ASSERT(bridge->context() == *Top::global_context());
+
+  // Allocate the builtins context.
+  Handle<Context> context =
+    Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, bridge);
+  context->set_global(*builtins);  // override builtins global object
+
+  global_context()->set_runtime_context(*context);
+
+  {  // -- S c r i p t
+    // Builtin functions for Script.
+    Handle<JSFunction> script_fun =
+        InstallFunction(builtins, "Script", JS_VALUE_TYPE, JSValue::kSize,
+                        Top::initial_object_prototype(), Builtins::Illegal,
+                        false);
+    Handle<JSObject> prototype =
+        Factory::NewJSObject(Top::object_function(), TENURED);
+    SetPrototype(script_fun, prototype);
+    global_context()->set_script_function(*script_fun);
+
+    // Add 'source' and 'data' property to scripts.
+    PropertyAttributes common_attributes =
+        static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
+    Handle<Proxy> proxy_source = Factory::NewProxy(&Accessors::ScriptSource);
+    Handle<DescriptorArray> script_descriptors =
+        Factory::CopyAppendProxyDescriptor(
+            Factory::empty_descriptor_array(),
+            Factory::LookupAsciiSymbol("source"),
+            proxy_source,
+            common_attributes);
+    Handle<Proxy> proxy_name = Factory::NewProxy(&Accessors::ScriptName);
+    script_descriptors =
+        Factory::CopyAppendProxyDescriptor(
+            script_descriptors,
+            Factory::LookupAsciiSymbol("name"),
+            proxy_name,
+            common_attributes);
+    Handle<Proxy> proxy_id = Factory::NewProxy(&Accessors::ScriptId);
+    script_descriptors =
+        Factory::CopyAppendProxyDescriptor(
+            script_descriptors,
+            Factory::LookupAsciiSymbol("id"),
+            proxy_id,
+            common_attributes);
+    Handle<Proxy> proxy_line_offset =
+        Factory::NewProxy(&Accessors::ScriptLineOffset);
+    script_descriptors =
+        Factory::CopyAppendProxyDescriptor(
+            script_descriptors,
+            Factory::LookupAsciiSymbol("line_offset"),
+            proxy_line_offset,
+            common_attributes);
+    Handle<Proxy> proxy_column_offset =
+        Factory::NewProxy(&Accessors::ScriptColumnOffset);
+    script_descriptors =
+        Factory::CopyAppendProxyDescriptor(
+            script_descriptors,
+            Factory::LookupAsciiSymbol("column_offset"),
+            proxy_column_offset,
+            common_attributes);
+    Handle<Proxy> proxy_type = Factory::NewProxy(&Accessors::ScriptType);
+    script_descriptors =
+        Factory::CopyAppendProxyDescriptor(
+            script_descriptors,
+            Factory::LookupAsciiSymbol("type"),
+            proxy_type,
+            common_attributes);
+    Handle<Proxy> proxy_line_ends =
+        Factory::NewProxy(&Accessors::ScriptLineEnds);
+    script_descriptors =
+        Factory::CopyAppendProxyDescriptor(
+            script_descriptors,
+            Factory::LookupAsciiSymbol("line_ends"),
+            proxy_line_ends,
+            common_attributes);
+
+    Handle<Map> script_map = Handle<Map>(script_fun->initial_map());
+    script_map->set_instance_descriptors(*script_descriptors);
+
+    // Allocate the empty script.
+    Handle<Script> script = Factory::NewScript(Factory::empty_string());
+    script->set_type(Smi::FromInt(SCRIPT_TYPE_NATIVE));
+    global_context()->set_empty_script(*script);
+  }
+
+  if (FLAG_natives_file == NULL) {
+    // Without natives file, install default natives.
+    for (int i = Natives::GetDelayCount();
+         i < Natives::GetBuiltinsCount();
+         i++) {
+      if (!CompileBuiltin(i)) return false;
+    }
+
+    // Setup natives with lazy loading.
+    SetupLazy(Handle<JSFunction>(global_context()->date_function()),
+              Natives::GetIndex("date"),
+              Top::global_context(),
+              Handle<Context>(Top::context()->runtime_context()));
+    SetupLazy(Handle<JSFunction>(global_context()->regexp_function()),
+              Natives::GetIndex("regexp"),
+              Top::global_context(),
+              Handle<Context>(Top::context()->runtime_context()));
+
+  } else if (strlen(FLAG_natives_file) != 0) {
+    // Otherwise install natives from natives file if file exists and
+    // compiles.
+    bool exists;
+    Vector<const char> source = ReadFile(FLAG_natives_file, &exists);
+    Handle<String> source_string = Factory::NewStringFromAscii(source);
+    if (source.is_empty()) return false;
+    bool result = CompileNative(CStrVector(FLAG_natives_file), source_string);
+    if (!result) return false;
+
+  } else {
+    // Empty natives file name - do not install any natives.
+    PrintF("Warning: Running without installed natives!\n");
+    return true;
+  }
+
+  InstallNativeFunctions();
+
+  // Install Function.prototype.call and apply.
+  { Handle<String> key = Factory::function_class_symbol();
+    Handle<JSFunction> function =
+        Handle<JSFunction>::cast(GetProperty(Top::global(), key));
+    Handle<JSObject> proto =
+        Handle<JSObject>(JSObject::cast(function->instance_prototype()));
+
+    // Install the call and the apply functions.
+    Handle<JSFunction> call =
+        InstallFunction(proto, "call", JS_OBJECT_TYPE, JSObject::kHeaderSize,
+                        Factory::NewJSObject(Top::object_function(), TENURED),
+                        Builtins::FunctionCall,
+                        false);
+    Handle<JSFunction> apply =
+        InstallFunction(proto, "apply", JS_OBJECT_TYPE, JSObject::kHeaderSize,
+                        Factory::NewJSObject(Top::object_function(), TENURED),
+                        Builtins::FunctionApply,
+                        false);
+
+    // Make sure that Function.prototype.call appears to be compiled.
+    // The code will never be called, but inline caching for call will
+    // only work if it appears to be compiled.
+    call->shared()->DontAdaptArguments();
+    ASSERT(call->is_compiled());
+
+    // Set the expected parameters for apply to 2; required by builtin.
+    apply->shared()->set_formal_parameter_count(2);
+
+    // Set the lengths for the functions to satisfy ECMA-262.
+    call->shared()->set_length(1);
+    apply->shared()->set_length(2);
+  }
+
+  // Make sure that the builtins object has fast properties.
+  // If the ASSERT below fails, please increase the expected number of
+  // properties for the builtins object.
+  ASSERT(builtins->HasFastProperties());
+#ifdef DEBUG
+  builtins->Verify();
+#endif
+  return true;
+}
+
+
+bool Genesis::InstallSpecialObjects() {
+  HandleScope scope;
+  Handle<JSGlobalObject> js_global(
+      JSGlobalObject::cast(global_context()->global()));
+  // Expose the natives in global if a name for it is specified.
+  if (FLAG_expose_natives_as != NULL && strlen(FLAG_expose_natives_as) != 0) {
+    Handle<String> natives_string =
+        Factory::LookupAsciiSymbol(FLAG_expose_natives_as);
+    SetProperty(js_global, natives_string,
+                Handle<JSObject>(js_global->builtins()), DONT_ENUM);
+  }
+
+  // Expose the debug global object in global if a name for it is specified.
+  if (FLAG_expose_debug_as != NULL && strlen(FLAG_expose_debug_as) != 0) {
+    // If loading fails we just bail out without installing the
+    // debugger but without tanking the whole context.
+    if (!Debug::Load())
+      return true;
+    // Set the security token for the debugger context to the same as
+    // the shell global context to allow calling between these (otherwise
+    // exposing debug global object doesn't make much sense).
+    Debug::debug_context()->set_security_token(
+        global_context()->security_token());
+
+    Handle<String> debug_string =
+        Factory::LookupAsciiSymbol(FLAG_expose_debug_as);
+    SetProperty(js_global, debug_string,
+        Handle<Object>(Debug::debug_context()->global_proxy()), DONT_ENUM);
+  }
+
+  return true;
+}
+
+
+bool Genesis::InstallExtensions(v8::ExtensionConfiguration* extensions) {
+  // Clear coloring of extension list
+  v8::RegisteredExtension* current = v8::RegisteredExtension::first_extension();
+  while (current != NULL) {
+    current->set_state(v8::UNVISITED);
+    current = current->next();
+  }
+  // Install auto extensions
+  current = v8::RegisteredExtension::first_extension();
+  while (current != NULL) {
+    if (current->extension()->auto_enable())
+      InstallExtension(current);
+    current = current->next();
+  }
+
+  if (FLAG_expose_gc) InstallExtension("v8/gc");
+
+  if (extensions == NULL) return true;
+  // Install required extensions
+  int count = v8::ImplementationUtilities::GetNameCount(extensions);
+  const char** names = v8::ImplementationUtilities::GetNames(extensions);
+  for (int i = 0; i < count; i++) {
+    if (!InstallExtension(names[i]))
+      return false;
+  }
+
+  return true;
+}
+
+
+// Installs a named extension.  This methods is unoptimized and does
+// not scale well if we want to support a large number of extensions.
+bool Genesis::InstallExtension(const char* name) {
+  v8::RegisteredExtension* current = v8::RegisteredExtension::first_extension();
+  // Loop until we find the relevant extension
+  while (current != NULL) {
+    if (strcmp(name, current->extension()->name()) == 0) break;
+    current = current->next();
+  }
+  // Didn't find the extension; fail.
+  if (current == NULL) {
+    v8::Utils::ReportApiFailure(
+        "v8::Context::New()", "Cannot find required extension");
+    return false;
+  }
+  return InstallExtension(current);
+}
+
+
+bool Genesis::InstallExtension(v8::RegisteredExtension* current) {
+  HandleScope scope;
+
+  if (current->state() == v8::INSTALLED) return true;
+  // The current node has already been visited so there must be a
+  // cycle in the dependency graph; fail.
+  if (current->state() == v8::VISITED) {
+    v8::Utils::ReportApiFailure(
+        "v8::Context::New()", "Circular extension dependency");
+    return false;
+  }
+  ASSERT(current->state() == v8::UNVISITED);
+  current->set_state(v8::VISITED);
+  v8::Extension* extension = current->extension();
+  // Install the extension's dependencies
+  for (int i = 0; i < extension->dependency_count(); i++) {
+    if (!InstallExtension(extension->dependencies()[i])) return false;
+  }
+  Vector<const char> source = CStrVector(extension->source());
+  Handle<String> source_code = Factory::NewStringFromAscii(source);
+  bool result = CompileScriptCached(CStrVector(extension->name()),
+                                    source_code,
+                                    &extensions_cache, extension,
+                                    false);
+  ASSERT(Top::has_pending_exception() != result);
+  if (!result) {
+    Top::clear_pending_exception();
+    v8::Utils::ReportApiFailure(
+        "v8::Context::New()", "Error installing extension");
+  }
+  current->set_state(v8::INSTALLED);
+  return result;
+}
+
+
+bool Genesis::ConfigureGlobalObjects(
+    v8::Handle<v8::ObjectTemplate> global_proxy_template) {
+  Handle<JSObject> global_proxy(
+      JSObject::cast(global_context()->global_proxy()));
+  Handle<JSObject> js_global(JSObject::cast(global_context()->global()));
+
+  if (!global_proxy_template.IsEmpty()) {
+    // Configure the global proxy object.
+    Handle<ObjectTemplateInfo> proxy_data =
+        v8::Utils::OpenHandle(*global_proxy_template);
+    if (!ConfigureApiObject(global_proxy, proxy_data)) return false;
+
+    // Configure the inner global object.
+    Handle<FunctionTemplateInfo> proxy_constructor(
+        FunctionTemplateInfo::cast(proxy_data->constructor()));
+    if (!proxy_constructor->prototype_template()->IsUndefined()) {
+      Handle<ObjectTemplateInfo> inner_data(
+          ObjectTemplateInfo::cast(proxy_constructor->prototype_template()));
+      if (!ConfigureApiObject(js_global, inner_data)) return false;
+    }
+  }
+
+  SetObjectPrototype(global_proxy, js_global);
+  return true;
+}
+
+
+bool Genesis::ConfigureApiObject(Handle<JSObject> object,
+    Handle<ObjectTemplateInfo> object_template) {
+  ASSERT(!object_template.is_null());
+  ASSERT(object->IsInstanceOf(
+      FunctionTemplateInfo::cast(object_template->constructor())));
+
+  bool pending_exception = false;
+  Handle<JSObject> obj =
+      Execution::InstantiateObject(object_template, &pending_exception);
+  if (pending_exception) {
+    ASSERT(Top::has_pending_exception());
+    Top::clear_pending_exception();
+    return false;
+  }
+  TransferObject(obj, object);
+  return true;
+}
+
+
+void Genesis::TransferNamedProperties(Handle<JSObject> from,
+                                      Handle<JSObject> to) {
+  if (from->HasFastProperties()) {
+    Handle<DescriptorArray> descs =
+        Handle<DescriptorArray>(from->map()->instance_descriptors());
+    int offset = 0;
+    while (true) {
+      // Iterating through the descriptors is not gc safe so we have to
+      // store the value in a handle and create a new stream for each entry.
+      DescriptorReader stream(*descs, offset);
+      if (stream.eos()) break;
+      // We have to read out the next offset before we do anything that may
+      // cause a gc, since the DescriptorReader is not gc safe.
+      offset = stream.next_position();
+      PropertyDetails details = stream.GetDetails();
+      switch (details.type()) {
+        case FIELD: {
+          HandleScope inner;
+          Handle<String> key = Handle<String>(stream.GetKey());
+          int index = stream.GetFieldIndex();
+          Handle<Object> value = Handle<Object>(from->FastPropertyAt(index));
+          SetProperty(to, key, value, details.attributes());
+          break;
+        }
+        case CONSTANT_FUNCTION: {
+          HandleScope inner;
+          Handle<String> key = Handle<String>(stream.GetKey());
+          Handle<JSFunction> fun =
+              Handle<JSFunction>(stream.GetConstantFunction());
+          SetProperty(to, key, fun, details.attributes());
+          break;
+        }
+        case CALLBACKS: {
+          LookupResult result;
+          to->LocalLookup(stream.GetKey(), &result);
+          // If the property is already there we skip it
+          if (result.IsValid()) continue;
+          HandleScope inner;
+          Handle<DescriptorArray> inst_descs =
+              Handle<DescriptorArray>(to->map()->instance_descriptors());
+          Handle<String> key = Handle<String>(stream.GetKey());
+          Handle<Object> entry = Handle<Object>(stream.GetCallbacksObject());
+          inst_descs = Factory::CopyAppendProxyDescriptor(inst_descs,
+                                                          key,
+                                                          entry,
+                                                          details.attributes());
+          to->map()->set_instance_descriptors(*inst_descs);
+          break;
+        }
+        case MAP_TRANSITION:
+        case CONSTANT_TRANSITION:
+        case NULL_DESCRIPTOR:
+          // Ignore non-properties.
+          break;
+        case NORMAL:
+          // Do not occur since the from object has fast properties.
+        case INTERCEPTOR:
+          // No element in instance descriptors have interceptor type.
+          UNREACHABLE();
+          break;
+      }
+    }
+  } else {
+    Handle<Dictionary> properties =
+        Handle<Dictionary>(from->property_dictionary());
+    int capacity = properties->Capacity();
+    for (int i = 0; i < capacity; i++) {
+      Object* raw_key(properties->KeyAt(i));
+      if (properties->IsKey(raw_key)) {
+        ASSERT(raw_key->IsString());
+        // If the property is already there we skip it.
+        LookupResult result;
+        to->LocalLookup(String::cast(raw_key), &result);
+        if (result.IsValid()) continue;
+        // Set the property.
+        Handle<String> key = Handle<String>(String::cast(raw_key));
+        Handle<Object> value = Handle<Object>(properties->ValueAt(i));
+        PropertyDetails details = properties->DetailsAt(i);
+        SetProperty(to, key, value, details.attributes());
+      }
+    }
+  }
+}
+
+
+void Genesis::TransferIndexedProperties(Handle<JSObject> from,
+                                        Handle<JSObject> to) {
+  // Cloning the elements array is sufficient.
+  Handle<FixedArray> from_elements =
+      Handle<FixedArray>(FixedArray::cast(from->elements()));
+  Handle<FixedArray> to_elements = Factory::CopyFixedArray(from_elements);
+  to->set_elements(*to_elements);
+}
+
+
+void Genesis::TransferObject(Handle<JSObject> from, Handle<JSObject> to) {
+  HandleScope outer;
+
+  ASSERT(!from->IsJSArray());
+  ASSERT(!to->IsJSArray());
+
+  TransferNamedProperties(from, to);
+  TransferIndexedProperties(from, to);
+
+  // Transfer the prototype (new map is needed).
+  Handle<Map> old_to_map = Handle<Map>(to->map());
+  Handle<Map> new_to_map = Factory::CopyMapDropTransitions(old_to_map);
+  new_to_map->set_prototype(from->map()->prototype());
+  to->set_map(*new_to_map);
+}
+
+
+void Genesis::MakeFunctionInstancePrototypeWritable() {
+  // Make a new function map so all future functions
+  // will have settable and enumerable prototype properties.
+  HandleScope scope;
+
+  Handle<DescriptorArray> function_map_descriptors =
+      ComputeFunctionInstanceDescriptor(false, true);
+  Handle<Map> fm = Factory::CopyMap(Top::function_map());
+  fm->set_instance_descriptors(*function_map_descriptors);
+  Top::context()->global_context()->set_function_map(*fm);
+}
+
+
+void Genesis::AddSpecialFunction(Handle<JSObject> prototype,
+                                 const char* name,
+                                 Handle<Code> code) {
+  Handle<String> key = Factory::LookupAsciiSymbol(name);
+  Handle<Object> value = Handle<Object>(prototype->GetProperty(*key));
+  if (value->IsJSFunction()) {
+    Handle<JSFunction> optimized = Factory::NewFunction(key,
+                                                        JS_OBJECT_TYPE,
+                                                        JSObject::kHeaderSize,
+                                                        code,
+                                                        false);
+    optimized->shared()->DontAdaptArguments();
+    int len = global_context()->special_function_table()->length();
+    Handle<FixedArray> new_array = Factory::NewFixedArray(len + 3);
+    for (int index = 0; index < len; index++) {
+      new_array->set(index,
+                     global_context()->special_function_table()->get(index));
+    }
+    new_array->set(len+0, *prototype);
+    new_array->set(len+1, *value);
+    new_array->set(len+2, *optimized);
+    global_context()->set_special_function_table(*new_array);
+  }
+}
+
+
+void Genesis::BuildSpecialFunctionTable() {
+  HandleScope scope;
+  Handle<JSObject> global = Handle<JSObject>(global_context()->global());
+  // Add special versions for Array.prototype.pop and push.
+  Handle<JSFunction> function =
+      Handle<JSFunction>(
+          JSFunction::cast(global->GetProperty(Heap::Array_symbol())));
+  Handle<JSObject> prototype =
+      Handle<JSObject>(JSObject::cast(function->prototype()));
+  AddSpecialFunction(prototype, "pop",
+                     Handle<Code>(Builtins::builtin(Builtins::ArrayPop)));
+  AddSpecialFunction(prototype, "push",
+                     Handle<Code>(Builtins::builtin(Builtins::ArrayPush)));
+}
+
+
+Genesis::Genesis(Handle<Object> global_object,
+                 v8::Handle<v8::ObjectTemplate> global_template,
+                 v8::ExtensionConfiguration* extensions) {
+  // Link this genesis object into the stacked genesis chain. This
+  // must be done before any early exits because the destructor
+  // will always do unlinking.
+  previous_ = current_;
+  current_  = this;
+  result_ = NULL;
+
+  // If V8 hasn't been and cannot be initialized, just return.
+  if (!V8::HasBeenSetup() && !V8::Initialize(NULL)) return;
+
+  // Before creating the roots we must save the context and restore it
+  // on all function exits.
+  HandleScope scope;
+  SaveContext context;
+
+  CreateRoots(global_template, global_object);
+  if (!InstallNatives()) return;
+
+  MakeFunctionInstancePrototypeWritable();
+  BuildSpecialFunctionTable();
+
+  if (!ConfigureGlobalObjects(global_template)) return;
+
+  if (!InstallExtensions(extensions)) return;
+
+  if (!InstallSpecialObjects()) return;
+
+  result_ = global_context_;
+}
+
+
+// Support for thread preemption.
+
+// Reserve space for statics needing saving and restoring.
+int Bootstrapper::ArchiveSpacePerThread() {
+  return Genesis::ArchiveSpacePerThread();
+}
+
+
+// Archive statics that are thread local.
+char* Bootstrapper::ArchiveState(char* to) {
+  return Genesis::ArchiveState(to);
+}
+
+
+// Restore statics that are thread local.
+char* Bootstrapper::RestoreState(char* from) {
+  return Genesis::RestoreState(from);
+}
+
+
+// Reserve space for statics needing saving and restoring.
+int Genesis::ArchiveSpacePerThread() {
+  return sizeof(current_);
+}
+
+
+// Archive statics that are thread local.
+char* Genesis::ArchiveState(char* to) {
+  *reinterpret_cast<Genesis**>(to) = current_;
+  current_ = NULL;
+  return to + sizeof(current_);
+}
+
+
+// Restore statics that are thread local.
+char* Genesis::RestoreState(char* from) {
+  current_ = *reinterpret_cast<Genesis**>(from);
+  return from + sizeof(current_);
+}
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/bootstrapper.h b/deps/v8/src/bootstrapper.h
new file mode 100644
index 0000000..e2883dc
--- /dev/null
+++ b/deps/v8/src/bootstrapper.h
@@ -0,0 +1,80 @@
+// 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_BOOTSTRAPPER_H_
+#define V8_BOOTSTRAPPER_H_
+
+namespace v8 { namespace internal {
+
+// The Boostrapper is the public interface for creating a JavaScript global
+// context.
+class Bootstrapper : public AllStatic {
+ public:
+  // Requires: Heap::Setup has been called.
+  static void Initialize(bool create_heap_objects);
+  static void TearDown();
+
+  // Creates a JavaScript Global Context with initial object graph.
+  // The returned value is a global handle casted to V8Environment*.
+  static Handle<Context> CreateEnvironment(
+      Handle<Object> global_object,
+      v8::Handle<v8::ObjectTemplate> global_template,
+      v8::ExtensionConfiguration* extensions);
+
+  // Detach the environment from its outer global object.
+  static void DetachGlobal(Handle<Context> env);
+
+  // Traverses the pointers for memory management.
+  static void Iterate(ObjectVisitor* v);
+
+  // Accessors for the native scripts cache. Used in lazy loading.
+  static Handle<String> NativesSourceLookup(int index);
+  static bool NativesCacheLookup(Vector<const char> name,
+                                 Handle<JSFunction>* handle);
+  static void NativesCacheAdd(Vector<const char> name, Handle<JSFunction> fun);
+
+  // Append code that needs fixup at the end of boot strapping.
+  static void AddFixup(Code* code, MacroAssembler* masm);
+
+  // Tells whether bootstrapping is active.
+  static bool IsActive();
+
+  // Encoding/decoding support for fixup flags.
+  class FixupFlagsIsPCRelative: public BitField<bool, 0, 1> {};
+  class FixupFlagsUseCodeObject: public BitField<bool, 1, 1> {};
+  class FixupFlagsArgumentsCount: public BitField<uint32_t, 2, 32-2> {};
+
+  // Support for thread preemption.
+  static int ArchiveSpacePerThread();
+  static char* ArchiveState(char* to);
+  static char* RestoreState(char* from);
+};
+
+}}  // namespace v8::internal
+
+#endif  // V8_BOOTSTRAPPER_H_
diff --git a/deps/v8/src/builtins-arm.cc b/deps/v8/src/builtins-arm.cc
new file mode 100644
index 0000000..2e6f255
--- /dev/null
+++ b/deps/v8/src/builtins-arm.cc
@@ -0,0 +1,658 @@
+// 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.
+
+#include "v8.h"
+
+#include "codegen-inl.h"
+#include "debug.h"
+#include "runtime.h"
+
+namespace v8 { namespace internal {
+
+
+#define __ masm->
+
+
+void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
+  // TODO(1238487): Don't pass the function in a static variable.
+  __ mov(ip, Operand(ExternalReference::builtin_passed_function()));
+  __ str(r1, MemOperand(ip, 0));
+
+  // The actual argument count has already been loaded into register
+  // r0, but JumpToBuiltin expects r0 to contain the number of
+  // arguments including the receiver.
+  __ add(r0, r0, Operand(1));
+  __ JumpToBuiltin(ExternalReference(id));
+}
+
+
+void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r0     : number of arguments
+  //  -- r1     : constructor function
+  //  -- lr     : return address
+  //  -- sp[...]: constructor arguments
+  // -----------------------------------
+
+  // Enter a construct frame.
+  __ EnterConstructFrame();
+
+  // Preserve the two incoming parameters
+  __ mov(r0, Operand(r0, LSL, kSmiTagSize));
+  __ push(r0);  // smi-tagged arguments count
+  __ push(r1);  // constructor function
+
+  // Allocate the new receiver object.
+  __ push(r1);  // argument for Runtime_NewObject
+  __ CallRuntime(Runtime::kNewObject, 1);
+  __ push(r0);  // save the receiver
+
+  // Push the function and the allocated receiver from the stack.
+  // sp[0]: receiver (newly allocated object)
+  // sp[1]: constructor function
+  // sp[2]: number of arguments (smi-tagged)
+  __ ldr(r1, MemOperand(sp, kPointerSize));
+  __ push(r1);  // function
+  __ push(r0);  // receiver
+
+  // Reload the number of arguments from the stack.
+  // r1: constructor function
+  // sp[0]: receiver
+  // sp[1]: constructor function
+  // sp[2]: receiver
+  // sp[3]: constructor function
+  // sp[4]: number of arguments (smi-tagged)
+  __ ldr(r3, MemOperand(sp, 4 * kPointerSize));
+
+  // Setup pointer to last argument.
+  __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
+
+  // Setup number of arguments for function call below
+  __ mov(r0, Operand(r3, LSR, kSmiTagSize));
+
+  // Copy arguments and receiver to the expression stack.
+  // r0: number of arguments
+  // r2: address of last argument (caller sp)
+  // r1: constructor function
+  // r3: number of arguments (smi-tagged)
+  // sp[0]: receiver
+  // sp[1]: constructor function
+  // sp[2]: receiver
+  // sp[3]: constructor function
+  // sp[4]: number of arguments (smi-tagged)
+  Label loop, entry;
+  __ b(&entry);
+  __ bind(&loop);
+  __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1));
+  __ push(ip);
+  __ bind(&entry);
+  __ sub(r3, r3, Operand(2), SetCC);
+  __ b(ge, &loop);
+
+  // Call the function.
+  // r0: number of arguments
+  // r1: constructor function
+  ParameterCount actual(r0);
+  __ InvokeFunction(r1, actual, CALL_FUNCTION);
+
+  // Pop the function from the stack.
+  // sp[0]: constructor function
+  // sp[2]: receiver
+  // sp[3]: constructor function
+  // sp[4]: number of arguments (smi-tagged)
+  __ pop();
+
+  // Restore context from the frame.
+  // r0: result
+  // sp[0]: receiver
+  // sp[1]: constructor function
+  // sp[2]: number of arguments (smi-tagged)
+  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+
+  // If the result is an object (in the ECMA sense), we should get rid
+  // of the receiver and use the result; see ECMA-262 section 13.2.2-7
+  // on page 74.
+  Label use_receiver, exit;
+
+  // If the result is a smi, it is *not* an object in the ECMA sense.
+  // r0: result
+  // sp[0]: receiver (newly allocated object)
+  // sp[1]: constructor function
+  // sp[2]: number of arguments (smi-tagged)
+  __ tst(r0, Operand(kSmiTagMask));
+  __ b(eq, &use_receiver);
+
+  // If the type of the result (stored in its map) is less than
+  // FIRST_JS_OBJECT_TYPE, it is not an object in the ECMA sense.
+  __ ldr(r3, FieldMemOperand(r0, HeapObject::kMapOffset));
+  __ ldrb(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
+  __ cmp(r3, Operand(FIRST_JS_OBJECT_TYPE));
+  __ b(ge, &exit);
+
+  // Throw away the result of the constructor invocation and use the
+  // on-stack receiver as the result.
+  __ bind(&use_receiver);
+  __ ldr(r0, MemOperand(sp));
+
+  // Remove receiver from the stack, remove caller arguments, and
+  // return.
+  __ bind(&exit);
+  // r0: result
+  // sp[0]: receiver (newly allocated object)
+  // sp[1]: constructor function
+  // sp[2]: number of arguments (smi-tagged)
+  __ ldr(r1, MemOperand(sp, 2 * kPointerSize));
+  __ LeaveConstructFrame();
+  __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
+  __ add(sp, sp, Operand(kPointerSize));
+  __ mov(pc, Operand(lr));
+}
+
+
+static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
+                                             bool is_construct) {
+  // Called from Generate_JS_Entry
+  // r0: code entry
+  // r1: function
+  // r2: receiver
+  // r3: argc
+  // r4: argv
+  // r5-r7, cp may be clobbered
+
+  // Clear the context before we push it when entering the JS frame.
+  __ mov(cp, Operand(0));
+
+  // Enter an internal frame.
+  __ EnterInternalFrame();
+
+  // Setup the context from the function argument.
+  __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
+
+  // Push the function and the receiver onto the stack.
+  __ push(r1);
+  __ push(r2);
+
+  // Copy arguments to the stack in a loop.
+  // r1: function
+  // r3: argc
+  // r4: argv, i.e. points to first arg
+  Label loop, entry;
+  __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2));
+  // r2 points past last arg.
+  __ b(&entry);
+  __ bind(&loop);
+  __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex));  // read next parameter
+  __ ldr(r0, MemOperand(r0));  // dereference handle
+  __ push(r0);  // push parameter
+  __ bind(&entry);
+  __ cmp(r4, Operand(r2));
+  __ b(ne, &loop);
+
+  // Initialize all JavaScript callee-saved registers, since they will be seen
+  // by the garbage collector as part of handlers.
+  __ mov(r4, Operand(Factory::undefined_value()));
+  __ mov(r5, Operand(r4));
+  __ mov(r6, Operand(r4));
+  __ mov(r7, Operand(r4));
+  if (kR9Available == 1)
+    __ mov(r9, Operand(r4));
+
+  // Invoke the code and pass argc as r0.
+  __ mov(r0, Operand(r3));
+  if (is_construct) {
+    __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)),
+            RelocInfo::CODE_TARGET);
+  } else {
+    ParameterCount actual(r0);
+    __ InvokeFunction(r1, actual, CALL_FUNCTION);
+  }
+
+  // Exit the JS frame and remove the parameters (except function), and return.
+  // Respect ABI stack constraint.
+  __ LeaveInternalFrame();
+  __ mov(pc, lr);
+
+  // r0: result
+}
+
+
+void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
+  Generate_JSEntryTrampolineHelper(masm, false);
+}
+
+
+void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
+  Generate_JSEntryTrampolineHelper(masm, true);
+}
+
+
+void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
+  // 1. Make sure we have at least one argument.
+  // r0: actual number of argument
+  { Label done;
+    __ tst(r0, Operand(r0));
+    __ b(ne, &done);
+    __ mov(r2, Operand(Factory::undefined_value()));
+    __ push(r2);
+    __ add(r0, r0, Operand(1));
+    __ bind(&done);
+  }
+
+  // 2. Get the function to call from the stack.
+  // r0: actual number of argument
+  { Label done, non_function, function;
+    __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
+    __ tst(r1, Operand(kSmiTagMask));
+    __ b(eq, &non_function);
+    __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+    __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
+    __ cmp(r2, Operand(JS_FUNCTION_TYPE));
+    __ b(eq, &function);
+
+    // Non-function called: Clear the function to force exception.
+    __ bind(&non_function);
+    __ mov(r1, Operand(0));
+    __ b(&done);
+
+    // Change the context eagerly because it will be used below to get the
+    // right global object.
+    __ bind(&function);
+    __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
+
+    __ bind(&done);
+  }
+
+  // 3. Make sure first argument is an object; convert if necessary.
+  // r0: actual number of arguments
+  // r1: function
+  { Label call_to_object, use_global_receiver, patch_receiver, done;
+    __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
+    __ ldr(r2, MemOperand(r2, -kPointerSize));
+
+    // r0: actual number of arguments
+    // r1: function
+    // r2: first argument
+    __ tst(r2, Operand(kSmiTagMask));
+    __ b(eq, &call_to_object);
+
+    __ mov(r3, Operand(Factory::null_value()));
+    __ cmp(r2, r3);
+    __ b(eq, &use_global_receiver);
+    __ mov(r3, Operand(Factory::undefined_value()));
+    __ cmp(r2, r3);
+    __ b(eq, &use_global_receiver);
+
+    __ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
+    __ ldrb(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
+    __ cmp(r3, Operand(FIRST_JS_OBJECT_TYPE));
+    __ b(lt, &call_to_object);
+    __ cmp(r3, Operand(LAST_JS_OBJECT_TYPE));
+    __ b(le, &done);
+
+    __ bind(&call_to_object);
+    __ EnterInternalFrame();
+
+    // Store number of arguments and function across the call into the runtime.
+    __ mov(r0, Operand(r0, LSL, kSmiTagSize));
+    __ push(r0);
+    __ push(r1);
+
+    __ push(r2);
+    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
+    __ mov(r2, r0);
+
+    // Restore number of arguments and function.
+    __ pop(r1);
+    __ pop(r0);
+    __ mov(r0, Operand(r0, ASR, kSmiTagSize));
+
+    __ LeaveInternalFrame();
+    __ b(&patch_receiver);
+
+    // Use the global receiver object from the called function as the receiver.
+    __ bind(&use_global_receiver);
+    const int kGlobalIndex =
+        Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
+    __ ldr(r2, FieldMemOperand(cp, kGlobalIndex));
+    __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
+
+    __ bind(&patch_receiver);
+    __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2));
+    __ str(r2, MemOperand(r3, -kPointerSize));
+
+    __ bind(&done);
+  }
+
+  // 4. Shift stuff one slot down the stack
+  // r0: actual number of arguments (including call() receiver)
+  // r1: function
+  { Label loop;
+    // Calculate the copy start address (destination). Copy end address is sp.
+    __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
+    __ add(r2, r2, Operand(kPointerSize));  // copy receiver too
+
+    __ bind(&loop);
+    __ ldr(ip, MemOperand(r2, -kPointerSize));
+    __ str(ip, MemOperand(r2));
+    __ sub(r2, r2, Operand(kPointerSize));
+    __ cmp(r2, sp);
+    __ b(ne, &loop);
+  }
+
+  // 5. Adjust the actual number of arguments and remove the top element.
+  // r0: actual number of arguments (including call() receiver)
+  // r1: function
+  __ sub(r0, r0, Operand(1));
+  __ add(sp, sp, Operand(kPointerSize));
+
+  // 6. Get the code for the function or the non-function builtin.
+  //    If number of expected arguments matches, then call. Otherwise restart
+  //    the arguments adaptor stub.
+  // r0: actual number of arguments
+  // r1: function
+  { Label invoke;
+    __ tst(r1, r1);
+    __ b(ne, &invoke);
+    __ mov(r2, Operand(0));  // expected arguments is 0 for CALL_NON_FUNCTION
+    __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
+    __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
+                         RelocInfo::CODE_TARGET);
+
+    __ bind(&invoke);
+    __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
+    __ ldr(r2,
+           FieldMemOperand(r3,
+                           SharedFunctionInfo::kFormalParameterCountOffset));
+    __ ldr(r3,
+           MemOperand(r3, SharedFunctionInfo::kCodeOffset - kHeapObjectTag));
+    __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
+    __ cmp(r2, r0);  // Check formal and actual parameter counts.
+    __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
+                         RelocInfo::CODE_TARGET, ne);
+
+    // 7. Jump to the code in r3 without checking arguments.
+    ParameterCount expected(0);
+    __ InvokeCode(r3, expected, expected, JUMP_FUNCTION);
+  }
+}
+
+
+void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
+  const int kIndexOffset    = -5 * kPointerSize;
+  const int kLimitOffset    = -4 * kPointerSize;
+  const int kArgsOffset     =  2 * kPointerSize;
+  const int kRecvOffset     =  3 * kPointerSize;
+  const int kFunctionOffset =  4 * kPointerSize;
+
+  __ EnterInternalFrame();
+
+  __ ldr(r0, MemOperand(fp, kFunctionOffset));  // get the function
+  __ push(r0);
+  __ ldr(r0, MemOperand(fp, kArgsOffset));  // get the args array
+  __ push(r0);
+  __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_JS);
+
+  // Eagerly check for stack-overflow before starting to push the arguments.
+  // r0: number of arguments
+  Label okay;
+  ExternalReference stack_guard_limit_address =
+      ExternalReference::address_of_stack_guard_limit();
+  __ mov(r2, Operand(stack_guard_limit_address));
+  __ ldr(r2, MemOperand(r2));
+  __ sub(r2, sp, r2);
+  __ sub(r2, r2, Operand(3 * kPointerSize));  // limit, index, receiver
+
+  __ cmp(r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
+  __ b(hi, &okay);
+
+  // Out of stack space.
+  __ ldr(r1, MemOperand(fp, kFunctionOffset));
+  __ push(r1);
+  __ push(r0);
+  __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_JS);
+
+  // Push current limit and index.
+  __ bind(&okay);
+  __ push(r0);  // limit
+  __ mov(r1, Operand(0));  // initial index
+  __ push(r1);
+
+  // Change context eagerly to get the right global object if necessary.
+  __ ldr(r0, MemOperand(fp, kFunctionOffset));
+  __ ldr(cp, FieldMemOperand(r0, JSFunction::kContextOffset));
+
+  // Compute the receiver.
+  Label call_to_object, use_global_receiver, push_receiver;
+  __ ldr(r0, MemOperand(fp, kRecvOffset));
+  __ tst(r0, Operand(kSmiTagMask));
+  __ b(eq, &call_to_object);
+  __ mov(r1, Operand(Factory::null_value()));
+  __ cmp(r0, r1);
+  __ b(eq, &use_global_receiver);
+  __ mov(r1, Operand(Factory::undefined_value()));
+  __ cmp(r0, r1);
+  __ b(eq, &use_global_receiver);
+
+  // Check if the receiver is already a JavaScript object.
+  // r0: receiver
+  __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
+  __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
+  __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE));
+  __ b(lt, &call_to_object);
+  __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE));
+  __ b(le, &push_receiver);
+
+  // Convert the receiver to a regular object.
+  // r0: receiver
+  __ bind(&call_to_object);
+  __ push(r0);
+  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
+  __ b(&push_receiver);
+
+  // Use the current global receiver object as the receiver.
+  __ bind(&use_global_receiver);
+  const int kGlobalOffset =
+      Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
+  __ ldr(r0, FieldMemOperand(cp, kGlobalOffset));
+  __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
+
+  // Push the receiver.
+  // r0: receiver
+  __ bind(&push_receiver);
+  __ push(r0);
+
+  // Copy all arguments from the array to the stack.
+  Label entry, loop;
+  __ ldr(r0, MemOperand(fp, kIndexOffset));
+  __ b(&entry);
+
+  // Load the current argument from the arguments array and push it to the
+  // stack.
+  // r0: current argument index
+  __ bind(&loop);
+  __ ldr(r1, MemOperand(fp, kArgsOffset));
+  __ push(r1);
+  __ push(r0);
+
+  // Call the runtime to access the property in the arguments array.
+  __ CallRuntime(Runtime::kGetProperty, 2);
+  __ push(r0);
+
+  // Use inline caching to access the arguments.
+  __ ldr(r0, MemOperand(fp, kIndexOffset));
+  __ add(r0, r0, Operand(1 << kSmiTagSize));
+  __ str(r0, MemOperand(fp, kIndexOffset));
+
+  // Test if the copy loop has finished copying all the elements from the
+  // arguments object.
+  __ bind(&entry);
+  __ ldr(r1, MemOperand(fp, kLimitOffset));
+  __ cmp(r0, r1);
+  __ b(ne, &loop);
+
+  // Invoke the function.
+  ParameterCount actual(r0);
+  __ mov(r0, Operand(r0, ASR, kSmiTagSize));
+  __ ldr(r1, MemOperand(fp, kFunctionOffset));
+  __ InvokeFunction(r1, actual, CALL_FUNCTION);
+
+  // Tear down the internal frame and remove function, receiver and args.
+  __ LeaveInternalFrame();
+  __ add(sp, sp, Operand(3 * kPointerSize));
+  __ mov(pc, lr);
+}
+
+
+static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
+  __ mov(r0, Operand(r0, LSL, kSmiTagSize));
+  __ mov(r4, Operand(ArgumentsAdaptorFrame::SENTINEL));
+  __ stm(db_w, sp, r0.bit() | r1.bit() | r4.bit() | fp.bit() | lr.bit());
+  __ add(fp, sp, Operand(3 * kPointerSize));
+}
+
+
+static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r0 : result being passed through
+  // -----------------------------------
+  // Get the number of arguments passed (as a smi), tear down the frame and
+  // then tear down the parameters.
+  __ ldr(r1, MemOperand(fp, -3 * kPointerSize));
+  __ mov(sp, fp);
+  __ ldm(ia_w, sp, fp.bit() | lr.bit());
+  __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));
+  __ add(sp, sp, Operand(kPointerSize));  // adjust for receiver
+}
+
+
+void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r0 : actual number of arguments
+  //  -- r1 : function (passed through to callee)
+  //  -- r2 : expected number of arguments
+  //  -- r3 : code entry to call
+  // -----------------------------------
+
+  Label invoke, dont_adapt_arguments;
+
+  Label enough, too_few;
+  __ cmp(r0, Operand(r2));
+  __ b(lt, &too_few);
+  __ cmp(r2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
+  __ b(eq, &dont_adapt_arguments);
+
+  {  // Enough parameters: actual >= expected
+    __ bind(&enough);
+    EnterArgumentsAdaptorFrame(masm);
+
+    // Calculate copy start address into r0 and copy end address into r2.
+    // r0: actual number of arguments as a smi
+    // r1: function
+    // r2: expected number of arguments
+    // r3: code entry to call
+    __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
+    // adjust for return address and receiver
+    __ add(r0, r0, Operand(2 * kPointerSize));
+    __ sub(r2, r0, Operand(r2, LSL, kPointerSizeLog2));
+
+    // Copy the arguments (including the receiver) to the new stack frame.
+    // r0: copy start address
+    // r1: function
+    // r2: copy end address
+    // r3: code entry to call
+
+    Label copy;
+    __ bind(&copy);
+    __ ldr(ip, MemOperand(r0, 0));
+    __ push(ip);
+    __ cmp(r0, r2);  // Compare before moving to next argument.
+    __ sub(r0, r0, Operand(kPointerSize));
+    __ b(ne, &copy);
+
+    __ b(&invoke);
+  }
+
+  {  // Too few parameters: Actual < expected
+    __ bind(&too_few);
+    EnterArgumentsAdaptorFrame(masm);
+
+    // Calculate copy start address into r0 and copy end address is fp.
+    // r0: actual number of arguments as a smi
+    // r1: function
+    // r2: expected number of arguments
+    // r3: code entry to call
+    __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
+
+    // Copy the arguments (including the receiver) to the new stack frame.
+    // r0: copy start address
+    // r1: function
+    // r2: expected number of arguments
+    // r3: code entry to call
+    Label copy;
+    __ bind(&copy);
+    // Adjust load for return address and receiver.
+    __ ldr(ip, MemOperand(r0, 2 * kPointerSize));
+    __ push(ip);
+    __ cmp(r0, fp);  // Compare before moving to next argument.
+    __ sub(r0, r0, Operand(kPointerSize));
+    __ b(ne, &copy);
+
+    // Fill the remaining expected arguments with undefined.
+    // r1: function
+    // r2: expected number of arguments
+    // r3: code entry to call
+    __ mov(ip, Operand(Factory::undefined_value()));
+    __ sub(r2, fp, Operand(r2, LSL, kPointerSizeLog2));
+    __ sub(r2, r2, Operand(4 * kPointerSize));  // Adjust for frame.
+
+    Label fill;
+    __ bind(&fill);
+    __ push(ip);
+    __ cmp(sp, r2);
+    __ b(ne, &fill);
+  }
+
+  // Call the entry point.
+  __ bind(&invoke);
+  __ Call(r3);
+
+  // Exit frame and return.
+  LeaveArgumentsAdaptorFrame(masm);
+  __ mov(pc, lr);
+
+
+  // -------------------------------------------
+  // Dont adapt arguments.
+  // -------------------------------------------
+  __ bind(&dont_adapt_arguments);
+  __ mov(pc, r3);
+}
+
+
+#undef __
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/builtins-ia32.cc b/deps/v8/src/builtins-ia32.cc
new file mode 100644
index 0000000..0e9de8c
--- /dev/null
+++ b/deps/v8/src/builtins-ia32.cc
@@ -0,0 +1,756 @@
+// 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.
+
+#include "v8.h"
+
+#include "codegen-inl.h"
+
+namespace v8 { namespace internal {
+
+
+#define __ masm->
+
+
+void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
+  // TODO(1238487): Don't pass the function in a static variable.
+  ExternalReference passed = ExternalReference::builtin_passed_function();
+  __ mov(Operand::StaticVariable(passed), edi);
+
+  // The actual argument count has already been loaded into register
+  // eax, but JumpToBuiltin expects eax to contain the number of
+  // arguments including the receiver.
+  __ inc(eax);
+  __ JumpToBuiltin(ExternalReference(id));
+}
+
+
+void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- eax: number of arguments
+  //  -- edi: constructor function
+  // -----------------------------------
+
+  // Enter a construct frame.
+  __ EnterConstructFrame();
+
+  // Store a smi-tagged arguments count on the stack.
+  __ shl(eax, kSmiTagSize);
+  __ push(eax);
+
+  // Push the function to invoke on the stack.
+  __ push(edi);
+
+  // Try to allocate the object without transitioning into C code. If any of the
+  // preconditions is not met, the code bails out to the runtime call.
+  Label rt_call, allocated;
+  if (FLAG_inline_new) {
+    Label undo_allocation;
+    ExternalReference debug_step_in_fp =
+        ExternalReference::debug_step_in_fp_address();
+    __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0));
+    __ j(not_equal, &rt_call);
+    // Check that function is not a Smi.
+    __ test(edi, Immediate(kSmiTagMask));
+    __ j(zero, &rt_call);
+    // Check that function is a JSFunction
+    __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax);
+    __ j(not_equal, &rt_call);
+
+    // Verified that the constructor is a JSFunction.
+    // Load the initial map and verify that it is in fact a map.
+    // edi: constructor
+    __ mov(eax, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
+    // Will both indicate a NULL and a Smi
+    __ test(eax, Immediate(kSmiTagMask));
+    __ j(zero, &rt_call);
+    // edi: constructor
+    // eax: initial map (if proven valid below)
+    __ CmpObjectType(eax, MAP_TYPE, ebx);
+    __ j(not_equal, &rt_call);
+
+    // Check that the constructor is not constructing a JSFunction (see comments
+    // in Runtime_NewObject in runtime.cc). In which case the initial map's
+    // instance type would be JS_FUNCTION_TYPE.
+    // edi: constructor
+    // eax: initial map
+    __ CmpInstanceType(eax, JS_FUNCTION_TYPE);
+    __ j(equal, &rt_call);
+
+    // Now allocate the JSObject on the heap.
+    // edi: constructor
+    // eax: initial map
+    __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset));
+    __ shl(edi, kPointerSizeLog2);
+    // Make sure that the maximum heap object size will never cause us
+    // problem here, because it is always greater than the maximum
+    // instance size that can be represented in a byte.
+    ASSERT(Heap::MaxHeapObjectSize() >= (1 << kBitsPerByte));
+    ExternalReference new_space_allocation_top =
+        ExternalReference::new_space_allocation_top_address();
+    __ mov(ebx, Operand::StaticVariable(new_space_allocation_top));
+    __ add(edi, Operand(ebx));  // Calculate new top
+    ExternalReference new_space_allocation_limit =
+        ExternalReference::new_space_allocation_limit_address();
+    __ cmp(edi, Operand::StaticVariable(new_space_allocation_limit));
+    __ j(greater_equal, &rt_call);
+    // Allocated the JSObject, now initialize the fields.
+    // eax: initial map
+    // ebx: JSObject
+    // edi: start of next object
+    __ mov(Operand(ebx, JSObject::kMapOffset), eax);
+    __ mov(ecx, Factory::empty_fixed_array());
+    __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx);
+    __ mov(Operand(ebx, JSObject::kElementsOffset), ecx);
+    // Set extra fields in the newly allocated object.
+    // eax: initial map
+    // ebx: JSObject
+    // edi: start of next object
+    { Label loop, entry;
+      __ mov(edx, Factory::undefined_value());
+      __ lea(ecx, Operand(ebx, JSObject::kHeaderSize));
+      __ jmp(&entry);
+      __ bind(&loop);
+      __ mov(Operand(ecx, 0), edx);
+      __ add(Operand(ecx), Immediate(kPointerSize));
+      __ bind(&entry);
+      __ cmp(ecx, Operand(edi));
+      __ j(less, &loop);
+    }
+
+    // Mostly done with the JSObject. Add the heap tag and store the new top, so
+    // that we can continue and jump into the continuation code at any time from
+    // now on. Any failures need to undo the setting of the new top, so that the
+    // heap is in a consistent state and verifiable.
+    // eax: initial map
+    // ebx: JSObject
+    // edi: start of next object
+    __ or_(Operand(ebx), Immediate(kHeapObjectTag));
+    __ mov(Operand::StaticVariable(new_space_allocation_top), edi);
+
+    // Check if a properties array should be setup and allocate one if needed.
+    // Otherwise initialize the properties to the empty_fixed_array as well.
+    // eax: initial map
+    // ebx: JSObject
+    // edi: start of next object
+    __ movzx_b(edx, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset));
+    __ movzx_b(ecx, FieldOperand(eax, Map::kInObjectPropertiesOffset));
+    // Calculate unused properties past the end of the in-object properties.
+    __ sub(edx, Operand(ecx));
+    __ test(edx, Operand(edx));
+    // Done if no extra properties are to be allocated.
+    __ j(zero, &allocated);
+
+    // Scale the number of elements by pointer size and add the header for
+    // FixedArrays to the start of the next object calculation from above.
+    // eax: initial map
+    // ebx: JSObject
+    // edi: start of next object (will be start of FixedArray)
+    // edx: number of elements in properties array
+    ASSERT(Heap::MaxHeapObjectSize() >
+           (FixedArray::kHeaderSize + 255*kPointerSize));
+    __ lea(ecx, Operand(edi, edx, times_4, FixedArray::kHeaderSize));
+    __ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit));
+    __ j(greater_equal, &undo_allocation);
+    __ mov(Operand::StaticVariable(new_space_allocation_top), ecx);
+
+    // Initialize the FixedArray.
+    // ebx: JSObject
+    // edi: FixedArray
+    // edx: number of elements
+    // ecx: start of next object
+    __ mov(eax, Factory::fixed_array_map());
+    __ mov(Operand(edi, JSObject::kMapOffset), eax);  // setup the map
+    __ mov(Operand(edi, Array::kLengthOffset), edx);  // and length
+
+    // Initialize the fields to undefined.
+    // ebx: JSObject
+    // edi: FixedArray
+    // ecx: start of next object
+    { Label loop, entry;
+      __ mov(edx, Factory::undefined_value());
+      __ lea(eax, Operand(edi, FixedArray::kHeaderSize));
+      __ jmp(&entry);
+      __ bind(&loop);
+      __ mov(Operand(eax, 0), edx);
+      __ add(Operand(eax), Immediate(kPointerSize));
+      __ bind(&entry);
+      __ cmp(eax, Operand(ecx));
+      __ j(less, &loop);
+    }
+
+    // Store the initialized FixedArray into the properties field of
+    // the JSObject
+    // ebx: JSObject
+    // edi: FixedArray
+    __ or_(Operand(edi), Immediate(kHeapObjectTag));  // add the heap tag
+    __ mov(FieldOperand(ebx, JSObject::kPropertiesOffset), edi);
+
+
+    // Continue with JSObject being successfully allocated
+    // ebx: JSObject
+    __ jmp(&allocated);
+
+    // Undo the setting of the new top so that the heap is verifiable. For
+    // example, the map's unused properties potentially do not match the
+    // allocated objects unused properties.
+    // ebx: JSObject (previous new top)
+    __ bind(&undo_allocation);
+    __ xor_(Operand(ebx), Immediate(kHeapObjectTag));  // clear the heap tag
+    __ mov(Operand::StaticVariable(new_space_allocation_top), ebx);
+  }
+
+  // Allocate the new receiver object using the runtime call.
+  // edi: function (constructor)
+  __ bind(&rt_call);
+  // Must restore edi (constructor) before calling runtime.
+  __ mov(edi, Operand(esp, 0));
+  __ push(edi);
+  __ CallRuntime(Runtime::kNewObject, 1);
+  __ mov(ebx, Operand(eax));  // store result in ebx
+
+  // New object allocated.
+  // ebx: newly allocated object
+  __ bind(&allocated);
+  // Retrieve the function from the stack.
+  __ pop(edi);
+
+  // Retrieve smi-tagged arguments count from the stack.
+  __ mov(eax, Operand(esp, 0));
+  __ shr(eax, kSmiTagSize);
+
+  // Push the allocated receiver to the stack. We need two copies
+  // because we may have to return the original one and the calling
+  // conventions dictate that the called function pops the receiver.
+  __ push(ebx);
+  __ push(ebx);
+
+  // Setup pointer to last argument.
+  __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset));
+
+  // Copy arguments and receiver to the expression stack.
+  Label loop, entry;
+  __ mov(ecx, Operand(eax));
+  __ jmp(&entry);
+  __ bind(&loop);
+  __ push(Operand(ebx, ecx, times_4, 0));
+  __ bind(&entry);
+  __ dec(ecx);
+  __ j(greater_equal, &loop);
+
+  // Call the function.
+  ParameterCount actual(eax);
+  __ InvokeFunction(edi, actual, CALL_FUNCTION);
+
+  // Restore context from the frame.
+  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+
+  // If the result is an object (in the ECMA sense), we should get rid
+  // of the receiver and use the result; see ECMA-262 section 13.2.2-7
+  // on page 74.
+  Label use_receiver, exit;
+
+  // If the result is a smi, it is *not* an object in the ECMA sense.
+  __ test(eax, Immediate(kSmiTagMask));
+  __ j(zero, &use_receiver, not_taken);
+
+  // If the type of the result (stored in its map) is less than
+  // FIRST_JS_OBJECT_TYPE, it is not an object in the ECMA sense.
+  __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
+  __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
+  __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
+  __ j(greater_equal, &exit, not_taken);
+
+  // Throw away the result of the constructor invocation and use the
+  // on-stack receiver as the result.
+  __ bind(&use_receiver);
+  __ mov(eax, Operand(esp, 0));
+
+  // Restore the arguments count and leave the construct frame.
+  __ bind(&exit);
+  __ mov(ebx, Operand(esp, kPointerSize));  // get arguments count
+  __ LeaveConstructFrame();
+
+  // Remove caller arguments from the stack and return.
+  ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
+  __ pop(ecx);
+  __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize));  // 1 ~ receiver
+  __ push(ecx);
+  __ ret(0);
+}
+
+
+static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
+                                             bool is_construct) {
+  // Clear the context before we push it when entering the JS frame.
+  __ xor_(esi, Operand(esi));  // clear esi
+
+  // Enter an internal frame.
+  __ EnterInternalFrame();
+
+  // Load the previous frame pointer (ebx) to access C arguments
+  __ mov(ebx, Operand(ebp, 0));
+
+  // Get the function from the frame and setup the context.
+  __ mov(ecx, Operand(ebx, EntryFrameConstants::kFunctionArgOffset));
+  __ mov(esi, FieldOperand(ecx, JSFunction::kContextOffset));
+
+  // Push the function and the receiver onto the stack.
+  __ push(ecx);
+  __ push(Operand(ebx, EntryFrameConstants::kReceiverArgOffset));
+
+  // Load the number of arguments and setup pointer to the arguments.
+  __ mov(eax, Operand(ebx, EntryFrameConstants::kArgcOffset));
+  __ mov(ebx, Operand(ebx, EntryFrameConstants::kArgvOffset));
+
+  // Copy arguments to the stack in a loop.
+  Label loop, entry;
+  __ xor_(ecx, Operand(ecx));  // clear ecx
+  __ jmp(&entry);
+  __ bind(&loop);
+  __ mov(edx, Operand(ebx, ecx, times_4, 0));  // push parameter from argv
+  __ push(Operand(edx, 0));  // dereference handle
+  __ inc(Operand(ecx));
+  __ bind(&entry);
+  __ cmp(ecx, Operand(eax));
+  __ j(not_equal, &loop);
+
+  // Get the function from the stack and call it.
+  __ mov(edi, Operand(esp, eax, times_4, +1 * kPointerSize));  // +1 ~ receiver
+
+  // Invoke the code.
+  if (is_construct) {
+    __ call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)),
+            RelocInfo::CODE_TARGET);
+  } else {
+    ParameterCount actual(eax);
+    __ InvokeFunction(edi, actual, CALL_FUNCTION);
+  }
+
+  // Exit the JS frame. Notice that this also removes the empty
+  // context and the function left on the stack by the code
+  // invocation.
+  __ LeaveInternalFrame();
+  __ ret(1 * kPointerSize);  // remove receiver
+}
+
+
+void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
+  Generate_JSEntryTrampolineHelper(masm, false);
+}
+
+
+void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
+  Generate_JSEntryTrampolineHelper(masm, true);
+}
+
+
+void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
+  // 1. Make sure we have at least one argument.
+  { Label done;
+    __ test(eax, Operand(eax));
+    __ j(not_zero, &done, taken);
+    __ pop(ebx);
+    __ push(Immediate(Factory::undefined_value()));
+    __ push(ebx);
+    __ inc(eax);
+    __ bind(&done);
+  }
+
+  // 2. Get the function to call from the stack.
+  { Label done, non_function, function;
+    // +1 ~ return address.
+    __ mov(edi, Operand(esp, eax, times_4, +1 * kPointerSize));
+    __ test(edi, Immediate(kSmiTagMask));
+    __ j(zero, &non_function, not_taken);
+    __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
+    __ j(equal, &function, taken);
+
+    // Non-function called: Clear the function to force exception.
+    __ bind(&non_function);
+    __ xor_(edi, Operand(edi));
+    __ jmp(&done);
+
+    // Function called: Change context eagerly to get the right global object.
+    __ bind(&function);
+    __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
+
+    __ bind(&done);
+  }
+
+  // 3. Make sure first argument is an object; convert if necessary.
+  { Label call_to_object, use_global_receiver, patch_receiver, done;
+    __ mov(ebx, Operand(esp, eax, times_4, 0));
+
+    __ test(ebx, Immediate(kSmiTagMask));
+    __ j(zero, &call_to_object);
+
+    __ cmp(ebx, Factory::null_value());
+    __ j(equal, &use_global_receiver);
+    __ cmp(ebx, Factory::undefined_value());
+    __ j(equal, &use_global_receiver);
+
+    __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset));
+    __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
+    __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
+    __ j(less, &call_to_object);
+    __ cmp(ecx, LAST_JS_OBJECT_TYPE);
+    __ j(less_equal, &done);
+
+    __ bind(&call_to_object);
+    __ EnterInternalFrame();  // preserves eax, ebx, edi
+
+    // Store the arguments count on the stack (smi tagged).
+    ASSERT(kSmiTag == 0);
+    __ shl(eax, kSmiTagSize);
+    __ push(eax);
+
+    __ push(edi);  // save edi across the call
+    __ push(ebx);
+    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+    __ mov(ebx, eax);
+    __ pop(edi);  // restore edi after the call
+
+    // Get the arguments count and untag it.
+    __ pop(eax);
+    __ shr(eax, kSmiTagSize);
+
+    __ LeaveInternalFrame();
+    __ jmp(&patch_receiver);
+
+    // Use the global receiver object from the called function as the receiver.
+    __ bind(&use_global_receiver);
+    const int kGlobalIndex =
+        Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
+    __ mov(ebx, FieldOperand(esi, kGlobalIndex));
+    __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
+
+    __ bind(&patch_receiver);
+    __ mov(Operand(esp, eax, times_4, 0), ebx);
+
+    __ bind(&done);
+  }
+
+  // 4. Shift stuff one slot down the stack.
+  { Label loop;
+    __ lea(ecx, Operand(eax, +1));  // +1 ~ copy receiver too
+    __ bind(&loop);
+    __ mov(ebx, Operand(esp, ecx, times_4, 0));
+    __ mov(Operand(esp, ecx, times_4, kPointerSize), ebx);
+    __ dec(ecx);
+    __ j(not_zero, &loop);
+  }
+
+  // 5. Remove TOS (copy of last arguments), but keep return address.
+  __ pop(ebx);
+  __ pop(ecx);
+  __ push(ebx);
+  __ dec(eax);
+
+  // 6. Check that function really was a function and get the code to
+  //    call from the function and check that the number of expected
+  //    arguments matches what we're providing.
+  { Label invoke;
+    __ test(edi, Operand(edi));
+    __ j(not_zero, &invoke, taken);
+    __ xor_(ebx, Operand(ebx));
+    __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
+    __ jmp(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
+           RelocInfo::CODE_TARGET);
+
+    __ bind(&invoke);
+    __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
+    __ mov(ebx,
+           FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
+    __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset));
+    __ lea(edx, FieldOperand(edx, Code::kHeaderSize));
+    __ cmp(eax, Operand(ebx));
+    __ j(not_equal, Handle<Code>(builtin(ArgumentsAdaptorTrampoline)));
+  }
+
+  // 7. Jump (tail-call) to the code in register edx without checking arguments.
+  ParameterCount expected(0);
+  __ InvokeCode(Operand(edx), expected, expected, JUMP_FUNCTION);
+}
+
+
+void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
+  __ EnterInternalFrame();
+
+  __ push(Operand(ebp, 4 * kPointerSize));  // push this
+  __ push(Operand(ebp, 2 * kPointerSize));  // push arguments
+  __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
+
+  if (FLAG_check_stack) {
+    // We need to catch preemptions right here, otherwise an unlucky preemption
+    // could show up as a failed apply.
+    ExternalReference stack_guard_limit =
+        ExternalReference::address_of_stack_guard_limit();
+    Label retry_preemption;
+    Label no_preemption;
+    __ bind(&retry_preemption);
+    __ mov(edi, Operand::StaticVariable(stack_guard_limit));
+    __ cmp(esp, Operand(edi));
+    __ j(above, &no_preemption, taken);
+
+    // Preemption!
+    // Because builtins always remove the receiver from the stack, we
+    // have to fake one to avoid underflowing the stack.
+    __ push(eax);
+    __ push(Immediate(Smi::FromInt(0)));
+
+    // Do call to runtime routine.
+    __ CallRuntime(Runtime::kStackGuard, 1);
+    __ pop(eax);
+    __ jmp(&retry_preemption);
+
+    __ bind(&no_preemption);
+
+    Label okay;
+    // Make ecx the space we have left.
+    __ mov(ecx, Operand(esp));
+    __ sub(ecx, Operand(edi));
+    // Make edx the space we need for the array when it is unrolled onto the
+    // stack.
+    __ mov(edx, Operand(eax));
+    __ shl(edx, kPointerSizeLog2 - kSmiTagSize);
+    __ cmp(ecx, Operand(edx));
+    __ j(greater, &okay, taken);
+
+    // Too bad: Out of stack space.
+    __ push(Operand(ebp, 4 * kPointerSize));  // push this
+    __ push(eax);
+    __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
+    __ bind(&okay);
+  }
+
+  // Push current index and limit.
+  const int kLimitOffset =
+      StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
+  const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
+  __ push(eax);  // limit
+  __ push(Immediate(0));  // index
+
+  // Change context eagerly to get the right global object if
+  // necessary.
+  __ mov(edi, Operand(ebp, 4 * kPointerSize));
+  __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
+
+  // Compute the receiver.
+  Label call_to_object, use_global_receiver, push_receiver;
+  __ mov(ebx, Operand(ebp, 3 * kPointerSize));
+  __ test(ebx, Immediate(kSmiTagMask));
+  __ j(zero, &call_to_object);
+  __ cmp(ebx, Factory::null_value());
+  __ j(equal, &use_global_receiver);
+  __ cmp(ebx, Factory::undefined_value());
+  __ j(equal, &use_global_receiver);
+
+  // If given receiver is already a JavaScript object then there's no
+  // reason for converting it.
+  __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset));
+  __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
+  __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
+  __ j(less, &call_to_object);
+  __ cmp(ecx, LAST_JS_OBJECT_TYPE);
+  __ j(less_equal, &push_receiver);
+
+  // Convert the receiver to an object.
+  __ bind(&call_to_object);
+  __ push(ebx);
+  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+  __ mov(ebx, Operand(eax));
+  __ jmp(&push_receiver);
+
+  // Use the current global receiver object as the receiver.
+  __ bind(&use_global_receiver);
+  const int kGlobalOffset =
+      Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
+  __ mov(ebx, FieldOperand(esi, kGlobalOffset));
+  __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
+
+  // Push the receiver.
+  __ bind(&push_receiver);
+  __ push(ebx);
+
+  // Copy all arguments from the array to the stack.
+  Label entry, loop;
+  __ mov(eax, Operand(ebp, kIndexOffset));
+  __ jmp(&entry);
+  __ bind(&loop);
+  __ mov(ecx, Operand(ebp, 2 * kPointerSize));  // load arguments
+  __ push(ecx);
+  __ push(eax);
+
+  // Use inline caching to speed up access to arguments.
+  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+  __ call(ic, RelocInfo::CODE_TARGET);
+  // It is important that we do not have a test instruction after the
+  // call.  A test instruction after the call is used to indicate that
+  // we have generated an inline version of the keyed load.  In this
+  // case, we know that we are not generating a test instruction next.
+
+  // Remove IC arguments from the stack and push the nth argument.
+  __ add(Operand(esp), Immediate(2 * kPointerSize));
+  __ push(eax);
+
+  // Update the index on the stack and in register eax.
+  __ mov(eax, Operand(ebp, kIndexOffset));
+  __ add(Operand(eax), Immediate(1 << kSmiTagSize));
+  __ mov(Operand(ebp, kIndexOffset), eax);
+
+  __ bind(&entry);
+  __ cmp(eax, Operand(ebp, kLimitOffset));
+  __ j(not_equal, &loop);
+
+  // Invoke the function.
+  ParameterCount actual(eax);
+  __ shr(eax, kSmiTagSize);
+  __ mov(edi, Operand(ebp, 4 * kPointerSize));
+  __ InvokeFunction(edi, actual, CALL_FUNCTION);
+
+  __ LeaveInternalFrame();
+  __ ret(3 * kPointerSize);  // remove this, receiver, and arguments
+}
+
+
+static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
+  __ push(ebp);
+  __ mov(ebp, Operand(esp));
+
+  // Store the arguments adaptor context sentinel.
+  __ push(Immediate(ArgumentsAdaptorFrame::SENTINEL));
+
+  // Push the function on the stack.
+  __ push(edi);
+
+  // Preserve the number of arguments on the stack. Must preserve both
+  // eax and ebx because these registers are used when copying the
+  // arguments and the receiver.
+  ASSERT(kSmiTagSize == 1);
+  __ lea(ecx, Operand(eax, eax, times_1, kSmiTag));
+  __ push(ecx);
+}
+
+
+static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
+  // Retrieve the number of arguments from the stack.
+  __ mov(ebx, Operand(ebp, ArgumentsAdaptorFrameConstants::kLengthOffset));
+
+  // Leave the frame.
+  __ leave();
+
+  // Remove caller arguments from the stack.
+  ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
+  __ pop(ecx);
+  __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize));  // 1 ~ receiver
+  __ push(ecx);
+}
+
+
+void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- eax : actual number of arguments
+  //  -- ebx : expected number of arguments
+  //  -- edx : code entry to call
+  // -----------------------------------
+
+  Label invoke, dont_adapt_arguments;
+  __ IncrementCounter(&Counters::arguments_adaptors, 1);
+
+  Label enough, too_few;
+  __ cmp(eax, Operand(ebx));
+  __ j(less, &too_few);
+  __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel);
+  __ j(equal, &dont_adapt_arguments);
+
+  {  // Enough parameters: Actual >= expected.
+    __ bind(&enough);
+    EnterArgumentsAdaptorFrame(masm);
+
+    // Copy receiver and all expected arguments.
+    const int offset = StandardFrameConstants::kCallerSPOffset;
+    __ lea(eax, Operand(ebp, eax, times_4, offset));
+    __ mov(ecx, -1);  // account for receiver
+
+    Label copy;
+    __ bind(&copy);
+    __ inc(ecx);
+    __ push(Operand(eax, 0));
+    __ sub(Operand(eax), Immediate(kPointerSize));
+    __ cmp(ecx, Operand(ebx));
+    __ j(less, &copy);
+    __ jmp(&invoke);
+  }
+
+  {  // Too few parameters: Actual < expected.
+    __ bind(&too_few);
+    EnterArgumentsAdaptorFrame(masm);
+
+    // Copy receiver and all actual arguments.
+    const int offset = StandardFrameConstants::kCallerSPOffset;
+    __ lea(edi, Operand(ebp, eax, times_4, offset));
+    __ mov(ecx, -1);  // account for receiver
+
+    Label copy;
+    __ bind(&copy);
+    __ inc(ecx);
+    __ push(Operand(edi, 0));
+    __ sub(Operand(edi), Immediate(kPointerSize));
+    __ cmp(ecx, Operand(eax));
+    __ j(less, &copy);
+
+    // Fill remaining expected arguments with undefined values.
+    Label fill;
+    __ bind(&fill);
+    __ inc(ecx);
+    __ push(Immediate(Factory::undefined_value()));
+    __ cmp(ecx, Operand(ebx));
+    __ j(less, &fill);
+
+    // Restore function pointer.
+    __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
+  }
+
+  // Call the entry point.
+  __ bind(&invoke);
+  __ call(Operand(edx));
+
+  // Leave frame and return.
+  LeaveArgumentsAdaptorFrame(masm);
+  __ ret(0);
+
+  // -------------------------------------------
+  // Dont adapt arguments.
+  // -------------------------------------------
+  __ bind(&dont_adapt_arguments);
+  __ jmp(Operand(edx));
+}
+
+
+#undef __
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/builtins.cc b/deps/v8/src/builtins.cc
new file mode 100644
index 0000000..c3935f1
--- /dev/null
+++ b/deps/v8/src/builtins.cc
@@ -0,0 +1,744 @@
+// 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.
+
+#include "v8.h"
+
+#include "api.h"
+#include "bootstrapper.h"
+#include "builtins.h"
+#include "ic-inl.h"
+
+namespace v8 { namespace internal {
+
+// ----------------------------------------------------------------------------
+// Support macros for defining builtins in C.
+// ----------------------------------------------------------------------------
+//
+// A builtin function is defined by writing:
+//
+//   BUILTIN(name) {
+//     ...
+//   }
+//   BUILTIN_END
+//
+// In the body of the builtin function, the variable 'receiver' is visible.
+// The arguments can be accessed through:
+//
+//   BUILTIN_ARG(0): Receiver (also available as 'receiver')
+//   BUILTIN_ARG(1): First argument
+//     ...
+//   BUILTIN_ARG(n): Last argument
+//
+// and they evaluate to undefined values if too few arguments were
+// passed to the builtin function invocation.
+//
+// __argc__ is the number of arguments including the receiver.
+// ----------------------------------------------------------------------------
+
+
+// TODO(1238487): We should consider passing whether or not the
+// builtin was invoked as a constructor as part of the
+// arguments. Maybe we also want to pass the called function?
+#define BUILTIN(name)                                                   \
+  static Object* Builtin_##name(int __argc__, Object** __argv__) {      \
+    Handle<Object> receiver(&__argv__[0]);
+
+
+// Use an inline function to avoid evaluating the index (n) more than
+// once in the BUILTIN_ARG macro.
+static inline Object* __builtin_arg__(int n, int argc, Object** argv) {
+  ASSERT(n >= 0);
+  return (argc > n) ? argv[-n] : Heap::undefined_value();
+}
+
+
+// NOTE: Argument 0 is the receiver. The first 'real' argument is
+// argument 1 - BUILTIN_ARG(1).
+#define BUILTIN_ARG(n) (__builtin_arg__(n, __argc__, __argv__))
+
+
+#define BUILTIN_END                             \
+  return Heap::undefined_value();               \
+}
+
+
+// TODO(1238487): Get rid of this function that determines if the
+// builtin is called as a constructor. This may be a somewhat slow
+// operation due to the stack frame iteration.
+static inline bool CalledAsConstructor() {
+  StackFrameIterator it;
+  ASSERT(it.frame()->is_exit());
+  it.Advance();
+  StackFrame* frame = it.frame();
+  return frame->is_construct();
+}
+
+
+// ----------------------------------------------------------------------------
+
+
+Handle<Code> Builtins::GetCode(JavaScript id, bool* resolved) {
+  Code* code = Builtins::builtin(Builtins::Illegal);
+  *resolved = false;
+
+  if (Top::context() != NULL) {
+    Object* object = Top::builtins()->javascript_builtin(id);
+    if (object->IsJSFunction()) {
+      Handle<JSFunction> function(JSFunction::cast(object));
+      // Make sure the number of parameters match the formal parameter count.
+      ASSERT(function->shared()->formal_parameter_count() ==
+             Builtins::GetArgumentsCount(id));
+      if (function->is_compiled() || CompileLazy(function, CLEAR_EXCEPTION)) {
+        code = function->code();
+        *resolved = true;
+      }
+    }
+  }
+
+  return Handle<Code>(code);
+}
+
+
+BUILTIN(Illegal) {
+  UNREACHABLE();
+}
+BUILTIN_END
+
+
+BUILTIN(EmptyFunction) {
+}
+BUILTIN_END
+
+
+BUILTIN(ArrayCode) {
+  JSArray* array;
+  if (CalledAsConstructor()) {
+    array = JSArray::cast(*receiver);
+  } else {
+    // Allocate the JS Array
+    JSFunction* constructor =
+        Top::context()->global_context()->array_function();
+    Object* obj = Heap::AllocateJSObject(constructor);
+    if (obj->IsFailure()) return obj;
+    array = JSArray::cast(obj);
+  }
+
+  // 'array' now contains the JSArray we should initialize.
+
+  // Optimize the case where there is one argument and the argument is a
+  // small smi.
+  if (__argc__ == 2) {
+    Object* obj = BUILTIN_ARG(1);
+    if (obj->IsSmi()) {
+      int len = Smi::cast(obj)->value();
+      if (len >= 0 && len < JSObject::kInitialMaxFastElementArray) {
+        Object* obj = Heap::AllocateFixedArrayWithHoles(len);
+        if (obj->IsFailure()) return obj;
+        array->SetContent(FixedArray::cast(obj));
+        return array;
+      }
+    }
+    // Take the argument as the length.
+    obj = array->Initialize(0);
+    if (obj->IsFailure()) return obj;
+    if (__argc__ == 2) return array->SetElementsLength(BUILTIN_ARG(1));
+  }
+
+  // Optimize the case where there are no parameters passed.
+  if (__argc__ == 1) return array->Initialize(4);
+
+  // Take the arguments as elements.
+  int number_of_elements = __argc__ - 1;
+  Smi* len = Smi::FromInt(number_of_elements);
+  Object* obj = Heap::AllocateFixedArrayWithHoles(len->value());
+  if (obj->IsFailure()) return obj;
+  FixedArray* elms = FixedArray::cast(obj);
+  WriteBarrierMode mode = elms->GetWriteBarrierMode();
+  // Fill in the content
+  for (int index = 0; index < number_of_elements; index++) {
+    elms->set(index, BUILTIN_ARG(index+1), mode);
+  }
+
+  // Set length and elements on the array.
+  array->set_elements(FixedArray::cast(obj));
+  array->set_length(len, SKIP_WRITE_BARRIER);
+
+  return array;
+}
+BUILTIN_END
+
+
+BUILTIN(ArrayPush) {
+  JSArray* array = JSArray::cast(*receiver);
+  ASSERT(array->HasFastElements());
+
+  // Make sure we have space for the elements.
+  int len = Smi::cast(array->length())->value();
+
+  // Set new length.
+  int new_length = len + __argc__ - 1;
+  FixedArray* elms = FixedArray::cast(array->elements());
+
+  if (new_length <= elms->length()) {
+    // Backing storage has extra space for the provided values.
+    for (int index = 0; index < __argc__ - 1; index++) {
+      elms->set(index + len, BUILTIN_ARG(index+1));
+    }
+  } else {
+    // New backing storage is needed.
+    int capacity = new_length + (new_length >> 1) + 16;
+    Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
+    if (obj->IsFailure()) return obj;
+    FixedArray* new_elms = FixedArray::cast(obj);
+    WriteBarrierMode mode = new_elms->GetWriteBarrierMode();
+    // Fill out the new array with old elements.
+    for (int i = 0; i < len; i++) new_elms->set(i, elms->get(i), mode);
+    // Add the provided values.
+    for (int index = 0; index < __argc__ - 1; index++) {
+      new_elms->set(index + len, BUILTIN_ARG(index+1), mode);
+    }
+    // Set the new backing storage.
+    array->set_elements(new_elms);
+  }
+  // Set the length.
+  array->set_length(Smi::FromInt(new_length), SKIP_WRITE_BARRIER);
+  return array->length();
+}
+BUILTIN_END
+
+
+BUILTIN(ArrayPop) {
+  JSArray* array = JSArray::cast(*receiver);
+  ASSERT(array->HasFastElements());
+  Object* undefined = Heap::undefined_value();
+
+  int len = Smi::cast(array->length())->value();
+  if (len == 0) return undefined;
+
+  // Get top element
+  FixedArray* elms = FixedArray::cast(array->elements());
+  Object* top = elms->get(len - 1);
+
+  // Set the length.
+  array->set_length(Smi::FromInt(len - 1), SKIP_WRITE_BARRIER);
+
+  if (!top->IsTheHole()) {
+    // Delete the top element.
+    elms->set_the_hole(len - 1);
+    return top;
+  }
+
+  // Remember to check the prototype chain.
+  JSFunction* array_function =
+      Top::context()->global_context()->array_function();
+  JSObject* prototype = JSObject::cast(array_function->prototype());
+  top = prototype->GetElement(len - 1);
+
+  return top;
+}
+BUILTIN_END
+
+
+// -----------------------------------------------------------------------------
+//
+
+
+// Returns the holder JSObject if the function can legally be called
+// with this receiver.  Returns Heap::null_value() if the call is
+// illegal.  Any arguments that don't fit the expected type is
+// overwritten with undefined.  Arguments that do fit the expected
+// type is overwritten with the object in the prototype chain that
+// actually has that type.
+static inline Object* TypeCheck(int argc,
+                                Object** argv,
+                                FunctionTemplateInfo* info) {
+  Object* recv = argv[0];
+  Object* sig_obj = info->signature();
+  if (sig_obj->IsUndefined()) return recv;
+  SignatureInfo* sig = SignatureInfo::cast(sig_obj);
+  // If necessary, check the receiver
+  Object* recv_type = sig->receiver();
+
+  Object* holder = recv;
+  if (!recv_type->IsUndefined()) {
+    for (; holder != Heap::null_value(); holder = holder->GetPrototype()) {
+      if (holder->IsInstanceOf(FunctionTemplateInfo::cast(recv_type))) {
+        break;
+      }
+    }
+    if (holder == Heap::null_value()) return holder;
+  }
+  Object* args_obj = sig->args();
+  // If there is no argument signature we're done
+  if (args_obj->IsUndefined()) return holder;
+  FixedArray* args = FixedArray::cast(args_obj);
+  int length = args->length();
+  if (argc <= length) length = argc - 1;
+  for (int i = 0; i < length; i++) {
+    Object* argtype = args->get(i);
+    if (argtype->IsUndefined()) continue;
+    Object** arg = &argv[-1 - i];
+    Object* current = *arg;
+    for (; current != Heap::null_value(); current = current->GetPrototype()) {
+      if (current->IsInstanceOf(FunctionTemplateInfo::cast(argtype))) {
+        *arg = current;
+        break;
+      }
+    }
+    if (current == Heap::null_value()) *arg = Heap::undefined_value();
+  }
+  return holder;
+}
+
+
+BUILTIN(HandleApiCall) {
+  HandleScope scope;
+  bool is_construct = CalledAsConstructor();
+
+  // TODO(1238487): This is not nice. We need to get rid of this
+  // kludgy behavior and start handling API calls in a more direct
+  // way - maybe compile specialized stubs lazily?.
+  Handle<JSFunction> function =
+      Handle<JSFunction>(JSFunction::cast(Builtins::builtin_passed_function));
+
+  if (is_construct) {
+    Handle<FunctionTemplateInfo> desc =
+        Handle<FunctionTemplateInfo>(
+            FunctionTemplateInfo::cast(function->shared()->function_data()));
+    bool pending_exception = false;
+    Factory::ConfigureInstance(desc, Handle<JSObject>::cast(receiver),
+                               &pending_exception);
+    ASSERT(Top::has_pending_exception() == pending_exception);
+    if (pending_exception) return Failure::Exception();
+  }
+
+  FunctionTemplateInfo* fun_data =
+      FunctionTemplateInfo::cast(function->shared()->function_data());
+  Object* raw_holder = TypeCheck(__argc__, __argv__, fun_data);
+
+  if (raw_holder->IsNull()) {
+    // This function cannot be called with the given receiver.  Abort!
+    Handle<Object> obj =
+        Factory::NewTypeError("illegal_invocation", HandleVector(&function, 1));
+    return Top::Throw(*obj);
+  }
+
+  Object* raw_call_data = fun_data->call_code();
+  if (!raw_call_data->IsUndefined()) {
+    CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
+    Object* callback_obj = call_data->callback();
+    v8::InvocationCallback callback =
+        v8::ToCData<v8::InvocationCallback>(callback_obj);
+    Object* data_obj = call_data->data();
+    Object* result;
+
+    v8::Local<v8::Object> self =
+        v8::Utils::ToLocal(Handle<JSObject>::cast(receiver));
+    Handle<Object> data_handle(data_obj);
+    v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle);
+    ASSERT(raw_holder->IsJSObject());
+    v8::Local<v8::Function> callee = v8::Utils::ToLocal(function);
+    Handle<JSObject> holder_handle(JSObject::cast(raw_holder));
+    v8::Local<v8::Object> holder = v8::Utils::ToLocal(holder_handle);
+    LOG(ApiObjectAccess("call", JSObject::cast(*receiver)));
+    v8::Arguments args = v8::ImplementationUtilities::NewArguments(
+        data,
+        holder,
+        callee,
+        is_construct,
+        reinterpret_cast<void**>(__argv__ - 1),
+        __argc__ - 1);
+
+    v8::Handle<v8::Value> value;
+    {
+      // Leaving JavaScript.
+      VMState state(EXTERNAL);
+      value = callback(args);
+    }
+    if (value.IsEmpty()) {
+      result = Heap::undefined_value();
+    } else {
+      result = *reinterpret_cast<Object**>(*value);
+    }
+
+    RETURN_IF_SCHEDULED_EXCEPTION();
+    if (!is_construct || result->IsJSObject()) return result;
+  }
+
+  return *receiver;
+}
+BUILTIN_END
+
+
+// Handle calls to non-function objects created through the API that
+// support calls.
+BUILTIN(HandleApiCallAsFunction) {
+  // Non-functions are never called as constructors.
+  ASSERT(!CalledAsConstructor());
+
+  // Get the object called.
+  JSObject* obj = JSObject::cast(*receiver);
+
+  // Get the invocation callback from the function descriptor that was
+  // used to create the called object.
+  ASSERT(obj->map()->has_instance_call_handler());
+  JSFunction* constructor = JSFunction::cast(obj->map()->constructor());
+  Object* template_info = constructor->shared()->function_data();
+  Object* handler =
+      FunctionTemplateInfo::cast(template_info)->instance_call_handler();
+  ASSERT(!handler->IsUndefined());
+  CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
+  Object* callback_obj = call_data->callback();
+  v8::InvocationCallback callback =
+      v8::ToCData<v8::InvocationCallback>(callback_obj);
+
+  // Get the data for the call and perform the callback.
+  Object* data_obj = call_data->data();
+  Object* result;
+  { HandleScope scope;
+    v8::Local<v8::Object> self =
+        v8::Utils::ToLocal(Handle<JSObject>::cast(receiver));
+    Handle<Object> data_handle(data_obj);
+    v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle);
+    Handle<JSFunction> callee_handle(constructor);
+    v8::Local<v8::Function> callee = v8::Utils::ToLocal(callee_handle);
+    LOG(ApiObjectAccess("call non-function", JSObject::cast(*receiver)));
+    v8::Arguments args = v8::ImplementationUtilities::NewArguments(
+        data,
+        self,
+        callee,
+        false,
+        reinterpret_cast<void**>(__argv__ - 1),
+        __argc__ - 1);
+    v8::Handle<v8::Value> value;
+    {
+      // Leaving JavaScript.
+      VMState state(EXTERNAL);
+      value = callback(args);
+    }
+    if (value.IsEmpty()) {
+      result = Heap::undefined_value();
+    } else {
+      result = *reinterpret_cast<Object**>(*value);
+    }
+  }
+  // Check for exceptions and return result.
+  RETURN_IF_SCHEDULED_EXCEPTION();
+  return result;
+}
+BUILTIN_END
+
+
+// TODO(1238487): This is a nasty hack. We need to improve the way we
+// call builtins considerable to get rid of this and the hairy macros
+// in builtins.cc.
+Object* Builtins::builtin_passed_function;
+
+
+
+static void Generate_LoadIC_ArrayLength(MacroAssembler* masm) {
+  LoadIC::GenerateArrayLength(masm);
+}
+
+
+static void Generate_LoadIC_StringLength(MacroAssembler* masm) {
+  LoadIC::GenerateStringLength(masm);
+}
+
+
+static void Generate_LoadIC_FunctionPrototype(MacroAssembler* masm) {
+  LoadIC::GenerateFunctionPrototype(masm);
+}
+
+
+static void Generate_LoadIC_Initialize(MacroAssembler* masm) {
+  LoadIC::GenerateInitialize(masm);
+}
+
+
+static void Generate_LoadIC_PreMonomorphic(MacroAssembler* masm) {
+  LoadIC::GeneratePreMonomorphic(masm);
+}
+
+
+static void Generate_LoadIC_Miss(MacroAssembler* masm) {
+  LoadIC::GenerateMiss(masm);
+}
+
+
+static void Generate_LoadIC_Megamorphic(MacroAssembler* masm) {
+  LoadIC::GenerateMegamorphic(masm);
+}
+
+
+static void Generate_LoadIC_Normal(MacroAssembler* masm) {
+  LoadIC::GenerateNormal(masm);
+}
+
+
+static void Generate_KeyedLoadIC_Initialize(MacroAssembler* masm) {
+  KeyedLoadIC::GenerateInitialize(masm);
+}
+
+
+static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
+  KeyedLoadIC::GenerateMiss(masm);
+}
+
+
+static void Generate_KeyedLoadIC_Generic(MacroAssembler* masm) {
+  KeyedLoadIC::GenerateGeneric(masm);
+}
+
+
+static void Generate_KeyedLoadIC_PreMonomorphic(MacroAssembler* masm) {
+  KeyedLoadIC::GeneratePreMonomorphic(masm);
+}
+
+
+static void Generate_StoreIC_Initialize(MacroAssembler* masm) {
+  StoreIC::GenerateInitialize(masm);
+}
+
+
+static void Generate_StoreIC_Miss(MacroAssembler* masm) {
+  StoreIC::GenerateMiss(masm);
+}
+
+
+static void Generate_StoreIC_ExtendStorage(MacroAssembler* masm) {
+  StoreIC::GenerateExtendStorage(masm);
+}
+
+static void Generate_StoreIC_Megamorphic(MacroAssembler* masm) {
+  StoreIC::GenerateMegamorphic(masm);
+}
+
+
+static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) {
+  KeyedStoreIC::GenerateGeneric(masm);
+}
+
+
+static void Generate_KeyedStoreIC_ExtendStorage(MacroAssembler* masm) {
+  KeyedStoreIC::GenerateExtendStorage(masm);
+}
+
+
+static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
+  KeyedStoreIC::GenerateMiss(masm);
+}
+
+
+static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
+  KeyedStoreIC::GenerateInitialize(masm);
+}
+
+
+static void Generate_LoadIC_DebugBreak(MacroAssembler* masm) {
+  Debug::GenerateLoadICDebugBreak(masm);
+}
+
+
+static void Generate_StoreIC_DebugBreak(MacroAssembler* masm) {
+  Debug::GenerateStoreICDebugBreak(masm);
+}
+
+
+static void Generate_KeyedLoadIC_DebugBreak(MacroAssembler* masm) {
+  Debug::GenerateKeyedLoadICDebugBreak(masm);
+}
+
+
+static void Generate_KeyedStoreIC_DebugBreak(MacroAssembler* masm) {
+  Debug::GenerateKeyedStoreICDebugBreak(masm);
+}
+
+
+static void Generate_ConstructCall_DebugBreak(MacroAssembler* masm) {
+  Debug::GenerateConstructCallDebugBreak(masm);
+}
+
+
+static void Generate_Return_DebugBreak(MacroAssembler* masm) {
+  Debug::GenerateReturnDebugBreak(masm);
+}
+
+
+static void Generate_Return_DebugBreakEntry(MacroAssembler* masm) {
+  Debug::GenerateReturnDebugBreakEntry(masm);
+}
+
+
+static void Generate_StubNoRegisters_DebugBreak(MacroAssembler* masm) {
+  Debug::GenerateStubNoRegistersDebugBreak(masm);
+}
+
+
+Object* Builtins::builtins_[builtin_count] = { NULL, };
+const char* Builtins::names_[builtin_count] = { NULL, };
+
+#define DEF_ENUM_C(name) FUNCTION_ADDR(Builtin_##name),
+  Address Builtins::c_functions_[cfunction_count] = {
+    BUILTIN_LIST_C(DEF_ENUM_C)
+  };
+#undef DEF_ENUM_C
+
+#define DEF_JS_NAME(name, ignore) #name,
+#define DEF_JS_ARGC(ignore, argc) argc,
+const char* Builtins::javascript_names_[id_count] = {
+  BUILTINS_LIST_JS(DEF_JS_NAME)
+};
+
+int Builtins::javascript_argc_[id_count] = {
+  BUILTINS_LIST_JS(DEF_JS_ARGC)
+};
+#undef DEF_JS_NAME
+#undef DEF_JS_ARGC
+
+static bool is_initialized = false;
+void Builtins::Setup(bool create_heap_objects) {
+  ASSERT(!is_initialized);
+
+  // Create a scope for the handles in the builtins.
+  HandleScope scope;
+
+  struct BuiltinDesc {
+    byte* generator;
+    byte* c_code;
+    const char* s_name;  // name is only used for generating log information.
+    int name;
+    Code::Flags flags;
+  };
+
+#define DEF_FUNCTION_PTR_C(name)         \
+    { FUNCTION_ADDR(Generate_Adaptor),   \
+      FUNCTION_ADDR(Builtin_##name),     \
+      #name,                             \
+      c_##name,                          \
+      Code::ComputeFlags(Code::BUILTIN)  \
+    },
+
+#define DEF_FUNCTION_PTR_A(name, kind, state) \
+    { FUNCTION_ADDR(Generate_##name),         \
+      NULL,                                   \
+      #name,                                  \
+      name,                                   \
+      Code::ComputeFlags(Code::kind, state)   \
+    },
+
+  // Define array of pointers to generators and C builtin functions.
+  static BuiltinDesc functions[] = {
+      BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
+      BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
+      BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
+      // Terminator:
+      { NULL, NULL, NULL, builtin_count, static_cast<Code::Flags>(0) }
+  };
+
+#undef DEF_FUNCTION_PTR_C
+#undef DEF_FUNCTION_PTR_A
+
+  // For now we generate builtin adaptor code into a stack-allocated
+  // buffer, before copying it into individual code objects.
+  byte buffer[4*KB];
+
+  // Traverse the list of builtins and generate an adaptor in a
+  // separate code object for each one.
+  for (int i = 0; i < builtin_count; i++) {
+    if (create_heap_objects) {
+      MacroAssembler masm(buffer, sizeof buffer);
+      // Generate the code/adaptor.
+      typedef void (*Generator)(MacroAssembler*, int);
+      Generator g = FUNCTION_CAST<Generator>(functions[i].generator);
+      // We pass all arguments to the generator, but it may not use all of
+      // them.  This works because the first arguments are on top of the
+      // stack.
+      g(&masm, functions[i].name);
+      // Move the code into the object heap.
+      CodeDesc desc;
+      masm.GetCode(&desc);
+      Code::Flags flags =  functions[i].flags;
+      Object* code;
+      {
+        // During startup it's OK to always allocate and defer GC to later.
+        // This simplifies things because we don't need to retry.
+        AlwaysAllocateScope __scope__;
+        code = Heap::CreateCode(desc, NULL, flags, masm.CodeObject());
+        if (code->IsFailure()) {
+          v8::internal::V8::FatalProcessOutOfMemory("CreateCode");
+        }
+      }
+      // Add any unresolved jumps or calls to the fixup list in the
+      // bootstrapper.
+      Bootstrapper::AddFixup(Code::cast(code), &masm);
+      // Log the event and add the code to the builtins array.
+      LOG(CodeCreateEvent("Builtin", Code::cast(code), functions[i].s_name));
+      builtins_[i] = code;
+#ifdef ENABLE_DISASSEMBLER
+      if (FLAG_print_builtin_code) {
+        PrintF("Builtin: %s\n", functions[i].s_name);
+        Code::cast(code)->Disassemble(functions[i].s_name);
+        PrintF("\n");
+      }
+#endif
+    } else {
+      // Deserializing. The values will be filled in during IterateBuiltins.
+      builtins_[i] = NULL;
+    }
+    names_[i] = functions[i].s_name;
+  }
+
+  // Mark as initialized.
+  is_initialized = true;
+}
+
+
+void Builtins::TearDown() {
+  is_initialized = false;
+}
+
+
+void Builtins::IterateBuiltins(ObjectVisitor* v) {
+  v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count);
+}
+
+
+const char* Builtins::Lookup(byte* pc) {
+  if (is_initialized) {  // may be called during initialization (disassembler!)
+    for (int i = 0; i < builtin_count; i++) {
+      Code* entry = Code::cast(builtins_[i]);
+      if (entry->contains(pc)) {
+        return names_[i];
+      }
+    }
+  }
+  return NULL;
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/builtins.h b/deps/v8/src/builtins.h
new file mode 100644
index 0000000..853c90e
--- /dev/null
+++ b/deps/v8/src/builtins.h
@@ -0,0 +1,217 @@
+// 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_BUILTINS_H_
+#define V8_BUILTINS_H_
+
+namespace v8 { namespace internal {
+
+// Define list of builtins implemented in C.
+#define BUILTIN_LIST_C(V)                          \
+  V(Illegal)                                       \
+                                                   \
+  V(EmptyFunction)                                 \
+                                                   \
+  V(ArrayCode)                                     \
+                                                   \
+  V(ArrayPush)                                     \
+  V(ArrayPop)                                      \
+                                                   \
+  V(HandleApiCall)                                 \
+  V(HandleApiCallAsFunction)
+
+
+// Define list of builtins implemented in assembly.
+#define BUILTIN_LIST_A(V)                                      \
+  V(ArgumentsAdaptorTrampoline, BUILTIN, UNINITIALIZED)        \
+  V(JSConstructCall,            BUILTIN, UNINITIALIZED)        \
+  V(JSEntryTrampoline,          BUILTIN, UNINITIALIZED)        \
+  V(JSConstructEntryTrampoline, BUILTIN, UNINITIALIZED)        \
+                                                               \
+  V(LoadIC_Miss,                BUILTIN, UNINITIALIZED)        \
+  V(KeyedLoadIC_Miss,           BUILTIN, UNINITIALIZED)        \
+  V(StoreIC_Miss,               BUILTIN, UNINITIALIZED)        \
+  V(KeyedStoreIC_Miss,          BUILTIN, UNINITIALIZED)        \
+                                                               \
+  V(StoreIC_ExtendStorage,      BUILTIN, UNINITIALIZED)        \
+  V(KeyedStoreIC_ExtendStorage, BUILTIN, UNINITIALIZED)        \
+                                                               \
+  V(LoadIC_Initialize,          LOAD_IC, UNINITIALIZED)        \
+  V(LoadIC_PreMonomorphic,      LOAD_IC, PREMONOMORPHIC)       \
+  V(LoadIC_Normal,              LOAD_IC, MONOMORPHIC)          \
+  V(LoadIC_ArrayLength,         LOAD_IC, MONOMORPHIC)          \
+  V(LoadIC_StringLength,        LOAD_IC, MONOMORPHIC)          \
+  V(LoadIC_FunctionPrototype,   LOAD_IC, MONOMORPHIC)          \
+  V(LoadIC_Megamorphic,         LOAD_IC, MEGAMORPHIC)          \
+                                                               \
+  V(KeyedLoadIC_Initialize,     KEYED_LOAD_IC, UNINITIALIZED)  \
+  V(KeyedLoadIC_PreMonomorphic, KEYED_LOAD_IC, PREMONOMORPHIC) \
+  V(KeyedLoadIC_Generic,        KEYED_LOAD_IC, MEGAMORPHIC)    \
+                                                               \
+  V(StoreIC_Initialize,         STORE_IC, UNINITIALIZED)       \
+  V(StoreIC_Megamorphic,        STORE_IC, MEGAMORPHIC)         \
+                                                               \
+  V(KeyedStoreIC_Initialize,    KEYED_STORE_IC, UNINITIALIZED) \
+  V(KeyedStoreIC_Generic,       KEYED_STORE_IC, MEGAMORPHIC)   \
+                                                               \
+  /* Uses KeyedLoadIC_Initialize; must be after in list. */    \
+  V(FunctionCall,               BUILTIN, UNINITIALIZED)        \
+  V(FunctionApply,              BUILTIN, UNINITIALIZED)
+
+
+// Define list of builtins used by the debugger implemented in assembly.
+#define BUILTIN_LIST_DEBUG_A(V)                                \
+  V(Return_DebugBreak,          BUILTIN, DEBUG_BREAK)          \
+  V(Return_DebugBreakEntry,     BUILTIN, DEBUG_BREAK)          \
+  V(ConstructCall_DebugBreak,   BUILTIN, DEBUG_BREAK)          \
+  V(StubNoRegisters_DebugBreak, BUILTIN, DEBUG_BREAK)          \
+  V(LoadIC_DebugBreak,          LOAD_IC, DEBUG_BREAK)          \
+  V(KeyedLoadIC_DebugBreak,     KEYED_LOAD_IC, DEBUG_BREAK)    \
+  V(StoreIC_DebugBreak,         STORE_IC, DEBUG_BREAK)         \
+  V(KeyedStoreIC_DebugBreak,    KEYED_STORE_IC, DEBUG_BREAK)
+
+
+// Define list of builtins implemented in JavaScript.
+#define BUILTINS_LIST_JS(V)    \
+  V(EQUALS, 1)                 \
+  V(STRICT_EQUALS, 1)          \
+  V(COMPARE, 2)                \
+  V(ADD, 1)                    \
+  V(SUB, 1)                    \
+  V(MUL, 1)                    \
+  V(DIV, 1)                    \
+  V(MOD, 1)                    \
+  V(BIT_OR, 1)                 \
+  V(BIT_AND, 1)                \
+  V(BIT_XOR, 1)                \
+  V(UNARY_MINUS, 0)            \
+  V(BIT_NOT, 0)                \
+  V(SHL, 1)                    \
+  V(SAR, 1)                    \
+  V(SHR, 1)                    \
+  V(DELETE, 1)                 \
+  V(IN, 1)                     \
+  V(INSTANCE_OF, 1)            \
+  V(GET_KEYS, 0)               \
+  V(FILTER_KEY, 1)             \
+  V(CALL_NON_FUNCTION, 0)      \
+  V(TO_OBJECT, 0)              \
+  V(TO_NUMBER, 0)              \
+  V(TO_STRING, 0)              \
+  V(STRING_ADD_LEFT, 1)        \
+  V(STRING_ADD_RIGHT, 1)       \
+  V(APPLY_PREPARE, 1)          \
+  V(APPLY_OVERFLOW, 1)
+
+
+class ObjectVisitor;
+
+
+class Builtins : public AllStatic {
+ public:
+  // Generate all builtin code objects. Should be called once during
+  // VM initialization.
+  static void Setup(bool create_heap_objects);
+  static void TearDown();
+
+  // Garbage collection support.
+  static void IterateBuiltins(ObjectVisitor* v);
+
+  // Disassembler support.
+  static const char* Lookup(byte* pc);
+
+  enum Name {
+#define DEF_ENUM_C(name) name,
+#define DEF_ENUM_A(name, kind, state) name,
+    BUILTIN_LIST_C(DEF_ENUM_C)
+    BUILTIN_LIST_A(DEF_ENUM_A)
+    BUILTIN_LIST_DEBUG_A(DEF_ENUM_A)
+#undef DEF_ENUM_C
+#undef DEF_ENUM_A
+    builtin_count
+  };
+
+  enum CFunctionId {
+#define DEF_ENUM_C(name) c_##name,
+    BUILTIN_LIST_C(DEF_ENUM_C)
+#undef DEF_ENUM_C
+    cfunction_count
+  };
+
+  enum JavaScript {
+#define DEF_ENUM(name, ignore) name,
+    BUILTINS_LIST_JS(DEF_ENUM)
+#undef DEF_ENUM
+    id_count
+  };
+
+  static Code* builtin(Name name) {
+    // Code::cast cannot be used here since we access builtins
+    // during the marking phase of mark sweep. See IC::Clear.
+    return reinterpret_cast<Code*>(builtins_[name]);
+  }
+
+  static Address builtin_address(Name name) {
+    return reinterpret_cast<Address>(&builtins_[name]);
+  }
+
+  static Address c_function_address(CFunctionId id) {
+    return c_functions_[id];
+  }
+
+  static const char* GetName(JavaScript id) { return javascript_names_[id]; }
+  static int GetArgumentsCount(JavaScript id) { return javascript_argc_[id]; }
+  static Handle<Code> GetCode(JavaScript id, bool* resolved);
+  static int NumberOfJavaScriptBuiltins() { return id_count; }
+
+  static Object* builtin_passed_function;
+
+ private:
+  // The external C++ functions called from the code.
+  static Address c_functions_[cfunction_count];
+
+  // Note: These are always Code objects, but to conform with
+  // IterateBuiltins() above which assumes Object**'s for the callback
+  // function f, we use an Object* array here.
+  static Object* builtins_[builtin_count];
+  static const char* names_[builtin_count];
+  static const char* javascript_names_[id_count];
+  static int javascript_argc_[id_count];
+
+  static void Generate_Adaptor(MacroAssembler* masm, CFunctionId id);
+  static void Generate_JSConstructCall(MacroAssembler* masm);
+  static void Generate_JSEntryTrampoline(MacroAssembler* masm);
+  static void Generate_JSConstructEntryTrampoline(MacroAssembler* masm);
+  static void Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm);
+
+  static void Generate_FunctionCall(MacroAssembler* masm);
+  static void Generate_FunctionApply(MacroAssembler* masm);
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_BUILTINS_H_
diff --git a/deps/v8/src/bytecodes-irregexp.h b/deps/v8/src/bytecodes-irregexp.h
new file mode 100644
index 0000000..94f37a8
--- /dev/null
+++ b/deps/v8/src/bytecodes-irregexp.h
@@ -0,0 +1,103 @@
+// Copyright 2008-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.
+
+
+#ifndef V8_BYTECODES_IRREGEXP_H_
+#define V8_BYTECODES_IRREGEXP_H_
+
+namespace v8 { namespace internal {
+
+
+static const int BYTECODE_MASK = 0xff;
+// The first argument is packed in with the byte code in one word, but so it
+// has 24 bits, but it can be positive and negative so only use 23 bits for
+// positive values.
+static const unsigned int MAX_FIRST_ARG = 0x7fffffu;
+static const int BYTECODE_SHIFT = 8;
+
+#define BYTECODE_ITERATOR(V)                                                   \
+V(BREAK,              0, 4)   /* bc8                                        */ \
+V(PUSH_CP,            1, 4)   /* bc8 pad24                                  */ \
+V(PUSH_BT,            2, 8)   /* bc8 pad24 offset32                         */ \
+V(PUSH_REGISTER,      3, 4)   /* bc8 reg_idx24                              */ \
+V(SET_REGISTER_TO_CP, 4, 8)   /* bc8 reg_idx24 offset32                     */ \
+V(SET_CP_TO_REGISTER, 5, 4)   /* bc8 reg_idx24                              */ \
+V(SET_REGISTER_TO_SP, 6, 4)   /* bc8 reg_idx24                              */ \
+V(SET_SP_TO_REGISTER, 7, 4)   /* bc8 reg_idx24                              */ \
+V(SET_REGISTER,       8, 8)   /* bc8 reg_idx24 value32                      */ \
+V(ADVANCE_REGISTER,   9, 8)   /* bc8 reg_idx24 value32                      */ \
+V(POP_CP,            10, 4)   /* bc8 pad24                                  */ \
+V(POP_BT,            11, 4)   /* bc8 pad24                                  */ \
+V(POP_REGISTER,      12, 4)   /* bc8 reg_idx24                              */ \
+V(FAIL,              13, 4)   /* bc8 pad24                                  */ \
+V(SUCCEED,           14, 4)   /* bc8 pad24                                  */ \
+V(ADVANCE_CP,        15, 4)   /* bc8 offset24                               */ \
+V(GOTO,              16, 8)   /* bc8 pad24 addr32                           */ \
+V(LOAD_CURRENT_CHAR, 17, 8)   /* bc8 offset24 addr32                        */ \
+V(LOAD_CURRENT_CHAR_UNCHECKED, 18, 4) /* bc8 offset24                       */ \
+V(LOAD_2_CURRENT_CHARS, 19, 8) /* bc8 offset24 addr32                       */ \
+V(LOAD_2_CURRENT_CHARS_UNCHECKED, 20, 4) /* bc8 offset24                    */ \
+V(LOAD_4_CURRENT_CHARS, 21, 8) /* bc8 offset24 addr32                       */ \
+V(LOAD_4_CURRENT_CHARS_UNCHECKED, 22, 4) /* bc8 offset24                    */ \
+V(CHECK_4_CHARS,     23, 12)  /* bc8 pad24 uint32 addr32                    */ \
+V(CHECK_CHAR,        24, 8)   /* bc8 pad8 uint16 addr32                     */ \
+V(CHECK_NOT_4_CHARS, 25, 12)  /* bc8 pad24 uint32 addr32                    */ \
+V(CHECK_NOT_CHAR,    26, 8)   /* bc8 pad8 uint16 addr32                     */ \
+V(AND_CHECK_4_CHARS, 27, 16)  /* bc8 pad24 uint32 uint32 addr32             */ \
+V(AND_CHECK_CHAR,    28, 12)  /* bc8 pad8 uint16 uint32 addr32              */ \
+V(AND_CHECK_NOT_4_CHARS, 29, 16) /* bc8 pad24 uint32 uint32 addr32          */ \
+V(AND_CHECK_NOT_CHAR, 30, 12) /* bc8 pad8 uint16 uint32 addr32              */ \
+V(MINUS_AND_CHECK_NOT_CHAR, 31, 12) /* bc8 pad8 uc16 uc16 addr32            */ \
+V(CHECK_LT,          32, 8)   /* bc8 pad8 uc16 addr32                       */ \
+V(CHECK_GT,          33, 8)   /* bc8 pad8 uc16 addr32                       */ \
+V(CHECK_NOT_BACK_REF, 34, 8)  /* bc8 reg_idx24 addr32                       */ \
+V(CHECK_NOT_BACK_REF_NO_CASE, 35, 8) /* bc8 reg_idx24 addr32                */ \
+V(CHECK_NOT_REGS_EQUAL, 36, 12) /* bc8 regidx24 reg_idx32 addr32            */ \
+V(LOOKUP_MAP1,       37, 12)  /* bc8 pad8 start16 bit_map_addr32 addr32     */ \
+V(LOOKUP_MAP2,       38, 96)  /* bc8 pad8 start16 half_nibble_map_addr32*   */ \
+V(LOOKUP_MAP8,       39, 96)  /* bc8 pad8  start16 byte_map addr32*         */ \
+V(LOOKUP_HI_MAP8,    40, 96)  /* bc8 start24 byte_map_addr32 addr32*        */ \
+V(CHECK_REGISTER_LT, 41, 12)  /* bc8 reg_idx24 value32 addr32               */ \
+V(CHECK_REGISTER_GE, 42, 12)  /* bc8 reg_idx24 value32 addr32               */ \
+V(CHECK_REGISTER_EQ_POS, 43, 8) /* bc8 reg_idx24 addr32                     */ \
+V(CHECK_AT_START,    44, 8)   /* bc8 pad24 addr32                           */ \
+V(CHECK_NOT_AT_START, 45, 8)  /* bc8 pad24 addr32                           */ \
+V(CHECK_GREEDY,      46, 8)   /* bc8 pad24 addr32                           */ \
+V(ADVANCE_CP_AND_GOTO, 47, 8) /* bc8 offset24 addr32                        */
+
+#define DECLARE_BYTECODES(name, code, length) \
+  static const int BC_##name = code;
+BYTECODE_ITERATOR(DECLARE_BYTECODES)
+#undef DECLARE_BYTECODES
+
+#define DECLARE_BYTECODE_LENGTH(name, code, length) \
+  static const int BC_##name##_LENGTH = length;
+BYTECODE_ITERATOR(DECLARE_BYTECODE_LENGTH)
+#undef DECLARE_BYTECODE_LENGTH
+} }
+
+#endif  // V8_BYTECODES_IRREGEXP_H_
diff --git a/deps/v8/src/char-predicates-inl.h b/deps/v8/src/char-predicates-inl.h
new file mode 100644
index 0000000..217db9c
--- /dev/null
+++ b/deps/v8/src/char-predicates-inl.h
@@ -0,0 +1,85 @@
+// 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_CHAR_PREDICATES_INL_H_
+#define V8_CHAR_PREDICATES_INL_H_
+
+#include "char-predicates.h"
+
+namespace v8 { namespace internal {
+
+
+inline bool IsCarriageReturn(uc32 c) {
+  return c == 0x000D;
+}
+
+
+inline bool IsLineFeed(uc32 c) {
+  return c == 0x000A;
+}
+
+
+static inline bool IsInRange(int value, int lower_limit, int higher_limit) {
+  ASSERT(lower_limit <= higher_limit);
+  return static_cast<unsigned int>(value - lower_limit) <=
+      static_cast<unsigned int>(higher_limit - lower_limit);
+}
+
+
+inline bool IsDecimalDigit(uc32 c) {
+  // ECMA-262, 3rd, 7.8.3 (p 16)
+  return IsInRange(c, '0', '9');
+}
+
+
+inline bool IsHexDigit(uc32 c) {
+  // ECMA-262, 3rd, 7.6 (p 15)
+  return IsDecimalDigit(c) || IsInRange(c | 0x20, 'a', 'f');
+}
+
+
+inline bool IsRegExpWord(uc16 c) {
+  return IsInRange(c | 0x20, 'a', 'z')
+      || IsDecimalDigit(c)
+      || (c == '_');
+}
+
+
+inline bool IsRegExpNewline(uc16 c) {
+  switch (c) {
+    //   CR           LF           LS           PS
+    case 0x000A: case 0x000D: case 0x2028: case 0x2029:
+      return false;
+    default:
+      return true;
+  }
+}
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_CHAR_PREDICATES_INL_H_
diff --git a/deps/v8/src/char-predicates.h b/deps/v8/src/char-predicates.h
new file mode 100644
index 0000000..63e83b4
--- /dev/null
+++ b/deps/v8/src/char-predicates.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_CHAR_PREDICATES_H_
+#define V8_CHAR_PREDICATES_H_
+
+namespace v8 { namespace internal {
+
+// Unicode character predicates as defined by ECMA-262, 3rd,
+// used for lexical analysis.
+
+inline bool IsCarriageReturn(uc32 c);
+inline bool IsLineFeed(uc32 c);
+inline bool IsDecimalDigit(uc32 c);
+inline bool IsHexDigit(uc32 c);
+inline bool IsRegExpWord(uc32 c);
+inline bool IsRegExpNewline(uc32 c);
+
+struct IdentifierStart {
+  static inline bool Is(uc32 c) {
+    switch (c) {
+      case '$': case '_': case '\\': return true;
+      default: return unibrow::Letter::Is(c);
+    }
+  }
+};
+
+
+struct IdentifierPart {
+  static inline bool Is(uc32 c) {
+    return IdentifierStart::Is(c)
+        || unibrow::Number::Is(c)
+        || unibrow::CombiningMark::Is(c)
+        || unibrow::ConnectorPunctuation::Is(c);
+  }
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_CHAR_PREDICATES_H_
diff --git a/deps/v8/src/checks.cc b/deps/v8/src/checks.cc
new file mode 100644
index 0000000..f8a2f24
--- /dev/null
+++ b/deps/v8/src/checks.cc
@@ -0,0 +1,98 @@
+// 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.
+
+#include <stdarg.h>
+
+#include "v8.h"
+
+#include "platform.h"
+#include "top.h"
+
+static int fatal_error_handler_nesting_depth = 0;
+
+// Contains protection against recursive calls (faults while handling faults).
+extern "C" void V8_Fatal(const char* file, int line, const char* format, ...) {
+  fatal_error_handler_nesting_depth++;
+  // First time we try to print an error message
+  if (fatal_error_handler_nesting_depth < 2) {
+    i::OS::PrintError("\n\n#\n# Fatal error in %s, line %d\n# ", file, line);
+    va_list arguments;
+    va_start(arguments, format);
+    i::OS::VPrintError(format, arguments);
+    va_end(arguments);
+    i::OS::PrintError("\n#\n\n");
+  }
+  // First two times we may try to print a stack dump.
+  if (fatal_error_handler_nesting_depth < 3) {
+    if (i::FLAG_stack_trace_on_abort) {
+      // Call this one twice on double fault
+      i::Top::PrintStack();
+    }
+  }
+  i::OS::Abort();
+}
+
+
+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) {
+  if (!expected->Equals(value)) {
+    v8::String::Utf8Value value_str(value);
+    v8::String::Utf8Value expected_str(expected);
+    V8_Fatal(file, line,
+             "CHECK_EQ(%s, %s) failed\n#   Expected: %s\n#   Found: %s",
+             expected_source, value_source, *expected_str, *value_str);
+  }
+}
+
+
+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) {
+  if (unexpected->Equals(value)) {
+    v8::String::Utf8Value value_str(value);
+    V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n#   Value: %s",
+             unexpected_source, value_source, *value_str);
+  }
+}
+
+
+void API_Fatal(const char* location, const char* format, ...) {
+  i::OS::PrintError("\n#\n# Fatal error in %s\n# ", location);
+  va_list arguments;
+  va_start(arguments, format);
+  i::OS::VPrintError(format, arguments);
+  va_end(arguments);
+  i::OS::PrintError("\n#\n\n");
+  i::OS::Abort();
+}
diff --git a/deps/v8/src/checks.h b/deps/v8/src/checks.h
new file mode 100644
index 0000000..0ff79af
--- /dev/null
+++ b/deps/v8/src/checks.h
@@ -0,0 +1,263 @@
+// 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_CHECKS_H_
+#define V8_CHECKS_H_
+
+#include <string.h>
+
+#include "flags.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.
+#ifdef DEBUG
+#define FATAL(msg)                              \
+  V8_Fatal(__FILE__, __LINE__, "%s", (msg))
+#define UNIMPLEMENTED()                         \
+  V8_Fatal(__FILE__, __LINE__, "unimplemented code")
+#define UNREACHABLE()                           \
+  V8_Fatal(__FILE__, __LINE__, "unreachable code")
+#else
+#define FATAL(msg)                              \
+  V8_Fatal("", 0, "%s", (msg))
+#define UNIMPLEMENTED()                         \
+  V8_Fatal("", 0, "unimplemented code")
+#define UNREACHABLE() ((void) 0)
+#endif
+
+
+// Used by the CHECK macro -- should not be called directly.
+static inline void CheckHelper(const char* file,
+                               int line,
+                               const char* source,
+                               bool condition) {
+  if (!condition)
+    V8_Fatal(file, line, "CHECK(%s) failed", source);
+}
+
+
+// The CHECK macro checks that the given condition is true; if not, it
+// prints a message to stderr and aborts.
+#define CHECK(condition) CheckHelper(__FILE__, __LINE__, #condition, condition)
+
+
+// Helper function used by the CHECK_EQ function when given int
+// arguments.  Should not be called directly.
+static inline void CheckEqualsHelper(const char* file, int line,
+                                     const char* expected_source, int expected,
+                                     const char* value_source, int value) {
+  if (expected != value) {
+    V8_Fatal(file, line,
+             "CHECK_EQ(%s, %s) failed\n#   Expected: %i\n#   Found: %i",
+             expected_source, value_source, expected, value);
+  }
+}
+
+
+// Helper function used by the CHECK_NE function when given int
+// arguments.  Should not be called directly.
+static inline void CheckNonEqualsHelper(const char* file,
+                                        int line,
+                                        const char* unexpected_source,
+                                        int unexpected,
+                                        const char* value_source,
+                                        int value) {
+  if (unexpected == value) {
+    V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n#   Value: %i",
+             unexpected_source, value_source, value);
+  }
+}
+
+
+// Helper function used by the CHECK function when given string
+// arguments.  Should not be called directly.
+static inline void CheckEqualsHelper(const char* file,
+                                     int line,
+                                     const char* expected_source,
+                                     const char* expected,
+                                     const char* value_source,
+                                     const char* value) {
+  if (strcmp(expected, value) != 0) {
+    V8_Fatal(file, line,
+             "CHECK_EQ(%s, %s) failed\n#   Expected: %s\n#   Found: %s",
+             expected_source, value_source, expected, value);
+  }
+}
+
+
+static inline void CheckNonEqualsHelper(const char* file,
+                                        int line,
+                                        const char* expected_source,
+                                        const char* expected,
+                                        const char* value_source,
+                                        const char* value) {
+  if (expected == value ||
+      (expected != NULL && value != NULL && strcmp(expected, value) == 0)) {
+    V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n#   Value: %s",
+             expected_source, value_source, value);
+  }
+}
+
+
+// Helper function used by the CHECK function when given pointer
+// arguments.  Should not be called directly.
+static inline void CheckEqualsHelper(const char* file,
+                                     int line,
+                                     const char* expected_source,
+                                     void* expected,
+                                     const char* value_source,
+                                     void* value) {
+  if (expected != value) {
+    V8_Fatal(file, line,
+             "CHECK_EQ(%s, %s) failed\n#   Expected: %p\n#   Found: %p",
+             expected_source, value_source,
+             expected, value);
+  }
+}
+
+
+static inline void CheckNonEqualsHelper(const char* file,
+                                        int line,
+                                        const char* expected_source,
+                                        void* expected,
+                                        const char* value_source,
+                                        void* value) {
+  if (expected == value) {
+    V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n#   Value: %p",
+             expected_source, value_source, value);
+  }
+}
+
+
+// Helper function used by the CHECK function when given floating
+// point arguments.  Should not be called directly.
+static inline void CheckEqualsHelper(const char* file,
+                                     int line,
+                                     const char* expected_source,
+                                     double expected,
+                                     const char* value_source,
+                                     double value) {
+  // Force values to 64 bit memory to truncate 80 bit precision on IA32.
+  volatile double* exp = new double[1];
+  *exp = expected;
+  volatile double* val = new double[1];
+  *val = value;
+  if (*exp != *val) {
+    V8_Fatal(file, line,
+             "CHECK_EQ(%s, %s) failed\n#   Expected: %f\n#   Found: %f",
+             expected_source, value_source, *exp, *val);
+  }
+  delete[] exp;
+  delete[] val;
+}
+
+
+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)
+
+
+#define CHECK_NE(unexpected, value) CheckNonEqualsHelper(__FILE__, __LINE__, \
+  #unexpected, unexpected, #value, value)
+
+
+#define CHECK_GT(a, b) CHECK((a) > (b))
+#define CHECK_GE(a, b) CHECK((a) >= (b))
+
+
+// This is inspired by the static assertion facility in boost.  This
+// is pretty magical.  If it causes you trouble on a platform you may
+// find a fix in the boost code.
+template <bool> class StaticAssertion;
+template <> class StaticAssertion<true> { };
+// This macro joins two tokens.  If one of the tokens is a macro the
+// helper call causes it to be resolved before joining.
+#define SEMI_STATIC_JOIN(a, b) SEMI_STATIC_JOIN_HELPER(a, b)
+#define SEMI_STATIC_JOIN_HELPER(a, b) a##b
+// Causes an error during compilation of the condition is not
+// statically known to be true.  It is formulated as a typedef so that
+// it can be used wherever a typedef can be used.  Beware that this
+// actually causes each use to introduce a new defined type with a
+// name depending on the source line.
+template <int> class StaticAssertionHelper { };
+#define STATIC_CHECK(test)                                                  \
+  typedef                                                                   \
+    StaticAssertionHelper<sizeof(StaticAssertion<static_cast<bool>(test)>)> \
+    SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__)
+
+
+// The ASSERT macro is equivalent to CHECK except that it only
+// generates code in debug builds.  Ditto STATIC_ASSERT.
+#ifdef DEBUG
+#define ASSERT_RESULT(expr)  CHECK(expr)
+#define ASSERT(condition)    CHECK(condition)
+#define ASSERT_EQ(v1, v2)    CHECK_EQ(v1, v2)
+#define ASSERT_NE(v1, v2)   CHECK_NE(v1, v2)
+#define STATIC_ASSERT(test)  STATIC_CHECK(test)
+#define SLOW_ASSERT(condition) if (FLAG_enable_slow_asserts) CHECK(condition)
+#else
+#define ASSERT_RESULT(expr)     (expr)
+#define ASSERT(condition)      ((void) 0)
+#define ASSERT_EQ(v1, v2)      ((void) 0)
+#define ASSERT_NE(v1, v2)     ((void) 0)
+#define STATIC_ASSERT(test)    ((void) 0)
+#define SLOW_ASSERT(condition) ((void) 0)
+#endif
+
+
+#define ASSERT_TAG_ALIGNED(address) \
+  ASSERT((reinterpret_cast<int>(address) & kHeapObjectTagMask) == 0)
+
+#define ASSERT_SIZE_TAG_ALIGNED(size) ASSERT((size & kHeapObjectTagMask) == 0)
+
+#define ASSERT_NOT_NULL(p)  ASSERT_NE(NULL, p)
+
+#endif  // V8_CHECKS_H_
diff --git a/deps/v8/src/code-stubs.cc b/deps/v8/src/code-stubs.cc
new file mode 100644
index 0000000..06c4dcd
--- /dev/null
+++ b/deps/v8/src/code-stubs.cc
@@ -0,0 +1,142 @@
+// 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.
+
+#include "v8.h"
+
+#include "bootstrapper.h"
+#include "code-stubs.h"
+#include "factory.h"
+#include "macro-assembler.h"
+
+namespace v8 { namespace internal {
+
+Handle<Code> CodeStub::GetCode() {
+  uint32_t key = GetKey();
+  int index = Heap::code_stubs()->FindNumberEntry(key);
+  if (index == -1) {
+    HandleScope scope;
+
+    // Update the static counter each time a new code stub is generated.
+    Counters::code_stubs.Increment();
+
+    // Generate the new code.
+    MacroAssembler masm(NULL, 256);
+
+    // Nested stubs are not allowed for leafs.
+    masm.set_allow_stub_calls(AllowsStubCalls());
+
+    // Generate the code for the stub.
+    masm.set_generating_stub(true);
+    Generate(&masm);
+
+    // Create the code object.
+    CodeDesc desc;
+    masm.GetCode(&desc);
+
+    // Copy the generated code into a heap object, and store the major key.
+    Code::Flags flags = Code::ComputeFlags(Code::STUB);
+    Handle<Code> code = Factory::NewCode(desc, NULL, flags, masm.CodeObject());
+    code->set_major_key(MajorKey());
+
+    // Add unresolved entries in the code to the fixup list.
+    Bootstrapper::AddFixup(*code, &masm);
+
+    LOG(CodeCreateEvent("Stub", *code, GetName()));
+    Counters::total_stubs_code_size.Increment(code->instruction_size());
+
+#ifdef ENABLE_DISASSEMBLER
+    if (FLAG_print_code_stubs) {
+#ifdef DEBUG
+      Print();
+#endif
+      code->Disassemble(GetName());
+      PrintF("\n");
+    }
+#endif
+
+    // Update the dictionary and the root in Heap.
+    Handle<Dictionary> dict =
+        Factory::DictionaryAtNumberPut(Handle<Dictionary>(Heap::code_stubs()),
+                                       key,
+                                       code);
+    Heap::set_code_stubs(*dict);
+    index = Heap::code_stubs()->FindNumberEntry(key);
+  }
+  ASSERT(index != -1);
+
+  return Handle<Code>(Code::cast(Heap::code_stubs()->ValueAt(index)));
+}
+
+
+const char* CodeStub::MajorName(CodeStub::Major major_key) {
+  switch (major_key) {
+    case CallFunction:
+      return "CallFunction";
+    case GenericBinaryOp:
+      return "GenericBinaryOp";
+    case SmiOp:
+      return "SmiOp";
+    case Compare:
+      return "Compare";
+    case RecordWrite:
+      return "RecordWrite";
+    case StackCheck:
+      return "StackCheck";
+    case UnarySub:
+      return "UnarySub";
+    case RevertToNumber:
+      return "RevertToNumber";
+    case ToBoolean:
+      return "ToBoolean";
+    case Instanceof:
+      return "Instanceof";
+    case CounterOp:
+      return "CounterOp";
+    case ArgumentsAccess:
+      return "ArgumentsAccess";
+    case Runtime:
+      return "Runtime";
+    case CEntry:
+      return "CEntry";
+    case JSEntry:
+      return "JSEntry";
+    case GetProperty:
+      return "GetProperty";
+    case SetProperty:
+      return "SetProperty";
+    case InvokeBuiltin:
+      return "InvokeBuiltin";
+    case JSExit:
+      return "JSExit";
+    default:
+      UNREACHABLE();
+      return NULL;
+  }
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/code-stubs.h b/deps/v8/src/code-stubs.h
new file mode 100644
index 0000000..d21b0ee
--- /dev/null
+++ b/deps/v8/src/code-stubs.h
@@ -0,0 +1,109 @@
+// 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_CODE_STUBS_H_
+#define V8_CODE_STUBS_H_
+
+namespace v8 { namespace internal {
+
+
+// Stub is base classes of all stubs.
+class CodeStub BASE_EMBEDDED {
+ public:
+  enum Major {
+    CallFunction,
+    GenericBinaryOp,
+    SmiOp,
+    Compare,
+    RecordWrite,  // Last stub that allows stub calls inside.
+    StackCheck,
+    UnarySub,
+    RevertToNumber,
+    ToBoolean,
+    Instanceof,
+    CounterOp,
+    ArgumentsAccess,
+    Runtime,
+    CEntry,
+    JSEntry,
+    GetProperty,   // ARM only
+    SetProperty,   // ARM only
+    InvokeBuiltin,  // ARM only
+    JSExit,        // ARM only
+    NUMBER_OF_IDS
+  };
+
+  // Retrieve the code for the stub. Generate the code if needed.
+  Handle<Code> GetCode();
+
+  static Major MajorKeyFromKey(uint32_t key) {
+    return static_cast<Major>(MajorKeyBits::decode(key));
+  };
+  static int MinorKeyFromKey(uint32_t key) {
+    return MinorKeyBits::decode(key);
+  };
+  static const char* MajorName(Major major_key);
+
+  virtual ~CodeStub() {}
+
+ protected:
+  static const int kMajorBits = 5;
+  static const int kMinorBits = kBitsPerPointer - kMajorBits - kSmiTagSize;
+
+ private:
+  // Generates the assembler code for the stub.
+  virtual void Generate(MacroAssembler* masm) = 0;
+
+  // Returns information for computing the number key.
+  virtual Major MajorKey() = 0;
+  virtual int MinorKey() = 0;
+
+  // Returns a name for logging/debugging purposes.
+  virtual const char* GetName() { return MajorName(MajorKey()); }
+
+#ifdef DEBUG
+  virtual void Print() { PrintF("%s\n", GetName()); }
+#endif
+
+  // Computes the key based on major and minor.
+  uint32_t GetKey() {
+    ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
+    return MinorKeyBits::encode(MinorKey()) |
+           MajorKeyBits::encode(MajorKey());
+  }
+
+  bool AllowsStubCalls() { return MajorKey() <= RecordWrite; }
+
+  class MajorKeyBits: public BitField<uint32_t, 0, kMajorBits> {};
+  class MinorKeyBits: public BitField<uint32_t, kMajorBits, kMinorBits> {};
+
+  friend class BreakPointIterator;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_CODE_STUBS_H_
diff --git a/deps/v8/src/code.h b/deps/v8/src/code.h
new file mode 100644
index 0000000..87e0794
--- /dev/null
+++ b/deps/v8/src/code.h
@@ -0,0 +1,67 @@
+// 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_CODE_H_
+#define V8_CODE_H_
+
+namespace v8 { namespace internal {
+
+
+// Wrapper class for passing expected and actual parameter counts as
+// either registers or immediate values. Used to make sure that the
+// caller provides exactly the expected number of parameters to the
+// callee.
+class ParameterCount BASE_EMBEDDED {
+ public:
+  explicit ParameterCount(Register reg)
+      : reg_(reg), immediate_(0) { }
+  explicit ParameterCount(int immediate)
+      : reg_(no_reg), immediate_(immediate) { }
+
+  bool is_reg() const { return !reg_.is(no_reg); }
+  bool is_immediate() const { return !is_reg(); }
+
+  Register reg() const {
+    ASSERT(is_reg());
+    return reg_;
+  }
+  int immediate() const {
+    ASSERT(is_immediate());
+    return immediate_;
+  }
+
+ private:
+  const Register reg_;
+  const int immediate_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ParameterCount);
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_CODE_H_
diff --git a/deps/v8/src/codegen-arm.cc b/deps/v8/src/codegen-arm.cc
new file mode 100644
index 0000000..6fdabc3
--- /dev/null
+++ b/deps/v8/src/codegen-arm.cc
@@ -0,0 +1,5203 @@
+// Copyright 2006-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.
+
+#include "v8.h"
+
+#include "bootstrapper.h"
+#include "codegen-inl.h"
+#include "debug.h"
+#include "parser.h"
+#include "register-allocator-inl.h"
+#include "runtime.h"
+#include "scopes.h"
+
+
+namespace v8 { namespace internal {
+
+#define __ masm_->
+
+// -------------------------------------------------------------------------
+// CodeGenState implementation.
+
+CodeGenState::CodeGenState(CodeGenerator* owner)
+    : owner_(owner),
+      typeof_state_(NOT_INSIDE_TYPEOF),
+      true_target_(NULL),
+      false_target_(NULL),
+      previous_(NULL) {
+  owner_->set_state(this);
+}
+
+
+CodeGenState::CodeGenState(CodeGenerator* owner,
+                           TypeofState typeof_state,
+                           JumpTarget* true_target,
+                           JumpTarget* false_target)
+    : owner_(owner),
+      typeof_state_(typeof_state),
+      true_target_(true_target),
+      false_target_(false_target),
+      previous_(owner->state()) {
+  owner_->set_state(this);
+}
+
+
+CodeGenState::~CodeGenState() {
+  ASSERT(owner_->state() == this);
+  owner_->set_state(previous_);
+}
+
+
+// -------------------------------------------------------------------------
+// CodeGenerator implementation
+
+CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script,
+                             bool is_eval)
+    : is_eval_(is_eval),
+      script_(script),
+      deferred_(8),
+      masm_(new MacroAssembler(NULL, buffer_size)),
+      scope_(NULL),
+      frame_(NULL),
+      allocator_(NULL),
+      cc_reg_(al),
+      state_(NULL),
+      function_return_is_shadowed_(false),
+      in_spilled_code_(false) {
+}
+
+
+// Calling conventions:
+// fp: caller's frame pointer
+// sp: stack pointer
+// r1: called JS function
+// cp: callee's context
+
+void CodeGenerator::GenCode(FunctionLiteral* fun) {
+  ZoneList<Statement*>* body = fun->body();
+
+  // Initialize state.
+  ASSERT(scope_ == NULL);
+  scope_ = fun->scope();
+  ASSERT(allocator_ == NULL);
+  RegisterAllocator register_allocator(this);
+  allocator_ = &register_allocator;
+  ASSERT(frame_ == NULL);
+  frame_ = new VirtualFrame(this);
+  cc_reg_ = al;
+  set_in_spilled_code(false);
+  {
+    CodeGenState state(this);
+
+    // Entry:
+    // Stack: receiver, arguments
+    // lr: return address
+    // fp: caller's frame pointer
+    // sp: stack pointer
+    // r1: called JS function
+    // cp: callee's context
+    allocator_->Initialize();
+    frame_->Enter();
+    // tos: code slot
+#ifdef DEBUG
+    if (strlen(FLAG_stop_at) > 0 &&
+        fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
+      frame_->SpillAll();
+      __ stop("stop-at");
+    }
+#endif
+
+    // Allocate space for locals and initialize them.
+    frame_->AllocateStackSlots(scope_->num_stack_slots());
+    // Initialize the function return target after the locals are set
+    // up, because it needs the expected frame height from the frame.
+    function_return_.Initialize(this, JumpTarget::BIDIRECTIONAL);
+    function_return_is_shadowed_ = false;
+
+    VirtualFrame::SpilledScope spilled_scope(this);
+    if (scope_->num_heap_slots() > 0) {
+      // Allocate local context.
+      // Get outer context and create a new context based on it.
+      __ ldr(r0, frame_->Function());
+      frame_->EmitPush(r0);
+      frame_->CallRuntime(Runtime::kNewContext, 1);  // r0 holds the result
+
+      if (kDebug) {
+        JumpTarget verified_true(this);
+        __ cmp(r0, Operand(cp));
+        verified_true.Branch(eq);
+        __ stop("NewContext: r0 is expected to be the same as cp");
+        verified_true.Bind();
+      }
+      // Update context local.
+      __ str(cp, frame_->Context());
+    }
+
+    // TODO(1241774): Improve this code:
+    // 1) only needed if we have a context
+    // 2) no need to recompute context ptr every single time
+    // 3) don't copy parameter operand code from SlotOperand!
+    {
+      Comment cmnt2(masm_, "[ copy context parameters into .context");
+
+      // Note that iteration order is relevant here! If we have the same
+      // parameter twice (e.g., function (x, y, x)), and that parameter
+      // needs to be copied into the context, it must be the last argument
+      // passed to the parameter that needs to be copied. This is a rare
+      // case so we don't check for it, instead we rely on the copying
+      // order: such a parameter is copied repeatedly into the same
+      // context location and thus the last value is what is seen inside
+      // the function.
+      for (int i = 0; i < scope_->num_parameters(); i++) {
+        Variable* par = scope_->parameter(i);
+        Slot* slot = par->slot();
+        if (slot != NULL && slot->type() == Slot::CONTEXT) {
+          ASSERT(!scope_->is_global_scope());  // no parameters in global scope
+          __ ldr(r1, frame_->ParameterAt(i));
+          // Loads r2 with context; used below in RecordWrite.
+          __ str(r1, SlotOperand(slot, r2));
+          // Load the offset into r3.
+          int slot_offset =
+              FixedArray::kHeaderSize + slot->index() * kPointerSize;
+          __ mov(r3, Operand(slot_offset));
+          __ RecordWrite(r2, r3, r1);
+        }
+      }
+    }
+
+    // Store the arguments object.  This must happen after context
+    // initialization because the arguments object may be stored in the
+    // context.
+    if (scope_->arguments() != NULL) {
+      ASSERT(scope_->arguments_shadow() != NULL);
+      Comment cmnt(masm_, "[ allocate arguments object");
+      { Reference shadow_ref(this, scope_->arguments_shadow());
+        { Reference arguments_ref(this, scope_->arguments());
+          ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
+          __ ldr(r2, frame_->Function());
+          // The receiver is below the arguments, the return address,
+          // and the frame pointer on the stack.
+          const int kReceiverDisplacement = 2 + scope_->num_parameters();
+          __ add(r1, fp, Operand(kReceiverDisplacement * kPointerSize));
+          __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
+          frame_->Adjust(3);
+          __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit());
+          frame_->CallStub(&stub, 3);
+          frame_->EmitPush(r0);
+          arguments_ref.SetValue(NOT_CONST_INIT);
+        }
+        shadow_ref.SetValue(NOT_CONST_INIT);
+      }
+      frame_->Drop();  // Value is no longer needed.
+    }
+
+    // Generate code to 'execute' declarations and initialize functions
+    // (source elements). In case of an illegal redeclaration we need to
+    // handle that instead of processing the declarations.
+    if (scope_->HasIllegalRedeclaration()) {
+      Comment cmnt(masm_, "[ illegal redeclarations");
+      scope_->VisitIllegalRedeclaration(this);
+    } else {
+      Comment cmnt(masm_, "[ declarations");
+      ProcessDeclarations(scope_->declarations());
+      // Bail out if a stack-overflow exception occurred when processing
+      // declarations.
+      if (HasStackOverflow()) return;
+    }
+
+    if (FLAG_trace) {
+      frame_->CallRuntime(Runtime::kTraceEnter, 0);
+      // Ignore the return value.
+    }
+    CheckStack();
+
+    // Compile the body of the function in a vanilla state. Don't
+    // bother compiling all the code if the scope has an illegal
+    // redeclaration.
+    if (!scope_->HasIllegalRedeclaration()) {
+      Comment cmnt(masm_, "[ function body");
+#ifdef DEBUG
+      bool is_builtin = Bootstrapper::IsActive();
+      bool should_trace =
+          is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls;
+      if (should_trace) {
+        frame_->CallRuntime(Runtime::kDebugTrace, 0);
+        // Ignore the return value.
+      }
+#endif
+      VisitStatementsAndSpill(body);
+    }
+  }
+
+  // Generate the return sequence if necessary.
+  if (frame_ != NULL || function_return_.is_linked()) {
+    // exit
+    // r0: result
+    // sp: stack pointer
+    // fp: frame pointer
+    // pp: parameter pointer
+    // cp: callee's context
+    __ mov(r0, Operand(Factory::undefined_value()));
+
+    function_return_.Bind();
+    if (FLAG_trace) {
+      // Push the return value on the stack as the parameter.
+      // Runtime::TraceExit returns the parameter as it is.
+      frame_->EmitPush(r0);
+      frame_->CallRuntime(Runtime::kTraceExit, 1);
+    }
+
+    // Tear down the frame which will restore the caller's frame pointer and
+    // the link register.
+    frame_->Exit();
+
+    __ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize));
+    __ mov(pc, lr);
+  }
+
+  // Code generation state must be reset.
+  ASSERT(!has_cc());
+  ASSERT(state_ == NULL);
+  ASSERT(!function_return_is_shadowed_);
+  function_return_.Unuse();
+  DeleteFrame();
+
+  // Process any deferred code using the register allocator.
+  if (HasStackOverflow()) {
+    ClearDeferred();
+  } else {
+    ProcessDeferred();
+  }
+
+  allocator_ = NULL;
+  scope_ = NULL;
+}
+
+
+MemOperand CodeGenerator::SlotOperand(Slot* slot, Register tmp) {
+  // Currently, this assertion will fail if we try to assign to
+  // a constant variable that is constant because it is read-only
+  // (such as the variable referring to a named function expression).
+  // We need to implement assignments to read-only variables.
+  // Ideally, we should do this during AST generation (by converting
+  // such assignments into expression statements); however, in general
+  // we may not be able to make the decision until past AST generation,
+  // that is when the entire program is known.
+  ASSERT(slot != NULL);
+  int index = slot->index();
+  switch (slot->type()) {
+    case Slot::PARAMETER:
+      return frame_->ParameterAt(index);
+
+    case Slot::LOCAL:
+      return frame_->LocalAt(index);
+
+    case Slot::CONTEXT: {
+      // Follow the context chain if necessary.
+      ASSERT(!tmp.is(cp));  // do not overwrite context register
+      Register context = cp;
+      int chain_length = scope()->ContextChainLength(slot->var()->scope());
+      for (int i = 0; i < chain_length; i++) {
+        // Load the closure.
+        // (All contexts, even 'with' contexts, have a closure,
+        // and it is the same for all contexts inside a function.
+        // There is no need to go to the function context first.)
+        __ ldr(tmp, ContextOperand(context, Context::CLOSURE_INDEX));
+        // Load the function context (which is the incoming, outer context).
+        __ ldr(tmp, FieldMemOperand(tmp, JSFunction::kContextOffset));
+        context = tmp;
+      }
+      // We may have a 'with' context now. Get the function context.
+      // (In fact this mov may never be the needed, since the scope analysis
+      // may not permit a direct context access in this case and thus we are
+      // always at a function context. However it is safe to dereference be-
+      // cause the function context of a function context is itself. Before
+      // deleting this mov we should try to create a counter-example first,
+      // though...)
+      __ ldr(tmp, ContextOperand(context, Context::FCONTEXT_INDEX));
+      return ContextOperand(tmp, index);
+    }
+
+    default:
+      UNREACHABLE();
+      return MemOperand(r0, 0);
+  }
+}
+
+
+MemOperand CodeGenerator::ContextSlotOperandCheckExtensions(
+    Slot* slot,
+    Register tmp,
+    Register tmp2,
+    JumpTarget* slow) {
+  ASSERT(slot->type() == Slot::CONTEXT);
+  Register context = cp;
+
+  for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) {
+    if (s->num_heap_slots() > 0) {
+      if (s->calls_eval()) {
+        // Check that extension is NULL.
+        __ ldr(tmp2, ContextOperand(context, Context::EXTENSION_INDEX));
+        __ tst(tmp2, tmp2);
+        slow->Branch(ne);
+      }
+      __ ldr(tmp, ContextOperand(context, Context::CLOSURE_INDEX));
+      __ ldr(tmp, FieldMemOperand(tmp, JSFunction::kContextOffset));
+      context = tmp;
+    }
+  }
+  // Check that last extension is NULL.
+  __ ldr(tmp2, ContextOperand(context, Context::EXTENSION_INDEX));
+  __ tst(tmp2, tmp2);
+  slow->Branch(ne);
+  __ ldr(tmp, ContextOperand(context, Context::FCONTEXT_INDEX));
+  return ContextOperand(tmp, slot->index());
+}
+
+
+void CodeGenerator::LoadConditionAndSpill(Expression* expression,
+                                          TypeofState typeof_state,
+                                          JumpTarget* true_target,
+                                          JumpTarget* false_target,
+                                          bool force_control) {
+  ASSERT(in_spilled_code());
+  set_in_spilled_code(false);
+  LoadCondition(expression, typeof_state, true_target, false_target,
+                force_control);
+  if (frame_ != NULL) {
+    frame_->SpillAll();
+  }
+  set_in_spilled_code(true);
+}
+
+
+// Loads a value on TOS. If it is a boolean value, the result may have been
+// (partially) translated into branches, or it may have set the condition
+// code register. If force_cc is set, the value is forced to set the
+// condition code register and no value is pushed. If the condition code
+// register was set, has_cc() is true and cc_reg_ contains the condition to
+// test for 'true'.
+void CodeGenerator::LoadCondition(Expression* x,
+                                  TypeofState typeof_state,
+                                  JumpTarget* true_target,
+                                  JumpTarget* false_target,
+                                  bool force_cc) {
+  ASSERT(!in_spilled_code());
+  ASSERT(!has_cc());
+  int original_height = frame_->height();
+
+  { CodeGenState new_state(this, typeof_state, true_target, false_target);
+    Visit(x);
+
+    // If we hit a stack overflow, we may not have actually visited
+    // the expression.  In that case, we ensure that we have a
+    // valid-looking frame state because we will continue to generate
+    // code as we unwind the C++ stack.
+    //
+    // It's possible to have both a stack overflow and a valid frame
+    // state (eg, a subexpression overflowed, visiting it returned
+    // with a dummied frame state, and visiting this expression
+    // returned with a normal-looking state).
+    if (HasStackOverflow() &&
+        has_valid_frame() &&
+        !has_cc() &&
+        frame_->height() == original_height) {
+      true_target->Jump();
+    }
+  }
+  if (force_cc && frame_ != NULL && !has_cc()) {
+    // Convert the TOS value to a boolean in the condition code register.
+    ToBoolean(true_target, false_target);
+  }
+  ASSERT(!force_cc || !has_valid_frame() || has_cc());
+  ASSERT(!has_valid_frame() ||
+         (has_cc() && frame_->height() == original_height) ||
+         (!has_cc() && frame_->height() == original_height + 1));
+}
+
+
+void CodeGenerator::LoadAndSpill(Expression* expression,
+                                 TypeofState typeof_state) {
+  ASSERT(in_spilled_code());
+  set_in_spilled_code(false);
+  Load(expression, typeof_state);
+  frame_->SpillAll();
+  set_in_spilled_code(true);
+}
+
+
+void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  ASSERT(!in_spilled_code());
+  JumpTarget true_target(this);
+  JumpTarget false_target(this);
+  LoadCondition(x, typeof_state, &true_target, &false_target, false);
+
+  if (has_cc()) {
+    // Convert cc_reg_ into a boolean value.
+    JumpTarget loaded(this);
+    JumpTarget materialize_true(this);
+    materialize_true.Branch(cc_reg_);
+    __ mov(r0, Operand(Factory::false_value()));
+    frame_->EmitPush(r0);
+    loaded.Jump();
+    materialize_true.Bind();
+    __ mov(r0, Operand(Factory::true_value()));
+    frame_->EmitPush(r0);
+    loaded.Bind();
+    cc_reg_ = al;
+  }
+
+  if (true_target.is_linked() || false_target.is_linked()) {
+    // We have at least one condition value that has been "translated"
+    // into a branch, thus it needs to be loaded explicitly.
+    JumpTarget loaded(this);
+    if (frame_ != NULL) {
+      loaded.Jump();  // Don't lose the current TOS.
+    }
+    bool both = true_target.is_linked() && false_target.is_linked();
+    // Load "true" if necessary.
+    if (true_target.is_linked()) {
+      true_target.Bind();
+      __ mov(r0, Operand(Factory::true_value()));
+      frame_->EmitPush(r0);
+    }
+    // If both "true" and "false" need to be loaded jump across the code for
+    // "false".
+    if (both) {
+      loaded.Jump();
+    }
+    // Load "false" if necessary.
+    if (false_target.is_linked()) {
+      false_target.Bind();
+      __ mov(r0, Operand(Factory::false_value()));
+      frame_->EmitPush(r0);
+    }
+    // A value is loaded on all paths reaching this point.
+    loaded.Bind();
+  }
+  ASSERT(has_valid_frame());
+  ASSERT(!has_cc());
+  ASSERT(frame_->height() == original_height + 1);
+}
+
+
+void CodeGenerator::LoadGlobal() {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  __ ldr(r0, GlobalObject());
+  frame_->EmitPush(r0);
+}
+
+
+void CodeGenerator::LoadGlobalReceiver(Register scratch) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  __ ldr(scratch, ContextOperand(cp, Context::GLOBAL_INDEX));
+  __ ldr(scratch,
+         FieldMemOperand(scratch, GlobalObject::kGlobalReceiverOffset));
+  frame_->EmitPush(scratch);
+}
+
+
+// TODO(1241834): Get rid of this function in favor of just using Load, now
+// that we have the INSIDE_TYPEOF typeof state. => Need to handle global
+// variables w/o reference errors elsewhere.
+void CodeGenerator::LoadTypeofExpression(Expression* x) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Variable* variable = x->AsVariableProxy()->AsVariable();
+  if (variable != NULL && !variable->is_this() && variable->is_global()) {
+    // NOTE: This is somewhat nasty. We force the compiler to load
+    // the variable as if through '<global>.<variable>' to make sure we
+    // do not get reference errors.
+    Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX);
+    Literal key(variable->name());
+    // TODO(1241834): Fetch the position from the variable instead of using
+    // no position.
+    Property property(&global, &key, RelocInfo::kNoPosition);
+    LoadAndSpill(&property);
+  } else {
+    LoadAndSpill(x, INSIDE_TYPEOF);
+  }
+}
+
+
+Reference::Reference(CodeGenerator* cgen, Expression* expression)
+    : cgen_(cgen), expression_(expression), type_(ILLEGAL) {
+  cgen->LoadReference(this);
+}
+
+
+Reference::~Reference() {
+  cgen_->UnloadReference(this);
+}
+
+
+void CodeGenerator::LoadReference(Reference* ref) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ LoadReference");
+  Expression* e = ref->expression();
+  Property* property = e->AsProperty();
+  Variable* var = e->AsVariableProxy()->AsVariable();
+
+  if (property != NULL) {
+    // The expression is either a property or a variable proxy that rewrites
+    // to a property.
+    LoadAndSpill(property->obj());
+    // We use a named reference if the key is a literal symbol, unless it is
+    // a string that can be legally parsed as an integer.  This is because
+    // otherwise we will not get into the slow case code that handles [] on
+    // String objects.
+    Literal* literal = property->key()->AsLiteral();
+    uint32_t dummy;
+    if (literal != NULL &&
+        literal->handle()->IsSymbol() &&
+        !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
+      ref->set_type(Reference::NAMED);
+    } else {
+      LoadAndSpill(property->key());
+      ref->set_type(Reference::KEYED);
+    }
+  } else if (var != NULL) {
+    // The expression is a variable proxy that does not rewrite to a
+    // property.  Global variables are treated as named property references.
+    if (var->is_global()) {
+      LoadGlobal();
+      ref->set_type(Reference::NAMED);
+    } else {
+      ASSERT(var->slot() != NULL);
+      ref->set_type(Reference::SLOT);
+    }
+  } else {
+    // Anything else is a runtime error.
+    LoadAndSpill(e);
+    frame_->CallRuntime(Runtime::kThrowReferenceError, 1);
+  }
+}
+
+
+void CodeGenerator::UnloadReference(Reference* ref) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  // Pop a reference from the stack while preserving TOS.
+  Comment cmnt(masm_, "[ UnloadReference");
+  int size = ref->size();
+  if (size > 0) {
+    frame_->EmitPop(r0);
+    frame_->Drop(size);
+    frame_->EmitPush(r0);
+  }
+}
+
+
+// ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given
+// register to a boolean in the condition code register. The code
+// may jump to 'false_target' in case the register converts to 'false'.
+void CodeGenerator::ToBoolean(JumpTarget* true_target,
+                              JumpTarget* false_target) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  // Note: The generated code snippet does not change stack variables.
+  //       Only the condition code should be set.
+  frame_->EmitPop(r0);
+
+  // Fast case checks
+
+  // Check if the value is 'false'.
+  __ cmp(r0, Operand(Factory::false_value()));
+  false_target->Branch(eq);
+
+  // Check if the value is 'true'.
+  __ cmp(r0, Operand(Factory::true_value()));
+  true_target->Branch(eq);
+
+  // Check if the value is 'undefined'.
+  __ cmp(r0, Operand(Factory::undefined_value()));
+  false_target->Branch(eq);
+
+  // Check if the value is a smi.
+  __ cmp(r0, Operand(Smi::FromInt(0)));
+  false_target->Branch(eq);
+  __ tst(r0, Operand(kSmiTagMask));
+  true_target->Branch(eq);
+
+  // Slow case: call the runtime.
+  frame_->EmitPush(r0);
+  frame_->CallRuntime(Runtime::kToBool, 1);
+  // Convert the result (r0) to a condition code.
+  __ cmp(r0, Operand(Factory::false_value()));
+
+  cc_reg_ = ne;
+}
+
+
+class GetPropertyStub : public CodeStub {
+ public:
+  GetPropertyStub() { }
+
+ private:
+  Major MajorKey() { return GetProperty; }
+  int MinorKey() { return 0; }
+  void Generate(MacroAssembler* masm);
+};
+
+
+class SetPropertyStub : public CodeStub {
+ public:
+  SetPropertyStub() { }
+
+ private:
+  Major MajorKey() { return SetProperty; }
+  int MinorKey() { return 0; }
+  void Generate(MacroAssembler* masm);
+};
+
+
+class GenericBinaryOpStub : public CodeStub {
+ public:
+  explicit GenericBinaryOpStub(Token::Value op) : op_(op) { }
+
+ private:
+  Token::Value op_;
+
+  Major MajorKey() { return GenericBinaryOp; }
+  int MinorKey() { return static_cast<int>(op_); }
+  void Generate(MacroAssembler* masm);
+
+  const char* GetName() {
+    switch (op_) {
+      case Token::ADD: return "GenericBinaryOpStub_ADD";
+      case Token::SUB: return "GenericBinaryOpStub_SUB";
+      case Token::MUL: return "GenericBinaryOpStub_MUL";
+      case Token::DIV: return "GenericBinaryOpStub_DIV";
+      case Token::BIT_OR: return "GenericBinaryOpStub_BIT_OR";
+      case Token::BIT_AND: return "GenericBinaryOpStub_BIT_AND";
+      case Token::BIT_XOR: return "GenericBinaryOpStub_BIT_XOR";
+      case Token::SAR: return "GenericBinaryOpStub_SAR";
+      case Token::SHL: return "GenericBinaryOpStub_SHL";
+      case Token::SHR: return "GenericBinaryOpStub_SHR";
+      default:         return "GenericBinaryOpStub";
+    }
+  }
+
+#ifdef DEBUG
+  void Print() { PrintF("GenericBinaryOpStub (%s)\n", Token::String(op_)); }
+#endif
+};
+
+
+void CodeGenerator::GenericBinaryOperation(Token::Value op) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  // sp[0] : y
+  // sp[1] : x
+  // result : r0
+
+  // Stub is entered with a call: 'return address' is in lr.
+  switch (op) {
+    case Token::ADD:  // fall through.
+    case Token::SUB:  // fall through.
+    case Token::MUL:
+    case Token::BIT_OR:
+    case Token::BIT_AND:
+    case Token::BIT_XOR:
+    case Token::SHL:
+    case Token::SHR:
+    case Token::SAR: {
+      frame_->EmitPop(r0);  // r0 : y
+      frame_->EmitPop(r1);  // r1 : x
+      GenericBinaryOpStub stub(op);
+      frame_->CallStub(&stub, 0);
+      break;
+    }
+
+    case Token::DIV: {
+      Result arg_count = allocator_->Allocate(r0);
+      ASSERT(arg_count.is_valid());
+      __ mov(arg_count.reg(), Operand(1));
+      frame_->InvokeBuiltin(Builtins::DIV, CALL_JS, &arg_count, 2);
+      break;
+    }
+
+    case Token::MOD: {
+      Result arg_count = allocator_->Allocate(r0);
+      ASSERT(arg_count.is_valid());
+      __ mov(arg_count.reg(), Operand(1));
+      frame_->InvokeBuiltin(Builtins::MOD, CALL_JS, &arg_count, 2);
+      break;
+    }
+
+    case Token::COMMA:
+      frame_->EmitPop(r0);
+      // simply discard left value
+      frame_->Drop();
+      break;
+
+    default:
+      // Other cases should have been handled before this point.
+      UNREACHABLE();
+      break;
+  }
+}
+
+
+class DeferredInlineSmiOperation: public DeferredCode {
+ public:
+  DeferredInlineSmiOperation(CodeGenerator* generator,
+                             Token::Value op,
+                             int value,
+                             bool reversed)
+      : DeferredCode(generator),
+        op_(op),
+        value_(value),
+        reversed_(reversed) {
+    set_comment("[ DeferredInlinedSmiOperation");
+  }
+
+  virtual void Generate();
+
+ private:
+  Token::Value op_;
+  int value_;
+  bool reversed_;
+};
+
+
+void DeferredInlineSmiOperation::Generate() {
+  enter()->Bind();
+  VirtualFrame::SpilledScope spilled_scope(generator());
+
+  switch (op_) {
+    case Token::ADD: {
+      if (reversed_) {
+        // revert optimistic add
+        __ sub(r0, r0, Operand(Smi::FromInt(value_)));
+        __ mov(r1, Operand(Smi::FromInt(value_)));
+      } else {
+        // revert optimistic add
+        __ sub(r1, r0, Operand(Smi::FromInt(value_)));
+        __ mov(r0, Operand(Smi::FromInt(value_)));
+      }
+      break;
+    }
+
+    case Token::SUB: {
+      if (reversed_) {
+        // revert optimistic sub
+        __ rsb(r0, r0, Operand(Smi::FromInt(value_)));
+        __ mov(r1, Operand(Smi::FromInt(value_)));
+      } else {
+        __ add(r1, r0, Operand(Smi::FromInt(value_)));
+        __ mov(r0, Operand(Smi::FromInt(value_)));
+      }
+      break;
+    }
+
+    case Token::BIT_OR:
+    case Token::BIT_XOR:
+    case Token::BIT_AND: {
+      if (reversed_) {
+        __ mov(r1, Operand(Smi::FromInt(value_)));
+      } else {
+        __ mov(r1, Operand(r0));
+        __ mov(r0, Operand(Smi::FromInt(value_)));
+      }
+      break;
+    }
+
+    case Token::SHL:
+    case Token::SHR:
+    case Token::SAR: {
+      if (!reversed_) {
+        __ mov(r1, Operand(r0));
+        __ mov(r0, Operand(Smi::FromInt(value_)));
+      } else {
+        UNREACHABLE();  // should have been handled in SmiOperation
+      }
+      break;
+    }
+
+    default:
+      // other cases should have been handled before this point.
+      UNREACHABLE();
+      break;
+  }
+
+  GenericBinaryOpStub igostub(op_);
+  Result arg0 = generator()->allocator()->Allocate(r1);
+  ASSERT(arg0.is_valid());
+  Result arg1 = generator()->allocator()->Allocate(r0);
+  ASSERT(arg1.is_valid());
+  generator()->frame()->CallStub(&igostub, &arg0, &arg1);
+  exit_.Jump();
+}
+
+
+void CodeGenerator::SmiOperation(Token::Value op,
+                                 Handle<Object> value,
+                                 bool reversed) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  // NOTE: This is an attempt to inline (a bit) more of the code for
+  // some possible smi operations (like + and -) when (at least) one
+  // of the operands is a literal smi. With this optimization, the
+  // performance of the system is increased by ~15%, and the generated
+  // code size is increased by ~1% (measured on a combination of
+  // different benchmarks).
+
+  // sp[0] : operand
+
+  int int_value = Smi::cast(*value)->value();
+
+  JumpTarget exit(this);
+  frame_->EmitPop(r0);
+
+  switch (op) {
+    case Token::ADD: {
+      DeferredCode* deferred =
+        new DeferredInlineSmiOperation(this, op, int_value, reversed);
+
+      __ add(r0, r0, Operand(value), SetCC);
+      deferred->enter()->Branch(vs);
+      __ tst(r0, Operand(kSmiTagMask));
+      deferred->enter()->Branch(ne);
+      deferred->BindExit();
+      break;
+    }
+
+    case Token::SUB: {
+      DeferredCode* deferred =
+        new DeferredInlineSmiOperation(this, op, int_value, reversed);
+
+      if (!reversed) {
+        __ sub(r0, r0, Operand(value), SetCC);
+      } else {
+        __ rsb(r0, r0, Operand(value), SetCC);
+      }
+      deferred->enter()->Branch(vs);
+      __ tst(r0, Operand(kSmiTagMask));
+      deferred->enter()->Branch(ne);
+      deferred->BindExit();
+      break;
+    }
+
+    case Token::BIT_OR:
+    case Token::BIT_XOR:
+    case Token::BIT_AND: {
+      DeferredCode* deferred =
+        new DeferredInlineSmiOperation(this, op, int_value, reversed);
+      __ tst(r0, Operand(kSmiTagMask));
+      deferred->enter()->Branch(ne);
+      switch (op) {
+        case Token::BIT_OR:  __ orr(r0, r0, Operand(value)); break;
+        case Token::BIT_XOR: __ eor(r0, r0, Operand(value)); break;
+        case Token::BIT_AND: __ and_(r0, r0, Operand(value)); break;
+        default: UNREACHABLE();
+      }
+      deferred->BindExit();
+      break;
+    }
+
+    case Token::SHL:
+    case Token::SHR:
+    case Token::SAR: {
+      if (reversed) {
+        __ mov(ip, Operand(value));
+        frame_->EmitPush(ip);
+        frame_->EmitPush(r0);
+        GenericBinaryOperation(op);
+
+      } else {
+        int shift_value = int_value & 0x1f;  // least significant 5 bits
+        DeferredCode* deferred =
+          new DeferredInlineSmiOperation(this, op, shift_value, false);
+        __ tst(r0, Operand(kSmiTagMask));
+        deferred->enter()->Branch(ne);
+        __ mov(r2, Operand(r0, ASR, kSmiTagSize));  // remove tags
+        switch (op) {
+          case Token::SHL: {
+            __ mov(r2, Operand(r2, LSL, shift_value));
+            // check that the *unsigned* result fits in a smi
+            __ add(r3, r2, Operand(0x40000000), SetCC);
+            deferred->enter()->Branch(mi);
+            break;
+          }
+          case Token::SHR: {
+            // LSR by immediate 0 means shifting 32 bits.
+            if (shift_value != 0) {
+              __ mov(r2, Operand(r2, LSR, shift_value));
+            }
+            // check that the *unsigned* result fits in a smi
+            // neither of the two high-order bits can be set:
+            // - 0x80000000: high bit would be lost when smi tagging
+            // - 0x40000000: this number would convert to negative when
+            // smi tagging these two cases can only happen with shifts
+            // by 0 or 1 when handed a valid smi
+            __ and_(r3, r2, Operand(0xc0000000), SetCC);
+            deferred->enter()->Branch(ne);
+            break;
+          }
+          case Token::SAR: {
+            if (shift_value != 0) {
+              // ASR by immediate 0 means shifting 32 bits.
+              __ mov(r2, Operand(r2, ASR, shift_value));
+            }
+            break;
+          }
+          default: UNREACHABLE();
+        }
+        __ mov(r0, Operand(r2, LSL, kSmiTagSize));
+        deferred->BindExit();
+      }
+      break;
+    }
+
+    default:
+      if (!reversed) {
+        frame_->EmitPush(r0);
+        __ mov(r0, Operand(value));
+        frame_->EmitPush(r0);
+      } else {
+        __ mov(ip, Operand(value));
+        frame_->EmitPush(ip);
+        frame_->EmitPush(r0);
+      }
+      GenericBinaryOperation(op);
+      break;
+  }
+
+  exit.Bind();
+}
+
+
+void CodeGenerator::Comparison(Condition cc, bool strict) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  // sp[0] : y
+  // sp[1] : x
+  // result : cc register
+
+  // Strict only makes sense for equality comparisons.
+  ASSERT(!strict || cc == eq);
+
+  JumpTarget exit(this);
+  JumpTarget smi(this);
+  // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
+  if (cc == gt || cc == le) {
+    cc = ReverseCondition(cc);
+    frame_->EmitPop(r1);
+    frame_->EmitPop(r0);
+  } else {
+    frame_->EmitPop(r0);
+    frame_->EmitPop(r1);
+  }
+  __ orr(r2, r0, Operand(r1));
+  __ tst(r2, Operand(kSmiTagMask));
+  smi.Branch(eq);
+
+  // Perform non-smi comparison by runtime call.
+  frame_->EmitPush(r1);
+
+  // Figure out which native to call and setup the arguments.
+  Builtins::JavaScript native;
+  int arg_count = 1;
+  if (cc == eq) {
+    native = strict ? Builtins::STRICT_EQUALS : Builtins::EQUALS;
+  } else {
+    native = Builtins::COMPARE;
+    int ncr;  // NaN compare result
+    if (cc == lt || cc == le) {
+      ncr = GREATER;
+    } else {
+      ASSERT(cc == gt || cc == ge);  // remaining cases
+      ncr = LESS;
+    }
+    frame_->EmitPush(r0);
+    arg_count++;
+    __ mov(r0, Operand(Smi::FromInt(ncr)));
+  }
+
+  // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
+  // tagged as a small integer.
+  frame_->EmitPush(r0);
+  Result arg_count_register = allocator_->Allocate(r0);
+  ASSERT(arg_count_register.is_valid());
+  __ mov(arg_count_register.reg(), Operand(arg_count));
+  Result result = frame_->InvokeBuiltin(native,
+                                        CALL_JS,
+                                        &arg_count_register,
+                                        arg_count + 1);
+  __ cmp(result.reg(), Operand(0));
+  result.Unuse();
+  exit.Jump();
+
+  // test smi equality by pointer comparison.
+  smi.Bind();
+  __ cmp(r1, Operand(r0));
+
+  exit.Bind();
+  cc_reg_ = cc;
+}
+
+
+class CallFunctionStub: public CodeStub {
+ public:
+  explicit CallFunctionStub(int argc) : argc_(argc) {}
+
+  void Generate(MacroAssembler* masm);
+
+ private:
+  int argc_;
+
+#if defined(DEBUG)
+  void Print() { PrintF("CallFunctionStub (argc %d)\n", argc_); }
+#endif  // defined(DEBUG)
+
+  Major MajorKey() { return CallFunction; }
+  int MinorKey() { return argc_; }
+};
+
+
+// Call the function on the stack with the given arguments.
+void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
+                                         int position) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  // Push the arguments ("left-to-right") on the stack.
+  int arg_count = args->length();
+  for (int i = 0; i < arg_count; i++) {
+    LoadAndSpill(args->at(i));
+  }
+
+  // Record the position for debugging purposes.
+  CodeForSourcePosition(position);
+
+  // Use the shared code stub to call the function.
+  CallFunctionStub call_function(arg_count);
+  frame_->CallStub(&call_function, arg_count + 1);
+
+  // Restore context and pop function from the stack.
+  __ ldr(cp, frame_->Context());
+  frame_->Drop();  // discard the TOS
+}
+
+
+void CodeGenerator::Branch(bool if_true, JumpTarget* target) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  ASSERT(has_cc());
+  Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_);
+  target->Branch(cc);
+  cc_reg_ = al;
+}
+
+
+void CodeGenerator::CheckStack() {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  if (FLAG_check_stack) {
+    Comment cmnt(masm_, "[ check stack");
+    StackCheckStub stub;
+    frame_->CallStub(&stub, 0);
+  }
+}
+
+
+void CodeGenerator::VisitAndSpill(Statement* statement) {
+  ASSERT(in_spilled_code());
+  set_in_spilled_code(false);
+  Visit(statement);
+  if (frame_ != NULL) {
+    frame_->SpillAll();
+    }
+  set_in_spilled_code(true);
+}
+
+
+void CodeGenerator::VisitStatementsAndSpill(ZoneList<Statement*>* statements) {
+  ASSERT(in_spilled_code());
+  set_in_spilled_code(false);
+  VisitStatements(statements);
+  if (frame_ != NULL) {
+    frame_->SpillAll();
+  }
+  set_in_spilled_code(true);
+}
+
+
+void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  for (int i = 0; frame_ != NULL && i < statements->length(); i++) {
+    VisitAndSpill(statements->at(i));
+  }
+  ASSERT(!has_valid_frame() || frame_->height() == original_height);
+}
+
+
+void CodeGenerator::VisitBlock(Block* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ Block");
+  CodeForStatementPosition(node);
+  node->break_target()->Initialize(this);
+  VisitStatementsAndSpill(node->statements());
+  if (node->break_target()->is_linked()) {
+    node->break_target()->Bind();
+  }
+  node->break_target()->Unuse();
+  ASSERT(!has_valid_frame() || frame_->height() == original_height);
+}
+
+
+void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  __ mov(r0, Operand(pairs));
+  frame_->EmitPush(r0);
+  frame_->EmitPush(cp);
+  __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
+  frame_->EmitPush(r0);
+  frame_->CallRuntime(Runtime::kDeclareGlobals, 3);
+  // The result is discarded.
+}
+
+
+void CodeGenerator::VisitDeclaration(Declaration* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ Declaration");
+  CodeForStatementPosition(node);
+  Variable* var = node->proxy()->var();
+  ASSERT(var != NULL);  // must have been resolved
+  Slot* slot = var->slot();
+
+  // If it was not possible to allocate the variable at compile time,
+  // we need to "declare" it at runtime to make sure it actually
+  // exists in the local context.
+  if (slot != NULL && slot->type() == Slot::LOOKUP) {
+    // Variables with a "LOOKUP" slot were introduced as non-locals
+    // during variable resolution and must have mode DYNAMIC.
+    ASSERT(var->is_dynamic());
+    // For now, just do a runtime call.
+    frame_->EmitPush(cp);
+    __ mov(r0, Operand(var->name()));
+    frame_->EmitPush(r0);
+    // Declaration nodes are always declared in only two modes.
+    ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST);
+    PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY;
+    __ mov(r0, Operand(Smi::FromInt(attr)));
+    frame_->EmitPush(r0);
+    // Push initial value, if any.
+    // Note: For variables we must not push an initial value (such as
+    // 'undefined') because we may have a (legal) redeclaration and we
+    // must not destroy the current value.
+    if (node->mode() == Variable::CONST) {
+      __ mov(r0, Operand(Factory::the_hole_value()));
+      frame_->EmitPush(r0);
+    } else if (node->fun() != NULL) {
+      LoadAndSpill(node->fun());
+    } else {
+      __ mov(r0, Operand(0));  // no initial value!
+      frame_->EmitPush(r0);
+    }
+    frame_->CallRuntime(Runtime::kDeclareContextSlot, 4);
+    // Ignore the return value (declarations are statements).
+    ASSERT(frame_->height() == original_height);
+    return;
+  }
+
+  ASSERT(!var->is_global());
+
+  // If we have a function or a constant, we need to initialize the variable.
+  Expression* val = NULL;
+  if (node->mode() == Variable::CONST) {
+    val = new Literal(Factory::the_hole_value());
+  } else {
+    val = node->fun();  // NULL if we don't have a function
+  }
+
+  if (val != NULL) {
+    {
+      // Set initial value.
+      Reference target(this, node->proxy());
+      LoadAndSpill(val);
+      target.SetValue(NOT_CONST_INIT);
+      // The reference is removed from the stack (preserving TOS) when
+      // it goes out of scope.
+    }
+    // Get rid of the assigned value (declarations are statements).
+    frame_->Drop();
+  }
+  ASSERT(frame_->height() == original_height);
+}
+
+
+void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ ExpressionStatement");
+  CodeForStatementPosition(node);
+  Expression* expression = node->expression();
+  expression->MarkAsStatement();
+  LoadAndSpill(expression);
+  frame_->Drop();
+  ASSERT(frame_->height() == original_height);
+}
+
+
+void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "// EmptyStatement");
+  CodeForStatementPosition(node);
+  // nothing to do
+  ASSERT(frame_->height() == original_height);
+}
+
+
+void CodeGenerator::VisitIfStatement(IfStatement* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ IfStatement");
+  // Generate different code depending on which parts of the if statement
+  // are present or not.
+  bool has_then_stm = node->HasThenStatement();
+  bool has_else_stm = node->HasElseStatement();
+
+  CodeForStatementPosition(node);
+
+  JumpTarget exit(this);
+  if (has_then_stm && has_else_stm) {
+    Comment cmnt(masm_, "[ IfThenElse");
+    JumpTarget then(this);
+    JumpTarget else_(this);
+    // if (cond)
+    LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
+                          &then, &else_, true);
+    if (frame_ != NULL) {
+      Branch(false, &else_);
+    }
+    // then
+    if (frame_ != NULL || then.is_linked()) {
+      then.Bind();
+      VisitAndSpill(node->then_statement());
+    }
+    if (frame_ != NULL) {
+      exit.Jump();
+    }
+    // else
+    if (else_.is_linked()) {
+      else_.Bind();
+      VisitAndSpill(node->else_statement());
+    }
+
+  } else if (has_then_stm) {
+    Comment cmnt(masm_, "[ IfThen");
+    ASSERT(!has_else_stm);
+    JumpTarget then(this);
+    // if (cond)
+    LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
+                          &then, &exit, true);
+    if (frame_ != NULL) {
+      Branch(false, &exit);
+    }
+    // then
+    if (frame_ != NULL || then.is_linked()) {
+      then.Bind();
+      VisitAndSpill(node->then_statement());
+    }
+
+  } else if (has_else_stm) {
+    Comment cmnt(masm_, "[ IfElse");
+    ASSERT(!has_then_stm);
+    JumpTarget else_(this);
+    // if (!cond)
+    LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
+                          &exit, &else_, true);
+    if (frame_ != NULL) {
+      Branch(true, &exit);
+    }
+    // else
+    if (frame_ != NULL || else_.is_linked()) {
+      else_.Bind();
+      VisitAndSpill(node->else_statement());
+    }
+
+  } else {
+    Comment cmnt(masm_, "[ If");
+    ASSERT(!has_then_stm && !has_else_stm);
+    // if (cond)
+    LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
+                          &exit, &exit, false);
+    if (frame_ != NULL) {
+      if (has_cc()) {
+        cc_reg_ = al;
+      } else {
+        frame_->Drop();
+      }
+    }
+  }
+
+  // end
+  if (exit.is_linked()) {
+    exit.Bind();
+  }
+  ASSERT(!has_valid_frame() || frame_->height() == original_height);
+}
+
+
+void CodeGenerator::VisitContinueStatement(ContinueStatement* node) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ ContinueStatement");
+  CodeForStatementPosition(node);
+  node->target()->continue_target()->Jump();
+}
+
+
+void CodeGenerator::VisitBreakStatement(BreakStatement* node) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ BreakStatement");
+  CodeForStatementPosition(node);
+  node->target()->break_target()->Jump();
+}
+
+
+void CodeGenerator::VisitReturnStatement(ReturnStatement* node) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ ReturnStatement");
+
+  if (function_return_is_shadowed_) {
+    CodeForStatementPosition(node);
+    LoadAndSpill(node->expression());
+    frame_->EmitPop(r0);
+    function_return_.Jump();
+  } else {
+    // Load the returned value.
+    CodeForStatementPosition(node);
+    LoadAndSpill(node->expression());
+
+    // Pop the result from the frame and prepare the frame for
+    // returning thus making it easier to merge.
+    frame_->EmitPop(r0);
+    frame_->PrepareForReturn();
+
+    function_return_.Jump();
+  }
+}
+
+
+void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ WithEnterStatement");
+  CodeForStatementPosition(node);
+  LoadAndSpill(node->expression());
+  if (node->is_catch_block()) {
+    frame_->CallRuntime(Runtime::kPushCatchContext, 1);
+  } else {
+    frame_->CallRuntime(Runtime::kPushContext, 1);
+  }
+  if (kDebug) {
+    JumpTarget verified_true(this);
+    __ cmp(r0, Operand(cp));
+    verified_true.Branch(eq);
+    __ stop("PushContext: r0 is expected to be the same as cp");
+    verified_true.Bind();
+  }
+  // Update context local.
+  __ str(cp, frame_->Context());
+  ASSERT(frame_->height() == original_height);
+}
+
+
+void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ WithExitStatement");
+  CodeForStatementPosition(node);
+  // Pop context.
+  __ ldr(cp, ContextOperand(cp, Context::PREVIOUS_INDEX));
+  // Update context local.
+  __ str(cp, frame_->Context());
+  ASSERT(frame_->height() == original_height);
+}
+
+
+int CodeGenerator::FastCaseSwitchMaxOverheadFactor() {
+  return kFastSwitchMaxOverheadFactor;
+}
+
+int CodeGenerator::FastCaseSwitchMinCaseCount() {
+  return kFastSwitchMinCaseCount;
+}
+
+
+void CodeGenerator::GenerateFastCaseSwitchJumpTable(
+    SwitchStatement* node,
+    int min_index,
+    int range,
+    Label* default_label,
+    Vector<Label*> case_targets,
+    Vector<Label> case_labels) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  JumpTarget setup_default(this);
+  JumpTarget is_smi(this);
+
+  // A non-null default label pointer indicates a default case among
+  // the case labels.  Otherwise we use the break target as a
+  // "default" for failure to hit the jump table.
+  JumpTarget* default_target =
+      (default_label == NULL) ? node->break_target() : &setup_default;
+
+  ASSERT(kSmiTag == 0 && kSmiTagSize <= 2);
+  frame_->EmitPop(r0);
+
+  // Test for a Smi value in a HeapNumber.
+  __ tst(r0, Operand(kSmiTagMask));
+  is_smi.Branch(eq);
+  __ ldr(r1, MemOperand(r0, HeapObject::kMapOffset - kHeapObjectTag));
+  __ ldrb(r1, MemOperand(r1, Map::kInstanceTypeOffset - kHeapObjectTag));
+  __ cmp(r1, Operand(HEAP_NUMBER_TYPE));
+  default_target->Branch(ne);
+  frame_->EmitPush(r0);
+  frame_->CallRuntime(Runtime::kNumberToSmi, 1);
+  is_smi.Bind();
+
+  if (min_index != 0) {
+    // Small positive numbers can be immediate operands.
+    if (min_index < 0) {
+      // If min_index is Smi::kMinValue, -min_index is not a Smi.
+      if (Smi::IsValid(-min_index)) {
+        __ add(r0, r0, Operand(Smi::FromInt(-min_index)));
+      } else {
+        __ add(r0, r0, Operand(Smi::FromInt(-min_index - 1)));
+        __ add(r0, r0, Operand(Smi::FromInt(1)));
+      }
+    } else {
+      __ sub(r0, r0, Operand(Smi::FromInt(min_index)));
+    }
+  }
+  __ tst(r0, Operand(0x80000000 | kSmiTagMask));
+  default_target->Branch(ne);
+  __ cmp(r0, Operand(Smi::FromInt(range)));
+  default_target->Branch(ge);
+  VirtualFrame* start_frame = new VirtualFrame(frame_);
+  __ SmiJumpTable(r0, case_targets);
+
+  GenerateFastCaseSwitchCases(node, case_labels, start_frame);
+
+  // If there was a default case among the case labels, we need to
+  // emit code to jump to it from the default target used for failure
+  // to hit the jump table.
+  if (default_label != NULL) {
+    if (has_valid_frame()) {
+      node->break_target()->Jump();
+    }
+    setup_default.Bind();
+    frame_->MergeTo(start_frame);
+    __ b(default_label);
+    DeleteFrame();
+  }
+  if (node->break_target()->is_linked()) {
+    node->break_target()->Bind();
+  }
+
+  delete start_frame;
+}
+
+
+void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ SwitchStatement");
+  CodeForStatementPosition(node);
+  node->break_target()->Initialize(this);
+
+  LoadAndSpill(node->tag());
+  if (TryGenerateFastCaseSwitchStatement(node)) {
+    ASSERT(!has_valid_frame() || frame_->height() == original_height);
+    return;
+  }
+
+  JumpTarget next_test(this);
+  JumpTarget fall_through(this);
+  JumpTarget default_entry(this);
+  JumpTarget default_exit(this, JumpTarget::BIDIRECTIONAL);
+  ZoneList<CaseClause*>* cases = node->cases();
+  int length = cases->length();
+  CaseClause* default_clause = NULL;
+
+  for (int i = 0; i < length; i++) {
+    CaseClause* clause = cases->at(i);
+    if (clause->is_default()) {
+      // Remember the default clause and compile it at the end.
+      default_clause = clause;
+      continue;
+    }
+
+    Comment cmnt(masm_, "[ Case clause");
+    // Compile the test.
+    next_test.Bind();
+    next_test.Unuse();
+    // Duplicate TOS.
+    __ ldr(r0, frame_->Top());
+    frame_->EmitPush(r0);
+    LoadAndSpill(clause->label());
+    Comparison(eq, true);
+    Branch(false, &next_test);
+
+    // Before entering the body from the test, remove the switch value from
+    // the stack.
+    frame_->Drop();
+
+    // Label the body so that fall through is enabled.
+    if (i > 0 && cases->at(i - 1)->is_default()) {
+      default_exit.Bind();
+    } else {
+      fall_through.Bind();
+      fall_through.Unuse();
+    }
+    VisitStatementsAndSpill(clause->statements());
+
+    // If control flow can fall through from the body, jump to the next body
+    // or the end of the statement.
+    if (frame_ != NULL) {
+      if (i < length - 1 && cases->at(i + 1)->is_default()) {
+        default_entry.Jump();
+      } else {
+        fall_through.Jump();
+      }
+    }
+  }
+
+  // The final "test" removes the switch value.
+  next_test.Bind();
+  frame_->Drop();
+
+  // If there is a default clause, compile it.
+  if (default_clause != NULL) {
+    Comment cmnt(masm_, "[ Default clause");
+    default_entry.Bind();
+    VisitStatementsAndSpill(default_clause->statements());
+    // If control flow can fall out of the default and there is a case after
+    // it, jup to that case's body.
+    if (frame_ != NULL && default_exit.is_bound()) {
+      default_exit.Jump();
+    }
+  }
+
+  if (fall_through.is_linked()) {
+    fall_through.Bind();
+  }
+
+  if (node->break_target()->is_linked()) {
+    node->break_target()->Bind();
+  }
+  node->break_target()->Unuse();
+  ASSERT(!has_valid_frame() || frame_->height() == original_height);
+}
+
+
+void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ LoopStatement");
+  CodeForStatementPosition(node);
+  node->break_target()->Initialize(this);
+
+  // Simple condition analysis.  ALWAYS_TRUE and ALWAYS_FALSE represent a
+  // known result for the test expression, with no side effects.
+  enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW;
+  if (node->cond() == NULL) {
+    ASSERT(node->type() == LoopStatement::FOR_LOOP);
+    info = ALWAYS_TRUE;
+  } else {
+    Literal* lit = node->cond()->AsLiteral();
+    if (lit != NULL) {
+      if (lit->IsTrue()) {
+        info = ALWAYS_TRUE;
+      } else if (lit->IsFalse()) {
+        info = ALWAYS_FALSE;
+      }
+    }
+  }
+
+  switch (node->type()) {
+    case LoopStatement::DO_LOOP: {
+      JumpTarget body(this, JumpTarget::BIDIRECTIONAL);
+
+      // Label the top of the loop for the backward CFG edge.  If the test
+      // is always true we can use the continue target, and if the test is
+      // always false there is no need.
+      if (info == ALWAYS_TRUE) {
+        node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
+        node->continue_target()->Bind();
+      } else if (info == ALWAYS_FALSE) {
+        node->continue_target()->Initialize(this);
+      } else {
+        ASSERT(info == DONT_KNOW);
+        node->continue_target()->Initialize(this);
+        body.Bind();
+      }
+
+      CheckStack();  // TODO(1222600): ignore if body contains calls.
+      VisitAndSpill(node->body());
+
+      // Compile the test.
+      if (info == ALWAYS_TRUE) {
+        if (has_valid_frame()) {
+          // If control can fall off the end of the body, jump back to the
+          // top.
+          node->continue_target()->Jump();
+        }
+      } else if (info == ALWAYS_FALSE) {
+        // If we have a continue in the body, we only have to bind its jump
+        // target.
+        if (node->continue_target()->is_linked()) {
+          node->continue_target()->Bind();
+        }
+      } else {
+        ASSERT(info == DONT_KNOW);
+        // We have to compile the test expression if it can be reached by
+        // control flow falling out of the body or via continue.
+        if (node->continue_target()->is_linked()) {
+          node->continue_target()->Bind();
+        }
+        if (has_valid_frame()) {
+          LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF,
+                                &body, node->break_target(), true);
+          if (has_valid_frame()) {
+            // A invalid frame here indicates that control did not
+            // fall out of the test expression.
+            Branch(true, &body);
+          }
+        }
+      }
+      break;
+    }
+
+    case LoopStatement::WHILE_LOOP: {
+      // If the test is never true and has no side effects there is no need
+      // to compile the test or body.
+      if (info == ALWAYS_FALSE) break;
+
+      // Label the top of the loop with the continue target for the backward
+      // CFG edge.
+      node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
+      node->continue_target()->Bind();
+
+      if (info == DONT_KNOW) {
+        JumpTarget body(this);
+        LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF,
+                              &body, node->break_target(), true);
+        if (has_valid_frame()) {
+          // A NULL frame indicates that control did not fall out of the
+          // test expression.
+          Branch(false, node->break_target());
+        }
+        if (has_valid_frame() || body.is_linked()) {
+          body.Bind();
+        }
+      }
+
+      if (has_valid_frame()) {
+        CheckStack();  // TODO(1222600): ignore if body contains calls.
+        VisitAndSpill(node->body());
+
+        // If control flow can fall out of the body, jump back to the top.
+        if (has_valid_frame()) {
+          node->continue_target()->Jump();
+        }
+      }
+      break;
+    }
+
+    case LoopStatement::FOR_LOOP: {
+      JumpTarget loop(this, JumpTarget::BIDIRECTIONAL);
+
+      if (node->init() != NULL) {
+        VisitAndSpill(node->init());
+      }
+
+      // There is no need to compile the test or body.
+      if (info == ALWAYS_FALSE) break;
+
+      // If there is no update statement, label the top of the loop with the
+      // continue target, otherwise with the loop target.
+      if (node->next() == NULL) {
+        node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
+        node->continue_target()->Bind();
+      } else {
+        node->continue_target()->Initialize(this);
+        loop.Bind();
+      }
+
+      // If the test is always true, there is no need to compile it.
+      if (info == DONT_KNOW) {
+        JumpTarget body(this);
+        LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF,
+                              &body, node->break_target(), true);
+        if (has_valid_frame()) {
+          Branch(false, node->break_target());
+        }
+        if (has_valid_frame() || body.is_linked()) {
+          body.Bind();
+        }
+      }
+
+      if (has_valid_frame()) {
+        CheckStack();  // TODO(1222600): ignore if body contains calls.
+        VisitAndSpill(node->body());
+
+        if (node->next() == NULL) {
+          // If there is no update statement and control flow can fall out
+          // of the loop, jump directly to the continue label.
+          if (has_valid_frame()) {
+            node->continue_target()->Jump();
+          }
+        } else {
+          // If there is an update statement and control flow can reach it
+          // via falling out of the body of the loop or continuing, we
+          // compile the update statement.
+          if (node->continue_target()->is_linked()) {
+            node->continue_target()->Bind();
+          }
+          if (has_valid_frame()) {
+            // Record source position of the statement as this code which is
+            // after the code for the body actually belongs to the loop
+            // statement and not the body.
+            CodeForStatementPosition(node);
+            VisitAndSpill(node->next());
+            loop.Jump();
+          }
+        }
+      }
+      break;
+    }
+  }
+
+  if (node->break_target()->is_linked()) {
+    node->break_target()->Bind();
+  }
+  node->continue_target()->Unuse();
+  node->break_target()->Unuse();
+  ASSERT(!has_valid_frame() || frame_->height() == original_height);
+}
+
+
+void CodeGenerator::VisitForInStatement(ForInStatement* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  ASSERT(!in_spilled_code());
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ ForInStatement");
+  CodeForStatementPosition(node);
+
+  JumpTarget primitive(this);
+  JumpTarget jsobject(this);
+  JumpTarget fixed_array(this);
+  JumpTarget entry(this, JumpTarget::BIDIRECTIONAL);
+  JumpTarget end_del_check(this);
+  JumpTarget exit(this);
+
+  // Get the object to enumerate over (converted to JSObject).
+  LoadAndSpill(node->enumerable());
+
+  // Both SpiderMonkey and kjs ignore null and undefined in contrast
+  // to the specification.  12.6.4 mandates a call to ToObject.
+  frame_->EmitPop(r0);
+  __ cmp(r0, Operand(Factory::undefined_value()));
+  exit.Branch(eq);
+  __ cmp(r0, Operand(Factory::null_value()));
+  exit.Branch(eq);
+
+  // Stack layout in body:
+  // [iteration counter (Smi)]
+  // [length of array]
+  // [FixedArray]
+  // [Map or 0]
+  // [Object]
+
+  // Check if enumerable is already a JSObject
+  __ tst(r0, Operand(kSmiTagMask));
+  primitive.Branch(eq);
+  __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
+  __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
+  __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE));
+  jsobject.Branch(hs);
+
+  primitive.Bind();
+  frame_->EmitPush(r0);
+  Result arg_count = allocator_->Allocate(r0);
+  ASSERT(arg_count.is_valid());
+  __ mov(arg_count.reg(), Operand(0));
+  frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS, &arg_count, 1);
+
+  jsobject.Bind();
+  // Get the set of properties (as a FixedArray or Map).
+  frame_->EmitPush(r0);  // duplicate the object being enumerated
+  frame_->EmitPush(r0);
+  frame_->CallRuntime(Runtime::kGetPropertyNamesFast, 1);
+
+  // If we got a Map, we can do a fast modification check.
+  // Otherwise, we got a FixedArray, and we have to do a slow check.
+  __ mov(r2, Operand(r0));
+  __ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset));
+  __ cmp(r1, Operand(Factory::meta_map()));
+  fixed_array.Branch(ne);
+
+  // Get enum cache
+  __ mov(r1, Operand(r0));
+  __ ldr(r1, FieldMemOperand(r1, Map::kInstanceDescriptorsOffset));
+  __ ldr(r1, FieldMemOperand(r1, DescriptorArray::kEnumerationIndexOffset));
+  __ ldr(r2,
+         FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset));
+
+  frame_->EmitPush(r0);  // map
+  frame_->EmitPush(r2);  // enum cache bridge cache
+  __ ldr(r0, FieldMemOperand(r2, FixedArray::kLengthOffset));
+  __ mov(r0, Operand(r0, LSL, kSmiTagSize));
+  frame_->EmitPush(r0);
+  __ mov(r0, Operand(Smi::FromInt(0)));
+  frame_->EmitPush(r0);
+  entry.Jump();
+
+  fixed_array.Bind();
+  __ mov(r1, Operand(Smi::FromInt(0)));
+  frame_->EmitPush(r1);  // insert 0 in place of Map
+  frame_->EmitPush(r0);
+
+  // Push the length of the array and the initial index onto the stack.
+  __ ldr(r0, FieldMemOperand(r0, FixedArray::kLengthOffset));
+  __ mov(r0, Operand(r0, LSL, kSmiTagSize));
+  frame_->EmitPush(r0);
+  __ mov(r0, Operand(Smi::FromInt(0)));  // init index
+  frame_->EmitPush(r0);
+
+  // Condition.
+  entry.Bind();
+  // sp[0] : index
+  // sp[1] : array/enum cache length
+  // sp[2] : array or enum cache
+  // sp[3] : 0 or map
+  // sp[4] : enumerable
+  // Grab the current frame's height for the break and continue
+  // targets only after all the state is pushed on the frame.
+  node->break_target()->Initialize(this);
+  node->continue_target()->Initialize(this);
+
+  __ ldr(r0, frame_->ElementAt(0));  // load the current count
+  __ ldr(r1, frame_->ElementAt(1));  // load the length
+  __ cmp(r0, Operand(r1));  // compare to the array length
+  node->break_target()->Branch(hs);
+
+  __ ldr(r0, frame_->ElementAt(0));
+
+  // Get the i'th entry of the array.
+  __ ldr(r2, frame_->ElementAt(2));
+  __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize));
+
+  // Get Map or 0.
+  __ ldr(r2, frame_->ElementAt(3));
+  // Check if this (still) matches the map of the enumerable.
+  // If not, we have to filter the key.
+  __ ldr(r1, frame_->ElementAt(4));
+  __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
+  __ cmp(r1, Operand(r2));
+  end_del_check.Branch(eq);
+
+  // Convert the entry to a string (or null if it isn't a property anymore).
+  __ ldr(r0, frame_->ElementAt(4));  // push enumerable
+  frame_->EmitPush(r0);
+  frame_->EmitPush(r3);  // push entry
+  Result arg_count_register = allocator_->Allocate(r0);
+  ASSERT(arg_count_register.is_valid());
+  __ mov(arg_count_register.reg(), Operand(1));
+  Result result = frame_->InvokeBuiltin(Builtins::FILTER_KEY,
+                                        CALL_JS,
+                                        &arg_count_register,
+                                        2);
+  __ mov(r3, Operand(result.reg()));
+  result.Unuse();
+
+  // If the property has been removed while iterating, we just skip it.
+  __ cmp(r3, Operand(Factory::null_value()));
+  node->continue_target()->Branch(eq);
+
+  end_del_check.Bind();
+  // Store the entry in the 'each' expression and take another spin in the
+  // loop.  r3: i'th entry of the enum cache (or string there of)
+  frame_->EmitPush(r3);  // push entry
+  { Reference each(this, node->each());
+    if (!each.is_illegal()) {
+      if (each.size() > 0) {
+        __ ldr(r0, frame_->ElementAt(each.size()));
+        frame_->EmitPush(r0);
+      }
+      // If the reference was to a slot we rely on the convenient property
+      // that it doesn't matter whether a value (eg, r3 pushed above) is
+      // right on top of or right underneath a zero-sized reference.
+      each.SetValue(NOT_CONST_INIT);
+      if (each.size() > 0) {
+        // It's safe to pop the value lying on top of the reference before
+        // unloading the reference itself (which preserves the top of stack,
+        // ie, now the topmost value of the non-zero sized reference), since
+        // we will discard the top of stack after unloading the reference
+        // anyway.
+        frame_->EmitPop(r0);
+      }
+    }
+  }
+  // Discard the i'th entry pushed above or else the remainder of the
+  // reference, whichever is currently on top of the stack.
+  frame_->Drop();
+
+  // Body.
+  CheckStack();  // TODO(1222600): ignore if body contains calls.
+  VisitAndSpill(node->body());
+
+  // Next.  Reestablish a spilled frame in case we are coming here via
+  // a continue in the body.
+  node->continue_target()->Bind();
+  frame_->SpillAll();
+  frame_->EmitPop(r0);
+  __ add(r0, r0, Operand(Smi::FromInt(1)));
+  frame_->EmitPush(r0);
+  entry.Jump();
+
+  // Cleanup.  No need to spill because VirtualFrame::Drop is safe for
+  // any frame.
+  node->break_target()->Bind();
+  frame_->Drop(5);
+
+  // Exit.
+  exit.Bind();
+  node->continue_target()->Unuse();
+  node->break_target()->Unuse();
+  ASSERT(frame_->height() == original_height);
+}
+
+
+void CodeGenerator::VisitTryCatch(TryCatch* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ TryCatch");
+  CodeForStatementPosition(node);
+
+  JumpTarget try_block(this);
+  JumpTarget exit(this);
+
+  try_block.Call();
+  // --- Catch block ---
+  frame_->EmitPush(r0);
+
+  // Store the caught exception in the catch variable.
+  { Reference ref(this, node->catch_var());
+    ASSERT(ref.is_slot());
+    // Here we make use of the convenient property that it doesn't matter
+    // whether a value is immediately on top of or underneath a zero-sized
+    // reference.
+    ref.SetValue(NOT_CONST_INIT);
+  }
+
+  // Remove the exception from the stack.
+  frame_->Drop();
+
+  VisitStatementsAndSpill(node->catch_block()->statements());
+  if (frame_ != NULL) {
+    exit.Jump();
+  }
+
+
+  // --- Try block ---
+  try_block.Bind();
+
+  frame_->PushTryHandler(TRY_CATCH_HANDLER);
+  int handler_height = frame_->height();
+
+  // Shadow the labels for all escapes from the try block, including
+  // returns. During shadowing, the original label is hidden as the
+  // LabelShadow and operations on the original actually affect the
+  // shadowing label.
+  //
+  // We should probably try to unify the escaping labels and the return
+  // label.
+  int nof_escapes = node->escaping_targets()->length();
+  List<ShadowTarget*> shadows(1 + nof_escapes);
+
+  // Add the shadow target for the function return.
+  static const int kReturnShadowIndex = 0;
+  shadows.Add(new ShadowTarget(&function_return_));
+  bool function_return_was_shadowed = function_return_is_shadowed_;
+  function_return_is_shadowed_ = true;
+  ASSERT(shadows[kReturnShadowIndex]->other_target() == &function_return_);
+
+  // Add the remaining shadow targets.
+  for (int i = 0; i < nof_escapes; i++) {
+    shadows.Add(new ShadowTarget(node->escaping_targets()->at(i)));
+  }
+
+  // Generate code for the statements in the try block.
+  VisitStatementsAndSpill(node->try_block()->statements());
+
+  // Stop the introduced shadowing and count the number of required unlinks.
+  // After shadowing stops, the original labels are unshadowed and the
+  // LabelShadows represent the formerly shadowing labels.
+  bool has_unlinks = false;
+  for (int i = 0; i < shadows.length(); i++) {
+    shadows[i]->StopShadowing();
+    has_unlinks = has_unlinks || shadows[i]->is_linked();
+  }
+  function_return_is_shadowed_ = function_return_was_shadowed;
+
+  // Get an external reference to the handler address.
+  ExternalReference handler_address(Top::k_handler_address);
+
+  // The next handler address is at kNextIndex in the stack.
+  const int kNextIndex = StackHandlerConstants::kNextOffset / kPointerSize;
+  // If we can fall off the end of the try block, unlink from try chain.
+  if (has_valid_frame()) {
+    __ ldr(r1, frame_->ElementAt(kNextIndex));
+    __ mov(r3, Operand(handler_address));
+    __ str(r1, MemOperand(r3));
+    frame_->Drop(StackHandlerConstants::kSize / kPointerSize);
+    if (has_unlinks) {
+      exit.Jump();
+    }
+  }
+
+  // Generate unlink code for the (formerly) shadowing labels that have been
+  // jumped to.  Deallocate each shadow target.
+  for (int i = 0; i < shadows.length(); i++) {
+    if (shadows[i]->is_linked()) {
+      // Unlink from try chain;
+      shadows[i]->Bind();
+      // Because we can be jumping here (to spilled code) from unspilled
+      // code, we need to reestablish a spilled frame at this block.
+      frame_->SpillAll();
+
+      // Reload sp from the top handler, because some statements that we
+      // break from (eg, for...in) may have left stuff on the stack.
+      __ mov(r3, Operand(handler_address));
+      __ ldr(sp, MemOperand(r3));
+      // The stack pointer was restored to just below the code slot
+      // (the topmost slot) in the handler.
+      frame_->Forget(frame_->height() - handler_height + 1);
+
+      // kNextIndex is off by one because the code slot has already
+      // been dropped.
+      __ ldr(r1, frame_->ElementAt(kNextIndex - 1));
+      __ str(r1, MemOperand(r3));
+      // The code slot has already been dropped from the handler.
+      frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
+
+      if (!function_return_is_shadowed_ && i == kReturnShadowIndex) {
+        frame_->PrepareForReturn();
+      }
+      shadows[i]->other_target()->Jump();
+    }
+    delete shadows[i];
+  }
+
+  exit.Bind();
+  ASSERT(!has_valid_frame() || frame_->height() == original_height);
+}
+
+
+void CodeGenerator::VisitTryFinally(TryFinally* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ TryFinally");
+  CodeForStatementPosition(node);
+
+  // State: Used to keep track of reason for entering the finally
+  // block. Should probably be extended to hold information for
+  // break/continue from within the try block.
+  enum { FALLING, THROWING, JUMPING };
+
+  JumpTarget try_block(this);
+  JumpTarget finally_block(this);
+
+  try_block.Call();
+
+  frame_->EmitPush(r0);  // save exception object on the stack
+  // In case of thrown exceptions, this is where we continue.
+  __ mov(r2, Operand(Smi::FromInt(THROWING)));
+  finally_block.Jump();
+
+  // --- Try block ---
+  try_block.Bind();
+
+  frame_->PushTryHandler(TRY_FINALLY_HANDLER);
+  int handler_height = frame_->height();
+
+  // Shadow the labels for all escapes from the try block, including
+  // returns.  Shadowing hides the original label as the LabelShadow and
+  // operations on the original actually affect the shadowing label.
+  //
+  // We should probably try to unify the escaping labels and the return
+  // label.
+  int nof_escapes = node->escaping_targets()->length();
+  List<ShadowTarget*> shadows(1 + nof_escapes);
+
+  // Add the shadow target for the function return.
+  static const int kReturnShadowIndex = 0;
+  shadows.Add(new ShadowTarget(&function_return_));
+  bool function_return_was_shadowed = function_return_is_shadowed_;
+  function_return_is_shadowed_ = true;
+  ASSERT(shadows[kReturnShadowIndex]->other_target() == &function_return_);
+
+  // Add the remaining shadow targets.
+  for (int i = 0; i < nof_escapes; i++) {
+    shadows.Add(new ShadowTarget(node->escaping_targets()->at(i)));
+  }
+
+  // Generate code for the statements in the try block.
+  VisitStatementsAndSpill(node->try_block()->statements());
+
+  // Stop the introduced shadowing and count the number of required unlinks.
+  // After shadowing stops, the original labels are unshadowed and the
+  // LabelShadows represent the formerly shadowing labels.
+  int nof_unlinks = 0;
+  for (int i = 0; i < shadows.length(); i++) {
+    shadows[i]->StopShadowing();
+    if (shadows[i]->is_linked()) nof_unlinks++;
+  }
+  function_return_is_shadowed_ = function_return_was_shadowed;
+
+  // Get an external reference to the handler address.
+  ExternalReference handler_address(Top::k_handler_address);
+
+  // The next handler address is at kNextIndex in the stack.
+  const int kNextIndex = StackHandlerConstants::kNextOffset / kPointerSize;
+  // If we can fall off the end of the try block, unlink from the try
+  // chain and set the state on the frame to FALLING.
+  if (has_valid_frame()) {
+    __ ldr(r1, frame_->ElementAt(kNextIndex));
+    __ mov(r3, Operand(handler_address));
+    __ str(r1, MemOperand(r3));
+    frame_->Drop(StackHandlerConstants::kSize / kPointerSize);
+
+    // Fake a top of stack value (unneeded when FALLING) and set the
+    // state in r2, then jump around the unlink blocks if any.
+    __ mov(r0, Operand(Factory::undefined_value()));
+    frame_->EmitPush(r0);
+    __ mov(r2, Operand(Smi::FromInt(FALLING)));
+    if (nof_unlinks > 0) {
+      finally_block.Jump();
+    }
+  }
+
+  // Generate code to unlink and set the state for the (formerly)
+  // shadowing targets that have been jumped to.
+  for (int i = 0; i < shadows.length(); i++) {
+    if (shadows[i]->is_linked()) {
+      // If we have come from the shadowed return, the return value is
+      // in (a non-refcounted reference to) r0.  We must preserve it
+      // until it is pushed.
+      //
+      // Because we can be jumping here (to spilled code) from
+      // unspilled code, we need to reestablish a spilled frame at
+      // this block.
+      shadows[i]->Bind();
+      frame_->SpillAll();
+
+      // Reload sp from the top handler, because some statements that
+      // we break from (eg, for...in) may have left stuff on the
+      // stack.
+      __ mov(r3, Operand(handler_address));
+      __ ldr(sp, MemOperand(r3));
+      // The stack pointer was restored to the address slot in the handler.
+      ASSERT(StackHandlerConstants::kNextOffset == 1 * kPointerSize);
+      frame_->Forget(frame_->height() - handler_height + 1);
+
+      // Unlink this handler and drop it from the frame.  The next
+      // handler address is now on top of the frame.
+      frame_->EmitPop(r1);
+      __ str(r1, MemOperand(r3));
+      // The top (code) and the second (handler) slot have both been
+      // dropped already.
+      frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 2);
+
+      if (i == kReturnShadowIndex) {
+        // If this label shadowed the function return, materialize the
+        // return value on the stack.
+        frame_->EmitPush(r0);
+      } else {
+        // Fake TOS for targets that shadowed breaks and continues.
+        __ mov(r0, Operand(Factory::undefined_value()));
+        frame_->EmitPush(r0);
+      }
+      __ mov(r2, Operand(Smi::FromInt(JUMPING + i)));
+      if (--nof_unlinks > 0) {
+        // If this is not the last unlink block, jump around the next.
+        finally_block.Jump();
+      }
+    }
+  }
+
+  // --- Finally block ---
+  finally_block.Bind();
+
+  // Push the state on the stack.
+  frame_->EmitPush(r2);
+
+  // We keep two elements on the stack - the (possibly faked) result
+  // and the state - while evaluating the finally block.
+  //
+  // Generate code for the statements in the finally block.
+  VisitStatementsAndSpill(node->finally_block()->statements());
+
+  if (has_valid_frame()) {
+    // Restore state and return value or faked TOS.
+    frame_->EmitPop(r2);
+    frame_->EmitPop(r0);
+  }
+
+  // Generate code to jump to the right destination for all used
+  // formerly shadowing targets.  Deallocate each shadow target.
+  for (int i = 0; i < shadows.length(); i++) {
+    if (has_valid_frame() && shadows[i]->is_bound()) {
+      JumpTarget* original = shadows[i]->other_target();
+      __ cmp(r2, Operand(Smi::FromInt(JUMPING + i)));
+      if (!function_return_is_shadowed_ && i == kReturnShadowIndex) {
+        JumpTarget skip(this);
+        skip.Branch(ne);
+        frame_->PrepareForReturn();
+        original->Jump();
+        skip.Bind();
+      } else {
+        original->Branch(eq);
+      }
+    }
+    delete shadows[i];
+  }
+
+  if (has_valid_frame()) {
+    // Check if we need to rethrow the exception.
+    JumpTarget exit(this);
+    __ cmp(r2, Operand(Smi::FromInt(THROWING)));
+    exit.Branch(ne);
+
+    // Rethrow exception.
+    frame_->EmitPush(r0);
+    frame_->CallRuntime(Runtime::kReThrow, 1);
+
+    // Done.
+    exit.Bind();
+  }
+  ASSERT(!has_valid_frame() || frame_->height() == original_height);
+}
+
+
+void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ DebuggerStatament");
+  CodeForStatementPosition(node);
+  frame_->CallRuntime(Runtime::kDebugBreak, 0);
+  // Ignore the return value.
+  ASSERT(frame_->height() == original_height);
+}
+
+
+void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  ASSERT(boilerplate->IsBoilerplate());
+
+  // Push the boilerplate on the stack.
+  __ mov(r0, Operand(boilerplate));
+  frame_->EmitPush(r0);
+
+  // Create a new closure.
+  frame_->EmitPush(cp);
+  frame_->CallRuntime(Runtime::kNewClosure, 2);
+  frame_->EmitPush(r0);
+}
+
+
+void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ FunctionLiteral");
+
+  // Build the function boilerplate and instantiate it.
+  Handle<JSFunction> boilerplate = BuildBoilerplate(node);
+  // Check for stack-overflow exception.
+  if (HasStackOverflow()) {
+    ASSERT(frame_->height() == original_height);
+    return;
+  }
+  InstantiateBoilerplate(boilerplate);
+  ASSERT(frame_->height() == original_height + 1);
+}
+
+
+void CodeGenerator::VisitFunctionBoilerplateLiteral(
+    FunctionBoilerplateLiteral* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ FunctionBoilerplateLiteral");
+  InstantiateBoilerplate(node->boilerplate());
+  ASSERT(frame_->height() == original_height + 1);
+}
+
+
+void CodeGenerator::VisitConditional(Conditional* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ Conditional");
+  JumpTarget then(this);
+  JumpTarget else_(this);
+  JumpTarget exit(this);
+  LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
+                        &then, &else_, true);
+  Branch(false, &else_);
+  then.Bind();
+  LoadAndSpill(node->then_expression(), typeof_state());
+  exit.Jump();
+  else_.Bind();
+  LoadAndSpill(node->else_expression(), typeof_state());
+  exit.Bind();
+  ASSERT(frame_->height() == original_height + 1);
+}
+
+
+void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  if (slot->type() == Slot::LOOKUP) {
+    ASSERT(slot->var()->is_dynamic());
+
+    JumpTarget slow(this);
+    JumpTarget done(this);
+
+    // Generate fast-case code for variables that might be shadowed by
+    // eval-introduced variables.  Eval is used a lot without
+    // introducing variables.  In those cases, we do not want to
+    // perform a runtime call for all variables in the scope
+    // containing the eval.
+    if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
+      LoadFromGlobalSlotCheckExtensions(slot, typeof_state, r1, r2, &slow);
+      // If there was no control flow to slow, we can exit early.
+      if (!slow.is_linked()) {
+        frame_->EmitPush(r0);
+        return;
+      }
+
+      done.Jump();
+
+    } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
+      Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot();
+      // Only generate the fast case for locals that rewrite to slots.
+      // This rules out argument loads.
+      if (potential_slot != NULL) {
+        __ ldr(r0,
+               ContextSlotOperandCheckExtensions(potential_slot,
+                                                 r1,
+                                                 r2,
+                                                 &slow));
+        if (potential_slot->var()->mode() == Variable::CONST) {
+          __ cmp(r0, Operand(Factory::the_hole_value()));
+          __ mov(r0, Operand(Factory::undefined_value()), LeaveCC, eq);
+        }
+        // There is always control flow to slow from
+        // ContextSlotOperandCheckExtensions so we have to jump around
+        // it.
+        done.Jump();
+      }
+    }
+
+    slow.Bind();
+    frame_->EmitPush(cp);
+    __ mov(r0, Operand(slot->var()->name()));
+    frame_->EmitPush(r0);
+
+    if (typeof_state == INSIDE_TYPEOF) {
+      frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
+    } else {
+      frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
+    }
+
+    done.Bind();
+    frame_->EmitPush(r0);
+
+  } else {
+    // Note: We would like to keep the assert below, but it fires because of
+    // some nasty code in LoadTypeofExpression() which should be removed...
+    // ASSERT(!slot->var()->is_dynamic());
+
+    // Special handling for locals allocated in registers.
+    __ ldr(r0, SlotOperand(slot, r2));
+    frame_->EmitPush(r0);
+    if (slot->var()->mode() == Variable::CONST) {
+      // Const slots may contain 'the hole' value (the constant hasn't been
+      // initialized yet) which needs to be converted into the 'undefined'
+      // value.
+      Comment cmnt(masm_, "[ Unhole const");
+      frame_->EmitPop(r0);
+      __ cmp(r0, Operand(Factory::the_hole_value()));
+      __ mov(r0, Operand(Factory::undefined_value()), LeaveCC, eq);
+      frame_->EmitPush(r0);
+    }
+  }
+}
+
+
+void CodeGenerator::LoadFromGlobalSlotCheckExtensions(Slot* slot,
+                                                      TypeofState typeof_state,
+                                                      Register tmp,
+                                                      Register tmp2,
+                                                      JumpTarget* slow) {
+  // Check that no extension objects have been created by calls to
+  // eval from the current scope to the global scope.
+  Register context = cp;
+  Scope* s = scope();
+  while (s != NULL) {
+    if (s->num_heap_slots() > 0) {
+      if (s->calls_eval()) {
+        // Check that extension is NULL.
+        __ ldr(tmp2, ContextOperand(context, Context::EXTENSION_INDEX));
+        __ tst(tmp2, tmp2);
+        slow->Branch(ne);
+      }
+      // Load next context in chain.
+      __ ldr(tmp, ContextOperand(context, Context::CLOSURE_INDEX));
+      __ ldr(tmp, FieldMemOperand(tmp, JSFunction::kContextOffset));
+      context = tmp;
+    }
+    // If no outer scope calls eval, we do not need to check more
+    // context extensions.
+    if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break;
+    s = s->outer_scope();
+  }
+
+  if (s->is_eval_scope()) {
+    Label next, fast;
+    if (!context.is(tmp)) __ mov(tmp, Operand(context));
+    __ bind(&next);
+    // Terminate at global context.
+    __ ldr(tmp2, FieldMemOperand(tmp, HeapObject::kMapOffset));
+    __ cmp(tmp2, Operand(Factory::global_context_map()));
+    __ b(eq, &fast);
+    // Check that extension is NULL.
+    __ ldr(tmp2, ContextOperand(tmp, Context::EXTENSION_INDEX));
+    __ tst(tmp2, tmp2);
+    slow->Branch(ne);
+    // Load next context in chain.
+    __ ldr(tmp, ContextOperand(tmp, Context::CLOSURE_INDEX));
+    __ ldr(tmp, FieldMemOperand(tmp, JSFunction::kContextOffset));
+    __ b(&next);
+    __ bind(&fast);
+  }
+
+  // All extension objects were empty and it is safe to use a global
+  // load IC call.
+  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+  // Load the global object.
+  LoadGlobal();
+  // Setup the name register.
+  Result name = allocator_->Allocate(r2);
+  ASSERT(name.is_valid());  // We are in spilled code.
+  __ mov(name.reg(), Operand(slot->var()->name()));
+  // Call IC stub.
+  if (typeof_state == INSIDE_TYPEOF) {
+    frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, &name, 0);
+  } else {
+    frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, &name, 0);
+  }
+
+  // Drop the global object. The result is in r0.
+  frame_->Drop();
+}
+
+
+void CodeGenerator::VisitSlot(Slot* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ Slot");
+  LoadFromSlot(node, typeof_state());
+  ASSERT(frame_->height() == original_height + 1);
+}
+
+
+void CodeGenerator::VisitVariableProxy(VariableProxy* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ VariableProxy");
+
+  Variable* var = node->var();
+  Expression* expr = var->rewrite();
+  if (expr != NULL) {
+    Visit(expr);
+  } else {
+    ASSERT(var->is_global());
+    Reference ref(this, node);
+    ref.GetValueAndSpill(typeof_state());
+  }
+  ASSERT(frame_->height() == original_height + 1);
+}
+
+
+void CodeGenerator::VisitLiteral(Literal* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ Literal");
+  __ mov(r0, Operand(node->handle()));
+  frame_->EmitPush(r0);
+  ASSERT(frame_->height() == original_height + 1);
+}
+
+
+void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ RexExp Literal");
+
+  // Retrieve the literal array and check the allocated entry.
+
+  // Load the function of this activation.
+  __ ldr(r1, frame_->Function());
+
+  // Load the literals array of the function.
+  __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset));
+
+  // Load the literal at the ast saved index.
+  int literal_offset =
+      FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
+  __ ldr(r2, FieldMemOperand(r1, literal_offset));
+
+  JumpTarget done(this);
+  __ cmp(r2, Operand(Factory::undefined_value()));
+  done.Branch(ne);
+
+  // If the entry is undefined we call the runtime system to computed
+  // the literal.
+  frame_->EmitPush(r1);  // literal array  (0)
+  __ mov(r0, Operand(Smi::FromInt(node->literal_index())));
+  frame_->EmitPush(r0);  // literal index  (1)
+  __ mov(r0, Operand(node->pattern()));  // RegExp pattern (2)
+  frame_->EmitPush(r0);
+  __ mov(r0, Operand(node->flags()));  // RegExp flags   (3)
+  frame_->EmitPush(r0);
+  frame_->CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
+  __ mov(r2, Operand(r0));
+
+  done.Bind();
+  // Push the literal.
+  frame_->EmitPush(r2);
+  ASSERT(frame_->height() == original_height + 1);
+}
+
+
+// This deferred code stub will be used for creating the boilerplate
+// by calling Runtime_CreateObjectLiteralBoilerplate.
+// Each created boilerplate is stored in the JSFunction and they are
+// therefore context dependent.
+class DeferredObjectLiteral: public DeferredCode {
+ public:
+  DeferredObjectLiteral(CodeGenerator* generator, ObjectLiteral* node)
+      : DeferredCode(generator), node_(node) {
+    set_comment("[ DeferredObjectLiteral");
+  }
+
+  virtual void Generate();
+
+ private:
+  ObjectLiteral* node_;
+};
+
+
+void DeferredObjectLiteral::Generate() {
+  // Argument is passed in r1.
+  enter()->Bind();
+  VirtualFrame::SpilledScope spilled_scope(generator());
+
+  // If the entry is undefined we call the runtime system to compute
+  // the literal.
+
+  VirtualFrame* frame = generator()->frame();
+  // Literal array (0).
+  frame->EmitPush(r1);
+  // Literal index (1).
+  __ mov(r0, Operand(Smi::FromInt(node_->literal_index())));
+  frame->EmitPush(r0);
+  // Constant properties (2).
+  __ mov(r0, Operand(node_->constant_properties()));
+  frame->EmitPush(r0);
+  Result boilerplate =
+      frame->CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3);
+  __ mov(r2, Operand(boilerplate.reg()));
+  // Result is returned in r2.
+  exit_.Jump();
+}
+
+
+void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ ObjectLiteral");
+
+  DeferredObjectLiteral* deferred = new DeferredObjectLiteral(this, node);
+
+  // Retrieve the literal array and check the allocated entry.
+
+  // Load the function of this activation.
+  __ ldr(r1, frame_->Function());
+
+  // Load the literals array of the function.
+  __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset));
+
+  // Load the literal at the ast saved index.
+  int literal_offset =
+      FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
+  __ ldr(r2, FieldMemOperand(r1, literal_offset));
+
+  // Check whether we need to materialize the object literal boilerplate.
+  // If so, jump to the deferred code.
+  __ cmp(r2, Operand(Factory::undefined_value()));
+  deferred->enter()->Branch(eq);
+  deferred->BindExit();
+
+  // Push the object literal boilerplate.
+  frame_->EmitPush(r2);
+
+  // Clone the boilerplate object.
+  Runtime::FunctionId clone_function_id = Runtime::kCloneLiteralBoilerplate;
+  if (node->depth() == 1) {
+    clone_function_id = Runtime::kCloneShallowLiteralBoilerplate;
+  }
+  frame_->CallRuntime(clone_function_id, 1);
+  frame_->EmitPush(r0);  // save the result
+  // r0: cloned object literal
+
+  for (int i = 0; i < node->properties()->length(); i++) {
+    ObjectLiteral::Property* property = node->properties()->at(i);
+    Literal* key = property->key();
+    Expression* value = property->value();
+    switch (property->kind()) {
+      case ObjectLiteral::Property::CONSTANT:
+        break;
+      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
+        if (CompileTimeValue::IsCompileTimeValue(property->value())) break;
+        // else fall through
+      case ObjectLiteral::Property::COMPUTED:  // fall through
+      case ObjectLiteral::Property::PROTOTYPE: {
+        frame_->EmitPush(r0);  // dup the result
+        LoadAndSpill(key);
+        LoadAndSpill(value);
+        frame_->CallRuntime(Runtime::kSetProperty, 3);
+        // restore r0
+        __ ldr(r0, frame_->Top());
+        break;
+      }
+      case ObjectLiteral::Property::SETTER: {
+        frame_->EmitPush(r0);
+        LoadAndSpill(key);
+        __ mov(r0, Operand(Smi::FromInt(1)));
+        frame_->EmitPush(r0);
+        LoadAndSpill(value);
+        frame_->CallRuntime(Runtime::kDefineAccessor, 4);
+        __ ldr(r0, frame_->Top());
+        break;
+      }
+      case ObjectLiteral::Property::GETTER: {
+        frame_->EmitPush(r0);
+        LoadAndSpill(key);
+        __ mov(r0, Operand(Smi::FromInt(0)));
+        frame_->EmitPush(r0);
+        LoadAndSpill(value);
+        frame_->CallRuntime(Runtime::kDefineAccessor, 4);
+        __ ldr(r0, frame_->Top());
+        break;
+      }
+    }
+  }
+  ASSERT(frame_->height() == original_height + 1);
+}
+
+
+// This deferred code stub will be used for creating the boilerplate
+// by calling Runtime_CreateArrayLiteralBoilerplate.
+// Each created boilerplate is stored in the JSFunction and they are
+// therefore context dependent.
+class DeferredArrayLiteral: public DeferredCode {
+ public:
+  DeferredArrayLiteral(CodeGenerator* generator, ArrayLiteral* node)
+      : DeferredCode(generator), node_(node) {
+    set_comment("[ DeferredArrayLiteral");
+  }
+
+  virtual void Generate();
+
+ private:
+  ArrayLiteral* node_;
+};
+
+
+void DeferredArrayLiteral::Generate() {
+  // Argument is passed in r1.
+  enter()->Bind();
+  VirtualFrame::SpilledScope spilled_scope(generator());
+
+  // If the entry is undefined we call the runtime system to computed
+  // the literal.
+
+  VirtualFrame* frame = generator()->frame();
+  // Literal array (0).
+  frame->EmitPush(r1);
+  // Literal index (1).
+  __ mov(r0, Operand(Smi::FromInt(node_->literal_index())));
+  frame->EmitPush(r0);
+  // Constant properties (2).
+  __ mov(r0, Operand(node_->literals()));
+  frame->EmitPush(r0);
+  Result boilerplate =
+      frame->CallRuntime(Runtime::kCreateArrayLiteralBoilerplate, 3);
+  __ mov(r2, Operand(boilerplate.reg()));
+  // Result is returned in r2.
+  exit_.Jump();
+}
+
+
+void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ ArrayLiteral");
+
+  DeferredArrayLiteral* deferred = new DeferredArrayLiteral(this, node);
+
+  // Retrieve the literal array and check the allocated entry.
+
+  // Load the function of this activation.
+  __ ldr(r1, frame_->Function());
+
+  // Load the literals array of the function.
+  __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset));
+
+  // Load the literal at the ast saved index.
+  int literal_offset =
+      FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
+  __ ldr(r2, FieldMemOperand(r1, literal_offset));
+
+  // Check whether we need to materialize the object literal boilerplate.
+  // If so, jump to the deferred code.
+  __ cmp(r2, Operand(Factory::undefined_value()));
+  deferred->enter()->Branch(eq);
+  deferred->BindExit();
+
+  // Push the object literal boilerplate.
+  frame_->EmitPush(r2);
+
+  // Clone the boilerplate object.
+  Runtime::FunctionId clone_function_id = Runtime::kCloneLiteralBoilerplate;
+  if (node->depth() == 1) {
+    clone_function_id = Runtime::kCloneShallowLiteralBoilerplate;
+  }
+  frame_->CallRuntime(clone_function_id, 1);
+  frame_->EmitPush(r0);  // save the result
+  // r0: cloned object literal
+
+  // Generate code to set the elements in the array that are not
+  // literals.
+  for (int i = 0; i < node->values()->length(); i++) {
+    Expression* value = node->values()->at(i);
+
+    // If value is a literal the property value is already set in the
+    // boilerplate object.
+    if (value->AsLiteral() != NULL) continue;
+    // If value is a materialized literal the property value is already set
+    // in the boilerplate object if it is simple.
+    if (CompileTimeValue::IsCompileTimeValue(value)) continue;
+
+    // The property must be set by generated code.
+    LoadAndSpill(value);
+    frame_->EmitPop(r0);
+
+    // Fetch the object literal.
+    __ ldr(r1, frame_->Top());
+    // Get the elements array.
+    __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset));
+
+    // Write to the indexed properties array.
+    int offset = i * kPointerSize + Array::kHeaderSize;
+    __ str(r0, FieldMemOperand(r1, offset));
+
+    // Update the write barrier for the array address.
+    __ mov(r3, Operand(offset));
+    __ RecordWrite(r1, r3, r2);
+  }
+  ASSERT(frame_->height() == original_height + 1);
+}
+
+
+void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  ASSERT(!in_spilled_code());
+  VirtualFrame::SpilledScope spilled_scope(this);
+  // Call runtime routine to allocate the catch extension object and
+  // assign the exception value to the catch variable.
+  Comment cmnt(masm_, "[ CatchExtensionObject");
+  LoadAndSpill(node->key());
+  LoadAndSpill(node->value());
+  Result result =
+      frame_->CallRuntime(Runtime::kCreateCatchExtensionObject, 2);
+  frame_->EmitPush(result.reg());
+  ASSERT(frame_->height() == original_height + 1);
+}
+
+
+void CodeGenerator::VisitAssignment(Assignment* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ Assignment");
+  CodeForStatementPosition(node);
+
+  { Reference target(this, node->target());
+    if (target.is_illegal()) {
+      // Fool the virtual frame into thinking that we left the assignment's
+      // value on the frame.
+      __ mov(r0, Operand(Smi::FromInt(0)));
+      frame_->EmitPush(r0);
+      ASSERT(frame_->height() == original_height + 1);
+      return;
+    }
+
+    if (node->op() == Token::ASSIGN ||
+        node->op() == Token::INIT_VAR ||
+        node->op() == Token::INIT_CONST) {
+      LoadAndSpill(node->value());
+
+    } else {
+      target.GetValueAndSpill(NOT_INSIDE_TYPEOF);
+      Literal* literal = node->value()->AsLiteral();
+      if (literal != NULL && literal->handle()->IsSmi()) {
+        SmiOperation(node->binary_op(), literal->handle(), false);
+        frame_->EmitPush(r0);
+
+      } else {
+        LoadAndSpill(node->value());
+        GenericBinaryOperation(node->binary_op());
+        frame_->EmitPush(r0);
+      }
+    }
+
+    Variable* var = node->target()->AsVariableProxy()->AsVariable();
+    if (var != NULL &&
+        (var->mode() == Variable::CONST) &&
+        node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) {
+      // Assignment ignored - leave the value on the stack.
+
+    } else {
+      CodeForSourcePosition(node->position());
+      if (node->op() == Token::INIT_CONST) {
+        // Dynamic constant initializations must use the function context
+        // and initialize the actual constant declared. Dynamic variable
+        // initializations are simply assignments and use SetValue.
+        target.SetValue(CONST_INIT);
+      } else {
+        target.SetValue(NOT_CONST_INIT);
+      }
+    }
+  }
+  ASSERT(frame_->height() == original_height + 1);
+}
+
+
+void CodeGenerator::VisitThrow(Throw* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ Throw");
+
+  LoadAndSpill(node->exception());
+  CodeForSourcePosition(node->position());
+  frame_->CallRuntime(Runtime::kThrow, 1);
+  frame_->EmitPush(r0);
+  ASSERT(frame_->height() == original_height + 1);
+}
+
+
+void CodeGenerator::VisitProperty(Property* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ Property");
+
+  { Reference property(this, node);
+    property.GetValueAndSpill(typeof_state());
+  }
+  ASSERT(frame_->height() == original_height + 1);
+}
+
+
+void CodeGenerator::VisitCall(Call* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ Call");
+
+  ZoneList<Expression*>* args = node->arguments();
+
+  CodeForStatementPosition(node);
+  // Standard function call.
+
+  // Check if the function is a variable or a property.
+  Expression* function = node->expression();
+  Variable* var = function->AsVariableProxy()->AsVariable();
+  Property* property = function->AsProperty();
+
+  // ------------------------------------------------------------------------
+  // Fast-case: Use inline caching.
+  // ---
+  // According to ECMA-262, section 11.2.3, page 44, the function to call
+  // must be resolved after the arguments have been evaluated. The IC code
+  // automatically handles this by loading the arguments before the function
+  // is resolved in cache misses (this also holds for megamorphic calls).
+  // ------------------------------------------------------------------------
+
+  if (var != NULL && !var->is_this() && var->is_global()) {
+    // ----------------------------------
+    // JavaScript example: 'foo(1, 2, 3)'  // foo is global
+    // ----------------------------------
+
+    // Push the name of the function and the receiver onto the stack.
+    __ mov(r0, Operand(var->name()));
+    frame_->EmitPush(r0);
+
+    // Pass the global object as the receiver and let the IC stub
+    // patch the stack to use the global proxy as 'this' in the
+    // invoked function.
+    LoadGlobal();
+
+    // Load the arguments.
+    int arg_count = args->length();
+    for (int i = 0; i < arg_count; i++) {
+      LoadAndSpill(args->at(i));
+    }
+
+    // Setup the receiver register and call the IC initialization code.
+    Handle<Code> stub = ComputeCallInitialize(arg_count);
+    CodeForSourcePosition(node->position());
+    frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT,
+                           arg_count + 1);
+    __ ldr(cp, frame_->Context());
+    // Remove the function from the stack.
+    frame_->Drop();
+    frame_->EmitPush(r0);
+
+  } else if (var != NULL && var->slot() != NULL &&
+             var->slot()->type() == Slot::LOOKUP) {
+    // ----------------------------------
+    // JavaScript example: 'with (obj) foo(1, 2, 3)'  // foo is in obj
+    // ----------------------------------
+
+    // Load the function
+    frame_->EmitPush(cp);
+    __ mov(r0, Operand(var->name()));
+    frame_->EmitPush(r0);
+    frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
+    // r0: slot value; r1: receiver
+
+    // Load the receiver.
+    frame_->EmitPush(r0);  // function
+    frame_->EmitPush(r1);  // receiver
+
+    // Call the function.
+    CallWithArguments(args, node->position());
+    frame_->EmitPush(r0);
+
+  } else if (property != NULL) {
+    // Check if the key is a literal string.
+    Literal* literal = property->key()->AsLiteral();
+
+    if (literal != NULL && literal->handle()->IsSymbol()) {
+      // ------------------------------------------------------------------
+      // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)'
+      // ------------------------------------------------------------------
+
+      // Push the name of the function and the receiver onto the stack.
+      __ mov(r0, Operand(literal->handle()));
+      frame_->EmitPush(r0);
+      LoadAndSpill(property->obj());
+
+      // Load the arguments.
+      int arg_count = args->length();
+      for (int i = 0; i < arg_count; i++) {
+        LoadAndSpill(args->at(i));
+      }
+
+      // Set the receiver register and call the IC initialization code.
+      Handle<Code> stub = ComputeCallInitialize(arg_count);
+      CodeForSourcePosition(node->position());
+      frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
+      __ ldr(cp, frame_->Context());
+
+      // Remove the function from the stack.
+      frame_->Drop();
+
+      frame_->EmitPush(r0);  // push after get rid of function from the stack
+
+    } else {
+      // -------------------------------------------
+      // JavaScript example: 'array[index](1, 2, 3)'
+      // -------------------------------------------
+
+      // Load the function to call from the property through a reference.
+      Reference ref(this, property);
+      ref.GetValueAndSpill(NOT_INSIDE_TYPEOF);  // receiver
+
+      // Pass receiver to called function.
+      if (property->is_synthetic()) {
+        LoadGlobalReceiver(r0);
+      } else {
+        __ ldr(r0, frame_->ElementAt(ref.size()));
+        frame_->EmitPush(r0);
+      }
+
+      // Call the function.
+      CallWithArguments(args, node->position());
+      frame_->EmitPush(r0);
+    }
+
+  } else {
+    // ----------------------------------
+    // JavaScript example: 'foo(1, 2, 3)'  // foo is not global
+    // ----------------------------------
+
+    // Load the function.
+    LoadAndSpill(function);
+
+    // Pass the global proxy as the receiver.
+    LoadGlobalReceiver(r0);
+
+    // Call the function.
+    CallWithArguments(args, node->position());
+    frame_->EmitPush(r0);
+  }
+  ASSERT(frame_->height() == original_height + 1);
+}
+
+
+void CodeGenerator::VisitCallEval(CallEval* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ CallEval");
+
+  // In a call to eval, we first call %ResolvePossiblyDirectEval to resolve
+  // the function we need to call and the receiver of the call.
+  // Then we call the resolved function using the given arguments.
+
+  ZoneList<Expression*>* args = node->arguments();
+  Expression* function = node->expression();
+
+  CodeForStatementPosition(node);
+
+  // Prepare stack for call to resolved function.
+  LoadAndSpill(function);
+  __ mov(r2, Operand(Factory::undefined_value()));
+  frame_->EmitPush(r2);  // Slot for receiver
+  int arg_count = args->length();
+  for (int i = 0; i < arg_count; i++) {
+    LoadAndSpill(args->at(i));
+  }
+
+  // Prepare stack for call to ResolvePossiblyDirectEval.
+  __ ldr(r1, MemOperand(sp, arg_count * kPointerSize + kPointerSize));
+  frame_->EmitPush(r1);
+  if (arg_count > 0) {
+    __ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
+    frame_->EmitPush(r1);
+  } else {
+    frame_->EmitPush(r2);
+  }
+
+  // Resolve the call.
+  frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 2);
+
+  // Touch up stack with the right values for the function and the receiver.
+  __ ldr(r1, FieldMemOperand(r0, FixedArray::kHeaderSize));
+  __ str(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
+  __ ldr(r1, FieldMemOperand(r0, FixedArray::kHeaderSize + kPointerSize));
+  __ str(r1, MemOperand(sp, arg_count * kPointerSize));
+
+  // Call the function.
+  CodeForSourcePosition(node->position());
+
+  CallFunctionStub call_function(arg_count);
+  frame_->CallStub(&call_function, arg_count + 1);
+
+  __ ldr(cp, frame_->Context());
+  // Remove the function from the stack.
+  frame_->Drop();
+  frame_->EmitPush(r0);
+  ASSERT(frame_->height() == original_height + 1);
+}
+
+
+void CodeGenerator::VisitCallNew(CallNew* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ CallNew");
+  CodeForStatementPosition(node);
+
+  // According to ECMA-262, section 11.2.2, page 44, the function
+  // expression in new calls must be evaluated before the
+  // arguments. This is different from ordinary calls, where the
+  // actual function to call is resolved after the arguments have been
+  // evaluated.
+
+  // Compute function to call and use the global object as the
+  // receiver. There is no need to use the global proxy here because
+  // it will always be replaced with a newly allocated object.
+  LoadAndSpill(node->expression());
+  LoadGlobal();
+
+  // Push the arguments ("left-to-right") on the stack.
+  ZoneList<Expression*>* args = node->arguments();
+  int arg_count = args->length();
+  for (int i = 0; i < arg_count; i++) {
+    LoadAndSpill(args->at(i));
+  }
+
+  // r0: the number of arguments.
+  Result num_args = allocator_->Allocate(r0);
+  ASSERT(num_args.is_valid());
+  __ mov(num_args.reg(), Operand(arg_count));
+
+  // Load the function into r1 as per calling convention.
+  Result function = allocator_->Allocate(r1);
+  ASSERT(function.is_valid());
+  __ ldr(function.reg(), frame_->ElementAt(arg_count + 1));
+
+  // Call the construct call builtin that handles allocation and
+  // constructor invocation.
+  CodeForSourcePosition(node->position());
+  Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall));
+  Result result = frame_->CallCodeObject(ic,
+                                         RelocInfo::CONSTRUCT_CALL,
+                                         &num_args,
+                                         &function,
+                                         arg_count + 1);
+
+  // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)).
+  __ str(r0, frame_->Top());
+  ASSERT(frame_->height() == original_height + 1);
+}
+
+
+void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  ASSERT(args->length() == 1);
+  JumpTarget leave(this);
+  LoadAndSpill(args->at(0));
+  frame_->EmitPop(r0);  // r0 contains object.
+  // if (object->IsSmi()) return the object.
+  __ tst(r0, Operand(kSmiTagMask));
+  leave.Branch(eq);
+  // It is a heap object - get map.
+  __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
+  __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
+  // if (!object->IsJSValue()) return the object.
+  __ cmp(r1, Operand(JS_VALUE_TYPE));
+  leave.Branch(ne);
+  // Load the value.
+  __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
+  leave.Bind();
+  frame_->EmitPush(r0);
+}
+
+
+void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  ASSERT(args->length() == 2);
+  JumpTarget leave(this);
+  LoadAndSpill(args->at(0));  // Load the object.
+  LoadAndSpill(args->at(1));  // Load the value.
+  frame_->EmitPop(r0);  // r0 contains value
+  frame_->EmitPop(r1);  // r1 contains object
+  // if (object->IsSmi()) return object.
+  __ tst(r1, Operand(kSmiTagMask));
+  leave.Branch(eq);
+  // It is a heap object - get map.
+  __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+  __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
+  // if (!object->IsJSValue()) return object.
+  __ cmp(r2, Operand(JS_VALUE_TYPE));
+  leave.Branch(ne);
+  // Store the value.
+  __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset));
+  // Update the write barrier.
+  __ mov(r2, Operand(JSValue::kValueOffset - kHeapObjectTag));
+  __ RecordWrite(r1, r2, r3);
+  // Leave.
+  leave.Bind();
+  frame_->EmitPush(r0);
+}
+
+
+void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  ASSERT(args->length() == 1);
+  LoadAndSpill(args->at(0));
+  frame_->EmitPop(r0);
+  __ tst(r0, Operand(kSmiTagMask));
+  cc_reg_ = eq;
+}
+
+
+void CodeGenerator::GenerateLog(ZoneList<Expression*>* args) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  // See comment in CodeGenerator::GenerateLog in codegen-ia32.cc.
+  ASSERT_EQ(args->length(), 3);
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (ShouldGenerateLog(args->at(0))) {
+    LoadAndSpill(args->at(1));
+    LoadAndSpill(args->at(2));
+    __ CallRuntime(Runtime::kLog, 2);
+  }
+#endif
+  __ mov(r0, Operand(Factory::undefined_value()));
+  frame_->EmitPush(r0);
+}
+
+
+void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  ASSERT(args->length() == 1);
+  LoadAndSpill(args->at(0));
+  frame_->EmitPop(r0);
+  __ tst(r0, Operand(kSmiTagMask | 0x80000000));
+  cc_reg_ = eq;
+}
+
+
+// This should generate code that performs a charCodeAt() call or returns
+// undefined in order to trigger the slow case, Runtime_StringCharCodeAt.
+// It is not yet implemented on ARM, so it always goes to the slow case.
+void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  ASSERT(args->length() == 2);
+  __ mov(r0, Operand(Factory::undefined_value()));
+  frame_->EmitPush(r0);
+}
+
+
+void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  ASSERT(args->length() == 1);
+  LoadAndSpill(args->at(0));
+  JumpTarget answer(this);
+  // We need the CC bits to come out as not_equal in the case where the
+  // object is a smi.  This can't be done with the usual test opcode so
+  // we use XOR to get the right CC bits.
+  frame_->EmitPop(r0);
+  __ and_(r1, r0, Operand(kSmiTagMask));
+  __ eor(r1, r1, Operand(kSmiTagMask), SetCC);
+  answer.Branch(ne);
+  // It is a heap object - get the map.
+  __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
+  __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
+  // Check if the object is a JS array or not.
+  __ cmp(r1, Operand(JS_ARRAY_TYPE));
+  answer.Bind();
+  cc_reg_ = eq;
+}
+
+
+void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  ASSERT(args->length() == 0);
+
+  // Seed the result with the formal parameters count, which will be used
+  // in case no arguments adaptor frame is found below the current frame.
+  __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
+
+  // Call the shared stub to get to the arguments.length.
+  ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
+  frame_->CallStub(&stub, 0);
+  frame_->EmitPush(r0);
+}
+
+
+void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  ASSERT(args->length() == 1);
+
+  // Satisfy contract with ArgumentsAccessStub:
+  // Load the key into r1 and the formal parameters count into r0.
+  LoadAndSpill(args->at(0));
+  frame_->EmitPop(r1);
+  __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
+
+  // Call the shared stub to get to arguments[key].
+  ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
+  frame_->CallStub(&stub, 0);
+  frame_->EmitPush(r0);
+}
+
+
+void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
+  VirtualFrame::SpilledScope spilled_scope(this);
+  ASSERT(args->length() == 2);
+
+  // Load the two objects into registers and perform the comparison.
+  LoadAndSpill(args->at(0));
+  LoadAndSpill(args->at(1));
+  frame_->EmitPop(r0);
+  frame_->EmitPop(r1);
+  __ cmp(r0, Operand(r1));
+  cc_reg_ = eq;
+}
+
+
+void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  if (CheckForInlineRuntimeCall(node)) {
+    ASSERT((has_cc() && frame_->height() == original_height) ||
+           (!has_cc() && frame_->height() == original_height + 1));
+    return;
+  }
+
+  ZoneList<Expression*>* args = node->arguments();
+  Comment cmnt(masm_, "[ CallRuntime");
+  Runtime::Function* function = node->function();
+
+  if (function == NULL) {
+    // Prepare stack for calling JS runtime function.
+    __ mov(r0, Operand(node->name()));
+    frame_->EmitPush(r0);
+    // Push the builtins object found in the current global object.
+    __ ldr(r1, GlobalObject());
+    __ ldr(r0, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset));
+    frame_->EmitPush(r0);
+  }
+
+  // Push the arguments ("left-to-right").
+  int arg_count = args->length();
+  for (int i = 0; i < arg_count; i++) {
+    LoadAndSpill(args->at(i));
+  }
+
+  if (function == NULL) {
+    // Call the JS runtime function.
+    Handle<Code> stub = ComputeCallInitialize(arg_count);
+    frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
+    __ ldr(cp, frame_->Context());
+    frame_->Drop();
+    frame_->EmitPush(r0);
+  } else {
+    // Call the C runtime function.
+    frame_->CallRuntime(function, arg_count);
+    frame_->EmitPush(r0);
+  }
+  ASSERT(frame_->height() == original_height + 1);
+}
+
+
+void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ UnaryOperation");
+
+  Token::Value op = node->op();
+
+  if (op == Token::NOT) {
+    LoadConditionAndSpill(node->expression(),
+                          NOT_INSIDE_TYPEOF,
+                          false_target(),
+                          true_target(),
+                          true);
+    cc_reg_ = NegateCondition(cc_reg_);
+
+  } else if (op == Token::DELETE) {
+    Property* property = node->expression()->AsProperty();
+    Variable* variable = node->expression()->AsVariableProxy()->AsVariable();
+    if (property != NULL) {
+      LoadAndSpill(property->obj());
+      LoadAndSpill(property->key());
+      Result arg_count = allocator_->Allocate(r0);
+      ASSERT(arg_count.is_valid());
+      __ mov(arg_count.reg(), Operand(1));  // not counting receiver
+      frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, &arg_count, 2);
+
+    } else if (variable != NULL) {
+      Slot* slot = variable->slot();
+      if (variable->is_global()) {
+        LoadGlobal();
+        __ mov(r0, Operand(variable->name()));
+        frame_->EmitPush(r0);
+        Result arg_count = allocator_->Allocate(r0);
+        ASSERT(arg_count.is_valid());
+        __ mov(arg_count.reg(), Operand(1));  // not counting receiver
+        frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, &arg_count, 2);
+
+      } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
+        // lookup the context holding the named variable
+        frame_->EmitPush(cp);
+        __ mov(r0, Operand(variable->name()));
+        frame_->EmitPush(r0);
+        frame_->CallRuntime(Runtime::kLookupContext, 2);
+        // r0: context
+        frame_->EmitPush(r0);
+        __ mov(r0, Operand(variable->name()));
+        frame_->EmitPush(r0);
+        Result arg_count = allocator_->Allocate(r0);
+        ASSERT(arg_count.is_valid());
+        __ mov(arg_count.reg(), Operand(1));  // not counting receiver
+        frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, &arg_count, 2);
+
+      } else {
+        // Default: Result of deleting non-global, not dynamically
+        // introduced variables is false.
+        __ mov(r0, Operand(Factory::false_value()));
+      }
+
+    } else {
+      // Default: Result of deleting expressions is true.
+      LoadAndSpill(node->expression());  // may have side-effects
+      frame_->Drop();
+      __ mov(r0, Operand(Factory::true_value()));
+    }
+    frame_->EmitPush(r0);
+
+  } else if (op == Token::TYPEOF) {
+    // Special case for loading the typeof expression; see comment on
+    // LoadTypeofExpression().
+    LoadTypeofExpression(node->expression());
+    frame_->CallRuntime(Runtime::kTypeof, 1);
+    frame_->EmitPush(r0);  // r0 has result
+
+  } else {
+    LoadAndSpill(node->expression());
+    frame_->EmitPop(r0);
+    switch (op) {
+      case Token::NOT:
+      case Token::DELETE:
+      case Token::TYPEOF:
+        UNREACHABLE();  // handled above
+        break;
+
+      case Token::SUB: {
+        UnarySubStub stub;
+        frame_->CallStub(&stub, 0);
+        break;
+      }
+
+      case Token::BIT_NOT: {
+        // smi check
+        JumpTarget smi_label(this);
+        JumpTarget continue_label(this);
+        __ tst(r0, Operand(kSmiTagMask));
+        smi_label.Branch(eq);
+
+        frame_->EmitPush(r0);
+        Result arg_count = allocator_->Allocate(r0);
+        ASSERT(arg_count.is_valid());
+        __ mov(arg_count.reg(), Operand(0));  // not counting receiver
+        frame_->InvokeBuiltin(Builtins::BIT_NOT, CALL_JS, &arg_count, 1);
+
+        continue_label.Jump();
+        smi_label.Bind();
+        __ mvn(r0, Operand(r0));
+        __ bic(r0, r0, Operand(kSmiTagMask));  // bit-clear inverted smi-tag
+        continue_label.Bind();
+        break;
+      }
+
+      case Token::VOID:
+        // since the stack top is cached in r0, popping and then
+        // pushing a value can be done by just writing to r0.
+        __ mov(r0, Operand(Factory::undefined_value()));
+        break;
+
+      case Token::ADD: {
+        // Smi check.
+        JumpTarget continue_label(this);
+        __ tst(r0, Operand(kSmiTagMask));
+        continue_label.Branch(eq);
+        frame_->EmitPush(r0);
+        Result arg_count = allocator_->Allocate(r0);
+        ASSERT(arg_count.is_valid());
+        __ mov(arg_count.reg(), Operand(0));  // not counting receiver
+        frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, &arg_count, 1);
+        continue_label.Bind();
+        break;
+      }
+      default:
+        UNREACHABLE();
+    }
+    frame_->EmitPush(r0);  // r0 has result
+  }
+  ASSERT((has_cc() && frame_->height() == original_height) ||
+         (!has_cc() && frame_->height() == original_height + 1));
+}
+
+
+void CodeGenerator::VisitCountOperation(CountOperation* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ CountOperation");
+
+  bool is_postfix = node->is_postfix();
+  bool is_increment = node->op() == Token::INC;
+
+  Variable* var = node->expression()->AsVariableProxy()->AsVariable();
+  bool is_const = (var != NULL && var->mode() == Variable::CONST);
+
+  // Postfix: Make room for the result.
+  if (is_postfix) {
+     __ mov(r0, Operand(0));
+     frame_->EmitPush(r0);
+  }
+
+  { Reference target(this, node->expression());
+    if (target.is_illegal()) {
+      // Spoof the virtual frame to have the expected height (one higher
+      // than on entry).
+      if (!is_postfix) {
+        __ mov(r0, Operand(Smi::FromInt(0)));
+        frame_->EmitPush(r0);
+      }
+      ASSERT(frame_->height() == original_height + 1);
+      return;
+    }
+    target.GetValueAndSpill(NOT_INSIDE_TYPEOF);
+    frame_->EmitPop(r0);
+
+    JumpTarget slow(this);
+    JumpTarget exit(this);
+
+    // Load the value (1) into register r1.
+    __ mov(r1, Operand(Smi::FromInt(1)));
+
+    // Check for smi operand.
+    __ tst(r0, Operand(kSmiTagMask));
+    slow.Branch(ne);
+
+    // Postfix: Store the old value as the result.
+    if (is_postfix) {
+      __ str(r0, frame_->ElementAt(target.size()));
+    }
+
+    // Perform optimistic increment/decrement.
+    if (is_increment) {
+      __ add(r0, r0, Operand(r1), SetCC);
+    } else {
+      __ sub(r0, r0, Operand(r1), SetCC);
+    }
+
+    // If the increment/decrement didn't overflow, we're done.
+    exit.Branch(vc);
+
+    // Revert optimistic increment/decrement.
+    if (is_increment) {
+      __ sub(r0, r0, Operand(r1));
+    } else {
+      __ add(r0, r0, Operand(r1));
+    }
+
+    // Slow case: Convert to number.
+    slow.Bind();
+    {
+      // Convert the operand to a number.
+      frame_->EmitPush(r0);
+      Result arg_count = allocator_->Allocate(r0);
+      ASSERT(arg_count.is_valid());
+      __ mov(arg_count.reg(), Operand(0));
+      frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, &arg_count, 1);
+    }
+    if (is_postfix) {
+      // Postfix: store to result (on the stack).
+      __ str(r0, frame_->ElementAt(target.size()));
+    }
+
+    // Compute the new value.
+    __ mov(r1, Operand(Smi::FromInt(1)));
+    frame_->EmitPush(r0);
+    frame_->EmitPush(r1);
+    if (is_increment) {
+      frame_->CallRuntime(Runtime::kNumberAdd, 2);
+    } else {
+      frame_->CallRuntime(Runtime::kNumberSub, 2);
+    }
+
+    // Store the new value in the target if not const.
+    exit.Bind();
+    frame_->EmitPush(r0);
+    if (!is_const) target.SetValue(NOT_CONST_INIT);
+  }
+
+  // Postfix: Discard the new value and use the old.
+  if (is_postfix) frame_->EmitPop(r0);
+  ASSERT(frame_->height() == original_height + 1);
+}
+
+
+void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ BinaryOperation");
+  Token::Value op = node->op();
+
+  // According to ECMA-262 section 11.11, page 58, the binary logical
+  // operators must yield the result of one of the two expressions
+  // before any ToBoolean() conversions. This means that the value
+  // produced by a && or || operator is not necessarily a boolean.
+
+  // NOTE: If the left hand side produces a materialized value (not in
+  // the CC register), we force the right hand side to do the
+  // same. This is necessary because we may have to branch to the exit
+  // after evaluating the left hand side (due to the shortcut
+  // semantics), but the compiler must (statically) know if the result
+  // of compiling the binary operation is materialized or not.
+
+  if (op == Token::AND) {
+    JumpTarget is_true(this);
+    LoadConditionAndSpill(node->left(),
+                          NOT_INSIDE_TYPEOF,
+                          &is_true,
+                          false_target(),
+                          false);
+    if (has_cc()) {
+      Branch(false, false_target());
+
+      // Evaluate right side expression.
+      is_true.Bind();
+      LoadConditionAndSpill(node->right(),
+                            NOT_INSIDE_TYPEOF,
+                            true_target(),
+                            false_target(),
+                            false);
+
+    } else {
+      JumpTarget pop_and_continue(this);
+      JumpTarget exit(this);
+
+      __ ldr(r0, frame_->Top());  // dup the stack top
+      frame_->EmitPush(r0);
+      // Avoid popping the result if it converts to 'false' using the
+      // standard ToBoolean() conversion as described in ECMA-262,
+      // section 9.2, page 30.
+      ToBoolean(&pop_and_continue, &exit);
+      Branch(false, &exit);
+
+      // Pop the result of evaluating the first part.
+      pop_and_continue.Bind();
+      frame_->EmitPop(r0);
+
+      // Evaluate right side expression.
+      is_true.Bind();
+      LoadAndSpill(node->right());
+
+      // Exit (always with a materialized value).
+      exit.Bind();
+    }
+
+  } else if (op == Token::OR) {
+    JumpTarget is_false(this);
+    LoadConditionAndSpill(node->left(),
+                          NOT_INSIDE_TYPEOF,
+                          true_target(),
+                          &is_false,
+                          false);
+    if (has_cc()) {
+      Branch(true, true_target());
+
+      // Evaluate right side expression.
+      is_false.Bind();
+      LoadConditionAndSpill(node->right(),
+                            NOT_INSIDE_TYPEOF,
+                            true_target(),
+                            false_target(),
+                            false);
+
+    } else {
+      JumpTarget pop_and_continue(this);
+      JumpTarget exit(this);
+
+      __ ldr(r0, frame_->Top());
+      frame_->EmitPush(r0);
+      // Avoid popping the result if it converts to 'true' using the
+      // standard ToBoolean() conversion as described in ECMA-262,
+      // section 9.2, page 30.
+      ToBoolean(&exit, &pop_and_continue);
+      Branch(true, &exit);
+
+      // Pop the result of evaluating the first part.
+      pop_and_continue.Bind();
+      frame_->EmitPop(r0);
+
+      // Evaluate right side expression.
+      is_false.Bind();
+      LoadAndSpill(node->right());
+
+      // Exit (always with a materialized value).
+      exit.Bind();
+    }
+
+  } else {
+    // Optimize for the case where (at least) one of the expressions
+    // is a literal small integer.
+    Literal* lliteral = node->left()->AsLiteral();
+    Literal* rliteral = node->right()->AsLiteral();
+
+    if (rliteral != NULL && rliteral->handle()->IsSmi()) {
+      LoadAndSpill(node->left());
+      SmiOperation(node->op(), rliteral->handle(), false);
+
+    } else if (lliteral != NULL && lliteral->handle()->IsSmi()) {
+      LoadAndSpill(node->right());
+      SmiOperation(node->op(), lliteral->handle(), true);
+
+    } else {
+      LoadAndSpill(node->left());
+      LoadAndSpill(node->right());
+      GenericBinaryOperation(node->op());
+    }
+    frame_->EmitPush(r0);
+  }
+  ASSERT((has_cc() && frame_->height() == original_height) ||
+         (!has_cc() && frame_->height() == original_height + 1));
+}
+
+
+void CodeGenerator::VisitThisFunction(ThisFunction* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  __ ldr(r0, frame_->Function());
+  frame_->EmitPush(r0);
+  ASSERT(frame_->height() == original_height + 1);
+}
+
+
+void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ CompareOperation");
+
+  // Get the expressions from the node.
+  Expression* left = node->left();
+  Expression* right = node->right();
+  Token::Value op = node->op();
+
+  // To make null checks efficient, we check if either left or right is the
+  // literal 'null'. If so, we optimize the code by inlining a null check
+  // instead of calling the (very) general runtime routine for checking
+  // equality.
+  if (op == Token::EQ || op == Token::EQ_STRICT) {
+    bool left_is_null =
+        left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
+    bool right_is_null =
+        right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
+    // The 'null' value can only be equal to 'null' or 'undefined'.
+    if (left_is_null || right_is_null) {
+      LoadAndSpill(left_is_null ? right : left);
+      frame_->EmitPop(r0);
+      __ cmp(r0, Operand(Factory::null_value()));
+
+      // The 'null' value is only equal to 'undefined' if using non-strict
+      // comparisons.
+      if (op != Token::EQ_STRICT) {
+        true_target()->Branch(eq);
+
+        __ cmp(r0, Operand(Factory::undefined_value()));
+        true_target()->Branch(eq);
+
+        __ tst(r0, Operand(kSmiTagMask));
+        false_target()->Branch(eq);
+
+        // It can be an undetectable object.
+        __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
+        __ ldrb(r0, FieldMemOperand(r0, Map::kBitFieldOffset));
+        __ and_(r0, r0, Operand(1 << Map::kIsUndetectable));
+        __ cmp(r0, Operand(1 << Map::kIsUndetectable));
+      }
+
+      cc_reg_ = eq;
+      ASSERT(has_cc() && frame_->height() == original_height);
+      return;
+    }
+  }
+
+  // To make typeof testing for natives implemented in JavaScript really
+  // efficient, we generate special code for expressions of the form:
+  // 'typeof <expression> == <string>'.
+  UnaryOperation* operation = left->AsUnaryOperation();
+  if ((op == Token::EQ || op == Token::EQ_STRICT) &&
+      (operation != NULL && operation->op() == Token::TYPEOF) &&
+      (right->AsLiteral() != NULL &&
+       right->AsLiteral()->handle()->IsString())) {
+    Handle<String> check(String::cast(*right->AsLiteral()->handle()));
+
+    // Load the operand, move it to register r1.
+    LoadTypeofExpression(operation->expression());
+    frame_->EmitPop(r1);
+
+    if (check->Equals(Heap::number_symbol())) {
+      __ tst(r1, Operand(kSmiTagMask));
+      true_target()->Branch(eq);
+      __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
+      __ cmp(r1, Operand(Factory::heap_number_map()));
+      cc_reg_ = eq;
+
+    } else if (check->Equals(Heap::string_symbol())) {
+      __ tst(r1, Operand(kSmiTagMask));
+      false_target()->Branch(eq);
+
+      __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
+
+      // It can be an undetectable string object.
+      __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset));
+      __ and_(r2, r2, Operand(1 << Map::kIsUndetectable));
+      __ cmp(r2, Operand(1 << Map::kIsUndetectable));
+      false_target()->Branch(eq);
+
+      __ ldrb(r2, FieldMemOperand(r1, Map::kInstanceTypeOffset));
+      __ cmp(r2, Operand(FIRST_NONSTRING_TYPE));
+      cc_reg_ = lt;
+
+    } else if (check->Equals(Heap::boolean_symbol())) {
+      __ cmp(r1, Operand(Factory::true_value()));
+      true_target()->Branch(eq);
+      __ cmp(r1, Operand(Factory::false_value()));
+      cc_reg_ = eq;
+
+    } else if (check->Equals(Heap::undefined_symbol())) {
+      __ cmp(r1, Operand(Factory::undefined_value()));
+      true_target()->Branch(eq);
+
+      __ tst(r1, Operand(kSmiTagMask));
+      false_target()->Branch(eq);
+
+      // It can be an undetectable object.
+      __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
+      __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset));
+      __ and_(r2, r2, Operand(1 << Map::kIsUndetectable));
+      __ cmp(r2, Operand(1 << Map::kIsUndetectable));
+
+      cc_reg_ = eq;
+
+    } else if (check->Equals(Heap::function_symbol())) {
+      __ tst(r1, Operand(kSmiTagMask));
+      false_target()->Branch(eq);
+      __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
+      __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
+      __ cmp(r1, Operand(JS_FUNCTION_TYPE));
+      cc_reg_ = eq;
+
+    } else if (check->Equals(Heap::object_symbol())) {
+      __ tst(r1, Operand(kSmiTagMask));
+      false_target()->Branch(eq);
+
+      __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+      __ cmp(r1, Operand(Factory::null_value()));
+      true_target()->Branch(eq);
+
+      // It can be an undetectable object.
+      __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset));
+      __ and_(r1, r1, Operand(1 << Map::kIsUndetectable));
+      __ cmp(r1, Operand(1 << Map::kIsUndetectable));
+      false_target()->Branch(eq);
+
+      __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
+      __ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE));
+      false_target()->Branch(lt);
+      __ cmp(r2, Operand(LAST_JS_OBJECT_TYPE));
+      cc_reg_ = le;
+
+    } else {
+      // Uncommon case: typeof testing against a string literal that is
+      // never returned from the typeof operator.
+      false_target()->Jump();
+    }
+    ASSERT(!has_valid_frame() ||
+           (has_cc() && frame_->height() == original_height));
+    return;
+  }
+
+  LoadAndSpill(left);
+  LoadAndSpill(right);
+  switch (op) {
+    case Token::EQ:
+      Comparison(eq, false);
+      break;
+
+    case Token::LT:
+      Comparison(lt);
+      break;
+
+    case Token::GT:
+      Comparison(gt);
+      break;
+
+    case Token::LTE:
+      Comparison(le);
+      break;
+
+    case Token::GTE:
+      Comparison(ge);
+      break;
+
+    case Token::EQ_STRICT:
+      Comparison(eq, true);
+      break;
+
+    case Token::IN: {
+      Result arg_count = allocator_->Allocate(r0);
+      ASSERT(arg_count.is_valid());
+      __ mov(arg_count.reg(), Operand(1));  // not counting receiver
+      Result result = frame_->InvokeBuiltin(Builtins::IN,
+                                            CALL_JS,
+                                            &arg_count,
+                                            2);
+      frame_->EmitPush(result.reg());
+      break;
+    }
+
+    case Token::INSTANCEOF: {
+      Result arg_count = allocator_->Allocate(r0);
+      ASSERT(arg_count.is_valid());
+      __ mov(arg_count.reg(), Operand(1));  // not counting receiver
+      Result result = frame_->InvokeBuiltin(Builtins::INSTANCE_OF,
+                                            CALL_JS,
+                                            &arg_count,
+                                            2);
+      __ tst(result.reg(), Operand(result.reg()));
+      cc_reg_ = eq;
+      break;
+    }
+
+    default:
+      UNREACHABLE();
+  }
+  ASSERT((has_cc() && frame_->height() == original_height) ||
+         (!has_cc() && frame_->height() == original_height + 1));
+}
+
+
+#ifdef DEBUG
+bool CodeGenerator::HasValidEntryRegisters() { return true; }
+#endif
+
+
+#undef __
+#define __ masm->
+
+Handle<String> Reference::GetName() {
+  ASSERT(type_ == NAMED);
+  Property* property = expression_->AsProperty();
+  if (property == NULL) {
+    // Global variable reference treated as a named property reference.
+    VariableProxy* proxy = expression_->AsVariableProxy();
+    ASSERT(proxy->AsVariable() != NULL);
+    ASSERT(proxy->AsVariable()->is_global());
+    return proxy->name();
+  } else {
+    Literal* raw_name = property->key()->AsLiteral();
+    ASSERT(raw_name != NULL);
+    return Handle<String>(String::cast(*raw_name->handle()));
+  }
+}
+
+
+void Reference::GetValueAndSpill(TypeofState typeof_state) {
+  ASSERT(cgen_->in_spilled_code());
+  cgen_->set_in_spilled_code(false);
+  GetValue(typeof_state);
+  cgen_->frame()->SpillAll();
+  cgen_->set_in_spilled_code(true);
+}
+
+
+void Reference::GetValue(TypeofState typeof_state) {
+  ASSERT(!cgen_->in_spilled_code());
+  ASSERT(cgen_->HasValidEntryRegisters());
+  ASSERT(!is_illegal());
+  ASSERT(!cgen_->has_cc());
+  MacroAssembler* masm = cgen_->masm();
+  Property* property = expression_->AsProperty();
+  if (property != NULL) {
+    cgen_->CodeForSourcePosition(property->position());
+  }
+
+  switch (type_) {
+    case SLOT: {
+      Comment cmnt(masm, "[ Load from Slot");
+      Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
+      ASSERT(slot != NULL);
+      cgen_->LoadFromSlot(slot, typeof_state);
+      break;
+    }
+
+    case NAMED: {
+      // TODO(1241834): Make sure that this it is safe to ignore the
+      // distinction between expressions in a typeof and not in a typeof. If
+      // there is a chance that reference errors can be thrown below, we
+      // must distinguish between the two kinds of loads (typeof expression
+      // loads must not throw a reference error).
+      VirtualFrame* frame = cgen_->frame();
+      Comment cmnt(masm, "[ Load from named Property");
+      Handle<String> name(GetName());
+      Variable* var = expression_->AsVariableProxy()->AsVariable();
+      Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+      // Setup the name register.
+      Result name_reg = cgen_->allocator()->Allocate(r2);
+      ASSERT(name_reg.is_valid());
+      __ mov(name_reg.reg(), Operand(name));
+      ASSERT(var == NULL || var->is_global());
+      RelocInfo::Mode rmode = (var == NULL)
+                            ? RelocInfo::CODE_TARGET
+                            : RelocInfo::CODE_TARGET_CONTEXT;
+      Result answer = frame->CallCodeObject(ic, rmode, &name_reg, 0);
+      frame->EmitPush(answer.reg());
+      break;
+    }
+
+    case KEYED: {
+      // TODO(1241834): Make sure that this it is safe to ignore the
+      // distinction between expressions in a typeof and not in a typeof.
+
+      // TODO(181): Implement inlined version of array indexing once
+      // loop nesting is properly tracked on ARM.
+      VirtualFrame* frame = cgen_->frame();
+      Comment cmnt(masm, "[ Load from keyed Property");
+      ASSERT(property != NULL);
+      Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+      Variable* var = expression_->AsVariableProxy()->AsVariable();
+      ASSERT(var == NULL || var->is_global());
+      RelocInfo::Mode rmode = (var == NULL)
+                            ? RelocInfo::CODE_TARGET
+                            : RelocInfo::CODE_TARGET_CONTEXT;
+      Result answer = frame->CallCodeObject(ic, rmode, 0);
+      frame->EmitPush(answer.reg());
+      break;
+    }
+
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void Reference::SetValue(InitState init_state) {
+  ASSERT(!is_illegal());
+  ASSERT(!cgen_->has_cc());
+  MacroAssembler* masm = cgen_->masm();
+  VirtualFrame* frame = cgen_->frame();
+  Property* property = expression_->AsProperty();
+  if (property != NULL) {
+    cgen_->CodeForSourcePosition(property->position());
+  }
+
+  switch (type_) {
+    case SLOT: {
+      Comment cmnt(masm, "[ Store to Slot");
+      Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
+      ASSERT(slot != NULL);
+      if (slot->type() == Slot::LOOKUP) {
+        ASSERT(slot->var()->is_dynamic());
+
+        // For now, just do a runtime call.
+        frame->EmitPush(cp);
+        __ mov(r0, Operand(slot->var()->name()));
+        frame->EmitPush(r0);
+
+        if (init_state == CONST_INIT) {
+          // Same as the case for a normal store, but ignores attribute
+          // (e.g. READ_ONLY) of context slot so that we can initialize
+          // const properties (introduced via eval("const foo = (some
+          // expr);")). Also, uses the current function context instead of
+          // the top context.
+          //
+          // Note that we must declare the foo upon entry of eval(), via a
+          // context slot declaration, but we cannot initialize it at the
+          // same time, because the const declaration may be at the end of
+          // the eval code (sigh...) and the const variable may have been
+          // used before (where its value is 'undefined'). Thus, we can only
+          // do the initialization when we actually encounter the expression
+          // and when the expression operands are defined and valid, and
+          // thus we need the split into 2 operations: declaration of the
+          // context slot followed by initialization.
+          frame->CallRuntime(Runtime::kInitializeConstContextSlot, 3);
+        } else {
+          frame->CallRuntime(Runtime::kStoreContextSlot, 3);
+        }
+        // Storing a variable must keep the (new) value on the expression
+        // stack. This is necessary for compiling assignment expressions.
+        frame->EmitPush(r0);
+
+      } else {
+        ASSERT(!slot->var()->is_dynamic());
+
+        JumpTarget exit(cgen_);
+        if (init_state == CONST_INIT) {
+          ASSERT(slot->var()->mode() == Variable::CONST);
+          // Only the first const initialization must be executed (the slot
+          // still contains 'the hole' value). When the assignment is
+          // executed, the code is identical to a normal store (see below).
+          Comment cmnt(masm, "[ Init const");
+          __ ldr(r2, cgen_->SlotOperand(slot, r2));
+          __ cmp(r2, Operand(Factory::the_hole_value()));
+          exit.Branch(ne);
+        }
+
+        // We must execute the store.  Storing a variable must keep the
+        // (new) value on the stack. This is necessary for compiling
+        // assignment expressions.
+        //
+        // Note: We will reach here even with slot->var()->mode() ==
+        // Variable::CONST because of const declarations which will
+        // initialize consts to 'the hole' value and by doing so, end up
+        // calling this code.  r2 may be loaded with context; used below in
+        // RecordWrite.
+        frame->EmitPop(r0);
+        __ str(r0, cgen_->SlotOperand(slot, r2));
+        frame->EmitPush(r0);
+        if (slot->type() == Slot::CONTEXT) {
+          // Skip write barrier if the written value is a smi.
+          __ tst(r0, Operand(kSmiTagMask));
+          exit.Branch(eq);
+          // r2 is loaded with context when calling SlotOperand above.
+          int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
+          __ mov(r3, Operand(offset));
+          __ RecordWrite(r2, r3, r1);
+        }
+        // If we definitely did not jump over the assignment, we do not need
+        // to bind the exit label.  Doing so can defeat peephole
+        // optimization.
+        if (init_state == CONST_INIT || slot->type() == Slot::CONTEXT) {
+          exit.Bind();
+        }
+      }
+      break;
+    }
+
+    case NAMED: {
+      Comment cmnt(masm, "[ Store to named Property");
+      // Call the appropriate IC code.
+      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+      Handle<String> name(GetName());
+
+      Result value = cgen_->allocator()->Allocate(r0);
+      ASSERT(value.is_valid());
+      frame->EmitPop(value.reg());
+
+      // Setup the name register.
+      Result property_name = cgen_->allocator()->Allocate(r2);
+      ASSERT(property_name.is_valid());
+      __ mov(property_name.reg(), Operand(name));
+      Result answer = frame->CallCodeObject(ic,
+                                            RelocInfo::CODE_TARGET,
+                                            &value,
+                                            &property_name,
+                                            0);
+      frame->EmitPush(answer.reg());
+      break;
+    }
+
+    case KEYED: {
+      Comment cmnt(masm, "[ Store to keyed Property");
+      Property* property = expression_->AsProperty();
+      ASSERT(property != NULL);
+      cgen_->CodeForSourcePosition(property->position());
+
+      // Call IC code.
+      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+      // TODO(1222589): Make the IC grab the values from the stack.
+      Result value = cgen_->allocator()->Allocate(r0);
+      ASSERT(value.is_valid());
+      frame->EmitPop(value.reg());  // value
+      Result result =
+          frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, &value, 0);
+      frame->EmitPush(result.reg());
+      break;
+    }
+
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void GetPropertyStub::Generate(MacroAssembler* masm) {
+  // sp[0]: key
+  // sp[1]: receiver
+  Label slow, fast;
+  // Get the key and receiver object from the stack.
+  __ ldm(ia, sp, r0.bit() | r1.bit());
+  // Check that the key is a smi.
+  __ tst(r0, Operand(kSmiTagMask));
+  __ b(ne, &slow);
+  __ mov(r0, Operand(r0, ASR, kSmiTagSize));
+  // Check that the object isn't a smi.
+  __ tst(r1, Operand(kSmiTagMask));
+  __ b(eq, &slow);
+
+  // Check that the object is some kind of JS object EXCEPT JS Value type.
+  // In the case that the object is a value-wrapper object,
+  // we enter the runtime system to make sure that indexing into string
+  // objects work as intended.
+  ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
+  __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+  __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
+  __ cmp(r2, Operand(JS_OBJECT_TYPE));
+  __ b(lt, &slow);
+
+  // Get the elements array of the object.
+  __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset));
+  // Check that the object is in fast mode (not dictionary).
+  __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
+  __ cmp(r3, Operand(Factory::hash_table_map()));
+  __ b(eq, &slow);
+  // Check that the key (index) is within bounds.
+  __ ldr(r3, FieldMemOperand(r1, Array::kLengthOffset));
+  __ cmp(r0, Operand(r3));
+  __ b(lo, &fast);
+
+  // Slow case: Push extra copies of the arguments (2).
+  __ bind(&slow);
+  __ ldm(ia, sp, r0.bit() | r1.bit());
+  __ stm(db_w, sp, r0.bit() | r1.bit());
+  // Do tail-call to runtime routine.
+  __ TailCallRuntime(ExternalReference(Runtime::kGetProperty), 2);
+
+  // Fast case: Do the load.
+  __ bind(&fast);
+  __ add(r3, r1, Operand(Array::kHeaderSize - kHeapObjectTag));
+  __ ldr(r0, MemOperand(r3, r0, LSL, kPointerSizeLog2));
+  __ cmp(r0, Operand(Factory::the_hole_value()));
+  // In case the loaded value is the_hole we have to consult GetProperty
+  // to ensure the prototype chain is searched.
+  __ b(eq, &slow);
+
+  __ StubReturn(1);
+}
+
+
+void SetPropertyStub::Generate(MacroAssembler* masm) {
+  // r0 : value
+  // sp[0] : key
+  // sp[1] : receiver
+
+  Label slow, fast, array, extra, exit;
+  // Get the key and the object from the stack.
+  __ ldm(ia, sp, r1.bit() | r3.bit());  // r1 = key, r3 = receiver
+  // Check that the key is a smi.
+  __ tst(r1, Operand(kSmiTagMask));
+  __ b(ne, &slow);
+  // Check that the object isn't a smi.
+  __ tst(r3, Operand(kSmiTagMask));
+  __ b(eq, &slow);
+  // Get the type of the object from its map.
+  __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
+  __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
+  // Check if the object is a JS array or not.
+  __ cmp(r2, Operand(JS_ARRAY_TYPE));
+  __ b(eq, &array);
+  // Check that the object is some kind of JS object.
+  __ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE));
+  __ b(lt, &slow);
+
+
+  // Object case: Check key against length in the elements array.
+  __ ldr(r3, FieldMemOperand(r3, JSObject::kElementsOffset));
+  // Check that the object is in fast mode (not dictionary).
+  __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
+  __ cmp(r2, Operand(Factory::hash_table_map()));
+  __ b(eq, &slow);
+  // Untag the key (for checking against untagged length in the fixed array).
+  __ mov(r1, Operand(r1, ASR, kSmiTagSize));
+  // Compute address to store into and check array bounds.
+  __ add(r2, r3, Operand(Array::kHeaderSize - kHeapObjectTag));
+  __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2));
+  __ ldr(ip, FieldMemOperand(r3, Array::kLengthOffset));
+  __ cmp(r1, Operand(ip));
+  __ b(lo, &fast);
+
+
+  // Slow case: Push extra copies of the arguments (3).
+  __ bind(&slow);
+  __ ldm(ia, sp, r1.bit() | r3.bit());  // r0 == value, r1 == key, r3 == object
+  __ stm(db_w, sp, r0.bit() | r1.bit() | r3.bit());
+  // Do tail-call to runtime routine.
+  __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3);
+
+
+  // Extra capacity case: Check if there is extra capacity to
+  // perform the store and update the length. Used for adding one
+  // element to the array by writing to array[array.length].
+  // r0 == value, r1 == key, r2 == elements, r3 == object
+  __ bind(&extra);
+  __ b(ne, &slow);  // do not leave holes in the array
+  __ mov(r1, Operand(r1, ASR, kSmiTagSize));  // untag
+  __ ldr(ip, FieldMemOperand(r2, Array::kLengthOffset));
+  __ cmp(r1, Operand(ip));
+  __ b(hs, &slow);
+  __ mov(r1, Operand(r1, LSL, kSmiTagSize));  // restore tag
+  __ add(r1, r1, Operand(1 << kSmiTagSize));  // and increment
+  __ str(r1, FieldMemOperand(r3, JSArray::kLengthOffset));
+  __ mov(r3, Operand(r2));
+  // NOTE: Computing the address to store into must take the fact
+  // that the key has been incremented into account.
+  int displacement = Array::kHeaderSize - kHeapObjectTag -
+      ((1 << kSmiTagSize) * 2);
+  __ add(r2, r2, Operand(displacement));
+  __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));
+  __ b(&fast);
+
+
+  // Array case: Get the length and the elements array from the JS
+  // array. Check that the array is in fast mode; if it is the
+  // length is always a smi.
+  // r0 == value, r3 == object
+  __ bind(&array);
+  __ ldr(r2, FieldMemOperand(r3, JSObject::kElementsOffset));
+  __ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset));
+  __ cmp(r1, Operand(Factory::hash_table_map()));
+  __ b(eq, &slow);
+
+  // Check the key against the length in the array, compute the
+  // address to store into and fall through to fast case.
+  __ ldr(r1, MemOperand(sp));
+  // r0 == value, r1 == key, r2 == elements, r3 == object.
+  __ ldr(ip, FieldMemOperand(r3, JSArray::kLengthOffset));
+  __ cmp(r1, Operand(ip));
+  __ b(hs, &extra);
+  __ mov(r3, Operand(r2));
+  __ add(r2, r2, Operand(Array::kHeaderSize - kHeapObjectTag));
+  __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));
+
+
+  // Fast case: Do the store.
+  // r0 == value, r2 == address to store into, r3 == elements
+  __ bind(&fast);
+  __ str(r0, MemOperand(r2));
+  // Skip write barrier if the written value is a smi.
+  __ tst(r0, Operand(kSmiTagMask));
+  __ b(eq, &exit);
+  // Update write barrier for the elements array address.
+  __ sub(r1, r2, Operand(r3));
+  __ RecordWrite(r3, r1, r2);
+  __ bind(&exit);
+  __ StubReturn(1);
+}
+
+
+void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
+  // r1 : x
+  // r0 : y
+  // result : r0
+
+  switch (op_) {
+    case Token::ADD: {
+      Label slow, exit;
+      // fast path
+      __ orr(r2, r1, Operand(r0));  // r2 = x | y;
+      __ add(r0, r1, Operand(r0), SetCC);  // add y optimistically
+      // go slow-path in case of overflow
+      __ b(vs, &slow);
+      // go slow-path in case of non-smi operands
+      ASSERT(kSmiTag == 0);  // adjust code below
+      __ tst(r2, Operand(kSmiTagMask));
+      __ b(eq, &exit);
+      // slow path
+      __ bind(&slow);
+      __ sub(r0, r0, Operand(r1));  // revert optimistic add
+      __ push(r1);
+      __ push(r0);
+      __ mov(r0, Operand(1));  // set number of arguments
+      __ InvokeBuiltin(Builtins::ADD, JUMP_JS);
+      // done
+      __ bind(&exit);
+      break;
+    }
+
+    case Token::SUB: {
+      Label slow, exit;
+      // fast path
+      __ orr(r2, r1, Operand(r0));  // r2 = x | y;
+      __ sub(r3, r1, Operand(r0), SetCC);  // subtract y optimistically
+      // go slow-path in case of overflow
+      __ b(vs, &slow);
+      // go slow-path in case of non-smi operands
+      ASSERT(kSmiTag == 0);  // adjust code below
+      __ tst(r2, Operand(kSmiTagMask));
+      __ mov(r0, Operand(r3), LeaveCC, eq);  // conditionally set r0 to result
+      __ b(eq, &exit);
+      // slow path
+      __ bind(&slow);
+      __ push(r1);
+      __ push(r0);
+      __ mov(r0, Operand(1));  // set number of arguments
+      __ InvokeBuiltin(Builtins::SUB, JUMP_JS);
+      // done
+      __ bind(&exit);
+      break;
+    }
+
+    case Token::MUL: {
+      Label slow, exit;
+      // tag check
+      __ orr(r2, r1, Operand(r0));  // r2 = x | y;
+      ASSERT(kSmiTag == 0);  // adjust code below
+      __ tst(r2, Operand(kSmiTagMask));
+      __ b(ne, &slow);
+      // remove tag from one operand (but keep sign), so that result is smi
+      __ mov(ip, Operand(r0, ASR, kSmiTagSize));
+      // do multiplication
+      __ smull(r3, r2, r1, ip);  // r3 = lower 32 bits of ip*r1
+      // go slow on overflows (overflow bit is not set)
+      __ mov(ip, Operand(r3, ASR, 31));
+      __ cmp(ip, Operand(r2));  // no overflow if higher 33 bits are identical
+      __ b(ne, &slow);
+      // go slow on zero result to handle -0
+      __ tst(r3, Operand(r3));
+      __ mov(r0, Operand(r3), LeaveCC, ne);
+      __ b(ne, &exit);
+      // slow case
+      __ bind(&slow);
+      __ push(r1);
+      __ push(r0);
+      __ mov(r0, Operand(1));  // set number of arguments
+      __ InvokeBuiltin(Builtins::MUL, JUMP_JS);
+      // done
+      __ bind(&exit);
+      break;
+    }
+
+    case Token::BIT_OR:
+    case Token::BIT_AND:
+    case Token::BIT_XOR: {
+      Label slow, exit;
+      // tag check
+      __ orr(r2, r1, Operand(r0));  // r2 = x | y;
+      ASSERT(kSmiTag == 0);  // adjust code below
+      __ tst(r2, Operand(kSmiTagMask));
+      __ b(ne, &slow);
+      switch (op_) {
+        case Token::BIT_OR:  __ orr(r0, r0, Operand(r1)); break;
+        case Token::BIT_AND: __ and_(r0, r0, Operand(r1)); break;
+        case Token::BIT_XOR: __ eor(r0, r0, Operand(r1)); break;
+        default: UNREACHABLE();
+      }
+      __ b(&exit);
+      __ bind(&slow);
+      __ push(r1);  // restore stack
+      __ push(r0);
+      __ mov(r0, Operand(1));  // 1 argument (not counting receiver).
+      switch (op_) {
+        case Token::BIT_OR:
+          __ InvokeBuiltin(Builtins::BIT_OR, JUMP_JS);
+          break;
+        case Token::BIT_AND:
+          __ InvokeBuiltin(Builtins::BIT_AND, JUMP_JS);
+          break;
+        case Token::BIT_XOR:
+          __ InvokeBuiltin(Builtins::BIT_XOR, JUMP_JS);
+          break;
+        default:
+          UNREACHABLE();
+      }
+      __ bind(&exit);
+      break;
+    }
+
+    case Token::SHL:
+    case Token::SHR:
+    case Token::SAR: {
+      Label slow, exit;
+      // tag check
+      __ orr(r2, r1, Operand(r0));  // r2 = x | y;
+      ASSERT(kSmiTag == 0);  // adjust code below
+      __ tst(r2, Operand(kSmiTagMask));
+      __ b(ne, &slow);
+      // remove tags from operands (but keep sign)
+      __ mov(r3, Operand(r1, ASR, kSmiTagSize));  // x
+      __ mov(r2, Operand(r0, ASR, kSmiTagSize));  // y
+      // use only the 5 least significant bits of the shift count
+      __ and_(r2, r2, Operand(0x1f));
+      // perform operation
+      switch (op_) {
+        case Token::SAR:
+          __ mov(r3, Operand(r3, ASR, r2));
+          // no checks of result necessary
+          break;
+
+        case Token::SHR:
+          __ mov(r3, Operand(r3, LSR, r2));
+          // check that the *unsigned* result fits in a smi
+          // neither of the two high-order bits can be set:
+          // - 0x80000000: high bit would be lost when smi tagging
+          // - 0x40000000: this number would convert to negative when
+          // smi tagging these two cases can only happen with shifts
+          // by 0 or 1 when handed a valid smi
+          __ and_(r2, r3, Operand(0xc0000000), SetCC);
+          __ b(ne, &slow);
+          break;
+
+        case Token::SHL:
+          __ mov(r3, Operand(r3, LSL, r2));
+          // check that the *signed* result fits in a smi
+          __ add(r2, r3, Operand(0x40000000), SetCC);
+          __ b(mi, &slow);
+          break;
+
+        default: UNREACHABLE();
+      }
+      // tag result and store it in r0
+      ASSERT(kSmiTag == 0);  // adjust code below
+      __ mov(r0, Operand(r3, LSL, kSmiTagSize));
+      __ b(&exit);
+      // slow case
+      __ bind(&slow);
+      __ push(r1);  // restore stack
+      __ push(r0);
+      __ mov(r0, Operand(1));  // 1 argument (not counting receiver).
+      switch (op_) {
+        case Token::SAR: __ InvokeBuiltin(Builtins::SAR, JUMP_JS); break;
+        case Token::SHR: __ InvokeBuiltin(Builtins::SHR, JUMP_JS); break;
+        case Token::SHL: __ InvokeBuiltin(Builtins::SHL, JUMP_JS); break;
+        default: UNREACHABLE();
+      }
+      __ bind(&exit);
+      break;
+    }
+
+    default: UNREACHABLE();
+  }
+  __ Ret();
+}
+
+
+void StackCheckStub::Generate(MacroAssembler* masm) {
+  Label within_limit;
+  __ mov(ip, Operand(ExternalReference::address_of_stack_guard_limit()));
+  __ ldr(ip, MemOperand(ip));
+  __ cmp(sp, Operand(ip));
+  __ b(hs, &within_limit);
+  // Do tail-call to runtime routine.
+  __ push(r0);
+  __ TailCallRuntime(ExternalReference(Runtime::kStackGuard), 1);
+  __ bind(&within_limit);
+
+  __ StubReturn(1);
+}
+
+
+void UnarySubStub::Generate(MacroAssembler* masm) {
+  Label undo;
+  Label slow;
+  Label done;
+
+  // Enter runtime system if the value is not a smi.
+  __ tst(r0, Operand(kSmiTagMask));
+  __ b(ne, &slow);
+
+  // Enter runtime system if the value of the expression is zero
+  // to make sure that we switch between 0 and -0.
+  __ cmp(r0, Operand(0));
+  __ b(eq, &slow);
+
+  // The value of the expression is a smi that is not zero.  Try
+  // optimistic subtraction '0 - value'.
+  __ rsb(r1, r0, Operand(0), SetCC);
+  __ b(vs, &slow);
+
+  // If result is a smi we are done.
+  __ tst(r1, Operand(kSmiTagMask));
+  __ mov(r0, Operand(r1), LeaveCC, eq);  // conditionally set r0 to result
+  __ b(eq, &done);
+
+  // Enter runtime system.
+  __ bind(&slow);
+  __ push(r0);
+  __ mov(r0, Operand(0));  // set number of arguments
+  __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_JS);
+
+  __ bind(&done);
+  __ StubReturn(1);
+}
+
+
+void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
+  // r0 holds exception
+  ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize);  // adjust this code
+  __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
+  __ ldr(sp, MemOperand(r3));
+  __ pop(r2);  // pop next in chain
+  __ str(r2, MemOperand(r3));
+  // restore parameter- and frame-pointer and pop state.
+  __ ldm(ia_w, sp, r3.bit() | pp.bit() | fp.bit());
+  // Before returning we restore the context from the frame pointer if not NULL.
+  // The frame pointer is NULL in the exception handler of a JS entry frame.
+  __ cmp(fp, Operand(0));
+  // Set cp to NULL if fp is NULL.
+  __ mov(cp, Operand(0), LeaveCC, eq);
+  // Restore cp otherwise.
+  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
+  if (kDebug && FLAG_debug_code) __ mov(lr, Operand(pc));
+  __ pop(pc);
+}
+
+
+void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) {
+  // Fetch top stack handler.
+  __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
+  __ ldr(r3, MemOperand(r3));
+
+  // Unwind the handlers until the ENTRY handler is found.
+  Label loop, done;
+  __ bind(&loop);
+  // Load the type of the current stack handler.
+  const int kStateOffset = StackHandlerConstants::kAddressDisplacement +
+      StackHandlerConstants::kStateOffset;
+  __ ldr(r2, MemOperand(r3, kStateOffset));
+  __ cmp(r2, Operand(StackHandler::ENTRY));
+  __ b(eq, &done);
+  // Fetch the next handler in the list.
+  const int kNextOffset =  StackHandlerConstants::kAddressDisplacement +
+      StackHandlerConstants::kNextOffset;
+  __ ldr(r3, MemOperand(r3, kNextOffset));
+  __ jmp(&loop);
+  __ bind(&done);
+
+  // Set the top handler address to next handler past the current ENTRY handler.
+  __ ldr(r0, MemOperand(r3, kNextOffset));
+  __ mov(r2, Operand(ExternalReference(Top::k_handler_address)));
+  __ str(r0, MemOperand(r2));
+
+  // Set external caught exception to false.
+  __ mov(r0, Operand(false));
+  ExternalReference external_caught(Top::k_external_caught_exception_address);
+  __ mov(r2, Operand(external_caught));
+  __ str(r0, MemOperand(r2));
+
+  // Set pending exception and r0 to out of memory exception.
+  Failure* out_of_memory = Failure::OutOfMemoryException();
+  __ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory)));
+  __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address)));
+  __ str(r0, MemOperand(r2));
+
+  // Restore the stack to the address of the ENTRY handler
+  __ mov(sp, Operand(r3));
+
+  // Stack layout at this point. See also PushTryHandler
+  // r3, sp ->   next handler
+  //             state (ENTRY)
+  //             pp
+  //             fp
+  //             lr
+
+  // Discard ENTRY state (r2 is not used), and restore parameter-
+  // and frame-pointer and pop state.
+  __ ldm(ia_w, sp, r2.bit() | r3.bit() | pp.bit() | fp.bit());
+  // Before returning we restore the context from the frame pointer if not NULL.
+  // The frame pointer is NULL in the exception handler of a JS entry frame.
+  __ cmp(fp, Operand(0));
+  // Set cp to NULL if fp is NULL.
+  __ mov(cp, Operand(0), LeaveCC, eq);
+  // Restore cp otherwise.
+  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
+  if (kDebug && FLAG_debug_code) __ mov(lr, Operand(pc));
+  __ pop(pc);
+}
+
+
+void CEntryStub::GenerateCore(MacroAssembler* masm,
+                              Label* throw_normal_exception,
+                              Label* throw_out_of_memory_exception,
+                              StackFrame::Type frame_type,
+                              bool do_gc,
+                              bool always_allocate) {
+  // r0: result parameter for PerformGC, if any
+  // r4: number of arguments including receiver  (C callee-saved)
+  // r5: pointer to builtin function  (C callee-saved)
+  // r6: pointer to the first argument (C callee-saved)
+
+  if (do_gc) {
+    // Passing r0.
+    __ Call(FUNCTION_ADDR(Runtime::PerformGC), RelocInfo::RUNTIME_ENTRY);
+  }
+
+  ExternalReference scope_depth =
+      ExternalReference::heap_always_allocate_scope_depth();
+  if (always_allocate) {
+    __ mov(r0, Operand(scope_depth));
+    __ ldr(r1, MemOperand(r0));
+    __ add(r1, r1, Operand(1));
+    __ str(r1, MemOperand(r0));
+  }
+
+  // Call C built-in.
+  // r0 = argc, r1 = argv
+  __ mov(r0, Operand(r4));
+  __ mov(r1, Operand(r6));
+
+  // TODO(1242173): To let the GC traverse the return address of the exit
+  // frames, we need to know where the return address is. Right now,
+  // we push it on the stack to be able to find it again, but we never
+  // restore from it in case of changes, which makes it impossible to
+  // support moving the C entry code stub. This should be fixed, but currently
+  // this is OK because the CEntryStub gets generated so early in the V8 boot
+  // sequence that it is not moving ever.
+  __ add(lr, pc, Operand(4));  // compute return address: (pc + 8) + 4
+  __ push(lr);
+#if !defined(__arm__)
+  // Notify the simulator of the transition to C code.
+  __ swi(assembler::arm::call_rt_r5);
+#else /* !defined(__arm__) */
+  __ Jump(r5);
+#endif /* !defined(__arm__) */
+
+  if (always_allocate) {
+    // It's okay to clobber r2 and r3 here. Don't mess with r0 and r1
+    // though (contain the result).
+    __ mov(r2, Operand(scope_depth));
+    __ ldr(r3, MemOperand(r2));
+    __ sub(r3, r3, Operand(1));
+    __ str(r3, MemOperand(r2));
+  }
+
+  // check for failure result
+  Label failure_returned;
+  ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
+  // Lower 2 bits of r2 are 0 iff r0 has failure tag.
+  __ add(r2, r0, Operand(1));
+  __ tst(r2, Operand(kFailureTagMask));
+  __ b(eq, &failure_returned);
+
+  // Exit C frame and return.
+  // r0:r1: result
+  // sp: stack pointer
+  // fp: frame pointer
+  // pp: caller's parameter pointer pp  (restored as C callee-saved)
+  __ LeaveExitFrame(frame_type);
+
+  // check if we should retry or throw exception
+  Label retry;
+  __ bind(&failure_returned);
+  ASSERT(Failure::RETRY_AFTER_GC == 0);
+  __ tst(r0, Operand(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
+  __ b(eq, &retry);
+
+  Label continue_exception;
+  // If the returned failure is EXCEPTION then promote Top::pending_exception().
+  __ cmp(r0, Operand(reinterpret_cast<int32_t>(Failure::Exception())));
+  __ b(ne, &continue_exception);
+
+  // Retrieve the pending exception and clear the variable.
+  __ mov(ip, Operand(ExternalReference::the_hole_value_location()));
+  __ ldr(r3, MemOperand(ip));
+  __ mov(ip, Operand(ExternalReference(Top::k_pending_exception_address)));
+  __ ldr(r0, MemOperand(ip));
+  __ str(r3, MemOperand(ip));
+
+  __ bind(&continue_exception);
+  // Special handling of out of memory exception.
+  Failure* out_of_memory = Failure::OutOfMemoryException();
+  __ cmp(r0, Operand(reinterpret_cast<int32_t>(out_of_memory)));
+  __ b(eq, throw_out_of_memory_exception);
+
+  // Handle normal exception.
+  __ jmp(throw_normal_exception);
+
+  __ bind(&retry);  // pass last failure (r0) as parameter (r0) when retrying
+}
+
+
+void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
+  // Called from JavaScript; parameters are on stack as if calling JS function
+  // r0: number of arguments including receiver
+  // r1: pointer to builtin function
+  // fp: frame pointer  (restored after C call)
+  // sp: stack pointer  (restored as callee's pp after C call)
+  // cp: current context  (C callee-saved)
+  // pp: caller's parameter pointer pp  (C callee-saved)
+
+  // NOTE: Invocations of builtins may return failure objects
+  // instead of a proper result. The builtin entry handles
+  // this by performing a garbage collection and retrying the
+  // builtin once.
+
+  StackFrame::Type frame_type = is_debug_break
+      ? StackFrame::EXIT_DEBUG
+      : StackFrame::EXIT;
+
+  // Enter the exit frame that transitions from JavaScript to C++.
+  __ EnterExitFrame(frame_type);
+
+  // r4: number of arguments (C callee-saved)
+  // r5: pointer to builtin function (C callee-saved)
+  // r6: pointer to first argument (C callee-saved)
+
+  Label throw_out_of_memory_exception;
+  Label throw_normal_exception;
+
+  // Call into the runtime system. Collect garbage before the call if
+  // running with --gc-greedy set.
+  if (FLAG_gc_greedy) {
+    Failure* failure = Failure::RetryAfterGC(0);
+    __ mov(r0, Operand(reinterpret_cast<intptr_t>(failure)));
+  }
+  GenerateCore(masm, &throw_normal_exception,
+               &throw_out_of_memory_exception,
+               frame_type,
+               FLAG_gc_greedy,
+               false);
+
+  // Do space-specific GC and retry runtime call.
+  GenerateCore(masm,
+               &throw_normal_exception,
+               &throw_out_of_memory_exception,
+               frame_type,
+               true,
+               false);
+
+  // Do full GC and retry runtime call one final time.
+  Failure* failure = Failure::InternalError();
+  __ mov(r0, Operand(reinterpret_cast<int32_t>(failure)));
+  GenerateCore(masm,
+               &throw_normal_exception,
+               &throw_out_of_memory_exception,
+               frame_type,
+               true,
+               true);
+
+  __ bind(&throw_out_of_memory_exception);
+  GenerateThrowOutOfMemory(masm);
+  // control flow for generated will not return.
+
+  __ bind(&throw_normal_exception);
+  GenerateThrowTOS(masm);
+}
+
+
+void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
+  // r0: code entry
+  // r1: function
+  // r2: receiver
+  // r3: argc
+  // [sp+0]: argv
+
+  Label invoke, exit;
+
+  // Called from C, so do not pop argc and args on exit (preserve sp)
+  // No need to save register-passed args
+  // Save callee-saved registers (incl. cp, pp, and fp), sp, and lr
+  __ stm(db_w, sp, kCalleeSaved | lr.bit());
+
+  // Get address of argv, see stm above.
+  // r0: code entry
+  // r1: function
+  // r2: receiver
+  // r3: argc
+  __ add(r4, sp, Operand((kNumCalleeSaved + 1)*kPointerSize));
+  __ ldr(r4, MemOperand(r4));  // argv
+
+  // Push a frame with special values setup to mark it as an entry frame.
+  // r0: code entry
+  // r1: function
+  // r2: receiver
+  // r3: argc
+  // r4: argv
+  int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
+  __ mov(r8, Operand(-1));  // Push a bad frame pointer to fail if it is used.
+  __ mov(r7, Operand(~ArgumentsAdaptorFrame::SENTINEL));
+  __ mov(r6, Operand(Smi::FromInt(marker)));
+  __ mov(r5, Operand(ExternalReference(Top::k_c_entry_fp_address)));
+  __ ldr(r5, MemOperand(r5));
+  __ stm(db_w, sp, r5.bit() | r6.bit() | r7.bit() | r8.bit());
+
+  // Setup frame pointer for the frame to be pushed.
+  __ add(fp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
+
+  // Call a faked try-block that does the invoke.
+  __ bl(&invoke);
+
+  // Caught exception: Store result (exception) in the pending
+  // exception field in the JSEnv and return a failure sentinel.
+  // Coming in here the fp will be invalid because the PushTryHandler below
+  // sets it to 0 to signal the existence of the JSEntry frame.
+  __ mov(ip, Operand(ExternalReference(Top::k_pending_exception_address)));
+  __ str(r0, MemOperand(ip));
+  __ mov(r0, Operand(reinterpret_cast<int32_t>(Failure::Exception())));
+  __ b(&exit);
+
+  // Invoke: Link this frame into the handler chain.
+  __ bind(&invoke);
+  // Must preserve r0-r4, r5-r7 are available.
+  __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER);
+  // If an exception not caught by another handler occurs, this handler returns
+  // control to the code after the bl(&invoke) above, which restores all
+  // kCalleeSaved registers (including cp, pp and fp) to their saved values
+  // before returning a failure to C.
+
+  // Clear any pending exceptions.
+  __ mov(ip, Operand(ExternalReference::the_hole_value_location()));
+  __ ldr(r5, MemOperand(ip));
+  __ mov(ip, Operand(ExternalReference(Top::k_pending_exception_address)));
+  __ str(r5, MemOperand(ip));
+
+  // Invoke the function by calling through JS entry trampoline builtin.
+  // Notice that we cannot store a reference to the trampoline code directly in
+  // this stub, because runtime stubs are not traversed when doing GC.
+
+  // Expected registers by Builtins::JSEntryTrampoline
+  // r0: code entry
+  // r1: function
+  // r2: receiver
+  // r3: argc
+  // r4: argv
+  if (is_construct) {
+    ExternalReference construct_entry(Builtins::JSConstructEntryTrampoline);
+    __ mov(ip, Operand(construct_entry));
+  } else {
+    ExternalReference entry(Builtins::JSEntryTrampoline);
+    __ mov(ip, Operand(entry));
+  }
+  __ ldr(ip, MemOperand(ip));  // deref address
+
+  // Branch and link to JSEntryTrampoline
+  __ mov(lr, Operand(pc));
+  __ add(pc, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
+
+  // Unlink this frame from the handler chain. When reading the
+  // address of the next handler, there is no need to use the address
+  // displacement since the current stack pointer (sp) points directly
+  // to the stack handler.
+  __ ldr(r3, MemOperand(sp, StackHandlerConstants::kNextOffset));
+  __ mov(ip, Operand(ExternalReference(Top::k_handler_address)));
+  __ str(r3, MemOperand(ip));
+  // No need to restore registers
+  __ add(sp, sp, Operand(StackHandlerConstants::kSize));
+
+  __ bind(&exit);  // r0 holds result
+  // Restore the top frame descriptors from the stack.
+  __ pop(r3);
+  __ mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address)));
+  __ str(r3, MemOperand(ip));
+
+  // Reset the stack to the callee saved registers.
+  __ add(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
+
+  // Restore callee-saved registers and return.
+#ifdef DEBUG
+  if (FLAG_debug_code) __ mov(lr, Operand(pc));
+#endif
+  __ ldm(ia_w, sp, kCalleeSaved | pc.bit());
+}
+
+
+void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) {
+  // Check if the calling frame is an arguments adaptor frame.
+  Label adaptor;
+  __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+  __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
+  __ cmp(r3, Operand(ArgumentsAdaptorFrame::SENTINEL));
+  __ b(eq, &adaptor);
+
+  // Nothing to do: The formal number of parameters has already been
+  // passed in register r0 by calling function. Just return it.
+  __ mov(pc, lr);
+
+  // Arguments adaptor case: Read the arguments length from the
+  // adaptor frame and return it.
+  __ bind(&adaptor);
+  __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
+  __ mov(pc, lr);
+}
+
+
+void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
+  // The displacement is the offset of the last parameter (if any)
+  // relative to the frame pointer.
+  static const int kDisplacement =
+      StandardFrameConstants::kCallerSPOffset - kPointerSize;
+
+  // Check that the key is a smi.
+  Label slow;
+  __ tst(r1, Operand(kSmiTagMask));
+  __ b(ne, &slow);
+
+  // Check if the calling frame is an arguments adaptor frame.
+  Label adaptor;
+  __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+  __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
+  __ cmp(r3, Operand(ArgumentsAdaptorFrame::SENTINEL));
+  __ b(eq, &adaptor);
+
+  // Check index against formal parameters count limit passed in
+  // through register eax. Use unsigned comparison to get negative
+  // check for free.
+  __ cmp(r1, r0);
+  __ b(cs, &slow);
+
+  // Read the argument from the stack and return it.
+  __ sub(r3, r0, r1);
+  __ add(r3, fp, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize));
+  __ ldr(r0, MemOperand(r3, kDisplacement));
+  __ mov(pc, lr);
+
+  // Arguments adaptor case: Check index against actual arguments
+  // limit found in the arguments adaptor frame. Use unsigned
+  // comparison to get negative check for free.
+  __ bind(&adaptor);
+  __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
+  __ cmp(r1, r0);
+  __ b(cs, &slow);
+
+  // Read the argument from the adaptor frame and return it.
+  __ sub(r3, r0, r1);
+  __ add(r3, r2, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize));
+  __ ldr(r0, MemOperand(r3, kDisplacement));
+  __ mov(pc, lr);
+
+  // Slow-case: Handle non-smi or out-of-bounds access to arguments
+  // by calling the runtime system.
+  __ bind(&slow);
+  __ push(r1);
+  __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1);
+}
+
+
+void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) {
+  // Check if the calling frame is an arguments adaptor frame.
+  Label runtime;
+  __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+  __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
+  __ cmp(r3, Operand(ArgumentsAdaptorFrame::SENTINEL));
+  __ b(ne, &runtime);
+
+  // Patch the arguments.length and the parameters pointer.
+  __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
+  __ str(r0, MemOperand(sp, 0 * kPointerSize));
+  __ add(r3, r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
+  __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset));
+  __ str(r3, MemOperand(sp, 1 * kPointerSize));
+
+  // Do the runtime call to allocate the arguments object.
+  __ bind(&runtime);
+  __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3);
+}
+
+
+void CallFunctionStub::Generate(MacroAssembler* masm) {
+  Label slow;
+  // Get the function to call from the stack.
+  // function, receiver [, arguments]
+  __ ldr(r1, MemOperand(sp, (argc_ + 1) * kPointerSize));
+
+  // Check that the function is really a JavaScript function.
+  // r1: pushed function (to be verified)
+  __ tst(r1, Operand(kSmiTagMask));
+  __ b(eq, &slow);
+  // Get the map of the function object.
+  __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+  __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
+  __ cmp(r2, Operand(JS_FUNCTION_TYPE));
+  __ b(ne, &slow);
+
+  // Fast-case: Invoke the function now.
+  // r1: pushed function
+  ParameterCount actual(argc_);
+  __ InvokeFunction(r1, actual, JUMP_FUNCTION);
+
+  // Slow-case: Non-function called.
+  __ bind(&slow);
+  __ mov(r0, Operand(argc_));  // Setup the number of arguments.
+  __ mov(r2, Operand(0));
+  __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
+  __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)),
+          RelocInfo::CODE_TARGET);
+}
+
+
+#undef __
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/codegen-arm.h b/deps/v8/src/codegen-arm.h
new file mode 100644
index 0000000..b072f75
--- /dev/null
+++ b/deps/v8/src/codegen-arm.h
@@ -0,0 +1,446 @@
+// 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_CODEGEN_ARM_H_
+#define V8_CODEGEN_ARM_H_
+
+namespace v8 { namespace internal {
+
+// Forward declarations
+class DeferredCode;
+class RegisterAllocator;
+class RegisterFile;
+
+// Mode to overwrite BinaryExpression values.
+enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
+
+enum InitState { CONST_INIT, NOT_CONST_INIT };
+enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
+
+
+// -------------------------------------------------------------------------
+// Reference support
+
+// A reference is a C++ stack-allocated object that keeps an ECMA
+// reference on the execution stack while in scope. For variables
+// the reference is empty, indicating that it isn't necessary to
+// store state on the stack for keeping track of references to those.
+// For properties, we keep either one (named) or two (indexed) values
+// on the execution stack to represent the reference.
+
+class Reference BASE_EMBEDDED {
+ public:
+  // The values of the types is important, see size().
+  enum Type { ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 };
+  Reference(CodeGenerator* cgen, Expression* expression);
+  ~Reference();
+
+  Expression* expression() const { return expression_; }
+  Type type() const { return type_; }
+  void set_type(Type value) {
+    ASSERT(type_ == ILLEGAL);
+    type_ = value;
+  }
+
+  // The size the reference takes up on the stack.
+  int size() const { return (type_ == ILLEGAL) ? 0 : type_; }
+
+  bool is_illegal() const { return type_ == ILLEGAL; }
+  bool is_slot() const { return type_ == SLOT; }
+  bool is_property() const { return type_ == NAMED || type_ == KEYED; }
+
+  // Return the name.  Only valid for named property references.
+  Handle<String> GetName();
+
+  // Generate code to push the value of the reference on top of the
+  // expression stack.  The reference is expected to be already on top of
+  // the expression stack, and it is left in place with its value above it.
+  void GetValue(TypeofState typeof_state);
+
+  // Generate code to push the value of a reference on top of the expression
+  // stack and then spill the stack frame.  This function is used temporarily
+  // while the code generator is being transformed.
+  inline void GetValueAndSpill(TypeofState typeof_state);
+
+  // Generate code to store the value on top of the expression stack in the
+  // reference.  The reference is expected to be immediately below the value
+  // on the expression stack.  The stored value is left in place (with the
+  // reference intact below it) to support chained assignments.
+  void SetValue(InitState init_state);
+
+ private:
+  CodeGenerator* cgen_;
+  Expression* expression_;
+  Type type_;
+};
+
+
+// -------------------------------------------------------------------------
+// Code generation state
+
+// The state is passed down the AST by the code generator (and back up, in
+// the form of the state of the label pair).  It is threaded through the
+// call stack.  Constructing a state implicitly pushes it on the owning code
+// generator's stack of states, and destroying one implicitly pops it.
+
+class CodeGenState BASE_EMBEDDED {
+ public:
+  // Create an initial code generator state.  Destroying the initial state
+  // leaves the code generator with a NULL state.
+  explicit CodeGenState(CodeGenerator* owner);
+
+  // Create a code generator state based on a code generator's current
+  // state.  The new state has its own typeof state and pair of branch
+  // labels.
+  CodeGenState(CodeGenerator* owner,
+               TypeofState typeof_state,
+               JumpTarget* true_target,
+               JumpTarget* false_target);
+
+  // Destroy a code generator state and restore the owning code generator's
+  // previous state.
+  ~CodeGenState();
+
+  TypeofState typeof_state() const { return typeof_state_; }
+  JumpTarget* true_target() const { return true_target_; }
+  JumpTarget* false_target() const { return false_target_; }
+
+ private:
+  CodeGenerator* owner_;
+  TypeofState typeof_state_;
+  JumpTarget* true_target_;
+  JumpTarget* false_target_;
+  CodeGenState* previous_;
+};
+
+
+// -------------------------------------------------------------------------
+// CodeGenerator
+
+class CodeGenerator: public AstVisitor {
+ public:
+  // Takes a function literal, generates code for it. This function should only
+  // be called by compiler.cc.
+  static Handle<Code> MakeCode(FunctionLiteral* fun,
+                               Handle<Script> script,
+                               bool is_eval);
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  static bool ShouldGenerateLog(Expression* type);
+#endif
+
+  static void SetFunctionInfo(Handle<JSFunction> fun,
+                              int length,
+                              int function_token_position,
+                              int start_position,
+                              int end_position,
+                              bool is_expression,
+                              bool is_toplevel,
+                              Handle<Script> script,
+                              Handle<String> inferred_name);
+
+  // Accessors
+  MacroAssembler* masm() { return masm_; }
+
+  VirtualFrame* frame() const { return frame_; }
+
+  bool has_valid_frame() const { return frame_ != NULL; }
+
+  // Set the virtual frame to be new_frame, with non-frame register
+  // reference counts given by non_frame_registers.  The non-frame
+  // register reference counts of the old frame are returned in
+  // non_frame_registers.
+  void SetFrame(VirtualFrame* new_frame, RegisterFile* non_frame_registers);
+
+  void DeleteFrame();
+
+  RegisterAllocator* allocator() const { return allocator_; }
+
+  CodeGenState* state() { return state_; }
+  void set_state(CodeGenState* state) { state_ = state; }
+
+  void AddDeferred(DeferredCode* code) { deferred_.Add(code); }
+
+  bool in_spilled_code() const { return in_spilled_code_; }
+  void set_in_spilled_code(bool flag) { in_spilled_code_ = flag; }
+
+ private:
+  // Construction/Destruction
+  CodeGenerator(int buffer_size, Handle<Script> script, bool is_eval);
+  virtual ~CodeGenerator() { delete masm_; }
+
+  // Accessors
+  Scope* scope() const { return scope_; }
+
+  // Clearing and generating deferred code.
+  void ClearDeferred();
+  void ProcessDeferred();
+
+  bool is_eval() { return is_eval_; }
+
+  // State
+  bool has_cc() const  { return cc_reg_ != al; }
+  TypeofState typeof_state() const { return state_->typeof_state(); }
+  JumpTarget* true_target() const  { return state_->true_target(); }
+  JumpTarget* false_target() const  { return state_->false_target(); }
+
+
+  // Node visitors.
+  void VisitStatements(ZoneList<Statement*>* statements);
+
+#define DEF_VISIT(type) \
+  void Visit##type(type* node);
+  NODE_LIST(DEF_VISIT)
+#undef DEF_VISIT
+
+  // Visit a statement and then spill the virtual frame if control flow can
+  // reach the end of the statement (ie, it does not exit via break,
+  // continue, return, or throw).  This function is used temporarily while
+  // the code generator is being transformed.
+  void VisitAndSpill(Statement* statement);
+
+  // Visit a list of statements and then spill the virtual frame if control
+  // flow can reach the end of the list.
+  void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
+
+  // Main code generation function
+  void GenCode(FunctionLiteral* fun);
+
+  // The following are used by class Reference.
+  void LoadReference(Reference* ref);
+  void UnloadReference(Reference* ref);
+
+  MemOperand ContextOperand(Register context, int index) const {
+    return MemOperand(context, Context::SlotOffset(index));
+  }
+
+  MemOperand SlotOperand(Slot* slot, Register tmp);
+
+  MemOperand ContextSlotOperandCheckExtensions(Slot* slot,
+                                               Register tmp,
+                                               Register tmp2,
+                                               JumpTarget* slow);
+
+  // Expressions
+  MemOperand GlobalObject() const  {
+    return ContextOperand(cp, Context::GLOBAL_INDEX);
+  }
+
+  void LoadCondition(Expression* x,
+                     TypeofState typeof_state,
+                     JumpTarget* true_target,
+                     JumpTarget* false_target,
+                     bool force_cc);
+  void Load(Expression* x, TypeofState typeof_state = NOT_INSIDE_TYPEOF);
+  void LoadGlobal();
+  void LoadGlobalReceiver(Register scratch);
+
+  // Generate code to push the value of an expression on top of the frame
+  // and then spill the frame fully to memory.  This function is used
+  // temporarily while the code generator is being transformed.
+  void LoadAndSpill(Expression* expression,
+                    TypeofState typeof_state = NOT_INSIDE_TYPEOF);
+
+  // Call LoadCondition and then spill the virtual frame unless control flow
+  // cannot reach the end of the expression (ie, by emitting only
+  // unconditional jumps to the control targets).
+  void LoadConditionAndSpill(Expression* expression,
+                             TypeofState typeof_state,
+                             JumpTarget* true_target,
+                             JumpTarget* false_target,
+                             bool force_control);
+
+  // Read a value from a slot and leave it on top of the expression stack.
+  void LoadFromSlot(Slot* slot, TypeofState typeof_state);
+  void LoadFromGlobalSlotCheckExtensions(Slot* slot,
+                                         TypeofState typeof_state,
+                                         Register tmp,
+                                         Register tmp2,
+                                         JumpTarget* slow);
+
+  // Special code for typeof expressions: Unfortunately, we must
+  // be careful when loading the expression in 'typeof'
+  // expressions. We are not allowed to throw reference errors for
+  // non-existing properties of the global object, so we must make it
+  // look like an explicit property access, instead of an access
+  // through the context chain.
+  void LoadTypeofExpression(Expression* x);
+
+  void ToBoolean(JumpTarget* true_target, JumpTarget* false_target);
+
+  void GenericBinaryOperation(Token::Value op);
+  void Comparison(Condition cc, bool strict = false);
+
+  void SmiOperation(Token::Value op, Handle<Object> value, bool reversed);
+
+  void CallWithArguments(ZoneList<Expression*>* arguments, int position);
+
+  // Control flow
+  void Branch(bool if_true, JumpTarget* target);
+  void CheckStack();
+
+  bool CheckForInlineRuntimeCall(CallRuntime* node);
+  Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node);
+  void ProcessDeclarations(ZoneList<Declaration*>* declarations);
+
+  Handle<Code> ComputeCallInitialize(int argc);
+  Handle<Code> ComputeCallInitializeInLoop(int argc);
+
+  // Declare global variables and functions in the given array of
+  // name/value pairs.
+  void DeclareGlobals(Handle<FixedArray> pairs);
+
+  // Instantiate the function boilerplate.
+  void InstantiateBoilerplate(Handle<JSFunction> boilerplate);
+
+  // Support for type checks.
+  void GenerateIsSmi(ZoneList<Expression*>* args);
+  void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
+  void GenerateIsArray(ZoneList<Expression*>* args);
+
+  // Support for arguments.length and arguments[?].
+  void GenerateArgumentsLength(ZoneList<Expression*>* args);
+  void GenerateArgumentsAccess(ZoneList<Expression*>* args);
+
+  // Support for accessing the value field of an object (used by Date).
+  void GenerateValueOf(ZoneList<Expression*>* args);
+  void GenerateSetValueOf(ZoneList<Expression*>* args);
+
+  // Fast support for charCodeAt(n).
+  void GenerateFastCharCodeAt(ZoneList<Expression*>* args);
+
+  // Fast support for object equality testing.
+  void GenerateObjectEquals(ZoneList<Expression*>* args);
+
+  void GenerateLog(ZoneList<Expression*>* args);
+
+  // Methods and constants for fast case switch statement support.
+  //
+  // Only allow fast-case switch if the range of labels is at most
+  // this factor times the number of case labels.
+  // Value is derived from comparing the size of code generated by the normal
+  // switch code for Smi-labels to the size of a single pointer. If code
+  // quality increases this number should be decreased to match.
+  static const int kFastSwitchMaxOverheadFactor = 10;
+
+  // Minimal number of switch cases required before we allow jump-table
+  // optimization.
+  static const int kFastSwitchMinCaseCount = 5;
+
+  // The limit of the range of a fast-case switch, as a factor of the number
+  // of cases of the switch. Each platform should return a value that
+  // is optimal compared to the default code generated for a switch statement
+  // on that platform.
+  int FastCaseSwitchMaxOverheadFactor();
+
+  // The minimal number of cases in a switch before the fast-case switch
+  // optimization is enabled. Each platform should return a value that
+  // is optimal compared to the default code generated for a switch statement
+  // on that platform.
+  int FastCaseSwitchMinCaseCount();
+
+  // Allocate a jump table and create code to jump through it.
+  // Should call GenerateFastCaseSwitchCases to generate the code for
+  // all the cases at the appropriate point.
+  void GenerateFastCaseSwitchJumpTable(SwitchStatement* node,
+                                       int min_index,
+                                       int range,
+                                       Label* default_label,
+                                       Vector<Label*> case_targets,
+                                       Vector<Label> case_labels);
+
+  // Generate the code for cases for the fast case switch.
+  // Called by GenerateFastCaseSwitchJumpTable.
+  void GenerateFastCaseSwitchCases(SwitchStatement* node,
+                                   Vector<Label> case_labels,
+                                   VirtualFrame* start_frame);
+
+  // Fast support for constant-Smi switches.
+  void GenerateFastCaseSwitchStatement(SwitchStatement* node,
+                                       int min_index,
+                                       int range,
+                                       int default_index);
+
+  // Fast support for constant-Smi switches. Tests whether switch statement
+  // permits optimization and calls GenerateFastCaseSwitch if it does.
+  // Returns true if the fast-case switch was generated, and false if not.
+  bool TryGenerateFastCaseSwitchStatement(SwitchStatement* node);
+
+
+  // Methods used to indicate which source code is generated for. Source
+  // positions are collected by the assembler and emitted with the relocation
+  // information.
+  void CodeForFunctionPosition(FunctionLiteral* fun);
+  void CodeForReturnPosition(FunctionLiteral* fun);
+  void CodeForStatementPosition(Node* node);
+  void CodeForSourcePosition(int pos);
+
+#ifdef DEBUG
+  // True if the registers are valid for entry to a block.
+  bool HasValidEntryRegisters();
+#endif
+
+  bool is_eval_;  // Tells whether code is generated for eval.
+
+  Handle<Script> script_;
+  List<DeferredCode*> deferred_;
+
+  // Assembler
+  MacroAssembler* masm_;  // to generate code
+
+  // Code generation state
+  Scope* scope_;
+  VirtualFrame* frame_;
+  RegisterAllocator* allocator_;
+  Condition cc_reg_;
+  CodeGenState* state_;
+
+  // Jump targets
+  BreakTarget function_return_;
+
+  // True if the function return is shadowed (ie, jumping to the target
+  // function_return_ does not jump to the true function return, but rather
+  // to some unlinking code).
+  bool function_return_is_shadowed_;
+
+  // True when we are in code that expects the virtual frame to be fully
+  // spilled.  Some virtual frame function are disabled in DEBUG builds when
+  // called from spilled code, because they do not leave the virtual frame
+  // in a spilled state.
+  bool in_spilled_code_;
+
+  friend class VirtualFrame;
+  friend class JumpTarget;
+  friend class Reference;
+
+  DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_CODEGEN_ARM_H_
diff --git a/deps/v8/src/codegen-ia32.cc b/deps/v8/src/codegen-ia32.cc
new file mode 100644
index 0000000..663f235
--- /dev/null
+++ b/deps/v8/src/codegen-ia32.cc
@@ -0,0 +1,7116 @@
+// Copyright 2006-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.
+
+#include "v8.h"
+
+#include "bootstrapper.h"
+#include "codegen-inl.h"
+#include "debug.h"
+#include "parser.h"
+#include "register-allocator-inl.h"
+#include "runtime.h"
+#include "scopes.h"
+
+namespace v8 { namespace internal {
+
+#define __ masm_->
+
+// -------------------------------------------------------------------------
+// CodeGenState implementation.
+
+CodeGenState::CodeGenState(CodeGenerator* owner)
+    : owner_(owner),
+      typeof_state_(NOT_INSIDE_TYPEOF),
+      destination_(NULL),
+      previous_(NULL) {
+  owner_->set_state(this);
+}
+
+
+CodeGenState::CodeGenState(CodeGenerator* owner,
+                           TypeofState typeof_state,
+                           ControlDestination* destination)
+    : owner_(owner),
+      typeof_state_(typeof_state),
+      destination_(destination),
+      previous_(owner->state()) {
+  owner_->set_state(this);
+}
+
+
+CodeGenState::~CodeGenState() {
+  ASSERT(owner_->state() == this);
+  owner_->set_state(previous_);
+}
+
+
+// -------------------------------------------------------------------------
+// CodeGenerator implementation
+
+CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script,
+                             bool is_eval)
+    : is_eval_(is_eval),
+      script_(script),
+      deferred_(8),
+      masm_(new MacroAssembler(NULL, buffer_size)),
+      scope_(NULL),
+      frame_(NULL),
+      allocator_(NULL),
+      state_(NULL),
+      loop_nesting_(0),
+      function_return_is_shadowed_(false),
+      in_spilled_code_(false) {
+}
+
+
+// Calling conventions:
+// ebp: caller's frame pointer
+// esp: stack pointer
+// edi: called JS function
+// esi: callee's context
+
+void CodeGenerator::GenCode(FunctionLiteral* fun) {
+  // Record the position for debugging purposes.
+  CodeForFunctionPosition(fun);
+
+  ZoneList<Statement*>* body = fun->body();
+
+  // Initialize state.
+  ASSERT(scope_ == NULL);
+  scope_ = fun->scope();
+  ASSERT(allocator_ == NULL);
+  RegisterAllocator register_allocator(this);
+  allocator_ = &register_allocator;
+  ASSERT(frame_ == NULL);
+  frame_ = new VirtualFrame(this);
+  set_in_spilled_code(false);
+
+  // Adjust for function-level loop nesting.
+  loop_nesting_ += fun->loop_nesting();
+
+  {
+    CodeGenState state(this);
+
+    // Entry:
+    // Stack: receiver, arguments, return address.
+    // ebp: caller's frame pointer
+    // esp: stack pointer
+    // edi: called JS function
+    // esi: callee's context
+    allocator_->Initialize();
+    frame_->Enter();
+
+#ifdef DEBUG
+    if (strlen(FLAG_stop_at) > 0 &&
+        fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
+      frame_->SpillAll();
+      __ int3();
+    }
+#endif
+
+    // Allocate space for locals and initialize them.
+    frame_->AllocateStackSlots(scope_->num_stack_slots());
+    // Initialize the function return target after the locals are set
+    // up, because it needs the expected frame height from the frame.
+    function_return_.Initialize(this, JumpTarget::BIDIRECTIONAL);
+    function_return_is_shadowed_ = false;
+
+    // Allocate the arguments object and copy the parameters into it.
+    if (scope_->arguments() != NULL) {
+      ASSERT(scope_->arguments_shadow() != NULL);
+      Comment cmnt(masm_, "[ Allocate arguments object");
+      ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
+      frame_->PushFunction();
+      frame_->PushReceiverSlotAddress();
+      frame_->Push(Smi::FromInt(scope_->num_parameters()));
+      Result answer = frame_->CallStub(&stub, 3);
+      frame_->Push(&answer);
+    }
+
+    if (scope_->num_heap_slots() > 0) {
+      Comment cmnt(masm_, "[ allocate local context");
+      // Allocate local context.
+      // Get outer context and create a new context based on it.
+      frame_->PushFunction();
+      Result context = frame_->CallRuntime(Runtime::kNewContext, 1);
+
+      // Update context local.
+      frame_->SaveContextRegister();
+
+      // Verify that the runtime call result and esi agree.
+      if (FLAG_debug_code) {
+        __ cmp(context.reg(), Operand(esi));
+        __ Assert(equal, "Runtime::NewContext should end up in esi");
+      }
+    }
+
+    // TODO(1241774): Improve this code:
+    // 1) only needed if we have a context
+    // 2) no need to recompute context ptr every single time
+    // 3) don't copy parameter operand code from SlotOperand!
+    {
+      Comment cmnt2(masm_, "[ copy context parameters into .context");
+
+      // Note that iteration order is relevant here! If we have the same
+      // parameter twice (e.g., function (x, y, x)), and that parameter
+      // needs to be copied into the context, it must be the last argument
+      // passed to the parameter that needs to be copied. This is a rare
+      // case so we don't check for it, instead we rely on the copying
+      // order: such a parameter is copied repeatedly into the same
+      // context location and thus the last value is what is seen inside
+      // the function.
+      for (int i = 0; i < scope_->num_parameters(); i++) {
+        Variable* par = scope_->parameter(i);
+        Slot* slot = par->slot();
+        if (slot != NULL && slot->type() == Slot::CONTEXT) {
+          // The use of SlotOperand below is safe in unspilled code
+          // because the slot is guaranteed to be a context slot.
+          //
+          // There are no parameters in the global scope.
+          ASSERT(!scope_->is_global_scope());
+          frame_->PushParameterAt(i);
+          Result value = frame_->Pop();
+          value.ToRegister();
+
+          // SlotOperand loads context.reg() with the context object
+          // stored to, used below in RecordWrite.
+          Result context = allocator_->Allocate();
+          ASSERT(context.is_valid());
+          __ mov(SlotOperand(slot, context.reg()), value.reg());
+          int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
+          Result scratch = allocator_->Allocate();
+          ASSERT(scratch.is_valid());
+          frame_->Spill(context.reg());
+          frame_->Spill(value.reg());
+          __ RecordWrite(context.reg(), offset, value.reg(), scratch.reg());
+        }
+      }
+    }
+
+    // This section stores the pointer to the arguments object that
+    // was allocated and copied into above. If the address was not
+    // saved to TOS, we push ecx onto the stack.
+    //
+    // Store the arguments object.  This must happen after context
+    // initialization because the arguments object may be stored in the
+    // context.
+    if (scope_->arguments() != NULL) {
+      Comment cmnt(masm_, "[ store arguments object");
+      { Reference shadow_ref(this, scope_->arguments_shadow());
+        ASSERT(shadow_ref.is_slot());
+        { Reference arguments_ref(this, scope_->arguments());
+          ASSERT(arguments_ref.is_slot());
+          // Here we rely on the convenient property that references to slot
+          // take up zero space in the frame (ie, it doesn't matter that the
+          // stored value is actually below the reference on the frame).
+          arguments_ref.SetValue(NOT_CONST_INIT);
+        }
+        shadow_ref.SetValue(NOT_CONST_INIT);
+      }
+      frame_->Drop();  // Value is no longer needed.
+    }
+
+    // Generate code to 'execute' declarations and initialize functions
+    // (source elements). In case of an illegal redeclaration we need to
+    // handle that instead of processing the declarations.
+    if (scope_->HasIllegalRedeclaration()) {
+      Comment cmnt(masm_, "[ illegal redeclarations");
+      scope_->VisitIllegalRedeclaration(this);
+    } else {
+      Comment cmnt(masm_, "[ declarations");
+      ProcessDeclarations(scope_->declarations());
+      // Bail out if a stack-overflow exception occurred when processing
+      // declarations.
+      if (HasStackOverflow()) return;
+    }
+
+    if (FLAG_trace) {
+      frame_->CallRuntime(Runtime::kTraceEnter, 0);
+      // Ignore the return value.
+    }
+    CheckStack();
+
+    // Compile the body of the function in a vanilla state. Don't
+    // bother compiling all the code if the scope has an illegal
+    // redeclaration.
+    if (!scope_->HasIllegalRedeclaration()) {
+      Comment cmnt(masm_, "[ function body");
+#ifdef DEBUG
+      bool is_builtin = Bootstrapper::IsActive();
+      bool should_trace =
+          is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls;
+      if (should_trace) {
+        frame_->CallRuntime(Runtime::kDebugTrace, 0);
+        // Ignore the return value.
+      }
+#endif
+      VisitStatements(body);
+
+      // Handle the return from the function.
+      if (has_valid_frame()) {
+        // If there is a valid frame, control flow can fall off the end of
+        // the body.  In that case there is an implicit return statement.
+        ASSERT(!function_return_is_shadowed_);
+        CodeForReturnPosition(fun);
+        frame_->PrepareForReturn();
+        Result undefined(Factory::undefined_value(), this);
+        if (function_return_.is_bound()) {
+          function_return_.Jump(&undefined);
+        } else {
+          // Though this is a (possibly) backward block, the frames
+          // can only differ on their top element.
+          function_return_.Bind(&undefined, 1);
+          GenerateReturnSequence(&undefined);
+        }
+      } else if (function_return_.is_linked()) {
+        // If the return target has dangling jumps to it, then we have not
+        // yet generated the return sequence.  This can happen when (a)
+        // control does not flow off the end of the body so we did not
+        // compile an artificial return statement just above, and (b) there
+        // are return statements in the body but (c) they are all shadowed.
+        Result return_value(this);
+        // Though this is a (possibly) backward block, the frames can
+        // only differ on their top element.
+        function_return_.Bind(&return_value, 1);
+        GenerateReturnSequence(&return_value);
+      }
+    }
+  }
+
+  // Adjust for function-level loop nesting.
+  loop_nesting_ -= fun->loop_nesting();
+
+  // Code generation state must be reset.
+  ASSERT(state_ == NULL);
+  ASSERT(loop_nesting() == 0);
+  ASSERT(!function_return_is_shadowed_);
+  function_return_.Unuse();
+  DeleteFrame();
+
+  // Process any deferred code using the register allocator.
+  if (HasStackOverflow()) {
+    ClearDeferred();
+  } else {
+    ProcessDeferred();
+  }
+
+  // There is no need to delete the register allocator, it is a
+  // stack-allocated local.
+  allocator_ = NULL;
+  scope_ = NULL;
+}
+
+
+Operand CodeGenerator::SlotOperand(Slot* slot, Register tmp) {
+  // Currently, this assertion will fail if we try to assign to
+  // a constant variable that is constant because it is read-only
+  // (such as the variable referring to a named function expression).
+  // We need to implement assignments to read-only variables.
+  // Ideally, we should do this during AST generation (by converting
+  // such assignments into expression statements); however, in general
+  // we may not be able to make the decision until past AST generation,
+  // that is when the entire program is known.
+  ASSERT(slot != NULL);
+  int index = slot->index();
+  switch (slot->type()) {
+    case Slot::PARAMETER:
+      return frame_->ParameterAt(index);
+
+    case Slot::LOCAL:
+      return frame_->LocalAt(index);
+
+    case Slot::CONTEXT: {
+      // Follow the context chain if necessary.
+      ASSERT(!tmp.is(esi));  // do not overwrite context register
+      Register context = esi;
+      int chain_length = scope()->ContextChainLength(slot->var()->scope());
+      for (int i = 0; i < chain_length; i++) {
+        // Load the closure.
+        // (All contexts, even 'with' contexts, have a closure,
+        // and it is the same for all contexts inside a function.
+        // There is no need to go to the function context first.)
+        __ mov(tmp, ContextOperand(context, Context::CLOSURE_INDEX));
+        // Load the function context (which is the incoming, outer context).
+        __ mov(tmp, FieldOperand(tmp, JSFunction::kContextOffset));
+        context = tmp;
+      }
+      // We may have a 'with' context now. Get the function context.
+      // (In fact this mov may never be the needed, since the scope analysis
+      // may not permit a direct context access in this case and thus we are
+      // always at a function context. However it is safe to dereference be-
+      // cause the function context of a function context is itself. Before
+      // deleting this mov we should try to create a counter-example first,
+      // though...)
+      __ mov(tmp, ContextOperand(context, Context::FCONTEXT_INDEX));
+      return ContextOperand(tmp, index);
+    }
+
+    default:
+      UNREACHABLE();
+      return Operand(eax);
+  }
+}
+
+
+Operand CodeGenerator::ContextSlotOperandCheckExtensions(Slot* slot,
+                                                         Result tmp,
+                                                         JumpTarget* slow) {
+  ASSERT(slot->type() == Slot::CONTEXT);
+  ASSERT(tmp.is_register());
+  Result context(esi, this);
+
+  for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) {
+    if (s->num_heap_slots() > 0) {
+      if (s->calls_eval()) {
+        // Check that extension is NULL.
+        __ cmp(ContextOperand(context.reg(), Context::EXTENSION_INDEX),
+               Immediate(0));
+        slow->Branch(not_equal, not_taken);
+      }
+      __ mov(tmp.reg(), ContextOperand(context.reg(), Context::CLOSURE_INDEX));
+      __ mov(tmp.reg(), FieldOperand(tmp.reg(), JSFunction::kContextOffset));
+      context = tmp;
+    }
+  }
+  // Check that last extension is NULL.
+  __ cmp(ContextOperand(context.reg(), Context::EXTENSION_INDEX),
+         Immediate(0));
+  slow->Branch(not_equal, not_taken);
+  __ mov(tmp.reg(), ContextOperand(context.reg(), Context::FCONTEXT_INDEX));
+  return ContextOperand(tmp.reg(), slot->index());
+}
+
+
+// Emit code to load the value of an expression to the top of the
+// frame. If the expression is boolean-valued it may be compiled (or
+// partially compiled) into control flow to the control destination.
+// If force_control is true, control flow is forced.
+void CodeGenerator::LoadCondition(Expression* x,
+                                  TypeofState typeof_state,
+                                  ControlDestination* dest,
+                                  bool force_control) {
+  ASSERT(!in_spilled_code());
+  int original_height = frame_->height();
+
+  { CodeGenState new_state(this, typeof_state, dest);
+    Visit(x);
+
+    // If we hit a stack overflow, we may not have actually visited
+    // the expression.  In that case, we ensure that we have a
+    // valid-looking frame state because we will continue to generate
+    // code as we unwind the C++ stack.
+    //
+    // It's possible to have both a stack overflow and a valid frame
+    // state (eg, a subexpression overflowed, visiting it returned
+    // with a dummied frame state, and visiting this expression
+    // returned with a normal-looking state).
+    if (HasStackOverflow() &&
+        !dest->is_used() &&
+        frame_->height() == original_height) {
+      dest->Goto(true);
+    }
+  }
+
+  if (force_control && !dest->is_used()) {
+    // Convert the TOS value into flow to the control destination.
+    ToBoolean(dest);
+  }
+
+  ASSERT(!(force_control && !dest->is_used()));
+  ASSERT(dest->is_used() || frame_->height() == original_height + 1);
+}
+
+
+void CodeGenerator::LoadAndSpill(Expression* expression,
+                                 TypeofState typeof_state) {
+  ASSERT(in_spilled_code());
+  set_in_spilled_code(false);
+  Load(expression, typeof_state);
+  frame_->SpillAll();
+  set_in_spilled_code(true);
+}
+
+
+void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
+  ASSERT(!in_spilled_code());
+  JumpTarget true_target(this);
+  JumpTarget false_target(this);
+  ControlDestination dest(&true_target, &false_target, true);
+  LoadCondition(x, typeof_state, &dest, false);
+
+  if (dest.false_was_fall_through()) {
+    // The false target was just bound.
+    JumpTarget loaded(this);
+    frame_->Push(Factory::false_value());
+    // There may be dangling jumps to the true target.
+    if (true_target.is_linked()) {
+      loaded.Jump();
+      true_target.Bind();
+      frame_->Push(Factory::true_value());
+      loaded.Bind();
+    }
+
+  } else if (dest.is_used()) {
+    // There is true, and possibly false, control flow (with true as
+    // the fall through).
+    JumpTarget loaded(this);
+    frame_->Push(Factory::true_value());
+    if (false_target.is_linked()) {
+      loaded.Jump();
+      false_target.Bind();
+      frame_->Push(Factory::false_value());
+      loaded.Bind();
+    }
+
+  } else {
+    // We have a valid value on top of the frame, but we still may
+    // have dangling jumps to the true and false targets from nested
+    // subexpressions (eg, the left subexpressions of the
+    // short-circuited boolean operators).
+    ASSERT(has_valid_frame());
+    if (true_target.is_linked() || false_target.is_linked()) {
+      JumpTarget loaded(this);
+      loaded.Jump();  // Don't lose the current TOS.
+      if (true_target.is_linked()) {
+        true_target.Bind();
+        frame_->Push(Factory::true_value());
+        if (false_target.is_linked()) {
+          loaded.Jump();
+        }
+      }
+      if (false_target.is_linked()) {
+        false_target.Bind();
+        frame_->Push(Factory::false_value());
+      }
+      loaded.Bind();
+    }
+  }
+
+  ASSERT(has_valid_frame());
+  ASSERT(frame_->height() == original_height + 1);
+}
+
+
+void CodeGenerator::LoadGlobal() {
+  if (in_spilled_code()) {
+    frame_->EmitPush(GlobalObject());
+  } else {
+    Result temp = allocator_->Allocate();
+    __ mov(temp.reg(), GlobalObject());
+    frame_->Push(&temp);
+  }
+}
+
+
+void CodeGenerator::LoadGlobalReceiver() {
+  Result temp = allocator_->Allocate();
+  Register reg = temp.reg();
+  __ mov(reg, GlobalObject());
+  __ mov(reg, FieldOperand(reg, GlobalObject::kGlobalReceiverOffset));
+  frame_->Push(&temp);
+}
+
+
+// TODO(1241834): Get rid of this function in favor of just using Load, now
+// that we have the INSIDE_TYPEOF typeof state. => Need to handle global
+// variables w/o reference errors elsewhere.
+void CodeGenerator::LoadTypeofExpression(Expression* x) {
+  Variable* variable = x->AsVariableProxy()->AsVariable();
+  if (variable != NULL && !variable->is_this() && variable->is_global()) {
+    // NOTE: This is somewhat nasty. We force the compiler to load
+    // the variable as if through '<global>.<variable>' to make sure we
+    // do not get reference errors.
+    Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX);
+    Literal key(variable->name());
+    // TODO(1241834): Fetch the position from the variable instead of using
+    // no position.
+    Property property(&global, &key, RelocInfo::kNoPosition);
+    Load(&property);
+  } else {
+    Load(x, INSIDE_TYPEOF);
+  }
+}
+
+
+Reference::Reference(CodeGenerator* cgen, Expression* expression)
+    : cgen_(cgen), expression_(expression), type_(ILLEGAL) {
+  cgen->LoadReference(this);
+}
+
+
+Reference::~Reference() {
+  cgen_->UnloadReference(this);
+}
+
+
+void CodeGenerator::LoadReference(Reference* ref) {
+  // References are loaded from both spilled and unspilled code.  Set the
+  // state to unspilled to allow that (and explicitly spill after
+  // construction at the construction sites).
+  bool was_in_spilled_code = in_spilled_code_;
+  in_spilled_code_ = false;
+
+  Comment cmnt(masm_, "[ LoadReference");
+  Expression* e = ref->expression();
+  Property* property = e->AsProperty();
+  Variable* var = e->AsVariableProxy()->AsVariable();
+
+  if (property != NULL) {
+    // The expression is either a property or a variable proxy that rewrites
+    // to a property.
+    Load(property->obj());
+    // We use a named reference if the key is a literal symbol, unless it is
+    // a string that can be legally parsed as an integer.  This is because
+    // otherwise we will not get into the slow case code that handles [] on
+    // String objects.
+    Literal* literal = property->key()->AsLiteral();
+    uint32_t dummy;
+    if (literal != NULL &&
+        literal->handle()->IsSymbol() &&
+        !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
+      ref->set_type(Reference::NAMED);
+    } else {
+      Load(property->key());
+      ref->set_type(Reference::KEYED);
+    }
+  } else if (var != NULL) {
+    // The expression is a variable proxy that does not rewrite to a
+    // property.  Global variables are treated as named property references.
+    if (var->is_global()) {
+      LoadGlobal();
+      ref->set_type(Reference::NAMED);
+    } else {
+      ASSERT(var->slot() != NULL);
+      ref->set_type(Reference::SLOT);
+    }
+  } else {
+    // Anything else is a runtime error.
+    Load(e);
+    frame_->CallRuntime(Runtime::kThrowReferenceError, 1);
+  }
+
+  in_spilled_code_ = was_in_spilled_code;
+}
+
+
+void CodeGenerator::UnloadReference(Reference* ref) {
+  // Pop a reference from the stack while preserving TOS.
+  Comment cmnt(masm_, "[ UnloadReference");
+  frame_->Nip(ref->size());
+}
+
+
+class ToBooleanStub: public CodeStub {
+ public:
+  ToBooleanStub() { }
+
+  void Generate(MacroAssembler* masm);
+
+ private:
+  Major MajorKey() { return ToBoolean; }
+  int MinorKey() { return 0; }
+};
+
+
+// ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and
+// convert it to a boolean in the condition code register or jump to
+// 'false_target'/'true_target' as appropriate.
+void CodeGenerator::ToBoolean(ControlDestination* dest) {
+  Comment cmnt(masm_, "[ ToBoolean");
+
+  // The value to convert should be popped from the frame.
+  Result value = frame_->Pop();
+  value.ToRegister();
+  // Fast case checks.
+
+  // 'false' => false.
+  __ cmp(value.reg(), Factory::false_value());
+  dest->false_target()->Branch(equal);
+
+  // 'true' => true.
+  __ cmp(value.reg(), Factory::true_value());
+  dest->true_target()->Branch(equal);
+
+  // 'undefined' => false.
+  __ cmp(value.reg(), Factory::undefined_value());
+  dest->false_target()->Branch(equal);
+
+  // Smi => false iff zero.
+  ASSERT(kSmiTag == 0);
+  __ test(value.reg(), Operand(value.reg()));
+  dest->false_target()->Branch(zero);
+  __ test(value.reg(), Immediate(kSmiTagMask));
+  dest->true_target()->Branch(zero);
+
+  // Call the stub for all other cases.
+  frame_->Push(&value);  // Undo the Pop() from above.
+  ToBooleanStub stub;
+  Result temp = frame_->CallStub(&stub, 1);
+  // Convert the result to a condition code.
+  __ test(temp.reg(), Operand(temp.reg()));
+  temp.Unuse();
+  dest->Split(not_equal);
+}
+
+
+class FloatingPointHelper : public AllStatic {
+ public:
+  // Code pattern for loading floating point values. Input values must
+  // be either smi or heap number objects (fp values). Requirements:
+  // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as
+  // floating point numbers on FPU stack.
+  static void LoadFloatOperands(MacroAssembler* masm, Register scratch);
+  // Test if operands are smi or number objects (fp). Requirements:
+  // operand_1 in eax, operand_2 in edx; falls through on float
+  // operands, jumps to the non_float label otherwise.
+  static void CheckFloatOperands(MacroAssembler* masm,
+                                 Label* non_float,
+                                 Register scratch);
+  // Allocate a heap number in new space with undefined value.
+  // Returns tagged pointer in eax, or jumps to need_gc if new space is full.
+  static void AllocateHeapNumber(MacroAssembler* masm,
+                                 Label* need_gc,
+                                 Register scratch1,
+                                 Register scratch2);
+};
+
+
+// Flag that indicates whether or not the code that handles smi arguments
+// should be placed in the stub, inlined, or omitted entirely.
+enum GenericBinaryFlags {
+  SMI_CODE_IN_STUB,
+  SMI_CODE_INLINED
+};
+
+
+class GenericBinaryOpStub: public CodeStub {
+ public:
+  GenericBinaryOpStub(Token::Value op,
+                      OverwriteMode mode,
+                      GenericBinaryFlags flags)
+      : op_(op), mode_(mode), flags_(flags) {
+    ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
+  }
+
+  void GenerateSmiCode(MacroAssembler* masm, Label* slow);
+
+ private:
+  Token::Value op_;
+  OverwriteMode mode_;
+  GenericBinaryFlags flags_;
+
+  const char* GetName();
+
+#ifdef DEBUG
+  void Print() {
+    PrintF("GenericBinaryOpStub (op %s), (mode %d, flags %d)\n",
+           Token::String(op_),
+           static_cast<int>(mode_),
+           static_cast<int>(flags_));
+  }
+#endif
+
+  // Minor key encoding in 16 bits FOOOOOOOOOOOOOMM.
+  class ModeBits: public BitField<OverwriteMode, 0, 2> {};
+  class OpBits: public BitField<Token::Value, 2, 13> {};
+  class FlagBits: public BitField<GenericBinaryFlags, 15, 1> {};
+
+  Major MajorKey() { return GenericBinaryOp; }
+  int MinorKey() {
+    // Encode the parameters in a unique 16 bit value.
+    return OpBits::encode(op_)
+           | ModeBits::encode(mode_)
+           | FlagBits::encode(flags_);
+  }
+  void Generate(MacroAssembler* masm);
+};
+
+
+const char* GenericBinaryOpStub::GetName() {
+  switch (op_) {
+    case Token::ADD: return "GenericBinaryOpStub_ADD";
+    case Token::SUB: return "GenericBinaryOpStub_SUB";
+    case Token::MUL: return "GenericBinaryOpStub_MUL";
+    case Token::DIV: return "GenericBinaryOpStub_DIV";
+    case Token::BIT_OR: return "GenericBinaryOpStub_BIT_OR";
+    case Token::BIT_AND: return "GenericBinaryOpStub_BIT_AND";
+    case Token::BIT_XOR: return "GenericBinaryOpStub_BIT_XOR";
+    case Token::SAR: return "GenericBinaryOpStub_SAR";
+    case Token::SHL: return "GenericBinaryOpStub_SHL";
+    case Token::SHR: return "GenericBinaryOpStub_SHR";
+    default:         return "GenericBinaryOpStub";
+  }
+}
+
+
+// A deferred code class implementing binary operations on likely smis.
+// This class generates both inline code and deferred code.
+// The fastest path is implemented inline.  Deferred code calls
+// the GenericBinaryOpStub stub for slow cases.
+class DeferredInlineBinaryOperation: public DeferredCode {
+ public:
+  DeferredInlineBinaryOperation(CodeGenerator* generator,
+                                Token::Value op,
+                                OverwriteMode mode,
+                                GenericBinaryFlags flags)
+      : DeferredCode(generator), stub_(op, mode, flags), op_(op) {
+    set_comment("[ DeferredInlineBinaryOperation");
+  }
+
+  // Consumes its arguments, left and right, leaving them invalid.
+  Result GenerateInlineCode(Result* left, Result* right);
+
+  virtual void Generate();
+
+ private:
+  GenericBinaryOpStub stub_;
+  Token::Value op_;
+};
+
+
+void DeferredInlineBinaryOperation::Generate() {
+  Result left(generator());
+  Result right(generator());
+  enter()->Bind(&left, &right);
+  generator()->frame()->Push(&left);
+  generator()->frame()->Push(&right);
+  Result answer = generator()->frame()->CallStub(&stub_, 2);
+  exit_.Jump(&answer);
+}
+
+
+void CodeGenerator::GenericBinaryOperation(Token::Value op,
+                                           SmiAnalysis* type,
+                                           OverwriteMode overwrite_mode) {
+  Comment cmnt(masm_, "[ BinaryOperation");
+  Comment cmnt_token(masm_, Token::String(op));
+
+  if (op == Token::COMMA) {
+    // Simply discard left value.
+    frame_->Nip(1);
+    return;
+  }
+
+  // Set the flags based on the operation, type and loop nesting level.
+  GenericBinaryFlags flags;
+  switch (op) {
+    case Token::BIT_OR:
+    case Token::BIT_AND:
+    case Token::BIT_XOR:
+    case Token::SHL:
+    case Token::SHR:
+    case Token::SAR:
+      // Bit operations always assume they likely operate on Smis. Still only
+      // generate the inline Smi check code if this operation is part of a loop.
+      flags = (loop_nesting() > 0)
+              ? SMI_CODE_INLINED
+              : SMI_CODE_IN_STUB;
+      break;
+
+    default:
+      // By default only inline the Smi check code for likely smis if this
+      // operation is part of a loop.
+      flags = ((loop_nesting() > 0) && type->IsLikelySmi())
+              ? SMI_CODE_INLINED
+              : SMI_CODE_IN_STUB;
+      break;
+  }
+
+  Result right = frame_->Pop();
+  Result left = frame_->Pop();
+
+  if (op == Token::ADD) {
+    bool left_is_string = left.static_type().is_jsstring();
+    bool right_is_string = right.static_type().is_jsstring();
+    if (left_is_string || right_is_string) {
+      frame_->Push(&left);
+      frame_->Push(&right);
+      Result answer(this);
+      if (left_is_string) {
+        if (right_is_string) {
+          // TODO(lrn): if (left.is_constant() && right.is_constant())
+          // -- do a compile time cons, if allocation during codegen is allowed.
+          answer = frame_->CallRuntime(Runtime::kStringAdd, 2);
+        } else {
+          answer =
+            frame_->InvokeBuiltin(Builtins::STRING_ADD_LEFT, CALL_FUNCTION, 2);
+        }
+      } else if (right_is_string) {
+        answer =
+          frame_->InvokeBuiltin(Builtins::STRING_ADD_RIGHT, CALL_FUNCTION, 2);
+      }
+      answer.set_static_type(StaticType::jsstring());
+      frame_->Push(&answer);
+      return;
+    }
+    // Neither operand is known to be a string.
+  }
+
+  bool left_is_smi = left.is_constant() && left.handle()->IsSmi();
+  bool left_is_non_smi = left.is_constant() && !left.handle()->IsSmi();
+  bool right_is_smi = right.is_constant() && right.handle()->IsSmi();
+  bool right_is_non_smi = right.is_constant() && !right.handle()->IsSmi();
+  bool generate_no_smi_code = false;  // No smi code at all, inline or in stub.
+
+  if (left_is_smi && right_is_smi) {
+    // Compute the constant result at compile time, and leave it on the frame.
+    int left_int = Smi::cast(*left.handle())->value();
+    int right_int = Smi::cast(*right.handle())->value();
+    if (FoldConstantSmis(op, left_int, right_int)) return;
+  }
+
+  if (left_is_non_smi || right_is_non_smi) {
+    // Set flag so that we go straight to the slow case, with no smi code.
+    generate_no_smi_code = true;
+  } else if (right_is_smi) {
+    ConstantSmiBinaryOperation(op, &left, right.handle(),
+                               type, false, overwrite_mode);
+    return;
+  } else if (left_is_smi) {
+    ConstantSmiBinaryOperation(op, &right, left.handle(),
+                               type, true, overwrite_mode);
+    return;
+  }
+
+  if (flags == SMI_CODE_INLINED && !generate_no_smi_code) {
+    LikelySmiBinaryOperation(op, &left, &right, overwrite_mode);
+  } else {
+    frame_->Push(&left);
+    frame_->Push(&right);
+    // If we know the arguments aren't smis, use the binary operation stub
+    // that does not check for the fast smi case.
+    // The same stub is used for NO_SMI_CODE and SMI_CODE_INLINED.
+    if (generate_no_smi_code) {
+      flags = SMI_CODE_INLINED;
+    }
+    GenericBinaryOpStub stub(op, overwrite_mode, flags);
+    Result answer = frame_->CallStub(&stub, 2);
+    frame_->Push(&answer);
+  }
+}
+
+
+bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) {
+  Object* answer_object = Heap::undefined_value();
+  switch (op) {
+    case Token::ADD:
+      if (Smi::IsValid(left + right)) {
+        answer_object = Smi::FromInt(left + right);
+      }
+      break;
+    case Token::SUB:
+      if (Smi::IsValid(left - right)) {
+        answer_object = Smi::FromInt(left - right);
+      }
+      break;
+    case Token::MUL: {
+        double answer = static_cast<double>(left) * right;
+        if (answer >= Smi::kMinValue && answer <= Smi::kMaxValue) {
+          // If the product is zero and the non-zero factor is negative,
+          // the spec requires us to return floating point negative zero.
+          if (answer != 0 || (left >= 0 && right >= 0)) {
+            answer_object = Smi::FromInt(static_cast<int>(answer));
+          }
+        }
+      }
+      break;
+    case Token::DIV:
+    case Token::MOD:
+      break;
+    case Token::BIT_OR:
+      answer_object = Smi::FromInt(left | right);
+      break;
+    case Token::BIT_AND:
+      answer_object = Smi::FromInt(left & right);
+      break;
+    case Token::BIT_XOR:
+      answer_object = Smi::FromInt(left ^ right);
+      break;
+
+    case Token::SHL: {
+        int shift_amount = right & 0x1F;
+        if (Smi::IsValid(left << shift_amount)) {
+          answer_object = Smi::FromInt(left << shift_amount);
+        }
+        break;
+      }
+    case Token::SHR: {
+        int shift_amount = right & 0x1F;
+        unsigned int unsigned_left = left;
+        unsigned_left >>= shift_amount;
+        if (unsigned_left <= static_cast<unsigned int>(Smi::kMaxValue)) {
+          answer_object = Smi::FromInt(unsigned_left);
+        }
+        break;
+      }
+    case Token::SAR: {
+        int shift_amount = right & 0x1F;
+        unsigned int unsigned_left = left;
+        if (left < 0) {
+          // Perform arithmetic shift of a negative number by
+          // complementing number, logical shifting, complementing again.
+          unsigned_left = ~unsigned_left;
+          unsigned_left >>= shift_amount;
+          unsigned_left = ~unsigned_left;
+        } else {
+          unsigned_left >>= shift_amount;
+        }
+        ASSERT(Smi::IsValid(unsigned_left));  // Converted to signed.
+        answer_object = Smi::FromInt(unsigned_left);  // Converted to signed.
+        break;
+      }
+    default:
+      UNREACHABLE();
+      break;
+  }
+  if (answer_object == Heap::undefined_value()) {
+    return false;
+  }
+  frame_->Push(Handle<Object>(answer_object));
+  return true;
+}
+
+
+void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
+                                             Result* left,
+                                             Result* right,
+                                             OverwriteMode overwrite_mode) {
+  // Implements a binary operation using a deferred code object
+  // and some inline code to operate on smis quickly.
+  DeferredInlineBinaryOperation* deferred =
+      new DeferredInlineBinaryOperation(this, op, overwrite_mode,
+                                        SMI_CODE_INLINED);
+  // Generate the inline code that handles some smi operations,
+  // and jumps to the deferred code for everything else.
+  Result answer = deferred->GenerateInlineCode(left, right);
+  deferred->BindExit(&answer);
+  frame_->Push(&answer);
+}
+
+
+class DeferredInlineSmiOperation: public DeferredCode {
+ public:
+  DeferredInlineSmiOperation(CodeGenerator* generator,
+                             Token::Value op,
+                             Smi* value,
+                             OverwriteMode overwrite_mode)
+      : DeferredCode(generator),
+        op_(op),
+        value_(value),
+        overwrite_mode_(overwrite_mode) {
+    set_comment("[ DeferredInlineSmiOperation");
+  }
+
+  virtual void Generate();
+
+ private:
+  Token::Value op_;
+  Smi* value_;
+  OverwriteMode overwrite_mode_;
+};
+
+
+void DeferredInlineSmiOperation::Generate() {
+  Result left(generator());
+  enter()->Bind(&left);
+  generator()->frame()->Push(&left);
+  generator()->frame()->Push(value_);
+  GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED);
+  Result answer = generator()->frame()->CallStub(&igostub, 2);
+  exit_.Jump(&answer);
+}
+
+
+class DeferredInlineSmiOperationReversed: public DeferredCode {
+ public:
+  DeferredInlineSmiOperationReversed(CodeGenerator* generator,
+                                     Token::Value op,
+                                     Smi* value,
+                                     OverwriteMode overwrite_mode)
+      : DeferredCode(generator),
+        op_(op),
+        value_(value),
+        overwrite_mode_(overwrite_mode) {
+    set_comment("[ DeferredInlineSmiOperationReversed");
+  }
+
+  virtual void Generate();
+
+ private:
+  Token::Value op_;
+  Smi* value_;
+  OverwriteMode overwrite_mode_;
+};
+
+
+void DeferredInlineSmiOperationReversed::Generate() {
+  Result right(generator());
+  enter()->Bind(&right);
+  generator()->frame()->Push(value_);
+  generator()->frame()->Push(&right);
+  GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED);
+  Result answer = generator()->frame()->CallStub(&igostub, 2);
+  exit_.Jump(&answer);
+}
+
+
+class DeferredInlineSmiAdd: public DeferredCode {
+ public:
+  DeferredInlineSmiAdd(CodeGenerator* generator,
+                       Smi* value,
+                       OverwriteMode overwrite_mode)
+      : DeferredCode(generator),
+        value_(value),
+        overwrite_mode_(overwrite_mode) {
+    set_comment("[ DeferredInlineSmiAdd");
+  }
+
+  virtual void Generate();
+
+ private:
+  Smi* value_;
+  OverwriteMode overwrite_mode_;
+};
+
+
+void DeferredInlineSmiAdd::Generate() {
+  // Undo the optimistic add operation and call the shared stub.
+  Result left(generator());  // Initially left + value_.
+  enter()->Bind(&left);
+  left.ToRegister();
+  generator()->frame()->Spill(left.reg());
+  __ sub(Operand(left.reg()), Immediate(value_));
+  generator()->frame()->Push(&left);
+  generator()->frame()->Push(value_);
+  GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED);
+  Result answer = generator()->frame()->CallStub(&igostub, 2);
+  exit_.Jump(&answer);
+}
+
+
+class DeferredInlineSmiAddReversed: public DeferredCode {
+ public:
+  DeferredInlineSmiAddReversed(CodeGenerator* generator,
+                               Smi* value,
+                               OverwriteMode overwrite_mode)
+      : DeferredCode(generator),
+        value_(value),
+        overwrite_mode_(overwrite_mode) {
+    set_comment("[ DeferredInlineSmiAddReversed");
+  }
+
+  virtual void Generate();
+
+ private:
+  Smi* value_;
+  OverwriteMode overwrite_mode_;
+};
+
+
+void DeferredInlineSmiAddReversed::Generate() {
+  // Undo the optimistic add operation and call the shared stub.
+  Result right(generator());  // Initially value_ + right.
+  enter()->Bind(&right);
+  right.ToRegister();
+  generator()->frame()->Spill(right.reg());
+  __ sub(Operand(right.reg()), Immediate(value_));
+  generator()->frame()->Push(value_);
+  generator()->frame()->Push(&right);
+  GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED);
+  Result answer = generator()->frame()->CallStub(&igostub, 2);
+  exit_.Jump(&answer);
+}
+
+
+class DeferredInlineSmiSub: public DeferredCode {
+ public:
+  DeferredInlineSmiSub(CodeGenerator* generator,
+                       Smi* value,
+                       OverwriteMode overwrite_mode)
+      : DeferredCode(generator),
+        value_(value),
+        overwrite_mode_(overwrite_mode) {
+    set_comment("[ DeferredInlineSmiSub");
+  }
+
+  virtual void Generate();
+
+ private:
+  Smi* value_;
+  OverwriteMode overwrite_mode_;
+};
+
+
+void DeferredInlineSmiSub::Generate() {
+  // Undo the optimistic sub operation and call the shared stub.
+  Result left(generator());  // Initially left - value_.
+  enter()->Bind(&left);
+  left.ToRegister();
+  generator()->frame()->Spill(left.reg());
+  __ add(Operand(left.reg()), Immediate(value_));
+  generator()->frame()->Push(&left);
+  generator()->frame()->Push(value_);
+  GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED);
+  Result answer = generator()->frame()->CallStub(&igostub, 2);
+  exit_.Jump(&answer);
+}
+
+
+class DeferredInlineSmiSubReversed: public DeferredCode {
+ public:
+  DeferredInlineSmiSubReversed(CodeGenerator* generator,
+                               Smi* value,
+                               OverwriteMode overwrite_mode)
+      : DeferredCode(generator),
+        value_(value),
+        overwrite_mode_(overwrite_mode) {
+    set_comment("[ DeferredInlineSmiSubReversed");
+  }
+
+  virtual void Generate();
+
+ private:
+  Smi* value_;
+  OverwriteMode overwrite_mode_;
+};
+
+
+void DeferredInlineSmiSubReversed::Generate() {
+  // Call the shared stub.
+  Result right(generator());
+  enter()->Bind(&right);
+  generator()->frame()->Push(value_);
+  generator()->frame()->Push(&right);
+  GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED);
+  Result answer = generator()->frame()->CallStub(&igostub, 2);
+  exit_.Jump(&answer);
+}
+
+
+void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
+                                               Result* operand,
+                                               Handle<Object> value,
+                                               SmiAnalysis* type,
+                                               bool reversed,
+                                               OverwriteMode overwrite_mode) {
+  // NOTE: This is an attempt to inline (a bit) more of the code for
+  // some possible smi operations (like + and -) when (at least) one
+  // of the operands is a constant smi.
+  // Consumes the argument "operand".
+
+  // TODO(199): Optimize some special cases of operations involving a
+  // smi literal (multiply by 2, shift by 0, etc.).
+  if (IsUnsafeSmi(value)) {
+    Result unsafe_operand(value, this);
+    if (reversed) {
+      LikelySmiBinaryOperation(op, &unsafe_operand, operand,
+                               overwrite_mode);
+    } else {
+      LikelySmiBinaryOperation(op, operand, &unsafe_operand,
+                               overwrite_mode);
+    }
+    ASSERT(!operand->is_valid());
+    return;
+  }
+
+  // Get the literal value.
+  Smi* smi_value = Smi::cast(*value);
+  int int_value = smi_value->value();
+
+  switch (op) {
+    case Token::ADD: {
+      DeferredCode* deferred = NULL;
+      if (reversed) {
+        deferred = new DeferredInlineSmiAddReversed(this, smi_value,
+                                                    overwrite_mode);
+      } else {
+        deferred = new DeferredInlineSmiAdd(this, smi_value, overwrite_mode);
+      }
+      operand->ToRegister();
+      frame_->Spill(operand->reg());
+      __ add(Operand(operand->reg()), Immediate(value));
+      deferred->enter()->Branch(overflow, operand, not_taken);
+      __ test(operand->reg(), Immediate(kSmiTagMask));
+      deferred->enter()->Branch(not_zero, operand, not_taken);
+      deferred->BindExit(operand);
+      frame_->Push(operand);
+      break;
+    }
+
+    case Token::SUB: {
+      DeferredCode* deferred = NULL;
+      Result answer(this);  // Only allocate a new register if reversed.
+      if (reversed) {
+        answer = allocator()->Allocate();
+        ASSERT(answer.is_valid());
+        deferred = new DeferredInlineSmiSubReversed(this,
+                                                    smi_value,
+                                                    overwrite_mode);
+        __ Set(answer.reg(), Immediate(value));
+        if (operand->is_register()) {
+          __ sub(answer.reg(), Operand(operand->reg()));
+        } else {
+          ASSERT(operand->is_constant());
+          __ sub(Operand(answer.reg()), Immediate(operand->handle()));
+        }
+      } else {
+        operand->ToRegister();
+        frame_->Spill(operand->reg());
+        deferred = new DeferredInlineSmiSub(this,
+                                            smi_value,
+                                            overwrite_mode);
+        __ sub(Operand(operand->reg()), Immediate(value));
+        answer = *operand;
+      }
+      deferred->enter()->Branch(overflow, operand, not_taken);
+      __ test(answer.reg(), Immediate(kSmiTagMask));
+      deferred->enter()->Branch(not_zero, operand, not_taken);
+      operand->Unuse();
+      deferred->BindExit(&answer);
+      frame_->Push(&answer);
+      break;
+    }
+
+    case Token::SAR: {
+      if (reversed) {
+        Result constant_operand(value, this);
+        LikelySmiBinaryOperation(op, &constant_operand, operand,
+                                 overwrite_mode);
+      } else {
+        // Only the least significant 5 bits of the shift value are used.
+        // In the slow case, this masking is done inside the runtime call.
+        int shift_value = int_value & 0x1f;
+        DeferredCode* deferred =
+            new DeferredInlineSmiOperation(this, Token::SAR, smi_value,
+                                           overwrite_mode);
+        operand->ToRegister();
+        __ test(operand->reg(), Immediate(kSmiTagMask));
+        deferred->enter()->Branch(not_zero, operand, not_taken);
+        if (shift_value > 0) {
+          frame_->Spill(operand->reg());
+          __ sar(operand->reg(), shift_value);
+          __ and_(operand->reg(), ~kSmiTagMask);
+        }
+        deferred->BindExit(operand);
+        frame_->Push(operand);
+      }
+      break;
+    }
+
+    case Token::SHR: {
+      if (reversed) {
+        Result constant_operand(value, this);
+        LikelySmiBinaryOperation(op, &constant_operand, operand,
+                                 overwrite_mode);
+      } else {
+        // Only the least significant 5 bits of the shift value are used.
+        // In the slow case, this masking is done inside the runtime call.
+        int shift_value = int_value & 0x1f;
+        DeferredCode* deferred =
+            new DeferredInlineSmiOperation(this, Token::SHR, smi_value,
+                                           overwrite_mode);
+        operand->ToRegister();
+        __ test(operand->reg(), Immediate(kSmiTagMask));
+        deferred->enter()->Branch(not_zero, operand, not_taken);
+        Result answer = allocator()->Allocate();
+        ASSERT(answer.is_valid());
+        __ mov(answer.reg(), operand->reg());
+        __ sar(answer.reg(), kSmiTagSize);
+        __ shr(answer.reg(), shift_value);
+        // A negative Smi shifted right two is in the positive Smi range.
+        if (shift_value < 2) {
+          __ test(answer.reg(), Immediate(0xc0000000));
+          deferred->enter()->Branch(not_zero, operand, not_taken);
+        }
+        operand->Unuse();
+        ASSERT(kSmiTagSize == times_2);  // Adjust the code if not true.
+        __ lea(answer.reg(),
+               Operand(answer.reg(), answer.reg(), times_1, kSmiTag));
+        deferred->BindExit(&answer);
+        frame_->Push(&answer);
+      }
+      break;
+    }
+
+    case Token::SHL: {
+      if (reversed) {
+        Result constant_operand(value, this);
+        LikelySmiBinaryOperation(op, &constant_operand, operand,
+                                 overwrite_mode);
+      } else {
+        // Only the least significant 5 bits of the shift value are used.
+        // In the slow case, this masking is done inside the runtime call.
+        int shift_value = int_value & 0x1f;
+        DeferredCode* deferred =
+            new DeferredInlineSmiOperation(this, Token::SHL, smi_value,
+                                           overwrite_mode);
+        operand->ToRegister();
+        __ test(operand->reg(), Immediate(kSmiTagMask));
+        deferred->enter()->Branch(not_zero, operand, not_taken);
+        Result answer = allocator()->Allocate();
+        ASSERT(answer.is_valid());
+        __ mov(answer.reg(), operand->reg());
+        ASSERT(kSmiTag == 0);  // adjust code if not the case
+        // We do no shifts, only the Smi conversion, if shift_value is 1.
+        if (shift_value == 0) {
+          __ sar(answer.reg(), kSmiTagSize);
+        } else if (shift_value > 1) {
+          __ shl(answer.reg(), shift_value - 1);
+        }
+        // Convert int result to Smi, checking that it is in int range.
+        ASSERT(kSmiTagSize == times_2);  // adjust code if not the case
+        __ add(answer.reg(), Operand(answer.reg()));
+        deferred->enter()->Branch(overflow, operand, not_taken);
+        operand->Unuse();
+        deferred->BindExit(&answer);
+        frame_->Push(&answer);
+      }
+      break;
+    }
+
+    case Token::BIT_OR:
+    case Token::BIT_XOR:
+    case Token::BIT_AND: {
+      DeferredCode* deferred = NULL;
+      if (reversed) {
+        deferred = new DeferredInlineSmiOperationReversed(this, op, smi_value,
+                                                          overwrite_mode);
+      } else {
+        deferred =  new DeferredInlineSmiOperation(this, op, smi_value,
+                                                   overwrite_mode);
+      }
+      operand->ToRegister();
+      __ test(operand->reg(), Immediate(kSmiTagMask));
+      deferred->enter()->Branch(not_zero, operand, not_taken);
+      frame_->Spill(operand->reg());
+      if (op == Token::BIT_AND) {
+        if (int_value == 0) {
+          __ xor_(Operand(operand->reg()), operand->reg());
+        } else {
+          __ and_(Operand(operand->reg()), Immediate(value));
+        }
+      } else if (op == Token::BIT_XOR) {
+        if (int_value != 0) {
+          __ xor_(Operand(operand->reg()), Immediate(value));
+        }
+      } else {
+        ASSERT(op == Token::BIT_OR);
+        if (int_value != 0) {
+          __ or_(Operand(operand->reg()), Immediate(value));
+        }
+      }
+      deferred->BindExit(operand);
+      frame_->Push(operand);
+      break;
+    }
+
+    default: {
+      Result constant_operand(value, this);
+      if (reversed) {
+        LikelySmiBinaryOperation(op, &constant_operand, operand,
+                                 overwrite_mode);
+      } else {
+        LikelySmiBinaryOperation(op, operand, &constant_operand,
+                                 overwrite_mode);
+      }
+      break;
+    }
+  }
+  ASSERT(!operand->is_valid());
+}
+
+
+class CompareStub: public CodeStub {
+ public:
+  CompareStub(Condition cc, bool strict) : cc_(cc), strict_(strict) { }
+
+  void Generate(MacroAssembler* masm);
+
+ private:
+  Condition cc_;
+  bool strict_;
+
+  Major MajorKey() { return Compare; }
+
+  int MinorKey() {
+    // Encode the three parameters in a unique 16 bit value.
+    ASSERT(static_cast<int>(cc_) < (1 << 15));
+    return (static_cast<int>(cc_) << 1) | (strict_ ? 1 : 0);
+  }
+
+#ifdef DEBUG
+  void Print() {
+    PrintF("CompareStub (cc %d), (strict %s)\n",
+           static_cast<int>(cc_),
+           strict_ ? "true" : "false");
+  }
+#endif
+};
+
+
+void CodeGenerator::Comparison(Condition cc,
+                               bool strict,
+                               ControlDestination* dest) {
+  // Strict only makes sense for equality comparisons.
+  ASSERT(!strict || cc == equal);
+
+  Result left_side(this);
+  Result right_side(this);
+  // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
+  if (cc == greater || cc == less_equal) {
+    cc = ReverseCondition(cc);
+    left_side = frame_->Pop();
+    right_side = frame_->Pop();
+  } else {
+    right_side = frame_->Pop();
+    left_side = frame_->Pop();
+  }
+  ASSERT(cc == less || cc == equal || cc == greater_equal);
+
+  // If either side is a constant smi, optimize the comparison.
+  bool left_side_constant_smi =
+      left_side.is_constant() && left_side.handle()->IsSmi();
+  bool right_side_constant_smi =
+      right_side.is_constant() && right_side.handle()->IsSmi();
+  bool left_side_constant_null =
+      left_side.is_constant() && left_side.handle()->IsNull();
+  bool right_side_constant_null =
+      right_side.is_constant() && right_side.handle()->IsNull();
+
+  if (left_side_constant_smi || right_side_constant_smi) {
+    if (left_side_constant_smi && right_side_constant_smi) {
+      // Trivial case, comparing two constants.
+      int left_value = Smi::cast(*left_side.handle())->value();
+      int right_value = Smi::cast(*right_side.handle())->value();
+      switch (cc) {
+        case less:
+          dest->Goto(left_value < right_value);
+          break;
+        case equal:
+          dest->Goto(left_value == right_value);
+          break;
+        case greater_equal:
+          dest->Goto(left_value >= right_value);
+          break;
+        default:
+          UNREACHABLE();
+      }
+    } else {  // Only one side is a constant Smi.
+      // If left side is a constant Smi, reverse the operands.
+      // Since one side is a constant Smi, conversion order does not matter.
+      if (left_side_constant_smi) {
+        Result temp = left_side;
+        left_side = right_side;
+        right_side = temp;
+        cc = ReverseCondition(cc);
+        // This may reintroduce greater or less_equal as the value of cc.
+        // CompareStub and the inline code both support all values of cc.
+      }
+      // Implement comparison against a constant Smi, inlining the case
+      // where both sides are Smis.
+      left_side.ToRegister();
+      ASSERT(left_side.is_valid());
+      JumpTarget is_smi(this);
+      __ test(left_side.reg(), Immediate(kSmiTagMask));
+      is_smi.Branch(zero, &left_side, &right_side, taken);
+
+      // Setup and call the compare stub, which expects its arguments
+      // in registers.
+      CompareStub stub(cc, strict);
+      Result result = frame_->CallStub(&stub, &left_side, &right_side);
+      result.ToRegister();
+      __ cmp(result.reg(), 0);
+      result.Unuse();
+      dest->true_target()->Branch(cc);
+      dest->false_target()->Jump();
+
+      is_smi.Bind(&left_side, &right_side);
+      left_side.ToRegister();
+      // Test smi equality and comparison by signed int comparison.
+      if (IsUnsafeSmi(right_side.handle())) {
+        right_side.ToRegister();
+        ASSERT(right_side.is_valid());
+        __ cmp(left_side.reg(), Operand(right_side.reg()));
+      } else {
+        __ cmp(Operand(left_side.reg()), Immediate(right_side.handle()));
+      }
+      left_side.Unuse();
+      right_side.Unuse();
+      dest->Split(cc);
+    }
+  } else if (cc == equal &&
+             (left_side_constant_null || right_side_constant_null)) {
+    // To make null checks efficient, we check if either the left side or
+    // the right side is the constant 'null'.
+    // If so, we optimize the code by inlining a null check instead of
+    // calling the (very) general runtime routine for checking equality.
+    Result operand = left_side_constant_null ? right_side : left_side;
+    right_side.Unuse();
+    left_side.Unuse();
+    operand.ToRegister();
+    __ cmp(operand.reg(), Factory::null_value());
+    if (strict) {
+      operand.Unuse();
+      dest->Split(equal);
+    } else {
+      // The 'null' value is only equal to 'undefined' if using non-strict
+      // comparisons.
+      dest->true_target()->Branch(equal);
+      __ cmp(operand.reg(), Factory::undefined_value());
+      dest->true_target()->Branch(equal);
+      __ test(operand.reg(), Immediate(kSmiTagMask));
+      dest->false_target()->Branch(equal);
+
+      // It can be an undetectable object.
+      // Use a scratch register in preference to spilling operand.reg().
+      Result temp = allocator()->Allocate();
+      ASSERT(temp.is_valid());
+      __ mov(temp.reg(),
+             FieldOperand(operand.reg(), HeapObject::kMapOffset));
+      __ movzx_b(temp.reg(),
+                 FieldOperand(temp.reg(), Map::kBitFieldOffset));
+      __ test(temp.reg(), Immediate(1 << Map::kIsUndetectable));
+      temp.Unuse();
+      operand.Unuse();
+      dest->Split(not_zero);
+    }
+  } else {  // Neither side is a constant Smi or null.
+    // If either side is a non-smi constant, skip the smi check.
+    bool known_non_smi =
+        (left_side.is_constant() && !left_side.handle()->IsSmi()) ||
+        (right_side.is_constant() && !right_side.handle()->IsSmi());
+    left_side.ToRegister();
+    right_side.ToRegister();
+    JumpTarget is_smi(this);
+    if (!known_non_smi) {
+      // Check for the smi case.
+      Result temp = allocator_->Allocate();
+      ASSERT(temp.is_valid());
+      __ mov(temp.reg(), left_side.reg());
+      __ or_(temp.reg(), Operand(right_side.reg()));
+      __ test(temp.reg(), Immediate(kSmiTagMask));
+      temp.Unuse();
+      is_smi.Branch(zero, &left_side, &right_side, taken);
+    }
+    // When non-smi, call out to the compare stub, which expects its
+    // arguments in registers.
+    CompareStub stub(cc, strict);
+    Result answer = frame_->CallStub(&stub, &left_side, &right_side);
+    if (cc == equal) {
+      __ test(answer.reg(), Operand(answer.reg()));
+    } else {
+      __ cmp(answer.reg(), 0);
+    }
+    answer.Unuse();
+    if (known_non_smi) {
+      dest->Split(cc);
+    } else {
+      dest->true_target()->Branch(cc);
+      dest->false_target()->Jump();
+      is_smi.Bind(&left_side, &right_side);
+      left_side.ToRegister();
+      right_side.ToRegister();
+      __ cmp(left_side.reg(), Operand(right_side.reg()));
+      right_side.Unuse();
+      left_side.Unuse();
+      dest->Split(cc);
+    }
+  }
+}
+
+
+class CallFunctionStub: public CodeStub {
+ public:
+  explicit CallFunctionStub(int argc) : argc_(argc) { }
+
+  void Generate(MacroAssembler* masm);
+
+ private:
+  int argc_;
+
+#ifdef DEBUG
+  void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); }
+#endif
+
+  Major MajorKey() { return CallFunction; }
+  int MinorKey() { return argc_; }
+};
+
+
+// Call the function just below TOS on the stack with the given
+// arguments. The receiver is the TOS.
+void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
+                                      int position) {
+  // Push the arguments ("left-to-right") on the stack.
+  int arg_count = args->length();
+  for (int i = 0; i < arg_count; i++) {
+    Load(args->at(i));
+  }
+
+  // Record the position for debugging purposes.
+  CodeForSourcePosition(position);
+
+  // Use the shared code stub to call the function.
+  CallFunctionStub call_function(arg_count);
+  Result answer = frame_->CallStub(&call_function, arg_count + 1);
+  // Restore context and replace function on the stack with the
+  // result of the stub invocation.
+  frame_->RestoreContextRegister();
+  frame_->SetElementAt(0, &answer);
+}
+
+
+class DeferredStackCheck: public DeferredCode {
+ public:
+  explicit DeferredStackCheck(CodeGenerator* generator)
+      : DeferredCode(generator) {
+    set_comment("[ DeferredStackCheck");
+  }
+
+  virtual void Generate();
+};
+
+
+void DeferredStackCheck::Generate() {
+  enter()->Bind();
+  StackCheckStub stub;
+  Result ignored = generator()->frame()->CallStub(&stub, 0);
+  ignored.Unuse();
+  exit_.Jump();
+}
+
+
+void CodeGenerator::CheckStack() {
+  if (FLAG_check_stack) {
+    DeferredStackCheck* deferred = new DeferredStackCheck(this);
+    ExternalReference stack_guard_limit =
+        ExternalReference::address_of_stack_guard_limit();
+    __ cmp(esp, Operand::StaticVariable(stack_guard_limit));
+    deferred->enter()->Branch(below, not_taken);
+    deferred->BindExit();
+  }
+}
+
+
+void CodeGenerator::VisitAndSpill(Statement* statement) {
+  ASSERT(in_spilled_code());
+  set_in_spilled_code(false);
+  Visit(statement);
+  if (frame_ != NULL) {
+    frame_->SpillAll();
+  }
+  set_in_spilled_code(true);
+}
+
+
+void CodeGenerator::VisitStatementsAndSpill(ZoneList<Statement*>* statements) {
+  ASSERT(in_spilled_code());
+  set_in_spilled_code(false);
+  VisitStatements(statements);
+  if (frame_ != NULL) {
+    frame_->SpillAll();
+  }
+  set_in_spilled_code(true);
+}
+
+
+void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) {
+  ASSERT(!in_spilled_code());
+  for (int i = 0; has_valid_frame() && i < statements->length(); i++) {
+    Visit(statements->at(i));
+  }
+}
+
+
+void CodeGenerator::VisitBlock(Block* node) {
+  ASSERT(!in_spilled_code());
+  Comment cmnt(masm_, "[ Block");
+  CodeForStatementPosition(node);
+  node->break_target()->Initialize(this);
+  VisitStatements(node->statements());
+  if (node->break_target()->is_linked()) {
+    node->break_target()->Bind();
+  }
+  node->break_target()->Unuse();
+}
+
+
+void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
+  frame_->Push(pairs);
+
+  // Duplicate the context register.
+  Result context(esi, this);
+  frame_->Push(&context);
+
+  frame_->Push(Smi::FromInt(is_eval() ? 1 : 0));
+  Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3);
+  // Return value is ignored.
+}
+
+
+void CodeGenerator::VisitDeclaration(Declaration* node) {
+  Comment cmnt(masm_, "[ Declaration");
+  CodeForStatementPosition(node);
+  Variable* var = node->proxy()->var();
+  ASSERT(var != NULL);  // must have been resolved
+  Slot* slot = var->slot();
+
+  // If it was not possible to allocate the variable at compile time,
+  // we need to "declare" it at runtime to make sure it actually
+  // exists in the local context.
+  if (slot != NULL && slot->type() == Slot::LOOKUP) {
+    // Variables with a "LOOKUP" slot were introduced as non-locals
+    // during variable resolution and must have mode DYNAMIC.
+    ASSERT(var->is_dynamic());
+    // For now, just do a runtime call.  Duplicate the context register.
+    Result context(esi, this);
+    frame_->Push(&context);
+    frame_->Push(var->name());
+    // Declaration nodes are always introduced in one of two modes.
+    ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST);
+    PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY;
+    frame_->Push(Smi::FromInt(attr));
+    // Push initial value, if any.
+    // Note: For variables we must not push an initial value (such as
+    // 'undefined') because we may have a (legal) redeclaration and we
+    // must not destroy the current value.
+    if (node->mode() == Variable::CONST) {
+      frame_->Push(Factory::the_hole_value());
+    } else if (node->fun() != NULL) {
+      Load(node->fun());
+    } else {
+      frame_->Push(Smi::FromInt(0));  // no initial value!
+    }
+    Result ignored = frame_->CallRuntime(Runtime::kDeclareContextSlot, 4);
+    // Ignore the return value (declarations are statements).
+    return;
+  }
+
+  ASSERT(!var->is_global());
+
+  // If we have a function or a constant, we need to initialize the variable.
+  Expression* val = NULL;
+  if (node->mode() == Variable::CONST) {
+    val = new Literal(Factory::the_hole_value());
+  } else {
+    val = node->fun();  // NULL if we don't have a function
+  }
+
+  if (val != NULL) {
+    {
+      // Set the initial value.
+      Reference target(this, node->proxy());
+      Load(val);
+      target.SetValue(NOT_CONST_INIT);
+      // The reference is removed from the stack (preserving TOS) when
+      // it goes out of scope.
+    }
+    // Get rid of the assigned value (declarations are statements).
+    frame_->Drop();
+  }
+}
+
+
+void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) {
+  ASSERT(!in_spilled_code());
+  Comment cmnt(masm_, "[ ExpressionStatement");
+  CodeForStatementPosition(node);
+  Expression* expression = node->expression();
+  expression->MarkAsStatement();
+  Load(expression);
+  // Remove the lingering expression result from the top of stack.
+  frame_->Drop();
+}
+
+
+void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) {
+  ASSERT(!in_spilled_code());
+  Comment cmnt(masm_, "// EmptyStatement");
+  CodeForStatementPosition(node);
+  // nothing to do
+}
+
+
+void CodeGenerator::VisitIfStatement(IfStatement* node) {
+  ASSERT(!in_spilled_code());
+  Comment cmnt(masm_, "[ IfStatement");
+  // Generate different code depending on which parts of the if statement
+  // are present or not.
+  bool has_then_stm = node->HasThenStatement();
+  bool has_else_stm = node->HasElseStatement();
+
+  CodeForStatementPosition(node);
+  JumpTarget exit(this);
+  if (has_then_stm && has_else_stm) {
+    JumpTarget then(this);
+    JumpTarget else_(this);
+    ControlDestination dest(&then, &else_, true);
+    LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true);
+
+    if (dest.false_was_fall_through()) {
+      // The else target was bound, so we compile the else part first.
+      Visit(node->else_statement());
+
+      // We may have dangling jumps to the then part.
+      if (then.is_linked()) {
+        if (has_valid_frame()) exit.Jump();
+        then.Bind();
+        Visit(node->then_statement());
+      }
+    } else {
+      // The then target was bound, so we compile the then part first.
+      Visit(node->then_statement());
+
+      if (else_.is_linked()) {
+        if (has_valid_frame()) exit.Jump();
+        else_.Bind();
+        Visit(node->else_statement());
+      }
+    }
+
+  } else if (has_then_stm) {
+    ASSERT(!has_else_stm);
+    JumpTarget then(this);
+    ControlDestination dest(&then, &exit, true);
+    LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true);
+
+    if (dest.false_was_fall_through()) {
+      // The exit label was bound.  We may have dangling jumps to the
+      // then part.
+      if (then.is_linked()) {
+        exit.Unuse();
+        exit.Jump();
+        then.Bind();
+        Visit(node->then_statement());
+      }
+    } else {
+      // The then label was bound.
+      Visit(node->then_statement());
+    }
+
+  } else if (has_else_stm) {
+    ASSERT(!has_then_stm);
+    JumpTarget else_(this);
+    ControlDestination dest(&exit, &else_, false);
+    LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true);
+
+    if (dest.true_was_fall_through()) {
+      // The exit label was bound.  We may have dangling jumps to the
+      // else part.
+      if (else_.is_linked()) {
+        exit.Unuse();
+        exit.Jump();
+        else_.Bind();
+        Visit(node->else_statement());
+      }
+    } else {
+      // The else label was bound.
+      Visit(node->else_statement());
+    }
+
+  } else {
+    ASSERT(!has_then_stm && !has_else_stm);
+    // We only care about the condition's side effects (not its value
+    // or control flow effect).  LoadCondition is called without
+    // forcing control flow.
+    ControlDestination dest(&exit, &exit, true);
+    LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, false);
+    if (!dest.is_used()) {
+      // We got a value on the frame rather than (or in addition to)
+      // control flow.
+      frame_->Drop();
+    }
+  }
+
+  if (exit.is_linked()) {
+    exit.Bind();
+  }
+}
+
+
+void CodeGenerator::VisitContinueStatement(ContinueStatement* node) {
+  ASSERT(!in_spilled_code());
+  Comment cmnt(masm_, "[ ContinueStatement");
+  CodeForStatementPosition(node);
+  node->target()->continue_target()->Jump();
+}
+
+
+void CodeGenerator::VisitBreakStatement(BreakStatement* node) {
+  ASSERT(!in_spilled_code());
+  Comment cmnt(masm_, "[ BreakStatement");
+  CodeForStatementPosition(node);
+  node->target()->break_target()->Jump();
+}
+
+
+void CodeGenerator::VisitReturnStatement(ReturnStatement* node) {
+  ASSERT(!in_spilled_code());
+  Comment cmnt(masm_, "[ ReturnStatement");
+
+  CodeForStatementPosition(node);
+  Load(node->expression());
+  Result return_value = frame_->Pop();
+  if (function_return_is_shadowed_) {
+    function_return_.Jump(&return_value);
+  } else {
+    frame_->PrepareForReturn();
+    if (function_return_.is_bound()) {
+      // If the function return label is already bound we reuse the
+      // code by jumping to the return site.
+      function_return_.Jump(&return_value);
+    } else {
+      // Though this is a (possibly) backward block, the frames can
+      // only differ on their top element.
+      function_return_.Bind(&return_value, 1);
+      GenerateReturnSequence(&return_value);
+    }
+  }
+}
+
+
+void CodeGenerator::GenerateReturnSequence(Result* return_value) {
+  // The return value is a live (but not currently reference counted)
+  // reference to eax.  This is safe because the current frame does not
+  // contain a reference to eax (it is prepared for the return by spilling
+  // all registers).
+  if (FLAG_trace) {
+    frame_->Push(return_value);
+    *return_value = frame_->CallRuntime(Runtime::kTraceExit, 1);
+  }
+  return_value->ToRegister(eax);
+
+  // Add a label for checking the size of the code used for returning.
+  Label check_exit_codesize;
+  __ bind(&check_exit_codesize);
+
+  // Leave the frame and return popping the arguments and the
+  // receiver.
+  frame_->Exit();
+  __ ret((scope_->num_parameters() + 1) * kPointerSize);
+  DeleteFrame();
+
+  // Check that the size of the code used for returning matches what is
+  // expected by the debugger.
+  ASSERT_EQ(Debug::kIa32JSReturnSequenceLength,
+            __ SizeOfCodeGeneratedSince(&check_exit_codesize));
+}
+
+
+void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) {
+  ASSERT(!in_spilled_code());
+  Comment cmnt(masm_, "[ WithEnterStatement");
+  CodeForStatementPosition(node);
+  Load(node->expression());
+  Result context(this);
+  if (node->is_catch_block()) {
+    context = frame_->CallRuntime(Runtime::kPushCatchContext, 1);
+  } else {
+    context = frame_->CallRuntime(Runtime::kPushContext, 1);
+  }
+
+  // Update context local.
+  frame_->SaveContextRegister();
+
+  // Verify that the runtime call result and esi agree.
+  if (FLAG_debug_code) {
+    __ cmp(context.reg(), Operand(esi));
+    __ Assert(equal, "Runtime::NewContext should end up in esi");
+  }
+}
+
+
+void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) {
+  ASSERT(!in_spilled_code());
+  Comment cmnt(masm_, "[ WithExitStatement");
+  CodeForStatementPosition(node);
+  // Pop context.
+  __ mov(esi, ContextOperand(esi, Context::PREVIOUS_INDEX));
+  // Update context local.
+  frame_->SaveContextRegister();
+}
+
+
+int CodeGenerator::FastCaseSwitchMaxOverheadFactor() {
+    return kFastSwitchMaxOverheadFactor;
+}
+
+
+int CodeGenerator::FastCaseSwitchMinCaseCount() {
+    return kFastSwitchMinCaseCount;
+}
+
+
+// Generate a computed jump to a switch case.
+void CodeGenerator::GenerateFastCaseSwitchJumpTable(
+    SwitchStatement* node,
+    int min_index,
+    int range,
+    Label* default_label,
+    Vector<Label*> case_targets,
+    Vector<Label> case_labels) {
+  // Notice: Internal references, used by both the jmp instruction and
+  // the table entries, need to be relocated if the buffer grows. This
+  // prevents the forward use of Labels, since a displacement cannot
+  // survive relocation, and it also cannot safely be distinguished
+  // from a real address.  Instead we put in zero-values as
+  // placeholders, and fill in the addresses after the labels have been
+  // bound.
+
+  JumpTarget setup_default(this);
+  JumpTarget is_smi(this);
+
+  // A non-null default label pointer indicates a default case among
+  // the case labels.  Otherwise we use the break target as a
+  // "default".
+  JumpTarget* default_target =
+      (default_label == NULL) ? node->break_target() : &setup_default;
+
+  // Test whether input is a smi.
+  ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
+  Result switch_value = frame_->Pop();
+  switch_value.ToRegister();
+  __ test(switch_value.reg(), Immediate(kSmiTagMask));
+  is_smi.Branch(equal, &switch_value, taken);
+
+  // It's a heap object, not a smi or a failure.  Check if it is a
+  // heap number.
+  Result temp = allocator()->Allocate();
+  ASSERT(temp.is_valid());
+  __ CmpObjectType(switch_value.reg(), HEAP_NUMBER_TYPE, temp.reg());
+  temp.Unuse();
+  default_target->Branch(not_equal);
+
+  // The switch value is a heap number.  Convert it to a smi.
+  frame_->Push(&switch_value);
+  Result smi_value = frame_->CallRuntime(Runtime::kNumberToSmi, 1);
+
+  is_smi.Bind(&smi_value);
+  smi_value.ToRegister();
+  // Convert the switch value to a 0-based table index.
+  if (min_index != 0) {
+    frame_->Spill(smi_value.reg());
+    __ sub(Operand(smi_value.reg()), Immediate(min_index << kSmiTagSize));
+  }
+  // Go to the default case if the table index is negative or not a smi.
+  __ test(smi_value.reg(), Immediate(0x80000000 | kSmiTagMask));
+  default_target->Branch(not_equal, not_taken);
+  __ cmp(smi_value.reg(), range << kSmiTagSize);
+  default_target->Branch(greater_equal, not_taken);
+
+  // The expected frame at all the case labels is a version of the
+  // current one (the bidirectional entry frame, which an arbitrary
+  // frame of the correct height can be merged to).  Keep a copy to
+  // restore at the start of every label.  Create a jump target and
+  // bind it to set its entry frame properly.
+  JumpTarget entry_target(this, JumpTarget::BIDIRECTIONAL);
+  entry_target.Bind(&smi_value);
+  VirtualFrame* start_frame = new VirtualFrame(frame_);
+
+  // 0 is placeholder.
+  // Jump to the address at table_address + 2 * smi_value.reg().
+  // The target of the jump is read from table_address + 4 * switch_value.
+  // The Smi encoding of smi_value.reg() is 2 * switch_value.
+  smi_value.ToRegister();
+  __ jmp(Operand(smi_value.reg(), smi_value.reg(),
+                 times_1, 0x0, RelocInfo::INTERNAL_REFERENCE));
+  smi_value.Unuse();
+  // Calculate address to overwrite later with actual address of table.
+  int32_t jump_table_ref = __ pc_offset() - sizeof(int32_t);
+  __ Align(4);
+  Label table_start;
+  __ bind(&table_start);
+  __ WriteInternalReference(jump_table_ref, table_start);
+
+  for (int i = 0; i < range; i++) {
+    // These are the table entries. 0x0 is the placeholder for case address.
+    __ dd(0x0, RelocInfo::INTERNAL_REFERENCE);
+  }
+
+  GenerateFastCaseSwitchCases(node, case_labels, start_frame);
+
+  // If there was a default case, we need to emit the code to match it.
+  if (default_label != NULL) {
+    if (has_valid_frame()) {
+      node->break_target()->Jump();
+    }
+    setup_default.Bind();
+    frame_->MergeTo(start_frame);
+    __ jmp(default_label);
+    DeleteFrame();
+  }
+  if (node->break_target()->is_linked()) {
+    node->break_target()->Bind();
+  }
+
+  for (int i = 0, entry_pos = table_start.pos();
+       i < range;
+       i++, entry_pos += sizeof(uint32_t)) {
+    if (case_targets[i] == NULL) {
+      __ WriteInternalReference(entry_pos,
+                                *node->break_target()->entry_label());
+    } else {
+      __ WriteInternalReference(entry_pos, *case_targets[i]);
+    }
+  }
+
+  delete start_frame;
+}
+
+
+void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
+  ASSERT(!in_spilled_code());
+  Comment cmnt(masm_, "[ SwitchStatement");
+  CodeForStatementPosition(node);
+  node->break_target()->Initialize(this);
+
+  // Compile the switch value.
+  Load(node->tag());
+
+  if (TryGenerateFastCaseSwitchStatement(node)) {
+    return;
+  }
+
+  ZoneList<CaseClause*>* cases = node->cases();
+  int length = cases->length();
+  CaseClause* default_clause = NULL;
+
+  JumpTarget next_test(this);
+  // Compile the case label expressions and comparisons.  Exit early
+  // if a comparison is unconditionally true.  The target next_test is
+  // bound before the loop in order to indicate control flow to the
+  // first comparison.
+  next_test.Bind();
+  for (int i = 0; i < length && !next_test.is_unused(); i++) {
+    CaseClause* clause = cases->at(i);
+    clause->body_target()->Initialize(this);
+    // The default is not a test, but remember it for later.
+    if (clause->is_default()) {
+      default_clause = clause;
+      continue;
+    }
+
+    Comment cmnt(masm_, "[ Case comparison");
+    // We recycle the same target next_test for each test.  Bind it if
+    // the previous test has not done so and then unuse it for the
+    // loop.
+    if (next_test.is_linked()) {
+      next_test.Bind();
+    }
+    next_test.Unuse();
+
+    // Duplicate the switch value.
+    frame_->Dup();
+
+    // Compile the label expression.
+    Load(clause->label());
+
+    // Compare and branch to the body if true or the next test if
+    // false.  Prefer the next test as a fall through.
+    ControlDestination dest(clause->body_target(), &next_test, false);
+    Comparison(equal, true, &dest);
+
+    // If the comparison fell through to the true target, jump to the
+    // actual body.
+    if (dest.true_was_fall_through()) {
+      clause->body_target()->Unuse();
+      clause->body_target()->Jump();
+    }
+  }
+
+  // If there was control flow to a next test from the last one
+  // compiled, compile a jump to the default or break target.
+  if (!next_test.is_unused()) {
+    if (next_test.is_linked()) {
+      next_test.Bind();
+    }
+    // Drop the switch value.
+    frame_->Drop();
+    if (default_clause != NULL) {
+      default_clause->body_target()->Jump();
+    } else {
+      node->break_target()->Jump();
+    }
+  }
+
+
+  // The last instruction emitted was a jump, either to the default
+  // clause or the break target, or else to a case body from the loop
+  // that compiles the tests.
+  ASSERT(!has_valid_frame());
+  // Compile case bodies as needed.
+  for (int i = 0; i < length; i++) {
+    CaseClause* clause = cases->at(i);
+
+    // There are two ways to reach the body: from the corresponding
+    // test or as the fall through of the previous body.
+    if (clause->body_target()->is_linked() || has_valid_frame()) {
+      if (clause->body_target()->is_linked()) {
+        if (has_valid_frame()) {
+          // If we have both a jump to the test and a fall through, put
+          // a jump on the fall through path to avoid the dropping of
+          // the switch value on the test path.  The exception is the
+          // default which has already had the switch value dropped.
+          if (clause->is_default()) {
+            clause->body_target()->Bind();
+          } else {
+            JumpTarget body(this);
+            body.Jump();
+            clause->body_target()->Bind();
+            frame_->Drop();
+            body.Bind();
+          }
+        } else {
+          // No fall through to worry about.
+          clause->body_target()->Bind();
+          if (!clause->is_default()) {
+            frame_->Drop();
+          }
+        }
+      } else {
+        // Otherwise, we have only fall through.
+        ASSERT(has_valid_frame());
+      }
+
+      // We are now prepared to compile the body.
+      Comment cmnt(masm_, "[ Case body");
+      VisitStatements(clause->statements());
+    }
+    clause->body_target()->Unuse();
+  }
+
+  // We may not have a valid frame here so bind the break target only
+  // if needed.
+  if (node->break_target()->is_linked()) {
+    node->break_target()->Bind();
+  }
+  node->break_target()->Unuse();
+}
+
+
+void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
+  ASSERT(!in_spilled_code());
+  Comment cmnt(masm_, "[ LoopStatement");
+  CodeForStatementPosition(node);
+  node->break_target()->Initialize(this);
+
+  // Simple condition analysis.  ALWAYS_TRUE and ALWAYS_FALSE represent a
+  // known result for the test expression, with no side effects.
+  enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW;
+  if (node->cond() == NULL) {
+    ASSERT(node->type() == LoopStatement::FOR_LOOP);
+    info = ALWAYS_TRUE;
+  } else {
+    Literal* lit = node->cond()->AsLiteral();
+    if (lit != NULL) {
+      if (lit->IsTrue()) {
+        info = ALWAYS_TRUE;
+      } else if (lit->IsFalse()) {
+        info = ALWAYS_FALSE;
+      }
+    }
+  }
+
+  switch (node->type()) {
+    case LoopStatement::DO_LOOP: {
+      JumpTarget body(this, JumpTarget::BIDIRECTIONAL);
+      IncrementLoopNesting();
+
+      // Label the top of the loop for the backward jump if necessary.
+      if (info == ALWAYS_TRUE) {
+        // Use the continue target.
+        node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
+        node->continue_target()->Bind();
+      } else if (info == ALWAYS_FALSE) {
+        // No need to label it.
+        node->continue_target()->Initialize(this);
+      } else {
+        // Continue is the test, so use the backward body target.
+        ASSERT(info == DONT_KNOW);
+        node->continue_target()->Initialize(this);
+        body.Bind();
+      }
+
+      CheckStack();  // TODO(1222600): ignore if body contains calls.
+      Visit(node->body());
+
+      // Compile the test.
+      if (info == ALWAYS_TRUE) {
+        // If control flow can fall off the end of the body, jump back
+        // to the top and bind the break target at the exit.
+        if (has_valid_frame()) {
+          node->continue_target()->Jump();
+        }
+        if (node->break_target()->is_linked()) {
+          node->break_target()->Bind();
+        }
+
+      } else if (info == ALWAYS_FALSE) {
+        // We may have had continues or breaks in the body.
+        if (node->continue_target()->is_linked()) {
+          node->continue_target()->Bind();
+        }
+        if (node->break_target()->is_linked()) {
+          node->break_target()->Bind();
+        }
+
+      } else {
+        ASSERT(info == DONT_KNOW);
+        // We have to compile the test expression if it can be reached by
+        // control flow falling out of the body or via continue.
+        if (node->continue_target()->is_linked()) {
+          node->continue_target()->Bind();
+        }
+        if (has_valid_frame()) {
+          ControlDestination dest(&body, node->break_target(), false);
+          LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
+        }
+        if (node->break_target()->is_linked()) {
+          node->break_target()->Bind();
+        }
+      }
+      break;
+    }
+
+    case LoopStatement::WHILE_LOOP: {
+      // Do not duplicate conditions that may have function literal
+      // subexpressions.  This can cause us to compile the function
+      // literal twice.
+      bool test_at_bottom = !node->may_have_function_literal();
+
+      IncrementLoopNesting();
+
+      // If the condition is always false and has no side effects, we
+      // do not need to compile anything.
+      if (info == ALWAYS_FALSE) break;
+
+      JumpTarget body;
+      if (test_at_bottom) {
+        body.Initialize(this, JumpTarget::BIDIRECTIONAL);
+      } else {
+        body.Initialize(this);
+      }
+
+      // Based on the condition analysis, compile the test as necessary.
+      if (info == ALWAYS_TRUE) {
+        // We will not compile the test expression.  Label the top of
+        // the loop with the continue target.
+        node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
+        node->continue_target()->Bind();
+      } else {
+        ASSERT(info == DONT_KNOW);  // ALWAYS_FALSE cannot reach here.
+        if (test_at_bottom) {
+          // Continue is the test at the bottom, no need to label the
+          // test at the top.  The body is a backward target.
+          node->continue_target()->Initialize(this);
+        } else {
+          // Label the test at the top as the continue target.  The
+          // body is a forward-only target.
+          node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
+          node->continue_target()->Bind();
+        }
+        // Compile the test with the body as the true target and
+        // preferred fall-through and with the break target as the
+        // false target.
+        ControlDestination dest(&body, node->break_target(), true);
+        LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
+
+        if (dest.false_was_fall_through()) {
+          // If we got the break target as fall-through, the test may
+          // have been unconditionally false (if there are no jumps to
+          // the body).
+          if (!body.is_linked()) break;
+
+          // Otherwise, jump around the body on the fall through and
+          // then bind the body target.
+          node->break_target()->Unuse();
+          node->break_target()->Jump();
+          body.Bind();
+        }
+      }
+
+      CheckStack();  // TODO(1222600): ignore if body contains calls.
+      Visit(node->body());
+
+      // Based on the condition analysis, compile the backward jump as
+      // necessary.
+      if (info == ALWAYS_TRUE) {
+        // The loop body has been labeled with the continue target.
+        if (has_valid_frame()) {
+          node->continue_target()->Jump();
+        }
+      } else {
+        ASSERT(info == DONT_KNOW);  // ALWAYS_FALSE cannot reach here.
+        if (test_at_bottom) {
+          // If we have chosen to recompile the test at the bottom,
+          // then it is the continue target.
+          if (node->continue_target()->is_linked()) {
+            node->continue_target()->Bind();
+          }
+          if (has_valid_frame()) {
+            // The break target is the fall-through (body is a backward
+            // jump from here and thus an invalid fall-through).
+            ControlDestination dest(&body, node->break_target(), false);
+            LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
+          }
+        } else {
+          // If we have chosen not to recompile the test at the
+          // bottom, jump back to the one at the top.
+          if (has_valid_frame()) {
+            node->continue_target()->Jump();
+          }
+        }
+      }
+
+      // The break target may be already bound (by the condition), or
+      // there may not be a valid frame.  Bind it only if needed.
+      if (node->break_target()->is_linked()) {
+        node->break_target()->Bind();
+      }
+      break;
+    }
+
+    case LoopStatement::FOR_LOOP: {
+      // Do not duplicate conditions that may have function literal
+      // subexpressions.  This can cause us to compile the function
+      // literal twice.
+      bool test_at_bottom = !node->may_have_function_literal();
+
+      // Compile the init expression if present.
+      if (node->init() != NULL) {
+        Visit(node->init());
+      }
+
+      IncrementLoopNesting();
+
+      // If the condition is always false and has no side effects, we
+      // do not need to compile anything else.
+      if (info == ALWAYS_FALSE) break;
+
+      // Target for backward edge if no test at the bottom, otherwise
+      // unused.
+      JumpTarget loop(this, JumpTarget::BIDIRECTIONAL);
+
+      // Target for backward edge if there is a test at the bottom,
+      // otherwise used as target for test at the top.
+      JumpTarget body;
+      if (test_at_bottom) {
+        body.Initialize(this, JumpTarget::BIDIRECTIONAL);
+      } else {
+        body.Initialize(this);
+      }
+
+      // Based on the condition analysis, compile the test as necessary.
+      if (info == ALWAYS_TRUE) {
+        // We will not compile the test expression.  Label the top of
+        // the loop.
+        if (node->next() == NULL) {
+          // Use the continue target if there is no update expression.
+          node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
+          node->continue_target()->Bind();
+        } else {
+          // Otherwise use the backward loop target.
+          node->continue_target()->Initialize(this);
+          loop.Bind();
+        }
+      } else {
+        ASSERT(info == DONT_KNOW);
+        if (test_at_bottom) {
+          // Continue is either the update expression or the test at
+          // the bottom, no need to label the test at the top.
+          node->continue_target()->Initialize(this);
+        } else if (node->next() == NULL) {
+          // We are not recompiling the test at the bottom and there
+          // is no update expression.
+          node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
+          node->continue_target()->Bind();
+        } else {
+          // We are not recompiling the test at the bottom and there
+          // is an update expression.
+          node->continue_target()->Initialize(this);
+          loop.Bind();
+        }
+
+        // Compile the test with the body as the true target and
+        // preferred fall-through and with the break target as the
+        // false target.
+        ControlDestination dest(&body, node->break_target(), true);
+        LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
+
+        if (dest.false_was_fall_through()) {
+          // If we got the break target as fall-through, the test may
+          // have been unconditionally false (if there are no jumps to
+          // the body).
+          if (!body.is_linked()) break;
+
+          // Otherwise, jump around the body on the fall through and
+          // then bind the body target.
+          node->break_target()->Unuse();
+          node->break_target()->Jump();
+          body.Bind();
+        }
+      }
+
+      CheckStack();  // TODO(1222600): ignore if body contains calls.
+      Visit(node->body());
+
+      // If there is an update expression, compile it if necessary.
+      if (node->next() != NULL) {
+        if (node->continue_target()->is_linked()) {
+          node->continue_target()->Bind();
+        }
+
+        // Control can reach the update by falling out of the body or
+        // by a continue.
+        if (has_valid_frame()) {
+          // Record the source position of the statement as this code
+          // which is after the code for the body actually belongs to
+          // the loop statement and not the body.
+          CodeForStatementPosition(node);
+          Visit(node->next());
+        }
+      }
+
+      // Based on the condition analysis, compile the backward jump as
+      // necessary.
+      if (info == ALWAYS_TRUE) {
+        if (has_valid_frame()) {
+          if (node->next() == NULL) {
+            node->continue_target()->Jump();
+          } else {
+            loop.Jump();
+          }
+        }
+      } else {
+        ASSERT(info == DONT_KNOW);  // ALWAYS_FALSE cannot reach here.
+        if (test_at_bottom) {
+          if (node->continue_target()->is_linked()) {
+            // We can have dangling jumps to the continue target if
+            // there was no update expression.
+            node->continue_target()->Bind();
+          }
+          // Control can reach the test at the bottom by falling out
+          // of the body, by a continue in the body, or from the
+          // update expression.
+          if (has_valid_frame()) {
+            // The break target is the fall-through (body is a
+            // backward jump from here).
+            ControlDestination dest(&body, node->break_target(), false);
+            LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
+          }
+        } else {
+          // Otherwise, jump back to the test at the top.
+          if (has_valid_frame()) {
+            if (node->next() == NULL) {
+              node->continue_target()->Jump();
+            } else {
+              loop.Jump();
+            }
+          }
+        }
+      }
+
+      // The break target may be already bound (by the condition), or
+      // there may not be a valid frame.  Bind it only if needed.
+      if (node->break_target()->is_linked()) {
+        node->break_target()->Bind();
+      }
+      break;
+    }
+  }
+
+  DecrementLoopNesting();
+  node->continue_target()->Unuse();
+  node->break_target()->Unuse();
+}
+
+
+void CodeGenerator::VisitForInStatement(ForInStatement* node) {
+  ASSERT(!in_spilled_code());
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ ForInStatement");
+  CodeForStatementPosition(node);
+
+  JumpTarget primitive(this);
+  JumpTarget jsobject(this);
+  JumpTarget fixed_array(this);
+  JumpTarget entry(this, JumpTarget::BIDIRECTIONAL);
+  JumpTarget end_del_check(this);
+  JumpTarget exit(this);
+
+  // Get the object to enumerate over (converted to JSObject).
+  LoadAndSpill(node->enumerable());
+
+  // Both SpiderMonkey and kjs ignore null and undefined in contrast
+  // to the specification.  12.6.4 mandates a call to ToObject.
+  frame_->EmitPop(eax);
+
+  // eax: value to be iterated over
+  __ cmp(eax, Factory::undefined_value());
+  exit.Branch(equal);
+  __ cmp(eax, Factory::null_value());
+  exit.Branch(equal);
+
+  // Stack layout in body:
+  // [iteration counter (smi)] <- slot 0
+  // [length of array]         <- slot 1
+  // [FixedArray]              <- slot 2
+  // [Map or 0]                <- slot 3
+  // [Object]                  <- slot 4
+
+  // Check if enumerable is already a JSObject
+  // eax: value to be iterated over
+  __ test(eax, Immediate(kSmiTagMask));
+  primitive.Branch(zero);
+  __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
+  __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
+  __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
+  jsobject.Branch(above_equal);
+
+  primitive.Bind();
+  frame_->EmitPush(eax);
+  frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION, 1);
+  // function call returns the value in eax, which is where we want it below
+
+  jsobject.Bind();
+  // Get the set of properties (as a FixedArray or Map).
+  // eax: value to be iterated over
+  frame_->EmitPush(eax);  // push the object being iterated over (slot 4)
+
+  frame_->EmitPush(eax);  // push the Object (slot 4) for the runtime call
+  frame_->CallRuntime(Runtime::kGetPropertyNamesFast, 1);
+
+  // If we got a Map, we can do a fast modification check.
+  // Otherwise, we got a FixedArray, and we have to do a slow check.
+  // eax: map or fixed array (result from call to
+  // Runtime::kGetPropertyNamesFast)
+  __ mov(edx, Operand(eax));
+  __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
+  __ cmp(ecx, Factory::meta_map());
+  fixed_array.Branch(not_equal);
+
+  // Get enum cache
+  // eax: map (result from call to Runtime::kGetPropertyNamesFast)
+  __ mov(ecx, Operand(eax));
+  __ mov(ecx, FieldOperand(ecx, Map::kInstanceDescriptorsOffset));
+  // Get the bridge array held in the enumeration index field.
+  __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset));
+  // Get the cache from the bridge array.
+  __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset));
+
+  frame_->EmitPush(eax);  // <- slot 3
+  frame_->EmitPush(edx);  // <- slot 2
+  __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset));
+  __ shl(eax, kSmiTagSize);
+  frame_->EmitPush(eax);  // <- slot 1
+  frame_->EmitPush(Immediate(Smi::FromInt(0)));  // <- slot 0
+  entry.Jump();
+
+  fixed_array.Bind();
+  // eax: fixed array (result from call to Runtime::kGetPropertyNamesFast)
+  frame_->EmitPush(Immediate(Smi::FromInt(0)));  // <- slot 3
+  frame_->EmitPush(eax);  // <- slot 2
+
+  // Push the length of the array and the initial index onto the stack.
+  __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
+  __ shl(eax, kSmiTagSize);
+  frame_->EmitPush(eax);  // <- slot 1
+  frame_->EmitPush(Immediate(Smi::FromInt(0)));  // <- slot 0
+
+  // Condition.
+  entry.Bind();
+  // Grab the current frame's height for the break and continue
+  // targets only after all the state is pushed on the frame.
+  node->break_target()->Initialize(this);
+  node->continue_target()->Initialize(this);
+
+  __ mov(eax, frame_->ElementAt(0));  // load the current count
+  __ cmp(eax, frame_->ElementAt(1));  // compare to the array length
+  node->break_target()->Branch(above_equal);
+
+  // Get the i'th entry of the array.
+  __ mov(edx, frame_->ElementAt(2));
+  __ mov(ebx, Operand(edx, eax, times_2,
+                      FixedArray::kHeaderSize - kHeapObjectTag));
+
+  // Get the expected map from the stack or a zero map in the
+  // permanent slow case eax: current iteration count ebx: i'th entry
+  // of the enum cache
+  __ mov(edx, frame_->ElementAt(3));
+  // Check if the expected map still matches that of the enumerable.
+  // If not, we have to filter the key.
+  // eax: current iteration count
+  // ebx: i'th entry of the enum cache
+  // edx: expected map value
+  __ mov(ecx, frame_->ElementAt(4));
+  __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset));
+  __ cmp(ecx, Operand(edx));
+  end_del_check.Branch(equal);
+
+  // Convert the entry to a string (or null if it isn't a property anymore).
+  frame_->EmitPush(frame_->ElementAt(4));  // push enumerable
+  frame_->EmitPush(ebx);  // push entry
+  frame_->InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION, 2);
+  __ mov(ebx, Operand(eax));
+
+  // If the property has been removed while iterating, we just skip it.
+  __ cmp(ebx, Factory::null_value());
+  node->continue_target()->Branch(equal);
+
+  end_del_check.Bind();
+  // Store the entry in the 'each' expression and take another spin in the
+  // loop.  edx: i'th entry of the enum cache (or string there of)
+  frame_->EmitPush(ebx);
+  { Reference each(this, node->each());
+    // Loading a reference may leave the frame in an unspilled state.
+    frame_->SpillAll();
+    if (!each.is_illegal()) {
+      if (each.size() > 0) {
+        frame_->EmitPush(frame_->ElementAt(each.size()));
+      }
+      // If the reference was to a slot we rely on the convenient property
+      // that it doesn't matter whether a value (eg, ebx pushed above) is
+      // right on top of or right underneath a zero-sized reference.
+      each.SetValue(NOT_CONST_INIT);
+      if (each.size() > 0) {
+        // It's safe to pop the value lying on top of the reference before
+        // unloading the reference itself (which preserves the top of stack,
+        // ie, now the topmost value of the non-zero sized reference), since
+        // we will discard the top of stack after unloading the reference
+        // anyway.
+        frame_->Drop();
+      }
+    }
+  }
+  // Unloading a reference may leave the frame in an unspilled state.
+  frame_->SpillAll();
+
+  // Discard the i'th entry pushed above or else the remainder of the
+  // reference, whichever is currently on top of the stack.
+  frame_->Drop();
+
+  // Body.
+  CheckStack();  // TODO(1222600): ignore if body contains calls.
+  VisitAndSpill(node->body());
+
+  // Next.  Reestablish a spilled frame in case we are coming here via
+  // a continue in the body.
+  node->continue_target()->Bind();
+  frame_->SpillAll();
+  frame_->EmitPop(eax);
+  __ add(Operand(eax), Immediate(Smi::FromInt(1)));
+  frame_->EmitPush(eax);
+  entry.Jump();
+
+  // Cleanup.  No need to spill because VirtualFrame::Drop is safe for
+  // any frame.
+  node->break_target()->Bind();
+  frame_->Drop(5);
+
+  // Exit.
+  exit.Bind();
+
+  node->continue_target()->Unuse();
+  node->break_target()->Unuse();
+}
+
+
+void CodeGenerator::VisitTryCatch(TryCatch* node) {
+  ASSERT(!in_spilled_code());
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ TryCatch");
+  CodeForStatementPosition(node);
+
+  JumpTarget try_block(this);
+  JumpTarget exit(this);
+
+  try_block.Call();
+  // --- Catch block ---
+  frame_->EmitPush(eax);
+
+  // Store the caught exception in the catch variable.
+  { Reference ref(this, node->catch_var());
+    ASSERT(ref.is_slot());
+    // Load the exception to the top of the stack.  Here we make use of the
+    // convenient property that it doesn't matter whether a value is
+    // immediately on top of or underneath a zero-sized reference.
+    ref.SetValue(NOT_CONST_INIT);
+  }
+
+  // Remove the exception from the stack.
+  frame_->Drop();
+
+  VisitStatementsAndSpill(node->catch_block()->statements());
+  if (has_valid_frame()) {
+    exit.Jump();
+  }
+
+
+  // --- Try block ---
+  try_block.Bind();
+
+  frame_->PushTryHandler(TRY_CATCH_HANDLER);
+  int handler_height = frame_->height();
+
+  // Shadow the jump targets for all escapes from the try block, including
+  // returns.  During shadowing, the original target is hidden as the
+  // ShadowTarget and operations on the original actually affect the
+  // shadowing target.
+  //
+  // We should probably try to unify the escaping targets and the return
+  // target.
+  int nof_escapes = node->escaping_targets()->length();
+  List<ShadowTarget*> shadows(1 + nof_escapes);
+
+  // Add the shadow target for the function return.
+  static const int kReturnShadowIndex = 0;
+  shadows.Add(new ShadowTarget(&function_return_));
+  bool function_return_was_shadowed = function_return_is_shadowed_;
+  function_return_is_shadowed_ = true;
+  ASSERT(shadows[kReturnShadowIndex]->other_target() == &function_return_);
+
+  // Add the remaining shadow targets.
+  for (int i = 0; i < nof_escapes; i++) {
+    shadows.Add(new ShadowTarget(node->escaping_targets()->at(i)));
+  }
+
+  // Generate code for the statements in the try block.
+  VisitStatementsAndSpill(node->try_block()->statements());
+
+  // Stop the introduced shadowing and count the number of required unlinks.
+  // After shadowing stops, the original targets are unshadowed and the
+  // ShadowTargets represent the formerly shadowing targets.
+  bool has_unlinks = false;
+  for (int i = 0; i < shadows.length(); i++) {
+    shadows[i]->StopShadowing();
+    has_unlinks = has_unlinks || shadows[i]->is_linked();
+  }
+  function_return_is_shadowed_ = function_return_was_shadowed;
+
+  // Get an external reference to the handler address.
+  ExternalReference handler_address(Top::k_handler_address);
+
+  // Make sure that there's nothing left on the stack above the
+  // handler structure.
+  if (FLAG_debug_code) {
+    __ mov(eax, Operand::StaticVariable(handler_address));
+    __ lea(eax, Operand(eax, StackHandlerConstants::kAddressDisplacement));
+    __ cmp(esp, Operand(eax));
+    __ Assert(equal, "stack pointer should point to top handler");
+  }
+
+  // If we can fall off the end of the try block, unlink from try chain.
+  if (has_valid_frame()) {
+    // The next handler address is on top of the frame.  Unlink from
+    // the handler list and drop the rest of this handler from the
+    // frame.
+    frame_->EmitPop(Operand::StaticVariable(handler_address));
+    frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
+    if (has_unlinks) {
+      exit.Jump();
+    }
+  }
+
+  // Generate unlink code for the (formerly) shadowing targets that
+  // have been jumped to.  Deallocate each shadow target.
+  Result return_value(this);
+  for (int i = 0; i < shadows.length(); i++) {
+    if (shadows[i]->is_linked()) {
+      // Unlink from try chain; be careful not to destroy the TOS if
+      // there is one.
+      if (i == kReturnShadowIndex) {
+        shadows[i]->Bind(&return_value);
+        return_value.ToRegister(eax);
+      } else {
+        shadows[i]->Bind();
+      }
+      // Because we can be jumping here (to spilled code) from
+      // unspilled code, we need to reestablish a spilled frame at
+      // this block.
+      frame_->SpillAll();
+
+      // Reload sp from the top handler, because some statements that we
+      // break from (eg, for...in) may have left stuff on the stack.
+      __ mov(edx, Operand::StaticVariable(handler_address));
+      const int kNextOffset = StackHandlerConstants::kNextOffset +
+          StackHandlerConstants::kAddressDisplacement;
+      __ lea(esp, Operand(edx, kNextOffset));
+      frame_->Forget(frame_->height() - handler_height);
+
+      frame_->EmitPop(Operand::StaticVariable(handler_address));
+      frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
+      // next_sp popped.
+
+      if (i == kReturnShadowIndex) {
+        if (!function_return_is_shadowed_) frame_->PrepareForReturn();
+        shadows[i]->other_target()->Jump(&return_value);
+      } else {
+        shadows[i]->other_target()->Jump();
+      }
+    }
+    delete shadows[i];
+  }
+
+  exit.Bind();
+}
+
+
+void CodeGenerator::VisitTryFinally(TryFinally* node) {
+  ASSERT(!in_spilled_code());
+  VirtualFrame::SpilledScope spilled_scope(this);
+  Comment cmnt(masm_, "[ TryFinally");
+  CodeForStatementPosition(node);
+
+  // State: Used to keep track of reason for entering the finally
+  // block. Should probably be extended to hold information for
+  // break/continue from within the try block.
+  enum { FALLING, THROWING, JUMPING };
+
+  JumpTarget try_block(this);
+  JumpTarget finally_block(this);
+
+  try_block.Call();
+
+  frame_->EmitPush(eax);
+  // In case of thrown exceptions, this is where we continue.
+  __ Set(ecx, Immediate(Smi::FromInt(THROWING)));
+  finally_block.Jump();
+
+  // --- Try block ---
+  try_block.Bind();
+
+  frame_->PushTryHandler(TRY_FINALLY_HANDLER);
+  int handler_height = frame_->height();
+
+  // Shadow the jump targets for all escapes from the try block, including
+  // returns.  During shadowing, the original target is hidden as the
+  // ShadowTarget and operations on the original actually affect the
+  // shadowing target.
+  //
+  // We should probably try to unify the escaping targets and the return
+  // target.
+  int nof_escapes = node->escaping_targets()->length();
+  List<ShadowTarget*> shadows(1 + nof_escapes);
+
+  // Add the shadow target for the function return.
+  static const int kReturnShadowIndex = 0;
+  shadows.Add(new ShadowTarget(&function_return_));
+  bool function_return_was_shadowed = function_return_is_shadowed_;
+  function_return_is_shadowed_ = true;
+  ASSERT(shadows[kReturnShadowIndex]->other_target() == &function_return_);
+
+  // Add the remaining shadow targets.
+  for (int i = 0; i < nof_escapes; i++) {
+    shadows.Add(new ShadowTarget(node->escaping_targets()->at(i)));
+  }
+
+  // Generate code for the statements in the try block.
+  VisitStatementsAndSpill(node->try_block()->statements());
+
+  // Stop the introduced shadowing and count the number of required unlinks.
+  // After shadowing stops, the original targets are unshadowed and the
+  // ShadowTargets represent the formerly shadowing targets.
+  int nof_unlinks = 0;
+  for (int i = 0; i < shadows.length(); i++) {
+    shadows[i]->StopShadowing();
+    if (shadows[i]->is_linked()) nof_unlinks++;
+  }
+  function_return_is_shadowed_ = function_return_was_shadowed;
+
+  // Get an external reference to the handler address.
+  ExternalReference handler_address(Top::k_handler_address);
+
+  // If we can fall off the end of the try block, unlink from the try
+  // chain and set the state on the frame to FALLING.
+  if (has_valid_frame()) {
+    // The next handler address is on top of the frame.
+    ASSERT(StackHandlerConstants::kNextOffset == 0);
+    frame_->EmitPop(eax);
+    __ mov(Operand::StaticVariable(handler_address), eax);
+    frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
+
+    // Fake a top of stack value (unneeded when FALLING) and set the
+    // state in ecx, then jump around the unlink blocks if any.
+    frame_->EmitPush(Immediate(Factory::undefined_value()));
+    __ Set(ecx, Immediate(Smi::FromInt(FALLING)));
+    if (nof_unlinks > 0) {
+      finally_block.Jump();
+    }
+  }
+
+  // Generate code to unlink and set the state for the (formerly)
+  // shadowing targets that have been jumped to.
+  for (int i = 0; i < shadows.length(); i++) {
+    if (shadows[i]->is_linked()) {
+      // If we have come from the shadowed return, the return value is
+      // on the virtual frame.  We must preserve it until it is
+      // pushed.
+      if (i == kReturnShadowIndex) {
+        Result return_value(this);
+        shadows[i]->Bind(&return_value);
+        return_value.ToRegister(eax);
+      } else {
+        shadows[i]->Bind();
+      }
+      // Because we can be jumping here (to spilled code) from
+      // unspilled code, we need to reestablish a spilled frame at
+      // this block.
+      frame_->SpillAll();
+
+      // Reload sp from the top handler, because some statements that
+      // we break from (eg, for...in) may have left stuff on the
+      // stack.
+      __ mov(edx, Operand::StaticVariable(handler_address));
+      const int kNextOffset = StackHandlerConstants::kNextOffset +
+          StackHandlerConstants::kAddressDisplacement;
+      __ lea(esp, Operand(edx, kNextOffset));
+      frame_->Forget(frame_->height() - handler_height);
+
+      // Unlink this handler and drop it from the frame.
+      frame_->EmitPop(Operand::StaticVariable(handler_address));
+      frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
+
+      if (i == kReturnShadowIndex) {
+        // If this target shadowed the function return, materialize
+        // the return value on the stack.
+        frame_->EmitPush(eax);
+      } else {
+        // Fake TOS for targets that shadowed breaks and continues.
+        frame_->EmitPush(Immediate(Factory::undefined_value()));
+      }
+      __ Set(ecx, Immediate(Smi::FromInt(JUMPING + i)));
+      if (--nof_unlinks > 0) {
+        // If this is not the last unlink block, jump around the next.
+        finally_block.Jump();
+      }
+    }
+  }
+
+  // --- Finally block ---
+  finally_block.Bind();
+
+  // Push the state on the stack.
+  frame_->EmitPush(ecx);
+
+  // We keep two elements on the stack - the (possibly faked) result
+  // and the state - while evaluating the finally block.
+  //
+  // Generate code for the statements in the finally block.
+  VisitStatementsAndSpill(node->finally_block()->statements());
+
+  if (has_valid_frame()) {
+    // Restore state and return value or faked TOS.
+    frame_->EmitPop(ecx);
+    frame_->EmitPop(eax);
+  }
+
+  // Generate code to jump to the right destination for all used
+  // formerly shadowing targets.  Deallocate each shadow target.
+  for (int i = 0; i < shadows.length(); i++) {
+    if (has_valid_frame() && shadows[i]->is_bound()) {
+      BreakTarget* original = shadows[i]->other_target();
+      __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i)));
+      if (i == kReturnShadowIndex) {
+        // The return value is (already) in eax.
+        Result return_value = allocator_->Allocate(eax);
+        ASSERT(return_value.is_valid());
+        if (function_return_is_shadowed_) {
+          original->Branch(equal, &return_value);
+        } else {
+          // Branch around the preparation for return which may emit
+          // code.
+          JumpTarget skip(this);
+          skip.Branch(not_equal);
+          frame_->PrepareForReturn();
+          original->Jump(&return_value);
+          skip.Bind();
+        }
+      } else {
+        original->Branch(equal);
+      }
+    }
+    delete shadows[i];
+  }
+
+  if (has_valid_frame()) {
+    // Check if we need to rethrow the exception.
+    JumpTarget exit(this);
+    __ cmp(Operand(ecx), Immediate(Smi::FromInt(THROWING)));
+    exit.Branch(not_equal);
+
+    // Rethrow exception.
+    frame_->EmitPush(eax);  // undo pop from above
+    frame_->CallRuntime(Runtime::kReThrow, 1);
+
+    // Done.
+    exit.Bind();
+  }
+}
+
+
+void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
+  ASSERT(!in_spilled_code());
+  Comment cmnt(masm_, "[ DebuggerStatement");
+  CodeForStatementPosition(node);
+  // Spill everything, even constants, to the frame.
+  frame_->SpillAll();
+  frame_->CallRuntime(Runtime::kDebugBreak, 0);
+  // Ignore the return value.
+}
+
+
+void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) {
+  ASSERT(boilerplate->IsBoilerplate());
+
+  // Push the boilerplate on the stack.
+  frame_->Push(boilerplate);
+
+  // Create a new closure.
+  frame_->Push(esi);
+  Result result = frame_->CallRuntime(Runtime::kNewClosure, 2);
+  frame_->Push(&result);
+}
+
+
+void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
+  Comment cmnt(masm_, "[ FunctionLiteral");
+
+  // Build the function boilerplate and instantiate it.
+  Handle<JSFunction> boilerplate = BuildBoilerplate(node);
+  // Check for stack-overflow exception.
+  if (HasStackOverflow()) return;
+  InstantiateBoilerplate(boilerplate);
+}
+
+
+void CodeGenerator::VisitFunctionBoilerplateLiteral(
+    FunctionBoilerplateLiteral* node) {
+  Comment cmnt(masm_, "[ FunctionBoilerplateLiteral");
+  InstantiateBoilerplate(node->boilerplate());
+}
+
+
+void CodeGenerator::VisitConditional(Conditional* node) {
+  Comment cmnt(masm_, "[ Conditional");
+  JumpTarget then(this);
+  JumpTarget else_(this);
+  JumpTarget exit(this);
+  ControlDestination dest(&then, &else_, true);
+  LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true);
+
+  if (dest.false_was_fall_through()) {
+    // The else target was bound, so we compile the else part first.
+    Load(node->else_expression(), typeof_state());
+
+    if (then.is_linked()) {
+      exit.Jump();
+      then.Bind();
+      Load(node->then_expression(), typeof_state());
+    }
+  } else {
+    // The then target was bound, so we compile the then part first.
+    Load(node->then_expression(), typeof_state());
+
+    if (else_.is_linked()) {
+      exit.Jump();
+      else_.Bind();
+      Load(node->else_expression(), typeof_state());
+    }
+  }
+
+  exit.Bind();
+}
+
+
+void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
+  if (slot->type() == Slot::LOOKUP) {
+    ASSERT(slot->var()->is_dynamic());
+
+    JumpTarget slow(this);
+    JumpTarget done(this);
+    Result value(this);
+
+    // Generate fast-case code for variables that might be shadowed by
+    // eval-introduced variables.  Eval is used a lot without
+    // introducing variables.  In those cases, we do not want to
+    // perform a runtime call for all variables in the scope
+    // containing the eval.
+    if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
+      value = LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow);
+      // If there was no control flow to slow, we can exit early.
+      if (!slow.is_linked()) {
+        frame_->Push(&value);
+        return;
+      }
+
+      done.Jump(&value);
+
+    } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
+      Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot();
+      // Only generate the fast case for locals that rewrite to slots.
+      // This rules out argument loads.
+      if (potential_slot != NULL) {
+        // Allocate a fresh register to use as a temp in
+        // ContextSlotOperandCheckExtensions and to hold the result
+        // value.
+        value = allocator_->Allocate();
+        ASSERT(value.is_valid());
+        __ mov(value.reg(),
+               ContextSlotOperandCheckExtensions(potential_slot,
+                                                 value,
+                                                 &slow));
+        if (potential_slot->var()->mode() == Variable::CONST) {
+          __ cmp(value.reg(), Factory::the_hole_value());
+          done.Branch(not_equal, &value);
+          __ mov(value.reg(), Factory::undefined_value());
+        }
+        // There is always control flow to slow from
+        // ContextSlotOperandCheckExtensions so we have to jump around
+        // it.
+        done.Jump(&value);
+      }
+    }
+
+    slow.Bind();
+    frame_->Push(esi);
+    frame_->Push(slot->var()->name());
+    if (typeof_state == INSIDE_TYPEOF) {
+      value =
+          frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
+    } else {
+      value = frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
+    }
+
+    done.Bind(&value);
+    frame_->Push(&value);
+
+  } else if (slot->var()->mode() == Variable::CONST) {
+    // Const slots may contain 'the hole' value (the constant hasn't been
+    // initialized yet) which needs to be converted into the 'undefined'
+    // value.
+    //
+    // We currently spill the virtual frame because constants use the
+    // potentially unsafe direct-frame access of SlotOperand.
+    VirtualFrame::SpilledScope spilled_scope(this);
+    Comment cmnt(masm_, "[ Load const");
+    JumpTarget exit(this);
+    __ mov(ecx, SlotOperand(slot, ecx));
+    __ cmp(ecx, Factory::the_hole_value());
+    exit.Branch(not_equal);
+    __ mov(ecx, Factory::undefined_value());
+    exit.Bind();
+    frame_->EmitPush(ecx);
+
+  } else if (slot->type() == Slot::PARAMETER) {
+    frame_->PushParameterAt(slot->index());
+
+  } else if (slot->type() == Slot::LOCAL) {
+    frame_->PushLocalAt(slot->index());
+
+  } else {
+    // The other remaining slot types (LOOKUP and GLOBAL) cannot reach
+    // here.
+    //
+    // The use of SlotOperand below is safe for an unspilled frame
+    // because it will always be a context slot.
+    ASSERT(slot->type() == Slot::CONTEXT);
+    Result temp = allocator_->Allocate();
+    ASSERT(temp.is_valid());
+    __ mov(temp.reg(), SlotOperand(slot, temp.reg()));
+    frame_->Push(&temp);
+  }
+}
+
+
+Result CodeGenerator::LoadFromGlobalSlotCheckExtensions(
+    Slot* slot,
+    TypeofState typeof_state,
+    JumpTarget* slow) {
+  // Check that no extension objects have been created by calls to
+  // eval from the current scope to the global scope.
+  Result context(esi, this);
+  Result tmp = allocator_->Allocate();
+  ASSERT(tmp.is_valid());  // All non-reserved registers were available.
+
+  Scope* s = scope();
+  while (s != NULL) {
+    if (s->num_heap_slots() > 0) {
+      if (s->calls_eval()) {
+        // Check that extension is NULL.
+        __ cmp(ContextOperand(context.reg(), Context::EXTENSION_INDEX),
+               Immediate(0));
+        slow->Branch(not_equal, not_taken);
+      }
+      // Load next context in chain.
+      __ mov(tmp.reg(), ContextOperand(context.reg(), Context::CLOSURE_INDEX));
+      __ mov(tmp.reg(), FieldOperand(tmp.reg(), JSFunction::kContextOffset));
+      context = tmp;
+    }
+    // If no outer scope calls eval, we do not need to check more
+    // context extensions.  If we have reached an eval scope, we check
+    // all extensions from this point.
+    if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break;
+    s = s->outer_scope();
+  }
+
+  if (s->is_eval_scope()) {
+    // Loop up the context chain.  There is no frame effect so it is
+    // safe to use raw labels here.
+    Label next, fast;
+    if (!context.reg().is(tmp.reg())) __ mov(tmp.reg(), context.reg());
+    __ bind(&next);
+    // Terminate at global context.
+    __ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset),
+           Immediate(Factory::global_context_map()));
+    __ j(equal, &fast);
+    // Check that extension is NULL.
+    __ cmp(ContextOperand(tmp.reg(), Context::EXTENSION_INDEX), Immediate(0));
+    slow->Branch(not_equal, not_taken);
+    // Load next context in chain.
+    __ mov(tmp.reg(), ContextOperand(tmp.reg(), Context::CLOSURE_INDEX));
+    __ mov(tmp.reg(), FieldOperand(tmp.reg(), JSFunction::kContextOffset));
+    __ jmp(&next);
+    __ bind(&fast);
+  }
+  context.Unuse();
+  tmp.Unuse();
+
+  // All extension objects were empty and it is safe to use a global
+  // load IC call.
+  LoadGlobal();
+  frame_->Push(slot->var()->name());
+  RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
+                         ? RelocInfo::CODE_TARGET
+                         : RelocInfo::CODE_TARGET_CONTEXT;
+  Result answer = frame_->CallLoadIC(mode);
+
+  // Discard the global object. The result is in answer.
+  frame_->Drop();
+  return answer;
+}
+
+
+void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
+  if (slot->type() == Slot::LOOKUP) {
+    ASSERT(slot->var()->is_dynamic());
+
+    // For now, just do a runtime call.
+    frame_->Push(esi);
+    frame_->Push(slot->var()->name());
+
+    Result value(this);
+    if (init_state == CONST_INIT) {
+      // Same as the case for a normal store, but ignores attribute
+      // (e.g. READ_ONLY) of context slot so that we can initialize const
+      // properties (introduced via eval("const foo = (some expr);")). Also,
+      // uses the current function context instead of the top context.
+      //
+      // Note that we must declare the foo upon entry of eval(), via a
+      // context slot declaration, but we cannot initialize it at the same
+      // time, because the const declaration may be at the end of the eval
+      // code (sigh...) and the const variable may have been used before
+      // (where its value is 'undefined'). Thus, we can only do the
+      // initialization when we actually encounter the expression and when
+      // the expression operands are defined and valid, and thus we need the
+      // split into 2 operations: declaration of the context slot followed
+      // by initialization.
+      value = frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3);
+    } else {
+      value = frame_->CallRuntime(Runtime::kStoreContextSlot, 3);
+    }
+    // Storing a variable must keep the (new) value on the expression
+    // stack. This is necessary for compiling chained assignment
+    // expressions.
+    frame_->Push(&value);
+
+  } else {
+    ASSERT(!slot->var()->is_dynamic());
+
+    JumpTarget exit(this);
+    if (init_state == CONST_INIT) {
+      ASSERT(slot->var()->mode() == Variable::CONST);
+      // Only the first const initialization must be executed (the slot
+      // still contains 'the hole' value). When the assignment is executed,
+      // the code is identical to a normal store (see below).
+      //
+      // We spill the frame in the code below because the direct-frame
+      // access of SlotOperand is potentially unsafe with an unspilled
+      // frame.
+      VirtualFrame::SpilledScope spilled_scope(this);
+      Comment cmnt(masm_, "[ Init const");
+      __ mov(ecx, SlotOperand(slot, ecx));
+      __ cmp(ecx, Factory::the_hole_value());
+      exit.Branch(not_equal);
+    }
+
+    // We must execute the store.  Storing a variable must keep the (new)
+    // value on the stack. This is necessary for compiling assignment
+    // expressions.
+    //
+    // Note: We will reach here even with slot->var()->mode() ==
+    // Variable::CONST because of const declarations which will initialize
+    // consts to 'the hole' value and by doing so, end up calling this code.
+    if (slot->type() == Slot::PARAMETER) {
+      frame_->StoreToParameterAt(slot->index());
+    } else if (slot->type() == Slot::LOCAL) {
+      frame_->StoreToLocalAt(slot->index());
+    } else {
+      // The other slot types (LOOKUP and GLOBAL) cannot reach here.
+      //
+      // The use of SlotOperand below is safe for an unspilled frame
+      // because the slot is a context slot.
+      ASSERT(slot->type() == Slot::CONTEXT);
+      frame_->Dup();
+      Result value = frame_->Pop();
+      value.ToRegister();
+      Result start = allocator_->Allocate();
+      ASSERT(start.is_valid());
+      __ mov(SlotOperand(slot, start.reg()), value.reg());
+      // RecordWrite may destroy the value registers.
+      //
+      // TODO(204): Avoid actually spilling when the value is not
+      // needed (probably the common case).
+      frame_->Spill(value.reg());
+      int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
+      Result temp = allocator_->Allocate();
+      ASSERT(temp.is_valid());
+      __ RecordWrite(start.reg(), offset, value.reg(), temp.reg());
+      // The results start, value, and temp are unused by going out of
+      // scope.
+    }
+
+    exit.Bind();
+  }
+}
+
+
+void CodeGenerator::VisitSlot(Slot* node) {
+  Comment cmnt(masm_, "[ Slot");
+  LoadFromSlot(node, typeof_state());
+}
+
+
+void CodeGenerator::VisitVariableProxy(VariableProxy* node) {
+  Comment cmnt(masm_, "[ VariableProxy");
+  Variable* var = node->var();
+  Expression* expr = var->rewrite();
+  if (expr != NULL) {
+    Visit(expr);
+  } else {
+    ASSERT(var->is_global());
+    Reference ref(this, node);
+    ref.GetValue(typeof_state());
+  }
+}
+
+
+void CodeGenerator::VisitLiteral(Literal* node) {
+  Comment cmnt(masm_, "[ Literal");
+  frame_->Push(node->handle());
+}
+
+
+void CodeGenerator::LoadUnsafeSmi(Register target, Handle<Object> value) {
+  ASSERT(target.is_valid());
+  ASSERT(value->IsSmi());
+  int bits = reinterpret_cast<int>(*value);
+  __ Set(target, Immediate(bits & 0x0000FFFF));
+  __ xor_(target, bits & 0xFFFF0000);
+}
+
+
+bool CodeGenerator::IsUnsafeSmi(Handle<Object> value) {
+  if (!value->IsSmi()) return false;
+  int int_value = Smi::cast(*value)->value();
+  return !is_intn(int_value, kMaxSmiInlinedBits);
+}
+
+
+class DeferredRegExpLiteral: public DeferredCode {
+ public:
+  DeferredRegExpLiteral(CodeGenerator* generator, RegExpLiteral* node)
+      : DeferredCode(generator), node_(node) {
+    set_comment("[ DeferredRegExpLiteral");
+  }
+
+  virtual void Generate();
+
+ private:
+  RegExpLiteral* node_;
+};
+
+
+void DeferredRegExpLiteral::Generate() {
+  Result literals(generator());
+  enter()->Bind(&literals);
+  // Since the entry is undefined we call the runtime system to
+  // compute the literal.
+
+  VirtualFrame* frame = generator()->frame();
+  // Literal array (0).
+  frame->Push(&literals);
+  // Literal index (1).
+  frame->Push(Smi::FromInt(node_->literal_index()));
+  // RegExp pattern (2).
+  frame->Push(node_->pattern());
+  // RegExp flags (3).
+  frame->Push(node_->flags());
+  Result boilerplate =
+      frame->CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
+  exit_.Jump(&boilerplate);
+}
+
+
+void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
+  Comment cmnt(masm_, "[ RegExp Literal");
+  DeferredRegExpLiteral* deferred = new DeferredRegExpLiteral(this, node);
+
+  // Retrieve the literals array and check the allocated entry.  Begin
+  // with a writable copy of the function of this activation in a
+  // register.
+  frame_->PushFunction();
+  Result literals = frame_->Pop();
+  literals.ToRegister();
+  frame_->Spill(literals.reg());
+
+  // Load the literals array of the function.
+  __ mov(literals.reg(),
+         FieldOperand(literals.reg(), JSFunction::kLiteralsOffset));
+
+  // Load the literal at the ast saved index.
+  int literal_offset =
+      FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
+  Result boilerplate = allocator_->Allocate();
+  ASSERT(boilerplate.is_valid());
+  __ mov(boilerplate.reg(), FieldOperand(literals.reg(), literal_offset));
+
+  // Check whether we need to materialize the RegExp object.  If so,
+  // jump to the deferred code passing the literals array.
+  __ cmp(boilerplate.reg(), Factory::undefined_value());
+  deferred->enter()->Branch(equal, &literals, not_taken);
+
+  literals.Unuse();
+  // The deferred code returns the boilerplate object.
+  deferred->BindExit(&boilerplate);
+
+  // Push the boilerplate object.
+  frame_->Push(&boilerplate);
+}
+
+
+// This deferred code stub will be used for creating the boilerplate
+// by calling Runtime_CreateObjectLiteral.
+// Each created boilerplate is stored in the JSFunction and they are
+// therefore context dependent.
+class DeferredObjectLiteral: public DeferredCode {
+ public:
+  DeferredObjectLiteral(CodeGenerator* generator,
+                        ObjectLiteral* node)
+      : DeferredCode(generator), node_(node) {
+    set_comment("[ DeferredObjectLiteral");
+  }
+
+  virtual void Generate();
+
+ private:
+  ObjectLiteral* node_;
+};
+
+
+void DeferredObjectLiteral::Generate() {
+  Result literals(generator());
+  enter()->Bind(&literals);
+  // Since the entry is undefined we call the runtime system to
+  // compute the literal.
+
+  VirtualFrame* frame = generator()->frame();
+  // Literal array (0).
+  frame->Push(&literals);
+  // Literal index (1).
+  frame->Push(Smi::FromInt(node_->literal_index()));
+  // Constant properties (2).
+  frame->Push(node_->constant_properties());
+  Result boilerplate =
+      frame->CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3);
+  exit_.Jump(&boilerplate);
+}
+
+
+void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
+  Comment cmnt(masm_, "[ ObjectLiteral");
+  DeferredObjectLiteral* deferred = new DeferredObjectLiteral(this, node);
+
+  // Retrieve the literals array and check the allocated entry.  Begin
+  // with a writable copy of the function of this activation in a
+  // register.
+  frame_->PushFunction();
+  Result literals = frame_->Pop();
+  literals.ToRegister();
+  frame_->Spill(literals.reg());
+
+  // Load the literals array of the function.
+  __ mov(literals.reg(),
+         FieldOperand(literals.reg(), JSFunction::kLiteralsOffset));
+
+  // Load the literal at the ast saved index.
+  int literal_offset =
+      FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
+  Result boilerplate = allocator_->Allocate();
+  ASSERT(boilerplate.is_valid());
+  __ mov(boilerplate.reg(), FieldOperand(literals.reg(), literal_offset));
+
+  // Check whether we need to materialize the object literal boilerplate.
+  // If so, jump to the deferred code passing the literals array.
+  __ cmp(boilerplate.reg(), Factory::undefined_value());
+  deferred->enter()->Branch(equal, &literals, not_taken);
+
+  literals.Unuse();
+  // The deferred code returns the boilerplate object.
+  deferred->BindExit(&boilerplate);
+
+  // Push the boilerplate object.
+  frame_->Push(&boilerplate);
+  // Clone the boilerplate object.
+  Runtime::FunctionId clone_function_id = Runtime::kCloneLiteralBoilerplate;
+  if (node->depth() == 1) {
+    clone_function_id = Runtime::kCloneShallowLiteralBoilerplate;
+  }
+  Result clone = frame_->CallRuntime(clone_function_id, 1);
+  // Push the newly cloned literal object as the result.
+  frame_->Push(&clone);
+
+  for (int i = 0; i < node->properties()->length(); i++) {
+    ObjectLiteral::Property* property = node->properties()->at(i);
+    switch (property->kind()) {
+      case ObjectLiteral::Property::CONSTANT:
+        break;
+      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
+        if (CompileTimeValue::IsCompileTimeValue(property->value())) break;
+        // else fall through.
+      case ObjectLiteral::Property::COMPUTED: {
+        Handle<Object> key(property->key()->handle());
+        if (key->IsSymbol()) {
+          // Duplicate the object as the IC receiver.
+          frame_->Dup();
+          Load(property->value());
+          frame_->Push(key);
+          Result ignored = frame_->CallStoreIC();
+          // Drop the duplicated receiver and ignore the result.
+          frame_->Drop();
+          break;
+        }
+        // Fall through
+      }
+      case ObjectLiteral::Property::PROTOTYPE: {
+        // Duplicate the object as an argument to the runtime call.
+        frame_->Dup();
+        Load(property->key());
+        Load(property->value());
+        Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3);
+        // Ignore the result.
+        break;
+      }
+      case ObjectLiteral::Property::SETTER: {
+        // Duplicate the object as an argument to the runtime call.
+        frame_->Dup();
+        Load(property->key());
+        frame_->Push(Smi::FromInt(1));
+        Load(property->value());
+        Result ignored = frame_->CallRuntime(Runtime::kDefineAccessor, 4);
+        // Ignore the result.
+        break;
+      }
+      case ObjectLiteral::Property::GETTER: {
+        // Duplicate the object as an argument to the runtime call.
+        frame_->Dup();
+        Load(property->key());
+        frame_->Push(Smi::FromInt(0));
+        Load(property->value());
+        Result ignored = frame_->CallRuntime(Runtime::kDefineAccessor, 4);
+        // Ignore the result.
+        break;
+      }
+      default: UNREACHABLE();
+    }
+  }
+}
+
+
+// This deferred code stub will be used for creating the boilerplate
+// by calling Runtime_CreateArrayLiteralBoilerplate.
+// Each created boilerplate is stored in the JSFunction and they are
+// therefore context dependent.
+class DeferredArrayLiteral: public DeferredCode {
+ public:
+  DeferredArrayLiteral(CodeGenerator* generator,
+                       ArrayLiteral* node)
+      : DeferredCode(generator), node_(node) {
+    set_comment("[ DeferredArrayLiteral");
+  }
+
+  virtual void Generate();
+
+ private:
+  ArrayLiteral* node_;
+};
+
+
+void DeferredArrayLiteral::Generate() {
+  Result literals(generator());
+  enter()->Bind(&literals);
+  // Since the entry is undefined we call the runtime system to
+  // compute the literal.
+
+  VirtualFrame* frame = generator()->frame();
+  // Literal array (0).
+  frame->Push(&literals);
+  // Literal index (1).
+  frame->Push(Smi::FromInt(node_->literal_index()));
+  // Constant properties (2).
+  frame->Push(node_->literals());
+  Result boilerplate =
+      frame->CallRuntime(Runtime::kCreateArrayLiteralBoilerplate, 3);
+  exit_.Jump(&boilerplate);
+}
+
+
+void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
+  Comment cmnt(masm_, "[ ArrayLiteral");
+  DeferredArrayLiteral* deferred = new DeferredArrayLiteral(this, node);
+
+  // Retrieve the literals array and check the allocated entry.  Begin
+  // with a writable copy of the function of this activation in a
+  // register.
+  frame_->PushFunction();
+  Result literals = frame_->Pop();
+  literals.ToRegister();
+  frame_->Spill(literals.reg());
+
+  // Load the literals array of the function.
+  __ mov(literals.reg(),
+         FieldOperand(literals.reg(), JSFunction::kLiteralsOffset));
+
+  // Load the literal at the ast saved index.
+  int literal_offset =
+      FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
+  Result boilerplate = allocator_->Allocate();
+  ASSERT(boilerplate.is_valid());
+  __ mov(boilerplate.reg(), FieldOperand(literals.reg(), literal_offset));
+
+  // Check whether we need to materialize the object literal boilerplate.
+  // If so, jump to the deferred code passing the literals array.
+  __ cmp(boilerplate.reg(), Factory::undefined_value());
+  deferred->enter()->Branch(equal, &literals, not_taken);
+
+  literals.Unuse();
+  // The deferred code returns the boilerplate object.
+  deferred->BindExit(&boilerplate);
+
+  // Push the resulting array literal on the stack.
+  frame_->Push(&boilerplate);
+
+  // Clone the boilerplate object.
+  Runtime::FunctionId clone_function_id = Runtime::kCloneLiteralBoilerplate;
+  if (node->depth() == 1) {
+    clone_function_id = Runtime::kCloneShallowLiteralBoilerplate;
+  }
+  Result clone = frame_->CallRuntime(clone_function_id, 1);
+  // Push the newly cloned literal object as the result.
+  frame_->Push(&clone);
+
+  // Generate code to set the elements in the array that are not
+  // literals.
+  for (int i = 0; i < node->values()->length(); i++) {
+    Expression* value = node->values()->at(i);
+
+    // If value is a literal the property value is already set in the
+    // boilerplate object.
+    if (value->AsLiteral() != NULL) continue;
+    // If value is a materialized literal the property value is already set
+    // in the boilerplate object if it is simple.
+    if (CompileTimeValue::IsCompileTimeValue(value)) continue;
+
+    // The property must be set by generated code.
+    Load(value);
+
+    // Get the property value off the stack.
+    Result prop_value = frame_->Pop();
+    prop_value.ToRegister();
+
+    // Fetch the array literal while leaving a copy on the stack and
+    // use it to get the elements array.
+    frame_->Dup();
+    Result elements = frame_->Pop();
+    elements.ToRegister();
+    frame_->Spill(elements.reg());
+    // Get the elements array.
+    __ mov(elements.reg(),
+           FieldOperand(elements.reg(), JSObject::kElementsOffset));
+
+    // Write to the indexed properties array.
+    int offset = i * kPointerSize + Array::kHeaderSize;
+    __ mov(FieldOperand(elements.reg(), offset), prop_value.reg());
+
+    // Update the write barrier for the array address.
+    frame_->Spill(prop_value.reg());  // Overwritten by the write barrier.
+    Result scratch = allocator_->Allocate();
+    ASSERT(scratch.is_valid());
+    __ RecordWrite(elements.reg(), offset, prop_value.reg(), scratch.reg());
+  }
+}
+
+
+void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) {
+  ASSERT(!in_spilled_code());
+  // Call runtime routine to allocate the catch extension object and
+  // assign the exception value to the catch variable.
+  Comment cmnt(masm_, "[ CatchExtensionObject");
+  Load(node->key());
+  Load(node->value());
+  Result result =
+      frame_->CallRuntime(Runtime::kCreateCatchExtensionObject, 2);
+  frame_->Push(&result);
+}
+
+
+void CodeGenerator::VisitAssignment(Assignment* node) {
+  Comment cmnt(masm_, "[ Assignment");
+  CodeForStatementPosition(node);
+
+  { Reference target(this, node->target());
+    if (target.is_illegal()) {
+      // Fool the virtual frame into thinking that we left the assignment's
+      // value on the frame.
+      frame_->Push(Smi::FromInt(0));
+      return;
+    }
+    Variable* var = node->target()->AsVariableProxy()->AsVariable();
+
+    if (node->starts_initialization_block()) {
+      ASSERT(target.type() == Reference::NAMED ||
+             target.type() == Reference::KEYED);
+      // Change to slow case in the beginning of an initialization
+      // block to avoid the quadratic behavior of repeatedly adding
+      // fast properties.
+
+      // The receiver is the argument to the runtime call.  It is the
+      // first value pushed when the reference was loaded to the
+      // frame.
+      frame_->PushElementAt(target.size() - 1);
+      Result ignored = frame_->CallRuntime(Runtime::kToSlowProperties, 1);
+    }
+    if (node->op() == Token::ASSIGN ||
+        node->op() == Token::INIT_VAR ||
+        node->op() == Token::INIT_CONST) {
+      Load(node->value());
+
+    } else {
+      Literal* literal = node->value()->AsLiteral();
+      Variable* right_var = node->value()->AsVariableProxy()->AsVariable();
+      // There are two cases where the target is not read in the right hand
+      // side, that are easy to test for: the right hand side is a literal,
+      // or the right hand side is a different variable.  TakeValue invalidates
+      // the target, with an implicit promise that it will be written to again
+      // before it is read.
+      if (literal != NULL || (right_var != NULL && right_var != var)) {
+        target.TakeValue(NOT_INSIDE_TYPEOF);
+      } else {
+        target.GetValue(NOT_INSIDE_TYPEOF);
+      }
+      Load(node->value());
+      GenericBinaryOperation(node->binary_op(), node->type());
+    }
+
+    if (var != NULL &&
+        var->mode() == Variable::CONST &&
+        node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) {
+      // Assignment ignored - leave the value on the stack.
+    } else {
+      CodeForSourcePosition(node->position());
+      if (node->op() == Token::INIT_CONST) {
+        // Dynamic constant initializations must use the function context
+        // and initialize the actual constant declared. Dynamic variable
+        // initializations are simply assignments and use SetValue.
+        target.SetValue(CONST_INIT);
+      } else {
+        target.SetValue(NOT_CONST_INIT);
+      }
+      if (node->ends_initialization_block()) {
+        ASSERT(target.type() == Reference::NAMED ||
+               target.type() == Reference::KEYED);
+        // End of initialization block. Revert to fast case.  The
+        // argument to the runtime call is the receiver, which is the
+        // first value pushed as part of the reference, which is below
+        // the lhs value.
+        frame_->PushElementAt(target.size());
+        Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1);
+      }
+    }
+  }
+}
+
+
+void CodeGenerator::VisitThrow(Throw* node) {
+  Comment cmnt(masm_, "[ Throw");
+  CodeForStatementPosition(node);
+
+  Load(node->exception());
+  Result result = frame_->CallRuntime(Runtime::kThrow, 1);
+  frame_->Push(&result);
+}
+
+
+void CodeGenerator::VisitProperty(Property* node) {
+  Comment cmnt(masm_, "[ Property");
+  Reference property(this, node);
+  property.GetValue(typeof_state());
+}
+
+
+void CodeGenerator::VisitCall(Call* node) {
+  Comment cmnt(masm_, "[ Call");
+
+  ZoneList<Expression*>* args = node->arguments();
+
+  CodeForStatementPosition(node);
+
+  // Check if the function is a variable or a property.
+  Expression* function = node->expression();
+  Variable* var = function->AsVariableProxy()->AsVariable();
+  Property* property = function->AsProperty();
+
+  // ------------------------------------------------------------------------
+  // Fast-case: Use inline caching.
+  // ---
+  // According to ECMA-262, section 11.2.3, page 44, the function to call
+  // must be resolved after the arguments have been evaluated. The IC code
+  // automatically handles this by loading the arguments before the function
+  // is resolved in cache misses (this also holds for megamorphic calls).
+  // ------------------------------------------------------------------------
+
+  if (var != NULL && !var->is_this() && var->is_global()) {
+    // ----------------------------------
+    // JavaScript example: 'foo(1, 2, 3)'  // foo is global
+    // ----------------------------------
+
+    // Push the name of the function and the receiver onto the stack.
+    frame_->Push(var->name());
+
+    // Pass the global object as the receiver and let the IC stub
+    // patch the stack to use the global proxy as 'this' in the
+    // invoked function.
+    LoadGlobal();
+
+    // Load the arguments.
+    int arg_count = args->length();
+    for (int i = 0; i < arg_count; i++) {
+      Load(args->at(i));
+    }
+
+    // Call the IC initialization code.
+    CodeForSourcePosition(node->position());
+    Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT,
+                                       arg_count,
+                                       loop_nesting());
+    frame_->RestoreContextRegister();
+    // Replace the function on the stack with the result.
+    frame_->SetElementAt(0, &result);
+
+  } else if (var != NULL && var->slot() != NULL &&
+             var->slot()->type() == Slot::LOOKUP) {
+    // ----------------------------------
+    // JavaScript example: 'with (obj) foo(1, 2, 3)'  // foo is in obj
+    // ----------------------------------
+
+    // Load the function
+    frame_->Push(esi);
+    frame_->Push(var->name());
+    frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
+    // eax: slot value; edx: receiver
+
+    // Load the receiver.
+    frame_->Push(eax);
+    frame_->Push(edx);
+
+    // Call the function.
+    CallWithArguments(args, node->position());
+
+  } else if (property != NULL) {
+    // Check if the key is a literal string.
+    Literal* literal = property->key()->AsLiteral();
+
+    if (literal != NULL && literal->handle()->IsSymbol()) {
+      // ------------------------------------------------------------------
+      // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)'
+      // ------------------------------------------------------------------
+
+      // Push the name of the function and the receiver onto the stack.
+      frame_->Push(literal->handle());
+      Load(property->obj());
+
+      // Load the arguments.
+      int arg_count = args->length();
+      for (int i = 0; i < arg_count; i++) {
+        Load(args->at(i));
+      }
+
+      // Call the IC initialization code.
+      CodeForSourcePosition(node->position());
+      Result result =
+          frame_->CallCallIC(RelocInfo::CODE_TARGET, arg_count, loop_nesting());
+      frame_->RestoreContextRegister();
+      // Replace the function on the stack with the result.
+      frame_->SetElementAt(0, &result);
+
+    } else {
+      // -------------------------------------------
+      // JavaScript example: 'array[index](1, 2, 3)'
+      // -------------------------------------------
+
+      // Load the function to call from the property through a reference.
+      Reference ref(this, property);
+      ref.GetValue(NOT_INSIDE_TYPEOF);
+
+      // Pass receiver to called function.
+      if (property->is_synthetic()) {
+        // Use global object as receiver.
+        LoadGlobalReceiver();
+      } else {
+        // The reference's size is non-negative.
+        frame_->PushElementAt(ref.size());
+      }
+
+      // Call the function.
+      CallWithArguments(args, node->position());
+    }
+
+  } else {
+    // ----------------------------------
+    // JavaScript example: 'foo(1, 2, 3)'  // foo is not global
+    // ----------------------------------
+
+    // Load the function.
+    Load(function);
+
+    // Pass the global proxy as the receiver.
+    LoadGlobalReceiver();
+
+    // Call the function.
+    CallWithArguments(args, node->position());
+  }
+}
+
+
+void CodeGenerator::VisitCallNew(CallNew* node) {
+  Comment cmnt(masm_, "[ CallNew");
+  CodeForStatementPosition(node);
+
+  // According to ECMA-262, section 11.2.2, page 44, the function
+  // expression in new calls must be evaluated before the
+  // arguments. This is different from ordinary calls, where the
+  // actual function to call is resolved after the arguments have been
+  // evaluated.
+
+  // Compute function to call and use the global object as the
+  // receiver. There is no need to use the global proxy here because
+  // it will always be replaced with a newly allocated object.
+  Load(node->expression());
+  LoadGlobal();
+
+  // Push the arguments ("left-to-right") on the stack.
+  ZoneList<Expression*>* args = node->arguments();
+  int arg_count = args->length();
+  for (int i = 0; i < arg_count; i++) {
+    Load(args->at(i));
+  }
+
+  // Call the construct call builtin that handles allocation and
+  // constructor invocation.
+  CodeForSourcePosition(node->position());
+  Result result = frame_->CallConstructor(arg_count);
+  // Replace the function on the stack with the result.
+  frame_->SetElementAt(0, &result);
+}
+
+
+void CodeGenerator::VisitCallEval(CallEval* node) {
+  Comment cmnt(masm_, "[ CallEval");
+
+  // In a call to eval, we first call %ResolvePossiblyDirectEval to resolve
+  // the function we need to call and the receiver of the call.
+  // Then we call the resolved function using the given arguments.
+
+  ZoneList<Expression*>* args = node->arguments();
+  Expression* function = node->expression();
+
+  CodeForStatementPosition(node);
+
+  // Prepare the stack for the call to the resolved function.
+  Load(function);
+
+  // Allocate a frame slot for the receiver.
+  frame_->Push(Factory::undefined_value());
+  int arg_count = args->length();
+  for (int i = 0; i < arg_count; i++) {
+    Load(args->at(i));
+  }
+
+  // Prepare the stack for the call to ResolvePossiblyDirectEval.
+  frame_->PushElementAt(arg_count + 1);
+  if (arg_count > 0) {
+    frame_->PushElementAt(arg_count);
+  } else {
+    frame_->Push(Factory::undefined_value());
+  }
+
+  // Resolve the call.
+  Result result =
+      frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 2);
+
+  // Touch up the stack with the right values for the function and the
+  // receiver.  Use a scratch register to avoid destroying the result.
+  Result scratch = allocator_->Allocate();
+  ASSERT(scratch.is_valid());
+  __ mov(scratch.reg(), FieldOperand(result.reg(), FixedArray::kHeaderSize));
+  frame_->SetElementAt(arg_count + 1, &scratch);
+
+  // We can reuse the result register now.
+  frame_->Spill(result.reg());
+  __ mov(result.reg(),
+         FieldOperand(result.reg(), FixedArray::kHeaderSize + kPointerSize));
+  frame_->SetElementAt(arg_count, &result);
+
+  // Call the function.
+  CodeForSourcePosition(node->position());
+  CallFunctionStub call_function(arg_count);
+  result = frame_->CallStub(&call_function, arg_count + 1);
+
+  // Restore the context and overwrite the function on the stack with
+  // the result.
+  frame_->RestoreContextRegister();
+  frame_->SetElementAt(0, &result);
+}
+
+
+void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
+  ASSERT(args->length() == 1);
+  Load(args->at(0));
+  Result value = frame_->Pop();
+  value.ToRegister();
+  ASSERT(value.is_valid());
+  __ test(value.reg(), Immediate(kSmiTagMask));
+  value.Unuse();
+  destination()->Split(zero);
+}
+
+
+void CodeGenerator::GenerateLog(ZoneList<Expression*>* args) {
+  // Conditionally generate a log call.
+  // Args:
+  //   0 (literal string): The type of logging (corresponds to the flags).
+  //     This is used to determine whether or not to generate the log call.
+  //   1 (string): Format string.  Access the string at argument index 2
+  //     with '%2s' (see Logger::LogRuntime for all the formats).
+  //   2 (array): Arguments to the format string.
+  ASSERT_EQ(args->length(), 3);
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (ShouldGenerateLog(args->at(0))) {
+    Load(args->at(1));
+    Load(args->at(2));
+    frame_->CallRuntime(Runtime::kLog, 2);
+  }
+#endif
+  // Finally, we're expected to leave a value on the top of the stack.
+  frame_->Push(Factory::undefined_value());
+}
+
+
+void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
+  ASSERT(args->length() == 1);
+  Load(args->at(0));
+  Result value = frame_->Pop();
+  value.ToRegister();
+  ASSERT(value.is_valid());
+  __ test(value.reg(), Immediate(kSmiTagMask | 0x80000000));
+  value.Unuse();
+  destination()->Split(zero);
+}
+
+
+// This generates code that performs a charCodeAt() call or returns
+// undefined in order to trigger the slow case, Runtime_StringCharCodeAt.
+// It can handle flat and sliced strings, 8 and 16 bit characters and
+// cons strings where the answer is found in the left hand branch of the
+// cons.  The slow case will flatten the string, which will ensure that
+// the answer is in the left hand side the next time around.
+void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
+  ASSERT(args->length() == 2);
+
+  JumpTarget slow_case(this);
+  JumpTarget end(this);
+  JumpTarget not_a_flat_string(this);
+  JumpTarget a_cons_string(this);
+  JumpTarget try_again_with_new_string(this, JumpTarget::BIDIRECTIONAL);
+  JumpTarget ascii_string(this);
+  JumpTarget got_char_code(this);
+
+  Load(args->at(0));
+  Load(args->at(1));
+  // Reserve register ecx, to use as shift amount later
+  Result shift_amount = allocator()->Allocate(ecx);
+  ASSERT(shift_amount.is_valid());
+  Result index = frame_->Pop();
+  index.ToRegister();
+  Result object = frame_->Pop();
+  object.ToRegister();
+  // If the receiver is a smi return undefined.
+  ASSERT(kSmiTag == 0);
+  __ test(object.reg(), Immediate(kSmiTagMask));
+  slow_case.Branch(zero, not_taken);
+
+  // Check for negative or non-smi index.
+  ASSERT(kSmiTag == 0);
+  __ test(index.reg(), Immediate(kSmiTagMask | 0x80000000));
+  slow_case.Branch(not_zero, not_taken);
+  // Get rid of the smi tag on the index.
+  frame_->Spill(index.reg());
+  __ sar(index.reg(), kSmiTagSize);
+
+  try_again_with_new_string.Bind(&object, &index, &shift_amount);
+  // Get the type of the heap object.
+  Result object_type = allocator()->Allocate();
+  ASSERT(object_type.is_valid());
+  __ mov(object_type.reg(), FieldOperand(object.reg(), HeapObject::kMapOffset));
+  __ movzx_b(object_type.reg(),
+             FieldOperand(object_type.reg(), Map::kInstanceTypeOffset));
+  // We don't handle non-strings.
+  __ test(object_type.reg(), Immediate(kIsNotStringMask));
+  slow_case.Branch(not_zero, not_taken);
+
+  // Here we make assumptions about the tag values and the shifts needed.
+  // See the comment in objects.h.
+  ASSERT(kLongStringTag == 0);
+  ASSERT(kMediumStringTag + String::kLongLengthShift ==
+         String::kMediumLengthShift);
+  ASSERT(kShortStringTag + String::kLongLengthShift ==
+         String::kShortLengthShift);
+  __ mov(shift_amount.reg(), Operand(object_type.reg()));
+  __ and_(shift_amount.reg(), kStringSizeMask);
+  __ add(Operand(shift_amount.reg()), Immediate(String::kLongLengthShift));
+  // Get the length field. Temporary register now used for length.
+  Result length = object_type;
+  __ mov(length.reg(), FieldOperand(object.reg(), String::kLengthOffset));
+  __ shr(length.reg());  // shift_amount, in ecx, is implicit operand.
+  // Check for index out of range.
+  __ cmp(index.reg(), Operand(length.reg()));
+  slow_case.Branch(greater_equal, not_taken);
+  length.Unuse();
+  // Load the object type into object_type again.
+  // These two instructions are duplicated from above, to save a register.
+  __ mov(object_type.reg(), FieldOperand(object.reg(), HeapObject::kMapOffset));
+  __ movzx_b(object_type.reg(),
+             FieldOperand(object_type.reg(), Map::kInstanceTypeOffset));
+
+  // We need special handling for non-flat strings.
+  ASSERT(kSeqStringTag == 0);
+  __ test(object_type.reg(), Immediate(kStringRepresentationMask));
+  not_a_flat_string.Branch(not_zero, &object, &index, &object_type,
+                           &shift_amount, not_taken);
+  shift_amount.Unuse();
+  // Check for 1-byte or 2-byte string.
+  __ test(object_type.reg(), Immediate(kStringEncodingMask));
+  ascii_string.Branch(not_zero, &object, &index, &object_type, taken);
+
+  // 2-byte string.
+  // Load the 2-byte character code.
+  __ movzx_w(object_type.reg(), FieldOperand(object.reg(),
+                                             index.reg(),
+                                             times_2,
+                                             SeqTwoByteString::kHeaderSize));
+  object.Unuse();
+  index.Unuse();
+  got_char_code.Jump(&object_type);
+
+  // ASCII string.
+  ascii_string.Bind(&object, &index, &object_type);
+  // Load the byte.
+  __ movzx_b(object_type.reg(), FieldOperand(object.reg(),
+                                             index.reg(),
+                                             times_1,
+                                             SeqAsciiString::kHeaderSize));
+  object.Unuse();
+  index.Unuse();
+  got_char_code.Bind(&object_type);
+  ASSERT(kSmiTag == 0);
+  __ shl(object_type.reg(), kSmiTagSize);
+  frame_->Push(&object_type);
+  end.Jump();
+
+  // Handle non-flat strings.
+  not_a_flat_string.Bind(&object, &index, &object_type, &shift_amount);
+  __ and_(object_type.reg(), kStringRepresentationMask);
+  __ cmp(object_type.reg(), kConsStringTag);
+  a_cons_string.Branch(equal, &object, &index, &shift_amount, taken);
+  __ cmp(object_type.reg(), kSlicedStringTag);
+  slow_case.Branch(not_equal, not_taken);
+  object_type.Unuse();
+
+  // SlicedString.
+  // Add the offset to the index.
+  __ add(index.reg(), FieldOperand(object.reg(), SlicedString::kStartOffset));
+  slow_case.Branch(overflow);
+  // Getting the underlying string is done by running the cons string code.
+
+  // ConsString.
+  a_cons_string.Bind(&object, &index, &shift_amount);
+  // Get the first of the two strings.
+  frame_->Spill(object.reg());
+  // Both sliced and cons strings store their source string at the same place.
+  ASSERT(SlicedString::kBufferOffset == ConsString::kFirstOffset);
+  __ mov(object.reg(), FieldOperand(object.reg(), ConsString::kFirstOffset));
+  try_again_with_new_string.Jump(&object, &index, &shift_amount);
+
+  // No results live at this point.
+  slow_case.Bind();
+  frame_->Push(Factory::undefined_value());
+  end.Bind();
+}
+
+
+void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
+  ASSERT(args->length() == 1);
+  Load(args->at(0));
+  Result value = frame_->Pop();
+  value.ToRegister();
+  ASSERT(value.is_valid());
+  __ test(value.reg(), Immediate(kSmiTagMask));
+  destination()->false_target()->Branch(equal);
+  // It is a heap object - get map.
+  Result temp = allocator()->Allocate();
+  ASSERT(temp.is_valid());
+  // Check if the object is a JS array or not.
+  __ CmpObjectType(value.reg(), JS_ARRAY_TYPE, temp.reg());
+  value.Unuse();
+  temp.Unuse();
+  destination()->Split(equal);
+}
+
+
+void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
+  ASSERT(args->length() == 0);
+  // ArgumentsAccessStub takes the parameter count as an input argument
+  // in register eax.  Create a constant result for it.
+  Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())), this);
+  // Call the shared stub to get to the arguments.length.
+  ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
+  Result result = frame_->CallStub(&stub, &count);
+  frame_->Push(&result);
+}
+
+
+void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
+  ASSERT(args->length() == 1);
+  JumpTarget leave(this);
+  Load(args->at(0));  // Load the object.
+  frame_->Dup();
+  Result object = frame_->Pop();
+  object.ToRegister();
+  ASSERT(object.is_valid());
+  // if (object->IsSmi()) return object.
+  __ test(object.reg(), Immediate(kSmiTagMask));
+  leave.Branch(zero, taken);
+  // It is a heap object - get map.
+  Result temp = allocator()->Allocate();
+  ASSERT(temp.is_valid());
+  // if (!object->IsJSValue()) return object.
+  __ CmpObjectType(object.reg(), JS_VALUE_TYPE, temp.reg());
+  leave.Branch(not_equal, not_taken);
+  __ mov(temp.reg(), FieldOperand(object.reg(), JSValue::kValueOffset));
+  object.Unuse();
+  frame_->SetElementAt(0, &temp);
+  leave.Bind();
+}
+
+
+void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) {
+  ASSERT(args->length() == 2);
+  JumpTarget leave(this);
+  Load(args->at(0));  // Load the object.
+  Load(args->at(1));  // Load the value.
+  Result value = frame_->Pop();
+  Result object = frame_->Pop();
+  value.ToRegister();
+  object.ToRegister();
+
+  // if (object->IsSmi()) return value.
+  __ test(object.reg(), Immediate(kSmiTagMask));
+  leave.Branch(zero, &value, taken);
+
+  // It is a heap object - get its map.
+  Result scratch = allocator_->Allocate();
+  ASSERT(scratch.is_valid());
+  // if (!object->IsJSValue()) return value.
+  __ CmpObjectType(object.reg(), JS_VALUE_TYPE, scratch.reg());
+  leave.Branch(not_equal, &value, not_taken);
+
+  // Store the value.
+  __ mov(FieldOperand(object.reg(), JSValue::kValueOffset), value.reg());
+  // Update the write barrier.  Save the value as it will be
+  // overwritten by the write barrier code and is needed afterward.
+  Result duplicate_value = allocator_->Allocate();
+  ASSERT(duplicate_value.is_valid());
+  __ mov(duplicate_value.reg(), value.reg());
+  // The object register is also overwritten by the write barrier and
+  // possibly aliased in the frame.
+  frame_->Spill(object.reg());
+  __ RecordWrite(object.reg(), JSValue::kValueOffset, duplicate_value.reg(),
+                 scratch.reg());
+  object.Unuse();
+  scratch.Unuse();
+  duplicate_value.Unuse();
+
+  // Leave.
+  leave.Bind(&value);
+  frame_->Push(&value);
+}
+
+
+void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
+  ASSERT(args->length() == 1);
+
+  // ArgumentsAccessStub expects the key in edx and the formal
+  // parameter count in eax.
+  Load(args->at(0));
+  Result key = frame_->Pop();
+  // Explicitly create a constant result.
+  Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())), this);
+  // Call the shared stub to get to arguments[key].
+  ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
+  Result result = frame_->CallStub(&stub, &key, &count);
+  frame_->Push(&result);
+}
+
+
+void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
+  ASSERT(args->length() == 2);
+
+  // Load the two objects into registers and perform the comparison.
+  Load(args->at(0));
+  Load(args->at(1));
+  Result right = frame_->Pop();
+  Result left = frame_->Pop();
+  right.ToRegister();
+  left.ToRegister();
+  __ cmp(right.reg(), Operand(left.reg()));
+  right.Unuse();
+  left.Unuse();
+  destination()->Split(equal);
+}
+
+
+void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
+  if (CheckForInlineRuntimeCall(node)) {
+    return;
+  }
+
+  ZoneList<Expression*>* args = node->arguments();
+  Comment cmnt(masm_, "[ CallRuntime");
+  Runtime::Function* function = node->function();
+
+  if (function == NULL) {
+    // Prepare stack for calling JS runtime function.
+    frame_->Push(node->name());
+    // 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(), FieldOperand(temp.reg(), GlobalObject::kBuiltinsOffset));
+    frame_->Push(&temp);
+  }
+
+  // Push the arguments ("left-to-right").
+  int arg_count = args->length();
+  for (int i = 0; i < arg_count; i++) {
+    Load(args->at(i));
+  }
+
+  if (function == NULL) {
+    // Call the JS runtime function.  Pass 0 as the loop nesting depth
+    // because we do not handle runtime calls specially in loops.
+    Result answer = frame_->CallCallIC(RelocInfo::CODE_TARGET, arg_count, 0);
+    frame_->RestoreContextRegister();
+    frame_->SetElementAt(0, &answer);
+  } else {
+    // Call the C runtime function.
+    Result answer = frame_->CallRuntime(function, arg_count);
+    frame_->Push(&answer);
+  }
+}
+
+
+void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
+  // Note that because of NOT and an optimization in comparison of a typeof
+  // expression to a literal string, this function can fail to leave a value
+  // on top of the frame or in the cc register.
+  Comment cmnt(masm_, "[ UnaryOperation");
+
+  Token::Value op = node->op();
+
+  if (op == Token::NOT) {
+    // Swap the true and false targets but keep the same actual label
+    // as the fall through.
+    destination()->Invert();
+    LoadCondition(node->expression(), NOT_INSIDE_TYPEOF, destination(), true);
+    // Swap the labels back.
+    destination()->Invert();
+
+  } else if (op == Token::DELETE) {
+    Property* property = node->expression()->AsProperty();
+    if (property != NULL) {
+      Load(property->obj());
+      Load(property->key());
+      Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2);
+      frame_->Push(&answer);
+      return;
+    }
+
+    Variable* variable = node->expression()->AsVariableProxy()->AsVariable();
+    if (variable != NULL) {
+      Slot* slot = variable->slot();
+      if (variable->is_global()) {
+        LoadGlobal();
+        frame_->Push(variable->name());
+        Result answer = frame_->InvokeBuiltin(Builtins::DELETE,
+                                              CALL_FUNCTION, 2);
+        frame_->Push(&answer);
+        return;
+
+      } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
+        // lookup the context holding the named variable
+        frame_->Push(esi);
+        frame_->Push(variable->name());
+        Result context = frame_->CallRuntime(Runtime::kLookupContext, 2);
+        frame_->Push(&context);
+        frame_->Push(variable->name());
+        Result answer = frame_->InvokeBuiltin(Builtins::DELETE,
+                                              CALL_FUNCTION, 2);
+        frame_->Push(&answer);
+        return;
+      }
+
+      // Default: Result of deleting non-global, not dynamically
+      // introduced variables is false.
+      frame_->Push(Factory::false_value());
+
+    } else {
+      // Default: Result of deleting expressions is true.
+      Load(node->expression());  // may have side-effects
+      frame_->SetElementAt(0, Factory::true_value());
+    }
+
+  } else if (op == Token::TYPEOF) {
+    // Special case for loading the typeof expression; see comment on
+    // LoadTypeofExpression().
+    LoadTypeofExpression(node->expression());
+    Result answer = frame_->CallRuntime(Runtime::kTypeof, 1);
+    frame_->Push(&answer);
+
+  } else if (op == Token::VOID) {
+    Expression* expression = node->expression();
+    if (expression && expression->AsLiteral() && (
+        expression->AsLiteral()->IsTrue() ||
+        expression->AsLiteral()->IsFalse() ||
+        expression->AsLiteral()->handle()->IsNumber() ||
+        expression->AsLiteral()->handle()->IsString() ||
+        expression->AsLiteral()->handle()->IsJSRegExp() ||
+        expression->AsLiteral()->IsNull())) {
+      // Omit evaluating the value of the primitive literal.
+      // It will be discarded anyway, and can have no side effect.
+      frame_->Push(Factory::undefined_value());
+    } else {
+      Load(node->expression());
+      frame_->SetElementAt(0, Factory::undefined_value());
+    }
+
+  } else {
+    Load(node->expression());
+    switch (op) {
+      case Token::NOT:
+      case Token::DELETE:
+      case Token::TYPEOF:
+        UNREACHABLE();  // handled above
+        break;
+
+      case Token::SUB: {
+        UnarySubStub stub;
+        // TODO(1222589): remove dependency of TOS being cached inside stub
+        Result operand = frame_->Pop();
+        Result answer = frame_->CallStub(&stub, &operand);
+        frame_->Push(&answer);
+        break;
+      }
+
+      case Token::BIT_NOT: {
+        // Smi check.
+        JumpTarget smi_label(this);
+        JumpTarget continue_label(this);
+        Result operand = frame_->Pop();
+        operand.ToRegister();
+        __ test(operand.reg(), Immediate(kSmiTagMask));
+        smi_label.Branch(zero, &operand, taken);
+
+        frame_->Push(&operand);  // undo popping of TOS
+        Result answer = frame_->InvokeBuiltin(Builtins::BIT_NOT,
+                                              CALL_FUNCTION, 1);
+
+        continue_label.Jump(&answer);
+        smi_label.Bind(&answer);
+        answer.ToRegister();
+        frame_->Spill(answer.reg());
+        __ not_(answer.reg());
+        __ and_(answer.reg(), ~kSmiTagMask);  // Remove inverted smi-tag.
+        continue_label.Bind(&answer);
+        frame_->Push(&answer);
+        break;
+      }
+
+      case Token::ADD: {
+        // Smi check.
+        JumpTarget continue_label(this);
+        Result operand = frame_->Pop();
+        operand.ToRegister();
+        __ test(operand.reg(), Immediate(kSmiTagMask));
+        continue_label.Branch(zero, &operand, taken);
+
+        frame_->Push(&operand);
+        Result answer = frame_->InvokeBuiltin(Builtins::TO_NUMBER,
+                                              CALL_FUNCTION, 1);
+
+        continue_label.Bind(&answer);
+        frame_->Push(&answer);
+        break;
+      }
+
+      default:
+        UNREACHABLE();
+    }
+  }
+}
+
+
+class DeferredCountOperation: public DeferredCode {
+ public:
+  DeferredCountOperation(CodeGenerator* generator,
+                         bool is_postfix,
+                         bool is_increment,
+                         int target_size)
+      : DeferredCode(generator),
+        is_postfix_(is_postfix),
+        is_increment_(is_increment),
+        target_size_(target_size) {
+    set_comment("[ DeferredCountOperation");
+  }
+
+  virtual void Generate();
+
+ private:
+  bool is_postfix_;
+  bool is_increment_;
+  int target_size_;
+};
+
+
+void DeferredCountOperation::Generate() {
+  CodeGenerator* cgen = generator();
+  Result value(cgen);
+  enter()->Bind(&value);
+  VirtualFrame* frame = cgen->frame();
+  // Undo the optimistic smi operation.
+  value.ToRegister();
+  frame->Spill(value.reg());
+  if (is_increment_) {
+    __ sub(Operand(value.reg()), Immediate(Smi::FromInt(1)));
+  } else {
+    __ add(Operand(value.reg()), Immediate(Smi::FromInt(1)));
+  }
+  frame->Push(&value);
+  value = frame->InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION, 1);
+  frame->Push(&value);
+  if (is_postfix_) {  // Fix up copy of old value with ToNumber(value).
+    // This is only safe because VisitCountOperation makes this frame slot
+    // beneath the reference a register, which is spilled at the above call.
+    // We cannot safely write to constants or copies below the water line.
+    frame->StoreToElementAt(target_size_ + 1);
+  }
+  frame->Push(Smi::FromInt(1));
+  if (is_increment_) {
+    value = frame->CallRuntime(Runtime::kNumberAdd, 2);
+  } else {
+    value = frame->CallRuntime(Runtime::kNumberSub, 2);
+  }
+  exit_.Jump(&value);
+}
+
+
+void CodeGenerator::VisitCountOperation(CountOperation* node) {
+  Comment cmnt(masm_, "[ CountOperation");
+
+  bool is_postfix = node->is_postfix();
+  bool is_increment = node->op() == Token::INC;
+
+  Variable* var = node->expression()->AsVariableProxy()->AsVariable();
+  bool is_const = (var != NULL && var->mode() == Variable::CONST);
+
+  // Postfix operators need a stack slot under the reference to hold
+  // the old value while the new one is being stored.
+  if (is_postfix) {
+    frame_->Push(Smi::FromInt(0));
+  }
+
+  { Reference target(this, node->expression());
+    if (target.is_illegal()) {
+      // Spoof the virtual frame to have the expected height (one higher
+      // than on entry).
+      if (!is_postfix) {
+        frame_->Push(Smi::FromInt(0));
+      }
+      return;
+    }
+    target.TakeValue(NOT_INSIDE_TYPEOF);
+
+    DeferredCountOperation* deferred =
+        new DeferredCountOperation(this, is_postfix,
+                                   is_increment, target.size());
+
+    Result value = frame_->Pop();
+    value.ToRegister();
+
+    // Postfix: Store the old value as the result.
+    if (is_postfix) {
+      // Explicitly back the slot for the old value with a new register.
+      // This improves performance in some cases.
+      Result old_value = allocator_->Allocate();
+      ASSERT(old_value.is_valid());
+      __ mov(old_value.reg(), value.reg());
+      // SetElement must not create a constant element or a copy in this slot,
+      // since we will write to it, below the waterline, in deferred code.
+      frame_->SetElementAt(target.size(), &old_value);
+    }
+
+    // Perform optimistic increment/decrement.  Ensure the value is
+    // writable.
+    frame_->Spill(value.reg());
+    ASSERT(allocator_->count(value.reg()) == 1);
+
+    // In order to combine the overflow and the smi check, we need to
+    // be able to allocate a byte register.  We attempt to do so
+    // without spilling.  If we fail, we will generate separate
+    // overflow and smi checks.
+    //
+    // We need to allocate and clear the temporary byte register
+    // before performing the count operation since clearing the
+    // register using xor will clear the overflow flag.
+    Result tmp = allocator_->AllocateByteRegisterWithoutSpilling();
+    if (tmp.is_valid()) {
+      __ Set(tmp.reg(), Immediate(0));
+    }
+
+    if (is_increment) {
+      __ add(Operand(value.reg()), Immediate(Smi::FromInt(1)));
+    } else {
+      __ sub(Operand(value.reg()), Immediate(Smi::FromInt(1)));
+    }
+
+    // If the count operation didn't overflow and the result is a
+    // valid smi, we're done. Otherwise, we jump to the deferred
+    // slow-case code.
+    //
+    // We combine the overflow and the smi check if we could
+    // successfully allocate a temporary byte register.
+    if (tmp.is_valid()) {
+      __ setcc(overflow, tmp.reg());
+      __ or_(Operand(value.reg()), tmp.reg());
+      tmp.Unuse();
+      __ test(value.reg(), Immediate(kSmiTagMask));
+      deferred->enter()->Branch(not_zero, &value, not_taken);
+    } else {  // Otherwise we test separately for overflow and smi check.
+      deferred->enter()->Branch(overflow, &value, not_taken);
+      __ test(value.reg(), Immediate(kSmiTagMask));
+      deferred->enter()->Branch(not_zero, &value, not_taken);
+    }
+
+    // Store the new value in the target if not const.
+    deferred->BindExit(&value);
+    frame_->Push(&value);
+    if (!is_const) {
+      target.SetValue(NOT_CONST_INIT);
+    }
+  }
+
+  // Postfix: Discard the new value and use the old.
+  if (is_postfix) {
+    frame_->Drop();
+  }
+}
+
+
+void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
+  // Note that due to an optimization in comparison operations (typeof
+  // compared to a string literal), we can evaluate a binary expression such
+  // as AND or OR and not leave a value on the frame or in the cc register.
+  Comment cmnt(masm_, "[ BinaryOperation");
+  Token::Value op = node->op();
+
+  // According to ECMA-262 section 11.11, page 58, the binary logical
+  // operators must yield the result of one of the two expressions
+  // before any ToBoolean() conversions. This means that the value
+  // produced by a && or || operator is not necessarily a boolean.
+
+  // NOTE: If the left hand side produces a materialized value (not
+  // control flow), we force the right hand side to do the same. This
+  // is necessary because we assume that if we get control flow on the
+  // last path out of an expression we got it on all paths.
+  if (op == Token::AND) {
+    JumpTarget is_true(this);
+    ControlDestination dest(&is_true, destination()->false_target(), true);
+    LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &dest, false);
+
+    if (dest.false_was_fall_through()) {
+      // The current false target was used as the fall-through.  If
+      // there are no dangling jumps to is_true then the left
+      // subexpression was unconditionally false.  Otherwise we have
+      // paths where we do have to evaluate the right subexpression.
+      if (is_true.is_linked()) {
+        // We need to compile the right subexpression.  If the jump to
+        // the current false target was a forward jump then we have a
+        // valid frame, we have just bound the false target, and we
+        // have to jump around the code for the right subexpression.
+        if (has_valid_frame()) {
+          destination()->false_target()->Unuse();
+          destination()->false_target()->Jump();
+        }
+        is_true.Bind();
+        // The left subexpression compiled to control flow, so the
+        // right one is free to do so as well.
+        LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(), false);
+      } else {
+        // We have actually just jumped to or bound the current false
+        // target but the current control destination is not marked as
+        // used.
+        destination()->Use(false);
+      }
+
+    } else if (dest.is_used()) {
+      // The left subexpression compiled to control flow (and is_true
+      // was just bound), so the right is free to do so as well.
+      LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(), false);
+
+    } else {
+      // We have a materialized value on the frame, so we exit with
+      // one on all paths.  There are possibly also jumps to is_true
+      // from nested subexpressions.
+      JumpTarget pop_and_continue(this);
+      JumpTarget exit(this);
+
+      // Avoid popping the result if it converts to 'false' using the
+      // standard ToBoolean() conversion as described in ECMA-262,
+      // section 9.2, page 30.
+      //
+      // Duplicate the TOS value. The duplicate will be popped by
+      // ToBoolean.
+      frame_->Dup();
+      ControlDestination dest(&pop_and_continue, &exit, true);
+      ToBoolean(&dest);
+
+      // Pop the result of evaluating the first part.
+      frame_->Drop();
+
+      // Compile right side expression.
+      is_true.Bind();
+      Load(node->right());
+
+      // Exit (always with a materialized value).
+      exit.Bind();
+    }
+
+  } else if (op == Token::OR) {
+    JumpTarget is_false(this);
+    ControlDestination dest(destination()->true_target(), &is_false, false);
+    LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &dest, false);
+
+    if (dest.true_was_fall_through()) {
+      // The current true target was used as the fall-through.  If
+      // there are no dangling jumps to is_false then the left
+      // subexpression was unconditionally true.  Otherwise we have
+      // paths where we do have to evaluate the right subexpression.
+      if (is_false.is_linked()) {
+        // We need to compile the right subexpression.  If the jump to
+        // the current true target was a forward jump then we have a
+        // valid frame, we have just bound the true target, and we
+        // have to jump around the code for the right subexpression.
+        if (has_valid_frame()) {
+          destination()->true_target()->Unuse();
+          destination()->true_target()->Jump();
+        }
+        is_false.Bind();
+        // The left subexpression compiled to control flow, so the
+        // right one is free to do so as well.
+        LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(), false);
+      } else {
+        // We have just jumped to or bound the current true target but
+        // the current control destination is not marked as used.
+        destination()->Use(true);
+      }
+
+    } else if (dest.is_used()) {
+      // The left subexpression compiled to control flow (and is_false
+      // was just bound), so the right is free to do so as well.
+      LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(), false);
+
+    } else {
+      // We have a materialized value on the frame, so we exit with
+      // one on all paths.  There are possibly also jumps to is_false
+      // from nested subexpressions.
+      JumpTarget pop_and_continue(this);
+      JumpTarget exit(this);
+
+      // Avoid popping the result if it converts to 'true' using the
+      // standard ToBoolean() conversion as described in ECMA-262,
+      // section 9.2, page 30.
+      //
+      // Duplicate the TOS value. The duplicate will be popped by
+      // ToBoolean.
+      frame_->Dup();
+      ControlDestination dest(&exit, &pop_and_continue, false);
+      ToBoolean(&dest);
+
+      // Pop the result of evaluating the first part.
+      frame_->Drop();
+
+      // Compile right side expression.
+      is_false.Bind();
+      Load(node->right());
+
+      // Exit (always with a materialized value).
+      exit.Bind();
+    }
+
+  } else {
+    // NOTE: The code below assumes that the slow cases (calls to runtime)
+    // never return a constant/immutable object.
+    OverwriteMode overwrite_mode = NO_OVERWRITE;
+    if (node->left()->AsBinaryOperation() != NULL &&
+        node->left()->AsBinaryOperation()->ResultOverwriteAllowed()) {
+      overwrite_mode = OVERWRITE_LEFT;
+    } else if (node->right()->AsBinaryOperation() != NULL &&
+               node->right()->AsBinaryOperation()->ResultOverwriteAllowed()) {
+      overwrite_mode = OVERWRITE_RIGHT;
+    }
+
+    Load(node->left());
+    Load(node->right());
+    GenericBinaryOperation(node->op(), node->type(), overwrite_mode);
+  }
+}
+
+
+void CodeGenerator::VisitThisFunction(ThisFunction* node) {
+  frame_->PushFunction();
+}
+
+
+class InstanceofStub: public CodeStub {
+ public:
+  InstanceofStub() { }
+
+  void Generate(MacroAssembler* masm);
+
+ private:
+  Major MajorKey() { return Instanceof; }
+  int MinorKey() { return 0; }
+};
+
+
+void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
+  Comment cmnt(masm_, "[ CompareOperation");
+
+  // Get the expressions from the node.
+  Expression* left = node->left();
+  Expression* right = node->right();
+  Token::Value op = node->op();
+  // To make typeof testing for natives implemented in JavaScript really
+  // efficient, we generate special code for expressions of the form:
+  // 'typeof <expression> == <string>'.
+  UnaryOperation* operation = left->AsUnaryOperation();
+  if ((op == Token::EQ || op == Token::EQ_STRICT) &&
+      (operation != NULL && operation->op() == Token::TYPEOF) &&
+      (right->AsLiteral() != NULL &&
+       right->AsLiteral()->handle()->IsString())) {
+    Handle<String> check(String::cast(*right->AsLiteral()->handle()));
+
+    // Load the operand and move it to a register.
+    LoadTypeofExpression(operation->expression());
+    Result answer = frame_->Pop();
+    answer.ToRegister();
+
+    if (check->Equals(Heap::number_symbol())) {
+      __ test(answer.reg(), Immediate(kSmiTagMask));
+      destination()->true_target()->Branch(zero);
+      frame_->Spill(answer.reg());
+      __ mov(answer.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
+      __ cmp(answer.reg(), Factory::heap_number_map());
+      answer.Unuse();
+      destination()->Split(equal);
+
+    } else if (check->Equals(Heap::string_symbol())) {
+      __ test(answer.reg(), Immediate(kSmiTagMask));
+      destination()->false_target()->Branch(zero);
+
+      // It can be an undetectable string object.
+      Result temp = allocator()->Allocate();
+      ASSERT(temp.is_valid());
+      __ mov(temp.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
+      __ movzx_b(temp.reg(), FieldOperand(temp.reg(), Map::kBitFieldOffset));
+      __ test(temp.reg(), Immediate(1 << Map::kIsUndetectable));
+      destination()->false_target()->Branch(not_zero);
+      __ mov(temp.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
+      __ movzx_b(temp.reg(),
+                 FieldOperand(temp.reg(), Map::kInstanceTypeOffset));
+      __ cmp(temp.reg(), FIRST_NONSTRING_TYPE);
+      temp.Unuse();
+      answer.Unuse();
+      destination()->Split(less);
+
+    } else if (check->Equals(Heap::boolean_symbol())) {
+      __ cmp(answer.reg(), Factory::true_value());
+      destination()->true_target()->Branch(equal);
+      __ cmp(answer.reg(), Factory::false_value());
+      answer.Unuse();
+      destination()->Split(equal);
+
+    } else if (check->Equals(Heap::undefined_symbol())) {
+      __ cmp(answer.reg(), Factory::undefined_value());
+      destination()->true_target()->Branch(equal);
+
+      __ test(answer.reg(), Immediate(kSmiTagMask));
+      destination()->false_target()->Branch(zero);
+
+      // It can be an undetectable object.
+      frame_->Spill(answer.reg());
+      __ mov(answer.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
+      __ movzx_b(answer.reg(),
+                 FieldOperand(answer.reg(), Map::kBitFieldOffset));
+      __ test(answer.reg(), Immediate(1 << Map::kIsUndetectable));
+      answer.Unuse();
+      destination()->Split(not_zero);
+
+    } else if (check->Equals(Heap::function_symbol())) {
+      __ test(answer.reg(), Immediate(kSmiTagMask));
+      destination()->false_target()->Branch(zero);
+      frame_->Spill(answer.reg());
+      __ CmpObjectType(answer.reg(), JS_FUNCTION_TYPE, answer.reg());
+      answer.Unuse();
+      destination()->Split(equal);
+
+    } else if (check->Equals(Heap::object_symbol())) {
+      __ test(answer.reg(), Immediate(kSmiTagMask));
+      destination()->false_target()->Branch(zero);
+      __ cmp(answer.reg(), Factory::null_value());
+      destination()->true_target()->Branch(equal);
+
+      // It can be an undetectable object.
+      Result map = allocator()->Allocate();
+      ASSERT(map.is_valid());
+      __ mov(map.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
+      __ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kBitFieldOffset));
+      __ test(map.reg(), Immediate(1 << Map::kIsUndetectable));
+      destination()->false_target()->Branch(not_zero);
+      __ mov(map.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
+      __ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kInstanceTypeOffset));
+      __ cmp(map.reg(), FIRST_JS_OBJECT_TYPE);
+      destination()->false_target()->Branch(less);
+      __ cmp(map.reg(), LAST_JS_OBJECT_TYPE);
+      answer.Unuse();
+      map.Unuse();
+      destination()->Split(less_equal);
+    } else {
+      // Uncommon case: typeof testing against a string literal that is
+      // never returned from the typeof operator.
+      answer.Unuse();
+      destination()->Goto(false);
+    }
+    return;
+  }
+
+  Condition cc = no_condition;
+  bool strict = false;
+  switch (op) {
+    case Token::EQ_STRICT:
+      strict = true;
+      // Fall through
+    case Token::EQ:
+      cc = equal;
+      break;
+    case Token::LT:
+      cc = less;
+      break;
+    case Token::GT:
+      cc = greater;
+      break;
+    case Token::LTE:
+      cc = less_equal;
+      break;
+    case Token::GTE:
+      cc = greater_equal;
+      break;
+    case Token::IN: {
+      Load(left);
+      Load(right);
+      Result answer = frame_->InvokeBuiltin(Builtins::IN, CALL_FUNCTION, 2);
+      frame_->Push(&answer);  // push the result
+      return;
+    }
+    case Token::INSTANCEOF: {
+      Load(left);
+      Load(right);
+      InstanceofStub stub;
+      Result answer = frame_->CallStub(&stub, 2);
+      answer.ToRegister();
+      __ test(answer.reg(), Operand(answer.reg()));
+      answer.Unuse();
+      destination()->Split(zero);
+      return;
+    }
+    default:
+      UNREACHABLE();
+  }
+  Load(left);
+  Load(right);
+  Comparison(cc, strict, destination());
+}
+
+
+#ifdef DEBUG
+bool CodeGenerator::HasValidEntryRegisters() {
+  return (allocator()->count(eax) == (frame()->is_used(eax) ? 1 : 0))
+      && (allocator()->count(ebx) == (frame()->is_used(ebx) ? 1 : 0))
+      && (allocator()->count(ecx) == (frame()->is_used(ecx) ? 1 : 0))
+      && (allocator()->count(edx) == (frame()->is_used(edx) ? 1 : 0))
+      && (allocator()->count(edi) == (frame()->is_used(edi) ? 1 : 0));
+}
+#endif
+
+
+class DeferredReferenceGetKeyedValue: public DeferredCode {
+ public:
+  DeferredReferenceGetKeyedValue(CodeGenerator* generator, bool is_global)
+      : DeferredCode(generator), is_global_(is_global) {
+    set_comment("[ DeferredReferenceGetKeyedValue");
+  }
+
+  virtual void Generate();
+
+  Label* patch_site() { return &patch_site_; }
+
+ private:
+  Label patch_site_;
+  bool is_global_;
+};
+
+
+void DeferredReferenceGetKeyedValue::Generate() {
+  CodeGenerator* cgen = generator();
+  Result receiver(cgen);
+  Result key(cgen);
+  enter()->Bind(&receiver, &key);
+  cgen->frame()->Push(&receiver);  // First IC argument.
+  cgen->frame()->Push(&key);       // Second IC argument.
+
+  // Calculate the delta from the IC call instruction to the map check
+  // cmp instruction in the inlined version.  This delta is stored in
+  // a test(eax, delta) instruction after the call so that we can find
+  // it in the IC initialization code and patch the cmp instruction.
+  // This means that we cannot allow test instructions after calls to
+  // KeyedLoadIC stubs in other places.
+  RelocInfo::Mode mode = is_global_
+                         ? RelocInfo::CODE_TARGET_CONTEXT
+                         : RelocInfo::CODE_TARGET;
+  Result value = cgen->frame()->CallKeyedLoadIC(mode);
+  // The result needs to be specifically the eax register because the
+  // offset to the patch site will be expected in a test eax
+  // instruction.
+  ASSERT(value.is_register() && value.reg().is(eax));
+  // The delta from the start of the map-compare instruction to the
+  // test eax instruction.
+  int delta_to_patch_site = __ SizeOfCodeGeneratedSince(patch_site());
+  __ test(value.reg(), Immediate(-delta_to_patch_site));
+  __ IncrementCounter(&Counters::keyed_load_inline_miss, 1);
+
+  // The receiver and key were spilled by the call, so their state as
+  // constants or copies has been changed.  Thus, they need to be
+  // "mergable" in the block at the exit label and are therefore
+  // passed as return results here.
+  key = cgen->frame()->Pop();
+  receiver = cgen->frame()->Pop();
+  exit_.Jump(&receiver, &key, &value);
+}
+
+
+#undef __
+#define __ masm->
+
+Handle<String> Reference::GetName() {
+  ASSERT(type_ == NAMED);
+  Property* property = expression_->AsProperty();
+  if (property == NULL) {
+    // Global variable reference treated as a named property reference.
+    VariableProxy* proxy = expression_->AsVariableProxy();
+    ASSERT(proxy->AsVariable() != NULL);
+    ASSERT(proxy->AsVariable()->is_global());
+    return proxy->name();
+  } else {
+    Literal* raw_name = property->key()->AsLiteral();
+    ASSERT(raw_name != NULL);
+    return Handle<String>(String::cast(*raw_name->handle()));
+  }
+}
+
+
+void Reference::GetValue(TypeofState typeof_state) {
+  ASSERT(!cgen_->in_spilled_code());
+  ASSERT(cgen_->HasValidEntryRegisters());
+  ASSERT(!is_illegal());
+  MacroAssembler* masm = cgen_->masm();
+  switch (type_) {
+    case SLOT: {
+      Comment cmnt(masm, "[ Load from Slot");
+      Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
+      ASSERT(slot != NULL);
+      cgen_->LoadFromSlot(slot, typeof_state);
+      break;
+    }
+
+    case NAMED: {
+      // TODO(1241834): Make sure that it is safe to ignore the
+      // distinction between expressions in a typeof and not in a
+      // typeof. If there is a chance that reference errors can be
+      // thrown below, we must distinguish between the two kinds of
+      // loads (typeof expression loads must not throw a reference
+      // error).
+      Comment cmnt(masm, "[ Load from named Property");
+      cgen_->frame()->Push(GetName());
+
+      Variable* var = expression_->AsVariableProxy()->AsVariable();
+      ASSERT(var == NULL || var->is_global());
+      RelocInfo::Mode mode = (var == NULL)
+                             ? RelocInfo::CODE_TARGET
+                             : RelocInfo::CODE_TARGET_CONTEXT;
+      Result answer = cgen_->frame()->CallLoadIC(mode);
+      cgen_->frame()->Push(&answer);
+      break;
+    }
+
+    case KEYED: {
+      // TODO(1241834): Make sure that this it is safe to ignore the
+      // distinction between expressions in a typeof and not in a typeof.
+      Comment cmnt(masm, "[ Load from keyed Property");
+      Variable* var = expression_->AsVariableProxy()->AsVariable();
+      bool is_global = var != NULL;
+      ASSERT(!is_global || var->is_global());
+      // Inline array load code if inside of a loop.  We do not know
+      // the receiver map yet, so we initially generate the code with
+      // a check against an invalid map.  In the inline cache code, we
+      // patch the map check if appropriate.
+      if (cgen_->loop_nesting() > 0) {
+        Comment cmnt(masm, "[ Inlined array index load");
+        DeferredReferenceGetKeyedValue* deferred =
+            new DeferredReferenceGetKeyedValue(cgen_, is_global);
+
+        Result key = cgen_->frame()->Pop();
+        Result receiver = cgen_->frame()->Pop();
+        key.ToRegister();
+        receiver.ToRegister();
+
+        // Check that the receiver is not a smi (only needed if this
+        // is not a load from the global context) and that it has the
+        // expected map.
+        if (!is_global) {
+          __ test(receiver.reg(), Immediate(kSmiTagMask));
+          deferred->enter()->Branch(zero, &receiver, &key, not_taken);
+        }
+
+        // Initially, use an invalid map. The map is patched in the IC
+        // initialization code.
+        __ bind(deferred->patch_site());
+        __ cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
+               Immediate(Factory::null_value()));
+        deferred->enter()->Branch(not_equal, &receiver, &key, not_taken);
+
+        // Check that the key is a smi.
+        __ test(key.reg(), Immediate(kSmiTagMask));
+        deferred->enter()->Branch(not_zero, &receiver, &key, not_taken);
+
+        // Get the elements array from the receiver and check that it
+        // is not a dictionary.
+        Result elements = cgen_->allocator()->Allocate();
+        ASSERT(elements.is_valid());
+        __ mov(elements.reg(),
+               FieldOperand(receiver.reg(), JSObject::kElementsOffset));
+        __ cmp(FieldOperand(elements.reg(), HeapObject::kMapOffset),
+               Immediate(Factory::hash_table_map()));
+        deferred->enter()->Branch(equal, &receiver, &key, not_taken);
+
+        // Shift the key to get the actual index value and check that
+        // it is within bounds.
+        Result index = cgen_->allocator()->Allocate();
+        ASSERT(index.is_valid());
+        __ mov(index.reg(), key.reg());
+        __ sar(index.reg(), kSmiTagSize);
+        __ cmp(index.reg(),
+               FieldOperand(elements.reg(), Array::kLengthOffset));
+        deferred->enter()->Branch(above_equal, &receiver, &key, not_taken);
+
+        // Load and check that the result is not the hole.  We could
+        // reuse the index or elements register for the value.
+        //
+        // TODO(206): Consider whether it makes sense to try some
+        // heuristic about which register to reuse.  For example, if
+        // one is eax, the we can reuse that one because the value
+        // coming from the deferred code will be in eax.
+        Result value = index;
+        __ mov(value.reg(), Operand(elements.reg(),
+                                    index.reg(),
+                                    times_4,
+                                    Array::kHeaderSize - kHeapObjectTag));
+        elements.Unuse();
+        index.Unuse();
+        __ cmp(Operand(value.reg()), Immediate(Factory::the_hole_value()));
+        deferred->enter()->Branch(equal, &receiver, &key, not_taken);
+        __ IncrementCounter(&Counters::keyed_load_inline, 1);
+
+        // Restore the receiver and key to the frame and push the
+        // result on top of it.
+        deferred->BindExit(&receiver, &key, &value);
+        cgen_->frame()->Push(&receiver);
+        cgen_->frame()->Push(&key);
+        cgen_->frame()->Push(&value);
+
+      } else {
+        Comment cmnt(masm, "[ Load from keyed Property");
+        RelocInfo::Mode mode = is_global
+                               ? RelocInfo::CODE_TARGET_CONTEXT
+                               : RelocInfo::CODE_TARGET;
+        Result answer = cgen_->frame()->CallKeyedLoadIC(mode);
+        // Make sure that we do not have a test instruction after the
+        // call.  A test instruction after the call is used to
+        // indicate that we have generated an inline version of the
+        // keyed load.  The explicit nop instruction is here because
+        // the push that follows might be peep-hole optimized away.
+        __ nop();
+        cgen_->frame()->Push(&answer);
+      }
+      break;
+    }
+
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void Reference::TakeValue(TypeofState typeof_state) {
+  // For non-constant frame-allocated slots, we invalidate the value in the
+  // slot.  For all others, we fall back on GetValue.
+  ASSERT(!cgen_->in_spilled_code());
+  ASSERT(!is_illegal());
+  if (type_ != SLOT) {
+    GetValue(typeof_state);
+    return;
+  }
+
+  Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
+  ASSERT(slot != NULL);
+  if (slot->type() == Slot::LOOKUP ||
+      slot->type() == Slot::CONTEXT ||
+      slot->var()->mode() == Variable::CONST) {
+    GetValue(typeof_state);
+    return;
+  }
+
+  // Only non-constant, frame-allocated parameters and locals can reach
+  // here.
+  if (slot->type() == Slot::PARAMETER) {
+    cgen_->frame()->TakeParameterAt(slot->index());
+  } else {
+    ASSERT(slot->type() == Slot::LOCAL);
+    cgen_->frame()->TakeLocalAt(slot->index());
+  }
+}
+
+
+void Reference::SetValue(InitState init_state) {
+  ASSERT(cgen_->HasValidEntryRegisters());
+  ASSERT(!is_illegal());
+  switch (type_) {
+    case SLOT: {
+      Comment cmnt(cgen_->masm(), "[ Store to Slot");
+      Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
+      ASSERT(slot != NULL);
+      cgen_->StoreToSlot(slot, init_state);
+      break;
+    }
+
+    case NAMED: {
+      Comment cmnt(cgen_->masm(), "[ Store to named Property");
+      cgen_->frame()->Push(GetName());
+      Result answer = cgen_->frame()->CallStoreIC();
+      cgen_->frame()->Push(&answer);
+      break;
+    }
+
+    case KEYED: {
+      Comment cmnt(cgen_->masm(), "[ Store to keyed Property");
+      Result answer = cgen_->frame()->CallKeyedStoreIC();
+      cgen_->frame()->Push(&answer);
+      break;
+    }
+
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+// NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined).
+void ToBooleanStub::Generate(MacroAssembler* masm) {
+  Label false_result, true_result, not_string;
+  __ mov(eax, Operand(esp, 1 * kPointerSize));
+
+  // 'null' => false.
+  __ cmp(eax, Factory::null_value());
+  __ j(equal, &false_result);
+
+  // Get the map and type of the heap object.
+  __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
+  __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset));
+
+  // Undetectable => false.
+  __ movzx_b(ebx, FieldOperand(edx, Map::kBitFieldOffset));
+  __ and_(ebx, 1 << Map::kIsUndetectable);
+  __ j(not_zero, &false_result);
+
+  // JavaScript object => true.
+  __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
+  __ j(above_equal, &true_result);
+
+  // String value => false iff empty.
+  __ cmp(ecx, FIRST_NONSTRING_TYPE);
+  __ j(above_equal, &not_string);
+  __ and_(ecx, kStringSizeMask);
+  __ cmp(ecx, kShortStringTag);
+  __ j(not_equal, &true_result);  // Empty string is always short.
+  __ mov(edx, FieldOperand(eax, String::kLengthOffset));
+  __ shr(edx, String::kShortLengthShift);
+  __ j(zero, &false_result);
+  __ jmp(&true_result);
+
+  __ bind(&not_string);
+  // HeapNumber => false iff +0, -0, or NaN.
+  __ cmp(edx, Factory::heap_number_map());
+  __ j(not_equal, &true_result);
+  __ fldz();
+  __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
+  __ fucompp();
+  __ push(eax);
+  __ fnstsw_ax();
+  __ sahf();
+  __ pop(eax);
+  __ j(zero, &false_result);
+  // Fall through to |true_result|.
+
+  // Return 1/0 for true/false in eax.
+  __ bind(&true_result);
+  __ mov(eax, 1);
+  __ ret(1 * kPointerSize);
+  __ bind(&false_result);
+  __ mov(eax, 0);
+  __ ret(1 * kPointerSize);
+}
+
+
+#undef __
+#define __ masm_->
+
+Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
+                                                         Result* right) {
+  // Perform fast-case smi code for the operation (left <op> right) and
+  // returns the result in a Result.
+  // If any fast-case tests fail, it jumps to the slow-case deferred code,
+  // which calls the binary operation stub, with the arguments (in registers)
+  // on top of the frame.
+  // Consumes its arguments (sets left and right to invalid and frees their
+  // registers).
+
+  left->ToRegister();
+  right->ToRegister();
+  // A newly allocated register answer is used to hold the answer.
+  // The registers containing left and right are not modified in
+  // most cases, so they usually don't need to be spilled in the fast case.
+  Result answer = generator()->allocator()->Allocate();
+
+  ASSERT(answer.is_valid());
+  // Perform the smi check.
+  if (left->reg().is(right->reg())) {
+    __ test(left->reg(), Immediate(kSmiTagMask));
+  } else {
+    __ mov(answer.reg(), left->reg());
+    __ or_(answer.reg(), Operand(right->reg()));
+    ASSERT(kSmiTag == 0);  // adjust zero check if not the case
+    __ test(answer.reg(), Immediate(kSmiTagMask));
+  }
+  enter()->Branch(not_zero, left, right, not_taken);
+
+  // All operations start by copying the left argument into answer.
+  __ mov(answer.reg(), left->reg());
+  switch (op_) {
+    case Token::ADD:
+      __ add(answer.reg(), Operand(right->reg()));  // add optimistically
+      enter()->Branch(overflow, left, right, not_taken);
+      break;
+
+    case Token::SUB:
+      __ sub(answer.reg(), Operand(right->reg()));  // subtract optimistically
+      enter()->Branch(overflow, left, right, not_taken);
+      break;
+
+    case Token::MUL: {
+      // If the smi tag is 0 we can just leave the tag on one operand.
+      ASSERT(kSmiTag == 0);  // adjust code below if not the case
+      // Remove tag from the left operand (but keep sign).
+      // Left hand operand has been copied into answer.
+      __ sar(answer.reg(), kSmiTagSize);
+      // Do multiplication of smis, leaving result in answer.
+      __ imul(answer.reg(), Operand(right->reg()));
+      // Go slow on overflows.
+      enter()->Branch(overflow, left, right, not_taken);
+      // Check for negative zero result.  If product is zero,
+      // and one argument is negative, go to slow case.
+      // The frame is unchanged in this block, so local control flow can
+      // use a Label rather than a JumpTarget.
+      Label non_zero_result;
+      __ test(answer.reg(), Operand(answer.reg()));
+      __ j(not_zero, &non_zero_result, taken);
+      __ mov(answer.reg(), left->reg());
+      __ or_(answer.reg(), Operand(right->reg()));
+      enter()->Branch(negative, left, right, not_taken);
+      __ xor_(answer.reg(), Operand(answer.reg()));  // Positive 0 is correct.
+      __ bind(&non_zero_result);
+      break;
+    }
+
+    case Token::DIV:  // Fall through.
+    case Token::MOD: {
+      // Div and mod use the registers eax and edx.  Left and right must
+      // be preserved, because the original operands are needed if we switch
+      // to the slow case.  Move them if either is in eax or edx.
+      // The Result answer should be changed into an alias for eax.
+      // Precondition:
+      // The Results left and right are valid.  They may be the same register,
+      // and may be unspilled.  The Result answer is valid and is distinct
+      // from left and right, and is spilled.
+      // The value in left is copied to answer.
+
+      Result reg_eax = generator()->allocator()->Allocate(eax);
+      Result reg_edx = generator()->allocator()->Allocate(edx);
+      // These allocations may have failed, if one of left, right, or answer
+      // is in register eax or edx.
+      bool left_copied_to_eax = false;  // We will make sure this becomes true.
+
+      // Part 1: Get eax
+      if (answer.reg().is(eax)) {
+        reg_eax = answer;
+        left_copied_to_eax = true;
+      } else if (right->reg().is(eax) || left->reg().is(eax)) {
+        // We need a non-edx register to move one or both of left and right to.
+        // We use answer if it is not edx, otherwise we allocate one.
+        if (answer.reg().is(edx)) {
+          reg_edx = answer;
+          answer = generator()->allocator()->Allocate();
+          ASSERT(answer.is_valid());
+        }
+
+        if (left->reg().is(eax)) {
+          reg_eax = *left;
+          left_copied_to_eax = true;
+          *left = answer;
+        }
+        if (right->reg().is(eax)) {
+          reg_eax = *right;
+          *right = answer;
+        }
+        __ mov(answer.reg(), eax);
+      }
+      // End of Part 1.
+      // reg_eax is valid, and neither left nor right is in eax.
+      ASSERT(reg_eax.is_valid());
+      ASSERT(!left->reg().is(eax));
+      ASSERT(!right->reg().is(eax));
+
+      // Part 2: Get edx
+      // reg_edx is invalid if and only if either left, right,
+      // or answer is in edx.  If edx is valid, then either edx
+      // was free, or it was answer, but answer was reallocated.
+      if (answer.reg().is(edx)) {
+        reg_edx = answer;
+      } else if (right->reg().is(edx) || left->reg().is(edx)) {
+        // Is answer used?
+        if (answer.reg().is(eax) || answer.reg().is(left->reg()) ||
+            answer.reg().is(right->reg())) {
+          answer = generator()->allocator()->Allocate();
+          ASSERT(answer.is_valid());  // We cannot hit both Allocate() calls.
+        }
+        if (left->reg().is(edx)) {
+          reg_edx = *left;
+          *left = answer;
+        }
+        if (right->reg().is(edx)) {
+          reg_edx = *right;
+          *right = answer;
+        }
+        __ mov(answer.reg(), edx);
+      }
+      // End of Part 2
+      ASSERT(reg_edx.is_valid());
+      ASSERT(!left->reg().is(eax));
+      ASSERT(!right->reg().is(eax));
+
+      answer = reg_eax;  // May free answer, if it was never used.
+      generator()->frame()->Spill(eax);
+      if (!left_copied_to_eax) {
+        __ mov(eax, left->reg());
+        left_copied_to_eax = true;
+      }
+      generator()->frame()->Spill(edx);
+
+      // Postcondition:
+      // reg_eax, reg_edx are valid, correct, and spilled.
+      // reg_eax contains the value originally in left
+      // left and right are not eax or edx.  They may or may not be
+      // spilled or distinct.
+      // answer is an alias for reg_eax.
+
+      // Sign extend eax into edx:eax.
+      __ cdq();
+      // Check for 0 divisor.
+      __ test(right->reg(), Operand(right->reg()));
+      enter()->Branch(zero, left, right, not_taken);
+      // Divide edx:eax by the right operand.
+      __ idiv(right->reg());
+      if (op_ == Token::DIV) {
+        // Check for negative zero result.  If result is zero, and divisor
+        // is negative, return a floating point negative zero.
+        // The frame is unchanged in this block, so local control flow can
+        // use a Label rather than a JumpTarget.
+        Label non_zero_result;
+        __ test(left->reg(), Operand(left->reg()));
+        __ j(not_zero, &non_zero_result, taken);
+        __ test(right->reg(), Operand(right->reg()));
+        enter()->Branch(negative, left, right, not_taken);
+        __ bind(&non_zero_result);
+        // Check for the corner case of dividing the most negative smi
+        // by -1. We cannot use the overflow flag, since it is not set
+        // by idiv instruction.
+        ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
+        __ cmp(eax, 0x40000000);
+        enter()->Branch(equal, left, right, not_taken);
+        // Check that the remainder is zero.
+        __ test(edx, Operand(edx));
+        enter()->Branch(not_zero, left, right, not_taken);
+        // Tag the result and store it in register temp.
+        ASSERT(kSmiTagSize == times_2);  // adjust code if not the case
+        __ lea(answer.reg(), Operand(eax, eax, times_1, kSmiTag));
+      } else {
+        ASSERT(op_ == Token::MOD);
+        // Check for a negative zero result.  If the result is zero, and the
+        // dividend is negative, return a floating point negative zero.
+        // The frame is unchanged in this block, so local control flow can
+        // use a Label rather than a JumpTarget.
+        Label non_zero_result;
+        __ test(edx, Operand(edx));
+        __ j(not_zero, &non_zero_result, taken);
+        __ test(left->reg(), Operand(left->reg()));
+        enter()->Branch(negative, left, right, not_taken);
+        __ bind(&non_zero_result);
+        // The answer is in edx.
+        answer = reg_edx;
+      }
+      break;
+    }
+    case Token::BIT_OR:
+      __ or_(answer.reg(), Operand(right->reg()));
+      break;
+
+    case Token::BIT_AND:
+      __ and_(answer.reg(), Operand(right->reg()));
+      break;
+
+    case Token::BIT_XOR:
+      __ xor_(answer.reg(), Operand(right->reg()));
+      break;
+
+    case Token::SHL:
+    case Token::SHR:
+    case Token::SAR:
+      // Move right into ecx.
+      // Left is in two registers already, so even if left or answer is ecx,
+      // we can move right to it, and use the other one.
+      // Right operand must be in register cl because x86 likes it that way.
+      if (right->reg().is(ecx)) {
+        // Right is already in the right place.  Left may be in the
+        // same register, which causes problems.  Use answer instead.
+        if (left->reg().is(ecx)) {
+          *left = answer;
+        }
+      } else if (left->reg().is(ecx)) {
+        generator()->frame()->Spill(left->reg());
+        __ mov(left->reg(), right->reg());
+        *right = *left;
+        *left = answer;  // Use copy of left in answer as left.
+      } else if (answer.reg().is(ecx)) {
+        __ mov(answer.reg(), right->reg());
+        *right = answer;
+      } else {
+        Result reg_ecx = generator()->allocator()->Allocate(ecx);
+        ASSERT(reg_ecx.is_valid());
+        __ mov(ecx, right->reg());
+        *right = reg_ecx;
+      }
+      ASSERT(left->reg().is_valid());
+      ASSERT(!left->reg().is(ecx));
+      ASSERT(right->reg().is(ecx));
+      answer.Unuse();  // Answer may now be being used for left or right.
+      // We will modify left and right, which we do not do in any other
+      // binary operation.  The exits to slow code need to restore the
+      // original values of left and right, or at least values that give
+      // the same answer.
+
+      // We are modifying left and right.  They must be spilled!
+      generator()->frame()->Spill(left->reg());
+      generator()->frame()->Spill(right->reg());
+
+      // Remove tags from operands (but keep sign).
+      __ sar(left->reg(), kSmiTagSize);
+      __ sar(ecx, kSmiTagSize);
+      // Perform the operation.
+      switch (op_) {
+        case Token::SAR:
+          __ sar(left->reg());
+          // No checks of result necessary
+          break;
+        case Token::SHR: {
+          __ shr(left->reg());
+          // Check that the *unsigned* result fits in a smi.
+          // Neither of the two high-order bits can be set:
+          // - 0x80000000: high bit would be lost when smi tagging.
+          // - 0x40000000: this number would convert to negative when
+          // Smi tagging these two cases can only happen with shifts
+          // by 0 or 1 when handed a valid smi.
+          // If the answer cannot be represented by a SMI, restore
+          // the left and right arguments, and jump to slow case.
+          // The low bit of the left argument may be lost, but only
+          // in a case where it is dropped anyway.
+          JumpTarget result_ok(generator());
+          __ test(left->reg(), Immediate(0xc0000000));
+          result_ok.Branch(zero, left, taken);
+          __ shl(left->reg());
+          ASSERT(kSmiTag == 0);
+          __ shl(left->reg(), kSmiTagSize);
+          __ shl(right->reg(), kSmiTagSize);
+          enter()->Jump(left, right);
+          result_ok.Bind(left);
+          break;
+        }
+        case Token::SHL: {
+          __ shl(left->reg());
+          // Check that the *signed* result fits in a smi.
+          //
+          // TODO(207): Can reduce registers from 4 to 3 by
+          // preallocating ecx.
+          JumpTarget result_ok(generator());
+          Result smi_test_reg = generator()->allocator()->Allocate();
+          ASSERT(smi_test_reg.is_valid());
+          __ lea(smi_test_reg.reg(), Operand(left->reg(), 0x40000000));
+          __ test(smi_test_reg.reg(), Immediate(0x80000000));
+          smi_test_reg.Unuse();
+          result_ok.Branch(zero, left, taken);
+          __ shr(left->reg());
+          ASSERT(kSmiTag == 0);
+          __ shl(left->reg(), kSmiTagSize);
+          __ shl(right->reg(), kSmiTagSize);
+          enter()->Jump(left, right);
+          result_ok.Bind(left);
+          break;
+        }
+        default:
+          UNREACHABLE();
+      }
+      // Smi-tag the result, in left, and make answer an alias for left->
+      answer = *left;
+      answer.ToRegister();
+      ASSERT(kSmiTagSize == times_2);  // adjust code if not the case
+      __ lea(answer.reg(),
+             Operand(answer.reg(), answer.reg(), times_1, kSmiTag));
+      break;
+
+    default:
+      UNREACHABLE();
+      break;
+  }
+  left->Unuse();
+  right->Unuse();
+  return answer;
+}
+
+
+#undef __
+#define __ masm->
+
+void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) {
+  // Perform fast-case smi code for the operation (eax <op> ebx) and
+  // leave result in register eax.
+
+  // Prepare the smi check of both operands by or'ing them together
+  // before checking against the smi mask.
+  __ mov(ecx, Operand(ebx));
+  __ or_(ecx, Operand(eax));
+
+  switch (op_) {
+    case Token::ADD:
+      __ add(eax, Operand(ebx));  // add optimistically
+      __ j(overflow, slow, not_taken);
+      break;
+
+    case Token::SUB:
+      __ sub(eax, Operand(ebx));  // subtract optimistically
+      __ j(overflow, slow, not_taken);
+      break;
+
+    case Token::DIV:
+    case Token::MOD:
+      // Sign extend eax into edx:eax.
+      __ cdq();
+      // Check for 0 divisor.
+      __ test(ebx, Operand(ebx));
+      __ j(zero, slow, not_taken);
+      break;
+
+    default:
+      // Fall-through to smi check.
+      break;
+  }
+
+  // Perform the actual smi check.
+  ASSERT(kSmiTag == 0);  // adjust zero check if not the case
+  __ test(ecx, Immediate(kSmiTagMask));
+  __ j(not_zero, slow, not_taken);
+
+  switch (op_) {
+    case Token::ADD:
+    case Token::SUB:
+      // Do nothing here.
+      break;
+
+    case Token::MUL:
+      // If the smi tag is 0 we can just leave the tag on one operand.
+      ASSERT(kSmiTag == 0);  // adjust code below if not the case
+      // Remove tag from one of the operands (but keep sign).
+      __ sar(eax, kSmiTagSize);
+      // Do multiplication.
+      __ imul(eax, Operand(ebx));  // multiplication of smis; result in eax
+      // Go slow on overflows.
+      __ j(overflow, slow, not_taken);
+      // Check for negative zero result.
+      __ NegativeZeroTest(eax, ecx, slow);  // use ecx = x | y
+      break;
+
+    case Token::DIV:
+      // Divide edx:eax by ebx.
+      __ idiv(ebx);
+      // Check for the corner case of dividing the most negative smi
+      // by -1. We cannot use the overflow flag, since it is not set
+      // by idiv instruction.
+      ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
+      __ cmp(eax, 0x40000000);
+      __ j(equal, slow);
+      // Check for negative zero result.
+      __ NegativeZeroTest(eax, ecx, slow);  // use ecx = x | y
+      // Check that the remainder is zero.
+      __ test(edx, Operand(edx));
+      __ j(not_zero, slow);
+      // Tag the result and store it in register eax.
+      ASSERT(kSmiTagSize == times_2);  // adjust code if not the case
+      __ lea(eax, Operand(eax, eax, times_1, kSmiTag));
+      break;
+
+    case Token::MOD:
+      // Divide edx:eax by ebx.
+      __ idiv(ebx);
+      // Check for negative zero result.
+      __ NegativeZeroTest(edx, ecx, slow);  // use ecx = x | y
+      // Move remainder to register eax.
+      __ mov(eax, Operand(edx));
+      break;
+
+    case Token::BIT_OR:
+      __ or_(eax, Operand(ebx));
+      break;
+
+    case Token::BIT_AND:
+      __ and_(eax, Operand(ebx));
+      break;
+
+    case Token::BIT_XOR:
+      __ xor_(eax, Operand(ebx));
+      break;
+
+    case Token::SHL:
+    case Token::SHR:
+    case Token::SAR:
+      // Move the second operand into register ecx.
+      __ mov(ecx, Operand(ebx));
+      // Remove tags from operands (but keep sign).
+      __ sar(eax, kSmiTagSize);
+      __ sar(ecx, kSmiTagSize);
+      // Perform the operation.
+      switch (op_) {
+        case Token::SAR:
+          __ sar(eax);
+          // No checks of result necessary
+          break;
+        case Token::SHR:
+          __ shr(eax);
+          // Check that the *unsigned* result fits in a smi.
+          // Neither of the two high-order bits can be set:
+          // - 0x80000000: high bit would be lost when smi tagging.
+          // - 0x40000000: this number would convert to negative when
+          // Smi tagging these two cases can only happen with shifts
+          // by 0 or 1 when handed a valid smi.
+          __ test(eax, Immediate(0xc0000000));
+          __ j(not_zero, slow, not_taken);
+          break;
+        case Token::SHL:
+          __ shl(eax);
+          // Check that the *signed* result fits in a smi.
+          __ cmp(eax, 0xc0000000);
+          __ j(sign, slow, not_taken);
+          break;
+        default:
+          UNREACHABLE();
+      }
+      // Tag the result and store it in register eax.
+      ASSERT(kSmiTagSize == times_2);  // adjust code if not the case
+      __ lea(eax, Operand(eax, eax, times_1, kSmiTag));
+      break;
+
+    default:
+      UNREACHABLE();
+      break;
+  }
+}
+
+
+void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
+  Label call_runtime;
+
+  if (flags_ == SMI_CODE_IN_STUB) {
+    // The fast case smi code wasn't inlined in the stub caller
+    // code. Generate it here to speed up common operations.
+    Label slow;
+    __ mov(ebx, Operand(esp, 1 * kPointerSize));  // get y
+    __ mov(eax, Operand(esp, 2 * kPointerSize));  // get x
+    GenerateSmiCode(masm, &slow);
+    __ ret(2 * kPointerSize);  // remove both operands
+
+    // Too bad. The fast case smi code didn't succeed.
+    __ bind(&slow);
+  }
+
+  // Setup registers.
+  __ mov(eax, Operand(esp, 1 * kPointerSize));  // get y
+  __ mov(edx, Operand(esp, 2 * kPointerSize));  // get x
+
+  // Floating point case.
+  switch (op_) {
+    case Token::ADD:
+    case Token::SUB:
+    case Token::MUL:
+    case Token::DIV: {
+      // eax: y
+      // edx: x
+      FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx);
+      // Fast-case: Both operands are numbers.
+      // Allocate a heap number, if needed.
+      Label skip_allocation;
+      switch (mode_) {
+        case OVERWRITE_LEFT:
+          __ mov(eax, Operand(edx));
+          // Fall through!
+        case OVERWRITE_RIGHT:
+          // If the argument in eax is already an object, we skip the
+          // allocation of a heap number.
+          __ test(eax, Immediate(kSmiTagMask));
+          __ j(not_zero, &skip_allocation, not_taken);
+          // Fall through!
+        case NO_OVERWRITE:
+          FloatingPointHelper::AllocateHeapNumber(masm,
+                                                  &call_runtime,
+                                                  ecx,
+                                                  edx);
+          __ bind(&skip_allocation);
+          break;
+        default: UNREACHABLE();
+      }
+      FloatingPointHelper::LoadFloatOperands(masm, ecx);
+
+      switch (op_) {
+        case Token::ADD: __ faddp(1); break;
+        case Token::SUB: __ fsubp(1); break;
+        case Token::MUL: __ fmulp(1); break;
+        case Token::DIV: __ fdivp(1); break;
+        default: UNREACHABLE();
+      }
+      __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
+      __ ret(2 * kPointerSize);
+    }
+    case Token::MOD: {
+      // For MOD we go directly to runtime in the non-smi case.
+      break;
+    }
+    case Token::BIT_OR:
+    case Token::BIT_AND:
+    case Token::BIT_XOR:
+    case Token::SAR:
+    case Token::SHL:
+    case Token::SHR: {
+      FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx);
+      FloatingPointHelper::LoadFloatOperands(masm, ecx);
+
+      Label skip_allocation, non_smi_result, operand_conversion_failure;
+
+      // Reserve space for converted numbers.
+      __ sub(Operand(esp), Immediate(2 * kPointerSize));
+
+      bool use_sse3 = CpuFeatures::IsSupported(CpuFeatures::SSE3);
+      if (use_sse3) {
+        // Truncate the operands to 32-bit integers and check for
+        // exceptions in doing so.
+         CpuFeatures::Scope scope(CpuFeatures::SSE3);
+        __ fisttp_s(Operand(esp, 0 * kPointerSize));
+        __ fisttp_s(Operand(esp, 1 * kPointerSize));
+        __ fnstsw_ax();
+        __ test(eax, Immediate(1));
+        __ j(not_zero, &operand_conversion_failure);
+      } else {
+        // Check if right operand is int32.
+        __ fist_s(Operand(esp, 0 * kPointerSize));
+        __ fild_s(Operand(esp, 0 * kPointerSize));
+        __ fucompp();
+        __ fnstsw_ax();
+        __ sahf();
+        __ j(not_zero, &operand_conversion_failure);
+        __ j(parity_even, &operand_conversion_failure);
+
+        // Check if left operand is int32.
+        __ fist_s(Operand(esp, 1 * kPointerSize));
+        __ fild_s(Operand(esp, 1 * kPointerSize));
+        __ fucompp();
+        __ fnstsw_ax();
+        __ sahf();
+        __ j(not_zero, &operand_conversion_failure);
+        __ j(parity_even, &operand_conversion_failure);
+      }
+
+      // Get int32 operands and perform bitop.
+      __ pop(ecx);
+      __ pop(eax);
+      switch (op_) {
+        case Token::BIT_OR:  __ or_(eax, Operand(ecx)); break;
+        case Token::BIT_AND: __ and_(eax, Operand(ecx)); break;
+        case Token::BIT_XOR: __ xor_(eax, Operand(ecx)); break;
+        case Token::SAR: __ sar(eax); break;
+        case Token::SHL: __ shl(eax); break;
+        case Token::SHR: __ shr(eax); break;
+        default: UNREACHABLE();
+      }
+
+      // Check if result is non-negative and fits in a smi.
+      __ test(eax, Immediate(0xc0000000));
+      __ j(not_zero, &non_smi_result);
+
+      // Tag smi result and return.
+      ASSERT(kSmiTagSize == times_2);  // adjust code if not the case
+      __ lea(eax, Operand(eax, eax, times_1, kSmiTag));
+      __ ret(2 * kPointerSize);
+
+      // All ops except SHR return a signed int32 that we load in a HeapNumber.
+      if (op_ != Token::SHR) {
+        __ bind(&non_smi_result);
+        // Allocate a heap number if needed.
+        __ mov(ebx, Operand(eax));  // ebx: result
+        switch (mode_) {
+          case OVERWRITE_LEFT:
+          case OVERWRITE_RIGHT:
+            // If the operand was an object, we skip the
+            // allocation of a heap number.
+            __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ?
+                                1 * kPointerSize : 2 * kPointerSize));
+            __ test(eax, Immediate(kSmiTagMask));
+            __ j(not_zero, &skip_allocation, not_taken);
+            // Fall through!
+          case NO_OVERWRITE:
+            FloatingPointHelper::AllocateHeapNumber(masm, &call_runtime,
+                                                    ecx, edx);
+            __ bind(&skip_allocation);
+            break;
+          default: UNREACHABLE();
+        }
+        // Store the result in the HeapNumber and return.
+        __ mov(Operand(esp, 1 * kPointerSize), ebx);
+        __ fild_s(Operand(esp, 1 * kPointerSize));
+        __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
+        __ ret(2 * kPointerSize);
+      }
+
+      // Clear the FPU exception flag and reset the stack before calling
+      // the runtime system.
+      __ bind(&operand_conversion_failure);
+      __ add(Operand(esp), Immediate(2 * kPointerSize));
+      if (use_sse3) {
+        // If we've used the SSE3 instructions for truncating the
+        // floating point values to integers and it failed, we have a
+        // pending #IA exception. Clear it.
+        __ fnclex();
+      } else {
+        // The non-SSE3 variant does early bailout if the right
+        // operand isn't a 32-bit integer, so we may have a single
+        // value on the FPU stack we need to get rid of.
+        __ ffree(0);
+      }
+
+      // SHR should return uint32 - go to runtime for non-smi/negative result.
+      if (op_ == Token::SHR) __ bind(&non_smi_result);
+      __ mov(eax, Operand(esp, 1 * kPointerSize));
+      __ mov(edx, Operand(esp, 2 * kPointerSize));
+      break;
+    }
+    default: UNREACHABLE(); break;
+  }
+
+  // If all else fails, use the runtime system to get the correct
+  // result.
+  __ bind(&call_runtime);
+  switch (op_) {
+    case Token::ADD:
+      __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION);
+      break;
+    case Token::SUB:
+      __ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION);
+      break;
+    case Token::MUL:
+      __ InvokeBuiltin(Builtins::MUL, JUMP_FUNCTION);
+        break;
+    case Token::DIV:
+      __ InvokeBuiltin(Builtins::DIV, JUMP_FUNCTION);
+      break;
+    case Token::MOD:
+      __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION);
+      break;
+    case Token::BIT_OR:
+      __ InvokeBuiltin(Builtins::BIT_OR, JUMP_FUNCTION);
+      break;
+    case Token::BIT_AND:
+      __ InvokeBuiltin(Builtins::BIT_AND, JUMP_FUNCTION);
+      break;
+    case Token::BIT_XOR:
+      __ InvokeBuiltin(Builtins::BIT_XOR, JUMP_FUNCTION);
+      break;
+    case Token::SAR:
+      __ InvokeBuiltin(Builtins::SAR, JUMP_FUNCTION);
+      break;
+    case Token::SHL:
+      __ InvokeBuiltin(Builtins::SHL, JUMP_FUNCTION);
+      break;
+    case Token::SHR:
+      __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION);
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void FloatingPointHelper::AllocateHeapNumber(MacroAssembler* masm,
+                                             Label* need_gc,
+                                             Register scratch1,
+                                             Register scratch2) {
+  ExternalReference allocation_top =
+      ExternalReference::new_space_allocation_top_address();
+  ExternalReference allocation_limit =
+      ExternalReference::new_space_allocation_limit_address();
+  __ mov(Operand(scratch1), Immediate(allocation_top));
+  __ mov(eax, Operand(scratch1, 0));
+  __ lea(scratch2, Operand(eax, HeapNumber::kSize));  // scratch2: new top
+  __ cmp(scratch2, Operand::StaticVariable(allocation_limit));
+  __ j(above, need_gc, not_taken);
+
+  __ mov(Operand(scratch1, 0), scratch2);  // store new top
+  __ mov(Operand(eax, HeapObject::kMapOffset),
+         Immediate(Factory::heap_number_map()));
+  // Tag old top and use as result.
+  __ add(Operand(eax), Immediate(kHeapObjectTag));
+}
+
+
+void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm,
+                                            Register scratch) {
+  Label load_smi_1, load_smi_2, done_load_1, done;
+  __ mov(scratch, Operand(esp, 2 * kPointerSize));
+  __ test(scratch, Immediate(kSmiTagMask));
+  __ j(zero, &load_smi_1, not_taken);
+  __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset));
+  __ bind(&done_load_1);
+
+  __ mov(scratch, Operand(esp, 1 * kPointerSize));
+  __ test(scratch, Immediate(kSmiTagMask));
+  __ j(zero, &load_smi_2, not_taken);
+  __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset));
+  __ jmp(&done);
+
+  __ bind(&load_smi_1);
+  __ sar(scratch, kSmiTagSize);
+  __ push(scratch);
+  __ fild_s(Operand(esp, 0));
+  __ pop(scratch);
+  __ jmp(&done_load_1);
+
+  __ bind(&load_smi_2);
+  __ sar(scratch, kSmiTagSize);
+  __ push(scratch);
+  __ fild_s(Operand(esp, 0));
+  __ pop(scratch);
+
+  __ bind(&done);
+}
+
+
+void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm,
+                                             Label* non_float,
+                                             Register scratch) {
+  Label test_other, done;
+  // Test if both operands are floats or smi -> scratch=k_is_float;
+  // Otherwise scratch = k_not_float.
+  __ test(edx, Immediate(kSmiTagMask));
+  __ j(zero, &test_other, not_taken);  // argument in edx is OK
+  __ mov(scratch, FieldOperand(edx, HeapObject::kMapOffset));
+  __ cmp(scratch, Factory::heap_number_map());
+  __ j(not_equal, non_float);  // argument in edx is not a number -> NaN
+
+  __ bind(&test_other);
+  __ test(eax, Immediate(kSmiTagMask));
+  __ j(zero, &done);  // argument in eax is OK
+  __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset));
+  __ cmp(scratch, Factory::heap_number_map());
+  __ j(not_equal, non_float);  // argument in eax is not a number -> NaN
+
+  // Fall-through: Both operands are numbers.
+  __ bind(&done);
+}
+
+
+void UnarySubStub::Generate(MacroAssembler* masm) {
+  Label undo;
+  Label slow;
+  Label done;
+  Label try_float;
+
+  // Check whether the value is a smi.
+  __ test(eax, Immediate(kSmiTagMask));
+  __ j(not_zero, &try_float, not_taken);
+
+  // Enter runtime system if the value of the expression is zero
+  // to make sure that we switch between 0 and -0.
+  __ test(eax, Operand(eax));
+  __ j(zero, &slow, not_taken);
+
+  // The value of the expression is a smi that is not zero.  Try
+  // optimistic subtraction '0 - value'.
+  __ mov(edx, Operand(eax));
+  __ Set(eax, Immediate(0));
+  __ sub(eax, Operand(edx));
+  __ j(overflow, &undo, not_taken);
+
+  // If result is a smi we are done.
+  __ test(eax, Immediate(kSmiTagMask));
+  __ j(zero, &done, taken);
+
+  // Restore eax and enter runtime system.
+  __ bind(&undo);
+  __ mov(eax, Operand(edx));
+
+  // Enter runtime system.
+  __ bind(&slow);
+  __ pop(ecx);  // pop return address
+  __ push(eax);
+  __ push(ecx);  // push return address
+  __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION);
+
+  // Try floating point case.
+  __ bind(&try_float);
+  __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
+  __ cmp(edx, Factory::heap_number_map());
+  __ j(not_equal, &slow);
+  __ mov(edx, Operand(eax));
+  // edx: operand
+  FloatingPointHelper::AllocateHeapNumber(masm, &undo, ebx, ecx);
+  // eax: allocated 'empty' number
+  __ fld_d(FieldOperand(edx, HeapNumber::kValueOffset));
+  __ fchs();
+  __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
+
+  __ bind(&done);
+
+  __ StubReturn(1);
+}
+
+
+void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) {
+  // Check if the calling frame is an arguments adaptor frame.
+  Label adaptor;
+  __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
+  __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
+  __ cmp(ecx, ArgumentsAdaptorFrame::SENTINEL);
+  __ j(equal, &adaptor);
+
+  // Nothing to do: The formal number of parameters has already been
+  // passed in register eax by calling function. Just return it.
+  __ ret(0);
+
+  // Arguments adaptor case: Read the arguments length from the
+  // adaptor frame and return it.
+  __ bind(&adaptor);
+  __ mov(eax, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
+  __ ret(0);
+}
+
+
+void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
+  // The key is in edx and the parameter count is in eax.
+
+  // The displacement is used for skipping the frame pointer on the
+  // stack. It is the offset of the last parameter (if any) relative
+  // to the frame pointer.
+  static const int kDisplacement = 1 * kPointerSize;
+
+  // Check that the key is a smi.
+  Label slow;
+  __ test(edx, Immediate(kSmiTagMask));
+  __ j(not_zero, &slow, not_taken);
+
+  // Check if the calling frame is an arguments adaptor frame.
+  Label adaptor;
+  __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
+  __ mov(ecx, Operand(ebx, StandardFrameConstants::kContextOffset));
+  __ cmp(ecx, ArgumentsAdaptorFrame::SENTINEL);
+  __ j(equal, &adaptor);
+
+  // Check index against formal parameters count limit passed in
+  // through register eax. Use unsigned comparison to get negative
+  // check for free.
+  __ cmp(edx, Operand(eax));
+  __ j(above_equal, &slow, not_taken);
+
+  // Read the argument from the stack and return it.
+  ASSERT(kSmiTagSize == 1 && kSmiTag == 0);  // shifting code depends on this
+  __ lea(ebx, Operand(ebp, eax, times_2, 0));
+  __ neg(edx);
+  __ mov(eax, Operand(ebx, edx, times_2, kDisplacement));
+  __ ret(0);
+
+  // Arguments adaptor case: Check index against actual arguments
+  // limit found in the arguments adaptor frame. Use unsigned
+  // comparison to get negative check for free.
+  __ bind(&adaptor);
+  __ mov(ecx, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
+  __ cmp(edx, Operand(ecx));
+  __ j(above_equal, &slow, not_taken);
+
+  // Read the argument from the stack and return it.
+  ASSERT(kSmiTagSize == 1 && kSmiTag == 0);  // shifting code depends on this
+  __ lea(ebx, Operand(ebx, ecx, times_2, 0));
+  __ neg(edx);
+  __ mov(eax, Operand(ebx, edx, times_2, kDisplacement));
+  __ ret(0);
+
+  // Slow-case: Handle non-smi or out-of-bounds access to arguments
+  // by calling the runtime system.
+  __ bind(&slow);
+  __ pop(ebx);  // Return address.
+  __ push(edx);
+  __ push(ebx);
+  __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1);
+}
+
+
+void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) {
+  // The displacement is used for skipping the return address and the
+  // frame pointer on the stack. It is the offset of the last
+  // parameter (if any) relative to the frame pointer.
+  static const int kDisplacement = 2 * kPointerSize;
+
+  // Check if the calling frame is an arguments adaptor frame.
+  Label runtime;
+  __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
+  __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
+  __ cmp(ecx, ArgumentsAdaptorFrame::SENTINEL);
+  __ j(not_equal, &runtime);
+
+  // Patch the arguments.length and the parameters pointer.
+  __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
+  __ mov(Operand(esp, 1 * kPointerSize), ecx);
+  __ lea(edx, Operand(edx, ecx, times_2, kDisplacement));
+  __ mov(Operand(esp, 2 * kPointerSize), edx);
+
+  // Do the runtime call to allocate the arguments object.
+  __ bind(&runtime);
+  __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3);
+}
+
+
+void CompareStub::Generate(MacroAssembler* masm) {
+  Label call_builtin, done;
+
+  // NOTICE! This code is only reached after a smi-fast-case check, so
+  // it is certain that at least one operand isn't a smi.
+
+  if (cc_ == equal) {  // Both strict and non-strict.
+    Label slow;  // Fallthrough label.
+    // Equality is almost reflexive (everything but NaN), so start by testing
+    // for "identity and not NaN".
+    {
+      Label not_identical;
+      __ cmp(eax, Operand(edx));
+      __ j(not_equal, &not_identical);
+      // Test for NaN. Sadly, we can't just compare to Factory::nan_value(),
+      // so we do the second best thing - test it ourselves.
+
+      Label return_equal;
+      Label heap_number;
+      // If it's not a heap number, then return equal.
+      __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
+             Immediate(Factory::heap_number_map()));
+      __ j(equal, &heap_number);
+      __ bind(&return_equal);
+      __ Set(eax, Immediate(0));
+      __ ret(0);
+
+      __ bind(&heap_number);
+      // It is a heap number, so return non-equal if it's NaN and equal if it's
+      // not NaN.
+      // The representation of NaN values has all exponent bits (52..62) set,
+      // and not all mantissa bits (0..51) clear.
+      // Read top bits of double representation (second word of value).
+      __ mov(eax, FieldOperand(edx, HeapNumber::kValueOffset + kPointerSize));
+      // Test that exponent bits are all set.
+      __ not_(eax);
+      __ test(eax, Immediate(0x7ff00000));
+      __ j(not_zero, &return_equal);
+      __ not_(eax);
+
+      // Shift out flag and all exponent bits, retaining only mantissa.
+      __ shl(eax, 12);
+      // Or with all low-bits of mantissa.
+      __ or_(eax, FieldOperand(edx, HeapNumber::kValueOffset));
+      // Return zero equal if all bits in mantissa is zero (it's an Infinity)
+      // and non-zero if not (it's a NaN).
+      __ ret(0);
+
+      __ bind(&not_identical);
+    }
+
+    // If we're doing a strict equality comparison, we don't have to do
+    // type conversion, so we generate code to do fast comparison for objects
+    // and oddballs. Non-smi numbers and strings still go through the usual
+    // slow-case code.
+    if (strict_) {
+      // If either is a Smi (we know that not both are), then they can only
+      // be equal if the other is a HeapNumber. If so, use the slow case.
+      {
+        Label not_smis;
+        ASSERT_EQ(0, kSmiTag);
+        ASSERT_EQ(0, Smi::FromInt(0));
+        __ mov(ecx, Immediate(kSmiTagMask));
+        __ and_(ecx, Operand(eax));
+        __ test(ecx, Operand(edx));
+        __ j(not_zero, &not_smis);
+        // One operand is a smi.
+
+        // Check whether the non-smi is a heap number.
+        ASSERT_EQ(1, kSmiTagMask);
+        // ecx still holds eax & kSmiTag, which is either zero or one.
+        __ sub(Operand(ecx), Immediate(0x01));
+        __ mov(ebx, edx);
+        __ xor_(ebx, Operand(eax));
+        __ and_(ebx, Operand(ecx));  // ebx holds either 0 or eax ^ edx.
+        __ xor_(ebx, Operand(eax));
+        // if eax was smi, ebx is now edx, else eax.
+
+        // Check if the non-smi operand is a heap number.
+        __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
+               Immediate(Factory::heap_number_map()));
+        // If heap number, handle it in the slow case.
+        __ j(equal, &slow);
+        // Return non-equal (ebx is not zero)
+        __ mov(eax, ebx);
+        __ ret(0);
+
+        __ bind(&not_smis);
+      }
+
+      // If either operand is a JSObject or an oddball value, then they are not
+      // equal since their pointers are different
+      // There is no test for undetectability in strict equality.
+
+      // Get the type of the first operand.
+      __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
+      __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
+
+      // If the first object is a JS object, we have done pointer comparison.
+      ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
+      Label first_non_object;
+      __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
+      __ j(less, &first_non_object);
+
+      // Return non-zero (eax is not zero)
+      Label return_not_equal;
+      ASSERT(kHeapObjectTag != 0);
+      __ bind(&return_not_equal);
+      __ ret(0);
+
+      __ bind(&first_non_object);
+      // Check for oddballs: true, false, null, undefined.
+      __ cmp(ecx, ODDBALL_TYPE);
+      __ j(equal, &return_not_equal);
+
+      __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
+      __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
+
+      __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
+      __ j(greater_equal, &return_not_equal);
+
+      // Check for oddballs: true, false, null, undefined.
+      __ cmp(ecx, ODDBALL_TYPE);
+      __ j(equal, &return_not_equal);
+
+      // Fall through to the general case.
+    }
+    __ bind(&slow);
+  }
+
+  // Save the return address (and get it off the stack).
+  __ pop(ecx);
+
+  // Push arguments.
+  __ push(eax);
+  __ push(edx);
+  __ push(ecx);
+
+  // Inlined floating point compare.
+  // Call builtin if operands are not floating point or smi.
+  FloatingPointHelper::CheckFloatOperands(masm, &call_builtin, ebx);
+  FloatingPointHelper::LoadFloatOperands(masm, ecx);
+  __ FCmp();
+
+  // Jump to builtin for NaN.
+  __ j(parity_even, &call_builtin, not_taken);
+
+  // TODO(1243847): Use cmov below once CpuFeatures are properly hooked up.
+  Label below_lbl, above_lbl;
+  // use edx, eax to convert unsigned to signed comparison
+  __ j(below, &below_lbl, not_taken);
+  __ j(above, &above_lbl, not_taken);
+
+  __ xor_(eax, Operand(eax));  // equal
+  __ ret(2 * kPointerSize);
+
+  __ bind(&below_lbl);
+  __ mov(eax, -1);
+  __ ret(2 * kPointerSize);
+
+  __ bind(&above_lbl);
+  __ mov(eax, 1);
+  __ ret(2 * kPointerSize);  // eax, edx were pushed
+
+  __ bind(&call_builtin);
+  // must swap argument order
+  __ pop(ecx);
+  __ pop(edx);
+  __ pop(eax);
+  __ push(edx);
+  __ push(eax);
+
+  // Figure out which native to call and setup the arguments.
+  Builtins::JavaScript builtin;
+  if (cc_ == equal) {
+    builtin = strict_ ? Builtins::STRICT_EQUALS : Builtins::EQUALS;
+  } else {
+    builtin = Builtins::COMPARE;
+    int ncr;  // NaN compare result
+    if (cc_ == less || cc_ == less_equal) {
+      ncr = GREATER;
+    } else {
+      ASSERT(cc_ == greater || cc_ == greater_equal);  // remaining cases
+      ncr = LESS;
+    }
+    __ push(Immediate(Smi::FromInt(ncr)));
+  }
+
+  // Restore return address on the stack.
+  __ push(ecx);
+
+  // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
+  // tagged as a small integer.
+  __ InvokeBuiltin(builtin, JUMP_FUNCTION);
+}
+
+
+void StackCheckStub::Generate(MacroAssembler* masm) {
+  // Because builtins always remove the receiver from the stack, we
+  // have to fake one to avoid underflowing the stack. The receiver
+  // must be inserted below the return address on the stack so we
+  // temporarily store that in a register.
+  __ pop(eax);
+  __ push(Immediate(Smi::FromInt(0)));
+  __ push(eax);
+
+  // Do tail-call to runtime routine.
+  __ TailCallRuntime(ExternalReference(Runtime::kStackGuard), 1);
+}
+
+
+void CallFunctionStub::Generate(MacroAssembler* masm) {
+  Label slow;
+
+  // Get the function to call from the stack.
+  // +2 ~ receiver, return address
+  __ mov(edi, Operand(esp, (argc_ + 2) * kPointerSize));
+
+  // Check that the function really is a JavaScript function.
+  __ test(edi, Immediate(kSmiTagMask));
+  __ j(zero, &slow, not_taken);
+  // Goto slow case if we do not have a function.
+  __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
+  __ j(not_equal, &slow, not_taken);
+
+  // Fast-case: Just invoke the function.
+  ParameterCount actual(argc_);
+  __ InvokeFunction(edi, actual, JUMP_FUNCTION);
+
+  // Slow-case: Non-function called.
+  __ bind(&slow);
+  __ Set(eax, Immediate(argc_));
+  __ Set(ebx, Immediate(0));
+  __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
+  Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
+  __ jmp(adaptor, RelocInfo::CODE_TARGET);
+}
+
+
+
+void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
+  ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize);  // adjust this code
+  ExternalReference handler_address(Top::k_handler_address);
+  __ mov(edx, Operand::StaticVariable(handler_address));
+  __ mov(ecx, Operand(edx, -1 * kPointerSize));  // get next in chain
+  __ mov(Operand::StaticVariable(handler_address), ecx);
+  __ mov(esp, Operand(edx));
+  __ pop(edi);
+  __ pop(ebp);
+  __ pop(edx);  // remove code pointer
+  __ pop(edx);  // remove state
+
+  // Before returning we restore the context from the frame pointer if not NULL.
+  // The frame pointer is NULL in the exception handler of a JS entry frame.
+  __ xor_(esi, Operand(esi));  // tentatively set context pointer to NULL
+  Label skip;
+  __ cmp(ebp, 0);
+  __ j(equal, &skip, not_taken);
+  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+  __ bind(&skip);
+
+  __ ret(0);
+}
+
+
+void CEntryStub::GenerateCore(MacroAssembler* masm,
+                              Label* throw_normal_exception,
+                              Label* throw_out_of_memory_exception,
+                              StackFrame::Type frame_type,
+                              bool do_gc,
+                              bool always_allocate_scope) {
+  // eax: result parameter for PerformGC, if any
+  // ebx: pointer to C function  (C callee-saved)
+  // ebp: frame pointer  (restored after C call)
+  // esp: stack pointer  (restored after C call)
+  // edi: number of arguments including receiver  (C callee-saved)
+  // esi: pointer to the first argument (C callee-saved)
+
+  if (do_gc) {
+    __ mov(Operand(esp, 0 * kPointerSize), eax);  // Result.
+    __ call(FUNCTION_ADDR(Runtime::PerformGC), RelocInfo::RUNTIME_ENTRY);
+  }
+
+  ExternalReference scope_depth =
+      ExternalReference::heap_always_allocate_scope_depth();
+  if (always_allocate_scope) {
+    __ inc(Operand::StaticVariable(scope_depth));
+  }
+
+  // Call C function.
+  __ mov(Operand(esp, 0 * kPointerSize), edi);  // argc.
+  __ mov(Operand(esp, 1 * kPointerSize), esi);  // argv.
+  __ call(Operand(ebx));
+  // Result is in eax or edx:eax - do not destroy these registers!
+
+  if (always_allocate_scope) {
+    __ dec(Operand::StaticVariable(scope_depth));
+  }
+
+  // Check for failure result.
+  Label failure_returned;
+  ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
+  __ lea(ecx, Operand(eax, 1));
+  // Lower 2 bits of ecx are 0 iff eax has failure tag.
+  __ test(ecx, Immediate(kFailureTagMask));
+  __ j(zero, &failure_returned, not_taken);
+
+  // Exit the JavaScript to C++ exit frame.
+  __ LeaveExitFrame(frame_type);
+  __ ret(0);
+
+  // Handling of failure.
+  __ bind(&failure_returned);
+
+  Label retry;
+  // If the returned exception is RETRY_AFTER_GC continue at retry label
+  ASSERT(Failure::RETRY_AFTER_GC == 0);
+  __ test(eax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
+  __ j(zero, &retry, taken);
+
+  Label continue_exception;
+  // If the returned failure is EXCEPTION then promote Top::pending_exception().
+  __ cmp(eax, reinterpret_cast<int32_t>(Failure::Exception()));
+  __ j(not_equal, &continue_exception);
+
+  // Retrieve the pending exception and clear the variable.
+  ExternalReference pending_exception_address(Top::k_pending_exception_address);
+  __ mov(eax, Operand::StaticVariable(pending_exception_address));
+  __ mov(edx,
+         Operand::StaticVariable(ExternalReference::the_hole_value_location()));
+  __ mov(Operand::StaticVariable(pending_exception_address), edx);
+
+  __ bind(&continue_exception);
+  // Special handling of out of memory exception.
+  __ cmp(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException()));
+  __ j(equal, throw_out_of_memory_exception);
+
+  // Handle normal exception.
+  __ jmp(throw_normal_exception);
+
+  // Retry.
+  __ bind(&retry);
+}
+
+
+void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) {
+  // Fetch top stack handler.
+  ExternalReference handler_address(Top::k_handler_address);
+  __ mov(edx, Operand::StaticVariable(handler_address));
+
+  // Unwind the handlers until the ENTRY handler is found.
+  Label loop, done;
+  __ bind(&loop);
+  // Load the type of the current stack handler.
+  const int kStateOffset = StackHandlerConstants::kAddressDisplacement +
+      StackHandlerConstants::kStateOffset;
+  __ cmp(Operand(edx, kStateOffset), Immediate(StackHandler::ENTRY));
+  __ j(equal, &done);
+  // Fetch the next handler in the list.
+  const int kNextOffset = StackHandlerConstants::kAddressDisplacement +
+      StackHandlerConstants::kNextOffset;
+  __ mov(edx, Operand(edx, kNextOffset));
+  __ jmp(&loop);
+  __ bind(&done);
+
+  // Set the top handler address to next handler past the current ENTRY handler.
+  __ mov(eax, Operand(edx, kNextOffset));
+  __ mov(Operand::StaticVariable(handler_address), eax);
+
+  // Set external caught exception to false.
+  __ mov(eax, false);
+  ExternalReference external_caught(Top::k_external_caught_exception_address);
+  __ mov(Operand::StaticVariable(external_caught), eax);
+
+  // Set pending exception and eax to out of memory exception.
+  __ mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException()));
+  ExternalReference pending_exception(Top::k_pending_exception_address);
+  __ mov(Operand::StaticVariable(pending_exception), eax);
+
+  // Restore the stack to the address of the ENTRY handler
+  __ mov(esp, Operand(edx));
+
+  // Clear the context pointer;
+  __ xor_(esi, Operand(esi));
+
+  // Restore registers from handler.
+  __ pop(edi);  // PP
+  __ pop(ebp);  // FP
+  __ pop(edx);  // Code
+  __ pop(edx);  // State
+
+  __ ret(0);
+}
+
+
+void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
+  // eax: number of arguments including receiver
+  // ebx: pointer to C function  (C callee-saved)
+  // ebp: frame pointer  (restored after C call)
+  // esp: stack pointer  (restored after C call)
+  // esi: current context (C callee-saved)
+  // edi: caller's parameter pointer pp  (C callee-saved)
+
+  // NOTE: Invocations of builtins may return failure objects
+  // instead of a proper result. The builtin entry handles
+  // this by performing a garbage collection and retrying the
+  // builtin once.
+
+  StackFrame::Type frame_type = is_debug_break ?
+      StackFrame::EXIT_DEBUG :
+      StackFrame::EXIT;
+
+  // Enter the exit frame that transitions from JavaScript to C++.
+  __ EnterExitFrame(frame_type);
+
+  // eax: result parameter for PerformGC, if any (setup below)
+  // ebx: pointer to builtin function  (C callee-saved)
+  // ebp: frame pointer  (restored after C call)
+  // esp: stack pointer  (restored after C call)
+  // edi: number of arguments including receiver (C callee-saved)
+  // esi: argv pointer (C callee-saved)
+
+  Label throw_out_of_memory_exception;
+  Label throw_normal_exception;
+
+  // Call into the runtime system. Collect garbage before the call if
+  // running with --gc-greedy set.
+  if (FLAG_gc_greedy) {
+    Failure* failure = Failure::RetryAfterGC(0);
+    __ mov(eax, Immediate(reinterpret_cast<int32_t>(failure)));
+  }
+  GenerateCore(masm, &throw_normal_exception,
+               &throw_out_of_memory_exception,
+               frame_type,
+               FLAG_gc_greedy,
+               false);
+
+  // Do space-specific GC and retry runtime call.
+  GenerateCore(masm,
+               &throw_normal_exception,
+               &throw_out_of_memory_exception,
+               frame_type,
+               true,
+               false);
+
+  // Do full GC and retry runtime call one final time.
+  Failure* failure = Failure::InternalError();
+  __ mov(eax, Immediate(reinterpret_cast<int32_t>(failure)));
+  GenerateCore(masm,
+               &throw_normal_exception,
+               &throw_out_of_memory_exception,
+               frame_type,
+               true,
+               true);
+
+  __ bind(&throw_out_of_memory_exception);
+  GenerateThrowOutOfMemory(masm);
+  // control flow for generated will not return.
+
+  __ bind(&throw_normal_exception);
+  GenerateThrowTOS(masm);
+}
+
+
+void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
+  Label invoke, exit;
+
+  // Setup frame.
+  __ push(ebp);
+  __ mov(ebp, Operand(esp));
+
+  // Save callee-saved registers (C calling conventions).
+  int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
+  // Push something that is not an arguments adaptor.
+  __ push(Immediate(~ArgumentsAdaptorFrame::SENTINEL));
+  __ push(Immediate(Smi::FromInt(marker)));  // @ function offset
+  __ push(edi);
+  __ push(esi);
+  __ push(ebx);
+
+  // Save copies of the top frame descriptor on the stack.
+  ExternalReference c_entry_fp(Top::k_c_entry_fp_address);
+  __ push(Operand::StaticVariable(c_entry_fp));
+
+  // Call a faked try-block that does the invoke.
+  __ call(&invoke);
+
+  // Caught exception: Store result (exception) in the pending
+  // exception field in the JSEnv and return a failure sentinel.
+  ExternalReference pending_exception(Top::k_pending_exception_address);
+  __ mov(Operand::StaticVariable(pending_exception), eax);
+  __ mov(eax, reinterpret_cast<int32_t>(Failure::Exception()));
+  __ jmp(&exit);
+
+  // Invoke: Link this frame into the handler chain.
+  __ bind(&invoke);
+  __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER);
+  __ push(eax);  // flush TOS
+
+  // Clear any pending exceptions.
+  __ mov(edx,
+         Operand::StaticVariable(ExternalReference::the_hole_value_location()));
+  __ mov(Operand::StaticVariable(pending_exception), edx);
+
+  // Fake a receiver (NULL).
+  __ push(Immediate(0));  // receiver
+
+  // Invoke the function by calling through JS entry trampoline
+  // builtin and pop the faked function when we return. Notice that we
+  // cannot store a reference to the trampoline code directly in this
+  // stub, because the builtin stubs may not have been generated yet.
+  if (is_construct) {
+    ExternalReference construct_entry(Builtins::JSConstructEntryTrampoline);
+    __ mov(edx, Immediate(construct_entry));
+  } else {
+    ExternalReference entry(Builtins::JSEntryTrampoline);
+    __ mov(edx, Immediate(entry));
+  }
+  __ mov(edx, Operand(edx, 0));  // deref address
+  __ lea(edx, FieldOperand(edx, Code::kHeaderSize));
+  __ call(Operand(edx));
+
+  // Unlink this frame from the handler chain.
+  __ pop(Operand::StaticVariable(ExternalReference(Top::k_handler_address)));
+  // Pop next_sp.
+  __ add(Operand(esp), Immediate(StackHandlerConstants::kSize - kPointerSize));
+
+  // Restore the top frame descriptor from the stack.
+  __ bind(&exit);
+  __ pop(Operand::StaticVariable(ExternalReference(Top::k_c_entry_fp_address)));
+
+  // Restore callee-saved registers (C calling conventions).
+  __ pop(ebx);
+  __ pop(esi);
+  __ pop(edi);
+  __ add(Operand(esp), Immediate(2 * kPointerSize));  // remove markers
+
+  // Restore frame pointer and return.
+  __ pop(ebp);
+  __ ret(0);
+}
+
+
+void InstanceofStub::Generate(MacroAssembler* masm) {
+  // Get the object - go slow case if it's a smi.
+  Label slow;
+  __ mov(eax, Operand(esp, 2 * kPointerSize));  // 2 ~ return address, function
+  __ test(eax, Immediate(kSmiTagMask));
+  __ j(zero, &slow, not_taken);
+
+  // Check that the left hand is a JS object.
+  __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));  // ebx - object map
+  __ movzx_b(ecx, FieldOperand(eax, Map::kInstanceTypeOffset));  // ecx - type
+  __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
+  __ j(less, &slow, not_taken);
+  __ cmp(ecx, LAST_JS_OBJECT_TYPE);
+  __ j(greater, &slow, not_taken);
+
+  // Get the prototype of the function.
+  __ mov(edx, Operand(esp, 1 * kPointerSize));  // 1 ~ return address
+  __ TryGetFunctionPrototype(edx, ebx, ecx, &slow);
+
+  // Check that the function prototype is a JS object.
+  __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset));
+  __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
+  __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
+  __ j(less, &slow, not_taken);
+  __ cmp(ecx, LAST_JS_OBJECT_TYPE);
+  __ j(greater, &slow, not_taken);
+
+  // Register mapping: eax is object map and ebx is function prototype.
+  __ mov(ecx, FieldOperand(eax, Map::kPrototypeOffset));
+
+  // Loop through the prototype chain looking for the function prototype.
+  Label loop, is_instance, is_not_instance;
+  __ bind(&loop);
+  __ cmp(ecx, Operand(ebx));
+  __ j(equal, &is_instance);
+  __ cmp(Operand(ecx), Immediate(Factory::null_value()));
+  __ j(equal, &is_not_instance);
+  __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset));
+  __ mov(ecx, FieldOperand(ecx, Map::kPrototypeOffset));
+  __ jmp(&loop);
+
+  __ bind(&is_instance);
+  __ Set(eax, Immediate(0));
+  __ ret(2 * kPointerSize);
+
+  __ bind(&is_not_instance);
+  __ Set(eax, Immediate(Smi::FromInt(1)));
+  __ ret(2 * kPointerSize);
+
+  // Slow-case: Go through the JavaScript implementation.
+  __ bind(&slow);
+  __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
+}
+
+
+#undef __
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/codegen-ia32.h b/deps/v8/src/codegen-ia32.h
new file mode 100644
index 0000000..24a57a0
--- /dev/null
+++ b/deps/v8/src/codegen-ia32.h
@@ -0,0 +1,621 @@
+// 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_CODEGEN_IA32_H_
+#define V8_CODEGEN_IA32_H_
+
+namespace v8 { namespace internal {
+
+// Forward declarations
+class DeferredCode;
+class RegisterAllocator;
+class RegisterFile;
+
+// Mode to overwrite BinaryExpression values.
+enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
+
+enum InitState { CONST_INIT, NOT_CONST_INIT };
+enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
+
+
+// -------------------------------------------------------------------------
+// Reference support
+
+// A reference is a C++ stack-allocated object that keeps an ECMA
+// reference on the execution stack while in scope. For variables
+// the reference is empty, indicating that it isn't necessary to
+// store state on the stack for keeping track of references to those.
+// For properties, we keep either one (named) or two (indexed) values
+// on the execution stack to represent the reference.
+
+class Reference BASE_EMBEDDED {
+ public:
+  // The values of the types is important, see size().
+  enum Type { ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 };
+  Reference(CodeGenerator* cgen, Expression* expression);
+  ~Reference();
+
+  Expression* expression() const { return expression_; }
+  Type type() const { return type_; }
+  void set_type(Type value) {
+    ASSERT(type_ == ILLEGAL);
+    type_ = value;
+  }
+
+  // The size the reference takes up on the stack.
+  int size() const { return (type_ == ILLEGAL) ? 0 : type_; }
+
+  bool is_illegal() const { return type_ == ILLEGAL; }
+  bool is_slot() const { return type_ == SLOT; }
+  bool is_property() const { return type_ == NAMED || type_ == KEYED; }
+
+  // Return the name.  Only valid for named property references.
+  Handle<String> GetName();
+
+  // Generate code to push the value of the reference on top of the
+  // expression stack.  The reference is expected to be already on top of
+  // the expression stack, and it is left in place with its value above it.
+  void GetValue(TypeofState typeof_state);
+
+  // Like GetValue except that the slot is expected to be written to before
+  // being read from again.  Thae value of the reference may be invalidated,
+  // causing subsequent attempts to read it to fail.
+  void TakeValue(TypeofState typeof_state);
+
+  // Generate code to store the value on top of the expression stack in the
+  // reference.  The reference is expected to be immediately below the value
+  // on the expression stack.  The stored value is left in place (with the
+  // reference intact below it) to support chained assignments.
+  void SetValue(InitState init_state);
+
+ private:
+  CodeGenerator* cgen_;
+  Expression* expression_;
+  Type type_;
+};
+
+
+// -------------------------------------------------------------------------
+// Control destinations.
+
+// A control destination encapsulates a pair of jump targets and a
+// flag indicating which one is the preferred fall-through.  The
+// preferred fall-through must be unbound, the other may be already
+// bound (ie, a backward target).
+//
+// The true and false targets may be jumped to unconditionally or
+// control may split conditionally.  Unconditional jumping and
+// splitting should be emitted in tail position (as the last thing
+// when compiling an expression) because they can cause either label
+// to be bound or the non-fall through to be jumped to leaving an
+// invalid virtual frame.
+//
+// The labels in the control destination can be extracted and
+// manipulated normally without affecting the state of the
+// destination.
+
+class ControlDestination BASE_EMBEDDED {
+ public:
+  ControlDestination(JumpTarget* true_target,
+                     JumpTarget* false_target,
+                     bool true_is_fall_through)
+      : true_target_(true_target),
+        false_target_(false_target),
+        true_is_fall_through_(true_is_fall_through),
+        is_used_(false) {
+    ASSERT(true_is_fall_through ? !true_target->is_bound()
+                                : !false_target->is_bound());
+  }
+
+  // Accessors for the jump targets.  Directly jumping or branching to
+  // or binding the targets will not update the destination's state.
+  JumpTarget* true_target() const { return true_target_; }
+  JumpTarget* false_target() const { return false_target_; }
+
+  // True if the the destination has been jumped to unconditionally or
+  // control has been split to both targets.  This predicate does not
+  // test whether the targets have been extracted and manipulated as
+  // raw jump targets.
+  bool is_used() const { return is_used_; }
+
+  // True if the destination is used and the true target (respectively
+  // false target) was the fall through.  If the target is backward,
+  // "fall through" included jumping unconditionally to it.
+  bool true_was_fall_through() const {
+    return is_used_ && true_is_fall_through_;
+  }
+
+  bool false_was_fall_through() const {
+    return is_used_ && !true_is_fall_through_;
+  }
+
+  // Emit a branch to one of the true or false targets, and bind the
+  // other target.  Because this binds the fall-through target, it
+  // should be emitted in tail position (as the last thing when
+  // compiling an expression).
+  void Split(Condition cc) {
+    ASSERT(!is_used_);
+    if (true_is_fall_through_) {
+      false_target_->Branch(NegateCondition(cc));
+      true_target_->Bind();
+    } else {
+      true_target_->Branch(cc);
+      false_target_->Bind();
+    }
+    is_used_ = true;
+  }
+
+  // Emit an unconditional jump in tail position, to the true target
+  // (if the argument is true) or the false target.  The "jump" will
+  // actually bind the jump target if it is forward, jump to it if it
+  // is backward.
+  void Goto(bool where) {
+    ASSERT(!is_used_);
+    JumpTarget* target = where ? true_target_ : false_target_;
+    if (target->is_bound()) {
+      target->Jump();
+    } else {
+      target->Bind();
+    }
+    is_used_ = true;
+    true_is_fall_through_ = where;
+  }
+
+  // Mark this jump target as used as if Goto had been called, but
+  // without generating a jump or binding a label (the control effect
+  // should have already happened).  This is used when the left
+  // subexpression of the short-circuit boolean operators are
+  // compiled.
+  void Use(bool where) {
+    ASSERT(!is_used_);
+    ASSERT((where ? true_target_ : false_target_)->is_bound());
+    is_used_ = true;
+    true_is_fall_through_ = where;
+  }
+
+  // Swap the true and false targets but keep the same actual label as
+  // the fall through.  This is used when compiling negated
+  // expressions, where we want to swap the targets but preserve the
+  // state.
+  void Invert() {
+    JumpTarget* temp_target = true_target_;
+    true_target_ = false_target_;
+    false_target_ = temp_target;
+
+    true_is_fall_through_ = !true_is_fall_through_;
+  }
+
+ private:
+  // True and false jump targets.
+  JumpTarget* true_target_;
+  JumpTarget* false_target_;
+
+  // Before using the destination: true if the true target is the
+  // preferred fall through, false if the false target is.  After
+  // using the destination: true if the true target was actually used
+  // as the fall through, false if the false target was.
+  bool true_is_fall_through_;
+
+  // True if the Split or Goto functions have been called.
+  bool is_used_;
+};
+
+
+// -------------------------------------------------------------------------
+// Code generation state
+
+// The state is passed down the AST by the code generator (and back up, in
+// the form of the state of the jump target pair).  It is threaded through
+// the call stack.  Constructing a state implicitly pushes it on the owning
+// code generator's stack of states, and destroying one implicitly pops it.
+//
+// The code generator state is only used for expressions, so statements have
+// the initial state.
+
+class CodeGenState BASE_EMBEDDED {
+ public:
+  // Create an initial code generator state.  Destroying the initial state
+  // leaves the code generator with a NULL state.
+  explicit CodeGenState(CodeGenerator* owner);
+
+  // Create a code generator state based on a code generator's current
+  // state.  The new state may or may not be inside a typeof, and has its
+  // own control destination.
+  CodeGenState(CodeGenerator* owner,
+               TypeofState typeof_state,
+               ControlDestination* destination);
+
+  // Destroy a code generator state and restore the owning code generator's
+  // previous state.
+  ~CodeGenState();
+
+  // Accessors for the state.
+  TypeofState typeof_state() const { return typeof_state_; }
+  ControlDestination* destination() const { return destination_; }
+
+ private:
+  // The owning code generator.
+  CodeGenerator* owner_;
+
+  // A flag indicating whether we are compiling the immediate subexpression
+  // of a typeof expression.
+  TypeofState typeof_state_;
+
+  // A control destination in case the expression has a control-flow
+  // effect.
+  ControlDestination* destination_;
+
+  // The previous state of the owning code generator, restored when
+  // this state is destroyed.
+  CodeGenState* previous_;
+};
+
+
+
+
+// -------------------------------------------------------------------------
+// CodeGenerator
+
+class CodeGenerator: public AstVisitor {
+ public:
+  // Takes a function literal, generates code for it. This function should only
+  // be called by compiler.cc.
+  static Handle<Code> MakeCode(FunctionLiteral* fun,
+                               Handle<Script> script,
+                               bool is_eval);
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  static bool ShouldGenerateLog(Expression* type);
+#endif
+
+  static void SetFunctionInfo(Handle<JSFunction> fun,
+                              int length,
+                              int function_token_position,
+                              int start_position,
+                              int end_position,
+                              bool is_expression,
+                              bool is_toplevel,
+                              Handle<Script> script,
+                              Handle<String> inferred_name);
+
+  // Accessors
+  MacroAssembler* masm() { return masm_; }
+
+  VirtualFrame* frame() const { return frame_; }
+
+  bool has_valid_frame() const { return frame_ != NULL; }
+
+  // Set the virtual frame to be new_frame, with non-frame register
+  // reference counts given by non_frame_registers.  The non-frame
+  // register reference counts of the old frame are returned in
+  // non_frame_registers.
+  void SetFrame(VirtualFrame* new_frame, RegisterFile* non_frame_registers);
+
+  void DeleteFrame();
+
+  RegisterAllocator* allocator() const { return allocator_; }
+
+  CodeGenState* state() { return state_; }
+  void set_state(CodeGenState* state) { state_ = state; }
+
+  void AddDeferred(DeferredCode* code) { deferred_.Add(code); }
+
+  bool in_spilled_code() const { return in_spilled_code_; }
+  void set_in_spilled_code(bool flag) { in_spilled_code_ = flag; }
+
+ private:
+  // Construction/Destruction
+  CodeGenerator(int buffer_size, Handle<Script> script, bool is_eval);
+  virtual ~CodeGenerator() { delete masm_; }
+
+  // Accessors
+  Scope* scope() const { return scope_; }
+
+  // Clearing and generating deferred code.
+  void ClearDeferred();
+  void ProcessDeferred();
+
+  bool is_eval() { return is_eval_; }
+
+  // State
+  TypeofState typeof_state() const { return state_->typeof_state(); }
+  ControlDestination* destination() const { return state_->destination(); }
+
+  // Track loop nesting level.
+  int loop_nesting() const { return loop_nesting_; }
+  void IncrementLoopNesting() { loop_nesting_++; }
+  void DecrementLoopNesting() { loop_nesting_--; }
+
+
+  // Node visitors.
+  void VisitStatements(ZoneList<Statement*>* statements);
+
+#define DEF_VISIT(type) \
+  void Visit##type(type* node);
+  NODE_LIST(DEF_VISIT)
+#undef DEF_VISIT
+
+  // Visit a statement and then spill the virtual frame if control flow can
+  // reach the end of the statement (ie, it does not exit via break,
+  // continue, return, or throw).  This function is used temporarily while
+  // the code generator is being transformed.
+  void VisitAndSpill(Statement* statement);
+
+  // Visit a list of statements and then spill the virtual frame if control
+  // flow can reach the end of the list.
+  void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
+
+  // Main code generation function
+  void GenCode(FunctionLiteral* fun);
+
+  // Generate the return sequence code.  Should be called no more than
+  // once per compiled function, immediately after binding the return
+  // target (which can not be done more than once).
+  void GenerateReturnSequence(Result* return_value);
+
+  // The following are used by class Reference.
+  void LoadReference(Reference* ref);
+  void UnloadReference(Reference* ref);
+
+  Operand ContextOperand(Register context, int index) const {
+    return Operand(context, Context::SlotOffset(index));
+  }
+
+  Operand SlotOperand(Slot* slot, Register tmp);
+
+  Operand ContextSlotOperandCheckExtensions(Slot* slot,
+                                            Result tmp,
+                                            JumpTarget* slow);
+
+  // Expressions
+  Operand GlobalObject() const {
+    return ContextOperand(esi, Context::GLOBAL_INDEX);
+  }
+
+  void LoadCondition(Expression* x,
+                     TypeofState typeof_state,
+                     ControlDestination* destination,
+                     bool force_control);
+  void Load(Expression* x, TypeofState typeof_state = NOT_INSIDE_TYPEOF);
+  void LoadGlobal();
+  void LoadGlobalReceiver();
+
+  // Generate code to push the value of an expression on top of the frame
+  // and then spill the frame fully to memory.  This function is used
+  // temporarily while the code generator is being transformed.
+  void LoadAndSpill(Expression* expression,
+                    TypeofState typeof_state = NOT_INSIDE_TYPEOF);
+
+  // Read a value from a slot and leave it on top of the expression stack.
+  void LoadFromSlot(Slot* slot, TypeofState typeof_state);
+  Result LoadFromGlobalSlotCheckExtensions(Slot* slot,
+                                           TypeofState typeof_state,
+                                           JumpTarget* slow);
+
+  // Store the value on top of the expression stack into a slot, leaving the
+  // value in place.
+  void StoreToSlot(Slot* slot, InitState init_state);
+
+  // Special code for typeof expressions: Unfortunately, we must
+  // be careful when loading the expression in 'typeof'
+  // expressions. We are not allowed to throw reference errors for
+  // non-existing properties of the global object, so we must make it
+  // look like an explicit property access, instead of an access
+  // through the context chain.
+  void LoadTypeofExpression(Expression* x);
+
+  // Translate the value on top of the frame into control flow to the
+  // control destination.
+  void ToBoolean(ControlDestination* destination);
+
+  void GenericBinaryOperation(
+      Token::Value op,
+      SmiAnalysis* type,
+      const OverwriteMode overwrite_mode = NO_OVERWRITE);
+
+  // If possible, combine two constant smi values using op to produce
+  // a smi result, and push it on the virtual frame, all at compile time.
+  // Returns true if it succeeds.  Otherwise it has no effect.
+  bool FoldConstantSmis(Token::Value op, int left, int right);
+
+  // Emit code to perform a binary operation on a constant
+  // smi and a likely smi.  Consumes the Result *operand.
+  void ConstantSmiBinaryOperation(Token::Value op,
+                                  Result* operand,
+                                  Handle<Object> constant_operand,
+                                  SmiAnalysis* type,
+                                  bool reversed,
+                                  OverwriteMode overwrite_mode);
+
+  // Emit code to perform a binary operation on two likely smis.
+  // The code to handle smi arguments is produced inline.
+  // Consumes the Results *left and *right.
+  void LikelySmiBinaryOperation(Token::Value op,
+                                Result* left,
+                                Result* right,
+                                OverwriteMode overwrite_mode);
+
+  void Comparison(Condition cc,
+                  bool strict,
+                  ControlDestination* destination);
+
+  // To prevent long attacker-controlled byte sequences, integer constants
+  // from the JavaScript source are loaded in two parts if they are larger
+  // than 16 bits.
+  static const int kMaxSmiInlinedBits = 16;
+  bool IsUnsafeSmi(Handle<Object> value);
+  // Load an integer constant x into a register target using
+  // at most 16 bits of user-controlled data per assembly operation.
+  void LoadUnsafeSmi(Register target, Handle<Object> value);
+
+  void CallWithArguments(ZoneList<Expression*>* arguments, int position);
+
+  void CheckStack();
+
+  bool CheckForInlineRuntimeCall(CallRuntime* node);
+  Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node);
+  void ProcessDeclarations(ZoneList<Declaration*>* declarations);
+
+  Handle<Code> ComputeCallInitialize(int argc);
+  Handle<Code> ComputeCallInitializeInLoop(int argc);
+
+  // Declare global variables and functions in the given array of
+  // name/value pairs.
+  void DeclareGlobals(Handle<FixedArray> pairs);
+
+  // Instantiate the function boilerplate.
+  void InstantiateBoilerplate(Handle<JSFunction> boilerplate);
+
+  // Support for type checks.
+  void GenerateIsSmi(ZoneList<Expression*>* args);
+  void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
+  void GenerateIsArray(ZoneList<Expression*>* args);
+
+  // Support for arguments.length and arguments[?].
+  void GenerateArgumentsLength(ZoneList<Expression*>* args);
+  void GenerateArgumentsAccess(ZoneList<Expression*>* args);
+
+  // Support for accessing the value field of an object (used by Date).
+  void GenerateValueOf(ZoneList<Expression*>* args);
+  void GenerateSetValueOf(ZoneList<Expression*>* args);
+
+  // Fast support for charCodeAt(n).
+  void GenerateFastCharCodeAt(ZoneList<Expression*>* args);
+
+  // Fast support for object equality testing.
+  void GenerateObjectEquals(ZoneList<Expression*>* args);
+
+  void GenerateLog(ZoneList<Expression*>* args);
+
+
+  // Methods and constants for fast case switch statement support.
+  //
+  // Only allow fast-case switch if the range of labels is at most
+  // this factor times the number of case labels.
+  // Value is derived from comparing the size of code generated by the normal
+  // switch code for Smi-labels to the size of a single pointer. If code
+  // quality increases this number should be decreased to match.
+  static const int kFastSwitchMaxOverheadFactor = 5;
+
+  // Minimal number of switch cases required before we allow jump-table
+  // optimization.
+  static const int kFastSwitchMinCaseCount = 5;
+
+  // The limit of the range of a fast-case switch, as a factor of the number
+  // of cases of the switch. Each platform should return a value that
+  // is optimal compared to the default code generated for a switch statement
+  // on that platform.
+  int FastCaseSwitchMaxOverheadFactor();
+
+  // The minimal number of cases in a switch before the fast-case switch
+  // optimization is enabled. Each platform should return a value that
+  // is optimal compared to the default code generated for a switch statement
+  // on that platform.
+  int FastCaseSwitchMinCaseCount();
+
+  // Allocate a jump table and create code to jump through it.
+  // Should call GenerateFastCaseSwitchCases to generate the code for
+  // all the cases at the appropriate point.
+  void GenerateFastCaseSwitchJumpTable(SwitchStatement* node,
+                                       int min_index,
+                                       int range,
+                                       Label* fail_label,
+                                       Vector<Label*> case_targets,
+                                       Vector<Label> case_labels);
+
+  // Generate the code for cases for the fast case switch.
+  // Called by GenerateFastCaseSwitchJumpTable.
+  void GenerateFastCaseSwitchCases(SwitchStatement* node,
+                                   Vector<Label> case_labels,
+                                   VirtualFrame* start_frame);
+
+  // Fast support for constant-Smi switches.
+  void GenerateFastCaseSwitchStatement(SwitchStatement* node,
+                                       int min_index,
+                                       int range,
+                                       int default_index);
+
+  // Fast support for constant-Smi switches. Tests whether switch statement
+  // permits optimization and calls GenerateFastCaseSwitch if it does.
+  // Returns true if the fast-case switch was generated, and false if not.
+  bool TryGenerateFastCaseSwitchStatement(SwitchStatement* node);
+
+  // Methods used to indicate which source code is generated for. Source
+  // positions are collected by the assembler and emitted with the relocation
+  // information.
+  void CodeForFunctionPosition(FunctionLiteral* fun);
+  void CodeForReturnPosition(FunctionLiteral* fun);
+  void CodeForStatementPosition(Node* node);
+  void CodeForSourcePosition(int pos);
+
+#ifdef DEBUG
+  // True if the registers are valid for entry to a block.  There should be
+  // no frame-external references to eax, ebx, ecx, edx, or edi.
+  bool HasValidEntryRegisters();
+#endif
+
+  bool is_eval_;  // Tells whether code is generated for eval.
+  Handle<Script> script_;
+  List<DeferredCode*> deferred_;
+
+  // Assembler
+  MacroAssembler* masm_;  // to generate code
+
+  // Code generation state
+  Scope* scope_;
+  VirtualFrame* frame_;
+  RegisterAllocator* allocator_;
+  CodeGenState* state_;
+  int loop_nesting_;
+
+  // Jump targets.
+  // The target of the return from the function.
+  BreakTarget function_return_;
+
+  // True if the function return is shadowed (ie, jumping to the target
+  // function_return_ does not jump to the true function return, but rather
+  // to some unlinking code).
+  bool function_return_is_shadowed_;
+
+  // True when we are in code that expects the virtual frame to be fully
+  // spilled.  Some virtual frame function are disabled in DEBUG builds when
+  // called from spilled code, because they do not leave the virtual frame
+  // in a spilled state.
+  bool in_spilled_code_;
+
+  friend class VirtualFrame;
+  friend class JumpTarget;
+  friend class Reference;
+  friend class Result;
+
+  DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_CODEGEN_IA32_H_
diff --git a/deps/v8/src/codegen-inl.h b/deps/v8/src/codegen-inl.h
new file mode 100644
index 0000000..c42f5ac
--- /dev/null
+++ b/deps/v8/src/codegen-inl.h
@@ -0,0 +1,75 @@
+// 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_CODEGEN_INL_H_
+#define V8_CODEGEN_INL_H_
+
+#include "codegen.h"
+
+namespace v8 { namespace internal {
+
+
+// -----------------------------------------------------------------------------
+// Support for "structured" code comments.
+//
+// By selecting matching brackets in disassembler output,
+// code segments can be identified more easily.
+
+#ifdef DEBUG
+
+class Comment BASE_EMBEDDED {
+ public:
+  Comment(MacroAssembler* masm, const char* msg)
+    : masm_(masm),
+      msg_(msg) {
+    masm_->RecordComment(msg);
+  }
+
+  ~Comment() {
+    if (msg_[0] == '[')
+      masm_->RecordComment("]");
+  }
+
+ private:
+  MacroAssembler* masm_;
+  const char* msg_;
+};
+
+#else
+
+class Comment BASE_EMBEDDED {
+ public:
+  Comment(MacroAssembler*, const char*)  {}
+};
+
+#endif  // DEBUG
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_CODEGEN_INL_H_
diff --git a/deps/v8/src/codegen.cc b/deps/v8/src/codegen.cc
new file mode 100644
index 0000000..edc498d
--- /dev/null
+++ b/deps/v8/src/codegen.cc
@@ -0,0 +1,622 @@
+// 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.
+
+#include "v8.h"
+
+#include "bootstrapper.h"
+#include "codegen-inl.h"
+#include "debug.h"
+#include "oprofile-agent.h"
+#include "prettyprinter.h"
+#include "register-allocator-inl.h"
+#include "rewriter.h"
+#include "runtime.h"
+#include "scopeinfo.h"
+#include "stub-cache.h"
+
+namespace v8 { namespace internal {
+
+DeferredCode::DeferredCode(CodeGenerator* generator)
+  : generator_(generator),
+    masm_(generator->masm()),
+    enter_(generator),
+    exit_(generator, JumpTarget::BIDIRECTIONAL),
+    statement_position_(masm_->current_statement_position()),
+    position_(masm_->current_position()) {
+  generator->AddDeferred(this);
+  ASSERT(statement_position_ != RelocInfo::kNoPosition);
+  ASSERT(position_ != RelocInfo::kNoPosition);
+#ifdef DEBUG
+  comment_ = "";
+#endif
+}
+
+
+void CodeGenerator::ClearDeferred() {
+  for (int i = 0; i < deferred_.length(); i++) {
+    deferred_[i]->Clear();
+  }
+}
+
+
+void CodeGenerator::ProcessDeferred() {
+  while (!deferred_.is_empty()) {
+    DeferredCode* code = deferred_.RemoveLast();
+    MacroAssembler* masm = code->masm();
+    // Record position of deferred code stub.
+    masm->RecordStatementPosition(code->statement_position());
+    if (code->position() != RelocInfo::kNoPosition) {
+      masm->RecordPosition(code->position());
+    }
+    // Generate the code.
+    Comment cmnt(masm, code->comment());
+    code->Generate();
+    ASSERT(code->enter()->is_bound());
+    code->Clear();
+  }
+}
+
+
+void CodeGenerator::SetFrame(VirtualFrame* new_frame,
+                             RegisterFile* non_frame_registers) {
+  RegisterFile saved_counts;
+  if (has_valid_frame()) {
+    frame_->DetachFromCodeGenerator();
+    // The remaining register reference counts are the non-frame ones.
+    allocator_->SaveTo(&saved_counts);
+  }
+
+  if (new_frame != NULL) {
+    // Restore the non-frame register references that go with the new frame.
+    allocator_->RestoreFrom(non_frame_registers);
+    new_frame->AttachToCodeGenerator();
+  }
+
+  frame_ = new_frame;
+  saved_counts.CopyTo(non_frame_registers);
+}
+
+
+void CodeGenerator::DeleteFrame() {
+  if (has_valid_frame()) {
+    frame_->DetachFromCodeGenerator();
+    delete frame_;
+    frame_ = NULL;
+  }
+}
+
+
+// Generate the code. Takes a function literal, generates code for it, assemble
+// all the pieces into a Code object. This function is only to be called by
+// the compiler.cc code.
+Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* flit,
+                                     Handle<Script> script,
+                                     bool is_eval) {
+#ifdef ENABLE_DISASSEMBLER
+  bool print_code = Bootstrapper::IsActive()
+      ? FLAG_print_builtin_code
+      : FLAG_print_code;
+#endif
+
+#ifdef DEBUG
+  bool print_source = false;
+  bool print_ast = false;
+  const char* ftype;
+
+  if (Bootstrapper::IsActive()) {
+    print_source = FLAG_print_builtin_source;
+    print_ast = FLAG_print_builtin_ast;
+    ftype = "builtin";
+  } else {
+    print_source = FLAG_print_source;
+    print_ast = FLAG_print_ast;
+    ftype = "user-defined";
+  }
+
+  if (FLAG_trace_codegen || print_source || print_ast) {
+    PrintF("*** Generate code for %s function: ", ftype);
+    flit->name()->ShortPrint();
+    PrintF(" ***\n");
+  }
+
+  if (print_source) {
+    PrintF("--- Source from AST ---\n%s\n", PrettyPrinter().PrintProgram(flit));
+  }
+
+  if (print_ast) {
+    PrintF("--- AST ---\n%s\n", AstPrinter().PrintProgram(flit));
+  }
+#endif  // DEBUG
+
+  // Generate code.
+  const int initial_buffer_size = 4 * KB;
+  CodeGenerator cgen(initial_buffer_size, script, is_eval);
+  cgen.GenCode(flit);
+  if (cgen.HasStackOverflow()) {
+    ASSERT(!Top::has_pending_exception());
+    return Handle<Code>::null();
+  }
+
+  // Allocate and install the code.
+  CodeDesc desc;
+  cgen.masm()->GetCode(&desc);
+  ScopeInfo<> sinfo(flit->scope());
+  Code::Flags flags = Code::ComputeFlags(Code::FUNCTION);
+  Handle<Code> code = Factory::NewCode(desc,
+                                       &sinfo,
+                                       flags,
+                                       cgen.masm()->CodeObject());
+
+  // Add unresolved entries in the code to the fixup list.
+  Bootstrapper::AddFixup(*code, cgen.masm());
+
+#ifdef ENABLE_DISASSEMBLER
+  if (print_code) {
+    // Print the source code if available.
+    if (!script->IsUndefined() && !script->source()->IsUndefined()) {
+      PrintF("--- Raw source ---\n");
+      StringInputBuffer stream(String::cast(script->source()));
+      stream.Seek(flit->start_position());
+      // flit->end_position() points to the last character in the stream. We
+      // need to compensate by adding one to calculate the length.
+      int source_len = flit->end_position() - flit->start_position() + 1;
+      for (int i = 0; i < source_len; i++) {
+        if (stream.has_more()) PrintF("%c", stream.GetNext());
+      }
+      PrintF("\n\n");
+    }
+    PrintF("--- Code ---\n");
+    code->Disassemble(*flit->name()->ToCString());
+  }
+#endif  // ENABLE_DISASSEMBLER
+
+  if (!code.is_null()) {
+    Counters::total_compiled_code_size.Increment(code->instruction_size());
+  }
+
+  return code;
+}
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+
+bool CodeGenerator::ShouldGenerateLog(Expression* type) {
+  ASSERT(type != NULL);
+  if (!Logger::is_enabled()) return false;
+  Handle<String> name = Handle<String>::cast(type->AsLiteral()->handle());
+  if (FLAG_log_regexp) {
+    static Vector<const char> kRegexp = CStrVector("regexp");
+    if (name->IsEqualTo(kRegexp))
+      return true;
+  }
+  return false;
+}
+
+#endif
+
+
+// Sets the function info on a function.
+// The start_position points to the first '(' character after the function name
+// in the full script source. When counting characters in the script source the
+// the first character is number 0 (not 1).
+void CodeGenerator::SetFunctionInfo(Handle<JSFunction> fun,
+                                    int length,
+                                    int function_token_position,
+                                    int start_position,
+                                    int end_position,
+                                    bool is_expression,
+                                    bool is_toplevel,
+                                    Handle<Script> script,
+                                    Handle<String> inferred_name) {
+  fun->shared()->set_length(length);
+  fun->shared()->set_formal_parameter_count(length);
+  fun->shared()->set_script(*script);
+  fun->shared()->set_function_token_position(function_token_position);
+  fun->shared()->set_start_position(start_position);
+  fun->shared()->set_end_position(end_position);
+  fun->shared()->set_is_expression(is_expression);
+  fun->shared()->set_is_toplevel(is_toplevel);
+  fun->shared()->set_inferred_name(*inferred_name);
+}
+
+
+static Handle<Code> ComputeLazyCompile(int argc) {
+  CALL_HEAP_FUNCTION(StubCache::ComputeLazyCompile(argc), Code);
+}
+
+
+Handle<JSFunction> CodeGenerator::BuildBoilerplate(FunctionLiteral* node) {
+#ifdef DEBUG
+  // We should not try to compile the same function literal more than
+  // once.
+  node->mark_as_compiled();
+#endif
+
+  // Determine if the function can be lazily compiled. This is
+  // necessary to allow some of our builtin JS files to be lazily
+  // compiled. These builtins cannot be handled lazily by the parser,
+  // since we have to know if a function uses the special natives
+  // syntax, which is something the parser records.
+  bool allow_lazy = node->AllowsLazyCompilation();
+
+  // Generate code
+  Handle<Code> code;
+  if (FLAG_lazy && allow_lazy) {
+    code = ComputeLazyCompile(node->num_parameters());
+  } else {
+    // The bodies of function literals have not yet been visited by
+    // the AST optimizer/analyzer.
+    if (!Rewriter::Optimize(node)) {
+      return Handle<JSFunction>::null();
+    }
+
+    code = MakeCode(node, script_, false);
+
+    // Check for stack-overflow exception.
+    if (code.is_null()) {
+      SetStackOverflow();
+      return Handle<JSFunction>::null();
+    }
+
+    // Function compilation complete.
+    LOG(CodeCreateEvent("Function", *code, *node->name()));
+
+#ifdef ENABLE_OPROFILE_AGENT
+    OProfileAgent::CreateNativeCodeRegion(*node->name(),
+                                          code->address(),
+                                          code->ExecutableSize());
+#endif
+  }
+
+  // Create a boilerplate function.
+  Handle<JSFunction> function =
+      Factory::NewFunctionBoilerplate(node->name(),
+                                      node->materialized_literal_count(),
+                                      node->contains_array_literal(),
+                                      code);
+  CodeGenerator::SetFunctionInfo(function, node->num_parameters(),
+                                 node->function_token_position(),
+                                 node->start_position(), node->end_position(),
+                                 node->is_expression(), false, script_,
+                                 node->inferred_name());
+
+  // Notify debugger that a new function has been added.
+  Debugger::OnNewFunction(function);
+
+  // Set the expected number of properties for instances and return
+  // the resulting function.
+  SetExpectedNofPropertiesFromEstimate(function,
+                                       node->expected_property_count());
+  return function;
+}
+
+
+Handle<Code> CodeGenerator::ComputeCallInitialize(int argc) {
+  CALL_HEAP_FUNCTION(StubCache::ComputeCallInitialize(argc), Code);
+}
+
+
+Handle<Code> CodeGenerator::ComputeCallInitializeInLoop(int argc) {
+  // Force the creation of the corresponding stub outside loops,
+  // because it will be used when clearing the ICs later - when we
+  // don't know if we're inside a loop or not.
+  ComputeCallInitialize(argc);
+  CALL_HEAP_FUNCTION(StubCache::ComputeCallInitializeInLoop(argc), Code);
+}
+
+
+void CodeGenerator::ProcessDeclarations(ZoneList<Declaration*>* declarations) {
+  int length = declarations->length();
+  int globals = 0;
+  for (int i = 0; i < length; i++) {
+    Declaration* node = declarations->at(i);
+    Variable* var = node->proxy()->var();
+    Slot* slot = var->slot();
+
+    // If it was not possible to allocate the variable at compile
+    // time, we need to "declare" it at runtime to make sure it
+    // actually exists in the local context.
+    if ((slot != NULL && slot->type() == Slot::LOOKUP) || !var->is_global()) {
+      VisitDeclaration(node);
+    } else {
+      // Count global variables and functions for later processing
+      globals++;
+    }
+  }
+
+  // Return in case of no declared global functions or variables.
+  if (globals == 0) return;
+
+  // Compute array of global variable and function declarations.
+  Handle<FixedArray> array = Factory::NewFixedArray(2 * globals, TENURED);
+  for (int j = 0, i = 0; i < length; i++) {
+    Declaration* node = declarations->at(i);
+    Variable* var = node->proxy()->var();
+    Slot* slot = var->slot();
+
+    if ((slot != NULL && slot->type() == Slot::LOOKUP) || !var->is_global()) {
+      // Skip - already processed.
+    } else {
+      array->set(j++, *(var->name()));
+      if (node->fun() == NULL) {
+        if (var->mode() == Variable::CONST) {
+          // In case this is const property use the hole.
+          array->set_the_hole(j++);
+        } else {
+          array->set_undefined(j++);
+        }
+      } else {
+        Handle<JSFunction> function = BuildBoilerplate(node->fun());
+        // Check for stack-overflow exception.
+        if (HasStackOverflow()) return;
+        array->set(j++, *function);
+      }
+    }
+  }
+
+  // Invoke the platform-dependent code generator to do the actual
+  // declaration the global variables and functions.
+  DeclareGlobals(array);
+}
+
+
+struct InlineRuntimeLUT {
+  void (CodeGenerator::*method)(ZoneList<Expression*>*);
+  const char* name;
+};
+
+
+bool CodeGenerator::CheckForInlineRuntimeCall(CallRuntime* node) {
+  ZoneList<Expression*>* args = node->arguments();
+  // Special cases: These 'runtime calls' manipulate the current
+  // frame and are only used 1 or two places, so we generate them
+  // inline instead of generating calls to them.  They are used
+  // for implementing Function.prototype.call() and
+  // Function.prototype.apply().
+  static const InlineRuntimeLUT kInlineRuntimeLUT[] = {
+    {&v8::internal::CodeGenerator::GenerateIsSmi,
+     "_IsSmi"},
+    {&v8::internal::CodeGenerator::GenerateIsNonNegativeSmi,
+     "_IsNonNegativeSmi"},
+    {&v8::internal::CodeGenerator::GenerateIsArray,
+     "_IsArray"},
+    {&v8::internal::CodeGenerator::GenerateArgumentsLength,
+     "_ArgumentsLength"},
+    {&v8::internal::CodeGenerator::GenerateArgumentsAccess,
+     "_Arguments"},
+    {&v8::internal::CodeGenerator::GenerateValueOf,
+     "_ValueOf"},
+    {&v8::internal::CodeGenerator::GenerateSetValueOf,
+     "_SetValueOf"},
+    {&v8::internal::CodeGenerator::GenerateFastCharCodeAt,
+     "_FastCharCodeAt"},
+    {&v8::internal::CodeGenerator::GenerateObjectEquals,
+     "_ObjectEquals"},
+    {&v8::internal::CodeGenerator::GenerateLog,
+     "_Log"}
+  };
+  Handle<String> name = node->name();
+  if (name->length() > 0 && name->Get(0) == '_') {
+    for (unsigned i = 0;
+         i < sizeof(kInlineRuntimeLUT) / sizeof(InlineRuntimeLUT);
+         i++) {
+      const InlineRuntimeLUT* entry = kInlineRuntimeLUT + i;
+      if (name->IsEqualTo(CStrVector(entry->name))) {
+        ((*this).*(entry->method))(args);
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+
+void CodeGenerator::GenerateFastCaseSwitchStatement(SwitchStatement* node,
+                                                    int min_index,
+                                                    int range,
+                                                    int default_index) {
+  ZoneList<CaseClause*>* cases = node->cases();
+  int length = cases->length();
+
+  // Label pointer per number in range.
+  SmartPointer<Label*> case_targets(NewArray<Label*>(range));
+
+  // Label per switch case.
+  SmartPointer<Label> case_labels(NewArray<Label>(length));
+
+  Label* fail_label =
+      default_index >= 0 ? &(case_labels[default_index]) : NULL;
+
+  // Populate array of label pointers for each number in the range.
+  // Initally put the failure label everywhere.
+  for (int i = 0; i < range; i++) {
+    case_targets[i] = fail_label;
+  }
+
+  // Overwrite with label of a case for the number value of that case.
+  // (In reverse order, so that if the same label occurs twice, the
+  // first one wins).
+  for (int i = length - 1; i >= 0 ; i--) {
+    CaseClause* clause = cases->at(i);
+    if (!clause->is_default()) {
+      Object* label_value = *(clause->label()->AsLiteral()->handle());
+      int case_value = Smi::cast(label_value)->value();
+      case_targets[case_value - min_index] = &(case_labels[i]);
+    }
+  }
+
+  GenerateFastCaseSwitchJumpTable(node,
+                                  min_index,
+                                  range,
+                                  fail_label,
+                                  Vector<Label*>(*case_targets, range),
+                                  Vector<Label>(*case_labels, length));
+}
+
+
+void CodeGenerator::GenerateFastCaseSwitchCases(
+    SwitchStatement* node,
+    Vector<Label> case_labels,
+    VirtualFrame* start_frame) {
+  ZoneList<CaseClause*>* cases = node->cases();
+  int length = cases->length();
+
+  for (int i = 0; i < length; i++) {
+    Comment cmnt(masm(), "[ Case clause");
+
+    // We may not have a virtual frame if control flow did not fall
+    // off the end of the previous case.  In that case, use the start
+    // frame.  Otherwise, we have to merge the existing one to the
+    // start frame as part of the previous case.
+    if (!has_valid_frame()) {
+      RegisterFile non_frame_registers = RegisterAllocator::Reserved();
+      SetFrame(new VirtualFrame(start_frame), &non_frame_registers);
+    } else {
+      frame_->MergeTo(start_frame);
+    }
+    masm()->bind(&case_labels[i]);
+    VisitStatements(cases->at(i)->statements());
+  }
+}
+
+
+bool CodeGenerator::TryGenerateFastCaseSwitchStatement(SwitchStatement* node) {
+  // TODO(238): Due to issue 238, fast case switches can crash on ARM
+  // and possibly IA32.  They are disabled for now.
+  // See http://code.google.com/p/v8/issues/detail?id=238
+  return false;
+
+  ZoneList<CaseClause*>* cases = node->cases();
+  int length = cases->length();
+
+  if (length < FastCaseSwitchMinCaseCount()) {
+    return false;
+  }
+
+  // Test whether fast-case should be used.
+  int default_index = -1;
+  int min_index = Smi::kMaxValue;
+  int max_index = Smi::kMinValue;
+  for (int i = 0; i < length; i++) {
+    CaseClause* clause = cases->at(i);
+    if (clause->is_default()) {
+      if (default_index >= 0) {
+        // There is more than one default label. Defer to the normal case
+        // for error.
+        return false;
+      }
+      default_index = i;
+    } else {
+      Expression* label = clause->label();
+      Literal* literal = label->AsLiteral();
+      if (literal == NULL) {
+        return false;  // fail fast case
+      }
+      Object* value = *(literal->handle());
+      if (!value->IsSmi()) {
+        return false;
+      }
+      int int_value = Smi::cast(value)->value();
+      min_index = Min(int_value, min_index);
+      max_index = Max(int_value, max_index);
+    }
+  }
+
+  // All labels are known to be Smis.
+  int range = max_index - min_index + 1;  // |min..max| inclusive
+  if (range / FastCaseSwitchMaxOverheadFactor() > length) {
+    return false;  // range of labels is too sparse
+  }
+
+  // Optimization accepted, generate code.
+  GenerateFastCaseSwitchStatement(node, min_index, range, default_index);
+  return true;
+}
+
+
+void CodeGenerator::CodeForFunctionPosition(FunctionLiteral* fun) {
+  if (FLAG_debug_info) {
+    int pos = fun->start_position();
+    if (pos != RelocInfo::kNoPosition) {
+      masm()->RecordStatementPosition(pos);
+      masm()->RecordPosition(pos);
+    }
+  }
+}
+
+
+void CodeGenerator::CodeForReturnPosition(FunctionLiteral* fun) {
+  if (FLAG_debug_info) {
+    int pos = fun->end_position();
+    if (pos != RelocInfo::kNoPosition) {
+      masm()->RecordStatementPosition(pos);
+      masm()->RecordPosition(pos);
+    }
+  }
+}
+
+
+void CodeGenerator::CodeForStatementPosition(Node* node) {
+  if (FLAG_debug_info) {
+    int pos = node->statement_pos();
+    if (pos != RelocInfo::kNoPosition) {
+      masm()->RecordStatementPosition(pos);
+      masm()->RecordPosition(pos);
+    }
+  }
+}
+
+
+void CodeGenerator::CodeForSourcePosition(int pos) {
+  if (FLAG_debug_info) {
+    if (pos != RelocInfo::kNoPosition) {
+      masm()->RecordPosition(pos);
+    }
+  }
+}
+
+
+const char* RuntimeStub::GetName() {
+  return Runtime::FunctionForId(id_)->stub_name;
+}
+
+
+void RuntimeStub::Generate(MacroAssembler* masm) {
+  masm->TailCallRuntime(ExternalReference(id_), num_arguments_);
+}
+
+
+void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
+  switch (type_) {
+    case READ_LENGTH: GenerateReadLength(masm); break;
+    case READ_ELEMENT: GenerateReadElement(masm); break;
+    case NEW_OBJECT: GenerateNewObject(masm); break;
+  }
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/codegen.h b/deps/v8/src/codegen.h
new file mode 100644
index 0000000..dd43cc0
--- /dev/null
+++ b/deps/v8/src/codegen.h
@@ -0,0 +1,311 @@
+// 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_CODEGEN_H_
+#define V8_CODEGEN_H_
+
+#include "ast.h"
+#include "code-stubs.h"
+#include "runtime.h"
+
+// Include the declaration of the architecture defined class CodeGenerator.
+// The contract  to the shared code is that the the CodeGenerator is a subclass
+// of Visitor and that the following methods are available publicly:
+//   MakeCode
+//   SetFunctionInfo
+//   masm
+//   frame
+//   has_valid_frame
+//   SetFrame
+//   DeleteFrame
+//   allocator
+//   AddDeferred
+//   in_spilled_code
+//   set_in_spilled_code
+//
+// These methods are either used privately by the shared code or implemented as
+// shared code:
+//   CodeGenerator
+//   ~CodeGenerator
+//   ProcessDeferred
+//   ClearDeferred
+//   GenCode
+//   BuildBoilerplate
+//   ComputeCallInitialize
+//   ComputeCallInitializeInLoop
+//   ProcessDeclarations
+//   DeclareGlobals
+//   CheckForInlineRuntimeCall
+//   GenerateFastCaseSwitchStatement
+//   GenerateFastCaseSwitchCases
+//   TryGenerateFastCaseSwitchStatement
+//   GenerateFastCaseSwitchJumpTable
+//   FastCaseSwitchMinCaseCount
+//   FastCaseSwitchMaxOverheadFactor
+//   CodeForFunctionPosition
+//   CodeForReturnPosition
+//   CodeForStatementPosition
+//   CodeForSourcePosition
+
+#ifdef ARM
+#include "codegen-arm.h"
+#else
+#include "codegen-ia32.h"
+#endif
+
+namespace v8 { namespace internal {
+
+
+// Use lazy compilation; defaults to true.
+// NOTE: Do not remove non-lazy compilation until we can properly
+//       install extensions with lazy compilation enabled. At the
+//       moment, this doesn't work for the extensions in Google3,
+//       and we can only run the tests with --nolazy.
+
+
+// Deferred code objects are small pieces of code that are compiled
+// out of line. They are used to defer the compilation of uncommon
+// paths thereby avoiding expensive jumps around uncommon code parts.
+class DeferredCode: public ZoneObject {
+ public:
+  explicit DeferredCode(CodeGenerator* generator);
+  virtual ~DeferredCode() { }
+
+  virtual void Generate() = 0;
+
+  // Unuse the entry and exit targets, deallocating all virtual frames
+  // held by them.  It will be impossible to emit a (correct) jump
+  // into or out of the deferred code after clearing.
+  void Clear() {
+    enter_.Unuse();
+    exit_.Unuse();
+  }
+
+  MacroAssembler* masm() const { return masm_; }
+  CodeGenerator* generator() const { return generator_; }
+
+  JumpTarget* enter() { return &enter_; }
+  void BindExit() { exit_.Bind(0); }
+  void BindExit(Result* result) { exit_.Bind(result, 1); }
+  void BindExit(Result* result0, Result* result1, Result* result2) {
+    exit_.Bind(result0, result1, result2, 3);
+  }
+
+  int statement_position() const { return statement_position_; }
+  int position() const { return position_; }
+
+#ifdef DEBUG
+  void set_comment(const char* comment) { comment_ = comment; }
+  const char* comment() const { return comment_; }
+#else
+  inline void set_comment(const char* comment) { }
+  const char* comment() const { return ""; }
+#endif
+
+ protected:
+  CodeGenerator* const generator_;
+  MacroAssembler* const masm_;
+  JumpTarget enter_;
+  JumpTarget exit_;
+
+ private:
+  int statement_position_;
+  int position_;
+#ifdef DEBUG
+  const char* comment_;
+#endif
+  DISALLOW_COPY_AND_ASSIGN(DeferredCode);
+};
+
+
+// RuntimeStub models code stubs calling entry points in the Runtime class.
+class RuntimeStub : public CodeStub {
+ public:
+  explicit RuntimeStub(Runtime::FunctionId id, int num_arguments)
+      : id_(id), num_arguments_(num_arguments) { }
+
+  void Generate(MacroAssembler* masm);
+
+  // Disassembler support.  It is useful to be able to print the name
+  // of the runtime function called through this stub.
+  static const char* GetNameFromMinorKey(int minor_key) {
+    return Runtime::FunctionForId(IdField::decode(minor_key))->stub_name;
+  }
+
+ private:
+  Runtime::FunctionId id_;
+  int num_arguments_;
+
+  class ArgumentField: public BitField<int,  0, 16> {};
+  class IdField: public BitField<Runtime::FunctionId, 16, kMinorBits - 16> {};
+
+  Major MajorKey() { return Runtime; }
+  int MinorKey() {
+    return IdField::encode(id_) | ArgumentField::encode(num_arguments_);
+  }
+
+  const char* GetName();
+
+#ifdef DEBUG
+  void Print() {
+    PrintF("RuntimeStub (id %s)\n", Runtime::FunctionForId(id_)->name);
+  }
+#endif
+};
+
+
+class StackCheckStub : public CodeStub {
+ public:
+  StackCheckStub() { }
+
+  void Generate(MacroAssembler* masm);
+
+ private:
+
+  const char* GetName() { return "StackCheckStub"; }
+
+  Major MajorKey() { return StackCheck; }
+  int MinorKey() { return 0; }
+};
+
+
+class UnarySubStub : public CodeStub {
+ public:
+  UnarySubStub() { }
+
+ private:
+  Major MajorKey() { return UnarySub; }
+  int MinorKey() { return 0; }
+  void Generate(MacroAssembler* masm);
+
+  const char* GetName() { return "UnarySubStub"; }
+};
+
+
+class CEntryStub : public CodeStub {
+ public:
+  CEntryStub() { }
+
+  void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
+
+ protected:
+  void GenerateBody(MacroAssembler* masm, bool is_debug_break);
+  void GenerateCore(MacroAssembler* masm,
+                    Label* throw_normal_exception,
+                    Label* throw_out_of_memory_exception,
+                    StackFrame::Type frame_type,
+                    bool do_gc,
+                    bool always_allocate_scope);
+  void GenerateThrowTOS(MacroAssembler* masm);
+  void GenerateThrowOutOfMemory(MacroAssembler* masm);
+
+ private:
+  Major MajorKey() { return CEntry; }
+  int MinorKey() { return 0; }
+
+  const char* GetName() { return "CEntryStub"; }
+};
+
+
+class CEntryDebugBreakStub : public CEntryStub {
+ public:
+  CEntryDebugBreakStub() { }
+
+  void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
+
+ private:
+  int MinorKey() { return 1; }
+
+  const char* GetName() { return "CEntryDebugBreakStub"; }
+};
+
+
+class JSEntryStub : public CodeStub {
+ public:
+  JSEntryStub() { }
+
+  void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
+
+ protected:
+  void GenerateBody(MacroAssembler* masm, bool is_construct);
+
+ private:
+  Major MajorKey() { return JSEntry; }
+  int MinorKey() { return 0; }
+
+  const char* GetName() { return "JSEntryStub"; }
+};
+
+
+class JSConstructEntryStub : public JSEntryStub {
+ public:
+  JSConstructEntryStub() { }
+
+  void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
+
+ private:
+  int MinorKey() { return 1; }
+
+  const char* GetName() { return "JSConstructEntryStub"; }
+};
+
+
+class ArgumentsAccessStub: public CodeStub {
+ public:
+  enum Type {
+    READ_LENGTH,
+    READ_ELEMENT,
+    NEW_OBJECT
+  };
+
+  explicit ArgumentsAccessStub(Type type) : type_(type) { }
+
+ private:
+  Type type_;
+
+  Major MajorKey() { return ArgumentsAccess; }
+  int MinorKey() { return type_; }
+
+  void Generate(MacroAssembler* masm);
+  void GenerateReadLength(MacroAssembler* masm);
+  void GenerateReadElement(MacroAssembler* masm);
+  void GenerateNewObject(MacroAssembler* masm);
+
+  const char* GetName() { return "ArgumentsAccessStub"; }
+
+#ifdef DEBUG
+  void Print() {
+    PrintF("ArgumentsAccessStub (type %d)\n", type_);
+  }
+#endif
+};
+
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_CODEGEN_H_
diff --git a/deps/v8/src/compilation-cache.cc b/deps/v8/src/compilation-cache.cc
new file mode 100644
index 0000000..4c02d86
--- /dev/null
+++ b/deps/v8/src/compilation-cache.cc
@@ -0,0 +1,230 @@
+// Copyright 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.
+
+#include "v8.h"
+
+#include "compilation-cache.h"
+
+namespace v8 { namespace internal {
+
+enum {
+  NUMBER_OF_ENTRY_KINDS = CompilationCache::LAST_ENTRY + 1
+};
+
+
+// Keep separate tables for the different entry kinds.
+static Object* tables[NUMBER_OF_ENTRY_KINDS] = { 0, };
+
+
+static Handle<CompilationCacheTable> AllocateTable(int size) {
+  CALL_HEAP_FUNCTION(CompilationCacheTable::Allocate(size),
+                     CompilationCacheTable);
+}
+
+
+static Handle<CompilationCacheTable> GetTable(CompilationCache::Entry entry) {
+  Handle<CompilationCacheTable> result;
+  if (tables[entry]->IsUndefined()) {
+    static const int kInitialCacheSize = 64;
+    result = AllocateTable(kInitialCacheSize);
+    tables[entry] = *result;
+  } else {
+    CompilationCacheTable* table = CompilationCacheTable::cast(tables[entry]);
+    result = Handle<CompilationCacheTable>(table);
+  }
+  return result;
+}
+
+
+static Handle<JSFunction> Lookup(Handle<String> source,
+                                 Handle<Context> context,
+                                 CompilationCache::Entry entry) {
+  // Make sure not to leak the table into the surrounding handle
+  // scope. Otherwise, we risk keeping old tables around even after
+  // having cleared the cache.
+  Object* result;
+  { HandleScope scope;
+    Handle<CompilationCacheTable> table = GetTable(entry);
+    result = table->LookupEval(*source, *context);
+  }
+  if (result->IsJSFunction()) {
+    return Handle<JSFunction>(JSFunction::cast(result));
+  } else {
+    return Handle<JSFunction>::null();
+  }
+}
+
+
+static Handle<FixedArray> Lookup(Handle<String> source,
+                                 JSRegExp::Flags flags) {
+  // Make sure not to leak the table into the surrounding handle
+  // scope. Otherwise, we risk keeping old tables around even after
+  // having cleared the cache.
+  Object* result;
+  { HandleScope scope;
+    Handle<CompilationCacheTable> table = GetTable(CompilationCache::REGEXP);
+    result = table->LookupRegExp(*source, flags);
+  }
+  if (result->IsFixedArray()) {
+    return Handle<FixedArray>(FixedArray::cast(result));
+  } else {
+    return Handle<FixedArray>::null();
+  }
+}
+
+
+// We only re-use a cached function for some script source code if the
+// script originates from the same place. This is to avoid issues
+// when reporting errors, etc.
+static bool HasOrigin(Handle<JSFunction> boilerplate,
+                      Handle<Object> name,
+                      int line_offset,
+                      int column_offset) {
+  Handle<Script> script =
+      Handle<Script>(Script::cast(boilerplate->shared()->script()));
+  // If the script name isn't set, the boilerplate script should have
+  // an undefined name to have the same origin.
+  if (name.is_null()) {
+    return script->name()->IsUndefined();
+  }
+  // Do the fast bailout checks first.
+  if (line_offset != script->line_offset()->value()) return false;
+  if (column_offset != script->column_offset()->value()) return false;
+  // Check that both names are strings. If not, no match.
+  if (!name->IsString() || !script->name()->IsString()) return false;
+  // Compare the two name strings for equality.
+  return String::cast(*name)->Equals(String::cast(script->name()));
+}
+
+
+static Handle<JSFunction> Lookup(Handle<String> source,
+                                 CompilationCache::Entry entry) {
+  // Make sure not to leak the table into the surrounding handle
+  // scope. Otherwise, we risk keeping old tables around even after
+  // having cleared the cache.
+  Object* result;
+  { HandleScope scope;
+    Handle<CompilationCacheTable> table = GetTable(entry);
+    result = table->Lookup(*source);
+  }
+  if (result->IsJSFunction()) {
+    return Handle<JSFunction>(JSFunction::cast(result));
+  } else {
+    return Handle<JSFunction>::null();
+  }
+}
+
+
+// TODO(245): Need to allow identical code from different contexts to be
+// cached. Currently the first use will be cached, but subsequent code
+// from different source / line won't.
+Handle<JSFunction> CompilationCache::LookupScript(Handle<String> source,
+                                                  Handle<Object> name,
+                                                  int line_offset,
+                                                  int column_offset) {
+  Handle<JSFunction> result = Lookup(source, SCRIPT);
+  if (result.is_null()) {
+    Counters::compilation_cache_misses.Increment();
+  } else if (HasOrigin(result, name, line_offset, column_offset)) {
+    Counters::compilation_cache_hits.Increment();
+  } else {
+    result = Handle<JSFunction>::null();
+    Counters::compilation_cache_misses.Increment();
+  }
+  return result;
+}
+
+
+Handle<JSFunction> CompilationCache::LookupEval(Handle<String> source,
+                                                Handle<Context> context,
+                                                Entry entry) {
+  ASSERT(entry == EVAL_GLOBAL || entry == EVAL_CONTEXTUAL);
+  Handle<JSFunction> result = Lookup(source, context, entry);
+  if (result.is_null()) {
+    Counters::compilation_cache_misses.Increment();
+  } else {
+    Counters::compilation_cache_hits.Increment();
+  }
+  return result;
+}
+
+
+Handle<FixedArray> CompilationCache::LookupRegExp(Handle<String> source,
+                                                  JSRegExp::Flags flags) {
+  Handle<FixedArray> result = Lookup(source, flags);
+  if (result.is_null()) {
+    Counters::compilation_cache_misses.Increment();
+  } else {
+    Counters::compilation_cache_hits.Increment();
+  }
+  return result;
+}
+
+
+void CompilationCache::PutScript(Handle<String> source,
+                                 Handle<JSFunction> boilerplate) {
+  HandleScope scope;
+  ASSERT(boilerplate->IsBoilerplate());
+  Handle<CompilationCacheTable> table = GetTable(SCRIPT);
+  CALL_HEAP_FUNCTION_VOID(table->Put(*source, *boilerplate));
+}
+
+
+void CompilationCache::PutEval(Handle<String> source,
+                               Handle<Context> context,
+                               Entry entry,
+                               Handle<JSFunction> boilerplate) {
+  HandleScope scope;
+  ASSERT(boilerplate->IsBoilerplate());
+  Handle<CompilationCacheTable> table = GetTable(entry);
+  CALL_HEAP_FUNCTION_VOID(table->PutEval(*source, *context, *boilerplate));
+}
+
+
+
+void CompilationCache::PutRegExp(Handle<String> source,
+                                 JSRegExp::Flags flags,
+                                 Handle<FixedArray> data) {
+  HandleScope scope;
+  Handle<CompilationCacheTable> table = GetTable(REGEXP);
+  CALL_HEAP_FUNCTION_VOID(table->PutRegExp(*source, flags, *data));
+}
+
+
+void CompilationCache::Clear() {
+  for (int i = 0; i < NUMBER_OF_ENTRY_KINDS; i++) {
+    tables[i] = Heap::undefined_value();
+  }
+}
+
+
+void CompilationCache::Iterate(ObjectVisitor* v) {
+  v->VisitPointers(&tables[0], &tables[NUMBER_OF_ENTRY_KINDS]);
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/compilation-cache.h b/deps/v8/src/compilation-cache.h
new file mode 100644
index 0000000..38a9e3a
--- /dev/null
+++ b/deps/v8/src/compilation-cache.h
@@ -0,0 +1,105 @@
+// Copyright 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_COMPILATION_CACHE_H_
+#define V8_COMPILATION_CACHE_H_
+
+namespace v8 { namespace internal {
+
+
+// The compilation cache keeps function boilerplates for compiled
+// scripts and evals. The boilerplates are looked up using the source
+// string as the key.
+class CompilationCache {
+ public:
+  // The same source code string has different compiled code for
+  // scripts and evals. Internally, we use separate caches to avoid
+  // getting the wrong kind of entry when looking up.
+  enum Entry {
+    SCRIPT,
+    EVAL_GLOBAL,
+    EVAL_CONTEXTUAL,
+    REGEXP,
+    LAST_ENTRY = REGEXP
+  };
+
+  // Finds the script function boilerplate for a source
+  // string. Returns an empty handle if the cache doesn't contain a
+  // script for the given source string with the right origin.
+  static Handle<JSFunction> LookupScript(Handle<String> source,
+                                         Handle<Object> name,
+                                         int line_offset,
+                                         int column_offset);
+
+  // Finds the function boilerplate for a source string for eval in a
+  // given context.  Returns an empty handle if the cache doesn't
+  // contain a script for the given source string.
+  static Handle<JSFunction> LookupEval(Handle<String> source,
+                                       Handle<Context> context,
+                                       Entry entry);
+
+  // Returns the regexp data associated with the given regexp if it
+  // is in cache, otherwise an empty handle.
+  static Handle<FixedArray> LookupRegExp(Handle<String> source,
+                                         JSRegExp::Flags flags);
+
+  // Associate the (source, kind) pair to the boilerplate. This may
+  // overwrite an existing mapping.
+  static void PutScript(Handle<String> source,
+                        Handle<JSFunction> boilerplate);
+
+  // Associate the (source, context->closure()->shared(), kind) triple
+  // with the boilerplate. This may overwrite an existing mapping.
+  static void PutEval(Handle<String> source,
+                      Handle<Context> context,
+                      Entry entry,
+                      Handle<JSFunction> boilerplate);
+
+  // Associate the (source, flags) pair to the given regexp data.
+  // This may overwrite an existing mapping.
+  static void PutRegExp(Handle<String> source,
+                        JSRegExp::Flags flags,
+                        Handle<FixedArray> data);
+
+  // Clear the cache - also used to initialize the cache at startup.
+  static void Clear();
+
+  // GC support.
+  static void Iterate(ObjectVisitor* v);
+
+  // Notify the cache that a mark-sweep garbage collection is about to
+  // take place. This is used to retire entries from the cache to
+  // avoid keeping them alive too long without using them. For now, we
+  // just clear the cache but we should consider are more
+  // sophisticated LRU scheme.
+  static void MarkCompactPrologue() { Clear(); }
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_COMPILATION_CACHE_H_
diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc
new file mode 100644
index 0000000..63fed4a
--- /dev/null
+++ b/deps/v8/src/compiler.cc
@@ -0,0 +1,353 @@
+// 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.
+
+#include "v8.h"
+
+#include "bootstrapper.h"
+#include "codegen-inl.h"
+#include "compilation-cache.h"
+#include "compiler.h"
+#include "debug.h"
+#include "oprofile-agent.h"
+#include "rewriter.h"
+#include "scopes.h"
+#include "usage-analyzer.h"
+
+namespace v8 { namespace internal {
+
+static Handle<Code> MakeCode(FunctionLiteral* literal,
+                             Handle<Script> script,
+                             Handle<Context> context,
+                             bool is_eval) {
+  ASSERT(literal != NULL);
+
+  // Rewrite the AST by introducing .result assignments where needed.
+  if (!Rewriter::Process(literal) || !AnalyzeVariableUsage(literal)) {
+    // Signal a stack overflow by returning a null handle.  The stack
+    // overflow exception will be thrown by the caller.
+    return Handle<Code>::null();
+  }
+
+  // Compute top scope and allocate variables. For lazy compilation
+  // the top scope only contains the single lazily compiled function,
+  // so this doesn't re-allocate variables repeatedly.
+  Scope* top = literal->scope();
+  while (top->outer_scope() != NULL) top = top->outer_scope();
+  top->AllocateVariables(context);
+
+#ifdef DEBUG
+  if (Bootstrapper::IsActive() ?
+      FLAG_print_builtin_scopes :
+      FLAG_print_scopes) {
+    literal->scope()->Print();
+  }
+#endif
+
+  // Optimize the AST.
+  if (!Rewriter::Optimize(literal)) {
+    // Signal a stack overflow by returning a null handle.  The stack
+    // overflow exception will be thrown by the caller.
+    return Handle<Code>::null();
+  }
+
+  // Generate code and return it.
+  Handle<Code> result = CodeGenerator::MakeCode(literal, script, is_eval);
+  return result;
+}
+
+
+static Handle<JSFunction> MakeFunction(bool is_global,
+                                       bool is_eval,
+                                       Handle<Script> script,
+                                       Handle<Context> context,
+                                       v8::Extension* extension,
+                                       ScriptDataImpl* pre_data) {
+  ZoneScope zone_scope(DELETE_ON_EXIT);
+
+  // Make sure we have an initial stack limit.
+  StackGuard guard;
+  PostponeInterruptsScope postpone;
+
+  // Notify debugger
+  Debugger::OnBeforeCompile(script);
+
+  // Only allow non-global compiles for eval.
+  ASSERT(is_eval || is_global);
+
+  // Build AST.
+  FunctionLiteral* lit = MakeAST(is_global, script, extension, pre_data);
+
+  // Check for parse errors.
+  if (lit == NULL) {
+    ASSERT(Top::has_pending_exception());
+    return Handle<JSFunction>::null();
+  }
+
+  // Measure how long it takes to do the compilation; only take the
+  // rest of the function into account to avoid overlap with the
+  // parsing statistics.
+  HistogramTimer* rate = is_eval
+      ? &Counters::compile_eval
+      : &Counters::compile;
+  HistogramTimerScope timer(rate);
+
+  // Compile the code.
+  Handle<Code> code = MakeCode(lit, script, context, is_eval);
+
+  // Check for stack-overflow exceptions.
+  if (code.is_null()) {
+    Top::StackOverflow();
+    return Handle<JSFunction>::null();
+  }
+
+#if defined ENABLE_LOGGING_AND_PROFILING || defined ENABLE_OPROFILE_AGENT
+  // Log the code generation for the script. Check explicit whether logging is
+  // to avoid allocating when not required.
+  if (Logger::is_enabled() || OProfileAgent::is_enabled()) {
+    if (script->name()->IsString()) {
+      SmartPointer<char> data =
+          String::cast(script->name())->ToCString(DISALLOW_NULLS);
+      LOG(CodeCreateEvent(is_eval ? "Eval" : "Script", *code, *data));
+      OProfileAgent::CreateNativeCodeRegion(*data, code->address(),
+                                            code->ExecutableSize());
+    } else {
+      LOG(CodeCreateEvent(is_eval ? "Eval" : "Script", *code, ""));
+      OProfileAgent::CreateNativeCodeRegion(is_eval ? "Eval" : "Script",
+          code->address(), code->ExecutableSize());
+    }
+  }
+#endif
+
+  // Allocate function.
+  Handle<JSFunction> fun =
+      Factory::NewFunctionBoilerplate(lit->name(),
+                                      lit->materialized_literal_count(),
+                                      lit->contains_array_literal(),
+                                      code);
+
+  CodeGenerator::SetFunctionInfo(fun, lit->scope()->num_parameters(),
+                                 RelocInfo::kNoPosition,
+                                 lit->start_position(), lit->end_position(),
+                                 lit->is_expression(), true, script,
+                                 lit->inferred_name());
+
+  // Hint to the runtime system used when allocating space for initial
+  // property space by setting the expected number of properties for
+  // the instances of the function.
+  SetExpectedNofPropertiesFromEstimate(fun, lit->expected_property_count());
+
+  // Notify debugger
+  Debugger::OnAfterCompile(script, fun);
+
+  return fun;
+}
+
+
+static StaticResource<SafeStringInputBuffer> safe_string_input_buffer;
+
+
+Handle<JSFunction> Compiler::Compile(Handle<String> source,
+                                     Handle<Object> script_name,
+                                     int line_offset, int column_offset,
+                                     v8::Extension* extension,
+                                     ScriptDataImpl* input_pre_data) {
+  int source_length = source->length();
+  Counters::total_load_size.Increment(source_length);
+  Counters::total_compile_size.Increment(source_length);
+
+  // The VM is in the COMPILER state until exiting this function.
+  VMState state(COMPILER);
+
+  // Do a lookup in the compilation cache but not for extensions.
+  Handle<JSFunction> result;
+  if (extension == NULL) {
+    result = CompilationCache::LookupScript(source,
+                                            script_name,
+                                            line_offset,
+                                            column_offset);
+  }
+
+  if (result.is_null()) {
+    // No cache entry found. Do pre-parsing and compile the script.
+    ScriptDataImpl* pre_data = input_pre_data;
+    if (pre_data == NULL && source_length >= FLAG_min_preparse_length) {
+      Access<SafeStringInputBuffer> buf(&safe_string_input_buffer);
+      buf->Reset(source.location());
+      pre_data = PreParse(buf.value(), extension);
+    }
+
+    // Create a script object describing the script to be compiled.
+    Handle<Script> script = Factory::NewScript(source);
+    if (!script_name.is_null()) {
+      script->set_name(*script_name);
+      script->set_line_offset(Smi::FromInt(line_offset));
+      script->set_column_offset(Smi::FromInt(column_offset));
+    }
+
+    // Compile the function and add it to the cache.
+    result = MakeFunction(true,
+                          false,
+                          script,
+                          Handle<Context>::null(),
+                          extension,
+                          pre_data);
+    if (extension == NULL && !result.is_null()) {
+      CompilationCache::PutScript(source, result);
+    }
+
+    // Get rid of the pre-parsing data (if necessary).
+    if (input_pre_data == NULL && pre_data != NULL) {
+      delete pre_data;
+    }
+  }
+
+  if (result.is_null()) Top::ReportPendingMessages();
+  return result;
+}
+
+
+Handle<JSFunction> Compiler::CompileEval(Handle<String> source,
+                                         Handle<Context> context,
+                                         int line_offset,
+                                         bool is_global) {
+  int source_length = source->length();
+  Counters::total_eval_size.Increment(source_length);
+  Counters::total_compile_size.Increment(source_length);
+
+  // The VM is in the COMPILER state until exiting this function.
+  VMState state(COMPILER);
+  CompilationCache::Entry entry = is_global
+      ? CompilationCache::EVAL_GLOBAL
+      : CompilationCache::EVAL_CONTEXTUAL;
+
+  // Do a lookup in the compilation cache; if the entry is not there,
+  // invoke the compiler and add the result to the cache.
+  Handle<JSFunction> result =
+      CompilationCache::LookupEval(source, context, entry);
+  if (result.is_null()) {
+    // Create a script object describing the script to be compiled.
+    Handle<Script> script = Factory::NewScript(source);
+    script->set_line_offset(Smi::FromInt(line_offset));
+    result = MakeFunction(is_global, true, script, context, NULL, NULL);
+    if (!result.is_null()) {
+      CompilationCache::PutEval(source, context, entry, result);
+    }
+  }
+
+  return result;
+}
+
+
+bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
+                           int loop_nesting) {
+  ZoneScope zone_scope(DELETE_ON_EXIT);
+
+  // The VM is in the COMPILER state until exiting this function.
+  VMState state(COMPILER);
+
+  // Make sure we have an initial stack limit.
+  StackGuard guard;
+  PostponeInterruptsScope postpone;
+
+  // Compute name, source code and script data.
+  Handle<String> name(String::cast(shared->name()));
+  Handle<Script> script(Script::cast(shared->script()));
+
+  int start_position = shared->start_position();
+  int end_position = shared->end_position();
+  bool is_expression = shared->is_expression();
+  Counters::total_compile_size.Increment(end_position - start_position);
+
+  // Generate the AST for the lazily compiled function. The AST may be
+  // NULL in case of parser stack overflow.
+  FunctionLiteral* lit = MakeLazyAST(script, name,
+                                     start_position,
+                                     end_position,
+                                     is_expression);
+
+  // Check for parse errors.
+  if (lit == NULL) {
+    ASSERT(Top::has_pending_exception());
+    return false;
+  }
+
+  // Update the loop nesting in the function literal.
+  lit->set_loop_nesting(loop_nesting);
+
+  // Measure how long it takes to do the lazy compilation; only take
+  // the rest of the function into account to avoid overlap with the
+  // lazy parsing statistics.
+  HistogramTimerScope timer(&Counters::compile_lazy);
+
+  // Compile the code.
+  Handle<Code> code = MakeCode(lit, script, Handle<Context>::null(), false);
+
+  // Check for stack-overflow exception.
+  if (code.is_null()) {
+    Top::StackOverflow();
+    return false;
+  }
+
+#if defined ENABLE_LOGGING_AND_PROFILING || defined ENABLE_OPROFILE_AGENT
+  // Log the code generation. If source information is available include script
+  // name and line number. Check explicit whether logging is enabled as finding
+  // the line number is not for free.
+  if (Logger::is_enabled() || OProfileAgent::is_enabled()) {
+    Handle<String> func_name(lit->name()->length() > 0 ?
+                             *lit->name() : shared->inferred_name());
+    if (script->name()->IsString()) {
+      int line_num = GetScriptLineNumber(script, start_position);
+      if (line_num > 0) {
+        line_num += script->line_offset()->value() + 1;
+      }
+      LOG(CodeCreateEvent("LazyCompile", *code, *func_name,
+                          String::cast(script->name()), line_num));
+      OProfileAgent::CreateNativeCodeRegion(*func_name,
+                                            String::cast(script->name()),
+                                            line_num, code->address(),
+                                            code->ExecutableSize());
+    } else {
+      LOG(CodeCreateEvent("LazyCompile", *code, *func_name));
+      OProfileAgent::CreateNativeCodeRegion(*func_name, code->address(),
+                                            code->ExecutableSize());
+    }
+  }
+#endif
+
+  // Update the shared function info with the compiled code.
+  shared->set_code(*code);
+
+  // Set the expected number of properties for instances.
+  SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
+
+  // Check the function has compiled code.
+  ASSERT(shared->is_compiled());
+  return true;
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/compiler.h b/deps/v8/src/compiler.h
new file mode 100644
index 0000000..4f589b7
--- /dev/null
+++ b/deps/v8/src/compiler.h
@@ -0,0 +1,73 @@
+// 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_COMPILER_H_
+#define V8_COMPILER_H_
+
+#include "parser.h"
+
+namespace v8 { namespace internal {
+
+// The V8 compiler
+//
+// General strategy: Source code is translated into an anonymous function w/o
+// parameters which then can be executed. If the source code contains other
+// functions, they will be compiled and allocated as part of the compilation
+// of the source code.
+
+// Please note this interface returns function boilerplates.
+// This means you need to call Factory::NewFunctionFromBoilerplate
+// before you have a real function with context.
+
+class Compiler : public AllStatic {
+ public:
+  // All routines return a JSFunction.
+  // If an error occurs an exception is raised and
+  // the return handle contains NULL.
+
+  // Compile a String source within a context.
+  static Handle<JSFunction> Compile(Handle<String> source,
+                                    Handle<Object> script_name,
+                                    int line_offset, int column_offset,
+                                    v8::Extension* extension,
+                                    ScriptDataImpl* script_Data);
+
+  // Compile a String source within a context for Eval.
+  static Handle<JSFunction> CompileEval(Handle<String> source,
+                                        Handle<Context> context,
+                                        int line_offset,
+                                        bool is_global);
+
+  // Compile from function info (used for lazy compilation). Returns
+  // true on success and false if the compilation resulted in a stack
+  // overflow.
+  static bool CompileLazy(Handle<SharedFunctionInfo> shared, int loop_nesting);
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_COMPILER_H_
diff --git a/deps/v8/src/constants-arm.h b/deps/v8/src/constants-arm.h
new file mode 100644
index 0000000..f553963
--- /dev/null
+++ b/deps/v8/src/constants-arm.h
@@ -0,0 +1,235 @@
+// Copyright 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_CONSTANTS_ARM_H_
+#define V8_CONSTANTS_ARM_H_
+
+namespace assembler { namespace arm {
+
+// Defines constants and accessor classes to assemble, disassemble and
+// simulate ARM instructions.
+//
+// Section references in the code refer to the "ARM Architecture Reference
+// Manual" from July 2005 (available at http://www.arm.com/miscPDFs/14128.pdf)
+//
+// Constants for specific fields are defined in their respective named enums.
+// General constants are in an anonymous enum in class Instr.
+
+typedef unsigned char byte;
+
+// Values for the condition field as defined in section A3.2
+enum Condition {
+  no_condition = -1,
+  EQ =  0,  // equal
+  NE =  1,  // not equal
+  CS =  2,  // carry set/unsigned higher or same
+  CC =  3,  // carry clear/unsigned lower
+  MI =  4,  // minus/negative
+  PL =  5,  // plus/positive or zero
+  VS =  6,  // overflow
+  VC =  7,  // no overflow
+  HI =  8,  // unsigned higher
+  LS =  9,  // unsigned lower or same
+  GE = 10,  // signed greater than or equal
+  LT = 11,  // signed less than
+  GT = 12,  // signed greater than
+  LE = 13,  // signed less than or equal
+  AL = 14,  // always (unconditional)
+  special_condition = 15,  // special condition (refer to section A3.2.1)
+  max_condition = 16
+};
+
+
+// Opcodes for Data-processing instructions (instructions with a type 0 and 1)
+// as defined in section A3.4
+enum Opcode {
+  no_operand = -1,
+  AND =  0,  // Logical AND
+  EOR =  1,  // Logical Exclusive OR
+  SUB =  2,  // Subtract
+  RSB =  3,  // Reverse Subtract
+  ADD =  4,  // Add
+  ADC =  5,  // Add with Carry
+  SBC =  6,  // Subtract with Carry
+  RSC =  7,  // Reverse Subtract with Carry
+  TST =  8,  // Test
+  TEQ =  9,  // Test Equivalence
+  CMP = 10,  // Compare
+  CMN = 11,  // Compare Negated
+  ORR = 12,  // Logical (inclusive) OR
+  MOV = 13,  // Move
+  BIC = 14,  // Bit Clear
+  MVN = 15,  // Move Not
+  max_operand = 16
+};
+
+
+// Shifter types for Data-processing operands as defined in section A5.1.2.
+enum Shift {
+  no_shift = -1,
+  LSL = 0,  // Logical shift left
+  LSR = 1,  // Logical shift right
+  ASR = 2,  // Arithmetic shift right
+  ROR = 3,  // Rotate right
+  max_shift = 4
+};
+
+
+// Special Software Interrupt codes when used in the presence of the ARM
+// simulator.
+enum SoftwareInterruptCodes {
+  // transition to C code
+  call_rt_r5 = 0x10,
+  call_rt_r2 = 0x11,
+  // break point
+  break_point = 0x20
+};
+
+
+typedef int32_t instr_t;
+
+
+// The class Instr enables access to individual fields defined in the ARM
+// architecture instruction set encoding as described in figure A3-1.
+//
+// Example: Test whether the instruction at ptr does set the condition code
+// bits.
+//
+// bool InstructionSetsConditionCodes(byte* ptr) {
+//   Instr* instr = Instr::At(ptr);
+//   int type = instr->TypeField();
+//   return ((type == 0) || (type == 1)) && instr->HasS();
+// }
+//
+class Instr {
+ public:
+  enum {
+    kInstrSize = 4,
+    kInstrSizeLog2 = 2,
+    kPCReadOffset = 8
+  };
+
+  // Get the raw instruction bits.
+  inline instr_t InstructionBits() const {
+    return *reinterpret_cast<const instr_t*>(this);
+  }
+
+  // Set the raw instruction bits to value.
+  inline void SetInstructionBits(instr_t value) {
+    *reinterpret_cast<instr_t*>(this) = value;
+  }
+
+  // Read one particular bit out of the instruction bits.
+  inline int Bit(int nr) const {
+    return (InstructionBits() >> nr) & 1;
+  }
+
+  // Read a bit field out of the instruction bits.
+  inline int Bits(int hi, int lo) const {
+    return (InstructionBits() >> lo) & ((2 << (hi - lo)) - 1);
+  }
+
+
+  // Accessors for the different named fields used in the ARM encoding.
+  // The naming of these accessor corresponds to figure A3-1.
+  // Generally applicable fields
+  inline Condition ConditionField() const {
+    return static_cast<Condition>(Bits(31, 28));
+  }
+  inline int TypeField() const { return Bits(27, 25); }
+
+  inline int RnField() const { return Bits(19, 16); }
+  inline int RdField() const { return Bits(15, 12); }
+
+  // Fields used in Data processing instructions
+  inline Opcode OpcodeField() const {
+    return static_cast<Opcode>(Bits(24, 21));
+  }
+  inline int SField() const { return Bit(20); }
+    // with register
+  inline int RmField() const { return Bits(3, 0); }
+  inline Shift ShiftField() const { return static_cast<Shift>(Bits(6, 5)); }
+  inline int RegShiftField() const { return Bit(4); }
+  inline int RsField() const { return Bits(11, 8); }
+  inline int ShiftAmountField() const { return Bits(11, 7); }
+    // with immediate
+  inline int RotateField() const { return Bits(11, 8); }
+  inline int Immed8Field() const { return Bits(7, 0); }
+
+  // Fields used in Load/Store instructions
+  inline int PUField() const { return Bits(24, 23); }
+  inline int  BField() const { return Bit(22); }
+  inline int  WField() const { return Bit(21); }
+  inline int  LField() const { return Bit(20); }
+    // with register uses same fields as Data processing instructions above
+    // with immediate
+  inline int Offset12Field() const { return Bits(11, 0); }
+    // multiple
+  inline int RlistField() const { return Bits(15, 0); }
+    // extra loads and stores
+  inline int SignField() const { return Bit(6); }
+  inline int HField() const { return Bit(5); }
+  inline int ImmedHField() const { return Bits(11, 8); }
+  inline int ImmedLField() const { return Bits(3, 0); }
+
+  // Fields used in Branch instructions
+  inline int LinkField() const { return Bit(24); }
+  inline int SImmed24Field() const { return ((InstructionBits() << 8) >> 8); }
+
+  // Fields used in Software interrupt instructions
+  inline SoftwareInterruptCodes SwiField() const {
+    return static_cast<SoftwareInterruptCodes>(Bits(23, 0));
+  }
+
+  // Test for special encodings of type 0 instructions (extra loads and stores,
+  // as well as multiplications).
+  inline bool IsSpecialType0() const { return (Bit(7) == 1) && (Bit(4) == 1); }
+
+  // Special accessors that test for existence of a value.
+  inline bool HasS()    const { return SField() == 1; }
+  inline bool HasB()    const { return BField() == 1; }
+  inline bool HasW()    const { return WField() == 1; }
+  inline bool HasL()    const { return LField() == 1; }
+  inline bool HasSign() const { return SignField() == 1; }
+  inline bool HasH()    const { return HField() == 1; }
+  inline bool HasLink() const { return LinkField() == 1; }
+
+  // Instructions are read of out a code stream. The only way to get a
+  // reference to an instruction is to convert a pointer. There is no way
+  // to allocate or create instances of class Instr.
+  // Use the At(pc) function to create references to Instr.
+  static Instr* At(byte* pc) { return reinterpret_cast<Instr*>(pc); }
+
+ private:
+  // We need to prevent the creation of instances of class Instr.
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Instr);
+};
+
+
+} }  // namespace assembler::arm
+
+#endif  // V8_CONSTANTS_ARM_H_
diff --git a/deps/v8/src/contexts.cc b/deps/v8/src/contexts.cc
new file mode 100644
index 0000000..36b5488
--- /dev/null
+++ b/deps/v8/src/contexts.cc
@@ -0,0 +1,252 @@
+// 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.
+
+#include "v8.h"
+
+#include "bootstrapper.h"
+#include "debug.h"
+#include "scopeinfo.h"
+
+namespace v8 { namespace internal {
+
+JSBuiltinsObject* Context::builtins() {
+  GlobalObject* object = global();
+  if (object->IsJSGlobalObject()) {
+    return JSGlobalObject::cast(object)->builtins();
+  } else {
+    ASSERT(object->IsJSBuiltinsObject());
+    return JSBuiltinsObject::cast(object);
+  }
+}
+
+
+Context* Context::global_context() {
+  // Fast case: the global object for this context has been set.  In
+  // that case, the global object has a direct pointer to the global
+  // context.
+  if (global()->IsGlobalObject()) {
+    return global()->global_context();
+  }
+  // During bootstrapping, the global object might not be set and we
+  // have to search the context chain to find the global context.
+  Context* current = this;
+  while (!current->IsGlobalContext()) {
+    current = Context::cast(JSFunction::cast(current->closure())->context());
+  }
+  return current;
+}
+
+
+JSObject* Context::global_proxy() {
+  return global_context()->global_proxy_object();
+}
+
+void Context::set_global_proxy(JSObject* object) {
+  global_context()->set_global_proxy_object(object);
+}
+
+
+Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
+                               int* index_, PropertyAttributes* attributes) {
+  Handle<Context> context(this);
+
+  bool follow_context_chain = (flags & FOLLOW_CONTEXT_CHAIN) != 0;
+  *index_ = -1;
+  *attributes = ABSENT;
+
+  if (FLAG_trace_contexts) {
+    PrintF("Context::Lookup(");
+    name->ShortPrint();
+    PrintF(")\n");
+  }
+
+  do {
+    if (FLAG_trace_contexts) {
+      PrintF(" - looking in context %p", *context);
+      if (context->IsGlobalContext()) PrintF(" (global context)");
+      PrintF("\n");
+    }
+
+    // check extension/with object
+    if (context->has_extension()) {
+      Handle<JSObject> extension = Handle<JSObject>(context->extension());
+      // Context extension objects needs to behave as if they have no
+      // prototype.  So even if we want to follow prototype chains, we
+      // need to only do a local lookup for context extension objects.
+      if ((flags & FOLLOW_PROTOTYPE_CHAIN) == 0 ||
+          extension->IsJSContextExtensionObject()) {
+        *attributes = extension->GetLocalPropertyAttribute(*name);
+      } else {
+        *attributes = extension->GetPropertyAttribute(*name);
+      }
+      if (*attributes != ABSENT) {
+        // property found
+        if (FLAG_trace_contexts) {
+          PrintF("=> found property in context object %p\n", *extension);
+        }
+        return extension;
+      }
+    }
+
+    if (context->is_function_context()) {
+      // we have context-local slots
+
+      // check non-parameter locals in context
+      Handle<Code> code(context->closure()->code());
+      Variable::Mode mode;
+      int index = ScopeInfo<>::ContextSlotIndex(*code, *name, &mode);
+      ASSERT(index < 0 || index >= MIN_CONTEXT_SLOTS);
+      if (index >= 0) {
+        // slot found
+        if (FLAG_trace_contexts) {
+          PrintF("=> found local in context slot %d (mode = %d)\n",
+                 index, mode);
+        }
+        *index_ = index;
+        // Note: Fixed context slots are statically allocated by the compiler.
+        // Statically allocated variables always have a statically known mode,
+        // which is the mode with which they were declared when added to the
+        // scope. Thus, the DYNAMIC mode (which corresponds to dynamically
+        // declared variables that were introduced through declaration nodes)
+        // must not appear here.
+        switch (mode) {
+          case Variable::INTERNAL:  // fall through
+          case Variable::VAR: *attributes = NONE; break;
+          case Variable::CONST: *attributes = READ_ONLY; break;
+          case Variable::DYNAMIC: UNREACHABLE(); break;
+          case Variable::DYNAMIC_GLOBAL: UNREACHABLE(); break;
+          case Variable::DYNAMIC_LOCAL: UNREACHABLE(); break;
+          case Variable::TEMPORARY: UNREACHABLE(); break;
+        }
+        return context;
+      }
+
+      // check parameter locals in context
+      int param_index = ScopeInfo<>::ParameterIndex(*code, *name);
+      if (param_index >= 0) {
+        // slot found
+        int index =
+            ScopeInfo<>::ContextSlotIndex(*code,
+                                          Heap::arguments_shadow_symbol(),
+                                          NULL);
+        ASSERT(index >= 0);  // arguments must exist and be in the heap context
+        Handle<JSObject> arguments(JSObject::cast(context->get(index)));
+        ASSERT(arguments->HasLocalProperty(Heap::length_symbol()));
+        if (FLAG_trace_contexts) {
+          PrintF("=> found parameter %d in arguments object\n", param_index);
+        }
+        *index_ = param_index;
+        *attributes = NONE;
+        return arguments;
+      }
+
+      // check intermediate context (holding only the function name variable)
+      if (follow_context_chain) {
+        int index = ScopeInfo<>::FunctionContextSlotIndex(*code, *name);
+        if (index >= 0) {
+          // slot found
+          if (FLAG_trace_contexts) {
+            PrintF("=> found intermediate function in context slot %d\n",
+                   index);
+          }
+          *index_ = index;
+          *attributes = READ_ONLY;
+          return context;
+        }
+      }
+    }
+
+    // proceed with enclosing context
+    if (context->IsGlobalContext()) {
+      follow_context_chain = false;
+    } else if (context->is_function_context()) {
+      context = Handle<Context>(Context::cast(context->closure()->context()));
+    } else {
+      context = Handle<Context>(context->previous());
+    }
+  } while (follow_context_chain);
+
+  // slot not found
+  if (FLAG_trace_contexts) {
+    PrintF("=> no property/slot found\n");
+  }
+  return Handle<Object>::null();
+}
+
+
+bool Context::GlobalIfNotShadowedByEval(Handle<String> name) {
+  Context* context = this;
+
+  // Check that there is no local with the given name in contexts
+  // before the global context and check that there are no context
+  // extension objects (conservative check for with statements).
+  while (!context->IsGlobalContext()) {
+    // Check if the context is a potentially a with context.
+    if (context->has_extension()) return false;
+
+    // Not a with context so it must be a function context.
+    ASSERT(context->is_function_context());
+
+    // Check non-parameter locals.
+    Handle<Code> code(context->closure()->code());
+    Variable::Mode mode;
+    int index = ScopeInfo<>::ContextSlotIndex(*code, *name, &mode);
+    ASSERT(index < 0 || index >= MIN_CONTEXT_SLOTS);
+    if (index >= 0) return false;
+
+    // Check parameter locals.
+    int param_index = ScopeInfo<>::ParameterIndex(*code, *name);
+    if (param_index >= 0) return false;
+
+    // Check context only holding the function name variable.
+    index = ScopeInfo<>::FunctionContextSlotIndex(*code, *name);
+    if (index >= 0) return false;
+    context = Context::cast(context->closure()->context());
+  }
+
+  // No local or potential with statement found so the variable is
+  // global unless it is shadowed by an eval-introduced variable.
+  return true;
+}
+
+
+#ifdef DEBUG
+bool Context::IsBootstrappingOrContext(Object* object) {
+  // During bootstrapping we allow all objects to pass as
+  // contexts. This is necessary to fix circular dependencies.
+  return Bootstrapper::IsActive() || object->IsContext();
+}
+
+
+bool Context::IsBootstrappingOrGlobalObject(Object* object) {
+  // During bootstrapping we allow all objects to pass as global
+  // objects. This is necessary to fix circular dependencies.
+  return Bootstrapper::IsActive() || object->IsGlobalObject();
+}
+#endif
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/contexts.h b/deps/v8/src/contexts.h
new file mode 100644
index 0000000..3c25bd3
--- /dev/null
+++ b/deps/v8/src/contexts.h
@@ -0,0 +1,335 @@
+// 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_CONTEXTS_H_
+#define V8_CONTEXTS_H_
+
+namespace v8 { namespace internal {
+
+
+enum ContextLookupFlags {
+  FOLLOW_CONTEXT_CHAIN = 1,
+  FOLLOW_PROTOTYPE_CHAIN = 2,
+
+  DONT_FOLLOW_CHAINS = 0,
+  FOLLOW_CHAINS = FOLLOW_CONTEXT_CHAIN | FOLLOW_PROTOTYPE_CHAIN
+};
+
+
+// Heap-allocated activation contexts.
+//
+// Contexts are implemented as FixedArray objects; the Context
+// class is a convenience interface casted on a FixedArray object.
+//
+// Note: Context must have no virtual functions and Context objects
+// must always be allocated via Heap::AllocateContext() or
+// Factory::NewContext.
+
+// Comment for special_function_table:
+// Table for providing optimized/specialized functions.
+// The array contains triplets [object, general_function, optimized_function].
+// Primarily added to support built-in optimized variants of
+// Array.prototype.{push,pop}.
+
+#define GLOBAL_CONTEXT_FIELDS(V) \
+  V(GLOBAL_PROXY_INDEX, JSObject, global_proxy_object) \
+  V(SECURITY_TOKEN_INDEX, Object, security_token) \
+  V(BOOLEAN_FUNCTION_INDEX, JSFunction, boolean_function) \
+  V(NUMBER_FUNCTION_INDEX, JSFunction, number_function) \
+  V(STRING_FUNCTION_INDEX, JSFunction, string_function) \
+  V(OBJECT_FUNCTION_INDEX, JSFunction, object_function) \
+  V(ARRAY_FUNCTION_INDEX, JSFunction, array_function) \
+  V(DATE_FUNCTION_INDEX, JSFunction, date_function) \
+  V(REGEXP_FUNCTION_INDEX, JSFunction, regexp_function) \
+  V(INITIAL_OBJECT_PROTOTYPE_INDEX, JSObject, initial_object_prototype) \
+  V(CREATE_DATE_FUN_INDEX, JSFunction,  create_date_fun) \
+  V(TO_NUMBER_FUN_INDEX, JSFunction, to_number_fun) \
+  V(TO_STRING_FUN_INDEX, JSFunction, to_string_fun) \
+  V(TO_DETAIL_STRING_FUN_INDEX, JSFunction, to_detail_string_fun) \
+  V(TO_OBJECT_FUN_INDEX, JSFunction, to_object_fun) \
+  V(TO_INTEGER_FUN_INDEX, JSFunction, to_integer_fun) \
+  V(TO_UINT32_FUN_INDEX, JSFunction, to_uint32_fun) \
+  V(TO_INT32_FUN_INDEX, JSFunction, to_int32_fun) \
+  V(TO_BOOLEAN_FUN_INDEX, JSFunction, to_boolean_fun) \
+  V(INSTANTIATE_FUN_INDEX, JSFunction, instantiate_fun) \
+  V(CONFIGURE_INSTANCE_FUN_INDEX, JSFunction, configure_instance_fun) \
+  V(FUNCTION_MAP_INDEX, Map, function_map) \
+  V(FUNCTION_INSTANCE_MAP_INDEX, Map, function_instance_map) \
+  V(JS_ARRAY_MAP_INDEX, Map, js_array_map)\
+  V(SPECIAL_FUNCTION_TABLE_INDEX, FixedArray, special_function_table) \
+  V(ARGUMENTS_BOILERPLATE_INDEX, JSObject, arguments_boilerplate) \
+  V(MESSAGE_LISTENERS_INDEX, JSObject, message_listeners) \
+  V(MAKE_MESSAGE_FUN_INDEX, JSFunction, make_message_fun) \
+  V(GET_STACK_TRACE_LINE_INDEX, JSFunction, get_stack_trace_line_fun) \
+  V(CONFIGURE_GLOBAL_INDEX, JSFunction, configure_global_fun) \
+  V(FUNCTION_CACHE_INDEX, JSObject, function_cache) \
+  V(RUNTIME_CONTEXT_INDEX, Context, runtime_context) \
+  V(CALL_AS_FUNCTION_DELEGATE_INDEX, JSFunction, call_as_function_delegate) \
+  V(EMPTY_SCRIPT_INDEX, Script, empty_script) \
+  V(SCRIPT_FUNCTION_INDEX, JSFunction, script_function) \
+  V(CONTEXT_EXTENSION_FUNCTION_INDEX, JSFunction, context_extension_function) \
+  V(OUT_OF_MEMORY_INDEX, Object, out_of_memory) \
+  V(MAP_CACHE_INDEX, Object, map_cache)
+
+// JSFunctions are pairs (context, function code), sometimes also called
+// closures. A Context object is used to represent function contexts and
+// dynamically pushed 'with' contexts (or 'scopes' in ECMA-262 speak).
+//
+// At runtime, the contexts build a stack in parallel to the execution
+// stack, with the top-most context being the current context. All contexts
+// have the following slots:
+//
+// [ closure   ]  This is the current function. It is the same for all
+//                contexts inside a function. It provides access to the
+//                incoming context (i.e., the outer context, which may
+//                or may not become the current function's context), and
+//                it provides access to the functions code and thus it's
+//                scope information, which in turn contains the names of
+//                statically allocated context slots. The names are needed
+//                for dynamic lookups in the presence of 'with' or 'eval'.
+//
+// [ fcontext  ]  A pointer to the innermost enclosing function context.
+//                It is the same for all contexts *allocated* inside a
+//                function, and the function context's fcontext points
+//                to itself. It is only needed for fast access of the
+//                function context (used for declarations, and static
+//                context slot access).
+//
+// [ previous  ]  A pointer to the previous context. It is NULL for
+//                function contexts, and non-NULL for 'with' contexts.
+//                Used to implement the 'with' statement.
+//
+// [ extension ]  A pointer to an extension JSObject, or NULL. Used to
+//                implement 'with' statements and dynamic declarations
+//                (through 'eval'). The object in a 'with' statement is
+//                stored in the extension slot of a 'with' context.
+//                Dynamically declared variables/functions are also added
+//                to lazily allocated extension object. Context::Lookup
+//                searches the extension object for properties.
+//
+// [ global    ]  A pointer to the global object. Provided for quick
+//                access to the global object from inside the code (since
+//                we always have a context pointer).
+//
+// In addition, function contexts may have statically allocated context slots
+// to store local variables/functions that are accessed from inner functions
+// (via static context addresses) or through 'eval' (dynamic context lookups).
+// Finally, the global context contains additional slots for fast access to
+// global properties.
+//
+// We may be able to simplify the implementation:
+//
+// - We may be able to get rid of 'fcontext': We can always use the fact that
+//   previous == NULL for function contexts and so we can search for them. They
+//   are only needed when doing dynamic declarations, and the context chains
+//   tend to be very very short (depth of nesting of 'with' statements). At
+//   the moment we also use it in generated code for context slot accesses -
+//   and there we don't want a loop because of code bloat - but we may not
+//   need it there after all (see comment in codegen_*.cc).
+//
+// - If we cannot get rid of fcontext, consider making 'previous' never NULL
+//   except for the global context. This could simplify Context::Lookup.
+
+class Context: public FixedArray {
+ public:
+  // Conversions.
+  static Context* cast(Object* context) {
+    ASSERT(context->IsContext());
+    return reinterpret_cast<Context*>(context);
+  }
+
+  // The default context slot layout; indices are FixedArray slot indices.
+  enum {
+    // These slots are in all contexts.
+    CLOSURE_INDEX,
+    FCONTEXT_INDEX,
+    PREVIOUS_INDEX,
+    EXTENSION_INDEX,
+    GLOBAL_INDEX,
+    MIN_CONTEXT_SLOTS,
+
+    // These slots are only in global contexts.
+    GLOBAL_PROXY_INDEX = MIN_CONTEXT_SLOTS,
+    SECURITY_TOKEN_INDEX,
+    ARGUMENTS_BOILERPLATE_INDEX,
+    JS_ARRAY_MAP_INDEX,
+    FUNCTION_MAP_INDEX,
+    FUNCTION_INSTANCE_MAP_INDEX,
+    INITIAL_OBJECT_PROTOTYPE_INDEX,
+    BOOLEAN_FUNCTION_INDEX,
+    NUMBER_FUNCTION_INDEX,
+    STRING_FUNCTION_INDEX,
+    OBJECT_FUNCTION_INDEX,
+    ARRAY_FUNCTION_INDEX,
+    DATE_FUNCTION_INDEX,
+    REGEXP_FUNCTION_INDEX,
+    CREATE_DATE_FUN_INDEX,
+    TO_NUMBER_FUN_INDEX,
+    TO_STRING_FUN_INDEX,
+    TO_DETAIL_STRING_FUN_INDEX,
+    TO_OBJECT_FUN_INDEX,
+    TO_INTEGER_FUN_INDEX,
+    TO_UINT32_FUN_INDEX,
+    TO_INT32_FUN_INDEX,
+    TO_BOOLEAN_FUN_INDEX,
+    INSTANTIATE_FUN_INDEX,
+    CONFIGURE_INSTANCE_FUN_INDEX,
+    SPECIAL_FUNCTION_TABLE_INDEX,
+    MESSAGE_LISTENERS_INDEX,
+    MAKE_MESSAGE_FUN_INDEX,
+    GET_STACK_TRACE_LINE_INDEX,
+    CONFIGURE_GLOBAL_INDEX,
+    FUNCTION_CACHE_INDEX,
+    RUNTIME_CONTEXT_INDEX,
+    CALL_AS_FUNCTION_DELEGATE_INDEX,
+    EMPTY_SCRIPT_INDEX,
+    SCRIPT_FUNCTION_INDEX,
+    CONTEXT_EXTENSION_FUNCTION_INDEX,
+    OUT_OF_MEMORY_INDEX,
+    MAP_CACHE_INDEX,
+    GLOBAL_CONTEXT_SLOTS
+  };
+
+  // Direct slot access.
+  JSFunction* closure() { return JSFunction::cast(get(CLOSURE_INDEX)); }
+  void set_closure(JSFunction* closure) { set(CLOSURE_INDEX, closure); }
+
+  Context* fcontext() { return Context::cast(get(FCONTEXT_INDEX)); }
+  void set_fcontext(Context* context) { set(FCONTEXT_INDEX, context); }
+
+  Context* previous() {
+    Object* result = unchecked_previous();
+    ASSERT(IsBootstrappingOrContext(result));
+    return reinterpret_cast<Context*>(result);
+  }
+  void set_previous(Context* context) { set(PREVIOUS_INDEX, context); }
+
+  bool has_extension() { return unchecked_extension() != NULL; }
+  JSObject* extension() { return JSObject::cast(unchecked_extension()); }
+  void set_extension(JSObject* object) { set(EXTENSION_INDEX, object); }
+
+  GlobalObject* global() {
+    Object* result = get(GLOBAL_INDEX);
+    ASSERT(IsBootstrappingOrGlobalObject(result));
+    return reinterpret_cast<GlobalObject*>(result);
+  }
+  void set_global(GlobalObject* global) { set(GLOBAL_INDEX, global); }
+
+  // Returns a JSGlobalProxy object or null.
+  JSObject* global_proxy();
+  void set_global_proxy(JSObject* global);
+
+  // The builtins object.
+  JSBuiltinsObject* builtins();
+
+  // Compute the global context by traversing the context chain.
+  Context* global_context();
+
+  // Tells if this is a function context (as opposed to a 'with' context).
+  bool is_function_context() { return unchecked_previous() == NULL; }
+
+  // Tells whether the global context is marked with out of memory.
+  bool has_out_of_memory() {
+    return global_context()->out_of_memory() == Heap::true_value();
+  }
+
+  // Mark the global context with out of memory.
+  void mark_out_of_memory() {
+    global_context()->set_out_of_memory(Heap::true_value());
+  }
+
+  // The exception holder is the object used as a with object in
+  // the implementation of a catch block.
+  bool is_exception_holder(Object* object) {
+    return IsCatchContext() && extension() == object;
+  }
+
+#define GLOBAL_CONTEXT_FIELD_ACCESSORS(index, type, name) \
+  void  set_##name(type* value) {                         \
+    ASSERT(IsGlobalContext());                            \
+    set(index, value);                                    \
+  }                                                       \
+  type* name() {                                          \
+    ASSERT(IsGlobalContext());                            \
+    return type::cast(get(index));                        \
+  }
+  GLOBAL_CONTEXT_FIELDS(GLOBAL_CONTEXT_FIELD_ACCESSORS)
+#undef GLOBAL_CONTEXT_FIELD_ACCESSORS
+
+  // Lookup the the slot called name, starting with the current context.
+  // There are 4 possible outcomes:
+  //
+  // 1) index_ >= 0 && result->IsContext():
+  //    most common case, the result is a Context, and index is the
+  //    context slot index, and the slot exists.
+  //    attributes == READ_ONLY for the function name variable, NONE otherwise.
+  //
+  // 2) index_ >= 0 && result->IsJSObject():
+  //    the result is the JSObject arguments object, the index is the parameter
+  //    index, i.e., key into the arguments object, and the property exists.
+  //    attributes != ABSENT.
+  //
+  // 3) index_ < 0 && result->IsJSObject():
+  //    the result is the JSObject extension context or the global object,
+  //    and the name is the property name, and the property exists.
+  //    attributes != ABSENT.
+  //
+  // 4) index_ < 0 && result.is_null():
+  //    there was no context found with the corresponding property.
+  //    attributes == ABSENT.
+  Handle<Object> Lookup(Handle<String> name, ContextLookupFlags flags,
+                        int* index_, PropertyAttributes* attributes);
+
+  // Determine if a local variable with the given name exists in a
+  // context.  Do not consider context extension objects.  This is
+  // used for compiling code using eval.  If the context surrounding
+  // the eval call does not have a local variable with this name and
+  // does not contain a with statement the property is global unless
+  // it is shadowed by a property in an extension object introduced by
+  // eval.
+  bool GlobalIfNotShadowedByEval(Handle<String> name);
+
+  // Code generation support.
+  static int SlotOffset(int index) {
+    return kHeaderSize + index * kPointerSize - kHeapObjectTag;
+  }
+
+ private:
+  // Unchecked access to the slots.
+  Object* unchecked_previous() { return get(PREVIOUS_INDEX); }
+  Object* unchecked_extension() { return get(EXTENSION_INDEX); }
+
+#ifdef DEBUG
+  // Bootstrapping-aware type checks.
+  static bool IsBootstrappingOrContext(Object* object);
+  static bool IsBootstrappingOrGlobalObject(Object* object);
+#endif
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_CONTEXTS_H_
diff --git a/deps/v8/src/conversions-inl.h b/deps/v8/src/conversions-inl.h
new file mode 100644
index 0000000..64e4a79
--- /dev/null
+++ b/deps/v8/src/conversions-inl.h
@@ -0,0 +1,94 @@
+// 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_CONVERSIONS_INL_H_
+#define V8_CONVERSIONS_INL_H_
+
+#include <math.h>
+#include <float.h>         // required for DBL_MAX and on Win32 for finite()
+#include <stdarg.h>
+
+// ----------------------------------------------------------------------------
+// Extra POSIX/ANSI functions for Win32/MSVC.
+
+#include "conversions.h"
+#include "platform.h"
+
+namespace v8 { namespace internal {
+
+// The fast double-to-int conversion routine does not guarantee
+// rounding towards zero.
+static inline int FastD2I(double x) {
+#ifdef __USE_ISOC99
+  // The ISO C99 standard defines the lrint() function which rounds a
+  // double to an integer according to the current rounding direction.
+  return lrint(x);
+#else
+  // This is incredibly slow on Intel x86. The reason is that rounding
+  // towards zero is implied by the C standard. This means that the
+  // status register of the FPU has to be changed with the 'fldcw'
+  // instruction. This completely stalls the pipeline and takes many
+  // hundreds of clock cycles.
+  return static_cast<int>(x);
+#endif
+}
+
+
+static inline double DoubleToInteger(double x) {
+  if (isnan(x)) return 0;
+  if (!isfinite(x) || x == 0) return x;
+  return (x >= 0) ? floor(x) : ceil(x);
+}
+
+
+int32_t NumberToInt32(Object* number) {
+  if (number->IsSmi()) return Smi::cast(number)->value();
+  return DoubleToInt32(number->Number());
+}
+
+
+uint32_t NumberToUint32(Object* number) {
+  if (number->IsSmi()) return Smi::cast(number)->value();
+  return DoubleToUint32(number->Number());
+}
+
+
+int32_t DoubleToInt32(double x) {
+  int32_t i = FastD2I(x);
+  if (FastI2D(i) == x) return i;
+  static const double two32 = 4294967296.0;
+  static const double two31 = 2147483648.0;
+  if (!isfinite(x) || x == 0) return 0;
+  if (x < 0 || x >= two32) x = fmod(x, two32);
+  x = (x >= 0) ? floor(x) : ceil(x) + two32;
+  return (int32_t) ((x >= two31) ? x - two32 : x);
+}
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_CONVERSIONS_INL_H_
diff --git a/deps/v8/src/conversions.cc b/deps/v8/src/conversions.cc
new file mode 100644
index 0000000..57a4568
--- /dev/null
+++ b/deps/v8/src/conversions.cc
@@ -0,0 +1,707 @@
+// 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.
+
+#include <stdarg.h>
+
+#include "v8.h"
+
+#include "conversions-inl.h"
+#include "factory.h"
+#include "scanner.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;
+}
+
+
+// Provide a common interface to getting a character at a certain
+// index from a char* or a String object.
+static inline int GetChar(const char* str, int index) {
+  ASSERT(index >= 0 && index < static_cast<int>(strlen(str)));
+  return str[index];
+}
+
+
+static inline int GetChar(String* str, int index) {
+  return str->Get(index);
+}
+
+
+static inline int GetLength(const char* str) {
+  return strlen(str);
+}
+
+
+static inline int GetLength(String* str) {
+  return str->length();
+}
+
+
+static inline const char* GetCString(const char* str, int index) {
+  return str + index;
+}
+
+
+static inline const char* GetCString(String* str, int index) {
+  int length = str->length();
+  char* result = NewArray<char>(length + 1);
+  for (int i = index; i < length; i++) {
+    uc16 c = str->Get(i);
+    if (c <= 127) {
+      result[i - index] = static_cast<char>(c);
+    } else {
+      result[i - index] = 127;  // Force number parsing to fail.
+    }
+  }
+  result[length - index] = '\0';
+  return result;
+}
+
+
+static inline void ReleaseCString(const char* original, const char* str) {
+}
+
+
+static inline void ReleaseCString(String* original, const char* str) {
+  DeleteArray(const_cast<char *>(str));
+}
+
+
+static inline bool IsSpace(const char* str, int index) {
+  ASSERT(index >= 0 && index < static_cast<int>(strlen(str)));
+  return Scanner::kIsWhiteSpace.get(str[index]);
+}
+
+
+static inline bool IsSpace(String* str, int index) {
+  return Scanner::kIsWhiteSpace.get(str->Get(index));
+}
+
+
+static inline bool SubStringEquals(const char* str,
+                                   int index,
+                                   const char* other) {
+  return strncmp(str + index, other, strlen(other)) != 0;
+}
+
+
+static inline bool SubStringEquals(String* str, int index, const char* other) {
+  HandleScope scope;
+  int str_length = str->length();
+  int other_length = strlen(other);
+  int end = index + other_length < str_length ?
+            index + other_length :
+            str_length;
+  Handle<String> slice =
+      Factory::NewStringSlice(Handle<String>(str), index, end);
+  return slice->IsEqualTo(Vector<const char>(other, other_length));
+}
+
+
+// Check if a string should be parsed as an octal number.  The string
+// can be either a char* or a String*.
+template<class S>
+static bool ShouldParseOctal(S* s, int i) {
+  int index = i;
+  int len = GetLength(s);
+  if (index < len && GetChar(s, index) != '0') return false;
+
+  // If the first real character (following '0') is not an octal
+  // digit, bail out early. This also takes care of numbers of the
+  // forms 0.xxx and 0exxx by not allowing the first 0 to be
+  // interpreted as an octal.
+  index++;
+  if (index < len) {
+    int d = GetChar(s, index) - '0';
+    if (d < 0 || d > 7) return false;
+  } else {
+    return false;
+  }
+
+  // Traverse all digits (including the first). If there is an octal
+  // prefix which is not a part of a longer decimal prefix, we return
+  // true. Otherwise, false is returned.
+  while (index < len) {
+    int d = GetChar(s, index++) - '0';
+    if (d == 8 || d == 9) return false;
+    if (d <  0 || d >  7) return true;
+  }
+  return true;
+}
+
+
+extern "C" double gay_strtod(const char* s00, const char** se);
+
+
+// Parse an int from a string starting a given index and in a given
+// radix.  The string can be either a char* or a String*.
+template <class S>
+static int InternalStringToInt(S* s, int i, int radix, double* value) {
+  int len = GetLength(s);
+
+  // Setup limits for computing the value.
+  ASSERT(2 <= radix && radix <= 36);
+  int lim_0 = '0' + (radix < 10 ? radix : 10);
+  int lim_a = 'a' + (radix - 10);
+  int lim_A = 'A' + (radix - 10);
+
+  // NOTE: The code for computing the value may seem a bit complex at
+  // first glance. It is structured to use 32-bit multiply-and-add
+  // loops as long as possible to avoid loosing precision.
+
+  double v = 0.0;
+  int j;
+  for (j = i; j < len;) {
+    // Parse the longest part of the string starting at index j
+    // possible while keeping the multiplier, and thus the part
+    // itself, within 32 bits.
+    uint32_t part = 0, multiplier = 1;
+    int k;
+    for (k = j; k < len; k++) {
+      int c = GetChar(s, k);
+      if (c >= '0' && c < lim_0) {
+        c = c - '0';
+      } else if (c >= 'a' && c < lim_a) {
+        c = c - 'a' + 10;
+      } else if (c >= 'A' && c < lim_A) {
+        c = c - 'A' + 10;
+      } else {
+        break;
+      }
+
+      // Update the value of the part as long as the multiplier fits
+      // in 32 bits. When we can't guarantee that the next iteration
+      // will not overflow the multiplier, we stop parsing the part
+      // by leaving the loop.
+      static const uint32_t kMaximumMultiplier = 0xffffffffU / 36;
+      uint32_t m = multiplier * radix;
+      if (m > kMaximumMultiplier) break;
+      part = part * radix + c;
+      multiplier = m;
+      ASSERT(multiplier > part);
+    }
+
+    // Compute the number of part digits. If no digits were parsed;
+    // we're done parsing the entire string.
+    int digits = k - j;
+    if (digits == 0) break;
+
+    // Update the value and skip the part in the string.
+    ASSERT(multiplier ==
+           pow(static_cast<double>(radix), static_cast<double>(digits)));
+    v = v * multiplier + part;
+    j = k;
+  }
+
+  // If the resulting value is larger than 2^53 the value does not fit
+  // in the mantissa of the double and there is a loss of precision.
+  // When the value is larger than 2^53 the rounding depends on the
+  // code generation.  If the code generator spills the double value
+  // it uses 64 bits and if it does not it uses 80 bits.
+  //
+  // If there is a potential for overflow we resort to strtod for
+  // radix 10 numbers to get higher precision.  For numbers in another
+  // radix we live with the loss of precision.
+  static const double kPreciseConversionLimit = 9007199254740992.0;
+  if (radix == 10 && v > kPreciseConversionLimit) {
+    const char* cstr = GetCString(s, i);
+    const char* end;
+    v = gay_strtod(cstr, &end);
+    ReleaseCString(s, cstr);
+  }
+
+  *value = v;
+  return j;
+}
+
+
+int StringToInt(String* str, int index, int radix, double* value) {
+  return InternalStringToInt(str, index, radix, value);
+}
+
+
+int StringToInt(const char* str, int index, int radix, double* value) {
+  return InternalStringToInt(const_cast<char*>(str), index, radix, value);
+}
+
+
+static const double JUNK_STRING_VALUE = OS::nan_value();
+
+
+// Convert a string to a double value.  The string can be either a
+// char* or a String*.
+template<class S>
+static double InternalStringToDouble(S* str,
+                                     int flags,
+                                     double empty_string_val) {
+  double result = 0.0;
+  int index = 0;
+
+  int len = GetLength(str);
+
+  // Skip leading spaces.
+  while ((index < len) && IsSpace(str, index)) index++;
+
+  // Is the string empty?
+  if (index >= len) return empty_string_val;
+
+  // Get the first character.
+  uint16_t first = GetChar(str, index);
+
+  // Numbers can only start with '-', '+', '.', 'I' (Infinity), or a digit.
+  if (first != '-' && first != '+' && first != '.' && first != 'I' &&
+      (first > '9' || first < '0')) {
+    return JUNK_STRING_VALUE;
+  }
+
+  // Compute sign of result based on first character.
+  int sign = 1;
+  if (first == '-') {
+    sign = -1;
+    index++;
+    // String only containing a '-' are junk chars.
+    if (index == len) return JUNK_STRING_VALUE;
+  }
+
+  // do we have a hex number?
+  // (since the string is 0-terminated, it's ok to look one char beyond the end)
+  if ((flags & ALLOW_HEX) != 0 &&
+      (index + 1) < len &&
+      GetChar(str, index) == '0' &&
+      (GetChar(str, index + 1) == 'x' || GetChar(str, index + 1) == 'X')) {
+    index += 2;
+    index = StringToInt(str, index, 16, &result);
+  } else if ((flags & ALLOW_OCTALS) != 0 && ShouldParseOctal(str, index)) {
+    // NOTE: We optimistically try to parse the number as an octal (if
+    // we're allowed to), even though this is not as dictated by
+    // ECMA-262. The reason for doing this is compatibility with IE and
+    // Firefox.
+    index = StringToInt(str, index, 8, &result);
+  } else {
+    const char* cstr = GetCString(str, index);
+    const char* end;
+    // Optimistically parse the number and then, if that fails,
+    // check if it might have been {+,-,}Infinity.
+    result = gay_strtod(cstr, &end);
+    ReleaseCString(str, cstr);
+    if (result != 0.0 || end != cstr) {
+      // It appears that strtod worked
+      index += end - cstr;
+    } else {
+      // Check for {+,-,}Infinity
+      bool is_negative = (GetChar(str, index) == '-');
+      if (GetChar(str, index) == '+' || GetChar(str, index) == '-')
+        index++;
+      if (!SubStringEquals(str, index, "Infinity"))
+        return JUNK_STRING_VALUE;
+      result = is_negative ? -INFINITY : INFINITY;
+      index += 8;
+    }
+  }
+
+  if ((flags & ALLOW_TRAILING_JUNK) == 0) {
+    // skip trailing spaces
+    while ((index < len) && IsSpace(str, index)) index++;
+    // string ending with junk?
+    if (index < len) return JUNK_STRING_VALUE;
+  }
+
+  return sign * result;
+}
+
+
+double StringToDouble(String* str, int flags, double empty_string_val) {
+  return InternalStringToDouble(str, flags, empty_string_val);
+}
+
+
+double StringToDouble(const char* str, int flags, double empty_string_val) {
+  return InternalStringToDouble(str, flags, empty_string_val);
+}
+
+
+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());
+
+  switch (fpclassify(v)) {
+    case FP_NAN:
+      builder.AddString("NaN");
+      break;
+
+    case FP_INFINITE:
+      if (v < 0.0) {
+        builder.AddString("-Infinity");
+      } else {
+        builder.AddString("Infinity");
+      }
+      break;
+
+    case FP_ZERO:
+      builder.AddCharacter('0');
+      break;
+
+    default: {
+      int decimal_point;
+      int sign;
+
+      char* decimal_rep = dtoa(v, 0, 0, &decimal_point, &sign, NULL);
+      int length = strlen(decimal_rep);
+
+      if (sign) builder.AddCharacter('-');
+
+      if (length <= decimal_point && decimal_point <= 21) {
+        // ECMA-262 section 9.8.1 step 6.
+        builder.AddString(decimal_rep);
+        builder.AddPadding('0', decimal_point - length);
+
+      } else if (0 < decimal_point && decimal_point <= 21) {
+        // ECMA-262 section 9.8.1 step 7.
+        builder.AddSubstring(decimal_rep, decimal_point);
+        builder.AddCharacter('.');
+        builder.AddString(decimal_rep + decimal_point);
+
+      } else if (decimal_point <= 0 && decimal_point > -6) {
+        // ECMA-262 section 9.8.1 step 8.
+        builder.AddString("0.");
+        builder.AddPadding('0', -decimal_point);
+        builder.AddString(decimal_rep);
+
+      } else {
+        // ECMA-262 section 9.8.1 step 9 and 10 combined.
+        builder.AddCharacter(decimal_rep[0]);
+        if (length != 1) {
+          builder.AddCharacter('.');
+          builder.AddString(decimal_rep + 1);
+        }
+        builder.AddCharacter('e');
+        builder.AddCharacter((decimal_point >= 0) ? '+' : '-');
+        int exponent = decimal_point - 1;
+        if (exponent < 0) exponent = -exponent;
+        builder.AddFormatted("%d", exponent);
+      }
+
+      freedtoa(decimal_rep);
+    }
+  }
+  return builder.Finalize();
+}
+
+
+const char* IntToCString(int n, Vector<char> buffer) {
+  bool negative = false;
+  if (n < 0) {
+    // We must not negate the most negative int.
+    if (n == kMinInt) return DoubleToCString(n, buffer);
+    negative = true;
+    n = -n;
+  }
+  // Build the string backwards from the least significant digit.
+  int i = buffer.length();
+  buffer[--i] = '\0';
+  do {
+    buffer[--i] = '0' + (n % 10);
+    n /= 10;
+  } while (n);
+  if (negative) buffer[--i] = '-';
+  return buffer.start() + i;
+}
+
+
+char* DoubleToFixedCString(double value, int f) {
+  ASSERT(f >= 0);
+
+  bool negative = false;
+  double abs_value = value;
+  if (value < 0) {
+    abs_value = -value;
+    negative = true;
+  }
+
+  if (abs_value >= 1e21) {
+    char arr[100];
+    Vector<char> buffer(arr, ARRAY_SIZE(arr));
+    return StrDup(DoubleToCString(value, buffer));
+  }
+
+  // Find a sufficiently precise decimal representation of n.
+  int decimal_point;
+  int sign;
+  char* decimal_rep = dtoa(abs_value, 3, f, &decimal_point, &sign, NULL);
+  int decimal_rep_length = strlen(decimal_rep);
+
+  // Create a representation that is padded with zeros if needed.
+  int zero_prefix_length = 0;
+  int zero_postfix_length = 0;
+
+  if (decimal_point <= 0) {
+    zero_prefix_length = -decimal_point + 1;
+    decimal_point = 1;
+  }
+
+  if (zero_prefix_length + decimal_rep_length < decimal_point + f) {
+    zero_postfix_length = decimal_point + f - decimal_rep_length -
+                          zero_prefix_length;
+  }
+
+  unsigned rep_length =
+      zero_prefix_length + decimal_rep_length + zero_postfix_length;
+  StringBuilder rep_builder(rep_length + 1);
+  rep_builder.AddPadding('0', zero_prefix_length);
+  rep_builder.AddString(decimal_rep);
+  rep_builder.AddPadding('0', zero_postfix_length);
+  char* rep = rep_builder.Finalize();
+  freedtoa(decimal_rep);
+
+  // Create the result string by appending a minus and putting in a
+  // decimal point if needed.
+  unsigned result_size = decimal_point + f + 2;
+  StringBuilder builder(result_size + 1);
+  if (negative) builder.AddCharacter('-');
+  builder.AddSubstring(rep, decimal_point);
+  if (f > 0) {
+    builder.AddCharacter('.');
+    builder.AddSubstring(rep + decimal_point, f);
+  }
+  DeleteArray(rep);
+  return builder.Finalize();
+}
+
+
+static char* CreateExponentialRepresentation(char* decimal_rep,
+                                             int exponent,
+                                             bool negative,
+                                             int significant_digits) {
+  bool negative_exponent = false;
+  if (exponent < 0) {
+    negative_exponent = true;
+    exponent = -exponent;
+  }
+
+  // Leave room in the result for appending a minus, for a period, the
+  // letter 'e', a minus or a plus depending on the exponent, and a
+  // three digit exponent.
+  unsigned result_size = significant_digits + 7;
+  StringBuilder builder(result_size + 1);
+
+  if (negative) builder.AddCharacter('-');
+  builder.AddCharacter(decimal_rep[0]);
+  if (significant_digits != 1) {
+    builder.AddCharacter('.');
+    builder.AddString(decimal_rep + 1);
+    builder.AddPadding('0', significant_digits - strlen(decimal_rep));
+  }
+
+  builder.AddCharacter('e');
+  builder.AddCharacter(negative_exponent ? '-' : '+');
+  builder.AddFormatted("%d", exponent);
+  return builder.Finalize();
+}
+
+
+
+char* DoubleToExponentialCString(double value, int f) {
+  // f might be -1 to signal that f was undefined in JavaScript.
+  ASSERT(f >= -1 && f <= 20);
+
+  bool negative = false;
+  if (value < 0) {
+    value = -value;
+    negative = true;
+  }
+
+  // Find a sufficiently precise decimal representation of n.
+  int decimal_point;
+  int sign;
+  char* decimal_rep = NULL;
+  if (f == -1) {
+    decimal_rep = dtoa(value, 0, 0, &decimal_point, &sign, NULL);
+    f = strlen(decimal_rep) - 1;
+  } else {
+    decimal_rep = dtoa(value, 2, f + 1, &decimal_point, &sign, NULL);
+  }
+  int decimal_rep_length = strlen(decimal_rep);
+  ASSERT(decimal_rep_length > 0);
+  ASSERT(decimal_rep_length <= f + 1);
+  USE(decimal_rep_length);
+
+  int exponent = decimal_point - 1;
+  char* result =
+      CreateExponentialRepresentation(decimal_rep, exponent, negative, f+1);
+
+  freedtoa(decimal_rep);
+
+  return result;
+}
+
+
+char* DoubleToPrecisionCString(double value, int p) {
+  ASSERT(p >= 1 && p <= 21);
+
+  bool negative = false;
+  if (value < 0) {
+    value = -value;
+    negative = true;
+  }
+
+  // Find a sufficiently precise decimal representation of n.
+  int decimal_point;
+  int sign;
+  char* decimal_rep = dtoa(value, 2, p, &decimal_point, &sign, NULL);
+  int decimal_rep_length = strlen(decimal_rep);
+  ASSERT(decimal_rep_length <= p);
+
+  int exponent = decimal_point - 1;
+
+  char* result = NULL;
+
+  if (exponent < -6 || exponent >= p) {
+    result =
+        CreateExponentialRepresentation(decimal_rep, exponent, negative, p);
+  } else {
+    // Use fixed notation.
+    //
+    // Leave room in the result for appending a minus, a period and in
+    // the case where decimal_point is not positive for a zero in
+    // front of the period.
+    unsigned result_size = (decimal_point <= 0)
+        ? -decimal_point + p + 3
+        : p + 2;
+    StringBuilder builder(result_size + 1);
+    if (negative) builder.AddCharacter('-');
+    if (decimal_point <= 0) {
+      builder.AddString("0.");
+      builder.AddPadding('0', -decimal_point);
+      builder.AddString(decimal_rep);
+      builder.AddPadding('0', p - decimal_rep_length);
+    } else {
+      const int m = Min(decimal_rep_length, decimal_point);
+      builder.AddSubstring(decimal_rep, m);
+      builder.AddPadding('0', decimal_point - decimal_rep_length);
+      if (decimal_point < p) {
+        builder.AddCharacter('.');
+        const int extra = negative ? 2 : 1;
+        if (decimal_rep_length > decimal_point) {
+          const int len = strlen(decimal_rep + decimal_point);
+          const int n = Min(len, p - (builder.position() - extra));
+          builder.AddSubstring(decimal_rep + decimal_point, n);
+        }
+        builder.AddPadding('0', extra + (p - builder.position()));
+      }
+    }
+    result = builder.Finalize();
+  }
+
+  freedtoa(decimal_rep);
+  return result;
+}
+
+
+char* DoubleToRadixCString(double value, int radix) {
+  ASSERT(radix >= 2 && radix <= 36);
+
+  // Character array used for conversion.
+  static const char chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+
+  // Buffer for the integer part of the result. 1024 chars is enough
+  // for max integer value in radix 2.  We need room for a sign too.
+  static const int kBufferSize = 1100;
+  char integer_buffer[kBufferSize];
+  integer_buffer[kBufferSize - 1] = '\0';
+
+  // Buffer for the decimal part of the result.  We only generate up
+  // to kBufferSize - 1 chars for the decimal part.
+  char decimal_buffer[kBufferSize];
+  decimal_buffer[kBufferSize - 1] = '\0';
+
+  // Make sure the value is positive.
+  bool is_negative = value < 0.0;
+  if (is_negative) value = -value;
+
+  // Get the integer part and the decimal part.
+  double integer_part = floor(value);
+  double decimal_part = value - integer_part;
+
+  // Convert the integer part starting from the back.  Always generate
+  // at least one digit.
+  int integer_pos = kBufferSize - 2;
+  do {
+    integer_buffer[integer_pos--] =
+        chars[static_cast<int>(fmod(integer_part, radix))];
+    integer_part /= radix;
+  } while (integer_part >= 1.0);
+  // Sanity check.
+  ASSERT(integer_pos > 0);
+  // Add sign if needed.
+  if (is_negative) integer_buffer[integer_pos--] = '-';
+
+  // Convert the decimal part.  Repeatedly multiply by the radix to
+  // generate the next char.  Never generate more than kBufferSize - 1
+  // chars.
+  //
+  // TODO(1093998): We will often generate a full decimal_buffer of
+  // chars because hitting zero will often not happen.  The right
+  // solution would be to continue until the string representation can
+  // be read back and yield the original value.  To implement this
+  // efficiently, we probably have to modify dtoa.
+  int decimal_pos = 0;
+  while ((decimal_part > 0.0) && (decimal_pos < kBufferSize - 1)) {
+    decimal_part *= radix;
+    decimal_buffer[decimal_pos++] =
+        chars[static_cast<int>(floor(decimal_part))];
+    decimal_part -= floor(decimal_part);
+  }
+  decimal_buffer[decimal_pos] = '\0';
+
+  // Compute the result size.
+  int integer_part_size = kBufferSize - 2 - integer_pos;
+  // Make room for zero termination.
+  unsigned result_size = integer_part_size + decimal_pos;
+  // If the number has a decimal part, leave room for the period.
+  if (decimal_pos > 0) result_size++;
+  // Allocate result and fill in the parts.
+  StringBuilder builder(result_size + 1);
+  builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size);
+  if (decimal_pos > 0) builder.AddCharacter('.');
+  builder.AddSubstring(decimal_buffer, decimal_pos);
+  return builder.Finalize();
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/conversions.h b/deps/v8/src/conversions.h
new file mode 100644
index 0000000..605327d
--- /dev/null
+++ b/deps/v8/src/conversions.h
@@ -0,0 +1,116 @@
+// 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_CONVERSIONS_H_
+#define V8_CONVERSIONS_H_
+
+namespace v8 { namespace internal {
+
+// The fast double-to-int conversion routine does not guarantee
+// rounding towards zero.
+// The result is unspecified if x is infinite or NaN, or if the rounded
+// integer value is outside the range of type int.
+static inline int FastD2I(double x);
+
+
+static inline double FastI2D(int x) {
+  // There is no rounding involved in converting an integer to a
+  // double, so this code should compile to a few instructions without
+  // any FPU pipeline stalls.
+  return static_cast<double>(x);
+}
+
+
+static inline double FastUI2D(unsigned x) {
+  // There is no rounding involved in converting an unsigned integer to a
+  // double, so this code should compile to a few instructions without
+  // any FPU pipeline stalls.
+  return static_cast<double>(x);
+}
+
+
+// This function should match the exact semantics of ECMA-262 9.4.
+static inline double DoubleToInteger(double x);
+
+
+// This function should match the exact semantics of ECMA-262 9.5.
+static inline int32_t DoubleToInt32(double x);
+
+
+// This function should match the exact semantics of ECMA-262 9.6.
+static inline uint32_t DoubleToUint32(double x) {
+  return static_cast<uint32_t>(DoubleToInt32(x));
+}
+
+
+// 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 {
+  NO_FLAGS = 0,
+  ALLOW_HEX = 1,
+  ALLOW_OCTALS = 2,
+  ALLOW_TRAILING_JUNK = 4
+};
+
+
+// Convert from Number object to C integer.
+static inline int32_t NumberToInt32(Object* number);
+static inline uint32_t NumberToUint32(Object* number);
+
+
+// Converts a string into a double value according to ECMA-262 9.3.1
+double StringToDouble(const char* str, int flags, double empty_string_val = 0);
+double StringToDouble(String* str, int flags, double empty_string_val = 0);
+
+// Converts a string into an integer.
+int StringToInt(String* str, int index, int radix, double* value);
+int StringToInt(const char* str, int index, int radix, double* value);
+
+// Converts a double to a string value according to ECMA-262 9.8.1.
+// The buffer should be large enough for any floating point number.
+// 100 characters is enough.
+const char* DoubleToCString(double value, Vector<char> buffer);
+
+// Convert an int to a null-terminated string. The returned string is
+// located inside the buffer, but not necessarily at the start.
+const char* IntToCString(int n, Vector<char> buffer);
+
+// Additional number to string conversions for the number type.
+// The caller is responsible for calling free on the returned pointer.
+char* DoubleToFixedCString(double value, int f);
+char* DoubleToExponentialCString(double value, int f);
+char* DoubleToPrecisionCString(double value, int f);
+char* DoubleToRadixCString(double value, int radix);
+
+} }  // namespace v8::internal
+
+#endif  // V8_CONVERSIONS_H_
diff --git a/deps/v8/src/counters.cc b/deps/v8/src/counters.cc
new file mode 100644
index 0000000..bf9b8d8
--- /dev/null
+++ b/deps/v8/src/counters.cc
@@ -0,0 +1,77 @@
+// 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.
+
+#include "v8.h"
+
+#include "counters.h"
+#include "platform.h"
+
+namespace v8 { namespace internal {
+
+CounterLookupCallback StatsTable::lookup_function_ = NULL;
+CreateHistogramCallback StatsTable::create_histogram_function_ = NULL;
+AddHistogramSampleCallback StatsTable::add_histogram_sample_function_ = NULL;
+
+// Start the timer.
+void StatsCounterTimer::Start() {
+  if (!counter_.Enabled())
+    return;
+  stop_time_ = 0;
+  start_time_ = OS::Ticks();
+}
+
+// Stop the timer and record the results.
+void StatsCounterTimer::Stop() {
+  if (!counter_.Enabled())
+    return;
+  stop_time_ = OS::Ticks();
+
+  // Compute the delta between start and stop, in milliseconds.
+  int milliseconds = static_cast<int>(stop_time_ - start_time_) / 1000;
+  counter_.Increment(milliseconds);
+}
+
+// Start the timer.
+void HistogramTimer::Start() {
+  if (GetHistogram() != NULL) {
+    stop_time_ = 0;
+    start_time_ = OS::Ticks();
+  }
+}
+
+// Stop the timer and record the results.
+void HistogramTimer::Stop() {
+  if (histogram_ != NULL) {
+    stop_time_ = OS::Ticks();
+
+    // Compute the delta between start and stop, in milliseconds.
+    int milliseconds = static_cast<int>(stop_time_ - start_time_) / 1000;
+    StatsTable::AddHistogramSample(histogram_, milliseconds);
+  }
+}
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/counters.h b/deps/v8/src/counters.h
new file mode 100644
index 0000000..df1c70a
--- /dev/null
+++ b/deps/v8/src/counters.h
@@ -0,0 +1,238 @@
+// 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.
+
+#ifndef V8_COUNTERS_H_
+#define V8_COUNTERS_H_
+
+namespace v8 { namespace internal {
+
+// StatsCounters is an interface for plugging into external
+// counters for monitoring.  Counters can be looked up and
+// manipulated by name.
+
+class StatsTable : public AllStatic {
+ public:
+  // Register an application-defined function where
+  // counters can be looked up.
+  static void SetCounterFunction(CounterLookupCallback f) {
+    lookup_function_ = f;
+  }
+
+  // Register an application-defined function to create
+  // a histogram for passing to the AddHistogramSample function
+  static void SetCreateHistogramFunction(CreateHistogramCallback f) {
+    create_histogram_function_ = f;
+  }
+
+  // Register an application-defined function to add a sample
+  // to a histogram created with CreateHistogram function
+  static void SetAddHistogramSampleFunction(AddHistogramSampleCallback f) {
+    add_histogram_sample_function_ = f;
+  }
+
+  static bool HasCounterFunction() {
+    return lookup_function_ != NULL;
+  }
+
+  // Lookup the location of a counter by name.  If the lookup
+  // is successful, returns a non-NULL pointer for writing the
+  // value of the counter.  Each thread calling this function
+  // may receive a different location to store it's counter.
+  // The return value must not be cached and re-used across
+  // threads, although a single thread is free to cache it.
+  static int *FindLocation(const char* name) {
+    if (!lookup_function_) return NULL;
+    return lookup_function_(name);
+  }
+
+  // Create a histogram by name. If the create is successful,
+  // returns a non-NULL pointer for use with AddHistogramSample
+  // function. min and max define the expected minimum and maximum
+  // sample values. buckets is the maximum number of buckets
+  // that the samples will be grouped into.
+  static void *CreateHistogram(const char* name,
+                               int min,
+                               int max,
+                               size_t buckets) {
+    if (!create_histogram_function_) return NULL;
+    return create_histogram_function_(name, min, max, buckets);
+  }
+
+  // Add a sample to a histogram created with the CreateHistogram
+  // function.
+  static void AddHistogramSample(void* histogram, int sample) {
+    if (!add_histogram_sample_function_) return;
+    return add_histogram_sample_function_(histogram, sample);
+  }
+
+ private:
+  static CounterLookupCallback lookup_function_;
+  static CreateHistogramCallback create_histogram_function_;
+  static AddHistogramSampleCallback add_histogram_sample_function_;
+};
+
+// StatsCounters are dynamically created values which can be tracked in
+// the StatsTable.  They are designed to be lightweight to create and
+// easy to use.
+//
+// Internally, a counter represents a value in a row of a StatsTable.
+// The row has a 32bit value for each process/thread in the table and also
+// a name (stored in the table metadata).  Since the storage location can be
+// thread-specific, this class cannot be shared across threads.
+//
+// This class is designed to be POD initialized.  It will be registered with
+// the counter system on first use.  For example:
+//   StatsCounter c = { "c:myctr", NULL, false };
+struct StatsCounter {
+  const char* name_;
+  int* ptr_;
+  bool lookup_done_;
+
+  // Sets the counter to a specific value.
+  void Set(int value) {
+    int* loc = GetPtr();
+    if (loc) *loc = value;
+  }
+
+  // Increments the counter.
+  void Increment() {
+    int* loc = GetPtr();
+    if (loc) (*loc)++;
+  }
+
+  void Increment(int value) {
+    int* loc = GetPtr();
+    if (loc)
+      (*loc) += value;
+  }
+
+  // Decrements the counter.
+  void Decrement() {
+    int* loc = GetPtr();
+    if (loc) (*loc)--;
+  }
+
+  void Decrement(int value) {
+    int* loc = GetPtr();
+    if (loc) (*loc) -= value;
+  }
+
+  // Is this counter enabled?
+  // Returns false if table is full.
+  bool Enabled() {
+    return GetPtr() != NULL;
+  }
+
+  // Get the internal pointer to the counter. This is used
+  // by the code generator to emit code that manipulates a
+  // given counter without calling the runtime system.
+  int* GetInternalPointer() {
+    int* loc = GetPtr();
+    ASSERT(loc != NULL);
+    return loc;
+  }
+
+ protected:
+  // Returns the cached address of this counter location.
+  int* GetPtr() {
+    if (lookup_done_)
+      return ptr_;
+    lookup_done_ = true;
+    ptr_ = StatsTable::FindLocation(name_);
+    return ptr_;
+  }
+};
+
+// StatsCounterTimer t = { { L"t:foo", NULL, false }, 0, 0 };
+struct StatsCounterTimer {
+  StatsCounter counter_;
+
+  int64_t start_time_;
+  int64_t stop_time_;
+
+  // Start the timer.
+  void Start();
+
+  // Stop the timer and record the results.
+  void Stop();
+
+  // Returns true if the timer is running.
+  bool Running() {
+    return counter_.Enabled() && start_time_ != 0 && stop_time_ == 0;
+  }
+};
+
+// A HistogramTimer allows distributions of results to be created
+// HistogramTimer t = { L"foo", NULL, false, 0, 0 };
+struct HistogramTimer {
+  const char* name_;
+  void* histogram_;
+  bool lookup_done_;
+
+  int64_t start_time_;
+  int64_t stop_time_;
+
+  // Start the timer.
+  void Start();
+
+  // Stop the timer and record the results.
+  void Stop();
+
+  // Returns true if the timer is running.
+  bool Running() {
+    return (histogram_ != NULL) && (start_time_ != 0) && (stop_time_ == 0);
+  }
+
+ protected:
+  // Returns the handle to the histogram.
+  void* GetHistogram() {
+    if (!lookup_done_) {
+      lookup_done_ = true;
+      histogram_ = StatsTable::CreateHistogram(name_, 0, 10000, 50);
+    }
+    return histogram_;
+  }
+};
+
+// Helper class for scoping a HistogramTimer.
+class HistogramTimerScope BASE_EMBEDDED {
+ public:
+  explicit HistogramTimerScope(HistogramTimer* timer) :
+  timer_(timer) {
+    timer_->Start();
+  }
+  ~HistogramTimerScope() {
+    timer_->Stop();
+  }
+ private:
+  HistogramTimer* timer_;
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_COUNTERS_H_
diff --git a/deps/v8/src/cpu-arm.cc b/deps/v8/src/cpu-arm.cc
new file mode 100644
index 0000000..7369661
--- /dev/null
+++ b/deps/v8/src/cpu-arm.cc
@@ -0,0 +1,124 @@
+// 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.
+
+// CPU specific code for arm independent of OS goes here.
+#if defined(__arm__)
+#include <sys/syscall.h>  // for cache flushing.
+#endif
+
+#include "v8.h"
+
+#include "cpu.h"
+
+namespace v8 { namespace internal {
+
+void CPU::Setup() {
+  // Nothing to do.
+}
+
+
+void CPU::FlushICache(void* start, size_t size) {
+#if !defined (__arm__)
+  // Not generating ARM instructions for C-code. This means that we are
+  // building an ARM emulator based target. No I$ flushes are necessary.
+#else
+  // Ideally, we would call
+  //   syscall(__ARM_NR_cacheflush, start,
+  //           reinterpret_cast<intptr_t>(start) + size, 0);
+  // however, syscall(int, ...) is not supported on all platforms, especially
+  // not when using EABI, so we call the __ARM_NR_cacheflush syscall directly.
+
+  register uint32_t beg asm("a1") = reinterpret_cast<uint32_t>(start);
+  register uint32_t end asm("a2") =
+      reinterpret_cast<uint32_t>(start) + size;
+  register uint32_t flg asm("a3") = 0;
+  #ifdef __ARM_EABI__
+    register uint32_t scno asm("r7") = __ARM_NR_cacheflush;
+    #if defined (__arm__) && !defined(__thumb__)
+      // __arm__ may be defined in thumb mode.
+      asm volatile(
+          "swi 0x0"
+          : "=r" (beg)
+          : "0" (beg), "r" (end), "r" (flg), "r" (scno));
+    #else
+      asm volatile(
+      "@   Enter ARM Mode  \n\t"
+          "adr r3, 1f      \n\t"
+          "bx  r3          \n\t"
+          ".ALIGN 4        \n\t"
+          ".ARM            \n"
+      "1:  swi 0x0         \n\t"
+      "@   Enter THUMB Mode\n\t"
+          "adr r3, 2f+1    \n\t"
+          "bx  r3          \n\t"
+          ".THUMB          \n"
+      "2:                  \n\t"
+          : "=r" (beg)
+          : "0" (beg), "r" (end), "r" (flg), "r" (scno)
+          : "r3");
+    #endif
+  #else
+    #if defined (__arm__) && !defined(__thumb__)
+      // __arm__ may be defined in thumb mode.
+      asm volatile(
+          "swi %1"
+          : "=r" (beg)
+          : "i" (__ARM_NR_cacheflush), "0" (beg), "r" (end), "r" (flg));
+    #else
+      // Do not use the value of __ARM_NR_cacheflush in the inline assembly
+      // below, because the thumb mode value would be used, which would be
+      // wrong, since we switch to ARM mode before executing the swi instruction
+      asm volatile(
+      "@   Enter ARM Mode  \n\t"
+          "adr r3, 1f      \n\t"
+          "bx  r3          \n\t"
+          ".ALIGN 4        \n\t"
+          ".ARM            \n"
+      "1:  swi 0x9f0002    \n"
+      "@   Enter THUMB Mode\n\t"
+          "adr r3, 2f+1    \n\t"
+          "bx  r3          \n\t"
+          ".THUMB          \n"
+      "2:                  \n\t"
+          : "=r" (beg)
+          : "0" (beg), "r" (end), "r" (flg)
+          : "r3");
+    #endif
+  #endif
+#endif
+}
+
+
+void CPU::DebugBreak() {
+#if !defined (__arm__)
+  UNIMPLEMENTED();  // when building ARM emulator target
+#else
+  asm volatile("bkpt 0");
+#endif
+}
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/cpu-ia32.cc b/deps/v8/src/cpu-ia32.cc
new file mode 100644
index 0000000..9cd6b10
--- /dev/null
+++ b/deps/v8/src/cpu-ia32.cc
@@ -0,0 +1,65 @@
+// 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.
+
+// CPU specific code for ia32 independent of OS goes here.
+
+#include "v8.h"
+
+#include "cpu.h"
+#include "macro-assembler.h"
+
+namespace v8 { namespace internal {
+
+void CPU::Setup() {
+  CpuFeatures::Probe();
+}
+
+
+void CPU::FlushICache(void* start, size_t size) {
+  // No need to flush the instruction cache on Intel. On Intel instruction
+  // cache flushing is only necessary when multiple cores running the same
+  // code simultaneously. V8 (and JavaScript) is single threaded and when code
+  // is patched on an intel CPU the core performing the patching will have its
+  // own instruction cache updated automatically.
+
+  // If flushing of the instruction cache becomes necessary Windows have the
+  // API function FlushInstructionCache.
+}
+
+
+void CPU::DebugBreak() {
+#ifdef _MSC_VER
+  // To avoid Visual Studio runtime support the following code can be used
+  // instead
+  // __asm { int 3 }
+  __debugbreak();
+#else
+  asm("int $3");
+#endif
+}
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/cpu.h b/deps/v8/src/cpu.h
new file mode 100644
index 0000000..d12c30c
--- /dev/null
+++ b/deps/v8/src/cpu.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.
+
+// This module contains the architecture-specific code. This make the rest of
+// the code less dependent on differences between different processor
+// architecture.
+// The classes have the same definition for all architectures. The
+// implementation for a particular architecture is put in cpu_<arch>.cc.
+// The build system then uses the implementation for the target architecture.
+//
+
+#ifndef V8_CPU_H_
+#define V8_CPU_H_
+
+namespace v8 { namespace internal {
+
+// ----------------------------------------------------------------------------
+// CPU
+//
+// This class has static methods for the architecture specific functions. Add
+// methods here to cope with differences between the supported architectures.
+//
+// For each architecture the file cpu_<arch>.cc contains the implementation of
+// these functions.
+
+class CPU : public AllStatic {
+ public:
+  // Initializes the cpu architecture support. Called once at VM startup.
+  static void Setup();
+
+  // Flush instruction cache.
+  static void FlushICache(void* start, size_t size);
+
+  // Try to activate a system level debugger.
+  static void DebugBreak();
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_CPU_H_
diff --git a/deps/v8/src/d8-debug.cc b/deps/v8/src/d8-debug.cc
new file mode 100644
index 0000000..4e0243a
--- /dev/null
+++ b/deps/v8/src/d8-debug.cc
@@ -0,0 +1,345 @@
+// Copyright 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.
+
+
+#include "d8.h"
+#include "d8-debug.h"
+#include "platform.h"
+#include "debug-agent.h"
+
+
+namespace v8 {
+
+
+void HandleDebugEvent(DebugEvent event,
+                      Handle<Object> exec_state,
+                      Handle<Object> event_data,
+                      Handle<Value> data) {
+  HandleScope scope;
+
+  // Check for handled event.
+  if (event != Break && event != Exception && event != AfterCompile) {
+    return;
+  }
+
+  TryCatch try_catch;
+
+  // Get the toJSONProtocol function on the event and get the JSON format.
+  Local<String> to_json_fun_name = String::New("toJSONProtocol");
+  Local<Function> to_json_fun =
+      Function::Cast(*event_data->Get(to_json_fun_name));
+  Local<Value> event_json = to_json_fun->Call(event_data, 0, NULL);
+  if (try_catch.HasCaught()) {
+    Shell::ReportException(&try_catch);
+    return;
+  }
+
+  // Print the event details.
+  Handle<Object> details =
+      Shell::DebugMessageDetails(Handle<String>::Cast(event_json));
+  if (try_catch.HasCaught()) {
+    Shell::ReportException(&try_catch);
+    return;
+  }
+  String::Utf8Value str(details->Get(String::New("text")));
+  if (str.length() == 0) {
+    // Empty string is used to signal not to process this event.
+    return;
+  }
+  printf("%s\n", *str);
+
+  // Get the debug command processor.
+  Local<String> fun_name = String::New("debugCommandProcessor");
+  Local<Function> fun = Function::Cast(*exec_state->Get(fun_name));
+  Local<Object> cmd_processor =
+      Object::Cast(*fun->Call(exec_state, 0, NULL));
+  if (try_catch.HasCaught()) {
+    Shell::ReportException(&try_catch);
+    return;
+  }
+
+  static const int kBufferSize = 256;
+  bool running = false;
+  while (!running) {
+    char command[kBufferSize];
+    printf("dbg> ");
+    char* str = fgets(command, kBufferSize, stdin);
+    if (str == NULL) break;
+
+    // Ignore empty commands.
+    if (strlen(command) == 0) continue;
+
+    TryCatch try_catch;
+
+    // Convert the debugger command to a JSON debugger request.
+    Handle<Value> request =
+        Shell::DebugCommandToJSONRequest(String::New(command));
+    if (try_catch.HasCaught()) {
+      Shell::ReportException(&try_catch);
+      continue;
+    }
+
+    // If undefined is returned the command was handled internally and there is
+    // no JSON to send.
+    if (request->IsUndefined()) {
+      continue;
+    }
+
+    Handle<String> fun_name;
+    Handle<Function> fun;
+    // All the functions used below take one argument.
+    static const int kArgc = 1;
+    Handle<Value> args[kArgc];
+
+    // Invoke the JavaScript to convert the debug command line to a JSON
+    // request, invoke the JSON request and convert the JSON respose to a text
+    // representation.
+    fun_name = String::New("processDebugRequest");
+    fun = Handle<Function>::Cast(cmd_processor->Get(fun_name));
+    args[0] = request;
+    Handle<Value> response_val = fun->Call(cmd_processor, kArgc, args);
+    if (try_catch.HasCaught()) {
+      Shell::ReportException(&try_catch);
+      continue;
+    }
+    Handle<String> response = Handle<String>::Cast(response_val);
+
+    // Convert the debugger response into text details and the running state.
+    Handle<Object> response_details = Shell::DebugMessageDetails(response);
+    if (try_catch.HasCaught()) {
+      Shell::ReportException(&try_catch);
+      continue;
+    }
+    String::Utf8Value text_str(response_details->Get(String::New("text")));
+    if (text_str.length() > 0) {
+      printf("%s\n", *text_str);
+    }
+    running =
+        response_details->Get(String::New("running"))->ToBoolean()->Value();
+  }
+}
+
+
+void RunRemoteDebugger(int port) {
+  RemoteDebugger debugger(port);
+  debugger.Run();
+}
+
+
+void RemoteDebugger::Run() {
+  bool ok;
+
+  // Make sure that socket support is initialized.
+  ok = i::Socket::Setup();
+  if (!ok) {
+    printf("Unable to initialize socket support %d\n", i::Socket::LastError());
+    return;
+  }
+
+  // Connect to the debugger agent.
+  conn_ = i::OS::CreateSocket();
+  static const int kPortStrSize = 6;
+  char port_str[kPortStrSize];
+  i::OS::SNPrintF(i::Vector<char>(port_str, kPortStrSize), "%d", port_);
+  ok = conn_->Connect("localhost", port_str);
+  if (!ok) {
+    printf("Unable to connect to debug agent %d\n", i::Socket::LastError());
+    return;
+  }
+
+  // Start the receiver thread.
+  ReceiverThread receiver(this);
+  receiver.Start();
+
+  // Start the keyboard thread.
+  KeyboardThread keyboard(this);
+  keyboard.Start();
+
+  // Process events received from debugged VM and from the keyboard.
+  bool terminate = false;
+  while (!terminate) {
+    event_available_->Wait();
+    RemoteDebuggerEvent* event = GetEvent();
+    switch (event->type()) {
+      case RemoteDebuggerEvent::kMessage:
+        HandleMessageReceived(event->data());
+        break;
+      case RemoteDebuggerEvent::kKeyboard:
+        HandleKeyboardCommand(event->data());
+        break;
+      case RemoteDebuggerEvent::kDisconnect:
+        terminate = true;
+        break;
+
+      default:
+        UNREACHABLE();
+    }
+    delete event;
+  }
+
+  // Wait for the receiver thread to end.
+  receiver.Join();
+}
+
+
+void RemoteDebugger::MessageReceived(i::SmartPointer<char> message) {
+  RemoteDebuggerEvent* event =
+      new RemoteDebuggerEvent(RemoteDebuggerEvent::kMessage, message);
+  AddEvent(event);
+}
+
+
+void RemoteDebugger::KeyboardCommand(i::SmartPointer<char> command) {
+  RemoteDebuggerEvent* event =
+      new RemoteDebuggerEvent(RemoteDebuggerEvent::kKeyboard, command);
+  AddEvent(event);
+}
+
+
+void RemoteDebugger::ConnectionClosed() {
+  RemoteDebuggerEvent* event =
+      new RemoteDebuggerEvent(RemoteDebuggerEvent::kDisconnect,
+                              i::SmartPointer<char>());
+  AddEvent(event);
+}
+
+
+void RemoteDebugger::AddEvent(RemoteDebuggerEvent* event) {
+  i::ScopedLock lock(event_access_);
+  if (head_ == NULL) {
+    ASSERT(tail_ == NULL);
+    head_ = event;
+    tail_ = event;
+  } else {
+    ASSERT(tail_ != NULL);
+    tail_->set_next(event);
+    tail_ = event;
+  }
+  event_available_->Signal();
+}
+
+
+RemoteDebuggerEvent* RemoteDebugger::GetEvent() {
+  i::ScopedLock lock(event_access_);
+  ASSERT(head_ != NULL);
+  RemoteDebuggerEvent* result = head_;
+  head_ = head_->next();
+  if (head_ == NULL) {
+    ASSERT(tail_ == result);
+    tail_ = NULL;
+  }
+  return result;
+}
+
+
+void RemoteDebugger::HandleMessageReceived(char* message) {
+  HandleScope scope;
+
+  // Print the event details.
+  TryCatch try_catch;
+  Handle<Object> details =
+      Shell::DebugMessageDetails(Handle<String>::Cast(String::New(message)));
+  if (try_catch.HasCaught()) {
+      Shell::ReportException(&try_catch);
+    return;
+  }
+  String::Utf8Value str(details->Get(String::New("text")));
+  if (str.length() == 0) {
+    // Empty string is used to signal not to process this event.
+    return;
+  }
+  if (*str != NULL) {
+    printf("%s\n", *str);
+  } else {
+    printf("???\n");
+  }
+  printf("dbg> ");
+}
+
+
+void RemoteDebugger::HandleKeyboardCommand(char* command) {
+  HandleScope scope;
+
+  // Convert the debugger command to a JSON debugger request.
+  TryCatch try_catch;
+  Handle<Value> request =
+      Shell::DebugCommandToJSONRequest(String::New(command));
+  if (try_catch.HasCaught()) {
+    Shell::ReportException(&try_catch);
+    return;
+  }
+
+  // If undefined is returned the command was handled internally and there is
+  // no JSON to send.
+  if (request->IsUndefined()) {
+    return;
+  }
+
+  // Send the JSON debugger request.
+  i::DebuggerAgentUtil::SendMessage(conn_, Handle<String>::Cast(request));
+}
+
+
+void ReceiverThread::Run() {
+  // Receive the connect message (with empty body).
+  i::SmartPointer<char> message =
+    i::DebuggerAgentUtil::ReceiveMessage(remote_debugger_->conn());
+  ASSERT(*message == NULL);
+
+  while (true) {
+    // Receive a message.
+    i::SmartPointer<char> message =
+      i::DebuggerAgentUtil::ReceiveMessage(remote_debugger_->conn());
+    if (*message == NULL) {
+      remote_debugger_->ConnectionClosed();
+      return;
+    }
+
+    // Pass the message to the main thread.
+    remote_debugger_->MessageReceived(message);
+  }
+}
+
+
+void KeyboardThread::Run() {
+  static const int kBufferSize = 256;
+  while (true) {
+    // read keyboard input.
+    char command[kBufferSize];
+    char* str = fgets(command, kBufferSize, stdin);
+    if (str == NULL) {
+      break;
+    }
+
+    // Pass the keyboard command to the main thread.
+    remote_debugger_->KeyboardCommand(
+        i::SmartPointer<char>(i::StrDup(command)));
+  }
+}
+
+
+}  // namespace v8
diff --git a/deps/v8/src/d8-debug.h b/deps/v8/src/d8-debug.h
new file mode 100644
index 0000000..c7acc2f
--- /dev/null
+++ b/deps/v8/src/d8-debug.h
@@ -0,0 +1,155 @@
+// Copyright 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_D8_DEBUG_H_
+#define V8_D8_DEBUG_H_
+
+
+#include "d8.h"
+#include "debug.h"
+
+
+namespace v8 {
+
+
+void HandleDebugEvent(DebugEvent event,
+                      Handle<Object> exec_state,
+                      Handle<Object> event_data,
+                      Handle<Value> data);
+
+// Start the remove debugger connecting to a V8 debugger agent on the specified
+// port.
+void RunRemoteDebugger(int port);
+
+// Forward declerations.
+class RemoteDebuggerEvent;
+class ReceiverThread;
+
+
+// Remote debugging class.
+class RemoteDebugger {
+ public:
+  explicit RemoteDebugger(int port)
+      : port_(port),
+        event_access_(i::OS::CreateMutex()),
+        event_available_(i::OS::CreateSemaphore(0)),
+        head_(NULL), tail_(NULL) {}
+  void Run();
+
+  // Handle events from the subordinate threads.
+  void MessageReceived(i::SmartPointer<char> message);
+  void KeyboardCommand(i::SmartPointer<char> command);
+  void ConnectionClosed();
+
+ private:
+  // Add new debugger event to the list.
+  void AddEvent(RemoteDebuggerEvent* event);
+  // Read next debugger event from the list.
+  RemoteDebuggerEvent* GetEvent();
+
+  // Handle a message from the debugged V8.
+  void HandleMessageReceived(char* message);
+  // Handle a keyboard command.
+  void HandleKeyboardCommand(char* command);
+
+  // Get connection to agent in debugged V8.
+  i::Socket* conn() { return conn_; }
+
+  int port_;  // Port used to connect to debugger V8.
+  i::Socket* conn_;  // Connection to debugger agent in debugged V8.
+
+  // Linked list of events from debugged V8 and from keyboard input. Access to
+  // the list is guarded by a mutex and a semaphore signals new items in the
+  // list.
+  i::Mutex* event_access_;
+  i::Semaphore* event_available_;
+  RemoteDebuggerEvent* head_;
+  RemoteDebuggerEvent* tail_;
+
+  friend class ReceiverThread;
+};
+
+
+// Thread reading from debugged V8 instance.
+class ReceiverThread: public i::Thread {
+ public:
+  explicit ReceiverThread(RemoteDebugger* remote_debugger)
+      : remote_debugger_(remote_debugger) {}
+  ~ReceiverThread() {}
+
+  void Run();
+
+ private:
+  RemoteDebugger* remote_debugger_;
+};
+
+
+// Thread reading keyboard input.
+class KeyboardThread: public i::Thread {
+ public:
+  explicit KeyboardThread(RemoteDebugger* remote_debugger)
+      : remote_debugger_(remote_debugger) {}
+  ~KeyboardThread() {}
+
+  void Run();
+
+ private:
+  RemoteDebugger* remote_debugger_;
+};
+
+
+// Events processed by the main deubgger thread.
+class RemoteDebuggerEvent {
+ public:
+  RemoteDebuggerEvent(int type, i::SmartPointer<char> data)
+      : type_(type), data_(data), next_(NULL) {
+    ASSERT(type == kMessage || type == kKeyboard || type == kDisconnect);
+  }
+
+  static const int kMessage = 1;
+  static const int kKeyboard = 2;
+  static const int kDisconnect = 3;
+
+  int type() { return type_; }
+  char* data() { return *data_; }
+
+ private:
+  void set_next(RemoteDebuggerEvent* event) { next_ = event; }
+  RemoteDebuggerEvent* next() { return next_; }
+
+  int type_;
+  i::SmartPointer<char> data_;
+  RemoteDebuggerEvent* next_;
+
+  friend class RemoteDebugger;
+};
+
+
+}  // namespace v8
+
+
+#endif  // V8_D8_DEBUG_H_
diff --git a/deps/v8/src/d8-posix.cc b/deps/v8/src/d8-posix.cc
new file mode 100644
index 0000000..c2dc531
--- /dev/null
+++ b/deps/v8/src/d8-posix.cc
@@ -0,0 +1,668 @@
+// 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.
+
+
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+
+#include "d8.h"
+#include "d8-debug.h"
+#include "debug.h"
+
+
+namespace v8 {
+
+
+// If the buffer ends in the middle of a UTF-8 sequence then we return
+// the length of the string up to but not including the incomplete UTF-8
+// sequence.  If the buffer ends with a valid UTF-8 sequence then we
+// return the whole buffer.
+static int LengthWithoutIncompleteUtf8(char* buffer, int len) {
+  int answer = len;
+  // 1-byte encoding.
+  static const int kUtf8SingleByteMask = 0x80;
+  static const int kUtf8SingleByteValue = 0x00;
+  // 2-byte encoding.
+  static const int kUtf8TwoByteMask = 0xe0;
+  static const int kUtf8TwoByteValue = 0xc0;
+  // 3-byte encoding.
+  static const int kUtf8ThreeByteMask = 0xf0;
+  static const int kUtf8ThreeByteValue = 0xe0;
+  // 4-byte encoding.
+  static const int kUtf8FourByteMask = 0xf8;
+  static const int kUtf8FourByteValue = 0xf0;
+  // Subsequent bytes of a multi-byte encoding.
+  static const int kMultiByteMask = 0xc0;
+  static const int kMultiByteValue = 0x80;
+  int multi_byte_bytes_seen = 0;
+  while (answer > 0) {
+    int c = buffer[answer - 1];
+    // Ends in valid single-byte sequence?
+    if ((c & kUtf8SingleByteMask) == kUtf8SingleByteValue) return answer;
+    // Ends in one or more subsequent bytes of a multi-byte value?
+    if ((c & kMultiByteMask) == kMultiByteValue) {
+      multi_byte_bytes_seen++;
+      answer--;
+    } else {
+      if ((c & kUtf8TwoByteMask) == kUtf8TwoByteValue) {
+        if (multi_byte_bytes_seen >= 1) {
+          return answer + 2;
+        }
+        return answer - 1;
+      } else if ((c & kUtf8ThreeByteMask) == kUtf8ThreeByteValue) {
+        if (multi_byte_bytes_seen >= 2) {
+          return answer + 3;
+        }
+        return answer - 1;
+      } else if ((c & kUtf8FourByteMask) == kUtf8FourByteValue) {
+        if (multi_byte_bytes_seen >= 3) {
+          return answer + 4;
+        }
+        return answer - 1;
+      } else {
+        return answer;  // Malformed UTF-8.
+      }
+    }
+  }
+  return 0;
+}
+
+
+// Suspends the thread until there is data available from the child process.
+// Returns false on timeout, true on data ready.
+static bool WaitOnFD(int fd,
+                     int read_timeout,
+                     int total_timeout,
+                     struct timeval& start_time) {
+  fd_set readfds, writefds, exceptfds;
+  struct timeval timeout;
+  int gone = 0;
+  if (total_timeout != -1) {
+    struct timeval time_now;
+    gettimeofday(&time_now, NULL);
+    int seconds = time_now.tv_sec - start_time.tv_sec;
+    gone = seconds * 1000 + (time_now.tv_usec - start_time.tv_usec) / 1000;
+    if (gone >= total_timeout) return false;
+  }
+  FD_ZERO(&readfds);
+  FD_ZERO(&writefds);
+  FD_ZERO(&exceptfds);
+  FD_SET(fd, &readfds);
+  FD_SET(fd, &exceptfds);
+  if (read_timeout == -1 ||
+      (total_timeout != -1 && total_timeout - gone < read_timeout)) {
+    read_timeout = total_timeout - gone;
+  }
+  timeout.tv_usec = (read_timeout % 1000) * 1000;
+  timeout.tv_sec = read_timeout / 1000;
+  int number_of_fds_ready = select(fd + 1,
+                                   &readfds,
+                                   &writefds,
+                                   &exceptfds,
+                                   read_timeout != -1 ? &timeout : NULL);
+  return number_of_fds_ready == 1;
+}
+
+
+// Checks whether we ran out of time on the timeout.  Returns true if we ran out
+// of time, false if we still have time.
+static bool TimeIsOut(const struct timeval& start_time, const int& total_time) {
+  if (total_time == -1) return false;
+  struct timeval time_now;
+  gettimeofday(&time_now, NULL);
+  // Careful about overflow.
+  int seconds = time_now.tv_sec - start_time.tv_sec;
+  if (seconds > 100) {
+    if (seconds * 1000 > total_time) return true;
+    return false;
+  }
+  int useconds = time_now.tv_usec - start_time.tv_usec;
+  if (seconds * 1000000 + useconds > total_time * 1000) {
+    return true;
+  }
+  return false;
+}
+
+
+// A utility class that does a non-hanging waitpid on the child process if we
+// bail out of the System() function early.  If you don't ever do a waitpid on
+// a subprocess then it turns into one of those annoying 'zombie processes'.
+class ZombieProtector {
+ public:
+  explicit ZombieProtector(int pid): pid_(pid) { }
+  ~ZombieProtector() { if (pid_ != 0) waitpid(pid_, NULL, 0); }
+  void ChildIsDeadNow() { pid_ = 0; }
+ private:
+  int pid_;
+};
+
+
+// A utility class that closes a file descriptor when it goes out of scope.
+class OpenFDCloser {
+ public:
+  explicit OpenFDCloser(int fd): fd_(fd) { }
+  ~OpenFDCloser() { close(fd_); }
+ private:
+  int fd_;
+};
+
+
+// A utility class that takes the array of command arguments and puts then in an
+// array of new[]ed UTF-8 C strings.  Deallocates them again when it goes out of
+// scope.
+class ExecArgs {
+ public:
+  ExecArgs() {
+    exec_args_[0] = NULL;
+  }
+  bool Init(Handle<Value> arg0, Handle<Array> command_args) {
+    String::Utf8Value prog(arg0);
+    if (*prog == NULL) {
+      const char* message =
+          "os.system(): String conversion of program name failed";
+      ThrowException(String::New(message));
+      return false;
+    }
+    int len = prog.length() + 3;
+    char* c_arg = new char[len];
+    snprintf(c_arg, len, "%s", *prog);
+    exec_args_[0] = c_arg;
+    int i = 1;
+    for (unsigned j = 0; j < command_args->Length(); i++, j++) {
+      Handle<Value> arg(command_args->Get(Integer::New(j)));
+      String::Utf8Value utf8_arg(arg);
+      if (*utf8_arg == NULL) {
+        exec_args_[i] = NULL;  // Consistent state for destructor.
+        const char* message =
+            "os.system(): String conversion of argument failed.";
+        ThrowException(String::New(message));
+        return false;
+      }
+      int len = utf8_arg.length() + 1;
+      char* c_arg = new char[len];
+      snprintf(c_arg, len, "%s", *utf8_arg);
+      exec_args_[i] = c_arg;
+    }
+    exec_args_[i] = NULL;
+    return true;
+  }
+  ~ExecArgs() {
+    for (unsigned i = 0; i < kMaxArgs; i++) {
+      if (exec_args_[i] == NULL) {
+        return;
+      }
+      delete [] exec_args_[i];
+      exec_args_[i] = 0;
+    }
+  }
+  static const unsigned kMaxArgs = 1000;
+  char** arg_array() { return exec_args_; }
+  char* arg0() { return exec_args_[0]; }
+ private:
+  char* exec_args_[kMaxArgs + 1];
+};
+
+
+// Gets the optional timeouts from the arguments to the system() call.
+static bool GetTimeouts(const Arguments& args,
+                        int* read_timeout,
+                        int* total_timeout) {
+  if (args.Length() > 3) {
+    if (args[3]->IsNumber()) {
+      *total_timeout = args[3]->Int32Value();
+    } else {
+      ThrowException(String::New("system: Argument 4 must be a number"));
+      return false;
+    }
+  }
+  if (args.Length() > 2) {
+    if (args[2]->IsNumber()) {
+      *read_timeout = args[2]->Int32Value();
+    } else {
+      ThrowException(String::New("system: Argument 3 must be a number"));
+      return false;
+    }
+  }
+  return true;
+}
+
+
+static const int kReadFD = 0;
+static const int kWriteFD = 1;
+
+
+// This is run in the child process after fork() but before exec().  It normally
+// ends with the child process being replaced with the desired child program.
+// It only returns if an error occurred.
+static void ExecSubprocess(int* exec_error_fds,
+                           int* stdout_fds,
+                           ExecArgs& exec_args) {
+  close(exec_error_fds[kReadFD]);  // Don't need this in the child.
+  close(stdout_fds[kReadFD]);      // Don't need this in the child.
+  close(1);                        // Close stdout.
+  dup2(stdout_fds[kWriteFD], 1);   // Dup pipe fd to stdout.
+  close(stdout_fds[kWriteFD]);     // Don't need the original fd now.
+  fcntl(exec_error_fds[kWriteFD], F_SETFD, FD_CLOEXEC);
+  execvp(exec_args.arg0(), exec_args.arg_array());
+  // Only get here if the exec failed.  Write errno to the parent to tell
+  // them it went wrong.  If it went well the pipe is closed.
+  int err = errno;
+  write(exec_error_fds[kWriteFD], &err, sizeof(err));
+  // Return (and exit child process).
+}
+
+
+// Runs in the parent process.  Checks that the child was able to exec (closing
+// the file desriptor), or reports an error if it failed.
+static bool ChildLaunchedOK(int* exec_error_fds) {
+  int bytes_read;
+  int err;
+  do {
+    bytes_read = read(exec_error_fds[kReadFD], &err, sizeof(err));
+  } while (bytes_read == -1 && errno == EINTR);
+  if (bytes_read != 0) {
+    ThrowException(String::New(strerror(err)));
+    return false;
+  }
+  return true;
+}
+
+
+// Accumulates the output from the child in a string handle.  Returns true if it
+// succeeded or false if an exception was thrown.
+static Handle<Value> GetStdout(int child_fd,
+                               struct timeval& start_time,
+                               int read_timeout,
+                               int total_timeout) {
+  Handle<String> accumulator = String::Empty();
+  const char* source = "function(a, b) { return a + b; }";
+  Handle<Value> cons_as_obj(Script::Compile(String::New(source))->Run());
+  Handle<Function> cons_function(Function::Cast(*cons_as_obj));
+  Handle<Value> cons_args[2];
+
+  int fullness = 0;
+  static const int kStdoutReadBufferSize = 4096;
+  char buffer[kStdoutReadBufferSize];
+
+  if (fcntl(child_fd, F_SETFL, O_NONBLOCK) != 0) {
+    return ThrowException(String::New(strerror(errno)));
+  }
+
+  int bytes_read;
+  do {
+    bytes_read = read(child_fd,
+                      buffer + fullness,
+                      kStdoutReadBufferSize - fullness);
+    if (bytes_read == -1) {
+      if (errno == EAGAIN) {
+        if (!WaitOnFD(child_fd,
+                      read_timeout,
+                      total_timeout,
+                      start_time) ||
+            (TimeIsOut(start_time, total_timeout))) {
+          return ThrowException(String::New("Timed out waiting for output"));
+        }
+        continue;
+      } else if (errno == EINTR) {
+        continue;
+      } else {
+        break;
+      }
+    }
+    if (bytes_read + fullness > 0) {
+      int length = bytes_read == 0 ?
+                   bytes_read + fullness :
+                   LengthWithoutIncompleteUtf8(buffer, bytes_read + fullness);
+      Handle<String> addition = String::New(buffer, length);
+      cons_args[0] = accumulator;
+      cons_args[1] = addition;
+      accumulator = Handle<String>::Cast(cons_function->Call(
+          Shell::utility_context()->Global(),
+          2,
+          cons_args));
+      fullness = bytes_read + fullness - length;
+      memcpy(buffer, buffer + length, fullness);
+    }
+  } while (bytes_read != 0);
+  return accumulator;
+}
+
+
+// Modern Linux has the waitid call, which is like waitpid, but more useful
+// if you want a timeout.  If we don't have waitid we can't limit the time
+// waiting for the process to exit without losing the information about
+// whether it exited normally.  In the common case this doesn't matter because
+// we don't get here before the child has closed stdout and most programs don't
+// do that before they exit.
+#if defined(WNOWAIT) && !defined(ANDROID)
+#define HAS_WAITID 1
+#endif
+
+
+// Get exit status of child.
+static bool WaitForChild(int pid,
+                         ZombieProtector& child_waiter,
+                         struct timeval& start_time,
+                         int read_timeout,
+                         int total_timeout) {
+#ifdef HAS_WAITID
+
+  siginfo_t child_info;
+  child_info.si_pid = 0;
+  int useconds = 1;
+  // Wait for child to exit.
+  while (child_info.si_pid == 0) {
+    waitid(P_PID, pid, &child_info, WEXITED | WNOHANG | WNOWAIT);
+    usleep(useconds);
+    if (useconds < 1000000) useconds <<= 1;
+    if ((read_timeout != -1 && useconds / 1000 > read_timeout) ||
+        (TimeIsOut(start_time, total_timeout))) {
+      ThrowException(String::New("Timed out waiting for process to terminate"));
+      kill(pid, SIGINT);
+      return false;
+    }
+  }
+  if (child_info.si_code == CLD_KILLED) {
+    char message[999];
+    snprintf(message,
+             sizeof(message),
+             "Child killed by signal %d",
+             child_info.si_status);
+    ThrowException(String::New(message));
+    return false;
+  }
+  if (child_info.si_code == CLD_EXITED && child_info.si_status != 0) {
+    char message[999];
+    snprintf(message,
+             sizeof(message),
+             "Child exited with status %d",
+             child_info.si_status);
+    ThrowException(String::New(message));
+    return false;
+  }
+
+#else  // No waitid call.
+
+  int child_status;
+  waitpid(pid, &child_status, 0);  // We hang here if the child doesn't exit.
+  child_waiter.ChildIsDeadNow();
+  if (WIFSIGNALED(child_status)) {
+    char message[999];
+    snprintf(message,
+             sizeof(message),
+             "Child killed by signal %d",
+             WTERMSIG(child_status));
+    ThrowException(String::New(message));
+    return false;
+  }
+  if (WEXITSTATUS(child_status) != 0) {
+    char message[999];
+    int exit_status = WEXITSTATUS(child_status);
+    snprintf(message,
+             sizeof(message),
+             "Child exited with status %d",
+             exit_status);
+    ThrowException(String::New(message));
+    return false;
+  }
+
+#endif  // No waitid call.
+
+  return true;
+}
+
+
+// Implementation of the system() function (see d8.h for details).
+Handle<Value> Shell::System(const Arguments& args) {
+  HandleScope scope;
+  int read_timeout = -1;
+  int total_timeout = -1;
+  if (!GetTimeouts(args, &read_timeout, &total_timeout)) return v8::Undefined();
+  Handle<Array> command_args;
+  if (args.Length() > 1) {
+    if (!args[1]->IsArray()) {
+      return ThrowException(String::New("system: Argument 2 must be an array"));
+    }
+    command_args = Handle<Array>::Cast(args[1]);
+  } else {
+    command_args = Array::New(0);
+  }
+  if (command_args->Length() > ExecArgs::kMaxArgs) {
+    return ThrowException(String::New("Too many arguments to system()"));
+  }
+  if (args.Length() < 1) {
+    return ThrowException(String::New("Too few arguments to system()"));
+  }
+
+  struct timeval start_time;
+  gettimeofday(&start_time, NULL);
+
+  ExecArgs exec_args;
+  if (!exec_args.Init(args[0], command_args)) {
+    return v8::Undefined();
+  }
+  int exec_error_fds[2];
+  int stdout_fds[2];
+
+  if (pipe(exec_error_fds) != 0) {
+    return ThrowException(String::New("pipe syscall failed."));
+  }
+  if (pipe(stdout_fds) != 0) {
+    return ThrowException(String::New("pipe syscall failed."));
+  }
+
+  pid_t pid = fork();
+  if (pid == 0) {  // Child process.
+    ExecSubprocess(exec_error_fds, stdout_fds, exec_args);
+    exit(1);
+  }
+
+  // Parent process.  Ensure that we clean up if we exit this function early.
+  ZombieProtector child_waiter(pid);
+  close(exec_error_fds[kWriteFD]);
+  close(stdout_fds[kWriteFD]);
+  OpenFDCloser error_read_closer(exec_error_fds[kReadFD]);
+  OpenFDCloser stdout_read_closer(stdout_fds[kReadFD]);
+
+  if (!ChildLaunchedOK(exec_error_fds)) return v8::Undefined();
+
+  Handle<Value> accumulator = GetStdout(stdout_fds[kReadFD],
+                                        start_time,
+                                        read_timeout,
+                                        total_timeout);
+  if (accumulator->IsUndefined()) {
+    kill(pid, SIGINT);  // On timeout, kill the subprocess.
+    return accumulator;
+  }
+
+  if (!WaitForChild(pid,
+                    child_waiter,
+                    start_time,
+                    read_timeout,
+                    total_timeout)) {
+    return v8::Undefined();
+  }
+
+  return scope.Close(accumulator);
+}
+
+
+Handle<Value> Shell::ChangeDirectory(const Arguments& args) {
+  if (args.Length() != 1) {
+    const char* message = "chdir() takes one argument";
+    return ThrowException(String::New(message));
+  }
+  String::Utf8Value directory(args[0]);
+  if (*directory == NULL) {
+    const char* message = "os.chdir(): String conversion of argument failed.";
+    return ThrowException(String::New(message));
+  }
+  if (chdir(*directory) != 0) {
+    return ThrowException(String::New(strerror(errno)));
+  }
+  return v8::Undefined();
+}
+
+
+Handle<Value> Shell::SetUMask(const Arguments& args) {
+  if (args.Length() != 1) {
+    const char* message = "umask() takes one argument";
+    return ThrowException(String::New(message));
+  }
+  if (args[0]->IsNumber()) {
+    mode_t mask = args[0]->Int32Value();
+    int previous = umask(mask);
+    return Number::New(previous);
+  } else {
+    const char* message = "umask() argument must be numeric";
+    return ThrowException(String::New(message));
+  }
+}
+
+
+static bool CheckItsADirectory(char* directory) {
+  struct stat stat_buf;
+  int stat_result = stat(directory, &stat_buf);
+  if (stat_result != 0) {
+    ThrowException(String::New(strerror(errno)));
+    return false;
+  }
+  if ((stat_buf.st_mode & S_IFDIR) != 0) return true;
+  ThrowException(String::New(strerror(EEXIST)));
+  return false;
+}
+
+
+// Returns true for success.  Creates intermediate directories as needed.  No
+// error if the directory exists already.
+static bool mkdirp(char* directory, mode_t mask) {
+  int result = mkdir(directory, mask);
+  if (result == 0) return true;
+  if (errno == EEXIST) {
+    return CheckItsADirectory(directory);
+  } else if (errno == ENOENT) {  // Intermediate path element is missing.
+    char* last_slash = strrchr(directory, '/');
+    if (last_slash == NULL) {
+      ThrowException(String::New(strerror(errno)));
+      return false;
+    }
+    *last_slash = 0;
+    if (!mkdirp(directory, mask)) return false;
+    *last_slash = '/';
+    result = mkdir(directory, mask);
+    if (result == 0) return true;
+    if (errno == EEXIST) {
+      return CheckItsADirectory(directory);
+    }
+    ThrowException(String::New(strerror(errno)));
+    return false;
+  } else {
+    ThrowException(String::New(strerror(errno)));
+    return false;
+  }
+}
+
+
+Handle<Value> Shell::MakeDirectory(const Arguments& args) {
+  mode_t mask = 0777;
+  if (args.Length() == 2) {
+    if (args[1]->IsNumber()) {
+      mask = args[1]->Int32Value();
+    } else {
+      const char* message = "mkdirp() second argument must be numeric";
+      return ThrowException(String::New(message));
+    }
+  } else if (args.Length() != 1) {
+    const char* message = "mkdirp() takes one or two arguments";
+    return ThrowException(String::New(message));
+  }
+  String::Utf8Value directory(args[0]);
+  if (*directory == NULL) {
+    const char* message = "os.mkdirp(): String conversion of argument failed.";
+    return ThrowException(String::New(message));
+  }
+  mkdirp(*directory, mask);
+  return v8::Undefined();
+}
+
+
+Handle<Value> Shell::RemoveDirectory(const Arguments& args) {
+  if (args.Length() != 1) {
+    const char* message = "rmdir() takes one or two arguments";
+    return ThrowException(String::New(message));
+  }
+  String::Utf8Value directory(args[0]);
+  if (*directory == NULL) {
+    const char* message = "os.rmdir(): String conversion of argument failed.";
+    return ThrowException(String::New(message));
+  }
+  rmdir(*directory);
+  return v8::Undefined();
+}
+
+
+Handle<Value> Shell::SetEnvironment(const Arguments& args) {
+  if (args.Length() != 2) {
+    const char* message = "setenv() takes two arguments";
+    return ThrowException(String::New(message));
+  }
+  String::Utf8Value var(args[0]);
+  String::Utf8Value value(args[1]);
+  if (*var == NULL) {
+    const char* message =
+        "os.setenv(): String conversion of variable name failed.";
+    return ThrowException(String::New(message));
+  }
+  if (*value == NULL) {
+    const char* message =
+        "os.setenv(): String conversion of variable contents failed.";
+    return ThrowException(String::New(message));
+  }
+  setenv(*var, *value, 1);
+  return v8::Undefined();
+}
+
+
+void Shell::AddOSMethods(Handle<ObjectTemplate> os_templ) {
+  os_templ->Set(String::New("system"), FunctionTemplate::New(System));
+  os_templ->Set(String::New("chdir"), FunctionTemplate::New(ChangeDirectory));
+  os_templ->Set(String::New("setenv"), FunctionTemplate::New(SetEnvironment));
+  os_templ->Set(String::New("umask"), FunctionTemplate::New(SetUMask));
+  os_templ->Set(String::New("mkdirp"), FunctionTemplate::New(MakeDirectory));
+  os_templ->Set(String::New("rmdir"), FunctionTemplate::New(RemoveDirectory));
+}
+
+}  // namespace v8
diff --git a/deps/v8/src/d8-readline.cc b/deps/v8/src/d8-readline.cc
new file mode 100644
index 0000000..34b7b60
--- /dev/null
+++ b/deps/v8/src/d8-readline.cc
@@ -0,0 +1,128 @@
+// Copyright 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.
+
+
+#include <cstdio>  // NOLINT
+#include <readline/readline.h>
+#include <readline/history.h>
+
+
+#include "d8.h"
+
+
+// There are incompatibilities between different versions and different
+// implementations of readline.  This smooths out one known incompatibility.
+#if RL_READLINE_VERSION >= 0x0500
+#define completion_matches rl_completion_matches
+#endif
+
+
+namespace v8 {
+
+
+class ReadLineEditor: public LineEditor {
+ public:
+  ReadLineEditor() : LineEditor(LineEditor::READLINE, "readline") { }
+  virtual i::SmartPointer<char> Prompt(const char* prompt);
+  virtual bool Open();
+  virtual bool Close();
+  virtual void AddHistory(const char* str);
+ private:
+  static char** AttemptedCompletion(const char* text, int start, int end);
+  static char* CompletionGenerator(const char* text, int state);
+  static char kWordBreakCharacters[];
+};
+
+
+static ReadLineEditor read_line_editor;
+char ReadLineEditor::kWordBreakCharacters[] = {' ', '\t', '\n', '"',
+    '\\', '\'', '`', '@', '.', '>', '<', '=', ';', '|', '&', '{', '(',
+    '\0'};
+
+
+bool ReadLineEditor::Open() {
+  rl_initialize();
+  rl_attempted_completion_function = AttemptedCompletion;
+  rl_completer_word_break_characters = kWordBreakCharacters;
+  rl_bind_key('\t', rl_complete);
+  using_history();
+  return read_history(Shell::kHistoryFileName) == 0;
+}
+
+
+bool ReadLineEditor::Close() {
+  return write_history(Shell::kHistoryFileName) == 0;
+}
+
+
+i::SmartPointer<char> ReadLineEditor::Prompt(const char* prompt) {
+  char* result = readline(prompt);
+  return i::SmartPointer<char>(result);
+}
+
+
+void ReadLineEditor::AddHistory(const char* str) {
+  add_history(str);
+}
+
+
+char** ReadLineEditor::AttemptedCompletion(const char* text,
+                                           int start,
+                                           int end) {
+  char** result = completion_matches(text, CompletionGenerator);
+  rl_attempted_completion_over = true;
+  return result;
+}
+
+
+char* ReadLineEditor::CompletionGenerator(const char* text, int state) {
+  static unsigned current_index;
+  static Persistent<Array> current_completions;
+  if (state == 0) {
+    i::SmartPointer<char> full_text(i::StrNDup(rl_line_buffer, rl_point));
+    HandleScope scope;
+    Handle<Array> completions =
+      Shell::GetCompletions(String::New(text), String::New(*full_text));
+    current_completions = Persistent<Array>::New(completions);
+    current_index = 0;
+  }
+  if (current_index < current_completions->Length()) {
+    HandleScope scope;
+    Handle<Integer> index = Integer::New(current_index);
+    Handle<Value> str_obj = current_completions->Get(index);
+    current_index++;
+    String::Utf8Value str(str_obj);
+    return strdup(*str);
+  } else {
+    current_completions.Dispose();
+    current_completions.Clear();
+    return NULL;
+  }
+}
+
+
+}  // namespace v8
diff --git a/deps/v8/src/d8-windows.cc b/deps/v8/src/d8-windows.cc
new file mode 100644
index 0000000..eeb4735
--- /dev/null
+++ b/deps/v8/src/d8-windows.cc
@@ -0,0 +1,42 @@
+// 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.
+
+
+#include "d8.h"
+#include "d8-debug.h"
+#include "debug.h"
+#include "api.h"
+
+
+namespace v8 {
+
+
+void Shell::AddOSMethods(Handle<ObjectTemplate> os_templ) {
+}
+
+
+}  // namespace v8
diff --git a/deps/v8/src/d8.cc b/deps/v8/src/d8.cc
new file mode 100644
index 0000000..9648168
--- /dev/null
+++ b/deps/v8/src/d8.cc
@@ -0,0 +1,726 @@
+// 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.
+
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include "d8.h"
+#include "d8-debug.h"
+#include "debug.h"
+#include "api.h"
+#include "natives.h"
+#include "platform.h"
+
+
+namespace v8 {
+
+
+const char* Shell::kHistoryFileName = ".d8_history";
+const char* Shell::kPrompt = "d8> ";
+
+
+LineEditor *LineEditor::first_ = NULL;
+
+
+LineEditor::LineEditor(Type type, const char* name)
+    : type_(type),
+      name_(name),
+      next_(first_) {
+  first_ = this;
+}
+
+
+LineEditor* LineEditor::Get() {
+  LineEditor* current = first_;
+  LineEditor* best = current;
+  while (current != NULL) {
+    if (current->type_ > best->type_)
+      best = current;
+    current = current->next_;
+  }
+  return best;
+}
+
+
+class DumbLineEditor: public LineEditor {
+ public:
+  DumbLineEditor() : LineEditor(LineEditor::DUMB, "dumb") { }
+  virtual i::SmartPointer<char> Prompt(const char* prompt);
+};
+
+
+static DumbLineEditor dumb_line_editor;
+
+
+i::SmartPointer<char> DumbLineEditor::Prompt(const char* prompt) {
+  static const int kBufferSize = 256;
+  char buffer[kBufferSize];
+  printf("%s", prompt);
+  char* str = fgets(buffer, kBufferSize, stdin);
+  return i::SmartPointer<char>(str ? i::StrDup(str) : str);
+}
+
+
+CounterMap* Shell::counter_map_;
+i::OS::MemoryMappedFile* Shell::counters_file_ = NULL;
+CounterCollection Shell::local_counters_;
+CounterCollection* Shell::counters_ = &local_counters_;
+Persistent<Context> Shell::utility_context_;
+Persistent<Context> Shell::evaluation_context_;
+
+
+bool CounterMap::Match(void* key1, void* key2) {
+  const char* name1 = reinterpret_cast<const char*>(key1);
+  const char* name2 = reinterpret_cast<const char*>(key2);
+  return strcmp(name1, name2) == 0;
+}
+
+
+// Converts a V8 value to a C string.
+const char* ToCString(const v8::String::Utf8Value& value) {
+  return *value ? *value : "<string conversion failed>";
+}
+
+
+// Executes a string within the current v8 context.
+bool Shell::ExecuteString(Handle<String> source,
+                          Handle<Value> name,
+                          bool print_result,
+                          bool report_exceptions) {
+  HandleScope handle_scope;
+  TryCatch try_catch;
+  if (i::FLAG_debugger) {
+    // When debugging make exceptions appear to be uncaught.
+    try_catch.SetVerbose(true);
+  }
+  Handle<Script> script = Script::Compile(source, name);
+  if (script.IsEmpty()) {
+    // Print errors that happened during compilation.
+    if (report_exceptions && !i::FLAG_debugger)
+      ReportException(&try_catch);
+    return false;
+  } else {
+    Handle<Value> result = script->Run();
+    if (result.IsEmpty()) {
+      // Print errors that happened during execution.
+      if (report_exceptions && !i::FLAG_debugger)
+        ReportException(&try_catch);
+      return false;
+    } else {
+      if (print_result && !result->IsUndefined()) {
+        // If all went well and the result wasn't undefined then print
+        // the returned value.
+        v8::String::Utf8Value str(result);
+        const char* cstr = ToCString(str);
+        printf("%s\n", cstr);
+      }
+      return true;
+    }
+  }
+}
+
+
+Handle<Value> Shell::Print(const Arguments& args) {
+  bool first = true;
+  for (int i = 0; i < args.Length(); i++) {
+    HandleScope handle_scope;
+    if (first) {
+      first = false;
+    } else {
+      printf(" ");
+    }
+    v8::String::Utf8Value str(args[i]);
+    const char* cstr = ToCString(str);
+    printf("%s", cstr);
+  }
+  printf("\n");
+  return Undefined();
+}
+
+
+Handle<Value> Shell::Load(const Arguments& args) {
+  for (int i = 0; i < args.Length(); i++) {
+    HandleScope handle_scope;
+    String::Utf8Value file(args[i]);
+    if (*file == NULL) {
+      return ThrowException(String::New("Error loading file"));
+    }
+    Handle<String> source = ReadFile(*file);
+    if (source.IsEmpty()) {
+      return ThrowException(String::New("Error loading file"));
+    }
+    if (!ExecuteString(source, String::New(*file), false, false)) {
+      return ThrowException(String::New("Error executing  file"));
+    }
+  }
+  return Undefined();
+}
+
+
+Handle<Value> Shell::Yield(const Arguments& args) {
+  v8::Unlocker unlocker;
+  return Undefined();
+}
+
+
+Handle<Value> Shell::Quit(const Arguments& args) {
+  int exit_code = args[0]->Int32Value();
+  OnExit();
+  exit(exit_code);
+  return Undefined();
+}
+
+
+Handle<Value> Shell::Version(const Arguments& args) {
+  return String::New(V8::GetVersion());
+}
+
+
+void Shell::ReportException(v8::TryCatch* try_catch) {
+  HandleScope handle_scope;
+  v8::String::Utf8Value exception(try_catch->Exception());
+  const char* exception_string = ToCString(exception);
+  Handle<Message> message = try_catch->Message();
+  if (message.IsEmpty()) {
+    // V8 didn't provide any extra information about this error; just
+    // print the exception.
+    printf("%s\n", exception_string);
+  } else {
+    // Print (filename):(line number): (message).
+    v8::String::Utf8Value filename(message->GetScriptResourceName());
+    const char* filename_string = ToCString(filename);
+    int linenum = message->GetLineNumber();
+    printf("%s:%i: %s\n", filename_string, linenum, exception_string);
+    // Print line of source code.
+    v8::String::Utf8Value sourceline(message->GetSourceLine());
+    const char* sourceline_string = ToCString(sourceline);
+    printf("%s\n", sourceline_string);
+    // Print wavy underline (GetUnderline is deprecated).
+    int start = message->GetStartColumn();
+    for (int i = 0; i < start; i++) {
+      printf(" ");
+    }
+    int end = message->GetEndColumn();
+    for (int i = start; i < end; i++) {
+      printf("^");
+    }
+    printf("\n");
+  }
+}
+
+
+Handle<Array> Shell::GetCompletions(Handle<String> text, Handle<String> full) {
+  HandleScope handle_scope;
+  Context::Scope context_scope(utility_context_);
+  Handle<Object> global = utility_context_->Global();
+  Handle<Value> fun = global->Get(String::New("GetCompletions"));
+  static const int kArgc = 3;
+  Handle<Value> argv[kArgc] = { evaluation_context_->Global(), text, full };
+  Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
+  return handle_scope.Close(Handle<Array>::Cast(val));
+}
+
+
+Handle<Object> Shell::DebugMessageDetails(Handle<String> message) {
+  Context::Scope context_scope(utility_context_);
+  Handle<Object> global = utility_context_->Global();
+  Handle<Value> fun = global->Get(String::New("DebugMessageDetails"));
+  static const int kArgc = 1;
+  Handle<Value> argv[kArgc] = { message };
+  Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
+  return Handle<Object>::Cast(val);
+}
+
+
+Handle<Value> Shell::DebugCommandToJSONRequest(Handle<String> command) {
+  Context::Scope context_scope(utility_context_);
+  Handle<Object> global = utility_context_->Global();
+  Handle<Value> fun = global->Get(String::New("DebugCommandToJSONRequest"));
+  static const int kArgc = 1;
+  Handle<Value> argv[kArgc] = { command };
+  Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
+  return val;
+}
+
+
+int32_t* Counter::Bind(const char* name, bool is_histogram) {
+  int i;
+  for (i = 0; i < kMaxNameSize - 1 && name[i]; i++)
+    name_[i] = static_cast<char>(name[i]);
+  name_[i] = '\0';
+  is_histogram_ = is_histogram;
+  return ptr();
+}
+
+
+void Counter::AddSample(int32_t sample) {
+  count_++;
+  sample_total_ += sample;
+}
+
+
+CounterCollection::CounterCollection() {
+  magic_number_ = 0xDEADFACE;
+  max_counters_ = kMaxCounters;
+  max_name_size_ = Counter::kMaxNameSize;
+  counters_in_use_ = 0;
+}
+
+
+Counter* CounterCollection::GetNextCounter() {
+  if (counters_in_use_ == kMaxCounters) return NULL;
+  return &counters_[counters_in_use_++];
+}
+
+
+void Shell::MapCounters(const char* name) {
+  counters_file_ = i::OS::MemoryMappedFile::create(name,
+    sizeof(CounterCollection), &local_counters_);
+  void* memory = (counters_file_ == NULL) ?
+      NULL : counters_file_->memory();
+  if (memory == NULL) {
+    printf("Could not map counters file %s\n", name);
+    exit(1);
+  }
+  counters_ = static_cast<CounterCollection*>(memory);
+  V8::SetCounterFunction(LookupCounter);
+  V8::SetCreateHistogramFunction(CreateHistogram);
+  V8::SetAddHistogramSampleFunction(AddHistogramSample);
+}
+
+
+int CounterMap::Hash(const char* name) {
+  int h = 0;
+  int c;
+  while ((c = *name++) != 0) {
+    h += h << 5;
+    h += c;
+  }
+  return h;
+}
+
+
+Counter* Shell::GetCounter(const char* name, bool is_histogram) {
+  Counter* counter = counter_map_->Lookup(name);
+
+  if (counter == NULL) {
+    counter = counters_->GetNextCounter();
+    if (counter != NULL) {
+      counter_map_->Set(name, counter);
+      counter->Bind(name, is_histogram);
+    }
+  } else {
+    ASSERT(counter->is_histogram() == is_histogram);
+  }
+  return counter;
+}
+
+
+int* Shell::LookupCounter(const char* name) {
+  Counter* counter = GetCounter(name, false);
+
+  if (counter != NULL) {
+    return counter->ptr();
+  } else {
+    return NULL;
+  }
+}
+
+
+void* Shell::CreateHistogram(const char* name,
+                             int min,
+                             int max,
+                             size_t buckets) {
+  return GetCounter(name, true);
+}
+
+
+void Shell::AddHistogramSample(void* histogram, int sample) {
+  Counter* counter = reinterpret_cast<Counter*>(histogram);
+  counter->AddSample(sample);
+}
+
+
+void Shell::Initialize() {
+  Shell::counter_map_ = new CounterMap();
+  // Set up counters
+  if (i::FLAG_map_counters != NULL)
+    MapCounters(i::FLAG_map_counters);
+  if (i::FLAG_dump_counters) {
+    V8::SetCounterFunction(LookupCounter);
+    V8::SetCreateHistogramFunction(CreateHistogram);
+    V8::SetAddHistogramSampleFunction(AddHistogramSample);
+  }
+
+  // Initialize the global objects
+  HandleScope scope;
+  Handle<ObjectTemplate> global_template = ObjectTemplate::New();
+  global_template->Set(String::New("print"), FunctionTemplate::New(Print));
+  global_template->Set(String::New("load"), FunctionTemplate::New(Load));
+  global_template->Set(String::New("quit"), FunctionTemplate::New(Quit));
+  global_template->Set(String::New("version"), FunctionTemplate::New(Version));
+
+  Handle<ObjectTemplate> os_templ = ObjectTemplate::New();
+  AddOSMethods(os_templ);
+  global_template->Set(String::New("os"), os_templ);
+
+  utility_context_ = Context::New(NULL, global_template);
+  utility_context_->SetSecurityToken(Undefined());
+  Context::Scope utility_scope(utility_context_);
+
+  i::JSArguments js_args = i::FLAG_js_arguments;
+  i::Handle<i::FixedArray> arguments_array =
+      i::Factory::NewFixedArray(js_args.argc());
+  for (int j = 0; j < js_args.argc(); j++) {
+    i::Handle<i::String> arg =
+        i::Factory::NewStringFromUtf8(i::CStrVector(js_args[j]));
+    arguments_array->set(j, *arg);
+  }
+  i::Handle<i::JSArray> arguments_jsarray =
+      i::Factory::NewJSArrayWithElements(arguments_array);
+  global_template->Set(String::New("arguments"),
+                       Utils::ToLocal(arguments_jsarray));
+
+  // Install the debugger object in the utility scope
+  i::Debug::Load();
+  i::JSObject* debug = i::Debug::debug_context()->global();
+  utility_context_->Global()->Set(String::New("$debug"),
+                                  Utils::ToLocal(&debug));
+
+  // Run the d8 shell utility script in the utility context
+  int source_index = i::NativesCollection<i::D8>::GetIndex("d8");
+  i::Vector<const char> shell_source
+      = i::NativesCollection<i::D8>::GetScriptSource(source_index);
+  i::Vector<const char> shell_source_name
+      = i::NativesCollection<i::D8>::GetScriptName(source_index);
+  Handle<String> source = String::New(shell_source.start(),
+                                      shell_source.length());
+  Handle<String> name = String::New(shell_source_name.start(),
+                                    shell_source_name.length());
+  Handle<Script> script = Script::Compile(source, name);
+  script->Run();
+
+  // Mark the d8 shell script as native to avoid it showing up as normal source
+  // in the debugger.
+  i::Handle<i::JSFunction> script_fun = Utils::OpenHandle(*script);
+  i::Handle<i::Script> script_object =
+      i::Handle<i::Script>(i::Script::cast(script_fun->shared()->script()));
+  script_object->set_type(i::Smi::FromInt(i::SCRIPT_TYPE_NATIVE));
+
+  // Create the evaluation context
+  evaluation_context_ = Context::New(NULL, global_template);
+  evaluation_context_->SetSecurityToken(Undefined());
+
+  // Set the security token of the debug context to allow access.
+  i::Debug::debug_context()->set_security_token(i::Heap::undefined_value());
+}
+
+
+void Shell::OnExit() {
+  if (i::FLAG_dump_counters) {
+    ::printf("+----------------------------------------+-------------+\n");
+    ::printf("| Name                                   | Value       |\n");
+    ::printf("+----------------------------------------+-------------+\n");
+    for (CounterMap::Iterator i(counter_map_); i.More(); i.Next()) {
+      Counter* counter = i.CurrentValue();
+      if (counter->is_histogram()) {
+        ::printf("| c:%-36s | %11i |\n", i.CurrentKey(), counter->count());
+        ::printf("| t:%-36s | %11i |\n",
+                 i.CurrentKey(),
+                 counter->sample_total());
+      } else {
+        ::printf("| %-38s | %11i |\n", i.CurrentKey(), counter->count());
+      }
+    }
+    ::printf("+----------------------------------------+-------------+\n");
+  }
+  if (counters_file_ != NULL)
+    delete counters_file_;
+}
+
+
+static char* ReadChars(const char *name, int* size_out) {
+  v8::Unlocker unlocker;  // Release the V8 lock while reading files.
+  FILE* file = i::OS::FOpen(name, "rb");
+  if (file == NULL) return NULL;
+
+  fseek(file, 0, SEEK_END);
+  int size = ftell(file);
+  rewind(file);
+
+  char* chars = new char[size + 1];
+  chars[size] = '\0';
+  for (int i = 0; i < size;) {
+    int read = fread(&chars[i], 1, size - i, file);
+    i += read;
+  }
+  fclose(file);
+  *size_out = size;
+  return chars;
+}
+
+
+static char* ReadToken(char* data, char token) {
+  char* next = i::OS::StrChr(data, token);
+  if (next != NULL) {
+    *next = '\0';
+    return (next + 1);
+  }
+
+  return NULL;
+}
+
+
+static char* ReadLine(char* data) {
+  return ReadToken(data, '\n');
+}
+
+
+static char* ReadWord(char* data) {
+  return ReadToken(data, ' ');
+}
+
+
+// Reads a file into a v8 string.
+Handle<String> Shell::ReadFile(const char* name) {
+  int size = 0;
+  char* chars = ReadChars(name, &size);
+  if (chars == NULL) return Handle<String>();
+  Handle<String> result = String::New(chars);
+  delete[] chars;
+  return result;
+}
+
+
+void Shell::RunShell() {
+  LineEditor* editor = LineEditor::Get();
+  printf("V8 version %s [console: %s]\n", V8::GetVersion(), editor->name());
+  editor->Open();
+  while (true) {
+    Locker locker;
+    HandleScope handle_scope;
+    Context::Scope context_scope(evaluation_context_);
+    i::SmartPointer<char> input = editor->Prompt(Shell::kPrompt);
+    if (input.is_empty())
+      break;
+    editor->AddHistory(*input);
+    Handle<String> name = String::New("(d8)");
+    ExecuteString(String::New(*input), name, true, true);
+  }
+  editor->Close();
+  printf("\n");
+}
+
+
+class ShellThread : public i::Thread {
+ public:
+  ShellThread(int no, i::Vector<const char> files)
+    : no_(no), files_(files) { }
+  virtual void Run();
+ private:
+  int no_;
+  i::Vector<const char> files_;
+};
+
+
+void ShellThread::Run() {
+  // Prepare the context for this thread.
+  Locker locker;
+  HandleScope scope;
+  Handle<ObjectTemplate> global_template = ObjectTemplate::New();
+  global_template->Set(String::New("print"),
+                       FunctionTemplate::New(Shell::Print));
+  global_template->Set(String::New("load"),
+                       FunctionTemplate::New(Shell::Load));
+  global_template->Set(String::New("yield"),
+                       FunctionTemplate::New(Shell::Yield));
+  global_template->Set(String::New("version"),
+                       FunctionTemplate::New(Shell::Version));
+
+  char* ptr = const_cast<char*>(files_.start());
+  while ((ptr != NULL) && (*ptr != '\0')) {
+    // For each newline-separated line.
+    char* next_line = ReadLine(ptr);
+
+    if (*ptr == '#') {
+      // Skip comment lines.
+      ptr = next_line;
+      continue;
+    }
+
+    Persistent<Context> thread_context = Context::New(NULL, global_template);
+    thread_context->SetSecurityToken(Undefined());
+    Context::Scope context_scope(thread_context);
+
+    while ((ptr != NULL) && (*ptr != '\0')) {
+      char* filename = ptr;
+      ptr = ReadWord(ptr);
+
+      // Skip empty strings.
+      if (strlen(filename) == 0) {
+        break;
+      }
+
+      Handle<String> str = Shell::ReadFile(filename);
+      if (str.IsEmpty()) {
+        printf("WARNING: %s not found\n", filename);
+        break;
+      }
+
+      Shell::ExecuteString(str, String::New(filename), false, false);
+    }
+
+    thread_context.Dispose();
+    ptr = next_line;
+  }
+}
+
+
+int Shell::Main(int argc, char* argv[]) {
+  i::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
+  if (i::FLAG_help) {
+    return 1;
+  }
+  Initialize();
+  bool run_shell = (argc == 1);
+
+  // Default use preemption if threads are created.
+  bool use_preemption = true;
+
+  // Default to use lowest possible thread preemption interval to test as many
+  // edgecases as possible.
+  int preemption_interval = 1;
+
+  i::List<i::Thread*> threads(1);
+
+  {
+    // Acquire the V8 lock once initialization has finished. Since the thread
+    // below may spawn new threads accessing V8 holding the V8 lock here is
+    // mandatory.
+    Locker locker;
+    Context::Scope context_scope(evaluation_context_);
+    for (int i = 1; i < argc; i++) {
+      char* str = argv[i];
+      if (strcmp(str, "--shell") == 0) {
+        run_shell = true;
+      } else if (strcmp(str, "--preemption") == 0) {
+        use_preemption = true;
+      } else if (strcmp(str, "--no-preemption") == 0) {
+        use_preemption = false;
+      } else if (strcmp(str, "--preemption-interval") == 0) {
+        if (i + 1 < argc) {
+          char *end = NULL;
+          preemption_interval = strtol(argv[++i], &end, 10);  // NOLINT
+          if (preemption_interval <= 0 || *end != '\0' || errno == ERANGE) {
+            printf("Invalid value for --preemption-interval '%s'\n", argv[i]);
+            return 1;
+          }
+        } else {
+          printf("Missing value for --preemption-interval\n");
+          return 1;
+       }
+      } else if (strcmp(str, "-f") == 0) {
+        // Ignore any -f flags for compatibility with other stand-alone
+        // JavaScript engines.
+        continue;
+      } else if (strncmp(str, "--", 2) == 0) {
+        printf("Warning: unknown flag %s.\nTry --help for options\n", str);
+      } else if (strcmp(str, "-e") == 0 && i + 1 < argc) {
+        // Execute argument given to -e option directly.
+        v8::HandleScope handle_scope;
+        v8::Handle<v8::String> file_name = v8::String::New("unnamed");
+        v8::Handle<v8::String> source = v8::String::New(argv[i + 1]);
+        if (!ExecuteString(source, file_name, false, true)) {
+          OnExit();
+          return 1;
+        }
+        i++;
+      } else if (strcmp(str, "-p") == 0 && i + 1 < argc) {
+        int size = 0;
+        const char *files = ReadChars(argv[++i], &size);
+        if (files == NULL) return 1;
+        ShellThread *thread =
+            new ShellThread(threads.length(),
+                            i::Vector<const char>(files, size));
+        thread->Start();
+        threads.Add(thread);
+      } else {
+        // Use all other arguments as names of files to load and run.
+        HandleScope handle_scope;
+        Handle<String> file_name = v8::String::New(str);
+        Handle<String> source = ReadFile(str);
+        if (source.IsEmpty()) {
+          printf("Error reading '%s'\n", str);
+          return 1;
+        }
+        if (!ExecuteString(source, file_name, false, true)) {
+          OnExit();
+          return 1;
+        }
+      }
+    }
+
+    // Start preemption if threads have been created and preemption is enabled.
+    if (threads.length() > 0 && use_preemption) {
+      Locker::StartPreemption(preemption_interval);
+    }
+
+    // Run the remote debugger if requested.
+    if (i::FLAG_remote_debugger) {
+      RunRemoteDebugger(i::FLAG_debugger_port);
+      return 0;
+    }
+
+    // Start the debugger agent if requested.
+    if (i::FLAG_debugger_agent) {
+      v8::Debug::EnableAgent("d8 shell", i::FLAG_debugger_port);
+    }
+
+    // Start the in-process debugger if requested.
+    if (i::FLAG_debugger && !i::FLAG_debugger_agent) {
+      v8::Debug::SetDebugEventListener(HandleDebugEvent);
+    }
+  }
+  if (run_shell)
+    RunShell();
+  for (int i = 0; i < threads.length(); i++) {
+    i::Thread *thread = threads[i];
+    thread->Join();
+    delete thread;
+  }
+  OnExit();
+  return 0;
+}
+
+
+}  // namespace v8
+
+
+int main(int argc, char* argv[]) {
+  return v8::Shell::Main(argc, argv);
+}
diff --git a/deps/v8/src/d8.h b/deps/v8/src/d8.h
new file mode 100644
index 0000000..342a0d2
--- /dev/null
+++ b/deps/v8/src/d8.h
@@ -0,0 +1,220 @@
+// 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.
+
+#ifndef V8_D8_H_
+#define V8_D8_H_
+
+#include "v8.h"
+#include "hashmap.h"
+
+
+namespace v8 {
+
+
+namespace i = v8::internal;
+
+
+// A single counter in a counter collection.
+class Counter {
+ public:
+  static const int kMaxNameSize = 64;
+  int32_t* Bind(const char* name, bool histogram);
+  int32_t* ptr() { return &count_; }
+  int32_t count() { return count_; }
+  int32_t sample_total() { return sample_total_; }
+  bool is_histogram() { return is_histogram_; }
+  void AddSample(int32_t sample);
+ private:
+  int32_t count_;
+  int32_t sample_total_;
+  bool is_histogram_;
+  uint8_t name_[kMaxNameSize];
+};
+
+
+// A set of counters and associated information.  An instance of this
+// class is stored directly in the memory-mapped counters file if
+// the --map-counters options is used
+class CounterCollection {
+ public:
+  CounterCollection();
+  Counter* GetNextCounter();
+ private:
+  static const unsigned kMaxCounters = 256;
+  uint32_t magic_number_;
+  uint32_t max_counters_;
+  uint32_t max_name_size_;
+  uint32_t counters_in_use_;
+  Counter counters_[kMaxCounters];
+};
+
+
+class CounterMap {
+ public:
+  CounterMap(): hash_map_(Match) { }
+  Counter* Lookup(const char* name) {
+    i::HashMap::Entry* answer = hash_map_.Lookup(
+        const_cast<char*>(name),
+        Hash(name),
+        false);
+    if (!answer) return NULL;
+    return reinterpret_cast<Counter*>(answer->value);
+  }
+  void Set(const char* name, Counter* value) {
+    i::HashMap::Entry* answer = hash_map_.Lookup(
+        const_cast<char*>(name),
+        Hash(name),
+        true);
+    ASSERT(answer != NULL);
+    answer->value = value;
+  }
+  class Iterator {
+   public:
+    explicit Iterator(CounterMap* map)
+        : map_(&map->hash_map_), entry_(map_->Start()) { }
+    void Next() { entry_ = map_->Next(entry_); }
+    bool More() { return entry_ != NULL; }
+    const char* CurrentKey() { return static_cast<const char*>(entry_->key); }
+    Counter* CurrentValue() { return static_cast<Counter*>(entry_->value); }
+   private:
+    i::HashMap* map_;
+    i::HashMap::Entry* entry_;
+  };
+ private:
+  static int Hash(const char* name);
+  static bool Match(void* key1, void* key2);
+  i::HashMap hash_map_;
+};
+
+
+class Shell: public i::AllStatic {
+ public:
+  static bool ExecuteString(Handle<String> source,
+                            Handle<Value> name,
+                            bool print_result,
+                            bool report_exceptions);
+  static void ReportException(TryCatch* try_catch);
+  static void Initialize();
+  static void OnExit();
+  static int* LookupCounter(const char* name);
+  static void* CreateHistogram(const char* name,
+                               int min,
+                               int max,
+                               size_t buckets);
+  static void AddHistogramSample(void* histogram, int sample);
+  static void MapCounters(const char* name);
+  static Handle<String> ReadFile(const char* name);
+  static void RunShell();
+  static int Main(int argc, char* argv[]);
+  static Handle<Array> GetCompletions(Handle<String> text,
+                                      Handle<String> full);
+  static Handle<Object> DebugMessageDetails(Handle<String> message);
+  static Handle<Value> DebugCommandToJSONRequest(Handle<String> command);
+
+  static Handle<Value> Print(const Arguments& args);
+  static Handle<Value> Yield(const Arguments& args);
+  static Handle<Value> Quit(const Arguments& args);
+  static Handle<Value> Version(const Arguments& args);
+  static Handle<Value> Load(const Arguments& args);
+  // The OS object on the global object contains methods for performing
+  // operating system calls:
+  //
+  // os.system("program_name", ["arg1", "arg2", ...], timeout1, timeout2) will
+  // run the command, passing the arguments to the program.  The standard output
+  // of the program will be picked up and returned as a multiline string.  If
+  // timeout1 is present then it should be a number.  -1 indicates no timeout
+  // and a positive number is used as a timeout in milliseconds that limits the
+  // time spent waiting between receiving output characters from the program.
+  // timeout2, if present, should be a number indicating the limit in
+  // milliseconds on the total running time of the program.  Exceptions are
+  // thrown on timeouts or other errors or if the exit status of the program
+  // indicates an error.
+  //
+  // os.chdir(dir) changes directory to the given directory.  Throws an
+  // exception/ on error.
+  //
+  // os.setenv(variable, value) sets an environment variable.  Repeated calls to
+  // this method leak memory due to the API of setenv in the standard C library.
+  //
+  // os.umask(alue) calls the umask system call and returns the old umask.
+  //
+  // os.mkdirp(name, mask) creates a directory.  The mask (if present) is anded
+  // with the current umask.  Intermediate directories are created if necessary.
+  // An exception is not thrown if the directory already exists.  Analogous to
+  // the "mkdir -p" command.
+  static Handle<Value> OSObject(const Arguments& args);
+  static Handle<Value> System(const Arguments& args);
+  static Handle<Value> ChangeDirectory(const Arguments& args);
+  static Handle<Value> SetEnvironment(const Arguments& args);
+  static Handle<Value> SetUMask(const Arguments& args);
+  static Handle<Value> MakeDirectory(const Arguments& args);
+  static Handle<Value> RemoveDirectory(const Arguments& args);
+
+  static void AddOSMethods(Handle<ObjectTemplate> os_template);
+
+  static Handle<Context> utility_context() { return utility_context_; }
+
+  static const char* kHistoryFileName;
+  static const char* kPrompt;
+ private:
+  static Persistent<Context> utility_context_;
+  static Persistent<Context> evaluation_context_;
+  static CounterMap* counter_map_;
+  // We statically allocate a set of local counters to be used if we
+  // don't want to store the stats in a memory-mapped file
+  static CounterCollection local_counters_;
+  static CounterCollection* counters_;
+  static i::OS::MemoryMappedFile* counters_file_;
+  static Counter* GetCounter(const char* name, bool is_histogram);
+};
+
+
+class LineEditor {
+ public:
+  enum Type { DUMB = 0, READLINE = 1 };
+  LineEditor(Type type, const char* name);
+  virtual ~LineEditor() { }
+
+  virtual i::SmartPointer<char> Prompt(const char* prompt) = 0;
+  virtual bool Open() { return true; }
+  virtual bool Close() { return true; }
+  virtual void AddHistory(const char* str) { }
+
+  const char* name() { return name_; }
+  static LineEditor* Get();
+ private:
+  Type type_;
+  const char* name_;
+  LineEditor* next_;
+  static LineEditor* first_;
+};
+
+
+}  // namespace v8
+
+
+#endif  // V8_D8_H_
diff --git a/deps/v8/src/d8.js b/deps/v8/src/d8.js
new file mode 100644
index 0000000..e2766d0
--- /dev/null
+++ b/deps/v8/src/d8.js
@@ -0,0 +1,1434 @@
+// Copyright 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.
+
+// How crappy is it that I have to implement completely basic stuff
+// like this myself?  Answer: very.
+String.prototype.startsWith = function (str) {
+  if (str.length > this.length)
+    return false;
+  return this.substr(0, str.length) == str;
+}
+
+function log10(num) {
+  return Math.log(num)/Math.log(10);
+}
+
+function ToInspectableObject(obj) {
+  if (!obj && typeof obj === 'object') {
+    return void 0;
+  } else {
+    return Object(obj);
+  }
+}
+
+function GetCompletions(global, last, full) {
+  var full_tokens = full.split();
+  full = full_tokens.pop();
+  var parts = full.split('.');
+  parts.pop();
+  var current = global;
+  for (var i = 0; i < parts.length; i++) {
+    var part = parts[i];
+    var next = current[part];
+    if (!next)
+      return [];
+    current = next;
+  }
+  var result = [];
+  current = ToInspectableObject(current);
+  while (typeof current !== 'undefined') {
+    var mirror = new $debug.ObjectMirror(current);
+    var properties = mirror.properties();
+    for (var i = 0; i < properties.length; i++) {
+      var name = properties[i].name();
+      if (typeof name === 'string' && name.startsWith(last))
+        result.push(name);
+    }
+    current = ToInspectableObject(current.__proto__);
+  }
+  return result;
+}
+
+
+// Global object holding debugger related constants and state.
+const Debug = {};
+
+
+// Debug events which can occour in the V8 JavaScript engine. These originate
+// from the API include file v8-debug.h.
+Debug.DebugEvent = { Break: 1,
+                     Exception: 2,
+                     NewFunction: 3,
+                     BeforeCompile: 4,
+                     AfterCompile: 5 };
+
+
+// The different types of scripts matching enum ScriptType in objects.h.
+Debug.ScriptType = { Native: 0,
+                     Extension: 1,
+                     Normal: 2 };
+
+
+// Current debug state.
+const kNoFrame = -1;
+Debug.State = {
+  currentFrame: kNoFrame,
+  currentSourceLine: -1
+}
+var trace_compile = false;  // Tracing all compile events?
+
+
+// Process a debugger JSON message into a display text and a running status.
+// This function returns an object with properties "text" and "running" holding
+// this information.
+function DebugMessageDetails(message) {
+  // Convert the JSON string to an object.
+  var response = new ProtocolPackage(message);
+
+  if (response.type() == 'event') {
+    return DebugEventDetails(response);
+  } else {
+    return DebugResponseDetails(response);
+  }
+}
+
+function DebugEventDetails(response) {
+  details = {text:'', running:false}
+
+  // Get the running state.
+  details.running = response.running();
+
+  var body = response.body();
+  var result = '';
+  switch (response.event()) {
+    case 'break':
+      if (body.breakpoints) {
+        result += 'breakpoint';
+        if (body.breakpoints.length > 1) {
+          result += 's';
+        }
+        result += ' #';
+        for (var i = 0; i < body.breakpoints.length; i++) {
+          if (i > 0) {
+            result += ', #';
+          }
+          result += body.breakpoints[i];
+        }
+      } else {
+        result += 'break';
+      }
+      result += ' in ';
+      result += body.invocationText;
+      result += ', ';
+      result += SourceInfo(body);
+      result += '\n';
+      result += SourceUnderline(body.sourceLineText, body.sourceColumn);
+      Debug.State.currentSourceLine = body.sourceLine;
+      Debug.State.currentFrame = 0;
+      details.text = result;
+      break;
+      
+    case 'exception':
+      if (body.uncaught) {
+        result += 'Uncaught: ';
+      } else {
+        result += 'Exception: ';
+      }
+      result += '"';
+      result += body.exception.text;
+      result += '"';
+      if (body.sourceLine >= 0) {
+        result += ', ';
+        result += SourceInfo(body);
+        result += '\n';
+        result += SourceUnderline(body.sourceLineText, body.sourceColumn);
+        Debug.State.currentSourceLine = body.sourceLine;
+        Debug.State.currentFrame = 0;
+      } else {
+        result += ' (empty stack)';
+        Debug.State.currentSourceLine = -1;
+        Debug.State.currentFrame = kNoFrame;
+      }
+      details.text = result;
+      break;
+
+    case 'afterCompile':
+      if (trace_compile) {
+        result = 'Source ' + body.script.name + ' compiled:\n'
+        var source = body.script.source;
+        if (!(source[source.length - 1] == '\n')) {
+          result += source;
+        } else {
+          result += source.substring(0, source.length - 1);
+        }
+      }
+      details.text = result;
+      break;
+
+    default:
+      details.text = 'Unknown debug event ' + response.event();
+  }
+
+  return details;
+};
+
+
+function SourceInfo(body) {
+  var result = '';
+  
+  if (body.script) {
+    if (body.script.name) {
+      result += body.script.name;
+    } else {
+      result += '[unnamed]';
+    }
+  }
+  result += ' line ';
+  result += body.sourceLine + 1;
+  result += ' column ';
+  result += body.sourceColumn + 1;
+  
+  return result;
+}
+
+
+function SourceUnderline(source_text, position) {
+  if (!source_text) {
+    return;
+  }
+
+  // Create an underline with a caret pointing to the source position. If the
+  // source contains a tab character the underline will have a tab character in
+  // the same place otherwise the underline will have a space character.
+  var underline = '';
+  for (var i = 0; i < position; i++) {
+    if (source_text[i] == '\t') {
+      underline += '\t';
+    } else {
+      underline += ' ';
+    }
+  }
+  underline += '^';
+
+  // Return the source line text with the underline beneath.
+  return source_text + '\n' + underline;
+};
+
+
+// Converts a text command to a JSON request.
+function DebugCommandToJSONRequest(cmd_line) {
+  return new DebugRequest(cmd_line).JSONRequest();
+};
+
+
+function DebugRequest(cmd_line) {
+  // If the very first character is a { assume that a JSON request have been
+  // entered as a command. Converting that to a JSON request is trivial.
+  if (cmd_line && cmd_line.length > 0 && cmd_line.charAt(0) == '{') {
+    this.request_ = cmd_line;
+    return;
+  }
+
+  // Trim string for leading and trailing whitespace.
+  cmd_line = cmd_line.replace(/^\s+|\s+$/g, '');
+
+  // Find the command.
+  var pos = cmd_line.indexOf(' ');
+  var cmd;
+  var args;
+  if (pos == -1) {
+    cmd = cmd_line;
+    args = '';
+  } else {
+    cmd = cmd_line.slice(0, pos);
+    args = cmd_line.slice(pos).replace(/^\s+|\s+$/g, '');
+  }
+
+  // Switch on command.
+  switch (cmd) {
+    case 'continue':
+    case 'c':
+      this.request_ = this.continueCommandToJSONRequest_(args);
+      break;
+
+    case 'step':
+    case 's':
+      this.request_ = this.stepCommandToJSONRequest_(args);
+      break;
+
+    case 'backtrace':
+    case 'bt':
+      this.request_ = this.backtraceCommandToJSONRequest_(args);
+      break;
+      
+    case 'frame':
+    case 'f':
+      this.request_ = this.frameCommandToJSONRequest_(args);
+      break;
+      
+    case 'print':
+    case 'p':
+      this.request_ = this.printCommandToJSONRequest_(args);
+      break;
+
+    case 'dir':
+      this.request_ = this.dirCommandToJSONRequest_(args);
+      break;
+
+    case 'references':
+      this.request_ = this.referencesCommandToJSONRequest_(args);
+      break;
+
+    case 'instances':
+      this.request_ = this.instancesCommandToJSONRequest_(args);
+      break;
+
+    case 'source':
+      this.request_ = this.sourceCommandToJSONRequest_(args);
+      break;
+      
+    case 'scripts':
+      this.request_ = this.scriptsCommandToJSONRequest_(args);
+      break;
+      
+    case 'break':
+    case 'b':
+      this.request_ = this.breakCommandToJSONRequest_(args);
+      break;
+      
+    case 'clear':
+      this.request_ = this.clearCommandToJSONRequest_(args);
+      break;
+
+    case 'threads':
+      this.request_ = this.threadsCommandToJSONRequest_(args);
+      break;
+
+    case 'trace':
+      // Return undefined to indicate command handled internally (no JSON).
+      this.request_ = void 0;
+      this.traceCommand_(args);
+      break;
+
+    case 'help':
+    case '?':
+      this.helpCommand_(args);
+      // Return undefined to indicate command handled internally (no JSON).
+      this.request_ = void 0;
+      break;
+
+    default:
+      throw new Error('Unknown command "' + cmd + '"');
+  }
+  
+  last_cmd = cmd;
+}
+
+DebugRequest.prototype.JSONRequest = function() {
+  return this.request_;
+}
+
+
+function RequestPacket(command) {
+  this.seq = 0;
+  this.type = 'request';
+  this.command = command;
+}
+
+
+RequestPacket.prototype.toJSONProtocol = function() {
+  // Encode the protocol header.
+  var json = '{';
+  json += '"seq":' + this.seq;
+  json += ',"type":"' + this.type + '"';
+  if (this.command) {
+    json += ',"command":' + StringToJSON_(this.command);
+  }
+  if (this.arguments) {
+    json += ',"arguments":';
+    // Encode the arguments part.
+    if (this.arguments.toJSONProtocol) {
+      json += this.arguments.toJSONProtocol()
+    } else {
+      json += SimpleObjectToJSON_(this.arguments);
+    }
+  }
+  json += '}';
+  return json;
+}
+
+
+DebugRequest.prototype.createRequest = function(command) {
+  return new RequestPacket(command);
+};
+
+
+// Create a JSON request for the evaluation command.
+DebugRequest.prototype.makeEvaluateJSONRequest_ = function(expression) {
+  // Check if the expression is a handle id in the form #<handle>#.
+  var handle_match = expression.match(/^#([0-9]*)#$/);
+  if (handle_match) {
+    // Build a lookup request.
+    var request = this.createRequest('lookup');
+    request.arguments = {};
+    request.arguments.handle = parseInt(handle_match[1]);
+    return request.toJSONProtocol();
+  } else {
+    // Build an evaluate request.
+    var request = this.createRequest('evaluate');
+    request.arguments = {};
+    request.arguments.expression = expression;
+    // Request a global evaluation if there is no current frame.
+    if (Debug.State.currentFrame == kNoFrame) {
+      request.arguments.global = true;
+    }
+    return request.toJSONProtocol();
+  }
+};
+
+
+// Create a JSON request for the references/instances command.
+DebugRequest.prototype.makeReferencesJSONRequest_ = function(handle, type) {
+  // Build a references request.
+  var handle_match = handle.match(/^#([0-9]*)#$/);
+  if (handle_match) {
+    var request = this.createRequest('references');
+    request.arguments = {};
+    request.arguments.type = type;
+    request.arguments.handle = parseInt(handle_match[1]);
+    return request.toJSONProtocol();
+  } else {
+    throw new Error('Invalid object id.');
+  }
+};
+
+
+// Create a JSON request for the continue command.
+DebugRequest.prototype.continueCommandToJSONRequest_ = function(args) {
+  var request = this.createRequest('continue');
+  return request.toJSONProtocol();
+};
+
+
+// Create a JSON request for the step command.
+DebugRequest.prototype.stepCommandToJSONRequest_ = function(args) {
+  // Requesting a step is through the continue command with additional
+  // arguments.
+  var request = this.createRequest('continue');
+  request.arguments = {};
+
+  // Process arguments if any.
+  if (args && args.length > 0) {
+    args = args.split(/\s*[ ]+\s*/g);
+
+    if (args.length > 2) {
+      throw new Error('Invalid step arguments.');
+    }
+
+    if (args.length > 0) {
+      // Get step count argument if any.
+      if (args.length == 2) {
+        var stepcount = parseInt(args[1]);
+        if (isNaN(stepcount) || stepcount <= 0) {
+          throw new Error('Invalid step count argument "' + args[0] + '".');
+        }
+        request.arguments.stepcount = stepcount;
+      }
+
+      // Get the step action.
+      switch (args[0]) {
+        case 'in':
+        case 'i':
+          request.arguments.stepaction = 'in';
+          break;
+          
+        case 'min':
+        case 'm':
+          request.arguments.stepaction = 'min';
+          break;
+          
+        case 'next':
+        case 'n':
+          request.arguments.stepaction = 'next';
+          break;
+          
+        case 'out':
+        case 'o':
+          request.arguments.stepaction = 'out';
+          break;
+          
+        default:
+          throw new Error('Invalid step argument "' + args[0] + '".');
+      }
+    }
+  } else {
+    // Default is step next.
+    request.arguments.stepaction = 'next';
+  }
+
+  return request.toJSONProtocol();
+};
+
+
+// Create a JSON request for the backtrace command.
+DebugRequest.prototype.backtraceCommandToJSONRequest_ = function(args) {
+  // Build a backtrace request from the text command.
+  var request = this.createRequest('backtrace');
+  args = args.split(/\s*[ ]+\s*/g);
+  if (args.length == 2) {
+    request.arguments = {};
+    var fromFrame = parseInt(args[0]);
+    var toFrame = parseInt(args[1]);
+    if (isNaN(fromFrame) || fromFrame < 0) {
+      throw new Error('Invalid start frame argument "' + args[0] + '".');
+    }
+    if (isNaN(toFrame) || toFrame < 0) {
+      throw new Error('Invalid end frame argument "' + args[1] + '".');
+    }
+    if (fromFrame > toFrame) {
+      throw new Error('Invalid arguments start frame cannot be larger ' +
+                      'than end frame.');
+    }
+    request.arguments.fromFrame = fromFrame;
+    request.arguments.toFrame = toFrame + 1;
+  }
+  return request.toJSONProtocol();
+};
+
+
+// Create a JSON request for the frame command.
+DebugRequest.prototype.frameCommandToJSONRequest_ = function(args) {
+  // Build a frame request from the text command.
+  var request = this.createRequest('frame');
+  args = args.split(/\s*[ ]+\s*/g);
+  if (args.length > 0 && args[0].length > 0) {
+    request.arguments = {};
+    request.arguments.number = args[0];
+  }
+  return request.toJSONProtocol();
+};
+
+
+// Create a JSON request for the print command.
+DebugRequest.prototype.printCommandToJSONRequest_ = function(args) {
+  // Build an evaluate request from the text command.
+  if (args.length == 0) {
+    throw new Error('Missing expression.');
+  }
+  return this.makeEvaluateJSONRequest_(args);
+};
+
+
+// Create a JSON request for the dir command.
+DebugRequest.prototype.dirCommandToJSONRequest_ = function(args) {
+  // Build an evaluate request from the text command.
+  if (args.length == 0) {
+    throw new Error('Missing expression.');
+  }
+  return this.makeEvaluateJSONRequest_(args);
+};
+
+
+// Create a JSON request for the references command.
+DebugRequest.prototype.referencesCommandToJSONRequest_ = function(args) {
+  // Build an evaluate request from the text command.
+  if (args.length == 0) {
+    throw new Error('Missing object id.');
+  }
+  
+  return this.makeReferencesJSONRequest_(args, 'referencedBy');
+};
+
+
+// Create a JSON request for the instances command.
+DebugRequest.prototype.instancesCommandToJSONRequest_ = function(args) {
+  // Build an evaluate request from the text command.
+  if (args.length == 0) {
+    throw new Error('Missing object id.');
+  }
+  
+  // Build a references request.
+  return this.makeReferencesJSONRequest_(args, 'constructedBy');
+};
+
+
+// Create a JSON request for the source command.
+DebugRequest.prototype.sourceCommandToJSONRequest_ = function(args) {
+  // Build a evaluate request from the text command.
+  var request = this.createRequest('source');
+
+  // Default is ten lines starting five lines before the current location.
+  var from = Debug.State.currentSourceLine - 5;
+  var lines = 10;
+
+  // Parse the arguments.
+  args = args.split(/\s*[ ]+\s*/g);
+  if (args.length > 1 && args[0].length > 0 && args[1].length > 0) {
+    from = parseInt(args[0]) - 1;
+    lines = parseInt(args[1]);
+  } else if (args.length > 0 && args[0].length > 0) {
+    from = parseInt(args[0]) - 1;
+  }
+
+  if (from < 0) from = 0;
+  if (lines < 0) lines = 10;
+
+  // Request source arround current source location.
+  request.arguments = {};
+  request.arguments.fromLine = from;
+  request.arguments.toLine = from + lines;
+
+  return request.toJSONProtocol();
+};
+
+
+// Create a JSON request for the scripts command.
+DebugRequest.prototype.scriptsCommandToJSONRequest_ = function(args) {
+  // Build a evaluate request from the text command.
+  var request = this.createRequest('scripts');
+
+  // Process arguments if any.
+  if (args && args.length > 0) {
+    args = args.split(/\s*[ ]+\s*/g);
+
+    if (args.length > 1) {
+      throw new Error('Invalid scripts arguments.');
+    }
+
+    request.arguments = {};
+    switch (args[0]) {
+      case 'natives':
+        request.arguments.types = ScriptTypeFlag(Debug.ScriptType.Native);
+        break;
+        
+      case 'extensions':
+        request.arguments.types = ScriptTypeFlag(Debug.ScriptType.Extension);
+        break;
+        
+      case 'all':
+        request.arguments.types =
+            ScriptTypeFlag(Debug.ScriptType.Normal) |
+            ScriptTypeFlag(Debug.ScriptType.Native) |
+            ScriptTypeFlag(Debug.ScriptType.Extension);
+        break;
+        
+      default:
+        throw new Error('Invalid argument "' + args[0] + '".');
+    }
+  }
+
+  return request.toJSONProtocol();
+};
+
+
+// Create a JSON request for the break command.
+DebugRequest.prototype.breakCommandToJSONRequest_ = function(args) {
+  // Build a evaluate request from the text command.
+  var request = this.createRequest('setbreakpoint');
+
+  // Process arguments if any.
+  if (args && args.length > 0) {
+    var target = args;
+    var condition;
+
+    var pos = args.indexOf(' ');
+    if (pos > 0) {
+      target = args.substring(0, pos);
+      condition = args.substring(pos + 1, args.length);
+    }
+
+    request.arguments = {};
+    request.arguments.type = 'function';
+    request.arguments.target = target;
+    request.arguments.condition = condition;
+  } else {
+    throw new Error('Invalid break arguments.');
+  }
+
+  return request.toJSONProtocol();
+};
+
+
+// Create a JSON request for the clear command.
+DebugRequest.prototype.clearCommandToJSONRequest_ = function(args) {
+  // Build a evaluate request from the text command.
+  var request = this.createRequest('clearbreakpoint');
+
+  // Process arguments if any.
+  if (args && args.length > 0) {
+    request.arguments = {};
+    request.arguments.breakpoint = parseInt(args);
+  } else {
+    throw new Error('Invalid break arguments.');
+  }
+
+  return request.toJSONProtocol();
+};
+
+
+// Create a JSON request for the threads command.
+DebugRequest.prototype.threadsCommandToJSONRequest_ = function(args) {
+  // Build a threads request from the text command.
+  var request = this.createRequest('threads');
+  return request.toJSONProtocol();
+};
+
+
+// Handle the trace command.
+DebugRequest.prototype.traceCommand_ = function(args) {
+  // Process arguments.
+  if (args && args.length > 0) {
+    if (args == 'compile') {
+      trace_compile = !trace_compile;
+      print('Tracing of compiled scripts ' + (trace_compile ? 'on' : 'off'));
+    } else {
+      throw new Error('Invalid trace arguments.');
+    }
+  } else {
+    throw new Error('Invalid trace arguments.');
+  }
+}
+
+// Handle the help command.
+DebugRequest.prototype.helpCommand_ = function(args) {
+  // Help os quite simple.
+  if (args && args.length > 0) {
+    print('warning: arguments to \'help\' are ignored');
+  }
+
+  print('break location [condition]');
+  print('clear <breakpoint #>');
+  print('backtrace [from frame #] [to frame #]]');
+  print('frame <frame #>');
+  print('step [in | next | out| min [step count]]');
+  print('print <expression>');
+  print('source [from line [num lines]]');
+  print('scripts');
+  print('continue');
+  print('trace compile');
+  print('help');
+}
+
+
+function formatHandleReference_(value) {
+  return '#' + value.handle() + '#';
+}
+
+
+function formatObject_(value, include_properties) {
+  var result = '';
+  result += formatHandleReference_(value);
+  result += ', type: object'
+  result += ', constructor ';
+  var ctor = value.constructorFunctionValue();
+  result += formatHandleReference_(ctor);
+  result += ', __proto__ ';
+  var proto = value.protoObjectValue();
+  result += formatHandleReference_(proto);
+  result += ', ';
+  result += value.propertyCount();
+  result +=  ' properties.';
+  if (include_properties) {
+    result +=  '\n';
+    for (var i = 0; i < value.propertyCount(); i++) {
+      result += '  ';
+      result += value.propertyName(i);
+      result += ': ';
+      var property_value = value.propertyValue(i);
+      if (property_value && property_value.type()) {
+        result += property_value.type();
+      } else {
+        result += '<no type>';
+      }
+      result += ' ';
+      result += formatHandleReference_(property_value);
+      result += '\n';
+    }
+  }
+  return result;
+}
+
+
+// Convert a JSON response to text for display in a text based debugger.
+function DebugResponseDetails(response) {
+  details = {text:'', running:false}
+
+  try {
+    if (!response.success()) {
+      details.text = response.message();
+      return details;
+    }
+
+    // Get the running state.
+    details.running = response.running();
+
+    var body = response.body();
+    var result = '';
+    switch (response.command()) {
+      case 'setbreakpoint':
+        result = 'set breakpoint #';
+        result += body.breakpoint;
+        details.text = result;
+        break;
+        
+      case 'clearbreakpoint':
+        result = 'cleared breakpoint #';
+        result += body.breakpoint;
+        details.text = result;
+        break;
+        
+      case 'backtrace':
+        if (body.totalFrames == 0) {
+          result = '(empty stack)';
+        } else {
+          var result = 'Frames #' + body.fromFrame + ' to #' +
+              (body.toFrame - 1) + ' of ' + body.totalFrames + '\n';
+          for (i = 0; i < body.frames.length; i++) {
+            if (i != 0) result += '\n';
+            result += body.frames[i].text;
+          }
+        }
+        details.text = result;
+        break;
+        
+      case 'frame':
+        details.text = SourceUnderline(body.sourceLineText,
+                                       body.column);
+        Debug.State.currentSourceLine = body.line;
+        Debug.State.currentFrame = body.index;
+        break;
+        
+      case 'evaluate':
+      case 'lookup':
+        if (last_cmd == 'p' || last_cmd == 'print') {
+          result = body.text;
+        } else {
+          var value = response.bodyValue();
+          if (value.isObject()) {
+            result += formatObject_(value, true);
+          } else {
+            result += 'type: ';
+            result += value.type();
+            if (!value.isUndefined() && !value.isNull()) {
+              result += ', ';
+              if (value.isString()) {
+                result += '"';
+              }
+              result += value.value();
+              if (value.isString()) {
+                result += '"';
+              }
+            }
+            result += '\n';
+          }
+        }
+        details.text = result;
+        break;
+
+      case 'references':
+        var count = body.length;
+        result += 'found ' + count + ' objects';
+        result += '\n';
+        for (var i = 0; i < count; i++) {
+          var value = response.bodyValue(i);
+          result += formatObject_(value, false);
+          result += '\n';
+        }
+        details.text = result;
+        break;
+        
+      case 'source':
+        // Get the source from the response.
+        var source = body.source;
+        var from_line = body.fromLine + 1;
+        var lines = source.split('\n');
+        var maxdigits = 1 + Math.floor(log10(from_line + lines.length));
+        if (maxdigits < 3) {
+          maxdigits = 3;
+        }
+        var result = '';
+        for (var num = 0; num < lines.length; num++) {
+          // Check if there's an extra newline at the end.
+          if (num == (lines.length - 1) && lines[num].length == 0) {
+            break;
+          }
+
+          var current_line = from_line + num;
+          spacer = maxdigits - (1 + Math.floor(log10(current_line)));
+          if (current_line == Debug.State.currentSourceLine + 1) {
+            for (var i = 0; i < maxdigits; i++) {
+              result += '>';
+            }
+            result += '  ';
+          } else {
+            for (var i = 0; i < spacer; i++) {
+              result += ' ';
+            }
+            result += current_line + ': ';
+          }
+          result += lines[num];
+          result += '\n';
+        }
+        details.text = result;
+        break;
+        
+      case 'scripts':
+        var result = '';
+        for (i = 0; i < body.length; i++) {
+          if (i != 0) result += '\n';
+          if (body[i].id) {
+            result += body[i].id;
+          } else {
+            result += '[no id]';
+          }
+          result += ', ';
+          if (body[i].name) {
+            result += body[i].name;
+          } else {
+            result += '[unnamed] ';
+          }
+          result += ' (lines: ';
+          result += body[i].lineCount;
+          result += ', length: ';
+          result += body[i].sourceLength;
+          if (body[i].type == Debug.ScriptType.Native) {
+            result += ', native';
+          } else if (body[i].type == Debug.ScriptType.Extension) {
+            result += ', extension';
+          }
+          result += '), [';
+          var sourceStart = body[i].sourceStart;
+          if (sourceStart.length > 40) {
+            sourceStart = sourceStart.substring(0, 37) + '...';
+          }
+          result += sourceStart;
+          result += ']';
+        }
+        details.text = result;
+        break;
+
+      case 'threads':
+        var result = 'Active V8 threads: ' + body.totalThreads + '\n';
+        body.threads.sort(function(a, b) { return a.id - b.id; });
+        for (i = 0; i < body.threads.length; i++) {
+          result += body.threads[i].current ? '*' : ' ';
+          result += ' ';
+          result += body.threads[i].id;
+          result += '\n';
+        }
+        details.text = result;
+        break;
+
+      case 'continue':
+        details.text = "(running)";
+        break;
+        
+      default:
+        details.text =
+            'Response for unknown command \'' + response.command + '\'' +
+            ' (' + json_response + ')';
+    }
+  } catch (e) {
+    details.text = 'Error: "' + e + '" formatting response';
+  }
+  
+  return details;
+};
+
+
+/**
+ * Protocol packages send from the debugger.
+ * @param {string} json - raw protocol packet as JSON string.
+ * @constructor
+ */
+function ProtocolPackage(json) {
+  this.packet_ = eval('(' + json + ')');
+  this.refs_ = [];
+  if (this.packet_.refs) {
+    for (var i = 0; i < this.packet_.refs.length; i++) {
+      this.refs_[this.packet_.refs[i].handle] = this.packet_.refs[i];
+    }
+  }
+}
+
+
+/**
+ * Get the packet type.
+ * @return {String} the packet type
+ */
+ProtocolPackage.prototype.type = function() {
+  return this.packet_.type;
+}
+
+
+/**
+ * Get the packet event.
+ * @return {Object} the packet event
+ */
+ProtocolPackage.prototype.event = function() {
+  return this.packet_.event;
+}
+
+
+/**
+ * Get the packet request sequence.
+ * @return {number} the packet request sequence
+ */
+ProtocolPackage.prototype.requestSeq = function() {
+  return this.packet_.request_seq;
+}
+
+
+/**
+ * Get the packet request sequence.
+ * @return {number} the packet request sequence
+ */
+ProtocolPackage.prototype.running = function() {
+  return this.packet_.running ? true : false;
+}
+
+
+ProtocolPackage.prototype.success = function() {
+  return this.packet_.success ? true : false;
+}
+
+
+ProtocolPackage.prototype.message = function() {
+  return this.packet_.message;
+}
+
+
+ProtocolPackage.prototype.command = function() {
+  return this.packet_.command;
+}
+
+
+ProtocolPackage.prototype.body = function() {
+  return this.packet_.body;
+}
+
+
+ProtocolPackage.prototype.bodyValue = function(index) {
+  if (index) {
+    return new ProtocolValue(this.packet_.body[index], this);
+  } else {
+    return new ProtocolValue(this.packet_.body, this);
+  }
+}
+
+
+ProtocolPackage.prototype.body = function() {
+  return this.packet_.body;
+}
+
+
+ProtocolPackage.prototype.lookup = function(handle) {
+  var value = this.refs_[handle];
+  if (value) {
+    return new ProtocolValue(value, this);
+  } else {
+    return new ProtocolReference(handle);
+  }
+}
+
+
+function ProtocolValue(value, packet) {
+  this.value_ = value;
+  this.packet_ = packet;
+}
+
+
+/**
+ * Get the value type.
+ * @return {String} the value type
+ */
+ProtocolValue.prototype.type = function() {
+  return this.value_.type;
+}
+
+
+/**
+ * Check is the value is a primitive value.
+ * @return {boolean} true if the value is primitive
+ */
+ProtocolValue.prototype.isPrimitive = function() {
+  return this.isUndefined() || this.isNull() || this.isBoolean() ||
+         this.isNumber() || this.isString();
+}
+
+
+/**
+ * Get the object handle.
+ * @return {number} the value handle
+ */
+ProtocolValue.prototype.handle = function() {
+  return this.value_.handle;
+}
+
+
+/**
+ * Check is the value is undefined.
+ * @return {boolean} true if the value is undefined
+ */
+ProtocolValue.prototype.isUndefined = function() {
+  return this.value_.type == 'undefined';
+}
+
+
+/**
+ * Check is the value is null.
+ * @return {boolean} true if the value is null
+ */
+ProtocolValue.prototype.isNull = function() {
+  return this.value_.type == 'null';
+}
+
+
+/**
+ * Check is the value is a boolean.
+ * @return {boolean} true if the value is a boolean
+ */
+ProtocolValue.prototype.isBoolean = function() {
+  return this.value_.type == 'boolean';
+}
+
+
+/**
+ * Check is the value is a number.
+ * @return {boolean} true if the value is a number
+ */
+ProtocolValue.prototype.isNumber = function() {
+  return this.value_.type == 'number';
+}
+
+
+/**
+ * Check is the value is a string.
+ * @return {boolean} true if the value is a string
+ */
+ProtocolValue.prototype.isString = function() {
+  return this.value_.type == 'string';
+}
+
+
+/**
+ * Check is the value is an object.
+ * @return {boolean} true if the value is an object
+ */
+ProtocolValue.prototype.isObject = function() {
+  return this.value_.type == 'object' || this.value_.type == 'function' ||
+         this.value_.type == 'error' || this.value_.type == 'regexp';
+}
+
+
+/**
+ * Get the constructor function
+ * @return {ProtocolValue} constructor function
+ */
+ProtocolValue.prototype.constructorFunctionValue = function() {
+  var ctor = this.value_.constructorFunction;
+  return this.packet_.lookup(ctor.ref);
+}
+
+
+/**
+ * Get the __proto__ value
+ * @return {ProtocolValue} __proto__ value
+ */
+ProtocolValue.prototype.protoObjectValue = function() {
+  var proto = this.value_.protoObject;
+  return this.packet_.lookup(proto.ref);
+}
+
+
+/**
+ * Get the number og properties.
+ * @return {number} the number of properties
+ */
+ProtocolValue.prototype.propertyCount = function() {
+  return this.value_.properties ? this.value_.properties.length : 0;
+}
+
+
+/**
+ * Get the specified property name.
+ * @return {string} property name
+ */
+ProtocolValue.prototype.propertyName = function(index) {
+  var property = this.value_.properties[index];
+  return property.name;
+}
+
+
+/**
+ * Return index for the property name.
+ * @param name The property name to look for
+ * @return {number} index for the property name
+ */
+ProtocolValue.prototype.propertyIndex = function(name) {
+  for (var i = 0; i < this.propertyCount(); i++) {
+    if (this.value_.properties[i].name == name) {
+      return i;
+    }
+  }
+  return null;
+}
+
+
+/**
+ * Get the specified property value.
+ * @return {ProtocolValue} property value
+ */
+ProtocolValue.prototype.propertyValue = function(index) {
+  var property = this.value_.properties[index];
+  return this.packet_.lookup(property.ref);
+}
+
+
+/**
+ * Check is the value is a string.
+ * @return {boolean} true if the value is a string
+ */
+ProtocolValue.prototype.value = function() {
+  return this.value_.value;
+}
+
+
+function ProtocolReference(handle) {
+  this.handle_ = handle;
+}
+
+
+ProtocolReference.prototype.handle = function() {
+  return this.handle_;
+}
+
+
+function MakeJSONPair_(name, value) {
+  return '"' + name + '":' + value;
+}
+
+
+function ArrayToJSONObject_(content) {
+  return '{' + content.join(',') + '}';
+}
+
+
+function ArrayToJSONArray_(content) {
+  return '[' + content.join(',') + ']';
+}
+
+
+function BooleanToJSON_(value) {
+  return String(value); 
+}
+
+
+function NumberToJSON_(value) {
+  return String(value); 
+}
+
+
+// Mapping of some control characters to avoid the \uXXXX syntax for most
+// commonly used control cahracters.
+const ctrlCharMap_ = {
+  '\b': '\\b',
+  '\t': '\\t',
+  '\n': '\\n',
+  '\f': '\\f',
+  '\r': '\\r',
+  '"' : '\\"',
+  '\\': '\\\\'
+};
+
+
+// Regular expression testing for ", \ and control characters (0x00 - 0x1F).
+const ctrlCharTest_ = new RegExp('["\\\\\x00-\x1F]');
+
+
+// Regular expression matching ", \ and control characters (0x00 - 0x1F)
+// globally.
+const ctrlCharMatch_ = new RegExp('["\\\\\x00-\x1F]', 'g');
+
+
+/**
+ * Convert a String to its JSON representation (see http://www.json.org/). To
+ * avoid depending on the String object this method calls the functions in
+ * string.js directly and not through the value.
+ * @param {String} value The String value to format as JSON
+ * @return {string} JSON formatted String value
+ */
+function StringToJSON_(value) {
+  // Check for" , \ and control characters (0x00 - 0x1F). No need to call
+  // RegExpTest as ctrlchar is constructed using RegExp.
+  if (ctrlCharTest_.test(value)) {
+    // Replace ", \ and control characters (0x00 - 0x1F).
+    return '"' +
+      value.replace(ctrlCharMatch_, function (char) {
+        // Use charmap if possible.
+        var mapped = ctrlCharMap_[char];
+        if (mapped) return mapped;
+        mapped = char.charCodeAt();
+        // Convert control character to unicode escape sequence.
+        return '\\u00' +
+          '0' + // TODO %NumberToRadixString(Math.floor(mapped / 16), 16) +
+          '0' // TODO %NumberToRadixString(mapped % 16, 16);
+      })
+    + '"';
+  }
+
+  // Simple string with no special characters.
+  return '"' + value + '"';
+}
+
+
+/**
+ * Convert a Date to ISO 8601 format. To avoid depending on the Date object
+ * this method calls the functions in date.js directly and not through the
+ * value.
+ * @param {Date} value The Date value to format as JSON
+ * @return {string} JSON formatted Date value
+ */
+function DateToISO8601_(value) {
+  function f(n) {
+    return n < 10 ? '0' + n : n;
+  }
+  function g(n) {
+    return n < 10 ? '00' + n : n < 100 ? '0' + n : n;
+  }
+  return builtins.GetUTCFullYearFrom(value)         + '-' +
+          f(builtins.GetUTCMonthFrom(value) + 1)    + '-' +
+          f(builtins.GetUTCDateFrom(value))         + 'T' +
+          f(builtins.GetUTCHoursFrom(value))        + ':' +
+          f(builtins.GetUTCMinutesFrom(value))      + ':' +
+          f(builtins.GetUTCSecondsFrom(value))      + '.' +
+          g(builtins.GetUTCMillisecondsFrom(value)) + 'Z';
+}
+
+
+/**
+ * Convert a Date to ISO 8601 format. To avoid depending on the Date object
+ * this method calls the functions in date.js directly and not through the
+ * value.
+ * @param {Date} value The Date value to format as JSON
+ * @return {string} JSON formatted Date value
+ */
+function DateToJSON_(value) {
+  return '"' + DateToISO8601_(value) + '"';
+}
+
+
+/**
+ * Convert an Object to its JSON representation (see http://www.json.org/).
+ * This implementation simply runs through all string property names and adds
+ * each property to the JSON representation for some predefined types. For type
+ * "object" the function calls itself recursively unless the object has the
+ * function property "toJSONProtocol" in which case that is used. This is not
+ * a general implementation but sufficient for the debugger. Note that circular
+ * structures will cause infinite recursion.
+ * @param {Object} object The object to format as JSON
+ * @return {string} JSON formatted object value
+ */
+function SimpleObjectToJSON_(object) {
+  var content = [];
+  for (var key in object) {
+    // Only consider string keys.
+    if (typeof key == 'string') {
+      var property_value = object[key];
+
+      // Format the value based on its type.
+      var property_value_json;
+      switch (typeof property_value) {
+        case 'object':
+          if (typeof property_value.toJSONProtocol == 'function') {
+            property_value_json = property_value.toJSONProtocol(true)
+          } else if (property_value.constructor.name == 'Array'){
+            property_value_json = SimpleArrayToJSON_(property_value);
+          } else {
+            property_value_json = SimpleObjectToJSON_(property_value);
+          }
+          break;
+
+        case 'boolean':
+          property_value_json = BooleanToJSON_(property_value);
+          break;
+
+        case 'number':
+          property_value_json = NumberToJSON_(property_value);
+          break;
+
+        case 'string':
+          property_value_json = StringToJSON_(property_value);
+          break;
+
+        default:
+          property_value_json = null;
+      }
+
+      // Add the property if relevant.
+      if (property_value_json) {
+        content.push(StringToJSON_(key) + ':' + property_value_json);
+      }
+    }
+  }
+
+  // Make JSON object representation.
+  return '{' + content.join(',') + '}';
+}
+
+
+/**
+ * Convert an array to its JSON representation. This is a VERY simple
+ * implementation just to support what is needed for the debugger.
+ * @param {Array} arrya The array to format as JSON
+ * @return {string} JSON formatted array value
+ */
+function SimpleArrayToJSON_(array) {
+  // Make JSON array representation.
+  var json = '[';
+  for (var i = 0; i < array.length; i++) {
+    if (i != 0) {
+      json += ',';
+    }
+    var elem = array[i];
+    if (elem.toJSONProtocol) {
+      json += elem.toJSONProtocol(true)
+    } else if (typeof(elem) === 'object')  {
+      json += SimpleObjectToJSON_(elem);
+    } else if (typeof(elem) === 'boolean')  {
+      json += BooleanToJSON_(elem);
+    } else if (typeof(elem) === 'number')  {
+      json += NumberToJSON_(elem);
+    } else if (typeof(elem) === 'string')  {
+      json += StringToJSON_(elem);
+    } else {
+      json += elem;
+    }
+  }
+  json += ']';
+  return json;
+}
diff --git a/deps/v8/src/date-delay.js b/deps/v8/src/date-delay.js
new file mode 100644
index 0000000..2421e5b
--- /dev/null
+++ b/deps/v8/src/date-delay.js
@@ -0,0 +1,1051 @@
+// 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.
+
+
+// This file relies on the fact that the following declarations have been made
+// in v8natives.js:
+// const $isNaN = GlobalIsNaN;
+// const $isFinite = GlobalIsFinite;
+
+// -------------------------------------------------------------------
+
+// This file contains date support implemented in JavaScript.
+
+
+// Keep reference to original values of some global properties.  This
+// has the added benefit that the code in this file is isolated from
+// changes to these properties.
+const $Date = global.Date;
+
+// ECMA 262 - 15.9.1.2
+function Day(time) {
+  return FLOOR(time/msPerDay);
+}
+
+
+// ECMA 262 - 5.2
+function Modulo(value, remainder) {
+  var mod = value % remainder;
+  // Guard against returning -0.
+  if (mod == 0) return 0;
+  return mod >= 0 ? mod : mod + remainder;
+}
+
+
+function TimeWithinDay(time) {
+  return Modulo(time, msPerDay);
+}
+
+
+// ECMA 262 - 15.9.1.3
+function DaysInYear(year) {
+  if (year % 4 != 0) return 365;
+  if ((year % 100 == 0) && (year % 400 != 0)) return 365;
+  return 366;
+}
+
+
+function DayFromYear(year) {
+  return 365 * (year-1970)
+      + FLOOR((year-1969)/4)
+      - FLOOR((year-1901)/100)
+      + FLOOR((year-1601)/400);
+}
+
+
+function TimeFromYear(year) {
+  return msPerDay * DayFromYear(year);
+}
+
+
+function YearFromTime(time) {
+  return FromJulianDay(Day(time) + kDayZeroInJulianDay).year;
+}
+
+
+function InLeapYear(time) {
+  return DaysInYear(YearFromTime(time)) == 366 ? 1 : 0;
+}
+
+
+// ECMA 262 - 15.9.1.4
+function MonthFromTime(time) {
+  return FromJulianDay(Day(time) + kDayZeroInJulianDay).month;
+}
+
+
+function DayWithinYear(time) {
+  return Day(time) - DayFromYear(YearFromTime(time));
+}
+
+
+// ECMA 262 - 15.9.1.5
+function DateFromTime(time) {
+  return FromJulianDay(Day(time) + kDayZeroInJulianDay).date;
+}
+
+
+// ECMA 262 - 15.9.1.9
+function EquivalentYear(year) {
+  // Returns an equivalent year in the range [2008-2035] matching
+  // - leap year.
+  // - week day of first day.
+  var time = TimeFromYear(year);
+  var recent_year = (InLeapYear(time) == 0 ? 1967 : 1956) + 
+      (WeekDay(time) * 12) % 28;
+  // Find the year in the range 2008..2037 that is equivalent mod 28.
+  // Add 3*28 to give a positive argument to the modulus operator.
+  return 2008 + (recent_year + 3*28 - 2008) % 28;
+}
+
+
+function EquivalentTime(t) {
+  // The issue here is that some library calls don't work right for dates
+  // that cannot be represented using a non-negative signed 32 bit integer
+  // (measured in whole seconds based on the 1970 epoch).
+  // We solve this by mapping the time to a year with same leap-year-ness
+  // and same starting day for the year.  The ECMAscript specification says
+  // we must do this, but for compatability with other browsers, we use
+  // the actual year if it is in the range 1970..2037
+  if (t >= 0 && t <= 2.1e12) return t;
+  var day = MakeDay(EquivalentYear(YearFromTime(t)), MonthFromTime(t), DateFromTime(t));
+  return TimeClip(MakeDate(day, TimeWithinDay(t)));
+}
+
+var daylight_cache_time = $NaN;
+var daylight_cache_offset;
+
+function DaylightSavingsOffset(t) {
+  if (t == daylight_cache_time) {
+    return daylight_cache_offset;
+  }
+  var offset = %DateDaylightSavingsOffset(EquivalentTime(t));
+  daylight_cache_time = t;
+  daylight_cache_offset = offset;
+  return offset;
+}
+
+
+var timezone_cache_time = $NaN;
+var timezone_cache_timezone;
+
+function LocalTimezone(t) {
+  if(t == timezone_cache_time) {
+    return timezone_cache_timezone;
+  }
+  var timezone = %DateLocalTimezone(EquivalentTime(t));
+  timezone_cache_time = t;
+  timezone_cache_timezone = timezone;
+  return timezone;
+}
+
+
+function WeekDay(time) {
+  return Modulo(Day(time) + 4, 7);
+}
+
+var local_time_offset = %DateLocalTimeOffset();
+
+function LocalTime(time) {
+  if ($isNaN(time)) return time;
+  return time + local_time_offset + DaylightSavingsOffset(time);
+}
+
+function LocalTimeNoCheck(time) {
+  return time + local_time_offset + DaylightSavingsOffset(time);
+}
+
+
+function UTC(time) {
+  if ($isNaN(time)) return time;
+  var tmp = time - local_time_offset;
+  return tmp - DaylightSavingsOffset(tmp);
+}
+
+
+// ECMA 262 - 15.9.1.10
+function HourFromTime(time) {
+  return Modulo(FLOOR(time / msPerHour), HoursPerDay);
+}
+
+
+function MinFromTime(time) {
+  return Modulo(FLOOR(time / msPerMinute), MinutesPerHour);
+}
+
+
+function SecFromTime(time) {
+  return Modulo(FLOOR(time / msPerSecond), SecondsPerMinute);
+}
+
+
+function msFromTime(time) {
+  return Modulo(time, msPerSecond);
+}
+
+
+// ECMA 262 - 15.9.1.11
+function MakeTime(hour, min, sec, ms) {
+  if (!$isFinite(hour)) return $NaN;
+  if (!$isFinite(min)) return $NaN;
+  if (!$isFinite(sec)) return $NaN;
+  if (!$isFinite(ms)) return $NaN;
+  return TO_INTEGER(hour) * msPerHour
+      + TO_INTEGER(min) * msPerMinute
+      + TO_INTEGER(sec) * msPerSecond
+      + TO_INTEGER(ms);
+}
+
+
+// ECMA 262 - 15.9.1.12
+function TimeInYear(year) {
+  return DaysInYear(year) * msPerDay;
+}
+
+
+// Compute modified Julian day from year, month, date.
+function ToJulianDay(year, month, date) {
+  var jy = (month > 1) ? year : year - 1;
+  var jm = (month > 1) ? month + 2 : month + 14;
+  var ja = FLOOR(jy / 100);
+  return FLOOR(FLOOR(365.25*jy) + FLOOR(30.6001*jm) + date + 1720995) + 2 - ja + FLOOR(0.25*ja);
+}
+
+var four_year_cycle_table = CalculateDateTable();
+
+
+function CalculateDateTable() {
+  var month_lengths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
+  var four_year_cycle_table = new $Array(1461);
+
+  var cumulative = 0;
+  var position = 0;
+  var leap_position = 0;
+  for (var month = 0; month < 12; month++) {
+    var month_bits = month << kMonthShift;
+    var length = month_lengths[month];
+    for (var day = 1; day <= length; day++) {
+      four_year_cycle_table[leap_position] =
+        month_bits + day;
+      four_year_cycle_table[366 + position] =
+        (1 << kYearShift) + month_bits + day;
+      four_year_cycle_table[731 + position] =
+        (2 << kYearShift) + month_bits + day;
+      four_year_cycle_table[1096 + position] =
+        (3 << kYearShift) + month_bits + day;
+      leap_position++;
+      position++;
+    }
+    if (month == 1) {
+      four_year_cycle_table[leap_position++] = month_bits + 29;
+    }
+  }
+  return four_year_cycle_table;
+}
+
+
+// Constructor for creating objects holding year, month, and date.
+// Introduced to ensure the two return points in FromJulianDay match same map.
+function DayTriplet(year, month, date) {
+  this.year = year;
+  this.month = month;
+  this.date = date;
+}
+
+var julian_day_cache_triplet;
+var julian_day_cache_day = $NaN;
+
+// Compute year, month, and day from modified Julian day.
+// The missing days in 1582 are ignored for JavaScript compatibility.
+function FromJulianDay(julian) {
+  if (julian_day_cache_day == julian) {
+    return julian_day_cache_triplet;
+  }
+  var result;
+  // Avoid floating point and non-Smi maths in common case.  This is also a period of
+  // time where leap years are very regular.  The range is not too large to avoid overflow
+  // when doing the multiply-to-divide trick.
+  if (julian > kDayZeroInJulianDay &&
+      (julian - kDayZeroInJulianDay) < 40177) { // 1970 - 2080
+    var jsimple = (julian - kDayZeroInJulianDay) + 731; // Day 0 is 1st January 1968
+    var y = 1968;
+    // Divide by 1461 by multiplying with 22967 and shifting down by 25!
+    var after_1968 = (jsimple * 22967) >> 25;
+    y += after_1968 << 2;
+    jsimple -= 1461 * after_1968;
+    var four_year_cycle = four_year_cycle_table[jsimple];
+    result = new DayTriplet(y + (four_year_cycle >> kYearShift),
+                            (four_year_cycle & kMonthMask) >> kMonthShift,
+                            four_year_cycle & kDayMask);
+  } else {
+    var jalpha = FLOOR((julian - 1867216.25) / 36524.25);
+    var jb = julian + 1 + jalpha - FLOOR(0.25 * jalpha) + 1524;
+    var jc = FLOOR(6680.0 + ((jb-2439870) - 122.1)/365.25);
+    var jd = FLOOR(365 * jc + (0.25 * jc));
+    var je = FLOOR((jb - jd)/30.6001);
+    var m = je - 1;
+    if (m > 12) m -= 13;
+    var y = jc - 4715;
+    if (m > 2) { --y; --m; }
+    var d = jb - jd - FLOOR(30.6001 * je);
+    result = new DayTriplet(y, m, d);
+  }
+  julian_day_cache_day = julian;
+  julian_day_cache_triplet = result;
+  return result;
+}
+
+
+// Compute number of days given a year, month, date.
+// Note that month and date can lie outside the normal range.
+//   For example:
+//     MakeDay(2007, -4, 20) --> MakeDay(2006, 8, 20)
+//     MakeDay(2007, -33, 1) --> MakeDay(2004, 3, 1)
+//     MakeDay(2007, 14, -50) --> MakeDay(2007, 8, 11)
+function MakeDay(year, month, date) {
+  if (!$isFinite(year) || !$isFinite(month) || !$isFinite(date)) return $NaN;
+
+  // Conversion to integers.
+  year = TO_INTEGER(year);
+  month = TO_INTEGER(month);
+  date = TO_INTEGER(date);
+
+  // Overflow months into year.
+  year = year + FLOOR(month/12);
+  month = month % 12;
+  if (month < 0) {
+    month += 12;
+  }
+
+  // Return days relative to Jan 1 1970.
+  return ToJulianDay(year, month, date) - kDayZeroInJulianDay;
+}
+
+
+// ECMA 262 - 15.9.1.13
+function MakeDate(day, time) {
+  if (!$isFinite(day)) return $NaN;
+  if (!$isFinite(time)) return $NaN;
+  return day * msPerDay + time;
+}
+
+
+// ECMA 262 - 15.9.1.14
+function TimeClip(time) {
+  if (!$isFinite(time)) return $NaN;
+  if ($abs(time) > 8.64E15) return $NaN;
+  return TO_INTEGER(time);
+}
+
+
+%SetCode($Date, function(year, month, date, hours, minutes, seconds, ms) {
+  if (%IsConstructCall()) {
+    // ECMA 262 - 15.9.3
+    var argc = %_ArgumentsLength();
+    if (argc == 0) {
+      %_SetValueOf(this, %DateCurrentTime());
+      return;
+    }
+    if (argc == 1) {
+      // According to ECMA 262, no hint should be given for this
+      // conversion.  However, ToPrimitive defaults to String Hint
+      // for Date objects which will lose precision when the Date
+      // constructor is called with another Date object as its
+      // argument.  We therefore use Number Hint for the conversion
+      // (which is the default for everything else than Date
+      // objects).  This makes us behave like KJS and SpiderMonkey.
+      var time = ToPrimitive(year, NUMBER_HINT);
+      if (IS_STRING(time)) {
+        %_SetValueOf(this, DateParse(time));
+      } else {
+        %_SetValueOf(this, TimeClip(ToNumber(time)));
+      }
+      return;
+    }
+    year = ToNumber(year);
+    month = ToNumber(month);
+    date = argc > 2 ? ToNumber(date) : 1;
+    hours = argc > 3 ? ToNumber(hours) : 0;
+    minutes = argc > 4 ? ToNumber(minutes) : 0;
+    seconds = argc > 5 ? ToNumber(seconds) : 0;
+    ms = argc > 6 ? ToNumber(ms) : 0;
+    year = (!$isNaN(year) && 0 <= TO_INTEGER(year) && TO_INTEGER(year) <= 99)
+        ? 1900 + TO_INTEGER(year) : year;
+    var day = MakeDay(year, month, date);
+    var time = MakeTime(hours, minutes, seconds, ms);
+    %_SetValueOf(this, TimeClip(UTC(MakeDate(day, time))));
+  } else {
+    // ECMA 262 - 15.9.2
+    return (new $Date()).toString();
+  }
+});
+
+
+// Helper functions.
+function GetTimeFrom(aDate) {
+  if (IS_DATE(aDate)) return %_ValueOf(aDate);
+  throw new $TypeError('this is not a Date object.');
+}
+
+
+function GetMillisecondsFrom(aDate) {
+  var t = GetTimeFrom(aDate);
+  if ($isNaN(t)) return t;
+  return msFromTime(LocalTimeNoCheck(t));
+}
+
+
+function GetUTCMillisecondsFrom(aDate) {
+  var t = GetTimeFrom(aDate);
+  if ($isNaN(t)) return t;
+  return msFromTime(t);
+}
+
+
+function GetSecondsFrom(aDate) {
+  var t = GetTimeFrom(aDate);
+  if ($isNaN(t)) return t;
+  return SecFromTime(LocalTimeNoCheck(t));
+}
+
+
+function GetUTCSecondsFrom(aDate) {
+  var t = GetTimeFrom(aDate);
+  if ($isNaN(t)) return t;
+  return SecFromTime(t);
+}
+
+
+function GetMinutesFrom(aDate) {
+  var t = GetTimeFrom(aDate);
+  if ($isNaN(t)) return t;
+  return MinFromTime(LocalTimeNoCheck(t));
+}
+
+
+function GetUTCMinutesFrom(aDate) {
+  var t = GetTimeFrom(aDate);
+  if ($isNaN(t)) return t;
+  return MinFromTime(t);
+}
+
+
+function GetHoursFrom(aDate) {
+  var t = GetTimeFrom(aDate);
+  if ($isNaN(t)) return t;
+  return HourFromTime(LocalTimeNoCheck(t));
+}
+
+
+function GetUTCHoursFrom(aDate) {
+  var t = GetTimeFrom(aDate);
+  if ($isNaN(t)) return t;
+  return HourFromTime(t);
+}
+
+
+function GetFullYearFrom(aDate) {
+  var t = GetTimeFrom(aDate);
+  if ($isNaN(t)) return t;
+  return YearFromTime(LocalTimeNoCheck(t));
+}
+
+
+function GetUTCFullYearFrom(aDate) {
+  var t = GetTimeFrom(aDate);
+  if ($isNaN(t)) return t;
+  return YearFromTime(t);
+}
+
+
+function GetMonthFrom(aDate) {
+  var t = GetTimeFrom(aDate);
+  if ($isNaN(t)) return t;
+  return MonthFromTime(LocalTimeNoCheck(t));
+}
+
+
+function GetUTCMonthFrom(aDate) {
+  var t = GetTimeFrom(aDate);
+  if ($isNaN(t)) return t;
+  return MonthFromTime(t);
+}
+
+
+function GetDateFrom(aDate) {
+  var t = GetTimeFrom(aDate);
+  if ($isNaN(t)) return t;
+  return DateFromTime(LocalTimeNoCheck(t));
+}
+
+
+function GetUTCDateFrom(aDate) {
+  var t = GetTimeFrom(aDate);
+  if ($isNaN(t)) return t;
+  return DateFromTime(t);
+}
+
+
+%FunctionSetPrototype($Date, new $Date($NaN));
+
+
+var WeekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
+var Months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+
+
+function TwoDigitString(value) {
+  return value < 10 ? "0" + value : "" + value;
+}
+
+
+function DateString(time) {
+  var YMD = FromJulianDay(Day(time) + kDayZeroInJulianDay);
+  return WeekDays[WeekDay(time)] + ' '
+      + Months[YMD.month] + ' '
+      + TwoDigitString(YMD.date) + ' '
+      + YMD.year;
+}
+
+
+var LongWeekDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
+var LongMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
+
+
+function LongDateString(time) {
+  var YMD = FromJulianDay(Day(time) + kDayZeroInJulianDay);
+  return LongWeekDays[WeekDay(time)] + ', '
+      + LongMonths[YMD.month] + ' '
+      + TwoDigitString(YMD.date) + ', '
+      + YMD.year;
+}
+
+
+function TimeString(time) {
+  return TwoDigitString(HourFromTime(time)) + ':'
+      + TwoDigitString(MinFromTime(time)) + ':'
+      + TwoDigitString(SecFromTime(time));
+}
+
+
+function LocalTimezoneString(time) {
+  var timezoneOffset = (local_time_offset + DaylightSavingsOffset(time)) / msPerMinute;
+  var sign = (timezoneOffset >= 0) ? 1 : -1;
+  var hours = FLOOR((sign * timezoneOffset)/60);
+  var min   = FLOOR((sign * timezoneOffset)%60);
+  var gmt = ' GMT' + ((sign == 1) ? '+' : '-') + TwoDigitString(hours) + TwoDigitString(min);
+  return gmt + ' (' +  LocalTimezone(time) + ')';
+}
+
+
+function DatePrintString(time) {
+  return DateString(time) + ' ' + TimeString(time);
+}
+
+// -------------------------------------------------------------------
+
+// Reused output buffer.
+var parse_buffer = $Array(7);
+
+// ECMA 262 - 15.9.4.2
+function DateParse(string) {
+  var arr = %DateParseString(ToString(string), parse_buffer);
+  if (IS_NULL(arr)) return $NaN;
+
+  var day = MakeDay(arr[0], arr[1], arr[2]);
+  var time = MakeTime(arr[3], arr[4], arr[5], 0);
+  var date = MakeDate(day, time);
+
+  if (IS_NULL(arr[6])) {
+    return TimeClip(UTC(date));
+  } else {
+    return TimeClip(date - arr[6] * 1000);
+  }
+}
+
+
+// ECMA 262 - 15.9.4.3
+function DateUTC(year, month, date, hours, minutes, seconds, ms) {
+  year = ToNumber(year);
+  month = ToNumber(month);
+  var argc = %_ArgumentsLength();
+  date = argc > 2 ? ToNumber(date) : 1;
+  hours = argc > 3 ? ToNumber(hours) : 0;
+  minutes = argc > 4 ? ToNumber(minutes) : 0;
+  seconds = argc > 5 ? ToNumber(seconds) : 0;
+  ms = argc > 6 ? ToNumber(ms) : 0;
+  year = (!$isNaN(year) && 0 <= TO_INTEGER(year) && TO_INTEGER(year) <= 99)
+      ? 1900 + TO_INTEGER(year) : year;
+  var day = MakeDay(year, month, date);
+  var time = MakeTime(hours, minutes, seconds, ms);
+  return %_SetValueOf(this, TimeClip(MakeDate(day, time)));
+}
+
+
+// Mozilla-specific extension. Returns the number of milliseconds
+// elapsed since 1 January 1970 00:00:00 UTC.
+function DateNow() {
+  return %DateCurrentTime();
+}
+
+
+// ECMA 262 - 15.9.5.2
+function DateToString() {
+  var t = GetTimeFrom(this);
+  if ($isNaN(t)) return kInvalidDate;
+  return DatePrintString(LocalTimeNoCheck(t)) + LocalTimezoneString(t);
+}
+
+
+// ECMA 262 - 15.9.5.3
+function DateToDateString() {
+  var t = GetTimeFrom(this);
+  if ($isNaN(t)) return kInvalidDate;
+  return DateString(LocalTimeNoCheck(t));
+}
+
+
+// ECMA 262 - 15.9.5.4
+function DateToTimeString() {
+  var t = GetTimeFrom(this);
+  if ($isNaN(t)) return kInvalidDate;
+  var lt = LocalTimeNoCheck(t);
+  return TimeString(lt) + LocalTimezoneString(lt);
+}
+
+
+// ECMA 262 - 15.9.5.5
+function DateToLocaleString() {
+  return DateToString.call(this);
+}
+
+
+// ECMA 262 - 15.9.5.6
+function DateToLocaleDateString() {
+  var t = GetTimeFrom(this);
+  if ($isNaN(t)) return kInvalidDate;
+  return LongDateString(LocalTimeNoCheck(t));
+}
+
+
+// ECMA 262 - 15.9.5.7
+function DateToLocaleTimeString() {
+  var t = GetTimeFrom(this);
+  if ($isNaN(t)) return kInvalidDate;
+  var lt = LocalTimeNoCheck(t);
+  return TimeString(lt);
+}
+
+
+// ECMA 262 - 15.9.5.8
+function DateValueOf() {
+  return GetTimeFrom(this);
+}
+
+
+// ECMA 262 - 15.9.5.9
+function DateGetTime() {
+  return GetTimeFrom(this);
+}
+
+
+// ECMA 262 - 15.9.5.10
+function DateGetFullYear() {
+  return GetFullYearFrom(this)
+}
+
+
+// ECMA 262 - 15.9.5.11
+function DateGetUTCFullYear() {
+  return GetUTCFullYearFrom(this)
+}
+
+
+// ECMA 262 - 15.9.5.12
+function DateGetMonth() {
+  return GetMonthFrom(this);
+}
+
+
+// ECMA 262 - 15.9.5.13
+function DateGetUTCMonth() {
+  return GetUTCMonthFrom(this);
+}
+
+
+// ECMA 262 - 15.9.5.14
+function DateGetDate() {
+  return GetDateFrom(this);
+}
+
+
+// ECMA 262 - 15.9.5.15
+function DateGetUTCDate() {
+  return GetUTCDateFrom(this);
+}
+
+
+// ECMA 262 - 15.9.5.16
+function DateGetDay() {
+  var t = GetTimeFrom(this);
+  if ($isNaN(t)) return t;
+  return WeekDay(LocalTimeNoCheck(t));
+}
+
+
+// ECMA 262 - 15.9.5.17
+function DateGetUTCDay() {
+  var t = GetTimeFrom(this);
+  if ($isNaN(t)) return t;
+  return WeekDay(t);
+}
+
+
+// ECMA 262 - 15.9.5.18
+function DateGetHours() {
+  return GetHoursFrom(this);
+}
+
+
+// ECMA 262 - 15.9.5.19
+function DateGetUTCHours() {
+  return GetUTCHoursFrom(this);
+}
+
+
+// ECMA 262 - 15.9.5.20
+function DateGetMinutes() {
+  return GetMinutesFrom(this);
+}
+
+
+// ECMA 262 - 15.9.5.21
+function DateGetUTCMinutes() {
+  return GetUTCMinutesFrom(this);
+}
+
+
+// ECMA 262 - 15.9.5.22
+function DateGetSeconds() {
+  return GetSecondsFrom(this);
+}
+
+
+// ECMA 262 - 15.9.5.23
+function DateGetUTCSeconds() {
+  return GetUTCSecondsFrom(this);
+}
+
+
+// ECMA 262 - 15.9.5.24
+function DateGetMilliseconds() {
+  return GetMillisecondsFrom(this);
+}
+
+
+// ECMA 262 - 15.9.5.25
+function DateGetUTCMilliseconds() {
+  return GetUTCMillisecondsFrom(this);
+}
+
+
+// ECMA 262 - 15.9.5.26
+function DateGetTimezoneOffset() {
+  var t = GetTimeFrom(this);
+  if ($isNaN(t)) return t;
+  return (t - LocalTimeNoCheck(t)) / msPerMinute;
+}
+
+
+// ECMA 262 - 15.9.5.27
+function DateSetTime(ms) {
+  if (!IS_DATE(this)) throw new $TypeError('this is not a Date object.');
+  return %_SetValueOf(this, TimeClip(ToNumber(ms)));
+}
+
+
+// ECMA 262 - 15.9.5.28
+function DateSetMilliseconds(ms) {
+  var t = LocalTime(GetTimeFrom(this));
+  ms = ToNumber(ms);
+  var time = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms);
+  return %_SetValueOf(this, TimeClip(UTC(MakeDate(Day(t), time))));
+}
+
+
+// ECMA 262 - 15.9.5.29
+function DateSetUTCMilliseconds(ms) {
+  var t = GetTimeFrom(this);
+  ms = ToNumber(ms);
+  var time = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms);
+  return %_SetValueOf(this, TimeClip(MakeDate(Day(t), time)));
+}
+
+
+// ECMA 262 - 15.9.5.30
+function DateSetSeconds(sec, ms) {
+  var t = LocalTime(GetTimeFrom(this));
+  sec = ToNumber(sec);
+  ms = %_ArgumentsLength() < 2 ? GetMillisecondsFrom(this) : ToNumber(ms);
+  var time = MakeTime(HourFromTime(t), MinFromTime(t), sec, ms);
+  return %_SetValueOf(this, TimeClip(UTC(MakeDate(Day(t), time))));
+}
+
+
+// ECMA 262 - 15.9.5.31
+function DateSetUTCSeconds(sec, ms) {
+  var t = GetTimeFrom(this);
+  sec = ToNumber(sec);
+  ms = %_ArgumentsLength() < 2 ? GetUTCMillisecondsFrom(this) : ToNumber(ms);
+  var time = MakeTime(HourFromTime(t), MinFromTime(t), sec, ms);
+  return %_SetValueOf(this, TimeClip(MakeDate(Day(t), time)));
+}
+
+
+// ECMA 262 - 15.9.5.33
+function DateSetMinutes(min, sec, ms) {
+  var t = LocalTime(GetTimeFrom(this));
+  min = ToNumber(min);
+  var argc = %_ArgumentsLength();
+  sec = argc < 2 ? GetSecondsFrom(this) : ToNumber(sec);
+  ms = argc < 3 ? GetMillisecondsFrom(this) : ToNumber(ms);
+  var time = MakeTime(HourFromTime(t), min, sec, ms);
+  return %_SetValueOf(this, TimeClip(UTC(MakeDate(Day(t), time))));
+}
+
+
+// ECMA 262 - 15.9.5.34
+function DateSetUTCMinutes(min, sec, ms) {
+  var t = GetTimeFrom(this);
+  min = ToNumber(min);
+  var argc = %_ArgumentsLength();
+  sec = argc < 2 ? GetUTCSecondsFrom(this) : ToNumber(sec);
+  ms = argc < 3 ? GetUTCMillisecondsFrom(this) : ToNumber(ms);
+  var time = MakeTime(HourFromTime(t), min, sec, ms);
+  return %_SetValueOf(this, TimeClip(MakeDate(Day(t), time)));
+}
+
+
+// ECMA 262 - 15.9.5.35
+function DateSetHours(hour, min, sec, ms) {
+  var t = LocalTime(GetTimeFrom(this));
+  hour = ToNumber(hour);
+  var argc = %_ArgumentsLength();
+  min = argc < 2 ? GetMinutesFrom(this) : ToNumber(min);
+  sec = argc < 3 ? GetSecondsFrom(this) : ToNumber(sec);
+  ms = argc < 4 ? GetMillisecondsFrom(this) : ToNumber(ms);
+  var time = MakeTime(hour, min, sec, ms);
+  return %_SetValueOf(this, TimeClip(UTC(MakeDate(Day(t), time))));
+}
+
+
+// ECMA 262 - 15.9.5.34
+function DateSetUTCHours(hour, min, sec, ms) {
+  var t = GetTimeFrom(this);
+  hour = ToNumber(hour);
+  var argc = %_ArgumentsLength();
+  min = argc < 2 ? GetUTCMinutesFrom(this) : ToNumber(min);
+  sec = argc < 3 ? GetUTCSecondsFrom(this) : ToNumber(sec);
+  ms = argc < 4 ? GetUTCMillisecondsFrom(this) : ToNumber(ms);
+  var time = MakeTime(hour, min, sec, ms);
+  return %_SetValueOf(this, TimeClip(MakeDate(Day(t), time)));
+}
+
+
+// ECMA 262 - 15.9.5.36
+function DateSetDate(date) {
+  var t = LocalTime(GetTimeFrom(this));
+  date = ToNumber(date);
+  var day = MakeDay(YearFromTime(t), MonthFromTime(t), date);
+  return %_SetValueOf(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t)))));
+}
+
+
+// ECMA 262 - 15.9.5.37
+function DateSetUTCDate(date) {
+  var t = GetTimeFrom(this);
+  date = ToNumber(date);
+  var day = MakeDay(YearFromTime(t), MonthFromTime(t), date);
+  return %_SetValueOf(this, TimeClip(MakeDate(day, TimeWithinDay(t))));
+}
+
+
+// ECMA 262 - 15.9.5.38
+function DateSetMonth(month, date) {
+  var t = LocalTime(GetTimeFrom(this));
+  month = ToNumber(month);
+  date = %_ArgumentsLength() < 2 ? GetDateFrom(this) : ToNumber(date);
+  var day = MakeDay(YearFromTime(t), month, date);
+  return %_SetValueOf(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t)))));
+}
+
+
+// ECMA 262 - 15.9.5.39
+function DateSetUTCMonth(month, date) {
+  var t = GetTimeFrom(this);
+  month = ToNumber(month);
+  date = %_ArgumentsLength() < 2 ? GetUTCDateFrom(this) : ToNumber(date);
+  var day = MakeDay(YearFromTime(t), month, date);
+  return %_SetValueOf(this, TimeClip(MakeDate(day, TimeWithinDay(t))));
+}
+
+
+// ECMA 262 - 15.9.5.40
+function DateSetFullYear(year, month, date) {
+  var t = GetTimeFrom(this);
+  t = $isNaN(t) ? 0 : LocalTimeNoCheck(t);
+  year = ToNumber(year);
+  var argc = %_ArgumentsLength();
+  month = argc < 2 ? MonthFromTime(t) : ToNumber(month);
+  date = argc < 3 ? DateFromTime(t) : ToNumber(date);
+  var day = MakeDay(year, month, date);
+  return %_SetValueOf(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t)))));
+}
+
+
+// ECMA 262 - 15.9.5.41
+function DateSetUTCFullYear(year, month, date) {
+  var t = GetTimeFrom(this);
+  if ($isNaN(t)) t = 0;
+  var argc = %_ArgumentsLength();
+  year = ToNumber(year);
+  month = argc < 2 ? MonthFromTime(t) : ToNumber(month);
+  date = argc < 3 ? DateFromTime(t) : ToNumber(date);
+  var day = MakeDay(year, month, date);
+  return %_SetValueOf(this, TimeClip(MakeDate(day, TimeWithinDay(t))));
+}
+
+
+// ECMA 262 - 15.9.5.42
+function DateToUTCString() {
+  var t = GetTimeFrom(this);
+  if ($isNaN(t)) return kInvalidDate;
+  // Return UTC string of the form: Sat, 31 Jan 1970 23:00:00 GMT
+  return WeekDays[WeekDay(t)] + ', '
+      + TwoDigitString(DateFromTime(t)) + ' '
+      + Months[MonthFromTime(t)] + ' '
+      + YearFromTime(t) + ' '
+      + TimeString(t) + ' GMT';
+}
+
+
+// ECMA 262 - B.2.4
+function DateGetYear() {
+  var t = GetTimeFrom(this);
+  if ($isNaN(t)) return $NaN;
+  return YearFromTime(LocalTimeNoCheck(t)) - 1900;
+}
+
+
+// ECMA 262 - B.2.5
+function DateSetYear(year) {
+  var t = LocalTime(GetTimeFrom(this));
+  if ($isNaN(t)) t = 0;
+  year = ToNumber(year);
+  if ($isNaN(year)) return %_SetValueOf(this, $NaN);
+  year = (0 <= TO_INTEGER(year) && TO_INTEGER(year) <= 99)
+      ? 1900 + TO_INTEGER(year) : year;
+  var day = MakeDay(year, MonthFromTime(t), DateFromTime(t));
+  return %_SetValueOf(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t)))));
+}
+
+
+// ECMA 262 - B.2.6
+//
+// Notice that this does not follow ECMA 262 completely.  ECMA 262
+// says that toGMTString should be the same Function object as
+// toUTCString.  JSC does not do this, so for compatibility we do not
+// do that either.  Instead, we create a new function whose name
+// property will return toGMTString.
+function DateToGMTString() {
+  return DateToUTCString.call(this);
+}
+
+
+// -------------------------------------------------------------------
+
+function SetupDate() {
+  // Setup non-enumerable properties of the Date object itself.
+  InstallFunctions($Date, DONT_ENUM, $Array(
+    "UTC", DateUTC,
+    "parse", DateParse,
+    "now", DateNow
+  ));
+
+  // Setup non-enumerable constructor property of the Date prototype object.
+  %SetProperty($Date.prototype, "constructor", $Date, DONT_ENUM);
+
+  // Setup non-enumerable functions of the Date prototype object and
+  // set their names.
+  InstallFunctions($Date.prototype, DONT_ENUM, $Array(
+    "toString", DateToString,
+    "toDateString", DateToDateString,
+    "toTimeString", DateToTimeString,
+    "toLocaleString", DateToLocaleString,
+    "toLocaleDateString", DateToLocaleDateString,
+    "toLocaleTimeString", DateToLocaleTimeString,
+    "valueOf", DateValueOf,
+    "getTime", DateGetTime,
+    "getFullYear", DateGetFullYear,
+    "getUTCFullYear", DateGetUTCFullYear,
+    "getMonth", DateGetMonth,
+    "getUTCMonth", DateGetUTCMonth,
+    "getDate", DateGetDate,
+    "getUTCDate", DateGetUTCDate,
+    "getDay", DateGetDay,
+    "getUTCDay", DateGetUTCDay,
+    "getHours", DateGetHours,
+    "getUTCHours", DateGetUTCHours,
+    "getMinutes", DateGetMinutes,
+    "getUTCMinutes", DateGetUTCMinutes,
+    "getSeconds", DateGetSeconds,
+    "getUTCSeconds", DateGetUTCSeconds,
+    "getMilliseconds", DateGetMilliseconds,
+    "getUTCMilliseconds", DateGetUTCMilliseconds,
+    "getTimezoneOffset", DateGetTimezoneOffset,
+    "setTime", DateSetTime,
+    "setMilliseconds", DateSetMilliseconds,
+    "setUTCMilliseconds", DateSetUTCMilliseconds,
+    "setSeconds", DateSetSeconds,
+    "setUTCSeconds", DateSetUTCSeconds,
+    "setMinutes", DateSetMinutes,
+    "setUTCMinutes", DateSetUTCMinutes,
+    "setHours", DateSetHours,
+    "setUTCHours", DateSetUTCHours,
+    "setDate", DateSetDate,
+    "setUTCDate", DateSetUTCDate,
+    "setMonth", DateSetMonth,
+    "setUTCMonth", DateSetUTCMonth,
+    "setFullYear", DateSetFullYear,
+    "setUTCFullYear", DateSetUTCFullYear,
+    "toGMTString", DateToGMTString,
+    "toUTCString", DateToUTCString,
+    "getYear", DateGetYear,
+    "setYear", DateSetYear
+  ));
+}
+
+SetupDate();
diff --git a/deps/v8/src/dateparser-inl.h b/deps/v8/src/dateparser-inl.h
new file mode 100644
index 0000000..734c151
--- /dev/null
+++ b/deps/v8/src/dateparser-inl.h
@@ -0,0 +1,106 @@
+// Copyright 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.
+
+namespace v8 { namespace internal {
+
+template <typename Char>
+bool DateParser::Parse(Vector<Char> str, FixedArray* out) {
+  ASSERT(out->length() >= OUTPUT_SIZE);
+  InputReader<Char> in(str);
+  TimeZoneComposer tz;
+  TimeComposer time;
+  DayComposer day;
+
+  while (!in.IsEnd()) {
+    if (in.IsAsciiDigit()) {
+      // Parse a number (possibly with 1 or 2 trailing colons).
+      int n = in.ReadUnsignedNumber();
+      if (in.Skip(':')) {
+        if (in.Skip(':')) {
+          // n + "::"
+          if (!time.IsEmpty()) return false;
+          time.Add(n);
+          time.Add(0);
+        } else {
+          // n + ":"
+          if (!time.Add(n)) return false;
+        }
+      } else if (tz.IsExpecting(n)) {
+        tz.SetAbsoluteMinute(n);
+      } else if (time.IsExpecting(n)) {
+        time.AddFinal(n);
+        // Require end or white space immediately after finalizing time.
+        if (!in.IsEnd() && !in.SkipWhiteSpace()) return false;
+      } else {
+        if (!day.Add(n)) return false;
+        in.Skip('-');  // Ignore suffix '-' for year, month, or day.
+      }
+    } else if (in.IsAsciiAlphaOrAbove()) {
+      // Parse a "word" (sequence of chars. >= 'A').
+      uint32_t pre[KeywordTable::kPrefixLength];
+      int len = in.ReadWord(pre, KeywordTable::kPrefixLength);
+      int index = KeywordTable::Lookup(pre, len);
+      KeywordType type = KeywordTable::GetType(index);
+
+      if (type == AM_PM && !time.IsEmpty()) {
+        time.SetHourOffset(KeywordTable::GetValue(index));
+      } else if (type == MONTH_NAME) {
+        day.SetNamedMonth(KeywordTable::GetValue(index));
+        in.Skip('-');  // Ignore suffix '-' for month names
+      } else if (type == TIME_ZONE_NAME && in.HasReadNumber()) {
+        tz.Set(KeywordTable::GetValue(index));
+      } else {
+        // Garbage words are illegal if a number has been read.
+        if (in.HasReadNumber()) return false;
+      }
+    } else if (in.IsAsciiSign() && (tz.IsUTC() || !time.IsEmpty())) {
+      // Parse UTC offset (only after UTC or time).
+      tz.SetSign(in.GetAsciiSignValue());
+      in.Next();
+      int n = in.ReadUnsignedNumber();
+      if (in.Skip(':')) {
+        tz.SetAbsoluteHour(n);
+        tz.SetAbsoluteMinute(kNone);
+      } else {
+        tz.SetAbsoluteHour(n / 100);
+        tz.SetAbsoluteMinute(n % 100);
+      }
+    } else if (in.Is('(')) {
+      // Ignore anything from '(' to a matching ')' or end of string.
+      in.SkipParentheses();
+    } else if ((in.IsAsciiSign() || in.Is(')')) && in.HasReadNumber()) {
+      // Extra sign or ')' is illegal if a number has been read.
+      return false;
+    } else {
+      // Ignore other characters.
+      in.Next();
+    }
+  }
+  return day.Write(out) && time.Write(out) && tz.Write(out);
+}
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/dateparser.cc b/deps/v8/src/dateparser.cc
new file mode 100644
index 0000000..a1ae55d
--- /dev/null
+++ b/deps/v8/src/dateparser.cc
@@ -0,0 +1,185 @@
+// Copyright 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.
+
+#include "v8.h"
+
+#include "dateparser.h"
+
+namespace v8 { namespace internal {
+
+bool DateParser::DayComposer::Write(FixedArray* output) {
+  int year = 0;  // Default year is 0 (=> 2000) for KJS compatibility.
+  int month = kNone;
+  int day = kNone;
+
+  if (named_month_ == kNone) {
+    if (index_ < 2) return false;
+    if (index_ == 3 && !IsDay(comp_[0])) {
+      // YMD
+      year = comp_[0];
+      month = comp_[1];
+      day = comp_[2];
+    } else {
+      // MD(Y)
+      month = comp_[0];
+      day = comp_[1];
+      if (index_ == 3) year = comp_[2];
+    }
+  } else {
+    month = named_month_;
+    if (index_ < 1) return false;
+    if (index_ == 1) {
+      // MD or DM
+      day = comp_[0];
+    } else if (!IsDay(comp_[0])) {
+      // YMD, MYD, or YDM
+      year = comp_[0];
+      day = comp_[1];
+    } else {
+      // DMY, MDY, or DYM
+      day = comp_[0];
+      year = comp_[1];
+    }
+  }
+
+  if (Between(year, 0, 49)) year += 2000;
+  else if (Between(year, 50, 99)) year += 1900;
+
+  if (!Smi::IsValid(year) || !IsMonth(month) || !IsDay(day)) return false;
+
+  output->set(YEAR,
+              Smi::FromInt(year),
+              SKIP_WRITE_BARRIER);
+  output->set(MONTH,
+              Smi::FromInt(month - 1),
+              SKIP_WRITE_BARRIER);  // 0-based
+  output->set(DAY,
+              Smi::FromInt(day),
+              SKIP_WRITE_BARRIER);
+  return true;
+}
+
+
+bool DateParser::TimeComposer::Write(FixedArray* output) {
+  // All time slots default to 0
+  while (index_ < kSize) {
+    comp_[index_++] = 0;
+  }
+
+  int& hour = comp_[0];
+  int& minute = comp_[1];
+  int& second = comp_[2];
+
+  if (hour_offset_ != kNone) {
+    if (!IsHour12(hour)) return false;
+    hour %= 12;
+    hour += hour_offset_;
+  }
+
+  if (!IsHour(hour) || !IsMinute(minute) || !IsSecond(second)) return false;
+
+  output->set(HOUR,
+              Smi::FromInt(hour),
+              SKIP_WRITE_BARRIER);
+  output->set(MINUTE,
+              Smi::FromInt(minute),
+              SKIP_WRITE_BARRIER);
+  output->set(SECOND,
+              Smi::FromInt(second),
+              SKIP_WRITE_BARRIER);
+  return true;
+}
+
+bool DateParser::TimeZoneComposer::Write(FixedArray* output) {
+  if (sign_ != kNone) {
+    if (hour_ == kNone) hour_ = 0;
+    if (minute_ == kNone) minute_ = 0;
+    int total_seconds = sign_ * (hour_ * 3600 + minute_ * 60);
+    if (!Smi::IsValid(total_seconds)) return false;
+    output->set(UTC_OFFSET,
+                Smi::FromInt(total_seconds),
+                SKIP_WRITE_BARRIER);
+  } else {
+    output->set(UTC_OFFSET,
+                Heap::null_value(),
+                SKIP_WRITE_BARRIER);
+  }
+  return true;
+}
+
+const int8_t DateParser::KeywordTable::
+    array[][DateParser::KeywordTable::kEntrySize] = {
+  {'j', 'a', 'n', DateParser::MONTH_NAME, 1},
+  {'f', 'e', 'b', DateParser::MONTH_NAME, 2},
+  {'m', 'a', 'r', DateParser::MONTH_NAME, 3},
+  {'a', 'p', 'r', DateParser::MONTH_NAME, 4},
+  {'m', 'a', 'y', DateParser::MONTH_NAME, 5},
+  {'j', 'u', 'n', DateParser::MONTH_NAME, 6},
+  {'j', 'u', 'l', DateParser::MONTH_NAME, 7},
+  {'a', 'u', 'g', DateParser::MONTH_NAME, 8},
+  {'s', 'e', 'p', DateParser::MONTH_NAME, 9},
+  {'o', 'c', 't', DateParser::MONTH_NAME, 10},
+  {'n', 'o', 'v', DateParser::MONTH_NAME, 11},
+  {'d', 'e', 'c', DateParser::MONTH_NAME, 12},
+  {'a', 'm', '\0', DateParser::AM_PM, 0},
+  {'p', 'm', '\0', DateParser::AM_PM, 12},
+  {'u', 't', '\0', DateParser::TIME_ZONE_NAME, 0},
+  {'u', 't', 'c', DateParser::TIME_ZONE_NAME, 0},
+  {'g', 'm', 't', DateParser::TIME_ZONE_NAME, 0},
+  {'c', 'd', 't', DateParser::TIME_ZONE_NAME, -5},
+  {'c', 's', 't', DateParser::TIME_ZONE_NAME, -6},
+  {'e', 'd', 't', DateParser::TIME_ZONE_NAME, -4},
+  {'e', 's', 't', DateParser::TIME_ZONE_NAME, -5},
+  {'m', 'd', 't', DateParser::TIME_ZONE_NAME, -6},
+  {'m', 's', 't', DateParser::TIME_ZONE_NAME, -7},
+  {'p', 'd', 't', DateParser::TIME_ZONE_NAME, -7},
+  {'p', 's', 't', DateParser::TIME_ZONE_NAME, -8},
+  {'\0', '\0', '\0', DateParser::INVALID, 0},
+};
+
+
+// We could use perfect hashing here, but this is not a bottleneck.
+int DateParser::KeywordTable::Lookup(const uint32_t* pre, int len) {
+  int i;
+  for (i = 0; array[i][kTypeOffset] != INVALID; i++) {
+    int j = 0;
+    while (j < kPrefixLength &&
+           pre[j] == static_cast<uint32_t>(array[i][j])) {
+      j++;
+    }
+    // Check if we have a match and the length is legal.
+    // Word longer than keyword is only allowed for month names.
+    if (j == kPrefixLength &&
+        (len <= kPrefixLength || array[i][kTypeOffset] == MONTH_NAME)) {
+      return i;
+    }
+  }
+  return i;
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/dateparser.h b/deps/v8/src/dateparser.h
new file mode 100644
index 0000000..04d7e8b
--- /dev/null
+++ b/deps/v8/src/dateparser.h
@@ -0,0 +1,239 @@
+// Copyright 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_DATEPARSER_H_
+#define V8_DATEPARSER_H_
+
+#include "scanner.h"
+
+namespace v8 { namespace internal {
+
+class DateParser : public AllStatic {
+ public:
+
+  // Parse the string as a date. If parsing succeeds, return true after
+  // filling out the output array as follows (all integers are Smis):
+  // [0]: year
+  // [1]: month (0 = Jan, 1 = Feb, ...)
+  // [2]: day
+  // [3]: hour
+  // [4]: minute
+  // [5]: second
+  // [6]: UTC offset in seconds, or null value if no timezone specified
+  // If parsing fails, return false (content of output array is not defined).
+  template <typename Char>
+  static bool Parse(Vector<Char> str, FixedArray* output);
+
+  enum {
+    YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, UTC_OFFSET, OUTPUT_SIZE
+  };
+
+ private:
+  // Range testing
+  static inline bool Between(int x, int lo, int hi) {
+    return static_cast<unsigned>(x - lo) <= static_cast<unsigned>(hi - lo);
+  }
+  // Indicates a missing value.
+  static const int kNone = kMaxInt;
+
+  // InputReader provides basic string parsing and character classification.
+  template <typename Char>
+  class InputReader BASE_EMBEDDED {
+   public:
+    explicit InputReader(Vector<Char> s)
+        : index_(0),
+          buffer_(s),
+          has_read_number_(false) {
+      Next();
+    }
+
+    // Advance to the next character of the string.
+    void Next() { ch_ = (index_ < buffer_.length()) ? buffer_[index_++] : 0; }
+
+    // Read a string of digits as an unsigned number (cap just below kMaxInt).
+    int ReadUnsignedNumber() {
+      has_read_number_ = true;
+      int n;
+      for (n = 0; IsAsciiDigit() && n < kMaxInt / 10 - 1; Next()) {
+        n = n * 10 + 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.
+    int ReadWord(uint32_t* prefix, int prefix_size) {
+      int len;
+      for (len = 0; IsAsciiAlphaOrAbove(); Next(), len++) {
+        if (len < prefix_size) prefix[len] = GetAsciiAlphaLower();
+      }
+      for (int i = len; i < prefix_size; i++) prefix[i] = 0;
+      return len;
+    }
+
+    // The skip methods return whether they actually skipped something.
+    bool Skip(uint32_t c) { return ch_ == c ?  (Next(), true) : false; }
+
+    bool SkipWhiteSpace() {
+      return Scanner::kIsWhiteSpace.get(ch_) ? (Next(), true) : false;
+    }
+
+    bool SkipParentheses() {
+      if (ch_ != '(') return false;
+      int balance = 0;
+      do {
+        if (ch_ == ')') --balance;
+        else if (ch_ == '(') ++balance;
+        Next();
+      } while (balance > 0 && ch_);
+      return true;
+    }
+
+    // Character testing/classification. Non-ASCII digits are not supported.
+    bool Is(uint32_t c) const { return ch_ == c; }
+    bool IsEnd() const { return ch_ == 0; }
+    bool IsAsciiDigit() const { return IsDecimalDigit(ch_); }
+    bool IsAsciiAlphaOrAbove() const { return ch_ >= 'A'; }
+    bool IsAsciiSign() const { return ch_ == '+' || ch_ == '-'; }
+
+    // Return 1 for '+' and -1 for '-'.
+    int GetAsciiSignValue() const { return 44 - static_cast<int>(ch_); }
+
+    // Indicates whether any (possibly empty!) numbers have been read.
+    bool HasReadNumber() const { return has_read_number_; }
+
+   private:
+    // If current character is in 'A'-'Z' or 'a'-'z', return its lower-case.
+    // Else, return something outside of 'A'-'Z' and 'a'-'z'.
+    uint32_t GetAsciiAlphaLower() const { return ch_ | 32; }
+
+    int index_;
+    Vector<Char> buffer_;
+    bool has_read_number_;
+    uint32_t ch_;
+  };
+
+  enum KeywordType { INVALID, MONTH_NAME, TIME_ZONE_NAME, AM_PM };
+
+  // KeywordTable maps names of months, time zones, am/pm to numbers.
+  class KeywordTable : public AllStatic {
+   public:
+    // Look up a word in the keyword table and return an index.
+    // 'pre' contains a prefix of the word, zero-padded to size kPrefixLength
+    // and 'len' is the word length.
+    static int Lookup(const uint32_t* pre, int len);
+    // Get the type of the keyword at index i.
+    static KeywordType GetType(int i) {
+      return static_cast<KeywordType>(array[i][kTypeOffset]);
+    }
+    // Get the value of the keyword at index i.
+    static int GetValue(int i) { return array[i][kValueOffset]; }
+
+    static const int kPrefixLength = 3;
+    static const int kTypeOffset = kPrefixLength;
+    static const int kValueOffset = kTypeOffset + 1;
+    static const int kEntrySize = kValueOffset + 1;
+    static const int8_t array[][kEntrySize];
+  };
+
+  class TimeZoneComposer BASE_EMBEDDED {
+   public:
+    TimeZoneComposer() : sign_(kNone), hour_(kNone), minute_(kNone) {}
+    void Set(int offset_in_hours) {
+      sign_ = offset_in_hours < 0 ? -1 : 1;
+      hour_ = offset_in_hours * sign_;
+      minute_ = 0;
+    }
+    void SetSign(int sign) { sign_ = sign < 0 ? -1 : 1; }
+    void SetAbsoluteHour(int hour) { hour_ = hour; }
+    void SetAbsoluteMinute(int minute) { minute_ = minute; }
+    bool IsExpecting(int n) const {
+      return hour_ != kNone && minute_ == kNone && TimeComposer::IsMinute(n);
+    }
+    bool IsUTC() const { return hour_ == 0 && minute_ == 0; }
+    bool Write(FixedArray* output);
+   private:
+    int sign_;
+    int hour_;
+    int minute_;
+  };
+
+  class TimeComposer BASE_EMBEDDED {
+   public:
+    TimeComposer() : index_(0), hour_offset_(kNone) {}
+    bool IsEmpty() const { return index_ == 0; }
+    bool IsExpecting(int n) const {
+      return (index_ == 1 && IsMinute(n)) || (index_ == 2 && IsSecond(n));
+    }
+    bool Add(int n) {
+      return index_ < kSize ? (comp_[index_++] = n, true) : false;
+    }
+    bool AddFinal(int n) {
+      if (!Add(n)) return false;
+      while (index_ < kSize) comp_[index_++] = 0;
+      return true;
+    }
+    void SetHourOffset(int n) { hour_offset_ = n; }
+    bool Write(FixedArray* output);
+
+    static bool IsMinute(int x) { return Between(x, 0, 59); }
+   private:
+    static bool IsHour(int x) { return Between(x, 0, 23); }
+    static bool IsHour12(int x) { return Between(x, 0, 12); }
+    static bool IsSecond(int x) { return Between(x, 0, 59); }
+
+    static const int kSize = 3;
+    int comp_[kSize];
+    int index_;
+    int hour_offset_;
+  };
+
+  class DayComposer BASE_EMBEDDED {
+   public:
+    DayComposer() : index_(0), named_month_(kNone) {}
+    bool IsEmpty() const { return index_ == 0; }
+    bool Add(int n) {
+      return index_ < kSize ? (comp_[index_++] = n, true) : false;
+    }
+    void SetNamedMonth(int n) { named_month_ = n; }
+    bool Write(FixedArray* output);
+   private:
+    static bool IsMonth(int x) { return Between(x, 1, 12); }
+    static bool IsDay(int x) { return Between(x, 1, 31); }
+
+    static const int kSize = 3;
+    int comp_[kSize];
+    int index_;
+    int named_month_;
+  };
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_DATEPARSER_H_
diff --git a/deps/v8/src/debug-agent.cc b/deps/v8/src/debug-agent.cc
new file mode 100644
index 0000000..e865e0e
--- /dev/null
+++ b/deps/v8/src/debug-agent.cc
@@ -0,0 +1,414 @@
+// 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.
+
+
+#include "v8.h"
+#include "debug-agent.h"
+
+namespace v8 { namespace internal {
+
+
+// Public V8 debugger API message handler function. This function just delegates
+// to the debugger agent through it's data parameter.
+void DebuggerAgentMessageHandler(const uint16_t* message, int length,
+                                 void *data) {
+  reinterpret_cast<DebuggerAgent*>(data)->DebuggerMessage(message, length);
+}
+
+
+// Debugger agent main thread.
+void DebuggerAgent::Run() {
+  const int kOneSecondInMicros = 1000000;
+
+  // Allow this socket to reuse port even if still in TIME_WAIT.
+  server_->SetReuseAddress(true);
+
+  // First bind the socket to the requested port.
+  bool bound = false;
+  while (!bound && !terminate_) {
+    bound = server_->Bind(port_);
+
+    // If an error occoured wait a bit before retrying. The most common error
+    // would be that the port is already in use so this avoids a busy loop and
+    // make the agent take over the port when it becomes free.
+    if (!bound) {
+      terminate_now_->Wait(kOneSecondInMicros);
+    }
+  }
+
+  // Accept connections on the bound port.
+  while (!terminate_) {
+    bool ok = server_->Listen(1);
+    if (ok) {
+      // Accept the new connection.
+      Socket* client = server_->Accept();
+      ok = client != NULL;
+      if (ok) {
+        // Create and start a new session.
+        CreateSession(client);
+      }
+    }
+  }
+}
+
+
+void DebuggerAgent::Shutdown() {
+  // Set the termination flag.
+  terminate_ = true;
+
+  // Signal termination and make the server exit either its listen call or its
+  // binding loop. This makes sure that no new sessions can be established.
+  terminate_now_->Signal();
+  server_->Shutdown();
+  Join();
+
+  // Close existing session if any.
+  CloseSession();
+}
+
+
+void DebuggerAgent::CreateSession(Socket* client) {
+  ScopedLock with(session_access_);
+
+  // If another session is already established terminate this one.
+  if (session_ != NULL) {
+    static const char* message = "Remote debugging session already active\r\n";
+
+    client->Send(message, strlen(message));
+    delete client;
+    return;
+  }
+
+  // Create a new session and hook up the debug message handler.
+  session_ = new DebuggerAgentSession(this, client);
+  v8::Debug::SetMessageHandler(DebuggerAgentMessageHandler, this);
+  session_->Start();
+}
+
+
+void DebuggerAgent::CloseSession() {
+  ScopedLock with(session_access_);
+
+  // Terminate the session.
+  if (session_ != NULL) {
+    session_->Shutdown();
+    session_->Join();
+    delete session_;
+    session_ = NULL;
+  }
+}
+
+
+void DebuggerAgent::DebuggerMessage(const uint16_t* message, int length) {
+  ScopedLock with(session_access_);
+
+  // Forward the message handling to the session.
+  if (session_ != NULL) {
+    session_->DebuggerMessage(Vector<uint16_t>(const_cast<uint16_t*>(message),
+                              length));
+  }
+}
+
+
+void DebuggerAgent::OnSessionClosed(DebuggerAgentSession* session) {
+  // Don't do anything during termination.
+  if (terminate_) {
+    return;
+  }
+
+  // Terminate the session.
+  ScopedLock with(session_access_);
+  ASSERT(session == session_);
+  if (session == session_) {
+    CloseSession();
+  }
+}
+
+
+void DebuggerAgentSession::Run() {
+  // Send the hello message.
+  bool ok = DebuggerAgentUtil::SendConnectMessage(client_, *agent_->name_);
+  if (!ok) return;
+
+  while (true) {
+    // Read data from the debugger front end.
+    SmartPointer<char> message = DebuggerAgentUtil::ReceiveMessage(client_);
+    if (*message == NULL) {
+      // Session is closed.
+      agent_->OnSessionClosed(this);
+      return;
+    }
+
+    // Convert UTF-8 to UTF-16.
+    unibrow::Utf8InputBuffer<> buf(*message, strlen(*message));
+    int len = 0;
+    while (buf.has_more()) {
+      buf.GetNext();
+      len++;
+    }
+    int16_t* temp = NewArray<int16_t>(len + 1);
+    buf.Reset(*message, strlen(*message));
+    for (int i = 0; i < len; i++) {
+      temp[i] = buf.GetNext();
+    }
+
+    // Send the request received to the debugger.
+    v8::Debug::SendCommand(reinterpret_cast<const uint16_t *>(temp), len);
+    DeleteArray(temp);
+  }
+}
+
+
+void DebuggerAgentSession::DebuggerMessage(Vector<uint16_t> message) {
+  DebuggerAgentUtil::SendMessage(client_, message);
+}
+
+
+void DebuggerAgentSession::Shutdown() {
+  // Shutdown the socket to end the blocking receive.
+  client_->Shutdown();
+}
+
+
+const char* DebuggerAgentUtil::kContentLength = "Content-Length";
+int DebuggerAgentUtil::kContentLengthSize = strlen(kContentLength);
+
+
+SmartPointer<char> DebuggerAgentUtil::ReceiveMessage(const Socket* conn) {
+  int received;
+
+  // Read header.
+  int content_length = 0;
+  while (true) {
+    const int kHeaderBufferSize = 80;
+    char header_buffer[kHeaderBufferSize];
+    int header_buffer_position = 0;
+    char c = '\0';  // One character receive buffer.
+    char prev_c = '\0';  // Previous character.
+
+    // Read until CRLF.
+    while (!(c == '\n' && prev_c == '\r')) {
+      prev_c = c;
+      received = conn->Receive(&c, 1);
+      if (received <= 0) {
+        PrintF("Error %d\n", Socket::LastError());
+        return SmartPointer<char>();
+      }
+
+      // Add character to header buffer.
+      if (header_buffer_position < kHeaderBufferSize) {
+        header_buffer[header_buffer_position++] = c;
+      }
+    }
+
+    // Check for end of header (empty header line).
+    if (header_buffer_position == 2) {  // Receive buffer contains CRLF.
+      break;
+    }
+
+    // Terminate header.
+    ASSERT(header_buffer_position > 1);  // At least CRLF is received.
+    ASSERT(header_buffer_position <= kHeaderBufferSize);
+    header_buffer[header_buffer_position - 2] = '\0';
+
+    // Split header.
+    char* key = header_buffer;
+    char* value = NULL;
+    for (int i = 0; header_buffer[i] != '\0'; i++) {
+      if (header_buffer[i] == ':') {
+        header_buffer[i] = '\0';
+        value = header_buffer + i + 1;
+        while (*value == ' ') {
+          value++;
+        }
+        break;
+      }
+    }
+
+    // Check that key is Content-Length.
+    if (strcmp(key, kContentLength) == 0) {
+      // Get the content length value if within a sensible range.
+      if (strlen(value) > 7) {
+        return SmartPointer<char>();
+      }
+      for (int i = 0; value[i] != '\0'; i++) {
+        // Bail out if illegal data.
+        if (value[i] < '0' || value[i] > '9') {
+          return SmartPointer<char>();
+        }
+        content_length = 10 * content_length + (value[i] - '0');
+      }
+    } else {
+      // For now just print all other headers than Content-Length.
+      PrintF("%s: %s\n", key, value != NULL ? value : "(no value)");
+    }
+  }
+
+  // Return now if no body.
+  if (content_length == 0) {
+    return SmartPointer<char>();
+  }
+
+  // Read body.
+  char* buffer = NewArray<char>(content_length + 1);
+  received = ReceiveAll(conn, buffer, content_length);
+  if (received < content_length) {
+    PrintF("Error %d\n", Socket::LastError());
+    return SmartPointer<char>();
+  }
+  buffer[content_length] = '\0';
+
+  return SmartPointer<char>(buffer);
+}
+
+
+bool DebuggerAgentUtil::SendConnectMessage(const Socket* conn,
+                                           const char* embedding_host) {
+  static const int kBufferSize = 80;
+  char buffer[kBufferSize];  // Sending buffer.
+  bool ok;
+  int len;
+
+  // Send the header.
+  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
+                     "Type: connect\r\n");
+  ok = conn->Send(buffer, len);
+  if (!ok) return false;
+
+  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
+                     "V8-Version: %s\r\n", v8::V8::GetVersion());
+  ok = conn->Send(buffer, len);
+  if (!ok) return false;
+
+  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
+                     "Protocol-Version: 1\r\n");
+  ok = conn->Send(buffer, len);
+  if (!ok) return false;
+
+  if (embedding_host != NULL) {
+    len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
+                       "Embedding-Host: %s\r\n", embedding_host);
+    ok = conn->Send(buffer, len);
+    if (!ok) return false;
+  }
+
+  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
+                     "%s: 0\r\n", kContentLength);
+  ok = conn->Send(buffer, len);
+  if (!ok) return false;
+
+  // Terminate header with empty line.
+  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
+  ok = conn->Send(buffer, len);
+  if (!ok) return false;
+
+  // No body for connect message.
+
+  return true;
+}
+
+
+bool DebuggerAgentUtil::SendMessage(const Socket* conn,
+                                    const Vector<uint16_t> message) {
+  static const int kBufferSize = 80;
+  char buffer[kBufferSize];  // Sending buffer both for header and body.
+
+  // Calculate the message size in UTF-8 encoding.
+  int utf8_len = 0;
+  for (int i = 0; i < message.length(); i++) {
+    utf8_len += unibrow::Utf8::Length(message[i]);
+  }
+
+  // Send the header.
+  int len;
+  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
+                     "%s: %d\r\n", kContentLength, utf8_len);
+  conn->Send(buffer, len);
+
+  // Terminate header with empty line.
+  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
+  conn->Send(buffer, len);
+
+  // Send message body as UTF-8.
+  int buffer_position = 0;  // Current buffer position.
+  for (int i = 0; i < message.length(); i++) {
+    // Write next UTF-8 encoded character to buffer.
+    buffer_position +=
+        unibrow::Utf8::Encode(buffer + buffer_position, message[i]);
+    ASSERT(buffer_position < kBufferSize);
+
+    // Send buffer if full or last character is encoded.
+    if (kBufferSize - buffer_position < 3 || i == message.length() - 1) {
+      conn->Send(buffer, buffer_position);
+      buffer_position = 0;
+    }
+  }
+
+  return true;
+}
+
+
+bool DebuggerAgentUtil::SendMessage(const Socket* conn,
+                                    const v8::Handle<v8::String> request) {
+  static const int kBufferSize = 80;
+  char buffer[kBufferSize];  // Sending buffer both for header and body.
+
+  // Convert the request to UTF-8 encoding.
+  v8::String::Utf8Value utf8_request(request);
+
+  // Send the header.
+  int len;
+  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
+                     "Content-Length: %d\r\n", utf8_request.length());
+  conn->Send(buffer, len);
+
+  // Terminate header with empty line.
+  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
+  conn->Send(buffer, len);
+
+  // Send message body as UTF-8.
+  conn->Send(*utf8_request, utf8_request.length());
+
+  return true;
+}
+
+
+// Receive the full buffer before returning unless an error occours.
+int DebuggerAgentUtil::ReceiveAll(const Socket* conn, char* data, int len) {
+  int total_received = 0;
+  while (total_received < len) {
+    int received = conn->Receive(data + total_received, len - total_received);
+    if (received <= 0) {
+      return total_received;
+    }
+    total_received += received;
+  }
+  return total_received;
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/debug-agent.h b/deps/v8/src/debug-agent.h
new file mode 100644
index 0000000..177af0c
--- /dev/null
+++ b/deps/v8/src/debug-agent.h
@@ -0,0 +1,117 @@
+// 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_V8_DEBUG_AGENT_H_
+#define V8_V8_DEBUG_AGENT_H_
+
+#include "../include/v8-debug.h"
+#include "platform.h"
+
+namespace v8 { namespace internal {
+
+
+// Forward decelrations.
+class DebuggerAgentSession;
+
+
+// Debugger agent which starts a socket listener on the debugger port and
+// handles connection from a remote debugger.
+class DebuggerAgent: public Thread {
+ public:
+  explicit DebuggerAgent(const char* name, int port)
+      : name_(StrDup(name)), port_(port),
+        server_(OS::CreateSocket()), terminate_(false),
+        session_access_(OS::CreateMutex()), session_(NULL),
+        terminate_now_(OS::CreateSemaphore(0)) {}
+  ~DebuggerAgent() { delete server_; }
+
+  void Shutdown();
+
+ private:
+  void Run();
+  void CreateSession(Socket* socket);
+  void DebuggerMessage(const uint16_t* message, int length);
+  void CloseSession();
+  void OnSessionClosed(DebuggerAgentSession* session);
+
+  SmartPointer<const char> name_;  // Name of the embedding application.
+  int port_;  // Port to use for the agent.
+  Socket* server_;  // Server socket for listen/accept.
+  bool terminate_;  // Termination flag.
+  Mutex* session_access_;  // Mutex guarging access to session_.
+  DebuggerAgentSession* session_;  // Current active session if any.
+  Semaphore* terminate_now_;  // Semaphore to signal termination.
+
+  friend class DebuggerAgentSession;
+  friend void DebuggerAgentMessageHandler(const uint16_t* message, int length,
+                                          void *data);
+
+  DISALLOW_COPY_AND_ASSIGN(DebuggerAgent);
+};
+
+
+// Debugger agent session. The session receives requests from the remote
+// debugger and sends debugger events/responses to the remote debugger.
+class DebuggerAgentSession: public Thread {
+ public:
+  DebuggerAgentSession(DebuggerAgent* agent, Socket* client)
+      : agent_(agent), client_(client) {}
+
+  void DebuggerMessage(Vector<uint16_t> message);
+  void Shutdown();
+
+ private:
+  void Run();
+
+  void DebuggerMessage(Vector<char> message);
+
+  DebuggerAgent* agent_;
+  Socket* client_;
+
+  DISALLOW_COPY_AND_ASSIGN(DebuggerAgentSession);
+};
+
+
+// Utility methods factored out to be used by the D8 shell as well.
+class DebuggerAgentUtil {
+ public:
+  static const char* kContentLength;
+  static int kContentLengthSize;
+
+  static SmartPointer<char> ReceiveMessage(const Socket* conn);
+  static bool SendConnectMessage(const Socket* conn,
+                                 const char* embedding_host);
+  static bool SendMessage(const Socket* conn, const Vector<uint16_t> message);
+  static bool SendMessage(const Socket* conn,
+                          const v8::Handle<v8::String> message);
+  static int ReceiveAll(const Socket* conn, char* data, int len);
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_V8_DEBUG_AGENT_H_
diff --git a/deps/v8/src/debug-arm.cc b/deps/v8/src/debug-arm.cc
new file mode 100644
index 0000000..9fb77b7
--- /dev/null
+++ b/deps/v8/src/debug-arm.cc
@@ -0,0 +1,195 @@
+// 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.
+
+#include "v8.h"
+
+#include "codegen-inl.h"
+#include "debug.h"
+
+namespace v8 { namespace internal {
+
+
+// Currently debug break is not supported in frame exit code on ARM.
+bool BreakLocationIterator::IsDebugBreakAtReturn() {
+  return false;
+}
+
+
+// Currently debug break is not supported in frame exit code on ARM.
+void BreakLocationIterator::SetDebugBreakAtReturn() {
+  UNIMPLEMENTED();
+}
+
+
+// Currently debug break is not supported in frame exit code on ARM.
+void BreakLocationIterator::ClearDebugBreakAtReturn() {
+  UNIMPLEMENTED();
+}
+
+
+bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) {
+  ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()));
+  // Currently debug break is not supported in frame exit code on ARM.
+  return false;
+}
+
+
+#define __ masm->
+
+
+static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
+                                          RegList pointer_regs) {
+  // Save the content of all general purpose registers in memory. This copy in
+  // memory is later pushed onto the JS expression stack for the fake JS frame
+  // generated and also to the C frame generated on top of that. In the JS
+  // frame ONLY the registers containing pointers will be pushed on the
+  // expression stack. This causes the GC to update these  pointers so that
+  // they will have the correct value when returning from the debugger.
+  __ SaveRegistersToMemory(kJSCallerSaved);
+
+  __ EnterInternalFrame();
+
+  // Store the registers containing object pointers on the expression stack to
+  // make sure that these are correctly updated during GC.
+  // Use sp as base to push.
+  __ CopyRegistersFromMemoryToStack(sp, pointer_regs);
+
+#ifdef DEBUG
+  __ RecordComment("// Calling from debug break to runtime - come in - over");
+#endif
+  __ mov(r0, Operand(0));  // no arguments
+  __ mov(r1, Operand(ExternalReference::debug_break()));
+
+  CEntryDebugBreakStub ceb;
+  __ CallStub(&ceb);
+
+  // Restore the register values containing object pointers from the expression
+  // stack in the reverse order as they where pushed.
+  // Use sp as base to pop.
+  __ CopyRegistersFromStackToMemory(sp, r3, pointer_regs);
+
+  __ LeaveInternalFrame();
+
+  // Inlined ExitJSFrame ends here.
+
+  // Finally restore all registers.
+  __ RestoreRegistersFromMemory(kJSCallerSaved);
+
+  // Now that the break point has been handled, resume normal execution by
+  // jumping to the target address intended by the caller and that was
+  // overwritten by the address of DebugBreakXXX.
+  __ mov(ip, Operand(ExternalReference(Debug_Address::AfterBreakTarget())));
+  __ ldr(ip, MemOperand(ip));
+  __ Jump(ip);
+}
+
+
+void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
+  // Calling convention for IC load (from ic-arm.cc).
+  // ----------- S t a t e -------------
+  //  -- r0    : receiver
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+  // Registers r0 and r2 contain objects that needs to be pushed on the
+  // expression stack of the fake JS frame.
+  Generate_DebugBreakCallHelper(masm, r0.bit() | r2.bit());
+}
+
+
+void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) {
+  // Calling convention for IC store (from ic-arm.cc).
+  // ----------- S t a t e -------------
+  //  -- r0    : receiver
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+  // Registers r0 and r2 contain objects that needs to be pushed on the
+  // expression stack of the fake JS frame.
+  Generate_DebugBreakCallHelper(masm, r0.bit() | r2.bit());
+}
+
+
+void Debug::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
+  // Keyed load IC not implemented on ARM.
+}
+
+
+void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
+  // Keyed store IC not implemented on ARM.
+}
+
+
+void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) {
+  // Calling convention for IC call (from ic-arm.cc)
+  // ----------- S t a t e -------------
+  //  -- r0: number of arguments
+  //  -- r1: receiver
+  //  -- lr: return address
+  // -----------------------------------
+  // Register r1 contains an object that needs to be pushed on the expression
+  // stack of the fake JS frame. r0 is the actual number of arguments not
+  // encoded as a smi, therefore it cannot be on the expression stack of the
+  // fake JS frame as it can easily be an invalid pointer (e.g. 1). r0 will be
+  // pushed on the stack of the C frame and restored from there.
+  Generate_DebugBreakCallHelper(masm, r1.bit());
+}
+
+
+void Debug::GenerateConstructCallDebugBreak(MacroAssembler* masm) {
+  // In places other than IC call sites it is expected that r0 is TOS which
+  // is an object - this is not generally the case so this should be used with
+  // care.
+  Generate_DebugBreakCallHelper(masm, r0.bit());
+}
+
+
+void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) {
+  // In places other than IC call sites it is expected that r0 is TOS which
+  // is an object - this is not generally the case so this should be used with
+  // care.
+  Generate_DebugBreakCallHelper(masm, r0.bit());
+}
+
+
+void Debug::GenerateReturnDebugBreakEntry(MacroAssembler* masm) {
+  // Generate nothing as this handling of debug break return is not done this
+  // way on ARM  - yet.
+}
+
+
+void Debug::GenerateStubNoRegistersDebugBreak(MacroAssembler* masm) {
+  // Generate nothing as CodeStub CallFunction is not used on ARM.
+}
+
+
+#undef __
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/debug-delay.js b/deps/v8/src/debug-delay.js
new file mode 100644
index 0000000..9944fb3
--- /dev/null
+++ b/deps/v8/src/debug-delay.js
@@ -0,0 +1,1853 @@
+// 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.
+
+// jsminify this file, js2c: jsmin
+
+// Default number of frames to include in the response to backtrace request.
+const kDefaultBacktraceLength = 10;
+
+const Debug = {};
+
+// Regular expression to skip "crud" at the beginning of a source line which is
+// not really code. Currently the regular expression matches whitespace and
+// comments.
+const sourceLineBeginningSkip = /^(?:[ \v\h]*(?:\/\*.*?\*\/)*)*/;
+
+// Debug events which can occour in the V8 JavaScript engine. These originate
+// from the API include file debug.h.
+Debug.DebugEvent = { Break: 1,
+                     Exception: 2,
+                     NewFunction: 3,
+                     BeforeCompile: 4,
+                     AfterCompile: 5 };
+
+// Types of exceptions that can be broken upon.
+Debug.ExceptionBreak = { All : 0,
+                         Uncaught: 1 };
+
+// The different types of steps.
+Debug.StepAction = { StepOut: 0,
+                     StepNext: 1,
+                     StepIn: 2,
+                     StepMin: 3,
+                     StepInMin: 4 };
+
+// The different types of scripts matching enum ScriptType in objects.h.
+Debug.ScriptType = { Native: 0,
+                     Extension: 1,
+                     Normal: 2 };
+
+// The different script break point types.
+Debug.ScriptBreakPointType = { ScriptId: 0,
+                               ScriptName: 1 };
+
+function ScriptTypeFlag(type) {
+  return (1 << type);
+}
+
+// Globals.
+var next_response_seq = 0;
+var next_break_point_number = 1;
+var break_points = [];
+var script_break_points = [];
+
+
+// Create a new break point object and add it to the list of break points.
+function MakeBreakPoint(source_position, opt_line, opt_column, opt_script_break_point) {
+  var break_point = new BreakPoint(source_position, opt_line, opt_column, opt_script_break_point);
+  break_points.push(break_point);
+  return break_point;
+}
+
+
+// Object representing a break point.
+// NOTE: This object does not have a reference to the function having break
+// point as this would cause function not to be garbage collected when it is
+// not used any more. We do not want break points to keep functions alive.
+function BreakPoint(source_position, opt_line, opt_column, opt_script_break_point) {
+  this.source_position_ = source_position;
+  this.source_line_ = opt_line;
+  this.source_column_ = opt_column;
+  if (opt_script_break_point) {
+    this.script_break_point_ = opt_script_break_point;
+  } else {
+    this.number_ = next_break_point_number++;
+  }
+  this.hit_count_ = 0;
+  this.active_ = true;
+  this.condition_ = null;
+  this.ignoreCount_ = 0;
+}
+
+
+BreakPoint.prototype.number = function() {
+  return this.number_;
+};
+
+
+BreakPoint.prototype.func = function() {
+  return this.func_;
+};
+
+
+BreakPoint.prototype.source_position = function() {
+  return this.source_position_;
+};
+
+
+BreakPoint.prototype.hit_count = function() {
+  return this.hit_count_;
+};
+
+
+BreakPoint.prototype.active = function() {
+  if (this.script_break_point()) {
+    return this.script_break_point().active();
+  }
+  return this.active_;
+};
+
+
+BreakPoint.prototype.condition = function() {
+  if (this.script_break_point() && this.script_break_point().condition()) {
+    return this.script_break_point().condition();
+  }
+  return this.condition_;
+};
+
+
+BreakPoint.prototype.ignoreCount = function() {
+  return this.ignoreCount_;
+};
+
+
+BreakPoint.prototype.script_break_point = function() {
+  return this.script_break_point_;
+};
+
+
+BreakPoint.prototype.enable = function() {
+  this.active_ = true;
+};
+
+
+BreakPoint.prototype.disable = function() {
+  this.active_ = false;
+};
+
+
+BreakPoint.prototype.setCondition = function(condition) {
+  this.condition_ = condition;
+};
+
+
+BreakPoint.prototype.setIgnoreCount = function(ignoreCount) {
+  this.ignoreCount_ = ignoreCount;
+};
+
+
+BreakPoint.prototype.isTriggered = function(exec_state) {
+  // Break point not active - not triggered.
+  if (!this.active()) return false;
+
+  // Check for conditional break point.
+  if (this.condition()) {
+    // If break point has condition try to evaluate it in the top frame.
+    try {
+      var mirror = exec_state.frame(0).evaluate(this.condition());
+      // If no sensible mirror or non true value break point not triggered.
+      if (!(mirror instanceof ValueMirror) || !%ToBoolean(mirror.value_)) {
+        return false;
+      }
+    } catch (e) {
+      // Exception evaluating condition counts as not triggered.
+      return false;
+    }
+  }
+
+  // Update the hit count.
+  this.hit_count_++;
+  if (this.script_break_point_) {
+    this.script_break_point_.hit_count_++;
+  }
+
+  // If the break point has an ignore count it is not triggered.
+  if (this.ignoreCount_ > 0) {
+    this.ignoreCount_--;
+    return false;
+  }
+
+  // Break point triggered.
+  return true;
+};
+
+
+// Function called from the runtime when a break point is hit. Returns true if
+// the break point is triggered and supposed to break execution.
+function IsBreakPointTriggered(break_id, break_point) {
+  return break_point.isTriggered(MakeExecutionState(break_id));
+}
+
+
+// Object representing a script break point. The script is referenced by its
+// script name or script id and the break point is represented as line and
+// column.
+function ScriptBreakPoint(type, script_id_or_name, opt_line, opt_column) {
+  this.type_ = type;
+  if (type == Debug.ScriptBreakPointType.ScriptId) {
+    this.script_id_ = script_id_or_name;
+  } else {  // type == Debug.ScriptBreakPointType.ScriptName
+    this.script_name_ = script_id_or_name;
+  }
+  this.line_ = opt_line || 0;
+  this.column_ = opt_column;
+  this.hit_count_ = 0;
+  this.active_ = true;
+  this.condition_ = null;
+  this.ignoreCount_ = 0;
+}
+
+
+ScriptBreakPoint.prototype.number = function() {
+  return this.number_;
+};
+
+
+ScriptBreakPoint.prototype.type = function() {
+  return this.type_;
+};
+
+
+ScriptBreakPoint.prototype.script_id = function() {
+  return this.script_id_;
+};
+
+
+ScriptBreakPoint.prototype.script_name = function() {
+  return this.script_name_;
+};
+
+
+ScriptBreakPoint.prototype.line = function() {
+  return this.line_;
+};
+
+
+ScriptBreakPoint.prototype.column = function() {
+  return this.column_;
+};
+
+
+ScriptBreakPoint.prototype.hit_count = function() {
+  return this.hit_count_;
+};
+
+
+ScriptBreakPoint.prototype.active = function() {
+  return this.active_;
+};
+
+
+ScriptBreakPoint.prototype.condition = function() {
+  return this.condition_;
+};
+
+
+ScriptBreakPoint.prototype.ignoreCount = function() {
+  return this.ignoreCount_;
+};
+
+
+ScriptBreakPoint.prototype.enable = function() {
+  this.active_ = true;
+};
+
+
+ScriptBreakPoint.prototype.disable = function() {
+  this.active_ = false;
+};
+
+
+ScriptBreakPoint.prototype.setCondition = function(condition) {
+  this.condition_ = condition;
+};
+
+
+ScriptBreakPoint.prototype.setIgnoreCount = function(ignoreCount) {
+  this.ignoreCount_ = ignoreCount;
+
+  // Set ignore count on all break points created from this script break point.
+  for (var i = 0; i < break_points.length; i++) {
+    if (break_points[i].script_break_point() === this) {
+      break_points[i].setIgnoreCount(ignoreCount);
+    }
+  }
+};
+
+
+// Check whether a script matches this script break point. Currently this is
+// only based on script name.
+ScriptBreakPoint.prototype.matchesScript = function(script) {
+  if (this.type_ == Debug.ScriptBreakPointType.ScriptId) {
+    return this.script_id_ == script.id;
+  } else {  // this.type_ == Debug.ScriptBreakPointType.ScriptName
+    return this.script_name_ == script.name &&
+           script.line_offset <= this.line_  &&
+           this.line_ < script.line_offset + script.lineCount();
+  }
+};
+
+
+// Set the script break point in a script.
+ScriptBreakPoint.prototype.set = function (script) {
+  var column = this.column();
+  var line = this.line();
+  // If the column is undefined the break is on the line. To help locate the
+  // first piece of breakable code on the line try to find the column on the
+  // line which contains some source.
+  if (IS_UNDEFINED(column)) {
+    var source_line = script.sourceLine(this.line());
+
+    // Allocate array for caching the columns where the actual source starts.
+    if (!script.sourceColumnStart_) {
+      script.sourceColumnStart_ = new Array(script.lineCount());
+    }
+    
+    // Fill cache if needed and get column where the actual source starts.
+    if (IS_UNDEFINED(script.sourceColumnStart_[line])) {
+      script.sourceColumnStart_[line] =
+          source_line.match(sourceLineBeginningSkip)[0].length;
+    }
+    column = script.sourceColumnStart_[line];
+  }
+
+  // Convert the line and column into an absolute position within the script.
+  var pos = Debug.findScriptSourcePosition(script, this.line(), column);
+  
+  // If the position is not found in the script (the script might be shorter
+  // than it used to be) just ignore it.
+  if (pos === null) return;
+  
+  // Create a break point object and set the break point.
+  break_point = MakeBreakPoint(pos, this.line(), this.column(), this);
+  break_point.setIgnoreCount(this.ignoreCount());
+  %SetScriptBreakPoint(script, pos, break_point);
+
+  return break_point;
+};
+
+
+// Clear all the break points created from this script break point
+ScriptBreakPoint.prototype.clear = function () {
+  var remaining_break_points = [];
+  for (var i = 0; i < break_points.length; i++) {
+    if (break_points[i].script_break_point() &&
+        break_points[i].script_break_point() === this) {
+      %ClearBreakPoint(break_points[i]);
+    } else {
+      remaining_break_points.push(break_points[i]);
+    }
+  }
+  break_points = remaining_break_points;
+};
+
+
+// Function called from runtime when a new script is compiled to set any script
+// break points set in this script.
+function UpdateScriptBreakPoints(script) {
+  for (var i = 0; i < script_break_points.length; i++) {
+    if (script_break_points[i].type() == Debug.ScriptBreakPointType.ScriptName &&
+        script_break_points[i].script_name() == script.name) {
+      script_break_points[i].set(script);
+    }
+  }
+}
+
+
+Debug.setListener = function(listener, opt_data) {
+  if (!IS_FUNCTION(listener) && !IS_UNDEFINED(listener) && !IS_NULL(listener)) {
+    throw new Error('Parameters have wrong types.');
+  }
+  %SetDebugEventListener(listener, opt_data);
+};
+
+
+Debug.breakExecution = function(f) {
+  %Break();
+};
+
+Debug.breakLocations = function(f) {
+  if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
+  return %GetBreakLocations(f);
+};
+
+// Returns a Script object. If the parameter is a function the return value
+// is the script in which the function is defined. If the parameter is a string
+// the return value is the script for which the script name has that string
+// value.  If it is a regexp and there is a unique script whose name matches
+// we return that, otherwise undefined.
+Debug.findScript = function(func_or_script_name) {
+  if (IS_FUNCTION(func_or_script_name)) {
+    return %FunctionGetScript(func_or_script_name);
+  } else if (IS_REGEXP(func_or_script_name)) {
+    var scripts = Debug.scripts();
+    var last_result = null;
+    var result_count = 0;
+    for (var i in scripts) {
+      var script = scripts[i];
+      if (func_or_script_name.test(script.name)) {
+        last_result = script;
+        result_count++;
+      }
+    }
+    // Return the unique script matching the regexp.  If there are more
+    // than one we don't return a value since there is no good way to
+    // decide which one to return.  Returning a "random" one, say the
+    // first, would introduce nondeterminism (or something close to it)
+    // because the order is the heap iteration order.
+    if (result_count == 1) {
+      return last_result;
+    } else {
+      return undefined;
+    }
+  } else {
+    return %GetScript(func_or_script_name);
+  }
+};
+
+// Returns the script source. If the parameter is a function the return value
+// is the script source for the script in which the function is defined. If the
+// parameter is a string the return value is the script for which the script
+// name has that string value.
+Debug.scriptSource = function(func_or_script_name) {
+  return this.findScript(func_or_script_name).source;
+};
+
+Debug.source = function(f) {
+  if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
+  return %FunctionGetSourceCode(f);
+};
+
+Debug.assembler = function(f) {
+  if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
+  return %FunctionGetAssemblerCode(f);
+};
+
+Debug.sourcePosition = function(f) {
+  if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
+  return %FunctionGetScriptSourcePosition(f);
+};
+
+
+Debug.findFunctionSourceLocation = function(func, opt_line, opt_column) {
+  var script = %FunctionGetScript(func);
+  var script_offset = %FunctionGetScriptSourcePosition(func);
+  return script.locationFromLine(opt_line, opt_column, script_offset);
+}
+
+
+// Returns the character position in a script based on a line number and an
+// optional position within that line.
+Debug.findScriptSourcePosition = function(script, opt_line, opt_column) {
+  var location = script.locationFromLine(opt_line, opt_column);  
+  return location ? location.position : null;
+}
+
+
+Debug.findBreakPoint = function(break_point_number, remove) {
+  var break_point;
+  for (var i = 0; i < break_points.length; i++) {
+    if (break_points[i].number() == break_point_number) {
+      break_point = break_points[i];
+      // Remove the break point from the list if requested.
+      if (remove) {
+        break_points.splice(i, 1);
+      }
+      break;
+    }
+  }
+  if (break_point) {
+    return break_point;
+  } else {
+    return this.findScriptBreakPoint(break_point_number, remove);
+  }
+};
+
+
+Debug.setBreakPoint = function(func, opt_line, opt_column, opt_condition) {
+  if (!IS_FUNCTION(func)) throw new Error('Parameters have wrong types.');
+  // Break points in API functions are not supported.
+  if (%FunctionIsAPIFunction(func)) {
+    throw new Error('Cannot set break point in native code.');
+  }
+  // Find source position relative to start of the function
+  var break_position =
+      this.findFunctionSourceLocation(func, opt_line, opt_column).position;
+  var source_position = break_position - this.sourcePosition(func);
+  // Find the script for the function.
+  var script = %FunctionGetScript(func);
+  // Break in builtin JavaScript code is not supported.
+  if (script.type == Debug.ScriptType.Native) {
+    throw new Error('Cannot set break point in native code.');
+  }
+  // If the script for the function has a name convert this to a script break
+  // point.
+  if (script && script.id) {
+    // Adjust the source position to be script relative.
+    source_position += %FunctionGetScriptSourcePosition(func);
+    // Find line and column for the position in the script and set a script
+    // break point from that.
+    var location = script.locationFromPosition(source_position, false);
+    return this.setScriptBreakPointById(script.id,
+                                        location.line, location.column,
+                                        opt_condition);
+  } else {
+    // Set a break point directly on the function.
+    var break_point = MakeBreakPoint(source_position, opt_line, opt_column);
+    %SetFunctionBreakPoint(func, source_position, break_point);
+    break_point.setCondition(opt_condition);
+    return break_point.number();
+  }
+};
+
+
+Debug.enableBreakPoint = function(break_point_number) {
+  var break_point = this.findBreakPoint(break_point_number, false);
+  break_point.enable();
+};
+
+
+Debug.disableBreakPoint = function(break_point_number) {
+  var break_point = this.findBreakPoint(break_point_number, false);
+  break_point.disable();
+};
+
+
+Debug.changeBreakPointCondition = function(break_point_number, condition) {
+  var break_point = this.findBreakPoint(break_point_number, false);
+  break_point.setCondition(condition);
+};
+
+
+Debug.changeBreakPointIgnoreCount = function(break_point_number, ignoreCount) {
+  if (ignoreCount < 0) {
+    throw new Error('Invalid argument');
+  }
+  var break_point = this.findBreakPoint(break_point_number, false);
+  break_point.setIgnoreCount(ignoreCount);
+};
+
+
+Debug.clearBreakPoint = function(break_point_number) {
+  var break_point = this.findBreakPoint(break_point_number, true);
+  if (break_point) {
+    return %ClearBreakPoint(break_point);
+  } else {
+    break_point = this.findScriptBreakPoint(break_point_number, true);
+    if (!break_point) {
+      throw new Error('Invalid breakpoint');
+    }
+  }
+};
+
+
+Debug.clearAllBreakPoints = function() {
+  for (var i = 0; i < break_points.length; i++) {
+    break_point = break_points[i];
+    %ClearBreakPoint(break_point);
+  }
+  break_points = [];
+};
+
+
+Debug.findScriptBreakPoint = function(break_point_number, remove) {
+  var script_break_point;
+  for (var i = 0; i < script_break_points.length; i++) {
+    if (script_break_points[i].number() == break_point_number) {
+      script_break_point = script_break_points[i];
+      // Remove the break point from the list if requested.
+      if (remove) {
+        script_break_point.clear();
+        script_break_points.splice(i,1);
+      }
+      break;
+    }
+  }
+  return script_break_point;
+}
+
+
+// Sets a breakpoint in a script identified through id or name at the
+// specified source line and column within that line.
+Debug.setScriptBreakPoint = function(type, script_id_or_name,
+                                     opt_line, opt_column, opt_condition) {
+  // Create script break point object.
+  var script_break_point =
+      new ScriptBreakPoint(type, script_id_or_name, opt_line, opt_column);
+
+  // Assign number to the new script break point and add it.
+  script_break_point.number_ = next_break_point_number++;
+  script_break_point.setCondition(opt_condition);
+  script_break_points.push(script_break_point);
+
+  // Run through all scripts to see if this script break point matches any
+  // loaded scripts.
+  var scripts = this.scripts();
+  for (var i = 0; i < scripts.length; i++) {
+    if (script_break_point.matchesScript(scripts[i])) {
+      script_break_point.set(scripts[i]);
+    }
+  }
+
+  return script_break_point.number();
+}
+
+
+Debug.setScriptBreakPointById = function(script_id,
+                                         opt_line, opt_column,
+                                         opt_condition) {
+  return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId,
+                                  script_id, opt_line, opt_column,
+                                  opt_condition)
+}
+
+
+Debug.setScriptBreakPointByName = function(script_name,
+                                           opt_line, opt_column,
+                                           opt_condition) {
+  return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptName,
+                                  script_name, opt_line, opt_column,
+                                  opt_condition)
+}
+
+
+Debug.enableScriptBreakPoint = function(break_point_number) {
+  var script_break_point = this.findScriptBreakPoint(break_point_number, false);
+  script_break_point.enable();
+};
+
+
+Debug.disableScriptBreakPoint = function(break_point_number) {
+  var script_break_point = this.findScriptBreakPoint(break_point_number, false);
+  script_break_point.disable();
+};
+
+
+Debug.changeScriptBreakPointCondition = function(break_point_number, condition) {
+  var script_break_point = this.findScriptBreakPoint(break_point_number, false);
+  script_break_point.setCondition(condition);
+};
+
+
+Debug.changeScriptBreakPointIgnoreCount = function(break_point_number, ignoreCount) {
+  if (ignoreCount < 0) {
+    throw new Error('Invalid argument');
+  }
+  var script_break_point = this.findScriptBreakPoint(break_point_number, false);
+  script_break_point.setIgnoreCount(ignoreCount);
+};
+
+
+Debug.scriptBreakPoints = function() {
+  return script_break_points;
+}
+
+
+Debug.clearStepping = function() {
+  %ClearStepping();
+}
+
+Debug.setBreakOnException = function() {
+  return %ChangeBreakOnException(Debug.ExceptionBreak.All, true);
+};
+
+Debug.clearBreakOnException = function() {
+  return %ChangeBreakOnException(Debug.ExceptionBreak.All, false);
+};
+
+Debug.setBreakOnUncaughtException = function() {
+  return %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, true);
+};
+
+Debug.clearBreakOnUncaughtException = function() {
+  return %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, false);
+};
+
+Debug.showBreakPoints = function(f, full) {
+  if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
+  var source = full ? this.scriptSource(f) : this.source(f);
+  var offset = full ? this.sourcePosition(f) : 0;
+  var locations = this.breakLocations(f);
+  if (!locations) return source;
+  locations.sort(function(x, y) { return x - y; });
+  var result = "";
+  var prev_pos = 0;
+  var pos;
+  for (var i = 0; i < locations.length; i++) {
+    pos = locations[i] - offset;
+    result += source.slice(prev_pos, pos);
+    result += "[B" + i + "]";
+    prev_pos = pos;
+  }
+  pos = source.length;
+  result += source.substring(prev_pos, pos);
+  return result;
+};
+
+
+// Get all the scripts currently loaded. Locating all the scripts is based on
+// scanning the heap.
+Debug.scripts = function() {
+  // Collect all scripts in the heap.
+  return %DebugGetLoadedScripts();
+}
+
+function MakeExecutionState(break_id) {
+  return new ExecutionState(break_id);
+}
+
+function ExecutionState(break_id) {
+  this.break_id = break_id;
+  this.selected_frame = 0;
+}
+
+ExecutionState.prototype.prepareStep = function(opt_action, opt_count) {
+  var action = Debug.StepAction.StepIn;
+  if (!IS_UNDEFINED(opt_action)) action = %ToNumber(opt_action);
+  var count = opt_count ? %ToNumber(opt_count) : 1;
+
+  return %PrepareStep(this.break_id, action, count);
+}
+
+ExecutionState.prototype.evaluateGlobal = function(source, disable_break) {
+  return MakeMirror(
+      %DebugEvaluateGlobal(this.break_id, source, Boolean(disable_break)));
+};
+
+ExecutionState.prototype.frameCount = function() {
+  return %GetFrameCount(this.break_id);
+};
+
+ExecutionState.prototype.threadCount = function() {
+  return %GetThreadCount(this.break_id);
+};
+
+ExecutionState.prototype.frame = function(opt_index) {
+  // If no index supplied return the selected frame.
+  if (opt_index == null) opt_index = this.selected_frame;
+  return new FrameMirror(this.break_id, opt_index);
+};
+
+ExecutionState.prototype.cframesValue = function(opt_from_index, opt_to_index) {
+  return %GetCFrames(this.break_id);
+};
+
+ExecutionState.prototype.setSelectedFrame = function(index) {
+  var i = %ToNumber(index);
+  if (i < 0 || i >= this.frameCount()) throw new Error('Illegal frame index.');
+  this.selected_frame = i;
+};
+
+ExecutionState.prototype.selectedFrame = function() {
+  return this.selected_frame;
+};
+
+ExecutionState.prototype.debugCommandProcessor = function(protocol) {
+  return new DebugCommandProcessor(this, protocol);
+};
+
+
+function MakeBreakEvent(exec_state, break_points_hit) {
+  return new BreakEvent(exec_state, break_points_hit);
+}
+
+
+function BreakEvent(exec_state, break_points_hit) {
+  this.exec_state_ = exec_state;
+  this.break_points_hit_ = break_points_hit;
+}
+
+
+BreakEvent.prototype.executionState = function() {
+  return this.exec_state_;
+};
+
+
+BreakEvent.prototype.eventType = function() {
+  return Debug.DebugEvent.Break;
+};
+
+
+BreakEvent.prototype.func = function() {
+  return this.exec_state_.frame(0).func();
+};
+
+
+BreakEvent.prototype.sourceLine = function() {
+  return this.exec_state_.frame(0).sourceLine();
+};
+
+
+BreakEvent.prototype.sourceColumn = function() {
+  return this.exec_state_.frame(0).sourceColumn();
+};
+
+
+BreakEvent.prototype.sourceLineText = function() {
+  return this.exec_state_.frame(0).sourceLineText();
+};
+
+
+BreakEvent.prototype.breakPointsHit = function() {
+  return this.break_points_hit_;
+};
+
+
+BreakEvent.prototype.toJSONProtocol = function() {
+  var o = { seq: next_response_seq++,
+            type: "event",
+            event: "break",
+            body: { invocationText: this.exec_state_.frame(0).invocationText(),
+                  }
+          }
+
+  // Add script related information to the event if available.
+  var script = this.func().script();
+  if (script) {
+    o.body.sourceLine = this.sourceLine(),
+    o.body.sourceColumn = this.sourceColumn(),
+    o.body.sourceLineText = this.sourceLineText(),
+    o.body.script = MakeScriptObject_(script, false);
+  }
+
+  // Add an Array of break points hit if any.
+  if (this.breakPointsHit()) {
+    o.body.breakpoints = [];
+    for (var i = 0; i < this.breakPointsHit().length; i++) {
+      // Find the break point number. For break points originating from a
+      // script break point supply the script break point number.
+      var breakpoint = this.breakPointsHit()[i];
+      var script_break_point = breakpoint.script_break_point();
+      var number;
+      if (script_break_point) {
+        number = script_break_point.number();
+      } else {
+        number = breakpoint.number();
+      }
+      o.body.breakpoints.push(number);
+    }
+  }
+
+  return SimpleObjectToJSON_(o);
+};
+
+
+function MakeExceptionEvent(exec_state, exception, uncaught) {
+  return new ExceptionEvent(exec_state, exception, uncaught);
+}
+
+
+function ExceptionEvent(exec_state, exception, uncaught) {
+  this.exec_state_ = exec_state;
+  this.exception_ = exception;
+  this.uncaught_ = uncaught;
+}
+
+
+ExceptionEvent.prototype.executionState = function() {
+  return this.exec_state_;
+};
+
+
+ExceptionEvent.prototype.eventType = function() {
+  return Debug.DebugEvent.Exception;
+};
+
+
+ExceptionEvent.prototype.exception = function() {
+  return this.exception_;
+}
+
+
+ExceptionEvent.prototype.uncaught = function() {
+  return this.uncaught_;
+}
+
+
+ExceptionEvent.prototype.func = function() {
+  return this.exec_state_.frame(0).func();
+};
+
+
+ExceptionEvent.prototype.sourceLine = function() {
+  return this.exec_state_.frame(0).sourceLine();
+};
+
+
+ExceptionEvent.prototype.sourceColumn = function() {
+  return this.exec_state_.frame(0).sourceColumn();
+};
+
+
+ExceptionEvent.prototype.sourceLineText = function() {
+  return this.exec_state_.frame(0).sourceLineText();
+};
+
+
+ExceptionEvent.prototype.toJSONProtocol = function() {
+  var o = new ProtocolMessage();
+  o.event = "exception";
+  o.body = { uncaught: this.uncaught_,
+             exception: MakeMirror(this.exception_)
+           }
+           
+  // Exceptions might happen whithout any JavaScript frames.
+  if (this.exec_state_.frameCount() > 0) {
+    o.body.sourceLine = this.sourceLine();
+    o.body.sourceColumn = this.sourceColumn();
+    o.body.sourceLineText = this.sourceLineText();
+
+    // Add script information to the event if available.
+    var script = this.func().script();
+    if (script) {
+      o.body.script = MakeScriptObject_(script, false);
+    }
+  } else {
+    o.body.sourceLine = -1;
+  }
+
+  return o.toJSONProtocol();
+};
+
+
+function MakeCompileEvent(exec_state, script, before) {
+  return new CompileEvent(exec_state, script, before);
+}
+
+
+function CompileEvent(exec_state, script, before) {
+  this.exec_state_ = exec_state;
+  this.script_ = MakeMirror(script);
+  this.before_ = before;
+}
+
+
+CompileEvent.prototype.executionState = function() {
+  return this.exec_state_;
+};
+
+
+CompileEvent.prototype.eventType = function() {
+  if (this.before_) {
+    return Debug.DebugEvent.BeforeCompile;
+  } else {
+    return Debug.DebugEvent.AfterCompile;
+  }
+};
+
+
+CompileEvent.prototype.script = function() {
+  return this.script_;
+};
+
+
+CompileEvent.prototype.toJSONProtocol = function() {
+  var o = new ProtocolMessage();
+  if (this.before_) {
+    o.event = "beforeCompile";
+  } else {
+    o.event = "afterCompile";
+  }
+  o.body = {};
+  o.body.script = MakeScriptObject_(this.script_, true);
+
+  return o.toJSONProtocol();
+}
+
+
+function MakeNewFunctionEvent(func) {
+  return new NewFunctionEvent(func);
+}
+
+
+function NewFunctionEvent(func) {
+  this.func = func;
+}
+
+
+NewFunctionEvent.prototype.eventType = function() {
+  return Debug.DebugEvent.NewFunction;
+};
+
+
+NewFunctionEvent.prototype.name = function() {
+  return this.func.name;
+};
+
+
+NewFunctionEvent.prototype.setBreakPoint = function(p) {
+  Debug.setBreakPoint(this.func, p || 0);
+};
+
+
+function MakeScriptObject_(script, include_source) {
+  var o = { id: script.id(),
+            name: script.name(),
+            lineOffset: script.lineOffset(),
+            columnOffset: script.columnOffset(),
+            lineCount: script.lineCount(),
+          };
+  if (include_source) {
+    o.source = script.source();
+  }
+  return o;
+};
+
+
+function DebugCommandProcessor(exec_state) {
+  this.exec_state_ = exec_state;
+  this.running_ = false;
+};
+
+
+DebugCommandProcessor.prototype.processDebugRequest = function (request) {
+  return this.processDebugJSONRequest(request);
+}
+
+
+function ProtocolMessage(request) {
+  // Update sequence number.
+  this.seq = next_response_seq++;
+  
+  if (request) {
+    // If message is based on a request this is a response. Fill the initial
+    // response from the request.
+    this.type = 'response';
+    this.request_seq = request.seq;
+    this.command = request.command;
+  } else {
+    // If message is not based on a request it is a dabugger generated event.
+    this.type = 'event';
+  }
+  this.success = true;
+  this.running = false;
+}
+
+
+ProtocolMessage.prototype.failed = function(message) {
+  this.success = false;
+  this.message = message;
+}
+
+
+ProtocolMessage.prototype.toJSONProtocol = function() {
+  // Encode the protocol header.
+  var json = '{';
+  json += '"seq":' + this.seq;
+  if (this.request_seq) {
+    json += ',"request_seq":' + this.request_seq;
+  }
+  json += ',"type":"' + this.type + '"';
+  if (this.event) {
+    json += ',"event":' + StringToJSON_(this.event);
+  }
+  if (this.command) {
+    json += ',"command":' + StringToJSON_(this.command);
+  }
+  if (this.success) {
+    json += ',"success":' + this.success;
+  } else {
+    json += ',"success":false';
+  }
+  if (this.body) {
+    json += ',"body":';
+    // Encode the body part.
+    var serializer = MakeMirrorSerializer(true);
+    if (this.body instanceof Mirror) {
+      json += serializer.serializeValue(this.body);
+    } else if (this.body instanceof Array) {
+      json += '[';
+      for (var i = 0; i < this.body.length; i++) {
+        if (i != 0) json += ',';
+        if (this.body[i] instanceof Mirror) {
+          json += serializer.serializeValue(this.body[i]);
+        } else {
+          json += SimpleObjectToJSON_(this.body[i], serializer);
+        }
+      }
+      json += ']';
+    } else {
+      json += SimpleObjectToJSON_(this.body, serializer);
+    }
+    json += ',"refs":';
+    json += serializer.serializeReferencedObjects();
+  }
+  if (this.message) {
+    json += ',"message":' + StringToJSON_(this.message) ;
+  }
+  if (this.running) {
+    json += ',"running":true';
+  } else {
+    json += ',"running":false';
+  }
+  json += '}';
+  return json;
+}
+
+
+DebugCommandProcessor.prototype.createResponse = function(request) {
+  return new ProtocolMessage(request);
+};
+
+
+DebugCommandProcessor.prototype.processDebugJSONRequest = function(json_request) {
+  var request;  // Current request.
+  var response;  // Generated response.
+  try {
+    try {
+      // Convert the JSON string to an object.
+      request = %CompileString('(' + json_request + ')', 0)();
+
+      // Create an initial response.
+      response = this.createResponse(request);
+
+      if (!request.type) {
+        throw new Error('Type not specified');
+      }
+
+      if (request.type != 'request') {
+        throw new Error("Illegal type '" + request.type + "' in request");
+      }
+
+      if (!request.command) {
+        throw new Error('Command not specified');
+      }
+
+      if (request.command == 'continue') {
+        this.continueRequest_(request, response);
+      } else if (request.command == 'break') {
+        this.breakRequest_(request, response);
+      } else if (request.command == 'setbreakpoint') {
+        this.setBreakPointRequest_(request, response);
+      } else if (request.command == 'changebreakpoint') {
+        this.changeBreakPointRequest_(request, response);
+      } else if (request.command == 'clearbreakpoint') {
+        this.clearBreakPointRequest_(request, response);
+      } else if (request.command == 'backtrace') {
+        this.backtraceRequest_(request, response);
+      } else if (request.command == 'frame') {
+        this.frameRequest_(request, response);
+      } else if (request.command == 'evaluate') {
+        this.evaluateRequest_(request, response);
+      } else if (request.command == 'lookup') {
+        this.lookupRequest_(request, response);
+      } else if (request.command == 'references') {
+        this.referencesRequest_(request, response);
+      } else if (request.command == 'source') {
+        this.sourceRequest_(request, response);
+      } else if (request.command == 'scripts') {
+        this.scriptsRequest_(request, response);
+      } else if (request.command == 'threads') {
+        this.threadsRequest_(request, response);
+      } else {
+        throw new Error('Unknown command "' + request.command + '" in request');
+      }
+    } catch (e) {
+      // If there is no response object created one (without command).
+      if (!response) {
+        response = this.createResponse();
+      }
+      response.success = false;
+      response.message = %ToString(e);
+    }
+
+    // Return the response as a JSON encoded string.
+    try {
+      this.running_ = response.running;  // Store the running state.
+      return response.toJSONProtocol();
+    } catch (e) {
+      // Failed to generate response - return generic error.
+      return '{"seq":' + response.seq + ',' +
+              '"request_seq":' + request.seq + ',' +
+              '"type":"response",' +
+              '"success":false,' +
+              '"message":"Internal error: ' + %ToString(e) + '"}';
+    }
+  } catch (e) {
+    // Failed in one of the catch blocks above - most generic error.
+    return '{"seq":0,"type":"response","success":false,"message":"Internal error"}';
+  }
+};
+
+
+DebugCommandProcessor.prototype.continueRequest_ = function(request, response) {
+  // Check for arguments for continue.
+  if (request.arguments) {
+    var count = 1;
+    var action = Debug.StepAction.StepIn;
+
+    // Pull out arguments.
+    var stepaction = request.arguments.stepaction;
+    var stepcount = request.arguments.stepcount;
+
+    // Get the stepcount argument if any.
+    if (stepcount) {
+      count = %ToNumber(stepcount);
+      if (count < 0) {
+        throw new Error('Invalid stepcount argument "' + stepcount + '".');
+      }
+    }
+
+    // Get the stepaction argument.
+    if (stepaction) {
+      if (stepaction == 'in') {
+        action = Debug.StepAction.StepIn;
+      } else if (stepaction == 'min') {
+        action = Debug.StepAction.StepMin;
+      } else if (stepaction == 'next') {
+        action = Debug.StepAction.StepNext;
+      } else if (stepaction == 'out') {
+        action = Debug.StepAction.StepOut;
+      } else {
+        throw new Error('Invalid stepaction argument "' + stepaction + '".');
+      }
+    }
+
+    // Setup the VM for stepping.
+    this.exec_state_.prepareStep(action, count);
+  }
+
+  // VM should be running after executing this request.
+  response.running = true;
+};
+
+
+DebugCommandProcessor.prototype.breakRequest_ = function(request, response) {
+  // Ignore as break command does not do anything when broken.
+};
+
+
+DebugCommandProcessor.prototype.setBreakPointRequest_ =
+    function(request, response) {
+  // Check for legal request.
+  if (!request.arguments) {
+    response.failed('Missing arguments');
+    return;
+  }
+
+  // Pull out arguments.
+  var type = request.arguments.type;
+  var target = request.arguments.target;
+  var line = request.arguments.line;
+  var column = request.arguments.column;
+  var enabled = IS_UNDEFINED(request.arguments.enabled) ?
+      true : request.arguments.enabled;
+  var condition = request.arguments.condition;
+  var ignoreCount = request.arguments.ignoreCount;
+
+  // Check for legal arguments.
+  if (!type || !target) {
+    response.failed('Missing argument "type" or "target"');
+    return;
+  }
+  if (type != 'function' && type != 'script' && type != 'scriptId') {
+    response.failed('Illegal type "' + type + '"');
+    return;
+  }
+
+  // Either function or script break point.
+  var break_point_number;
+  if (type == 'function') {
+    // Handle function break point.
+    if (!IS_STRING(target)) {
+      response.failed('Argument "target" is not a string value');
+      return;
+    }
+    var f;
+    try {
+      // Find the function through a global evaluate.
+      f = this.exec_state_.evaluateGlobal(target).value();
+    } catch (e) {
+      response.failed('Error: "' + %ToString(e) +
+                      '" evaluating "' + target + '"');
+      return;
+    }
+    if (!IS_FUNCTION(f)) {
+      response.failed('"' + target + '" does not evaluate to a function');
+      return;
+    }
+
+    // Set function break point.
+    break_point_number = Debug.setBreakPoint(f, line, column, condition);
+  } else if (type == 'script') {
+    // set script break point.
+    break_point_number =
+        Debug.setScriptBreakPointByName(target, line, column, condition);
+  } else {  // type == 'scriptId.
+    break_point_number =
+        Debug.setScriptBreakPointById(target, line, column, condition);
+  }
+
+  // Set additional break point properties.
+  var break_point = Debug.findBreakPoint(break_point_number);
+  if (ignoreCount) {
+    Debug.changeBreakPointIgnoreCount(break_point_number, ignoreCount);
+  }
+  if (!enabled) {
+    Debug.disableBreakPoint(break_point_number);
+  }
+
+  // Add the break point number to the response.
+  response.body = { type: type,
+                    breakpoint: break_point_number }
+
+  // Add break point information to the response.
+  if (break_point instanceof ScriptBreakPoint) {
+    if (break_point.type() == Debug.ScriptBreakPointType.ScriptId) {
+      response.body.type = 'scriptId';
+      response.body.script_id = break_point.script_id();
+    } else {
+      response.body.type = 'scriptName';
+      response.body.script_name = break_point.script_name();
+    }
+    response.body.line = break_point.line();
+    response.body.column = break_point.column();
+  } else {
+    response.body.type = 'function';
+  }
+};
+
+
+DebugCommandProcessor.prototype.changeBreakPointRequest_ = function(request, response) {
+  // Check for legal request.
+  if (!request.arguments) {
+    response.failed('Missing arguments');
+    return;
+  }
+
+  // Pull out arguments.
+  var break_point = %ToNumber(request.arguments.breakpoint);
+  var enabled = request.arguments.enabled;
+  var condition = request.arguments.condition;
+  var ignoreCount = request.arguments.ignoreCount;
+
+  // Check for legal arguments.
+  if (!break_point) {
+    response.failed('Missing argument "breakpoint"');
+    return;
+  }
+
+  // Change enabled state if supplied.
+  if (!IS_UNDEFINED(enabled)) {
+    if (enabled) {
+      Debug.enableBreakPoint(break_point);
+    } else {
+      Debug.disableBreakPoint(break_point);
+    }
+  }
+
+  // Change condition if supplied
+  if (!IS_UNDEFINED(condition)) {
+    Debug.changeBreakPointCondition(break_point, condition);
+  }
+
+  // Change ignore count if supplied
+  if (!IS_UNDEFINED(ignoreCount)) {
+    Debug.changeBreakPointIgnoreCount(break_point, ignoreCount);
+  }
+}
+
+
+DebugCommandProcessor.prototype.clearBreakPointRequest_ = function(request, response) {
+  // Check for legal request.
+  if (!request.arguments) {
+    response.failed('Missing arguments');
+    return;
+  }
+
+  // Pull out arguments.
+  var break_point = %ToNumber(request.arguments.breakpoint);
+
+  // Check for legal arguments.
+  if (!break_point) {
+    response.failed('Missing argument "breakpoint"');
+    return;
+  }
+
+  // Clear break point.
+  Debug.clearBreakPoint(break_point);
+
+  // Add the cleared break point number to the response.
+  response.body = { breakpoint: break_point }
+}
+
+
+DebugCommandProcessor.prototype.backtraceRequest_ = function(request, response) {
+  // Get the number of frames.
+  var total_frames = this.exec_state_.frameCount();
+
+  // Create simple response if there are no frames.
+  if (total_frames == 0) {
+    response.body = {
+      totalFrames: total_frames
+    }
+    return;
+  }
+
+  // Default frame range to include in backtrace.
+  var from_index = 0
+  var to_index = kDefaultBacktraceLength;
+
+  // Get the range from the arguments.
+  if (request.arguments) {
+    from_index = request.arguments.fromFrame;
+    if (from_index < 0) {
+      return response.failed('Invalid frame number');
+    }
+    to_index = request.arguments.toFrame;
+    if (to_index < 0) {
+      return response.failed('Invalid frame number');
+    }
+  }
+
+  // Adjust the index.
+  to_index = Math.min(total_frames, to_index);
+
+  if (to_index <= from_index) {
+    var error = 'Invalid frame range';
+    return response.failed(error);
+  }
+
+  // Create the response body.
+  var frames = [];
+  for (var i = from_index; i < to_index; i++) {
+    frames.push(this.exec_state_.frame(i));
+  }
+  response.body = {
+    fromFrame: from_index,
+    toFrame: to_index,
+    totalFrames: total_frames,
+    frames: frames
+  }
+};
+
+
+DebugCommandProcessor.prototype.backtracec = function(cmd, args) {
+  return this.exec_state_.cframesValue();
+};
+
+
+DebugCommandProcessor.prototype.frameRequest_ = function(request, response) {
+  // No frames no source.
+  if (this.exec_state_.frameCount() == 0) {
+    return response.failed('No frames');
+  }
+
+  // With no arguments just keep the selected frame.
+  if (request.arguments) {
+    index = request.arguments.number;
+    if (index < 0 || this.exec_state_.frameCount() <= index) {
+      return response.failed('Invalid frame number');
+    }
+    
+    this.exec_state_.setSelectedFrame(request.arguments.number);
+  }
+  response.body = this.exec_state_.frame();
+};
+
+
+DebugCommandProcessor.prototype.evaluateRequest_ = function(request, response) {
+  if (!request.arguments) {
+    return response.failed('Missing arguments');
+  }
+
+  // Pull out arguments.
+  var expression = request.arguments.expression;
+  var frame = request.arguments.frame;
+  var global = request.arguments.global;
+  var disable_break = request.arguments.disable_break;
+
+  // The expression argument could be an integer so we convert it to a
+  // string.
+  try {
+    expression = String(expression);
+  } catch(e) {
+    return response.failed('Failed to convert expression argument to string');
+  }
+
+  // Check for legal arguments.
+  if (!IS_UNDEFINED(frame) && global) {
+    return response.failed('Arguments "frame" and "global" are exclusive');
+  }
+
+  // Global evaluate.
+  if (global) {
+    // Evaluate in the global context.
+    response.body =
+        this.exec_state_.evaluateGlobal(expression), Boolean(disable_break);
+    return;
+  }
+
+  // Default value for disable_break is true.
+  if (IS_UNDEFINED(disable_break)) {
+    disable_break = true;
+  }
+
+  // No frames no evaluate in frame.
+  if (this.exec_state_.frameCount() == 0) {
+    return response.failed('No frames');
+  }
+
+  // Check whether a frame was specified.
+  if (!IS_UNDEFINED(frame)) {
+    var frame_number = %ToNumber(frame);
+    if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) {
+      return response.failed('Invalid frame "' + frame + '"');
+    }
+    // Evaluate in the specified frame.
+    response.body = this.exec_state_.frame(frame_number).evaluate(
+        expression, Boolean(disable_break));
+    return;
+  } else {
+    // Evaluate in the selected frame.
+    response.body = this.exec_state_.frame().evaluate(
+        expression, Boolean(disable_break));
+    return;
+  }
+};
+
+
+DebugCommandProcessor.prototype.lookupRequest_ = function(request, response) {
+  if (!request.arguments) {
+    return response.failed('Missing arguments');
+  }
+
+  // Pull out arguments.
+  var handle = request.arguments.handle;
+
+  // Check for legal arguments.
+  if (IS_UNDEFINED(handle)) {
+    return response.failed('Argument "handle" missing');
+  }
+
+  // Lookup handle.
+  var mirror = LookupMirror(handle);
+  if (mirror) {
+    response.body = mirror;
+  } else {
+    return response.failed('Object #' + handle + '# not found');
+  }
+};
+
+
+DebugCommandProcessor.prototype.referencesRequest_ =
+    function(request, response) {
+  if (!request.arguments) {
+    return response.failed('Missing arguments');
+  }
+
+  // Pull out arguments.
+  var type = request.arguments.type;
+  var handle = request.arguments.handle;
+
+  // Check for legal arguments.
+  if (IS_UNDEFINED(type)) {
+    return response.failed('Argument "type" missing');
+  }
+  if (IS_UNDEFINED(handle)) {
+    return response.failed('Argument "handle" missing');
+  }
+  if (type != 'referencedBy' && type != 'constructedBy') {
+    return response.failed('Invalid type "' + type + '"');
+  }
+
+  // Lookup handle and return objects with references the object.
+  var mirror = LookupMirror(handle);
+  if (mirror) {
+    if (type == 'referencedBy') {
+      response.body = mirror.referencedBy();
+    } else {
+      response.body = mirror.constructedBy();
+    }
+  } else {
+    return response.failed('Object #' + handle + '# not found');
+  }
+};
+
+
+DebugCommandProcessor.prototype.sourceRequest_ = function(request, response) {
+  // No frames no source.
+  if (this.exec_state_.frameCount() == 0) {
+    return response.failed('No source');
+  }
+
+  var from_line;
+  var to_line;
+  var frame = this.exec_state_.frame();
+  if (request.arguments) {
+    // Pull out arguments.
+    from_line = request.arguments.fromLine;
+    to_line = request.arguments.toLine;
+
+    if (!IS_UNDEFINED(request.arguments.frame)) {
+      var frame_number = %ToNumber(request.arguments.frame);
+      if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) {
+        return response.failed('Invalid frame "' + frame + '"');
+      }
+      frame = this.exec_state_.frame(frame_number);
+    }
+  }
+
+  // Get the script selected.
+  var script = frame.func().script();
+  if (!script) {
+    return response.failed('No source');
+  }
+
+  // Get the source slice and fill it into the response.
+  var slice = script.sourceSlice(from_line, to_line);
+  if (!slice) {
+    return response.failed('Invalid line interval');
+  }
+  response.body = {};
+  response.body.source = slice.sourceText();
+  response.body.fromLine = slice.from_line;
+  response.body.toLine = slice.to_line;
+  response.body.fromPosition = slice.from_position;
+  response.body.toPosition = slice.to_position;
+  response.body.totalLines = script.lineCount();
+};
+
+
+DebugCommandProcessor.prototype.scriptsRequest_ = function(request, response) {
+  var types = ScriptTypeFlag(Debug.ScriptType.Normal);
+  var includeSource = false;
+  if (request.arguments) {
+    // Pull out arguments.
+    if (!IS_UNDEFINED(request.arguments.types)) {
+      types = %ToNumber(request.arguments.types);
+      if (isNaN(types) || types < 0) {
+        return response.failed('Invalid types "' + request.arguments.types + '"');
+      }
+    }
+    
+    if (!IS_UNDEFINED(request.arguments.includeSource)) {
+      includeSource = %ToBoolean(request.arguments.includeSource);
+    }
+  }
+
+  // Collect all scripts in the heap.
+  var scripts = %DebugGetLoadedScripts();
+
+  response.body = [];
+
+  for (var i = 0; i < scripts.length; i++) {
+    if (types & ScriptTypeFlag(scripts[i].type)) {
+      var script = {};
+      if (scripts[i].name) {
+        script.name = scripts[i].name;
+      }
+      script.id = scripts[i].id;
+      script.lineOffset = scripts[i].line_offset;
+      script.columnOffset = scripts[i].column_offset;
+      script.lineCount = scripts[i].lineCount();
+      if (includeSource) {
+        script.source = scripts[i].source;
+      } else {
+        script.sourceStart = scripts[i].source.substring(0, 80);
+      }
+      script.sourceLength = scripts[i].source.length;
+      script.type = scripts[i].type;
+      response.body.push(script);
+    }
+  }
+};
+
+
+DebugCommandProcessor.prototype.threadsRequest_ = function(request, response) {
+  // Get the number of threads.
+  var total_threads = this.exec_state_.threadCount();
+
+  // Get information for all threads.
+  var threads = [];
+  for (var i = 0; i < total_threads; i++) {
+    var details = %GetThreadDetails(this.exec_state_.break_id, i);
+    var thread_info = { current: details[0],
+                        id: details[1]
+                      }
+    threads.push(thread_info);
+  }
+
+  // Create the response body.
+  response.body = {
+    totalThreads: total_threads,
+    threads: threads
+  }
+};
+
+
+// Check whether the previously processed command caused the VM to become
+// running.
+DebugCommandProcessor.prototype.isRunning = function() {
+  return this.running_;
+}
+
+
+DebugCommandProcessor.prototype.systemBreak = function(cmd, args) {
+  return %SystemBreak();
+};
+
+
+function NumberToHex8Str(n) {
+  var r = "";
+  for (var i = 0; i < 8; ++i) {
+    var c = hexCharArray[n & 0x0F];  // hexCharArray is defined in uri.js
+    r = c + r;
+    n = n >>> 4;
+  }
+  return r;
+};
+
+DebugCommandProcessor.prototype.formatCFrames = function(cframes_value) {
+  var result = "";
+  if (cframes_value == null || cframes_value.length == 0) {
+    result += "(stack empty)";
+  } else {
+    for (var i = 0; i < cframes_value.length; ++i) {
+      if (i != 0) result += "\n";
+      result += this.formatCFrame(cframes_value[i]);
+    }
+  }
+  return result;
+};
+
+
+DebugCommandProcessor.prototype.formatCFrame = function(cframe_value) {
+  var result = "";
+  result += "0x" + NumberToHex8Str(cframe_value.address);
+  if (!IS_UNDEFINED(cframe_value.text)) {
+    result += " " + cframe_value.text;
+  }
+  return result;
+}
+
+
+/**
+ * Convert an Object to its JSON representation (see http://www.json.org/).
+ * This implementation simply runs through all string property names and adds
+ * each property to the JSON representation for some predefined types. For type
+ * "object" the function calls itself recursively unless the object has the
+ * function property "toJSONProtocol" in which case that is used. This is not
+ * a general implementation but sufficient for the debugger. Note that circular
+ * structures will cause infinite recursion.
+ * @param {Object} object The object to format as JSON
+ * @param {MirrorSerializer} mirror_serializer The serializer to use if any
+ *     mirror objects are encountered.
+ * @return {string} JSON formatted object value
+ */
+function SimpleObjectToJSON_(object, mirror_serializer) {
+  var content = [];
+  for (var key in object) {
+    // Only consider string keys.
+    if (typeof key == 'string') {
+      var property_value = object[key];
+
+      // Format the value based on its type.
+      var property_value_json;
+      switch (typeof property_value) {
+        case 'object':
+          if (property_value instanceof Mirror) {
+            property_value_json = mirror_serializer.serializeValue(property_value);
+          } else if (typeof property_value.toJSONProtocol == 'function') {
+            property_value_json = property_value.toJSONProtocol(true)
+          } else if (IS_ARRAY(property_value)){
+            property_value_json = SimpleArrayToJSON_(property_value, mirror_serializer);
+          } else {
+            property_value_json = SimpleObjectToJSON_(property_value, mirror_serializer);
+          }
+          break;
+
+        case 'boolean':
+          property_value_json = BooleanToJSON_(property_value);
+          break;
+
+        case 'number':
+          property_value_json = NumberToJSON_(property_value);
+          break;
+
+        case 'string':
+          property_value_json = StringToJSON_(property_value);
+          break;
+
+        default:
+          property_value_json = null;
+      }
+
+      // Add the property if relevant.
+      if (property_value_json) {
+        content.push(StringToJSON_(key) + ':' + property_value_json);
+      }
+    }
+  }
+
+  // Make JSON object representation.
+  return '{' + content.join(',') + '}';
+}
+
+/**
+ * Convert an array to its JSON representation. This is a VERY simple
+ * implementation just to support what is needed for the debugger.
+ * @param {Array} array The array to format as JSON
+ * @param {MirrorSerializer} mirror_serializer The serializer to use if any
+ *     mirror objects are encountered.
+ * @return {string} JSON formatted array value
+ */
+function SimpleArrayToJSON_(array, mirror_serializer) {
+  // Make JSON array representation.
+  var json = '[';
+  for (var i = 0; i < array.length; i++) {
+    if (i != 0) {
+      json += ',';
+    }
+    var elem = array[i];
+    if (elem instanceof Mirror) {
+      json += mirror_serializer.serializeValue(elem);
+    } else if (IS_OBJECT(elem))  {
+      json += SimpleObjectToJSON_(elem);
+    } else if (IS_BOOLEAN(elem)) {
+      json += BooleanToJSON_(elem);
+    } else if (IS_NUMBER(elem)) {
+      json += NumberToJSON_(elem);
+    } else if (IS_STRING(elem)) {
+      json += StringToJSON_(elem);
+    } else {
+      json += elem;
+    }
+  }
+  json += ']';
+  return json;
+}
diff --git a/deps/v8/src/debug-ia32.cc b/deps/v8/src/debug-ia32.cc
new file mode 100644
index 0000000..6d59889
--- /dev/null
+++ b/deps/v8/src/debug-ia32.cc
@@ -0,0 +1,218 @@
+// 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.
+
+#include "v8.h"
+
+#include "codegen-inl.h"
+#include "debug.h"
+
+
+namespace v8 { namespace internal {
+
+
+// A debug break in the frame exit code is identified by a call instruction.
+bool BreakLocationIterator::IsDebugBreakAtReturn() {
+  // Opcode E8 is call.
+  return Debug::IsDebugBreakAtReturn(rinfo());
+}
+
+
+// Patch the JS frame exit code with a debug break call. See
+// CodeGenerator::VisitReturnStatement and VirtualFrame::Exit in codegen-ia32.cc
+// for the precise return instructions sequence.
+void BreakLocationIterator::SetDebugBreakAtReturn() {
+  ASSERT(Debug::kIa32JSReturnSequenceLength >=
+         Debug::kIa32CallInstructionLength);
+  rinfo()->PatchCodeWithCall(Debug::debug_break_return_entry()->entry(),
+      Debug::kIa32JSReturnSequenceLength - Debug::kIa32CallInstructionLength);
+}
+
+
+// Restore the JS frame exit code.
+void BreakLocationIterator::ClearDebugBreakAtReturn() {
+  rinfo()->PatchCode(original_rinfo()->pc(),
+                     Debug::kIa32JSReturnSequenceLength);
+}
+
+
+// Check whether the JS frame exit code has been patched with a debug break.
+bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) {
+  ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()));
+  // Opcode E8 is call.
+  return (*(rinfo->pc()) == 0xE8);
+}
+
+
+#define __ masm->
+
+
+static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
+                                          RegList pointer_regs,
+                                          bool convert_call_to_jmp) {
+  // Save the content of all general purpose registers in memory. This copy in
+  // memory is later pushed onto the JS expression stack for the fake JS frame
+  // generated and also to the C frame generated on top of that. In the JS
+  // frame ONLY the registers containing pointers will be pushed on the
+  // expression stack. This causes the GC to update these pointers so that
+  // they will have the correct value when returning from the debugger.
+  __ SaveRegistersToMemory(kJSCallerSaved);
+
+  // Enter an internal frame.
+  __ EnterInternalFrame();
+
+  // Store the registers containing object pointers on the expression stack to
+  // make sure that these are correctly updated during GC.
+  __ PushRegistersFromMemory(pointer_regs);
+
+#ifdef DEBUG
+  __ RecordComment("// Calling from debug break to runtime - come in - over");
+#endif
+  __ Set(eax, Immediate(0));  // no arguments
+  __ mov(ebx, Immediate(ExternalReference::debug_break()));
+
+  CEntryDebugBreakStub ceb;
+  __ CallStub(&ceb);
+
+  // Restore the register values containing object pointers from the expression
+  // stack in the reverse order as they where pushed.
+  __ PopRegistersToMemory(pointer_regs);
+
+  // Get rid of the internal frame.
+  __ LeaveInternalFrame();
+
+  // If this call did not replace a call but patched other code then there will
+  // be an unwanted return address left on the stack. Here we get rid of that.
+  if (convert_call_to_jmp) {
+    __ pop(eax);
+  }
+
+  // Finally restore all registers.
+  __ RestoreRegistersFromMemory(kJSCallerSaved);
+
+  // Now that the break point has been handled, resume normal execution by
+  // jumping to the target address intended by the caller and that was
+  // overwritten by the address of DebugBreakXXX.
+  ExternalReference after_break_target =
+      ExternalReference(Debug_Address::AfterBreakTarget());
+  __ jmp(Operand::StaticVariable(after_break_target));
+}
+
+
+void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
+  // Register state for IC load call (from ic-ia32.cc).
+  // ----------- S t a t e -------------
+  //  -- ecx    : name
+  // -----------------------------------
+  Generate_DebugBreakCallHelper(masm, ecx.bit(), false);
+}
+
+
+void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) {
+  // REgister state for IC store call (from ic-ia32.cc).
+  // ----------- S t a t e -------------
+  //  -- eax    : value
+  //  -- ecx    : name
+  // -----------------------------------
+  Generate_DebugBreakCallHelper(masm, eax.bit() | ecx.bit(), false);
+}
+
+
+void Debug::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
+  // Register state for keyed IC load call (from ic-ia32.cc).
+  // ----------- S t a t e -------------
+  //  No registers used on entry.
+  // -----------------------------------
+  Generate_DebugBreakCallHelper(masm, 0, false);
+}
+
+
+void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
+  // Register state for keyed IC load call (from ic-ia32.cc).
+  // ----------- S t a t e -------------
+  //  -- eax    : value
+  // -----------------------------------
+  // Register eax contains an object that needs to be pushed on the
+  // expression stack of the fake JS frame.
+  Generate_DebugBreakCallHelper(masm, eax.bit(), false);
+}
+
+
+void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) {
+  // Register state for keyed IC call call (from ic-ia32.cc)
+  // ----------- S t a t e -------------
+  //  -- eax: number of arguments
+  // -----------------------------------
+  // The number of arguments in eax is not smi encoded.
+  Generate_DebugBreakCallHelper(masm, 0, false);
+}
+
+
+void Debug::GenerateConstructCallDebugBreak(MacroAssembler* masm) {
+  // Register state just before return from JS function (from codegen-ia32.cc).
+  // eax is the actual number of arguments not encoded as a smi see comment
+  // above IC call.
+  // ----------- S t a t e -------------
+  //  -- eax: number of arguments
+  // -----------------------------------
+  // The number of arguments in eax is not smi encoded.
+  Generate_DebugBreakCallHelper(masm, 0, false);
+}
+
+
+void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) {
+  // Register state just before return from JS function (from codegen-ia32.cc).
+  // ----------- S t a t e -------------
+  //  -- eax: return value
+  // -----------------------------------
+  Generate_DebugBreakCallHelper(masm, eax.bit(), true);
+}
+
+
+void Debug::GenerateReturnDebugBreakEntry(MacroAssembler* masm) {
+  // OK to clobber ebx as we are returning from a JS function in the code
+  // generated by Ia32CodeGenerator::ExitJSFrame.
+  ExternalReference debug_break_return =
+      ExternalReference(Debug_Address::DebugBreakReturn());
+  __ mov(ebx, Operand::StaticVariable(debug_break_return));
+  __ add(Operand(ebx), Immediate(Code::kHeaderSize - kHeapObjectTag));
+  __ jmp(Operand(ebx));
+}
+
+
+void Debug::GenerateStubNoRegistersDebugBreak(MacroAssembler* masm) {
+  // Register state for stub CallFunction (from CallFunctionStub in ic-ia32.cc).
+  // ----------- S t a t e -------------
+  //  No registers used on entry.
+  // -----------------------------------
+  Generate_DebugBreakCallHelper(masm, 0, false);
+}
+
+
+#undef __
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/debug.cc b/deps/v8/src/debug.cc
new file mode 100644
index 0000000..a4bb04d
--- /dev/null
+++ b/deps/v8/src/debug.cc
@@ -0,0 +1,2227 @@
+// 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.
+
+#include "v8.h"
+
+#include "api.h"
+#include "arguments.h"
+#include "bootstrapper.h"
+#include "code-stubs.h"
+#include "compiler.h"
+#include "debug.h"
+#include "execution.h"
+#include "global-handles.h"
+#include "natives.h"
+#include "stub-cache.h"
+#include "log.h"
+
+namespace v8 { namespace internal {
+
+static void PrintLn(v8::Local<v8::Value> value) {
+  v8::Local<v8::String> s = value->ToString();
+  char* data = NewArray<char>(s->Length() + 1);
+  if (data == NULL) {
+    V8::FatalProcessOutOfMemory("PrintLn");
+    return;
+  }
+  s->WriteAscii(data);
+  PrintF("%s\n", data);
+  DeleteArray(data);
+}
+
+
+static Handle<Code> ComputeCallDebugBreak(int argc) {
+  CALL_HEAP_FUNCTION(StubCache::ComputeCallDebugBreak(argc), Code);
+}
+
+
+static Handle<Code> ComputeCallDebugPrepareStepIn(int argc) {
+  CALL_HEAP_FUNCTION(StubCache::ComputeCallDebugPrepareStepIn(argc), Code);
+}
+
+
+BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info,
+                                             BreakLocatorType type) {
+  debug_info_ = debug_info;
+  type_ = type;
+  reloc_iterator_ = NULL;
+  reloc_iterator_original_ = NULL;
+  Reset();  // Initialize the rest of the member variables.
+}
+
+
+BreakLocationIterator::~BreakLocationIterator() {
+  ASSERT(reloc_iterator_ != NULL);
+  ASSERT(reloc_iterator_original_ != NULL);
+  delete reloc_iterator_;
+  delete reloc_iterator_original_;
+}
+
+
+void BreakLocationIterator::Next() {
+  AssertNoAllocation nogc;
+  ASSERT(!RinfoDone());
+
+  // Iterate through reloc info for code and original code stopping at each
+  // breakable code target.
+  bool first = break_point_ == -1;
+  while (!RinfoDone()) {
+    if (!first) RinfoNext();
+    first = false;
+    if (RinfoDone()) return;
+
+    // Whenever a statement position or (plain) position is passed update the
+    // current value of these.
+    if (RelocInfo::IsPosition(rmode())) {
+      if (RelocInfo::IsStatementPosition(rmode())) {
+        statement_position_ =
+            rinfo()->data() - debug_info_->shared()->start_position();
+      }
+      // Always update the position as we don't want that to be before the
+      // statement position.
+      position_ = rinfo()->data() - debug_info_->shared()->start_position();
+      ASSERT(position_ >= 0);
+      ASSERT(statement_position_ >= 0);
+    }
+
+    // Check for breakable code target. Look in the original code as setting
+    // break points can cause the code targets in the running (debugged) code to
+    // be of a different kind than in the original code.
+    if (RelocInfo::IsCodeTarget(rmode())) {
+      Address target = original_rinfo()->target_address();
+      Code* code = Code::GetCodeFromTargetAddress(target);
+      if (code->is_inline_cache_stub() || RelocInfo::IsConstructCall(rmode())) {
+        break_point_++;
+        return;
+      }
+      if (code->kind() == Code::STUB) {
+        if (type_ == ALL_BREAK_LOCATIONS) {
+          if (Debug::IsBreakStub(code)) {
+            break_point_++;
+            return;
+          }
+        } else {
+          ASSERT(type_ == SOURCE_BREAK_LOCATIONS);
+          if (Debug::IsSourceBreakStub(code)) {
+            break_point_++;
+            return;
+          }
+        }
+      }
+    }
+
+    // Check for break at return.
+    if (RelocInfo::IsJSReturn(rmode())) {
+      // Set the positions to the end of the function.
+      if (debug_info_->shared()->HasSourceCode()) {
+        position_ = debug_info_->shared()->end_position() -
+                    debug_info_->shared()->start_position();
+      } else {
+        position_ = 0;
+      }
+      statement_position_ = position_;
+      break_point_++;
+      return;
+    }
+  }
+}
+
+
+void BreakLocationIterator::Next(int count) {
+  while (count > 0) {
+    Next();
+    count--;
+  }
+}
+
+
+// Find the break point closest to the supplied address.
+void BreakLocationIterator::FindBreakLocationFromAddress(Address pc) {
+  // Run through all break points to locate the one closest to the address.
+  int closest_break_point = 0;
+  int distance = kMaxInt;
+  while (!Done()) {
+    // Check if this break point is closer that what was previously found.
+    if (this->pc() < pc && pc - this->pc() < distance) {
+      closest_break_point = break_point();
+      distance = pc - this->pc();
+      // Check whether we can't get any closer.
+      if (distance == 0) break;
+    }
+    Next();
+  }
+
+  // Move to the break point found.
+  Reset();
+  Next(closest_break_point);
+}
+
+
+// Find the break point closest to the supplied source position.
+void BreakLocationIterator::FindBreakLocationFromPosition(int position) {
+  // Run through all break points to locate the one closest to the source
+  // position.
+  int closest_break_point = 0;
+  int distance = kMaxInt;
+  while (!Done()) {
+    // Check if this break point is closer that what was previously found.
+    if (position <= statement_position() &&
+        statement_position() - position < distance) {
+      closest_break_point = break_point();
+      distance = statement_position() - position;
+      // Check whether we can't get any closer.
+      if (distance == 0) break;
+    }
+    Next();
+  }
+
+  // Move to the break point found.
+  Reset();
+  Next(closest_break_point);
+}
+
+
+void BreakLocationIterator::Reset() {
+  // Create relocation iterators for the two code objects.
+  if (reloc_iterator_ != NULL) delete reloc_iterator_;
+  if (reloc_iterator_original_ != NULL) delete reloc_iterator_original_;
+  reloc_iterator_ = new RelocIterator(debug_info_->code());
+  reloc_iterator_original_ = new RelocIterator(debug_info_->original_code());
+
+  // Position at the first break point.
+  break_point_ = -1;
+  position_ = 1;
+  statement_position_ = 1;
+  Next();
+}
+
+
+bool BreakLocationIterator::Done() const {
+  return RinfoDone();
+}
+
+
+void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) {
+  // If there is not already a real break point here patch code with debug
+  // break.
+  if (!HasBreakPoint()) {
+    SetDebugBreak();
+  }
+  ASSERT(IsDebugBreak());
+  // Set the break point information.
+  DebugInfo::SetBreakPoint(debug_info_, code_position(),
+                           position(), statement_position(),
+                           break_point_object);
+}
+
+
+void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) {
+  // Clear the break point information.
+  DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object);
+  // If there are no more break points here remove the debug break.
+  if (!HasBreakPoint()) {
+    ClearDebugBreak();
+    ASSERT(!IsDebugBreak());
+  }
+}
+
+
+void BreakLocationIterator::SetOneShot() {
+  // If there is a real break point here no more to do.
+  if (HasBreakPoint()) {
+    ASSERT(IsDebugBreak());
+    return;
+  }
+
+  // Patch code with debug break.
+  SetDebugBreak();
+}
+
+
+void BreakLocationIterator::ClearOneShot() {
+  // If there is a real break point here no more to do.
+  if (HasBreakPoint()) {
+    ASSERT(IsDebugBreak());
+    return;
+  }
+
+  // Patch code removing debug break.
+  ClearDebugBreak();
+  ASSERT(!IsDebugBreak());
+}
+
+
+void BreakLocationIterator::SetDebugBreak() {
+  // If there is already a break point here just return. This might happen if
+  // the same code is flooded with break points twice. Flooding the same
+  // function twice might happen when stepping in a function with an exception
+  // handler as the handler and the function is the same.
+  if (IsDebugBreak()) {
+    return;
+  }
+
+  if (RelocInfo::IsJSReturn(rmode())) {
+    // Patch the frame exit code with a break point.
+    SetDebugBreakAtReturn();
+  } else {
+    // Patch the original code with the current address as the current address
+    // might have changed by the inline caching since the code was copied.
+    original_rinfo()->set_target_address(rinfo()->target_address());
+
+    // Patch the code to invoke the builtin debug break function matching the
+    // calling convention used by the call site.
+    Handle<Code> dbgbrk_code(Debug::FindDebugBreak(rinfo()));
+    rinfo()->set_target_address(dbgbrk_code->entry());
+  }
+  ASSERT(IsDebugBreak());
+}
+
+
+void BreakLocationIterator::ClearDebugBreak() {
+  if (RelocInfo::IsJSReturn(rmode())) {
+    // Restore the frame exit code.
+    ClearDebugBreakAtReturn();
+  } else {
+    // Patch the code to the original invoke.
+    rinfo()->set_target_address(original_rinfo()->target_address());
+  }
+  ASSERT(!IsDebugBreak());
+}
+
+
+void BreakLocationIterator::PrepareStepIn() {
+  HandleScope scope;
+
+  // Step in can only be prepared if currently positioned on an IC call or
+  // construct call.
+  Address target = rinfo()->target_address();
+  Code* code = Code::GetCodeFromTargetAddress(target);
+  if (code->is_call_stub()) {
+    // Step in through IC call is handled by the runtime system. Therefore make
+    // sure that the any current IC is cleared and the runtime system is
+    // called. If the executing code has a debug break at the location change
+    // the call in the original code as it is the code there that will be
+    // executed in place of the debug break call.
+    Handle<Code> stub = ComputeCallDebugPrepareStepIn(code->arguments_count());
+    if (IsDebugBreak()) {
+      original_rinfo()->set_target_address(stub->entry());
+    } else {
+      rinfo()->set_target_address(stub->entry());
+    }
+  } else {
+    // Step in through constructs call requires no changes to the running code.
+    ASSERT(RelocInfo::IsConstructCall(rmode()));
+  }
+}
+
+
+// Check whether the break point is at a position which will exit the function.
+bool BreakLocationIterator::IsExit() const {
+  return (RelocInfo::IsJSReturn(rmode()));
+}
+
+
+bool BreakLocationIterator::HasBreakPoint() {
+  return debug_info_->HasBreakPoint(code_position());
+}
+
+
+// Check whether there is a debug break at the current position.
+bool BreakLocationIterator::IsDebugBreak() {
+  if (RelocInfo::IsJSReturn(rmode())) {
+    return IsDebugBreakAtReturn();
+  } else {
+    return Debug::IsDebugBreak(rinfo()->target_address());
+  }
+}
+
+
+Object* BreakLocationIterator::BreakPointObjects() {
+  return debug_info_->GetBreakPointObjects(code_position());
+}
+
+
+// Clear out all the debug break code. This is ONLY supposed to be used when
+// shutting down the debugger as it will leave the break point information in
+// DebugInfo even though the code is patched back to the non break point state.
+void BreakLocationIterator::ClearAllDebugBreak() {
+  while (!Done()) {
+    ClearDebugBreak();
+    Next();
+  }
+}
+
+
+bool BreakLocationIterator::RinfoDone() const {
+  ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
+  return reloc_iterator_->done();
+}
+
+
+void BreakLocationIterator::RinfoNext() {
+  reloc_iterator_->next();
+  reloc_iterator_original_->next();
+#ifdef DEBUG
+  ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
+  if (!reloc_iterator_->done()) {
+    ASSERT(rmode() == original_rmode());
+  }
+#endif
+}
+
+
+bool Debug::has_break_points_ = false;
+DebugInfoListNode* Debug::debug_info_list_ = NULL;
+
+
+// Threading support.
+void Debug::ThreadInit() {
+  thread_local_.break_count_ = 0;
+  thread_local_.break_id_ = 0;
+  thread_local_.break_frame_id_ = StackFrame::NO_ID;
+  thread_local_.last_step_action_ = StepNone;
+  thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
+  thread_local_.step_count_ = 0;
+  thread_local_.last_fp_ = 0;
+  thread_local_.step_into_fp_ = 0;
+  thread_local_.after_break_target_ = 0;
+  thread_local_.debugger_entry_ = NULL;
+  thread_local_.preemption_pending_ = false;
+}
+
+
+JSCallerSavedBuffer Debug::registers_;
+Debug::ThreadLocal Debug::thread_local_;
+
+
+char* Debug::ArchiveDebug(char* storage) {
+  char* to = storage;
+  memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
+  to += sizeof(ThreadLocal);
+  memcpy(to, reinterpret_cast<char*>(&registers_), sizeof(registers_));
+  ThreadInit();
+  ASSERT(to <= storage + ArchiveSpacePerThread());
+  return storage + ArchiveSpacePerThread();
+}
+
+
+char* Debug::RestoreDebug(char* storage) {
+  char* from = storage;
+  memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
+  from += sizeof(ThreadLocal);
+  memcpy(reinterpret_cast<char*>(&registers_), from, sizeof(registers_));
+  ASSERT(from <= storage + ArchiveSpacePerThread());
+  return storage + ArchiveSpacePerThread();
+}
+
+
+int Debug::ArchiveSpacePerThread() {
+  return sizeof(ThreadLocal) + sizeof(registers_);
+}
+
+
+// Default break enabled.
+bool Debug::disable_break_ = false;
+
+// Default call debugger on uncaught exception.
+bool Debug::break_on_exception_ = false;
+bool Debug::break_on_uncaught_exception_ = true;
+
+Handle<Context> Debug::debug_context_ = Handle<Context>();
+Code* Debug::debug_break_return_entry_ = NULL;
+Code* Debug::debug_break_return_ = NULL;
+
+
+void Debug::HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data) {
+  DebugInfoListNode* node = reinterpret_cast<DebugInfoListNode*>(data);
+  RemoveDebugInfo(node->debug_info());
+#ifdef DEBUG
+  node = Debug::debug_info_list_;
+  while (node != NULL) {
+    ASSERT(node != reinterpret_cast<DebugInfoListNode*>(data));
+    node = node->next();
+  }
+#endif
+}
+
+
+DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
+  // Globalize the request debug info object and make it weak.
+  debug_info_ = Handle<DebugInfo>::cast((GlobalHandles::Create(debug_info)));
+  GlobalHandles::MakeWeak(reinterpret_cast<Object**>(debug_info_.location()),
+                          this, Debug::HandleWeakDebugInfo);
+}
+
+
+DebugInfoListNode::~DebugInfoListNode() {
+  GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_.location()));
+}
+
+
+void Debug::Setup(bool create_heap_objects) {
+  ThreadInit();
+  if (create_heap_objects) {
+    // Get code to handle entry to debug break on return.
+    debug_break_return_entry_ =
+        Builtins::builtin(Builtins::Return_DebugBreakEntry);
+    ASSERT(debug_break_return_entry_->IsCode());
+
+    // Get code to handle debug break on return.
+    debug_break_return_ =
+        Builtins::builtin(Builtins::Return_DebugBreak);
+    ASSERT(debug_break_return_->IsCode());
+  }
+}
+
+
+bool Debug::CompileDebuggerScript(int index) {
+  HandleScope scope;
+
+  // Bail out if the index is invalid.
+  if (index == -1) {
+    return false;
+  }
+
+  // Find source and name for the requested script.
+  Handle<String> source_code = Bootstrapper::NativesSourceLookup(index);
+  Vector<const char> name = Natives::GetScriptName(index);
+  Handle<String> script_name = Factory::NewStringFromAscii(name);
+
+  // Compile the script.
+  bool allow_natives_syntax = FLAG_allow_natives_syntax;
+  FLAG_allow_natives_syntax = true;
+  Handle<JSFunction> boilerplate;
+  boilerplate = Compiler::Compile(source_code, script_name, 0, 0, NULL, NULL);
+  FLAG_allow_natives_syntax = allow_natives_syntax;
+
+  // Silently ignore stack overflows during compilation.
+  if (boilerplate.is_null()) {
+    ASSERT(Top::has_pending_exception());
+    Top::clear_pending_exception();
+    return false;
+  }
+
+  // Execute the boilerplate function in the debugger context.
+  Handle<Context> context = Top::global_context();
+  bool caught_exception = false;
+  Handle<JSFunction> function =
+      Factory::NewFunctionFromBoilerplate(boilerplate, context);
+  Handle<Object> result =
+      Execution::TryCall(function, Handle<Object>(context->global()),
+                         0, NULL, &caught_exception);
+
+  // Check for caught exceptions.
+  if (caught_exception) {
+    Handle<Object> message = MessageHandler::MakeMessageObject(
+        "error_loading_debugger", NULL, HandleVector<Object>(&result, 1),
+        Handle<String>());
+    MessageHandler::ReportMessage(NULL, message);
+    return false;
+  }
+
+  // Mark this script as native and return successfully.
+  Handle<Script> script(Script::cast(function->shared()->script()));
+  script->set_type(Smi::FromInt(SCRIPT_TYPE_NATIVE));
+  return true;
+}
+
+
+bool Debug::Load() {
+  // Return if debugger is already loaded.
+  if (IsLoaded()) return true;
+
+  // Bail out if we're already in the process of compiling the native
+  // JavaScript source code for the debugger.
+  if (Debugger::compiling_natives() || Debugger::is_loading_debugger())
+    return false;
+  Debugger::set_loading_debugger(true);
+
+  // Disable breakpoints and interrupts while compiling and running the
+  // debugger scripts including the context creation code.
+  DisableBreak disable(true);
+  PostponeInterruptsScope postpone;
+
+  // Create the debugger context.
+  HandleScope scope;
+  Handle<Context> context =
+      Bootstrapper::CreateEnvironment(Handle<Object>::null(),
+                                      v8::Handle<ObjectTemplate>(),
+                                      NULL);
+
+  // Use the debugger context.
+  SaveContext save;
+  Top::set_context(*context);
+
+  // Expose the builtins object in the debugger context.
+  Handle<String> key = Factory::LookupAsciiSymbol("builtins");
+  Handle<GlobalObject> global = Handle<GlobalObject>(context->global());
+  SetProperty(global, key, Handle<Object>(global->builtins()), NONE);
+
+  // Compile the JavaScript for the debugger in the debugger context.
+  Debugger::set_compiling_natives(true);
+  bool caught_exception =
+      !CompileDebuggerScript(Natives::GetIndex("mirror")) ||
+      !CompileDebuggerScript(Natives::GetIndex("debug"));
+  Debugger::set_compiling_natives(false);
+
+  // Make sure we mark the debugger as not loading before we might
+  // return.
+  Debugger::set_loading_debugger(false);
+
+  // Check for caught exceptions.
+  if (caught_exception) return false;
+
+  // Debugger loaded.
+  debug_context_ = Handle<Context>::cast(GlobalHandles::Create(*context));
+  return true;
+}
+
+
+void Debug::Unload() {
+  // Return debugger is not loaded.
+  if (!IsLoaded()) {
+    return;
+  }
+
+  // Clear debugger context global handle.
+  GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location()));
+  debug_context_ = Handle<Context>();
+}
+
+
+// Set the flag indicating that preemption happened during debugging.
+void Debug::PreemptionWhileInDebugger() {
+  ASSERT(InDebugger());
+  Debug::set_preemption_pending(true);
+}
+
+
+void Debug::Iterate(ObjectVisitor* v) {
+  v->VisitPointer(bit_cast<Object**, Code**>(&(debug_break_return_entry_)));
+  v->VisitPointer(bit_cast<Object**, Code**>(&(debug_break_return_)));
+}
+
+
+Object* Debug::Break(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 0);
+
+  // Get the top-most JavaScript frame.
+  JavaScriptFrameIterator it;
+  JavaScriptFrame* frame = it.frame();
+
+  // Just continue if breaks are disabled or debugger cannot be loaded.
+  if (disable_break() || !Load()) {
+    SetAfterBreakTarget(frame);
+    return Heap::undefined_value();
+  }
+
+  // Enter the debugger.
+  EnterDebugger debugger;
+  if (debugger.FailedToEnter()) {
+    return Heap::undefined_value();
+  }
+
+  // Postpone interrupt during breakpoint processing.
+  PostponeInterruptsScope postpone;
+
+  // Get the debug info (create it if it does not exist).
+  Handle<SharedFunctionInfo> shared =
+      Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared());
+  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
+
+  // Find the break point where execution has stopped.
+  BreakLocationIterator break_location_iterator(debug_info,
+                                                ALL_BREAK_LOCATIONS);
+  break_location_iterator.FindBreakLocationFromAddress(frame->pc());
+
+  // Check whether step next reached a new statement.
+  if (!StepNextContinue(&break_location_iterator, frame)) {
+    // Decrease steps left if performing multiple steps.
+    if (thread_local_.step_count_ > 0) {
+      thread_local_.step_count_--;
+    }
+  }
+
+  // If there is one or more real break points check whether any of these are
+  // triggered.
+  Handle<Object> break_points_hit(Heap::undefined_value());
+  if (break_location_iterator.HasBreakPoint()) {
+    Handle<Object> break_point_objects =
+        Handle<Object>(break_location_iterator.BreakPointObjects());
+    break_points_hit = CheckBreakPoints(break_point_objects);
+  }
+
+  // Notify debugger if a real break point is triggered or if performing single
+  // stepping with no more steps to perform. Otherwise do another step.
+  if (!break_points_hit->IsUndefined() ||
+    (thread_local_.last_step_action_ != StepNone &&
+     thread_local_.step_count_ == 0)) {
+    // Clear all current stepping setup.
+    ClearStepping();
+
+    // Notify the debug event listeners.
+    Debugger::OnDebugBreak(break_points_hit, false);
+  } else if (thread_local_.last_step_action_ != StepNone) {
+    // Hold on to last step action as it is cleared by the call to
+    // ClearStepping.
+    StepAction step_action = thread_local_.last_step_action_;
+    int step_count = thread_local_.step_count_;
+
+    // Clear all current stepping setup.
+    ClearStepping();
+
+    // Set up for the remaining steps.
+    PrepareStep(step_action, step_count);
+  }
+
+  // Install jump to the call address which was overwritten.
+  SetAfterBreakTarget(frame);
+
+  return Heap::undefined_value();
+}
+
+
+// Check the break point objects for whether one or more are actually
+// triggered. This function returns a JSArray with the break point objects
+// which is triggered.
+Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) {
+  int break_points_hit_count = 0;
+  Handle<JSArray> break_points_hit = Factory::NewJSArray(1);
+
+  // If there are multiple break points they are in a FixedArray.
+  ASSERT(!break_point_objects->IsUndefined());
+  if (break_point_objects->IsFixedArray()) {
+    Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
+    for (int i = 0; i < array->length(); i++) {
+      Handle<Object> o(array->get(i));
+      if (CheckBreakPoint(o)) {
+        break_points_hit->SetElement(break_points_hit_count++, *o);
+      }
+    }
+  } else {
+    if (CheckBreakPoint(break_point_objects)) {
+      break_points_hit->SetElement(break_points_hit_count++,
+                                   *break_point_objects);
+    }
+  }
+
+  // Return undefined if no break points where triggered.
+  if (break_points_hit_count == 0) {
+    return Factory::undefined_value();
+  }
+  return break_points_hit;
+}
+
+
+// Check whether a single break point object is triggered.
+bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
+  HandleScope scope;
+
+  // Ignore check if break point object is not a JSObject.
+  if (!break_point_object->IsJSObject()) return true;
+
+  // Get the function CheckBreakPoint (defined in debug.js).
+  Handle<JSFunction> check_break_point =
+    Handle<JSFunction>(JSFunction::cast(
+      debug_context()->global()->GetProperty(
+          *Factory::LookupAsciiSymbol("IsBreakPointTriggered"))));
+
+  // Get the break id as an object.
+  Handle<Object> break_id = Factory::NewNumberFromInt(Debug::break_id());
+
+  // Call HandleBreakPointx.
+  bool caught_exception = false;
+  const int argc = 2;
+  Object** argv[argc] = {
+    break_id.location(),
+    reinterpret_cast<Object**>(break_point_object.location())
+  };
+  Handle<Object> result = Execution::TryCall(check_break_point,
+                                             Top::builtins(), argc, argv,
+                                             &caught_exception);
+
+  // If exception or non boolean result handle as not triggered
+  if (caught_exception || !result->IsBoolean()) {
+    return false;
+  }
+
+  // Return whether the break point is triggered.
+  return *result == Heap::true_value();
+}
+
+
+// Check whether the function has debug information.
+bool Debug::HasDebugInfo(Handle<SharedFunctionInfo> shared) {
+  return !shared->debug_info()->IsUndefined();
+}
+
+
+// Return the debug info for this function. EnsureDebugInfo must be called
+// prior to ensure the debug info has been generated for shared.
+Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) {
+  ASSERT(HasDebugInfo(shared));
+  return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info()));
+}
+
+
+void Debug::SetBreakPoint(Handle<SharedFunctionInfo> shared,
+                          int source_position,
+                          Handle<Object> break_point_object) {
+  HandleScope scope;
+
+  if (!EnsureDebugInfo(shared)) {
+    // Return if retrieving debug info failed.
+    return;
+  }
+
+  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
+  // Source positions starts with zero.
+  ASSERT(source_position >= 0);
+
+  // Find the break point and change it.
+  BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
+  it.FindBreakLocationFromPosition(source_position);
+  it.SetBreakPoint(break_point_object);
+
+  // At least one active break point now.
+  ASSERT(debug_info->GetBreakPointCount() > 0);
+}
+
+
+void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
+  HandleScope scope;
+
+  DebugInfoListNode* node = debug_info_list_;
+  while (node != NULL) {
+    Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(),
+                                                   break_point_object);
+    if (!result->IsUndefined()) {
+      // Get information in the break point.
+      BreakPointInfo* break_point_info = BreakPointInfo::cast(result);
+      Handle<DebugInfo> debug_info = node->debug_info();
+      Handle<SharedFunctionInfo> shared(debug_info->shared());
+      int source_position =  break_point_info->statement_position()->value();
+
+      // Source positions starts with zero.
+      ASSERT(source_position >= 0);
+
+      // Find the break point and clear it.
+      BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
+      it.FindBreakLocationFromPosition(source_position);
+      it.ClearBreakPoint(break_point_object);
+
+      // If there are no more break points left remove the debug info for this
+      // function.
+      if (debug_info->GetBreakPointCount() == 0) {
+        RemoveDebugInfo(debug_info);
+      }
+
+      return;
+    }
+    node = node->next();
+  }
+}
+
+
+void Debug::ClearAllBreakPoints() {
+  DebugInfoListNode* node = debug_info_list_;
+  while (node != NULL) {
+    // Remove all debug break code.
+    BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
+    it.ClearAllDebugBreak();
+    node = node->next();
+  }
+
+  // Remove all debug info.
+  while (debug_info_list_ != NULL) {
+    RemoveDebugInfo(debug_info_list_->debug_info());
+  }
+}
+
+
+void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared) {
+  // Make sure the function has setup the debug info.
+  if (!EnsureDebugInfo(shared)) {
+    // Return if we failed to retrieve the debug info.
+    return;
+  }
+
+  // Flood the function with break points.
+  BreakLocationIterator it(GetDebugInfo(shared), ALL_BREAK_LOCATIONS);
+  while (!it.Done()) {
+    it.SetOneShot();
+    it.Next();
+  }
+}
+
+
+void Debug::FloodHandlerWithOneShot() {
+  // Iterate through the JavaScript stack looking for handlers.
+  StackFrame::Id id = break_frame_id();
+  if (id == StackFrame::NO_ID) {
+    // If there is no JavaScript stack don't do anything.
+    return;
+  }
+  for (JavaScriptFrameIterator it(id); !it.done(); it.Advance()) {
+    JavaScriptFrame* frame = it.frame();
+    if (frame->HasHandler()) {
+      Handle<SharedFunctionInfo> shared =
+          Handle<SharedFunctionInfo>(
+              JSFunction::cast(frame->function())->shared());
+      // Flood the function with the catch block with break points
+      FloodWithOneShot(shared);
+      return;
+    }
+  }
+}
+
+
+void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
+  if (type == BreakUncaughtException) {
+    break_on_uncaught_exception_ = enable;
+  } else {
+    break_on_exception_ = enable;
+  }
+}
+
+
+void Debug::PrepareStep(StepAction step_action, int step_count) {
+  HandleScope scope;
+  ASSERT(Debug::InDebugger());
+
+  // Remember this step action and count.
+  thread_local_.last_step_action_ = step_action;
+  thread_local_.step_count_ = step_count;
+
+  // Get the frame where the execution has stopped and skip the debug frame if
+  // any. The debug frame will only be present if execution was stopped due to
+  // hitting a break point. In other situations (e.g. unhandled exception) the
+  // debug frame is not present.
+  StackFrame::Id id = break_frame_id();
+  if (id == StackFrame::NO_ID) {
+    // If there is no JavaScript stack don't do anything.
+    return;
+  }
+  JavaScriptFrameIterator frames_it(id);
+  JavaScriptFrame* frame = frames_it.frame();
+
+  // First of all ensure there is one-shot break points in the top handler
+  // if any.
+  FloodHandlerWithOneShot();
+
+  // If the function on the top frame is unresolved perform step out. This will
+  // be the case when calling unknown functions and having the debugger stopped
+  // in an unhandled exception.
+  if (!frame->function()->IsJSFunction()) {
+    // Step out: Find the calling JavaScript frame and flood it with
+    // breakpoints.
+    frames_it.Advance();
+    // Fill the function to return to with one-shot break points.
+    JSFunction* function = JSFunction::cast(frames_it.frame()->function());
+    FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared()));
+    return;
+  }
+
+  // Get the debug info (create it if it does not exist).
+  Handle<SharedFunctionInfo> shared =
+      Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared());
+  if (!EnsureDebugInfo(shared)) {
+    // Return if ensuring debug info failed.
+    return;
+  }
+  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
+
+  // Find the break location where execution has stopped.
+  BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
+  it.FindBreakLocationFromAddress(frame->pc());
+
+  // Compute whether or not the target is a call target.
+  bool is_call_target = false;
+  if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) {
+    Address target = it.rinfo()->target_address();
+    Code* code = Code::GetCodeFromTargetAddress(target);
+    if (code->is_call_stub()) is_call_target = true;
+  }
+
+  // If this is the last break code target step out is the only possibility.
+  if (it.IsExit() || step_action == StepOut) {
+    // Step out: If there is a JavaScript caller frame, we need to
+    // flood it with breakpoints.
+    frames_it.Advance();
+    if (!frames_it.done()) {
+      // Fill the function to return to with one-shot break points.
+      JSFunction* function = JSFunction::cast(frames_it.frame()->function());
+      FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared()));
+    }
+  } else if (!(is_call_target || RelocInfo::IsConstructCall(it.rmode())) ||
+             step_action == StepNext || step_action == StepMin) {
+    // Step next or step min.
+
+    // Fill the current function with one-shot break points.
+    FloodWithOneShot(shared);
+
+    // Remember source position and frame to handle step next.
+    thread_local_.last_statement_position_ =
+        debug_info->code()->SourceStatementPosition(frame->pc());
+    thread_local_.last_fp_ = frame->fp();
+  } else {
+    // Fill the current function with one-shot break points even for step in on
+    // a call target as the function called might be a native function for
+    // which step in will not stop.
+    FloodWithOneShot(shared);
+
+    // Step in or Step in min
+    it.PrepareStepIn();
+    ActivateStepIn(frame);
+  }
+}
+
+
+// Check whether the current debug break should be reported to the debugger. It
+// is used to have step next and step in only report break back to the debugger
+// if on a different frame or in a different statement. In some situations
+// there will be several break points in the same statement when the code is
+// flooded with one-shot break points. This function helps to perform several
+// steps before reporting break back to the debugger.
+bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator,
+                             JavaScriptFrame* frame) {
+  // If the step last action was step next or step in make sure that a new
+  // statement is hit.
+  if (thread_local_.last_step_action_ == StepNext ||
+      thread_local_.last_step_action_ == StepIn) {
+    // Never continue if returning from function.
+    if (break_location_iterator->IsExit()) return false;
+
+    // Continue if we are still on the same frame and in the same statement.
+    int current_statement_position =
+        break_location_iterator->code()->SourceStatementPosition(frame->pc());
+    return thread_local_.last_fp_ == frame->fp() &&
+        thread_local_.last_statement_position_ == current_statement_position;
+  }
+
+  // No step next action - don't continue.
+  return false;
+}
+
+
+// Check whether the code object at the specified address is a debug break code
+// object.
+bool Debug::IsDebugBreak(Address addr) {
+  Code* code = Code::GetCodeFromTargetAddress(addr);
+  return code->ic_state() == DEBUG_BREAK;
+}
+
+
+// Check whether a code stub with the specified major key is a possible break
+// point location when looking for source break locations.
+bool Debug::IsSourceBreakStub(Code* code) {
+  CodeStub::Major major_key = code->major_key();
+  return major_key == CodeStub::CallFunction;
+}
+
+
+// Check whether a code stub with the specified major key is a possible break
+// location.
+bool Debug::IsBreakStub(Code* code) {
+  CodeStub::Major major_key = code->major_key();
+  return major_key == CodeStub::CallFunction ||
+         major_key == CodeStub::StackCheck;
+}
+
+
+// Find the builtin to use for invoking the debug break
+Handle<Code> Debug::FindDebugBreak(RelocInfo* rinfo) {
+  // Find the builtin debug break function matching the calling convention
+  // used by the call site.
+  RelocInfo::Mode mode = rinfo->rmode();
+
+  if (RelocInfo::IsCodeTarget(mode)) {
+    Address target = rinfo->target_address();
+    Code* code = Code::GetCodeFromTargetAddress(target);
+    if (code->is_inline_cache_stub()) {
+      if (code->is_call_stub()) {
+        return ComputeCallDebugBreak(code->arguments_count());
+      }
+      if (code->is_load_stub()) {
+        return Handle<Code>(Builtins::builtin(Builtins::LoadIC_DebugBreak));
+      }
+      if (code->is_store_stub()) {
+        return Handle<Code>(Builtins::builtin(Builtins::StoreIC_DebugBreak));
+      }
+      if (code->is_keyed_load_stub()) {
+        Handle<Code> result =
+            Handle<Code>(Builtins::builtin(Builtins::KeyedLoadIC_DebugBreak));
+        return result;
+      }
+      if (code->is_keyed_store_stub()) {
+        Handle<Code> result =
+            Handle<Code>(Builtins::builtin(Builtins::KeyedStoreIC_DebugBreak));
+        return result;
+      }
+    }
+    if (RelocInfo::IsConstructCall(mode)) {
+      Handle<Code> result =
+          Handle<Code>(Builtins::builtin(Builtins::ConstructCall_DebugBreak));
+      return result;
+    }
+    if (code->kind() == Code::STUB) {
+      ASSERT(code->major_key() == CodeStub::CallFunction ||
+             code->major_key() == CodeStub::StackCheck);
+      Handle<Code> result =
+          Handle<Code>(Builtins::builtin(Builtins::StubNoRegisters_DebugBreak));
+      return result;
+    }
+  }
+
+  UNREACHABLE();
+  return Handle<Code>::null();
+}
+
+
+// Simple function for returning the source positions for active break points.
+Handle<Object> Debug::GetSourceBreakLocations(
+    Handle<SharedFunctionInfo> shared) {
+  if (!HasDebugInfo(shared)) return Handle<Object>(Heap::undefined_value());
+  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
+  if (debug_info->GetBreakPointCount() == 0) {
+    return Handle<Object>(Heap::undefined_value());
+  }
+  Handle<FixedArray> locations =
+      Factory::NewFixedArray(debug_info->GetBreakPointCount());
+  int count = 0;
+  for (int i = 0; i < debug_info->break_points()->length(); i++) {
+    if (!debug_info->break_points()->get(i)->IsUndefined()) {
+      BreakPointInfo* break_point_info =
+          BreakPointInfo::cast(debug_info->break_points()->get(i));
+      if (break_point_info->GetBreakPointCount() > 0) {
+        locations->set(count++, break_point_info->statement_position());
+      }
+    }
+  }
+  return locations;
+}
+
+
+void Debug::NewBreak(StackFrame::Id break_frame_id) {
+  thread_local_.break_frame_id_ = break_frame_id;
+  thread_local_.break_id_ = ++thread_local_.break_count_;
+}
+
+
+void Debug::SetBreak(StackFrame::Id break_frame_id, int break_id) {
+  thread_local_.break_frame_id_ = break_frame_id;
+  thread_local_.break_id_ = break_id;
+}
+
+
+// Handle stepping into a function.
+void Debug::HandleStepIn(Handle<JSFunction> function,
+                         Address fp,
+                         bool is_constructor) {
+  // If the frame pointer is not supplied by the caller find it.
+  if (fp == 0) {
+    StackFrameIterator it;
+    it.Advance();
+    // For constructor functions skip another frame.
+    if (is_constructor) {
+      ASSERT(it.frame()->is_construct());
+      it.Advance();
+    }
+    fp = it.frame()->fp();
+  }
+
+  // Flood the function with one-shot break points if it is called from where
+  // step into was requested.
+  if (fp == Debug::step_in_fp()) {
+    // Don't allow step into functions in the native context.
+    if (function->context()->global() != Top::context()->builtins()) {
+      if (function->shared()->code() ==
+          Builtins::builtin(Builtins::FunctionApply) ||
+          function->shared()->code() ==
+          Builtins::builtin(Builtins::FunctionCall)) {
+        // Handle function.apply and function.call separately to flood the
+        // function to be called and not the code for Builtins::FunctionApply or
+        // Builtins::FunctionCall. At the point of the call IC to call either
+        // Builtins::FunctionApply or Builtins::FunctionCall the expression
+        // stack has the following content:
+        //   symbol "apply" or "call"
+        //   function apply or call was called on
+        //   receiver for apply or call (first parameter to apply or call)
+        //   ... further arguments to apply or call.
+        JavaScriptFrameIterator it;
+        ASSERT(it.frame()->fp() == fp);
+        ASSERT(it.frame()->GetExpression(1)->IsJSFunction());
+        if (it.frame()->GetExpression(1)->IsJSFunction()) {
+          Handle<JSFunction>
+              actual_function(JSFunction::cast(it.frame()->GetExpression(1)));
+          Handle<SharedFunctionInfo> actual_shared(actual_function->shared());
+          Debug::FloodWithOneShot(actual_shared);
+        }
+      } else {
+        Debug::FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared()));
+      }
+    }
+  }
+}
+
+
+void Debug::ClearStepping() {
+  // Clear the various stepping setup.
+  ClearOneShot();
+  ClearStepIn();
+  ClearStepNext();
+
+  // Clear multiple step counter.
+  thread_local_.step_count_ = 0;
+}
+
+// Clears all the one-shot break points that are currently set. Normally this
+// function is called each time a break point is hit as one shot break points
+// are used to support stepping.
+void Debug::ClearOneShot() {
+  // The current implementation just runs through all the breakpoints. When the
+  // last break point for a function is removed that function is automatically
+  // removed from the list.
+
+  DebugInfoListNode* node = debug_info_list_;
+  while (node != NULL) {
+    BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
+    while (!it.Done()) {
+      it.ClearOneShot();
+      it.Next();
+    }
+    node = node->next();
+  }
+}
+
+
+void Debug::ActivateStepIn(StackFrame* frame) {
+  thread_local_.step_into_fp_ = frame->fp();
+}
+
+
+void Debug::ClearStepIn() {
+  thread_local_.step_into_fp_ = 0;
+}
+
+
+void Debug::ClearStepNext() {
+  thread_local_.last_step_action_ = StepNone;
+  thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
+  thread_local_.last_fp_ = 0;
+}
+
+
+bool Debug::EnsureCompiled(Handle<SharedFunctionInfo> shared) {
+  if (shared->is_compiled()) return true;
+  return CompileLazyShared(shared, CLEAR_EXCEPTION, 0);
+}
+
+
+// Ensures the debug information is present for shared.
+bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared) {
+  // Return if we already have the debug info for shared.
+  if (HasDebugInfo(shared)) return true;
+
+  // Ensure shared in compiled. Return false if this failed.
+  if (!EnsureCompiled(shared)) return false;
+
+  // Create the debug info object.
+  Handle<DebugInfo> debug_info = Factory::NewDebugInfo(shared);
+
+  // Add debug info to the list.
+  DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
+  node->set_next(debug_info_list_);
+  debug_info_list_ = node;
+
+  // Now there is at least one break point.
+  has_break_points_ = true;
+
+  return true;
+}
+
+
+void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) {
+  ASSERT(debug_info_list_ != NULL);
+  // Run through the debug info objects to find this one and remove it.
+  DebugInfoListNode* prev = NULL;
+  DebugInfoListNode* current = debug_info_list_;
+  while (current != NULL) {
+    if (*current->debug_info() == *debug_info) {
+      // Unlink from list. If prev is NULL we are looking at the first element.
+      if (prev == NULL) {
+        debug_info_list_ = current->next();
+      } else {
+        prev->set_next(current->next());
+      }
+      current->debug_info()->shared()->set_debug_info(Heap::undefined_value());
+      delete current;
+
+      // If there are no more debug info objects there are not more break
+      // points.
+      has_break_points_ = debug_info_list_ != NULL;
+
+      return;
+    }
+    // Move to next in list.
+    prev = current;
+    current = current->next();
+  }
+  UNREACHABLE();
+}
+
+
+void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
+  HandleScope scope;
+
+  // Get the executing function in which the debug break occurred.
+  Handle<SharedFunctionInfo> shared =
+      Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared());
+  if (!EnsureDebugInfo(shared)) {
+    // Return if we failed to retrieve the debug info.
+    return;
+  }
+  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
+  Handle<Code> code(debug_info->code());
+  Handle<Code> original_code(debug_info->original_code());
+#ifdef DEBUG
+  // Get the code which is actually executing.
+  Handle<Code> frame_code(frame->code());
+  ASSERT(frame_code.is_identical_to(code));
+#endif
+
+  // Find the call address in the running code. This address holds the call to
+  // either a DebugBreakXXX or to the debug break return entry code if the
+  // break point is still active after processing the break point.
+  Address addr = frame->pc() - Assembler::kTargetAddrToReturnAddrDist;
+
+  // Check if the location is at JS exit.
+  bool at_js_exit = false;
+  RelocIterator it(debug_info->code());
+  while (!it.done()) {
+    if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
+      at_js_exit = it.rinfo()->pc() == addr - 1;
+    }
+    it.next();
+  }
+
+  // Handle the jump to continue execution after break point depending on the
+  // break location.
+  if (at_js_exit) {
+    // First check if the call in the code is still the debug break return
+    // entry code. If it is the break point is still active. If not the break
+    // point was removed during break point processing.
+    if (Assembler::target_address_at(addr) ==
+        debug_break_return_entry()->entry()) {
+      // Break point still active. Jump to the corresponding place in the
+      // original code.
+      addr +=  original_code->instruction_start() - code->instruction_start();
+    }
+
+    // Move one byte back to where the call instruction was placed.
+    thread_local_.after_break_target_ = addr - 1;
+  } else {
+    // Check if there still is a debug break call at the target address. If the
+    // break point has been removed it will have disappeared. If it have
+    // disappeared don't try to look in the original code as the running code
+    // will have the right address. This takes care of the case where the last
+    // break point is removed from the function and therefore no "original code"
+    // is available. If the debug break call is still there find the address in
+    // the original code.
+    if (IsDebugBreak(Assembler::target_address_at(addr))) {
+      // If the break point is still there find the call address which was
+      // overwritten in the original code by the call to DebugBreakXXX.
+
+      // Find the corresponding address in the original code.
+      addr += original_code->instruction_start() - code->instruction_start();
+    }
+
+    // Install jump to the call address in the original code. This will be the
+    // call which was overwritten by the call to DebugBreakXXX.
+    thread_local_.after_break_target_ = Assembler::target_address_at(addr);
+  }
+}
+
+
+bool Debug::IsDebugGlobal(GlobalObject* global) {
+  return IsLoaded() && global == Debug::debug_context()->global();
+}
+
+
+void Debug::ClearMirrorCache() {
+  HandleScope scope;
+  ASSERT(Top::context() == *Debug::debug_context());
+
+  // Clear the mirror cache.
+  Handle<String> function_name =
+      Factory::LookupSymbol(CStrVector("ClearMirrorCache"));
+  Handle<Object> fun(Top::global()->GetProperty(*function_name));
+  ASSERT(fun->IsJSFunction());
+  bool caught_exception;
+  Handle<Object> js_object = Execution::TryCall(
+      Handle<JSFunction>::cast(fun),
+      Handle<JSObject>(Debug::debug_context()->global()),
+      0, NULL, &caught_exception);
+}
+
+
+Mutex* Debugger::debugger_access_ = OS::CreateMutex();
+Handle<Object> Debugger::event_listener_ = Handle<Object>();
+Handle<Object> Debugger::event_listener_data_ = Handle<Object>();
+bool Debugger::compiling_natives_ = false;
+bool Debugger::is_loading_debugger_ = false;
+bool Debugger::never_unload_debugger_ = false;
+DebugMessageThread* Debugger::message_thread_ = NULL;
+v8::DebugMessageHandler Debugger::message_handler_ = NULL;
+bool Debugger::message_handler_cleared_ = false;
+void* Debugger::message_handler_data_ = NULL;
+v8::DebugHostDispatchHandler Debugger::host_dispatch_handler_ = NULL;
+void* Debugger::host_dispatch_handler_data_ = NULL;
+DebuggerAgent* Debugger::agent_ = NULL;
+LockingMessageQueue Debugger::command_queue_(kQueueInitialSize);
+LockingMessageQueue Debugger::message_queue_(kQueueInitialSize);
+Semaphore* Debugger::command_received_ = OS::CreateSemaphore(0);
+Semaphore* Debugger::message_received_ = OS::CreateSemaphore(0);
+
+
+Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name,
+                                      int argc, Object*** argv,
+                                      bool* caught_exception) {
+  ASSERT(Top::context() == *Debug::debug_context());
+
+  // Create the execution state object.
+  Handle<String> constructor_str = Factory::LookupSymbol(constructor_name);
+  Handle<Object> constructor(Top::global()->GetProperty(*constructor_str));
+  ASSERT(constructor->IsJSFunction());
+  if (!constructor->IsJSFunction()) {
+    *caught_exception = true;
+    return Factory::undefined_value();
+  }
+  Handle<Object> js_object = Execution::TryCall(
+      Handle<JSFunction>::cast(constructor),
+      Handle<JSObject>(Debug::debug_context()->global()), argc, argv,
+      caught_exception);
+  return js_object;
+}
+
+
+Handle<Object> Debugger::MakeExecutionState(bool* caught_exception) {
+  // Create the execution state object.
+  Handle<Object> break_id = Factory::NewNumberFromInt(Debug::break_id());
+  const int argc = 1;
+  Object** argv[argc] = { break_id.location() };
+  return MakeJSObject(CStrVector("MakeExecutionState"),
+                      argc, argv, caught_exception);
+}
+
+
+Handle<Object> Debugger::MakeBreakEvent(Handle<Object> exec_state,
+                                        Handle<Object> break_points_hit,
+                                        bool* caught_exception) {
+  // Create the new break event object.
+  const int argc = 2;
+  Object** argv[argc] = { exec_state.location(),
+                          break_points_hit.location() };
+  return MakeJSObject(CStrVector("MakeBreakEvent"),
+                      argc,
+                      argv,
+                      caught_exception);
+}
+
+
+Handle<Object> Debugger::MakeExceptionEvent(Handle<Object> exec_state,
+                                            Handle<Object> exception,
+                                            bool uncaught,
+                                            bool* caught_exception) {
+  // Create the new exception event object.
+  const int argc = 3;
+  Object** argv[argc] = { exec_state.location(),
+                          exception.location(),
+                          uncaught ? Factory::true_value().location() :
+                                     Factory::false_value().location()};
+  return MakeJSObject(CStrVector("MakeExceptionEvent"),
+                      argc, argv, caught_exception);
+}
+
+
+Handle<Object> Debugger::MakeNewFunctionEvent(Handle<Object> function,
+                                              bool* caught_exception) {
+  // Create the new function event object.
+  const int argc = 1;
+  Object** argv[argc] = { function.location() };
+  return MakeJSObject(CStrVector("MakeNewFunctionEvent"),
+                      argc, argv, caught_exception);
+}
+
+
+Handle<Object> Debugger::MakeCompileEvent(Handle<Script> script,
+                                          bool before,
+                                          bool* caught_exception) {
+  // Create the compile event object.
+  Handle<Object> exec_state = MakeExecutionState(caught_exception);
+  Handle<Object> script_wrapper = GetScriptWrapper(script);
+  const int argc = 3;
+  Object** argv[argc] = { exec_state.location(),
+                          script_wrapper.location(),
+                          before ? Factory::true_value().location() :
+                                   Factory::false_value().location() };
+
+  return MakeJSObject(CStrVector("MakeCompileEvent"),
+                      argc,
+                      argv,
+                      caught_exception);
+}
+
+
+void Debugger::OnException(Handle<Object> exception, bool uncaught) {
+  HandleScope scope;
+
+  // Bail out based on state or if there is no listener for this event
+  if (Debug::InDebugger()) return;
+  if (!Debugger::EventActive(v8::Exception)) return;
+
+  // Bail out if exception breaks are not active
+  if (uncaught) {
+    // Uncaught exceptions are reported by either flags.
+    if (!(Debug::break_on_uncaught_exception() ||
+          Debug::break_on_exception())) return;
+  } else {
+    // Caught exceptions are reported is activated.
+    if (!Debug::break_on_exception()) return;
+  }
+
+  // Enter the debugger.
+  EnterDebugger debugger;
+  if (debugger.FailedToEnter()) return;
+
+  // Clear all current stepping setup.
+  Debug::ClearStepping();
+  // Create the event data object.
+  bool caught_exception = false;
+  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
+  Handle<Object> event_data;
+  if (!caught_exception) {
+    event_data = MakeExceptionEvent(exec_state, exception, uncaught,
+                                    &caught_exception);
+  }
+  // Bail out and don't call debugger if exception.
+  if (caught_exception) {
+    return;
+  }
+
+  // Process debug event
+  ProcessDebugEvent(v8::Exception, event_data, false);
+  // Return to continue execution from where the exception was thrown.
+}
+
+
+void Debugger::OnDebugBreak(Handle<Object> break_points_hit,
+                            bool auto_continue) {
+  HandleScope scope;
+
+  // Debugger has already been entered by caller.
+  ASSERT(Top::context() == *Debug::debug_context());
+
+  // Bail out if there is no listener for this event
+  if (!Debugger::EventActive(v8::Break)) return;
+
+  // Debugger must be entered in advance.
+  ASSERT(Top::context() == *Debug::debug_context());
+
+  // Create the event data object.
+  bool caught_exception = false;
+  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
+  Handle<Object> event_data;
+  if (!caught_exception) {
+    event_data = MakeBreakEvent(exec_state, break_points_hit,
+                                &caught_exception);
+  }
+  // Bail out and don't call debugger if exception.
+  if (caught_exception) {
+    return;
+  }
+
+  // Process debug event
+  ProcessDebugEvent(v8::Break, event_data, auto_continue);
+}
+
+
+void Debugger::OnBeforeCompile(Handle<Script> script) {
+  HandleScope scope;
+
+  // Bail out based on state or if there is no listener for this event
+  if (Debug::InDebugger()) return;
+  if (compiling_natives()) return;
+  if (!EventActive(v8::BeforeCompile)) return;
+
+  // Enter the debugger.
+  EnterDebugger debugger;
+  if (debugger.FailedToEnter()) return;
+
+  // Create the event data object.
+  bool caught_exception = false;
+  Handle<Object> event_data = MakeCompileEvent(script, true, &caught_exception);
+  // Bail out and don't call debugger if exception.
+  if (caught_exception) {
+    return;
+  }
+
+  // Process debug event
+  ProcessDebugEvent(v8::BeforeCompile, event_data, false);
+}
+
+
+// Handle debugger actions when a new script is compiled.
+void Debugger::OnAfterCompile(Handle<Script> script, Handle<JSFunction> fun) {
+  HandleScope scope;
+
+  // No compile events while compiling natives.
+  if (compiling_natives()) return;
+
+  // No more to do if not debugging.
+  if (!IsDebuggerActive()) return;
+
+  // Store whether in debugger before entering debugger.
+  bool in_debugger = Debug::InDebugger();
+
+  // Enter the debugger.
+  EnterDebugger debugger;
+  if (debugger.FailedToEnter()) return;
+
+  // If debugging there might be script break points registered for this
+  // script. Make sure that these break points are set.
+
+  // Get the function UpdateScriptBreakPoints (defined in debug-delay.js).
+  Handle<Object> update_script_break_points =
+      Handle<Object>(Debug::debug_context()->global()->GetProperty(
+          *Factory::LookupAsciiSymbol("UpdateScriptBreakPoints")));
+  if (!update_script_break_points->IsJSFunction()) {
+    return;
+  }
+  ASSERT(update_script_break_points->IsJSFunction());
+
+  // Wrap the script object in a proper JS object before passing it
+  // to JavaScript.
+  Handle<JSValue> wrapper = GetScriptWrapper(script);
+
+  // Call UpdateScriptBreakPoints expect no exceptions.
+  bool caught_exception = false;
+  const int argc = 1;
+  Object** argv[argc] = { reinterpret_cast<Object**>(wrapper.location()) };
+  Handle<Object> result = Execution::TryCall(
+      Handle<JSFunction>::cast(update_script_break_points),
+      Top::builtins(), argc, argv,
+      &caught_exception);
+  if (caught_exception) {
+    return;
+  }
+  // Bail out based on state or if there is no listener for this event
+  if (in_debugger) return;
+  if (!Debugger::EventActive(v8::AfterCompile)) return;
+
+  // Create the compile state object.
+  Handle<Object> event_data = MakeCompileEvent(script,
+                                               false,
+                                               &caught_exception);
+  // Bail out and don't call debugger if exception.
+  if (caught_exception) {
+    return;
+  }
+  // Process debug event
+  ProcessDebugEvent(v8::AfterCompile, event_data, false);
+}
+
+
+void Debugger::OnNewFunction(Handle<JSFunction> function) {
+  return;
+  HandleScope scope;
+
+  // Bail out based on state or if there is no listener for this event
+  if (Debug::InDebugger()) return;
+  if (compiling_natives()) return;
+  if (!Debugger::EventActive(v8::NewFunction)) return;
+
+  // Enter the debugger.
+  EnterDebugger debugger;
+  if (debugger.FailedToEnter()) return;
+
+  // Create the event object.
+  bool caught_exception = false;
+  Handle<Object> event_data = MakeNewFunctionEvent(function, &caught_exception);
+  // Bail out and don't call debugger if exception.
+  if (caught_exception) {
+    return;
+  }
+  // Process debug event.
+  ProcessDebugEvent(v8::NewFunction, event_data, false);
+}
+
+
+void Debugger::ProcessDebugEvent(v8::DebugEvent event,
+                                 Handle<Object> event_data,
+                                 bool auto_continue) {
+  HandleScope scope;
+
+  // Create the execution state.
+  bool caught_exception = false;
+  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
+  if (caught_exception) {
+    return;
+  }
+  // First notify the message handler if any.
+  if (message_handler_ != NULL) {
+    NotifyMessageHandler(event, exec_state, event_data, auto_continue);
+  }
+  // Notify registered debug event listener. This can be either a C or a
+  // JavaScript function.
+  if (!event_listener_.is_null()) {
+    if (event_listener_->IsProxy()) {
+      // C debug event listener.
+      Handle<Proxy> callback_obj(Handle<Proxy>::cast(event_listener_));
+      v8::DebugEventCallback callback =
+            FUNCTION_CAST<v8::DebugEventCallback>(callback_obj->proxy());
+      callback(event,
+               v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
+               v8::Utils::ToLocal(Handle<JSObject>::cast(event_data)),
+               v8::Utils::ToLocal(Handle<Object>::cast(event_listener_data_)));
+    } else {
+      // JavaScript debug event listener.
+      ASSERT(event_listener_->IsJSFunction());
+      Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_));
+
+      // Invoke the JavaScript debug event listener.
+      const int argc = 4;
+      Object** argv[argc] = { Handle<Object>(Smi::FromInt(event)).location(),
+                              exec_state.location(),
+                              event_data.location(),
+                              event_listener_data_.location() };
+      Handle<Object> result = Execution::TryCall(fun, Top::global(),
+                                                 argc, argv, &caught_exception);
+      if (caught_exception) {
+        // Silently ignore exceptions from debug event listeners.
+      }
+    }
+  }
+
+  // Clear the mirror cache.
+  Debug::ClearMirrorCache();
+}
+
+
+void Debugger::UnloadDebugger() {
+  // Make sure that there are no breakpoints left.
+  Debug::ClearAllBreakPoints();
+
+  // Unload the debugger if feasible.
+  if (!never_unload_debugger_) {
+    Debug::Unload();
+  }
+
+  // Clear the flag indicating that the message handler was recently cleared.
+  message_handler_cleared_ = false;
+}
+
+
+void Debugger::NotifyMessageHandler(v8::DebugEvent event,
+                                    Handle<Object> exec_state,
+                                    Handle<Object> event_data,
+                                    bool auto_continue) {
+  HandleScope scope;
+
+  if (!Debug::Load()) return;
+
+  // Process the individual events.
+  bool interactive = false;
+  switch (event) {
+    case v8::Break:
+      interactive = true;  // Break event is always interactive
+      break;
+    case v8::Exception:
+      interactive = true;  // Exception event is always interactive
+      break;
+    case v8::BeforeCompile:
+      break;
+    case v8::AfterCompile:
+      break;
+    case v8::NewFunction:
+      break;
+    default:
+      UNREACHABLE();
+  }
+
+  // Done if not interactive.
+  if (!interactive) return;
+
+  // Get the DebugCommandProcessor.
+  v8::Local<v8::Object> api_exec_state =
+      v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state));
+  v8::Local<v8::String> fun_name =
+      v8::String::New("debugCommandProcessor");
+  v8::Local<v8::Function> fun =
+      v8::Function::Cast(*api_exec_state->Get(fun_name));
+  v8::TryCatch try_catch;
+  v8::Local<v8::Object> cmd_processor =
+      v8::Object::Cast(*fun->Call(api_exec_state, 0, NULL));
+  if (try_catch.HasCaught()) {
+    PrintLn(try_catch.Exception());
+    return;
+  }
+
+  // Notify the debugger that a debug event has occurred unless auto continue is
+  // active in which case no event is send.
+  if (!auto_continue) {
+    bool success = SendEventMessage(event_data);
+    if (!success) {
+      // If failed to notify debugger just continue running.
+      return;
+    }
+  }
+
+  // Process requests from the debugger.
+  while (true) {
+    // Wait for new command in the queue.
+    command_received_->Wait();
+
+    // The debug command interrupt flag might have been set when the command was
+    // added.
+    StackGuard::Continue(DEBUGCOMMAND);
+
+    // Get the command from the queue.
+    Vector<uint16_t> command = command_queue_.Get();
+    Logger::DebugTag("Got request from command queue, in interactive loop.");
+    if (!Debugger::IsDebuggerActive()) {
+      return;
+    }
+
+    // Check if the command is a host dispatch.
+    if (command[0] == 0) {
+      if (Debugger::host_dispatch_handler_) {
+        int32_t dispatch = (command[1] << 16) | command[2];
+        Debugger::host_dispatch_handler_(reinterpret_cast<void*>(dispatch),
+                                         Debugger::host_dispatch_handler_data_);
+      }
+      if (auto_continue && !HasCommands()) {
+        return;
+      }
+      continue;
+    }
+
+    // Invoke JavaScript to process the debug request.
+    v8::Local<v8::String> fun_name;
+    v8::Local<v8::Function> fun;
+    v8::Local<v8::Value> request;
+    v8::TryCatch try_catch;
+    fun_name = v8::String::New("processDebugRequest");
+    fun = v8::Function::Cast(*cmd_processor->Get(fun_name));
+    request = v8::String::New(reinterpret_cast<uint16_t*>(command.start()),
+                              command.length());
+    static const int kArgc = 1;
+    v8::Handle<Value> argv[kArgc] = { request };
+    v8::Local<v8::Value> response_val = fun->Call(cmd_processor, kArgc, argv);
+
+    // Get the response.
+    v8::Local<v8::String> response;
+    bool running = false;
+    if (!try_catch.HasCaught()) {
+      // Get response string.
+      if (!response_val->IsUndefined()) {
+        response = v8::String::Cast(*response_val);
+      } else {
+        response = v8::String::New("");
+      }
+
+      // Log the JSON request/response.
+      if (FLAG_trace_debug_json) {
+        PrintLn(request);
+        PrintLn(response);
+      }
+
+      // Get the running state.
+      fun_name = v8::String::New("isRunning");
+      fun = v8::Function::Cast(*cmd_processor->Get(fun_name));
+      static const int kArgc = 1;
+      v8::Handle<Value> argv[kArgc] = { response };
+      v8::Local<v8::Value> running_val = fun->Call(cmd_processor, kArgc, argv);
+      if (!try_catch.HasCaught()) {
+        running = running_val->ToBoolean()->Value();
+      }
+    } else {
+      // In case of failure the result text is the exception text.
+      response = try_catch.Exception()->ToString();
+    }
+
+    // Convert text result to C string.
+    v8::String::Value val(response);
+    Vector<uint16_t> str(reinterpret_cast<uint16_t*>(*val),
+                        response->Length());
+
+    // Return the result.
+    SendMessage(str);
+
+    // Return from debug event processing if either the VM is put into the
+    // runnning state (through a continue command) or auto continue is active
+    // and there are no more commands queued.
+    if (running || (auto_continue && !HasCommands())) {
+      return;
+    }
+  }
+}
+
+
+void Debugger::SetEventListener(Handle<Object> callback,
+                                Handle<Object> data) {
+  HandleScope scope;
+
+  // Clear the global handles for the event listener and the event listener data
+  // object.
+  if (!event_listener_.is_null()) {
+    GlobalHandles::Destroy(
+        reinterpret_cast<Object**>(event_listener_.location()));
+    event_listener_ = Handle<Object>();
+  }
+  if (!event_listener_data_.is_null()) {
+    GlobalHandles::Destroy(
+        reinterpret_cast<Object**>(event_listener_data_.location()));
+    event_listener_data_ = Handle<Object>();
+  }
+
+  // If there is a new debug event listener register it together with its data
+  // object.
+  if (!callback->IsUndefined() && !callback->IsNull()) {
+    event_listener_ = Handle<Object>::cast(GlobalHandles::Create(*callback));
+    if (data.is_null()) {
+      data = Factory::undefined_value();
+    }
+    event_listener_data_ = Handle<Object>::cast(GlobalHandles::Create(*data));
+  }
+
+  // Unload the debugger if event listener cleared.
+  if (callback->IsUndefined()) {
+    UnloadDebugger();
+  }
+}
+
+
+void Debugger::SetMessageHandler(v8::DebugMessageHandler handler, void* data,
+                                 bool message_handler_thread) {
+  ScopedLock with(debugger_access_);
+
+  message_handler_ = handler;
+  message_handler_data_ = data;
+  if (handler != NULL) {
+    if (!message_thread_ && message_handler_thread) {
+      message_thread_ = new DebugMessageThread();
+      message_thread_->Start();
+    }
+  } else {
+    // Indicate that the message handler was recently cleared.
+    message_handler_cleared_ = true;
+
+    // Send an empty command to the debugger if in a break to make JavaScript
+    // run again if the debugger is closed.
+    if (Debug::InDebugger()) {
+      ProcessCommand(Vector<const uint16_t>::empty());
+    }
+  }
+}
+
+
+void Debugger::SetHostDispatchHandler(v8::DebugHostDispatchHandler handler,
+                                      void* data) {
+  host_dispatch_handler_ = handler;
+  host_dispatch_handler_data_ = data;
+}
+
+
+// Calls the registered debug message handler. This callback is part of the
+// public API. Messages are kept internally as Vector<uint16_t> strings, which
+// are allocated in various places and deallocated by the calling function
+// sometime after this call.
+void Debugger::InvokeMessageHandler(Vector<uint16_t> message) {
+  ScopedLock with(debugger_access_);
+
+  if (message_handler_ != NULL) {
+    message_handler_(message.start(), message.length(), message_handler_data_);
+  }
+}
+
+
+void Debugger::SendMessage(Vector<uint16_t> message) {
+  if (message_thread_ == NULL) {
+    // If there is no message thread just invoke the message handler from the
+    // V8 thread.
+    InvokeMessageHandler(message);
+  } else {
+    // Put a copy of the message coming from V8 on the queue. The new copy of
+    // the event string is destroyed by the message thread.
+    Vector<uint16_t> message_copy = message.Clone();
+    Logger::DebugTag("Put message on event message_queue.");
+    message_queue_.Put(message_copy);
+    message_received_->Signal();
+  }
+}
+
+
+bool Debugger::SendEventMessage(Handle<Object> event_data) {
+  v8::HandleScope scope;
+  // Call toJSONProtocol on the debug event object.
+  v8::Local<v8::Object> api_event_data =
+      v8::Utils::ToLocal(Handle<JSObject>::cast(event_data));
+  v8::Local<v8::String> fun_name = v8::String::New("toJSONProtocol");
+  v8::Local<v8::Function> fun =
+      v8::Function::Cast(*api_event_data->Get(fun_name));
+  v8::TryCatch try_catch;
+  v8::Local<v8::Value> json_event = *fun->Call(api_event_data, 0, NULL);
+  v8::Local<v8::String> json_event_string;
+  if (!try_catch.HasCaught()) {
+    if (!json_event->IsUndefined()) {
+      json_event_string = json_event->ToString();
+      if (FLAG_trace_debug_json) {
+        PrintLn(json_event_string);
+      }
+      v8::String::Value val(json_event_string);
+      Vector<uint16_t> str(reinterpret_cast<uint16_t*>(*val),
+                           json_event_string->Length());
+      SendMessage(str);
+    } else {
+      SendMessage(Vector<uint16_t>::empty());
+    }
+  } else {
+    PrintLn(try_catch.Exception());
+    return false;
+  }
+  return true;
+}
+
+
+// Puts a command coming from the public API on the queue.  Creates
+// a copy of the command string managed by the debugger.  Up to this
+// point, the command data was managed by the API client.  Called
+// by the API client thread.  This is where the API client hands off
+// processing of the command to the DebugMessageThread thread.
+// The new copy of the command is destroyed in HandleCommand().
+void Debugger::ProcessCommand(Vector<const uint16_t> command) {
+  // Make a copy of the command. Need to cast away const for Clone to work.
+  Vector<uint16_t> command_copy =
+      Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
+                       command.length()).Clone();
+  Logger::DebugTag("Put command on command_queue.");
+  command_queue_.Put(command_copy);
+  command_received_->Signal();
+
+  // Set the debug command break flag to have the command processed.
+  if (!Debug::InDebugger()) {
+    StackGuard::DebugCommand();
+  }
+}
+
+
+bool Debugger::HasCommands() {
+  return !command_queue_.IsEmpty();
+}
+
+
+void Debugger::ProcessHostDispatch(void* dispatch) {
+  // Puts a host dispatch comming from the public API on the queue.
+  uint16_t hack[3];
+  hack[0] = 0;
+  hack[1] = reinterpret_cast<uint32_t>(dispatch) >> 16;
+  hack[2] = reinterpret_cast<uint32_t>(dispatch) & 0xFFFF;
+  Logger::DebugTag("Put dispatch on command_queue.");
+  command_queue_.Put(Vector<uint16_t>(hack, 3).Clone());
+  command_received_->Signal();
+
+  // Set the debug command break flag to have the host dispatch processed.
+  if (!Debug::InDebugger()) {
+    StackGuard::DebugCommand();
+  }
+}
+
+
+bool Debugger::IsDebuggerActive() {
+  ScopedLock with(debugger_access_);
+
+  return message_handler_ != NULL || !event_listener_.is_null();
+}
+
+
+Handle<Object> Debugger::Call(Handle<JSFunction> fun,
+                              Handle<Object> data,
+                              bool* pending_exception) {
+  // When calling functions in the debugger prevent it from beeing unloaded.
+  Debugger::never_unload_debugger_ = true;
+
+  // Enter the debugger.
+  EnterDebugger debugger;
+  if (debugger.FailedToEnter() || !debugger.HasJavaScriptFrames()) {
+    return Factory::undefined_value();
+  }
+
+  // Create the execution state.
+  bool caught_exception = false;
+  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
+  if (caught_exception) {
+    return Factory::undefined_value();
+  }
+
+  static const int kArgc = 2;
+  Object** argv[kArgc] = { exec_state.location(), data.location() };
+  Handle<Object> result = Execution::Call(fun, Factory::undefined_value(),
+                                          kArgc, argv, pending_exception);
+  return result;
+}
+
+
+bool Debugger::StartAgent(const char* name, int port) {
+  if (Socket::Setup()) {
+    agent_ = new DebuggerAgent(name, port);
+    agent_->Start();
+    return true;
+  }
+
+  return false;
+}
+
+
+void Debugger::StopAgent() {
+  if (agent_ != NULL) {
+    agent_->Shutdown();
+    agent_->Join();
+    delete agent_;
+    agent_ = NULL;
+  }
+}
+
+
+void Debugger::TearDown() {
+  if (message_thread_ != NULL) {
+    message_thread_->Stop();
+    delete message_thread_;
+    message_thread_ = NULL;
+  }
+}
+
+
+void DebugMessageThread::Run() {
+  // Sends debug events to an installed debugger message callback.
+  while (keep_running_) {
+    // Wait and Get are paired so that semaphore count equals queue length.
+    Debugger::message_received_->Wait();
+    Logger::DebugTag("Get message from event message_queue.");
+    Vector<uint16_t> message = Debugger::message_queue_.Get();
+    if (message.length() > 0) {
+      Debugger::InvokeMessageHandler(message);
+    }
+  }
+}
+
+
+void DebugMessageThread::Stop() {
+  keep_running_ = false;
+  Debugger::SendMessage(Vector<uint16_t>(NULL, 0));
+  Join();
+}
+
+
+MessageQueue::MessageQueue(int size) : start_(0), end_(0), size_(size) {
+  messages_ = NewArray<Vector<uint16_t> >(size);
+}
+
+
+MessageQueue::~MessageQueue() {
+  DeleteArray(messages_);
+}
+
+
+Vector<uint16_t> MessageQueue::Get() {
+  ASSERT(!IsEmpty());
+  int result = start_;
+  start_ = (start_ + 1) % size_;
+  return messages_[result];
+}
+
+
+void MessageQueue::Put(const Vector<uint16_t>& message) {
+  if ((end_ + 1) % size_ == start_) {
+    Expand();
+  }
+  messages_[end_] = message;
+  end_ = (end_ + 1) % size_;
+}
+
+
+void MessageQueue::Expand() {
+  MessageQueue new_queue(size_ * 2);
+  while (!IsEmpty()) {
+    new_queue.Put(Get());
+  }
+  Vector<uint16_t>* array_to_free = messages_;
+  *this = new_queue;
+  new_queue.messages_ = array_to_free;
+  // Automatic destructor called on new_queue, freeing array_to_free.
+}
+
+
+LockingMessageQueue::LockingMessageQueue(int size) : queue_(size) {
+  lock_ = OS::CreateMutex();
+}
+
+
+LockingMessageQueue::~LockingMessageQueue() {
+  delete lock_;
+}
+
+
+bool LockingMessageQueue::IsEmpty() const {
+  ScopedLock sl(lock_);
+  return queue_.IsEmpty();
+}
+
+
+Vector<uint16_t> LockingMessageQueue::Get() {
+  ScopedLock sl(lock_);
+  Vector<uint16_t> result = queue_.Get();
+  Logger::DebugEvent("Get", result);
+  return result;
+}
+
+
+void LockingMessageQueue::Put(const Vector<uint16_t>& message) {
+  ScopedLock sl(lock_);
+  queue_.Put(message);
+  Logger::DebugEvent("Put", message);
+}
+
+
+void LockingMessageQueue::Clear() {
+  ScopedLock sl(lock_);
+  queue_.Clear();
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/debug.h b/deps/v8/src/debug.h
new file mode 100644
index 0000000..8822c50
--- /dev/null
+++ b/deps/v8/src/debug.h
@@ -0,0 +1,722 @@
+// 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_V8_DEBUG_H_
+#define V8_V8_DEBUG_H_
+
+#include "../include/v8-debug.h"
+#include "assembler.h"
+#include "code-stubs.h"
+#include "debug-agent.h"
+#include "execution.h"
+#include "factory.h"
+#include "platform.h"
+#include "string-stream.h"
+#include "v8threads.h"
+
+
+namespace v8 { namespace internal {
+
+
+// Forward declarations.
+class EnterDebugger;
+
+
+// Step actions. NOTE: These values are in macros.py as well.
+enum StepAction {
+  StepNone = -1,  // Stepping not prepared.
+  StepOut = 0,   // Step out of the current function.
+  StepNext = 1,  // Step to the next statement in the current function.
+  StepIn = 2,    // Step into new functions invoked or the next statement
+                 // in the current function.
+  StepMin = 3,   // Perform a minimum step in the current function.
+  StepInMin = 4  // Step into new functions invoked or perform a minimum step
+                 // in the current function.
+};
+
+
+// Type of exception break. NOTE: These values are in macros.py as well.
+enum ExceptionBreakType {
+  BreakException = 0,
+  BreakUncaughtException = 1
+};
+
+
+// Type of exception break. NOTE: These values are in macros.py as well.
+enum BreakLocatorType {
+  ALL_BREAK_LOCATIONS = 0,
+  SOURCE_BREAK_LOCATIONS = 1
+};
+
+
+// Class for iterating through the break points in a function and changing
+// them.
+class BreakLocationIterator {
+ public:
+  explicit BreakLocationIterator(Handle<DebugInfo> debug_info,
+                                 BreakLocatorType type);
+  virtual ~BreakLocationIterator();
+
+  void Next();
+  void Next(int count);
+  void FindBreakLocationFromAddress(Address pc);
+  void FindBreakLocationFromPosition(int position);
+  void Reset();
+  bool Done() const;
+  void SetBreakPoint(Handle<Object> break_point_object);
+  void ClearBreakPoint(Handle<Object> break_point_object);
+  void SetOneShot();
+  void ClearOneShot();
+  void PrepareStepIn();
+  bool IsExit() const;
+  bool HasBreakPoint();
+  bool IsDebugBreak();
+  Object* BreakPointObjects();
+  void ClearAllDebugBreak();
+
+
+  inline int code_position() { return pc() - debug_info_->code()->entry(); }
+  inline int break_point() { return break_point_; }
+  inline int position() { return position_; }
+  inline int statement_position() { return statement_position_; }
+  inline Address pc() { return reloc_iterator_->rinfo()->pc(); }
+  inline Code* code() { return debug_info_->code(); }
+  inline RelocInfo* rinfo() { return reloc_iterator_->rinfo(); }
+  inline RelocInfo::Mode rmode() const {
+    return reloc_iterator_->rinfo()->rmode();
+  }
+  inline RelocInfo* original_rinfo() {
+    return reloc_iterator_original_->rinfo();
+  }
+  inline RelocInfo::Mode original_rmode() const {
+    return reloc_iterator_original_->rinfo()->rmode();
+  }
+
+ protected:
+  bool RinfoDone() const;
+  void RinfoNext();
+
+  BreakLocatorType type_;
+  int break_point_;
+  int position_;
+  int statement_position_;
+  Handle<DebugInfo> debug_info_;
+  RelocIterator* reloc_iterator_;
+  RelocIterator* reloc_iterator_original_;
+
+ private:
+  void SetDebugBreak();
+  void ClearDebugBreak();
+  bool IsDebugBreakAtReturn();
+  void SetDebugBreakAtReturn();
+  void ClearDebugBreakAtReturn();
+
+  DISALLOW_COPY_AND_ASSIGN(BreakLocationIterator);
+};
+
+
+// Linked list holding debug info objects. The debug info objects are kept as
+// weak handles to avoid a debug info object to keep a function alive.
+class DebugInfoListNode {
+ public:
+  explicit DebugInfoListNode(DebugInfo* debug_info);
+  virtual ~DebugInfoListNode();
+
+  DebugInfoListNode* next() { return next_; }
+  void set_next(DebugInfoListNode* next) { next_ = next; }
+  Handle<DebugInfo> debug_info() { return debug_info_; }
+
+ private:
+  // Global (weak) handle to the debug info object.
+  Handle<DebugInfo> debug_info_;
+
+  // Next pointer for linked list.
+  DebugInfoListNode* next_;
+};
+
+
+// This class contains the debugger support. The main purpose is to handle
+// setting break points in the code.
+//
+// This class controls the debug info for all functions which currently have
+// active breakpoints in them. This debug info is held in the heap root object
+// debug_info which is a FixedArray. Each entry in this list is of class
+// DebugInfo.
+class Debug {
+ public:
+  static void Setup(bool create_heap_objects);
+  static bool Load();
+  static void Unload();
+  static bool IsLoaded() { return !debug_context_.is_null(); }
+  static bool InDebugger() { return thread_local_.debugger_entry_ != NULL; }
+  static void PreemptionWhileInDebugger();
+  static void Iterate(ObjectVisitor* v);
+
+  static Object* Break(Arguments args);
+  static void SetBreakPoint(Handle<SharedFunctionInfo> shared,
+                            int source_position,
+                            Handle<Object> break_point_object);
+  static void ClearBreakPoint(Handle<Object> break_point_object);
+  static void ClearAllBreakPoints();
+  static void FloodWithOneShot(Handle<SharedFunctionInfo> shared);
+  static void FloodHandlerWithOneShot();
+  static void ChangeBreakOnException(ExceptionBreakType type, bool enable);
+  static void PrepareStep(StepAction step_action, int step_count);
+  static void ClearStepping();
+  static bool StepNextContinue(BreakLocationIterator* break_location_iterator,
+                               JavaScriptFrame* frame);
+  static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared);
+  static bool HasDebugInfo(Handle<SharedFunctionInfo> shared);
+
+  // Returns whether the operation succeeded.
+  static bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared);
+
+  static bool IsDebugBreak(Address addr);
+  static bool IsDebugBreakAtReturn(RelocInfo* rinfo);
+
+  // Check whether a code stub with the specified major key is a possible break
+  // point location.
+  static bool IsSourceBreakStub(Code* code);
+  static bool IsBreakStub(Code* code);
+
+  // Find the builtin to use for invoking the debug break
+  static Handle<Code> FindDebugBreak(RelocInfo* rinfo);
+
+  static Handle<Object> GetSourceBreakLocations(
+      Handle<SharedFunctionInfo> shared);
+
+  // Getter for the debug_context.
+  inline static Handle<Context> debug_context() { return debug_context_; }
+
+  // Check whether a global object is the debug global object.
+  static bool IsDebugGlobal(GlobalObject* global);
+
+  // Fast check to see if any break points are active.
+  inline static bool has_break_points() { return has_break_points_; }
+
+  static void NewBreak(StackFrame::Id break_frame_id);
+  static void SetBreak(StackFrame::Id break_frame_id, int break_id);
+  static StackFrame::Id break_frame_id() {
+    return thread_local_.break_frame_id_;
+  }
+  static int break_id() { return thread_local_.break_id_; }
+
+
+
+
+  static bool StepInActive() { return thread_local_.step_into_fp_ != 0; }
+  static void HandleStepIn(Handle<JSFunction> function,
+                           Address fp,
+                           bool is_constructor);
+  static Address step_in_fp() { return thread_local_.step_into_fp_; }
+  static Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; }
+
+  static EnterDebugger* debugger_entry() {
+    return thread_local_.debugger_entry_;
+  }
+  static void set_debugger_entry(EnterDebugger* entry) {
+    thread_local_.debugger_entry_ = entry;
+  }
+
+  static bool preemption_pending() {
+    return thread_local_.preemption_pending_;
+  }
+  static void set_preemption_pending(bool preemption_pending) {
+    thread_local_.preemption_pending_ = preemption_pending;
+  }
+
+  // Getter and setter for the disable break state.
+  static bool disable_break() { return disable_break_; }
+  static void set_disable_break(bool disable_break) {
+    disable_break_ = disable_break;
+  }
+
+  // Getters for the current exception break state.
+  static bool break_on_exception() { return break_on_exception_; }
+  static bool break_on_uncaught_exception() {
+    return break_on_uncaught_exception_;
+  }
+
+  enum AddressId {
+    k_after_break_target_address,
+    k_debug_break_return_address,
+    k_register_address
+  };
+
+  // Support for setting the address to jump to when returning from break point.
+  static Address* after_break_target_address() {
+    return reinterpret_cast<Address*>(&thread_local_.after_break_target_);
+  }
+
+  // Support for saving/restoring registers when handling debug break calls.
+  static Object** register_address(int r) {
+    return &registers_[r];
+  }
+
+  // Address of the debug break return entry code.
+  static Code* debug_break_return_entry() { return debug_break_return_entry_; }
+
+  // Support for getting the address of the debug break on return code.
+  static Code** debug_break_return_address() {
+    return &debug_break_return_;
+  }
+
+  static const int kEstimatedNofDebugInfoEntries = 16;
+  static const int kEstimatedNofBreakPointsInFunction = 16;
+
+  static void HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data);
+
+  friend class Debugger;
+  friend Handle<FixedArray> GetDebuggedFunctions();  // In test-debug.cc
+  friend void CheckDebuggerUnloaded(bool check_functions);  // In test-debug.cc
+
+  // Threading support.
+  static char* ArchiveDebug(char* to);
+  static char* RestoreDebug(char* from);
+  static int ArchiveSpacePerThread();
+
+  // Mirror cache handling.
+  static void ClearMirrorCache();
+
+  // Code generation assumptions.
+  static const int kIa32CallInstructionLength = 5;
+  static const int kIa32JSReturnSequenceLength = 6;
+
+  // Code generator routines.
+  static void GenerateLoadICDebugBreak(MacroAssembler* masm);
+  static void GenerateStoreICDebugBreak(MacroAssembler* masm);
+  static void GenerateKeyedLoadICDebugBreak(MacroAssembler* masm);
+  static void GenerateKeyedStoreICDebugBreak(MacroAssembler* masm);
+  static void GenerateConstructCallDebugBreak(MacroAssembler* masm);
+  static void GenerateReturnDebugBreak(MacroAssembler* masm);
+  static void GenerateReturnDebugBreakEntry(MacroAssembler* masm);
+  static void GenerateStubNoRegistersDebugBreak(MacroAssembler* masm);
+
+  // Called from stub-cache.cc.
+  static void GenerateCallICDebugBreak(MacroAssembler* masm);
+
+ private:
+  static bool CompileDebuggerScript(int index);
+  static void ClearOneShot();
+  static void ActivateStepIn(StackFrame* frame);
+  static void ClearStepIn();
+  static void ClearStepNext();
+  // Returns whether the compile succeeded.
+  static bool EnsureCompiled(Handle<SharedFunctionInfo> shared);
+  static void RemoveDebugInfo(Handle<DebugInfo> debug_info);
+  static void SetAfterBreakTarget(JavaScriptFrame* frame);
+  static Handle<Object> CheckBreakPoints(Handle<Object> break_point);
+  static bool CheckBreakPoint(Handle<Object> break_point_object);
+
+  // Global handle to debug context where all the debugger JavaScript code is
+  // loaded.
+  static Handle<Context> debug_context_;
+
+  // Boolean state indicating whether any break points are set.
+  static bool has_break_points_;
+  static DebugInfoListNode* debug_info_list_;
+
+  static bool disable_break_;
+  static bool break_on_exception_;
+  static bool break_on_uncaught_exception_;
+
+  // Per-thread data.
+  class ThreadLocal {
+   public:
+    // Counter for generating next break id.
+    int break_count_;
+
+    // Current break id.
+    int break_id_;
+
+    // Frame id for the frame of the current break.
+    StackFrame::Id break_frame_id_;
+
+    // Step action for last step performed.
+    StepAction last_step_action_;
+
+    // Source statement position from last step next action.
+    int last_statement_position_;
+
+    // Number of steps left to perform before debug event.
+    int step_count_;
+
+    // Frame pointer from last step next action.
+    Address last_fp_;
+
+    // Frame pointer for frame from which step in was performed.
+    Address step_into_fp_;
+
+    // Storage location for jump when exiting debug break calls.
+    Address after_break_target_;
+
+    // Top debugger entry.
+    EnterDebugger* debugger_entry_;
+
+    // Preemption happened while debugging.
+    bool preemption_pending_;
+  };
+
+  // Storage location for registers when handling debug break calls
+  static JSCallerSavedBuffer registers_;
+  static ThreadLocal thread_local_;
+  static void ThreadInit();
+
+  // Code object for debug break return entry code.
+  static Code* debug_break_return_entry_;
+
+  // Code to call for handling debug break on return.
+  static Code* debug_break_return_;
+
+  DISALLOW_COPY_AND_ASSIGN(Debug);
+};
+
+
+// A Queue of Vector<uint16_t> objects.  A thread-safe version is
+// LockingMessageQueue, based on this class.
+class MessageQueue BASE_EMBEDDED {
+ public:
+  explicit MessageQueue(int size);
+  ~MessageQueue();
+  bool IsEmpty() const { return start_ == end_; }
+  Vector<uint16_t> Get();
+  void Put(const Vector<uint16_t>& message);
+  void Clear() { start_ = end_ = 0; }  // Queue is empty after Clear().
+ private:
+  // Doubles the size of the message queue, and copies the messages.
+  void Expand();
+
+  Vector<uint16_t>* messages_;
+  int start_;
+  int end_;
+  int size_;  // The size of the queue buffer.  Queue can hold size-1 messages.
+};
+
+
+// LockingMessageQueue is a thread-safe circular buffer of Vector<uint16_t>
+// messages.  The message data is not managed by LockingMessageQueue.
+// Pointers to the data are passed in and out. Implemented by adding a
+// Mutex to MessageQueue.  Includes logging of all puts and gets.
+class LockingMessageQueue BASE_EMBEDDED {
+ public:
+  explicit LockingMessageQueue(int size);
+  ~LockingMessageQueue();
+  bool IsEmpty() const;
+  Vector<uint16_t> Get();
+  void Put(const Vector<uint16_t>& message);
+  void Clear();
+ private:
+  MessageQueue queue_;
+  Mutex* lock_;
+  DISALLOW_COPY_AND_ASSIGN(LockingMessageQueue);
+};
+
+
+class DebugMessageThread;
+
+class Debugger {
+ public:
+  static void DebugRequest(const uint16_t* json_request, int length);
+
+  static Handle<Object> MakeJSObject(Vector<const char> constructor_name,
+                                     int argc, Object*** argv,
+                                     bool* caught_exception);
+  static Handle<Object> MakeExecutionState(bool* caught_exception);
+  static Handle<Object> MakeBreakEvent(Handle<Object> exec_state,
+                                       Handle<Object> break_points_hit,
+                                       bool* caught_exception);
+  static Handle<Object> MakeExceptionEvent(Handle<Object> exec_state,
+                                           Handle<Object> exception,
+                                           bool uncaught,
+                                           bool* caught_exception);
+  static Handle<Object> MakeNewFunctionEvent(Handle<Object> func,
+                                             bool* caught_exception);
+  static Handle<Object> MakeCompileEvent(Handle<Script> script,
+                                         bool before,
+                                         bool* caught_exception);
+  static void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue);
+  static void OnException(Handle<Object> exception, bool uncaught);
+  static void OnBeforeCompile(Handle<Script> script);
+  static void OnAfterCompile(Handle<Script> script,
+                           Handle<JSFunction> fun);
+  static void OnNewFunction(Handle<JSFunction> fun);
+  static void ProcessDebugEvent(v8::DebugEvent event,
+                                Handle<Object> event_data,
+                                bool auto_continue);
+  static void NotifyMessageHandler(v8::DebugEvent event,
+                                   Handle<Object> exec_state,
+                                   Handle<Object> event_data,
+                                   bool auto_continue);
+  static void SetEventListener(Handle<Object> callback, Handle<Object> data);
+  static void SetMessageHandler(v8::DebugMessageHandler handler, void* data,
+                                bool message_handler_thread);
+  static void TearDown();
+  static void SetHostDispatchHandler(v8::DebugHostDispatchHandler handler,
+                                     void* data);
+
+  // Invoke the message handler function.
+  static void InvokeMessageHandler(Vector< uint16_t> message);
+
+  // Send a message to the message handler eiher through the message thread or
+  // directly.
+  static void SendMessage(Vector<uint16_t> message);
+
+  // Send the JSON message for a debug event.
+  static bool SendEventMessage(Handle<Object> event_data);
+
+  // Add a debugger command to the command queue.
+  static void ProcessCommand(Vector<const uint16_t> command);
+
+  // Check whether there are commands in the command queue.
+  static bool HasCommands();
+
+  static void ProcessHostDispatch(void* dispatch);
+  static Handle<Object> Call(Handle<JSFunction> fun,
+                             Handle<Object> data,
+                             bool* pending_exception);
+
+  // Start the debugger agent listening on the provided port.
+  static bool StartAgent(const char* name, int port);
+
+  // Stop the debugger agent.
+  static void StopAgent();
+
+  // Unload the debugger if possible. Only called when no debugger is currently
+  // active.
+  static void UnloadDebugger();
+
+  inline static bool EventActive(v8::DebugEvent event) {
+    ScopedLock with(debugger_access_);
+
+    // Check whether the message handler was been cleared.
+    if (message_handler_cleared_) {
+      UnloadDebugger();
+    }
+
+    // Currently argument event is not used.
+    return !compiling_natives_ && Debugger::IsDebuggerActive();
+  }
+
+  static void set_compiling_natives(bool compiling_natives) {
+    Debugger::compiling_natives_ = compiling_natives;
+  }
+  static bool compiling_natives() { return Debugger::compiling_natives_; }
+  static void set_loading_debugger(bool v) { is_loading_debugger_ = v; }
+  static bool is_loading_debugger() { return Debugger::is_loading_debugger_; }
+
+ private:
+  static bool IsDebuggerActive();
+
+  static Mutex* debugger_access_;  // Mutex guarding debugger variables.
+  static Handle<Object> event_listener_;  // Global handle to listener.
+  static Handle<Object> event_listener_data_;
+  static bool compiling_natives_;  // Are we compiling natives?
+  static bool is_loading_debugger_;  // Are we loading the debugger?
+  static bool never_unload_debugger_;  // Can we unload the debugger?
+  static DebugMessageThread* message_thread_;
+  static v8::DebugMessageHandler message_handler_;
+  static bool message_handler_cleared_;  // Was message handler cleared?
+  static void* message_handler_data_;
+  static v8::DebugHostDispatchHandler host_dispatch_handler_;
+  static void* host_dispatch_handler_data_;
+
+  static DebuggerAgent* agent_;
+
+  static const int kQueueInitialSize = 4;
+  static LockingMessageQueue command_queue_;
+  static LockingMessageQueue message_queue_;
+  static Semaphore* command_received_;  // Signaled for each command received.
+  static Semaphore* message_received_;  // Signalled for each message send.
+
+  friend class EnterDebugger;
+  friend class DebugMessageThread;
+};
+
+
+// Thread to read messages from the message queue and invoke the debug message
+// handler in another thread as the V8 thread. This thread is started if the
+// registration of the debug message handler requested to be called in a thread
+// seperate from the V8 thread.
+class DebugMessageThread: public Thread {
+ public:
+  DebugMessageThread() : keep_running_(true) {}
+  virtual ~DebugMessageThread() {}
+
+  // Main function of DebugMessageThread thread.
+  void Run();
+  void Stop();
+
+ private:
+  bool keep_running_;
+  DISALLOW_COPY_AND_ASSIGN(DebugMessageThread);
+};
+
+
+// This class is used for entering the debugger. Create an instance in the stack
+// to enter the debugger. This will set the current break state, make sure the
+// debugger is loaded and switch to the debugger context. If the debugger for
+// some reason could not be entered FailedToEnter will return true.
+class EnterDebugger BASE_EMBEDDED {
+ public:
+  EnterDebugger()
+      : prev_(Debug::debugger_entry()),
+        has_js_frames_(!it_.done()) {
+    ASSERT(prev_ == NULL ? !Debug::preemption_pending() : true);
+
+    // Link recursive debugger entry.
+    Debug::set_debugger_entry(this);
+
+    // Store the previous break id and frame id.
+    break_id_ = Debug::break_id();
+    break_frame_id_ = Debug::break_frame_id();
+
+    // Create the new break info. If there is no JavaScript frames there is no
+    // break frame id.
+    if (has_js_frames_) {
+      Debug::NewBreak(it_.frame()->id());
+    } else {
+      Debug::NewBreak(StackFrame::NO_ID);
+    }
+
+    // Make sure that debugger is loaded and enter the debugger context.
+    load_failed_ = !Debug::Load();
+    if (!load_failed_) {
+      // NOTE the member variable save which saves the previous context before
+      // this change.
+      Top::set_context(*Debug::debug_context());
+    }
+  }
+
+  ~EnterDebugger() {
+    // Restore to the previous break state.
+    Debug::SetBreak(break_frame_id_, break_id_);
+
+    // Request preemption when leaving the last debugger entry and a preemption
+    // had been recorded while debugging. This is to avoid starvation in some
+    // debugging scenarios.
+    if (prev_ == NULL && Debug::preemption_pending()) {
+      StackGuard::Preempt();
+      Debug::set_preemption_pending(false);
+    }
+
+    // If there are commands in the queue when leaving the debugger request that
+    // these commands are processed.
+    if (prev_ == NULL && Debugger::HasCommands()) {
+      StackGuard::DebugCommand();
+    }
+
+    // If leaving the debugger with the debugger no longer active unload it.
+    if (prev_ == NULL) {
+      if (!Debugger::IsDebuggerActive()) {
+        Debugger::UnloadDebugger();
+      }
+    }
+
+    // Leaving this debugger entry.
+    Debug::set_debugger_entry(prev_);
+  }
+
+  // Check whether the debugger could be entered.
+  inline bool FailedToEnter() { return load_failed_; }
+
+  // Check whether there are any JavaScript frames on the stack.
+  inline bool HasJavaScriptFrames() { return has_js_frames_; }
+
+ private:
+  EnterDebugger* prev_;  // Previous debugger entry if entered recursively.
+  JavaScriptFrameIterator it_;
+  const bool has_js_frames_;  // Were there any JavaScript frames?
+  StackFrame::Id break_frame_id_;  // Previous break frame id.
+  int break_id_;  // Previous break id.
+  bool load_failed_;  // Did the debugger fail to load?
+  SaveContext save_;  // Saves previous context.
+};
+
+
+// Stack allocated class for disabling break.
+class DisableBreak BASE_EMBEDDED {
+ public:
+  // Enter the debugger by storing the previous top context and setting the
+  // current top context to the debugger context.
+  explicit DisableBreak(bool disable_break)  {
+    prev_disable_break_ = Debug::disable_break();
+    Debug::set_disable_break(disable_break);
+  }
+  ~DisableBreak() {
+    Debug::set_disable_break(prev_disable_break_);
+  }
+
+ private:
+  // The previous state of the disable break used to restore the value when this
+  // object is destructed.
+  bool prev_disable_break_;
+};
+
+
+// Debug_Address encapsulates the Address pointers used in generating debug
+// code.
+class Debug_Address {
+ public:
+  Debug_Address(Debug::AddressId id, int reg = 0)
+    : id_(id), reg_(reg) {
+    ASSERT(reg == 0 || id == Debug::k_register_address);
+  }
+
+  static Debug_Address AfterBreakTarget() {
+    return Debug_Address(Debug::k_after_break_target_address);
+  }
+
+  static Debug_Address DebugBreakReturn() {
+    return Debug_Address(Debug::k_debug_break_return_address);
+  }
+
+  static Debug_Address Register(int reg) {
+    return Debug_Address(Debug::k_register_address, reg);
+  }
+
+  Address address() const {
+    switch (id_) {
+      case Debug::k_after_break_target_address:
+        return reinterpret_cast<Address>(Debug::after_break_target_address());
+      case Debug::k_debug_break_return_address:
+        return reinterpret_cast<Address>(Debug::debug_break_return_address());
+      case Debug::k_register_address:
+        return reinterpret_cast<Address>(Debug::register_address(reg_));
+      default:
+        UNREACHABLE();
+        return NULL;
+    }
+  }
+ private:
+  Debug::AddressId id_;
+  int reg_;
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_V8_DEBUG_H_
diff --git a/deps/v8/src/disasm-arm.cc b/deps/v8/src/disasm-arm.cc
new file mode 100644
index 0000000..d19e042
--- /dev/null
+++ b/deps/v8/src/disasm-arm.cc
@@ -0,0 +1,891 @@
+// 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.
+
+// A Disassembler object is used to disassemble a block of code instruction by
+// instruction. The default implementation of the NameConverter object can be
+// overriden to modify register names or to do symbol lookup on addresses.
+//
+// The example below will disassemble a block of code and print it to stdout.
+//
+//   NameConverter converter;
+//   Disassembler d(converter);
+//   for (byte* pc = begin; pc < end;) {
+//     char buffer[128];
+//     buffer[0] = '\0';
+//     byte* prev_pc = pc;
+//     pc += d.InstructionDecode(buffer, sizeof buffer, pc);
+//     printf("%p    %08x      %s\n",
+//            prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
+//   }
+//
+// The Disassembler class also has a convenience method to disassemble a block
+// of code into a FILE*, meaning that the above functionality could also be
+// achieved by just calling Disassembler::Disassemble(stdout, begin, end);
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#ifndef WIN32
+#include <stdint.h>
+#endif
+
+#include "v8.h"
+
+#include "disasm.h"
+#include "macro-assembler.h"
+#include "platform.h"
+
+
+namespace assembler { namespace arm {
+
+namespace v8i = v8::internal;
+
+
+//------------------------------------------------------------------------------
+
+// Decoder decodes and disassembles instructions into an output buffer.
+// It uses the converter to convert register names and call destinations into
+// more informative description.
+class Decoder {
+ public:
+  Decoder(const disasm::NameConverter& converter,
+          v8::internal::Vector<char> out_buffer)
+    : converter_(converter),
+      out_buffer_(out_buffer),
+      out_buffer_pos_(0) {
+    out_buffer_[out_buffer_pos_] = '\0';
+  }
+
+  ~Decoder() {}
+
+  // Writes one disassembled instruction into 'buffer' (0-terminated).
+  // Returns the length of the disassembled machine instruction in bytes.
+  int InstructionDecode(byte* instruction);
+
+ private:
+  // Bottleneck functions to print into the out_buffer.
+  void PrintChar(const char ch);
+  void Print(const char* str);
+
+  // Printing of common values.
+  void PrintRegister(int reg);
+  void PrintCondition(Instr* instr);
+  void PrintShiftRm(Instr* instr);
+  void PrintShiftImm(Instr* instr);
+  void PrintPU(Instr* instr);
+  void PrintSoftwareInterrupt(SoftwareInterruptCodes swi);
+
+  // Handle formatting of instructions and their options.
+  int FormatRegister(Instr* instr, const char* option);
+  int FormatOption(Instr* instr, const char* option);
+  void Format(Instr* instr, const char* format);
+  void Unknown(Instr* instr);
+
+  // Each of these functions decodes one particular instruction type, a 3-bit
+  // field in the instruction encoding.
+  // Types 0 and 1 are combined as they are largely the same except for the way
+  // they interpret the shifter operand.
+  void DecodeType01(Instr* instr);
+  void DecodeType2(Instr* instr);
+  void DecodeType3(Instr* instr);
+  void DecodeType4(Instr* instr);
+  void DecodeType5(Instr* instr);
+  void DecodeType6(Instr* instr);
+  void DecodeType7(Instr* instr);
+
+  const disasm::NameConverter& converter_;
+  v8::internal::Vector<char> out_buffer_;
+  int out_buffer_pos_;
+
+  DISALLOW_COPY_AND_ASSIGN(Decoder);
+};
+
+
+// Support for assertions in the Decoder formatting functions.
+#define STRING_STARTS_WITH(string, compare_string) \
+  (strncmp(string, compare_string, strlen(compare_string)) == 0)
+
+
+// Append the ch to the output buffer.
+void Decoder::PrintChar(const char ch) {
+  out_buffer_[out_buffer_pos_++] = ch;
+}
+
+
+// Append the str to the output buffer.
+void Decoder::Print(const char* str) {
+  char cur = *str++;
+  while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
+    PrintChar(cur);
+    cur = *str++;
+  }
+  out_buffer_[out_buffer_pos_] = 0;
+}
+
+
+// These condition names are defined in a way to match the native disassembler
+// formatting. See for example the command "objdump -d <binary file>".
+static const char* cond_names[max_condition] = {
+  "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" ,
+  "hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
+};
+
+
+// Print the condition guarding the instruction.
+void Decoder::PrintCondition(Instr* instr) {
+  Print(cond_names[instr->ConditionField()]);
+}
+
+
+// Print the register name according to the active name converter.
+void Decoder::PrintRegister(int reg) {
+  Print(converter_.NameOfCPURegister(reg));
+}
+
+
+// These shift names are defined in a way to match the native disassembler
+// formatting. See for example the command "objdump -d <binary file>".
+static const char* shift_names[max_shift] = {
+  "lsl", "lsr", "asr", "ror"
+};
+
+
+// Print the register shift operands for the instruction. Generally used for
+// data processing instructions.
+void Decoder::PrintShiftRm(Instr* instr) {
+  Shift shift = instr->ShiftField();
+  int shift_amount = instr->ShiftAmountField();
+  int rm = instr->RmField();
+
+  PrintRegister(rm);
+
+  if ((instr->RegShiftField() == 0) && (shift == LSL) && (shift_amount == 0)) {
+    // Special case for using rm only.
+    return;
+  }
+  if (instr->RegShiftField() == 0) {
+    // by immediate
+    if ((shift == ROR) && (shift_amount == 0)) {
+      Print(", RRX");
+      return;
+    } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
+      shift_amount = 32;
+    }
+    out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                         ", %s #%d",
+                                         shift_names[shift], shift_amount);
+  } else {
+    // by register
+    int rs = instr->RsField();
+    out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                         ", %s ", shift_names[shift]);
+    PrintRegister(rs);
+  }
+}
+
+
+// Print the immediate operand for the instruction. Generally used for data
+// processing instructions.
+void Decoder::PrintShiftImm(Instr* instr) {
+  int rotate = instr->RotateField() * 2;
+  int immed8 = instr->Immed8Field();
+  int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
+  out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                       "#%d", imm);
+}
+
+
+// Print PU formatting to reduce complexity of FormatOption.
+void Decoder::PrintPU(Instr* instr) {
+  switch (instr->PUField()) {
+    case 0: {
+      Print("da");
+      break;
+    }
+    case 1: {
+      Print("ia");
+      break;
+    }
+    case 2: {
+      Print("db");
+      break;
+    }
+    case 3: {
+      Print("ib");
+      break;
+    }
+    default: {
+      UNREACHABLE();
+      break;
+    }
+  }
+}
+
+
+// Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
+// the FormatOption method.
+void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes swi) {
+  switch (swi) {
+    case call_rt_r5:
+      Print("call_rt_r5");
+      return;
+    case call_rt_r2:
+      Print("call_rt_r2");
+      return;
+    case break_point:
+      Print("break_point");
+      return;
+    default:
+      out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                           "%d",
+                                           swi);
+      return;
+  }
+}
+
+
+// Handle all register based formatting in this function to reduce the
+// complexity of FormatOption.
+int Decoder::FormatRegister(Instr* instr, const char* format) {
+  ASSERT(format[0] == 'r');
+  if (format[1] == 'n') {  // 'rn: Rn register
+    int reg = instr->RnField();
+    PrintRegister(reg);
+    return 2;
+  } else if (format[1] == 'd') {  // 'rd: Rd register
+    int reg = instr->RdField();
+    PrintRegister(reg);
+    return 2;
+  } else if (format[1] == 's') {  // 'rs: Rs register
+    int reg = instr->RsField();
+    PrintRegister(reg);
+    return 2;
+  } else if (format[1] == 'm') {  // 'rm: Rm register
+    int reg = instr->RmField();
+    PrintRegister(reg);
+    return 2;
+  } else if (format[1] == 'l') {
+    // 'rlist: register list for load and store multiple instructions
+    ASSERT(STRING_STARTS_WITH(format, "rlist"));
+    int rlist = instr->RlistField();
+    int reg = 0;
+    Print("{");
+    // Print register list in ascending order, by scanning the bit mask.
+    while (rlist != 0) {
+      if ((rlist & 1) != 0) {
+        PrintRegister(reg);
+        if ((rlist >> 1) != 0) {
+          Print(", ");
+        }
+      }
+      reg++;
+      rlist >>= 1;
+    }
+    Print("}");
+    return 5;
+  }
+  UNREACHABLE();
+  return -1;
+}
+
+
+// FormatOption takes a formatting string and interprets it based on
+// the current instructions. The format string points to the first
+// character of the option string (the option escape has already been
+// consumed by the caller.)  FormatOption returns the number of
+// characters that were consumed from the formatting string.
+int Decoder::FormatOption(Instr* instr, const char* format) {
+  switch (format[0]) {
+    case 'a': {  // 'a: accumulate multiplies
+      if (instr->Bit(21) == 0) {
+        Print("ul");
+      } else {
+        Print("la");
+      }
+      return 1;
+    }
+    case 'b': {  // 'b: byte loads or stores
+      if (instr->HasB()) {
+        Print("b");
+      }
+      return 1;
+    }
+    case 'c': {  // 'cond: conditional execution
+      ASSERT(STRING_STARTS_WITH(format, "cond"));
+      PrintCondition(instr);
+      return 4;
+    }
+    case 'h': {  // 'h: halfword operation for extra loads and stores
+      if (instr->HasH()) {
+        Print("h");
+      } else {
+        Print("b");
+      }
+      return 1;
+    }
+    case 'l': {  // 'l: branch and link
+      if (instr->HasLink()) {
+        Print("l");
+      }
+      return 1;
+    }
+    case 'm': {
+      if (format[1] == 'e') {  // 'memop: load/store instructions
+        ASSERT(STRING_STARTS_WITH(format, "memop"));
+        if (instr->HasL()) {
+          Print("ldr");
+        } else {
+          Print("str");
+        }
+        return 5;
+      }
+      // 'msg: for simulator break instructions
+      ASSERT(STRING_STARTS_WITH(format, "msg"));
+      byte* str =
+          reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff);
+      out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                           "%s", converter_.NameInCode(str));
+      return 3;
+    }
+    case 'o': {
+      if (format[3] == '1') {
+        // 'off12: 12-bit offset for load and store instructions
+        ASSERT(STRING_STARTS_WITH(format, "off12"));
+        out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                             "%d", instr->Offset12Field());
+        return 5;
+      }
+      // 'off8: 8-bit offset for extra load and store instructions
+      ASSERT(STRING_STARTS_WITH(format, "off8"));
+      int offs8 = (instr->ImmedHField() << 4) | instr->ImmedLField();
+      out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                           "%d", offs8);
+      return 4;
+    }
+    case 'p': {  // 'pu: P and U bits for load and store instructions
+      ASSERT(STRING_STARTS_WITH(format, "pu"));
+      PrintPU(instr);
+      return 2;
+    }
+    case 'r': {
+      return FormatRegister(instr, format);
+    }
+    case 's': {
+      if (format[1] == 'h') {  // 'shift_op or 'shift_rm
+        if (format[6] == 'o') {  // 'shift_op
+          ASSERT(STRING_STARTS_WITH(format, "shift_op"));
+          if (instr->TypeField() == 0) {
+            PrintShiftRm(instr);
+          } else {
+            ASSERT(instr->TypeField() == 1);
+            PrintShiftImm(instr);
+          }
+          return 8;
+        } else {  // 'shift_rm
+          ASSERT(STRING_STARTS_WITH(format, "shift_rm"));
+          PrintShiftRm(instr);
+          return 8;
+        }
+      } else if (format[1] == 'w') {  // 'swi
+        ASSERT(STRING_STARTS_WITH(format, "swi"));
+        PrintSoftwareInterrupt(instr->SwiField());
+        return 3;
+      } else if (format[1] == 'i') {  // 'sign: signed extra loads and stores
+        ASSERT(STRING_STARTS_WITH(format, "sign"));
+        if (instr->HasSign()) {
+          Print("s");
+        }
+        return 4;
+      }
+      // 's: S field of data processing instructions
+      if (instr->HasS()) {
+        Print("s");
+      }
+      return 1;
+    }
+    case 't': {  // 'target: target of branch instructions
+      ASSERT(STRING_STARTS_WITH(format, "target"));
+      int off = (instr->SImmed24Field() << 2) + 8;
+      out_buffer_pos_ += v8i::OS::SNPrintF(
+          out_buffer_ + out_buffer_pos_,
+          "%+d -> %s",
+          off,
+          converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off));
+      return 6;
+    }
+    case 'u': {  // 'u: signed or unsigned multiplies
+      if (instr->Bit(22) == 0) {
+        Print("u");
+      } else {
+        Print("s");
+      }
+      return 1;
+    }
+    case 'w': {  // 'w: W field of load and store instructions
+      if (instr->HasW()) {
+        Print("!");
+      }
+      return 1;
+    }
+    default: {
+      UNREACHABLE();
+      break;
+    }
+  }
+  UNREACHABLE();
+  return -1;
+}
+
+
+// Format takes a formatting string for a whole instruction and prints it into
+// the output buffer. All escaped options are handed to FormatOption to be
+// parsed further.
+void Decoder::Format(Instr* instr, const char* format) {
+  char cur = *format++;
+  while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
+    if (cur == '\'') {  // Single quote is used as the formatting escape.
+      format += FormatOption(instr, format);
+    } else {
+      out_buffer_[out_buffer_pos_++] = cur;
+    }
+    cur = *format++;
+  }
+  out_buffer_[out_buffer_pos_]  = '\0';
+}
+
+
+// For currently unimplemented decodings the disassembler calls Unknown(instr)
+// which will just print "unknown" of the instruction bits.
+void Decoder::Unknown(Instr* instr) {
+  Format(instr, "unknown");
+}
+
+
+void Decoder::DecodeType01(Instr* instr) {
+  int type = instr->TypeField();
+  if ((type == 0) && instr->IsSpecialType0()) {
+    // multiply instruction or extra loads and stores
+    if (instr->Bits(7, 4) == 9) {
+      if (instr->Bit(24) == 0) {
+        // multiply instructions
+        if (instr->Bit(23) == 0) {
+          if (instr->Bit(21) == 0) {
+            Format(instr, "mul'cond's 'rd, 'rm, 'rs");
+          } else {
+            Format(instr, "mla'cond's 'rd, 'rm, 'rs, 'rn");
+          }
+        } else {
+          Format(instr, "'um'al'cond's 'rn, 'rd, 'rs, 'rm");
+        }
+      } else {
+        Unknown(instr);  // not used by V8
+      }
+    } else {
+      // extra load/store instructions
+      switch (instr->PUField()) {
+        case 0: {
+          if (instr->Bit(22) == 0) {
+            Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
+          } else {
+            Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
+          }
+          break;
+        }
+        case 1: {
+          if (instr->Bit(22) == 0) {
+            Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
+          } else {
+            Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
+          }
+          break;
+        }
+        case 2: {
+          if (instr->Bit(22) == 0) {
+            Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
+          } else {
+            Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
+          }
+          break;
+        }
+        case 3: {
+          if (instr->Bit(22) == 0) {
+            Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
+          } else {
+            Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
+          }
+          break;
+        }
+        default: {
+          // The PU field is a 2-bit field.
+          UNREACHABLE();
+          break;
+        }
+      }
+      return;
+    }
+  } else {
+    switch (instr->OpcodeField()) {
+      case AND: {
+        Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
+        break;
+      }
+      case EOR: {
+        Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
+        break;
+      }
+      case SUB: {
+        Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
+        break;
+      }
+      case RSB: {
+        Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
+        break;
+      }
+      case ADD: {
+        Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
+        break;
+      }
+      case ADC: {
+        Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
+        break;
+      }
+      case SBC: {
+        Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
+        break;
+      }
+      case RSC: {
+        Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
+        break;
+      }
+      case TST: {
+        if (instr->HasS()) {
+          Format(instr, "tst'cond 'rn, 'shift_op");
+        } else {
+          Unknown(instr);  // not used by V8
+        }
+        break;
+      }
+      case TEQ: {
+        if (instr->HasS()) {
+          Format(instr, "teq'cond 'rn, 'shift_op");
+        } else {
+          Unknown(instr);  // not used by V8
+        }
+        break;
+      }
+      case CMP: {
+        if (instr->HasS()) {
+          Format(instr, "cmp'cond 'rn, 'shift_op");
+        } else {
+          Unknown(instr);  // not used by V8
+        }
+        break;
+      }
+      case CMN: {
+        if (instr->HasS()) {
+          Format(instr, "cmn'cond 'rn, 'shift_op");
+        } else {
+          Unknown(instr);  // not used by V8
+        }
+        break;
+      }
+      case ORR: {
+        Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
+        break;
+      }
+      case MOV: {
+        Format(instr, "mov'cond's 'rd, 'shift_op");
+        break;
+      }
+      case BIC: {
+        Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
+        break;
+      }
+      case MVN: {
+        Format(instr, "mvn'cond's 'rd, 'shift_op");
+        break;
+      }
+      default: {
+        // The Opcode field is a 4-bit field.
+        UNREACHABLE();
+        break;
+      }
+    }
+  }
+}
+
+
+void Decoder::DecodeType2(Instr* instr) {
+  switch (instr->PUField()) {
+    case 0: {
+      if (instr->HasW()) {
+        Unknown(instr);  // not used in V8
+      }
+      Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
+      break;
+    }
+    case 1: {
+      if (instr->HasW()) {
+        Unknown(instr);  // not used in V8
+      }
+      Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
+      break;
+    }
+    case 2: {
+      Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
+      break;
+    }
+    case 3: {
+      Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
+      break;
+    }
+    default: {
+      // The PU field is a 2-bit field.
+      UNREACHABLE();
+      break;
+    }
+  }
+}
+
+
+void Decoder::DecodeType3(Instr* instr) {
+  switch (instr->PUField()) {
+    case 0: {
+      ASSERT(!instr->HasW());
+      Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
+      break;
+    }
+    case 1: {
+      ASSERT(!instr->HasW());
+      Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
+      break;
+    }
+    case 2: {
+      Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
+      break;
+    }
+    case 3: {
+      Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
+      break;
+    }
+    default: {
+      // The PU field is a 2-bit field.
+      UNREACHABLE();
+      break;
+    }
+  }
+}
+
+
+void Decoder::DecodeType4(Instr* instr) {
+  ASSERT(instr->Bit(22) == 0);  // Privileged mode currently not supported.
+  if (instr->HasL()) {
+    Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
+  } else {
+    Format(instr, "stm'cond'pu 'rn'w, 'rlist");
+  }
+}
+
+
+void Decoder::DecodeType5(Instr* instr) {
+  Format(instr, "b'l'cond 'target");
+}
+
+
+void Decoder::DecodeType6(Instr* instr) {
+  // Coprocessor instructions currently not supported.
+  Unknown(instr);
+}
+
+
+void Decoder::DecodeType7(Instr* instr) {
+  if (instr->Bit(24) == 1) {
+    Format(instr, "swi'cond 'swi");
+  } else {
+    // Coprocessor instructions currently not supported.
+    Unknown(instr);
+  }
+}
+
+
+// Disassemble the instruction at *instr_ptr into the output buffer.
+int Decoder::InstructionDecode(byte* instr_ptr) {
+  Instr* instr = Instr::At(instr_ptr);
+  // Print raw instruction bytes.
+  out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                       "%08x       ",
+                                       instr->InstructionBits());
+  if (instr->ConditionField() == special_condition) {
+    Format(instr, "break 'msg");
+    return Instr::kInstrSize;
+  }
+  switch (instr->TypeField()) {
+    case 0:
+    case 1: {
+      DecodeType01(instr);
+      break;
+    }
+    case 2: {
+      DecodeType2(instr);
+      break;
+    }
+    case 3: {
+      DecodeType3(instr);
+      break;
+    }
+    case 4: {
+      DecodeType4(instr);
+      break;
+    }
+    case 5: {
+      DecodeType5(instr);
+      break;
+    }
+    case 6: {
+      DecodeType6(instr);
+      break;
+    }
+    case 7: {
+      DecodeType7(instr);
+      break;
+    }
+    default: {
+      // The type field is 3-bits in the ARM encoding.
+      UNREACHABLE();
+      break;
+    }
+  }
+  return Instr::kInstrSize;
+}
+
+
+} }  // namespace assembler::arm
+
+
+
+//------------------------------------------------------------------------------
+
+namespace disasm {
+
+namespace v8i = v8::internal;
+
+
+static const int kMaxRegisters = 16;
+
+// These register names are defined in a way to match the native disassembler
+// formatting. See for example the command "objdump -d <binary file>".
+static const char* reg_names[kMaxRegisters] = {
+  "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+  "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc",
+};
+
+
+const char* NameConverter::NameOfAddress(byte* addr) const {
+  static v8::internal::EmbeddedVector<char, 32> tmp_buffer;
+  v8::internal::OS::SNPrintF(tmp_buffer, "%p", addr);
+  return tmp_buffer.start();
+}
+
+
+const char* NameConverter::NameOfConstant(byte* addr) const {
+  return NameOfAddress(addr);
+}
+
+
+const char* NameConverter::NameOfCPURegister(int reg) const {
+  const char* result;
+  if ((0 <= reg) && (reg < kMaxRegisters)) {
+    result = reg_names[reg];
+  } else {
+    result = "noreg";
+  }
+  return result;
+}
+
+
+const char* NameConverter::NameOfByteCPURegister(int reg) const {
+  UNREACHABLE();  // ARM does not have the concept of a byte register
+  return "nobytereg";
+}
+
+
+const char* NameConverter::NameOfXMMRegister(int reg) const {
+  UNREACHABLE();  // ARM does not have any XMM registers
+  return "noxmmreg";
+}
+
+
+const char* NameConverter::NameInCode(byte* addr) const {
+  // The default name converter is called for unknown code. So we will not try
+  // to access any memory.
+  return "";
+}
+
+
+//------------------------------------------------------------------------------
+
+Disassembler::Disassembler(const NameConverter& converter)
+    : converter_(converter) {}
+
+
+Disassembler::~Disassembler() {}
+
+
+int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
+                                    byte* instruction) {
+  assembler::arm::Decoder d(converter_, buffer);
+  return d.InstructionDecode(instruction);
+}
+
+
+int Disassembler::ConstantPoolSizeAt(byte* instruction) {
+  int instruction_bits = *(reinterpret_cast<int*>(instruction));
+  if ((instruction_bits & 0xfff00000) == 0x03000000) {
+    return instruction_bits & 0x0000ffff;
+  } else {
+    return -1;
+  }
+}
+
+
+void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
+  NameConverter converter;
+  Disassembler d(converter);
+  for (byte* pc = begin; pc < end;) {
+    v8::internal::EmbeddedVector<char, 128> buffer;
+    buffer[0] = '\0';
+    byte* prev_pc = pc;
+    pc += d.InstructionDecode(buffer, pc);
+    fprintf(f, "%p    %08x      %s\n",
+            prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
+  }
+}
+
+
+}  // namespace disasm
diff --git a/deps/v8/src/disasm-ia32.cc b/deps/v8/src/disasm-ia32.cc
new file mode 100644
index 0000000..458844e
--- /dev/null
+++ b/deps/v8/src/disasm-ia32.cc
@@ -0,0 +1,1202 @@
+// 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.
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "v8.h"
+#include "disasm.h"
+
+namespace disasm {
+
+enum OperandOrder {
+  UNSET_OP_ORDER = 0,
+  REG_OPER_OP_ORDER,
+  OPER_REG_OP_ORDER
+};
+
+
+//------------------------------------------------------------------
+// Tables
+//------------------------------------------------------------------
+struct ByteMnemonic {
+  int b;  // -1 terminates, otherwise must be in range (0..255)
+  const char* mnem;
+  OperandOrder op_order_;
+};
+
+
+static ByteMnemonic two_operands_instr[] = {
+  {0x03, "add", REG_OPER_OP_ORDER},
+  {0x21, "and", OPER_REG_OP_ORDER},
+  {0x23, "and", REG_OPER_OP_ORDER},
+  {0x3B, "cmp", REG_OPER_OP_ORDER},
+  {0x8D, "lea", REG_OPER_OP_ORDER},
+  {0x09, "or", OPER_REG_OP_ORDER},
+  {0x0B, "or", REG_OPER_OP_ORDER},
+  {0x1B, "sbb", REG_OPER_OP_ORDER},
+  {0x29, "sub", OPER_REG_OP_ORDER},
+  {0x2B, "sub", REG_OPER_OP_ORDER},
+  {0x85, "test", REG_OPER_OP_ORDER},
+  {0x31, "xor", OPER_REG_OP_ORDER},
+  {0x33, "xor", REG_OPER_OP_ORDER},
+  {0x87, "xchg", REG_OPER_OP_ORDER},
+  {0x8A, "mov_b", REG_OPER_OP_ORDER},
+  {0x8B, "mov", REG_OPER_OP_ORDER},
+  {-1, "", UNSET_OP_ORDER}
+};
+
+
+static ByteMnemonic zero_operands_instr[] = {
+  {0xC3, "ret", UNSET_OP_ORDER},
+  {0xC9, "leave", UNSET_OP_ORDER},
+  {0x90, "nop", UNSET_OP_ORDER},
+  {0xF4, "hlt", UNSET_OP_ORDER},
+  {0xCC, "int3", UNSET_OP_ORDER},
+  {0x60, "pushad", UNSET_OP_ORDER},
+  {0x61, "popad", UNSET_OP_ORDER},
+  {0x9C, "pushfd", UNSET_OP_ORDER},
+  {0x9D, "popfd", UNSET_OP_ORDER},
+  {0x9E, "sahf", UNSET_OP_ORDER},
+  {0x99, "cdq", UNSET_OP_ORDER},
+  {0x9B, "fwait", UNSET_OP_ORDER},
+  {-1, "", UNSET_OP_ORDER}
+};
+
+
+static ByteMnemonic call_jump_instr[] = {
+  {0xE8, "call", UNSET_OP_ORDER},
+  {0xE9, "jmp", UNSET_OP_ORDER},
+  {-1, "", UNSET_OP_ORDER}
+};
+
+
+static ByteMnemonic short_immediate_instr[] = {
+  {0x05, "add", UNSET_OP_ORDER},
+  {0x0D, "or", UNSET_OP_ORDER},
+  {0x15, "adc", UNSET_OP_ORDER},
+  {0x25, "and", UNSET_OP_ORDER},
+  {0x2D, "sub", UNSET_OP_ORDER},
+  {0x35, "xor", UNSET_OP_ORDER},
+  {0x3D, "cmp", UNSET_OP_ORDER},
+  {-1, "", UNSET_OP_ORDER}
+};
+
+
+static const char* jump_conditional_mnem[] = {
+  /*0*/ "jo", "jno", "jc", "jnc",
+  /*4*/ "jz", "jnz", "jna", "ja",
+  /*8*/ "js", "jns", "jpe", "jpo",
+  /*12*/ "jl", "jnl", "jng", "jg"
+};
+
+
+static const char* set_conditional_mnem[] = {
+  /*0*/ "seto", "setno", "setc", "setnc",
+  /*4*/ "setz", "setnz", "setna", "seta",
+  /*8*/ "sets", "setns", "setpe", "setpo",
+  /*12*/ "setl", "setnl", "setng", "setg"
+};
+
+
+enum InstructionType {
+  NO_INSTR,
+  ZERO_OPERANDS_INSTR,
+  TWO_OPERANDS_INSTR,
+  JUMP_CONDITIONAL_SHORT_INSTR,
+  REGISTER_INSTR,
+  MOVE_REG_INSTR,
+  CALL_JUMP_INSTR,
+  SHORT_IMMEDIATE_INSTR
+};
+
+
+struct InstructionDesc {
+  const char* mnem;
+  InstructionType type;
+  OperandOrder op_order_;
+};
+
+
+class InstructionTable {
+ public:
+  InstructionTable();
+  const InstructionDesc& Get(byte x) const { return instructions_[x]; }
+
+ private:
+  InstructionDesc instructions_[256];
+  void Clear();
+  void Init();
+  void CopyTable(ByteMnemonic bm[], InstructionType type);
+  void SetTableRange(InstructionType type,
+                     byte start,
+                     byte end,
+                     const char* mnem);
+  void AddJumpConditionalShort();
+};
+
+
+InstructionTable::InstructionTable() {
+  Clear();
+  Init();
+}
+
+
+void InstructionTable::Clear() {
+  for (int i = 0; i < 256; i++) {
+    instructions_[i].mnem = "";
+    instructions_[i].type = NO_INSTR;
+    instructions_[i].op_order_ = UNSET_OP_ORDER;
+  }
+}
+
+
+void InstructionTable::Init() {
+  CopyTable(two_operands_instr, TWO_OPERANDS_INSTR);
+  CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR);
+  CopyTable(call_jump_instr, CALL_JUMP_INSTR);
+  CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR);
+  AddJumpConditionalShort();
+  SetTableRange(REGISTER_INSTR, 0x40, 0x47, "inc");
+  SetTableRange(REGISTER_INSTR, 0x48, 0x4F, "dec");
+  SetTableRange(REGISTER_INSTR, 0x50, 0x57, "push");
+  SetTableRange(REGISTER_INSTR, 0x58, 0x5F, "pop");
+  SetTableRange(REGISTER_INSTR, 0x91, 0x97, "xchg eax,");  // 0x90 is nop.
+  SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, "mov");
+}
+
+
+void InstructionTable::CopyTable(ByteMnemonic bm[], InstructionType type) {
+  for (int i = 0; bm[i].b >= 0; i++) {
+    InstructionDesc* id = &instructions_[bm[i].b];
+    id->mnem = bm[i].mnem;
+    id->op_order_ = bm[i].op_order_;
+    assert(id->type == NO_INSTR);  // Information already entered
+    id->type = type;
+  }
+}
+
+
+void InstructionTable::SetTableRange(InstructionType type,
+                                     byte start,
+                                     byte end,
+                                     const char* mnem) {
+  for (byte b = start; b <= end; b++) {
+    InstructionDesc* id = &instructions_[b];
+    assert(id->type == NO_INSTR);  // Information already entered
+    id->mnem = mnem;
+    id->type = type;
+  }
+}
+
+
+void InstructionTable::AddJumpConditionalShort() {
+  for (byte b = 0x70; b <= 0x7F; b++) {
+    InstructionDesc* id = &instructions_[b];
+    assert(id->type == NO_INSTR);  // Information already entered
+    id->mnem = jump_conditional_mnem[b & 0x0F];
+    id->type = JUMP_CONDITIONAL_SHORT_INSTR;
+  }
+}
+
+
+static InstructionTable instruction_table;
+
+
+// The IA32 disassembler implementation.
+class DisassemblerIA32 {
+ public:
+  DisassemblerIA32(const NameConverter& converter,
+                   bool abort_on_unimplemented = true)
+      : converter_(converter),
+        tmp_buffer_pos_(0),
+        abort_on_unimplemented_(abort_on_unimplemented) {
+    tmp_buffer_[0] = '\0';
+  }
+
+  virtual ~DisassemblerIA32() {}
+
+  // Writes one disassembled instruction into 'buffer' (0-terminated).
+  // Returns the length of the disassembled machine instruction in bytes.
+  int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction);
+
+ private:
+  const NameConverter& converter_;
+  v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
+  unsigned int tmp_buffer_pos_;
+  bool abort_on_unimplemented_;
+
+
+  enum {
+    eax = 0,
+    ecx = 1,
+    edx = 2,
+    ebx = 3,
+    esp = 4,
+    ebp = 5,
+    esi = 6,
+    edi = 7
+  };
+
+
+  const char* NameOfCPURegister(int reg) const {
+    return converter_.NameOfCPURegister(reg);
+  }
+
+
+  const char* NameOfByteCPURegister(int reg) const {
+    return converter_.NameOfByteCPURegister(reg);
+  }
+
+
+  const char* NameOfXMMRegister(int reg) const {
+    return converter_.NameOfXMMRegister(reg);
+  }
+
+
+  const char* NameOfAddress(byte* addr) const {
+    return converter_.NameOfAddress(addr);
+  }
+
+
+  // Disassembler helper functions.
+  static void get_modrm(byte data, int* mod, int* regop, int* rm) {
+    *mod = (data >> 6) & 3;
+    *regop = (data & 0x38) >> 3;
+    *rm = data & 7;
+  }
+
+
+  static void get_sib(byte data, int* scale, int* index, int* base) {
+    *scale = (data >> 6) & 3;
+    *index = (data >> 3) & 7;
+    *base = data & 7;
+  }
+
+  typedef const char* (DisassemblerIA32::*RegisterNameMapping)(int reg) const;
+
+  int PrintRightOperandHelper(byte* modrmp, RegisterNameMapping register_name);
+  int PrintRightOperand(byte* modrmp);
+  int PrintRightByteOperand(byte* modrmp);
+  int PrintOperands(const char* mnem, OperandOrder op_order, byte* data);
+  int PrintImmediateOp(byte* data);
+  int F7Instruction(byte* data);
+  int D1D3C1Instruction(byte* data);
+  int JumpShort(byte* data);
+  int JumpConditional(byte* data, const char* comment);
+  int JumpConditionalShort(byte* data, const char* comment);
+  int SetCC(byte* data);
+  int FPUInstruction(byte* data);
+  void AppendToBuffer(const char* format, ...);
+
+
+  void UnimplementedInstruction() {
+    if (abort_on_unimplemented_) {
+      UNIMPLEMENTED();
+    } else {
+      AppendToBuffer("'Unimplemented Instruction'");
+    }
+  }
+};
+
+
+void DisassemblerIA32::AppendToBuffer(const char* format, ...) {
+  v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_;
+  va_list args;
+  va_start(args, format);
+  int result = v8::internal::OS::VSNPrintF(buf, format, args);
+  va_end(args);
+  tmp_buffer_pos_ += result;
+}
+
+int DisassemblerIA32::PrintRightOperandHelper(
+    byte* modrmp,
+    RegisterNameMapping register_name) {
+  int mod, regop, rm;
+  get_modrm(*modrmp, &mod, &regop, &rm);
+  switch (mod) {
+    case 0:
+      if (rm == ebp) {
+        int32_t disp = *reinterpret_cast<int32_t*>(modrmp+1);
+        AppendToBuffer("[0x%x]", disp);
+        return 5;
+      } else if (rm == esp) {
+        byte sib = *(modrmp + 1);
+        int scale, index, base;
+        get_sib(sib, &scale, &index, &base);
+        if (index == esp && base == esp && scale == 0 /*times_1*/) {
+          AppendToBuffer("[%s]", (this->*register_name)(rm));
+          return 2;
+        } else if (base == ebp) {
+          int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2);
+          AppendToBuffer("[%s*%d+0x%x]",
+                         (this->*register_name)(index),
+                         1 << scale,
+                         disp);
+          return 6;
+        } else if (index != esp && base != ebp) {
+          // [base+index*scale]
+          AppendToBuffer("[%s+%s*%d]",
+                         (this->*register_name)(base),
+                         (this->*register_name)(index),
+                         1 << scale);
+          return 2;
+        } else {
+          UnimplementedInstruction();
+          return 1;
+        }
+      } else {
+        AppendToBuffer("[%s]", (this->*register_name)(rm));
+        return 1;
+      }
+      break;
+    case 1:  // fall through
+    case 2:
+      if (rm == esp) {
+        byte sib = *(modrmp + 1);
+        int scale, index, base;
+        get_sib(sib, &scale, &index, &base);
+        int disp =
+            mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 2) : *(modrmp + 2);
+        if (index == base && index == rm /*esp*/ && scale == 0 /*times_1*/) {
+          AppendToBuffer("[%s+0x%x]", (this->*register_name)(rm), disp);
+        } else {
+          AppendToBuffer("[%s+%s*%d+0x%x]",
+                         (this->*register_name)(base),
+                         (this->*register_name)(index),
+                         1 << scale,
+                         disp);
+        }
+        return mod == 2 ? 6 : 3;
+      } else {
+        // No sib.
+        int disp =
+            mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 1) : *(modrmp + 1);
+        AppendToBuffer("[%s+0x%x]", (this->*register_name)(rm), disp);
+        return mod == 2 ? 5 : 2;
+      }
+      break;
+    case 3:
+      AppendToBuffer("%s", (this->*register_name)(rm));
+      return 1;
+    default:
+      UnimplementedInstruction();
+      return 1;
+  }
+  UNREACHABLE();
+}
+
+
+int DisassemblerIA32::PrintRightOperand(byte* modrmp) {
+  return PrintRightOperandHelper(modrmp, &DisassemblerIA32::NameOfCPURegister);
+}
+
+
+int DisassemblerIA32::PrintRightByteOperand(byte* modrmp) {
+  return PrintRightOperandHelper(modrmp,
+                                 &DisassemblerIA32::NameOfByteCPURegister);
+}
+
+
+// Returns number of bytes used including the current *data.
+// Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'.
+int DisassemblerIA32::PrintOperands(const char* mnem,
+                                    OperandOrder op_order,
+                                    byte* data) {
+  byte modrm = *data;
+  int mod, regop, rm;
+  get_modrm(modrm, &mod, &regop, &rm);
+  int advance = 0;
+  switch (op_order) {
+    case REG_OPER_OP_ORDER: {
+      AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop));
+      advance = PrintRightOperand(data);
+      break;
+    }
+    case OPER_REG_OP_ORDER: {
+      AppendToBuffer("%s ", mnem);
+      advance = PrintRightOperand(data);
+      AppendToBuffer(",%s", NameOfCPURegister(regop));
+      break;
+    }
+    default:
+      UNREACHABLE();
+      break;
+  }
+  return advance;
+}
+
+
+// Returns number of bytes used by machine instruction, including *data byte.
+// Writes immediate instructions to 'tmp_buffer_'.
+int DisassemblerIA32::PrintImmediateOp(byte* data) {
+  bool sign_extension_bit = (*data & 0x02) != 0;
+  byte modrm = *(data+1);
+  int mod, regop, rm;
+  get_modrm(modrm, &mod, &regop, &rm);
+  const char* mnem = "Imm???";
+  switch (regop) {
+    case 0: mnem = "add"; break;
+    case 1: mnem = "or"; break;
+    case 2: mnem = "adc"; break;
+    case 4: mnem = "and"; break;
+    case 5: mnem = "sub"; break;
+    case 6: mnem = "xor"; break;
+    case 7: mnem = "cmp"; break;
+    default: UnimplementedInstruction();
+  }
+  AppendToBuffer("%s ", mnem);
+  int count = PrintRightOperand(data+1);
+  if (sign_extension_bit) {
+    AppendToBuffer(",0x%x", *(data + 1 + count));
+    return 1 + count + 1 /*int8*/;
+  } else {
+    AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + 1 + count));
+    return 1 + count + 4 /*int32_t*/;
+  }
+}
+
+
+// Returns number of bytes used, including *data.
+int DisassemblerIA32::F7Instruction(byte* data) {
+  assert(*data == 0xF7);
+  byte modrm = *(data+1);
+  int mod, regop, rm;
+  get_modrm(modrm, &mod, &regop, &rm);
+  if (mod == 3 && regop != 0) {
+    const char* mnem = NULL;
+    switch (regop) {
+      case 2: mnem = "not"; break;
+      case 3: mnem = "neg"; break;
+      case 4: mnem = "mul"; break;
+      case 7: mnem = "idiv"; break;
+      default: UnimplementedInstruction();
+    }
+    AppendToBuffer("%s %s", mnem, NameOfCPURegister(rm));
+    return 2;
+  } else if (mod == 3 && regop == eax) {
+    int32_t imm = *reinterpret_cast<int32_t*>(data+2);
+    AppendToBuffer("test %s,0x%x", NameOfCPURegister(rm), imm);
+    return 6;
+  } else if (regop == eax) {
+    AppendToBuffer("test ");
+    int count = PrintRightOperand(data+1);
+    int32_t imm = *reinterpret_cast<int32_t*>(data+1+count);
+    AppendToBuffer(",0x%x", imm);
+    return 1+count+4 /*int32_t*/;
+  } else {
+    UnimplementedInstruction();
+    return 2;
+  }
+}
+
+int DisassemblerIA32::D1D3C1Instruction(byte* data) {
+  byte op = *data;
+  assert(op == 0xD1 || op == 0xD3 || op == 0xC1);
+  byte modrm = *(data+1);
+  int mod, regop, rm;
+  get_modrm(modrm, &mod, &regop, &rm);
+  int imm8 = -1;
+  int num_bytes = 2;
+  if (mod == 3) {
+    const char* mnem = NULL;
+    if (op == 0xD1) {
+      imm8 = 1;
+      switch (regop) {
+        case edx: mnem = "rcl"; break;
+        case edi: mnem = "sar"; break;
+        case esp: mnem = "shl"; break;
+        default: UnimplementedInstruction();
+      }
+    } else if (op == 0xC1) {
+      imm8 = *(data+2);
+      num_bytes = 3;
+      switch (regop) {
+        case edx: mnem = "rcl"; break;
+        case esp: mnem = "shl"; break;
+        case ebp: mnem = "shr"; break;
+        case edi: mnem = "sar"; break;
+        default: UnimplementedInstruction();
+      }
+    } else if (op == 0xD3) {
+      switch (regop) {
+        case esp: mnem = "shl"; break;
+        case ebp: mnem = "shr"; break;
+        case edi: mnem = "sar"; break;
+        default: UnimplementedInstruction();
+      }
+    }
+    assert(mnem != NULL);
+    AppendToBuffer("%s %s,", mnem, NameOfCPURegister(rm));
+    if (imm8 > 0) {
+      AppendToBuffer("%d", imm8);
+    } else {
+      AppendToBuffer("cl");
+    }
+  } else {
+    UnimplementedInstruction();
+  }
+  return num_bytes;
+}
+
+
+// Returns number of bytes used, including *data.
+int DisassemblerIA32::JumpShort(byte* data) {
+  assert(*data == 0xEB);
+  byte b = *(data+1);
+  byte* dest = data + static_cast<int8_t>(b) + 2;
+  AppendToBuffer("jmp %s", NameOfAddress(dest));
+  return 2;
+}
+
+
+// Returns number of bytes used, including *data.
+int DisassemblerIA32::JumpConditional(byte* data, const char* comment) {
+  assert(*data == 0x0F);
+  byte cond = *(data+1) & 0x0F;
+  byte* dest = data + *reinterpret_cast<int32_t*>(data+2) + 6;
+  const char* mnem = jump_conditional_mnem[cond];
+  AppendToBuffer("%s %s", mnem, NameOfAddress(dest));
+  if (comment != NULL) {
+    AppendToBuffer(", %s", comment);
+  }
+  return 6;  // includes 0x0F
+}
+
+
+// Returns number of bytes used, including *data.
+int DisassemblerIA32::JumpConditionalShort(byte* data, const char* comment) {
+  byte cond = *data & 0x0F;
+  byte b = *(data+1);
+  byte* dest = data + static_cast<int8_t>(b) + 2;
+  const char* mnem = jump_conditional_mnem[cond];
+  AppendToBuffer("%s %s", mnem, NameOfAddress(dest));
+  if (comment != NULL) {
+    AppendToBuffer(", %s", comment);
+  }
+  return 2;
+}
+
+
+// Returns number of bytes used, including *data.
+int DisassemblerIA32::SetCC(byte* data) {
+  assert(*data == 0x0F);
+  byte cond = *(data+1) & 0x0F;
+  const char* mnem = set_conditional_mnem[cond];
+  AppendToBuffer("%s ", mnem);
+  PrintRightByteOperand(data+2);
+  return 3;  // includes 0x0F
+}
+
+
+// Returns number of bytes used, including *data.
+int DisassemblerIA32::FPUInstruction(byte* data) {
+  byte b1 = *data;
+  byte b2 = *(data + 1);
+  if (b1 == 0xD9) {
+    const char* mnem = NULL;
+    switch (b2) {
+      case 0xE8: mnem = "fld1"; break;
+      case 0xEE: mnem = "fldz"; break;
+      case 0xE1: mnem = "fabs"; break;
+      case 0xE0: mnem = "fchs"; break;
+      case 0xF8: mnem = "fprem"; break;
+      case 0xF5: mnem = "fprem1"; break;
+      case 0xF7: mnem = "fincstp"; break;
+      case 0xE4: mnem = "ftst"; break;
+    }
+    if (mnem != NULL) {
+      AppendToBuffer("%s", mnem);
+      return 2;
+    } else if ((b2 & 0xF8) == 0xC8) {
+      AppendToBuffer("fxch st%d", b2 & 0x7);
+      return 2;
+    } else {
+      int mod, regop, rm;
+      get_modrm(*(data+1), &mod, &regop, &rm);
+      const char* mnem = "?";
+      switch (regop) {
+        case eax: mnem = "fld_s"; break;
+        case ebx: mnem = "fstp_s"; break;
+        default: UnimplementedInstruction();
+      }
+      AppendToBuffer("%s ", mnem);
+      int count = PrintRightOperand(data + 1);
+      return count + 1;
+    }
+  } else if (b1 == 0xDD) {
+    if ((b2 & 0xF8) == 0xC0) {
+      AppendToBuffer("ffree st%d", b2 & 0x7);
+      return 2;
+    } else {
+      int mod, regop, rm;
+      get_modrm(*(data+1), &mod, &regop, &rm);
+      const char* mnem = "?";
+      switch (regop) {
+        case eax: mnem = "fld_d"; break;
+        case ebx: mnem = "fstp_d"; break;
+        default: UnimplementedInstruction();
+      }
+      AppendToBuffer("%s ", mnem);
+      int count = PrintRightOperand(data + 1);
+      return count + 1;
+    }
+  } else if (b1 == 0xDB) {
+    int mod, regop, rm;
+    get_modrm(*(data+1), &mod, &regop, &rm);
+    const char* mnem = "?";
+    switch (regop) {
+      case eax: mnem = "fild_s"; break;
+      case edx: mnem = "fist_s"; break;
+      case ebx: mnem = "fistp_s"; break;
+      default: UnimplementedInstruction();
+    }
+    AppendToBuffer("%s ", mnem);
+    int count = PrintRightOperand(data + 1);
+    return count + 1;
+  } else if (b1 == 0xDF) {
+    if (b2 == 0xE0) {
+      AppendToBuffer("fnstsw_ax");
+      return 2;
+    }
+    int mod, regop, rm;
+    get_modrm(*(data+1), &mod, &regop, &rm);
+    const char* mnem = "?";
+    switch (regop) {
+      case ebp: mnem = "fild_d"; break;
+      case edi: mnem = "fistp_d"; break;
+      default: UnimplementedInstruction();
+    }
+    AppendToBuffer("%s ", mnem);
+    int count = PrintRightOperand(data + 1);
+    return count + 1;
+  } else if (b1 == 0xDC || b1 == 0xDE) {
+    bool is_pop = (b1 == 0xDE);
+    if (is_pop && b2 == 0xD9) {
+      AppendToBuffer("fcompp");
+      return 2;
+    }
+    const char* mnem = "FP0xDC";
+    switch (b2 & 0xF8) {
+      case 0xC0: mnem = "fadd"; break;
+      case 0xE8: mnem = "fsub"; break;
+      case 0xC8: mnem = "fmul"; break;
+      case 0xF8: mnem = "fdiv"; break;
+      default: UnimplementedInstruction();
+    }
+    AppendToBuffer("%s%s st%d", mnem, is_pop ? "p" : "", b2 & 0x7);
+    return 2;
+  } else if (b1 == 0xDA && b2 == 0xE9) {
+    const char* mnem = "fucompp";
+    AppendToBuffer("%s", mnem);
+    return 2;
+  }
+  AppendToBuffer("Unknown FP instruction");
+  return 2;
+}
+
+
+// Mnemonics for instructions 0xF0 byte.
+// Returns NULL if the instruction is not handled here.
+static const char* F0Mnem(byte f0byte) {
+  switch (f0byte) {
+    case 0xA2: return "cpuid";
+    case 0x31: return "rdtsc";
+    case 0xBE: return "movsx_b";
+    case 0xBF: return "movsx_w";
+    case 0xB6: return "movzx_b";
+    case 0xB7: return "movzx_w";
+    case 0xAF: return "imul";
+    case 0xA5: return "shld";
+    case 0xAD: return "shrd";
+    case 0xAB: return "bts";
+    default: return NULL;
+  }
+}
+
+
+// Disassembled instruction '*instr' and writes it into 'out_buffer'.
+int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
+                                        byte* instr) {
+  tmp_buffer_pos_ = 0;  // starting to write as position 0
+  byte* data = instr;
+  // Check for hints.
+  const char* branch_hint = NULL;
+  // We use these two prefixes only with branch prediction
+  if (*data == 0x3E /*ds*/) {
+    branch_hint = "predicted taken";
+    data++;
+  } else if (*data == 0x2E /*cs*/) {
+    branch_hint = "predicted not taken";
+    data++;
+  }
+  bool processed = true;  // Will be set to false if the current instruction
+                          // is not in 'instructions' table.
+  const InstructionDesc& idesc = instruction_table.Get(*data);
+  switch (idesc.type) {
+    case ZERO_OPERANDS_INSTR:
+      AppendToBuffer(idesc.mnem);
+      data++;
+      break;
+
+    case TWO_OPERANDS_INSTR:
+      data++;
+      data += PrintOperands(idesc.mnem, idesc.op_order_, data);
+      break;
+
+    case JUMP_CONDITIONAL_SHORT_INSTR:
+      data += JumpConditionalShort(data, branch_hint);
+      break;
+
+    case REGISTER_INSTR:
+      AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07));
+      data++;
+      break;
+
+    case MOVE_REG_INSTR: {
+      byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1));
+      AppendToBuffer("mov %s,%s",
+                     NameOfCPURegister(*data & 0x07),
+                     NameOfAddress(addr));
+      data += 5;
+      break;
+    }
+
+    case CALL_JUMP_INSTR: {
+      byte* addr = data + *reinterpret_cast<int32_t*>(data+1) + 5;
+      AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
+      data += 5;
+      break;
+    }
+
+    case SHORT_IMMEDIATE_INSTR: {
+      byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1));
+      AppendToBuffer("%s eax, %s", idesc.mnem, NameOfAddress(addr));
+      data += 5;
+      break;
+    }
+
+    case NO_INSTR:
+      processed = false;
+      break;
+
+    default:
+      UNIMPLEMENTED();  // This type is not implemented.
+  }
+  //----------------------------
+  if (!processed) {
+    switch (*data) {
+      case 0xC2:
+        AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data+1));
+        data += 3;
+        break;
+
+      case 0x69:  // fall through
+      case 0x6B:
+        { int mod, regop, rm;
+          get_modrm(*(data+1), &mod, &regop, &rm);
+          int32_t imm =
+              *data == 0x6B ? *(data+2) : *reinterpret_cast<int32_t*>(data+2);
+          AppendToBuffer("imul %s,%s,0x%x",
+                         NameOfCPURegister(regop),
+                         NameOfCPURegister(rm),
+                         imm);
+          data += 2 + (*data == 0x6B ? 1 : 4);
+        }
+        break;
+
+      case 0xF6:
+        { int mod, regop, rm;
+          get_modrm(*(data+1), &mod, &regop, &rm);
+          if (mod == 3 && regop == eax) {
+            AppendToBuffer("test_b %s,%d", NameOfCPURegister(rm), *(data+2));
+          } else {
+            UnimplementedInstruction();
+          }
+          data += 3;
+        }
+        break;
+
+      case 0x81:  // fall through
+      case 0x83:  // 0x81 with sign extension bit set
+        data += PrintImmediateOp(data);
+        break;
+
+      case 0x0F:
+        { byte f0byte = *(data+1);
+          const char* f0mnem = F0Mnem(f0byte);
+          if (f0byte == 0xA2 || f0byte == 0x31) {
+            AppendToBuffer("%s", f0mnem);
+            data += 2;
+          } else if ((f0byte & 0xF0) == 0x80) {
+            data += JumpConditional(data, branch_hint);
+          } else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 ||
+                     f0byte == 0xB7 || f0byte == 0xAF) {
+            data += 2;
+            data += PrintOperands(f0mnem, REG_OPER_OP_ORDER, data);
+          } else if ((f0byte & 0xF0) == 0x90) {
+            data += SetCC(data);
+          } else {
+            data += 2;
+            if (f0byte == 0xAB || f0byte == 0xA5 || f0byte == 0xAD) {
+              // shrd, shld, bts
+              AppendToBuffer("%s ", f0mnem);
+              int mod, regop, rm;
+              get_modrm(*data, &mod, &regop, &rm);
+              data += PrintRightOperand(data);
+              if (f0byte == 0xAB) {
+                AppendToBuffer(",%s", NameOfCPURegister(regop));
+              } else {
+                AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
+              }
+            } else {
+              UnimplementedInstruction();
+            }
+          }
+        }
+        break;
+
+      case 0x8F:
+        { data++;
+          int mod, regop, rm;
+          get_modrm(*data, &mod, &regop, &rm);
+          if (regop == eax) {
+            AppendToBuffer("pop ");
+            data += PrintRightOperand(data);
+          }
+        }
+        break;
+
+      case 0xFF:
+        { data++;
+          int mod, regop, rm;
+          get_modrm(*data, &mod, &regop, &rm);
+          const char* mnem = NULL;
+          switch (regop) {
+            case esi: mnem = "push"; break;
+            case eax: mnem = "inc"; break;
+            case ecx: mnem = "dec"; break;
+            case edx: mnem = "call"; break;
+            case esp: mnem = "jmp"; break;
+            default: mnem = "???";
+          }
+          AppendToBuffer("%s ", mnem);
+          data += PrintRightOperand(data);
+        }
+        break;
+
+      case 0xC7:  // imm32, fall through
+      case 0xC6:  // imm8
+        { bool is_byte = *data == 0xC6;
+          data++;
+          AppendToBuffer("%s ", is_byte ? "mov_b" : "mov");
+          data += PrintRightOperand(data);
+          int32_t imm = is_byte ? *data : *reinterpret_cast<int32_t*>(data);
+          AppendToBuffer(",0x%x", imm);
+          data += is_byte ? 1 : 4;
+        }
+        break;
+
+      case 0x80:
+        { data++;
+          AppendToBuffer("%s ", "cmpb");
+          data += PrintRightOperand(data);
+          int32_t imm = *data;
+          AppendToBuffer(",0x%x", imm);
+          data++;
+        }
+        break;
+
+      case 0x88:  // 8bit, fall through
+      case 0x89:  // 32bit
+        { bool is_byte = *data == 0x88;
+          int mod, regop, rm;
+          data++;
+          get_modrm(*data, &mod, &regop, &rm);
+          AppendToBuffer("%s ", is_byte ? "mov_b" : "mov");
+          data += PrintRightOperand(data);
+          AppendToBuffer(",%s", NameOfCPURegister(regop));
+        }
+        break;
+
+      case 0x66:  // prefix
+        data++;
+        if (*data == 0x8B) {
+          data++;
+          data += PrintOperands("mov_w", REG_OPER_OP_ORDER, data);
+        } else if (*data == 0x89) {
+          data++;
+          int mod, regop, rm;
+          get_modrm(*data, &mod, &regop, &rm);
+          AppendToBuffer("mov_w ");
+          data += PrintRightOperand(data);
+          AppendToBuffer(",%s", NameOfCPURegister(regop));
+        } else {
+          UnimplementedInstruction();
+        }
+        break;
+
+      case 0xFE:
+        { data++;
+          int mod, regop, rm;
+          get_modrm(*data, &mod, &regop, &rm);
+          if (mod == 3 && regop == ecx) {
+            AppendToBuffer("dec_b %s", NameOfCPURegister(rm));
+          } else {
+            UnimplementedInstruction();
+          }
+          data++;
+        }
+        break;
+
+      case 0x68:
+        AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data+1));
+        data += 5;
+        break;
+
+      case 0x6A:
+        AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
+        data += 2;
+        break;
+
+      case 0xA8:
+        AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data+1));
+        data += 2;
+        break;
+
+      case 0xA9:
+        AppendToBuffer("test eax,0x%x", *reinterpret_cast<int32_t*>(data+1));
+        data += 5;
+        break;
+
+      case 0xD1:  // fall through
+      case 0xD3:  // fall through
+      case 0xC1:
+        data += D1D3C1Instruction(data);
+        break;
+
+      case 0xD9:  // fall through
+      case 0xDA:  // fall through
+      case 0xDB:  // fall through
+      case 0xDC:  // fall through
+      case 0xDD:  // fall through
+      case 0xDE:  // fall through
+      case 0xDF:
+        data += FPUInstruction(data);
+        break;
+
+      case 0xEB:
+        data += JumpShort(data);
+        break;
+
+      case 0xF2:
+        if (*(data+1) == 0x0F) {
+          byte b2 = *(data+2);
+          if (b2 == 0x11) {
+            AppendToBuffer("movsd ");
+            data += 3;
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            data += PrintRightOperand(data);
+            AppendToBuffer(",%s", NameOfXMMRegister(regop));
+          } else if (b2 == 0x10) {
+            data += 3;
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            AppendToBuffer("movsd %s,", NameOfXMMRegister(regop));
+            data += PrintRightOperand(data);
+          } else {
+            const char* mnem = "?";
+            switch (b2) {
+              case 0x2A: mnem = "cvtsi2sd"; break;
+              case 0x58: mnem = "addsd"; break;
+              case 0x59: mnem = "mulsd"; break;
+              case 0x5C: mnem = "subsd"; break;
+              case 0x5E: mnem = "divsd"; break;
+            }
+            data += 3;
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            if (b2 == 0x2A) {
+              AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
+              data += PrintRightOperand(data);
+            } else {
+              AppendToBuffer("%s %s,%s",
+                             mnem,
+                             NameOfXMMRegister(regop),
+                             NameOfXMMRegister(rm));
+              data++;
+            }
+          }
+        } else {
+          UnimplementedInstruction();
+        }
+        break;
+
+      case 0xF3:
+        if (*(data+1) == 0x0F && *(data+2) == 0x2C) {
+          data += 3;
+          data += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, data);
+        } else {
+          UnimplementedInstruction();
+        }
+        break;
+
+      case 0xF7:
+        data += F7Instruction(data);
+        break;
+
+      default:
+        UnimplementedInstruction();
+    }
+  }
+
+  if (tmp_buffer_pos_ < sizeof tmp_buffer_) {
+    tmp_buffer_[tmp_buffer_pos_] = '\0';
+  }
+
+  int instr_len = data - instr;
+  ASSERT(instr_len > 0);  // Ensure progress.
+
+  int outp = 0;
+  // Instruction bytes.
+  for (byte* bp = instr; bp < data; bp++) {
+    outp += v8::internal::OS::SNPrintF(out_buffer + outp,
+                                       "%02x",
+                                       *bp);
+  }
+  for (int i = 6 - instr_len; i >= 0; i--) {
+    outp += v8::internal::OS::SNPrintF(out_buffer + outp,
+                                       "  ");
+  }
+
+  outp += v8::internal::OS::SNPrintF(out_buffer + outp,
+                                     " %s",
+                                     tmp_buffer_.start());
+  return instr_len;
+}
+
+
+//------------------------------------------------------------------------------
+
+
+static const char* cpu_regs[8] = {
+  "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
+};
+
+
+static const char* byte_cpu_regs[8] = {
+  "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"
+};
+
+
+static const char* xmm_regs[8] = {
+  "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
+};
+
+
+const char* NameConverter::NameOfAddress(byte* addr) const {
+  static v8::internal::EmbeddedVector<char, 32> tmp_buffer;
+  v8::internal::OS::SNPrintF(tmp_buffer, "%p", addr);
+  return tmp_buffer.start();
+}
+
+
+const char* NameConverter::NameOfConstant(byte* addr) const {
+  return NameOfAddress(addr);
+}
+
+
+const char* NameConverter::NameOfCPURegister(int reg) const {
+  if (0 <= reg && reg < 8) return cpu_regs[reg];
+  return "noreg";
+}
+
+
+const char* NameConverter::NameOfByteCPURegister(int reg) const {
+  if (0 <= reg && reg < 8) return byte_cpu_regs[reg];
+  return "noreg";
+}
+
+
+const char* NameConverter::NameOfXMMRegister(int reg) const {
+  if (0 <= reg && reg < 8) return xmm_regs[reg];
+  return "noxmmreg";
+}
+
+
+const char* NameConverter::NameInCode(byte* addr) const {
+  // IA32 does not embed debug strings at the moment.
+  UNREACHABLE();
+  return "";
+}
+
+
+//------------------------------------------------------------------------------
+
+Disassembler::Disassembler(const NameConverter& converter)
+    : converter_(converter) {}
+
+
+Disassembler::~Disassembler() {}
+
+
+int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
+                                    byte* instruction) {
+  DisassemblerIA32 d(converter_, false /*do not crash if unimplemented*/);
+  return d.InstructionDecode(buffer, instruction);
+}
+
+
+// The IA-32 assembler does not currently use constant pools.
+int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; }
+
+
+/*static*/ void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
+  NameConverter converter;
+  Disassembler d(converter);
+  for (byte* pc = begin; pc < end;) {
+    v8::internal::EmbeddedVector<char, 128> buffer;
+    buffer[0] = '\0';
+    byte* prev_pc = pc;
+    pc += d.InstructionDecode(buffer, pc);
+    fprintf(f, "%p", prev_pc);
+    fprintf(f, "    ");
+
+    for (byte* bp = prev_pc; bp < pc; bp++) {
+      fprintf(f, "%02x",  *bp);
+    }
+    for (int i = 6 - (pc - prev_pc); i >= 0; i--) {
+      fprintf(f, "  ");
+    }
+    fprintf(f, "  %s\n", buffer.start());
+  }
+}
+
+
+}  // namespace disasm
diff --git a/deps/v8/src/disasm.h b/deps/v8/src/disasm.h
new file mode 100644
index 0000000..6ecd1c8
--- /dev/null
+++ b/deps/v8/src/disasm.h
@@ -0,0 +1,77 @@
+// 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.
+
+#ifndef V8_DISASM_H_
+#define V8_DISASM_H_
+
+namespace disasm {
+
+typedef unsigned char byte;
+
+// Interface and default implementation for converting addresses and
+// register-numbers to text.  The default implementation is machine
+// specific.
+class NameConverter {
+ public:
+  virtual ~NameConverter() {}
+  virtual const char* NameOfCPURegister(int reg) const;
+  virtual const char* NameOfByteCPURegister(int reg) const;
+  virtual const char* NameOfXMMRegister(int reg) const;
+  virtual const char* NameOfAddress(byte* addr) const;
+  virtual const char* NameOfConstant(byte* addr) const;
+  virtual const char* NameInCode(byte* addr) const;
+};
+
+
+// A generic Disassembler interface
+class Disassembler {
+ public:
+  // Caller deallocates converter.
+  explicit Disassembler(const NameConverter& converter);
+
+  virtual ~Disassembler();
+
+  // Writes one disassembled instruction into 'buffer' (0-terminated).
+  // Returns the length of the disassembled machine instruction in bytes.
+  int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction);
+
+  // Returns -1 if instruction does not mark the beginning of a constant pool,
+  // or the number of entries in the constant pool beginning here.
+  int ConstantPoolSizeAt(byte* instruction);
+
+  // Write disassembly into specified file 'f' using specified NameConverter
+  // (see constructor).
+  static void Disassemble(FILE* f, byte* begin, byte* end);
+ private:
+  const NameConverter& converter_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Disassembler);
+};
+
+}  // namespace disasm
+
+#endif  // V8_DISASM_H_
diff --git a/deps/v8/src/disassembler.cc b/deps/v8/src/disassembler.cc
new file mode 100644
index 0000000..a838a08
--- /dev/null
+++ b/deps/v8/src/disassembler.cc
@@ -0,0 +1,309 @@
+// 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.
+
+#include "v8.h"
+
+#include "code-stubs.h"
+#include "codegen-inl.h"
+#include "debug.h"
+#include "disasm.h"
+#include "disassembler.h"
+#include "macro-assembler.h"
+#include "serialize.h"
+#include "string-stream.h"
+
+namespace v8 { namespace internal {
+
+#ifdef ENABLE_DISASSEMBLER
+
+void Disassembler::Dump(FILE* f, byte* begin, byte* end) {
+  for (byte* pc = begin; pc < end; pc++) {
+    if (f == NULL) {
+      PrintF("%p  %4d  %02x\n", pc, pc - begin, *pc);
+    } else {
+      fprintf(f, "%p  %4d  %02x\n", pc, pc - begin, *pc);
+    }
+  }
+}
+
+
+class V8NameConverter: public disasm::NameConverter {
+ public:
+  explicit V8NameConverter(Code* code) : code_(code) {}
+  virtual const char* NameOfAddress(byte* pc) const;
+  virtual const char* NameInCode(byte* addr) const;
+  Code* code() const { return code_; }
+ private:
+  Code* code_;
+};
+
+
+const char* V8NameConverter::NameOfAddress(byte* pc) const {
+  static v8::internal::EmbeddedVector<char, 128> buffer;
+
+  const char* name = Builtins::Lookup(pc);
+  if (name != NULL) {
+    OS::SNPrintF(buffer, "%s  (%p)", name, pc);
+    return buffer.start();
+  }
+
+  if (code_ != NULL) {
+    int offs = pc - code_->instruction_start();
+    // print as code offset, if it seems reasonable
+    if (0 <= offs && offs < code_->instruction_size()) {
+      OS::SNPrintF(buffer, "%d  (%p)", offs, pc);
+      return buffer.start();
+    }
+  }
+
+  return disasm::NameConverter::NameOfAddress(pc);
+}
+
+
+const char* V8NameConverter::NameInCode(byte* addr) const {
+  // The V8NameConverter is used for well known code, so we can "safely"
+  // dereference pointers in generated code.
+  return (code_ != NULL) ? reinterpret_cast<const char*>(addr) : "";
+}
+
+
+static void DumpBuffer(FILE* f, char* buff) {
+  if (f == NULL) {
+    PrintF("%s", buff);
+  } else {
+    fprintf(f, "%s", buff);
+  }
+}
+
+static const int kOutBufferSize = 2048 + String::kMaxShortPrintLength;
+static const int kRelocInfoPosition = 57;
+
+static int DecodeIt(FILE* f,
+                    const V8NameConverter& converter,
+                    byte* begin,
+                    byte* end) {
+  NoHandleAllocation ha;
+  AssertNoAllocation no_alloc;
+  ExternalReferenceEncoder ref_encoder;
+
+  v8::internal::EmbeddedVector<char, 128> decode_buffer;
+  v8::internal::EmbeddedVector<char, kOutBufferSize> out_buffer;
+  byte* pc = begin;
+  disasm::Disassembler d(converter);
+  RelocIterator* it = NULL;
+  if (converter.code() != NULL) {
+    it = new RelocIterator(converter.code());
+  } else {
+    // No relocation information when printing code stubs.
+  }
+  int constants = -1;  // no constants being decoded at the start
+
+  while (pc < end) {
+    // First decode instruction so that we know its length.
+    byte* prev_pc = pc;
+    if (constants > 0) {
+      OS::SNPrintF(decode_buffer,
+                   "%08x       constant",
+                   *reinterpret_cast<int32_t*>(pc));
+      constants--;
+      pc += 4;
+    } else {
+      int num_const = d.ConstantPoolSizeAt(pc);
+      if (num_const >= 0) {
+        OS::SNPrintF(decode_buffer,
+                     "%08x       constant pool begin",
+                     *reinterpret_cast<int32_t*>(pc));
+        constants = num_const;
+        pc += 4;
+      } else if (it != NULL && !it->done() && it->rinfo()->pc() == pc &&
+          it->rinfo()->rmode() == RelocInfo::INTERNAL_REFERENCE) {
+        // raw pointer embedded in code stream, e.g., jump table
+        byte* ptr = *reinterpret_cast<byte**>(pc);
+        OS::SNPrintF(decode_buffer,
+                     "%08x      jump table entry %4d",
+                     reinterpret_cast<int32_t>(ptr),
+                     ptr - begin);
+        pc += 4;
+      } else {
+        decode_buffer[0] = '\0';
+        pc += d.InstructionDecode(decode_buffer, pc);
+      }
+    }
+
+    // Collect RelocInfo for this instruction (prev_pc .. pc-1)
+    List<const char*> comments(4);
+    List<byte*> pcs(1);
+    List<RelocInfo::Mode> rmodes(1);
+    List<intptr_t> datas(1);
+    if (it != NULL) {
+      while (!it->done() && it->rinfo()->pc() < pc) {
+        if (RelocInfo::IsComment(it->rinfo()->rmode())) {
+          // For comments just collect the text.
+          comments.Add(reinterpret_cast<const char*>(it->rinfo()->data()));
+        } else {
+          // For other reloc info collect all data.
+          pcs.Add(it->rinfo()->pc());
+          rmodes.Add(it->rinfo()->rmode());
+          datas.Add(it->rinfo()->data());
+        }
+        it->next();
+      }
+    }
+
+    StringBuilder out(out_buffer.start(), out_buffer.length());
+
+    // Comments.
+    for (int i = 0; i < comments.length(); i++) {
+      out.AddFormatted("                  %s\n", comments[i]);
+    }
+
+    // Write out comments, resets outp so that we can format the next line.
+    DumpBuffer(f, out.Finalize());
+    out.Reset();
+
+    // Instruction address and instruction offset.
+    out.AddFormatted("%p  %4d  ", prev_pc, prev_pc - begin);
+
+    // Instruction.
+    out.AddFormatted("%s", decode_buffer.start());
+
+    // Print all the reloc info for this instruction which are not comments.
+    for (int i = 0; i < pcs.length(); i++) {
+      // Put together the reloc info
+      RelocInfo relocinfo(pcs[i], rmodes[i], datas[i]);
+
+      // Indent the printing of the reloc info.
+      if (i == 0) {
+        // The first reloc info is printed after the disassembled instruction.
+        out.AddPadding(' ', kRelocInfoPosition - out.position());
+      } else {
+        // Additional reloc infos are printed on separate lines.
+        out.AddFormatted("\n");
+        out.AddPadding(' ', kRelocInfoPosition);
+      }
+
+      RelocInfo::Mode rmode = relocinfo.rmode();
+      if (RelocInfo::IsPosition(rmode)) {
+        if (RelocInfo::IsStatementPosition(rmode)) {
+          out.AddFormatted("    ;; debug: statement %d", relocinfo.data());
+        } else {
+          out.AddFormatted("    ;; debug: position %d", relocinfo.data());
+        }
+      } else if (rmode == RelocInfo::EMBEDDED_OBJECT) {
+        HeapStringAllocator allocator;
+        StringStream accumulator(&allocator);
+        relocinfo.target_object()->ShortPrint(&accumulator);
+        SmartPointer<const char> obj_name = accumulator.ToCString();
+        out.AddFormatted("    ;; object: %s", *obj_name);
+      } else if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
+        const char* reference_name =
+            ref_encoder.NameOfAddress(*relocinfo.target_reference_address());
+        out.AddFormatted("    ;; external reference (%s)", reference_name);
+      } else if (RelocInfo::IsCodeTarget(rmode)) {
+        out.AddFormatted("    ;; code:");
+        if (rmode == RelocInfo::CONSTRUCT_CALL) {
+          out.AddFormatted(" constructor,");
+        }
+        Code* code = Code::GetCodeFromTargetAddress(relocinfo.target_address());
+        Code::Kind kind = code->kind();
+        if (code->is_inline_cache_stub()) {
+          if (rmode == RelocInfo::CODE_TARGET_CONTEXT) {
+            out.AddFormatted(" contextual,");
+          }
+          InlineCacheState ic_state = code->ic_state();
+          out.AddFormatted(" %s, %s", Code::Kind2String(kind),
+              Code::ICState2String(ic_state));
+          if (kind == Code::CALL_IC) {
+            out.AddFormatted(", argc = %d", code->arguments_count());
+          }
+        } else if (kind == Code::STUB) {
+          // Reverse lookup required as the minor key cannot be retrieved
+          // from the code object.
+          Object* obj = Heap::code_stubs()->SlowReverseLookup(code);
+          if (obj != Heap::undefined_value()) {
+            ASSERT(obj->IsSmi());
+            // Get the STUB key and extract major and minor key.
+            uint32_t key = Smi::cast(obj)->value();
+            uint32_t minor_key = CodeStub::MinorKeyFromKey(key);
+            ASSERT(code->major_key() == CodeStub::MajorKeyFromKey(key));
+            out.AddFormatted(" %s, %s, ",
+                             Code::Kind2String(kind),
+                             CodeStub::MajorName(code->major_key()));
+            switch (code->major_key()) {
+              case CodeStub::CallFunction:
+                out.AddFormatted("argc = %d", minor_key);
+                break;
+              case CodeStub::Runtime: {
+                const char* name =
+                    RuntimeStub::GetNameFromMinorKey(minor_key);
+                out.AddFormatted("%s", name);
+                break;
+              }
+              default:
+                out.AddFormatted("minor: %d", minor_key);
+            }
+          }
+        } else {
+          out.AddFormatted(" %s", Code::Kind2String(kind));
+        }
+      } else {
+        out.AddFormatted("    ;; %s", RelocInfo::RelocModeName(rmode));
+      }
+    }
+    out.AddString("\n");
+    DumpBuffer(f, out.Finalize());
+    out.Reset();
+  }
+
+  delete it;
+  return pc - begin;
+}
+
+
+int Disassembler::Decode(FILE* f, byte* begin, byte* end) {
+  V8NameConverter defaultConverter(NULL);
+  return DecodeIt(f, defaultConverter, begin, end);
+}
+
+
+// Called by Code::CodePrint.
+void Disassembler::Decode(FILE* f, Code* code) {
+  byte* begin = Code::cast(code)->instruction_start();
+  byte* end = begin + Code::cast(code)->instruction_size();
+  V8NameConverter v8NameConverter(code);
+  DecodeIt(f, v8NameConverter, begin, end);
+}
+
+#else  // ENABLE_DISASSEMBLER
+
+void Disassembler::Dump(FILE* f, byte* begin, byte* end) {}
+int Disassembler::Decode(FILE* f, byte* begin, byte* end) { return 0; }
+void Disassembler::Decode(FILE* f, Code* code) {}
+
+#endif  // ENABLE_DISASSEMBLER
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/disassembler.h b/deps/v8/src/disassembler.h
new file mode 100644
index 0000000..5003c00
--- /dev/null
+++ b/deps/v8/src/disassembler.h
@@ -0,0 +1,55 @@
+// 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_DISASSEMBLER_H_
+#define V8_DISASSEMBLER_H_
+
+namespace v8 { namespace internal {
+
+class Disassembler : public AllStatic {
+ public:
+  // Print the bytes in the interval [begin, end) into f.
+  static void Dump(FILE* f, byte* begin, byte* end);
+
+  // Decode instructions in the the interval [begin, end) and print the
+  // code into f. Returns the number of bytes disassembled or 1 if no
+  // instruction could be decoded.
+  static int Decode(FILE* f, byte* begin, byte* end);
+
+  // Decode instructions in code.
+  static void Decode(FILE* f, Code* code);
+ private:
+  // Decode instruction at pc and print disassembled instruction into f.
+  // Returns the instruction length in bytes, or 1 if the instruction could
+  // not be decoded.  The number of characters written is written into
+  // the out parameter char_count.
+  static int Decode(FILE* f, byte* pc, int* char_count);
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_DISASSEMBLER_H_
diff --git a/deps/v8/src/dtoa-config.c b/deps/v8/src/dtoa-config.c
new file mode 100644
index 0000000..9fcd0dd
--- /dev/null
+++ b/deps/v8/src/dtoa-config.c
@@ -0,0 +1,84 @@
+/*
+ * 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__)
+#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__) && __FLOAT_WORD_ORDER == __BIG_ENDIAN
+#define  IEEE_MC68k
+#else
+#define  IEEE_8087
+#endif
+
+#define __MATH_H__
+#if defined(__APPLE__) && defined(__MACH__) || defined(__FreeBSD__)
+/* 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__ */
+
+/* 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/deps/v8/src/execution.cc b/deps/v8/src/execution.cc
new file mode 100644
index 0000000..03017d0
--- /dev/null
+++ b/deps/v8/src/execution.cc
@@ -0,0 +1,637 @@
+// 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.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "api.h"
+#include "codegen-inl.h"
+
+#ifdef ARM
+#include "simulator-arm.h"
+#else  // ia32
+#include "simulator-ia32.h"
+#endif
+
+#include "debug.h"
+#include "v8threads.h"
+
+namespace v8 { namespace internal {
+
+
+static Handle<Object> Invoke(bool construct,
+                             Handle<JSFunction> func,
+                             Handle<Object> receiver,
+                             int argc,
+                             Object*** args,
+                             bool* has_pending_exception) {
+  // Make sure we have a real function, not a boilerplate function.
+  ASSERT(!func->IsBoilerplate());
+
+  // Entering JavaScript.
+  VMState state(JS);
+
+  // Guard the stack against too much recursion.
+  StackGuard guard;
+
+  // Placeholder for return value.
+  Object* value = reinterpret_cast<Object*>(kZapValue);
+
+  typedef Object* (*JSEntryFunction)(
+    byte* entry,
+    Object* function,
+    Object* receiver,
+    int argc,
+    Object*** args);
+
+  Handle<Code> code;
+  if (construct) {
+    JSConstructEntryStub stub;
+    code = stub.GetCode();
+  } else {
+    JSEntryStub stub;
+    code = stub.GetCode();
+  }
+
+  {
+    // Save and restore context around invocation and block the
+    // allocation of handles without explicit handle scopes.
+    SaveContext save;
+    NoHandleAllocation na;
+    JSEntryFunction entry = FUNCTION_CAST<JSEntryFunction>(code->entry());
+
+    // Call the function through the right JS entry stub.
+    value = CALL_GENERATED_CODE(entry, func->code()->entry(), *func,
+                                *receiver, argc, args);
+  }
+
+#ifdef DEBUG
+  value->Verify();
+#endif
+
+  // Update the pending exception flag and return the value.
+  *has_pending_exception = value->IsException();
+  ASSERT(*has_pending_exception == Top::has_pending_exception());
+  if (*has_pending_exception) {
+    Top::ReportPendingMessages();
+    return Handle<Object>();
+  } else {
+    Top::clear_pending_message();
+  }
+
+  return Handle<Object>(value);
+}
+
+
+Handle<Object> Execution::Call(Handle<JSFunction> func,
+                               Handle<Object> receiver,
+                               int argc,
+                               Object*** args,
+                               bool* pending_exception) {
+  return Invoke(false, func, receiver, argc, args, pending_exception);
+}
+
+
+Handle<Object> Execution::New(Handle<JSFunction> func, int argc,
+                              Object*** args, bool* pending_exception) {
+  return Invoke(true, func, Top::global(), argc, args, pending_exception);
+}
+
+
+Handle<Object> Execution::TryCall(Handle<JSFunction> func,
+                                  Handle<Object> receiver,
+                                  int argc,
+                                  Object*** args,
+                                  bool* caught_exception) {
+  // Enter a try-block while executing the JavaScript code. To avoid
+  // duplicate error printing it must be non-verbose.  Also, to avoid
+  // creating message objects during stack overflow we shouldn't
+  // capture messages.
+  v8::TryCatch catcher;
+  catcher.SetVerbose(false);
+  catcher.SetCaptureMessage(false);
+
+  Handle<Object> result = Invoke(false, func, receiver, argc, args,
+                                 caught_exception);
+
+  if (*caught_exception) {
+    ASSERT(catcher.HasCaught());
+    ASSERT(Top::has_pending_exception());
+    ASSERT(Top::external_caught_exception());
+    Top::optional_reschedule_exception(true);
+    result = v8::Utils::OpenHandle(*catcher.Exception());
+  }
+
+  ASSERT(!Top::has_pending_exception());
+  ASSERT(!Top::external_caught_exception());
+  return result;
+}
+
+
+Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) {
+  ASSERT(!object->IsJSFunction());
+
+  // If you return a function from here, it will be called when an
+  // attempt is made to call the given object as a function.
+
+  // The regular expression code here is really meant more as an
+  // example than anything else. KJS does not support calling regular
+  // expressions as functions, but SpiderMonkey does.
+  if (FLAG_call_regexp) {
+    bool is_regexp =
+        object->IsHeapObject() &&
+        (HeapObject::cast(*object)->map()->constructor() ==
+         *Top::regexp_function());
+
+    if (is_regexp) {
+      Handle<String> exec = Factory::exec_symbol();
+      return Handle<Object>(object->GetProperty(*exec));
+    }
+  }
+
+  // Objects created through the API can have an instance-call handler
+  // that should be used when calling the object as a function.
+  if (object->IsHeapObject() &&
+      HeapObject::cast(*object)->map()->has_instance_call_handler()) {
+    return Handle<JSFunction>(
+        Top::global_context()->call_as_function_delegate());
+  }
+
+  return Factory::undefined_value();
+}
+
+
+// Static state for stack guards.
+StackGuard::ThreadLocal StackGuard::thread_local_;
+
+
+StackGuard::StackGuard() {
+  // NOTE: Overall the StackGuard code assumes that the stack grows towards
+  // lower addresses.
+  ExecutionAccess access;
+  if (thread_local_.nesting_++ == 0) {
+    // Initial StackGuard is being set. We will set the stack limits based on
+    // the current stack pointer allowing the stack to grow kLimitSize from
+    // here.
+
+    // Ensure that either the stack limits are unset (kIllegalLimit) or that
+    // they indicate a pending interruption. The interrupt limit will be
+    // temporarily reset through the code below and reestablished if the
+    // interrupt flags indicate that an interrupt is pending.
+    ASSERT(thread_local_.jslimit_ == kIllegalLimit ||
+           (thread_local_.jslimit_ == kInterruptLimit &&
+            thread_local_.interrupt_flags_ != 0));
+    ASSERT(thread_local_.climit_ == kIllegalLimit ||
+           (thread_local_.climit_ == kInterruptLimit &&
+            thread_local_.interrupt_flags_ != 0));
+
+    thread_local_.initial_jslimit_ = thread_local_.jslimit_ =
+        GENERATED_CODE_STACK_LIMIT(kLimitSize);
+    // NOTE: The check for overflow is not safe as there is no guarantee that
+    // the running thread has its stack in all memory up to address 0x00000000.
+    thread_local_.initial_climit_ = thread_local_.climit_ =
+        reinterpret_cast<uintptr_t>(this) >= kLimitSize ?
+            reinterpret_cast<uintptr_t>(this) - kLimitSize : 0;
+
+    if (thread_local_.interrupt_flags_ != 0) {
+      set_limits(kInterruptLimit, access);
+    }
+  }
+  // Ensure that proper limits have been set.
+  ASSERT(thread_local_.jslimit_ != kIllegalLimit &&
+         thread_local_.climit_ != kIllegalLimit);
+  ASSERT(thread_local_.initial_jslimit_ != kIllegalLimit &&
+         thread_local_.initial_climit_ != kIllegalLimit);
+}
+
+
+StackGuard::~StackGuard() {
+  ExecutionAccess access;
+  if (--thread_local_.nesting_ == 0) {
+    set_limits(kIllegalLimit, access);
+  }
+}
+
+
+bool StackGuard::IsStackOverflow() {
+  ExecutionAccess access;
+  return (thread_local_.jslimit_ != kInterruptLimit &&
+          thread_local_.climit_ != kInterruptLimit);
+}
+
+
+void StackGuard::EnableInterrupts() {
+  ExecutionAccess access;
+  if (IsSet(access)) {
+    set_limits(kInterruptLimit, access);
+  }
+}
+
+
+void StackGuard::SetStackLimit(uintptr_t limit) {
+  ExecutionAccess access;
+  // If the current limits are special (eg due to a pending interrupt) then
+  // leave them alone.
+  if (thread_local_.jslimit_ == thread_local_.initial_jslimit_) {
+    thread_local_.jslimit_ = limit;
+  }
+  if (thread_local_.climit_ == thread_local_.initial_climit_) {
+    thread_local_.climit_ = limit;
+  }
+  thread_local_.initial_climit_ = limit;
+  thread_local_.initial_jslimit_ = limit;
+}
+
+
+void StackGuard::DisableInterrupts() {
+  ExecutionAccess access;
+  reset_limits(access);
+}
+
+
+bool StackGuard::IsSet(const ExecutionAccess& lock) {
+  return thread_local_.interrupt_flags_ != 0;
+}
+
+
+bool StackGuard::IsInterrupted() {
+  ExecutionAccess access;
+  return thread_local_.interrupt_flags_ & INTERRUPT;
+}
+
+
+void StackGuard::Interrupt() {
+  ExecutionAccess access;
+  thread_local_.interrupt_flags_ |= INTERRUPT;
+  set_limits(kInterruptLimit, access);
+}
+
+
+bool StackGuard::IsPreempted() {
+  ExecutionAccess access;
+  return thread_local_.interrupt_flags_ & PREEMPT;
+}
+
+
+void StackGuard::Preempt() {
+  ExecutionAccess access;
+  thread_local_.interrupt_flags_ |= PREEMPT;
+  set_limits(kInterruptLimit, access);
+}
+
+
+bool StackGuard::IsDebugBreak() {
+  ExecutionAccess access;
+  return thread_local_.interrupt_flags_ & DEBUGBREAK;
+}
+
+
+void StackGuard::DebugBreak() {
+  ExecutionAccess access;
+  thread_local_.interrupt_flags_ |= DEBUGBREAK;
+  set_limits(kInterruptLimit, access);
+}
+
+
+bool StackGuard::IsDebugCommand() {
+  ExecutionAccess access;
+  return thread_local_.interrupt_flags_ & DEBUGCOMMAND;
+}
+
+
+void StackGuard::DebugCommand() {
+  if (FLAG_debugger_auto_break) {
+    ExecutionAccess access;
+    thread_local_.interrupt_flags_ |= DEBUGCOMMAND;
+    set_limits(kInterruptLimit, access);
+  }
+}
+
+
+void StackGuard::Continue(InterruptFlag after_what) {
+  ExecutionAccess access;
+  thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what);
+  if (thread_local_.interrupt_flags_ == 0) {
+    reset_limits(access);
+  }
+}
+
+
+int StackGuard::ArchiveSpacePerThread() {
+  return sizeof(ThreadLocal);
+}
+
+
+char* StackGuard::ArchiveStackGuard(char* to) {
+  ExecutionAccess access;
+  memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
+  ThreadLocal blank;
+  thread_local_ = blank;
+  return to + sizeof(ThreadLocal);
+}
+
+
+char* StackGuard::RestoreStackGuard(char* from) {
+  ExecutionAccess access;
+  memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
+  return from + sizeof(ThreadLocal);
+}
+
+
+// --- C a l l s   t o   n a t i v e s ---
+
+#define RETURN_NATIVE_CALL(name, argc, argv, has_pending_exception) \
+  do {                                                              \
+    Object** args[argc] = argv;                                     \
+    ASSERT(has_pending_exception != NULL);                          \
+    return Call(Top::name##_fun(), Top::builtins(), argc, args,     \
+                has_pending_exception);                             \
+  } while (false)
+
+
+Handle<Object> Execution::ToBoolean(Handle<Object> obj) {
+  // See the similar code in runtime.js:ToBoolean.
+  if (obj->IsBoolean()) return obj;
+  bool result = true;
+  if (obj->IsString()) {
+    result = Handle<String>::cast(obj)->length() != 0;
+  } else if (obj->IsNull() || obj->IsUndefined()) {
+    result = false;
+  } else if (obj->IsNumber()) {
+    double value = obj->Number();
+    result = !((value == 0) || isnan(value));
+  }
+  return Handle<Object>(Heap::ToBoolean(result));
+}
+
+
+Handle<Object> Execution::ToNumber(Handle<Object> obj, bool* exc) {
+  RETURN_NATIVE_CALL(to_number, 1, { obj.location() }, exc);
+}
+
+
+Handle<Object> Execution::ToString(Handle<Object> obj, bool* exc) {
+  RETURN_NATIVE_CALL(to_string, 1, { obj.location() }, exc);
+}
+
+
+Handle<Object> Execution::ToDetailString(Handle<Object> obj, bool* exc) {
+  RETURN_NATIVE_CALL(to_detail_string, 1, { obj.location() }, exc);
+}
+
+
+Handle<Object> Execution::ToObject(Handle<Object> obj, bool* exc) {
+  if (obj->IsJSObject()) return obj;
+  RETURN_NATIVE_CALL(to_object, 1, { obj.location() }, exc);
+}
+
+
+Handle<Object> Execution::ToInteger(Handle<Object> obj, bool* exc) {
+  RETURN_NATIVE_CALL(to_integer, 1, { obj.location() }, exc);
+}
+
+
+Handle<Object> Execution::ToUint32(Handle<Object> obj, bool* exc) {
+  RETURN_NATIVE_CALL(to_uint32, 1, { obj.location() }, exc);
+}
+
+
+Handle<Object> Execution::ToInt32(Handle<Object> obj, bool* exc) {
+  RETURN_NATIVE_CALL(to_int32, 1, { obj.location() }, exc);
+}
+
+
+Handle<Object> Execution::NewDate(double time, bool* exc) {
+  Handle<Object> time_obj = Factory::NewNumber(time);
+  RETURN_NATIVE_CALL(create_date, 1, { time_obj.location() }, exc);
+}
+
+
+#undef RETURN_NATIVE_CALL
+
+
+Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
+  int int_index = static_cast<int>(index);
+  if (int_index < 0 || int_index >= string->length()) {
+    return Factory::undefined_value();
+  }
+
+  Handle<Object> char_at =
+      GetProperty(Top::builtins(), Factory::char_at_symbol());
+  if (!char_at->IsJSFunction()) {
+    return Factory::undefined_value();
+  }
+
+  bool caught_exception;
+  Handle<Object> index_object = Factory::NewNumberFromInt(int_index);
+  Object** index_arg[] = { index_object.location() };
+  Handle<Object> result = TryCall(Handle<JSFunction>::cast(char_at),
+                                  string,
+                                  ARRAY_SIZE(index_arg),
+                                  index_arg,
+                                  &caught_exception);
+  if (caught_exception) {
+    return Factory::undefined_value();
+  }
+  return result;
+}
+
+
+Handle<JSFunction> Execution::InstantiateFunction(
+    Handle<FunctionTemplateInfo> data, bool* exc) {
+  // Fast case: see if the function has already been instantiated
+  int serial_number = Smi::cast(data->serial_number())->value();
+  Object* elm =
+      Top::global_context()->function_cache()->GetElement(serial_number);
+  if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm));
+  // The function has not yet been instantiated in this context; do it.
+  Object** args[1] = { Handle<Object>::cast(data).location() };
+  Handle<Object> result =
+      Call(Top::instantiate_fun(), Top::builtins(), 1, args, exc);
+  if (*exc) return Handle<JSFunction>::null();
+  return Handle<JSFunction>::cast(result);
+}
+
+
+Handle<JSObject> Execution::InstantiateObject(Handle<ObjectTemplateInfo> data,
+                                              bool* exc) {
+  if (data->property_list()->IsUndefined() &&
+      !data->constructor()->IsUndefined()) {
+    // Initialization to make gcc happy.
+    Object* result = NULL;
+    {
+      HandleScope scope;
+      Handle<FunctionTemplateInfo> cons_template =
+          Handle<FunctionTemplateInfo>(
+              FunctionTemplateInfo::cast(data->constructor()));
+      Handle<JSFunction> cons = InstantiateFunction(cons_template, exc);
+      if (*exc) return Handle<JSObject>::null();
+      Handle<Object> value = New(cons, 0, NULL, exc);
+      if (*exc) return Handle<JSObject>::null();
+      result = *value;
+    }
+    ASSERT(!*exc);
+    return Handle<JSObject>(JSObject::cast(result));
+  } else {
+    Object** args[1] = { Handle<Object>::cast(data).location() };
+    Handle<Object> result =
+        Call(Top::instantiate_fun(), Top::builtins(), 1, args, exc);
+    if (*exc) return Handle<JSObject>::null();
+    return Handle<JSObject>::cast(result);
+  }
+}
+
+
+void Execution::ConfigureInstance(Handle<Object> instance,
+                                  Handle<Object> instance_template,
+                                  bool* exc) {
+  Object** args[2] = { instance.location(), instance_template.location() };
+  Execution::Call(Top::configure_instance_fun(), Top::builtins(), 2, args, exc);
+}
+
+
+Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
+                                            Handle<JSFunction> fun,
+                                            Handle<Object> pos,
+                                            Handle<Object> is_global) {
+  const int argc = 4;
+  Object** args[argc] = { recv.location(),
+                          Handle<Object>::cast(fun).location(),
+                          pos.location(),
+                          is_global.location() };
+  bool caught_exception = false;
+  Handle<Object> result = TryCall(Top::get_stack_trace_line_fun(),
+                                  Top::builtins(), argc, args,
+                                  &caught_exception);
+  if (caught_exception || !result->IsString()) return Factory::empty_symbol();
+  return Handle<String>::cast(result);
+}
+
+
+static Object* RuntimePreempt() {
+  // Clear the preempt request flag.
+  StackGuard::Continue(PREEMPT);
+
+  ContextSwitcher::PreemptionReceived();
+
+  if (Debug::InDebugger()) {
+    // If currently in the debugger don't do any actual preemption but record
+    // that preemption occoured while in the debugger.
+    Debug::PreemptionWhileInDebugger();
+  } else {
+    // Perform preemption.
+    v8::Unlocker unlocker;
+    Thread::YieldCPU();
+  }
+
+  return Heap::undefined_value();
+}
+
+
+Object* Execution::DebugBreakHelper() {
+  // Just continue if breaks are disabled.
+  if (Debug::disable_break()) {
+    return Heap::undefined_value();
+  }
+
+  // Don't break in system functions. If the current function is
+  // either in the builtins object of some context or is in the debug
+  // context just return with the debug break stack guard active.
+  JavaScriptFrameIterator it;
+  JavaScriptFrame* frame = it.frame();
+  Object* fun = frame->function();
+  if (fun->IsJSFunction()) {
+    GlobalObject* global = JSFunction::cast(fun)->context()->global();
+    if (global->IsJSBuiltinsObject() || Debug::IsDebugGlobal(global)) {
+      return Heap::undefined_value();
+    }
+  }
+
+  // Check for debug command break only.
+  bool debug_command_only =
+      StackGuard::IsDebugCommand() && !StackGuard::IsDebugBreak();
+
+  // Clear the debug request flags.
+  StackGuard::Continue(DEBUGBREAK);
+  StackGuard::Continue(DEBUGCOMMAND);
+
+  // If debug command only and already in debugger ignore it.
+  if (debug_command_only && Debug::InDebugger()) {
+    return Heap::undefined_value();
+  }
+
+  HandleScope scope;
+  // Enter the debugger. Just continue if we fail to enter the debugger.
+  EnterDebugger debugger;
+  if (debugger.FailedToEnter()) {
+    return Heap::undefined_value();
+  }
+
+  // Notify the debug event listeners.
+  Debugger::OnDebugBreak(Factory::undefined_value(), debug_command_only);
+
+  // Return to continue execution.
+  return Heap::undefined_value();
+}
+
+
+Object* Execution::HandleStackGuardInterrupt() {
+  if (StackGuard::IsDebugBreak() || StackGuard::IsDebugCommand()) {
+    DebugBreakHelper();
+  }
+  if (StackGuard::IsPreempted()) RuntimePreempt();
+  if (StackGuard::IsInterrupted()) {
+    // interrupt
+    StackGuard::Continue(INTERRUPT);
+    return Top::StackOverflow();
+  }
+  return Heap::undefined_value();
+}
+
+// --- G C   E x t e n s i o n ---
+
+const char* 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::CollectGarbage(0, OLD_DATA_SPACE);
+  return v8::Undefined();
+}
+
+
+static GCExtension kGCExtension;
+v8::DeclareExtension kGCExtensionDeclaration(&kGCExtension);
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/execution.h b/deps/v8/src/execution.h
new file mode 100644
index 0000000..6531572
--- /dev/null
+++ b/deps/v8/src/execution.h
@@ -0,0 +1,276 @@
+// 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_EXECUTION_H_
+#define V8_EXECUTION_H_
+
+namespace v8 { namespace internal {
+
+
+// Flag used to set the interrupt causes.
+enum InterruptFlag {
+  INTERRUPT = 1 << 0,
+  DEBUGBREAK = 1 << 1,
+  DEBUGCOMMAND = 1 << 2,
+  PREEMPT = 1 << 3
+};
+
+class Execution : public AllStatic {
+ public:
+  // Call a function, the caller supplies a receiver and an array
+  // of arguments. Arguments are Object* type. After function returns,
+  // pointers in 'args' might be invalid.
+  //
+  // *pending_exception tells whether the invoke resulted in
+  // a pending exception.
+  //
+  static Handle<Object> Call(Handle<JSFunction> func,
+                             Handle<Object> receiver,
+                             int argc,
+                             Object*** args,
+                             bool* pending_exception);
+
+  // Construct object from function, the caller supplies an array of
+  // arguments. Arguments are Object* type. After function returns,
+  // pointers in 'args' might be invalid.
+  //
+  // *pending_exception tells whether the invoke resulted in
+  // a pending exception.
+  //
+  static Handle<Object> New(Handle<JSFunction> func,
+                            int argc,
+                            Object*** args,
+                            bool* pending_exception);
+
+  // Call a function, just like Call(), but make sure to silently catch
+  // any thrown exceptions. The return value is either the result of
+  // calling the function (if caught exception is false) or the exception
+  // that occurred (if caught exception is true).
+  static Handle<Object> TryCall(Handle<JSFunction> func,
+                                Handle<Object> receiver,
+                                int argc,
+                                Object*** args,
+                                bool* caught_exception);
+
+  // ECMA-262 9.2
+  static Handle<Object> ToBoolean(Handle<Object> obj);
+
+  // ECMA-262 9.3
+  static Handle<Object> ToNumber(Handle<Object> obj, bool* exc);
+
+  // ECMA-262 9.4
+  static Handle<Object> ToInteger(Handle<Object> obj, bool* exc);
+
+  // ECMA-262 9.5
+  static Handle<Object> ToInt32(Handle<Object> obj, bool* exc);
+
+  // ECMA-262 9.6
+  static Handle<Object> ToUint32(Handle<Object> obj, bool* exc);
+
+  // ECMA-262 9.8
+  static Handle<Object> ToString(Handle<Object> obj, bool* exc);
+
+  // ECMA-262 9.8
+  static Handle<Object> ToDetailString(Handle<Object> obj, bool* exc);
+
+  // ECMA-262 9.9
+  static Handle<Object> ToObject(Handle<Object> obj, bool* exc);
+
+  // Create a new date object from 'time'.
+  static Handle<Object> NewDate(double time, bool* exc);
+
+  // Used to implement [] notation on strings (calls JS code)
+  static Handle<Object> CharAt(Handle<String> str, uint32_t index);
+
+  static Handle<Object> GetFunctionFor();
+  static Handle<JSFunction> InstantiateFunction(
+      Handle<FunctionTemplateInfo> data, bool* exc);
+  static Handle<JSObject> InstantiateObject(Handle<ObjectTemplateInfo> data,
+                                            bool* exc);
+  static void ConfigureInstance(Handle<Object> instance,
+                                Handle<Object> data,
+                                bool* exc);
+  static Handle<String> GetStackTraceLine(Handle<Object> recv,
+                                          Handle<JSFunction> fun,
+                                          Handle<Object> pos,
+                                          Handle<Object> is_global);
+
+  static Object* DebugBreakHelper();
+
+  // If the stack guard is triggered, but it is not an actual
+  // stack overflow, then handle the interruption accordingly.
+  static Object* HandleStackGuardInterrupt();
+
+  // Get a function delegate (or undefined) for the given non-function
+  // object. Used for support calling objects as functions.
+  static Handle<Object> GetFunctionDelegate(Handle<Object> object);
+};
+
+
+class ExecutionAccess;
+
+
+// Stack guards are used to limit the number of nested invocations of
+// JavaScript and the stack size used in each invocation.
+class StackGuard BASE_EMBEDDED {
+ public:
+  StackGuard();
+
+  ~StackGuard();
+
+  static void SetStackLimit(uintptr_t limit);
+
+  static Address address_of_jslimit() {
+    return reinterpret_cast<Address>(&thread_local_.jslimit_);
+  }
+
+  // Threading support.
+  static char* ArchiveStackGuard(char* to);
+  static char* RestoreStackGuard(char* from);
+  static int ArchiveSpacePerThread();
+
+  static bool IsStackOverflow();
+  static bool IsPreempted();
+  static void Preempt();
+  static bool IsInterrupted();
+  static void Interrupt();
+  static bool IsDebugBreak();
+  static void DebugBreak();
+  static bool IsDebugCommand();
+  static void DebugCommand();
+  static void Continue(InterruptFlag after_what);
+
+ private:
+  // You should hold the ExecutionAccess lock when calling this method.
+  static bool IsSet(const ExecutionAccess& lock);
+
+  // This provides an asynchronous read of the stack limit for the current
+  // thread.  There are no locks protecting this, but it is assumed that you
+  // have the global V8 lock if you are using multiple V8 threads.
+  static uintptr_t climit() {
+    return thread_local_.climit_;
+  }
+
+  // You should hold the ExecutionAccess lock when calling this method.
+  static void set_limits(uintptr_t value, const ExecutionAccess& lock) {
+    thread_local_.jslimit_ = value;
+    thread_local_.climit_ = value;
+  }
+
+  // Reset limits to initial values. For example after handling interrupt.
+  // You should hold the ExecutionAccess lock when calling this method.
+  static void reset_limits(const ExecutionAccess& lock) {
+    if (thread_local_.nesting_ == 0) {
+      // No limits have been set yet.
+      set_limits(kIllegalLimit, lock);
+    } else {
+      thread_local_.jslimit_ = thread_local_.initial_jslimit_;
+      thread_local_.climit_ = thread_local_.initial_climit_;
+    }
+  }
+
+  // Enable or disable interrupts.
+  static void EnableInterrupts();
+  static void DisableInterrupts();
+
+  static const uintptr_t kLimitSize = 512 * KB;
+  static const uintptr_t kInterruptLimit = 0xfffffffe;
+  static const uintptr_t kIllegalLimit = 0xffffffff;
+
+  class ThreadLocal {
+   public:
+    ThreadLocal()
+     : initial_jslimit_(kIllegalLimit),
+       jslimit_(kIllegalLimit),
+       initial_climit_(kIllegalLimit),
+       climit_(kIllegalLimit),
+       nesting_(0),
+       postpone_interrupts_nesting_(0),
+       interrupt_flags_(0) {}
+    uintptr_t initial_jslimit_;
+    uintptr_t jslimit_;
+    uintptr_t initial_climit_;
+    uintptr_t climit_;
+    int nesting_;
+    int postpone_interrupts_nesting_;
+    int interrupt_flags_;
+  };
+
+  static ThreadLocal thread_local_;
+
+  friend class StackLimitCheck;
+  friend class PostponeInterruptsScope;
+};
+
+
+// Support for checking for stack-overflows in C++ code.
+class StackLimitCheck BASE_EMBEDDED {
+ public:
+  bool HasOverflowed() const {
+    // Stack has overflowed in C++ code only if stack pointer exceeds the C++
+    // stack guard and the limits are not set to interrupt values.
+    // TODO(214): Stack overflows are ignored if a interrupt is pending. This
+    // code should probably always use the initial C++ limit.
+    return (reinterpret_cast<uintptr_t>(this) < StackGuard::climit()) &&
+           StackGuard::IsStackOverflow();
+  }
+};
+
+
+// Support for temporarily postponing interrupts. When the outermost
+// postpone scope is left the interrupts will be re-enabled and any
+// interrupts that occurred while in the scope will be taken into
+// account.
+class PostponeInterruptsScope BASE_EMBEDDED {
+ public:
+  PostponeInterruptsScope() {
+    StackGuard::thread_local_.postpone_interrupts_nesting_++;
+    StackGuard::DisableInterrupts();
+  }
+
+  ~PostponeInterruptsScope() {
+    if (--StackGuard::thread_local_.postpone_interrupts_nesting_ == 0) {
+      StackGuard::EnableInterrupts();
+    }
+  }
+};
+
+
+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* kSource;
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_EXECUTION_H_
diff --git a/deps/v8/src/factory.cc b/deps/v8/src/factory.cc
new file mode 100644
index 0000000..e29c84d
--- /dev/null
+++ b/deps/v8/src/factory.cc
@@ -0,0 +1,902 @@
+// 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.
+
+#include "v8.h"
+
+#include "api.h"
+#include "debug.h"
+#include "execution.h"
+#include "factory.h"
+#include "macro-assembler.h"
+
+namespace v8 { namespace internal {
+
+
+Handle<FixedArray> Factory::NewFixedArray(int size, PretenureFlag pretenure) {
+  ASSERT(0 <= size);
+  CALL_HEAP_FUNCTION(Heap::AllocateFixedArray(size, pretenure), FixedArray);
+}
+
+
+Handle<FixedArray> Factory::NewFixedArrayWithHoles(int size) {
+  ASSERT(0 <= size);
+  CALL_HEAP_FUNCTION(Heap::AllocateFixedArrayWithHoles(size), FixedArray);
+}
+
+
+Handle<Dictionary> Factory::NewDictionary(int at_least_space_for) {
+  ASSERT(0 <= at_least_space_for);
+  CALL_HEAP_FUNCTION(Dictionary::Allocate(at_least_space_for), Dictionary);
+}
+
+
+Handle<DescriptorArray> Factory::NewDescriptorArray(int number_of_descriptors) {
+  ASSERT(0 <= number_of_descriptors);
+  CALL_HEAP_FUNCTION(DescriptorArray::Allocate(number_of_descriptors),
+                     DescriptorArray);
+}
+
+
+// Symbols are created in the old generation (data space).
+Handle<String> Factory::LookupSymbol(Vector<const char> string) {
+  CALL_HEAP_FUNCTION(Heap::LookupSymbol(string), String);
+}
+
+
+Handle<String> Factory::NewStringFromAscii(Vector<const char> string,
+                                           PretenureFlag pretenure) {
+  CALL_HEAP_FUNCTION(Heap::AllocateStringFromAscii(string, pretenure), String);
+}
+
+Handle<String> Factory::NewStringFromUtf8(Vector<const char> string,
+                                          PretenureFlag pretenure) {
+  CALL_HEAP_FUNCTION(Heap::AllocateStringFromUtf8(string, pretenure), String);
+}
+
+
+Handle<String> Factory::NewStringFromTwoByte(Vector<const uc16> string) {
+  CALL_HEAP_FUNCTION(Heap::AllocateStringFromTwoByte(string), String);
+}
+
+
+Handle<String> Factory::NewRawTwoByteString(int length,
+                                            PretenureFlag pretenure) {
+  CALL_HEAP_FUNCTION(Heap::AllocateRawTwoByteString(length, pretenure), String);
+}
+
+
+Handle<String> Factory::NewConsString(Handle<String> first,
+                                      Handle<String> second) {
+  if (first->length() == 0) return second;
+  if (second->length() == 0) return first;
+  CALL_HEAP_FUNCTION(Heap::AllocateConsString(*first, *second), String);
+}
+
+
+Handle<String> Factory::NewStringSlice(Handle<String> str,
+                                       int begin,
+                                       int end) {
+  CALL_HEAP_FUNCTION(str->Slice(begin, end), String);
+}
+
+
+Handle<String> Factory::NewExternalStringFromAscii(
+    ExternalAsciiString::Resource* resource) {
+  CALL_HEAP_FUNCTION(Heap::AllocateExternalStringFromAscii(resource), String);
+}
+
+
+Handle<String> Factory::NewExternalStringFromTwoByte(
+    ExternalTwoByteString::Resource* resource) {
+  CALL_HEAP_FUNCTION(Heap::AllocateExternalStringFromTwoByte(resource), String);
+}
+
+
+Handle<Context> Factory::NewGlobalContext() {
+  CALL_HEAP_FUNCTION(Heap::AllocateGlobalContext(), Context);
+}
+
+
+Handle<Context> Factory::NewFunctionContext(int length,
+                                            Handle<JSFunction> closure) {
+  CALL_HEAP_FUNCTION(Heap::AllocateFunctionContext(length, *closure), Context);
+}
+
+
+Handle<Context> Factory::NewWithContext(Handle<Context> previous,
+                                        Handle<JSObject> extension,
+                                        bool is_catch_context) {
+  CALL_HEAP_FUNCTION(Heap::AllocateWithContext(*previous,
+                                               *extension,
+                                               is_catch_context),
+                     Context);
+}
+
+
+Handle<Struct> Factory::NewStruct(InstanceType type) {
+  CALL_HEAP_FUNCTION(Heap::AllocateStruct(type), Struct);
+}
+
+
+Handle<AccessorInfo> Factory::NewAccessorInfo() {
+  Handle<AccessorInfo> info =
+      Handle<AccessorInfo>::cast(NewStruct(ACCESSOR_INFO_TYPE));
+  info->set_flag(0);  // Must clear the flag, it was initialized as undefined.
+  return info;
+}
+
+
+Handle<Script> Factory::NewScript(Handle<String> source) {
+  // Generate id for this script.
+  int id;
+  if (Heap::last_script_id()->IsUndefined()) {
+    // Script ids start from one.
+    id = 1;
+  } else {
+    // Increment id, wrap when positive smi is exhausted.
+    id = Smi::cast(Heap::last_script_id())->value();
+    id++;
+    if (!Smi::IsValid(id)) {
+      id = 0;
+    }
+  }
+  Heap::SetLastScriptId(Smi::FromInt(id));
+
+  // Create and initialize script object.
+  Handle<Script> script = Handle<Script>::cast(NewStruct(SCRIPT_TYPE));
+  script->set_source(*source);
+  script->set_name(Heap::undefined_value());
+  script->set_id(Heap::last_script_id());
+  script->set_line_offset(Smi::FromInt(0));
+  script->set_column_offset(Smi::FromInt(0));
+  script->set_type(Smi::FromInt(SCRIPT_TYPE_NORMAL));
+  script->set_wrapper(*Factory::NewProxy(0, TENURED));
+  script->set_line_ends(Heap::undefined_value());
+
+  return script;
+}
+
+
+Handle<Proxy> Factory::NewProxy(Address addr, PretenureFlag pretenure) {
+  CALL_HEAP_FUNCTION(Heap::AllocateProxy(addr, pretenure), Proxy);
+}
+
+
+Handle<Proxy> Factory::NewProxy(const AccessorDescriptor* desc) {
+  return NewProxy((Address) desc, TENURED);
+}
+
+
+Handle<ByteArray> Factory::NewByteArray(int length, PretenureFlag pretenure) {
+  ASSERT(0 <= length);
+  CALL_HEAP_FUNCTION(Heap::AllocateByteArray(length, pretenure), ByteArray);
+}
+
+
+Handle<Map> Factory::NewMap(InstanceType type, int instance_size) {
+  CALL_HEAP_FUNCTION(Heap::AllocateMap(type, instance_size), Map);
+}
+
+
+Handle<JSObject> Factory::NewFunctionPrototype(Handle<JSFunction> function) {
+  CALL_HEAP_FUNCTION(Heap::AllocateFunctionPrototype(*function), JSObject);
+}
+
+
+Handle<Map> Factory::CopyMap(Handle<Map> src) {
+  CALL_HEAP_FUNCTION(src->Copy(), Map);
+}
+
+
+Handle<Map> Factory::CopyMap(Handle<Map> src,
+                             int extra_inobject_properties) {
+  Handle<Map> copy = CopyMap(src);
+  // Check that we do not overflow the instance size when adding the
+  // extra inobject properties.
+  int instance_size_delta = extra_inobject_properties * kPointerSize;
+  int max_instance_size_delta =
+      JSObject::kMaxInstanceSize - copy->instance_size();
+  if (instance_size_delta > max_instance_size_delta) {
+    // If the instance size overflows, we allocate as many properties
+    // as we can as inobject properties.
+    instance_size_delta = max_instance_size_delta;
+    extra_inobject_properties = max_instance_size_delta >> kPointerSizeLog2;
+  }
+  // Adjust the map with the extra inobject properties.
+  int inobject_properties =
+      copy->inobject_properties() + extra_inobject_properties;
+  copy->set_inobject_properties(inobject_properties);
+  copy->set_unused_property_fields(inobject_properties);
+  copy->set_instance_size(copy->instance_size() + instance_size_delta);
+  return copy;
+}
+
+Handle<Map> Factory::CopyMapDropTransitions(Handle<Map> src) {
+  CALL_HEAP_FUNCTION(src->CopyDropTransitions(), Map);
+}
+
+
+Handle<FixedArray> Factory::CopyFixedArray(Handle<FixedArray> array) {
+  CALL_HEAP_FUNCTION(array->Copy(), FixedArray);
+}
+
+
+Handle<JSFunction> Factory::BaseNewFunctionFromBoilerplate(
+    Handle<JSFunction> boilerplate,
+    Handle<Map> function_map) {
+  ASSERT(boilerplate->IsBoilerplate());
+  ASSERT(!boilerplate->has_initial_map());
+  ASSERT(!boilerplate->has_prototype());
+  ASSERT(boilerplate->properties() == Heap::empty_fixed_array());
+  ASSERT(boilerplate->elements() == Heap::empty_fixed_array());
+  CALL_HEAP_FUNCTION(Heap::AllocateFunction(*function_map,
+                                            boilerplate->shared(),
+                                            Heap::the_hole_value()),
+                     JSFunction);
+}
+
+
+Handle<JSFunction> Factory::NewFunctionFromBoilerplate(
+    Handle<JSFunction> boilerplate,
+    Handle<Context> context) {
+  Handle<JSFunction> result =
+      BaseNewFunctionFromBoilerplate(boilerplate, Top::function_map());
+  result->set_context(*context);
+  int number_of_literals = boilerplate->NumberOfLiterals();
+  Handle<FixedArray> literals =
+      Factory::NewFixedArray(number_of_literals, TENURED);
+  if (number_of_literals > 0) {
+    // Store the object, regexp and array functions in the literals
+    // array prefix.  These functions will be used when creating
+    // object, regexp and array literals in this function.
+    literals->set(JSFunction::kLiteralGlobalContextIndex,
+                  context->global_context());
+  }
+  result->set_literals(*literals);
+  ASSERT(!result->IsBoilerplate());
+  return result;
+}
+
+
+Handle<Object> Factory::NewNumber(double value,
+                                  PretenureFlag pretenure) {
+  CALL_HEAP_FUNCTION(Heap::NumberFromDouble(value, pretenure), Object);
+}
+
+
+Handle<Object> Factory::NewNumberFromInt(int value) {
+  CALL_HEAP_FUNCTION(Heap::NumberFromInt32(value), Object);
+}
+
+
+Handle<Object> Factory::NewNumberFromUint(uint32_t value) {
+  CALL_HEAP_FUNCTION(Heap::NumberFromUint32(value), Object);
+}
+
+
+Handle<JSObject> Factory::NewNeanderObject() {
+  CALL_HEAP_FUNCTION(Heap::AllocateJSObjectFromMap(Heap::neander_map()),
+                     JSObject);
+}
+
+
+Handle<Object> Factory::NewTypeError(const char* type,
+                                     Vector< Handle<Object> > args) {
+  return NewError("MakeTypeError", type, args);
+}
+
+
+Handle<Object> Factory::NewTypeError(Handle<String> message) {
+  return NewError("$TypeError", message);
+}
+
+
+Handle<Object> Factory::NewRangeError(const char* type,
+                                      Vector< Handle<Object> > args) {
+  return NewError("MakeRangeError", type, args);
+}
+
+
+Handle<Object> Factory::NewRangeError(Handle<String> message) {
+  return NewError("$RangeError", message);
+}
+
+
+Handle<Object> Factory::NewSyntaxError(const char* type, Handle<JSArray> args) {
+  return NewError("MakeSyntaxError", type, args);
+}
+
+
+Handle<Object> Factory::NewSyntaxError(Handle<String> message) {
+  return NewError("$SyntaxError", message);
+}
+
+
+Handle<Object> Factory::NewReferenceError(const char* type,
+                                          Vector< Handle<Object> > args) {
+  return NewError("MakeReferenceError", type, args);
+}
+
+
+Handle<Object> Factory::NewReferenceError(Handle<String> message) {
+  return NewError("$ReferenceError", message);
+}
+
+
+Handle<Object> Factory::NewError(const char* maker, const char* type,
+    Vector< Handle<Object> > args) {
+  v8::HandleScope scope;  // Instantiate a closeable HandleScope for EscapeFrom.
+  Handle<FixedArray> array = Factory::NewFixedArray(args.length());
+  for (int i = 0; i < args.length(); i++) {
+    array->set(i, *args[i]);
+  }
+  Handle<JSArray> object = Factory::NewJSArrayWithElements(array);
+  Handle<Object> result = NewError(maker, type, object);
+  return result.EscapeFrom(&scope);
+}
+
+
+Handle<Object> Factory::NewEvalError(const char* type,
+                                     Vector< Handle<Object> > args) {
+  return NewError("MakeEvalError", type, args);
+}
+
+
+Handle<Object> Factory::NewError(const char* type,
+                                 Vector< Handle<Object> > args) {
+  return NewError("MakeError", type, args);
+}
+
+
+Handle<Object> Factory::NewError(const char* maker,
+                                 const char* type,
+                                 Handle<JSArray> args) {
+  Handle<String> make_str = Factory::LookupAsciiSymbol(maker);
+  Handle<JSFunction> fun =
+      Handle<JSFunction>(
+          JSFunction::cast(
+              Top::builtins()->GetProperty(*make_str)));
+  Handle<Object> type_obj = Factory::LookupAsciiSymbol(type);
+  Object** argv[2] = { type_obj.location(),
+                       Handle<Object>::cast(args).location() };
+
+  // Invoke the JavaScript factory method. If an exception is thrown while
+  // running the factory method, use the exception as the result.
+  bool caught_exception;
+  Handle<Object> result = Execution::TryCall(fun,
+                                             Top::builtins(),
+                                             2,
+                                             argv,
+                                             &caught_exception);
+  return result;
+}
+
+
+Handle<Object> Factory::NewError(Handle<String> message) {
+  return NewError("$Error", message);
+}
+
+
+Handle<Object> Factory::NewError(const char* constructor,
+                                 Handle<String> message) {
+  Handle<String> constr = Factory::LookupAsciiSymbol(constructor);
+  Handle<JSFunction> fun =
+      Handle<JSFunction>(
+          JSFunction::cast(
+              Top::builtins()->GetProperty(*constr)));
+  Object** argv[1] = { Handle<Object>::cast(message).location() };
+
+  // Invoke the JavaScript factory method. If an exception is thrown while
+  // running the factory method, use the exception as the result.
+  bool caught_exception;
+  Handle<Object> result = Execution::TryCall(fun,
+                                             Top::builtins(),
+                                             1,
+                                             argv,
+                                             &caught_exception);
+  return result;
+}
+
+
+Handle<JSFunction> Factory::NewFunction(Handle<String> name,
+                                        InstanceType type,
+                                        int instance_size,
+                                        Handle<Code> code,
+                                        bool force_initial_map) {
+  // Allocate the function
+  Handle<JSFunction> function = NewFunction(name, the_hole_value());
+  function->set_code(*code);
+
+  if (force_initial_map ||
+      type != JS_OBJECT_TYPE ||
+      instance_size != JSObject::kHeaderSize) {
+    Handle<Map> initial_map = NewMap(type, instance_size);
+    Handle<JSObject> prototype = NewFunctionPrototype(function);
+    initial_map->set_prototype(*prototype);
+    function->set_initial_map(*initial_map);
+    initial_map->set_constructor(*function);
+  } else {
+    ASSERT(!function->has_initial_map());
+    ASSERT(!function->has_prototype());
+  }
+
+  return function;
+}
+
+
+Handle<JSFunction> Factory::NewFunctionBoilerplate(Handle<String> name,
+                                                   int number_of_literals,
+                                                   bool contains_array_literal,
+                                                   Handle<Code> code) {
+  Handle<JSFunction> function = NewFunctionBoilerplate(name);
+  function->set_code(*code);
+  int literals_array_size = number_of_literals;
+  // If the function contains object, regexp or array literals,
+  // allocate extra space for a literals array prefix containing the
+  // object, regexp and array constructor functions.
+  if (number_of_literals > 0 || contains_array_literal) {
+    literals_array_size += JSFunction::kLiteralsPrefixSize;
+  }
+  Handle<FixedArray> literals =
+      Factory::NewFixedArray(literals_array_size, TENURED);
+  function->set_literals(*literals);
+  ASSERT(!function->has_initial_map());
+  ASSERT(!function->has_prototype());
+  return function;
+}
+
+
+Handle<JSFunction> Factory::NewFunctionBoilerplate(Handle<String> name) {
+  Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name);
+  CALL_HEAP_FUNCTION(Heap::AllocateFunction(Heap::boilerplate_function_map(),
+                                            *shared,
+                                            Heap::the_hole_value()),
+                     JSFunction);
+}
+
+
+Handle<JSFunction> Factory::NewFunctionWithPrototype(Handle<String> name,
+                                                     InstanceType type,
+                                                     int instance_size,
+                                                     Handle<JSObject> prototype,
+                                                     Handle<Code> code,
+                                                     bool force_initial_map) {
+  // Allocate the function
+  Handle<JSFunction> function = NewFunction(name, prototype);
+
+  function->set_code(*code);
+
+  if (force_initial_map ||
+      type != JS_OBJECT_TYPE ||
+      instance_size != JSObject::kHeaderSize) {
+    Handle<Map> initial_map = NewMap(type, instance_size);
+    function->set_initial_map(*initial_map);
+    initial_map->set_constructor(*function);
+  }
+
+  // Set function.prototype and give the prototype a constructor
+  // property that refers to the function.
+  SetPrototypeProperty(function, prototype);
+  SetProperty(prototype, Factory::constructor_symbol(), function, DONT_ENUM);
+  return function;
+}
+
+
+Handle<Code> Factory::NewCode(const CodeDesc& desc, ScopeInfo<>* sinfo,
+                              Code::Flags flags, Handle<Object> self_ref) {
+  CALL_HEAP_FUNCTION(Heap::CreateCode(desc, sinfo, flags, self_ref), Code);
+}
+
+
+Handle<Code> Factory::CopyCode(Handle<Code> code) {
+  CALL_HEAP_FUNCTION(Heap::CopyCode(*code), Code);
+}
+
+
+static inline Object* DoCopyInsert(DescriptorArray* array,
+                                   String* key,
+                                   Object* value,
+                                   PropertyAttributes attributes) {
+  CallbacksDescriptor desc(key, value, attributes);
+  Object* obj = array->CopyInsert(&desc, REMOVE_TRANSITIONS);
+  return obj;
+}
+
+
+// Allocate the new array.
+Handle<DescriptorArray> Factory::CopyAppendProxyDescriptor(
+    Handle<DescriptorArray> array,
+    Handle<String> key,
+    Handle<Object> value,
+    PropertyAttributes attributes) {
+  CALL_HEAP_FUNCTION(DoCopyInsert(*array, *key, *value, attributes),
+                     DescriptorArray);
+}
+
+
+Handle<String> Factory::SymbolFromString(Handle<String> value) {
+  CALL_HEAP_FUNCTION(Heap::LookupSymbol(*value), String);
+}
+
+
+Handle<DescriptorArray> Factory::CopyAppendCallbackDescriptors(
+    Handle<DescriptorArray> array,
+    Handle<Object> descriptors) {
+  v8::NeanderArray callbacks(descriptors);
+  int nof_callbacks = callbacks.length();
+  Handle<DescriptorArray> result =
+      NewDescriptorArray(array->number_of_descriptors() + nof_callbacks);
+
+  // Number of descriptors added to the result so far.
+  int descriptor_count = 0;
+
+  // Copy the descriptors from the array.
+  DescriptorWriter w(*result);
+  for (DescriptorReader r(*array); !r.eos(); r.advance()) {
+    if (!r.IsNullDescriptor()) {
+      w.WriteFrom(&r);
+    }
+    descriptor_count++;
+  }
+
+  // Number of duplicates detected.
+  int duplicates = 0;
+
+  // Fill in new callback descriptors.  Process the callbacks from
+  // back to front so that the last callback with a given name takes
+  // precedence over previously added callbacks with that name.
+  for (int i = nof_callbacks - 1; i >= 0; i--) {
+    Handle<AccessorInfo> entry =
+        Handle<AccessorInfo>(AccessorInfo::cast(callbacks.get(i)));
+    // Ensure the key is a symbol before writing into the instance descriptor.
+    Handle<String> key =
+        SymbolFromString(Handle<String>(String::cast(entry->name())));
+    // Check if a descriptor with this name already exists before writing.
+    if (result->LinearSearch(*key, descriptor_count) ==
+        DescriptorArray::kNotFound) {
+      CallbacksDescriptor desc(*key, *entry, entry->property_attributes());
+      w.Write(&desc);
+      descriptor_count++;
+    } else {
+      duplicates++;
+    }
+  }
+
+  // If duplicates were detected, allocate a result of the right size
+  // and transfer the elements.
+  if (duplicates > 0) {
+    Handle<DescriptorArray> new_result =
+        NewDescriptorArray(result->number_of_descriptors() - duplicates);
+    DescriptorWriter w(*new_result);
+    DescriptorReader r(*result);
+    while (!w.eos()) {
+      w.WriteFrom(&r);
+      r.advance();
+    }
+    result = new_result;
+  }
+
+  // Sort the result before returning.
+  result->Sort();
+  return result;
+}
+
+
+Handle<JSObject> Factory::NewJSObject(Handle<JSFunction> constructor,
+                                      PretenureFlag pretenure) {
+  CALL_HEAP_FUNCTION(Heap::AllocateJSObject(*constructor, pretenure), JSObject);
+}
+
+
+Handle<JSObject> Factory::NewJSObjectFromMap(Handle<Map> map) {
+  CALL_HEAP_FUNCTION(Heap::AllocateJSObjectFromMap(*map, NOT_TENURED),
+                     JSObject);
+}
+
+
+Handle<JSArray> Factory::NewJSArray(int length,
+                                    PretenureFlag pretenure) {
+  Handle<JSObject> obj = NewJSObject(Top::array_function(), pretenure);
+  CALL_HEAP_FUNCTION(Handle<JSArray>::cast(obj)->Initialize(length), JSArray);
+}
+
+
+Handle<JSArray> Factory::NewJSArrayWithElements(Handle<FixedArray> elements,
+                                                PretenureFlag pretenure) {
+  Handle<JSArray> result =
+      Handle<JSArray>::cast(NewJSObject(Top::array_function(), pretenure));
+  result->SetContent(*elements);
+  return result;
+}
+
+
+Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(Handle<String> name) {
+  CALL_HEAP_FUNCTION(Heap::AllocateSharedFunctionInfo(*name),
+                     SharedFunctionInfo);
+}
+
+
+Handle<Dictionary> Factory::DictionaryAtNumberPut(Handle<Dictionary> dictionary,
+                                                  uint32_t key,
+                                                  Handle<Object> value) {
+  CALL_HEAP_FUNCTION(dictionary->AtNumberPut(key, *value), Dictionary);
+}
+
+
+Handle<JSFunction> Factory::NewFunctionHelper(Handle<String> name,
+                                              Handle<Object> prototype) {
+  Handle<SharedFunctionInfo> function_share = NewSharedFunctionInfo(name);
+  CALL_HEAP_FUNCTION(Heap::AllocateFunction(*Top::function_map(),
+                                            *function_share,
+                                            *prototype),
+                     JSFunction);
+}
+
+
+Handle<JSFunction> Factory::NewFunction(Handle<String> name,
+                                        Handle<Object> prototype) {
+  Handle<JSFunction> fun = NewFunctionHelper(name, prototype);
+  fun->set_context(Top::context()->global_context());
+  return fun;
+}
+
+
+Handle<Object> Factory::ToObject(Handle<Object> object,
+                                 Handle<Context> global_context) {
+  CALL_HEAP_FUNCTION(object->ToObject(*global_context), Object);
+}
+
+
+Handle<DebugInfo> Factory::NewDebugInfo(Handle<SharedFunctionInfo> shared) {
+  // Get the original code of the function.
+  Handle<Code> code(shared->code());
+
+  // Create a copy of the code before allocating the debug info object to avoid
+  // allocation while setting up the debug info object.
+  Handle<Code> original_code(*Factory::CopyCode(code));
+
+  // Allocate initial fixed array for active break points before allocating the
+  // debug info object to avoid allocation while setting up the debug info
+  // object.
+  Handle<FixedArray> break_points(
+      Factory::NewFixedArray(Debug::kEstimatedNofBreakPointsInFunction));
+
+  // Create and set up the debug info object. Debug info contains function, a
+  // copy of the original code, the executing code and initial fixed array for
+  // active break points.
+  Handle<DebugInfo> debug_info =
+      Handle<DebugInfo>::cast(Factory::NewStruct(DEBUG_INFO_TYPE));
+  debug_info->set_shared(*shared);
+  debug_info->set_original_code(*original_code);
+  debug_info->set_code(*code);
+  debug_info->set_break_points(*break_points);
+
+  // Link debug info to function.
+  shared->set_debug_info(*debug_info);
+
+  return debug_info;
+}
+
+
+Handle<JSObject> Factory::NewArgumentsObject(Handle<Object> callee,
+                                             int length) {
+  CALL_HEAP_FUNCTION(Heap::AllocateArgumentsObject(*callee, length), JSObject);
+}
+
+
+Handle<JSFunction> Factory::CreateApiFunction(
+    Handle<FunctionTemplateInfo> obj, ApiInstanceType instance_type) {
+  Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::HandleApiCall));
+
+  int internal_field_count = 0;
+  if (!obj->instance_template()->IsUndefined()) {
+    Handle<ObjectTemplateInfo> instance_template =
+        Handle<ObjectTemplateInfo>(
+            ObjectTemplateInfo::cast(obj->instance_template()));
+    internal_field_count =
+        Smi::cast(instance_template->internal_field_count())->value();
+  }
+
+  int instance_size = kPointerSize * internal_field_count;
+  InstanceType type = INVALID_TYPE;
+  switch (instance_type) {
+    case JavaScriptObject:
+      type = JS_OBJECT_TYPE;
+      instance_size += JSObject::kHeaderSize;
+      break;
+    case InnerGlobalObject:
+      type = JS_GLOBAL_OBJECT_TYPE;
+      instance_size += JSGlobalObject::kSize;
+      break;
+    case OuterGlobalObject:
+      type = JS_GLOBAL_PROXY_TYPE;
+      instance_size += JSGlobalProxy::kSize;
+      break;
+    default:
+      break;
+  }
+  ASSERT(type != INVALID_TYPE);
+
+  Handle<JSFunction> result =
+      Factory::NewFunction(Factory::empty_symbol(),
+                           type,
+                           instance_size,
+                           code,
+                           true);
+  // Set class name.
+  Handle<Object> class_name = Handle<Object>(obj->class_name());
+  if (class_name->IsString()) {
+    result->shared()->set_instance_class_name(*class_name);
+    result->shared()->set_name(*class_name);
+  }
+
+  Handle<Map> map = Handle<Map>(result->initial_map());
+
+  // Mark as undetectable if needed.
+  if (obj->undetectable()) {
+    map->set_is_undetectable();
+  }
+
+  // Mark as hidden for the __proto__ accessor if needed.
+  if (obj->hidden_prototype()) {
+    map->set_is_hidden_prototype();
+  }
+
+  // Mark as needs_access_check if needed.
+  if (obj->needs_access_check()) {
+    map->set_is_access_check_needed(true);
+  }
+
+  // Set interceptor information in the map.
+  if (!obj->named_property_handler()->IsUndefined()) {
+    map->set_has_named_interceptor();
+  }
+  if (!obj->indexed_property_handler()->IsUndefined()) {
+    map->set_has_indexed_interceptor();
+  }
+
+  // Set instance call-as-function information in the map.
+  if (!obj->instance_call_handler()->IsUndefined()) {
+    map->set_has_instance_call_handler();
+  }
+
+  result->shared()->set_function_data(*obj);
+  result->shared()->DontAdaptArguments();
+
+  // Recursively copy parent templates' accessors, 'data' may be modified.
+  Handle<DescriptorArray> array =
+      Handle<DescriptorArray>(map->instance_descriptors());
+  while (true) {
+    Handle<Object> props = Handle<Object>(obj->property_accessors());
+    if (!props->IsUndefined()) {
+      array = Factory::CopyAppendCallbackDescriptors(array, props);
+    }
+    Handle<Object> parent = Handle<Object>(obj->parent_template());
+    if (parent->IsUndefined()) break;
+    obj = Handle<FunctionTemplateInfo>::cast(parent);
+  }
+  if (!array->IsEmpty()) {
+    map->set_instance_descriptors(*array);
+  }
+
+  return result;
+}
+
+
+Handle<MapCache> Factory::NewMapCache(int at_least_space_for) {
+  CALL_HEAP_FUNCTION(MapCache::Allocate(at_least_space_for), MapCache);
+}
+
+
+static Object* UpdateMapCacheWith(Context* context,
+                                  FixedArray* keys,
+                                  Map* map) {
+  Object* result = MapCache::cast(context->map_cache())->Put(keys, map);
+  if (!result->IsFailure()) context->set_map_cache(MapCache::cast(result));
+  return result;
+}
+
+
+Handle<MapCache> Factory::AddToMapCache(Handle<Context> context,
+                                        Handle<FixedArray> keys,
+                                        Handle<Map> map) {
+  CALL_HEAP_FUNCTION(UpdateMapCacheWith(*context, *keys, *map), MapCache);
+}
+
+
+Handle<Map> Factory::ObjectLiteralMapFromCache(Handle<Context> context,
+                                               Handle<FixedArray> keys) {
+  if (context->map_cache()->IsUndefined()) {
+    // Allocate the new map cache for the global context.
+    Handle<MapCache> new_cache = NewMapCache(24);
+    context->set_map_cache(*new_cache);
+  }
+  // Check to see whether there is a matching element in the cache.
+  Handle<MapCache> cache =
+      Handle<MapCache>(MapCache::cast(context->map_cache()));
+  Handle<Object> result = Handle<Object>(cache->Lookup(*keys));
+  if (result->IsMap()) return Handle<Map>::cast(result);
+  // Create a new map and add it to the cache.
+  Handle<Map> map =
+      CopyMap(Handle<Map>(context->object_function()->initial_map()),
+              keys->length());
+  AddToMapCache(context, keys, map);
+  return Handle<Map>(map);
+}
+
+
+void Factory::SetRegExpAtomData(Handle<JSRegExp> regexp,
+                                JSRegExp::Type type,
+                                Handle<String> source,
+                                JSRegExp::Flags flags,
+                                Handle<Object> data) {
+  Handle<FixedArray> store = NewFixedArray(JSRegExp::kAtomDataSize);
+
+  store->set(JSRegExp::kTagIndex, Smi::FromInt(type));
+  store->set(JSRegExp::kSourceIndex, *source);
+  store->set(JSRegExp::kFlagsIndex, Smi::FromInt(flags.value()));
+  store->set(JSRegExp::kAtomPatternIndex, *data);
+  regexp->set_data(*store);
+}
+
+void Factory::SetRegExpIrregexpData(Handle<JSRegExp> regexp,
+                                    JSRegExp::Type type,
+                                    Handle<String> source,
+                                    JSRegExp::Flags flags,
+                                    int capture_count) {
+  Handle<FixedArray> store = NewFixedArray(JSRegExp::kIrregexpDataSize);
+
+  store->set(JSRegExp::kTagIndex, Smi::FromInt(type));
+  store->set(JSRegExp::kSourceIndex, *source);
+  store->set(JSRegExp::kFlagsIndex, Smi::FromInt(flags.value()));
+  store->set(JSRegExp::kIrregexpASCIICodeIndex, Heap::the_hole_value());
+  store->set(JSRegExp::kIrregexpUC16CodeIndex, Heap::the_hole_value());
+  store->set(JSRegExp::kIrregexpMaxRegisterCountIndex, Smi::FromInt(0));
+  store->set(JSRegExp::kIrregexpCaptureCountIndex,
+             Smi::FromInt(capture_count));
+  regexp->set_data(*store);
+}
+
+
+
+void Factory::ConfigureInstance(Handle<FunctionTemplateInfo> desc,
+                                Handle<JSObject> instance,
+                                bool* pending_exception) {
+  // Configure the instance by adding the properties specified by the
+  // instance template.
+  Handle<Object> instance_template = Handle<Object>(desc->instance_template());
+  if (!instance_template->IsUndefined()) {
+    Execution::ConfigureInstance(instance,
+                                 instance_template,
+                                 pending_exception);
+  } else {
+    *pending_exception = false;
+  }
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/factory.h b/deps/v8/src/factory.h
new file mode 100644
index 0000000..2564c3c
--- /dev/null
+++ b/deps/v8/src/factory.h
@@ -0,0 +1,361 @@
+// 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_FACTORY_H_
+#define V8_FACTORY_H_
+
+#include "heap.h"
+
+namespace v8 { namespace internal {
+
+
+// Interface for handle based allocation.
+
+class Factory : public AllStatic {
+ public:
+  // Allocate a new fixed array with undefined entries.
+  static Handle<FixedArray> NewFixedArray(
+      int size,
+      PretenureFlag pretenure = NOT_TENURED);
+
+  // Allocate a new fixed array with non-existing entries (the hole).
+  static Handle<FixedArray> NewFixedArrayWithHoles(int size);
+
+  static Handle<Dictionary> NewDictionary(int at_least_space_for);
+
+  static Handle<DescriptorArray> NewDescriptorArray(int number_of_descriptors);
+
+  static Handle<String> LookupSymbol(Vector<const char> str);
+  static Handle<String> LookupAsciiSymbol(const char* str) {
+    return LookupSymbol(CStrVector(str));
+  }
+
+
+  // String creation functions.  Most of the string creation functions take
+  // a Heap::PretenureFlag argument to optionally request that they be
+  // allocated in the old generation.  The pretenure flag defaults to
+  // DONT_TENURE.
+  //
+  // Creates a new String object.  There are two String encodings: ASCII and
+  // two byte.  One should choose between the three string factory functions
+  // based on the encoding of the string buffer that the string is
+  // initialized from.
+  //   - ...FromAscii initializes the string from a buffer that is ASCII
+  //     encoded (it does not check that the buffer is ASCII encoded) and
+  //     the result will be ASCII encoded.
+  //   - ...FromUtf8 initializes the string from a buffer that is UTF-8
+  //     encoded.  If the characters are all single-byte characters, the
+  //     result will be ASCII encoded, otherwise it will converted to two
+  //     byte.
+  //   - ...FromTwoByte initializes the string from a buffer that is two
+  //     byte encoded.  If the characters are all single-byte characters,
+  //     the result will be converted to ASCII, otherwise it will be left as
+  //     two byte.
+  //
+  // ASCII strings are pretenured when used as keys in the SourceCodeCache.
+  static Handle<String> NewStringFromAscii(
+      Vector<const char> str,
+      PretenureFlag pretenure = NOT_TENURED);
+
+  // UTF8 strings are pretenured when used for regexp literal patterns and
+  // flags in the parser.
+  static Handle<String> NewStringFromUtf8(
+      Vector<const char> str,
+      PretenureFlag pretenure = NOT_TENURED);
+
+  static Handle<String> NewStringFromTwoByte(Vector<const uc16> str);
+
+  // Allocates and partially initializes a TwoByte String. The characters of
+  // the string are uninitialized. Currently used in regexp code only, where
+  // they are pretenured.
+  static Handle<String> NewRawTwoByteString(
+      int length,
+      PretenureFlag pretenure = NOT_TENURED);
+
+  // Create a new cons string object which consists of a pair of strings.
+  static Handle<String> NewConsString(Handle<String> first,
+                                      Handle<String> second);
+
+  // Create a new sliced string object which represents a substring of a
+  // backing string.
+  static Handle<String> NewStringSlice(Handle<String> str,
+                                       int begin,
+                                       int end);
+
+  // Creates a new external String object.  There are two String encodings
+  // in the system: ASCII and two byte.  Unlike other String types, it does
+  // not make sense to have a UTF-8 factory function for external strings,
+  // because we cannot change the underlying buffer.
+  static Handle<String> NewExternalStringFromAscii(
+      ExternalAsciiString::Resource* resource);
+  static Handle<String> NewExternalStringFromTwoByte(
+      ExternalTwoByteString::Resource* resource);
+
+  // Create a global (but otherwise uninitialized) context.
+  static Handle<Context> NewGlobalContext();
+
+  // Create a function context.
+  static Handle<Context> NewFunctionContext(int length,
+                                            Handle<JSFunction> closure);
+
+  // Create a 'with' context.
+  static Handle<Context> NewWithContext(Handle<Context> previous,
+                                        Handle<JSObject> extension,
+                                        bool is_catch_context);
+
+  // Return the Symbol matching the passed in string.
+  static Handle<String> SymbolFromString(Handle<String> value);
+
+  // Allocate a new struct.  The struct is pretenured (allocated directly in
+  // the old generation).
+  static Handle<Struct> NewStruct(InstanceType type);
+
+  static Handle<AccessorInfo> NewAccessorInfo();
+
+  static Handle<Script> NewScript(Handle<String> source);
+
+  // Proxies are pretenured when allocated by the bootstrapper.
+  static Handle<Proxy> NewProxy(Address addr,
+                                PretenureFlag pretenure = NOT_TENURED);
+
+  // Allocate a new proxy.  The proxy is pretenured (allocated directly in
+  // the old generation).
+  static Handle<Proxy> NewProxy(const AccessorDescriptor* proxy);
+
+  static Handle<ByteArray> NewByteArray(int length,
+                                        PretenureFlag pretenure = NOT_TENURED);
+
+  static Handle<Map> NewMap(InstanceType type, int instance_size);
+
+  static Handle<JSObject> NewFunctionPrototype(Handle<JSFunction> function);
+
+  static Handle<Map> CopyMap(Handle<Map> map);
+
+  // Copy the map adding more inobject properties if possible without
+  // overflowing the instance size.
+  static Handle<Map> CopyMap(Handle<Map> map, int extra_inobject_props);
+
+  static Handle<Map> CopyMapDropTransitions(Handle<Map> map);
+
+  static Handle<FixedArray> CopyFixedArray(Handle<FixedArray> array);
+
+  // Numbers (eg, literals) are pretenured by the parser.
+  static Handle<Object> NewNumber(double value,
+                                  PretenureFlag pretenure = NOT_TENURED);
+
+  static Handle<Object> NewNumberFromInt(int value);
+  static Handle<Object> NewNumberFromUint(uint32_t value);
+
+  // These objects are used by the api to create env-independent data
+  // structures in the heap.
+  static Handle<JSObject> NewNeanderObject();
+
+  static Handle<JSObject> NewArgumentsObject(Handle<Object> callee, int length);
+
+  // JS objects are pretenured when allocated by the bootstrapper and
+  // runtime.
+  static Handle<JSObject> NewJSObject(Handle<JSFunction> constructor,
+                                      PretenureFlag pretenure = NOT_TENURED);
+
+  // JS objects are pretenured when allocated by the bootstrapper and
+  // runtime.
+  static Handle<JSObject> NewJSObjectFromMap(Handle<Map> map);
+
+  // JS arrays are pretenured when allocated by the parser.
+  static Handle<JSArray> NewJSArray(int init_length,
+                                    PretenureFlag pretenure = NOT_TENURED);
+
+  static Handle<JSArray> NewJSArrayWithElements(
+      Handle<FixedArray> elements,
+      PretenureFlag pretenure = NOT_TENURED);
+
+  static Handle<JSFunction> NewFunction(Handle<String> name,
+                                        Handle<Object> prototype);
+
+  static Handle<JSFunction> NewFunction(Handle<Object> super, bool is_global);
+
+  static Handle<JSFunction> NewFunctionFromBoilerplate(
+      Handle<JSFunction> boilerplate,
+      Handle<Context> context);
+
+  static Handle<Code> NewCode(const CodeDesc& desc, ScopeInfo<>* sinfo,
+                              Code::Flags flags, Handle<Object> self_reference);
+
+  static Handle<Code> CopyCode(Handle<Code> code);
+
+  static Handle<Object> ToObject(Handle<Object> object,
+                                 Handle<Context> global_context);
+
+  // Interface for creating error objects.
+
+  static Handle<Object> NewError(const char* maker, const char* type,
+                                 Handle<JSArray> args);
+  static Handle<Object> NewError(const char* maker, const char* type,
+                                 Vector< Handle<Object> > args);
+  static Handle<Object> NewError(const char* type,
+                                 Vector< Handle<Object> > args);
+  static Handle<Object> NewError(Handle<String> message);
+  static Handle<Object> NewError(const char* constructor,
+                                 Handle<String> message);
+
+  static Handle<Object> NewTypeError(const char* type,
+                                     Vector< Handle<Object> > args);
+  static Handle<Object> NewTypeError(Handle<String> message);
+
+  static Handle<Object> NewRangeError(const char* type,
+                                      Vector< Handle<Object> > args);
+  static Handle<Object> NewRangeError(Handle<String> message);
+
+  static Handle<Object> NewSyntaxError(const char* type, Handle<JSArray> args);
+  static Handle<Object> NewSyntaxError(Handle<String> message);
+
+  static Handle<Object> NewReferenceError(const char* type,
+                                          Vector< Handle<Object> > args);
+  static Handle<Object> NewReferenceError(Handle<String> message);
+
+  static Handle<Object> NewEvalError(const char* type,
+                                     Vector< Handle<Object> > args);
+
+
+  static Handle<JSFunction> NewFunction(Handle<String> name,
+                                        InstanceType type,
+                                        int instance_size,
+                                        Handle<Code> code,
+                                        bool force_initial_map);
+
+  static Handle<JSFunction> NewFunctionBoilerplate(Handle<String> name,
+                                                   int number_of_literals,
+                                                   bool contains_array_literal,
+                                                   Handle<Code> code);
+
+  static Handle<JSFunction> NewFunctionBoilerplate(Handle<String> name);
+
+  static Handle<JSFunction> NewFunction(Handle<Map> function_map,
+      Handle<SharedFunctionInfo> shared, Handle<Object> prototype);
+
+
+  static Handle<JSFunction> NewFunctionWithPrototype(Handle<String> name,
+                                                     InstanceType type,
+                                                     int instance_size,
+                                                     Handle<JSObject> prototype,
+                                                     Handle<Code> code,
+                                                     bool force_initial_map);
+
+  static Handle<DescriptorArray> CopyAppendProxyDescriptor(
+      Handle<DescriptorArray> array,
+      Handle<String> key,
+      Handle<Object> value,
+      PropertyAttributes attributes);
+
+  enum ApiInstanceType {
+    JavaScriptObject,
+    InnerGlobalObject,
+    OuterGlobalObject
+  };
+
+  static Handle<JSFunction> CreateApiFunction(
+      Handle<FunctionTemplateInfo> data,
+      ApiInstanceType type = JavaScriptObject);
+
+  static Handle<JSFunction> InstallMembers(Handle<JSFunction> function);
+
+  // Installs interceptors on the instance.  'desc' is a function template,
+  // and instance is an object instance created by the function of this
+  // function template.
+  static void ConfigureInstance(Handle<FunctionTemplateInfo> desc,
+                                Handle<JSObject> instance,
+                                bool* pending_exception);
+
+#define ROOT_ACCESSOR(type, name) \
+  static Handle<type> name() { return Handle<type>(&Heap::name##_); }
+  ROOT_LIST(ROOT_ACCESSOR)
+#undef ROOT_ACCESSOR_ACCESSOR
+
+#define SYMBOL_ACCESSOR(name, str) \
+  static Handle<String> name() { return Handle<String>(&Heap::name##_); }
+  SYMBOL_LIST(SYMBOL_ACCESSOR)
+#undef SYMBOL_ACCESSOR
+
+  static Handle<String> hidden_symbol() {
+    return Handle<String>(&Heap::hidden_symbol_);
+  }
+
+  static Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name);
+
+  static Handle<Dictionary> DictionaryAtNumberPut(Handle<Dictionary>,
+                                                  uint32_t key,
+                                                  Handle<Object> value);
+
+  static Handle<DebugInfo> NewDebugInfo(Handle<SharedFunctionInfo> shared);
+
+
+  // Return a map using the map cache in the global context.
+  // The key the an ordered set of property names.
+  static Handle<Map> ObjectLiteralMapFromCache(Handle<Context> context,
+                                               Handle<FixedArray> keys);
+
+  // Creates a new FixedArray that holds the data associated with the
+  // atom regexp and stores it in the regexp.
+  static void SetRegExpAtomData(Handle<JSRegExp> regexp,
+                                JSRegExp::Type type,
+                                Handle<String> source,
+                                JSRegExp::Flags flags,
+                                Handle<Object> match_pattern);
+
+  // Creates a new FixedArray that holds the data associated with the
+  // irregexp regexp and stores it in the regexp.
+  static void SetRegExpIrregexpData(Handle<JSRegExp> regexp,
+                                    JSRegExp::Type type,
+                                    Handle<String> source,
+                                    JSRegExp::Flags flags,
+                                    int capture_count);
+
+ private:
+  static Handle<JSFunction> NewFunctionHelper(Handle<String> name,
+                                              Handle<Object> prototype);
+
+  static Handle<DescriptorArray> CopyAppendCallbackDescriptors(
+      Handle<DescriptorArray> array,
+      Handle<Object> descriptors);
+
+  static Handle<JSFunction> BaseNewFunctionFromBoilerplate(
+      Handle<JSFunction> boilerplate,
+      Handle<Map> function_map);
+
+  // Create a new map cache.
+  static Handle<MapCache> NewMapCache(int at_least_space_for);
+
+  // Update the map cache in the global context with (keys, map)
+  static Handle<MapCache> AddToMapCache(Handle<Context> context,
+                                        Handle<FixedArray> keys,
+                                        Handle<Map> map);
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_FACTORY_H_
diff --git a/deps/v8/src/flag-definitions.h b/deps/v8/src/flag-definitions.h
new file mode 100644
index 0000000..db49453
--- /dev/null
+++ b/deps/v8/src/flag-definitions.h
@@ -0,0 +1,384 @@
+// Copyright 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.
+
+// This file defines all of the flags.  It is separated into different section,
+// for Debug, Release, Logging and Profiling, etc.  To add a new flag, find the
+// correct section, and use one of the DEFINE_ macros, without a trailing ';'.
+//
+// This include does not have a guard, because it is a template-style include,
+// which can be included multiple times in different modes.  It expects to have
+// a mode defined before it's included.  The modes are FLAG_MODE_... below:
+
+// We want to declare the names of the variables for the header file.  Normally
+// this will just be an extern declaration, but for a readonly flag we let the
+// compiler make better optimizations by giving it the value.
+#if defined(FLAG_MODE_DECLARE)
+#define FLAG_FULL(ftype, ctype, nam, def, cmt) \
+  extern ctype FLAG_##nam;
+#define FLAG_READONLY(ftype, ctype, nam, def, cmt) \
+  static ctype const FLAG_##nam = def;
+
+// We want to supply the actual storage and value for the flag variable in the
+// .cc file.  We only do this for writable flags.
+#elif defined(FLAG_MODE_DEFINE)
+#define FLAG_FULL(ftype, ctype, nam, def, cmt) \
+  ctype FLAG_##nam = def;
+#define FLAG_READONLY(ftype, ctype, nam, def, cmt)
+
+// We need to define all of our default values so that the Flag structure can
+// access them by pointer.  These are just used internally inside of one .cc,
+// for MODE_META, so there is no impact on the flags interface.
+#elif defined(FLAG_MODE_DEFINE_DEFAULTS)
+#define FLAG_FULL(ftype, ctype, nam, def, cmt) \
+  static ctype const FLAGDEFAULT_##nam = def;
+#define FLAG_READONLY(ftype, ctype, nam, def, cmt)
+
+
+// We want to write entries into our meta data table, for internal parsing and
+// printing / etc in the flag parser code.  We only do this for writable flags.
+#elif defined(FLAG_MODE_META)
+#define FLAG_FULL(ftype, ctype, nam, def, cmt) \
+  { Flag::TYPE_##ftype, #nam, &FLAG_##nam, &FLAGDEFAULT_##nam, cmt, false },
+#define FLAG_READONLY(ftype, ctype, nam, def, cmt)
+
+#else
+#error No mode supplied when including flags.defs
+#endif
+
+#ifdef FLAG_MODE_DECLARE
+// Structure used to hold a collection of arguments to the JavaScript code.
+struct JSArguments {
+public:
+  JSArguments();
+  JSArguments(int argc, const char** argv);
+  int argc() const;
+  const char** argv();
+  const char*& operator[](int idx);
+  JSArguments& operator=(JSArguments args);
+private:
+  int argc_;
+  const char** argv_;
+};
+#endif
+
+#define DEFINE_bool(nam, def, cmt) FLAG(BOOL, bool, nam, def, cmt)
+#define DEFINE_int(nam, def, cmt) FLAG(INT, int, nam, def, cmt)
+#define DEFINE_float(nam, def, cmt) FLAG(FLOAT, double, nam, def, cmt)
+#define DEFINE_string(nam, def, cmt) FLAG(STRING, const char*, nam, def, cmt)
+#define DEFINE_args(nam, def, cmt) FLAG(ARGS, JSArguments, nam, def, cmt)
+
+//
+// Flags in all modes.
+//
+#define FLAG FLAG_FULL
+
+// assembler-ia32.cc / assembler-arm.cc
+DEFINE_bool(debug_code, false,
+            "generate extra code (comments, assertions) for debugging")
+DEFINE_bool(emit_branch_hints, false, "emit branch hints")
+DEFINE_bool(push_pop_elimination, true,
+            "eliminate redundant push/pops in assembly code")
+DEFINE_bool(print_push_pop_elimination, false,
+            "print elimination of redundant push/pops in assembly code")
+
+// bootstrapper.cc
+DEFINE_string(expose_natives_as, NULL, "expose natives in global object")
+DEFINE_string(expose_debug_as, NULL, "expose debug in global object")
+DEFINE_string(natives_file, NULL, "alternative natives file")
+DEFINE_bool(expose_gc, false, "expose gc extension")
+
+// builtins-ia32.cc
+DEFINE_bool(inline_new, true, "use fast inline allocation")
+
+// checks.cc
+DEFINE_bool(stack_trace_on_abort, true,
+            "print a stack trace if an assertion failure occurs")
+
+// codegen-ia32.cc / codegen-arm.cc
+DEFINE_bool(trace, false, "trace function calls")
+DEFINE_bool(defer_negation, true, "defer negation operation")
+DEFINE_bool(check_stack, true,
+            "check stack for overflow, interrupt, breakpoint")
+
+// codegen.cc
+DEFINE_bool(lazy, true, "use lazy compilation")
+DEFINE_bool(debug_info, true, "add debug information to compiled functions")
+
+// compiler.cc
+DEFINE_bool(strict, false, "strict error checking")
+DEFINE_int(min_preparse_length, 1024,
+           "Minimum length for automatic enable preparsing")
+
+// debug.cc
+DEFINE_bool(remote_debugging, false, "enable remote debugging")
+DEFINE_bool(trace_debug_json, false, "trace debugging JSON request/response")
+DEFINE_bool(debugger_auto_break, false,
+            "automatically set the debug break flag when debugger commands are "
+            "in the queue (experimental)")
+
+// execution.cc
+DEFINE_bool(call_regexp, false, "allow calls to RegExp objects")
+
+// frames.cc
+DEFINE_int(max_stack_trace_source_length, 300,
+           "maximum length of function source code printed in a stack trace.")
+
+// heap.cc
+DEFINE_int(new_space_size, 0, "size of (each semispace in) the new generation")
+DEFINE_int(old_space_size, 0, "size of the old generation")
+DEFINE_bool(gc_global, false, "always perform global GCs")
+DEFINE_int(gc_interval, -1, "garbage collect after <n> allocations")
+DEFINE_bool(trace_gc, false,
+            "print one trace line following each garbage collection")
+DEFINE_bool(collect_maps, true,
+            "garbage collect maps from which no objects can be reached")
+
+// ic.cc
+DEFINE_bool(use_ic, true, "use inline caching")
+
+// macro-assembler-ia32.cc
+DEFINE_bool(native_code_counters, false,
+            "generate extra code for manipulating stats counters")
+
+// mark-compact.cc
+DEFINE_bool(always_compact, false, "Perform compaction on every full GC")
+DEFINE_bool(never_compact, false,
+            "Never perform compaction on full GC - testing only")
+DEFINE_bool(cleanup_ics_at_gc, true,
+            "Flush inline caches prior to mark compact collection.")
+DEFINE_bool(cleanup_caches_in_maps_at_gc, true,
+            "Flush code caches in maps during mark compact cycle.")
+
+DEFINE_bool(canonicalize_object_literal_maps, true,
+            "Canonicalize maps for object literals.")
+
+// mksnapshot.cc
+DEFINE_bool(h, false, "print this message")
+
+// parser.cc
+DEFINE_bool(allow_natives_syntax, false, "allow natives syntax")
+
+// rewriter.cc
+DEFINE_bool(optimize_ast, true, "optimize the ast")
+
+// simulator-arm.cc
+DEFINE_bool(trace_sim, false, "trace simulator execution")
+DEFINE_int(stop_sim_at, 0, "Simulator stop after x number of instructions")
+
+// top.cc
+DEFINE_bool(trace_exception, false,
+            "print stack trace when throwing exceptions")
+DEFINE_bool(preallocate_message_memory, false,
+            "preallocate some memory to build stack traces.")
+
+// usage-analyzer.cc
+DEFINE_bool(usage_computation, true, "compute variable usage counts")
+
+// v8.cc
+DEFINE_bool(preemption, false,
+            "activate a 100ms timer that switches between V8 threads")
+
+// Regexp
+DEFINE_bool(trace_regexps, false, "trace regexp execution")
+DEFINE_bool(regexp_native, true,
+            "use native code regexp implementation (IA32 only)")
+DEFINE_bool(regexp_optimization, true, "generate optimized regexp code")
+
+// Testing flags test/cctest/test-{flags,api,serialization}.cc
+DEFINE_bool(testing_bool_flag, true, "testing_bool_flag")
+DEFINE_int(testing_int_flag, 13, "testing_int_flag")
+DEFINE_float(testing_float_flag, 2.5, "float-flag")
+DEFINE_string(testing_string_flag, "Hello, world!", "string-flag")
+DEFINE_int(testing_prng_seed, 42, "Seed used for threading test randomness")
+#ifdef WIN32
+DEFINE_string(testing_serialization_file, "C:\\Windows\\Temp\\serdes",
+              "file in which to testing_serialize heap")
+#else
+DEFINE_string(testing_serialization_file, "/tmp/serdes",
+              "file in which to serialize heap")
+#endif
+
+//
+// Dev shell flags
+//
+
+DEFINE_bool(help, false, "Print usage message, including flags, on console")
+DEFINE_bool(dump_counters, false, "Dump counters on exit")
+DEFINE_bool(debugger, true, "Enable JavaScript debugger")
+DEFINE_bool(remote_debugger, false, "Connect JavaScript debugger to the "
+                                    "debugger agent in another process")
+DEFINE_bool(debugger_agent, false, "Enable debugger agent")
+DEFINE_int(debugger_port, 5858, "Port to use for remote debugging")
+DEFINE_string(map_counters, false, "Map counters to a file")
+DEFINE_args(js_arguments, JSArguments(),
+            "Pass all remaining arguments to the script. Alias for \"--\".")
+
+//
+// Debug only flags
+//
+#undef FLAG
+#ifdef DEBUG
+#define FLAG FLAG_FULL
+#else
+#define FLAG FLAG_READONLY
+#endif
+
+// checks.cc
+DEFINE_bool(enable_slow_asserts, false,
+            "enable asserts that are slow to execute")
+
+// codegen-ia32.cc / codegen-arm.cc
+DEFINE_bool(trace_codegen, false,
+            "print name of functions for which code is generated")
+DEFINE_bool(print_source, false, "pretty print source code")
+DEFINE_bool(print_builtin_source, false,
+            "pretty print source code for builtins")
+DEFINE_bool(print_ast, false, "print source AST")
+DEFINE_bool(print_builtin_ast, false, "print source AST for builtins")
+DEFINE_bool(trace_calls, false, "trace calls")
+DEFINE_bool(trace_builtin_calls, false, "trace builtins calls")
+DEFINE_string(stop_at, "", "function name where to insert a breakpoint")
+
+// compiler.cc
+DEFINE_bool(print_builtin_scopes, false, "print scopes for builtins")
+DEFINE_bool(print_scopes, false, "print scopes")
+
+// contexts.cc
+DEFINE_bool(trace_contexts, false, "trace contexts operations")
+
+// heap.cc
+DEFINE_bool(gc_greedy, false, "perform GC prior to some allocations")
+DEFINE_bool(gc_verbose, false, "print stuff during garbage collection")
+DEFINE_bool(heap_stats, false, "report heap statistics before and after GC")
+DEFINE_bool(code_stats, false, "report code statistics after GC")
+DEFINE_bool(verify_heap, false, "verify heap pointers before and after GC")
+DEFINE_bool(print_handles, false, "report handles after GC")
+DEFINE_bool(print_global_handles, false, "report global handles after GC")
+DEFINE_bool(print_rset, false, "print remembered sets before GC")
+
+// ic.cc
+DEFINE_bool(trace_ic, false, "trace inline cache state transitions")
+
+// objects.cc
+DEFINE_bool(trace_normalization,
+            false,
+            "prints when objects are turned into dictionaries.")
+
+// runtime.cc
+DEFINE_bool(trace_lazy, false, "trace lazy compilation")
+
+// serialize.cc
+DEFINE_bool(debug_serialization, false,
+            "write debug information into the snapshot.")
+
+// spaces.cc
+DEFINE_bool(collect_heap_spill_statistics, false,
+            "report heap spill statistics along with heap_stats "
+            "(requires heap_stats)")
+
+// Regexp
+DEFINE_bool(trace_regexp_bytecodes, false, "trace regexp bytecode execution")
+DEFINE_bool(trace_regexp_assembler,
+            false,
+            "trace regexp macro assembler calls.")
+
+//
+// Logging and profiling only flags
+//
+#undef FLAG
+#ifdef ENABLE_LOGGING_AND_PROFILING
+#define FLAG FLAG_FULL
+#else
+#define FLAG FLAG_READONLY
+#endif
+
+// log.cc
+DEFINE_bool(log, false,
+            "Minimal logging (no API, code, GC, suspect, or handles samples).")
+DEFINE_bool(log_all, false, "Log all events to the log file.")
+DEFINE_bool(log_runtime, false, "Activate runtime system %Log call.")
+DEFINE_bool(log_api, false, "Log API events to the log file.")
+DEFINE_bool(log_code, false,
+            "Log code events to the log file without profiling.")
+DEFINE_bool(log_gc, false,
+            "Log heap samples on garbage collection for the hp2ps tool.")
+DEFINE_bool(log_handles, false, "Log global handle events.")
+DEFINE_bool(log_state_changes, false, "Log state changes.")
+DEFINE_bool(log_suspect, false, "Log suspect operations.")
+DEFINE_bool(prof, false,
+            "Log statistical profiling information (implies --log-code).")
+DEFINE_bool(prof_auto, true,
+            "Used with --prof, starts profiling automatically")
+DEFINE_bool(log_regexp, false, "Log regular expression execution.")
+DEFINE_bool(sliding_state_window, false,
+            "Update sliding state window counters.")
+DEFINE_string(logfile, "v8.log", "Specify the name of the log file.")
+DEFINE_bool(oprofile, false, "Enable JIT agent for OProfile.")
+
+//
+// Heap protection flags
+// Using heap protection requires ENABLE_LOGGING_AND_PROFILING as well.
+//
+#ifdef ENABLE_HEAP_PROTECTION
+#undef FLAG
+#define FLAG FLAG_FULL
+
+DEFINE_bool(protect_heap, false,
+            "Protect/unprotect V8's heap when leaving/entring the VM.")
+
+#endif
+
+//
+// Disassembler only flags
+//
+#undef FLAG
+#ifdef ENABLE_DISASSEMBLER
+#define FLAG FLAG_FULL
+#else
+#define FLAG FLAG_READONLY
+#endif
+
+// code-stubs.cc
+DEFINE_bool(print_code_stubs, false, "print code stubs")
+
+// codegen-ia32.cc / codegen-arm.cc
+DEFINE_bool(print_code, false, "print generated code")
+DEFINE_bool(print_builtin_code, false, "print generated code for builtins")
+
+// Cleanup...
+#undef FLAG_FULL
+#undef FLAG_READONLY
+#undef FLAG
+
+#undef DEFINE_bool
+#undef DEFINE_int
+#undef DEFINE_string
+
+#undef FLAG_MODE_DECLARE
+#undef FLAG_MODE_DEFINE
+#undef FLAG_MODE_DEFINE_DEFAULTS
+#undef FLAG_MODE_META
diff --git a/deps/v8/src/flags.cc b/deps/v8/src/flags.cc
new file mode 100644
index 0000000..733d31a
--- /dev/null
+++ b/deps/v8/src/flags.cc
@@ -0,0 +1,554 @@
+// 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.
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "platform.h"
+#include "smart-pointer.h"
+#include "string-stream.h"
+
+
+namespace v8 { namespace internal {
+
+// Define all of our flags.
+#define FLAG_MODE_DEFINE
+#include "flag-definitions.h"
+
+// Define all of our flags default values.
+#define FLAG_MODE_DEFINE_DEFAULTS
+#include "flag-definitions.h"
+
+namespace {
+
+// This structure represents a single entry in the flag system, with a pointer
+// to the actual flag, default value, comment, etc.  This is designed to be POD
+// initialized as to avoid requiring static constructors.
+struct Flag {
+  enum FlagType { TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_ARGS };
+
+  FlagType type_;           // What type of flag, bool, int, or string.
+  const char* name_;        // Name of the flag, ex "my_flag".
+  void* valptr_;            // Pointer to the global flag variable.
+  const void* defptr_;      // Pointer to the default value.
+  const char* cmt_;         // A comment about the flags purpose.
+  bool owns_ptr_;           // Does the flag own its string value?
+
+  FlagType type() const { return type_; }
+
+  const char* name() const { return name_; }
+
+  const char* comment() const { return cmt_; }
+
+  bool* bool_variable() const {
+    ASSERT(type_ == TYPE_BOOL);
+    return reinterpret_cast<bool*>(valptr_);
+  }
+
+  int* int_variable() const {
+    ASSERT(type_ == TYPE_INT);
+    return reinterpret_cast<int*>(valptr_);
+  }
+
+  double* float_variable() const {
+    ASSERT(type_ == TYPE_FLOAT);
+    return reinterpret_cast<double*>(valptr_);
+  }
+
+  const char* string_value() const {
+    ASSERT(type_ == TYPE_STRING);
+    return *reinterpret_cast<const char**>(valptr_);
+  }
+
+  void set_string_value(const char *value, bool owns_ptr) {
+    ASSERT(type_ == TYPE_STRING);
+    const char **ptr = reinterpret_cast<const char **>(valptr_);
+    if (owns_ptr_ && *ptr != NULL) DeleteArray(*ptr);
+    *ptr = value;
+    owns_ptr_ = owns_ptr;
+  }
+
+  JSArguments* args_variable() const {
+    ASSERT(type_ == TYPE_ARGS);
+    return reinterpret_cast<JSArguments*>(valptr_);
+  }
+
+  bool bool_default() const {
+    ASSERT(type_ == TYPE_BOOL);
+    return *reinterpret_cast<const bool*>(defptr_);
+  }
+
+  int int_default() const {
+    ASSERT(type_ == TYPE_INT);
+    return *reinterpret_cast<const int*>(defptr_);
+  }
+
+  double float_default() const {
+    ASSERT(type_ == TYPE_FLOAT);
+    return *reinterpret_cast<const double*>(defptr_);
+  }
+
+  const char* string_default() const {
+    ASSERT(type_ == TYPE_STRING);
+    return *reinterpret_cast<const char* const *>(defptr_);
+  }
+
+  JSArguments args_default() const {
+    ASSERT(type_ == TYPE_ARGS);
+    return *reinterpret_cast<const JSArguments*>(defptr_);
+  }
+
+  // Compare this flag's current value against the default.
+  bool IsDefault() const {
+    switch (type_) {
+      case TYPE_BOOL:
+        return *bool_variable() == bool_default();
+      case TYPE_INT:
+        return *int_variable() == int_default();
+      case TYPE_FLOAT:
+        return *float_variable() == float_default();
+      case TYPE_STRING: {
+        const char* str1 = string_value();
+        const char* str2 = string_default();
+        if (str2 == NULL) return str1 == NULL;
+        if (str1 == NULL) return str2 == NULL;
+        return strcmp(str1, str2) == 0;
+      }
+      case TYPE_ARGS:
+        return args_variable()->argc() == 0;
+    }
+    UNREACHABLE();
+    return true;
+  }
+
+  // Set a flag back to it's default value.
+  void Reset() {
+    switch (type_) {
+      case TYPE_BOOL:
+        *bool_variable() = bool_default();
+        break;
+      case TYPE_INT:
+        *int_variable() = int_default();
+        break;
+      case TYPE_FLOAT:
+        *float_variable() = float_default();
+        break;
+      case TYPE_STRING:
+        set_string_value(string_default(), false);
+        break;
+      case TYPE_ARGS:
+        *args_variable() = args_default();
+        break;
+    }
+  }
+};
+
+Flag flags[] = {
+#define FLAG_MODE_META
+#include "flag-definitions.h"
+};
+
+const size_t num_flags = sizeof(flags) / sizeof(*flags);
+
+}  // namespace
+
+
+static const char* Type2String(Flag::FlagType type) {
+  switch (type) {
+    case Flag::TYPE_BOOL: return "bool";
+    case Flag::TYPE_INT: return "int";
+    case Flag::TYPE_FLOAT: return "float";
+    case Flag::TYPE_STRING: return "string";
+    case Flag::TYPE_ARGS: return "arguments";
+  }
+  UNREACHABLE();
+  return NULL;
+}
+
+
+static SmartPointer<const char> ToString(Flag* flag) {
+  HeapStringAllocator string_allocator;
+  StringStream buffer(&string_allocator);
+  switch (flag->type()) {
+    case Flag::TYPE_BOOL:
+      buffer.Add("%s", (*flag->bool_variable() ? "true" : "false"));
+      break;
+    case Flag::TYPE_INT:
+      buffer.Add("%d", *flag->int_variable());
+      break;
+    case Flag::TYPE_FLOAT:
+      buffer.Add("%f", FmtElm(*flag->float_variable()));
+      break;
+    case Flag::TYPE_STRING: {
+      const char* str = flag->string_value();
+      buffer.Add("%s", str ? str : "NULL");
+      break;
+    }
+    case Flag::TYPE_ARGS: {
+      JSArguments args = *flag->args_variable();
+      if (args.argc() > 0) {
+        buffer.Add("%s",  args[0]);
+        for (int i = 1; i < args.argc(); i++) {
+          buffer.Add(" %s", args[i]);
+        }
+      }
+      break;
+    }
+  }
+  return buffer.ToCString();
+}
+
+
+// static
+List<const char*>* FlagList::argv() {
+  List<const char*>* args = new List<const char*>(8);
+  Flag* args_flag = NULL;
+  for (size_t i = 0; i < num_flags; ++i) {
+    Flag* f = &flags[i];
+    if (!f->IsDefault()) {
+      if (f->type() == Flag::TYPE_ARGS) {
+        ASSERT(args_flag == NULL);
+        args_flag = f;  // Must be last in arguments.
+        continue;
+      }
+      HeapStringAllocator string_allocator;
+      StringStream buffer(&string_allocator);
+      if (f->type() != Flag::TYPE_BOOL || *(f->bool_variable())) {
+        buffer.Add("--%s", f->name());
+      } else {
+        buffer.Add("--no%s", f->name());
+      }
+      args->Add(buffer.ToCString().Detach());
+      if (f->type() != Flag::TYPE_BOOL) {
+        args->Add(ToString(f).Detach());
+      }
+    }
+  }
+  if (args_flag != NULL) {
+    HeapStringAllocator string_allocator;
+    StringStream buffer(&string_allocator);
+    buffer.Add("--%s", args_flag->name());
+    args->Add(buffer.ToCString().Detach());
+    JSArguments jsargs = *args_flag->args_variable();
+    for (int j = 0; j < jsargs.argc(); j++) {
+      args->Add(StrDup(jsargs[j]));
+    }
+  }
+  return args;
+}
+
+
+// Helper function to parse flags: Takes an argument arg and splits it into
+// a flag name and flag value (or NULL if they are missing). is_bool is set
+// if the arg started with "-no" or "--no". The buffer may be used to NUL-
+// terminate the name, it must be large enough to hold any possible name.
+static void SplitArgument(const char* arg,
+                          char* buffer,
+                          int buffer_size,
+                          const char** name,
+                          const char** value,
+                          bool* is_bool) {
+  *name = NULL;
+  *value = NULL;
+  *is_bool = false;
+
+  if (*arg == '-') {
+    // find the begin of the flag name
+    arg++;  // remove 1st '-'
+    if (*arg == '-') {
+      arg++;  // remove 2nd '-'
+      if (arg[0] == '\0') {
+        const char* kJSArgumentsFlagName = "js_arguments";
+        *name = kJSArgumentsFlagName;
+        return;
+      }
+    }
+    if (arg[0] == 'n' && arg[1] == 'o') {
+      arg += 2;  // remove "no"
+      *is_bool = true;
+    }
+    *name = arg;
+
+    // find the end of the flag name
+    while (*arg != '\0' && *arg != '=')
+      arg++;
+
+    // get the value if any
+    if (*arg == '=') {
+      // make a copy so we can NUL-terminate flag name
+      int n = arg - *name;
+      CHECK(n < buffer_size);  // buffer is too small
+      memcpy(buffer, *name, n);
+      buffer[n] = '\0';
+      *name = buffer;
+      // get the value
+      *value = arg + 1;
+    }
+  }
+}
+
+
+inline char NormalizeChar(char ch) {
+  return ch == '_' ? '-' : ch;
+}
+
+
+static bool EqualNames(const char* a, const char* b) {
+  for (int i = 0; NormalizeChar(a[i]) == NormalizeChar(b[i]); i++) {
+    if (a[i] == '\0') {
+      return true;
+    }
+  }
+  return false;
+}
+
+
+static Flag* FindFlag(const char* name) {
+  for (size_t i = 0; i < num_flags; ++i) {
+    if (EqualNames(name, flags[i].name()))
+      return &flags[i];
+  }
+  return NULL;
+}
+
+
+// static
+int FlagList::SetFlagsFromCommandLine(int* argc,
+                                      char** argv,
+                                      bool remove_flags) {
+  // parse arguments
+  for (int i = 1; i < *argc;) {
+    int j = i;  // j > 0
+    const char* arg = argv[i++];
+
+    // split arg into flag components
+    char buffer[1*KB];
+    const char* name;
+    const char* value;
+    bool is_bool;
+    SplitArgument(arg, buffer, sizeof buffer, &name, &value, &is_bool);
+
+    if (name != NULL) {
+      // lookup the flag
+      Flag* flag = FindFlag(name);
+      if (flag == NULL) {
+        if (remove_flags) {
+          // We don't recognize this flag but since we're removing
+          // the flags we recognize we assume that the remaining flags
+          // will be processed somewhere else so this flag might make
+          // sense there.
+          continue;
+        } else {
+          fprintf(stderr, "Error: unrecognized flag %s\n"
+                  "Try --help for options\n", arg);
+          return j;
+        }
+      }
+
+      // if we still need a flag value, use the next argument if available
+      if (flag->type() != Flag::TYPE_BOOL &&
+          flag->type() != Flag::TYPE_ARGS &&
+          value == NULL) {
+        if (i < *argc) {
+          value = argv[i++];
+        } else {
+          fprintf(stderr, "Error: missing value for flag %s of type %s\n"
+                  "Try --help for options\n",
+                  arg, Type2String(flag->type()));
+          return j;
+        }
+      }
+
+      // set the flag
+      char* endp = const_cast<char*>("");  // *endp is only read
+      switch (flag->type()) {
+        case Flag::TYPE_BOOL:
+          *flag->bool_variable() = !is_bool;
+          break;
+        case Flag::TYPE_INT:
+          *flag->int_variable() = strtol(value, &endp, 10);  // NOLINT
+          break;
+        case Flag::TYPE_FLOAT:
+          *flag->float_variable() = strtod(value, &endp);
+          break;
+        case Flag::TYPE_STRING:
+          flag->set_string_value(value ? StrDup(value) : NULL, true);
+          break;
+        case Flag::TYPE_ARGS: {
+          int start_pos = (value == NULL) ? i : i - 1;
+          int js_argc = *argc - start_pos;
+          const char** js_argv = NewArray<const char*>(js_argc);
+          if (value != NULL) {
+            js_argv[0] = StrDup(value);
+          }
+          for (int k = i; k < *argc; k++) {
+            js_argv[k - start_pos] = StrDup(argv[k]);
+          }
+          *flag->args_variable() = JSArguments(js_argc, js_argv);
+          i = *argc;  // Consume all arguments
+          break;
+        }
+      }
+
+      // handle errors
+      if ((flag->type() == Flag::TYPE_BOOL && value != NULL) ||
+          (flag->type() != Flag::TYPE_BOOL && is_bool) ||
+          *endp != '\0') {
+        fprintf(stderr, "Error: illegal value for flag %s of type %s\n"
+                "Try --help for options\n",
+                arg, Type2String(flag->type()));
+        return j;
+      }
+
+      // remove the flag & value from the command
+      if (remove_flags) {
+        while (j < i) {
+          argv[j++] = NULL;
+        }
+      }
+    }
+  }
+
+  // shrink the argument list
+  if (remove_flags) {
+    int j = 1;
+    for (int i = 1; i < *argc; i++) {
+      if (argv[i] != NULL)
+        argv[j++] = argv[i];
+    }
+    *argc = j;
+  }
+
+  if (FLAG_help) {
+    PrintHelp();
+    exit(0);
+  }
+  // parsed all flags successfully
+  return 0;
+}
+
+
+static char* SkipWhiteSpace(char* p) {
+  while (*p != '\0' && isspace(*p) != 0) p++;
+  return p;
+}
+
+
+static char* SkipBlackSpace(char* p) {
+  while (*p != '\0' && isspace(*p) == 0) p++;
+  return p;
+}
+
+
+// static
+int FlagList::SetFlagsFromString(const char* str, int len) {
+  // make a 0-terminated copy of str
+  char* copy0 = NewArray<char>(len + 1);
+  memcpy(copy0, str, len);
+  copy0[len] = '\0';
+
+  // strip leading white space
+  char* copy = SkipWhiteSpace(copy0);
+
+  // count the number of 'arguments'
+  int argc = 1;  // be compatible with SetFlagsFromCommandLine()
+  for (char* p = copy; *p != '\0'; argc++) {
+    p = SkipBlackSpace(p);
+    p = SkipWhiteSpace(p);
+  }
+
+  // allocate argument array
+  char** argv = NewArray<char*>(argc);
+
+  // split the flags string into arguments
+  argc = 1;  // be compatible with SetFlagsFromCommandLine()
+  for (char* p = copy; *p != '\0'; argc++) {
+    argv[argc] = p;
+    p = SkipBlackSpace(p);
+    if (*p != '\0') *p++ = '\0';  // 0-terminate argument
+    p = SkipWhiteSpace(p);
+  }
+
+  // set the flags
+  int result = SetFlagsFromCommandLine(&argc, argv, false);
+
+  // cleanup
+  DeleteArray(argv);
+  DeleteArray(copy0);
+
+  return result;
+}
+
+
+// static
+void FlagList::ResetAllFlags() {
+  for (size_t i = 0; i < num_flags; ++i) {
+    flags[i].Reset();
+  }
+}
+
+
+// static
+void FlagList::PrintHelp() {
+  printf("Usage:\n");
+  printf("  shell [options] -e string\n");
+  printf("    execute string in V8\n");
+  printf("  shell [options] file1 file2 ... filek\n");
+  printf("    run JavaScript scripts in file1, file2, ..., filek\n");
+  printf("  shell [options]\n");
+  printf("  shell [options] --shell [file1 file2 ... filek]\n");
+  printf("    run an interactive JavaScript shell\n");
+  printf("  d8 [options] file1 file2 ... filek\n");
+  printf("  d8 [options]\n");
+  printf("  d8 [options] --shell [file1 file2 ... filek]\n");
+  printf("    run the new debugging shell\n\n");
+  printf("Options:\n");
+  for (size_t i = 0; i < num_flags; ++i) {
+    Flag* f = &flags[i];
+    SmartPointer<const char> value = ToString(f);
+    printf("  --%s (%s)\n        type: %s  default: %s\n",
+           f->name(), f->comment(), Type2String(f->type()), *value);
+  }
+}
+
+JSArguments::JSArguments()
+    : argc_(0), argv_(NULL) {}
+JSArguments::JSArguments(int argc, const char** argv)
+    : argc_(argc), argv_(argv) {}
+int JSArguments::argc() const { return argc_; }
+const char** JSArguments::argv() { return argv_; }
+const char*& JSArguments::operator[](int idx) { return argv_[idx]; }
+JSArguments& JSArguments::operator=(JSArguments args) {
+    argc_ = args.argc_;
+    argv_ = args.argv_;
+    return *this;
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/flags.h b/deps/v8/src/flags.h
new file mode 100644
index 0000000..e6cbe3c
--- /dev/null
+++ b/deps/v8/src/flags.h
@@ -0,0 +1,80 @@
+// 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_FLAGS_H_
+#define V8_FLAGS_H_
+
+#include "checks.h"
+
+namespace v8 { namespace internal {
+
+// Declare all of our flags.
+#define FLAG_MODE_DECLARE
+#include "flag-definitions.h"
+
+// The global list of all flags.
+class FlagList {
+ public:
+  // The list of all flags with a value different from the default
+  // and their values. The format of the list is like the format of the
+  // argv array passed to the main function, e.g.
+  // ("--prof", "--log-file", "v8.prof", "--nolazy").
+  //
+  // The caller is responsible for disposing the list, as well
+  // as every element of it.
+  static List<const char*>* argv();
+
+  // Set the flag values by parsing the command line. If remove_flags is
+  // set, the flags and associated values are removed from (argc,
+  // argv). Returns 0 if no error occurred. Otherwise, returns the argv
+  // index > 0 for the argument where an error occurred. In that case,
+  // (argc, argv) will remain unchanged independent of the remove_flags
+  // value, and no assumptions about flag settings should be made.
+  //
+  // The following syntax for flags is accepted (both '-' and '--' are ok):
+  //
+  //   --flag        (bool flags only)
+  //   --noflag      (bool flags only)
+  //   --flag=value  (non-bool flags only, no spaces around '=')
+  //   --flag value  (non-bool flags only)
+  //   --            (equivalent to --js_arguments, captures all remaining args)
+  static int SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags);
+
+  // Set the flag values by parsing the string str. Splits string into argc
+  // substrings argv[], each of which consisting of non-white-space chars,
+  // and then calls SetFlagsFromCommandLine() and returns its result.
+  static int SetFlagsFromString(const char* str, int len);
+
+  // Reset all flags to their default value.
+  static void ResetAllFlags();
+
+  // Print help to stdout with flags, types, and default values.
+  static void PrintHelp();
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_FLAGS_H_
diff --git a/deps/v8/src/frames-arm.cc b/deps/v8/src/frames-arm.cc
new file mode 100644
index 0000000..121fb75
--- /dev/null
+++ b/deps/v8/src/frames-arm.cc
@@ -0,0 +1,117 @@
+// 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.
+
+#include "v8.h"
+
+#include "frames-inl.h"
+#include "assembler-arm-inl.h"
+
+
+namespace v8 { namespace internal {
+
+
+StackFrame::Type StackFrame::ComputeType(State* state) {
+  ASSERT(state->fp != NULL);
+  if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
+    return ARGUMENTS_ADAPTOR;
+  }
+  // The marker and function offsets overlap. If the marker isn't a
+  // smi then the frame is a JavaScript frame -- and the marker is
+  // really the function.
+  const int offset = StandardFrameConstants::kMarkerOffset;
+  Object* marker = Memory::Object_at(state->fp + offset);
+  if (!marker->IsSmi()) return JAVA_SCRIPT;
+  return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
+}
+
+
+StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
+  if (fp == 0) return NONE;
+  // Compute frame type and stack pointer.
+  Address sp = fp + ExitFrameConstants::kSPDisplacement;
+  Type type;
+  if (Memory::Address_at(fp + ExitFrameConstants::kDebugMarkOffset) != 0) {
+    type = EXIT_DEBUG;
+    sp -= kNumJSCallerSaved * kPointerSize;
+  } else {
+    type = EXIT;
+  }
+  // Fill in the state.
+  state->sp = sp;
+  state->fp = fp;
+  state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
+  return type;
+}
+
+
+void ExitFrame::Iterate(ObjectVisitor* v) const {
+  // Do nothing
+}
+
+
+int JavaScriptFrame::GetProvidedParametersCount() const {
+  return ComputeParametersCount();
+}
+
+
+Address JavaScriptFrame::GetCallerStackPointer() const {
+  int arguments;
+  if (Heap::gc_state() != Heap::NOT_IN_GC || disable_heap_access_) {
+    // The arguments for cooked frames are traversed as if they were
+    // expression stack elements of the calling frame. The reason for
+    // this rather strange decision is that we cannot access the
+    // function during mark-compact GCs when the stack is cooked.
+    // In fact accessing heap objects (like function->shared() below)
+    // at all during GC is problematic.
+    arguments = 0;
+  } else {
+    // Compute the number of arguments by getting the number of formal
+    // parameters of the function. We must remember to take the
+    // receiver into account (+1).
+    JSFunction* function = JSFunction::cast(this->function());
+    arguments = function->shared()->formal_parameter_count() + 1;
+  }
+  const int offset = StandardFrameConstants::kCallerSPOffset;
+  return fp() + offset + (arguments * kPointerSize);
+}
+
+
+Address ArgumentsAdaptorFrame::GetCallerStackPointer() const {
+  const int arguments = Smi::cast(GetExpression(0))->value();
+  const int offset = StandardFrameConstants::kCallerSPOffset;
+  return fp() + offset + (arguments + 1) * kPointerSize;
+}
+
+
+Address InternalFrame::GetCallerStackPointer() const {
+  // Internal frames have no arguments. The stack pointer of the
+  // caller is at a fixed offset from the frame pointer.
+  return fp() + StandardFrameConstants::kCallerSPOffset;
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/frames-arm.h b/deps/v8/src/frames-arm.h
new file mode 100644
index 0000000..930f6e0
--- /dev/null
+++ b/deps/v8/src/frames-arm.h
@@ -0,0 +1,379 @@
+// 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_FRAMES_ARM_H_
+#define V8_FRAMES_ARM_H_
+
+namespace v8 { namespace internal {
+
+
+// The ARM ABI does not specify the usage of register r9, which may be reserved
+// as the static base or thread register on some platforms, in which case we
+// leave it alone. Adjust the value of kR9Available accordingly:
+static const int kR9Available = 1;  // 1 if available to us, 0 if reserved
+
+
+// Register list in load/store instructions
+// Note that the bit values must match those used in actual instruction encoding
+static const int kNumRegs = 16;
+
+
+// Caller-saved/arguments registers
+static const RegList kJSCallerSaved =
+  1 << 0 |  // r0 a1
+  1 << 1 |  // r1 a2
+  1 << 2 |  // r2 a3
+  1 << 3;   // r3 a4
+
+static const int kNumJSCallerSaved = 4;
+
+typedef Object* JSCallerSavedBuffer[kNumJSCallerSaved];
+
+// Return the code of the n-th caller-saved register available to JavaScript
+// e.g. JSCallerSavedReg(0) returns r0.code() == 0
+int JSCallerSavedCode(int n);
+
+
+// Callee-saved registers preserved when switching from C to JavaScript
+static const RegList kCalleeSaved =
+  1 <<  4 |  //  r4 v1
+  1 <<  5 |  //  r5 v2
+  1 <<  6 |  //  r6 v3
+  1 <<  7 |  //  r7 v4
+  1 <<  8 |  //  r8 v5 (cp in JavaScript code)
+  kR9Available
+    <<  9 |  //  r9 v6
+  1 << 10 |  // r10 v7 (pp in JavaScript code)
+  1 << 11;   // r11 v8 (fp in JavaScript code)
+
+static const int kNumCalleeSaved = 7 + kR9Available;
+
+
+// ----------------------------------------------------
+
+
+class StackHandlerConstants : public AllStatic {
+ public:
+  // TODO(1233780): Get rid of the code slot in stack handlers.
+  static const int kCodeOffset  = 0 * kPointerSize;
+  static const int kNextOffset  = 1 * kPointerSize;
+  static const int kStateOffset = 2 * kPointerSize;
+  static const int kPPOffset    = 3 * kPointerSize;
+  static const int kFPOffset    = 4 * kPointerSize;
+  static const int kPCOffset    = 5 * kPointerSize;
+
+  static const int kAddressDisplacement = -1 * kPointerSize;
+  static const int kSize = kPCOffset + kPointerSize;
+};
+
+
+class EntryFrameConstants : public AllStatic {
+ public:
+  static const int kCallerFPOffset      = -3 * kPointerSize;
+};
+
+
+class ExitFrameConstants : public AllStatic {
+ public:
+  // Exit frames have a debug marker on the stack.
+  static const int kSPDisplacement = -1 * kPointerSize;
+
+  // The debug marker is just above the frame pointer.
+  static const int kDebugMarkOffset = -1 * kPointerSize;
+
+  static const int kSavedRegistersOffset = 0 * kPointerSize;
+
+  // Let the parameters pointer for exit frames point just below the
+  // frame structure on the stack.
+  static const int kPPDisplacement = 3 * kPointerSize;
+
+  // The caller fields are below the frame pointer on the stack.
+  static const int kCallerFPOffset = +0 * kPointerSize;
+  static const int kCallerPPOffset = +1 * kPointerSize;
+  static const int kCallerPCOffset = +2 * kPointerSize;
+};
+
+
+class StandardFrameConstants : public AllStatic {
+ public:
+  static const int kExpressionsOffset = -3 * kPointerSize;
+  static const int kMarkerOffset      = -2 * kPointerSize;
+  static const int kContextOffset     = -1 * kPointerSize;
+  static const int kCallerFPOffset    =  0 * kPointerSize;
+  static const int kCallerPCOffset    = +1 * kPointerSize;
+  static const int kCallerSPOffset    = +2 * kPointerSize;
+};
+
+
+class JavaScriptFrameConstants : public AllStatic {
+ public:
+  // FP-relative.
+  static const int kLocal0Offset = StandardFrameConstants::kExpressionsOffset;
+  static const int kSavedRegistersOffset = +2 * kPointerSize;
+  static const int kFunctionOffset = StandardFrameConstants::kMarkerOffset;
+
+  // PP-relative.
+  static const int kParam0Offset   = -2 * kPointerSize;
+  static const int kReceiverOffset = -1 * kPointerSize;
+};
+
+
+class ArgumentsAdaptorFrameConstants : public AllStatic {
+ public:
+  static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
+};
+
+
+class InternalFrameConstants : public AllStatic {
+ public:
+  static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
+};
+
+
+inline Object* JavaScriptFrame::function_slot_object() const {
+  const int offset = JavaScriptFrameConstants::kFunctionOffset;
+  return Memory::Object_at(fp() + offset);
+}
+
+
+// ----------------------------------------------------
+
+
+
+
+  //    lower    |    Stack    |
+  //  addresses  |      ^      |
+  //             |      |      |
+  //             |             |
+  //             |  JS frame   |
+  //             |             |
+  //             |             |
+  // ----------- +=============+ <--- sp (stack pointer)
+  //             |  function   |
+  //             +-------------+
+  //             +-------------+
+  //             |             |
+  //             | expressions |
+  //             |             |
+  //             +-------------+
+  //             |             |
+  //      a      |   locals    |
+  //      c      |             |
+  //      t      +- - - - - - -+ <---
+  //      i   -4 |   local0    |   ^
+  //      v      +-------------+   |
+  //      a   -3 |    code     |   |
+  //      t      +-------------+   | kLocal0Offset
+  //      i   -2 |   context   |   |
+  //      o      +-------------+   |
+  //      n   -1 | args_length |   v
+  //             +-------------+ <--- fp (frame pointer)
+  //           0 |  caller_pp  |
+  //      f      +-------------+
+  //      r    1 |  caller_fp  |
+  //      a      +-------------+
+  //      m    2 |  sp_on_exit |  (pp if return, caller_sp if no return)
+  //      e      +-------------+
+  //           3 |  caller_pc  |
+  //             +-------------+ <--- caller_sp (incl. parameters)
+  //             |             |
+  //             | parameters  |
+  //             |             |
+  //             +- - - - - - -+ <---
+  //          -2 | parameter0  |   ^
+  //             +-------------+   | kParam0Offset
+  //          -1 |  receiver   |   v
+  // ----------- +=============+ <--- pp (parameter pointer, r10)
+  //           0 |  function   |
+  //             +-------------+
+  //             |             |
+  //             |caller-saved |  (must be valid JS values, traversed during GC)
+  //             |    regs     |
+  //             |             |
+  //             +-------------+
+  //             |             |
+  //             |   caller    |
+  //   higher    | expressions |
+  //  addresses  |             |
+  //             |             |
+  //             |  JS frame   |
+
+
+
+  // Handler frames (part of expressions of JS frames):
+
+  //    lower    |    Stack    |
+  //  addresses  |      ^      |
+  //             |      |      |
+  //             |             |
+  //      h      | expressions |
+  //      a      |             |
+  //      n      +-------------+
+  //      d   -1 |    code     |
+  //      l      +-------------+ <--- handler sp
+  //      e    0 |   next_sp   |  link to next handler (next handler's sp)
+  //      r      +-------------+
+  //           1 |    state    |
+  //      f      +-------------+
+  //      r    2 |     pp      |
+  //      a      +-------------+
+  //      m    3 |     fp      |
+  //      e      +-------------+
+  //           4 |     pc      |
+  //             +-------------+
+  //             |             |
+  //   higher    | expressions |
+  //  addresses  |             |
+
+
+
+  // JS entry frames: When calling from C to JS, we construct two extra
+  // frames: An entry frame (C) and a trampoline frame (JS). The
+  // following pictures shows the two frames:
+
+  //    lower    |    Stack    |
+  //  addresses  |      ^      |
+  //             |      |      |
+  //             |             |
+  //             |  JS frame   |
+  //             |             |
+  //             |             |
+  // ----------- +=============+ <--- sp (stack pointer)
+  //             |             |
+  //             | parameters  |
+  //      t      |             |
+  //      r      +- - - - - - -+
+  //      a      | parameter0  |
+  //      m      +-------------+
+  //      p      |  receiver   |
+  //      o      +-------------+
+  //      l      |  function   |
+  //      i      +-------------+
+  //      n   -3 |    code     |
+  //      e      +-------------+
+  //          -2 |    NULL     |  context is always NULL
+  //             +-------------+
+  //      f   -1 |      0      |  args_length is always zero
+  //      r      +-------------+ <--- fp (frame pointer)
+  //      a    0 |    NULL     |  caller pp is always NULL for entries
+  //      m      +-------------+
+  //      e    1 |  caller_fp  |
+  //             +-------------+
+  //           2 |  sp_on_exit |  (caller_sp)
+  //             +-------------+
+  //           3 |  caller_pc  |
+  // ----------- +=============+ <--- caller_sp == pp
+  //                    .          ^
+  //                    .          |  try-handler, fake, not GC'ed
+  //                    .          v
+  //             +-------------+ <---
+  //          -2 | next top pp |
+  //             +-------------+
+  //          -1 | next top fp |
+  //             +-------------+ <--- fp
+  //             |     r4      |  r4-r9 holding non-JS values must be preserved
+  //             +-------------+
+  //      J      |     r5      |  before being initialized not to confuse GC
+  //      S      +-------------+
+  //             |     r6      |
+  //             +-------------+
+  //      e      |     r7      |
+  //      n      +-------------+
+  //      t      |     r8      |
+  //      r      +-------------+
+  //      y    [ |     r9      | ]  only if r9 available
+  //             +-------------+
+  //             |     r10     |
+  //      f      +-------------+
+  //      r      |     r11     |
+  //      a      +-------------+
+  //      m      |  caller_sp  |
+  //      e      +-------------+
+  //             |  caller_pc  |
+  //             +-------------+ <--- caller_sp
+  //             |    argv     |    passed on stack from C code
+  //             +-------------+
+  //             |             |
+  //   higher    |             |
+  //  addresses  |   C frame   |
+
+
+  // The first 4 args are passed from C in r0-r3 and are not spilled on entry:
+  // r0: code entry
+  // r1: function
+  // r2: receiver
+  // r3: argc
+  // [sp+0]: argv
+
+
+  // C entry frames: When calling from JS to C, we construct one extra
+  // frame:
+
+  //    lower    |    Stack    |
+  //  addresses  |      ^      |
+  //             |      |      |
+  //             |             |
+  //             |   C frame   |
+  //             |             |
+  //             |             |
+  // ----------- +=============+ <--- sp (stack pointer)
+  //             |             |
+  //             | parameters  |  (first 4 args are passed in r0-r3)
+  //             |             |
+  //             +-------------+ <--- fp (frame pointer)
+  //      f  4/5 |  caller_fp  |
+  //      r      +-------------+
+  //      a  5/6 |  sp_on_exit |  (pp)
+  //      m      +-------------+
+  //      e  6/7 |  caller_pc  |
+  //             +-------------+ <--- caller_sp (incl. parameters)
+  //         7/8 |             |
+  //             | parameters  |
+  //             |             |
+  //             +- - - - - - -+ <---
+  //          -2 | parameter0  |   ^
+  //             +-------------+   | kParam0Offset
+  //          -1 |  receiver   |   v
+  // ----------- +=============+ <--- pp (parameter pointer, r10)
+  //           0 |  function   |
+  //             +-------------+
+  //             |             |
+  //             |caller-saved |
+  //             |    regs     |
+  //             |             |
+  //             +-------------+
+  //             |             |
+  //             |   caller    |
+  //             | expressions |
+  //             |             |
+  //   higher    |             |
+  //  addresses  |  JS frame   |
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_FRAMES_ARM_H_
diff --git a/deps/v8/src/frames-ia32.cc b/deps/v8/src/frames-ia32.cc
new file mode 100644
index 0000000..1bc62ec
--- /dev/null
+++ b/deps/v8/src/frames-ia32.cc
@@ -0,0 +1,115 @@
+// 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.
+
+#include "v8.h"
+
+#include "frames-inl.h"
+
+namespace v8 { namespace internal {
+
+
+StackFrame::Type StackFrame::ComputeType(State* state) {
+  ASSERT(state->fp != NULL);
+  if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
+    return ARGUMENTS_ADAPTOR;
+  }
+  // The marker and function offsets overlap. If the marker isn't a
+  // smi then the frame is a JavaScript frame -- and the marker is
+  // really the function.
+  const int offset = StandardFrameConstants::kMarkerOffset;
+  Object* marker = Memory::Object_at(state->fp + offset);
+  if (!marker->IsSmi()) return JAVA_SCRIPT;
+  return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
+}
+
+
+StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
+  if (fp == 0) return NONE;
+  // Compute the stack pointer.
+  Address sp = Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
+  // Fill in the state.
+  state->fp = fp;
+  state->sp = sp;
+  state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
+  // Determine frame type.
+  if (Memory::Address_at(fp + ExitFrameConstants::kDebugMarkOffset) != 0) {
+    return EXIT_DEBUG;
+  } else {
+    return EXIT;
+  }
+}
+
+
+void ExitFrame::Iterate(ObjectVisitor* v) const {
+  // Exit frames on IA-32 do not contain any pointers. The arguments
+  // are traversed as part of the expression stack of the calling
+  // frame.
+}
+
+
+int JavaScriptFrame::GetProvidedParametersCount() const {
+  return ComputeParametersCount();
+}
+
+
+Address JavaScriptFrame::GetCallerStackPointer() const {
+  int arguments;
+  if (Heap::gc_state() != Heap::NOT_IN_GC || disable_heap_access_) {
+    // The arguments for cooked frames are traversed as if they were
+    // expression stack elements of the calling frame. The reason for
+    // this rather strange decision is that we cannot access the
+    // function during mark-compact GCs when the stack is cooked.
+    // In fact accessing heap objects (like function->shared() below)
+    // at all during GC is problematic.
+    arguments = 0;
+  } else {
+    // Compute the number of arguments by getting the number of formal
+    // parameters of the function. We must remember to take the
+    // receiver into account (+1).
+    JSFunction* function = JSFunction::cast(this->function());
+    arguments = function->shared()->formal_parameter_count() + 1;
+  }
+  const int offset = StandardFrameConstants::kCallerSPOffset;
+  return fp() + offset + (arguments * kPointerSize);
+}
+
+
+Address ArgumentsAdaptorFrame::GetCallerStackPointer() const {
+  const int arguments = Smi::cast(GetExpression(0))->value();
+  const int offset = StandardFrameConstants::kCallerSPOffset;
+  return fp() + offset + (arguments + 1) * kPointerSize;
+}
+
+
+Address InternalFrame::GetCallerStackPointer() const {
+  // Internal frames have no arguments. The stack pointer of the
+  // caller is at a fixed offset from the frame pointer.
+  return fp() + StandardFrameConstants::kCallerSPOffset;
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/frames-ia32.h b/deps/v8/src/frames-ia32.h
new file mode 100644
index 0000000..518b1ca
--- /dev/null
+++ b/deps/v8/src/frames-ia32.h
@@ -0,0 +1,291 @@
+// 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_FRAMES_IA32_H_
+#define V8_FRAMES_IA32_H_
+
+namespace v8 { namespace internal {
+
+
+// Register lists
+// Note that the bit values must match those used in actual instruction encoding
+static const int kNumRegs = 8;
+
+
+// Caller-saved registers
+static const RegList kJSCallerSaved =
+  1 << 0 |  // eax
+  1 << 1 |  // ecx
+  1 << 2 |  // edx
+  1 << 3 |  // ebx - used as a caller-saved register in JavaScript code
+  1 << 7;   // edi - callee function
+
+static const int kNumJSCallerSaved = 5;
+
+typedef Object* JSCallerSavedBuffer[kNumJSCallerSaved];
+
+// ----------------------------------------------------
+
+
+class StackHandlerConstants : public AllStatic {
+ public:
+  static const int kNextOffset  = 0 * kPointerSize;
+  static const int kPPOffset    = 1 * kPointerSize;
+  static const int kFPOffset    = 2 * kPointerSize;
+
+  // TODO(1233780): Get rid of the code slot in stack handlers.
+  static const int kCodeOffset  = 3 * kPointerSize;
+
+  static const int kStateOffset = 4 * kPointerSize;
+  static const int kPCOffset    = 5 * kPointerSize;
+
+  static const int kAddressDisplacement = -1 * kPointerSize;
+  static const int kSize = kPCOffset + kPointerSize;
+};
+
+
+class EntryFrameConstants : public AllStatic {
+ public:
+  static const int kCallerFPOffset      = -6 * kPointerSize;
+
+  static const int kFunctionArgOffset   = +3 * kPointerSize;
+  static const int kReceiverArgOffset   = +4 * kPointerSize;
+  static const int kArgcOffset          = +5 * kPointerSize;
+  static const int kArgvOffset          = +6 * kPointerSize;
+};
+
+
+class ExitFrameConstants : public AllStatic {
+ public:
+  static const int kDebugMarkOffset = -2 * kPointerSize;
+  static const int kSPOffset        = -1 * kPointerSize;
+
+  // Let the parameters pointer for exit frames point just below the
+  // frame structure on the stack (frame pointer and return address).
+  static const int kPPDisplacement = +2 * kPointerSize;
+
+  static const int kCallerFPOffset =  0 * kPointerSize;
+  static const int kCallerPCOffset = +1 * kPointerSize;
+};
+
+
+class StandardFrameConstants : public AllStatic {
+ public:
+  static const int kExpressionsOffset = -3 * kPointerSize;
+  static const int kMarkerOffset      = -2 * kPointerSize;
+  static const int kContextOffset     = -1 * kPointerSize;
+  static const int kCallerFPOffset    =  0 * kPointerSize;
+  static const int kCallerPCOffset    = +1 * kPointerSize;
+  static const int kCallerSPOffset    = +2 * kPointerSize;
+};
+
+
+class JavaScriptFrameConstants : public AllStatic {
+ public:
+  // FP-relative.
+  static const int kLocal0Offset = StandardFrameConstants::kExpressionsOffset;
+  static const int kSavedRegistersOffset = +2 * kPointerSize;
+  static const int kFunctionOffset = StandardFrameConstants::kMarkerOffset;
+
+  // CallerSP-relative (aka PP-relative)
+  static const int kParam0Offset   = -2 * kPointerSize;
+  static const int kReceiverOffset = -1 * kPointerSize;
+};
+
+
+class ArgumentsAdaptorFrameConstants : public AllStatic {
+ public:
+  static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
+};
+
+
+class InternalFrameConstants : public AllStatic {
+ public:
+  static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
+};
+
+
+inline Object* JavaScriptFrame::function_slot_object() const {
+  const int offset = JavaScriptFrameConstants::kFunctionOffset;
+  return Memory::Object_at(fp() + offset);
+}
+
+
+// ----------------------------------------------------
+
+
+
+
+  // C Entry frames:
+
+  //    lower    |    Stack    |
+  //  addresses  |      ^      |
+  //             |      |      |
+  //             |             |
+  //             +-------------+
+  //             |  entry_pc   |
+  //             +-------------+ <--+ entry_sp
+  //                    .           |
+  //                    .           |
+  //                    .           |
+  //             +-------------+    |
+  //          -3 |  entry_sp --+----+
+  //      e      +-------------+
+  //      n   -2 | C function  |
+  //      t      +-------------+
+  //      r   -1 |  caller_pp  |
+  //      y      +-------------+ <--- fp (frame pointer, ebp)
+  //           0 |  caller_fp  |
+  //      f      +-------------+
+  //      r    1 |  caller_pc  |
+  //      a      +-------------+ <--- caller_sp (stack pointer, esp)
+  //      m    2 |             |
+  //      e      |  arguments  |
+  //             |             |
+  //             +- - - - - - -+
+  //             |  argument0  |
+  //             +=============+
+  //             |             |
+  //             |   caller    |
+  //   higher    | expressions |
+  //  addresses  |             |
+
+
+  // Proper JS frames:
+
+  //    lower    |    Stack    |
+  //  addresses  |      ^      |
+  //             |      |      |
+  //             |             |
+  // ----------- +=============+ <--- sp (stack pointer, esp)
+  //             |  function   |
+  //             +-------------+
+  //             |             |
+  //             | expressions |
+  //             |             |
+  //             +-------------+
+  //      a      |             |
+  //      c      |   locals    |
+  //      t      |             |
+  //      i      +- - - - - - -+ <---
+  //      v   -4 |   local0    |   ^
+  //      a      +-------------+   |
+  //      t   -3 |    code     |   |
+  //      i      +-------------+   |
+  //      o   -2 |   context   |   | kLocal0Offset
+  //      n      +-------------+   |
+  //          -1 |  caller_pp  |   v
+  //      f      +-------------+ <--- fp (frame pointer, ebp)
+  //      r    0 |  caller_fp  |
+  //      a      +-------------+
+  //      m    1 |  caller_pc  |
+  //      e      +-------------+ <--- caller_sp (incl. parameters)
+  //           2 |             |
+  //             | parameters  |
+  //             |             |
+  //             +- - - - - - -+ <---
+  //          -2 | parameter0  |   ^
+  //             +-------------+   | kParam0Offset
+  //          -1 |  receiver   |   v
+  // ----------- +=============+ <--- pp (parameter pointer, edi)
+  //           0 |  function   |
+  //             +-------------+
+  //             |             |
+  //             |   caller    |
+  //   higher    | expressions |
+  //  addresses  |             |
+
+
+  // JS entry frames: When calling from C to JS, we construct two extra
+  // frames: An entry frame (C) and a trampoline frame (JS). The
+  // following pictures shows the two frames:
+
+  //    lower    |    Stack    |
+  //  addresses  |      ^      |
+  //             |      |      |
+  //             |             |
+  // ----------- +=============+ <--- sp (stack pointer, esp)
+  //             |             |
+  //             | parameters  |
+  //      t      |             |
+  //      r      +- - - - - - -+
+  //      a      | parameter0  |
+  //      m      +-------------+
+  //      p      |  receiver   |
+  //      o      +-------------+ <---
+  //      l      |  function   |   ^
+  //      i      +-------------+   |
+  //      n   -3 |    code     |   | kLocal0Offset
+  //      e      +-------------+
+  //          -2 |    NULL     | context is always NULL
+  //             +-------------+
+  //      f   -1 |    NULL     | caller pp is always NULL for entry frames
+  //      r      +-------------+ <--- fp (frame pointer, ebp)
+  //      a    0 |  caller fp  |
+  //      m      +-------------+
+  //      e    1 |  caller pc  |
+  //             +-------------+ <--- caller_sp (incl. parameters)
+  //             |      0      |
+  // ----------- +=============+ <--- pp (parameter pointer, edi)
+  //             |      0      |
+  //             +-------------+ <---
+  //                    .          ^
+  //                    .          |  try-handler (HandlerOffsets::kSize)
+  //                    .          v
+  //             +-------------+ <---
+  //          -5 | next top pp |
+  //             +-------------+
+  //      e   -4 | next top fp |
+  //      n      +-------------+ <---
+  //      t   -3 |     ebx     |   ^
+  //      r      +-------------+   |
+  //      y   -2 |     esi     |   |  callee-saved registers
+  //             +-------------+   |
+  //          -1 |     edi     |   v
+  //      f      +-------------+ <--- fp
+  //      r    0 |  caller fp  |
+  //      a      +-------------+      pp == NULL (parameter pointer)
+  //      m    1 |  caller pc  |
+  //      e      +-------------+ <--- caller sp
+  //           2 | code  entry |   ^
+  //             +-------------+   |
+  //           3 |  function   |   |
+  //             +-------------+   |  arguments passed from C code
+  //           4 |  receiver   |   |
+  //             +-------------+   |
+  //           5 |    argc     |   |
+  //             +-------------+   |
+  //           6 |    argv     |   v
+  //             +-------------+ <---
+  //             |             |
+  //   higher    |             |
+  //  addresses  |             |
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_FRAMES_IA32_H_
diff --git a/deps/v8/src/frames-inl.h b/deps/v8/src/frames-inl.h
new file mode 100644
index 0000000..cb03e2f
--- /dev/null
+++ b/deps/v8/src/frames-inl.h
@@ -0,0 +1,226 @@
+// 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_FRAMES_INL_H_
+#define V8_FRAMES_INL_H_
+
+#include "frames.h"
+#ifdef ARM
+#include "frames-arm.h"
+#else
+#include "frames-ia32.h"
+#endif
+
+
+namespace v8 { namespace internal {
+
+
+inline Address StackHandler::address() const {
+  // NOTE: There's an obvious problem with the address of the NULL
+  // stack handler. Right now, it benefits us that the subtraction
+  // leads to a very high address (above everything else on the
+  // stack), but maybe we should stop relying on it?
+  const int displacement = StackHandlerConstants::kAddressDisplacement;
+  Address address = reinterpret_cast<Address>(const_cast<StackHandler*>(this));
+  return address + displacement;
+}
+
+
+inline StackHandler* StackHandler::next() const {
+  const int offset = StackHandlerConstants::kNextOffset;
+  return FromAddress(Memory::Address_at(address() + offset));
+}
+
+
+inline bool StackHandler::includes(Address address) const {
+  Address start = this->address();
+  Address end = start + StackHandlerConstants::kSize;
+  return start <= address && address <= end;
+}
+
+
+inline void StackHandler::Iterate(ObjectVisitor* v) const {
+  // Stack handlers do not contain any pointers that need to be
+  // traversed. The only field that have to worry about is the code
+  // field which is unused and should always be uninitialized.
+#ifdef DEBUG
+  const int offset = StackHandlerConstants::kCodeOffset;
+  Object* code = Memory::Object_at(address() + offset);
+  ASSERT(Smi::cast(code)->value() == StackHandler::kCodeNotPresent);
+#endif
+}
+
+
+inline StackHandler* StackHandler::FromAddress(Address address) {
+  return reinterpret_cast<StackHandler*>(address);
+}
+
+
+inline StackHandler::State StackHandler::state() const {
+  const int offset = StackHandlerConstants::kStateOffset;
+  return static_cast<State>(Memory::int_at(address() + offset));
+}
+
+
+inline Address StackHandler::pc() const {
+  const int offset = StackHandlerConstants::kPCOffset;
+  return Memory::Address_at(address() + offset);
+}
+
+
+inline void StackHandler::set_pc(Address value) {
+  const int offset = StackHandlerConstants::kPCOffset;
+  Memory::Address_at(address() + offset) = value;
+}
+
+
+inline StackHandler* StackFrame::top_handler() const {
+  return iterator_->handler();
+}
+
+
+inline Object* StandardFrame::GetExpression(int index) const {
+  return Memory::Object_at(GetExpressionAddress(index));
+}
+
+
+inline void StandardFrame::SetExpression(int index, Object* value) {
+  Memory::Object_at(GetExpressionAddress(index)) = value;
+}
+
+
+inline Object* StandardFrame::context() const {
+  const int offset = StandardFrameConstants::kContextOffset;
+  return Memory::Object_at(fp() + offset);
+}
+
+
+inline Address StandardFrame::caller_sp() const {
+  return pp();
+}
+
+
+inline Address StandardFrame::caller_fp() const {
+  return Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset);
+}
+
+
+inline Address StandardFrame::caller_pc() const {
+  return Memory::Address_at(ComputePCAddress(fp()));
+}
+
+
+inline Address StandardFrame::ComputePCAddress(Address fp) {
+  return fp + StandardFrameConstants::kCallerPCOffset;
+}
+
+
+inline bool StandardFrame::IsArgumentsAdaptorFrame(Address fp) {
+  int context = Memory::int_at(fp + StandardFrameConstants::kContextOffset);
+  return context == ArgumentsAdaptorFrame::SENTINEL;
+}
+
+
+inline bool StandardFrame::IsConstructFrame(Address fp) {
+  Object* marker =
+      Memory::Object_at(fp + StandardFrameConstants::kMarkerOffset);
+  return marker == Smi::FromInt(CONSTRUCT);
+}
+
+
+inline Object* JavaScriptFrame::receiver() const {
+  const int offset = JavaScriptFrameConstants::kReceiverOffset;
+  return Memory::Object_at(pp() + offset);
+}
+
+
+inline void JavaScriptFrame::set_receiver(Object* value) {
+  const int offset = JavaScriptFrameConstants::kReceiverOffset;
+  Memory::Object_at(pp() + offset) = value;
+}
+
+
+inline bool JavaScriptFrame::has_adapted_arguments() const {
+  return IsArgumentsAdaptorFrame(caller_fp());
+}
+
+
+inline Object* JavaScriptFrame::function() const {
+  Object* result = function_slot_object();
+  ASSERT(result->IsJSFunction());
+  return result;
+}
+
+
+template<typename Iterator>
+inline JavaScriptFrame* JavaScriptFrameIteratorTemp<Iterator>::frame() const {
+  // TODO(1233797): The frame hierarchy needs to change. It's
+  // problematic that we can't use the safe-cast operator to cast to
+  // the JavaScript frame type, because we may encounter arguments
+  // adaptor frames.
+  StackFrame* frame = iterator_.frame();
+  ASSERT(frame->is_java_script() || frame->is_arguments_adaptor());
+  return static_cast<JavaScriptFrame*>(frame);
+}
+
+
+template<typename Iterator>
+JavaScriptFrameIteratorTemp<Iterator>::JavaScriptFrameIteratorTemp(
+    StackFrame::Id id) {
+  while (!done()) {
+    Advance();
+    if (frame()->id() == id) return;
+  }
+}
+
+
+template<typename Iterator>
+void JavaScriptFrameIteratorTemp<Iterator>::Advance() {
+  do {
+    iterator_.Advance();
+  } while (!iterator_.done() && !iterator_.frame()->is_java_script());
+}
+
+
+template<typename Iterator>
+void JavaScriptFrameIteratorTemp<Iterator>::AdvanceToArgumentsFrame() {
+  if (!frame()->has_adapted_arguments()) return;
+  iterator_.Advance();
+  ASSERT(iterator_.frame()->is_arguments_adaptor());
+}
+
+
+template<typename Iterator>
+void JavaScriptFrameIteratorTemp<Iterator>::Reset() {
+  iterator_.Reset();
+  if (!done()) Advance();
+}
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_FRAMES_INL_H_
diff --git a/deps/v8/src/frames.cc b/deps/v8/src/frames.cc
new file mode 100644
index 0000000..88c723d
--- /dev/null
+++ b/deps/v8/src/frames.cc
@@ -0,0 +1,740 @@
+// 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.
+
+#include "v8.h"
+
+#include "frames-inl.h"
+#include "mark-compact.h"
+#include "scopeinfo.h"
+#include "string-stream.h"
+#include "top.h"
+#include "zone-inl.h"
+
+namespace v8 { namespace internal {
+
+// Iterator that supports traversing the stack handlers of a
+// particular frame. Needs to know the top of the handler chain.
+class StackHandlerIterator BASE_EMBEDDED {
+ public:
+  StackHandlerIterator(const StackFrame* frame, StackHandler* handler)
+      : limit_(frame->fp()), handler_(handler) {
+    // Make sure the handler has already been unwound to this frame.
+    ASSERT(frame->sp() <= handler->address());
+  }
+
+  StackHandler* handler() const { return handler_; }
+
+  bool done() { return handler_->address() > limit_; }
+  void Advance() {
+    ASSERT(!done());
+    handler_ = handler_->next();
+  }
+
+ private:
+  const Address limit_;
+  StackHandler* handler_;
+};
+
+
+// -------------------------------------------------------------------------
+
+
+#define INITIALIZE_SINGLETON(type, field) field##_(this),
+StackFrameIterator::StackFrameIterator()
+    : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
+      frame_(NULL), handler_(NULL), thread_(Top::GetCurrentThread()),
+      fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
+  Reset();
+}
+StackFrameIterator::StackFrameIterator(ThreadLocalTop* t)
+    : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
+      frame_(NULL), handler_(NULL), thread_(t),
+      fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
+  Reset();
+}
+StackFrameIterator::StackFrameIterator(bool use_top, Address fp, Address sp)
+    : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
+      frame_(NULL), handler_(NULL),
+      thread_(use_top ? Top::GetCurrentThread() : NULL),
+      fp_(use_top ? NULL : fp), sp_(sp),
+      advance_(use_top ? &StackFrameIterator::AdvanceWithHandler :
+               &StackFrameIterator::AdvanceWithoutHandler) {
+  if (use_top || fp != NULL) {
+    Reset();
+  }
+  JavaScriptFrame_.DisableHeapAccess();
+}
+
+#undef INITIALIZE_SINGLETON
+
+
+void StackFrameIterator::AdvanceWithHandler() {
+  ASSERT(!done());
+  // Compute the state of the calling frame before restoring
+  // callee-saved registers and unwinding handlers. This allows the
+  // frame code that computes the caller state to access the top
+  // handler and the value of any callee-saved register if needed.
+  StackFrame::State state;
+  StackFrame::Type type = frame_->GetCallerState(&state);
+
+  // Unwind handlers corresponding to the current frame.
+  StackHandlerIterator it(frame_, handler_);
+  while (!it.done()) it.Advance();
+  handler_ = it.handler();
+
+  // Advance to the calling frame.
+  frame_ = SingletonFor(type, &state);
+
+  // When we're done iterating over the stack frames, the handler
+  // chain must have been completely unwound.
+  ASSERT(!done() || handler_ == NULL);
+}
+
+
+void StackFrameIterator::AdvanceWithoutHandler() {
+  // A simpler version of Advance which doesn't care about handler.
+  ASSERT(!done());
+  StackFrame::State state;
+  StackFrame::Type type = frame_->GetCallerState(&state);
+  frame_ = SingletonFor(type, &state);
+}
+
+
+void StackFrameIterator::Reset() {
+  StackFrame::State state;
+  StackFrame::Type type;
+  if (thread_ != NULL) {
+    type = ExitFrame::GetStateForFramePointer(Top::c_entry_fp(thread_), &state);
+    handler_ = StackHandler::FromAddress(Top::handler(thread_));
+  } else {
+    ASSERT(fp_ != NULL);
+    state.fp = fp_;
+    state.sp = sp_;
+    state.pc_address =
+        reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_));
+    type = StackFrame::ComputeType(&state);
+    if (SingletonFor(type) == NULL) return;
+  }
+  frame_ = SingletonFor(type, &state);
+}
+
+
+StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type,
+                                             StackFrame::State* state) {
+  if (type == StackFrame::NONE) return NULL;
+  StackFrame* result = SingletonFor(type);
+  ASSERT(result != NULL);
+  result->state_ = *state;
+  return result;
+}
+
+
+StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type) {
+#define FRAME_TYPE_CASE(type, field) \
+  case StackFrame::type: result = &field##_; break;
+
+  StackFrame* result = NULL;
+  switch (type) {
+    case StackFrame::NONE: return NULL;
+    STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
+    default: break;
+  }
+  return result;
+
+#undef FRAME_TYPE_CASE
+}
+
+
+// -------------------------------------------------------------------------
+
+
+StackTraceFrameIterator::StackTraceFrameIterator() {
+  if (!done() && !frame()->function()->IsJSFunction()) Advance();
+}
+
+
+void StackTraceFrameIterator::Advance() {
+  while (true) {
+    JavaScriptFrameIterator::Advance();
+    if (done()) return;
+    if (frame()->function()->IsJSFunction()) return;
+  }
+}
+
+
+// -------------------------------------------------------------------------
+
+
+SafeStackFrameIterator::SafeStackFrameIterator(
+    Address fp, Address sp, Address low_bound, Address high_bound) :
+    low_bound_(low_bound), high_bound_(high_bound),
+    is_valid_top_(
+        IsWithinBounds(low_bound, high_bound,
+                       Top::c_entry_fp(Top::GetCurrentThread())) &&
+        Top::handler(Top::GetCurrentThread()) != NULL),
+    is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)),
+    is_working_iterator_(is_valid_top_ || is_valid_fp_),
+    iteration_done_(!is_working_iterator_),
+    iterator_(is_valid_top_, is_valid_fp_ ? fp : NULL, sp) {
+}
+
+
+void SafeStackFrameIterator::Advance() {
+  ASSERT(is_working_iterator_);
+  ASSERT(!done());
+  StackFrame* last_frame = iterator_.frame();
+  Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
+  // Before advancing to the next stack frame, perform pointer validity tests
+  iteration_done_ = !IsValidFrame(last_frame) ||
+      !CanIterateHandles(last_frame, iterator_.handler()) ||
+      !IsValidCaller(last_frame);
+  if (iteration_done_) return;
+
+  iterator_.Advance();
+  if (iterator_.done()) return;
+  // Check that we have actually moved to the previous frame in the stack
+  StackFrame* prev_frame = iterator_.frame();
+  iteration_done_ = prev_frame->sp() < last_sp || prev_frame->fp() < last_fp;
+}
+
+
+bool SafeStackFrameIterator::CanIterateHandles(StackFrame* frame,
+                                               StackHandler* handler) {
+  // If StackIterator iterates over StackHandles, verify that
+  // StackHandlerIterator can be instantiated (see StackHandlerIterator
+  // constructor.)
+  return !is_valid_top_ || (frame->sp() <= handler->address());
+}
+
+
+bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
+  return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
+}
+
+
+bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
+  StackFrame::State state;
+  if (frame->is_entry() || frame->is_entry_construct()) {
+    // See EntryFrame::GetCallerState. It computes the caller FP address
+    // and calls ExitFrame::GetStateForFramePointer on it. We need to be
+    // sure that caller FP address is valid.
+    Address caller_fp = Memory::Address_at(
+        frame->fp() + EntryFrameConstants::kCallerFPOffset);
+    if (!IsValidStackAddress(caller_fp)) {
+      return false;
+    }
+  } else if (frame->is_arguments_adaptor()) {
+    // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
+    // the number of arguments is stored on stack as Smi. We need to check
+    // that it really an Smi.
+    Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->
+        GetExpression(0);
+    if (!number_of_args->IsSmi()) {
+      return false;
+    }
+  }
+  frame->ComputeCallerState(&state);
+  return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
+      iterator_.SingletonFor(frame->GetCallerState(&state)) != NULL;
+}
+
+
+void SafeStackFrameIterator::Reset() {
+  if (is_working_iterator_) {
+    iterator_.Reset();
+    iteration_done_ = false;
+  }
+}
+
+
+// -------------------------------------------------------------------------
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+SafeStackTraceFrameIterator::SafeStackTraceFrameIterator(
+    Address fp, Address sp, Address low_bound, Address high_bound) :
+    SafeJavaScriptFrameIterator(fp, sp, low_bound, high_bound) {
+  if (!done() && !frame()->is_java_script()) Advance();
+}
+
+
+void SafeStackTraceFrameIterator::Advance() {
+  while (true) {
+    SafeJavaScriptFrameIterator::Advance();
+    if (done()) return;
+    if (frame()->is_java_script()) return;
+  }
+}
+#endif
+
+
+// -------------------------------------------------------------------------
+
+
+void StackHandler::Cook(Code* code) {
+  ASSERT(MarkCompactCollector::IsCompacting());
+  ASSERT(code->contains(pc()));
+  set_pc(AddressFrom<Address>(pc() - code->instruction_start()));
+}
+
+
+void StackHandler::Uncook(Code* code) {
+  ASSERT(MarkCompactCollector::IsCompacting());
+  set_pc(code->instruction_start() + OffsetFrom(pc()));
+  ASSERT(code->contains(pc()));
+}
+
+
+// -------------------------------------------------------------------------
+
+
+bool StackFrame::HasHandler() const {
+  StackHandlerIterator it(this, top_handler());
+  return !it.done();
+}
+
+
+void StackFrame::CookFramesForThread(ThreadLocalTop* thread) {
+  // Only cooking frames when the collector is compacting and thus moving code
+  // around.
+  ASSERT(MarkCompactCollector::IsCompacting());
+  ASSERT(!thread->stack_is_cooked());
+  for (StackFrameIterator it(thread); !it.done(); it.Advance()) {
+    it.frame()->Cook();
+  }
+  thread->set_stack_is_cooked(true);
+}
+
+
+void StackFrame::UncookFramesForThread(ThreadLocalTop* thread) {
+  // Only uncooking frames when the collector is compacting and thus moving code
+  // around.
+  ASSERT(MarkCompactCollector::IsCompacting());
+  ASSERT(thread->stack_is_cooked());
+  for (StackFrameIterator it(thread); !it.done(); it.Advance()) {
+    it.frame()->Uncook();
+  }
+  thread->set_stack_is_cooked(false);
+}
+
+
+void StackFrame::Cook() {
+  Code* code = this->code();
+  for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
+    it.handler()->Cook(code);
+  }
+  ASSERT(code->contains(pc()));
+  set_pc(AddressFrom<Address>(pc() - code->instruction_start()));
+}
+
+
+void StackFrame::Uncook() {
+  Code* code = this->code();
+  for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
+    it.handler()->Uncook(code);
+  }
+  set_pc(code->instruction_start() + OffsetFrom(pc()));
+  ASSERT(code->contains(pc()));
+}
+
+
+StackFrame::Type StackFrame::GetCallerState(State* state) const {
+  ComputeCallerState(state);
+  return ComputeType(state);
+}
+
+
+Code* EntryFrame::code() const {
+  return Heap::js_entry_code();
+}
+
+
+void EntryFrame::ComputeCallerState(State* state) const {
+  GetCallerState(state);
+}
+
+
+StackFrame::Type EntryFrame::GetCallerState(State* state) const {
+  const int offset = EntryFrameConstants::kCallerFPOffset;
+  Address fp = Memory::Address_at(this->fp() + offset);
+  return ExitFrame::GetStateForFramePointer(fp, state);
+}
+
+
+Code* EntryConstructFrame::code() const {
+  return Heap::js_construct_entry_code();
+}
+
+
+Code* ExitFrame::code() const {
+  return Heap::c_entry_code();
+}
+
+
+void ExitFrame::ComputeCallerState(State* state) const {
+  // Setup the caller state.
+  state->sp = pp();
+  state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
+  state->pc_address
+      = reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset);
+}
+
+
+Address ExitFrame::GetCallerStackPointer() const {
+  return fp() + ExitFrameConstants::kPPDisplacement;
+}
+
+
+Code* ExitDebugFrame::code() const {
+  return Heap::c_entry_debug_break_code();
+}
+
+
+Address StandardFrame::GetExpressionAddress(int n) const {
+  const int offset = StandardFrameConstants::kExpressionsOffset;
+  return fp() + offset - n * kPointerSize;
+}
+
+
+int StandardFrame::ComputeExpressionsCount() const {
+  const int offset =
+      StandardFrameConstants::kExpressionsOffset + kPointerSize;
+  Address base = fp() + offset;
+  Address limit = sp();
+  ASSERT(base >= limit);  // stack grows downwards
+  // Include register-allocated locals in number of expressions.
+  return (base - limit) / kPointerSize;
+}
+
+
+void StandardFrame::ComputeCallerState(State* state) const {
+  state->sp = caller_sp();
+  state->fp = caller_fp();
+  state->pc_address = reinterpret_cast<Address*>(ComputePCAddress(fp()));
+}
+
+
+bool StandardFrame::IsExpressionInsideHandler(int n) const {
+  Address address = GetExpressionAddress(n);
+  for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
+    if (it.handler()->includes(address)) return true;
+  }
+  return false;
+}
+
+
+Object* JavaScriptFrame::GetParameter(int index) const {
+  ASSERT(index >= 0 && index < ComputeParametersCount());
+  const int offset = JavaScriptFrameConstants::kParam0Offset;
+  return Memory::Object_at(pp() + offset - (index * kPointerSize));
+}
+
+
+int JavaScriptFrame::ComputeParametersCount() const {
+  Address base  = pp() + JavaScriptFrameConstants::kReceiverOffset;
+  Address limit = fp() + JavaScriptFrameConstants::kSavedRegistersOffset;
+  return (base - limit) / kPointerSize;
+}
+
+
+bool JavaScriptFrame::IsConstructor() const {
+  Address fp = caller_fp();
+  if (has_adapted_arguments()) {
+    // Skip the arguments adaptor frame and look at the real caller.
+    fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
+  }
+  return IsConstructFrame(fp);
+}
+
+
+Code* JavaScriptFrame::code() const {
+  JSFunction* function = JSFunction::cast(this->function());
+  return function->shared()->code();
+}
+
+
+Code* ArgumentsAdaptorFrame::code() const {
+  return Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline);
+}
+
+
+Code* InternalFrame::code() const {
+  const int offset = InternalFrameConstants::kCodeOffset;
+  Object* code = Memory::Object_at(fp() + offset);
+  ASSERT(code != NULL);
+  return Code::cast(code);
+}
+
+
+void StackFrame::PrintIndex(StringStream* accumulator,
+                            PrintMode mode,
+                            int index) {
+  accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
+}
+
+
+void JavaScriptFrame::Print(StringStream* accumulator,
+                            PrintMode mode,
+                            int index) const {
+  HandleScope scope;
+  Object* receiver = this->receiver();
+  Object* function = this->function();
+
+  accumulator->PrintSecurityTokenIfChanged(function);
+  PrintIndex(accumulator, mode, index);
+  Code* code = NULL;
+  if (IsConstructor()) accumulator->Add("new ");
+  accumulator->PrintFunction(function, receiver, &code);
+  accumulator->Add("(this=%o", receiver);
+
+  // Get scope information for nicer output, if possible. If code is
+  // NULL, or doesn't contain scope info, info will return 0 for the
+  // number of parameters, stack slots, or context slots.
+  ScopeInfo<PreallocatedStorage> info(code);
+
+  // Print the parameters.
+  int parameters_count = ComputeParametersCount();
+  for (int i = 0; i < parameters_count; i++) {
+    accumulator->Add(",");
+    // If we have a name for the parameter we print it. Nameless
+    // parameters are either because we have more actual parameters
+    // than formal parameters or because we have no scope information.
+    if (i < info.number_of_parameters()) {
+      accumulator->PrintName(*info.parameter_name(i));
+      accumulator->Add("=");
+    }
+    accumulator->Add("%o", GetParameter(i));
+  }
+
+  accumulator->Add(")");
+  if (mode == OVERVIEW) {
+    accumulator->Add("\n");
+    return;
+  }
+  accumulator->Add(" {\n");
+
+  // Compute the number of locals and expression stack elements.
+  int stack_locals_count = info.number_of_stack_slots();
+  int heap_locals_count = info.number_of_context_slots();
+  int expressions_count = ComputeExpressionsCount();
+
+  // Print stack-allocated local variables.
+  if (stack_locals_count > 0) {
+    accumulator->Add("  // stack-allocated locals\n");
+  }
+  for (int i = 0; i < stack_locals_count; i++) {
+    accumulator->Add("  var ");
+    accumulator->PrintName(*info.stack_slot_name(i));
+    accumulator->Add(" = ");
+    if (i < expressions_count) {
+      accumulator->Add("%o", GetExpression(i));
+    } else {
+      accumulator->Add("// no expression found - inconsistent frame?");
+    }
+    accumulator->Add("\n");
+  }
+
+  // Try to get hold of the context of this frame.
+  Context* context = NULL;
+  if (this->context() != NULL && this->context()->IsContext()) {
+    context = Context::cast(this->context());
+  }
+
+  // Print heap-allocated local variables.
+  if (heap_locals_count > Context::MIN_CONTEXT_SLOTS) {
+    accumulator->Add("  // heap-allocated locals\n");
+  }
+  for (int i = Context::MIN_CONTEXT_SLOTS; i < heap_locals_count; i++) {
+    accumulator->Add("  var ");
+    accumulator->PrintName(*info.context_slot_name(i));
+    accumulator->Add(" = ");
+    if (context != NULL) {
+      if (i < context->length()) {
+        accumulator->Add("%o", context->get(i));
+      } else {
+        accumulator->Add(
+            "// warning: missing context slot - inconsistent frame?");
+      }
+    } else {
+      accumulator->Add("// warning: no context found - inconsistent frame?");
+    }
+    accumulator->Add("\n");
+  }
+
+  // Print the expression stack.
+  int expressions_start = stack_locals_count;
+  if (expressions_start < expressions_count) {
+    accumulator->Add("  // expression stack (top to bottom)\n");
+  }
+  for (int i = expressions_count - 1; i >= expressions_start; i--) {
+    if (IsExpressionInsideHandler(i)) continue;
+    accumulator->Add("  [%02d] : %o\n", i, GetExpression(i));
+  }
+
+  // Print details about the function.
+  if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
+    SharedFunctionInfo* shared = JSFunction::cast(function)->shared();
+    accumulator->Add("--------- s o u r c e   c o d e ---------\n");
+    shared->SourceCodePrint(accumulator, FLAG_max_stack_trace_source_length);
+    accumulator->Add("\n-----------------------------------------\n");
+  }
+
+  accumulator->Add("}\n\n");
+}
+
+
+void ArgumentsAdaptorFrame::Print(StringStream* accumulator,
+                                  PrintMode mode,
+                                  int index) const {
+  int actual = ComputeParametersCount();
+  int expected = -1;
+  Object* function = this->function();
+  if (function->IsJSFunction()) {
+    expected = JSFunction::cast(function)->shared()->formal_parameter_count();
+  }
+
+  PrintIndex(accumulator, mode, index);
+  accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
+  if (mode == OVERVIEW) {
+    accumulator->Add("\n");
+    return;
+  }
+  accumulator->Add(" {\n");
+
+  // Print actual arguments.
+  if (actual > 0) accumulator->Add("  // actual arguments\n");
+  for (int i = 0; i < actual; i++) {
+    accumulator->Add("  [%02d] : %o", i, GetParameter(i));
+    if (expected != -1 && i >= expected) {
+      accumulator->Add("  // not passed to callee");
+    }
+    accumulator->Add("\n");
+  }
+
+  accumulator->Add("}\n\n");
+}
+
+
+void EntryFrame::Iterate(ObjectVisitor* v) const {
+  StackHandlerIterator it(this, top_handler());
+  ASSERT(!it.done());
+  StackHandler* handler = it.handler();
+  ASSERT(handler->is_entry());
+  handler->Iterate(v);
+  // Make sure that there's the entry frame does not contain more than
+  // one stack handler.
+  if (kDebug) {
+    it.Advance();
+    ASSERT(it.done());
+  }
+}
+
+
+void StandardFrame::IterateExpressions(ObjectVisitor* v) const {
+  const int offset = StandardFrameConstants::kContextOffset;
+  Object** base = &Memory::Object_at(sp());
+  Object** limit = &Memory::Object_at(fp() + offset) + 1;
+  for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
+    StackHandler* handler = it.handler();
+    // Traverse pointers down to - but not including - the next
+    // handler in the handler chain. Update the base to skip the
+    // handler and allow the handler to traverse its own pointers.
+    const Address address = handler->address();
+    v->VisitPointers(base, reinterpret_cast<Object**>(address));
+    base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize);
+    // Traverse the pointers in the handler itself.
+    handler->Iterate(v);
+  }
+  v->VisitPointers(base, limit);
+}
+
+
+void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
+  IterateExpressions(v);
+
+  // Traverse callee-saved registers, receiver, and parameters.
+  const int kBaseOffset = JavaScriptFrameConstants::kSavedRegistersOffset;
+  const int kLimitOffset = JavaScriptFrameConstants::kReceiverOffset;
+  Object** base = &Memory::Object_at(fp() + kBaseOffset);
+  Object** limit = &Memory::Object_at(pp() + kLimitOffset) + 1;
+  v->VisitPointers(base, limit);
+}
+
+
+void InternalFrame::Iterate(ObjectVisitor* v) const {
+  // Internal frames only have object pointers on the expression stack
+  // as they never have any arguments.
+  IterateExpressions(v);
+}
+
+
+// -------------------------------------------------------------------------
+
+
+JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) {
+  ASSERT(n >= 0);
+  for (int i = 0; i <= n; i++) {
+    while (!iterator_.frame()->is_java_script()) iterator_.Advance();
+    if (i == n) return JavaScriptFrame::cast(iterator_.frame());
+    iterator_.Advance();
+  }
+  UNREACHABLE();
+  return NULL;
+}
+
+
+// -------------------------------------------------------------------------
+
+
+int NumRegs(RegList reglist) {
+  int n = 0;
+  while (reglist != 0) {
+    n++;
+    reglist &= reglist - 1;  // clear one bit
+  }
+  return n;
+}
+
+
+int JSCallerSavedCode(int n) {
+  static int reg_code[kNumJSCallerSaved];
+  static bool initialized = false;
+  if (!initialized) {
+    initialized = true;
+    int i = 0;
+    for (int r = 0; r < kNumRegs; r++)
+      if ((kJSCallerSaved & (1 << r)) != 0)
+        reg_code[i++] = r;
+
+    ASSERT(i == kNumJSCallerSaved);
+  }
+  ASSERT(0 <= n && n < kNumJSCallerSaved);
+  return reg_code[n];
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/frames.h b/deps/v8/src/frames.h
new file mode 100644
index 0000000..8ab4be9
--- /dev/null
+++ b/deps/v8/src/frames.h
@@ -0,0 +1,689 @@
+// 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_FRAMES_H_
+#define V8_FRAMES_H_
+
+namespace v8 { namespace internal {
+
+typedef uint32_t RegList;
+
+// Get the number of registers in a given register list.
+int NumRegs(RegList list);
+
+// Return the code of the n-th saved register available to JavaScript.
+int JSCallerSavedCode(int n);
+
+
+// Forward declarations.
+class StackFrameIterator;
+class Top;
+class ThreadLocalTop;
+
+
+class StackHandler BASE_EMBEDDED {
+ public:
+  enum State {
+    ENTRY,
+    TRY_CATCH,
+    TRY_FINALLY
+  };
+
+  // Get the address of this stack handler.
+  inline Address address() const;
+
+  // Get the next stack handler in the chain.
+  inline StackHandler* next() const;
+
+  // Tells whether the given address is inside this handler.
+  inline bool includes(Address address) const;
+
+  // Garbage collection support.
+  inline void Iterate(ObjectVisitor* v) const;
+
+  // Conversion support.
+  static inline StackHandler* FromAddress(Address address);
+
+  // Testers
+  bool is_entry() { return state() == ENTRY; }
+  bool is_try_catch() { return state() == TRY_CATCH; }
+  bool is_try_finally() { return state() == TRY_FINALLY; }
+
+  // Garbage collection support.
+  void Cook(Code* code);
+  void Uncook(Code* code);
+
+  // TODO(1233780): Get rid of the code slot in stack handlers.
+  static const int kCodeNotPresent = 0;
+
+ private:
+  // Accessors.
+  inline State state() const;
+
+  inline Address pc() const;
+  inline void set_pc(Address value);
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
+};
+
+
+#define STACK_FRAME_TYPE_LIST(V)              \
+  V(ENTRY,             EntryFrame)            \
+  V(ENTRY_CONSTRUCT,   EntryConstructFrame)   \
+  V(EXIT,              ExitFrame)             \
+  V(EXIT_DEBUG,        ExitDebugFrame)        \
+  V(JAVA_SCRIPT,       JavaScriptFrame)       \
+  V(INTERNAL,          InternalFrame)         \
+  V(CONSTRUCT,         ConstructFrame)        \
+  V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)
+
+
+// Abstract base class for all stack frames.
+class StackFrame BASE_EMBEDDED {
+ public:
+#define DECLARE_TYPE(type, ignore) type,
+  enum Type {
+    NONE = 0,
+    STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
+    NUMBER_OF_TYPES
+  };
+#undef DECLARE_TYPE
+
+  // Opaque data type for identifying stack frames. Used extensively
+  // by the debugger.
+  enum Id { NO_ID = 0 };
+
+  // Type testers.
+  bool is_entry() const { return type() == ENTRY; }
+  bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
+  bool is_exit() const { return type() == EXIT; }
+  bool is_exit_debug() const { return type() == EXIT_DEBUG; }
+  bool is_java_script() const { return type() == JAVA_SCRIPT; }
+  bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
+  bool is_internal() const { return type() == INTERNAL; }
+  bool is_construct() const { return type() == CONSTRUCT; }
+  virtual bool is_standard() const { return false; }
+
+  // Accessors.
+  Address sp() const { return state_.sp; }
+  Address fp() const { return state_.fp; }
+  Address pp() const { return GetCallerStackPointer(); }
+
+  Address pc() const { return *pc_address(); }
+  void set_pc(Address pc) { *pc_address() = pc; }
+
+  Address* pc_address() const { return state_.pc_address; }
+
+  // Get the id of this stack frame.
+  Id id() const { return static_cast<Id>(OffsetFrom(pp())); }
+
+  // Checks if this frame includes any stack handlers.
+  bool HasHandler() const;
+
+  // Get the type of this frame.
+  virtual Type type() const = 0;
+
+  // Get the code associated with this frame.
+  virtual Code* code() const = 0;
+
+  // Garbage collection support.
+  static void CookFramesForThread(ThreadLocalTop* thread);
+  static void UncookFramesForThread(ThreadLocalTop* thread);
+
+  virtual void Iterate(ObjectVisitor* v) const { }
+
+  // Printing support.
+  enum PrintMode { OVERVIEW, DETAILS };
+  virtual void Print(StringStream* accumulator,
+                     PrintMode mode,
+                     int index) const { }
+
+ protected:
+  struct State {
+    Address sp;
+    Address fp;
+    Address* pc_address;
+  };
+
+  explicit StackFrame(StackFrameIterator* iterator) : iterator_(iterator) { }
+  virtual ~StackFrame() { }
+
+  // Compute the stack pointer for the calling frame.
+  virtual Address GetCallerStackPointer() const = 0;
+
+  // Printing support.
+  static void PrintIndex(StringStream* accumulator,
+                         PrintMode mode,
+                         int index);
+
+  // Get the top handler from the current stack iterator.
+  inline StackHandler* top_handler() const;
+
+  // Compute the stack frame type for the given state.
+  static Type ComputeType(State* state);
+
+ private:
+  const StackFrameIterator* iterator_;
+  State state_;
+
+  // Fill in the state of the calling frame.
+  virtual void ComputeCallerState(State* state) const = 0;
+
+  // Get the type and the state of the calling frame.
+  virtual Type GetCallerState(State* state) const;
+
+  // Cooking/uncooking support.
+  void Cook();
+  void Uncook();
+
+  friend class StackFrameIterator;
+  friend class StackHandlerIterator;
+  friend class SafeStackFrameIterator;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(StackFrame);
+};
+
+
+// Entry frames are used to enter JavaScript execution from C.
+class EntryFrame: public StackFrame {
+ public:
+  virtual Type type() const { return ENTRY; }
+
+  virtual Code* code() const;
+
+  // Garbage collection support.
+  virtual void Iterate(ObjectVisitor* v) const;
+
+  static EntryFrame* cast(StackFrame* frame) {
+    ASSERT(frame->is_entry());
+    return static_cast<EntryFrame*>(frame);
+  }
+
+ protected:
+  explicit EntryFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
+
+  // The caller stack pointer for entry frames is always zero. The
+  // real information about the caller frame is available through the
+  // link to the top exit frame.
+  virtual Address GetCallerStackPointer() const { return 0; }
+
+ private:
+  virtual void ComputeCallerState(State* state) const;
+  virtual Type GetCallerState(State* state) const;
+
+  friend class StackFrameIterator;
+};
+
+
+class EntryConstructFrame: public EntryFrame {
+ public:
+  virtual Type type() const { return ENTRY_CONSTRUCT; }
+
+  virtual Code* code() const;
+
+  static EntryConstructFrame* cast(StackFrame* frame) {
+    ASSERT(frame->is_entry_construct());
+    return static_cast<EntryConstructFrame*>(frame);
+  }
+
+ protected:
+  explicit EntryConstructFrame(StackFrameIterator* iterator)
+      : EntryFrame(iterator) { }
+
+ private:
+  friend class StackFrameIterator;
+};
+
+
+// Exit frames are used to exit JavaScript execution and go to C.
+class ExitFrame: public StackFrame {
+ public:
+  virtual Type type() const { return EXIT; }
+
+  virtual Code* code() const;
+
+  // Garbage collection support.
+  virtual void Iterate(ObjectVisitor* v) const;
+
+  static ExitFrame* cast(StackFrame* frame) {
+    ASSERT(frame->is_exit());
+    return static_cast<ExitFrame*>(frame);
+  }
+
+  // Compute the state and type of an exit frame given a frame
+  // pointer. Used when constructing the first stack frame seen by an
+  // iterator and the frames following entry frames.
+  static Type GetStateForFramePointer(Address fp, State* state);
+
+ protected:
+  explicit ExitFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
+
+  virtual Address GetCallerStackPointer() const;
+
+ private:
+  virtual void ComputeCallerState(State* state) const;
+
+  friend class StackFrameIterator;
+};
+
+
+class ExitDebugFrame: public ExitFrame {
+ public:
+  virtual Type type() const { return EXIT_DEBUG; }
+
+  virtual Code* code() const;
+
+  static ExitDebugFrame* cast(StackFrame* frame) {
+    ASSERT(frame->is_exit_debug());
+    return static_cast<ExitDebugFrame*>(frame);
+  }
+
+ protected:
+  explicit ExitDebugFrame(StackFrameIterator* iterator)
+      : ExitFrame(iterator) { }
+
+ private:
+  friend class StackFrameIterator;
+};
+
+
+class StandardFrame: public StackFrame {
+ public:
+  // Testers.
+  virtual bool is_standard() const { return true; }
+
+  // Accessors.
+  inline Object* context() const;
+
+  // Access the expressions in the stack frame including locals.
+  inline Object* GetExpression(int index) const;
+  inline void SetExpression(int index, Object* value);
+  int ComputeExpressionsCount() const;
+
+  static StandardFrame* cast(StackFrame* frame) {
+    ASSERT(frame->is_standard());
+    return static_cast<StandardFrame*>(frame);
+  }
+
+ protected:
+  explicit StandardFrame(StackFrameIterator* iterator)
+      : StackFrame(iterator) { }
+
+  virtual void ComputeCallerState(State* state) const;
+
+  // Accessors.
+  inline Address caller_sp() const;
+  inline Address caller_fp() const;
+  inline Address caller_pc() const;
+
+  // Computes the address of the PC field in the standard frame given
+  // by the provided frame pointer.
+  static inline Address ComputePCAddress(Address fp);
+
+  // Iterate over expression stack including stack handlers, locals,
+  // and parts of the fixed part including context and code fields.
+  void IterateExpressions(ObjectVisitor* v) const;
+
+  // Returns the address of the n'th expression stack element.
+  Address GetExpressionAddress(int n) const;
+
+  // Determines if the n'th expression stack element is in a stack
+  // handler or not. Requires traversing all handlers in this frame.
+  bool IsExpressionInsideHandler(int n) const;
+
+  // Determines if the standard frame for the given frame pointer is
+  // an arguments adaptor frame.
+  static inline bool IsArgumentsAdaptorFrame(Address fp);
+
+  // Determines if the standard frame for the given frame pointer is a
+  // construct frame.
+  static inline bool IsConstructFrame(Address fp);
+
+ private:
+  friend class StackFrame;
+};
+
+
+class JavaScriptFrame: public StandardFrame {
+ public:
+  virtual Type type() const { return JAVA_SCRIPT; }
+
+  // Accessors.
+  inline Object* function() const;
+  inline Object* receiver() const;
+  inline void set_receiver(Object* value);
+
+  // Access the parameters.
+  Object* GetParameter(int index) const;
+  int ComputeParametersCount() const;
+
+  // Temporary way of getting access to the number of parameters
+  // passed on the stack by the caller. Once argument adaptor frames
+  // has been introduced on ARM, this number will always match the
+  // computed parameters count.
+  int GetProvidedParametersCount() const;
+
+  // Check if this frame is a constructor frame invoked through 'new'.
+  bool IsConstructor() const;
+
+  // Check if this frame has "adapted" arguments in the sense that the
+  // actual passed arguments are available in an arguments adaptor
+  // frame below it on the stack.
+  inline bool has_adapted_arguments() const;
+
+  // Garbage collection support.
+  virtual void Iterate(ObjectVisitor* v) const;
+
+  // Printing support.
+  virtual void Print(StringStream* accumulator,
+                     PrintMode mode,
+                     int index) const;
+
+  // Determine the code for the frame.
+  virtual Code* code() const;
+
+  static JavaScriptFrame* cast(StackFrame* frame) {
+    ASSERT(frame->is_java_script());
+    return static_cast<JavaScriptFrame*>(frame);
+  }
+
+ protected:
+  explicit JavaScriptFrame(StackFrameIterator* iterator)
+      : StandardFrame(iterator), disable_heap_access_(false) { }
+
+  virtual Address GetCallerStackPointer() const;
+
+  // When this mode is enabled it is not allowed to access heap objects.
+  // This is a special mode used when gathering stack samples in profiler.
+  // A shortcoming is that caller's SP value will be calculated incorrectly
+  // (see GetCallerStackPointer implementation), but it is not used for stack
+  // sampling.
+  void DisableHeapAccess() { disable_heap_access_ = true; }
+
+ private:
+  bool disable_heap_access_;
+  inline Object* function_slot_object() const;
+
+  friend class StackFrameIterator;
+};
+
+
+// Arguments adaptor frames are automatically inserted below
+// JavaScript frames when the actual number of parameters does not
+// match the formal number of parameters.
+class ArgumentsAdaptorFrame: public JavaScriptFrame {
+ public:
+  // This sentinel value is temporarily used to distinguish arguments
+  // adaptor frames from ordinary JavaScript frames. If a frame has
+  // the sentinel as its context, it is an arguments adaptor frame. It
+  // must be tagged as a small integer to avoid GC issues. Crud.
+  enum {
+    SENTINEL = (1 << kSmiTagSize) | kSmiTag
+  };
+
+  virtual Type type() const { return ARGUMENTS_ADAPTOR; }
+
+  // Determine the code for the frame.
+  virtual Code* code() const;
+
+  static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
+    ASSERT(frame->is_arguments_adaptor());
+    return static_cast<ArgumentsAdaptorFrame*>(frame);
+  }
+
+  // Printing support.
+  virtual void Print(StringStream* accumulator,
+                     PrintMode mode,
+                     int index) const;
+ protected:
+  explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator)
+      : JavaScriptFrame(iterator) { }
+
+  virtual Address GetCallerStackPointer() const;
+
+ private:
+  friend class StackFrameIterator;
+};
+
+
+class InternalFrame: public StandardFrame {
+ public:
+  virtual Type type() const { return INTERNAL; }
+
+  // Garbage collection support.
+  virtual void Iterate(ObjectVisitor* v) const;
+
+  // Determine the code for the frame.
+  virtual Code* code() const;
+
+  static InternalFrame* cast(StackFrame* frame) {
+    ASSERT(frame->is_internal());
+    return static_cast<InternalFrame*>(frame);
+  }
+
+ protected:
+  explicit InternalFrame(StackFrameIterator* iterator)
+      : StandardFrame(iterator) { }
+
+  virtual Address GetCallerStackPointer() const;
+
+ private:
+  friend class StackFrameIterator;
+};
+
+
+// Construct frames are special trampoline frames introduced to handle
+// function invocations through 'new'.
+class ConstructFrame: public InternalFrame {
+ public:
+  virtual Type type() const { return CONSTRUCT; }
+
+  static ConstructFrame* cast(StackFrame* frame) {
+    ASSERT(frame->is_construct());
+    return static_cast<ConstructFrame*>(frame);
+  }
+
+ protected:
+  explicit ConstructFrame(StackFrameIterator* iterator)
+      : InternalFrame(iterator) { }
+
+ private:
+  friend class StackFrameIterator;
+};
+
+
+class StackFrameIterator BASE_EMBEDDED {
+ public:
+  // An iterator that iterates over the current thread's stack.
+  StackFrameIterator();
+
+  // An iterator that iterates over a given thread's stack.
+  explicit StackFrameIterator(ThreadLocalTop* thread);
+
+  // An iterator that can start from a given FP address.
+  // If use_top, then work as usual, if fp isn't NULL, use it,
+  // otherwise, do nothing.
+  StackFrameIterator(bool use_top, Address fp, Address sp);
+
+  StackFrame* frame() const {
+    ASSERT(!done());
+    return frame_;
+  }
+
+  bool done() const { return frame_ == NULL; }
+  void Advance() { (this->*advance_)(); }
+
+  // Go back to the first frame.
+  void Reset();
+
+ private:
+#define DECLARE_SINGLETON(ignore, type) type type##_;
+  STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
+#undef DECLARE_SINGLETON
+  StackFrame* frame_;
+  StackHandler* handler_;
+  ThreadLocalTop* thread_;
+  Address fp_;
+  Address sp_;
+  void (StackFrameIterator::*advance_)();
+
+  StackHandler* handler() const {
+    ASSERT(!done());
+    return handler_;
+  }
+
+  // Get the type-specific frame singleton in a given state.
+  StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
+  // A helper function, can return a NULL pointer.
+  StackFrame* SingletonFor(StackFrame::Type type);
+
+  void AdvanceWithHandler();
+  void AdvanceWithoutHandler();
+
+  friend class StackFrame;
+  friend class SafeStackFrameIterator;
+  DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
+};
+
+
+// Iterator that supports iterating through all JavaScript frames.
+template<typename Iterator>
+class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
+ public:
+  JavaScriptFrameIteratorTemp() { if (!done()) Advance(); }
+
+  explicit JavaScriptFrameIteratorTemp(ThreadLocalTop* thread) :
+      iterator_(thread) {
+    if (!done()) Advance();
+  }
+
+  // Skip frames until the frame with the given id is reached.
+  explicit JavaScriptFrameIteratorTemp(StackFrame::Id id);
+
+  JavaScriptFrameIteratorTemp(Address fp, Address sp,
+                              Address low_bound, Address high_bound) :
+      iterator_(fp, sp, low_bound, high_bound) {
+    if (!done()) Advance();
+  }
+
+  inline JavaScriptFrame* frame() const;
+
+  bool done() const { return iterator_.done(); }
+  void Advance();
+
+  // Advance to the frame holding the arguments for the current
+  // frame. This only affects the current frame if it has adapted
+  // arguments.
+  void AdvanceToArgumentsFrame();
+
+  // Go back to the first frame.
+  void Reset();
+
+ private:
+  Iterator iterator_;
+};
+
+
+typedef JavaScriptFrameIteratorTemp<StackFrameIterator> JavaScriptFrameIterator;
+
+
+// NOTE: The stack trace frame iterator is an iterator that only
+// traverse proper JavaScript frames; that is JavaScript frames that
+// have proper JavaScript functions. This excludes the problematic
+// functions in runtime.js.
+class StackTraceFrameIterator: public JavaScriptFrameIterator {
+ public:
+  StackTraceFrameIterator();
+  void Advance();
+};
+
+
+class SafeStackFrameIterator BASE_EMBEDDED {
+ public:
+  SafeStackFrameIterator(Address fp, Address sp,
+                         Address low_bound, Address high_bound);
+
+  StackFrame* frame() const {
+    ASSERT(is_working_iterator_);
+    return iterator_.frame();
+  }
+
+  bool done() const { return iteration_done_ ? true : iterator_.done(); }
+
+  void Advance();
+  void Reset();
+
+ private:
+  static bool IsWithinBounds(
+      Address low_bound, Address high_bound, Address addr) {
+    return low_bound <= addr && addr <= high_bound;
+  }
+  bool IsValidStackAddress(Address addr) const {
+    return IsWithinBounds(low_bound_, high_bound_, addr);
+  }
+  bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
+  bool IsValidFrame(StackFrame* frame) const;
+  bool IsValidCaller(StackFrame* frame);
+
+  Address low_bound_;
+  Address high_bound_;
+  const bool is_valid_top_;
+  const bool is_valid_fp_;
+  const bool is_working_iterator_;
+  bool iteration_done_;
+  StackFrameIterator iterator_;
+};
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
+    SafeJavaScriptFrameIterator;
+
+
+class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
+ public:
+  explicit SafeStackTraceFrameIterator(Address fp, Address sp,
+                                       Address low_bound, Address high_bound);
+  void Advance();
+};
+#endif
+
+
+class StackFrameLocator BASE_EMBEDDED {
+ public:
+  // Find the nth JavaScript frame on the stack. The caller must
+  // guarantee that such a frame exists.
+  JavaScriptFrame* FindJavaScriptFrame(int n);
+
+ private:
+  StackFrameIterator iterator_;
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_FRAMES_H_
diff --git a/deps/v8/src/func-name-inferrer.cc b/deps/v8/src/func-name-inferrer.cc
new file mode 100644
index 0000000..ef0c7db
--- /dev/null
+++ b/deps/v8/src/func-name-inferrer.cc
@@ -0,0 +1,74 @@
+// 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.
+
+#include "v8.h"
+
+#include "ast.h"
+#include "func-name-inferrer.h"
+
+namespace v8 { namespace internal {
+
+
+void FuncNameInferrer::PushEnclosingName(Handle<String> name) {
+  // Enclosing name is a name of a constructor function. To check
+  // that it is really a constructor, we check that it is not empty
+  // and starts with a capital letter.
+  if (name->length() > 0 && Runtime::IsUpperCaseChar(name->Get(0))) {
+    names_stack_.Add(name);
+  }
+}
+
+
+Handle<String> FuncNameInferrer::MakeNameFromStack() {
+  if (names_stack_.is_empty()) {
+    return Factory::empty_string();
+  } else {
+    return MakeNameFromStackHelper(1, names_stack_.at(0));
+  }
+}
+
+
+Handle<String> FuncNameInferrer::MakeNameFromStackHelper(int pos,
+                                                         Handle<String> prev) {
+  if (pos >= names_stack_.length()) {
+    return prev;
+  } else {
+    Handle<String> curr = Factory::NewConsString(dot_, names_stack_.at(pos));
+    return MakeNameFromStackHelper(pos + 1, Factory::NewConsString(prev, curr));
+  }
+}
+
+
+void FuncNameInferrer::MaybeInferFunctionName() {
+  if (func_to_infer_ != NULL) {
+    func_to_infer_->set_inferred_name(MakeNameFromStack());
+    func_to_infer_ = NULL;
+  }
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/func-name-inferrer.h b/deps/v8/src/func-name-inferrer.h
new file mode 100644
index 0000000..9dcf7c5
--- /dev/null
+++ b/deps/v8/src/func-name-inferrer.h
@@ -0,0 +1,127 @@
+// Copyright 2006-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.
+
+#ifndef V8_FUNC_NAME_INFERRER_H_
+#define V8_FUNC_NAME_INFERRER_H_
+
+namespace v8 { namespace internal {
+
+// FuncNameInferrer is a stateful class that is used to perform name
+// inference for anonymous functions during static analysis of source code.
+// Inference is performed in cases when an anonymous function is assigned
+// to a variable or a property (see test-func-name-inference.cc for examples.)
+
+// The basic idea is that during AST traversal LHSs of expressions are
+// always visited before RHSs. Thus, during visiting the LHS, a name can be
+// collected, and during visiting the RHS, a function literal can be collected.
+// Inference is performed while leaving the assignment node.
+
+class FuncNameInferrer BASE_EMBEDDED {
+ public:
+  FuncNameInferrer() :
+      entries_stack_(10),
+      names_stack_(5),
+      func_to_infer_(NULL),
+      dot_(Factory::NewStringFromAscii(CStrVector("."))) {
+  }
+
+  bool IsOpen() const { return !entries_stack_.is_empty(); }
+
+  void PushEnclosingName(Handle<String> name);
+
+  void Enter() {
+    entries_stack_.Add(names_stack_.length());
+  }
+
+  void Leave() {
+    ASSERT(IsOpen());
+    names_stack_.Rewind(entries_stack_.RemoveLast());
+  }
+
+  void PushName(Handle<String> name) {
+    if (IsOpen()) {
+      names_stack_.Add(name);
+    }
+  }
+
+  void SetFuncToInfer(FunctionLiteral* func_to_infer) {
+    if (IsOpen()) {
+      // If we encounter another function literal after already having
+      // encountered one, the second one replaces the first.
+      func_to_infer_ = func_to_infer;
+    }
+  }
+
+  void InferAndLeave() {
+    ASSERT(IsOpen());
+    MaybeInferFunctionName();
+    Leave();
+  }
+
+ private:
+  Handle<String> MakeNameFromStack();
+  Handle<String> MakeNameFromStackHelper(int pos, Handle<String> prev);
+  void MaybeInferFunctionName();
+
+  List<int> entries_stack_;
+  List<Handle<String> > names_stack_;
+  FunctionLiteral* func_to_infer_;
+  Handle<String> dot_;
+
+  DISALLOW_COPY_AND_ASSIGN(FuncNameInferrer);
+};
+
+
+// A wrapper class that automatically calls InferAndLeave when
+// leaving scope.
+class ScopedFuncNameInferrer BASE_EMBEDDED {
+ public:
+  explicit ScopedFuncNameInferrer(FuncNameInferrer* inferrer) :
+      inferrer_(inferrer),
+      is_entered_(false) {}
+  ~ScopedFuncNameInferrer() {
+    if (is_entered_) {
+      inferrer_->InferAndLeave();
+    }
+  }
+
+  void Enter() {
+    inferrer_->Enter();
+    is_entered_ = true;
+  }
+
+ private:
+  FuncNameInferrer* inferrer_;
+  bool is_entered_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedFuncNameInferrer);
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_FUNC_NAME_INFERRER_H_
diff --git a/deps/v8/src/global-handles.cc b/deps/v8/src/global-handles.cc
new file mode 100644
index 0000000..c2194fc
--- /dev/null
+++ b/deps/v8/src/global-handles.cc
@@ -0,0 +1,383 @@
+// 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.
+
+#include "v8.h"
+
+#include "api.h"
+#include "global-handles.h"
+
+namespace v8 { namespace internal {
+
+class GlobalHandles::Node : public Malloced {
+ public:
+
+  void Initialize(Object* object) {
+    // Set the initial value of the handle.
+    object_ = object;
+    state_  = NORMAL;
+    parameter_or_next_free_.parameter = NULL;
+    callback_ = NULL;
+  }
+
+  explicit Node(Object* object) {
+    Initialize(object);
+    // Initialize link structure.
+    next_ = NULL;
+  }
+
+  ~Node() {
+    if (state_ != DESTROYED) Destroy();
+#ifdef DEBUG
+    // Zap the values for eager trapping.
+    object_ = NULL;
+    next_ = NULL;
+    parameter_or_next_free_.next_free = NULL;
+#endif
+  }
+
+  void Destroy() {
+    if (state_ == WEAK || IsNearDeath()) {
+      GlobalHandles::number_of_weak_handles_--;
+      if (object_->IsJSGlobalObject()) {
+        GlobalHandles::number_of_global_object_weak_handles_--;
+      }
+    }
+    state_ = DESTROYED;
+  }
+
+  // Accessors for next_.
+  Node* next() { return next_; }
+  void set_next(Node* value) { next_ = value; }
+  Node** next_addr() { return &next_; }
+
+  // Accessors for next free node in the free list.
+  Node* next_free() {
+    ASSERT(state_ == DESTROYED);
+    return parameter_or_next_free_.next_free;
+  }
+  void set_next_free(Node* value) {
+    ASSERT(state_ == DESTROYED);
+    parameter_or_next_free_.next_free = value;
+  }
+
+  // Returns a link from the handle.
+  static Node* FromLocation(Object** location) {
+    ASSERT(OFFSET_OF(Node, object_) == 0);
+    return reinterpret_cast<Node*>(location);
+  }
+
+  // Returns the handle.
+  Handle<Object> handle() { return Handle<Object>(&object_); }
+
+  // Make this handle weak.
+  void MakeWeak(void* parameter, WeakReferenceCallback callback) {
+    LOG(HandleEvent("GlobalHandle::MakeWeak", handle().location()));
+    ASSERT(state_ != DESTROYED);
+    if (state_ != WEAK && !IsNearDeath()) {
+      GlobalHandles::number_of_weak_handles_++;
+      if (object_->IsJSGlobalObject()) {
+        GlobalHandles::number_of_global_object_weak_handles_++;
+      }
+    }
+    state_ = WEAK;
+    set_parameter(parameter);
+    callback_ = callback;
+  }
+
+  void ClearWeakness() {
+    LOG(HandleEvent("GlobalHandle::ClearWeakness", handle().location()));
+    ASSERT(state_ != DESTROYED);
+    if (state_ == WEAK || IsNearDeath()) {
+      GlobalHandles::number_of_weak_handles_--;
+      if (object_->IsJSGlobalObject()) {
+        GlobalHandles::number_of_global_object_weak_handles_--;
+      }
+    }
+    state_ = NORMAL;
+    set_parameter(NULL);
+  }
+
+  bool IsNearDeath() {
+    // Check for PENDING to ensure correct answer when processing callbacks.
+    return state_ == PENDING || state_ == NEAR_DEATH;
+  }
+
+  bool IsWeak() {
+    return state_ == WEAK;
+  }
+
+  // Returns the id for this weak handle.
+  void set_parameter(void* parameter) {
+    ASSERT(state_ != DESTROYED);
+    parameter_or_next_free_.parameter = parameter;
+  }
+  void* parameter() {
+    ASSERT(state_ != DESTROYED);
+    return parameter_or_next_free_.parameter;
+  }
+
+  // Returns the callback for this weak handle.
+  WeakReferenceCallback callback() { return callback_; }
+
+  void PostGarbageCollectionProcessing() {
+    if (state_ != Node::PENDING) return;
+    LOG(HandleEvent("GlobalHandle::Processing", handle().location()));
+    void* par = parameter();
+    state_ = NEAR_DEATH;
+    set_parameter(NULL);
+    // The callback function is resolved as late as possible to preserve old
+    // behavior.
+    WeakReferenceCallback func = callback();
+    if (func != NULL) {
+      v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle());
+      {
+        // Leaving V8.
+        VMState state(EXTERNAL);
+        func(object, par);
+      }
+    }
+  }
+
+  // Place the handle address first to avoid offset computation.
+  Object* object_;  // Storage for object pointer.
+
+  // Transition diagram:
+  // NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, DESTROYED }
+  enum State {
+    NORMAL,      // Normal global handle.
+    WEAK,        // Flagged as weak but not yet finalized.
+    PENDING,     // Has been recognized as only reachable by weak handles.
+    NEAR_DEATH,  // Callback has informed the handle is near death.
+    DESTROYED
+  };
+  State state_;
+
+ private:
+  // Handle specific callback.
+  WeakReferenceCallback callback_;
+  // Provided data for callback.  In DESTROYED state, this is used for
+  // the free list link.
+  union {
+    void* parameter;
+    Node* next_free;
+  } parameter_or_next_free_;
+
+  // Linkage for the list.
+  Node* next_;
+
+ public:
+  TRACK_MEMORY("GlobalHandles::Node")
+};
+
+
+Handle<Object> GlobalHandles::Create(Object* value) {
+  Counters::global_handles.Increment();
+  Node* result;
+  if (first_free() == NULL) {
+    // Allocate a new node.
+    result = new Node(value);
+    result->set_next(head());
+    set_head(result);
+  } else {
+    // Take the first node in the free list.
+    result = first_free();
+    set_first_free(result->next_free());
+    result->Initialize(value);
+  }
+  return result->handle();
+}
+
+
+void GlobalHandles::Destroy(Object** location) {
+  Counters::global_handles.Decrement();
+  if (location == NULL) return;
+  Node* node = Node::FromLocation(location);
+  node->Destroy();
+  // Link the destroyed.
+  node->set_next_free(first_free());
+  set_first_free(node);
+}
+
+
+void GlobalHandles::MakeWeak(Object** location, void* parameter,
+                             WeakReferenceCallback callback) {
+  ASSERT(callback != NULL);
+  Node::FromLocation(location)->MakeWeak(parameter, callback);
+}
+
+
+void GlobalHandles::ClearWeakness(Object** location) {
+  Node::FromLocation(location)->ClearWeakness();
+}
+
+
+bool GlobalHandles::IsNearDeath(Object** location) {
+  return Node::FromLocation(location)->IsNearDeath();
+}
+
+
+bool GlobalHandles::IsWeak(Object** location) {
+  return Node::FromLocation(location)->IsWeak();
+}
+
+
+void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) {
+  // Traversal of GC roots in the global handle list that are marked as
+  // WEAK or PENDING.
+  for (Node* current = head_; current != NULL; current = current->next()) {
+    if (current->state_ == Node::WEAK
+      || current->state_ == Node::PENDING
+      || current->state_ == Node::NEAR_DEATH) {
+      v->VisitPointer(&current->object_);
+    }
+  }
+}
+
+
+void GlobalHandles::MarkWeakRoots(WeakSlotCallback f) {
+  for (Node* current = head_; current != NULL; current = current->next()) {
+    if (current->state_ == Node::WEAK) {
+      if (f(&current->object_)) {
+        current->state_ = Node::PENDING;
+        LOG(HandleEvent("GlobalHandle::Pending", current->handle().location()));
+      }
+    }
+  }
+}
+
+
+void GlobalHandles::PostGarbageCollectionProcessing() {
+  // Process weak global handle callbacks. This must be done after the
+  // GC is completely done, because the callbacks may invoke arbitrary
+  // API functions.
+  // At the same time deallocate all DESTROYED nodes
+  ASSERT(Heap::gc_state() == Heap::NOT_IN_GC);
+  Node** p = &head_;
+  while (*p != NULL) {
+    (*p)->PostGarbageCollectionProcessing();
+    if ((*p)->state_ == Node::DESTROYED) {
+      // Delete the link.
+      Node* node = *p;
+      *p = node->next();  // Update the link.
+      delete node;
+    } else {
+      p = (*p)->next_addr();
+    }
+  }
+  set_first_free(NULL);
+}
+
+
+void GlobalHandles::IterateRoots(ObjectVisitor* v) {
+  // Traversal of global handles marked as NORMAL or NEAR_DEATH.
+  for (Node* current = head_; current != NULL; current = current->next()) {
+    if (current->state_ == Node::NORMAL) {
+      v->VisitPointer(&current->object_);
+    }
+  }
+}
+
+void GlobalHandles::TearDown() {
+  // Delete all the nodes in the linked list.
+  Node* current = head_;
+  while (current != NULL) {
+    Node* n = current;
+    current = current->next();
+    delete n;
+  }
+  // Reset the head and free_list.
+  set_head(NULL);
+  set_first_free(NULL);
+}
+
+
+int GlobalHandles::number_of_weak_handles_ = 0;
+int GlobalHandles::number_of_global_object_weak_handles_ = 0;
+
+GlobalHandles::Node* GlobalHandles::head_ = NULL;
+GlobalHandles::Node* GlobalHandles::first_free_ = NULL;
+
+#ifdef DEBUG
+
+void GlobalHandles::PrintStats() {
+  int total = 0;
+  int weak = 0;
+  int pending = 0;
+  int near_death = 0;
+  int destroyed = 0;
+
+  for (Node* current = head_; current != NULL; current = current->next()) {
+    total++;
+    if (current->state_ == Node::WEAK) weak++;
+    if (current->state_ == Node::PENDING) pending++;
+    if (current->state_ == Node::NEAR_DEATH) near_death++;
+    if (current->state_ == Node::DESTROYED) destroyed++;
+  }
+
+  PrintF("Global Handle Statistics:\n");
+  PrintF("  allocated memory = %dB\n", sizeof(Node) * total);
+  PrintF("  # weak       = %d\n", weak);
+  PrintF("  # pending    = %d\n", pending);
+  PrintF("  # near_death = %d\n", near_death);
+  PrintF("  # destroyed  = %d\n", destroyed);
+  PrintF("  # total      = %d\n", total);
+}
+
+void GlobalHandles::Print() {
+  PrintF("Global handles:\n");
+  for (Node* current = head_; current != NULL; current = current->next()) {
+    PrintF("  handle %p to %p (weak=%d)\n", current->handle().location(),
+           *current->handle(), current->state_ == Node::WEAK);
+  }
+}
+
+#endif
+
+List<ObjectGroup*>* GlobalHandles::ObjectGroups() {
+  // Lazily initialize the list to avoid startup time static constructors.
+  static List<ObjectGroup*> groups(4);
+  return &groups;
+}
+
+void GlobalHandles::AddGroup(Object*** handles, size_t length) {
+  ObjectGroup* new_entry = new ObjectGroup(length);
+  for (size_t i = 0; i < length; ++i)
+    new_entry->objects_.Add(handles[i]);
+  ObjectGroups()->Add(new_entry);
+}
+
+
+void GlobalHandles::RemoveObjectGroups() {
+  List<ObjectGroup*>* object_groups = ObjectGroups();
+  for (int i = 0; i< object_groups->length(); i++) {
+    delete object_groups->at(i);
+  }
+  object_groups->Clear();
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/global-handles.h b/deps/v8/src/global-handles.h
new file mode 100644
index 0000000..c5f4450
--- /dev/null
+++ b/deps/v8/src/global-handles.h
@@ -0,0 +1,148 @@
+// 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.
+
+#ifndef V8_GLOBAL_HANDLES_H_
+#define V8_GLOBAL_HANDLES_H_
+
+#include "list-inl.h"
+
+namespace v8 { namespace internal {
+
+// Structure for tracking global handles.
+// A single list keeps all the allocated global handles.
+// Destroyed handles stay in the list but is added to the free list.
+// At GC the destroyed global handles are removed from the free list
+// and deallocated.
+
+// Callback function on handling weak global handles.
+// typedef bool (*WeakSlotCallback)(Object** pointer);
+
+// An object group is treated like a single JS object: if one of object in
+// the group is alive, all objects in the same group are considered alive.
+// An object group is used to simulate object relationship in a DOM tree.
+class ObjectGroup : public Malloced {
+ public:
+  ObjectGroup() : objects_(4) {}
+  explicit ObjectGroup(size_t capacity) : objects_(capacity) {}
+
+  List<Object**> objects_;
+};
+
+
+class GlobalHandles : public AllStatic {
+ public:
+  // Creates a new global handle that is alive until Destroy is called.
+  static Handle<Object> Create(Object* value);
+
+  // Destroy a global handle.
+  static void Destroy(Object** location);
+
+  // Make the global handle weak and set the callback parameter for the
+  // handle.  When the garbage collector recognizes that only weak global
+  // handles point to an object the handles are cleared and the callback
+  // function is invoked (for each handle) with the handle and corresponding
+  // parameter as arguments.  Note: cleared means set to Smi::FromInt(0). The
+  // reason is that Smi::FromInt(0) does not change during garage collection.
+  static void MakeWeak(Object** location,
+                       void* parameter,
+                       WeakReferenceCallback callback);
+
+  // Returns the current number of weak handles.
+  static int NumberOfWeakHandles() { return number_of_weak_handles_; }
+
+  // Returns the current number of weak handles to global objects.
+  // These handles are also included in NumberOfWeakHandles().
+  static int NumberOfGlobalObjectWeakHandles() {
+    return number_of_global_object_weak_handles_;
+  }
+
+  // Clear the weakness of a global handle.
+  static void ClearWeakness(Object** location);
+
+  // Tells whether global handle is near death.
+  static bool IsNearDeath(Object** location);
+
+  // Tells whether global handle is weak.
+  static bool IsWeak(Object** location);
+
+  // Process pending weak handles.
+  static void PostGarbageCollectionProcessing();
+
+  // Iterates over all handles.
+  static void IterateRoots(ObjectVisitor* v);
+
+  // Iterates over all weak roots in heap.
+  static void IterateWeakRoots(ObjectVisitor* v);
+
+  // Mark the weak pointers based on the callback.
+  static void MarkWeakRoots(WeakSlotCallback f);
+
+  // Add an object group.
+  // Should only used in GC callback function before a collection.
+  // All groups are destroyed after a mark-compact collection.
+  static void AddGroup(Object*** handles, size_t length);
+
+  // Returns the object groups.
+  static List<ObjectGroup*>* ObjectGroups();
+
+  // Remove bags, this should only happen after GC.
+  static void RemoveObjectGroups();
+
+  // Tear down the global handle structure.
+  static void TearDown();
+
+#ifdef DEBUG
+  static void PrintStats();
+  static void Print();
+#endif
+ private:
+  // Internal node structure, one for each global handle.
+  class Node;
+
+  // Field always containing the number of weak and near-death handles.
+  static int number_of_weak_handles_;
+
+  // Field always containing the number of weak and near-death handles
+  // to global objects.  These objects are also included in
+  // number_of_weak_handles_.
+  static int number_of_global_object_weak_handles_;
+
+  // Global handles are kept in a single linked list pointed to by head_.
+  static Node* head_;
+  static Node* head() { return head_; }
+  static void set_head(Node* value) { head_ = value; }
+
+  // Free list for DESTROYED global handles not yet deallocated.
+  static Node* first_free_;
+  static Node* first_free() { return first_free_; }
+  static void set_first_free(Node* value) { first_free_ = value; }
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_GLOBAL_HANDLES_H_
diff --git a/deps/v8/src/globals.h b/deps/v8/src/globals.h
new file mode 100644
index 0000000..1579c3d
--- /dev/null
+++ b/deps/v8/src/globals.h
@@ -0,0 +1,519 @@
+// 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_GLOBALS_H_
+#define V8_GLOBALS_H_
+
+// -----------------------------------------------------------------------------
+// Types
+// Visual Studio C++ is missing the stdint.h header file. Instead we define
+// standard integer types for Windows here.
+
+#ifdef _MSC_VER
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef short int16_t;  // NOLINT
+typedef unsigned short uint16_t;  // NOLINT
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#else  // _MSC_VER
+#include <stdint.h>  // for intptr_t
+#endif  // _MSC_VER
+
+
+namespace v8 { namespace internal {
+
+// Support for alternative bool type. This is only enabled if the code is
+// compiled with USE_MYBOOL defined. This catches some nasty type bugs.
+// For instance, 'bool b = "false";' results in b == true! This is a hidden
+// source of bugs.
+// However, redefining the bool type does have some negative impact on some
+// platforms. It gives rise to compiler warnings (i.e. with
+// MSVC) in the API header files when mixing code that uses the standard
+// bool with code that uses the redefined version.
+// This does not actually belong in the platform code, but needs to be
+// defined here because the platform code uses bool, and platform.h is
+// include very early in the main include file.
+
+#ifdef USE_MYBOOL
+typedef unsigned int __my_bool__;
+#define bool __my_bool__  // use 'indirection' to avoid name clashes
+#endif
+
+typedef uint8_t byte;
+typedef byte* Address;
+
+// Code-point values in Unicode 4.0 are 21 bits wide.
+typedef uint16_t uc16;
+typedef signed int uc32;
+
+#ifndef ARM
+#define CAN_READ_UNALIGNED 1
+#endif
+
+// -----------------------------------------------------------------------------
+// Constants
+
+#ifdef DEBUG
+const bool kDebug = true;
+#else
+const bool kDebug = false;
+#endif  // DEBUG
+
+const int KB = 1024;
+const int MB = KB * KB;
+const int GB = KB * KB * KB;
+const int kMaxInt = 0x7FFFFFFF;
+const int kMinInt = -kMaxInt - 1;
+
+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 kPointerSize  = sizeof(void*);   // NOLINT
+
+const int kPointerSizeLog2 = 2;
+
+const int kObjectAlignmentBits = 2;
+const int kObjectAlignmentMask = (1 << kObjectAlignmentBits) - 1;
+const int kObjectAlignment = 1 << kObjectAlignmentBits;
+
+
+// Tag information for HeapObject.
+const int kHeapObjectTag = 1;
+const int kHeapObjectTagSize = 2;
+const int kHeapObjectTagMask = (1 << kHeapObjectTagSize) - 1;
+
+
+// Tag information for Smi.
+const int kSmiTag = 0;
+const int kSmiTagSize = 1;
+const int kSmiTagMask = (1 << kSmiTagSize) - 1;
+
+
+// Tag information for Failure.
+const int kFailureTag = 3;
+const int kFailureTagSize = 2;
+const int kFailureTagMask = (1 << kFailureTagSize) - 1;
+
+
+const int kBitsPerByte = 8;
+const int kBitsPerByteLog2 = 3;
+const int kBitsPerPointer = kPointerSize * kBitsPerByte;
+const int kBitsPerInt = kIntSize * kBitsPerByte;
+
+
+// Zap-value: The value used for zapping dead objects. Should be a recognizable
+// illegal heap object pointer.
+const Address kZapValue = reinterpret_cast<Address>(0xdeadbeed);
+const Address kHandleZapValue = reinterpret_cast<Address>(0xbaddead);
+const Address kFromSpaceZapValue = reinterpret_cast<Address>(0xbeefdad);
+
+// -----------------------------------------------------------------------------
+// Forward declarations for frequently used classes
+// (sorted alphabetically)
+
+class AccessorInfo;
+class Allocation;
+class Arguments;
+class Assembler;
+class BreakableStatement;
+class Code;
+class CodeGenerator;
+class CodeRegion;
+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 Dictionary;
+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 OldSpace;
+class Property;
+class Proxy;
+class RegExpNode;
+struct RegExpCompileData;
+class RegExpTree;
+class RegExpCompiler;
+class RegExpVisitor;
+class Scope;
+template<class Allocator = FreeStoreAllocationPolicy> class ScopeInfo;
+class Script;
+class Slot;
+class Smi;
+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,  // Must be first of the paged spaces - see PagedSpaces.
+  OLD_DATA_SPACE,     // May not have pointers to new space.
+  CODE_SPACE,         // Also one of the old spaces.  Marked executable.
+  MAP_SPACE,          // Only map objects.
+  LO_SPACE,           // Large objects.
+  FIRST_SPACE = NEW_SPACE,
+  LAST_SPACE = LO_SPACE  // <= 5 (see kSpaceBits and kLOSpacePointer)
+};
+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 };
+
+
+// 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 never been executed, but is in a loop.
+  UNINITIALIZED_IN_LOOP,
+  // 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
+};
+
+
+// Type of properties.
+// Order of properties is significant.
+// Must fit in the BitField PropertyDetails::TypeField.
+// A copy of this is in mirror-delay.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
+};
+
+
+// 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; }
+};
+
+
+// AccessorCallback
+struct AccessorDescriptor {
+  Object* (*getter)(Object* object, void* data);
+  Object* (*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_LOGGING_AND_PROFILING, 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<int>(value) & kSmiTagMask) == kSmiTag)
+
+#define HAS_FAILURE_TAG(value) \
+  ((reinterpret_cast<int>(value) & kFailureTagMask) == kFailureTag)
+
+#define HAS_HEAP_OBJECT_TAG(value) \
+  ((reinterpret_cast<int>(value) & kHeapObjectTagMask) == kHeapObjectTag)
+
+// OBJECT_SIZE_ALIGN returns the value aligned HeapObject size
+#define OBJECT_SIZE_ALIGN(value)                                \
+  ((value + kObjectAlignmentMask) & ~kObjectAlignmentMask)
+
+// 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
+// use 0 or NULL, which causes a problem with the compiler warnings
+// we have enabled (which is also why 'offsetof' doesn't seem to work).
+// Here we simply use the non-zero value 4, which seems to work.
+#define OFFSET_OF(type, field)                                          \
+  (reinterpret_cast<intptr_t>(&(reinterpret_cast<type*>(4)->field)) - 4)
+
+
+// The expression ARRAY_SIZE(a) is a compile-time constant of type
+// size_t which represents the number of elements of the given
+// array. You should only use ARRAY_SIZE on statically allocated
+// arrays.
+#define ARRAY_SIZE(a)                                   \
+  ((sizeof(a) / sizeof(*(a))) /                         \
+  static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
+
+
+// The USE(x) template is used to silence C++ compiler warnings
+// issued for (yet) unused variables (typically parameters).
+template <typename T>
+static inline void USE(T) { }
+
+
+// FUNCTION_ADDR(f) gets the address of a C function f.
+#define FUNCTION_ADDR(f)                                        \
+  (reinterpret_cast<v8::internal::Address>(reinterpret_cast<intptr_t>(f)))
+
+
+// FUNCTION_CAST<F>(addr) casts an address into a function
+// of type F. Used to invoke generated code from within C.
+template <typename F>
+F FUNCTION_CAST(Address addr) {
+  return reinterpret_cast<F>(reinterpret_cast<intptr_t>(addr));
+}
+
+
+// A macro to disallow the evil copy constructor and operator= functions
+// This should be used in the private: declarations for a class
+#define DISALLOW_COPY_AND_ASSIGN(TypeName)      \
+  TypeName(const TypeName&);                    \
+  void operator=(const TypeName&)
+
+
+// A macro to disallow all the implicit constructors, namely the
+// default constructor, copy constructor and operator= functions.
+//
+// This should be used in the private: declarations for a class
+// that wants to prevent anyone from instantiating it. This is
+// especially useful for classes containing only static methods.
+#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
+  TypeName();                                    \
+  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.
+#if defined(__GNUC__) && !defined(DEBUG)
+#if (__GNUC__ >= 4)
+#define INLINE(header) inline header  __attribute__((always_inline))
+#else
+#define INLINE(header) inline __attribute__((always_inline)) header
+#endif
+#else
+#define INLINE(header) inline header
+#endif
+
+// The type-based aliasing rule allows the compiler to assume that pointers of
+// different types (for some definition of different) never alias each other.
+// Thus the following code does not work:
+//
+// float f = foo();
+// int fbits = *(int*)(&f);
+//
+// The compiler 'knows' that the int pointer can't refer to f since the types
+// don't match, so the compiler may cache f in a register, leaving random data
+// in fbits.  Using C++ style casts makes no difference, however a pointer to
+// char data is assumed to alias any other pointer.  This is the 'memcpy
+// exception'.
+//
+// Bit_cast uses the memcpy exception to move the bits from a variable of one
+// type o a variable of another type.  Of course the end result is likely to
+// be implementation dependent.  Most compilers (gcc-4.2 and MSVC 2005)
+// will completely optimize bit_cast away.
+//
+// There is an additional use for bit_cast.
+// Recent gccs will warn when they see casts that may result in breakage due to
+// the type-based aliasing rule.  If you have checked that there is no breakage
+// you can use bit_cast to cast one pointer type to another.  This confuses gcc
+// enough that it can no longer see that you have cast one pointer type to
+// another thus avoiding the warning.
+template <class Dest, class Source>
+inline Dest bit_cast(const Source& source) {
+  // Compile time assertion: sizeof(Dest) == sizeof(Source)
+  // A compile error here means your Dest and Source have different sizes.
+  typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
+
+  Dest dest;
+  memcpy(&dest, &source, sizeof(dest));
+  return dest;
+}
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_GLOBALS_H_
diff --git a/deps/v8/src/handles-inl.h b/deps/v8/src/handles-inl.h
new file mode 100644
index 0000000..e5899e3
--- /dev/null
+++ b/deps/v8/src/handles-inl.h
@@ -0,0 +1,75 @@
+// 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_HANDLES_INL_H_
+#define V8_HANDLES_INL_H_
+
+#include "apiutils.h"
+#include "handles.h"
+#include "api.h"
+
+namespace v8 { namespace internal {
+
+template<class T>
+Handle<T>::Handle(T* obj) {
+  ASSERT(!obj->IsFailure());
+  location_ = reinterpret_cast<T**>(HandleScope::CreateHandle(obj));
+}
+
+
+template <class T>
+inline T* Handle<T>::operator*() const {
+  ASSERT(location_ != NULL);
+  ASSERT(reinterpret_cast<Address>(*location_) != kHandleZapValue);
+  return *location_;
+}
+
+
+#ifdef DEBUG
+inline NoHandleAllocation::NoHandleAllocation() {
+  v8::ImplementationUtilities::HandleScopeData* current =
+      v8::ImplementationUtilities::CurrentHandleScope();
+  extensions_ = current->extensions;
+  // Shrink the current handle scope to make it impossible to do
+  // handle allocations without an explicit handle scope.
+  current->limit = current->next;
+  current->extensions = -1;
+}
+
+
+inline NoHandleAllocation::~NoHandleAllocation() {
+  // Restore state in current handle scope to re-enable handle
+  // allocations.
+  v8::ImplementationUtilities::CurrentHandleScope()->extensions = extensions_;
+}
+#endif
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_HANDLES_INL_H_
diff --git a/deps/v8/src/handles.cc b/deps/v8/src/handles.cc
new file mode 100644
index 0000000..60d8236
--- /dev/null
+++ b/deps/v8/src/handles.cc
@@ -0,0 +1,688 @@
+// 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.
+
+#include "v8.h"
+
+#include "accessors.h"
+#include "api.h"
+#include "bootstrapper.h"
+#include "compiler.h"
+#include "debug.h"
+#include "execution.h"
+#include "global-handles.h"
+#include "natives.h"
+#include "runtime.h"
+
+namespace v8 { namespace internal {
+
+
+v8::ImplementationUtilities::HandleScopeData HandleScope::current_ =
+    { -1, NULL, NULL };
+
+
+int HandleScope::NumberOfHandles() {
+  int n = HandleScopeImplementer::instance()->Blocks()->length();
+  if (n == 0) return 0;
+  return ((n - 1) * kHandleBlockSize) +
+      (current_.next - HandleScopeImplementer::instance()->Blocks()->last());
+}
+
+
+void** HandleScope::Extend() {
+  void** result = current_.next;
+
+  ASSERT(result == current_.limit);
+  // Make sure there's at least one scope on the stack and that the
+  // top of the scope stack isn't a barrier.
+  if (current_.extensions < 0) {
+    Utils::ReportApiFailure("v8::HandleScope::CreateHandle()",
+                            "Cannot create a handle without a HandleScope");
+    return NULL;
+  }
+  HandleScopeImplementer* impl = HandleScopeImplementer::instance();
+  // If there's more room in the last block, we use that. This is used
+  // for fast creation of scopes after scope barriers.
+  if (!impl->Blocks()->is_empty()) {
+    void** limit = &impl->Blocks()->last()[kHandleBlockSize];
+    if (current_.limit != limit) {
+      current_.limit = limit;
+    }
+  }
+
+  // If we still haven't found a slot for the handle, we extend the
+  // current handle scope by allocating a new handle block.
+  if (result == current_.limit) {
+    // If there's a spare block, use it for growing the current scope.
+    result = impl->GetSpareOrNewBlock();
+    // Add the extension to the global list of blocks, but count the
+    // extension as part of the current scope.
+    impl->Blocks()->Add(result);
+    current_.extensions++;
+    current_.limit = &result[kHandleBlockSize];
+  }
+
+  return result;
+}
+
+
+void HandleScope::DeleteExtensions() {
+  ASSERT(current_.extensions != 0);
+  HandleScopeImplementer::instance()->DeleteExtensions(current_.extensions);
+}
+
+
+void HandleScope::ZapRange(void** start, void** end) {
+  if (start == NULL) return;
+  for (void** p = start; p < end; p++) {
+    *p = reinterpret_cast<void*>(v8::internal::kHandleZapValue);
+  }
+}
+
+
+Handle<FixedArray> AddKeysFromJSArray(Handle<FixedArray> content,
+                                      Handle<JSArray> array) {
+  CALL_HEAP_FUNCTION(content->AddKeysFromJSArray(*array), FixedArray);
+}
+
+
+Handle<FixedArray> UnionOfKeys(Handle<FixedArray> first,
+                               Handle<FixedArray> second) {
+  CALL_HEAP_FUNCTION(first->UnionOfKeys(*second), FixedArray);
+}
+
+
+Handle<JSGlobalProxy> ReinitializeJSGlobalProxy(
+    Handle<JSFunction> constructor,
+    Handle<JSGlobalProxy> global) {
+  CALL_HEAP_FUNCTION(Heap::ReinitializeJSGlobalProxy(*constructor, *global),
+                     JSGlobalProxy);
+}
+
+
+void SetExpectedNofProperties(Handle<JSFunction> func, int nof) {
+  func->shared()->set_expected_nof_properties(nof);
+  if (func->has_initial_map()) {
+    Handle<Map> new_initial_map =
+        Factory::CopyMapDropTransitions(Handle<Map>(func->initial_map()));
+    new_initial_map->set_unused_property_fields(nof);
+    func->set_initial_map(*new_initial_map);
+  }
+}
+
+
+void SetPrototypeProperty(Handle<JSFunction> func, Handle<JSObject> value) {
+  CALL_HEAP_FUNCTION_VOID(func->SetPrototype(*value));
+}
+
+
+static int ExpectedNofPropertiesFromEstimate(int estimate) {
+  // TODO(1231235): We need dynamic feedback to estimate the number
+  // of expected properties in an object. The static hack below
+  // is barely a solution.
+  if (estimate == 0) return 4;
+  return estimate + 2;
+}
+
+
+void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared,
+                                          int estimate) {
+  shared->set_expected_nof_properties(
+      ExpectedNofPropertiesFromEstimate(estimate));
+}
+
+
+void SetExpectedNofPropertiesFromEstimate(Handle<JSFunction> func,
+                                          int estimate) {
+  SetExpectedNofProperties(
+      func, ExpectedNofPropertiesFromEstimate(estimate));
+}
+
+
+void NormalizeProperties(Handle<JSObject> object,
+                         PropertyNormalizationMode mode) {
+  CALL_HEAP_FUNCTION_VOID(object->NormalizeProperties(mode));
+}
+
+
+void NormalizeElements(Handle<JSObject> object) {
+  CALL_HEAP_FUNCTION_VOID(object->NormalizeElements());
+}
+
+
+void TransformToFastProperties(Handle<JSObject> object,
+                               int unused_property_fields) {
+  CALL_HEAP_FUNCTION_VOID(
+      object->TransformToFastProperties(unused_property_fields));
+}
+
+
+void FlattenString(Handle<String> string) {
+  CALL_HEAP_FUNCTION_VOID(string->TryFlattenIfNotFlat());
+  ASSERT(string->IsFlat());
+}
+
+
+Handle<Object> SetPrototype(Handle<JSFunction> function,
+                            Handle<Object> prototype) {
+  CALL_HEAP_FUNCTION(Accessors::FunctionSetPrototype(*function,
+                                                     *prototype,
+                                                     NULL),
+                     Object);
+}
+
+
+Handle<Object> SetProperty(Handle<JSObject> object,
+                           Handle<String> key,
+                           Handle<Object> value,
+                           PropertyAttributes attributes) {
+  CALL_HEAP_FUNCTION(object->SetProperty(*key, *value, attributes), Object);
+}
+
+
+Handle<Object> SetProperty(Handle<Object> object,
+                           Handle<Object> key,
+                           Handle<Object> value,
+                           PropertyAttributes attributes) {
+  CALL_HEAP_FUNCTION(
+      Runtime::SetObjectProperty(object, key, value, attributes), Object);
+}
+
+
+Handle<Object> IgnoreAttributesAndSetLocalProperty(Handle<JSObject> object,
+                           Handle<String> key,
+                           Handle<Object> value,
+                           PropertyAttributes attributes) {
+  CALL_HEAP_FUNCTION(object->
+      IgnoreAttributesAndSetLocalProperty(*key, *value, attributes), Object);
+}
+
+Handle<Object> SetPropertyWithInterceptor(Handle<JSObject> object,
+                                          Handle<String> key,
+                                          Handle<Object> value,
+                                          PropertyAttributes attributes) {
+  CALL_HEAP_FUNCTION(object->SetPropertyWithInterceptor(*key,
+                                                        *value,
+                                                        attributes),
+                     Object);
+}
+
+
+Handle<Object> GetProperty(Handle<JSObject> obj,
+                           const char* name) {
+  Handle<String> str = Factory::LookupAsciiSymbol(name);
+  CALL_HEAP_FUNCTION(obj->GetProperty(*str), Object);
+}
+
+
+Handle<Object> GetProperty(Handle<Object> obj,
+                           Handle<Object> key) {
+  CALL_HEAP_FUNCTION(Runtime::GetObjectProperty(obj, key), Object);
+}
+
+
+Handle<Object> GetPropertyWithInterceptor(Handle<JSObject> receiver,
+                                          Handle<JSObject> holder,
+                                          Handle<String> name,
+                                          PropertyAttributes* attributes) {
+  CALL_HEAP_FUNCTION(holder->GetPropertyWithInterceptor(*receiver,
+                                                        *name,
+                                                        attributes),
+                     Object);
+}
+
+
+Handle<Object> GetPrototype(Handle<Object> obj) {
+  Handle<Object> result(obj->GetPrototype());
+  return result;
+}
+
+
+Handle<Object> GetHiddenProperties(Handle<JSObject> obj,
+                                   bool create_if_needed) {
+  CALL_HEAP_FUNCTION(obj->GetHiddenProperties(create_if_needed), Object);
+}
+
+
+Handle<Object> DeleteElement(Handle<JSObject> obj,
+                             uint32_t index) {
+  CALL_HEAP_FUNCTION(obj->DeleteElement(index), Object);
+}
+
+
+Handle<Object> DeleteProperty(Handle<JSObject> obj,
+                              Handle<String> prop) {
+  CALL_HEAP_FUNCTION(obj->DeleteProperty(*prop), Object);
+}
+
+
+Handle<Object> LookupSingleCharacterStringFromCode(uint32_t index) {
+  CALL_HEAP_FUNCTION(Heap::LookupSingleCharacterStringFromCode(index), Object);
+}
+
+
+Handle<String> SubString(Handle<String> str, int start, int end) {
+  CALL_HEAP_FUNCTION(str->Slice(start, end), String);
+}
+
+
+Handle<Object> SetElement(Handle<JSObject> object,
+                          uint32_t index,
+                          Handle<Object> value) {
+  CALL_HEAP_FUNCTION(object->SetElement(index, *value), Object);
+}
+
+
+Handle<JSObject> Copy(Handle<JSObject> obj) {
+  CALL_HEAP_FUNCTION(Heap::CopyJSObject(*obj), JSObject);
+}
+
+
+// Wrappers for scripts are kept alive and cached in weak global
+// handles referred from proxy objects held by the scripts as long as
+// they are used. When they are not used anymore, the garbage
+// collector will call the weak callback on the global handle
+// associated with the wrapper and get rid of both the wrapper and the
+// handle.
+static void ClearWrapperCache(Persistent<v8::Value> handle, void*) {
+#ifdef ENABLE_HEAP_PROTECTION
+  // Weak reference callbacks are called as if from outside V8.  We
+  // need to reeenter to unprotect the heap.
+  VMState state(OTHER);
+#endif
+  Handle<Object> cache = Utils::OpenHandle(*handle);
+  JSValue* wrapper = JSValue::cast(*cache);
+  Proxy* proxy = Script::cast(wrapper->value())->wrapper();
+  ASSERT(proxy->proxy() == reinterpret_cast<Address>(cache.location()));
+  proxy->set_proxy(0);
+  GlobalHandles::Destroy(cache.location());
+  Counters::script_wrappers.Decrement();
+}
+
+
+Handle<JSValue> GetScriptWrapper(Handle<Script> script) {
+  Handle<Object> cache(reinterpret_cast<Object**>(script->wrapper()->proxy()));
+  if (!cache.is_null()) {
+    // Return the script wrapper directly from the cache.
+    return Handle<JSValue>(JSValue::cast(*cache));
+  }
+
+  // Construct a new script wrapper.
+  Counters::script_wrappers.Increment();
+  Handle<JSFunction> constructor = Top::script_function();
+  Handle<JSValue> result =
+      Handle<JSValue>::cast(Factory::NewJSObject(constructor));
+  result->set_value(*script);
+
+  // Create a new weak global handle and use it to cache the wrapper
+  // for future use. The cache will automatically be cleared by the
+  // garbage collector when it is not used anymore.
+  Handle<Object> handle = GlobalHandles::Create(*result);
+  GlobalHandles::MakeWeak(handle.location(), NULL, &ClearWrapperCache);
+  script->wrapper()->set_proxy(reinterpret_cast<Address>(handle.location()));
+  return result;
+}
+
+
+// Init line_ends array with code positions of line ends inside script
+// source.
+void InitScriptLineEnds(Handle<Script> script) {
+  if (!script->line_ends()->IsUndefined()) return;
+
+  if (!script->source()->IsString()) {
+    ASSERT(script->source()->IsUndefined());
+    script->set_line_ends(*(Factory::NewJSArray(0)));
+    ASSERT(script->line_ends()->IsJSArray());
+    return;
+  }
+
+  Handle<String> src(String::cast(script->source()));
+  const int src_len = src->length();
+  Handle<String> new_line = Factory::NewStringFromAscii(CStrVector("\n"));
+
+  // Pass 1: Identify line count.
+  int line_count = 0;
+  int position = 0;
+  while (position != -1 && position < src_len) {
+    position = Runtime::StringMatch(src, new_line, position);
+    if (position != -1) {
+      position++;
+    }
+    // Even if the last line misses a line end, it is counted.
+    line_count++;
+  }
+
+  // Pass 2: Fill in line ends positions
+  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 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(position != -1 ? position++ : src_len));
+  }
+  ASSERT(array_index == line_count);
+
+  Handle<JSArray> object = Factory::NewJSArrayWithElements(array);
+  script->set_line_ends(*object);
+  ASSERT(script->line_ends()->IsJSArray());
+}
+
+
+// Convert code position into line number.
+int GetScriptLineNumber(Handle<Script> script, int code_pos) {
+  InitScriptLineEnds(script);
+  AssertNoAllocation no_allocation;
+  JSArray* line_ends_array = JSArray::cast(script->line_ends());
+  const int line_ends_len = (Smi::cast(line_ends_array->length()))->value();
+
+  int line = -1;
+  if (line_ends_len > 0 &&
+      code_pos <= (Smi::cast(line_ends_array->GetElement(0)))->value()) {
+    line = 0;
+  } else {
+    for (int i = 1; i < line_ends_len; ++i) {
+      if ((Smi::cast(line_ends_array->GetElement(i - 1)))->value() < code_pos &&
+          code_pos <= (Smi::cast(line_ends_array->GetElement(i)))->value()) {
+        line = i;
+        break;
+      }
+    }
+  }
+
+  return line != -1 ? line + script->line_offset()->value() : line;
+}
+
+
+// Compute the property keys from the interceptor.
+v8::Handle<v8::Array> GetKeysForNamedInterceptor(Handle<JSObject> receiver,
+                                                 Handle<JSObject> object) {
+  Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
+  Handle<Object> data(interceptor->data());
+  v8::AccessorInfo info(
+    v8::Utils::ToLocal(receiver),
+    v8::Utils::ToLocal(data),
+    v8::Utils::ToLocal(object));
+  v8::Handle<v8::Array> result;
+  if (!interceptor->enumerator()->IsUndefined()) {
+    v8::NamedPropertyEnumerator enum_fun =
+        v8::ToCData<v8::NamedPropertyEnumerator>(interceptor->enumerator());
+    LOG(ApiObjectAccess("interceptor-named-enum", *object));
+    {
+      // Leaving JavaScript.
+      VMState state(EXTERNAL);
+      result = enum_fun(info);
+    }
+  }
+  return result;
+}
+
+
+// Compute the element keys from the interceptor.
+v8::Handle<v8::Array> GetKeysForIndexedInterceptor(Handle<JSObject> receiver,
+                                                   Handle<JSObject> object) {
+  Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
+  Handle<Object> data(interceptor->data());
+  v8::AccessorInfo info(
+    v8::Utils::ToLocal(receiver),
+    v8::Utils::ToLocal(data),
+    v8::Utils::ToLocal(object));
+  v8::Handle<v8::Array> result;
+  if (!interceptor->enumerator()->IsUndefined()) {
+    v8::IndexedPropertyEnumerator enum_fun =
+        v8::ToCData<v8::IndexedPropertyEnumerator>(interceptor->enumerator());
+    LOG(ApiObjectAccess("interceptor-indexed-enum", *object));
+    {
+      // Leaving JavaScript.
+      VMState state(EXTERNAL);
+      result = enum_fun(info);
+    }
+  }
+  return result;
+}
+
+
+Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object) {
+  Handle<FixedArray> content = Factory::empty_fixed_array();
+
+  JSObject* arguments_boilerplate =
+      Top::context()->global_context()->arguments_boilerplate();
+  JSFunction* arguments_function =
+      JSFunction::cast(arguments_boilerplate->map()->constructor());
+  bool allow_enumeration = (object->map()->constructor() != arguments_function);
+
+  // Only collect keys if access is permitted.
+  if (allow_enumeration) {
+    for (Handle<Object> p = object;
+         *p != Heap::null_value();
+         p = Handle<Object>(p->GetPrototype())) {
+      Handle<JSObject> current(JSObject::cast(*p));
+
+      // Check access rights if required.
+      if (current->IsAccessCheckNeeded() &&
+        !Top::MayNamedAccess(*current, Heap::undefined_value(),
+                             v8::ACCESS_KEYS)) {
+        Top::ReportFailedAccessCheck(*current, v8::ACCESS_KEYS);
+        break;
+      }
+
+      // Compute the property keys.
+      content = UnionOfKeys(content, GetEnumPropertyKeys(current));
+
+      // Add the property keys from the interceptor.
+      if (current->HasNamedInterceptor()) {
+        v8::Handle<v8::Array> result =
+            GetKeysForNamedInterceptor(object, current);
+        if (!result.IsEmpty())
+          content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result));
+      }
+
+      // Compute the element keys.
+      Handle<FixedArray> element_keys =
+          Factory::NewFixedArray(current->NumberOfEnumElements());
+      current->GetEnumElementKeys(*element_keys);
+      content = UnionOfKeys(content, element_keys);
+
+      // Add the element keys from the interceptor.
+      if (current->HasIndexedInterceptor()) {
+        v8::Handle<v8::Array> result =
+            GetKeysForIndexedInterceptor(object, current);
+        if (!result.IsEmpty())
+          content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result));
+      }
+    }
+  }
+  return content;
+}
+
+
+Handle<JSArray> GetKeysFor(Handle<JSObject> object) {
+  Counters::for_in.Increment();
+  Handle<FixedArray> elements = GetKeysInFixedArrayFor(object);
+  return Factory::NewJSArrayWithElements(elements);
+}
+
+
+Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object) {
+  int index = 0;
+  if (object->HasFastProperties()) {
+    if (object->map()->instance_descriptors()->HasEnumCache()) {
+      Counters::enum_cache_hits.Increment();
+      DescriptorArray* desc = object->map()->instance_descriptors();
+      return Handle<FixedArray>(FixedArray::cast(desc->GetEnumCache()));
+    }
+    Counters::enum_cache_misses.Increment();
+    int num_enum = object->NumberOfEnumProperties();
+    Handle<FixedArray> storage = Factory::NewFixedArray(num_enum);
+    Handle<FixedArray> sort_array = Factory::NewFixedArray(num_enum);
+    for (DescriptorReader r(object->map()->instance_descriptors());
+         !r.eos();
+         r.advance()) {
+      if (r.IsProperty() && !r.IsDontEnum()) {
+        (*storage)->set(index, r.GetKey());
+        (*sort_array)->set(index, Smi::FromInt(r.GetDetails().index()));
+        index++;
+      }
+    }
+    (*storage)->SortPairs(*sort_array);
+    Handle<FixedArray> bridge_storage =
+        Factory::NewFixedArray(DescriptorArray::kEnumCacheBridgeLength);
+    DescriptorArray* desc = object->map()->instance_descriptors();
+    desc->SetEnumCache(*bridge_storage, *storage);
+    ASSERT(storage->length() == index);
+    return storage;
+  } else {
+    int num_enum = object->NumberOfEnumProperties();
+    Handle<FixedArray> storage = Factory::NewFixedArray(num_enum);
+    Handle<FixedArray> sort_array = Factory::NewFixedArray(num_enum);
+    object->property_dictionary()->CopyEnumKeysTo(*storage, *sort_array);
+    return storage;
+  }
+}
+
+
+bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
+                       ClearExceptionFlag flag,
+                       int loop_nesting) {
+  // Compile the source information to a code object.
+  ASSERT(!shared->is_compiled());
+  bool result = Compiler::CompileLazy(shared, loop_nesting);
+  ASSERT(result != Top::has_pending_exception());
+  if (!result && flag == CLEAR_EXCEPTION) Top::clear_pending_exception();
+  return result;
+}
+
+
+bool CompileLazy(Handle<JSFunction> function, ClearExceptionFlag flag) {
+  // Compile the source information to a code object.
+  Handle<SharedFunctionInfo> shared(function->shared());
+  return CompileLazyShared(shared, flag, 0);
+}
+
+
+bool CompileLazyInLoop(Handle<JSFunction> function, ClearExceptionFlag flag) {
+  // Compile the source information to a code object.
+  Handle<SharedFunctionInfo> shared(function->shared());
+  return CompileLazyShared(shared, flag, 1);
+}
+
+OptimizedObjectForAddingMultipleProperties::
+OptimizedObjectForAddingMultipleProperties(Handle<JSObject> object,
+                                           bool condition) {
+  object_ = object;
+  if (condition && object_->HasFastProperties()) {
+    // Normalize the properties of object to avoid n^2 behavior
+    // when extending the object multiple properties.
+    unused_property_fields_ = object->map()->unused_property_fields();
+    NormalizeProperties(object_, KEEP_INOBJECT_PROPERTIES);
+    has_been_transformed_ = true;
+
+  } else {
+    has_been_transformed_ = false;
+  }
+}
+
+
+OptimizedObjectForAddingMultipleProperties::
+~OptimizedObjectForAddingMultipleProperties() {
+  // Reoptimize the object to allow fast property access.
+  if (has_been_transformed_) {
+    TransformToFastProperties(object_, unused_property_fields_);
+  }
+}
+
+
+void LoadLazy(Handle<JSFunction> fun, bool* pending_exception) {
+  HandleScope scope;
+  Handle<FixedArray> info(FixedArray::cast(fun->shared()->lazy_load_data()));
+  int index = Smi::cast(info->get(0))->value();
+  ASSERT(index >= 0);
+  Handle<Context> compile_context(Context::cast(info->get(1)));
+  Handle<Context> function_context(Context::cast(info->get(2)));
+  Handle<Object> receiver(compile_context->global()->builtins());
+
+  Vector<const char> name = Natives::GetScriptName(index);
+
+  Handle<JSFunction> boilerplate;
+
+  if (!Bootstrapper::NativesCacheLookup(name, &boilerplate)) {
+    Handle<String> source_code = Bootstrapper::NativesSourceLookup(index);
+    Handle<String> script_name = Factory::NewStringFromAscii(name);
+    bool allow_natives_syntax = FLAG_allow_natives_syntax;
+    FLAG_allow_natives_syntax = true;
+    boilerplate = Compiler::Compile(source_code, script_name, 0, 0, NULL, NULL);
+    FLAG_allow_natives_syntax = allow_natives_syntax;
+    // If the compilation failed (possibly due to stack overflows), we
+    // should never enter the result in the natives cache. Instead we
+    // return from the function without marking the function as having
+    // been lazily loaded.
+    if (boilerplate.is_null()) {
+      *pending_exception = true;
+      return;
+    }
+    Bootstrapper::NativesCacheAdd(name, boilerplate);
+  }
+
+  // We shouldn't get here if compiling the script failed.
+  ASSERT(!boilerplate.is_null());
+
+  // When the debugger running in its own context touches lazy loaded
+  // functions loading can be triggered. In that case ensure that the
+  // execution of the boilerplate is in the correct context.
+  SaveContext save;
+  if (!Debug::debug_context().is_null() &&
+      Top::context() == *Debug::debug_context()) {
+    Top::set_context(*compile_context);
+  }
+
+  // Reset the lazy load data before running the script to make sure
+  // not to get recursive lazy loading.
+  fun->shared()->set_lazy_load_data(Heap::undefined_value());
+
+  // Run the script.
+  Handle<JSFunction> script_fun(
+      Factory::NewFunctionFromBoilerplate(boilerplate, function_context));
+  Execution::Call(script_fun, receiver, 0, NULL, pending_exception);
+
+  // If lazy loading failed, restore the unloaded state of fun.
+  if (*pending_exception) fun->shared()->set_lazy_load_data(*info);
+}
+
+
+void SetupLazy(Handle<JSFunction> fun,
+               int index,
+               Handle<Context> compile_context,
+               Handle<Context> function_context) {
+  Handle<FixedArray> arr = Factory::NewFixedArray(3);
+  arr->set(0, Smi::FromInt(index));
+  arr->set(1, *compile_context);  // Compile in this context
+  arr->set(2, *function_context);  // Set function context to this
+  fun->shared()->set_lazy_load_data(*arr);
+}
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/handles.h b/deps/v8/src/handles.h
new file mode 100644
index 0000000..c8e534e
--- /dev/null
+++ b/deps/v8/src/handles.h
@@ -0,0 +1,338 @@
+// 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_HANDLES_H_
+#define V8_HANDLES_H_
+
+#include "apiutils.h"
+
+namespace v8 { namespace internal {
+
+// ----------------------------------------------------------------------------
+// A Handle provides a reference to an object that survives relocation by
+// the garbage collector.
+// Handles are only valid within a HandleScope.
+// When a handle is created for an object a cell is allocated in the heap.
+
+template<class T>
+class Handle {
+ public:
+  INLINE(Handle(T** location))  { location_ = location; }
+  INLINE(explicit Handle(T* obj));
+
+  INLINE(Handle()) : location_(NULL) {}
+
+  // Constructor for handling automatic up casting.
+  // Ex. Handle<JSFunction> can be passed when Handle<Object> is expected.
+  template <class S> Handle(Handle<S> handle) {
+#ifdef DEBUG
+    T* a = NULL;
+    S* b = NULL;
+    a = b;  // Fake assignment to enforce type checks.
+    USE(a);
+#endif
+    location_ = reinterpret_cast<T**>(handle.location());
+  }
+
+  INLINE(T* operator ->() const)  { return operator*(); }
+
+  // Check if this handle refers to the exact same object as the other handle.
+  bool is_identical_to(const Handle<T> other) const {
+    return operator*() == *other;
+  }
+
+  // Provides the C++ dereference operator.
+  INLINE(T* operator*() const);
+
+  // Returns the address to where the raw pointer is stored.
+  T** location() const {
+    ASSERT(location_ == NULL ||
+           reinterpret_cast<Address>(*location_) != kZapValue);
+    return location_;
+  }
+
+  template <class S> static Handle<T> cast(Handle<S> that) {
+    T::cast(*that);
+    return Handle<T>(reinterpret_cast<T**>(that.location()));
+  }
+
+  static Handle<T> null() { return Handle<T>(); }
+  bool is_null() {return location_ == NULL; }
+
+  // Closes the given scope, but lets this handle escape. See
+  // implementation in api.h.
+  inline Handle<T> EscapeFrom(v8::HandleScope* scope);
+
+ private:
+  T** location_;
+};
+
+
+// A stack-allocated class that governs a number of local handles.
+// After a handle scope has been created, all local handles will be
+// allocated within that handle scope until either the handle scope is
+// deleted or another handle scope is created.  If there is already a
+// handle scope and a new one is created, all allocations will take
+// place in the new handle scope until it is deleted.  After that,
+// new handles will again be allocated in the original handle scope.
+//
+// After the handle scope of a local handle has been deleted the
+// garbage collector will no longer track the object stored in the
+// handle and may deallocate it.  The behavior of accessing a handle
+// for which the handle scope has been deleted is undefined.
+class HandleScope {
+ public:
+  HandleScope() : previous_(current_) {
+    current_.extensions = 0;
+  }
+
+  ~HandleScope() {
+    Leave(&previous_);
+  }
+
+  // Counts the number of allocated handles.
+  static int NumberOfHandles();
+
+  // Creates a new handle with the given value.
+  static inline void** CreateHandle(void* value) {
+    void** result = current_.next;
+    if (result == current_.limit) result = Extend();
+    // Update the current next field, set the value in the created
+    // handle, and return the result.
+    ASSERT(result < current_.limit);
+    current_.next = result + 1;
+    *result = value;
+    return result;
+  }
+
+ private:
+  // Prevent heap allocation or illegal handle scopes.
+  HandleScope(const HandleScope&);
+  void operator=(const HandleScope&);
+  void* operator new(size_t size);
+  void operator delete(void* size_t);
+
+  static v8::ImplementationUtilities::HandleScopeData current_;
+  const v8::ImplementationUtilities::HandleScopeData previous_;
+
+  // Pushes a fresh handle scope to be used when allocating new handles.
+  static void Enter(
+      v8::ImplementationUtilities::HandleScopeData* previous) {
+    *previous = current_;
+    current_.extensions = 0;
+  }
+
+  // Re-establishes the previous scope state. Should be called only
+  // once, and only for the current scope.
+  static void Leave(
+      const v8::ImplementationUtilities::HandleScopeData* previous) {
+    if (current_.extensions > 0) {
+      DeleteExtensions();
+    }
+    current_ = *previous;
+#ifdef DEBUG
+    ZapRange(current_.next, current_.limit);
+#endif
+  }
+
+  // Extend the handle scope making room for more handles.
+  static void** Extend();
+
+  // Deallocates any extensions used by the current scope.
+  static void DeleteExtensions();
+
+  // Zaps the handles in the half-open interval [start, end).
+  static void ZapRange(void** start, void** end);
+
+  friend class v8::HandleScope;
+  friend class v8::ImplementationUtilities;
+};
+
+
+// ----------------------------------------------------------------------------
+// Handle operations.
+// They might invoke garbage collection. The result is an handle to
+// an object of expected type, or the handle is an error if running out
+// of space or encountering an internal error.
+
+void NormalizeProperties(Handle<JSObject> object,
+                         PropertyNormalizationMode mode);
+void NormalizeElements(Handle<JSObject> object);
+void TransformToFastProperties(Handle<JSObject> object,
+                               int unused_property_fields);
+void FlattenString(Handle<String> str);
+
+Handle<Object> SetProperty(Handle<JSObject> object,
+                           Handle<String> key,
+                           Handle<Object> value,
+                           PropertyAttributes attributes);
+
+Handle<Object> SetProperty(Handle<Object> object,
+                           Handle<Object> key,
+                           Handle<Object> value,
+                           PropertyAttributes attributes);
+
+Handle<Object> IgnoreAttributesAndSetLocalProperty(Handle<JSObject> object,
+                                                   Handle<String> key,
+                                                   Handle<Object> value,
+    PropertyAttributes attributes);
+
+Handle<Object> SetPropertyWithInterceptor(Handle<JSObject> object,
+                                          Handle<String> key,
+                                          Handle<Object> value,
+                                          PropertyAttributes attributes);
+
+Handle<Object> SetElement(Handle<JSObject> object,
+                          uint32_t index,
+                          Handle<Object> value);
+
+Handle<Object> GetProperty(Handle<JSObject> obj,
+                           const char* name);
+
+Handle<Object> GetProperty(Handle<Object> obj,
+                           Handle<Object> key);
+
+Handle<Object> GetPropertyWithInterceptor(Handle<JSObject> receiver,
+                                          Handle<JSObject> holder,
+                                          Handle<String> name,
+                                          PropertyAttributes* attributes);
+
+Handle<Object> GetPrototype(Handle<Object> obj);
+
+Handle<Object> GetHiddenProperties(Handle<JSObject> obj, bool create_if_needed);
+
+Handle<Object> DeleteElement(Handle<JSObject> obj, uint32_t index);
+Handle<Object> DeleteProperty(Handle<JSObject> obj, Handle<String> prop);
+
+Handle<Object> LookupSingleCharacterStringFromCode(uint32_t index);
+
+Handle<JSObject> Copy(Handle<JSObject> obj);
+
+Handle<FixedArray> AddKeysFromJSArray(Handle<FixedArray>,
+                                      Handle<JSArray> array);
+
+// Get the JS object corresponding to the given script; create it
+// if none exists.
+Handle<JSValue> GetScriptWrapper(Handle<Script> script);
+
+// Script line number computations.
+void InitScriptLineEnds(Handle<Script> script);
+int GetScriptLineNumber(Handle<Script> script, int code_position);
+
+// Computes the enumerable keys from interceptors. Used for debug mirrors and
+// by GetKeysInFixedArrayFor below.
+v8::Handle<v8::Array> GetKeysForNamedInterceptor(Handle<JSObject> receiver,
+                                                 Handle<JSObject> object);
+v8::Handle<v8::Array> GetKeysForIndexedInterceptor(Handle<JSObject> receiver,
+                                                   Handle<JSObject> object);
+// Computes the enumerable keys for a JSObject. Used for implementing
+// "for (n in object) { }".
+Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object);
+Handle<JSArray> GetKeysFor(Handle<JSObject> object);
+Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object);
+
+// Computes the union of keys and return the result.
+// Used for implementing "for (n in object) { }"
+Handle<FixedArray> UnionOfKeys(Handle<FixedArray> first,
+                               Handle<FixedArray> second);
+
+Handle<String> SubString(Handle<String> str, int start, int end);
+
+
+// Sets the expected number of properties for the function's instances.
+void SetExpectedNofProperties(Handle<JSFunction> func, int nof);
+
+// Sets the prototype property for a function instance.
+void SetPrototypeProperty(Handle<JSFunction> func, Handle<JSObject> value);
+
+// Sets the expected number of properties based on estimate from compiler.
+void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared,
+                                          int estimate);
+void SetExpectedNofPropertiesFromEstimate(Handle<JSFunction> func,
+                                          int estimate);
+
+
+Handle<JSGlobalProxy> ReinitializeJSGlobalProxy(
+    Handle<JSFunction> constructor,
+    Handle<JSGlobalProxy> global);
+
+Handle<Object> SetPrototype(Handle<JSFunction> function,
+                            Handle<Object> prototype);
+
+
+// Do lazy compilation of the given function. Returns true on success
+// and false if the compilation resulted in a stack overflow.
+enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION };
+
+bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
+                       ClearExceptionFlag flag,
+                       int loop_nesting);
+
+bool CompileLazy(Handle<JSFunction> function, ClearExceptionFlag flag);
+bool CompileLazyInLoop(Handle<JSFunction> function, ClearExceptionFlag flag);
+
+// These deal with lazily loaded properties.
+void SetupLazy(Handle<JSFunction> fun,
+               int index,
+               Handle<Context> compile_context,
+               Handle<Context> function_context);
+void LoadLazy(Handle<JSFunction> fun, bool* pending_exception);
+
+class NoHandleAllocation BASE_EMBEDDED {
+ public:
+#ifndef DEBUG
+  NoHandleAllocation() {}
+  ~NoHandleAllocation() {}
+#else
+  inline NoHandleAllocation();
+  inline ~NoHandleAllocation();
+ private:
+  int extensions_;
+#endif
+};
+
+
+// ----------------------------------------------------------------------------
+
+
+// Stack allocated wrapper call for optimizing adding multiple
+// properties to an object.
+class OptimizedObjectForAddingMultipleProperties BASE_EMBEDDED {
+ public:
+  OptimizedObjectForAddingMultipleProperties(Handle<JSObject> object,
+                                             bool condition = true);
+  ~OptimizedObjectForAddingMultipleProperties();
+ private:
+  bool has_been_transformed_;  // Tells whether the object has been transformed.
+  int unused_property_fields_;  // Captures the unused number of field.
+  Handle<JSObject> object_;    // The object being optimized.
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_HANDLES_H_
diff --git a/deps/v8/src/hashmap.cc b/deps/v8/src/hashmap.cc
new file mode 100644
index 0000000..126f739
--- /dev/null
+++ b/deps/v8/src/hashmap.cc
@@ -0,0 +1,170 @@
+// Copyright 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.
+
+#include "v8.h"
+
+#include "hashmap.h"
+
+namespace v8 { namespace internal {
+
+
+static inline bool IsPowerOf2(uint32_t x) {
+  ASSERT(x != 0);
+  return (x & (x - 1)) == 0;
+}
+
+
+Allocator HashMap::DefaultAllocator;
+
+
+HashMap::HashMap() {
+  allocator_ = NULL;
+  match_ = NULL;
+}
+
+
+HashMap::HashMap(MatchFun match,
+                 Allocator* allocator,
+                 uint32_t initial_capacity) {
+  allocator_ = allocator;
+  match_ = match;
+  Initialize(initial_capacity);
+}
+
+
+HashMap::~HashMap() {
+  if (allocator_) {
+    allocator_->Delete(map_);
+  }
+}
+
+
+HashMap::Entry* HashMap::Lookup(void* key, uint32_t hash, bool insert) {
+  // Find a matching entry.
+  Entry* p = Probe(key, hash);
+    if (p->key != NULL) {
+    return p;
+  }
+
+  // No entry found; insert one if necessary.
+  if (insert) {
+    p->key = key;
+    p->value = NULL;
+    p->hash = hash;
+    occupancy_++;
+
+    // Grow the map if we reached >= 80% occupancy.
+    if (occupancy_ + occupancy_/4 >= capacity_) {
+      Resize();
+      p = Probe(key, hash);
+    }
+
+    return p;
+  }
+
+  // No entry found and none inserted.
+  return NULL;
+}
+
+
+void HashMap::Clear() {
+  // Mark all entries as empty.
+  const Entry* end = map_end();
+  for (Entry* p = map_; p < end; p++) {
+    p->key = NULL;
+  }
+  occupancy_ = 0;
+}
+
+
+HashMap::Entry* HashMap::Start() const {
+  return Next(map_ - 1);
+}
+
+
+HashMap::Entry* HashMap::Next(Entry* p) const {
+  const Entry* end = map_end();
+  ASSERT(map_ - 1 <= p && p < end);
+  for (p++; p < end; p++) {
+    if (p->key != NULL) {
+      return p;
+    }
+  }
+  return NULL;
+}
+
+
+HashMap::Entry* HashMap::Probe(void* key, uint32_t hash) {
+  ASSERT(key != NULL);
+
+  ASSERT(IsPowerOf2(capacity_));
+  Entry* p = map_ + (hash & (capacity_ - 1));
+  const Entry* end = map_end();
+  ASSERT(map_ <= p && p < end);
+
+  ASSERT(occupancy_ < capacity_);  // guarantees loop termination
+  while (p->key != NULL && (hash != p->hash || !match_(key, p->key))) {
+    p++;
+    if (p >= end) {
+      p = map_;
+    }
+  }
+
+  return p;
+}
+
+
+void HashMap::Initialize(uint32_t capacity) {
+  ASSERT(IsPowerOf2(capacity));
+  map_ = reinterpret_cast<Entry*>(allocator_->New(capacity * sizeof(Entry)));
+  if (map_ == NULL) V8::FatalProcessOutOfMemory("HashMap::Initialize");
+  capacity_ = capacity;
+  Clear();
+}
+
+
+void HashMap::Resize() {
+  Entry* map = map_;
+  uint32_t n = occupancy_;
+
+  // Allocate larger map.
+  Initialize(capacity_ * 2);
+
+  // Rehash all current entries.
+  for (Entry* p = map; n > 0; p++) {
+    if (p->key != NULL) {
+      Lookup(p->key, p->hash, true)->value = p->value;
+      n--;
+    }
+  }
+
+  // Delete old map.
+  allocator_->Delete(map);
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/hashmap.h b/deps/v8/src/hashmap.h
new file mode 100644
index 0000000..fabf3dc
--- /dev/null
+++ b/deps/v8/src/hashmap.h
@@ -0,0 +1,116 @@
+// Copyright 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_HASHMAP_H_
+#define V8_HASHMAP_H_
+
+namespace v8 { namespace internal {
+
+
+// Allocator defines the memory allocator interface
+// used by HashMap and implements a default allocator.
+class Allocator BASE_EMBEDDED {
+ public:
+  virtual ~Allocator()  {}
+  virtual void* New(size_t size)  { return Malloced::New(size); }
+  virtual void Delete(void* p)  { Malloced::Delete(p); }
+};
+
+
+class HashMap {
+ public:
+  static Allocator DefaultAllocator;
+
+  typedef bool (*MatchFun) (void* key1, void* key2);
+
+  // Dummy constructor.  This constructor doesn't set up the hash
+  // map properly so don't use it unless you have good reason.
+  HashMap();
+
+  // initial_capacity is the size of the initial hash map;
+  // it must be a power of 2 (and thus must not be 0).
+  HashMap(MatchFun match,
+          Allocator* allocator = &DefaultAllocator,
+          uint32_t initial_capacity = 8);
+
+  ~HashMap();
+
+  // HashMap entries are (key, value, hash) triplets.
+  // Some clients may not need to use the value slot
+  // (e.g. implementers of sets, where the key is the value).
+  struct Entry {
+    void* key;
+    void* value;
+    uint32_t hash;  // the full hash value for key
+  };
+
+  // If an entry with matching key is found, Lookup()
+  // returns that entry. If no matching entry is found,
+  // but insert is set, a new entry is inserted with
+  // corresponding key, key hash, and NULL value.
+  // Otherwise, NULL is returned.
+  Entry* Lookup(void* key, uint32_t hash, bool insert);
+
+  // Empties the hash map (occupancy() == 0).
+  void Clear();
+
+  // The number of (non-empty) entries in the table.
+  uint32_t occupancy() const  { return occupancy_; }
+
+  // The capacity of the table. The implementation
+  // makes sure that occupancy is at most 80% of
+  // the table capacity.
+  uint32_t capacity() const  { return capacity_; }
+
+  // Iteration
+  //
+  // for (Entry* p = map.Start(); p != NULL; p = map.Next(p)) {
+  //   ...
+  // }
+  //
+  // If entries are inserted during iteration, the effect of
+  // calling Next() is undefined.
+  Entry* Start() const;
+  Entry* Next(Entry* p) const;
+
+ private:
+  Allocator* allocator_;
+  MatchFun match_;
+  Entry* map_;
+  uint32_t capacity_;
+  uint32_t occupancy_;
+
+  Entry* map_end() const  { return map_ + capacity_; }
+  Entry* Probe(void* key, uint32_t hash);
+  void Initialize(uint32_t capacity);
+  void Resize();
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_HASHMAP_H_
diff --git a/deps/v8/src/heap-inl.h b/deps/v8/src/heap-inl.h
new file mode 100644
index 0000000..6090dd4
--- /dev/null
+++ b/deps/v8/src/heap-inl.h
@@ -0,0 +1,286 @@
+// 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_HEAP_INL_H_
+#define V8_HEAP_INL_H_
+
+#include "log.h"
+#include "v8-counters.h"
+
+namespace v8 { namespace internal {
+
+int Heap::MaxHeapObjectSize() {
+  return Page::kMaxHeapObjectSize;
+}
+
+
+Object* Heap::AllocateSymbol(Vector<const char> str,
+                             int chars,
+                             uint32_t length_field) {
+  unibrow::Utf8InputBuffer<> buffer(str.start(),
+                                    static_cast<unsigned>(str.length()));
+  return AllocateInternalSymbol(&buffer, chars, length_field);
+}
+
+
+Object* Heap::AllocateRaw(int size_in_bytes,
+                          AllocationSpace space,
+                          AllocationSpace retry_space) {
+  ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC);
+  ASSERT(space != NEW_SPACE ||
+         retry_space == OLD_POINTER_SPACE ||
+         retry_space == OLD_DATA_SPACE);
+#ifdef DEBUG
+  if (FLAG_gc_interval >= 0 &&
+      !disallow_allocation_failure_ &&
+      Heap::allocation_timeout_-- <= 0) {
+    return Failure::RetryAfterGC(size_in_bytes, space);
+  }
+  Counters::objs_since_last_full.Increment();
+  Counters::objs_since_last_young.Increment();
+#endif
+  Object* result;
+  if (NEW_SPACE == space) {
+    result = new_space_.AllocateRaw(size_in_bytes);
+    if (always_allocate() && result->IsFailure()) {
+      space = retry_space;
+    } else {
+      return result;
+    }
+  }
+
+  if (OLD_POINTER_SPACE == space) {
+    result = old_pointer_space_->AllocateRaw(size_in_bytes);
+  } else if (OLD_DATA_SPACE == space) {
+    result = old_data_space_->AllocateRaw(size_in_bytes);
+  } else if (CODE_SPACE == space) {
+    result = code_space_->AllocateRaw(size_in_bytes);
+  } else if (LO_SPACE == space) {
+    result = lo_space_->AllocateRaw(size_in_bytes);
+  } else {
+    ASSERT(MAP_SPACE == space);
+    result = map_space_->AllocateRaw(size_in_bytes);
+  }
+  if (result->IsFailure()) old_gen_exhausted_ = true;
+  return result;
+}
+
+
+Object* Heap::NumberFromInt32(int32_t value) {
+  if (Smi::IsValid(value)) return Smi::FromInt(value);
+  // Bypass NumberFromDouble to avoid various redundant checks.
+  return AllocateHeapNumber(FastI2D(value));
+}
+
+
+Object* Heap::NumberFromUint32(uint32_t value) {
+  if ((int32_t)value >= 0 && Smi::IsValid((int32_t)value)) {
+    return Smi::FromInt((int32_t)value);
+  }
+  // Bypass NumberFromDouble to avoid various redundant checks.
+  return AllocateHeapNumber(FastUI2D(value));
+}
+
+
+Object* Heap::AllocateRawMap(int size_in_bytes) {
+#ifdef DEBUG
+  Counters::objs_since_last_full.Increment();
+  Counters::objs_since_last_young.Increment();
+#endif
+  Object* result = map_space_->AllocateRaw(size_in_bytes);
+  if (result->IsFailure()) old_gen_exhausted_ = true;
+  return result;
+}
+
+
+bool Heap::InNewSpace(Object* object) {
+  return new_space_.Contains(object);
+}
+
+
+bool Heap::InFromSpace(Object* object) {
+  return new_space_.FromSpaceContains(object);
+}
+
+
+bool Heap::InToSpace(Object* object) {
+  return new_space_.ToSpaceContains(object);
+}
+
+
+bool Heap::ShouldBePromoted(Address old_address, int object_size) {
+  // An object should be promoted if:
+  // - the object has survived a scavenge operation or
+  // - to space is already 25% full.
+  return old_address < new_space_.age_mark()
+      || (new_space_.Size() + object_size) >= (new_space_.Capacity() >> 2);
+}
+
+
+void Heap::RecordWrite(Address address, int offset) {
+  if (new_space_.Contains(address)) return;
+  ASSERT(!new_space_.FromSpaceContains(address));
+  SLOW_ASSERT(Contains(address + offset));
+  Page::SetRSet(address, offset);
+}
+
+
+OldSpace* Heap::TargetSpace(HeapObject* object) {
+  InstanceType type = object->map()->instance_type();
+  AllocationSpace space = TargetSpaceId(type);
+  return (space == OLD_POINTER_SPACE)
+      ? old_pointer_space_
+      : old_data_space_;
+}
+
+
+AllocationSpace Heap::TargetSpaceId(InstanceType type) {
+  // Heap numbers and sequential strings are promoted to old data space, all
+  // other object types are promoted to old pointer space.  We do not use
+  // object->IsHeapNumber() and object->IsSeqString() because we already
+  // know that object has the heap object tag.
+  ASSERT((type != CODE_TYPE) && (type != MAP_TYPE));
+  bool has_pointers =
+      type != HEAP_NUMBER_TYPE &&
+      (type >= FIRST_NONSTRING_TYPE ||
+       (type & kStringRepresentationMask) != kSeqStringTag);
+  return has_pointers ? OLD_POINTER_SPACE : OLD_DATA_SPACE;
+}
+
+
+void Heap::CopyBlock(Object** dst, Object** src, int byte_size) {
+  ASSERT(IsAligned(byte_size, kPointerSize));
+
+  // Use block copying memcpy if the segment we're copying is
+  // enough to justify the extra call/setup overhead.
+  static const int kBlockCopyLimit = 16 * kPointerSize;
+
+  if (byte_size >= kBlockCopyLimit) {
+    memcpy(dst, src, byte_size);
+  } else {
+    int remaining = byte_size / kPointerSize;
+    do {
+      remaining--;
+      *dst++ = *src++;
+    } while (remaining > 0);
+  }
+}
+
+
+Object* Heap::GetKeyedLookupCache() {
+  if (keyed_lookup_cache()->IsUndefined()) {
+    Object* obj = LookupCache::Allocate(4);
+    if (obj->IsFailure()) return obj;
+    keyed_lookup_cache_ = obj;
+  }
+  return keyed_lookup_cache();
+}
+
+
+void Heap::SetKeyedLookupCache(LookupCache* cache) {
+  keyed_lookup_cache_ = cache;
+}
+
+
+void Heap::ClearKeyedLookupCache() {
+  keyed_lookup_cache_ = undefined_value();
+}
+
+
+void Heap::SetLastScriptId(Object* last_script_id) {
+  last_script_id_ = last_script_id;
+}
+
+
+#define GC_GREEDY_CHECK() \
+  ASSERT(!FLAG_gc_greedy || v8::internal::Heap::GarbageCollectionGreedyCheck())
+
+
+// Calls the FUNCTION_CALL function and retries it up to three times
+// to guarantee that any allocations performed during the call will
+// succeed if there's enough memory.
+
+// Warning: Do not use the identifiers __object__ or __scope__ in a
+// call to this macro.
+
+#define CALL_AND_RETRY(FUNCTION_CALL, RETURN_VALUE, RETURN_EMPTY)         \
+  do {                                                                    \
+    GC_GREEDY_CHECK();                                                    \
+    Object* __object__ = FUNCTION_CALL;                                   \
+    if (!__object__->IsFailure()) RETURN_VALUE;                           \
+    if (__object__->IsOutOfMemoryFailure()) {                             \
+      v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_0");      \
+    }                                                                     \
+    if (!__object__->IsRetryAfterGC()) RETURN_EMPTY;                      \
+    Heap::CollectGarbage(Failure::cast(__object__)->requested(),          \
+                         Failure::cast(__object__)->allocation_space());  \
+    __object__ = FUNCTION_CALL;                                           \
+    if (!__object__->IsFailure()) RETURN_VALUE;                           \
+    if (__object__->IsOutOfMemoryFailure()) {                             \
+      v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_1");      \
+    }                                                                     \
+    if (!__object__->IsRetryAfterGC()) RETURN_EMPTY;                      \
+    Counters::gc_last_resort_from_handles.Increment();                    \
+    Heap::CollectAllGarbage();                                            \
+    {                                                                     \
+      AlwaysAllocateScope __scope__;                                      \
+      __object__ = FUNCTION_CALL;                                         \
+    }                                                                     \
+    if (!__object__->IsFailure()) RETURN_VALUE;                           \
+    if (__object__->IsOutOfMemoryFailure()) {                             \
+      /* TODO(1181417): Fix this. */                                      \
+      v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_2");      \
+    }                                                                     \
+    ASSERT(!__object__->IsRetryAfterGC());                                \
+    RETURN_EMPTY;                                                         \
+  } while (false)
+
+
+#define CALL_HEAP_FUNCTION(FUNCTION_CALL, TYPE)                \
+  CALL_AND_RETRY(FUNCTION_CALL,                                \
+                 return Handle<TYPE>(TYPE::cast(__object__)),  \
+                 return Handle<TYPE>())
+
+
+#define CALL_HEAP_FUNCTION_VOID(FUNCTION_CALL) \
+  CALL_AND_RETRY(FUNCTION_CALL, return, return)
+
+
+#ifdef DEBUG
+
+inline bool Heap::allow_allocation(bool new_state) {
+  bool old = allocation_allowed_;
+  allocation_allowed_ = new_state;
+  return old;
+}
+
+#endif
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_HEAP_INL_H_
diff --git a/deps/v8/src/heap.cc b/deps/v8/src/heap.cc
new file mode 100644
index 0000000..7a8b728
--- /dev/null
+++ b/deps/v8/src/heap.cc
@@ -0,0 +1,3393 @@
+// 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.
+
+#include "v8.h"
+
+#include "accessors.h"
+#include "api.h"
+#include "bootstrapper.h"
+#include "codegen-inl.h"
+#include "compilation-cache.h"
+#include "debug.h"
+#include "global-handles.h"
+#include "mark-compact.h"
+#include "natives.h"
+#include "scanner.h"
+#include "scopeinfo.h"
+#include "v8threads.h"
+
+namespace v8 { namespace internal {
+
+#define ROOT_ALLOCATION(type, name) type* Heap::name##_;
+  ROOT_LIST(ROOT_ALLOCATION)
+#undef ROOT_ALLOCATION
+
+
+#define STRUCT_ALLOCATION(NAME, Name, name) Map* Heap::name##_map_;
+  STRUCT_LIST(STRUCT_ALLOCATION)
+#undef STRUCT_ALLOCATION
+
+
+#define SYMBOL_ALLOCATION(name, string) String* Heap::name##_;
+  SYMBOL_LIST(SYMBOL_ALLOCATION)
+#undef SYMBOL_ALLOCATION
+
+String* Heap::hidden_symbol_;
+
+NewSpace Heap::new_space_;
+OldSpace* Heap::old_pointer_space_ = NULL;
+OldSpace* Heap::old_data_space_ = NULL;
+OldSpace* Heap::code_space_ = NULL;
+MapSpace* Heap::map_space_ = NULL;
+LargeObjectSpace* Heap::lo_space_ = NULL;
+
+static const int kMinimumPromotionLimit = 2*MB;
+static const int kMinimumAllocationLimit = 8*MB;
+
+int Heap::old_gen_promotion_limit_ = kMinimumPromotionLimit;
+int Heap::old_gen_allocation_limit_ = kMinimumAllocationLimit;
+
+int Heap::old_gen_exhausted_ = false;
+
+int Heap::amount_of_external_allocated_memory_ = 0;
+int Heap::amount_of_external_allocated_memory_at_last_global_gc_ = 0;
+
+// semispace_size_ should be a power of 2 and old_generation_size_ should be
+// a multiple of Page::kPageSize.
+int Heap::semispace_size_  = 2*MB;
+int Heap::old_generation_size_ = 512*MB;
+int Heap::initial_semispace_size_ = 256*KB;
+
+GCCallback Heap::global_gc_prologue_callback_ = NULL;
+GCCallback Heap::global_gc_epilogue_callback_ = NULL;
+
+// Variables set based on semispace_size_ and old_generation_size_ in
+// ConfigureHeap.
+int Heap::young_generation_size_ = 0;  // Will be 2 * semispace_size_.
+
+// Double the new space after this many scavenge collections.
+int Heap::new_space_growth_limit_ = 8;
+int Heap::scavenge_count_ = 0;
+Heap::HeapState Heap::gc_state_ = NOT_IN_GC;
+
+int Heap::mc_count_ = 0;
+int Heap::gc_count_ = 0;
+
+int Heap::always_allocate_scope_depth_ = 0;
+bool Heap::context_disposed_pending_ = false;
+
+#ifdef DEBUG
+bool Heap::allocation_allowed_ = true;
+
+int Heap::allocation_timeout_ = 0;
+bool Heap::disallow_allocation_failure_ = false;
+#endif  // DEBUG
+
+
+int Heap::Capacity() {
+  if (!HasBeenSetup()) return 0;
+
+  return new_space_.Capacity() +
+      old_pointer_space_->Capacity() +
+      old_data_space_->Capacity() +
+      code_space_->Capacity() +
+      map_space_->Capacity();
+}
+
+
+int Heap::Available() {
+  if (!HasBeenSetup()) return 0;
+
+  return new_space_.Available() +
+      old_pointer_space_->Available() +
+      old_data_space_->Available() +
+      code_space_->Available() +
+      map_space_->Available();
+}
+
+
+bool Heap::HasBeenSetup() {
+  return old_pointer_space_ != NULL &&
+         old_data_space_ != NULL &&
+         code_space_ != NULL &&
+         map_space_ != NULL &&
+         lo_space_ != NULL;
+}
+
+
+GarbageCollector Heap::SelectGarbageCollector(AllocationSpace space) {
+  // Is global GC requested?
+  if (space != NEW_SPACE || FLAG_gc_global) {
+    Counters::gc_compactor_caused_by_request.Increment();
+    return MARK_COMPACTOR;
+  }
+
+  // Is enough data promoted to justify a global GC?
+  if (OldGenerationPromotionLimitReached()) {
+    Counters::gc_compactor_caused_by_promoted_data.Increment();
+    return MARK_COMPACTOR;
+  }
+
+  // Have allocation in OLD and LO failed?
+  if (old_gen_exhausted_) {
+    Counters::gc_compactor_caused_by_oldspace_exhaustion.Increment();
+    return MARK_COMPACTOR;
+  }
+
+  // Is there enough space left in OLD to guarantee that a scavenge can
+  // succeed?
+  //
+  // Note that MemoryAllocator->MaxAvailable() undercounts the memory available
+  // for object promotion. It counts only the bytes that the memory
+  // allocator has not yet allocated from the OS and assigned to any space,
+  // and does not count available bytes already in the old space or code
+  // space.  Undercounting is safe---we may get an unrequested full GC when
+  // a scavenge would have succeeded.
+  if (MemoryAllocator::MaxAvailable() <= new_space_.Size()) {
+    Counters::gc_compactor_caused_by_oldspace_exhaustion.Increment();
+    return MARK_COMPACTOR;
+  }
+
+  // Default
+  return SCAVENGER;
+}
+
+
+// TODO(1238405): Combine the infrastructure for --heap-stats and
+// --log-gc to avoid the complicated preprocessor and flag testing.
+#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
+void Heap::ReportStatisticsBeforeGC() {
+  // Heap::ReportHeapStatistics will also log NewSpace statistics when
+  // compiled with ENABLE_LOGGING_AND_PROFILING and --log-gc is set.  The
+  // following logic is used to avoid double logging.
+#if defined(DEBUG) && defined(ENABLE_LOGGING_AND_PROFILING)
+  if (FLAG_heap_stats || FLAG_log_gc) new_space_.CollectStatistics();
+  if (FLAG_heap_stats) {
+    ReportHeapStatistics("Before GC");
+  } else if (FLAG_log_gc) {
+    new_space_.ReportStatistics();
+  }
+  if (FLAG_heap_stats || FLAG_log_gc) new_space_.ClearHistograms();
+#elif defined(DEBUG)
+  if (FLAG_heap_stats) {
+    new_space_.CollectStatistics();
+    ReportHeapStatistics("Before GC");
+    new_space_.ClearHistograms();
+  }
+#elif defined(ENABLE_LOGGING_AND_PROFILING)
+  if (FLAG_log_gc) {
+    new_space_.CollectStatistics();
+    new_space_.ReportStatistics();
+    new_space_.ClearHistograms();
+  }
+#endif
+}
+
+
+// TODO(1238405): Combine the infrastructure for --heap-stats and
+// --log-gc to avoid the complicated preprocessor and flag testing.
+void Heap::ReportStatisticsAfterGC() {
+  // Similar to the before GC, we use some complicated logic to ensure that
+  // NewSpace statistics are logged exactly once when --log-gc is turned on.
+#if defined(DEBUG) && defined(ENABLE_LOGGING_AND_PROFILING)
+  if (FLAG_heap_stats) {
+    ReportHeapStatistics("After GC");
+  } else if (FLAG_log_gc) {
+    new_space_.ReportStatistics();
+  }
+#elif defined(DEBUG)
+  if (FLAG_heap_stats) ReportHeapStatistics("After GC");
+#elif defined(ENABLE_LOGGING_AND_PROFILING)
+  if (FLAG_log_gc) new_space_.ReportStatistics();
+#endif
+}
+#endif  // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
+
+
+void Heap::GarbageCollectionPrologue() {
+  gc_count_++;
+#ifdef DEBUG
+  ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC);
+  allow_allocation(false);
+
+  if (FLAG_verify_heap) {
+    Verify();
+  }
+
+  if (FLAG_gc_verbose) Print();
+
+  if (FLAG_print_rset) {
+    // Not all spaces have remembered set bits that we care about.
+    old_pointer_space_->PrintRSet();
+    map_space_->PrintRSet();
+    lo_space_->PrintRSet();
+  }
+#endif
+
+#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
+  ReportStatisticsBeforeGC();
+#endif
+}
+
+int Heap::SizeOfObjects() {
+  int total = 0;
+  AllSpaces spaces;
+  while (Space* space = spaces.next()) total += space->Size();
+  return total;
+}
+
+void Heap::GarbageCollectionEpilogue() {
+#ifdef DEBUG
+  allow_allocation(true);
+  ZapFromSpace();
+
+  if (FLAG_verify_heap) {
+    Verify();
+  }
+
+  if (FLAG_print_global_handles) GlobalHandles::Print();
+  if (FLAG_print_handles) PrintHandles();
+  if (FLAG_gc_verbose) Print();
+  if (FLAG_code_stats) ReportCodeStatistics("After GC");
+#endif
+
+  Counters::alive_after_last_gc.Set(SizeOfObjects());
+
+  SymbolTable* symbol_table = SymbolTable::cast(Heap::symbol_table_);
+  Counters::symbol_table_capacity.Set(symbol_table->Capacity());
+  Counters::number_of_symbols.Set(symbol_table->NumberOfElements());
+#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
+  ReportStatisticsAfterGC();
+#endif
+}
+
+
+void Heap::CollectAllGarbage() {
+  // Since we are ignoring the return value, the exact choice of space does
+  // not matter, so long as we do not specify NEW_SPACE, which would not
+  // cause a full GC.
+  CollectGarbage(0, OLD_POINTER_SPACE);
+}
+
+
+void Heap::CollectAllGarbageIfContextDisposed() {
+  // If the garbage collector interface is exposed through the global
+  // gc() function, we avoid being clever about forcing GCs when
+  // contexts are disposed and leave it to the embedder to make
+  // informed decisions about when to force a collection.
+  if (!FLAG_expose_gc && context_disposed_pending_) {
+    HistogramTimerScope scope(&Counters::gc_context);
+    CollectAllGarbage();
+  }
+  context_disposed_pending_ = false;
+}
+
+
+void Heap::NotifyContextDisposed() {
+  context_disposed_pending_ = true;
+}
+
+
+bool Heap::CollectGarbage(int requested_size, AllocationSpace space) {
+  // The VM is in the GC state until exiting this function.
+  VMState state(GC);
+
+#ifdef DEBUG
+  // Reset the allocation timeout to the GC interval, but make sure to
+  // allow at least a few allocations after a collection. The reason
+  // for this is that we have a lot of allocation sequences and we
+  // assume that a garbage collection will allow the subsequent
+  // allocation attempts to go through.
+  allocation_timeout_ = Max(6, FLAG_gc_interval);
+#endif
+
+  { GCTracer tracer;
+    GarbageCollectionPrologue();
+    // The GC count was incremented in the prologue.  Tell the tracer about
+    // it.
+    tracer.set_gc_count(gc_count_);
+
+    GarbageCollector collector = SelectGarbageCollector(space);
+    // Tell the tracer which collector we've selected.
+    tracer.set_collector(collector);
+
+    HistogramTimer* rate = (collector == SCAVENGER)
+        ? &Counters::gc_scavenger
+        : &Counters::gc_compactor;
+    rate->Start();
+    PerformGarbageCollection(space, collector, &tracer);
+    rate->Stop();
+
+    GarbageCollectionEpilogue();
+  }
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (FLAG_log_gc) HeapProfiler::WriteSample();
+#endif
+
+  switch (space) {
+    case NEW_SPACE:
+      return new_space_.Available() >= requested_size;
+    case OLD_POINTER_SPACE:
+      return old_pointer_space_->Available() >= requested_size;
+    case OLD_DATA_SPACE:
+      return old_data_space_->Available() >= requested_size;
+    case CODE_SPACE:
+      return code_space_->Available() >= requested_size;
+    case MAP_SPACE:
+      return map_space_->Available() >= requested_size;
+    case LO_SPACE:
+      return lo_space_->Available() >= requested_size;
+  }
+  return false;
+}
+
+
+void Heap::PerformScavenge() {
+  GCTracer tracer;
+  PerformGarbageCollection(NEW_SPACE, SCAVENGER, &tracer);
+}
+
+
+#ifdef DEBUG
+// Helper class for verifying the symbol table.
+class SymbolTableVerifier : public ObjectVisitor {
+ public:
+  SymbolTableVerifier() { }
+  void VisitPointers(Object** start, Object** end) {
+    // Visit all HeapObject pointers in [start, end).
+    for (Object** p = start; p < end; p++) {
+      if ((*p)->IsHeapObject()) {
+        // Check that the symbol is actually a symbol.
+        ASSERT((*p)->IsNull() || (*p)->IsUndefined() || (*p)->IsSymbol());
+      }
+    }
+  }
+};
+#endif  // DEBUG
+
+
+static void VerifySymbolTable() {
+#ifdef DEBUG
+  SymbolTableVerifier verifier;
+  SymbolTable* symbol_table = SymbolTable::cast(Heap::symbol_table());
+  symbol_table->IterateElements(&verifier);
+#endif  // DEBUG
+}
+
+
+void Heap::PerformGarbageCollection(AllocationSpace space,
+                                    GarbageCollector collector,
+                                    GCTracer* tracer) {
+  VerifySymbolTable();
+  if (collector == MARK_COMPACTOR && global_gc_prologue_callback_) {
+    ASSERT(!allocation_allowed_);
+    global_gc_prologue_callback_();
+  }
+
+  if (collector == MARK_COMPACTOR) {
+    MarkCompact(tracer);
+
+    int old_gen_size = PromotedSpaceSize();
+    old_gen_promotion_limit_ =
+        old_gen_size + Max(kMinimumPromotionLimit, old_gen_size / 3);
+    old_gen_allocation_limit_ =
+        old_gen_size + Max(kMinimumAllocationLimit, old_gen_size / 3);
+    old_gen_exhausted_ = false;
+
+    // If we have used the mark-compact collector to collect the new
+    // space, and it has not compacted the new space, we force a
+    // separate scavenge collection.  This is a hack.  It covers the
+    // case where (1) a new space collection was requested, (2) the
+    // collector selection policy selected the mark-compact collector,
+    // and (3) the mark-compact collector policy selected not to
+    // compact the new space.  In that case, there is no more (usable)
+    // free space in the new space after the collection compared to
+    // before.
+    if (space == NEW_SPACE && !MarkCompactCollector::HasCompacted()) {
+      Scavenge();
+    }
+  } else {
+    Scavenge();
+  }
+  Counters::objs_since_last_young.Set(0);
+
+  PostGarbageCollectionProcessing();
+
+  if (collector == MARK_COMPACTOR) {
+    // Register the amount of external allocated memory.
+    amount_of_external_allocated_memory_at_last_global_gc_ =
+        amount_of_external_allocated_memory_;
+  }
+
+  if (collector == MARK_COMPACTOR && global_gc_epilogue_callback_) {
+    ASSERT(!allocation_allowed_);
+    global_gc_epilogue_callback_();
+  }
+  VerifySymbolTable();
+}
+
+
+void Heap::PostGarbageCollectionProcessing() {
+  // Process weak handles post gc.
+  GlobalHandles::PostGarbageCollectionProcessing();
+  // Update flat string readers.
+  FlatStringReader::PostGarbageCollectionProcessing();
+}
+
+
+void Heap::MarkCompact(GCTracer* tracer) {
+  gc_state_ = MARK_COMPACT;
+  mc_count_++;
+  tracer->set_full_gc_count(mc_count_);
+  LOG(ResourceEvent("markcompact", "begin"));
+
+  MarkCompactCollector::Prepare(tracer);
+
+  bool is_compacting = MarkCompactCollector::IsCompacting();
+
+  MarkCompactPrologue(is_compacting);
+
+  MarkCompactCollector::CollectGarbage();
+
+  MarkCompactEpilogue(is_compacting);
+
+  LOG(ResourceEvent("markcompact", "end"));
+
+  gc_state_ = NOT_IN_GC;
+
+  Shrink();
+
+  Counters::objs_since_last_full.Set(0);
+  context_disposed_pending_ = false;
+}
+
+
+void Heap::MarkCompactPrologue(bool is_compacting) {
+  // At any old GC clear the keyed lookup cache to enable collection of unused
+  // maps.
+  ClearKeyedLookupCache();
+
+  CompilationCache::MarkCompactPrologue();
+
+  Top::MarkCompactPrologue(is_compacting);
+  ThreadManager::MarkCompactPrologue(is_compacting);
+}
+
+
+void Heap::MarkCompactEpilogue(bool is_compacting) {
+  Top::MarkCompactEpilogue(is_compacting);
+  ThreadManager::MarkCompactEpilogue(is_compacting);
+}
+
+
+Object* Heap::FindCodeObject(Address a) {
+  Object* obj = code_space_->FindObject(a);
+  if (obj->IsFailure()) {
+    obj = lo_space_->FindObject(a);
+  }
+  ASSERT(!obj->IsFailure());
+  return obj;
+}
+
+
+// Helper class for copying HeapObjects
+class ScavengeVisitor: public ObjectVisitor {
+ public:
+
+  void VisitPointer(Object** p) { ScavengePointer(p); }
+
+  void VisitPointers(Object** start, Object** end) {
+    // Copy all HeapObject pointers in [start, end)
+    for (Object** p = start; p < end; p++) ScavengePointer(p);
+  }
+
+ private:
+  void ScavengePointer(Object** p) {
+    Object* object = *p;
+    if (!Heap::InNewSpace(object)) return;
+    Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p),
+                         reinterpret_cast<HeapObject*>(object));
+  }
+};
+
+
+// Shared state read by the scavenge collector and set by ScavengeObject.
+static Address promoted_top = NULL;
+
+
+#ifdef DEBUG
+// Visitor class to verify pointers in code or data space do not point into
+// new space.
+class VerifyNonPointerSpacePointersVisitor: public ObjectVisitor {
+ public:
+  void VisitPointers(Object** start, Object**end) {
+    for (Object** current = start; current < end; current++) {
+      if ((*current)->IsHeapObject()) {
+        ASSERT(!Heap::InNewSpace(HeapObject::cast(*current)));
+      }
+    }
+  }
+};
+#endif
+
+void Heap::Scavenge() {
+#ifdef DEBUG
+  if (FLAG_enable_slow_asserts) {
+    VerifyNonPointerSpacePointersVisitor v;
+    HeapObjectIterator it(code_space_);
+    while (it.has_next()) {
+      HeapObject* object = it.next();
+      if (object->IsCode()) {
+        Code::cast(object)->ConvertICTargetsFromAddressToObject();
+      }
+      object->Iterate(&v);
+      if (object->IsCode()) {
+        Code::cast(object)->ConvertICTargetsFromObjectToAddress();
+      }
+    }
+  }
+#endif
+
+  gc_state_ = SCAVENGE;
+
+  // Implements Cheney's copying algorithm
+  LOG(ResourceEvent("scavenge", "begin"));
+
+  scavenge_count_++;
+  if (new_space_.Capacity() < new_space_.MaximumCapacity() &&
+      scavenge_count_ > new_space_growth_limit_) {
+    // Double the size of the new space, and double the limit.  The next
+    // doubling attempt will occur after the current new_space_growth_limit_
+    // more collections.
+    // TODO(1240712): NewSpace::Double has a return value which is
+    // ignored here.
+    new_space_.Double();
+    new_space_growth_limit_ *= 2;
+  }
+
+  // Flip the semispaces.  After flipping, to space is empty, from space has
+  // live objects.
+  new_space_.Flip();
+  new_space_.ResetAllocationInfo();
+
+  // We need to sweep newly copied objects which can be in either the to space
+  // or the old space.  For to space objects, we use a mark.  Newly copied
+  // objects lie between the mark and the allocation top.  For objects
+  // promoted to old space, we write their addresses downward from the top of
+  // the new space.  Sweeping newly promoted objects requires an allocation
+  // pointer and a mark.  Note that the allocation pointer 'top' actually
+  // moves downward from the high address in the to space.
+  //
+  // There is guaranteed to be enough room at the top of the to space for the
+  // addresses of promoted objects: every object promoted frees up its size in
+  // bytes from the top of the new space, and objects are at least one pointer
+  // in size.  Using the new space to record promoted addresses makes the
+  // scavenge collector agnostic to the allocation strategy (eg, linear or
+  // free-list) used in old space.
+  Address new_mark = new_space_.ToSpaceLow();
+  Address promoted_mark = new_space_.ToSpaceHigh();
+  promoted_top = new_space_.ToSpaceHigh();
+
+  ScavengeVisitor scavenge_visitor;
+  // Copy roots.
+  IterateRoots(&scavenge_visitor);
+
+  // Copy objects reachable from the old generation.  By definition, there
+  // are no intergenerational pointers in code or data spaces.
+  IterateRSet(old_pointer_space_, &ScavengePointer);
+  IterateRSet(map_space_, &ScavengePointer);
+  lo_space_->IterateRSet(&ScavengePointer);
+
+  bool has_processed_weak_pointers = false;
+
+  while (true) {
+    ASSERT(new_mark <= new_space_.top());
+    ASSERT(promoted_mark >= promoted_top);
+
+    // Copy objects reachable from newly copied objects.
+    while (new_mark < new_space_.top() || promoted_mark > promoted_top) {
+      // Sweep newly copied objects in the to space.  The allocation pointer
+      // can change during sweeping.
+      Address previous_top = new_space_.top();
+      SemiSpaceIterator new_it(new_space(), new_mark);
+      while (new_it.has_next()) {
+        new_it.next()->Iterate(&scavenge_visitor);
+      }
+      new_mark = previous_top;
+
+      // Sweep newly copied objects in the old space.  The promotion 'top'
+      // pointer could change during sweeping.
+      previous_top = promoted_top;
+      for (Address current = promoted_mark - kPointerSize;
+           current >= previous_top;
+           current -= kPointerSize) {
+        HeapObject* object = HeapObject::cast(Memory::Object_at(current));
+        object->Iterate(&scavenge_visitor);
+        UpdateRSet(object);
+      }
+      promoted_mark = previous_top;
+    }
+
+    if (has_processed_weak_pointers) break;  // We are done.
+    // Copy objects reachable from weak pointers.
+    GlobalHandles::IterateWeakRoots(&scavenge_visitor);
+    has_processed_weak_pointers = true;
+  }
+
+  // Set age mark.
+  new_space_.set_age_mark(new_mark);
+
+  LOG(ResourceEvent("scavenge", "end"));
+
+  gc_state_ = NOT_IN_GC;
+}
+
+
+void Heap::ClearRSetRange(Address start, int size_in_bytes) {
+  uint32_t start_bit;
+  Address start_word_address =
+      Page::ComputeRSetBitPosition(start, 0, &start_bit);
+  uint32_t end_bit;
+  Address end_word_address =
+      Page::ComputeRSetBitPosition(start + size_in_bytes - kIntSize,
+                                   0,
+                                   &end_bit);
+
+  // We want to clear the bits in the starting word starting with the
+  // first bit, and in the ending word up to and including the last
+  // bit.  Build a pair of bitmasks to do that.
+  uint32_t start_bitmask = start_bit - 1;
+  uint32_t end_bitmask = ~((end_bit << 1) - 1);
+
+  // If the start address and end address are the same, we mask that
+  // word once, otherwise mask the starting and ending word
+  // separately and all the ones in between.
+  if (start_word_address == end_word_address) {
+    Memory::uint32_at(start_word_address) &= (start_bitmask | end_bitmask);
+  } else {
+    Memory::uint32_at(start_word_address) &= start_bitmask;
+    Memory::uint32_at(end_word_address) &= end_bitmask;
+    start_word_address += kIntSize;
+    memset(start_word_address, 0, end_word_address - start_word_address);
+  }
+}
+
+
+class UpdateRSetVisitor: public ObjectVisitor {
+ public:
+
+  void VisitPointer(Object** p) {
+    UpdateRSet(p);
+  }
+
+  void VisitPointers(Object** start, Object** end) {
+    // Update a store into slots [start, end), used (a) to update remembered
+    // set when promoting a young object to old space or (b) to rebuild
+    // remembered sets after a mark-compact collection.
+    for (Object** p = start; p < end; p++) UpdateRSet(p);
+  }
+ private:
+
+  void UpdateRSet(Object** p) {
+    // The remembered set should not be set.  It should be clear for objects
+    // newly copied to old space, and it is cleared before rebuilding in the
+    // mark-compact collector.
+    ASSERT(!Page::IsRSetSet(reinterpret_cast<Address>(p), 0));
+    if (Heap::InNewSpace(*p)) {
+      Page::SetRSet(reinterpret_cast<Address>(p), 0);
+    }
+  }
+};
+
+
+int Heap::UpdateRSet(HeapObject* obj) {
+  ASSERT(!InNewSpace(obj));
+  // Special handling of fixed arrays to iterate the body based on the start
+  // address and offset.  Just iterating the pointers as in UpdateRSetVisitor
+  // will not work because Page::SetRSet needs to have the start of the
+  // object.
+  if (obj->IsFixedArray()) {
+    FixedArray* array = FixedArray::cast(obj);
+    int length = array->length();
+    for (int i = 0; i < length; i++) {
+      int offset = FixedArray::kHeaderSize + i * kPointerSize;
+      ASSERT(!Page::IsRSetSet(obj->address(), offset));
+      if (Heap::InNewSpace(array->get(i))) {
+        Page::SetRSet(obj->address(), offset);
+      }
+    }
+  } else if (!obj->IsCode()) {
+    // Skip code object, we know it does not contain inter-generational
+    // pointers.
+    UpdateRSetVisitor v;
+    obj->Iterate(&v);
+  }
+  return obj->Size();
+}
+
+
+void Heap::RebuildRSets() {
+  // By definition, we do not care about remembered set bits in code or data
+  // spaces.
+  map_space_->ClearRSet();
+  RebuildRSets(map_space_);
+
+  old_pointer_space_->ClearRSet();
+  RebuildRSets(old_pointer_space_);
+
+  Heap::lo_space_->ClearRSet();
+  RebuildRSets(lo_space_);
+}
+
+
+void Heap::RebuildRSets(PagedSpace* space) {
+  HeapObjectIterator it(space);
+  while (it.has_next()) Heap::UpdateRSet(it.next());
+}
+
+
+void Heap::RebuildRSets(LargeObjectSpace* space) {
+  LargeObjectIterator it(space);
+  while (it.has_next()) Heap::UpdateRSet(it.next());
+}
+
+
+#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
+void Heap::RecordCopiedObject(HeapObject* obj) {
+  bool should_record = false;
+#ifdef DEBUG
+  should_record = FLAG_heap_stats;
+#endif
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  should_record = should_record || FLAG_log_gc;
+#endif
+  if (should_record) {
+    if (new_space_.Contains(obj)) {
+      new_space_.RecordAllocation(obj);
+    } else {
+      new_space_.RecordPromotion(obj);
+    }
+  }
+}
+#endif  // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
+
+
+
+HeapObject* Heap::MigrateObject(HeapObject* source,
+                                HeapObject* target,
+                                int size) {
+  // Copy the content of source to target.
+  CopyBlock(reinterpret_cast<Object**>(target->address()),
+            reinterpret_cast<Object**>(source->address()),
+            size);
+
+  // Set the forwarding address.
+  source->set_map_word(MapWord::FromForwardingAddress(target));
+
+  // Update NewSpace stats if necessary.
+#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
+  RecordCopiedObject(target);
+#endif
+
+  return target;
+}
+
+
+// Inlined function.
+void Heap::ScavengeObject(HeapObject** p, HeapObject* object) {
+  ASSERT(InFromSpace(object));
+
+  // We use the first word (where the map pointer usually is) of a heap
+  // object to record the forwarding pointer.  A forwarding pointer can
+  // point to an old space, the code space, or the to space of the new
+  // generation.
+  MapWord first_word = object->map_word();
+
+  // If the first word is a forwarding address, the object has already been
+  // copied.
+  if (first_word.IsForwardingAddress()) {
+    *p = first_word.ToForwardingAddress();
+    return;
+  }
+
+  // Call the slow part of scavenge object.
+  return ScavengeObjectSlow(p, object);
+}
+
+
+static inline bool IsShortcutCandidate(HeapObject* object, Map* map) {
+  STATIC_ASSERT(kNotStringTag != 0 && kSymbolTag != 0);
+  ASSERT(object->map() == map);
+  InstanceType type = map->instance_type();
+  if ((type & kShortcutTypeMask) != kShortcutTypeTag) return false;
+  ASSERT(object->IsString() && !object->IsSymbol());
+  return ConsString::cast(object)->unchecked_second() == Heap::empty_string();
+}
+
+
+void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) {
+  ASSERT(InFromSpace(object));
+  MapWord first_word = object->map_word();
+  ASSERT(!first_word.IsForwardingAddress());
+
+  // Optimization: Bypass flattened ConsString objects.
+  if (IsShortcutCandidate(object, first_word.ToMap())) {
+    object = HeapObject::cast(ConsString::cast(object)->unchecked_first());
+    *p = object;
+    // After patching *p we have to repeat the checks that object is in the
+    // active semispace of the young generation and not already copied.
+    if (!InNewSpace(object)) return;
+    first_word = object->map_word();
+    if (first_word.IsForwardingAddress()) {
+      *p = first_word.ToForwardingAddress();
+      return;
+    }
+  }
+
+  int object_size = object->SizeFromMap(first_word.ToMap());
+  // If the object should be promoted, we try to copy it to old space.
+  if (ShouldBePromoted(object->address(), object_size)) {
+    OldSpace* target_space = Heap::TargetSpace(object);
+    ASSERT(target_space == Heap::old_pointer_space_ ||
+           target_space == Heap::old_data_space_);
+    Object* result = target_space->AllocateRaw(object_size);
+    if (!result->IsFailure()) {
+      *p = MigrateObject(object, HeapObject::cast(result), object_size);
+      if (target_space == Heap::old_pointer_space_) {
+        // Record the object's address at the top of the to space, to allow
+        // it to be swept by the scavenger.
+        promoted_top -= kPointerSize;
+        Memory::Object_at(promoted_top) = *p;
+      } else {
+#ifdef DEBUG
+        // Objects promoted to the data space should not have pointers to
+        // new space.
+        VerifyNonPointerSpacePointersVisitor v;
+        (*p)->Iterate(&v);
+#endif
+      }
+      return;
+    }
+  }
+
+  // The object should remain in new space or the old space allocation failed.
+  Object* result = new_space_.AllocateRaw(object_size);
+  // Failed allocation at this point is utterly unexpected.
+  ASSERT(!result->IsFailure());
+  *p = MigrateObject(object, HeapObject::cast(result), object_size);
+}
+
+
+void Heap::ScavengePointer(HeapObject** p) {
+  ScavengeObject(p, *p);
+}
+
+
+Object* Heap::AllocatePartialMap(InstanceType instance_type,
+                                 int instance_size) {
+  Object* result = AllocateRawMap(Map::kSize);
+  if (result->IsFailure()) return result;
+
+  // Map::cast cannot be used due to uninitialized map field.
+  reinterpret_cast<Map*>(result)->set_map(meta_map());
+  reinterpret_cast<Map*>(result)->set_instance_type(instance_type);
+  reinterpret_cast<Map*>(result)->set_instance_size(instance_size);
+  reinterpret_cast<Map*>(result)->set_inobject_properties(0);
+  reinterpret_cast<Map*>(result)->set_unused_property_fields(0);
+  return result;
+}
+
+
+Object* Heap::AllocateMap(InstanceType instance_type, int instance_size) {
+  Object* result = AllocateRawMap(Map::kSize);
+  if (result->IsFailure()) return result;
+
+  Map* map = reinterpret_cast<Map*>(result);
+  map->set_map(meta_map());
+  map->set_instance_type(instance_type);
+  map->set_prototype(null_value());
+  map->set_constructor(null_value());
+  map->set_instance_size(instance_size);
+  map->set_inobject_properties(0);
+  map->set_instance_descriptors(empty_descriptor_array());
+  map->set_code_cache(empty_fixed_array());
+  map->set_unused_property_fields(0);
+  map->set_bit_field(0);
+  return map;
+}
+
+
+bool Heap::CreateInitialMaps() {
+  Object* obj = AllocatePartialMap(MAP_TYPE, Map::kSize);
+  if (obj->IsFailure()) return false;
+
+  // Map::cast cannot be used due to uninitialized map field.
+  meta_map_ = reinterpret_cast<Map*>(obj);
+  meta_map()->set_map(meta_map());
+
+  obj = AllocatePartialMap(FIXED_ARRAY_TYPE, Array::kHeaderSize);
+  if (obj->IsFailure()) return false;
+  fixed_array_map_ = Map::cast(obj);
+
+  obj = AllocatePartialMap(ODDBALL_TYPE, Oddball::kSize);
+  if (obj->IsFailure()) return false;
+  oddball_map_ = Map::cast(obj);
+
+  // Allocate the empty array
+  obj = AllocateEmptyFixedArray();
+  if (obj->IsFailure()) return false;
+  empty_fixed_array_ = FixedArray::cast(obj);
+
+  obj = Allocate(oddball_map(), OLD_DATA_SPACE);
+  if (obj->IsFailure()) return false;
+  null_value_ = obj;
+
+  // Allocate the empty descriptor array.  AllocateMap can now be used.
+  obj = AllocateEmptyFixedArray();
+  if (obj->IsFailure()) return false;
+  // There is a check against empty_descriptor_array() in cast().
+  empty_descriptor_array_ = reinterpret_cast<DescriptorArray*>(obj);
+
+  // Fix the instance_descriptors for the existing maps.
+  meta_map()->set_instance_descriptors(empty_descriptor_array());
+  meta_map()->set_code_cache(empty_fixed_array());
+
+  fixed_array_map()->set_instance_descriptors(empty_descriptor_array());
+  fixed_array_map()->set_code_cache(empty_fixed_array());
+
+  oddball_map()->set_instance_descriptors(empty_descriptor_array());
+  oddball_map()->set_code_cache(empty_fixed_array());
+
+  // Fix prototype object for existing maps.
+  meta_map()->set_prototype(null_value());
+  meta_map()->set_constructor(null_value());
+
+  fixed_array_map()->set_prototype(null_value());
+  fixed_array_map()->set_constructor(null_value());
+  oddball_map()->set_prototype(null_value());
+  oddball_map()->set_constructor(null_value());
+
+  obj = AllocateMap(HEAP_NUMBER_TYPE, HeapNumber::kSize);
+  if (obj->IsFailure()) return false;
+  heap_number_map_ = Map::cast(obj);
+
+  obj = AllocateMap(PROXY_TYPE, Proxy::kSize);
+  if (obj->IsFailure()) return false;
+  proxy_map_ = Map::cast(obj);
+
+#define ALLOCATE_STRING_MAP(type, size, name)   \
+    obj = AllocateMap(type, size);              \
+    if (obj->IsFailure()) return false;         \
+    name##_map_ = Map::cast(obj);
+  STRING_TYPE_LIST(ALLOCATE_STRING_MAP);
+#undef ALLOCATE_STRING_MAP
+
+  obj = AllocateMap(SHORT_STRING_TYPE, SeqTwoByteString::kHeaderSize);
+  if (obj->IsFailure()) return false;
+  undetectable_short_string_map_ = Map::cast(obj);
+  undetectable_short_string_map_->set_is_undetectable();
+
+  obj = AllocateMap(MEDIUM_STRING_TYPE, SeqTwoByteString::kHeaderSize);
+  if (obj->IsFailure()) return false;
+  undetectable_medium_string_map_ = Map::cast(obj);
+  undetectable_medium_string_map_->set_is_undetectable();
+
+  obj = AllocateMap(LONG_STRING_TYPE, SeqTwoByteString::kHeaderSize);
+  if (obj->IsFailure()) return false;
+  undetectable_long_string_map_ = Map::cast(obj);
+  undetectable_long_string_map_->set_is_undetectable();
+
+  obj = AllocateMap(SHORT_ASCII_STRING_TYPE, SeqAsciiString::kHeaderSize);
+  if (obj->IsFailure()) return false;
+  undetectable_short_ascii_string_map_ = Map::cast(obj);
+  undetectable_short_ascii_string_map_->set_is_undetectable();
+
+  obj = AllocateMap(MEDIUM_ASCII_STRING_TYPE, SeqAsciiString::kHeaderSize);
+  if (obj->IsFailure()) return false;
+  undetectable_medium_ascii_string_map_ = Map::cast(obj);
+  undetectable_medium_ascii_string_map_->set_is_undetectable();
+
+  obj = AllocateMap(LONG_ASCII_STRING_TYPE, SeqAsciiString::kHeaderSize);
+  if (obj->IsFailure()) return false;
+  undetectable_long_ascii_string_map_ = Map::cast(obj);
+  undetectable_long_ascii_string_map_->set_is_undetectable();
+
+  obj = AllocateMap(BYTE_ARRAY_TYPE, Array::kHeaderSize);
+  if (obj->IsFailure()) return false;
+  byte_array_map_ = Map::cast(obj);
+
+  obj = AllocateMap(CODE_TYPE, Code::kHeaderSize);
+  if (obj->IsFailure()) return false;
+  code_map_ = Map::cast(obj);
+
+  obj = AllocateMap(FILLER_TYPE, kPointerSize);
+  if (obj->IsFailure()) return false;
+  one_word_filler_map_ = Map::cast(obj);
+
+  obj = AllocateMap(FILLER_TYPE, 2 * kPointerSize);
+  if (obj->IsFailure()) return false;
+  two_word_filler_map_ = Map::cast(obj);
+
+#define ALLOCATE_STRUCT_MAP(NAME, Name, name)      \
+  obj = AllocateMap(NAME##_TYPE, Name::kSize);     \
+  if (obj->IsFailure()) return false;              \
+  name##_map_ = Map::cast(obj);
+  STRUCT_LIST(ALLOCATE_STRUCT_MAP)
+#undef ALLOCATE_STRUCT_MAP
+
+  obj = AllocateMap(FIXED_ARRAY_TYPE, HeapObject::kHeaderSize);
+  if (obj->IsFailure()) return false;
+  hash_table_map_ = Map::cast(obj);
+
+  obj = AllocateMap(FIXED_ARRAY_TYPE, HeapObject::kHeaderSize);
+  if (obj->IsFailure()) return false;
+  context_map_ = Map::cast(obj);
+
+  obj = AllocateMap(FIXED_ARRAY_TYPE, HeapObject::kHeaderSize);
+  if (obj->IsFailure()) return false;
+  catch_context_map_ = Map::cast(obj);
+
+  obj = AllocateMap(FIXED_ARRAY_TYPE, HeapObject::kHeaderSize);
+  if (obj->IsFailure()) return false;
+  global_context_map_ = Map::cast(obj);
+
+  obj = AllocateMap(JS_FUNCTION_TYPE, JSFunction::kSize);
+  if (obj->IsFailure()) return false;
+  boilerplate_function_map_ = Map::cast(obj);
+
+  obj = AllocateMap(SHARED_FUNCTION_INFO_TYPE, SharedFunctionInfo::kSize);
+  if (obj->IsFailure()) return false;
+  shared_function_info_map_ = Map::cast(obj);
+
+  ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
+  return true;
+}
+
+
+Object* Heap::AllocateHeapNumber(double value, PretenureFlag pretenure) {
+  // Statically ensure that it is safe to allocate heap numbers in paged
+  // spaces.
+  STATIC_ASSERT(HeapNumber::kSize <= Page::kMaxHeapObjectSize);
+  AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
+  Object* result = AllocateRaw(HeapNumber::kSize, space, OLD_DATA_SPACE);
+  if (result->IsFailure()) return result;
+
+  HeapObject::cast(result)->set_map(heap_number_map());
+  HeapNumber::cast(result)->set_value(value);
+  return result;
+}
+
+
+Object* Heap::AllocateHeapNumber(double value) {
+  // Use general version, if we're forced to always allocate.
+  if (always_allocate()) return AllocateHeapNumber(value, NOT_TENURED);
+  // This version of AllocateHeapNumber is optimized for
+  // allocation in new space.
+  STATIC_ASSERT(HeapNumber::kSize <= Page::kMaxHeapObjectSize);
+  ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC);
+  Object* result = new_space_.AllocateRaw(HeapNumber::kSize);
+  if (result->IsFailure()) return result;
+  HeapObject::cast(result)->set_map(heap_number_map());
+  HeapNumber::cast(result)->set_value(value);
+  return result;
+}
+
+
+Object* Heap::CreateOddball(Map* map,
+                            const char* to_string,
+                            Object* to_number) {
+  Object* result = Allocate(map, OLD_DATA_SPACE);
+  if (result->IsFailure()) return result;
+  return Oddball::cast(result)->Initialize(to_string, to_number);
+}
+
+
+bool Heap::CreateApiObjects() {
+  Object* obj;
+
+  obj = AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
+  if (obj->IsFailure()) return false;
+  neander_map_ = Map::cast(obj);
+
+  obj = Heap::AllocateJSObjectFromMap(neander_map_);
+  if (obj->IsFailure()) return false;
+  Object* elements = AllocateFixedArray(2);
+  if (elements->IsFailure()) return false;
+  FixedArray::cast(elements)->set(0, Smi::FromInt(0));
+  JSObject::cast(obj)->set_elements(FixedArray::cast(elements));
+  message_listeners_ = JSObject::cast(obj);
+
+  return true;
+}
+
+void Heap::CreateFixedStubs() {
+  // Here we create roots for fixed stubs. They are needed at GC
+  // for cooking and uncooking (check out frames.cc).
+  // The eliminates the need for doing dictionary lookup in the
+  // stub cache for these stubs.
+  HandleScope scope;
+  {
+    CEntryStub stub;
+    c_entry_code_ = *stub.GetCode();
+  }
+  {
+    CEntryDebugBreakStub stub;
+    c_entry_debug_break_code_ = *stub.GetCode();
+  }
+  {
+    JSEntryStub stub;
+    js_entry_code_ = *stub.GetCode();
+  }
+  {
+    JSConstructEntryStub stub;
+    js_construct_entry_code_ = *stub.GetCode();
+  }
+}
+
+
+bool Heap::CreateInitialObjects() {
+  Object* obj;
+
+  // The -0 value must be set before NumberFromDouble works.
+  obj = AllocateHeapNumber(-0.0, TENURED);
+  if (obj->IsFailure()) return false;
+  minus_zero_value_ = obj;
+  ASSERT(signbit(minus_zero_value_->Number()) != 0);
+
+  obj = AllocateHeapNumber(OS::nan_value(), TENURED);
+  if (obj->IsFailure()) return false;
+  nan_value_ = obj;
+
+  obj = Allocate(oddball_map(), OLD_DATA_SPACE);
+  if (obj->IsFailure()) return false;
+  undefined_value_ = obj;
+  ASSERT(!InNewSpace(undefined_value()));
+
+  // Allocate initial symbol table.
+  obj = SymbolTable::Allocate(kInitialSymbolTableSize);
+  if (obj->IsFailure()) return false;
+  symbol_table_ = obj;
+
+  // Assign the print strings for oddballs after creating symboltable.
+  Object* symbol = LookupAsciiSymbol("undefined");
+  if (symbol->IsFailure()) return false;
+  Oddball::cast(undefined_value_)->set_to_string(String::cast(symbol));
+  Oddball::cast(undefined_value_)->set_to_number(nan_value_);
+
+  // Assign the print strings for oddballs after creating symboltable.
+  symbol = LookupAsciiSymbol("null");
+  if (symbol->IsFailure()) return false;
+  Oddball::cast(null_value_)->set_to_string(String::cast(symbol));
+  Oddball::cast(null_value_)->set_to_number(Smi::FromInt(0));
+
+  // Allocate the null_value
+  obj = Oddball::cast(null_value())->Initialize("null", Smi::FromInt(0));
+  if (obj->IsFailure()) return false;
+
+  obj = CreateOddball(oddball_map(), "true", Smi::FromInt(1));
+  if (obj->IsFailure()) return false;
+  true_value_ = obj;
+
+  obj = CreateOddball(oddball_map(), "false", Smi::FromInt(0));
+  if (obj->IsFailure()) return false;
+  false_value_ = obj;
+
+  obj = CreateOddball(oddball_map(), "hole", Smi::FromInt(-1));
+  if (obj->IsFailure()) return false;
+  the_hole_value_ = obj;
+
+  // Allocate the empty string.
+  obj = AllocateRawAsciiString(0, TENURED);
+  if (obj->IsFailure()) return false;
+  empty_string_ = String::cast(obj);
+
+#define SYMBOL_INITIALIZE(name, string)                 \
+  obj = LookupAsciiSymbol(string);                      \
+  if (obj->IsFailure()) return false;                   \
+  (name##_) = String::cast(obj);
+  SYMBOL_LIST(SYMBOL_INITIALIZE)
+#undef SYMBOL_INITIALIZE
+
+  // Allocate the hidden symbol which is used to identify the hidden properties
+  // in JSObjects. The hash code has a special value so that it will not match
+  // the empty string when searching for the property. It cannot be part of the
+  // SYMBOL_LIST because it needs to be allocated manually with the special
+  // hash code in place. The hash code for the hidden_symbol is zero to ensure
+  // that it will always be at the first entry in property descriptors.
+  obj = AllocateSymbol(CStrVector(""), 0, String::kHashComputedMask);
+  if (obj->IsFailure()) return false;
+  hidden_symbol_ = String::cast(obj);
+
+  // Allocate the proxy for __proto__.
+  obj = AllocateProxy((Address) &Accessors::ObjectPrototype);
+  if (obj->IsFailure()) return false;
+  prototype_accessors_ = Proxy::cast(obj);
+
+  // Allocate the code_stubs dictionary.
+  obj = Dictionary::Allocate(4);
+  if (obj->IsFailure()) return false;
+  code_stubs_ = Dictionary::cast(obj);
+
+  // Allocate the non_monomorphic_cache used in stub-cache.cc
+  obj = Dictionary::Allocate(4);
+  if (obj->IsFailure()) return false;
+  non_monomorphic_cache_ =  Dictionary::cast(obj);
+
+  CreateFixedStubs();
+
+  // Allocate the number->string conversion cache
+  obj = AllocateFixedArray(kNumberStringCacheSize * 2);
+  if (obj->IsFailure()) return false;
+  number_string_cache_ = FixedArray::cast(obj);
+
+  // Allocate cache for single character strings.
+  obj = AllocateFixedArray(String::kMaxAsciiCharCode+1);
+  if (obj->IsFailure()) return false;
+  single_character_string_cache_ = FixedArray::cast(obj);
+
+  // Allocate cache for external strings pointing to native source code.
+  obj = AllocateFixedArray(Natives::GetBuiltinsCount());
+  if (obj->IsFailure()) return false;
+  natives_source_cache_ = FixedArray::cast(obj);
+
+  // Handling of script id generation is in Factory::NewScript.
+  last_script_id_ = undefined_value();
+
+  // Initialize keyed lookup cache.
+  ClearKeyedLookupCache();
+
+  // Initialize compilation cache.
+  CompilationCache::Clear();
+
+  return true;
+}
+
+
+static inline int double_get_hash(double d) {
+  DoubleRepresentation rep(d);
+  return ((static_cast<int>(rep.bits) ^ static_cast<int>(rep.bits >> 32)) &
+          (Heap::kNumberStringCacheSize - 1));
+}
+
+
+static inline int smi_get_hash(Smi* smi) {
+  return (smi->value() & (Heap::kNumberStringCacheSize - 1));
+}
+
+
+
+Object* Heap::GetNumberStringCache(Object* number) {
+  int hash;
+  if (number->IsSmi()) {
+    hash = smi_get_hash(Smi::cast(number));
+  } else {
+    hash = double_get_hash(number->Number());
+  }
+  Object* key = number_string_cache_->get(hash * 2);
+  if (key == number) {
+    return String::cast(number_string_cache_->get(hash * 2 + 1));
+  } else if (key->IsHeapNumber() &&
+             number->IsHeapNumber() &&
+             key->Number() == number->Number()) {
+    return String::cast(number_string_cache_->get(hash * 2 + 1));
+  }
+  return undefined_value();
+}
+
+
+void Heap::SetNumberStringCache(Object* number, String* string) {
+  int hash;
+  if (number->IsSmi()) {
+    hash = smi_get_hash(Smi::cast(number));
+    number_string_cache_->set(hash * 2, number, SKIP_WRITE_BARRIER);
+  } else {
+    hash = double_get_hash(number->Number());
+    number_string_cache_->set(hash * 2, number);
+  }
+  number_string_cache_->set(hash * 2 + 1, string);
+}
+
+
+Object* Heap::SmiOrNumberFromDouble(double value,
+                                    bool new_object,
+                                    PretenureFlag pretenure) {
+  // We need to distinguish the minus zero value and this cannot be
+  // done after conversion to int. Doing this by comparing bit
+  // patterns is faster than using fpclassify() et al.
+  static const DoubleRepresentation plus_zero(0.0);
+  static const DoubleRepresentation minus_zero(-0.0);
+  static const DoubleRepresentation nan(OS::nan_value());
+  ASSERT(minus_zero_value_ != NULL);
+  ASSERT(sizeof(plus_zero.value) == sizeof(plus_zero.bits));
+
+  DoubleRepresentation rep(value);
+  if (rep.bits == plus_zero.bits) return Smi::FromInt(0);  // not uncommon
+  if (rep.bits == minus_zero.bits) {
+    return new_object ? AllocateHeapNumber(-0.0, pretenure)
+                      : minus_zero_value_;
+  }
+  if (rep.bits == nan.bits) {
+    return new_object
+        ? AllocateHeapNumber(OS::nan_value(), pretenure)
+        : nan_value_;
+  }
+
+  // Try to represent the value as a tagged small integer.
+  int int_value = FastD2I(value);
+  if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
+    return Smi::FromInt(int_value);
+  }
+
+  // Materialize the value in the heap.
+  return AllocateHeapNumber(value, pretenure);
+}
+
+
+Object* Heap::NewNumberFromDouble(double value, PretenureFlag pretenure) {
+  return SmiOrNumberFromDouble(value,
+                               true /* number object must be new */,
+                               pretenure);
+}
+
+
+Object* Heap::NumberFromDouble(double value, PretenureFlag pretenure) {
+  return SmiOrNumberFromDouble(value,
+                               false /* use preallocated NaN, -0.0 */,
+                               pretenure);
+}
+
+
+Object* Heap::AllocateProxy(Address proxy, PretenureFlag pretenure) {
+  // Statically ensure that it is safe to allocate proxies in paged spaces.
+  STATIC_ASSERT(Proxy::kSize <= Page::kMaxHeapObjectSize);
+  AllocationSpace space =
+      (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
+  Object* result = Allocate(proxy_map(), space);
+  if (result->IsFailure()) return result;
+
+  Proxy::cast(result)->set_proxy(proxy);
+  return result;
+}
+
+
+Object* Heap::AllocateSharedFunctionInfo(Object* name) {
+  Object* result = Allocate(shared_function_info_map(), NEW_SPACE);
+  if (result->IsFailure()) return result;
+
+  SharedFunctionInfo* share = SharedFunctionInfo::cast(result);
+  share->set_name(name);
+  Code* illegal = Builtins::builtin(Builtins::Illegal);
+  share->set_code(illegal);
+  share->set_expected_nof_properties(0);
+  share->set_length(0);
+  share->set_formal_parameter_count(0);
+  share->set_instance_class_name(Object_symbol());
+  share->set_function_data(undefined_value());
+  share->set_lazy_load_data(undefined_value());
+  share->set_script(undefined_value());
+  share->set_start_position_and_type(0);
+  share->set_debug_info(undefined_value());
+  share->set_inferred_name(empty_string());
+  return result;
+}
+
+
+Object* Heap::AllocateConsString(String* first,
+                                 String* second) {
+  int first_length = first->length();
+  int second_length = second->length();
+  int length = first_length + second_length;
+  bool is_ascii = StringShape(first).IsAsciiRepresentation()
+      && StringShape(second).IsAsciiRepresentation();
+
+  // If the resulting string is small make a flat string.
+  if (length < String::kMinNonFlatLength) {
+    ASSERT(first->IsFlat());
+    ASSERT(second->IsFlat());
+    if (is_ascii) {
+      Object* result = AllocateRawAsciiString(length);
+      if (result->IsFailure()) return result;
+      // Copy the characters into the new object.
+      char* dest = SeqAsciiString::cast(result)->GetChars();
+      String::WriteToFlat(first, dest, 0, first_length);
+      String::WriteToFlat(second, dest + first_length, 0, second_length);
+      return result;
+    } else {
+      Object* result = AllocateRawTwoByteString(length);
+      if (result->IsFailure()) return result;
+      // Copy the characters into the new object.
+      uc16* dest = SeqTwoByteString::cast(result)->GetChars();
+      String::WriteToFlat(first, dest, 0, first_length);
+      String::WriteToFlat(second, dest + first_length, 0, second_length);
+      return result;
+    }
+  }
+
+  Map* map;
+  if (length <= String::kMaxShortStringSize) {
+    map = is_ascii ? short_cons_ascii_string_map()
+      : short_cons_string_map();
+  } else if (length <= String::kMaxMediumStringSize) {
+    map = is_ascii ? medium_cons_ascii_string_map()
+      : medium_cons_string_map();
+  } else {
+    map = is_ascii ? long_cons_ascii_string_map()
+      : long_cons_string_map();
+  }
+
+  Object* result = Allocate(map, NEW_SPACE);
+  if (result->IsFailure()) return result;
+  ASSERT(InNewSpace(result));
+  ConsString* cons_string = ConsString::cast(result);
+  cons_string->set_first(first, SKIP_WRITE_BARRIER);
+  cons_string->set_second(second, SKIP_WRITE_BARRIER);
+  cons_string->set_length(length);
+  return result;
+}
+
+
+Object* Heap::AllocateSlicedString(String* buffer,
+                                   int start,
+                                   int end) {
+  int length = end - start;
+
+  // If the resulting string is small make a sub string.
+  if (end - start <= String::kMinNonFlatLength) {
+    return Heap::AllocateSubString(buffer, start, end);
+  }
+
+  Map* map;
+  if (length <= String::kMaxShortStringSize) {
+    map = StringShape(buffer).IsAsciiRepresentation() ?
+      short_sliced_ascii_string_map() :
+      short_sliced_string_map();
+  } else if (length <= String::kMaxMediumStringSize) {
+    map = StringShape(buffer).IsAsciiRepresentation() ?
+      medium_sliced_ascii_string_map() :
+      medium_sliced_string_map();
+  } else {
+    map = StringShape(buffer).IsAsciiRepresentation() ?
+      long_sliced_ascii_string_map() :
+      long_sliced_string_map();
+  }
+
+  Object* result = Allocate(map, NEW_SPACE);
+  if (result->IsFailure()) return result;
+
+  SlicedString* sliced_string = SlicedString::cast(result);
+  sliced_string->set_buffer(buffer);
+  sliced_string->set_start(start);
+  sliced_string->set_length(length);
+
+  return result;
+}
+
+
+Object* Heap::AllocateSubString(String* buffer,
+                                int start,
+                                int end) {
+  int length = end - start;
+
+  if (length == 1) {
+    return Heap::LookupSingleCharacterStringFromCode(
+        buffer->Get(start));
+  }
+
+  // Make an attempt to flatten the buffer to reduce access time.
+  if (!buffer->IsFlat()) {
+    buffer->TryFlatten();
+  }
+
+  Object* result = StringShape(buffer).IsAsciiRepresentation()
+      ? AllocateRawAsciiString(length)
+      : AllocateRawTwoByteString(length);
+  if (result->IsFailure()) return result;
+
+  // Copy the characters into the new object.
+  String* string_result = String::cast(result);
+  StringHasher hasher(length);
+  int i = 0;
+  for (; i < length && hasher.is_array_index(); i++) {
+    uc32 c = buffer->Get(start + i);
+    hasher.AddCharacter(c);
+    string_result->Set(i, c);
+  }
+  for (; i < length; i++) {
+    uc32 c = buffer->Get(start + i);
+    hasher.AddCharacterNoIndex(c);
+    string_result->Set(i, c);
+  }
+  string_result->set_length_field(hasher.GetHashField());
+  return result;
+}
+
+
+Object* Heap::AllocateExternalStringFromAscii(
+    ExternalAsciiString::Resource* resource) {
+  Map* map;
+  int length = resource->length();
+  if (length <= String::kMaxShortStringSize) {
+    map = short_external_ascii_string_map();
+  } else if (length <= String::kMaxMediumStringSize) {
+    map = medium_external_ascii_string_map();
+  } else {
+    map = long_external_ascii_string_map();
+  }
+
+  Object* result = Allocate(map, NEW_SPACE);
+  if (result->IsFailure()) return result;
+
+  ExternalAsciiString* external_string = ExternalAsciiString::cast(result);
+  external_string->set_length(length);
+  external_string->set_resource(resource);
+
+  return result;
+}
+
+
+Object* Heap::AllocateExternalStringFromTwoByte(
+    ExternalTwoByteString::Resource* resource) {
+  int length = resource->length();
+
+  Map* map = ExternalTwoByteString::StringMap(length);
+  Object* result = Allocate(map, NEW_SPACE);
+  if (result->IsFailure()) return result;
+
+  ExternalTwoByteString* external_string = ExternalTwoByteString::cast(result);
+  external_string->set_length(length);
+  external_string->set_resource(resource);
+
+  return result;
+}
+
+
+Object* Heap::LookupSingleCharacterStringFromCode(uint16_t code) {
+  if (code <= String::kMaxAsciiCharCode) {
+    Object* value = Heap::single_character_string_cache()->get(code);
+    if (value != Heap::undefined_value()) return value;
+
+    char buffer[1];
+    buffer[0] = static_cast<char>(code);
+    Object* result = LookupSymbol(Vector<const char>(buffer, 1));
+
+    if (result->IsFailure()) return result;
+    Heap::single_character_string_cache()->set(code, result);
+    return result;
+  }
+
+  Object* result = Heap::AllocateRawTwoByteString(1);
+  if (result->IsFailure()) return result;
+  String* answer = String::cast(result);
+  answer->Set(0, code);
+  return answer;
+}
+
+
+Object* Heap::AllocateByteArray(int length, PretenureFlag pretenure) {
+  if (pretenure == NOT_TENURED) {
+    return AllocateByteArray(length);
+  }
+  int size = ByteArray::SizeFor(length);
+  AllocationSpace space =
+      size > MaxHeapObjectSize() ? LO_SPACE : OLD_DATA_SPACE;
+
+  Object* result = AllocateRaw(size, space, OLD_DATA_SPACE);
+
+  if (result->IsFailure()) return result;
+
+  reinterpret_cast<Array*>(result)->set_map(byte_array_map());
+  reinterpret_cast<Array*>(result)->set_length(length);
+  return result;
+}
+
+
+Object* Heap::AllocateByteArray(int length) {
+  int size = ByteArray::SizeFor(length);
+  AllocationSpace space =
+      size > MaxHeapObjectSize() ? LO_SPACE : NEW_SPACE;
+
+  Object* result = AllocateRaw(size, space, OLD_DATA_SPACE);
+
+  if (result->IsFailure()) return result;
+
+  reinterpret_cast<Array*>(result)->set_map(byte_array_map());
+  reinterpret_cast<Array*>(result)->set_length(length);
+  return result;
+}
+
+
+void Heap::CreateFillerObjectAt(Address addr, int size) {
+  if (size == 0) return;
+  HeapObject* filler = HeapObject::FromAddress(addr);
+  if (size == kPointerSize) {
+    filler->set_map(Heap::one_word_filler_map());
+  } else {
+    filler->set_map(Heap::byte_array_map());
+    ByteArray::cast(filler)->set_length(ByteArray::LengthFor(size));
+  }
+}
+
+
+Object* Heap::CreateCode(const CodeDesc& desc,
+                         ScopeInfo<>* sinfo,
+                         Code::Flags flags,
+                         Handle<Object> self_reference) {
+  // Compute size
+  int body_size = RoundUp(desc.instr_size + desc.reloc_size, kObjectAlignment);
+  int sinfo_size = 0;
+  if (sinfo != NULL) sinfo_size = sinfo->Serialize(NULL);
+  int obj_size = Code::SizeFor(body_size, sinfo_size);
+  ASSERT(IsAligned(obj_size, Code::kCodeAlignment));
+  Object* result;
+  if (obj_size > MaxHeapObjectSize()) {
+    result = lo_space_->AllocateRawCode(obj_size);
+  } else {
+    result = code_space_->AllocateRaw(obj_size);
+  }
+
+  if (result->IsFailure()) return result;
+
+  // Initialize the object
+  HeapObject::cast(result)->set_map(code_map());
+  Code* code = Code::cast(result);
+  code->set_instruction_size(desc.instr_size);
+  code->set_relocation_size(desc.reloc_size);
+  code->set_sinfo_size(sinfo_size);
+  code->set_flags(flags);
+  code->set_ic_flag(Code::IC_TARGET_IS_ADDRESS);
+  // Allow self references to created code object by patching the handle to
+  // point to the newly allocated Code object.
+  if (!self_reference.is_null()) {
+    *(self_reference.location()) = code;
+  }
+  // Migrate generated code.
+  // The generated code can contain Object** values (typically from handles)
+  // that are dereferenced during the copy to point directly to the actual heap
+  // objects. These pointers can include references to the code object itself,
+  // through the self_reference parameter.
+  code->CopyFrom(desc);
+  if (sinfo != NULL) sinfo->Serialize(code);  // write scope info
+  LOG(CodeAllocateEvent(code, desc.origin));
+
+#ifdef DEBUG
+  code->Verify();
+#endif
+  return code;
+}
+
+
+Object* Heap::CopyCode(Code* code) {
+  // Allocate an object the same size as the code object.
+  int obj_size = code->Size();
+  Object* result;
+  if (obj_size > MaxHeapObjectSize()) {
+    result = lo_space_->AllocateRawCode(obj_size);
+  } else {
+    result = code_space_->AllocateRaw(obj_size);
+  }
+
+  if (result->IsFailure()) return result;
+
+  // Copy code object.
+  Address old_addr = code->address();
+  Address new_addr = reinterpret_cast<HeapObject*>(result)->address();
+  CopyBlock(reinterpret_cast<Object**>(new_addr),
+            reinterpret_cast<Object**>(old_addr),
+            obj_size);
+  // Relocate the copy.
+  Code* new_code = Code::cast(result);
+  new_code->Relocate(new_addr - old_addr);
+  return new_code;
+}
+
+
+Object* Heap::Allocate(Map* map, AllocationSpace space) {
+  ASSERT(gc_state_ == NOT_IN_GC);
+  ASSERT(map->instance_type() != MAP_TYPE);
+  Object* result = AllocateRaw(map->instance_size(),
+                               space,
+                               TargetSpaceId(map->instance_type()));
+  if (result->IsFailure()) return result;
+  HeapObject::cast(result)->set_map(map);
+  return result;
+}
+
+
+Object* Heap::InitializeFunction(JSFunction* function,
+                                 SharedFunctionInfo* shared,
+                                 Object* prototype) {
+  ASSERT(!prototype->IsMap());
+  function->initialize_properties();
+  function->initialize_elements();
+  function->set_shared(shared);
+  function->set_prototype_or_initial_map(prototype);
+  function->set_context(undefined_value());
+  function->set_literals(empty_fixed_array(), SKIP_WRITE_BARRIER);
+  return function;
+}
+
+
+Object* Heap::AllocateFunctionPrototype(JSFunction* function) {
+  // Allocate the prototype.  Make sure to use the object function
+  // from the function's context, since the function can be from a
+  // different context.
+  JSFunction* object_function =
+      function->context()->global_context()->object_function();
+  Object* prototype = AllocateJSObject(object_function);
+  if (prototype->IsFailure()) return prototype;
+  // When creating the prototype for the function we must set its
+  // constructor to the function.
+  Object* result =
+      JSObject::cast(prototype)->SetProperty(constructor_symbol(),
+                                             function,
+                                             DONT_ENUM);
+  if (result->IsFailure()) return result;
+  return prototype;
+}
+
+
+Object* Heap::AllocateFunction(Map* function_map,
+                               SharedFunctionInfo* shared,
+                               Object* prototype) {
+  Object* result = Allocate(function_map, OLD_POINTER_SPACE);
+  if (result->IsFailure()) return result;
+  return InitializeFunction(JSFunction::cast(result), shared, prototype);
+}
+
+
+Object* Heap::AllocateArgumentsObject(Object* callee, int length) {
+  // To get fast allocation and map sharing for arguments objects we
+  // allocate them based on an arguments boilerplate.
+
+  // This calls Copy directly rather than using Heap::AllocateRaw so we
+  // duplicate the check here.
+  ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC);
+
+  JSObject* boilerplate =
+      Top::context()->global_context()->arguments_boilerplate();
+
+  // Make the clone.
+  Map* map = boilerplate->map();
+  int object_size = map->instance_size();
+  Object* result = AllocateRaw(object_size, NEW_SPACE, OLD_POINTER_SPACE);
+  if (result->IsFailure()) return result;
+
+  // Copy the content. The arguments boilerplate doesn't have any
+  // fields that point to new space so it's safe to skip the write
+  // barrier here.
+  CopyBlock(reinterpret_cast<Object**>(HeapObject::cast(result)->address()),
+            reinterpret_cast<Object**>(boilerplate->address()),
+            object_size);
+
+  // Set the two properties.
+  JSObject::cast(result)->InObjectPropertyAtPut(arguments_callee_index,
+                                                callee);
+  JSObject::cast(result)->InObjectPropertyAtPut(arguments_length_index,
+                                                Smi::FromInt(length),
+                                                SKIP_WRITE_BARRIER);
+
+  // Check the state of the object
+  ASSERT(JSObject::cast(result)->HasFastProperties());
+  ASSERT(JSObject::cast(result)->HasFastElements());
+
+  return result;
+}
+
+
+Object* Heap::AllocateInitialMap(JSFunction* fun) {
+  ASSERT(!fun->has_initial_map());
+
+  // First create a new map with the expected number of properties being
+  // allocated in-object.
+  int expected_nof_properties = fun->shared()->expected_nof_properties();
+  int instance_size = JSObject::kHeaderSize +
+                      expected_nof_properties * kPointerSize;
+  if (instance_size > JSObject::kMaxInstanceSize) {
+    instance_size = JSObject::kMaxInstanceSize;
+    expected_nof_properties = (instance_size - JSObject::kHeaderSize) /
+                              kPointerSize;
+  }
+  Object* map_obj = Heap::AllocateMap(JS_OBJECT_TYPE, instance_size);
+  if (map_obj->IsFailure()) return map_obj;
+
+  // Fetch or allocate prototype.
+  Object* prototype;
+  if (fun->has_instance_prototype()) {
+    prototype = fun->instance_prototype();
+  } else {
+    prototype = AllocateFunctionPrototype(fun);
+    if (prototype->IsFailure()) return prototype;
+  }
+  Map* map = Map::cast(map_obj);
+  map->set_inobject_properties(expected_nof_properties);
+  map->set_unused_property_fields(expected_nof_properties);
+  map->set_prototype(prototype);
+  return map;
+}
+
+
+void Heap::InitializeJSObjectFromMap(JSObject* obj,
+                                     FixedArray* properties,
+                                     Map* map) {
+  obj->set_properties(properties);
+  obj->initialize_elements();
+  // TODO(1240798): Initialize the object's body using valid initial values
+  // according to the object's initial map.  For example, if the map's
+  // instance type is JS_ARRAY_TYPE, the length field should be initialized
+  // to a number (eg, Smi::FromInt(0)) and the elements initialized to a
+  // fixed array (eg, Heap::empty_fixed_array()).  Currently, the object
+  // verification code has to cope with (temporarily) invalid objects.  See
+  // for example, JSArray::JSArrayVerify).
+  obj->InitializeBody(map->instance_size());
+}
+
+
+Object* Heap::AllocateJSObjectFromMap(Map* map, PretenureFlag pretenure) {
+  // JSFunctions should be allocated using AllocateFunction to be
+  // properly initialized.
+  ASSERT(map->instance_type() != JS_FUNCTION_TYPE);
+
+  // Allocate the backing storage for the properties.
+  int prop_size = map->unused_property_fields() - map->inobject_properties();
+  Object* properties = AllocateFixedArray(prop_size);
+  if (properties->IsFailure()) return properties;
+
+  // Allocate the JSObject.
+  AllocationSpace space =
+      (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE;
+  if (map->instance_size() > MaxHeapObjectSize()) space = LO_SPACE;
+  Object* obj = Allocate(map, space);
+  if (obj->IsFailure()) return obj;
+
+  // Initialize the JSObject.
+  InitializeJSObjectFromMap(JSObject::cast(obj),
+                            FixedArray::cast(properties),
+                            map);
+  return obj;
+}
+
+
+Object* Heap::AllocateJSObject(JSFunction* constructor,
+                               PretenureFlag pretenure) {
+  // Allocate the initial map if absent.
+  if (!constructor->has_initial_map()) {
+    Object* initial_map = AllocateInitialMap(constructor);
+    if (initial_map->IsFailure()) return initial_map;
+    constructor->set_initial_map(Map::cast(initial_map));
+    Map::cast(initial_map)->set_constructor(constructor);
+  }
+  // Allocate the object based on the constructors initial map.
+  return AllocateJSObjectFromMap(constructor->initial_map(), pretenure);
+}
+
+
+Object* Heap::CopyJSObject(JSObject* source) {
+  // Never used to copy functions.  If functions need to be copied we
+  // have to be careful to clear the literals array.
+  ASSERT(!source->IsJSFunction());
+
+  // Make the clone.
+  Map* map = source->map();
+  int object_size = map->instance_size();
+  Object* clone;
+
+  // If we're forced to always allocate, we use the general allocation
+  // functions which may leave us with an object in old space.
+  if (always_allocate()) {
+    clone = AllocateRaw(object_size, NEW_SPACE, OLD_POINTER_SPACE);
+    if (clone->IsFailure()) return clone;
+    Address clone_address = HeapObject::cast(clone)->address();
+    CopyBlock(reinterpret_cast<Object**>(clone_address),
+              reinterpret_cast<Object**>(source->address()),
+              object_size);
+    // Update write barrier for all fields that lie beyond the header.
+    for (int offset = JSObject::kHeaderSize;
+         offset < object_size;
+         offset += kPointerSize) {
+      RecordWrite(clone_address, offset);
+    }
+  } else {
+    clone = new_space_.AllocateRaw(object_size);
+    if (clone->IsFailure()) return clone;
+    ASSERT(Heap::InNewSpace(clone));
+    // Since we know the clone is allocated in new space, we can copy
+    // the contents without worrying about updating the write barrier.
+    CopyBlock(reinterpret_cast<Object**>(HeapObject::cast(clone)->address()),
+              reinterpret_cast<Object**>(source->address()),
+              object_size);
+  }
+
+  FixedArray* elements = FixedArray::cast(source->elements());
+  FixedArray* properties = FixedArray::cast(source->properties());
+  // Update elements if necessary.
+  if (elements->length()> 0) {
+    Object* elem = CopyFixedArray(elements);
+    if (elem->IsFailure()) return elem;
+    JSObject::cast(clone)->set_elements(FixedArray::cast(elem));
+  }
+  // Update properties if necessary.
+  if (properties->length() > 0) {
+    Object* prop = CopyFixedArray(properties);
+    if (prop->IsFailure()) return prop;
+    JSObject::cast(clone)->set_properties(FixedArray::cast(prop));
+  }
+  // Return the new clone.
+  return clone;
+}
+
+
+Object* Heap::ReinitializeJSGlobalProxy(JSFunction* constructor,
+                                        JSGlobalProxy* object) {
+  // Allocate initial map if absent.
+  if (!constructor->has_initial_map()) {
+    Object* initial_map = AllocateInitialMap(constructor);
+    if (initial_map->IsFailure()) return initial_map;
+    constructor->set_initial_map(Map::cast(initial_map));
+    Map::cast(initial_map)->set_constructor(constructor);
+  }
+
+  Map* map = constructor->initial_map();
+
+  // Check that the already allocated object has the same size as
+  // objects allocated using the constructor.
+  ASSERT(map->instance_size() == object->map()->instance_size());
+
+  // Allocate the backing storage for the properties.
+  int prop_size = map->unused_property_fields() - map->inobject_properties();
+  Object* properties = AllocateFixedArray(prop_size);
+  if (properties->IsFailure()) return properties;
+
+  // Reset the map for the object.
+  object->set_map(constructor->initial_map());
+
+  // Reinitialize the object from the constructor map.
+  InitializeJSObjectFromMap(object, FixedArray::cast(properties), map);
+  return object;
+}
+
+
+Object* Heap::AllocateStringFromAscii(Vector<const char> string,
+                                      PretenureFlag pretenure) {
+  Object* result = AllocateRawAsciiString(string.length(), pretenure);
+  if (result->IsFailure()) return result;
+
+  // Copy the characters into the new object.
+  SeqAsciiString* string_result = SeqAsciiString::cast(result);
+  for (int i = 0; i < string.length(); i++) {
+    string_result->SeqAsciiStringSet(i, string[i]);
+  }
+  return result;
+}
+
+
+Object* Heap::AllocateStringFromUtf8(Vector<const char> string,
+                                     PretenureFlag pretenure) {
+  // 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());
+  decoder->Reset(string.start(), string.length());
+  int chars = 0;
+  bool is_ascii = true;
+  while (decoder->has_more()) {
+    uc32 r = decoder->GetNext();
+    if (r > String::kMaxAsciiCharCode) is_ascii = false;
+    chars++;
+  }
+
+  // If the string is ascii, we do not need to convert the characters
+  // since UTF8 is backwards compatible with ascii.
+  if (is_ascii) return AllocateStringFromAscii(string, pretenure);
+
+  Object* result = AllocateRawTwoByteString(chars, pretenure);
+  if (result->IsFailure()) return result;
+
+  // Convert and copy the characters into the new object.
+  String* string_result = String::cast(result);
+  decoder->Reset(string.start(), string.length());
+  for (int i = 0; i < chars; i++) {
+    uc32 r = decoder->GetNext();
+    string_result->Set(i, r);
+  }
+  return result;
+}
+
+
+Object* Heap::AllocateStringFromTwoByte(Vector<const uc16> string,
+                                        PretenureFlag pretenure) {
+  // Check if the string is an ASCII string.
+  int i = 0;
+  while (i < string.length() && string[i] <= String::kMaxAsciiCharCode) i++;
+
+  Object* result;
+  if (i == string.length()) {  // It's an ASCII string.
+    result = AllocateRawAsciiString(string.length(), pretenure);
+  } else {  // It's not an ASCII string.
+    result = AllocateRawTwoByteString(string.length(), pretenure);
+  }
+  if (result->IsFailure()) return result;
+
+  // Copy the characters into the new object, which may be either ASCII or
+  // UTF-16.
+  String* string_result = String::cast(result);
+  for (int i = 0; i < string.length(); i++) {
+    string_result->Set(i, string[i]);
+  }
+  return result;
+}
+
+
+Map* Heap::SymbolMapForString(String* string) {
+  // If the string is in new space it cannot be used as a symbol.
+  if (InNewSpace(string)) return NULL;
+
+  // Find the corresponding symbol map for strings.
+  Map* map = string->map();
+
+  if (map == short_ascii_string_map()) return short_ascii_symbol_map();
+  if (map == medium_ascii_string_map()) return medium_ascii_symbol_map();
+  if (map == long_ascii_string_map()) return long_ascii_symbol_map();
+
+  if (map == short_string_map()) return short_symbol_map();
+  if (map == medium_string_map()) return medium_symbol_map();
+  if (map == long_string_map()) return long_symbol_map();
+
+  if (map == short_cons_string_map()) return short_cons_symbol_map();
+  if (map == medium_cons_string_map()) return medium_cons_symbol_map();
+  if (map == long_cons_string_map()) return long_cons_symbol_map();
+
+  if (map == short_cons_ascii_string_map()) {
+    return short_cons_ascii_symbol_map();
+  }
+  if (map == medium_cons_ascii_string_map()) {
+    return medium_cons_ascii_symbol_map();
+  }
+  if (map == long_cons_ascii_string_map()) {
+    return long_cons_ascii_symbol_map();
+  }
+
+  if (map == short_sliced_string_map()) return short_sliced_symbol_map();
+  if (map == medium_sliced_string_map()) return medium_sliced_symbol_map();
+  if (map == long_sliced_string_map()) return long_sliced_symbol_map();
+
+  if (map == short_sliced_ascii_string_map()) {
+    return short_sliced_ascii_symbol_map();
+  }
+  if (map == medium_sliced_ascii_string_map()) {
+    return medium_sliced_ascii_symbol_map();
+  }
+  if (map == long_sliced_ascii_string_map()) {
+    return long_sliced_ascii_symbol_map();
+  }
+
+  if (map == short_external_string_map()) {
+    return short_external_symbol_map();
+  }
+  if (map == medium_external_string_map()) {
+    return medium_external_symbol_map();
+  }
+  if (map == long_external_string_map()) {
+    return long_external_symbol_map();
+  }
+
+  if (map == short_external_ascii_string_map()) {
+    return short_external_ascii_symbol_map();
+  }
+  if (map == medium_external_ascii_string_map()) {
+    return medium_external_ascii_symbol_map();
+  }
+  if (map == long_external_ascii_string_map()) {
+    return long_external_ascii_symbol_map();
+  }
+
+  // No match found.
+  return NULL;
+}
+
+
+Object* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer,
+                                     int chars,
+                                     uint32_t length_field) {
+  // Ensure the chars matches the number of characters in the buffer.
+  ASSERT(static_cast<unsigned>(chars) == buffer->Length());
+  // Determine whether the string is ascii.
+  bool is_ascii = true;
+  while (buffer->has_more() && is_ascii) {
+    if (buffer->GetNext() > unibrow::Utf8::kMaxOneByteChar) is_ascii = false;
+  }
+  buffer->Rewind();
+
+  // Compute map and object size.
+  int size;
+  Map* map;
+
+  if (is_ascii) {
+    if (chars <= String::kMaxShortStringSize) {
+      map = short_ascii_symbol_map();
+    } else if (chars <= String::kMaxMediumStringSize) {
+      map = medium_ascii_symbol_map();
+    } else {
+      map = long_ascii_symbol_map();
+    }
+    size = SeqAsciiString::SizeFor(chars);
+  } else {
+    if (chars <= String::kMaxShortStringSize) {
+      map = short_symbol_map();
+    } else if (chars <= String::kMaxMediumStringSize) {
+      map = medium_symbol_map();
+    } else {
+      map = long_symbol_map();
+    }
+    size = SeqTwoByteString::SizeFor(chars);
+  }
+
+  // Allocate string.
+  AllocationSpace space =
+      (size > MaxHeapObjectSize()) ? LO_SPACE : OLD_DATA_SPACE;
+  Object* result = AllocateRaw(size, space, OLD_DATA_SPACE);
+  if (result->IsFailure()) return result;
+
+  reinterpret_cast<HeapObject*>(result)->set_map(map);
+  // The hash value contains the length of the string.
+  String* answer = String::cast(result);
+  answer->set_length_field(length_field);
+
+  ASSERT_EQ(size, answer->Size());
+
+  // Fill in the characters.
+  for (int i = 0; i < chars; i++) {
+    answer->Set(i, buffer->GetNext());
+  }
+  return answer;
+}
+
+
+Object* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) {
+  AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
+  int size = SeqAsciiString::SizeFor(length);
+  if (size > MaxHeapObjectSize()) {
+    space = LO_SPACE;
+  }
+
+  // Use AllocateRaw rather than Allocate because the object's size cannot be
+  // determined from the map.
+  Object* result = AllocateRaw(size, space, OLD_DATA_SPACE);
+  if (result->IsFailure()) return result;
+
+  // Determine the map based on the string's length.
+  Map* map;
+  if (length <= String::kMaxShortStringSize) {
+    map = short_ascii_string_map();
+  } else if (length <= String::kMaxMediumStringSize) {
+    map = medium_ascii_string_map();
+  } else {
+    map = long_ascii_string_map();
+  }
+
+  // Partially initialize the object.
+  HeapObject::cast(result)->set_map(map);
+  String::cast(result)->set_length(length);
+  ASSERT_EQ(size, HeapObject::cast(result)->Size());
+  return result;
+}
+
+
+Object* Heap::AllocateRawTwoByteString(int length, PretenureFlag pretenure) {
+  AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
+  int size = SeqTwoByteString::SizeFor(length);
+  if (size > MaxHeapObjectSize()) {
+    space = LO_SPACE;
+  }
+
+  // Use AllocateRaw rather than Allocate because the object's size cannot be
+  // determined from the map.
+  Object* result = AllocateRaw(size, space, OLD_DATA_SPACE);
+  if (result->IsFailure()) return result;
+
+  // Determine the map based on the string's length.
+  Map* map;
+  if (length <= String::kMaxShortStringSize) {
+    map = short_string_map();
+  } else if (length <= String::kMaxMediumStringSize) {
+    map = medium_string_map();
+  } else {
+    map = long_string_map();
+  }
+
+  // Partially initialize the object.
+  HeapObject::cast(result)->set_map(map);
+  String::cast(result)->set_length(length);
+  ASSERT_EQ(size, HeapObject::cast(result)->Size());
+  return result;
+}
+
+
+Object* Heap::AllocateEmptyFixedArray() {
+  int size = FixedArray::SizeFor(0);
+  Object* result = AllocateRaw(size, OLD_DATA_SPACE, OLD_DATA_SPACE);
+  if (result->IsFailure()) return result;
+  // Initialize the object.
+  reinterpret_cast<Array*>(result)->set_map(fixed_array_map());
+  reinterpret_cast<Array*>(result)->set_length(0);
+  return result;
+}
+
+
+Object* Heap::AllocateRawFixedArray(int length) {
+  // Use the general function if we're forced to always allocate.
+  if (always_allocate()) return AllocateFixedArray(length, NOT_TENURED);
+  // Allocate the raw data for a fixed array.
+  int size = FixedArray::SizeFor(length);
+  return (size > MaxHeapObjectSize())
+      ? lo_space_->AllocateRawFixedArray(size)
+      : new_space_.AllocateRaw(size);
+}
+
+
+Object* Heap::CopyFixedArray(FixedArray* src) {
+  int len = src->length();
+  Object* obj = AllocateRawFixedArray(len);
+  if (obj->IsFailure()) return obj;
+  if (Heap::InNewSpace(obj)) {
+    HeapObject* dst = HeapObject::cast(obj);
+    CopyBlock(reinterpret_cast<Object**>(dst->address()),
+              reinterpret_cast<Object**>(src->address()),
+              FixedArray::SizeFor(len));
+    return obj;
+  }
+  HeapObject::cast(obj)->set_map(src->map());
+  FixedArray* result = FixedArray::cast(obj);
+  result->set_length(len);
+  // Copy the content
+  WriteBarrierMode mode = result->GetWriteBarrierMode();
+  for (int i = 0; i < len; i++) result->set(i, src->get(i), mode);
+  return result;
+}
+
+
+Object* Heap::AllocateFixedArray(int length) {
+  if (length == 0) return empty_fixed_array();
+  Object* result = AllocateRawFixedArray(length);
+  if (!result->IsFailure()) {
+    // Initialize header.
+    reinterpret_cast<Array*>(result)->set_map(fixed_array_map());
+    FixedArray* array = FixedArray::cast(result);
+    array->set_length(length);
+    Object* value = undefined_value();
+    // Initialize body.
+    for (int index = 0; index < length; index++) {
+      array->set(index, value, SKIP_WRITE_BARRIER);
+    }
+  }
+  return result;
+}
+
+
+Object* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) {
+  ASSERT(empty_fixed_array()->IsFixedArray());
+  if (length == 0) return empty_fixed_array();
+
+  int size = FixedArray::SizeFor(length);
+  Object* result;
+  if (size > MaxHeapObjectSize()) {
+    result = lo_space_->AllocateRawFixedArray(size);
+  } else {
+    AllocationSpace space =
+        (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE;
+    result = AllocateRaw(size, space, OLD_POINTER_SPACE);
+  }
+  if (result->IsFailure()) return result;
+
+  // Initialize the object.
+  reinterpret_cast<Array*>(result)->set_map(fixed_array_map());
+  FixedArray* array = FixedArray::cast(result);
+  array->set_length(length);
+  Object* value = undefined_value();
+  for (int index = 0; index < length; index++) {
+    array->set(index, value, SKIP_WRITE_BARRIER);
+  }
+  return array;
+}
+
+
+Object* Heap::AllocateFixedArrayWithHoles(int length) {
+  if (length == 0) return empty_fixed_array();
+  Object* result = AllocateRawFixedArray(length);
+  if (!result->IsFailure()) {
+    // Initialize header.
+    reinterpret_cast<Array*>(result)->set_map(fixed_array_map());
+    FixedArray* array = FixedArray::cast(result);
+    array->set_length(length);
+    // Initialize body.
+    Object* value = the_hole_value();
+    for (int index = 0; index < length; index++)  {
+      array->set(index, value, SKIP_WRITE_BARRIER);
+    }
+  }
+  return result;
+}
+
+
+Object* Heap::AllocateHashTable(int length) {
+  Object* result = Heap::AllocateFixedArray(length);
+  if (result->IsFailure()) return result;
+  reinterpret_cast<Array*>(result)->set_map(hash_table_map());
+  ASSERT(result->IsDictionary());
+  return result;
+}
+
+
+Object* Heap::AllocateGlobalContext() {
+  Object* result = Heap::AllocateFixedArray(Context::GLOBAL_CONTEXT_SLOTS);
+  if (result->IsFailure()) return result;
+  Context* context = reinterpret_cast<Context*>(result);
+  context->set_map(global_context_map());
+  ASSERT(context->IsGlobalContext());
+  ASSERT(result->IsContext());
+  return result;
+}
+
+
+Object* Heap::AllocateFunctionContext(int length, JSFunction* function) {
+  ASSERT(length >= Context::MIN_CONTEXT_SLOTS);
+  Object* result = Heap::AllocateFixedArray(length);
+  if (result->IsFailure()) return result;
+  Context* context = reinterpret_cast<Context*>(result);
+  context->set_map(context_map());
+  context->set_closure(function);
+  context->set_fcontext(context);
+  context->set_previous(NULL);
+  context->set_extension(NULL);
+  context->set_global(function->context()->global());
+  ASSERT(!context->IsGlobalContext());
+  ASSERT(context->is_function_context());
+  ASSERT(result->IsContext());
+  return result;
+}
+
+
+Object* Heap::AllocateWithContext(Context* previous,
+                                  JSObject* extension,
+                                  bool is_catch_context) {
+  Object* result = Heap::AllocateFixedArray(Context::MIN_CONTEXT_SLOTS);
+  if (result->IsFailure()) return result;
+  Context* context = reinterpret_cast<Context*>(result);
+  context->set_map(is_catch_context ? catch_context_map() : context_map());
+  context->set_closure(previous->closure());
+  context->set_fcontext(previous->fcontext());
+  context->set_previous(previous);
+  context->set_extension(extension);
+  context->set_global(previous->global());
+  ASSERT(!context->IsGlobalContext());
+  ASSERT(!context->is_function_context());
+  ASSERT(result->IsContext());
+  return result;
+}
+
+
+Object* Heap::AllocateStruct(InstanceType type) {
+  Map* map;
+  switch (type) {
+#define MAKE_CASE(NAME, Name, name) case NAME##_TYPE: map = name##_map(); break;
+STRUCT_LIST(MAKE_CASE)
+#undef MAKE_CASE
+    default:
+      UNREACHABLE();
+      return Failure::InternalError();
+  }
+  int size = map->instance_size();
+  AllocationSpace space =
+      (size > MaxHeapObjectSize()) ? LO_SPACE : OLD_POINTER_SPACE;
+  Object* result = Heap::Allocate(map, space);
+  if (result->IsFailure()) return result;
+  Struct::cast(result)->InitializeBody(size);
+  return result;
+}
+
+
+#ifdef DEBUG
+
+void Heap::Print() {
+  if (!HasBeenSetup()) return;
+  Top::PrintStack();
+  AllSpaces spaces;
+  while (Space* space = spaces.next()) space->Print();
+}
+
+
+void Heap::ReportCodeStatistics(const char* title) {
+  PrintF(">>>>>> Code Stats (%s) >>>>>>\n", title);
+  PagedSpace::ResetCodeStatistics();
+  // We do not look for code in new space, map space, or old space.  If code
+  // somehow ends up in those spaces, we would miss it here.
+  code_space_->CollectCodeStatistics();
+  lo_space_->CollectCodeStatistics();
+  PagedSpace::ReportCodeStatistics();
+}
+
+
+// This function expects that NewSpace's allocated objects histogram is
+// populated (via a call to CollectStatistics or else as a side effect of a
+// just-completed scavenge collection).
+void Heap::ReportHeapStatistics(const char* title) {
+  USE(title);
+  PrintF(">>>>>> =============== %s (%d) =============== >>>>>>\n",
+         title, gc_count_);
+  PrintF("mark-compact GC : %d\n", mc_count_);
+  PrintF("old_gen_promotion_limit_ %d\n", old_gen_promotion_limit_);
+  PrintF("old_gen_allocation_limit_ %d\n", old_gen_allocation_limit_);
+
+  PrintF("\n");
+  PrintF("Number of handles : %d\n", HandleScope::NumberOfHandles());
+  GlobalHandles::PrintStats();
+  PrintF("\n");
+
+  PrintF("Heap statistics : ");
+  MemoryAllocator::ReportStatistics();
+  PrintF("To space : ");
+  new_space_.ReportStatistics();
+  PrintF("Old pointer space : ");
+  old_pointer_space_->ReportStatistics();
+  PrintF("Old data space : ");
+  old_data_space_->ReportStatistics();
+  PrintF("Code space : ");
+  code_space_->ReportStatistics();
+  PrintF("Map space : ");
+  map_space_->ReportStatistics();
+  PrintF("Large object space : ");
+  lo_space_->ReportStatistics();
+  PrintF(">>>>>> ========================================= >>>>>>\n");
+}
+
+#endif  // DEBUG
+
+bool Heap::Contains(HeapObject* value) {
+  return Contains(value->address());
+}
+
+
+bool Heap::Contains(Address addr) {
+  if (OS::IsOutsideAllocatedSpace(addr)) return false;
+  return HasBeenSetup() &&
+    (new_space_.ToSpaceContains(addr) ||
+     old_pointer_space_->Contains(addr) ||
+     old_data_space_->Contains(addr) ||
+     code_space_->Contains(addr) ||
+     map_space_->Contains(addr) ||
+     lo_space_->SlowContains(addr));
+}
+
+
+bool Heap::InSpace(HeapObject* value, AllocationSpace space) {
+  return InSpace(value->address(), space);
+}
+
+
+bool Heap::InSpace(Address addr, AllocationSpace space) {
+  if (OS::IsOutsideAllocatedSpace(addr)) return false;
+  if (!HasBeenSetup()) return false;
+
+  switch (space) {
+    case NEW_SPACE:
+      return new_space_.ToSpaceContains(addr);
+    case OLD_POINTER_SPACE:
+      return old_pointer_space_->Contains(addr);
+    case OLD_DATA_SPACE:
+      return old_data_space_->Contains(addr);
+    case CODE_SPACE:
+      return code_space_->Contains(addr);
+    case MAP_SPACE:
+      return map_space_->Contains(addr);
+    case LO_SPACE:
+      return lo_space_->SlowContains(addr);
+  }
+
+  return false;
+}
+
+
+#ifdef DEBUG
+void Heap::Verify() {
+  ASSERT(HasBeenSetup());
+
+  VerifyPointersVisitor visitor;
+  Heap::IterateRoots(&visitor);
+
+  AllSpaces spaces;
+  while (Space* space = spaces.next()) {
+    space->Verify();
+  }
+}
+#endif  // DEBUG
+
+
+Object* Heap::LookupSymbol(Vector<const char> string) {
+  Object* symbol = NULL;
+  Object* new_table =
+      SymbolTable::cast(symbol_table_)->LookupSymbol(string, &symbol);
+  if (new_table->IsFailure()) return new_table;
+  symbol_table_ = new_table;
+  ASSERT(symbol != NULL);
+  return symbol;
+}
+
+
+Object* Heap::LookupSymbol(String* string) {
+  if (string->IsSymbol()) return string;
+  Object* symbol = NULL;
+  Object* new_table =
+      SymbolTable::cast(symbol_table_)->LookupString(string, &symbol);
+  if (new_table->IsFailure()) return new_table;
+  symbol_table_ = new_table;
+  ASSERT(symbol != NULL);
+  return symbol;
+}
+
+
+bool Heap::LookupSymbolIfExists(String* string, String** symbol) {
+  if (string->IsSymbol()) {
+    *symbol = string;
+    return true;
+  }
+  SymbolTable* table = SymbolTable::cast(symbol_table_);
+  return table->LookupSymbolIfExists(string, symbol);
+}
+
+
+#ifdef DEBUG
+void Heap::ZapFromSpace() {
+  ASSERT(HAS_HEAP_OBJECT_TAG(kFromSpaceZapValue));
+  for (Address a = new_space_.FromSpaceLow();
+       a < new_space_.FromSpaceHigh();
+       a += kPointerSize) {
+    Memory::Address_at(a) = kFromSpaceZapValue;
+  }
+}
+#endif  // DEBUG
+
+
+void Heap::IterateRSetRange(Address object_start,
+                            Address object_end,
+                            Address rset_start,
+                            ObjectSlotCallback copy_object_func) {
+  Address object_address = object_start;
+  Address rset_address = rset_start;
+
+  // Loop over all the pointers in [object_start, object_end).
+  while (object_address < object_end) {
+    uint32_t rset_word = Memory::uint32_at(rset_address);
+    if (rset_word != 0) {
+      uint32_t result_rset = rset_word;
+      for (uint32_t bitmask = 1; bitmask != 0; bitmask = bitmask << 1) {
+        // Do not dereference pointers at or past object_end.
+        if ((rset_word & bitmask) != 0 && object_address < object_end) {
+          Object** object_p = reinterpret_cast<Object**>(object_address);
+          if (Heap::InNewSpace(*object_p)) {
+            copy_object_func(reinterpret_cast<HeapObject**>(object_p));
+          }
+          // If this pointer does not need to be remembered anymore, clear
+          // the remembered set bit.
+          if (!Heap::InNewSpace(*object_p)) result_rset &= ~bitmask;
+        }
+        object_address += kPointerSize;
+      }
+      // Update the remembered set if it has changed.
+      if (result_rset != rset_word) {
+        Memory::uint32_at(rset_address) = result_rset;
+      }
+    } else {
+      // No bits in the word were set.  This is the common case.
+      object_address += kPointerSize * kBitsPerInt;
+    }
+    rset_address += kIntSize;
+  }
+}
+
+
+void Heap::IterateRSet(PagedSpace* space, ObjectSlotCallback copy_object_func) {
+  ASSERT(Page::is_rset_in_use());
+  ASSERT(space == old_pointer_space_ || space == map_space_);
+
+  PageIterator it(space, PageIterator::PAGES_IN_USE);
+  while (it.has_next()) {
+    Page* page = it.next();
+    IterateRSetRange(page->ObjectAreaStart(), page->AllocationTop(),
+                     page->RSetStart(), copy_object_func);
+  }
+}
+
+
+#ifdef DEBUG
+#define SYNCHRONIZE_TAG(tag) v->Synchronize(tag)
+#else
+#define SYNCHRONIZE_TAG(tag)
+#endif
+
+void Heap::IterateRoots(ObjectVisitor* v) {
+  IterateStrongRoots(v);
+  v->VisitPointer(reinterpret_cast<Object**>(&symbol_table_));
+  SYNCHRONIZE_TAG("symbol_table");
+}
+
+
+void Heap::IterateStrongRoots(ObjectVisitor* v) {
+#define ROOT_ITERATE(type, name) \
+  v->VisitPointer(bit_cast<Object**, type**>(&name##_));
+  STRONG_ROOT_LIST(ROOT_ITERATE);
+#undef ROOT_ITERATE
+  SYNCHRONIZE_TAG("strong_root_list");
+
+#define STRUCT_MAP_ITERATE(NAME, Name, name) \
+  v->VisitPointer(bit_cast<Object**, Map**>(&name##_map_));
+  STRUCT_LIST(STRUCT_MAP_ITERATE);
+#undef STRUCT_MAP_ITERATE
+  SYNCHRONIZE_TAG("struct_map");
+
+#define SYMBOL_ITERATE(name, string) \
+  v->VisitPointer(bit_cast<Object**, String**>(&name##_));
+  SYMBOL_LIST(SYMBOL_ITERATE)
+#undef SYMBOL_ITERATE
+  v->VisitPointer(bit_cast<Object**, String**>(&hidden_symbol_));
+  SYNCHRONIZE_TAG("symbol");
+
+  Bootstrapper::Iterate(v);
+  SYNCHRONIZE_TAG("bootstrapper");
+  Top::Iterate(v);
+  SYNCHRONIZE_TAG("top");
+  Debug::Iterate(v);
+  SYNCHRONIZE_TAG("debug");
+  CompilationCache::Iterate(v);
+  SYNCHRONIZE_TAG("compilationcache");
+
+  // Iterate over local handles in handle scopes.
+  HandleScopeImplementer::Iterate(v);
+  SYNCHRONIZE_TAG("handlescope");
+
+  // Iterate over the builtin code objects and code stubs in the heap. Note
+  // that it is not strictly necessary to iterate over code objects on
+  // scavenge collections.  We still do it here because this same function
+  // is used by the mark-sweep collector and the deserializer.
+  Builtins::IterateBuiltins(v);
+  SYNCHRONIZE_TAG("builtins");
+
+  // Iterate over global handles.
+  GlobalHandles::IterateRoots(v);
+  SYNCHRONIZE_TAG("globalhandles");
+
+  // Iterate over pointers being held by inactive threads.
+  ThreadManager::Iterate(v);
+  SYNCHRONIZE_TAG("threadmanager");
+}
+#undef SYNCHRONIZE_TAG
+
+
+// Flag is set when the heap has been configured.  The heap can be repeatedly
+// configured through the API until it is setup.
+static bool heap_configured = false;
+
+// TODO(1236194): Since the heap size is configurable on the command line
+// and through the API, we should gracefully handle the case that the heap
+// size is not big enough to fit all the initial objects.
+bool Heap::ConfigureHeap(int semispace_size, int old_gen_size) {
+  if (HasBeenSetup()) return false;
+
+  if (semispace_size > 0) semispace_size_ = semispace_size;
+  if (old_gen_size > 0) old_generation_size_ = old_gen_size;
+
+  // The new space size must be a power of two to support single-bit testing
+  // for containment.
+  semispace_size_ = RoundUpToPowerOf2(semispace_size_);
+  initial_semispace_size_ = Min(initial_semispace_size_, semispace_size_);
+  young_generation_size_ = 2 * semispace_size_;
+
+  // The old generation is paged.
+  old_generation_size_ = RoundUp(old_generation_size_, Page::kPageSize);
+
+  heap_configured = true;
+  return true;
+}
+
+
+bool Heap::ConfigureHeapDefault() {
+  return ConfigureHeap(FLAG_new_space_size, FLAG_old_space_size);
+}
+
+
+int Heap::PromotedSpaceSize() {
+  return old_pointer_space_->Size()
+      + old_data_space_->Size()
+      + code_space_->Size()
+      + map_space_->Size()
+      + lo_space_->Size();
+}
+
+
+int Heap::PromotedExternalMemorySize() {
+  if (amount_of_external_allocated_memory_
+      <= amount_of_external_allocated_memory_at_last_global_gc_) return 0;
+  return amount_of_external_allocated_memory_
+      - amount_of_external_allocated_memory_at_last_global_gc_;
+}
+
+
+bool Heap::Setup(bool create_heap_objects) {
+  // Initialize heap spaces and initial maps and objects. Whenever something
+  // goes wrong, just return false. The caller should check the results and
+  // call Heap::TearDown() to release allocated memory.
+  //
+  // If the heap is not yet configured (eg, through the API), configure it.
+  // Configuration is based on the flags new-space-size (really the semispace
+  // size) and old-space-size if set or the initial values of semispace_size_
+  // and old_generation_size_ otherwise.
+  if (!heap_configured) {
+    if (!ConfigureHeapDefault()) return false;
+  }
+
+  // Setup memory allocator and allocate an initial chunk of memory.  The
+  // initial chunk is double the size of the new space to ensure that we can
+  // find a pair of semispaces that are contiguous and aligned to their size.
+  if (!MemoryAllocator::Setup(MaxCapacity())) return false;
+  void* chunk
+      = MemoryAllocator::ReserveInitialChunk(2 * young_generation_size_);
+  if (chunk == NULL) return false;
+
+  // Put the initial chunk of the old space at the start of the initial
+  // chunk, then the two new space semispaces, then the initial chunk of
+  // code space.  Align the pair of semispaces to their size, which must be
+  // a power of 2.
+  ASSERT(IsPowerOf2(young_generation_size_));
+  Address code_space_start = reinterpret_cast<Address>(chunk);
+  Address new_space_start = RoundUp(code_space_start, young_generation_size_);
+  Address old_space_start = new_space_start + young_generation_size_;
+  int code_space_size = new_space_start - code_space_start;
+  int old_space_size = young_generation_size_ - code_space_size;
+
+  // Initialize new space.
+  if (!new_space_.Setup(new_space_start, young_generation_size_)) return false;
+
+  // Initialize old space, set the maximum capacity to the old generation
+  // size. It will not contain code.
+  old_pointer_space_ =
+      new OldSpace(old_generation_size_, OLD_POINTER_SPACE, NOT_EXECUTABLE);
+  if (old_pointer_space_ == NULL) return false;
+  if (!old_pointer_space_->Setup(old_space_start, old_space_size >> 1)) {
+    return false;
+  }
+  old_data_space_ =
+      new OldSpace(old_generation_size_, OLD_DATA_SPACE, NOT_EXECUTABLE);
+  if (old_data_space_ == NULL) return false;
+  if (!old_data_space_->Setup(old_space_start + (old_space_size >> 1),
+                              old_space_size >> 1)) {
+    return false;
+  }
+
+  // Initialize the code space, set its maximum capacity to the old
+  // generation size. It needs executable memory.
+  code_space_ =
+      new OldSpace(old_generation_size_, CODE_SPACE, EXECUTABLE);
+  if (code_space_ == NULL) return false;
+  if (!code_space_->Setup(code_space_start, code_space_size)) return false;
+
+  // Initialize map space.
+  map_space_ = new MapSpace(kMaxMapSpaceSize, MAP_SPACE);
+  if (map_space_ == NULL) return false;
+  // Setting up a paged space without giving it a virtual memory range big
+  // enough to hold at least a page will cause it to allocate.
+  if (!map_space_->Setup(NULL, 0)) return false;
+
+  // The large object code space may contain code or data.  We set the memory
+  // to be non-executable here for safety, but this means we need to enable it
+  // explicitly when allocating large code objects.
+  lo_space_ = new LargeObjectSpace(LO_SPACE);
+  if (lo_space_ == NULL) return false;
+  if (!lo_space_->Setup()) return false;
+
+  if (create_heap_objects) {
+    // Create initial maps.
+    if (!CreateInitialMaps()) return false;
+    if (!CreateApiObjects()) return false;
+
+    // Create initial objects
+    if (!CreateInitialObjects()) return false;
+  }
+
+  LOG(IntEvent("heap-capacity", Capacity()));
+  LOG(IntEvent("heap-available", Available()));
+
+  return true;
+}
+
+
+void Heap::TearDown() {
+  GlobalHandles::TearDown();
+
+  new_space_.TearDown();
+
+  if (old_pointer_space_ != NULL) {
+    old_pointer_space_->TearDown();
+    delete old_pointer_space_;
+    old_pointer_space_ = NULL;
+  }
+
+  if (old_data_space_ != NULL) {
+    old_data_space_->TearDown();
+    delete old_data_space_;
+    old_data_space_ = NULL;
+  }
+
+  if (code_space_ != NULL) {
+    code_space_->TearDown();
+    delete code_space_;
+    code_space_ = NULL;
+  }
+
+  if (map_space_ != NULL) {
+    map_space_->TearDown();
+    delete map_space_;
+    map_space_ = NULL;
+  }
+
+  if (lo_space_ != NULL) {
+    lo_space_->TearDown();
+    delete lo_space_;
+    lo_space_ = NULL;
+  }
+
+  MemoryAllocator::TearDown();
+}
+
+
+void Heap::Shrink() {
+  // Try to shrink map, old, and code spaces.
+  map_space_->Shrink();
+  old_pointer_space_->Shrink();
+  old_data_space_->Shrink();
+  code_space_->Shrink();
+}
+
+
+#ifdef ENABLE_HEAP_PROTECTION
+
+void Heap::Protect() {
+  if (HasBeenSetup()) {
+    new_space_.Protect();
+    map_space_->Protect();
+    old_pointer_space_->Protect();
+    old_data_space_->Protect();
+    code_space_->Protect();
+    lo_space_->Protect();
+  }
+}
+
+
+void Heap::Unprotect() {
+  if (HasBeenSetup()) {
+    new_space_.Unprotect();
+    map_space_->Unprotect();
+    old_pointer_space_->Unprotect();
+    old_data_space_->Unprotect();
+    code_space_->Unprotect();
+    lo_space_->Unprotect();
+  }
+}
+
+#endif
+
+
+#ifdef DEBUG
+
+class PrintHandleVisitor: public ObjectVisitor {
+ public:
+  void VisitPointers(Object** start, Object** end) {
+    for (Object** p = start; p < end; p++)
+      PrintF("  handle %p to %p\n", p, *p);
+  }
+};
+
+void Heap::PrintHandles() {
+  PrintF("Handles:\n");
+  PrintHandleVisitor v;
+  HandleScopeImplementer::Iterate(&v);
+}
+
+#endif
+
+
+Space* AllSpaces::next() {
+  switch (counter_++) {
+    case NEW_SPACE:
+      return Heap::new_space();
+    case OLD_POINTER_SPACE:
+      return Heap::old_pointer_space();
+    case OLD_DATA_SPACE:
+      return Heap::old_data_space();
+    case CODE_SPACE:
+      return Heap::code_space();
+    case MAP_SPACE:
+      return Heap::map_space();
+    case LO_SPACE:
+      return Heap::lo_space();
+    default:
+      return NULL;
+  }
+}
+
+
+PagedSpace* PagedSpaces::next() {
+  switch (counter_++) {
+    case OLD_POINTER_SPACE:
+      return Heap::old_pointer_space();
+    case OLD_DATA_SPACE:
+      return Heap::old_data_space();
+    case CODE_SPACE:
+      return Heap::code_space();
+    case MAP_SPACE:
+      return Heap::map_space();
+    default:
+      return NULL;
+  }
+}
+
+
+
+OldSpace* OldSpaces::next() {
+  switch (counter_++) {
+    case OLD_POINTER_SPACE:
+      return Heap::old_pointer_space();
+    case OLD_DATA_SPACE:
+      return Heap::old_data_space();
+    case CODE_SPACE:
+      return Heap::code_space();
+    default:
+      return NULL;
+  }
+}
+
+
+SpaceIterator::SpaceIterator() : current_space_(FIRST_SPACE), iterator_(NULL) {
+}
+
+
+SpaceIterator::~SpaceIterator() {
+  // Delete active iterator if any.
+  delete iterator_;
+}
+
+
+bool SpaceIterator::has_next() {
+  // Iterate until no more spaces.
+  return current_space_ != LAST_SPACE;
+}
+
+
+ObjectIterator* SpaceIterator::next() {
+  if (iterator_ != NULL) {
+    delete iterator_;
+    iterator_ = NULL;
+    // Move to the next space
+    current_space_++;
+    if (current_space_ > LAST_SPACE) {
+      return NULL;
+    }
+  }
+
+  // Return iterator for the new current space.
+  return CreateIterator();
+}
+
+
+// Create an iterator for the space to iterate.
+ObjectIterator* SpaceIterator::CreateIterator() {
+  ASSERT(iterator_ == NULL);
+
+  switch (current_space_) {
+    case NEW_SPACE:
+      iterator_ = new SemiSpaceIterator(Heap::new_space());
+      break;
+    case OLD_POINTER_SPACE:
+      iterator_ = new HeapObjectIterator(Heap::old_pointer_space());
+      break;
+    case OLD_DATA_SPACE:
+      iterator_ = new HeapObjectIterator(Heap::old_data_space());
+      break;
+    case CODE_SPACE:
+      iterator_ = new HeapObjectIterator(Heap::code_space());
+      break;
+    case MAP_SPACE:
+      iterator_ = new HeapObjectIterator(Heap::map_space());
+      break;
+    case LO_SPACE:
+      iterator_ = new LargeObjectIterator(Heap::lo_space());
+      break;
+  }
+
+  // Return the newly allocated iterator;
+  ASSERT(iterator_ != NULL);
+  return iterator_;
+}
+
+
+HeapIterator::HeapIterator() {
+  Init();
+}
+
+
+HeapIterator::~HeapIterator() {
+  Shutdown();
+}
+
+
+void HeapIterator::Init() {
+  // Start the iteration.
+  space_iterator_ = new SpaceIterator();
+  object_iterator_ = space_iterator_->next();
+}
+
+
+void HeapIterator::Shutdown() {
+  // Make sure the last iterator is deallocated.
+  delete space_iterator_;
+  space_iterator_ = NULL;
+  object_iterator_ = NULL;
+}
+
+
+bool HeapIterator::has_next() {
+  // No iterator means we are done.
+  if (object_iterator_ == NULL) return false;
+
+  if (object_iterator_->has_next_object()) {
+    // If the current iterator has more objects we are fine.
+    return true;
+  } else {
+    // Go though the spaces looking for one that has objects.
+    while (space_iterator_->has_next()) {
+      object_iterator_ = space_iterator_->next();
+      if (object_iterator_->has_next_object()) {
+        return true;
+      }
+    }
+  }
+  // Done with the last space.
+  object_iterator_ = NULL;
+  return false;
+}
+
+
+HeapObject* HeapIterator::next() {
+  if (has_next()) {
+    return object_iterator_->next_object();
+  } else {
+    return NULL;
+  }
+}
+
+
+void HeapIterator::reset() {
+  // Restart the iterator.
+  Shutdown();
+  Init();
+}
+
+
+//
+// HeapProfiler class implementation.
+//
+#ifdef ENABLE_LOGGING_AND_PROFILING
+void HeapProfiler::CollectStats(HeapObject* obj, HistogramInfo* info) {
+  InstanceType type = obj->map()->instance_type();
+  ASSERT(0 <= type && type <= LAST_TYPE);
+  info[type].increment_number(1);
+  info[type].increment_bytes(obj->Size());
+}
+#endif
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+void HeapProfiler::WriteSample() {
+  LOG(HeapSampleBeginEvent("Heap", "allocated"));
+
+  HistogramInfo info[LAST_TYPE+1];
+#define DEF_TYPE_NAME(name) info[name].set_name(#name);
+  INSTANCE_TYPE_LIST(DEF_TYPE_NAME)
+#undef DEF_TYPE_NAME
+
+  HeapIterator iterator;
+  while (iterator.has_next()) {
+    CollectStats(iterator.next(), info);
+  }
+
+  // Lump all the string types together.
+  int string_number = 0;
+  int string_bytes = 0;
+#define INCREMENT_SIZE(type, size, name)   \
+    string_number += info[type].number();  \
+    string_bytes += info[type].bytes();
+  STRING_TYPE_LIST(INCREMENT_SIZE)
+#undef INCREMENT_SIZE
+  if (string_bytes > 0) {
+    LOG(HeapSampleItemEvent("STRING_TYPE", string_number, string_bytes));
+  }
+
+  for (int i = FIRST_NONSTRING_TYPE; i <= LAST_TYPE; ++i) {
+    if (info[i].bytes() > 0) {
+      LOG(HeapSampleItemEvent(info[i].name(), info[i].number(),
+                              info[i].bytes()));
+    }
+  }
+
+  LOG(HeapSampleEndEvent("Heap", "allocated"));
+}
+
+
+#endif
+
+
+
+#ifdef DEBUG
+
+static bool search_for_any_global;
+static Object* search_target;
+static bool found_target;
+static List<Object*> object_stack(20);
+
+
+// Tags 0, 1, and 3 are used. Use 2 for marking visited HeapObject.
+static const int kMarkTag = 2;
+
+static void MarkObjectRecursively(Object** p);
+class MarkObjectVisitor : public ObjectVisitor {
+ public:
+  void VisitPointers(Object** start, Object** end) {
+    // Copy all HeapObject pointers in [start, end)
+    for (Object** p = start; p < end; p++) {
+      if ((*p)->IsHeapObject())
+        MarkObjectRecursively(p);
+    }
+  }
+};
+
+static MarkObjectVisitor mark_visitor;
+
+static void MarkObjectRecursively(Object** p) {
+  if (!(*p)->IsHeapObject()) return;
+
+  HeapObject* obj = HeapObject::cast(*p);
+
+  Object* map = obj->map();
+
+  if (!map->IsHeapObject()) return;  // visited before
+
+  if (found_target) return;  // stop if target found
+  object_stack.Add(obj);
+  if ((search_for_any_global && obj->IsJSGlobalObject()) ||
+      (!search_for_any_global && (obj == search_target))) {
+    found_target = true;
+    return;
+  }
+
+  if (obj->IsCode()) {
+    Code::cast(obj)->ConvertICTargetsFromAddressToObject();
+  }
+
+  // not visited yet
+  Map* map_p = reinterpret_cast<Map*>(HeapObject::cast(map));
+
+  Address map_addr = map_p->address();
+
+  obj->set_map(reinterpret_cast<Map*>(map_addr + kMarkTag));
+
+  MarkObjectRecursively(&map);
+
+  obj->IterateBody(map_p->instance_type(), obj->SizeFromMap(map_p),
+                   &mark_visitor);
+
+  if (!found_target)  // don't pop if found the target
+    object_stack.RemoveLast();
+}
+
+
+static void UnmarkObjectRecursively(Object** p);
+class UnmarkObjectVisitor : public ObjectVisitor {
+ public:
+  void VisitPointers(Object** start, Object** end) {
+    // Copy all HeapObject pointers in [start, end)
+    for (Object** p = start; p < end; p++) {
+      if ((*p)->IsHeapObject())
+        UnmarkObjectRecursively(p);
+    }
+  }
+};
+
+static UnmarkObjectVisitor unmark_visitor;
+
+static void UnmarkObjectRecursively(Object** p) {
+  if (!(*p)->IsHeapObject()) return;
+
+  HeapObject* obj = HeapObject::cast(*p);
+
+  Object* map = obj->map();
+
+  if (map->IsHeapObject()) return;  // unmarked already
+
+  Address map_addr = reinterpret_cast<Address>(map);
+
+  map_addr -= kMarkTag;
+
+  ASSERT_TAG_ALIGNED(map_addr);
+
+  HeapObject* map_p = HeapObject::FromAddress(map_addr);
+
+  obj->set_map(reinterpret_cast<Map*>(map_p));
+
+  UnmarkObjectRecursively(reinterpret_cast<Object**>(&map_p));
+
+  obj->IterateBody(Map::cast(map_p)->instance_type(),
+                   obj->SizeFromMap(Map::cast(map_p)),
+                   &unmark_visitor);
+
+  if (obj->IsCode()) {
+    Code::cast(obj)->ConvertICTargetsFromObjectToAddress();
+  }
+}
+
+
+static void MarkRootObjectRecursively(Object** root) {
+  if (search_for_any_global) {
+    ASSERT(search_target == NULL);
+  } else {
+    ASSERT(search_target->IsHeapObject());
+  }
+  found_target = false;
+  object_stack.Clear();
+
+  MarkObjectRecursively(root);
+  UnmarkObjectRecursively(root);
+
+  if (found_target) {
+    PrintF("=====================================\n");
+    PrintF("====        Path to object       ====\n");
+    PrintF("=====================================\n\n");
+
+    ASSERT(!object_stack.is_empty());
+    for (int i = 0; i < object_stack.length(); i++) {
+      if (i > 0) PrintF("\n     |\n     |\n     V\n\n");
+      Object* obj = object_stack[i];
+      obj->Print();
+    }
+    PrintF("=====================================\n");
+  }
+}
+
+
+// Helper class for visiting HeapObjects recursively.
+class MarkRootVisitor: public ObjectVisitor {
+ public:
+  void VisitPointers(Object** start, Object** end) {
+    // Visit all HeapObject pointers in [start, end)
+    for (Object** p = start; p < end; p++) {
+      if ((*p)->IsHeapObject())
+        MarkRootObjectRecursively(p);
+    }
+  }
+};
+
+
+// Triggers a depth-first traversal of reachable objects from roots
+// and finds a path to a specific heap object and prints it.
+void Heap::TracePathToObject() {
+  search_target = NULL;
+  search_for_any_global = false;
+
+  MarkRootVisitor root_visitor;
+  IterateRoots(&root_visitor);
+}
+
+
+// Triggers a depth-first traversal of reachable objects from roots
+// and finds a path to any global object and prints it. Useful for
+// determining the source for leaks of global objects.
+void Heap::TracePathToGlobal() {
+  search_target = NULL;
+  search_for_any_global = true;
+
+  MarkRootVisitor root_visitor;
+  IterateRoots(&root_visitor);
+}
+#endif
+
+
+GCTracer::GCTracer()
+    : start_time_(0.0),
+      start_size_(0.0),
+      gc_count_(0),
+      full_gc_count_(0),
+      is_compacting_(false),
+      marked_count_(0) {
+  // These two fields reflect the state of the previous full collection.
+  // Set them before they are changed by the collector.
+  previous_has_compacted_ = MarkCompactCollector::HasCompacted();
+  previous_marked_count_ = MarkCompactCollector::previous_marked_count();
+  if (!FLAG_trace_gc) return;
+  start_time_ = OS::TimeCurrentMillis();
+  start_size_ = SizeOfHeapObjects();
+}
+
+
+GCTracer::~GCTracer() {
+  if (!FLAG_trace_gc) return;
+  // Printf ONE line iff flag is set.
+  PrintF("%s %.1f -> %.1f MB, %d ms.\n",
+         CollectorString(),
+         start_size_, SizeOfHeapObjects(),
+         static_cast<int>(OS::TimeCurrentMillis() - start_time_));
+}
+
+
+const char* GCTracer::CollectorString() {
+  switch (collector_) {
+    case SCAVENGER:
+      return "Scavenge";
+    case MARK_COMPACTOR:
+      return MarkCompactCollector::HasCompacted() ? "Mark-compact"
+                                                  : "Mark-sweep";
+  }
+  return "Unknown GC";
+}
+
+
+#ifdef DEBUG
+bool Heap::GarbageCollectionGreedyCheck() {
+  ASSERT(FLAG_gc_greedy);
+  if (Bootstrapper::IsActive()) return true;
+  if (disallow_allocation_failure()) return true;
+  return CollectGarbage(0, NEW_SPACE);
+}
+#endif
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/heap.h b/deps/v8/src/heap.h
new file mode 100644
index 0000000..ccc552f
--- /dev/null
+++ b/deps/v8/src/heap.h
@@ -0,0 +1,1313 @@
+// 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_HEAP_H_
+#define V8_HEAP_H_
+
+namespace v8 { namespace internal {
+
+// Defines all the roots in Heap.
+#define STRONG_ROOT_LIST(V)                             \
+  V(Map, meta_map)                                      \
+  V(Map, heap_number_map)                               \
+  V(Map, short_string_map)                              \
+  V(Map, medium_string_map)                             \
+  V(Map, long_string_map)                               \
+  V(Map, short_ascii_string_map)                        \
+  V(Map, medium_ascii_string_map)                       \
+  V(Map, long_ascii_string_map)                         \
+  V(Map, short_symbol_map)                              \
+  V(Map, medium_symbol_map)                             \
+  V(Map, long_symbol_map)                               \
+  V(Map, short_ascii_symbol_map)                        \
+  V(Map, medium_ascii_symbol_map)                       \
+  V(Map, long_ascii_symbol_map)                         \
+  V(Map, short_cons_symbol_map)                         \
+  V(Map, medium_cons_symbol_map)                        \
+  V(Map, long_cons_symbol_map)                          \
+  V(Map, short_cons_ascii_symbol_map)                   \
+  V(Map, medium_cons_ascii_symbol_map)                  \
+  V(Map, long_cons_ascii_symbol_map)                    \
+  V(Map, short_sliced_symbol_map)                       \
+  V(Map, medium_sliced_symbol_map)                      \
+  V(Map, long_sliced_symbol_map)                        \
+  V(Map, short_sliced_ascii_symbol_map)                 \
+  V(Map, medium_sliced_ascii_symbol_map)                \
+  V(Map, long_sliced_ascii_symbol_map)                  \
+  V(Map, short_external_symbol_map)                     \
+  V(Map, medium_external_symbol_map)                    \
+  V(Map, long_external_symbol_map)                      \
+  V(Map, short_external_ascii_symbol_map)               \
+  V(Map, medium_external_ascii_symbol_map)              \
+  V(Map, long_external_ascii_symbol_map)                \
+  V(Map, short_cons_string_map)                         \
+  V(Map, medium_cons_string_map)                        \
+  V(Map, long_cons_string_map)                          \
+  V(Map, short_cons_ascii_string_map)                   \
+  V(Map, medium_cons_ascii_string_map)                  \
+  V(Map, long_cons_ascii_string_map)                    \
+  V(Map, short_sliced_string_map)                       \
+  V(Map, medium_sliced_string_map)                      \
+  V(Map, long_sliced_string_map)                        \
+  V(Map, short_sliced_ascii_string_map)                 \
+  V(Map, medium_sliced_ascii_string_map)                \
+  V(Map, long_sliced_ascii_string_map)                  \
+  V(Map, short_external_string_map)                     \
+  V(Map, medium_external_string_map)                    \
+  V(Map, long_external_string_map)                      \
+  V(Map, short_external_ascii_string_map)               \
+  V(Map, medium_external_ascii_string_map)              \
+  V(Map, long_external_ascii_string_map)                \
+  V(Map, undetectable_short_string_map)                 \
+  V(Map, undetectable_medium_string_map)                \
+  V(Map, undetectable_long_string_map)                  \
+  V(Map, undetectable_short_ascii_string_map)           \
+  V(Map, undetectable_medium_ascii_string_map)          \
+  V(Map, undetectable_long_ascii_string_map)            \
+  V(Map, byte_array_map)                                \
+  V(Map, fixed_array_map)                               \
+  V(Map, hash_table_map)                                \
+  V(Map, context_map)                                   \
+  V(Map, catch_context_map)                             \
+  V(Map, global_context_map)                            \
+  V(Map, code_map)                                      \
+  V(Map, oddball_map)                                   \
+  V(Map, boilerplate_function_map)                      \
+  V(Map, shared_function_info_map)                      \
+  V(Map, proxy_map)                                     \
+  V(Map, one_word_filler_map)                           \
+  V(Map, two_word_filler_map)                           \
+  V(Object, nan_value)                                  \
+  V(Object, undefined_value)                            \
+  V(Object, minus_zero_value)                           \
+  V(Object, null_value)                                 \
+  V(Object, true_value)                                 \
+  V(Object, false_value)                                \
+  V(String, empty_string)                               \
+  V(FixedArray, empty_fixed_array)                      \
+  V(DescriptorArray, empty_descriptor_array)            \
+  V(Object, the_hole_value)                             \
+  V(Map, neander_map)                                   \
+  V(JSObject, message_listeners)                        \
+  V(Proxy, prototype_accessors)                         \
+  V(Dictionary, code_stubs)                             \
+  V(Dictionary, non_monomorphic_cache)                  \
+  V(Code, js_entry_code)                                \
+  V(Code, js_construct_entry_code)                      \
+  V(Code, c_entry_code)                                 \
+  V(Code, c_entry_debug_break_code)                     \
+  V(FixedArray, number_string_cache)                    \
+  V(FixedArray, single_character_string_cache)          \
+  V(FixedArray, natives_source_cache)                   \
+  V(Object, keyed_lookup_cache)                         \
+  V(Object, last_script_id)
+
+
+#define ROOT_LIST(V)                                  \
+  STRONG_ROOT_LIST(V)                                 \
+  V(Object, symbol_table)
+
+#define SYMBOL_LIST(V)                                                   \
+  V(Array_symbol, "Array")                                               \
+  V(Object_symbol, "Object")                                             \
+  V(Proto_symbol, "__proto__")                                           \
+  V(StringImpl_symbol, "StringImpl")                                     \
+  V(arguments_symbol, "arguments")                                       \
+  V(Arguments_symbol, "Arguments")                                       \
+  V(arguments_shadow_symbol, ".arguments")                               \
+  V(call_symbol, "call")                                                 \
+  V(apply_symbol, "apply")                                               \
+  V(caller_symbol, "caller")                                             \
+  V(boolean_symbol, "boolean")                                           \
+  V(Boolean_symbol, "Boolean")                                           \
+  V(callee_symbol, "callee")                                             \
+  V(constructor_symbol, "constructor")                                   \
+  V(code_symbol, ".code")                                                \
+  V(result_symbol, ".result")                                            \
+  V(catch_var_symbol, ".catch-var")                                      \
+  V(empty_symbol, "")                                                    \
+  V(eval_symbol, "eval")                                                 \
+  V(function_symbol, "function")                                         \
+  V(length_symbol, "length")                                             \
+  V(name_symbol, "name")                                                 \
+  V(number_symbol, "number")                                             \
+  V(Number_symbol, "Number")                                             \
+  V(RegExp_symbol, "RegExp")                                             \
+  V(object_symbol, "object")                                             \
+  V(prototype_symbol, "prototype")                                       \
+  V(string_symbol, "string")                                             \
+  V(String_symbol, "String")                                             \
+  V(Date_symbol, "Date")                                                 \
+  V(this_symbol, "this")                                                 \
+  V(to_string_symbol, "toString")                                        \
+  V(char_at_symbol, "CharAt")                                            \
+  V(undefined_symbol, "undefined")                                       \
+  V(value_of_symbol, "valueOf")                                          \
+  V(InitializeVarGlobal_symbol, "InitializeVarGlobal")                   \
+  V(InitializeConstGlobal_symbol, "InitializeConstGlobal")               \
+  V(stack_overflow_symbol, "kStackOverflowBoilerplate")                  \
+  V(illegal_access_symbol, "illegal access")                             \
+  V(out_of_memory_symbol, "out-of-memory")                               \
+  V(illegal_execution_state_symbol, "illegal execution state")           \
+  V(get_symbol, "get")                                                   \
+  V(set_symbol, "set")                                                   \
+  V(function_class_symbol, "Function")                                   \
+  V(illegal_argument_symbol, "illegal argument")                         \
+  V(MakeReferenceError_symbol, "MakeReferenceError")                     \
+  V(MakeSyntaxError_symbol, "MakeSyntaxError")                           \
+  V(MakeTypeError_symbol, "MakeTypeError")                               \
+  V(invalid_lhs_in_assignment_symbol, "invalid_lhs_in_assignment")       \
+  V(invalid_lhs_in_for_in_symbol, "invalid_lhs_in_for_in")               \
+  V(invalid_lhs_in_postfix_op_symbol, "invalid_lhs_in_postfix_op")       \
+  V(invalid_lhs_in_prefix_op_symbol, "invalid_lhs_in_prefix_op")         \
+  V(illegal_return_symbol, "illegal_return")                             \
+  V(illegal_break_symbol, "illegal_break")                               \
+  V(illegal_continue_symbol, "illegal_continue")                         \
+  V(unknown_label_symbol, "unknown_label")                               \
+  V(redeclaration_symbol, "redeclaration")                               \
+  V(failure_symbol, "<failure>")                                         \
+  V(space_symbol, " ")                                                   \
+  V(exec_symbol, "exec")                                                 \
+  V(zero_symbol, "0")                                                    \
+  V(global_eval_symbol, "GlobalEval")                                    \
+  V(identity_hash_symbol, "v8::IdentityHash")
+
+
+// Forward declaration of the GCTracer class.
+class GCTracer;
+
+
+// The all static Heap captures the interface to the global object heap.
+// All JavaScript contexts by this process share the same object heap.
+
+class Heap : public AllStatic {
+ public:
+  // Configure heap size before setup. Return false if the heap has been
+  // setup already.
+  static bool ConfigureHeap(int semispace_size, int old_gen_size);
+  static bool ConfigureHeapDefault();
+
+  // Initializes the global object heap. If create_heap_objects is true,
+  // also creates the basic non-mutable objects.
+  // Returns whether it succeeded.
+  static bool Setup(bool create_heap_objects);
+
+  // Destroys all memory allocated by the heap.
+  static void TearDown();
+
+  // Returns whether Setup has been called.
+  static bool HasBeenSetup();
+
+  // Returns the maximum heap capacity.
+  static int MaxCapacity() {
+    return young_generation_size_ + old_generation_size_;
+  }
+  static int SemiSpaceSize() { return semispace_size_; }
+  static int InitialSemiSpaceSize() { return initial_semispace_size_; }
+  static int YoungGenerationSize() { return young_generation_size_; }
+  static int OldGenerationSize() { return old_generation_size_; }
+
+  // Returns the capacity of the heap in bytes w/o growing. Heap grows when
+  // more spaces are needed until it reaches the limit.
+  static int Capacity();
+
+  // Returns the available bytes in space w/o growing.
+  // Heap doesn't guarantee that it can allocate an object that requires
+  // all available bytes. Check MaxHeapObjectSize() instead.
+  static int Available();
+
+  // Returns the maximum object size that heap supports. Objects larger than
+  // the maximum heap object size are allocated in a large object space.
+  static inline int MaxHeapObjectSize();
+
+  // Returns of size of all objects residing in the heap.
+  static int SizeOfObjects();
+
+  // Return the starting address and a mask for the new space.  And-masking an
+  // address with the mask will result in the start address of the new space
+  // for all addresses in either semispace.
+  static Address NewSpaceStart() { return new_space_.start(); }
+  static uint32_t NewSpaceMask() { return new_space_.mask(); }
+  static Address NewSpaceTop() { return new_space_.top(); }
+
+  static NewSpace* new_space() { return &new_space_; }
+  static OldSpace* old_pointer_space() { return old_pointer_space_; }
+  static OldSpace* old_data_space() { return old_data_space_; }
+  static OldSpace* code_space() { return code_space_; }
+  static MapSpace* map_space() { return map_space_; }
+  static LargeObjectSpace* lo_space() { return lo_space_; }
+
+  static bool always_allocate() { return always_allocate_scope_depth_ != 0; }
+  static Address always_allocate_scope_depth_address() {
+    return reinterpret_cast<Address>(&always_allocate_scope_depth_);
+  }
+
+  static Address* NewSpaceAllocationTopAddress() {
+    return new_space_.allocation_top_address();
+  }
+  static Address* NewSpaceAllocationLimitAddress() {
+    return new_space_.allocation_limit_address();
+  }
+
+#ifdef ENABLE_HEAP_PROTECTION
+  // Protect/unprotect the heap by marking all spaces read-only/writable.
+  static void Protect();
+  static void Unprotect();
+#endif
+
+  // Allocates and initializes a new JavaScript object based on a
+  // constructor.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  static Object* AllocateJSObject(JSFunction* constructor,
+                                  PretenureFlag pretenure = NOT_TENURED);
+
+  // Returns a deep copy of the JavaScript object.
+  // Properties and elements are copied too.
+  // Returns failure if allocation failed.
+  static Object* CopyJSObject(JSObject* source);
+
+  // Allocates the function prototype.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  static Object* AllocateFunctionPrototype(JSFunction* function);
+
+  // Reinitialize an JSGlobalProxy based on a constructor.  The object
+  // must have the same size as objects allocated using the
+  // constructor.  The object is reinitialized and behaves as an
+  // object that has been freshly allocated using the constructor.
+  static Object* ReinitializeJSGlobalProxy(JSFunction* constructor,
+                                           JSGlobalProxy* global);
+
+  // Allocates and initializes a new JavaScript object based on a map.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  static Object* AllocateJSObjectFromMap(Map* map,
+                                         PretenureFlag pretenure = NOT_TENURED);
+
+  // Allocates a heap object based on the map.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this function does not perform a garbage collection.
+  static Object* Allocate(Map* map, AllocationSpace space);
+
+  // Allocates a JS Map in the heap.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this function does not perform a garbage collection.
+  static Object* AllocateMap(InstanceType instance_type, int instance_size);
+
+  // Allocates a partial map for bootstrapping.
+  static Object* AllocatePartialMap(InstanceType instance_type,
+                                    int instance_size);
+
+  // Allocate a map for the specified function
+  static Object* AllocateInitialMap(JSFunction* fun);
+
+  // Allocates and fully initializes a String.  There are two String
+  // encodings: ASCII and two byte. One should choose between the three string
+  // allocation functions based on the encoding of the string buffer used to
+  // initialized the string.
+  //   - ...FromAscii initializes the string from a buffer that is ASCII
+  //     encoded (it does not check that the buffer is ASCII encoded) and the
+  //     result will be ASCII encoded.
+  //   - ...FromUTF8 initializes the string from a buffer that is UTF-8
+  //     encoded.  If the characters are all single-byte characters, the
+  //     result will be ASCII encoded, otherwise it will converted to two
+  //     byte.
+  //   - ...FromTwoByte initializes the string from a buffer that is two-byte
+  //     encoded.  If the characters are all single-byte characters, the
+  //     result will be converted to ASCII, otherwise it will be left as
+  //     two-byte.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  static Object* AllocateStringFromAscii(
+      Vector<const char> str,
+      PretenureFlag pretenure = NOT_TENURED);
+  static Object* AllocateStringFromUtf8(
+      Vector<const char> str,
+      PretenureFlag pretenure = NOT_TENURED);
+  static Object* AllocateStringFromTwoByte(
+      Vector<const uc16> str,
+      PretenureFlag pretenure = NOT_TENURED);
+
+  // Allocates a symbol in old space based on the character stream.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this function does not perform a garbage collection.
+  static inline Object* AllocateSymbol(Vector<const char> str,
+                                       int chars,
+                                       uint32_t length_field);
+
+  static Object* AllocateInternalSymbol(unibrow::CharacterStream* buffer,
+                                        int chars,
+                                        uint32_t length_field);
+
+  static Object* AllocateExternalSymbol(Vector<const char> str,
+                                        int chars);
+
+
+  // Allocates and partially initializes a String.  There are two String
+  // encodings: ASCII and two byte.  These functions allocate a string of the
+  // given length and set its map and length fields.  The characters of the
+  // string are uninitialized.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  static Object* AllocateRawAsciiString(
+      int length,
+      PretenureFlag pretenure = NOT_TENURED);
+  static Object* AllocateRawTwoByteString(
+      int length,
+      PretenureFlag pretenure = NOT_TENURED);
+
+  // Computes a single character string where the character has code.
+  // A cache is used for ascii codes.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed. Please note this does not perform a garbage collection.
+  static Object* LookupSingleCharacterStringFromCode(uint16_t code);
+
+  // Allocate a byte array of the specified length
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  static Object* AllocateByteArray(int length, PretenureFlag pretenure);
+
+  // Allocate a non-tenured byte array of the specified length
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  static Object* AllocateByteArray(int length);
+
+  // Allocates a fixed array initialized with undefined values
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  static Object* AllocateFixedArray(int length, PretenureFlag pretenure);
+  // Allocate uninitialized, non-tenured fixed array with length elements.
+  static Object* AllocateFixedArray(int length);
+
+  // Make a copy of src and return it. Returns
+  // Failure::RetryAfterGC(requested_bytes, space) if the allocation failed.
+  static Object* CopyFixedArray(FixedArray* src);
+
+  // Allocates a fixed array initialized with the hole values.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  static Object* AllocateFixedArrayWithHoles(int length);
+
+  // AllocateHashTable is identical to AllocateFixedArray except
+  // that the resulting object has hash_table_map as map.
+  static Object* AllocateHashTable(int length);
+
+  // Allocate a global (but otherwise uninitialized) context.
+  static Object* AllocateGlobalContext();
+
+  // Allocate a function context.
+  static Object* AllocateFunctionContext(int length, JSFunction* closure);
+
+  // Allocate a 'with' context.
+  static Object* AllocateWithContext(Context* previous,
+                                     JSObject* extension,
+                                     bool is_catch_context);
+
+  // Allocates a new utility object in the old generation.
+  static Object* AllocateStruct(InstanceType type);
+
+
+  // Initializes a function with a shared part and prototype.
+  // Returns the function.
+  // Note: this code was factored out of AllocateFunction such that
+  // other parts of the VM could use it. Specifically, a function that creates
+  // instances of type JS_FUNCTION_TYPE benefit from the use of this function.
+  // Please note this does not perform a garbage collection.
+  static Object* InitializeFunction(JSFunction* function,
+                                    SharedFunctionInfo* shared,
+                                    Object* prototype);
+
+  // Allocates a function initialized with a shared part.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  static Object* AllocateFunction(Map* function_map,
+                                  SharedFunctionInfo* shared,
+                                  Object* prototype);
+
+  // Indicies for direct access into argument objects.
+  static const int arguments_callee_index = 0;
+  static const int arguments_length_index = 1;
+
+  // Allocates an arguments object - optionally with an elements array.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  static Object* AllocateArgumentsObject(Object* callee, int length);
+
+  // Converts a double into either a Smi or a HeapNumber object.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  static Object* NewNumberFromDouble(double value,
+                                     PretenureFlag pretenure = NOT_TENURED);
+
+  // Same as NewNumberFromDouble, but may return a preallocated/immutable
+  // number object (e.g., minus_zero_value_, nan_value_)
+  static Object* NumberFromDouble(double value,
+                                  PretenureFlag pretenure = NOT_TENURED);
+
+  // Allocated a HeapNumber from value.
+  static Object* AllocateHeapNumber(double value, PretenureFlag pretenure);
+  static Object* AllocateHeapNumber(double value);  // pretenure = NOT_TENURED
+
+  // Converts an int into either a Smi or a HeapNumber object.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  static inline Object* NumberFromInt32(int32_t value);
+
+  // Converts an int into either a Smi or a HeapNumber object.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  static inline Object* NumberFromUint32(uint32_t value);
+
+  // Allocates a new proxy object.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  static Object* AllocateProxy(Address proxy,
+                               PretenureFlag pretenure = NOT_TENURED);
+
+  // Allocates a new SharedFunctionInfo object.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  static Object* AllocateSharedFunctionInfo(Object* name);
+
+  // Allocates a new cons string object.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  static Object* AllocateConsString(String* first,
+                                    String* second);
+
+  // Allocates a new sliced string object which is a slice of an underlying
+  // string buffer stretching from the index start (inclusive) to the index
+  // end (exclusive).
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  static Object* AllocateSlicedString(String* buffer,
+                                      int start,
+                                      int end);
+
+  // Allocates a new sub string object which is a substring of an underlying
+  // string buffer stretching from the index start (inclusive) to the index
+  // end (exclusive).
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  static Object* AllocateSubString(String* buffer,
+                                   int start,
+                                   int end);
+
+  // Allocate a new external string object, which is backed by a string
+  // resource that resides outside the V8 heap.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  static Object* AllocateExternalStringFromAscii(
+      ExternalAsciiString::Resource* resource);
+  static Object* AllocateExternalStringFromTwoByte(
+      ExternalTwoByteString::Resource* resource);
+
+  // Allocates an uninitialized object.  The memory is non-executable if the
+  // hardware and OS allow.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this function does not perform a garbage collection.
+  static inline Object* AllocateRaw(int size_in_bytes,
+                                    AllocationSpace space,
+                                    AllocationSpace retry_space);
+
+  // Initialize a filler object to keep the ability to iterate over the heap
+  // when shortening objects.
+  static void CreateFillerObjectAt(Address addr, int size);
+
+  // Makes a new native code object
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed. On success, the pointer to the Code object is stored in the
+  // self_reference. This allows generated code to reference its own Code
+  // object by containing this pointer.
+  // Please note this function does not perform a garbage collection.
+  static Object* CreateCode(const CodeDesc& desc,
+                            ScopeInfo<>* sinfo,
+                            Code::Flags flags,
+                            Handle<Object> self_reference);
+
+  static Object* CopyCode(Code* code);
+  // Finds the symbol for string in the symbol table.
+  // If not found, a new symbol is added to the table and returned.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if allocation
+  // failed.
+  // Please note this function does not perform a garbage collection.
+  static Object* LookupSymbol(Vector<const char> str);
+  static Object* LookupAsciiSymbol(const char* str) {
+    return LookupSymbol(CStrVector(str));
+  }
+  static Object* LookupSymbol(String* str);
+  static bool LookupSymbolIfExists(String* str, String** symbol);
+
+  // Compute the matching symbol map for a string if possible.
+  // NULL is returned if string is in new space or not flattened.
+  static Map* SymbolMapForString(String* str);
+
+  // Converts the given boolean condition to JavaScript boolean value.
+  static Object* ToBoolean(bool condition) {
+    return condition ? true_value() : false_value();
+  }
+
+  // Code that should be run before and after each GC.  Includes some
+  // reporting/verification activities when compiled with DEBUG set.
+  static void GarbageCollectionPrologue();
+  static void GarbageCollectionEpilogue();
+
+  // Code that should be executed after the garbage collection proper.
+  static void PostGarbageCollectionProcessing();
+
+  // Performs garbage collection operation.
+  // Returns whether required_space bytes are available after the collection.
+  static bool CollectGarbage(int required_space, AllocationSpace space);
+
+  // Performs a full garbage collection.
+  static void CollectAllGarbage();
+
+  // Performs a full garbage collection if a context has been disposed
+  // since the last time the check was performed.
+  static void CollectAllGarbageIfContextDisposed();
+
+  // Notify the heap that a context has been disposed.
+  static void NotifyContextDisposed();
+
+  // Utility to invoke the scavenger. This is needed in test code to
+  // ensure correct callback for weak global handles.
+  static void PerformScavenge();
+
+#ifdef DEBUG
+  // Utility used with flag gc-greedy.
+  static bool GarbageCollectionGreedyCheck();
+#endif
+
+  static void SetGlobalGCPrologueCallback(GCCallback callback) {
+    global_gc_prologue_callback_ = callback;
+  }
+  static void SetGlobalGCEpilogueCallback(GCCallback callback) {
+    global_gc_epilogue_callback_ = callback;
+  }
+
+  // Heap roots
+#define ROOT_ACCESSOR(type, name) static type* name() { return name##_; }
+  ROOT_LIST(ROOT_ACCESSOR)
+#undef ROOT_ACCESSOR
+
+// Utility type maps
+#define STRUCT_MAP_ACCESSOR(NAME, Name, name) \
+    static Map* name##_map() { return name##_map_; }
+  STRUCT_LIST(STRUCT_MAP_ACCESSOR)
+#undef STRUCT_MAP_ACCESSOR
+
+#define SYMBOL_ACCESSOR(name, str) static String* name() { return name##_; }
+  SYMBOL_LIST(SYMBOL_ACCESSOR)
+#undef SYMBOL_ACCESSOR
+
+  // The hidden_symbol is special because it is the empty string, but does
+  // not match the empty string.
+  static String* hidden_symbol() { return hidden_symbol_; }
+
+  // Iterates over all roots in the heap.
+  static void IterateRoots(ObjectVisitor* v);
+  // Iterates over all strong roots in the heap.
+  static void IterateStrongRoots(ObjectVisitor* v);
+
+  // Iterates remembered set of an old space.
+  static void IterateRSet(PagedSpace* space, ObjectSlotCallback callback);
+
+  // Iterates a range of remembered set addresses starting with rset_start
+  // corresponding to the range of allocated pointers
+  // [object_start, object_end).
+  static void IterateRSetRange(Address object_start,
+                               Address object_end,
+                               Address rset_start,
+                               ObjectSlotCallback copy_object_func);
+
+  // Returns whether the object resides in new space.
+  static inline bool InNewSpace(Object* object);
+  static inline bool InFromSpace(Object* object);
+  static inline bool InToSpace(Object* object);
+
+  // Checks whether an address/object in the heap (including auxiliary
+  // area and unused area).
+  static bool Contains(Address addr);
+  static bool Contains(HeapObject* value);
+
+  // Checks whether an address/object in a space.
+  // Currently used by tests and heap verification only.
+  static bool InSpace(Address addr, AllocationSpace space);
+  static bool InSpace(HeapObject* value, AllocationSpace space);
+
+  // Finds out which space an object should get promoted to based on its type.
+  static inline OldSpace* TargetSpace(HeapObject* object);
+  static inline AllocationSpace TargetSpaceId(InstanceType type);
+
+  // Sets the stub_cache_ (only used when expanding the dictionary).
+  static void set_code_stubs(Dictionary* value) { code_stubs_ = value; }
+
+  // Sets the non_monomorphic_cache_ (only used when expanding the dictionary).
+  static void set_non_monomorphic_cache(Dictionary* value) {
+    non_monomorphic_cache_ = value;
+  }
+
+  // Gets, sets and clears the lookup cache used for keyed access.
+  static inline Object* GetKeyedLookupCache();
+  static inline void SetKeyedLookupCache(LookupCache* cache);
+  static inline void ClearKeyedLookupCache();
+
+  // Update the next script id.
+  static inline void SetLastScriptId(Object* last_script_id);
+
+#ifdef DEBUG
+  static void Print();
+  static void PrintHandles();
+
+  // Verify the heap is in its normal state before or after a GC.
+  static void Verify();
+
+  // Report heap statistics.
+  static void ReportHeapStatistics(const char* title);
+  static void ReportCodeStatistics(const char* title);
+
+  // Fill in bogus values in from space
+  static void ZapFromSpace();
+#endif
+
+  // Makes a new symbol object
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this function does not perform a garbage collection.
+  static Object* CreateSymbol(const char* str, int length, int hash);
+  static Object* CreateSymbol(String* str);
+
+  // Write barrier support for address[offset] = o.
+  inline static void RecordWrite(Address address, int offset);
+
+  // Given an address occupied by a live code object, return that object.
+  static Object* FindCodeObject(Address a);
+
+  // Invoke Shrink on shrinkable spaces.
+  static void Shrink();
+
+  enum HeapState { NOT_IN_GC, SCAVENGE, MARK_COMPACT };
+  static inline HeapState gc_state() { return gc_state_; }
+
+#ifdef DEBUG
+  static bool IsAllocationAllowed() { return allocation_allowed_; }
+  static inline bool allow_allocation(bool enable);
+
+  static bool disallow_allocation_failure() {
+    return disallow_allocation_failure_;
+  }
+
+  static void TracePathToObject();
+  static void TracePathToGlobal();
+#endif
+
+  // Callback function passed to Heap::Iterate etc.  Copies an object if
+  // necessary, the object might be promoted to an old space.  The caller must
+  // ensure the precondition that the object is (a) a heap object and (b) in
+  // the heap's from space.
+  static void ScavengePointer(HeapObject** p);
+  static inline void ScavengeObject(HeapObject** p, HeapObject* object);
+
+  // Clear a range of remembered set addresses corresponding to the object
+  // area address 'start' with size 'size_in_bytes', eg, when adding blocks
+  // to the free list.
+  static void ClearRSetRange(Address start, int size_in_bytes);
+
+  // Rebuild remembered set in old and map spaces.
+  static void RebuildRSets();
+
+  //
+  // Support for the API.
+  //
+
+  static bool CreateApiObjects();
+
+  // Attempt to find the number in a small cache.  If we finds it, return
+  // the string representation of the number.  Otherwise return undefined.
+  static Object* GetNumberStringCache(Object* number);
+
+  // Update the cache with a new number-string pair.
+  static void SetNumberStringCache(Object* number, String* str);
+
+  // Entries in the cache.  Must be a power of 2.
+  static const int kNumberStringCacheSize = 64;
+
+  // Adjusts the amount of registered external memory.
+  // Returns the adjusted value.
+  static int AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
+    int amount = amount_of_external_allocated_memory_ + change_in_bytes;
+    if (change_in_bytes >= 0) {
+      // Avoid overflow.
+      if (amount > amount_of_external_allocated_memory_) {
+        amount_of_external_allocated_memory_ = amount;
+      }
+    } else {
+      // Avoid underflow.
+      if (amount >= 0) {
+        amount_of_external_allocated_memory_ = amount;
+      }
+    }
+    ASSERT(amount_of_external_allocated_memory_ >= 0);
+    return amount_of_external_allocated_memory_;
+  }
+
+  // Allocate unitialized fixed array (pretenure == NON_TENURE).
+  static Object* AllocateRawFixedArray(int length);
+
+  // True if we have reached the allocation limit in the old generation that
+  // should force the next GC (caused normally) to be a full one.
+  static bool OldGenerationPromotionLimitReached() {
+    return (PromotedSpaceSize() + PromotedExternalMemorySize())
+           > old_gen_promotion_limit_;
+  }
+
+  // True if we have reached the allocation limit in the old generation that
+  // should artificially cause a GC right now.
+  static bool OldGenerationAllocationLimitReached() {
+    return (PromotedSpaceSize() + PromotedExternalMemorySize())
+           > old_gen_allocation_limit_;
+  }
+
+ private:
+  static int semispace_size_;
+  static int initial_semispace_size_;
+  static int young_generation_size_;
+  static int old_generation_size_;
+
+  static int new_space_growth_limit_;
+  static int scavenge_count_;
+
+  static int always_allocate_scope_depth_;
+  static bool context_disposed_pending_;
+
+  static const int kMaxMapSpaceSize = 8*MB;
+
+  static NewSpace new_space_;
+  static OldSpace* old_pointer_space_;
+  static OldSpace* old_data_space_;
+  static OldSpace* code_space_;
+  static MapSpace* map_space_;
+  static LargeObjectSpace* lo_space_;
+  static HeapState gc_state_;
+
+  // Returns the size of object residing in non new spaces.
+  static int PromotedSpaceSize();
+
+  // Returns the amount of external memory registered since last global gc.
+  static int PromotedExternalMemorySize();
+
+  static int mc_count_;  // how many mark-compact collections happened
+  static int gc_count_;  // how many gc happened
+
+#ifdef DEBUG
+  static bool allocation_allowed_;
+
+  // If the --gc-interval flag is set to a positive value, this
+  // variable holds the value indicating the number of allocations
+  // remain until the next failure and garbage collection.
+  static int allocation_timeout_;
+
+  // Do we expect to be able to handle allocation failure at this
+  // time?
+  static bool disallow_allocation_failure_;
+#endif  // DEBUG
+
+  // Limit that triggers a global GC on the next (normally caused) GC.  This
+  // is checked when we have already decided to do a GC to help determine
+  // which collector to invoke.
+  static int old_gen_promotion_limit_;
+
+  // Limit that triggers a global GC as soon as is reasonable.  This is
+  // checked before expanding a paged space in the old generation and on
+  // every allocation in large object space.
+  static int old_gen_allocation_limit_;
+
+  // The amount of external memory registered through the API kept alive
+  // by global handles
+  static int amount_of_external_allocated_memory_;
+
+  // Caches the amount of external memory registered at the last global gc.
+  static int amount_of_external_allocated_memory_at_last_global_gc_;
+
+  // Indicates that an allocation has failed in the old generation since the
+  // last GC.
+  static int old_gen_exhausted_;
+
+  // Declare all the roots
+#define ROOT_DECLARATION(type, name) static type* name##_;
+  ROOT_LIST(ROOT_DECLARATION)
+#undef ROOT_DECLARATION
+
+// Utility type maps
+#define DECLARE_STRUCT_MAP(NAME, Name, name) static Map* name##_map_;
+  STRUCT_LIST(DECLARE_STRUCT_MAP)
+#undef DECLARE_STRUCT_MAP
+
+#define SYMBOL_DECLARATION(name, str) static String* name##_;
+  SYMBOL_LIST(SYMBOL_DECLARATION)
+#undef SYMBOL_DECLARATION
+
+  // The special hidden symbol which is an empty string, but does not match
+  // any string when looked up in properties.
+  static String* hidden_symbol_;
+
+  // GC callback function, called before and after mark-compact GC.
+  // Allocations in the callback function are disallowed.
+  static GCCallback global_gc_prologue_callback_;
+  static GCCallback global_gc_epilogue_callback_;
+
+  // Checks whether a global GC is necessary
+  static GarbageCollector SelectGarbageCollector(AllocationSpace space);
+
+  // Performs garbage collection
+  static void PerformGarbageCollection(AllocationSpace space,
+                                       GarbageCollector collector,
+                                       GCTracer* tracer);
+
+  // Returns either a Smi or a Number object from 'value'. If 'new_object'
+  // is false, it may return a preallocated immutable object.
+  static Object* SmiOrNumberFromDouble(double value,
+                                       bool new_object,
+                                       PretenureFlag pretenure = NOT_TENURED);
+
+  // Allocate an uninitialized object in map space.  The behavior is identical
+  // to Heap::AllocateRaw(size_in_bytes, MAP_SPACE), except that (a) it doesn't
+  // have to test the allocation space argument and (b) can reduce code size
+  // (since both AllocateRaw and AllocateRawMap are inlined).
+  static inline Object* AllocateRawMap(int size_in_bytes);
+
+  // Initializes a JSObject based on its map.
+  static void InitializeJSObjectFromMap(JSObject* obj,
+                                        FixedArray* properties,
+                                        Map* map);
+
+  static bool CreateInitialMaps();
+  static bool CreateInitialObjects();
+  static void CreateFixedStubs();
+  static Object* CreateOddball(Map* map,
+                               const char* to_string,
+                               Object* to_number);
+
+  // Allocate empty fixed array.
+  static Object* AllocateEmptyFixedArray();
+
+  // Performs a minor collection in new generation.
+  static void Scavenge();
+
+  // Performs a major collection in the whole heap.
+  static void MarkCompact(GCTracer* tracer);
+
+  // Code to be run before and after mark-compact.
+  static void MarkCompactPrologue(bool is_compacting);
+  static void MarkCompactEpilogue(bool is_compacting);
+
+  // Helper function used by CopyObject to copy a source object to an
+  // allocated target object and update the forwarding pointer in the source
+  // object.  Returns the target object.
+  static HeapObject* MigrateObject(HeapObject* source,
+                                   HeapObject* target,
+                                   int size);
+
+  // Helper function that governs the promotion policy from new space to
+  // old.  If the object's old address lies below the new space's age
+  // mark or if we've already filled the bottom 1/16th of the to space,
+  // we try to promote this object.
+  static inline bool ShouldBePromoted(Address old_address, int object_size);
+#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
+  // Record the copy of an object in the NewSpace's statistics.
+  static void RecordCopiedObject(HeapObject* obj);
+
+  // Record statistics before and after garbage collection.
+  static void ReportStatisticsBeforeGC();
+  static void ReportStatisticsAfterGC();
+#endif
+
+  // Update an old object's remembered set
+  static int UpdateRSet(HeapObject* obj);
+
+  // Rebuild remembered set in an old space.
+  static void RebuildRSets(PagedSpace* space);
+
+  // Rebuild remembered set in the large object space.
+  static void RebuildRSets(LargeObjectSpace* space);
+
+  // Slow part of scavenge object.
+  static void ScavengeObjectSlow(HeapObject** p, HeapObject* object);
+
+  // Copy memory from src to dst.
+  inline static void CopyBlock(Object** dst, Object** src, int byte_size);
+
+  static const int kInitialSymbolTableSize = 2048;
+  static const int kInitialEvalCacheSize = 64;
+
+  friend class Factory;
+  friend class DisallowAllocationFailure;
+  friend class AlwaysAllocateScope;
+};
+
+
+class AlwaysAllocateScope {
+ public:
+  AlwaysAllocateScope() {
+    // We shouldn't hit any nested scopes, because that requires
+    // non-handle code to call handle code. The code still works but
+    // performance will degrade, so we want to catch this situation
+    // in debug mode.
+    ASSERT(Heap::always_allocate_scope_depth_ == 0);
+    Heap::always_allocate_scope_depth_++;
+  }
+
+  ~AlwaysAllocateScope() {
+    Heap::always_allocate_scope_depth_--;
+    ASSERT(Heap::always_allocate_scope_depth_ == 0);
+  }
+};
+
+
+#ifdef DEBUG
+// Visitor class to verify interior pointers that do not have remembered set
+// bits.  All heap object pointers have to point into the heap to a location
+// that has a map pointer at its first word.  Caveat: Heap::Contains is an
+// approximation because it can return true for objects in a heap space but
+// above the allocation pointer.
+class VerifyPointersVisitor: public ObjectVisitor {
+ public:
+  void VisitPointers(Object** start, Object** end) {
+    for (Object** current = start; current < end; current++) {
+      if ((*current)->IsHeapObject()) {
+        HeapObject* object = HeapObject::cast(*current);
+        ASSERT(Heap::Contains(object));
+        ASSERT(object->map()->IsMap());
+      }
+    }
+  }
+};
+
+
+// Visitor class to verify interior pointers that have remembered set bits.
+// As VerifyPointersVisitor but also checks that remembered set bits are
+// always set for pointers into new space.
+class VerifyPointersAndRSetVisitor: public ObjectVisitor {
+ public:
+  void VisitPointers(Object** start, Object** end) {
+    for (Object** current = start; current < end; current++) {
+      if ((*current)->IsHeapObject()) {
+        HeapObject* object = HeapObject::cast(*current);
+        ASSERT(Heap::Contains(object));
+        ASSERT(object->map()->IsMap());
+        if (Heap::InNewSpace(object)) {
+          ASSERT(Page::IsRSetSet(reinterpret_cast<Address>(current), 0));
+        }
+      }
+    }
+  }
+};
+#endif
+
+
+// Space iterator for iterating over all spaces of the heap.
+// Returns each space in turn, and null when it is done.
+class AllSpaces BASE_EMBEDDED {
+ public:
+  Space* next();
+  AllSpaces() { counter_ = FIRST_SPACE; }
+ private:
+  int counter_;
+};
+
+
+// Space iterator for iterating over all old spaces of the heap: Old pointer
+// space, old data space and code space.
+// Returns each space in turn, and null when it is done.
+class OldSpaces BASE_EMBEDDED {
+ public:
+  OldSpace* next();
+  OldSpaces() { counter_ = OLD_POINTER_SPACE; }
+ private:
+  int counter_;
+};
+
+
+// Space iterator for iterating over all the paged spaces of the heap:
+// Map space, old pointer space, old data space and code space.
+// Returns each space in turn, and null when it is done.
+class PagedSpaces BASE_EMBEDDED {
+ public:
+  PagedSpace* next();
+  PagedSpaces() { counter_ = OLD_POINTER_SPACE; }
+ private:
+  int counter_;
+};
+
+
+// Space iterator for iterating over all spaces of the heap.
+// For each space an object iterator is provided. The deallocation of the
+// returned object iterators is handled by the space iterator.
+class SpaceIterator : public Malloced {
+ public:
+  SpaceIterator();
+  virtual ~SpaceIterator();
+
+  bool has_next();
+  ObjectIterator* next();
+
+ private:
+  ObjectIterator* CreateIterator();
+
+  int current_space_;  // from enum AllocationSpace.
+  ObjectIterator* iterator_;  // object iterator for the current space.
+};
+
+
+// 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.
+
+class HeapIterator BASE_EMBEDDED {
+ public:
+  explicit HeapIterator();
+  virtual ~HeapIterator();
+
+  bool has_next();
+  HeapObject* next();
+  void reset();
+
+ private:
+  // Perform the initialization.
+  void Init();
+
+  // Perform all necessary shutdown (destruction) work.
+  void Shutdown();
+
+  // Space iterator for iterating all the spaces.
+  SpaceIterator* space_iterator_;
+  // Object iterator for the space currently being iterated.
+  ObjectIterator* object_iterator_;
+};
+
+
+// ----------------------------------------------------------------------------
+// Marking stack for tracing live objects.
+
+class MarkingStack {
+ public:
+  void Initialize(Address low, Address high) {
+    top_ = low_ = reinterpret_cast<HeapObject**>(low);
+    high_ = reinterpret_cast<HeapObject**>(high);
+    overflowed_ = false;
+  }
+
+  bool is_full() { return top_ >= high_; }
+
+  bool is_empty() { return top_ <= low_; }
+
+  bool overflowed() { return overflowed_; }
+
+  void clear_overflowed() { overflowed_ = false; }
+
+  // Push the (marked) object on the marking stack if there is room,
+  // otherwise mark the object as overflowed and wait for a rescan of the
+  // heap.
+  void Push(HeapObject* object) {
+    CHECK(object->IsHeapObject());
+    if (is_full()) {
+      object->SetOverflow();
+      overflowed_ = true;
+    } else {
+      *(top_++) = object;
+    }
+  }
+
+  HeapObject* Pop() {
+    ASSERT(!is_empty());
+    HeapObject* object = *(--top_);
+    CHECK(object->IsHeapObject());
+    return object;
+  }
+
+ private:
+  HeapObject** low_;
+  HeapObject** top_;
+  HeapObject** high_;
+  bool overflowed_;
+};
+
+
+// A helper class to document/test C++ scopes where we do not
+// expect a GC. Usage:
+//
+// /* Allocation not allowed: we cannot handle a GC in this scope. */
+// { AssertNoAllocation nogc;
+//   ...
+// }
+
+#ifdef DEBUG
+
+class DisallowAllocationFailure {
+ public:
+  DisallowAllocationFailure() {
+    old_state_ = Heap::disallow_allocation_failure_;
+    Heap::disallow_allocation_failure_ = true;
+  }
+  ~DisallowAllocationFailure() {
+    Heap::disallow_allocation_failure_ = old_state_;
+  }
+ private:
+  bool old_state_;
+};
+
+class AssertNoAllocation {
+ public:
+  AssertNoAllocation() {
+    old_state_ = Heap::allow_allocation(false);
+  }
+
+  ~AssertNoAllocation() {
+    Heap::allow_allocation(old_state_);
+  }
+
+ private:
+  bool old_state_;
+};
+
+#else  // ndef DEBUG
+
+class AssertNoAllocation {
+ public:
+  AssertNoAllocation() { }
+  ~AssertNoAllocation() { }
+};
+
+#endif
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+// The HeapProfiler writes data to the log files, which can be postprocessed
+// to generate .hp files for use by the GHC/Valgrind tool hp2ps.
+class HeapProfiler {
+ public:
+  // Write a single heap sample to the log file.
+  static void WriteSample();
+
+ private:
+  // Update the array info with stats from obj.
+  static void CollectStats(HeapObject* obj, HistogramInfo* info);
+};
+#endif
+
+// GCTracer collects and prints ONE line after each garbage collector
+// invocation IFF --trace_gc is used.
+
+class GCTracer BASE_EMBEDDED {
+ public:
+  GCTracer();
+
+  ~GCTracer();
+
+  // Sets the collector.
+  void set_collector(GarbageCollector collector) { collector_ = collector; }
+
+  // Sets the GC count.
+  void set_gc_count(int count) { gc_count_ = count; }
+
+  // Sets the full GC count.
+  void set_full_gc_count(int count) { full_gc_count_ = count; }
+
+  // Sets the flag that this is a compacting full GC.
+  void set_is_compacting() { is_compacting_ = true; }
+
+  // Increment and decrement the count of marked objects.
+  void increment_marked_count() { ++marked_count_; }
+  void decrement_marked_count() { --marked_count_; }
+
+  int marked_count() { return marked_count_; }
+
+ private:
+  // Returns a string matching the collector.
+  const char* CollectorString();
+
+  // Returns size of object in heap (in MB).
+  double SizeOfHeapObjects() {
+    return (static_cast<double>(Heap::SizeOfObjects())) / MB;
+  }
+
+  double start_time_;  // Timestamp set in the constructor.
+  double start_size_;  // Size of objects in heap set in constructor.
+  GarbageCollector collector_;  // Type of collector.
+
+  // A count (including this one, eg, the first collection is 1) of the
+  // number of garbage collections.
+  int gc_count_;
+
+  // A count (including this one) of the number of full garbage collections.
+  int full_gc_count_;
+
+  // True if the current GC is a compacting full collection, false
+  // otherwise.
+  bool is_compacting_;
+
+  // True if the *previous* full GC cwas a compacting collection (will be
+  // false if there has not been a previous full GC).
+  bool previous_has_compacted_;
+
+  // On a full GC, a count of the number of marked objects.  Incremented
+  // when an object is marked and decremented when an object's mark bit is
+  // cleared.  Will be zero on a scavenge collection.
+  int marked_count_;
+
+  // The count from the end of the previous full GC.  Will be zero if there
+  // was no previous full GC.
+  int previous_marked_count_;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_HEAP_H_
diff --git a/deps/v8/src/ic-arm.cc b/deps/v8/src/ic-arm.cc
new file mode 100644
index 0000000..4db3980
--- /dev/null
+++ b/deps/v8/src/ic-arm.cc
@@ -0,0 +1,799 @@
+// 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.
+
+#include "v8.h"
+
+#include "codegen-inl.h"
+#include "ic-inl.h"
+#include "runtime.h"
+#include "stub-cache.h"
+
+namespace v8 { namespace internal {
+
+
+// ----------------------------------------------------------------------------
+// Static IC stub generators.
+//
+
+#define __ masm->
+
+
+// Helper function used from LoadIC/CallIC GenerateNormal.
+static void GenerateDictionaryLoad(MacroAssembler* masm,
+                                   Label* miss,
+                                   Register t0,
+                                   Register t1) {
+  // Register use:
+  //
+  // t0 - used to hold the property dictionary.
+  //
+  // t1 - initially the receiver
+  //    - used for the index into the property dictionary
+  //    - holds the result on exit.
+  //
+  // r3 - used as temporary and to hold the capacity of the property
+  //      dictionary.
+  //
+  // r2 - holds the name of the property and is unchanges.
+
+  Label done;
+
+  // Check for the absence of an interceptor.
+  // Load the map into t0.
+  __ ldr(t0, FieldMemOperand(t1, JSObject::kMapOffset));
+  // Test the has_named_interceptor bit in the map.
+  __ ldr(t0, FieldMemOperand(t1, Map::kInstanceAttributesOffset));
+  __ tst(t0, Operand(1 << (Map::kHasNamedInterceptor + (3 * 8))));
+  // Jump to miss if the interceptor bit is set.
+  __ b(ne, miss);
+
+
+  // Check that the properties array is a dictionary.
+  __ ldr(t0, FieldMemOperand(t1, JSObject::kPropertiesOffset));
+  __ ldr(r3, FieldMemOperand(t0, HeapObject::kMapOffset));
+  __ cmp(r3, Operand(Factory::hash_table_map()));
+  __ b(ne, miss);
+
+  // Compute the capacity mask.
+  const int kCapacityOffset =
+      Array::kHeaderSize + Dictionary::kCapacityIndex * kPointerSize;
+  __ ldr(r3, FieldMemOperand(t0, kCapacityOffset));
+  __ mov(r3, Operand(r3, ASR, kSmiTagSize));  // convert smi to int
+  __ sub(r3, r3, Operand(1));
+
+  const int kElementsStartOffset =
+      Array::kHeaderSize + Dictionary::kElementsStartIndex * kPointerSize;
+
+  // Generate an unrolled loop that performs a few probes before
+  // giving up. Measurements done on Gmail indicate that 2 probes
+  // cover ~93% of loads from dictionaries.
+  static const int kProbes = 4;
+  for (int i = 0; i < kProbes; i++) {
+    // Compute the masked index: (hash + i + i * i) & mask.
+    __ ldr(t1, FieldMemOperand(r2, String::kLengthOffset));
+    __ mov(t1, Operand(t1, LSR, String::kHashShift));
+    if (i > 0) __ add(t1, t1, Operand(Dictionary::GetProbeOffset(i)));
+    __ and_(t1, t1, Operand(r3));
+
+    // Scale the index by multiplying by the element size.
+    ASSERT(Dictionary::kElementSize == 3);
+    __ add(t1, t1, Operand(t1, LSL, 1));  // t1 = t1 * 3
+
+    // Check if the key is identical to the name.
+    __ add(t1, t0, Operand(t1, LSL, 2));
+    __ ldr(ip, FieldMemOperand(t1, kElementsStartOffset));
+    __ cmp(r2, Operand(ip));
+    if (i != kProbes - 1) {
+      __ b(eq, &done);
+    } else {
+      __ b(ne, miss);
+    }
+  }
+
+  // Check that the value is a normal property.
+  __ bind(&done);  // t1 == t0 + 4*index
+  __ ldr(r3, FieldMemOperand(t1, kElementsStartOffset + 2 * kPointerSize));
+  __ tst(r3, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize));
+  __ b(ne, miss);
+
+  // Get the value at the masked, scaled index and return.
+  __ ldr(t1, FieldMemOperand(t1, kElementsStartOffset + 1 * kPointerSize));
+}
+
+
+// Helper function used to check that a value is either not a function
+// or is loaded if it is a function.
+static void GenerateCheckNonFunctionOrLoaded(MacroAssembler* masm,
+                                             Label* miss,
+                                             Register value,
+                                             Register scratch) {
+  Label done;
+  // Check if the value is a Smi.
+  __ tst(value, Operand(kSmiTagMask));
+  __ b(eq, &done);
+  // Check if the value is a function.
+  __ ldr(scratch, FieldMemOperand(value, HeapObject::kMapOffset));
+  __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
+  __ cmp(scratch, Operand(JS_FUNCTION_TYPE));
+  __ b(ne, &done);
+  // Check if the function has been loaded.
+  __ ldr(scratch,
+         FieldMemOperand(value, JSFunction::kSharedFunctionInfoOffset));
+  __ ldr(scratch,
+         FieldMemOperand(scratch, SharedFunctionInfo::kLazyLoadDataOffset));
+  __ cmp(scratch, Operand(Factory::undefined_value()));
+  __ b(ne, miss);
+  __ bind(&done);
+}
+
+
+void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+
+  Label miss;
+
+  __ ldr(r0, MemOperand(sp, 0));
+
+  StubCompiler::GenerateLoadArrayLength(masm, r0, r3, &miss);
+  __ bind(&miss);
+  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
+}
+
+
+void LoadIC::GenerateStringLength(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+  Label miss;
+
+  __ ldr(r0, MemOperand(sp, 0));
+
+  StubCompiler::GenerateLoadStringLength2(masm, r0, r1, r3, &miss);
+  // Cache miss: Jump to runtime.
+  __ bind(&miss);
+  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
+}
+
+
+void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+
+  // NOTE: Right now, this code always misses on ARM which is
+  // sub-optimal. We should port the fast case code from IA-32.
+
+  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+}
+
+
+// Defined in ic.cc.
+Object* CallIC_Miss(Arguments args);
+
+void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
+  // ----------- S t a t e -------------
+  //  -- lr: return address
+  // -----------------------------------
+  Label number, non_number, non_string, boolean, probe, miss;
+
+  // Get the receiver of the function from the stack into r1.
+  __ ldr(r1, MemOperand(sp, argc * kPointerSize));
+  // Get the name of the function from the stack; 1 ~ receiver.
+  __ ldr(r2, MemOperand(sp, (argc + 1) * kPointerSize));
+
+  // Probe the stub cache.
+  Code::Flags flags =
+      Code::ComputeFlags(Code::CALL_IC, MONOMORPHIC, NORMAL, argc);
+  StubCache::GenerateProbe(masm, flags, r1, r2, r3);
+
+  // If the stub cache probing failed, the receiver might be a value.
+  // For value objects, we use the map of the prototype objects for
+  // the corresponding JSValue for the cache and that is what we need
+  // to probe.
+  //
+  // Check for number.
+  __ tst(r1, Operand(kSmiTagMask));
+  __ b(eq, &number);
+  __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
+  __ ldrb(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
+  __ cmp(r3, Operand(HEAP_NUMBER_TYPE));
+  __ b(ne, &non_number);
+  __ bind(&number);
+  StubCompiler::GenerateLoadGlobalFunctionPrototype(
+      masm, Context::NUMBER_FUNCTION_INDEX, r1);
+  __ b(&probe);
+
+  // Check for string.
+  __ bind(&non_number);
+  __ cmp(r3, Operand(FIRST_NONSTRING_TYPE));
+  __ b(hs, &non_string);
+  StubCompiler::GenerateLoadGlobalFunctionPrototype(
+      masm, Context::STRING_FUNCTION_INDEX, r1);
+  __ b(&probe);
+
+  // Check for boolean.
+  __ bind(&non_string);
+  __ cmp(r1, Operand(Factory::true_value()));
+  __ b(eq, &boolean);
+  __ cmp(r1, Operand(Factory::false_value()));
+  __ b(ne, &miss);
+  __ bind(&boolean);
+  StubCompiler::GenerateLoadGlobalFunctionPrototype(
+      masm, Context::BOOLEAN_FUNCTION_INDEX, r1);
+
+  // Probe the stub cache for the value object.
+  __ bind(&probe);
+  StubCache::GenerateProbe(masm, flags, r1, r2, r3);
+
+  // Cache miss: Jump to runtime.
+  __ bind(&miss);
+  Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
+}
+
+
+static void GenerateNormalHelper(MacroAssembler* masm,
+                                 int argc,
+                                 bool is_global_object,
+                                 Label* miss) {
+  // Search dictionary - put result in register r1.
+  GenerateDictionaryLoad(masm, miss, r0, r1);
+
+  // Check that the value isn't a smi.
+  __ tst(r1, Operand(kSmiTagMask));
+  __ b(eq, miss);
+
+  // Check that the value is a JSFunction.
+  __ ldr(r0, FieldMemOperand(r1, HeapObject::kMapOffset));
+  __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
+  __ cmp(r0, Operand(JS_FUNCTION_TYPE));
+  __ b(ne, miss);
+
+  // Check that the function has been loaded.
+  __ ldr(r0, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
+  __ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kLazyLoadDataOffset));
+  __ cmp(r0, Operand(Factory::undefined_value()));
+  __ b(ne, miss);
+
+  // Patch the receiver with the global proxy if necessary.
+  if (is_global_object) {
+    __ ldr(r2, MemOperand(sp, argc * kPointerSize));
+    __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
+    __ str(r2, MemOperand(sp, argc * kPointerSize));
+  }
+
+  // Invoke the function.
+  ParameterCount actual(argc);
+  __ InvokeFunction(r1, actual, JUMP_FUNCTION);
+}
+
+
+void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
+  // ----------- S t a t e -------------
+  //  -- lr: return address
+  // -----------------------------------
+
+  Label miss, global_object, non_global_object;
+
+  // Get the receiver of the function from the stack into r1.
+  __ ldr(r1, MemOperand(sp, argc * kPointerSize));
+  // Get the name of the function from the stack; 1 ~ receiver.
+  __ ldr(r2, MemOperand(sp, (argc + 1) * kPointerSize));
+
+  // Check that the receiver isn't a smi.
+  __ tst(r1, Operand(kSmiTagMask));
+  __ b(eq, &miss);
+
+  // Check that the receiver is a valid JS object.
+  __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
+  __ ldrb(r0, FieldMemOperand(r3, Map::kInstanceTypeOffset));
+  __ cmp(r0, Operand(FIRST_JS_OBJECT_TYPE));
+  __ b(lt, &miss);
+
+  // If this assert fails, we have to check upper bound too.
+  ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
+
+  // Check for access to global object.
+  __ cmp(r0, Operand(JS_GLOBAL_OBJECT_TYPE));
+  __ b(eq, &global_object);
+  __ cmp(r0, Operand(JS_BUILTINS_OBJECT_TYPE));
+  __ b(ne, &non_global_object);
+
+  // Accessing global object: Load and invoke.
+  __ bind(&global_object);
+  // Check that the global object does not require access checks.
+  __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset));
+  __ tst(r3, Operand(1 << Map::kIsAccessCheckNeeded));
+  __ b(ne, &miss);
+  GenerateNormalHelper(masm, argc, true, &miss);
+
+  // Accessing non-global object: Check for access to global proxy.
+  Label global_proxy, invoke;
+  __ bind(&non_global_object);
+  __ cmp(r0, Operand(JS_GLOBAL_PROXY_TYPE));
+  __ b(eq, &global_proxy);
+  // Check that the non-global, non-global-proxy object does not
+  // require access checks.
+  __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset));
+  __ tst(r3, Operand(1 << Map::kIsAccessCheckNeeded));
+  __ b(ne, &miss);
+  __ bind(&invoke);
+  GenerateNormalHelper(masm, argc, false, &miss);
+
+  // Global object access: Check access rights.
+  __ bind(&global_proxy);
+  __ CheckAccessGlobalProxy(r1, r0, &miss);
+  __ b(&invoke);
+
+  // Cache miss: Jump to runtime.
+  __ bind(&miss);
+  Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
+}
+
+
+void CallIC::Generate(MacroAssembler* masm,
+                      int argc,
+                      const ExternalReference& f) {
+  // ----------- S t a t e -------------
+  //  -- lr: return address
+  // -----------------------------------
+
+  // Get the receiver of the function from the stack.
+  __ ldr(r2, MemOperand(sp, argc * kPointerSize));
+  // Get the name of the function to call from the stack.
+  __ ldr(r1, MemOperand(sp, (argc + 1) * kPointerSize));
+
+  __ EnterInternalFrame();
+
+  // Push the receiver and the name of the function.
+  __ stm(db_w, sp, r1.bit() | r2.bit());
+
+  // Call the entry.
+  __ mov(r0, Operand(2));
+  __ mov(r1, Operand(f));
+
+  CEntryStub stub;
+  __ CallStub(&stub);
+
+  // Move result to r1 and leave the internal frame.
+  __ mov(r1, Operand(r0));
+  __ LeaveInternalFrame();
+
+  // Check if the receiver is a global object of some sort.
+  Label invoke, global;
+  __ ldr(r2, MemOperand(sp, argc * kPointerSize));  // receiver
+  __ tst(r2, Operand(kSmiTagMask));
+  __ b(eq, &invoke);
+  __ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
+  __ ldrb(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
+  __ cmp(r3, Operand(JS_GLOBAL_OBJECT_TYPE));
+  __ b(eq, &global);
+  __ cmp(r3, Operand(JS_BUILTINS_OBJECT_TYPE));
+  __ b(ne, &invoke);
+
+  // Patch the receiver on the stack.
+  __ bind(&global);
+  __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
+  __ str(r2, MemOperand(sp, argc * kPointerSize));
+
+  // Invoke the function.
+  ParameterCount actual(argc);
+  __ bind(&invoke);
+  __ InvokeFunction(r1, actual, JUMP_FUNCTION);
+}
+
+
+// Defined in ic.cc.
+Object* LoadIC_Miss(Arguments args);
+
+void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+
+  __ ldr(r0, MemOperand(sp, 0));
+  // Probe the stub cache.
+  Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, MONOMORPHIC);
+  StubCache::GenerateProbe(masm, flags, r0, r2, r3);
+
+  // Cache miss: Jump to runtime.
+  Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
+}
+
+
+void LoadIC::GenerateNormal(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+
+  Label miss, probe, global;
+
+  __ ldr(r0, MemOperand(sp, 0));
+  // Check that the receiver isn't a smi.
+  __ tst(r0, Operand(kSmiTagMask));
+  __ b(eq, &miss);
+
+  // Check that the receiver is a valid JS object.
+  __ ldr(r3, FieldMemOperand(r0, HeapObject::kMapOffset));
+  __ ldrb(r1, FieldMemOperand(r3, Map::kInstanceTypeOffset));
+  __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE));
+  __ b(lt, &miss);
+  // If this assert fails, we have to check upper bound too.
+  ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
+
+  // Check for access to global object (unlikely).
+  __ cmp(r1, Operand(JS_GLOBAL_PROXY_TYPE));
+  __ b(eq, &global);
+
+  // Check for non-global object that requires access check.
+  __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset));
+  __ tst(r3, Operand(1 << Map::kIsAccessCheckNeeded));
+  __ b(ne, &miss);
+
+  __ bind(&probe);
+  GenerateDictionaryLoad(masm, &miss, r1, r0);
+  GenerateCheckNonFunctionOrLoaded(masm, &miss, r0, r1);
+  __ Ret();
+
+  // Global object access: Check access rights.
+  __ bind(&global);
+  __ CheckAccessGlobalProxy(r0, r1, &miss);
+  __ b(&probe);
+
+  // Cache miss: Restore receiver from stack and jump to runtime.
+  __ bind(&miss);
+  Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
+}
+
+
+void LoadIC::GenerateMiss(MacroAssembler* masm) {
+  Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
+}
+
+
+void LoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
+  // ----------- S t a t e -------------
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+
+  __ ldr(r3, MemOperand(sp, 0));
+  __ stm(db_w, sp, r2.bit() | r3.bit());
+
+  // Perform tail call to the entry.
+  __ TailCallRuntime(f, 2);
+}
+
+
+// TODO(181): Implement map patching once loop nesting is tracked on
+// the ARM platform so we can generate inlined fast-case code for
+// array indexing in loops.
+void KeyedLoadIC::PatchInlinedMapCheck(Address address, Object* value) { }
+
+
+Object* KeyedLoadIC_Miss(Arguments args);
+
+
+void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
+  Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss)));
+}
+
+
+void KeyedLoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
+  // ---------- S t a t e --------------
+  //  -- lr     : return address
+  //  -- sp[0]  : key
+  //  -- sp[4]  : receiver
+  __ ldm(ia, sp, r2.bit() | r3.bit());
+  __ stm(db_w, sp, r2.bit() | r3.bit());
+
+  __ TailCallRuntime(f, 2);
+}
+
+
+void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
+  // ---------- S t a t e --------------
+  //  -- lr     : return address
+  //  -- sp[0]  : key
+  //  -- sp[4]  : receiver
+  Label slow, fast;
+
+  // Get the key and receiver object from the stack.
+  __ ldm(ia, sp, r0.bit() | r1.bit());
+  // Check that the key is a smi.
+  __ tst(r0, Operand(kSmiTagMask));
+  __ b(ne, &slow);
+  __ mov(r0, Operand(r0, ASR, kSmiTagSize));
+  // Check that the object isn't a smi.
+  __ tst(r1, Operand(kSmiTagMask));
+  __ b(eq, &slow);
+
+  // Get the map of the receiver.
+  __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+  // Check that the receiver does not require access checks.  We need
+  // to check this explicitly since this generic stub does not perform
+  // map checks.
+  __ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset));
+  __ tst(r3, Operand(1 << Map::kIsAccessCheckNeeded));
+  __ b(ne, &slow);
+  // Check that the object is some kind of JS object EXCEPT JS Value type.
+  // In the case that the object is a value-wrapper object,
+  // we enter the runtime system to make sure that indexing into string
+  // objects work as intended.
+  ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
+  __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
+  __ cmp(r2, Operand(JS_OBJECT_TYPE));
+  __ b(lt, &slow);
+
+  // Get the elements array of the object.
+  __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset));
+  // Check that the object is in fast mode (not dictionary).
+  __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
+  __ cmp(r3, Operand(Factory::hash_table_map()));
+  __ b(eq, &slow);
+  // Check that the key (index) is within bounds.
+  __ ldr(r3, FieldMemOperand(r1, Array::kLengthOffset));
+  __ cmp(r0, Operand(r3));
+  __ b(lo, &fast);
+
+  // Slow case: Push extra copies of the arguments (2).
+  __ bind(&slow);
+  __ IncrementCounter(&Counters::keyed_load_generic_slow, 1, r0, r1);
+  __ ldm(ia, sp, r0.bit() | r1.bit());
+  __ stm(db_w, sp, r0.bit() | r1.bit());
+  // Do tail-call to runtime routine.
+  __ TailCallRuntime(ExternalReference(Runtime::kGetProperty), 2);
+
+  // Fast case: Do the load.
+  __ bind(&fast);
+  __ add(r3, r1, Operand(Array::kHeaderSize - kHeapObjectTag));
+  __ ldr(r0, MemOperand(r3, r0, LSL, kPointerSizeLog2));
+  __ cmp(r0, Operand(Factory::the_hole_value()));
+  // In case the loaded value is the_hole we have to consult GetProperty
+  // to ensure the prototype chain is searched.
+  __ b(eq, &slow);
+
+  __ Ret();
+}
+
+
+void KeyedStoreIC::Generate(MacroAssembler* masm,
+                            const ExternalReference& f) {
+  // ---------- S t a t e --------------
+  //  -- r0     : value
+  //  -- lr     : return address
+  //  -- sp[0]  : key
+  //  -- sp[1]  : receiver
+
+  __ ldm(ia, sp, r2.bit() | r3.bit());
+  __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
+
+  __ TailCallRuntime(f, 3);
+}
+
+
+void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
+  // ---------- S t a t e --------------
+  //  -- r0     : value
+  //  -- lr     : return address
+  //  -- sp[0]  : key
+  //  -- sp[1]  : receiver
+  Label slow, fast, array, extra, exit;
+  // Get the key and the object from the stack.
+  __ ldm(ia, sp, r1.bit() | r3.bit());  // r1 = key, r3 = receiver
+  // Check that the key is a smi.
+  __ tst(r1, Operand(kSmiTagMask));
+  __ b(ne, &slow);
+  // Check that the object isn't a smi.
+  __ tst(r3, Operand(kSmiTagMask));
+  __ b(eq, &slow);
+  // Get the map of the object.
+  __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
+  // Check that the receiver does not require access checks.  We need
+  // to do this because this generic stub does not perform map checks.
+  __ ldrb(ip, FieldMemOperand(r2, Map::kBitFieldOffset));
+  __ tst(ip, Operand(1 << Map::kIsAccessCheckNeeded));
+  __ b(ne, &slow);
+  // Check if the object is a JS array or not.
+  __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
+  __ cmp(r2, Operand(JS_ARRAY_TYPE));
+  // r1 == key.
+  __ b(eq, &array);
+  // Check that the object is some kind of JS object.
+  __ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE));
+  __ b(lt, &slow);
+
+
+  // Object case: Check key against length in the elements array.
+  __ ldr(r3, FieldMemOperand(r3, JSObject::kElementsOffset));
+  // Check that the object is in fast mode (not dictionary).
+  __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
+  __ cmp(r2, Operand(Factory::hash_table_map()));
+  __ b(eq, &slow);
+  // Untag the key (for checking against untagged length in the fixed array).
+  __ mov(r1, Operand(r1, ASR, kSmiTagSize));
+  // Compute address to store into and check array bounds.
+  __ add(r2, r3, Operand(Array::kHeaderSize - kHeapObjectTag));
+  __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2));
+  __ ldr(ip, FieldMemOperand(r3, Array::kLengthOffset));
+  __ cmp(r1, Operand(ip));
+  __ b(lo, &fast);
+
+
+  // Slow case: Push extra copies of the arguments (3).
+  __ bind(&slow);
+  __ ldm(ia, sp, r1.bit() | r3.bit());  // r0 == value, r1 == key, r3 == object
+  __ stm(db_w, sp, r0.bit() | r1.bit() | r3.bit());
+  // Do tail-call to runtime routine.
+  __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3);
+
+  // Extra capacity case: Check if there is extra capacity to
+  // perform the store and update the length. Used for adding one
+  // element to the array by writing to array[array.length].
+  // r0 == value, r1 == key, r2 == elements, r3 == object
+  __ bind(&extra);
+  __ b(ne, &slow);  // do not leave holes in the array
+  __ mov(r1, Operand(r1, ASR, kSmiTagSize));  // untag
+  __ ldr(ip, FieldMemOperand(r2, Array::kLengthOffset));
+  __ cmp(r1, Operand(ip));
+  __ b(hs, &slow);
+  __ mov(r1, Operand(r1, LSL, kSmiTagSize));  // restore tag
+  __ add(r1, r1, Operand(1 << kSmiTagSize));  // and increment
+  __ str(r1, FieldMemOperand(r3, JSArray::kLengthOffset));
+  __ mov(r3, Operand(r2));
+  // NOTE: Computing the address to store into must take the fact
+  // that the key has been incremented into account.
+  int displacement = Array::kHeaderSize - kHeapObjectTag -
+      ((1 << kSmiTagSize) * 2);
+  __ add(r2, r2, Operand(displacement));
+  __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));
+  __ b(&fast);
+
+
+  // Array case: Get the length and the elements array from the JS
+  // array. Check that the array is in fast mode; if it is the
+  // length is always a smi.
+  // r0 == value, r3 == object
+  __ bind(&array);
+  __ ldr(r2, FieldMemOperand(r3, JSObject::kElementsOffset));
+  __ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset));
+  __ cmp(r1, Operand(Factory::hash_table_map()));
+  __ b(eq, &slow);
+
+  // Check the key against the length in the array, compute the
+  // address to store into and fall through to fast case.
+  __ ldr(r1, MemOperand(sp));  // restore key
+  // r0 == value, r1 == key, r2 == elements, r3 == object.
+  __ ldr(ip, FieldMemOperand(r3, JSArray::kLengthOffset));
+  __ cmp(r1, Operand(ip));
+  __ b(hs, &extra);
+  __ mov(r3, Operand(r2));
+  __ add(r2, r2, Operand(Array::kHeaderSize - kHeapObjectTag));
+  __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));
+
+
+  // Fast case: Do the store.
+  // r0 == value, r2 == address to store into, r3 == elements
+  __ bind(&fast);
+  __ str(r0, MemOperand(r2));
+  // Skip write barrier if the written value is a smi.
+  __ tst(r0, Operand(kSmiTagMask));
+  __ b(eq, &exit);
+  // Update write barrier for the elements array address.
+  __ sub(r1, r2, Operand(r3));
+  __ RecordWrite(r3, r1, r2);
+
+  __ bind(&exit);
+  __ Ret();
+}
+
+
+void KeyedStoreIC::GenerateExtendStorage(MacroAssembler* masm) {
+  // ---------- S t a t e --------------
+  //  -- r0     : value
+  //  -- lr     : return address
+  //  -- sp[0]  : key
+  //  -- sp[1]  : receiver
+  // ----------- S t a t e -------------
+
+  __ ldm(ia, sp, r2.bit() | r3.bit());
+  __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
+
+  // Perform tail call to the entry.
+  __ TailCallRuntime(
+      ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3);
+}
+
+
+void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r0    : value
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+
+  // Get the receiver from the stack and probe the stub cache.
+  __ ldr(r1, MemOperand(sp));
+  Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, MONOMORPHIC);
+  StubCache::GenerateProbe(masm, flags, r1, r2, r3);
+
+  // Cache miss: Jump to runtime.
+  Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss)));
+}
+
+
+void StoreIC::GenerateExtendStorage(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r0    : value
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+
+  __ ldr(r3, MemOperand(sp));  // copy receiver
+  __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
+
+  // Perform tail call to the entry.
+  __ TailCallRuntime(
+      ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3);
+}
+
+
+void StoreIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
+  // ----------- S t a t e -------------
+  //  -- r0    : value
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+
+  __ ldr(r3, MemOperand(sp));  // copy receiver
+  __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
+
+  // Perform tail call to the entry.
+  __ TailCallRuntime(f, 3);
+}
+
+
+#undef __
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/ic-ia32.cc b/deps/v8/src/ic-ia32.cc
new file mode 100644
index 0000000..9060f2d
--- /dev/null
+++ b/deps/v8/src/ic-ia32.cc
@@ -0,0 +1,892 @@
+// 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.
+
+#include "v8.h"
+
+#include "codegen-inl.h"
+#include "ic-inl.h"
+#include "runtime.h"
+#include "stub-cache.h"
+
+namespace v8 { namespace internal {
+
+// ----------------------------------------------------------------------------
+// Static IC stub generators.
+//
+
+#define __ masm->
+
+
+// Helper function used to load a property from a dictionary backing storage.
+static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label,
+                                   Register r0, Register r1, Register r2,
+                                   Register name) {
+  // Register use:
+  //
+  // r0   - used to hold the property dictionary.
+  //
+  // r1   - initially the receiver
+  //      - used for the index into the property dictionary
+  //      - holds the result on exit.
+  //
+  // r2   - used to hold the capacity of the property dictionary.
+  //
+  // name - holds the name of the property and is unchanges.
+
+  Label done;
+
+  // Check for the absence of an interceptor.
+  // Load the map into r0.
+  __ mov(r0, FieldOperand(r1, JSObject::kMapOffset));
+  // Test the has_named_interceptor bit in the map.
+  __ test(FieldOperand(r0, Map::kInstanceAttributesOffset),
+          Immediate(1 << (Map::kHasNamedInterceptor + (3 * 8))));
+  // Jump to miss if the interceptor bit is set.
+  __ j(not_zero, miss_label, not_taken);
+
+  // Check that the properties array is a dictionary.
+  __ mov(r0, FieldOperand(r1, JSObject::kPropertiesOffset));
+  __ cmp(FieldOperand(r0, HeapObject::kMapOffset),
+         Immediate(Factory::hash_table_map()));
+  __ j(not_equal, miss_label);
+
+  // Compute the capacity mask.
+  const int kCapacityOffset =
+      Array::kHeaderSize + Dictionary::kCapacityIndex * kPointerSize;
+  __ mov(r2, FieldOperand(r0, kCapacityOffset));
+  __ shr(r2, kSmiTagSize);  // convert smi to int
+  __ dec(r2);
+
+  // Generate an unrolled loop that performs a few probes before
+  // giving up. Measurements done on Gmail indicate that 2 probes
+  // cover ~93% of loads from dictionaries.
+  static const int kProbes = 4;
+  const int kElementsStartOffset =
+      Array::kHeaderSize + Dictionary::kElementsStartIndex * kPointerSize;
+  for (int i = 0; i < kProbes; i++) {
+    // Compute the masked index: (hash + i + i * i) & mask.
+    __ mov(r1, FieldOperand(name, String::kLengthOffset));
+    __ shr(r1, String::kHashShift);
+    if (i > 0) __ add(Operand(r1), Immediate(Dictionary::GetProbeOffset(i)));
+    __ and_(r1, Operand(r2));
+
+    // Scale the index by multiplying by the element size.
+    ASSERT(Dictionary::kElementSize == 3);
+    __ lea(r1, Operand(r1, r1, times_2, 0));  // r1 = r1 * 3
+
+    // Check if the key is identical to the name.
+    __ cmp(name,
+           Operand(r0, r1, times_4, kElementsStartOffset - kHeapObjectTag));
+    if (i != kProbes - 1) {
+      __ j(equal, &done, taken);
+    } else {
+      __ j(not_equal, miss_label, not_taken);
+    }
+  }
+
+  // Check that the value is a normal property.
+  __ bind(&done);
+  const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
+  __ test(Operand(r0, r1, times_4, kDetailsOffset - kHeapObjectTag),
+          Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize));
+  __ j(not_zero, miss_label, not_taken);
+
+  // Get the value at the masked, scaled index.
+  const int kValueOffset = kElementsStartOffset + kPointerSize;
+  __ mov(r1, Operand(r0, r1, times_4, kValueOffset - kHeapObjectTag));
+}
+
+
+// Helper function used to check that a value is either not a function
+// or is loaded if it is a function.
+static void GenerateCheckNonFunctionOrLoaded(MacroAssembler* masm, Label* miss,
+                                             Register value, Register scratch) {
+  Label done;
+  // Check if the value is a Smi.
+  __ test(value, Immediate(kSmiTagMask));
+  __ j(zero, &done, not_taken);
+  // Check if the value is a function.
+  __ CmpObjectType(value, JS_FUNCTION_TYPE, scratch);
+  __ j(not_equal, &done, taken);
+  // Check if the function has been loaded.
+  __ mov(scratch, FieldOperand(value, JSFunction::kSharedFunctionInfoOffset));
+  __ mov(scratch,
+         FieldOperand(scratch, SharedFunctionInfo::kLazyLoadDataOffset));
+  __ cmp(scratch, Factory::undefined_value());
+  __ j(not_equal, miss, not_taken);
+  __ bind(&done);
+}
+
+
+void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- ecx    : name
+  //  -- esp[0] : return address
+  //  -- esp[4] : receiver
+  // -----------------------------------
+
+  Label miss;
+
+  __ mov(eax, Operand(esp, kPointerSize));
+
+  StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss);
+  __ bind(&miss);
+  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
+}
+
+
+void LoadIC::GenerateStringLength(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- ecx    : name
+  //  -- esp[0] : return address
+  //  -- esp[4] : receiver
+  // -----------------------------------
+
+  Label miss;
+
+  __ mov(eax, Operand(esp, kPointerSize));
+
+  StubCompiler::GenerateLoadStringLength(masm, eax, edx, &miss);
+  __ bind(&miss);
+  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
+}
+
+
+void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- ecx    : name
+  //  -- esp[0] : return address
+  //  -- esp[4] : receiver
+  // -----------------------------------
+
+  Label miss;
+
+  __ mov(eax, Operand(esp, kPointerSize));
+
+  StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss);
+  __ bind(&miss);
+  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
+}
+
+
+#ifdef DEBUG
+// For use in assert below.
+static int TenToThe(int exponent) {
+  ASSERT(exponent <= 9);
+  ASSERT(exponent >= 1);
+  int answer = 10;
+  for (int i = 1; i < exponent; i++) answer *= 10;
+  return answer;
+}
+#endif
+
+
+void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- esp[0] : return address
+  //  -- esp[4] : name
+  //  -- esp[8] : receiver
+  // -----------------------------------
+  Label slow, fast, check_string, index_int, index_string;
+
+  // Load name and receiver.
+  __ mov(eax, (Operand(esp, kPointerSize)));
+  __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
+
+  // Check that the object isn't a smi.
+  __ test(ecx, Immediate(kSmiTagMask));
+  __ j(zero, &slow, not_taken);
+
+  // Get the map of the receiver.
+  __ mov(edx, FieldOperand(ecx, HeapObject::kMapOffset));
+  // Check that the receiver does not require access checks.  We need
+  // to check this explicitly since this generic stub does not perform
+  // map checks.
+  __ movzx_b(ebx, FieldOperand(edx, Map::kBitFieldOffset));
+  __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
+  __ j(not_zero, &slow, not_taken);
+  // Check that the object is some kind of JS object EXCEPT JS Value type.
+  // In the case that the object is a value-wrapper object,
+  // we enter the runtime system to make sure that indexing
+  // into string objects work as intended.
+  ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
+  __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset));
+  __ cmp(edx, JS_OBJECT_TYPE);
+  __ j(less, &slow, not_taken);
+  // Check that the key is a smi.
+  __ test(eax, Immediate(kSmiTagMask));
+  __ j(not_zero, &check_string, not_taken);
+  __ sar(eax, kSmiTagSize);
+  // Get the elements array of the object.
+  __ bind(&index_int);
+  __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset));
+  // Check that the object is in fast mode (not dictionary).
+  __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
+         Immediate(Factory::hash_table_map()));
+  __ j(equal, &slow, not_taken);
+  // Check that the key (index) is within bounds.
+  __ cmp(eax, FieldOperand(ecx, Array::kLengthOffset));
+  __ j(below, &fast, taken);
+  // Slow case: Load name and receiver from stack and jump to runtime.
+  __ bind(&slow);
+  __ IncrementCounter(&Counters::keyed_load_generic_slow, 1);
+  KeyedLoadIC::Generate(masm, ExternalReference(Runtime::kKeyedGetProperty));
+  // Check if the key is a symbol that is not an array index.
+  __ bind(&check_string);
+  __ mov(ebx, FieldOperand(eax, String::kLengthOffset));
+  __ test(ebx, Immediate(String::kIsArrayIndexMask));
+  __ j(not_zero, &index_string, not_taken);
+  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
+  __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
+  __ test(ebx, Immediate(kIsSymbolMask));
+  __ j(not_zero, &slow, not_taken);
+  // Probe the dictionary leaving result in ecx.
+  GenerateDictionaryLoad(masm, &slow, ebx, ecx, edx, eax);
+  GenerateCheckNonFunctionOrLoaded(masm, &slow, ecx, edx);
+  __ mov(eax, Operand(ecx));
+  __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
+  __ ret(0);
+  // Array index string: If short enough use cache in length/hash field (ebx).
+  // We assert that there are enough bits in an int32_t after the hash shift
+  // bits have been subtracted to allow space for the length and the cached
+  // array index.
+  ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
+         (1 << (String::kShortLengthShift - String::kHashShift)));
+  __ bind(&index_string);
+  const int kLengthFieldLimit =
+      (String::kMaxCachedArrayIndexLength + 1) << String::kShortLengthShift;
+  __ cmp(ebx, kLengthFieldLimit);
+  __ j(above_equal, &slow);
+  __ mov(eax, Operand(ebx));
+  __ and_(eax, (1 << String::kShortLengthShift) - 1);
+  __ shr(eax, String::kLongLengthShift);
+  __ jmp(&index_int);
+  // Fast case: Do the load.
+  __ bind(&fast);
+  __ mov(eax, Operand(ecx, eax, times_4, Array::kHeaderSize - kHeapObjectTag));
+  __ cmp(Operand(eax), Immediate(Factory::the_hole_value()));
+  // In case the loaded value is the_hole we have to consult GetProperty
+  // to ensure the prototype chain is searched.
+  __ j(equal, &slow, not_taken);
+  __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
+  __ ret(0);
+}
+
+
+void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- eax    : value
+  //  -- esp[0] : return address
+  //  -- esp[4] : key
+  //  -- esp[8] : receiver
+  // -----------------------------------
+  Label slow, fast, array, extra;
+
+  // Get the receiver from the stack.
+  __ mov(edx, Operand(esp, 2 * kPointerSize));  // 2 ~ return address, key
+  // Check that the object isn't a smi.
+  __ test(edx, Immediate(kSmiTagMask));
+  __ j(zero, &slow, not_taken);
+  // Get the map from the receiver.
+  __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
+  // Check that the receiver does not require access checks.  We need
+  // to do this because this generic stub does not perform map checks.
+  __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset));
+  __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
+  __ j(not_zero, &slow, not_taken);
+  // Get the key from the stack.
+  __ mov(ebx, Operand(esp, 1 * kPointerSize));  // 1 ~ return address
+  // Check that the key is a smi.
+  __ test(ebx, Immediate(kSmiTagMask));
+  __ j(not_zero, &slow, not_taken);
+  // Get the instance type from the map of the receiver.
+  __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
+  // Check if the object is a JS array or not.
+  __ cmp(ecx, JS_ARRAY_TYPE);
+  __ j(equal, &array);
+  // Check that the object is some kind of JS object.
+  __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
+  __ j(less, &slow, not_taken);
+
+  // Object case: Check key against length in the elements array.
+  // eax: value
+  // edx: JSObject
+  // ebx: index (as a smi)
+  __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
+  // Check that the object is in fast mode (not dictionary).
+  __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
+         Immediate(Factory::hash_table_map()));
+  __ j(equal, &slow, not_taken);
+  // Untag the key (for checking against untagged length in the fixed array).
+  __ mov(edx, Operand(ebx));
+  __ sar(edx, kSmiTagSize);  // untag the index and use it for the comparison
+  __ cmp(edx, FieldOperand(ecx, Array::kLengthOffset));
+  // eax: value
+  // ecx: FixedArray
+  // ebx: index (as a smi)
+  __ j(below, &fast, taken);
+
+
+  // Slow case: Push extra copies of the arguments (3).
+  __ bind(&slow);
+  __ pop(ecx);
+  __ push(Operand(esp, 1 * kPointerSize));
+  __ push(Operand(esp, 1 * kPointerSize));
+  __ push(eax);
+  __ push(ecx);
+  // Do tail-call to runtime routine.
+  __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3);
+
+
+  // Extra capacity case: Check if there is extra capacity to
+  // perform the store and update the length. Used for adding one
+  // element to the array by writing to array[array.length].
+  __ bind(&extra);
+  // eax: value
+  // edx: JSArray
+  // ecx: FixedArray
+  // ebx: index (as a smi)
+  // flags: compare (ebx, edx.length())
+  __ j(not_equal, &slow, not_taken);  // do not leave holes in the array
+  __ sar(ebx, kSmiTagSize);  // untag
+  __ cmp(ebx, FieldOperand(ecx, Array::kLengthOffset));
+  __ j(above_equal, &slow, not_taken);
+  // Restore tag and increment.
+  __ lea(ebx, Operand(ebx, times_2, 1 << kSmiTagSize));
+  __ mov(FieldOperand(edx, JSArray::kLengthOffset), ebx);
+  __ sub(Operand(ebx), Immediate(1 << kSmiTagSize));  // decrement ebx again
+  __ jmp(&fast);
+
+
+  // Array case: Get the length and the elements array from the JS
+  // array. Check that the array is in fast mode; if it is the
+  // length is always a smi.
+  __ bind(&array);
+  // eax: value
+  // edx: JSArray
+  // ebx: index (as a smi)
+  __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
+  __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
+         Immediate(Factory::hash_table_map()));
+  __ j(equal, &slow, not_taken);
+
+  // Check the key against the length in the array, compute the
+  // address to store into and fall through to fast case.
+  __ cmp(ebx, FieldOperand(edx, JSArray::kLengthOffset));
+  __ j(above_equal, &extra, not_taken);
+
+
+  // Fast case: Do the store.
+  __ bind(&fast);
+  // eax: value
+  // ecx: FixedArray
+  // ebx: index (as a smi)
+  __ mov(Operand(ecx, ebx, times_2, Array::kHeaderSize - kHeapObjectTag), eax);
+  // Update write barrier for the elements array address.
+  __ mov(edx, Operand(eax));
+  __ RecordWrite(ecx, 0, edx, ebx);
+  __ ret(0);
+}
+
+
+// Defined in ic.cc.
+Object* CallIC_Miss(Arguments args);
+
+void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
+  // ----------- S t a t e -------------
+  // -----------------------------------
+  Label number, non_number, non_string, boolean, probe, miss;
+
+  // Get the receiver of the function from the stack; 1 ~ return address.
+  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
+  // Get the name of the function from the stack; 2 ~ return address, receiver
+  __ mov(ecx, Operand(esp, (argc + 2) * kPointerSize));
+
+  // Probe the stub cache.
+  Code::Flags flags =
+      Code::ComputeFlags(Code::CALL_IC, MONOMORPHIC, NORMAL, argc);
+  StubCache::GenerateProbe(masm, flags, edx, ecx, ebx);
+
+  // If the stub cache probing failed, the receiver might be a value.
+  // For value objects, we use the map of the prototype objects for
+  // the corresponding JSValue for the cache and that is what we need
+  // to probe.
+  //
+  // Check for number.
+  __ test(edx, Immediate(kSmiTagMask));
+  __ j(zero, &number, not_taken);
+  __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx);
+  __ j(not_equal, &non_number, taken);
+  __ bind(&number);
+  StubCompiler::GenerateLoadGlobalFunctionPrototype(
+      masm, Context::NUMBER_FUNCTION_INDEX, edx);
+  __ jmp(&probe);
+
+  // Check for string.
+  __ bind(&non_number);
+  __ cmp(ebx, FIRST_NONSTRING_TYPE);
+  __ j(above_equal, &non_string, taken);
+  StubCompiler::GenerateLoadGlobalFunctionPrototype(
+      masm, Context::STRING_FUNCTION_INDEX, edx);
+  __ jmp(&probe);
+
+  // Check for boolean.
+  __ bind(&non_string);
+  __ cmp(edx, Factory::true_value());
+  __ j(equal, &boolean, not_taken);
+  __ cmp(edx, Factory::false_value());
+  __ j(not_equal, &miss, taken);
+  __ bind(&boolean);
+  StubCompiler::GenerateLoadGlobalFunctionPrototype(
+      masm, Context::BOOLEAN_FUNCTION_INDEX, edx);
+
+  // Probe the stub cache for the value object.
+  __ bind(&probe);
+  StubCache::GenerateProbe(masm, flags, edx, ecx, ebx);
+
+  // Cache miss: Jump to runtime.
+  __ bind(&miss);
+  Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
+}
+
+
+static void GenerateNormalHelper(MacroAssembler* masm,
+                                 int argc,
+                                 bool is_global_object,
+                                 Label* miss) {
+  // Search dictionary - put result in register edx.
+  GenerateDictionaryLoad(masm, miss, eax, edx, ebx, ecx);
+
+  // Move the result to register edi and check that it isn't a smi.
+  __ mov(edi, Operand(edx));
+  __ test(edx, Immediate(kSmiTagMask));
+  __ j(zero, miss, not_taken);
+
+  // Check that the value is a JavaScript function.
+  __ CmpObjectType(edx, JS_FUNCTION_TYPE, edx);
+  __ j(not_equal, miss, not_taken);
+
+  // Check that the function has been loaded.
+  __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
+  __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kLazyLoadDataOffset));
+  __ cmp(edx, Factory::undefined_value());
+  __ j(not_equal, miss, not_taken);
+
+  // Patch the receiver with the global proxy if necessary.
+  if (is_global_object) {
+    __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
+    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
+    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
+  }
+
+  // Invoke the function.
+  ParameterCount actual(argc);
+  __ InvokeFunction(edi, actual, JUMP_FUNCTION);
+}
+
+
+void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
+  // ----------- S t a t e -------------
+  // -----------------------------------
+
+  Label miss, global_object, non_global_object;
+
+  // Get the receiver of the function from the stack; 1 ~ return address.
+  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
+  // Get the name of the function from the stack; 2 ~ return address, receiver.
+  __ mov(ecx, Operand(esp, (argc + 2) * kPointerSize));
+
+  // Check that the receiver isn't a smi.
+  __ test(edx, Immediate(kSmiTagMask));
+  __ j(zero, &miss, not_taken);
+
+  // Check that the receiver is a valid JS object.
+  __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
+  __ movzx_b(eax, FieldOperand(ebx, Map::kInstanceTypeOffset));
+  __ cmp(eax, FIRST_JS_OBJECT_TYPE);
+  __ j(less, &miss, not_taken);
+
+  // If this assert fails, we have to check upper bound too.
+  ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
+
+  // Check for access to global object.
+  __ cmp(eax, JS_GLOBAL_OBJECT_TYPE);
+  __ j(equal, &global_object);
+  __ cmp(eax, JS_BUILTINS_OBJECT_TYPE);
+  __ j(not_equal, &non_global_object);
+
+  // Accessing global object: Load and invoke.
+  __ bind(&global_object);
+  // Check that the global object does not require access checks.
+  __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
+  __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
+  __ j(not_equal, &miss, not_taken);
+  GenerateNormalHelper(masm, argc, true, &miss);
+
+  // Accessing non-global object: Check for access to global proxy.
+  Label global_proxy, invoke;
+  __ bind(&non_global_object);
+  __ cmp(eax, JS_GLOBAL_PROXY_TYPE);
+  __ j(equal, &global_proxy, not_taken);
+  // Check that the non-global, non-global-proxy object does not
+  // require access checks.
+  __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
+  __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
+  __ j(not_equal, &miss, not_taken);
+  __ bind(&invoke);
+  GenerateNormalHelper(masm, argc, false, &miss);
+
+  // Global object proxy access: Check access rights.
+  __ bind(&global_proxy);
+  __ CheckAccessGlobalProxy(edx, eax, &miss);
+  __ jmp(&invoke);
+
+  // Cache miss: Jump to runtime.
+  __ bind(&miss);
+  Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
+}
+
+
+void CallIC::Generate(MacroAssembler* masm,
+                      int argc,
+                      const ExternalReference& f) {
+  // ----------- S t a t e -------------
+  // -----------------------------------
+
+  // Get the receiver of the function from the stack; 1 ~ return address.
+  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
+  // Get the name of the function to call from the stack.
+  // 2 ~ receiver, return address.
+  __ mov(ebx, Operand(esp, (argc + 2) * kPointerSize));
+
+  // Enter an internal frame.
+  __ EnterInternalFrame();
+
+  // Push the receiver and the name of the function.
+  __ push(edx);
+  __ push(ebx);
+
+  // Call the entry.
+  CEntryStub stub;
+  __ mov(eax, Immediate(2));
+  __ mov(ebx, Immediate(f));
+  __ CallStub(&stub);
+
+  // Move result to edi and exit the internal frame.
+  __ mov(edi, eax);
+  __ LeaveInternalFrame();
+
+  // Check if the receiver is a global object of some sort.
+  Label invoke, global;
+  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));  // receiver
+  __ test(edx, Immediate(kSmiTagMask));
+  __ j(zero, &invoke, not_taken);
+  __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
+  __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
+  __ cmp(ecx, JS_GLOBAL_OBJECT_TYPE);
+  __ j(equal, &global);
+  __ cmp(ecx, JS_BUILTINS_OBJECT_TYPE);
+  __ j(not_equal, &invoke);
+
+  // Patch the receiver on the stack.
+  __ bind(&global);
+  __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
+  __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
+
+  // Invoke the function.
+  ParameterCount actual(argc);
+  __ bind(&invoke);
+  __ InvokeFunction(edi, actual, JUMP_FUNCTION);
+}
+
+
+// Defined in ic.cc.
+Object* LoadIC_Miss(Arguments args);
+
+void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- ecx    : name
+  //  -- esp[0] : return address
+  //  -- esp[4] : receiver
+  // -----------------------------------
+
+  __ mov(eax, Operand(esp, kPointerSize));
+
+  // Probe the stub cache.
+  Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, MONOMORPHIC);
+  StubCache::GenerateProbe(masm, flags, eax, ecx, ebx);
+
+  // Cache miss: Jump to runtime.
+  Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
+}
+
+
+void LoadIC::GenerateNormal(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- ecx    : name
+  //  -- esp[0] : return address
+  //  -- esp[4] : receiver
+  // -----------------------------------
+
+  Label miss, probe, global;
+
+  __ mov(eax, Operand(esp, kPointerSize));
+
+  // Check that the receiver isn't a smi.
+  __ test(eax, Immediate(kSmiTagMask));
+  __ j(zero, &miss, not_taken);
+
+  // Check that the receiver is a valid JS object.
+  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
+  __ movzx_b(edx, FieldOperand(ebx, Map::kInstanceTypeOffset));
+  __ cmp(edx, FIRST_JS_OBJECT_TYPE);
+  __ j(less, &miss, not_taken);
+
+  // If this assert fails, we have to check upper bound too.
+  ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
+
+  // Check for access to global object (unlikely).
+  __ cmp(edx, JS_GLOBAL_PROXY_TYPE);
+  __ j(equal, &global, not_taken);
+
+  // Check for non-global object that requires access check.
+  __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
+  __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
+  __ j(not_zero, &miss, not_taken);
+
+  // Search the dictionary placing the result in eax.
+  __ bind(&probe);
+  GenerateDictionaryLoad(masm, &miss, edx, eax, ebx, ecx);
+  GenerateCheckNonFunctionOrLoaded(masm, &miss, eax, edx);
+  __ ret(0);
+
+  // Global object access: Check access rights.
+  __ bind(&global);
+  __ CheckAccessGlobalProxy(eax, edx, &miss);
+  __ jmp(&probe);
+
+  // Cache miss: Restore receiver from stack and jump to runtime.
+  __ bind(&miss);
+  __ mov(eax, Operand(esp, 1 * kPointerSize));
+  Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
+}
+
+
+void LoadIC::GenerateMiss(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- ecx    : name
+  //  -- esp[0] : return address
+  //  -- esp[4] : receiver
+  // -----------------------------------
+
+  Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
+}
+
+
+void LoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
+  // ----------- S t a t e -------------
+  //  -- ecx    : name
+  //  -- esp[0] : return address
+  //  -- esp[4] : receiver
+  // -----------------------------------
+
+  __ mov(eax, Operand(esp, kPointerSize));
+
+  // Move the return address below the arguments.
+  __ pop(ebx);
+  __ push(eax);
+  __ push(ecx);
+  __ push(ebx);
+
+  // Perform tail call to the entry.
+  __ TailCallRuntime(f, 2);
+}
+
+
+void KeyedLoadIC::PatchInlinedMapCheck(Address address, Object* value) {
+  static const byte kTestEaxByte = 0xA9;
+  Address test_instruction_address = address + 4;  // 4 = stub address
+  // The keyed load has a fast inlined case if the IC call instruction
+  // is immediately followed by a test instruction.
+  if (*test_instruction_address == kTestEaxByte) {
+    // Fetch the offset from the test instruction to the map cmp
+    // instruction.  This offset is stored in the last 4 bytes of the
+    // 5 byte test instruction.
+    Address offset_address = test_instruction_address + 1;
+    int offset_value = *(reinterpret_cast<int*>(offset_address));
+    // Compute the map address.  The map address is in the last 4
+    // bytes of the 7-byte operand-immediate compare instruction, so
+    // we add 3 to the offset to get the map address.
+    Address map_address = test_instruction_address + offset_value + 3;
+    // patch the map check.
+    (*(reinterpret_cast<Object**>(map_address))) = value;
+  }
+}
+
+
+// Defined in ic.cc.
+Object* KeyedLoadIC_Miss(Arguments args);
+
+
+void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- esp[0] : return address
+  //  -- esp[4] : name
+  //  -- esp[8] : receiver
+  // -----------------------------------
+
+  Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss)));
+}
+
+
+void KeyedLoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
+  // ----------- S t a t e -------------
+  //  -- esp[0] : return address
+  //  -- esp[4] : name
+  //  -- esp[8] : receiver
+  // -----------------------------------
+
+  __ mov(eax, Operand(esp, kPointerSize));
+  __ mov(ecx, Operand(esp, 2 * kPointerSize));
+
+  // Move the return address below the arguments.
+  __ pop(ebx);
+  __ push(ecx);
+  __ push(eax);
+  __ push(ebx);
+
+  // Perform tail call to the entry.
+  __ TailCallRuntime(f, 2);
+}
+
+
+void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- eax    : value
+  //  -- ecx    : name
+  //  -- esp[0] : return address
+  //  -- esp[4] : receiver
+  // -----------------------------------
+
+  // Get the receiver from the stack and probe the stub cache.
+  __ mov(edx, Operand(esp, 4));
+  Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, MONOMORPHIC);
+  StubCache::GenerateProbe(masm, flags, edx, ecx, ebx);
+
+  // Cache miss: Jump to runtime.
+  Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss)));
+}
+
+
+void StoreIC::GenerateExtendStorage(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- eax    : value
+  //  -- ecx    : transition map
+  //  -- esp[0] : return address
+  //  -- esp[4] : receiver
+  // -----------------------------------
+
+  // Move the return address below the arguments.
+  __ pop(ebx);
+  __ push(Operand(esp, 0));
+  __ push(ecx);
+  __ push(eax);
+  __ push(ebx);
+  // Perform tail call to the entry.
+  __ TailCallRuntime(
+      ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3);
+}
+
+
+void StoreIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
+  // ----------- S t a t e -------------
+  //  -- eax    : value
+  //  -- ecx    : name
+  //  -- esp[0] : return address
+  //  -- esp[4] : receiver
+  // -----------------------------------
+
+  // Move the return address below the arguments.
+  __ pop(ebx);
+  __ push(Operand(esp, 0));
+  __ push(ecx);
+  __ push(eax);
+  __ push(ebx);
+
+  // Perform tail call to the entry.
+  __ TailCallRuntime(f, 3);
+}
+
+
+// Defined in ic.cc.
+Object* KeyedStoreIC_Miss(Arguments args);
+
+void KeyedStoreIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
+  // ----------- S t a t e -------------
+  //  -- eax    : value
+  //  -- esp[0] : return address
+  //  -- esp[4] : key
+  //  -- esp[8] : receiver
+  // -----------------------------------
+
+  // Move the return address below the arguments.
+  __ pop(ecx);
+  __ push(Operand(esp, 1 * kPointerSize));
+  __ push(Operand(esp, 1 * kPointerSize));
+  __ push(eax);
+  __ push(ecx);
+
+  // Do tail-call to runtime routine.
+  __ TailCallRuntime(f, 3);
+}
+
+
+void KeyedStoreIC::GenerateExtendStorage(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- eax    : value
+  //  -- ecx    : transition map
+  //  -- esp[0] : return address
+  //  -- esp[4] : key
+  //  -- esp[8] : receiver
+  // -----------------------------------
+
+  // Move the return address below the arguments.
+  __ pop(ebx);
+  __ push(Operand(esp, 1 * kPointerSize));
+  __ push(ecx);
+  __ push(eax);
+  __ push(ebx);
+
+  // Do tail-call to runtime routine.
+  __ TailCallRuntime(
+      ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3);
+}
+
+#undef __
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/ic-inl.h b/deps/v8/src/ic-inl.h
new file mode 100644
index 0000000..f5ce0ad
--- /dev/null
+++ b/deps/v8/src/ic-inl.h
@@ -0,0 +1,88 @@
+// 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_IC_INL_H_
+#define V8_IC_INL_H_
+
+#include "ic.h"
+#include "debug.h"
+#include "macro-assembler.h"
+
+namespace v8 { namespace internal {
+
+
+Address IC::address() {
+  // Get the address of the call.
+  Address result = pc() - Assembler::kTargetAddrToReturnAddrDist;
+
+  // First check if any break points are active if not just return the address
+  // of the call.
+  if (!Debug::has_break_points()) return result;
+
+  // At least one break point is active perform additional test to ensure that
+  // break point locations are updated correctly.
+  if (Debug::IsDebugBreak(Assembler::target_address_at(result))) {
+    // If the call site is a call to debug break then return the address in
+    // the original code instead of the address in the running code. This will
+    // cause the original code to be updated and keeps the breakpoint active in
+    // the running code.
+    return OriginalCodeAddress();
+  } else {
+    // No break point here just return the address of the call.
+    return result;
+  }
+}
+
+
+Code* IC::GetTargetAtAddress(Address address) {
+  // Get the target address of the IC.
+  Address target = Assembler::target_address_at(address);
+  // Convert target address to the code object. Code::GetCodeFromTargetAddress
+  // is safe for use during GC where the map might be marked.
+  Code* result = Code::GetCodeFromTargetAddress(target);
+  ASSERT(result->is_inline_cache_stub());
+  return result;
+}
+
+
+void IC::SetTargetAtAddress(Address address, Code* target) {
+  ASSERT(target->is_inline_cache_stub());
+  Assembler::set_target_address_at(address, target->instruction_start());
+}
+
+
+Map* IC::GetCodeCacheMapForObject(Object* object) {
+  if (object->IsJSObject()) return JSObject::cast(object)->map();
+  // If the object is a value, we use the prototype map for the cache.
+  ASSERT(object->IsString() || object->IsNumber() || object->IsBoolean());
+  return JSObject::cast(object->GetPrototype())->map();
+}
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_IC_INL_H_
diff --git a/deps/v8/src/ic.cc b/deps/v8/src/ic.cc
new file mode 100644
index 0000000..d7bd764
--- /dev/null
+++ b/deps/v8/src/ic.cc
@@ -0,0 +1,1218 @@
+// 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.
+
+#include "v8.h"
+
+#include "accessors.h"
+#include "api.h"
+#include "arguments.h"
+#include "execution.h"
+#include "ic-inl.h"
+#include "runtime.h"
+#include "stub-cache.h"
+
+namespace v8 { namespace internal {
+
+#ifdef DEBUG
+static char TransitionMarkFromState(IC::State state) {
+  switch (state) {
+    case UNINITIALIZED: return '0';
+    case UNINITIALIZED_IN_LOOP: return 'L';
+    case PREMONOMORPHIC: return '0';
+    case MONOMORPHIC: return '1';
+    case MONOMORPHIC_PROTOTYPE_FAILURE: return '^';
+    case MEGAMORPHIC: return 'N';
+
+    // We never see the debugger states here, because the state is
+    // computed from the original code - not the patched code. Let
+    // these cases fall through to the unreachable code below.
+    case DEBUG_BREAK: break;
+    case DEBUG_PREPARE_STEP_IN: break;
+  }
+  UNREACHABLE();
+  return 0;
+}
+
+void IC::TraceIC(const char* type,
+                 Handle<String> name,
+                 State old_state,
+                 Code* new_target) {
+  if (FLAG_trace_ic) {
+    State new_state = StateFrom(new_target, Heap::undefined_value());
+    PrintF("[%s (%c->%c) ", type,
+           TransitionMarkFromState(old_state),
+           TransitionMarkFromState(new_state));
+    name->Print();
+    PrintF("]\n");
+  }
+}
+#endif
+
+
+IC::IC(FrameDepth depth) {
+  // To improve the performance of the (much used) IC code, we unfold
+  // a few levels of the stack frame iteration code. This yields a
+  // ~35% speedup when running DeltaBlue with the '--nouse-ic' flag.
+  const Address entry = Top::c_entry_fp(Top::GetCurrentThread());
+  Address* pc_address =
+      reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
+  Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
+  // If there's another JavaScript frame on the stack, we need to look
+  // one frame further down the stack to find the frame pointer and
+  // the return address stack slot.
+  if (depth == EXTRA_CALL_FRAME) {
+    const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset;
+    pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset);
+    fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
+  }
+#ifdef DEBUG
+  StackFrameIterator it;
+  for (int i = 0; i < depth + 1; i++) it.Advance();
+  StackFrame* frame = it.frame();
+  ASSERT(fp == frame->fp() && pc_address == frame->pc_address());
+#endif
+  fp_ = fp;
+  pc_address_ = pc_address;
+}
+
+
+Address IC::OriginalCodeAddress() {
+  HandleScope scope;
+  // Compute the JavaScript frame for the frame pointer of this IC
+  // structure. We need this to be able to find the function
+  // corresponding to the frame.
+  StackFrameIterator it;
+  while (it.frame()->fp() != this->fp()) it.Advance();
+  JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
+  // Find the function on the stack and both the active code for the
+  // function and the original code.
+  JSFunction* function = JSFunction::cast(frame->function());
+  Handle<SharedFunctionInfo> shared(function->shared());
+  Code* code = shared->code();
+  ASSERT(Debug::HasDebugInfo(shared));
+  Code* original_code = Debug::GetDebugInfo(shared)->original_code();
+  ASSERT(original_code->IsCode());
+  // Get the address of the call site in the active code. This is the
+  // place where the call to DebugBreakXXX is and where the IC
+  // normally would be.
+  Address addr = pc() - Assembler::kTargetAddrToReturnAddrDist;
+  // Return the address in the original code. This is the place where
+  // the call which has been overwritten by the DebugBreakXXX resides
+  // and the place where the inline cache system should look.
+  int delta = original_code->instruction_start() - code->instruction_start();
+  return addr + delta;
+}
+
+
+IC::State IC::StateFrom(Code* target, Object* receiver) {
+  IC::State state = target->ic_state();
+
+  if (state != MONOMORPHIC) return state;
+  if (receiver->IsUndefined() || receiver->IsNull()) return state;
+
+  Map* map = GetCodeCacheMapForObject(receiver);
+
+  // Decide whether the inline cache failed because of changes to the
+  // receiver itself or changes to one of its prototypes.
+  //
+  // If there are changes to the receiver itself, the map of the
+  // receiver will have changed and the current target will not be in
+  // the receiver map's code cache.  Therefore, if the current target
+  // is in the receiver map's code cache, the inline cache failed due
+  // to prototype check failure.
+  int index = map->IndexInCodeCache(target);
+  if (index >= 0) {
+    // For keyed load/store, the most likely cause of cache failure is
+    // that the key has changed.  We do not distinguish between
+    // prototype and non-prototype failures for keyed access.
+    Code::Kind kind = target->kind();
+    if (kind == Code::KEYED_LOAD_IC || kind == Code::KEYED_STORE_IC) {
+      return MONOMORPHIC;
+    }
+
+    // Remove the target from the code cache to avoid hitting the same
+    // invalid stub again.
+    map->RemoveFromCodeCache(index);
+
+    return MONOMORPHIC_PROTOTYPE_FAILURE;
+  }
+
+  // The builtins object is special.  It only changes when JavaScript
+  // builtins are loaded lazily.  It is important to keep inline
+  // caches for the builtins object monomorphic.  Therefore, if we get
+  // an inline cache miss for the builtins object after lazily loading
+  // JavaScript builtins, we return uninitialized as the state to
+  // force the inline cache back to monomorphic state.
+  if (receiver->IsJSBuiltinsObject()) {
+    return UNINITIALIZED;
+  }
+
+  return MONOMORPHIC;
+}
+
+
+RelocInfo::Mode IC::ComputeMode() {
+  Address addr = address();
+  Code* code = Code::cast(Heap::FindCodeObject(addr));
+  for (RelocIterator it(code, RelocInfo::kCodeTargetMask);
+       !it.done(); it.next()) {
+    RelocInfo* info = it.rinfo();
+    if (info->pc() == addr) return info->rmode();
+  }
+  UNREACHABLE();
+  return RelocInfo::NONE;
+}
+
+
+Failure* IC::TypeError(const char* type,
+                       Handle<Object> object,
+                       Handle<String> name) {
+  HandleScope scope;
+  Handle<Object> args[2] = { name, object };
+  Handle<Object> error = Factory::NewTypeError(type, HandleVector(args, 2));
+  return Top::Throw(*error);
+}
+
+
+Failure* IC::ReferenceError(const char* type, Handle<String> name) {
+  HandleScope scope;
+  Handle<Object> error =
+      Factory::NewReferenceError(type, HandleVector(&name, 1));
+  return Top::Throw(*error);
+}
+
+
+void IC::Clear(Address address) {
+  Code* target = GetTargetAtAddress(address);
+
+  // Don't clear debug break inline cache as it will remove the break point.
+  if (target->ic_state() == DEBUG_BREAK) return;
+
+  switch (target->kind()) {
+    case Code::LOAD_IC: return LoadIC::Clear(address, target);
+    case Code::KEYED_LOAD_IC: return KeyedLoadIC::Clear(address, target);
+    case Code::STORE_IC: return StoreIC::Clear(address, target);
+    case Code::KEYED_STORE_IC: return KeyedStoreIC::Clear(address, target);
+    case Code::CALL_IC: return CallIC::Clear(address, target);
+    default: UNREACHABLE();
+  }
+}
+
+
+void CallIC::Clear(Address address, Code* target) {
+  State state = target->ic_state();
+  if (state == UNINITIALIZED || state == UNINITIALIZED_IN_LOOP) return;
+  Code* code = StubCache::FindCallInitialize(target->arguments_count());
+  SetTargetAtAddress(address, code);
+}
+
+
+void KeyedLoadIC::Clear(Address address, Code* target) {
+  if (target->ic_state() == UNINITIALIZED) return;
+  // Make sure to also clear the map used in inline fast cases.  If we
+  // do not clear these maps, cached code can keep objects alive
+  // through the embedded maps.
+  PatchInlinedMapCheck(address, Heap::null_value());
+  SetTargetAtAddress(address, initialize_stub());
+}
+
+
+void LoadIC::Clear(Address address, Code* target) {
+  if (target->ic_state() == UNINITIALIZED) return;
+  SetTargetAtAddress(address, initialize_stub());
+}
+
+
+void StoreIC::Clear(Address address, Code* target) {
+  if (target->ic_state() == UNINITIALIZED) return;
+  SetTargetAtAddress(address, initialize_stub());
+}
+
+
+void KeyedStoreIC::Clear(Address address, Code* target) {
+  if (target->ic_state() == UNINITIALIZED) return;
+  SetTargetAtAddress(address, initialize_stub());
+}
+
+
+Object* CallIC::TryCallAsFunction(Object* object) {
+  HandleScope scope;
+  Handle<Object> target(object);
+  Handle<Object> delegate = Execution::GetFunctionDelegate(target);
+
+  if (delegate->IsJSFunction()) {
+    // Patch the receiver and use the delegate as the function to
+    // invoke. This is used for invoking objects as if they were
+    // functions.
+    const int argc = this->target()->arguments_count();
+    StackFrameLocator locator;
+    JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
+    int index = frame->ComputeExpressionsCount() - (argc + 1);
+    frame->SetExpression(index, *target);
+  }
+
+  return *delegate;
+}
+
+
+Object* CallIC::LoadFunction(State state,
+                             Handle<Object> object,
+                             Handle<String> name) {
+  // If the object is undefined or null it's illegal to try to get any
+  // of its properties; throw a TypeError in that case.
+  if (object->IsUndefined() || object->IsNull()) {
+    return TypeError("non_object_property_call", object, name);
+  }
+
+  Object* result = Heap::the_hole_value();
+
+  // Check if the name is trivially convertible to an index and get
+  // the element if so.
+  uint32_t index;
+  if (name->AsArrayIndex(&index)) {
+    result = object->GetElement(index);
+    if (result->IsJSFunction()) return result;
+
+    // Try to find a suitable function delegate for the object at hand.
+    result = TryCallAsFunction(result);
+    if (result->IsJSFunction()) return result;
+
+    // Otherwise, it will fail in the lookup step.
+  }
+
+  // Lookup the property in the object.
+  LookupResult lookup;
+  object->Lookup(*name, &lookup);
+
+  if (!lookup.IsValid()) {
+    // If the object does not have the requested property, check which
+    // exception we need to throw.
+    if (is_contextual()) {
+      return ReferenceError("not_defined", name);
+    }
+    return TypeError("undefined_method", object, name);
+  }
+
+  // Lookup is valid: Update inline cache and stub cache.
+  if (FLAG_use_ic && lookup.IsLoaded()) {
+    UpdateCaches(&lookup, state, object, name);
+  }
+
+  if (lookup.type() == INTERCEPTOR) {
+    // Get the property.
+    PropertyAttributes attr;
+    result = object->GetProperty(*name, &attr);
+    if (result->IsFailure()) return result;
+    // If the object does not have the requested property, check which
+    // exception we need to throw.
+    if (attr == ABSENT) {
+      if (is_contextual()) {
+        return ReferenceError("not_defined", name);
+      }
+      return TypeError("undefined_method", object, name);
+    }
+  } else {
+    // Lookup is valid and no interceptors are involved. Get the
+    // property.
+    result = object->GetProperty(*name);
+    if (result->IsFailure()) return result;
+  }
+
+  ASSERT(result != Heap::the_hole_value());
+
+  if (result->IsJSFunction()) {
+    // Check if there is an optimized (builtin) version of the function.
+    // Ignored this will degrade performance for Array.prototype.{push,pop}.
+    // Please note we only return the optimized function iff
+    // the JSObject has FastElements.
+    if (object->IsJSObject() && JSObject::cast(*object)->HasFastElements()) {
+      Object* opt = Top::LookupSpecialFunction(JSObject::cast(*object),
+                                               lookup.holder(),
+                                               JSFunction::cast(result));
+      if (opt->IsJSFunction()) return opt;
+    }
+
+    // Handle stepping into a function if step into is active.
+    if (Debug::StepInActive()) {
+      // Protect the result in a handle as the debugger can allocate and might
+      // cause GC.
+      HandleScope scope;
+      Handle<JSFunction> function(JSFunction::cast(result));
+      Debug::HandleStepIn(function, fp(), false);
+      return *function;
+    }
+
+    return result;
+  }
+
+  // Try to find a suitable function delegate for the object at hand.
+  result = TryCallAsFunction(result);
+  return result->IsJSFunction() ?
+      result : TypeError("property_not_function", object, name);
+}
+
+
+void CallIC::UpdateCaches(LookupResult* lookup,
+                          State state,
+                          Handle<Object> object,
+                          Handle<String> name) {
+  ASSERT(lookup->IsLoaded());
+  // Bail out if we didn't find a result.
+  if (!lookup->IsValid() || !lookup->IsCacheable()) return;
+
+  // Compute the number of arguments.
+  int argc = target()->arguments_count();
+  Object* code = NULL;
+
+  if (state == UNINITIALIZED) {
+    // This is the first time we execute this inline cache.
+    // Set the target to the pre monomorphic stub to delay
+    // setting the monomorphic state.
+    code = StubCache::ComputeCallPreMonomorphic(argc);
+  } else if (state == MONOMORPHIC) {
+    code = StubCache::ComputeCallMegamorphic(argc);
+  } else {
+    // Compute monomorphic stub.
+    switch (lookup->type()) {
+      case FIELD: {
+        int index = lookup->GetFieldIndex();
+        code = StubCache::ComputeCallField(argc, *name, *object,
+                                           lookup->holder(), index);
+        break;
+      }
+      case CONSTANT_FUNCTION: {
+        // Get the constant function and compute the code stub for this
+        // call; used for rewriting to monomorphic state and making sure
+        // that the code stub is in the stub cache.
+        JSFunction* function = lookup->GetConstantFunction();
+        code = StubCache::ComputeCallConstant(argc, *name, *object,
+                                              lookup->holder(), function);
+        break;
+      }
+      case NORMAL: {
+        // There is only one shared stub for calling normalized
+        // properties. It does not traverse the prototype chain, so the
+        // property must be found in the receiver for the stub to be
+        // applicable.
+        if (!object->IsJSObject()) return;
+        Handle<JSObject> receiver = Handle<JSObject>::cast(object);
+        if (lookup->holder() != *receiver) return;
+        code = StubCache::ComputeCallNormal(argc, *name, *receiver);
+        break;
+      }
+      case INTERCEPTOR: {
+        code = StubCache::ComputeCallInterceptor(argc, *name, *object,
+                                                 lookup->holder());
+        break;
+      }
+      default:
+        return;
+    }
+  }
+
+  // If we're unable to compute the stub (not enough memory left), we
+  // simply avoid updating the caches.
+  if (code->IsFailure()) return;
+
+  // Patch the call site depending on the state of the cache.
+  if (state == UNINITIALIZED || state == UNINITIALIZED_IN_LOOP ||
+      state == PREMONOMORPHIC || state == MONOMORPHIC ||
+      state == MONOMORPHIC_PROTOTYPE_FAILURE) {
+    set_target(Code::cast(code));
+  }
+
+#ifdef DEBUG
+  TraceIC("CallIC", name, state, target());
+#endif
+}
+
+
+Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) {
+  // If the object is undefined or null it's illegal to try to get any
+  // of its properties; throw a TypeError in that case.
+  if (object->IsUndefined() || object->IsNull()) {
+    return TypeError("non_object_property_load", object, name);
+  }
+
+  if (FLAG_use_ic) {
+    // Use specialized code for getting the length of strings and
+    // string wrapper objects.  The length property of string wrapper
+    // objects is read-only and therefore always returns the length of
+    // the underlying string value.  See ECMA-262 15.5.5.1.
+    if ((object->IsString() || object->IsStringWrapper()) &&
+        name->Equals(Heap::length_symbol())) {
+      HandleScope scope;
+      // Get the string if we have a string wrapper object.
+      if (object->IsJSValue()) {
+        object = Handle<Object>(Handle<JSValue>::cast(object)->value());
+      }
+#ifdef DEBUG
+      if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
+#endif
+      Code* target = NULL;
+      target = Builtins::builtin(Builtins::LoadIC_StringLength);
+      set_target(target);
+      StubCache::Set(*name, HeapObject::cast(*object)->map(), target);
+      return Smi::FromInt(String::cast(*object)->length());
+    }
+
+    // Use specialized code for getting the length of arrays.
+    if (object->IsJSArray() && name->Equals(Heap::length_symbol())) {
+#ifdef DEBUG
+      if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
+#endif
+      Code* target = Builtins::builtin(Builtins::LoadIC_ArrayLength);
+      set_target(target);
+      StubCache::Set(*name, HeapObject::cast(*object)->map(), target);
+      return JSArray::cast(*object)->length();
+    }
+
+    // Use specialized code for getting prototype of functions.
+    if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol())) {
+#ifdef DEBUG
+      if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
+#endif
+      Code* target = Builtins::builtin(Builtins::LoadIC_FunctionPrototype);
+      set_target(target);
+      StubCache::Set(*name, HeapObject::cast(*object)->map(), target);
+      return Accessors::FunctionGetPrototype(*object, 0);
+    }
+  }
+
+  // Check if the name is trivially convertible to an index and get
+  // the element if so.
+  uint32_t index;
+  if (name->AsArrayIndex(&index)) return object->GetElement(index);
+
+  // Named lookup in the object.
+  LookupResult lookup;
+  object->Lookup(*name, &lookup);
+
+  // If lookup is invalid, check if we need to throw an exception.
+  if (!lookup.IsValid()) {
+    if (FLAG_strict || is_contextual()) {
+      return ReferenceError("not_defined", name);
+    }
+    LOG(SuspectReadEvent(*name, *object));
+  }
+
+  // Update inline cache and stub cache.
+  if (FLAG_use_ic && lookup.IsLoaded()) {
+    UpdateCaches(&lookup, state, object, name);
+  }
+
+  PropertyAttributes attr;
+  if (lookup.IsValid() && lookup.type() == INTERCEPTOR) {
+    // Get the property.
+    Object* result = object->GetProperty(*object, &lookup, *name, &attr);
+    if (result->IsFailure()) return result;
+    // If the property is not present, check if we need to throw an
+    // exception.
+    if (attr == ABSENT && is_contextual()) {
+      return ReferenceError("not_defined", name);
+    }
+    return result;
+  }
+
+  // Get the property.
+  return object->GetProperty(*object, &lookup, *name, &attr);
+}
+
+
+void LoadIC::UpdateCaches(LookupResult* lookup,
+                          State state,
+                          Handle<Object> object,
+                          Handle<String> name) {
+  ASSERT(lookup->IsLoaded());
+  // Bail out if we didn't find a result.
+  if (!lookup->IsValid() || !lookup->IsCacheable()) return;
+
+  // Loading properties from values is not common, so don't try to
+  // deal with non-JS objects here.
+  if (!object->IsJSObject()) return;
+  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
+
+  // Compute the code stub for this load.
+  Object* code = NULL;
+  if (state == UNINITIALIZED) {
+    // This is the first time we execute this inline cache.
+    // Set the target to the pre monomorphic stub to delay
+    // setting the monomorphic state.
+    code = pre_monomorphic_stub();
+  } else {
+    // Compute monomorphic stub.
+    switch (lookup->type()) {
+      case FIELD: {
+        code = StubCache::ComputeLoadField(*name, *receiver,
+                                           lookup->holder(),
+                                           lookup->GetFieldIndex());
+        break;
+      }
+      case CONSTANT_FUNCTION: {
+        Object* constant = lookup->GetConstantFunction();
+        code = StubCache::ComputeLoadConstant(*name, *receiver,
+                                              lookup->holder(), constant);
+        break;
+      }
+      case NORMAL: {
+        // There is only one shared stub for loading normalized
+        // properties. It does not traverse the prototype chain, so the
+        // property must be found in the receiver for the stub to be
+        // applicable.
+        if (lookup->holder() != *receiver) return;
+        code = StubCache::ComputeLoadNormal(*name, *receiver);
+        break;
+      }
+      case CALLBACKS: {
+        if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
+        AccessorInfo* callback =
+            AccessorInfo::cast(lookup->GetCallbackObject());
+        if (v8::ToCData<Address>(callback->getter()) == 0) return;
+        code = StubCache::ComputeLoadCallback(*name, *receiver,
+                                              lookup->holder(), callback);
+        break;
+      }
+      case INTERCEPTOR: {
+        code = StubCache::ComputeLoadInterceptor(*name, *receiver,
+                                                 lookup->holder());
+        break;
+      }
+      default:
+        return;
+    }
+  }
+
+  // If we're unable to compute the stub (not enough memory left), we
+  // simply avoid updating the caches.
+  if (code->IsFailure()) return;
+
+  // Patch the call site depending on the state of the cache.
+  if (state == UNINITIALIZED || state == PREMONOMORPHIC ||
+      state == MONOMORPHIC_PROTOTYPE_FAILURE) {
+    set_target(Code::cast(code));
+  } else if (state == MONOMORPHIC) {
+    set_target(megamorphic_stub());
+  }
+
+#ifdef DEBUG
+  TraceIC("LoadIC", name, state, target());
+#endif
+}
+
+
+Object* KeyedLoadIC::Load(State state,
+                          Handle<Object> object,
+                          Handle<Object> key) {
+  if (key->IsSymbol()) {
+    Handle<String> name = Handle<String>::cast(key);
+
+    // If the object is undefined or null it's illegal to try to get any
+    // of its properties; throw a TypeError in that case.
+    if (object->IsUndefined() || object->IsNull()) {
+      return TypeError("non_object_property_load", object, name);
+    }
+
+    if (FLAG_use_ic) {
+      // Use specialized code for getting the length of strings.
+      if (object->IsString() && name->Equals(Heap::length_symbol())) {
+        Handle<String> string = Handle<String>::cast(object);
+        Object* code = NULL;
+        code = StubCache::ComputeKeyedLoadStringLength(*name, *string);
+        if (code->IsFailure()) return code;
+        set_target(Code::cast(code));
+#ifdef DEBUG
+        TraceIC("KeyedLoadIC", name, state, target());
+#endif
+        return Smi::FromInt(string->length());
+      }
+
+      // Use specialized code for getting the length of arrays.
+      if (object->IsJSArray() && name->Equals(Heap::length_symbol())) {
+        Handle<JSArray> array = Handle<JSArray>::cast(object);
+        Object* code = StubCache::ComputeKeyedLoadArrayLength(*name, *array);
+        if (code->IsFailure()) return code;
+        set_target(Code::cast(code));
+#ifdef DEBUG
+        TraceIC("KeyedLoadIC", name, state, target());
+#endif
+        return JSArray::cast(*object)->length();
+      }
+
+      // Use specialized code for getting prototype of functions.
+      if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol())) {
+        Handle<JSFunction> function = Handle<JSFunction>::cast(object);
+        Object* code =
+            StubCache::ComputeKeyedLoadFunctionPrototype(*name, *function);
+        if (code->IsFailure()) return code;
+        set_target(Code::cast(code));
+#ifdef DEBUG
+        TraceIC("KeyedLoadIC", name, state, target());
+#endif
+        return Accessors::FunctionGetPrototype(*object, 0);
+      }
+    }
+
+    // Check if the name is trivially convertible to an index and get
+    // the element or char if so.
+    uint32_t index = 0;
+    if (name->AsArrayIndex(&index)) {
+      HandleScope scope;
+      // Rewrite to the generic keyed load stub.
+      if (FLAG_use_ic) set_target(generic_stub());
+      return Runtime::GetElementOrCharAt(object, index);
+    }
+
+    // Named lookup.
+    LookupResult lookup;
+    object->Lookup(*name, &lookup);
+
+    // If lookup is invalid, check if we need to throw an exception.
+    if (!lookup.IsValid()) {
+      if (FLAG_strict || is_contextual()) {
+        return ReferenceError("not_defined", name);
+      }
+    }
+
+    // Update the inline cache.
+    if (FLAG_use_ic && lookup.IsLoaded()) {
+      UpdateCaches(&lookup, state, object, name);
+    }
+
+    PropertyAttributes attr;
+    if (lookup.IsValid() && lookup.type() == INTERCEPTOR) {
+      // Get the property.
+      Object* result = object->GetProperty(*object, &lookup, *name, &attr);
+      if (result->IsFailure()) return result;
+      // If the property is not present, check if we need to throw an
+      // exception.
+      if (attr == ABSENT && is_contextual()) {
+        return ReferenceError("not_defined", name);
+      }
+      return result;
+    }
+
+    return object->GetProperty(*object, &lookup, *name, &attr);
+  }
+
+  // Do not use ICs for objects that require access checks (including
+  // the global object).
+  bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
+
+  if (use_ic) {
+    set_target(generic_stub());
+    // For JSObjects that are not value wrappers and that do not have
+    // indexed interceptors, we initialize the inlined fast case (if
+    // present) by patching the inlined map check.
+    if (object->IsJSObject() &&
+        !object->IsJSValue() &&
+        !JSObject::cast(*object)->HasIndexedInterceptor()) {
+      Map* map = JSObject::cast(*object)->map();
+      PatchInlinedMapCheck(address(), map);
+    }
+  }
+
+  // Get the property.
+  return Runtime::GetObjectProperty(object, key);
+}
+
+
+void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
+                               Handle<Object> object, Handle<String> name) {
+  ASSERT(lookup->IsLoaded());
+  // Bail out if we didn't find a result.
+  if (!lookup->IsValid() || !lookup->IsCacheable()) return;
+
+  if (!object->IsJSObject()) return;
+  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
+
+  // Compute the code stub for this load.
+  Object* code = NULL;
+
+  if (state == UNINITIALIZED) {
+    // This is the first time we execute this inline cache.
+    // Set the target to the pre monomorphic stub to delay
+    // setting the monomorphic state.
+    code = pre_monomorphic_stub();
+  } else {
+    // Compute a monomorphic stub.
+    switch (lookup->type()) {
+      case FIELD: {
+        code = StubCache::ComputeKeyedLoadField(*name, *receiver,
+                                                lookup->holder(),
+                                                lookup->GetFieldIndex());
+        break;
+      }
+      case CONSTANT_FUNCTION: {
+        Object* constant = lookup->GetConstantFunction();
+        code = StubCache::ComputeKeyedLoadConstant(*name, *receiver,
+                                                   lookup->holder(), constant);
+        break;
+      }
+      case CALLBACKS: {
+        if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
+        AccessorInfo* callback =
+            AccessorInfo::cast(lookup->GetCallbackObject());
+        if (v8::ToCData<Address>(callback->getter()) == 0) return;
+        code = StubCache::ComputeKeyedLoadCallback(*name, *receiver,
+                                                   lookup->holder(), callback);
+        break;
+      }
+      case INTERCEPTOR: {
+        code = StubCache::ComputeKeyedLoadInterceptor(*name, *receiver,
+                                                      lookup->holder());
+        break;
+      }
+      default: {
+        // Always rewrite to the generic case so that we do not
+        // repeatedly try to rewrite.
+        code = generic_stub();
+        break;
+      }
+    }
+  }
+
+  // If we're unable to compute the stub (not enough memory left), we
+  // simply avoid updating the caches.
+  if (code->IsFailure()) return;
+
+  // Patch the call site depending on the state of the cache.  Make
+  // sure to always rewrite from monomorphic to megamorphic.
+  ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE);
+  if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
+    set_target(Code::cast(code));
+  } else if (state == MONOMORPHIC) {
+    set_target(megamorphic_stub());
+  }
+
+#ifdef DEBUG
+  TraceIC("KeyedLoadIC", name, state, target());
+#endif
+}
+
+
+Object* StoreIC::Store(State state,
+                       Handle<Object> object,
+                       Handle<String> name,
+                       Handle<Object> value) {
+  // If the object is undefined or null it's illegal to try to set any
+  // properties on it; throw a TypeError in that case.
+  if (object->IsUndefined() || object->IsNull()) {
+    return TypeError("non_object_property_store", object, name);
+  }
+
+  // Ignore stores where the receiver is not a JSObject.
+  if (!object->IsJSObject()) return *value;
+  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
+
+  // Check if the given name is an array index.
+  uint32_t index;
+  if (name->AsArrayIndex(&index)) {
+    HandleScope scope;
+    Handle<Object> result = SetElement(receiver, index, value);
+    if (result.is_null()) return Failure::Exception();
+    return *value;
+  }
+
+  // Lookup the property locally in the receiver.
+  LookupResult lookup;
+  receiver->LocalLookup(*name, &lookup);
+
+  // Update inline cache and stub cache.
+  if (FLAG_use_ic && lookup.IsLoaded()) {
+    UpdateCaches(&lookup, state, receiver, name, value);
+  }
+
+  // Set the property.
+  return receiver->SetProperty(*name, *value, NONE);
+}
+
+
+void StoreIC::UpdateCaches(LookupResult* lookup,
+                           State state,
+                           Handle<JSObject> receiver,
+                           Handle<String> name,
+                           Handle<Object> value) {
+  ASSERT(lookup->IsLoaded());
+  // Skip JSGlobalProxy.
+  if (receiver->IsJSGlobalProxy()) return;
+
+  // Bail out if we didn't find a result.
+  if (!lookup->IsValid() || !lookup->IsCacheable()) return;
+
+  // If the property is read-only, we leave the IC in its current
+  // state.
+  if (lookup->IsReadOnly()) return;
+
+  // If the property has a non-field type allowing map transitions
+  // where there is extra room in the object, we leave the IC in its
+  // current state.
+  PropertyType type = lookup->type();
+
+  // Compute the code stub for this store; used for rewriting to
+  // monomorphic state and making sure that the code stub is in the
+  // stub cache.
+  Object* code = NULL;
+  switch (type) {
+    case FIELD: {
+      code = StubCache::ComputeStoreField(*name, *receiver,
+                                          lookup->GetFieldIndex());
+      break;
+    }
+    case MAP_TRANSITION: {
+      if (lookup->GetAttributes() != NONE) return;
+      HandleScope scope;
+      ASSERT(type == MAP_TRANSITION);
+      Handle<Map> transition(lookup->GetTransitionMap());
+      int index = transition->PropertyIndexFor(*name);
+      code = StubCache::ComputeStoreField(*name, *receiver, index, *transition);
+      break;
+    }
+    case CALLBACKS: {
+      if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
+      AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
+      if (v8::ToCData<Address>(callback->setter()) == 0) return;
+      code = StubCache::ComputeStoreCallback(*name, *receiver, callback);
+      break;
+    }
+    case INTERCEPTOR: {
+      code = StubCache::ComputeStoreInterceptor(*name, *receiver);
+      break;
+    }
+    default:
+      return;
+  }
+
+  // If we're unable to compute the stub (not enough memory left), we
+  // simply avoid updating the caches.
+  if (code->IsFailure()) return;
+
+  // Patch the call site depending on the state of the cache.
+  if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
+    set_target(Code::cast(code));
+  } else if (state == MONOMORPHIC) {
+    // Only move to mega morphic if the target changes.
+    if (target() != Code::cast(code)) set_target(megamorphic_stub());
+  }
+
+#ifdef DEBUG
+  TraceIC("StoreIC", name, state, target());
+#endif
+}
+
+
+Object* KeyedStoreIC::Store(State state,
+                            Handle<Object> object,
+                            Handle<Object> key,
+                            Handle<Object> value) {
+  if (key->IsSymbol()) {
+    Handle<String> name = Handle<String>::cast(key);
+
+    // If the object is undefined or null it's illegal to try to set any
+    // properties on it; throw a TypeError in that case.
+    if (object->IsUndefined() || object->IsNull()) {
+      return TypeError("non_object_property_store", object, name);
+    }
+
+    // Ignore stores where the receiver is not a JSObject.
+    if (!object->IsJSObject()) return *value;
+    Handle<JSObject> receiver = Handle<JSObject>::cast(object);
+
+    // Check if the given name is an array index.
+    uint32_t index;
+    if (name->AsArrayIndex(&index)) {
+      HandleScope scope;
+      Handle<Object> result = SetElement(receiver, index, value);
+      if (result.is_null()) return Failure::Exception();
+      return *value;
+    }
+
+    // Lookup the property locally in the receiver.
+    LookupResult lookup;
+    receiver->LocalLookup(*name, &lookup);
+
+    // Update inline cache and stub cache.
+    if (FLAG_use_ic && lookup.IsLoaded()) {
+      UpdateCaches(&lookup, state, receiver, name, value);
+    }
+
+    // Set the property.
+    return receiver->SetProperty(*name, *value, NONE);
+  }
+
+  // Do not use ICs for objects that require access checks (including
+  // the global object).
+  bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
+  ASSERT(!(use_ic && object->IsJSGlobalProxy()));
+
+  if (use_ic) set_target(generic_stub());
+
+  // Set the property.
+  return Runtime::SetObjectProperty(object, key, value, NONE);
+}
+
+
+void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
+                                State state,
+                                Handle<JSObject> receiver,
+                                Handle<String> name,
+                                Handle<Object> value) {
+  ASSERT(lookup->IsLoaded());
+
+  // Skip JSGlobalProxy.
+  if (receiver->IsJSGlobalProxy()) return;
+
+  // Bail out if we didn't find a result.
+  if (!lookup->IsValid() || !lookup->IsCacheable()) return;
+
+  // If the property is read-only, we leave the IC in its current
+  // state.
+  if (lookup->IsReadOnly()) return;
+
+  // If the property has a non-field type allowing map transitions
+  // where there is extra room in the object, we leave the IC in its
+  // current state.
+  PropertyType type = lookup->type();
+
+  // Compute the code stub for this store; used for rewriting to
+  // monomorphic state and making sure that the code stub is in the
+  // stub cache.
+  Object* code = NULL;
+
+  switch (type) {
+    case FIELD: {
+      code = StubCache::ComputeKeyedStoreField(*name, *receiver,
+                                               lookup->GetFieldIndex());
+      break;
+    }
+    case MAP_TRANSITION: {
+      if (lookup->GetAttributes() == NONE) {
+        HandleScope scope;
+        ASSERT(type == MAP_TRANSITION);
+        Handle<Map> transition(lookup->GetTransitionMap());
+        int index = transition->PropertyIndexFor(*name);
+        code = StubCache::ComputeKeyedStoreField(*name, *receiver,
+                                                 index, *transition);
+        break;
+      }
+      // fall through.
+    }
+    default: {
+      // Always rewrite to the generic case so that we do not
+      // repeatedly try to rewrite.
+      code = generic_stub();
+      break;
+    }
+  }
+
+  // If we're unable to compute the stub (not enough memory left), we
+  // simply avoid updating the caches.
+  if (code->IsFailure()) return;
+
+  // Patch the call site depending on the state of the cache.  Make
+  // sure to always rewrite from monomorphic to megamorphic.
+  ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE);
+  if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
+    set_target(Code::cast(code));
+  } else if (state == MONOMORPHIC) {
+    set_target(megamorphic_stub());
+  }
+
+#ifdef DEBUG
+  TraceIC("KeyedStoreIC", name, state, target());
+#endif
+}
+
+
+// ----------------------------------------------------------------------------
+// Static IC stub generators.
+//
+
+// Used from ic_<arch>.cc.
+Object* CallIC_Miss(Arguments args) {
+  NoHandleAllocation na;
+  ASSERT(args.length() == 2);
+  CallIC ic;
+  IC::State state = IC::StateFrom(ic.target(), args[0]);
+  Object* result =
+      ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1));
+  if (state != UNINITIALIZED_IN_LOOP || !result->IsJSFunction())
+    return result;
+
+  // Compile the function with the knowledge that it's called from
+  // within a loop. This enables further optimization of the function.
+  HandleScope scope;
+  Handle<JSFunction> function = Handle<JSFunction>(JSFunction::cast(result));
+  if (!function->is_compiled()) CompileLazyInLoop(function, CLEAR_EXCEPTION);
+  return *function;
+}
+
+
+void CallIC::GenerateInitialize(MacroAssembler* masm, int argc) {
+  Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
+}
+
+
+void CallIC::GeneratePreMonomorphic(MacroAssembler* masm, int argc) {
+  Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
+}
+
+
+void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
+  Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
+}
+
+
+// Used from ic_<arch>.cc.
+Object* LoadIC_Miss(Arguments args) {
+  NoHandleAllocation na;
+  ASSERT(args.length() == 2);
+  LoadIC ic;
+  IC::State state = IC::StateFrom(ic.target(), args[0]);
+  return ic.Load(state, args.at<Object>(0), args.at<String>(1));
+}
+
+
+void LoadIC::GenerateInitialize(MacroAssembler* masm) {
+  Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
+}
+
+
+void LoadIC::GeneratePreMonomorphic(MacroAssembler* masm) {
+  Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
+}
+
+
+// Used from ic_<arch>.cc
+Object* KeyedLoadIC_Miss(Arguments args) {
+  NoHandleAllocation na;
+  ASSERT(args.length() == 2);
+  KeyedLoadIC ic;
+  IC::State state = IC::StateFrom(ic.target(), args[0]);
+  return ic.Load(state, args.at<Object>(0), args.at<Object>(1));
+}
+
+
+void KeyedLoadIC::GenerateInitialize(MacroAssembler* masm) {
+  Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss)));
+}
+
+
+void KeyedLoadIC::GeneratePreMonomorphic(MacroAssembler* masm) {
+  Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss)));
+}
+
+
+// Used from ic_<arch>.cc.
+Object* StoreIC_Miss(Arguments args) {
+  NoHandleAllocation na;
+  ASSERT(args.length() == 3);
+  StoreIC ic;
+  IC::State state = IC::StateFrom(ic.target(), args[0]);
+  return ic.Store(state, args.at<Object>(0), args.at<String>(1),
+                  args.at<Object>(2));
+}
+
+
+// Extend storage is called in a store inline cache when
+// it is necessary to extend the properties array of a
+// JSObject.
+Object* SharedStoreIC_ExtendStorage(Arguments args) {
+  NoHandleAllocation na;
+  ASSERT(args.length() == 3);
+
+  // Convert the parameters
+  JSObject* object = JSObject::cast(args[0]);
+  Map* transition = Map::cast(args[1]);
+  Object* value = args[2];
+
+  // Check the object has run out out property space.
+  ASSERT(object->HasFastProperties());
+  ASSERT(object->map()->unused_property_fields() == 0);
+
+  // Expand the properties array.
+  FixedArray* old_storage = object->properties();
+  int new_unused = transition->unused_property_fields();
+  int new_size = old_storage->length() + new_unused + 1;
+  Object* result = old_storage->CopySize(new_size);
+  if (result->IsFailure()) return result;
+  FixedArray* new_storage = FixedArray::cast(result);
+  new_storage->set(old_storage->length(), value);
+
+  // Set the new property value and do the map transition.
+  object->set_properties(new_storage);
+  object->set_map(transition);
+
+  // Return the stored value.
+  return value;
+}
+
+
+void StoreIC::GenerateInitialize(MacroAssembler* masm) {
+  Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss)));
+}
+
+
+void StoreIC::GenerateMiss(MacroAssembler* masm) {
+  Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss)));
+}
+
+
+// Used from ic_<arch>.cc.
+Object* KeyedStoreIC_Miss(Arguments args) {
+  NoHandleAllocation na;
+  ASSERT(args.length() == 3);
+  KeyedStoreIC ic;
+  IC::State state = IC::StateFrom(ic.target(), args[0]);
+  return ic.Store(state, args.at<Object>(0), args.at<Object>(1),
+                  args.at<Object>(2));
+}
+
+
+void KeyedStoreIC::GenerateInitialize(MacroAssembler* masm) {
+  Generate(masm, ExternalReference(IC_Utility(kKeyedStoreIC_Miss)));
+}
+
+
+void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
+  Generate(masm, ExternalReference(IC_Utility(kKeyedStoreIC_Miss)));
+}
+
+
+static Address IC_utilities[] = {
+#define ADDR(name) FUNCTION_ADDR(name),
+    IC_UTIL_LIST(ADDR)
+    NULL
+#undef ADDR
+};
+
+
+Address IC::AddressFromUtilityId(IC::UtilityId id) {
+  return IC_utilities[id];
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/ic.h b/deps/v8/src/ic.h
new file mode 100644
index 0000000..bbe1f6d
--- /dev/null
+++ b/deps/v8/src/ic.h
@@ -0,0 +1,369 @@
+// 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_IC_H_
+#define V8_IC_H_
+
+#include "assembler.h"
+
+namespace v8 { namespace internal {
+
+// IC_UTIL_LIST defines all utility functions called from generated
+// inline caching code. The argument for the macro, ICU, is the function name.
+#define IC_UTIL_LIST(ICU)          \
+  ICU(LoadIC_Miss)                 \
+  ICU(KeyedLoadIC_Miss)            \
+  ICU(CallIC_Miss)                 \
+  ICU(StoreIC_Miss)                \
+  ICU(SharedStoreIC_ExtendStorage) \
+  ICU(KeyedStoreIC_Miss)           \
+  /* Utilities for IC stubs. */    \
+  ICU(LoadCallbackProperty)        \
+  ICU(StoreCallbackProperty)       \
+  ICU(LoadInterceptorProperty)     \
+  ICU(StoreInterceptorProperty)
+
+//
+// IC is the base class for LoadIC, StoreIC and CallIC.
+//
+class IC {
+ public:
+
+  // The ids for utility called from the generated code.
+  enum UtilityId {
+  #define CONST_NAME(name) k##name,
+    IC_UTIL_LIST(CONST_NAME)
+  #undef CONST_NAME
+    kUtilityCount
+  };
+
+  // Looks up the address of the named utility.
+  static Address AddressFromUtilityId(UtilityId id);
+
+  // Alias the inline cache state type to make the IC code more readable.
+  typedef InlineCacheState State;
+
+  // The IC code is either invoked with no extra frames on the stack
+  // or with a single extra frame for supporting calls.
+  enum FrameDepth {
+    NO_EXTRA_FRAME = 0,
+    EXTRA_CALL_FRAME = 1
+  };
+
+  // Construct the IC structure with the given number of extra
+  // JavaScript frames on the stack.
+  explicit IC(FrameDepth depth);
+
+  // Get the call-site target; used for determining the state.
+  Code* target() { return GetTargetAtAddress(address()); }
+  inline Address address();
+
+  // Compute the current IC state based on the target stub and the receiver.
+  static State StateFrom(Code* target, Object* receiver);
+
+  // Clear the inline cache to initial state.
+  static void Clear(Address address);
+
+  // Computes the reloc info for this IC. This is a fairly expensive
+  // operation as it has to search through the heap to find the code
+  // object that contains this IC site.
+  RelocInfo::Mode ComputeMode();
+
+  // Returns if this IC is for contextual (no explicit receiver)
+  // access to properties.
+  bool is_contextual() {
+    return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT;
+  }
+
+  // Returns the map to use for caching stubs for a given object.
+  // This method should not be called with undefined or null.
+  static inline Map* GetCodeCacheMapForObject(Object* object);
+
+ protected:
+  Address fp() const { return fp_; }
+  Address pc() const { return *pc_address_; }
+
+  // Computes the address in the original code when the code running is
+  // containing break points (calls to DebugBreakXXX builtins).
+  Address OriginalCodeAddress();
+
+  // Set the call-site target.
+  void set_target(Code* code) { SetTargetAtAddress(address(), code); }
+
+#ifdef DEBUG
+  static void TraceIC(const char* type,
+                      Handle<String> name,
+                      State old_state,
+                      Code* new_target);
+#endif
+
+  static Failure* TypeError(const char* type,
+                            Handle<Object> object,
+                            Handle<String> name);
+  static Failure* ReferenceError(const char* type, Handle<String> name);
+
+  // Access the target code for the given IC address.
+  static inline Code* GetTargetAtAddress(Address address);
+  static inline void SetTargetAtAddress(Address address, Code* target);
+
+ private:
+  // Frame pointer for the frame that uses (calls) the IC.
+  Address fp_;
+
+  // All access to the program counter of an IC structure is indirect
+  // to make the code GC safe. This feature is crucial since
+  // GetProperty and SetProperty are called and they in turn might
+  // invoke the garbage collector.
+  Address* pc_address_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
+};
+
+
+// An IC_Utility encapsulates IC::UtilityId. It exists mainly because you
+// cannot make forward declarations to an enum.
+class IC_Utility {
+ public:
+  explicit IC_Utility(IC::UtilityId id)
+    : address_(IC::AddressFromUtilityId(id)), id_(id) {}
+
+  Address address() const { return address_; }
+
+  IC::UtilityId id() const { return id_; }
+ private:
+  Address address_;
+  IC::UtilityId id_;
+};
+
+
+class CallIC: public IC {
+ public:
+  CallIC() : IC(EXTRA_CALL_FRAME) { ASSERT(target()->is_call_stub()); }
+
+  Object* LoadFunction(State state, Handle<Object> object, Handle<String> name);
+
+
+  // Code generator routines.
+  static void GenerateInitialize(MacroAssembler* masm, int argc);
+  static void GeneratePreMonomorphic(MacroAssembler* masm, int argc);
+  static void GenerateMiss(MacroAssembler* masm, int argc);
+  static void GenerateMegamorphic(MacroAssembler* masm, int argc);
+  static void GenerateNormal(MacroAssembler* masm, int argc);
+
+ private:
+  static void Generate(MacroAssembler* masm,
+                       int argc,
+                       const ExternalReference& f);
+
+  // Update the inline cache and the global stub cache based on the
+  // lookup result.
+  void UpdateCaches(LookupResult* lookup,
+                    State state,
+                    Handle<Object> object,
+                    Handle<String> name);
+
+  // Returns a JSFunction if the object can be called as a function,
+  // and patches the stack to be ready for the call.
+  // Otherwise, it returns the undefined value.
+  Object* TryCallAsFunction(Object* object);
+
+  static void Clear(Address address, Code* target);
+  friend class IC;
+};
+
+
+class LoadIC: public IC {
+ public:
+  LoadIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_load_stub()); }
+
+  Object* Load(State state, Handle<Object> object, Handle<String> name);
+
+  // Code generator routines.
+  static void GenerateInitialize(MacroAssembler* masm);
+  static void GeneratePreMonomorphic(MacroAssembler* masm);
+  static void GenerateMiss(MacroAssembler* masm);
+  static void GenerateMegamorphic(MacroAssembler* masm);
+  static void GenerateNormal(MacroAssembler* masm);
+
+  // Specialized code generator routines.
+  static void GenerateArrayLength(MacroAssembler* masm);
+  static void GenerateStringLength(MacroAssembler* masm);
+  static void GenerateFunctionPrototype(MacroAssembler* masm);
+
+ private:
+  static void Generate(MacroAssembler* masm, const ExternalReference& f);
+
+  // Update the inline cache and the global stub cache based on the
+  // lookup result.
+  void UpdateCaches(LookupResult* lookup,
+                    State state,
+                    Handle<Object> object,
+                    Handle<String> name);
+
+  // Stub accessors.
+  static Code* megamorphic_stub() {
+    return Builtins::builtin(Builtins::LoadIC_Megamorphic);
+  }
+  static Code* initialize_stub() {
+    return Builtins::builtin(Builtins::LoadIC_Initialize);
+  }
+  static Code* pre_monomorphic_stub() {
+    return Builtins::builtin(Builtins::LoadIC_PreMonomorphic);
+  }
+
+  static void Clear(Address address, Code* target);
+  friend class IC;
+};
+
+
+class KeyedLoadIC: public IC {
+ public:
+  KeyedLoadIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_keyed_load_stub()); }
+
+  Object* Load(State state, Handle<Object> object, Handle<Object> key);
+
+  // Code generator routines.
+  static void GenerateMiss(MacroAssembler* masm);
+  static void GenerateInitialize(MacroAssembler* masm);
+  static void GeneratePreMonomorphic(MacroAssembler* masm);
+  static void GenerateGeneric(MacroAssembler* masm);
+
+ private:
+  static void Generate(MacroAssembler* masm, const ExternalReference& f);
+
+  // Update the inline cache.
+  void UpdateCaches(LookupResult* lookup,
+                    State state,
+                    Handle<Object> object,
+                    Handle<String> name);
+
+  // Stub accessors.
+  static Code* initialize_stub() {
+    return Builtins::builtin(Builtins::KeyedLoadIC_Initialize);
+  }
+  static Code* megamorphic_stub() {
+    return Builtins::builtin(Builtins::KeyedLoadIC_Generic);
+  }
+  static Code* generic_stub() {
+    return Builtins::builtin(Builtins::KeyedLoadIC_Generic);
+  }
+  static Code* pre_monomorphic_stub() {
+    return Builtins::builtin(Builtins::KeyedLoadIC_PreMonomorphic);
+  }
+
+  static void Clear(Address address, Code* target);
+
+  // Support for patching the map that is checked in an inlined
+  // version of keyed load.
+  static void PatchInlinedMapCheck(Address address, Object* map);
+
+  friend class IC;
+};
+
+
+class StoreIC: public IC {
+ public:
+  StoreIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_store_stub()); }
+
+  Object* Store(State state,
+                Handle<Object> object,
+                Handle<String> name,
+                Handle<Object> value);
+
+  // Code generators for stub routines. Only called once at startup.
+  static void GenerateInitialize(MacroAssembler* masm);
+  static void GenerateMiss(MacroAssembler* masm);
+  static void GenerateMegamorphic(MacroAssembler* masm);
+  static void GenerateExtendStorage(MacroAssembler* masm);
+
+ private:
+  static void Generate(MacroAssembler* masm, const ExternalReference& f);
+
+  // Update the inline cache and the global stub cache based on the
+  // lookup result.
+  void UpdateCaches(LookupResult* lookup,
+                    State state, Handle<JSObject> receiver,
+                    Handle<String> name,
+                    Handle<Object> value);
+
+  // Stub accessors.
+  static Code* megamorphic_stub() {
+    return Builtins::builtin(Builtins::StoreIC_Megamorphic);
+  }
+  static Code* initialize_stub() {
+    return Builtins::builtin(Builtins::StoreIC_Initialize);
+  }
+
+  static void Clear(Address address, Code* target);
+  friend class IC;
+};
+
+
+class KeyedStoreIC: public IC {
+ public:
+  KeyedStoreIC() : IC(NO_EXTRA_FRAME) { }
+
+  Object* Store(State state,
+                Handle<Object> object,
+                Handle<Object> name,
+                Handle<Object> value);
+
+  // Code generators for stub routines.  Only called once at startup.
+  static void GenerateInitialize(MacroAssembler* masm);
+  static void GenerateMiss(MacroAssembler* masm);
+  static void GenerateGeneric(MacroAssembler* masm);
+  static void GenerateExtendStorage(MacroAssembler* masm);
+
+ private:
+  static void Generate(MacroAssembler* masm, const ExternalReference& f);
+
+  // Update the inline cache.
+  void UpdateCaches(LookupResult* lookup,
+                    State state,
+                    Handle<JSObject> receiver,
+                    Handle<String> name,
+                    Handle<Object> value);
+
+  // Stub accessors.
+  static Code* initialize_stub() {
+    return Builtins::builtin(Builtins::KeyedStoreIC_Initialize);
+  }
+  static Code* megamorphic_stub() {
+    return Builtins::builtin(Builtins::KeyedStoreIC_Generic);
+  }
+  static Code* generic_stub() {
+    return Builtins::builtin(Builtins::KeyedStoreIC_Generic);
+  }
+
+  static void Clear(Address address, Code* target);
+  friend class IC;
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_IC_H_
diff --git a/deps/v8/src/interpreter-irregexp.cc b/deps/v8/src/interpreter-irregexp.cc
new file mode 100644
index 0000000..1cc5c5a
--- /dev/null
+++ b/deps/v8/src/interpreter-irregexp.cc
@@ -0,0 +1,596 @@
+// Copyright 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.
+
+// A simple interpreter for the Irregexp byte code.
+
+
+#include "v8.h"
+#include "unicode.h"
+#include "utils.h"
+#include "ast.h"
+#include "bytecodes-irregexp.h"
+#include "interpreter-irregexp.h"
+
+
+namespace v8 { namespace internal {
+
+
+static unibrow::Mapping<unibrow::Ecma262Canonicalize> interp_canonicalize;
+
+
+static bool BackRefMatchesNoCase(int from,
+                                 int current,
+                                 int len,
+                                 Vector<const uc16> subject) {
+  for (int i = 0; i < len; i++) {
+    unibrow::uchar old_char = subject[from++];
+    unibrow::uchar new_char = subject[current++];
+    if (old_char == new_char) continue;
+    interp_canonicalize.get(old_char, '\0', &old_char);
+    interp_canonicalize.get(new_char, '\0', &new_char);
+    if (old_char != new_char) {
+      return false;
+    }
+  }
+  return true;
+}
+
+
+static bool BackRefMatchesNoCase(int from,
+                                 int current,
+                                 int len,
+                                 Vector<const char> subject) {
+  for (int i = 0; i < len; i++) {
+    unsigned int old_char = subject[from++];
+    unsigned int new_char = subject[current++];
+    if (old_char == new_char) continue;
+    if (old_char - 'A' <= 'Z' - 'A') old_char |= 0x20;
+    if (new_char - 'A' <= 'Z' - 'A') new_char |= 0x20;
+    if (old_char != new_char) return false;
+  }
+  return true;
+}
+
+
+#ifdef DEBUG
+static void TraceInterpreter(const byte* code_base,
+                             const byte* pc,
+                             int stack_depth,
+                             int current_position,
+                             uint32_t current_char,
+                             int bytecode_length,
+                             const char* bytecode_name) {
+  if (FLAG_trace_regexp_bytecodes) {
+    bool printable = (current_char < 127 && current_char >= 32);
+    const char* format =
+        printable ?
+        "pc = %02x, sp = %d, curpos = %d, curchar = %08x (%c), bc = %s" :
+        "pc = %02x, sp = %d, curpos = %d, curchar = %08x .%c., bc = %s";
+    PrintF(format,
+           pc - code_base,
+           stack_depth,
+           current_position,
+           current_char,
+           printable ? current_char : '.',
+           bytecode_name);
+    for (int i = 0; i < bytecode_length; i++) {
+      printf(", %02x", pc[i]);
+    }
+    printf(" ");
+    for (int i = 1; i < bytecode_length; i++) {
+      unsigned char b = pc[i];
+      if (b < 127 && b >= 32) {
+        printf("%c", b);
+      } else {
+        printf(".");
+      }
+    }
+    printf("\n");
+  }
+}
+
+
+#define BYTECODE(name)                                  \
+  case BC_##name:                                       \
+    TraceInterpreter(code_base,                         \
+                     pc,                                \
+                     backtrack_sp - backtrack_stack,    \
+                     current,                           \
+                     current_char,                      \
+                     BC_##name##_LENGTH,                \
+                     #name);
+#else
+#define BYTECODE(name)                                  \
+  case BC_##name:
+#endif
+
+
+static int32_t Load32Aligned(const byte* pc) {
+  ASSERT((reinterpret_cast<int>(pc) & 3) == 0);
+  return *reinterpret_cast<const int32_t *>(pc);
+}
+
+
+static int32_t Load16Aligned(const byte* pc) {
+  ASSERT((reinterpret_cast<int>(pc) & 1) == 0);
+  return *reinterpret_cast<const uint16_t *>(pc);
+}
+
+
+template <typename Char>
+static bool RawMatch(const byte* code_base,
+                     Vector<const Char> subject,
+                     int* registers,
+                     int current,
+                     uint32_t current_char) {
+  const byte* pc = code_base;
+  static const int kBacktrackStackSize = 10000;
+  int backtrack_stack[kBacktrackStackSize];
+  int backtrack_stack_space = kBacktrackStackSize;
+  int* backtrack_sp = backtrack_stack;
+#ifdef DEBUG
+  if (FLAG_trace_regexp_bytecodes) {
+    PrintF("\n\nStart bytecode interpreter\n\n");
+  }
+#endif
+  while (true) {
+    int32_t insn = Load32Aligned(pc);
+    switch (insn & BYTECODE_MASK) {
+      BYTECODE(BREAK)
+        UNREACHABLE();
+        return false;
+      BYTECODE(PUSH_CP)
+        if (--backtrack_stack_space < 0) {
+          return false;  // No match on backtrack stack overflow.
+        }
+        *backtrack_sp++ = current;
+        pc += BC_PUSH_CP_LENGTH;
+        break;
+      BYTECODE(PUSH_BT)
+        if (--backtrack_stack_space < 0) {
+          return false;  // No match on backtrack stack overflow.
+        }
+        *backtrack_sp++ = Load32Aligned(pc + 4);
+        pc += BC_PUSH_BT_LENGTH;
+        break;
+      BYTECODE(PUSH_REGISTER)
+        if (--backtrack_stack_space < 0) {
+          return false;  // No match on backtrack stack overflow.
+        }
+        *backtrack_sp++ = registers[insn >> BYTECODE_SHIFT];
+        pc += BC_PUSH_REGISTER_LENGTH;
+        break;
+      BYTECODE(SET_REGISTER)
+        registers[insn >> BYTECODE_SHIFT] = Load32Aligned(pc + 4);
+        pc += BC_SET_REGISTER_LENGTH;
+        break;
+      BYTECODE(ADVANCE_REGISTER)
+        registers[insn >> BYTECODE_SHIFT] += Load32Aligned(pc + 4);
+        pc += BC_ADVANCE_REGISTER_LENGTH;
+        break;
+      BYTECODE(SET_REGISTER_TO_CP)
+        registers[insn >> BYTECODE_SHIFT] = current + Load32Aligned(pc + 4);
+        pc += BC_SET_REGISTER_TO_CP_LENGTH;
+        break;
+      BYTECODE(SET_CP_TO_REGISTER)
+        current = registers[insn >> BYTECODE_SHIFT];
+        pc += BC_SET_CP_TO_REGISTER_LENGTH;
+        break;
+      BYTECODE(SET_REGISTER_TO_SP)
+        registers[insn >> BYTECODE_SHIFT] = backtrack_sp - backtrack_stack;
+        pc += BC_SET_REGISTER_TO_SP_LENGTH;
+        break;
+      BYTECODE(SET_SP_TO_REGISTER)
+        backtrack_sp = backtrack_stack + registers[insn >> BYTECODE_SHIFT];
+        backtrack_stack_space = kBacktrackStackSize -
+                                (backtrack_sp - backtrack_stack);
+        pc += BC_SET_SP_TO_REGISTER_LENGTH;
+        break;
+      BYTECODE(POP_CP)
+        backtrack_stack_space++;
+        --backtrack_sp;
+        current = *backtrack_sp;
+        pc += BC_POP_CP_LENGTH;
+        break;
+      BYTECODE(POP_BT)
+        backtrack_stack_space++;
+        --backtrack_sp;
+        pc = code_base + *backtrack_sp;
+        break;
+      BYTECODE(POP_REGISTER)
+        backtrack_stack_space++;
+        --backtrack_sp;
+        registers[insn >> BYTECODE_SHIFT] = *backtrack_sp;
+        pc += BC_POP_REGISTER_LENGTH;
+        break;
+      BYTECODE(FAIL)
+        return false;
+      BYTECODE(SUCCEED)
+        return true;
+      BYTECODE(ADVANCE_CP)
+        current += insn >> BYTECODE_SHIFT;
+        pc += BC_ADVANCE_CP_LENGTH;
+        break;
+      BYTECODE(GOTO)
+        pc = code_base + Load32Aligned(pc + 4);
+        break;
+      BYTECODE(ADVANCE_CP_AND_GOTO)
+        current += insn >> BYTECODE_SHIFT;
+        pc = code_base + Load32Aligned(pc + 4);
+        break;
+      BYTECODE(CHECK_GREEDY)
+        if (current == backtrack_sp[-1]) {
+          backtrack_sp--;
+          backtrack_stack_space++;
+          pc = code_base + Load32Aligned(pc + 4);
+        } else {
+          pc += BC_CHECK_GREEDY_LENGTH;
+        }
+        break;
+      BYTECODE(LOAD_CURRENT_CHAR) {
+        int pos = current + (insn >> BYTECODE_SHIFT);
+        if (pos >= subject.length()) {
+          pc = code_base + Load32Aligned(pc + 4);
+        } else {
+          current_char = subject[pos];
+          pc += BC_LOAD_CURRENT_CHAR_LENGTH;
+        }
+        break;
+      }
+      BYTECODE(LOAD_CURRENT_CHAR_UNCHECKED) {
+        int pos = current + (insn >> BYTECODE_SHIFT);
+        current_char = subject[pos];
+        pc += BC_LOAD_CURRENT_CHAR_UNCHECKED_LENGTH;
+        break;
+      }
+      BYTECODE(LOAD_2_CURRENT_CHARS) {
+        int pos = current + (insn >> BYTECODE_SHIFT);
+        if (pos + 2 > subject.length()) {
+          pc = code_base + Load32Aligned(pc + 4);
+        } else {
+          Char next = subject[pos + 1];
+          current_char =
+              (subject[pos] | (next << (kBitsPerByte * sizeof(Char))));
+          pc += BC_LOAD_2_CURRENT_CHARS_LENGTH;
+        }
+        break;
+      }
+      BYTECODE(LOAD_2_CURRENT_CHARS_UNCHECKED) {
+        int pos = current + (insn >> BYTECODE_SHIFT);
+        Char next = subject[pos + 1];
+        current_char = (subject[pos] | (next << (kBitsPerByte * sizeof(Char))));
+        pc += BC_LOAD_2_CURRENT_CHARS_UNCHECKED_LENGTH;
+        break;
+      }
+      BYTECODE(LOAD_4_CURRENT_CHARS) {
+        ASSERT(sizeof(Char) == 1);
+        int pos = current + (insn >> BYTECODE_SHIFT);
+        if (pos + 4 > subject.length()) {
+          pc = code_base + Load32Aligned(pc + 4);
+        } else {
+          Char next1 = subject[pos + 1];
+          Char next2 = subject[pos + 2];
+          Char next3 = subject[pos + 3];
+          current_char = (subject[pos] |
+                          (next1 << 8) |
+                          (next2 << 16) |
+                          (next3 << 24));
+          pc += BC_LOAD_4_CURRENT_CHARS_LENGTH;
+        }
+        break;
+      }
+      BYTECODE(LOAD_4_CURRENT_CHARS_UNCHECKED) {
+        ASSERT(sizeof(Char) == 1);
+        int pos = current + (insn >> BYTECODE_SHIFT);
+        Char next1 = subject[pos + 1];
+        Char next2 = subject[pos + 2];
+        Char next3 = subject[pos + 3];
+        current_char = (subject[pos] |
+                        (next1 << 8) |
+                        (next2 << 16) |
+                        (next3 << 24));
+        pc += BC_LOAD_4_CURRENT_CHARS_UNCHECKED_LENGTH;
+        break;
+      }
+      BYTECODE(CHECK_4_CHARS) {
+        uint32_t c = Load32Aligned(pc + 4);
+        if (c == current_char) {
+          pc = code_base + Load32Aligned(pc + 8);
+        } else {
+          pc += BC_CHECK_4_CHARS_LENGTH;
+        }
+        break;
+      }
+      BYTECODE(CHECK_CHAR) {
+        uint32_t c = (insn >> BYTECODE_SHIFT);
+        if (c == current_char) {
+          pc = code_base + Load32Aligned(pc + 4);
+        } else {
+          pc += BC_CHECK_CHAR_LENGTH;
+        }
+        break;
+      }
+      BYTECODE(CHECK_NOT_4_CHARS) {
+        uint32_t c = Load32Aligned(pc + 4);
+        if (c != current_char) {
+          pc = code_base + Load32Aligned(pc + 8);
+        } else {
+          pc += BC_CHECK_NOT_4_CHARS_LENGTH;
+        }
+        break;
+      }
+      BYTECODE(CHECK_NOT_CHAR) {
+        uint32_t c = (insn >> BYTECODE_SHIFT);
+        if (c != current_char) {
+          pc = code_base + Load32Aligned(pc + 4);
+        } else {
+          pc += BC_CHECK_NOT_CHAR_LENGTH;
+        }
+        break;
+      }
+      BYTECODE(AND_CHECK_4_CHARS) {
+        uint32_t c = Load32Aligned(pc + 4);
+        if (c == (current_char & Load32Aligned(pc + 8))) {
+          pc = code_base + Load32Aligned(pc + 12);
+        } else {
+          pc += BC_AND_CHECK_4_CHARS_LENGTH;
+        }
+        break;
+      }
+      BYTECODE(AND_CHECK_CHAR) {
+        uint32_t c = (insn >> BYTECODE_SHIFT);
+        if (c == (current_char & Load32Aligned(pc + 4))) {
+          pc = code_base + Load32Aligned(pc + 8);
+        } else {
+          pc += BC_AND_CHECK_CHAR_LENGTH;
+        }
+        break;
+      }
+      BYTECODE(AND_CHECK_NOT_4_CHARS) {
+        uint32_t c = Load32Aligned(pc + 4);
+        if (c != (current_char & Load32Aligned(pc + 8))) {
+          pc = code_base + Load32Aligned(pc + 12);
+        } else {
+          pc += BC_AND_CHECK_NOT_4_CHARS_LENGTH;
+        }
+        break;
+      }
+      BYTECODE(AND_CHECK_NOT_CHAR) {
+        uint32_t c = (insn >> BYTECODE_SHIFT);
+        if (c != (current_char & Load32Aligned(pc + 4))) {
+          pc = code_base + Load32Aligned(pc + 8);
+        } else {
+          pc += BC_AND_CHECK_NOT_CHAR_LENGTH;
+        }
+        break;
+      }
+      BYTECODE(MINUS_AND_CHECK_NOT_CHAR) {
+        uint32_t c = (insn >> BYTECODE_SHIFT);
+        uint32_t minus = Load16Aligned(pc + 4);
+        uint32_t mask = Load16Aligned(pc + 6);
+        if (c != ((current_char - minus) & mask)) {
+          pc = code_base + Load32Aligned(pc + 8);
+        } else {
+          pc += BC_MINUS_AND_CHECK_NOT_CHAR_LENGTH;
+        }
+        break;
+      }
+      BYTECODE(CHECK_LT) {
+        uint32_t limit = (insn >> BYTECODE_SHIFT);
+        if (current_char < limit) {
+          pc = code_base + Load32Aligned(pc + 4);
+        } else {
+          pc += BC_CHECK_LT_LENGTH;
+        }
+        break;
+      }
+      BYTECODE(CHECK_GT) {
+        uint32_t limit = (insn >> BYTECODE_SHIFT);
+        if (current_char > limit) {
+          pc = code_base + Load32Aligned(pc + 4);
+        } else {
+          pc += BC_CHECK_GT_LENGTH;
+        }
+        break;
+      }
+      BYTECODE(CHECK_REGISTER_LT)
+        if (registers[insn >> BYTECODE_SHIFT] < Load32Aligned(pc + 4)) {
+          pc = code_base + Load32Aligned(pc + 8);
+        } else {
+          pc += BC_CHECK_REGISTER_LT_LENGTH;
+        }
+        break;
+      BYTECODE(CHECK_REGISTER_GE)
+        if (registers[insn >> BYTECODE_SHIFT] >= Load32Aligned(pc + 4)) {
+          pc = code_base + Load32Aligned(pc + 8);
+        } else {
+          pc += BC_CHECK_REGISTER_GE_LENGTH;
+        }
+        break;
+      BYTECODE(CHECK_REGISTER_EQ_POS)
+        if (registers[insn >> BYTECODE_SHIFT] == current) {
+          pc = code_base + Load32Aligned(pc + 4);
+        } else {
+          pc += BC_CHECK_REGISTER_EQ_POS_LENGTH;
+        }
+        break;
+      BYTECODE(LOOKUP_MAP1) {
+        // Look up character in a bitmap.  If we find a 0, then jump to the
+        // location at pc + 8.  Otherwise fall through!
+        int index = current_char - (insn >> BYTECODE_SHIFT);
+        byte map = code_base[Load32Aligned(pc + 4) + (index >> 3)];
+        map = ((map >> (index & 7)) & 1);
+        if (map == 0) {
+          pc = code_base + Load32Aligned(pc + 8);
+        } else {
+          pc += BC_LOOKUP_MAP1_LENGTH;
+        }
+        break;
+      }
+      BYTECODE(LOOKUP_MAP2) {
+        // Look up character in a half-nibble map.  If we find 00, then jump to
+        // the location at pc + 8.   If we find 01 then jump to location at
+        // pc + 11, etc.
+        int index = (current_char - (insn >> BYTECODE_SHIFT)) << 1;
+        byte map = code_base[Load32Aligned(pc + 3) + (index >> 3)];
+        map = ((map >> (index & 7)) & 3);
+        if (map < 2) {
+          if (map == 0) {
+            pc = code_base + Load32Aligned(pc + 8);
+          } else {
+            pc = code_base + Load32Aligned(pc + 12);
+          }
+        } else {
+          if (map == 2) {
+            pc = code_base + Load32Aligned(pc + 16);
+          } else {
+            pc = code_base + Load32Aligned(pc + 20);
+          }
+        }
+        break;
+      }
+      BYTECODE(LOOKUP_MAP8) {
+        // Look up character in a byte map.  Use the byte as an index into a
+        // table that follows this instruction immediately.
+        int index = current_char - (insn >> BYTECODE_SHIFT);
+        byte map = code_base[Load32Aligned(pc + 4) + index];
+        const byte* new_pc = code_base + Load32Aligned(pc + 8) + (map << 2);
+        pc = code_base + Load32Aligned(new_pc);
+        break;
+      }
+      BYTECODE(LOOKUP_HI_MAP8) {
+        // Look up high byte of this character in a byte map.  Use the byte as
+        // an index into a table that follows this instruction immediately.
+        int index = (current_char >> 8) - (insn >> BYTECODE_SHIFT);
+        byte map = code_base[Load32Aligned(pc + 4) + index];
+        const byte* new_pc = code_base + Load32Aligned(pc + 8) + (map << 2);
+        pc = code_base + Load32Aligned(new_pc);
+        break;
+      }
+      BYTECODE(CHECK_NOT_REGS_EQUAL)
+        if (registers[insn >> BYTECODE_SHIFT] ==
+            registers[Load32Aligned(pc + 4)]) {
+          pc += BC_CHECK_NOT_REGS_EQUAL_LENGTH;
+        } else {
+          pc = code_base + Load32Aligned(pc + 8);
+        }
+        break;
+      BYTECODE(CHECK_NOT_BACK_REF) {
+        int from = registers[insn >> BYTECODE_SHIFT];
+        int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
+        if (from < 0 || len <= 0) {
+          pc += BC_CHECK_NOT_BACK_REF_LENGTH;
+          break;
+        }
+        if (current + len > subject.length()) {
+          pc = code_base + Load32Aligned(pc + 4);
+          break;
+        } else {
+          int i;
+          for (i = 0; i < len; i++) {
+            if (subject[from + i] != subject[current + i]) {
+              pc = code_base + Load32Aligned(pc + 4);
+              break;
+            }
+          }
+          if (i < len) break;
+          current += len;
+        }
+        pc += BC_CHECK_NOT_BACK_REF_LENGTH;
+        break;
+      }
+      BYTECODE(CHECK_NOT_BACK_REF_NO_CASE) {
+        int from = registers[insn >> BYTECODE_SHIFT];
+        int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
+        if (from < 0 || len <= 0) {
+          pc += BC_CHECK_NOT_BACK_REF_NO_CASE_LENGTH;
+          break;
+        }
+        if (current + len > subject.length()) {
+          pc = code_base + Load32Aligned(pc + 4);
+          break;
+        } else {
+          if (BackRefMatchesNoCase(from, current, len, subject)) {
+            current += len;
+            pc += BC_CHECK_NOT_BACK_REF_NO_CASE_LENGTH;
+          } else {
+            pc = code_base + Load32Aligned(pc + 4);
+          }
+        }
+        break;
+      }
+      BYTECODE(CHECK_AT_START)
+        if (current == 0) {
+          pc = code_base + Load32Aligned(pc + 4);
+        } else {
+          pc += BC_CHECK_AT_START_LENGTH;
+        }
+        break;
+      BYTECODE(CHECK_NOT_AT_START)
+        if (current == 0) {
+          pc += BC_CHECK_NOT_AT_START_LENGTH;
+        } else {
+          pc = code_base + Load32Aligned(pc + 4);
+        }
+        break;
+      default:
+        UNREACHABLE();
+        break;
+    }
+  }
+}
+
+
+bool IrregexpInterpreter::Match(Handle<ByteArray> code_array,
+                                Handle<String> subject,
+                                int* registers,
+                                int start_position) {
+  ASSERT(subject->IsFlat());
+
+  AssertNoAllocation a;
+  const byte* code_base = code_array->GetDataStartAddress();
+  uc16 previous_char = '\n';
+  if (StringShape(*subject).IsAsciiRepresentation()) {
+    Vector<const char> subject_vector = subject->ToAsciiVector();
+    if (start_position != 0) previous_char = subject_vector[start_position - 1];
+    return RawMatch(code_base,
+                    subject_vector,
+                    registers,
+                    start_position,
+                    previous_char);
+  } else {
+    Vector<const uc16> subject_vector = subject->ToUC16Vector();
+    if (start_position != 0) previous_char = subject_vector[start_position - 1];
+    return RawMatch(code_base,
+                    subject_vector,
+                    registers,
+                    start_position,
+                    previous_char);
+  }
+}
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/interpreter-irregexp.h b/deps/v8/src/interpreter-irregexp.h
new file mode 100644
index 0000000..c65cb9e
--- /dev/null
+++ b/deps/v8/src/interpreter-irregexp.h
@@ -0,0 +1,47 @@
+// Copyright 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.
+
+// A simple interpreter for the Irregexp byte code.
+
+#ifndef V8_INTERPRETER_IRREGEXP_H_
+#define V8_INTERPRETER_IRREGEXP_H_
+
+namespace v8 { namespace internal {
+
+
+class IrregexpInterpreter {
+ public:
+  static bool Match(Handle<ByteArray> code,
+                    Handle<String> subject,
+                    int* captures,
+                    int start_position);
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_INTERPRETER_IRREGEXP_H_
diff --git a/deps/v8/src/jsregexp-inl.h b/deps/v8/src/jsregexp-inl.h
new file mode 100644
index 0000000..09c4c8f
--- /dev/null
+++ b/deps/v8/src/jsregexp-inl.h
@@ -0,0 +1,259 @@
+// Copyright 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_JSREGEXP_INL_H_
+#define V8_JSREGEXP_INL_H_
+
+
+#include "jsregexp.h"
+#include "regexp-macro-assembler.h"
+
+
+namespace v8 { namespace internal {
+
+
+template <typename C>
+bool ZoneSplayTree<C>::Insert(const Key& key, Locator* locator) {
+  if (is_empty()) {
+    // If the tree is empty, insert the new node.
+    root_ = new Node(key, C::kNoValue);
+  } else {
+    // Splay on the key to move the last node on the search path
+    // for the key to the root of the tree.
+    Splay(key);
+    // Ignore repeated insertions with the same key.
+    int cmp = C::Compare(key, root_->key_);
+    if (cmp == 0) {
+      locator->bind(root_);
+      return false;
+    }
+    // Insert the new node.
+    Node* node = new Node(key, C::kNoValue);
+    if (cmp > 0) {
+      node->left_ = root_;
+      node->right_ = root_->right_;
+      root_->right_ = NULL;
+    } else {
+      node->right_ = root_;
+      node->left_ = root_->left_;
+      root_->left_ = NULL;
+    }
+    root_ = node;
+  }
+  locator->bind(root_);
+  return true;
+}
+
+
+template <typename C>
+bool ZoneSplayTree<C>::Find(const Key& key, Locator* locator) {
+  if (is_empty())
+    return false;
+  Splay(key);
+  if (C::Compare(key, root_->key_) == 0) {
+    locator->bind(root_);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+
+template <typename C>
+bool ZoneSplayTree<C>::FindGreatestLessThan(const Key& key,
+                                            Locator* locator) {
+  if (is_empty())
+    return false;
+  // Splay on the key to move the node with the given key or the last
+  // node on the search path to the top of the tree.
+  Splay(key);
+  // Now the result is either the root node or the greatest node in
+  // the left subtree.
+  int cmp = C::Compare(root_->key_, key);
+  if (cmp <= 0) {
+    locator->bind(root_);
+    return true;
+  } else {
+    Node* temp = root_;
+    root_ = root_->left_;
+    bool result = FindGreatest(locator);
+    root_ = temp;
+    return result;
+  }
+}
+
+
+template <typename C>
+bool ZoneSplayTree<C>::FindLeastGreaterThan(const Key& key,
+                                            Locator* locator) {
+  if (is_empty())
+    return false;
+  // Splay on the key to move the node with the given key or the last
+  // node on the search path to the top of the tree.
+  Splay(key);
+  // Now the result is either the root node or the least node in
+  // the right subtree.
+  int cmp = C::Compare(root_->key_, key);
+  if (cmp >= 0) {
+    locator->bind(root_);
+    return true;
+  } else {
+    Node* temp = root_;
+    root_ = root_->right_;
+    bool result = FindLeast(locator);
+    root_ = temp;
+    return result;
+  }
+}
+
+
+template <typename C>
+bool ZoneSplayTree<C>::FindGreatest(Locator* locator) {
+  if (is_empty())
+    return false;
+  Node* current = root_;
+  while (current->right_ != NULL)
+    current = current->right_;
+  locator->bind(current);
+  return true;
+}
+
+
+template <typename C>
+bool ZoneSplayTree<C>::FindLeast(Locator* locator) {
+  if (is_empty())
+    return false;
+  Node* current = root_;
+  while (current->left_ != NULL)
+    current = current->left_;
+  locator->bind(current);
+  return true;
+}
+
+
+template <typename C>
+bool ZoneSplayTree<C>::Remove(const Key& key) {
+  // Bail if the tree is empty
+  if (is_empty())
+    return false;
+  // Splay on the key to move the node with the given key to the top.
+  Splay(key);
+  // Bail if the key is not in the tree
+  if (C::Compare(key, root_->key_) != 0)
+    return false;
+  if (root_->left_ == NULL) {
+    // No left child, so the new tree is just the right child.
+    root_ = root_->right_;
+  } else {
+    // Left child exists.
+    Node* right = root_->right_;
+    // Make the original left child the new root.
+    root_ = root_->left_;
+    // Splay to make sure that the new root has an empty right child.
+    Splay(key);
+    // Insert the original right child as the right child of the new
+    // root.
+    root_->right_ = right;
+  }
+  return true;
+}
+
+
+template <typename C>
+void ZoneSplayTree<C>::Splay(const Key& key) {
+  if (is_empty())
+    return;
+  Node dummy_node(C::kNoKey, C::kNoValue);
+  // Create a dummy node.  The use of the dummy node is a bit
+  // counter-intuitive: The right child of the dummy node will hold
+  // the L tree of the algorithm.  The left child of the dummy node
+  // will hold the R tree of the algorithm.  Using a dummy node, left
+  // and right will always be nodes and we avoid special cases.
+  Node* dummy = &dummy_node;
+  Node* left = dummy;
+  Node* right = dummy;
+  Node* current = root_;
+  while (true) {
+    int cmp = C::Compare(key, current->key_);
+    if (cmp < 0) {
+      if (current->left_ == NULL)
+        break;
+      if (C::Compare(key, current->left_->key_) < 0) {
+        // Rotate right.
+        Node* temp = current->left_;
+        current->left_ = temp->right_;
+        temp->right_ = current;
+        current = temp;
+        if (current->left_ == NULL)
+          break;
+      }
+      // Link right.
+      right->left_ = current;
+      right = current;
+      current = current->left_;
+    } else if (cmp > 0) {
+      if (current->right_ == NULL)
+        break;
+      if (C::Compare(key, current->right_->key_) > 0) {
+        // Rotate left.
+        Node* temp = current->right_;
+        current->right_ = temp->left_;
+        temp->left_ = current;
+        current = temp;
+        if (current->right_ == NULL)
+          break;
+      }
+      // Link left.
+      left->right_ = current;
+      left = current;
+      current = current->right_;
+    } else {
+      break;
+    }
+  }
+  // Assemble.
+  left->right_ = current->left_;
+  right->left_ = current->right_;
+  current->left_ = dummy->right_;
+  current->right_ = dummy->left_;
+  root_ = current;
+}
+
+
+template <typename Node, class Callback>
+static void DoForEach(Node* node, Callback* callback) {
+  if (node == NULL) return;
+  DoForEach<Node, Callback>(node->left(), callback);
+  callback->Call(node->key(), node->value());
+  DoForEach<Node, Callback>(node->right(), callback);
+}
+
+
+}}  // namespace v8::internal
+
+
+#endif  // V8_JSREGEXP_INL_H_
diff --git a/deps/v8/src/jsregexp.cc b/deps/v8/src/jsregexp.cc
new file mode 100644
index 0000000..40241e6
--- /dev/null
+++ b/deps/v8/src/jsregexp.cc
@@ -0,0 +1,4463 @@
+// Copyright 2006-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.
+
+#include "v8.h"
+
+#include "ast.h"
+#include "execution.h"
+#include "factory.h"
+#include "jsregexp-inl.h"
+#include "platform.h"
+#include "runtime.h"
+#include "top.h"
+#include "compilation-cache.h"
+#include "string-stream.h"
+#include "parser.h"
+#include "regexp-macro-assembler.h"
+#include "regexp-macro-assembler-tracer.h"
+#include "regexp-macro-assembler-irregexp.h"
+#include "regexp-stack.h"
+
+#ifdef ARM
+#include "regexp-macro-assembler-arm.h"
+#else  // IA32
+#include "macro-assembler-ia32.h"
+#include "regexp-macro-assembler-ia32.h"
+#endif
+
+#include "interpreter-irregexp.h"
+
+
+namespace v8 { namespace internal {
+
+
+Handle<Object> RegExpImpl::CreateRegExpLiteral(Handle<JSFunction> constructor,
+                                               Handle<String> pattern,
+                                               Handle<String> flags,
+                                               bool* has_pending_exception) {
+  // Ensure that the constructor function has been loaded.
+  if (!constructor->IsLoaded()) {
+    LoadLazy(constructor, has_pending_exception);
+    if (*has_pending_exception) return Handle<Object>();
+  }
+  // Call the construct code with 2 arguments.
+  Object** argv[2] = { Handle<Object>::cast(pattern).location(),
+                       Handle<Object>::cast(flags).location() };
+  return Execution::New(constructor, 2, argv, has_pending_exception);
+}
+
+
+static JSRegExp::Flags RegExpFlagsFromString(Handle<String> str) {
+  int flags = JSRegExp::NONE;
+  for (int i = 0; i < str->length(); i++) {
+    switch (str->Get(i)) {
+      case 'i':
+        flags |= JSRegExp::IGNORE_CASE;
+        break;
+      case 'g':
+        flags |= JSRegExp::GLOBAL;
+        break;
+      case 'm':
+        flags |= JSRegExp::MULTILINE;
+        break;
+    }
+  }
+  return JSRegExp::Flags(flags);
+}
+
+
+static inline void ThrowRegExpException(Handle<JSRegExp> re,
+                                        Handle<String> pattern,
+                                        Handle<String> error_text,
+                                        const char* message) {
+  Handle<JSArray> array = Factory::NewJSArray(2);
+  SetElement(array, 0, pattern);
+  SetElement(array, 1, error_text);
+  Handle<Object> regexp_err = Factory::NewSyntaxError(message, array);
+  Top::Throw(*regexp_err);
+}
+
+
+// Generic RegExp methods. Dispatches to implementation specific methods.
+
+
+class OffsetsVector {
+ public:
+  inline OffsetsVector(int num_registers)
+      : offsets_vector_length_(num_registers) {
+    if (offsets_vector_length_ > kStaticOffsetsVectorSize) {
+      vector_ = NewArray<int>(offsets_vector_length_);
+    } else {
+      vector_ = static_offsets_vector_;
+    }
+  }
+  inline ~OffsetsVector() {
+    if (offsets_vector_length_ > kStaticOffsetsVectorSize) {
+      DeleteArray(vector_);
+      vector_ = NULL;
+    }
+  }
+  inline int* vector() { return vector_; }
+  inline int length() { return offsets_vector_length_; }
+
+ private:
+  int* vector_;
+  int offsets_vector_length_;
+  static const int kStaticOffsetsVectorSize = 50;
+  static int static_offsets_vector_[kStaticOffsetsVectorSize];
+};
+
+
+int OffsetsVector::static_offsets_vector_[
+    OffsetsVector::kStaticOffsetsVectorSize];
+
+
+Handle<Object> RegExpImpl::Compile(Handle<JSRegExp> re,
+                                   Handle<String> pattern,
+                                   Handle<String> flag_str) {
+  JSRegExp::Flags flags = RegExpFlagsFromString(flag_str);
+  Handle<FixedArray> cached = CompilationCache::LookupRegExp(pattern, flags);
+  bool in_cache = !cached.is_null();
+  LOG(RegExpCompileEvent(re, in_cache));
+
+  Handle<Object> result;
+  if (in_cache) {
+    re->set_data(*cached);
+    return re;
+  }
+  FlattenString(pattern);
+  ZoneScope zone_scope(DELETE_ON_EXIT);
+  RegExpCompileData parse_result;
+  FlatStringReader reader(pattern);
+  if (!ParseRegExp(&reader, flags.is_multiline(), &parse_result)) {
+    // Throw an exception if we fail to parse the pattern.
+    ThrowRegExpException(re,
+                         pattern,
+                         parse_result.error,
+                         "malformed_regexp");
+    return Handle<Object>::null();
+  }
+
+  if (parse_result.simple && !flags.is_ignore_case()) {
+    // Parse-tree is a single atom that is equal to the pattern.
+    AtomCompile(re, pattern, flags, pattern);
+  } else if (parse_result.tree->IsAtom() &&
+      !flags.is_ignore_case() &&
+      parse_result.capture_count == 0) {
+    RegExpAtom* atom = parse_result.tree->AsAtom();
+    Vector<const uc16> atom_pattern = atom->data();
+    Handle<String> atom_string = Factory::NewStringFromTwoByte(atom_pattern);
+    AtomCompile(re, pattern, flags, atom_string);
+  } else {
+    IrregexpPrepare(re, pattern, flags, parse_result.capture_count);
+  }
+  ASSERT(re->data()->IsFixedArray());
+  // Compilation succeeded so the data is set on the regexp
+  // and we can store it in the cache.
+  Handle<FixedArray> data(FixedArray::cast(re->data()));
+  CompilationCache::PutRegExp(pattern, flags, data);
+
+  return re;
+}
+
+
+Handle<Object> RegExpImpl::Exec(Handle<JSRegExp> regexp,
+                                Handle<String> subject,
+                                int index,
+                                Handle<JSArray> last_match_info) {
+  switch (regexp->TypeTag()) {
+    case JSRegExp::ATOM:
+      return AtomExec(regexp, subject, index, last_match_info);
+    case JSRegExp::IRREGEXP: {
+      Handle<Object> result =
+          IrregexpExec(regexp, subject, index, last_match_info);
+      ASSERT(!result.is_null() || Top::has_pending_exception());
+      return result;
+    }
+    default:
+      UNREACHABLE();
+      return Handle<Object>::null();
+  }
+}
+
+
+// RegExp Atom implementation: Simple string search using indexOf.
+
+
+void RegExpImpl::AtomCompile(Handle<JSRegExp> re,
+                             Handle<String> pattern,
+                             JSRegExp::Flags flags,
+                             Handle<String> match_pattern) {
+  Factory::SetRegExpAtomData(re,
+                             JSRegExp::ATOM,
+                             pattern,
+                             flags,
+                             match_pattern);
+}
+
+
+static void SetAtomLastCapture(FixedArray* array,
+                               String* subject,
+                               int from,
+                               int to) {
+  NoHandleAllocation no_handles;
+  RegExpImpl::SetLastCaptureCount(array, 2);
+  RegExpImpl::SetLastSubject(array, subject);
+  RegExpImpl::SetLastInput(array, subject);
+  RegExpImpl::SetCapture(array, 0, from);
+  RegExpImpl::SetCapture(array, 1, to);
+}
+
+
+Handle<Object> RegExpImpl::AtomExec(Handle<JSRegExp> re,
+                                    Handle<String> subject,
+                                    int index,
+                                    Handle<JSArray> last_match_info) {
+  Handle<String> needle(String::cast(re->DataAt(JSRegExp::kAtomPatternIndex)));
+
+  uint32_t start_index = index;
+
+  int value = Runtime::StringMatch(subject, needle, start_index);
+  if (value == -1) return Factory::null_value();
+  ASSERT(last_match_info->HasFastElements());
+
+  {
+    NoHandleAllocation no_handles;
+    FixedArray* array = last_match_info->elements();
+    SetAtomLastCapture(array, *subject, value, value + needle->length());
+  }
+  return last_match_info;
+}
+
+
+// Irregexp implementation.
+
+
+// Ensures that the regexp object contains a compiled version of the
+// source for either ASCII or non-ASCII strings.
+// If the compiled version doesn't already exist, it is compiled
+// from the source pattern.
+// If compilation fails, an exception is thrown and this function
+// returns false.
+bool RegExpImpl::EnsureCompiledIrregexp(Handle<JSRegExp> re, bool is_ascii) {
+  int index;
+  if (is_ascii) {
+    index = JSRegExp::kIrregexpASCIICodeIndex;
+  } else {
+    index = JSRegExp::kIrregexpUC16CodeIndex;
+  }
+  Object* entry = re->DataAt(index);
+  if (!entry->IsTheHole()) {
+    // A value has already been compiled.
+    if (entry->IsJSObject()) {
+      // If it's a JS value, it's an error.
+      Top::Throw(entry);
+      return false;
+    }
+    return true;
+  }
+
+  // Compile the RegExp.
+  ZoneScope zone_scope(DELETE_ON_EXIT);
+
+  JSRegExp::Flags flags = re->GetFlags();
+
+  Handle<String> pattern(re->Pattern());
+  if (!pattern->IsFlat()) {
+    FlattenString(pattern);
+  }
+
+  RegExpCompileData compile_data;
+  FlatStringReader reader(pattern);
+  if (!ParseRegExp(&reader, flags.is_multiline(), &compile_data)) {
+    // Throw an exception if we fail to parse the pattern.
+    // THIS SHOULD NOT HAPPEN. We already parsed it successfully once.
+    ThrowRegExpException(re,
+                         pattern,
+                         compile_data.error,
+                         "malformed_regexp");
+    return false;
+  }
+  RegExpEngine::CompilationResult result =
+      RegExpEngine::Compile(&compile_data,
+                            flags.is_ignore_case(),
+                            flags.is_multiline(),
+                            pattern,
+                            is_ascii);
+  if (result.error_message != NULL) {
+    // Unable to compile regexp.
+    Handle<JSArray> array = Factory::NewJSArray(2);
+    SetElement(array, 0, pattern);
+    SetElement(array,
+               1,
+               Factory::NewStringFromUtf8(CStrVector(result.error_message)));
+    Handle<Object> regexp_err =
+        Factory::NewSyntaxError("malformed_regexp", array);
+    Top::Throw(*regexp_err);
+    re->SetDataAt(index, *regexp_err);
+    return false;
+  }
+
+  NoHandleAllocation no_handles;
+
+  FixedArray* data = FixedArray::cast(re->data());
+  data->set(index, result.code);
+  int register_max = IrregexpMaxRegisterCount(data);
+  if (result.num_registers > register_max) {
+    SetIrregexpMaxRegisterCount(data, result.num_registers);
+  }
+
+  return true;
+}
+
+
+int RegExpImpl::IrregexpMaxRegisterCount(FixedArray* re) {
+  return Smi::cast(
+      re->get(JSRegExp::kIrregexpMaxRegisterCountIndex))->value();
+}
+
+
+void RegExpImpl::SetIrregexpMaxRegisterCount(FixedArray* re, int value) {
+  re->set(JSRegExp::kIrregexpMaxRegisterCountIndex, Smi::FromInt(value));
+}
+
+
+int RegExpImpl::IrregexpNumberOfCaptures(FixedArray* re) {
+  return Smi::cast(re->get(JSRegExp::kIrregexpCaptureCountIndex))->value();
+}
+
+
+int RegExpImpl::IrregexpNumberOfRegisters(FixedArray* re) {
+  return Smi::cast(re->get(JSRegExp::kIrregexpMaxRegisterCountIndex))->value();
+}
+
+
+ByteArray* RegExpImpl::IrregexpByteCode(FixedArray* re, bool is_ascii) {
+  int index;
+  if (is_ascii) {
+    index = JSRegExp::kIrregexpASCIICodeIndex;
+  } else {
+    index = JSRegExp::kIrregexpUC16CodeIndex;
+  }
+  return ByteArray::cast(re->get(index));
+}
+
+
+Code* RegExpImpl::IrregexpNativeCode(FixedArray* re, bool is_ascii) {
+  int index;
+  if (is_ascii) {
+    index = JSRegExp::kIrregexpASCIICodeIndex;
+  } else {
+    index = JSRegExp::kIrregexpUC16CodeIndex;
+  }
+  return Code::cast(re->get(index));
+}
+
+
+void RegExpImpl::IrregexpPrepare(Handle<JSRegExp> re,
+                                 Handle<String> pattern,
+                                 JSRegExp::Flags flags,
+                                 int capture_count) {
+  // Initialize compiled code entries to null.
+  Factory::SetRegExpIrregexpData(re,
+                                 JSRegExp::IRREGEXP,
+                                 pattern,
+                                 flags,
+                                 capture_count);
+}
+
+
+Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> jsregexp,
+                                        Handle<String> subject,
+                                        int previous_index,
+                                        Handle<JSArray> last_match_info) {
+  ASSERT_EQ(jsregexp->TypeTag(), JSRegExp::IRREGEXP);
+
+  // Prepare space for the return values.
+  int number_of_capture_registers =
+      (IrregexpNumberOfCaptures(FixedArray::cast(jsregexp->data())) + 1) * 2;
+  OffsetsVector offsets(number_of_capture_registers);
+
+#ifdef DEBUG
+  if (FLAG_trace_regexp_bytecodes) {
+    String* pattern = jsregexp->Pattern();
+    PrintF("\n\nRegexp match:   /%s/\n\n", *(pattern->ToCString()));
+    PrintF("\n\nSubject string: '%s'\n\n", *(subject->ToCString()));
+  }
+#endif
+
+  if (!subject->IsFlat()) {
+    FlattenString(subject);
+  }
+
+  last_match_info->EnsureSize(number_of_capture_registers + kLastMatchOverhead);
+
+  int* offsets_vector = offsets.vector();
+  bool rc;
+
+  // Dispatch to the correct RegExp implementation.
+
+  Handle<String> original_subject = subject;
+  Handle<FixedArray> regexp(FixedArray::cast(jsregexp->data()));
+  if (UseNativeRegexp()) {
+#ifdef ARM
+    UNREACHABLE();
+#else
+    RegExpMacroAssemblerIA32::Result res;
+    do {
+      bool is_ascii = StringShape(*subject).IsAsciiRepresentation();
+      if (!EnsureCompiledIrregexp(jsregexp, is_ascii)) {
+        return Handle<Object>::null();
+      }
+      Handle<Code> code(RegExpImpl::IrregexpNativeCode(*regexp, is_ascii));
+      res = RegExpMacroAssemblerIA32::Match(code,
+                                            subject,
+                                            offsets_vector,
+                                            offsets.length(),
+                                            previous_index);
+      // If result is RETRY, the string have changed representation, and we
+      // must restart from scratch.
+    } while (res == RegExpMacroAssemblerIA32::RETRY);
+    if (res == RegExpMacroAssemblerIA32::EXCEPTION) {
+      ASSERT(Top::has_pending_exception());
+      return Handle<Object>::null();
+    }
+    ASSERT(res == RegExpMacroAssemblerIA32::SUCCESS
+        || res == RegExpMacroAssemblerIA32::FAILURE);
+
+    rc = (res == RegExpMacroAssemblerIA32::SUCCESS);
+#endif
+  } else {
+    bool is_ascii = StringShape(*subject).IsAsciiRepresentation();
+    if (!EnsureCompiledIrregexp(jsregexp, is_ascii)) {
+      return Handle<Object>::null();
+    }
+    for (int i = number_of_capture_registers - 1; i >= 0; i--) {
+      offsets_vector[i] = -1;
+    }
+    Handle<ByteArray> byte_codes(IrregexpByteCode(*regexp, is_ascii));
+
+    rc = IrregexpInterpreter::Match(byte_codes,
+                                    subject,
+                                    offsets_vector,
+                                    previous_index);
+  }
+
+  // Handle results from RegExp implementation.
+
+  if (!rc) {
+    return Factory::null_value();
+  }
+
+  FixedArray* array = last_match_info->elements();
+  ASSERT(array->length() >= number_of_capture_registers + kLastMatchOverhead);
+  // The captures come in (start, end+1) pairs.
+  SetLastCaptureCount(array, number_of_capture_registers);
+  SetLastSubject(array, *original_subject);
+  SetLastInput(array, *original_subject);
+  for (int i = 0; i < number_of_capture_registers; i+=2) {
+    SetCapture(array, i, offsets_vector[i]);
+    SetCapture(array, i + 1, offsets_vector[i + 1]);
+  }
+  return last_match_info;
+}
+
+
+// -------------------------------------------------------------------
+// Implementation of the Irregexp regular expression engine.
+//
+// The Irregexp regular expression engine is intended to be a complete
+// implementation of ECMAScript regular expressions.  It generates either
+// bytecodes or native code.
+
+//   The Irregexp regexp engine is structured in three steps.
+//   1) The parser generates an abstract syntax tree.  See ast.cc.
+//   2) From the AST a node network is created.  The nodes are all
+//      subclasses of RegExpNode.  The nodes represent states when
+//      executing a regular expression.  Several optimizations are
+//      performed on the node network.
+//   3) From the nodes we generate either byte codes or native code
+//      that can actually execute the regular expression (perform
+//      the search).  The code generation step is described in more
+//      detail below.
+
+// Code generation.
+//
+//   The nodes are divided into four main categories.
+//   * Choice nodes
+//        These represent places where the regular expression can
+//        match in more than one way.  For example on entry to an
+//        alternation (foo|bar) or a repetition (*, +, ? or {}).
+//   * Action nodes
+//        These represent places where some action should be
+//        performed.  Examples include recording the current position
+//        in the input string to a register (in order to implement
+//        captures) or other actions on register for example in order
+//        to implement the counters needed for {} repetitions.
+//   * Matching nodes
+//        These attempt to match some element part of the input string.
+//        Examples of elements include character classes, plain strings
+//        or back references.
+//   * End nodes
+//        These are used to implement the actions required on finding
+//        a successful match or failing to find a match.
+//
+//   The code generated (whether as byte codes or native code) maintains
+//   some state as it runs.  This consists of the following elements:
+//
+//   * The capture registers.  Used for string captures.
+//   * Other registers.  Used for counters etc.
+//   * The current position.
+//   * The stack of backtracking information.  Used when a matching node
+//     fails to find a match and needs to try an alternative.
+//
+// Conceptual regular expression execution model:
+//
+//   There is a simple conceptual model of regular expression execution
+//   which will be presented first.  The actual code generated is a more
+//   efficient simulation of the simple conceptual model:
+//
+//   * Choice nodes are implemented as follows:
+//     For each choice except the last {
+//       push current position
+//       push backtrack code location
+//       <generate code to test for choice>
+//       backtrack code location:
+//       pop current position
+//     }
+//     <generate code to test for last choice>
+//
+//   * Actions nodes are generated as follows
+//     <push affected registers on backtrack stack>
+//     <generate code to perform action>
+//     push backtrack code location
+//     <generate code to test for following nodes>
+//     backtrack code location:
+//     <pop affected registers to restore their state>
+//     <pop backtrack location from stack and go to it>
+//
+//   * Matching nodes are generated as follows:
+//     if input string matches at current position
+//       update current position
+//       <generate code to test for following nodes>
+//     else
+//       <pop backtrack location from stack and go to it>
+//
+//   Thus it can be seen that the current position is saved and restored
+//   by the choice nodes, whereas the registers are saved and restored by
+//   by the action nodes that manipulate them.
+//
+//   The other interesting aspect of this model is that nodes are generated
+//   at the point where they are needed by a recursive call to Emit().  If
+//   the node has already been code generated then the Emit() call will
+//   generate a jump to the previously generated code instead.  In order to
+//   limit recursion it is possible for the Emit() function to put the node
+//   on a work list for later generation and instead generate a jump.  The
+//   destination of the jump is resolved later when the code is generated.
+//
+// Actual regular expression code generation.
+//
+//   Code generation is actually more complicated than the above.  In order
+//   to improve the efficiency of the generated code some optimizations are
+//   performed
+//
+//   * Choice nodes have 1-character lookahead.
+//     A choice node looks at the following character and eliminates some of
+//     the choices immediately based on that character.  This is not yet
+//     implemented.
+//   * Simple greedy loops store reduced backtracking information.
+//     A quantifier like /.*foo/m will greedily match the whole input.  It will
+//     then need to backtrack to a point where it can match "foo".  The naive
+//     implementation of this would push each character position onto the
+//     backtracking stack, then pop them off one by one.  This would use space
+//     proportional to the length of the input string.  However since the "."
+//     can only match in one way and always has a constant length (in this case
+//     of 1) it suffices to store the current position on the top of the stack
+//     once.  Matching now becomes merely incrementing the current position and
+//     backtracking becomes decrementing the current position and checking the
+//     result against the stored current position.  This is faster and saves
+//     space.
+//   * The current state is virtualized.
+//     This is used to defer expensive operations until it is clear that they
+//     are needed and to generate code for a node more than once, allowing
+//     specialized an efficient versions of the code to be created. This is
+//     explained in the section below.
+//
+// Execution state virtualization.
+//
+//   Instead of emitting code, nodes that manipulate the state can record their
+//   manipulation in an object called the Trace.  The Trace object can record a
+//   current position offset, an optional backtrack code location on the top of
+//   the virtualized backtrack stack and some register changes.  When a node is
+//   to be emitted it can flush the Trace or update it.  Flushing the Trace
+//   will emit code to bring the actual state into line with the virtual state.
+//   Avoiding flushing the state can postpone some work (eg updates of capture
+//   registers).  Postponing work can save time when executing the regular
+//   expression since it may be found that the work never has to be done as a
+//   failure to match can occur.  In addition it is much faster to jump to a
+//   known backtrack code location than it is to pop an unknown backtrack
+//   location from the stack and jump there.
+//
+//   The virtual state found in the Trace affects code generation.  For example
+//   the virtual state contains the difference between the actual current
+//   position and the virtual current position, and matching code needs to use
+//   this offset to attempt a match in the correct location of the input
+//   string.  Therefore code generated for a non-trivial trace is specialized
+//   to that trace.  The code generator therefore has the ability to generate
+//   code for each node several times.  In order to limit the size of the
+//   generated code there is an arbitrary limit on how many specialized sets of
+//   code may be generated for a given node.  If the limit is reached, the
+//   trace is flushed and a generic version of the code for a node is emitted.
+//   This is subsequently used for that node.  The code emitted for non-generic
+//   trace is not recorded in the node and so it cannot currently be reused in
+//   the event that code generation is requested for an identical trace.
+
+
+void RegExpTree::AppendToText(RegExpText* text) {
+  UNREACHABLE();
+}
+
+
+void RegExpAtom::AppendToText(RegExpText* text) {
+  text->AddElement(TextElement::Atom(this));
+}
+
+
+void RegExpCharacterClass::AppendToText(RegExpText* text) {
+  text->AddElement(TextElement::CharClass(this));
+}
+
+
+void RegExpText::AppendToText(RegExpText* text) {
+  for (int i = 0; i < elements()->length(); i++)
+    text->AddElement(elements()->at(i));
+}
+
+
+TextElement TextElement::Atom(RegExpAtom* atom) {
+  TextElement result = TextElement(ATOM);
+  result.data.u_atom = atom;
+  return result;
+}
+
+
+TextElement TextElement::CharClass(
+      RegExpCharacterClass* char_class) {
+  TextElement result = TextElement(CHAR_CLASS);
+  result.data.u_char_class = char_class;
+  return result;
+}
+
+
+int TextElement::length() {
+  if (type == ATOM) {
+    return data.u_atom->length();
+  } else {
+    ASSERT(type == CHAR_CLASS);
+    return 1;
+  }
+}
+
+
+DispatchTable* ChoiceNode::GetTable(bool ignore_case) {
+  if (table_ == NULL) {
+    table_ = new DispatchTable();
+    DispatchTableConstructor cons(table_, ignore_case);
+    cons.BuildTable(this);
+  }
+  return table_;
+}
+
+
+class RegExpCompiler {
+ public:
+  RegExpCompiler(int capture_count, bool ignore_case, bool is_ascii);
+
+  int AllocateRegister() {
+    if (next_register_ >= RegExpMacroAssembler::kMaxRegister) {
+      reg_exp_too_big_ = true;
+      return next_register_;
+    }
+    return next_register_++;
+  }
+
+  RegExpEngine::CompilationResult Assemble(RegExpMacroAssembler* assembler,
+                                           RegExpNode* start,
+                                           int capture_count,
+                                           Handle<String> pattern);
+
+  inline void AddWork(RegExpNode* node) { work_list_->Add(node); }
+
+  static const int kImplementationOffset = 0;
+  static const int kNumberOfRegistersOffset = 0;
+  static const int kCodeOffset = 1;
+
+  RegExpMacroAssembler* macro_assembler() { return macro_assembler_; }
+  EndNode* accept() { return accept_; }
+
+  static const int kMaxRecursion = 100;
+  inline int recursion_depth() { return recursion_depth_; }
+  inline void IncrementRecursionDepth() { recursion_depth_++; }
+  inline void DecrementRecursionDepth() { recursion_depth_--; }
+
+  void SetRegExpTooBig() { reg_exp_too_big_ = true; }
+
+  inline bool ignore_case() { return ignore_case_; }
+  inline bool ascii() { return ascii_; }
+
+  static const int kNoRegister = -1;
+ private:
+  EndNode* accept_;
+  int next_register_;
+  List<RegExpNode*>* work_list_;
+  int recursion_depth_;
+  RegExpMacroAssembler* macro_assembler_;
+  bool ignore_case_;
+  bool ascii_;
+  bool reg_exp_too_big_;
+};
+
+
+class RecursionCheck {
+ public:
+  explicit RecursionCheck(RegExpCompiler* compiler) : compiler_(compiler) {
+    compiler->IncrementRecursionDepth();
+  }
+  ~RecursionCheck() { compiler_->DecrementRecursionDepth(); }
+ private:
+  RegExpCompiler* compiler_;
+};
+
+
+static RegExpEngine::CompilationResult IrregexpRegExpTooBig() {
+  return RegExpEngine::CompilationResult("RegExp too big");
+}
+
+
+// Attempts to compile the regexp using an Irregexp code generator.  Returns
+// a fixed array or a null handle depending on whether it succeeded.
+RegExpCompiler::RegExpCompiler(int capture_count, bool ignore_case, bool ascii)
+    : next_register_(2 * (capture_count + 1)),
+      work_list_(NULL),
+      recursion_depth_(0),
+      ignore_case_(ignore_case),
+      ascii_(ascii),
+      reg_exp_too_big_(false) {
+  accept_ = new EndNode(EndNode::ACCEPT);
+  ASSERT(next_register_ - 1 <= RegExpMacroAssembler::kMaxRegister);
+}
+
+
+RegExpEngine::CompilationResult RegExpCompiler::Assemble(
+    RegExpMacroAssembler* macro_assembler,
+    RegExpNode* start,
+    int capture_count,
+    Handle<String> pattern) {
+#ifdef DEBUG
+  if (FLAG_trace_regexp_assembler)
+    macro_assembler_ = new RegExpMacroAssemblerTracer(macro_assembler);
+  else
+#endif
+    macro_assembler_ = macro_assembler;
+  List <RegExpNode*> work_list(0);
+  work_list_ = &work_list;
+  Label fail;
+  macro_assembler_->PushBacktrack(&fail);
+  Trace new_trace;
+  start->Emit(this, &new_trace);
+  macro_assembler_->Bind(&fail);
+  macro_assembler_->Fail();
+  while (!work_list.is_empty()) {
+    work_list.RemoveLast()->Emit(this, &new_trace);
+  }
+  if (reg_exp_too_big_) return IrregexpRegExpTooBig();
+
+  Handle<Object> code = macro_assembler_->GetCode(pattern);
+
+  work_list_ = NULL;
+#ifdef DEBUG
+  if (FLAG_trace_regexp_assembler) {
+    delete macro_assembler_;
+  }
+#endif
+  return RegExpEngine::CompilationResult(*code, next_register_);
+}
+
+
+bool Trace::DeferredAction::Mentions(int that) {
+  if (type() == ActionNode::CLEAR_CAPTURES) {
+    Interval range = static_cast<DeferredClearCaptures*>(this)->range();
+    return range.Contains(that);
+  } else {
+    return reg() == that;
+  }
+}
+
+
+bool Trace::mentions_reg(int reg) {
+  for (DeferredAction* action = actions_;
+       action != NULL;
+       action = action->next()) {
+    if (action->Mentions(reg))
+      return true;
+  }
+  return false;
+}
+
+
+bool Trace::GetStoredPosition(int reg, int* cp_offset) {
+  ASSERT_EQ(0, *cp_offset);
+  for (DeferredAction* action = actions_;
+       action != NULL;
+       action = action->next()) {
+    if (action->Mentions(reg)) {
+      if (action->type() == ActionNode::STORE_POSITION) {
+        *cp_offset = static_cast<DeferredCapture*>(action)->cp_offset();
+        return true;
+      } else {
+        return false;
+      }
+    }
+  }
+  return false;
+}
+
+
+int Trace::FindAffectedRegisters(OutSet* affected_registers) {
+  int max_register = RegExpCompiler::kNoRegister;
+  for (DeferredAction* action = actions_;
+       action != NULL;
+       action = action->next()) {
+    if (action->type() == ActionNode::CLEAR_CAPTURES) {
+      Interval range = static_cast<DeferredClearCaptures*>(action)->range();
+      for (int i = range.from(); i <= range.to(); i++)
+        affected_registers->Set(i);
+      if (range.to() > max_register) max_register = range.to();
+    } else {
+      affected_registers->Set(action->reg());
+      if (action->reg() > max_register) max_register = action->reg();
+    }
+  }
+  return max_register;
+}
+
+
+void Trace::RestoreAffectedRegisters(RegExpMacroAssembler* assembler,
+                                     int max_register,
+                                     OutSet& registers_to_pop,
+                                     OutSet& registers_to_clear) {
+  for (int reg = max_register; reg >= 0; reg--) {
+    if (registers_to_pop.Get(reg)) assembler->PopRegister(reg);
+    else if (registers_to_clear.Get(reg)) {
+      int clear_to = reg;
+      while (reg > 0 && registers_to_clear.Get(reg - 1)) {
+        reg--;
+      }
+      assembler->ClearRegisters(reg, clear_to);
+    }
+  }
+}
+
+
+void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler,
+                                   int max_register,
+                                   OutSet& affected_registers,
+                                   OutSet* registers_to_pop,
+                                   OutSet* registers_to_clear) {
+  // The "+1" is to avoid a push_limit of zero if stack_limit_slack() is 1.
+  const int push_limit = (assembler->stack_limit_slack() + 1) / 2;
+
+  for (int reg = 0; reg <= max_register; reg++) {
+    if (!affected_registers.Get(reg)) {
+      continue;
+    }
+    // Count pushes performed to force a stack limit check occasionally.
+    int pushes = 0;
+
+    // The chronologically first deferred action in the trace
+    // is used to infer the action needed to restore a register
+    // to its previous state (or not, if it's safe to ignore it).
+    enum DeferredActionUndoType { IGNORE, RESTORE, CLEAR };
+    DeferredActionUndoType undo_action = IGNORE;
+
+    int value = 0;
+    bool absolute = false;
+    bool clear = false;
+    int store_position = -1;
+    // This is a little tricky because we are scanning the actions in reverse
+    // historical order (newest first).
+    for (DeferredAction* action = actions_;
+         action != NULL;
+         action = action->next()) {
+      if (action->Mentions(reg)) {
+        switch (action->type()) {
+          case ActionNode::SET_REGISTER: {
+            Trace::DeferredSetRegister* psr =
+                static_cast<Trace::DeferredSetRegister*>(action);
+            if (!absolute) {
+              value += psr->value();
+              absolute = true;
+            }
+            // SET_REGISTER is currently only used for newly introduced loop
+            // counters. They can have a significant previous value if they
+            // occour in a loop. TODO(lrn): Propagate this information, so
+            // we can set undo_action to IGNORE if we know there is no value to
+            // restore.
+            undo_action = RESTORE;
+            ASSERT_EQ(store_position, -1);
+            ASSERT(!clear);
+            break;
+          }
+          case ActionNode::INCREMENT_REGISTER:
+            if (!absolute) {
+              value++;
+            }
+            ASSERT_EQ(store_position, -1);
+            ASSERT(!clear);
+            undo_action = RESTORE;
+            break;
+          case ActionNode::STORE_POSITION: {
+            Trace::DeferredCapture* pc =
+                static_cast<Trace::DeferredCapture*>(action);
+            if (!clear && store_position == -1) {
+              store_position = pc->cp_offset();
+            }
+
+            // For captures we know that stores and clears alternate.
+            // Other register, are never cleared, and if the occur
+            // inside a loop, they might be assigned more than once.
+            if (reg <= 1) {
+              // Registers zero and one, aka "capture zero", is
+              // always set correctly if we succeed. There is no
+              // need to undo a setting on backtrack, because we
+              // will set it again or fail.
+              undo_action = IGNORE;
+            } else {
+              undo_action = pc->is_capture() ? CLEAR : RESTORE;
+            }
+            ASSERT(!absolute);
+            ASSERT_EQ(value, 0);
+            break;
+          }
+          case ActionNode::CLEAR_CAPTURES: {
+            // Since we're scanning in reverse order, if we've already
+            // set the position we have to ignore historically earlier
+            // clearing operations.
+            if (store_position == -1) {
+              clear = true;
+            }
+            undo_action = RESTORE;
+            ASSERT(!absolute);
+            ASSERT_EQ(value, 0);
+            break;
+          }
+          default:
+            UNREACHABLE();
+            break;
+        }
+      }
+    }
+    // Prepare for the undo-action (e.g., push if it's going to be popped).
+    if (undo_action == RESTORE) {
+      pushes++;
+      RegExpMacroAssembler::StackCheckFlag stack_check =
+          RegExpMacroAssembler::kNoStackLimitCheck;
+      if (pushes == push_limit) {
+        stack_check = RegExpMacroAssembler::kCheckStackLimit;
+        pushes = 0;
+      }
+
+      assembler->PushRegister(reg, stack_check);
+      registers_to_pop->Set(reg);
+    } else if (undo_action == CLEAR) {
+      registers_to_clear->Set(reg);
+    }
+    // Perform the chronologically last action (or accumulated increment)
+    // for the register.
+    if (store_position != -1) {
+      assembler->WriteCurrentPositionToRegister(reg, store_position);
+    } else if (clear) {
+      assembler->ClearRegisters(reg, reg);
+    } else if (absolute) {
+      assembler->SetRegister(reg, value);
+    } else if (value != 0) {
+      assembler->AdvanceRegister(reg, value);
+    }
+  }
+}
+
+
+// This is called as we come into a loop choice node and some other tricky
+// nodes.  It normalizes the state of the code generator to ensure we can
+// generate generic code.
+void Trace::Flush(RegExpCompiler* compiler, RegExpNode* successor) {
+  RegExpMacroAssembler* assembler = compiler->macro_assembler();
+
+  ASSERT(!is_trivial());
+
+  if (actions_ == NULL && backtrack() == NULL) {
+    // Here we just have some deferred cp advances to fix and we are back to
+    // a normal situation.  We may also have to forget some information gained
+    // through a quick check that was already performed.
+    if (cp_offset_ != 0) assembler->AdvanceCurrentPosition(cp_offset_);
+    // Create a new trivial state and generate the node with that.
+    Trace new_state;
+    successor->Emit(compiler, &new_state);
+    return;
+  }
+
+  // Generate deferred actions here along with code to undo them again.
+  OutSet affected_registers;
+
+  if (backtrack() != NULL) {
+    // Here we have a concrete backtrack location.  These are set up by choice
+    // nodes and so they indicate that we have a deferred save of the current
+    // position which we may need to emit here.
+    assembler->PushCurrentPosition();
+  }
+
+  int max_register = FindAffectedRegisters(&affected_registers);
+  OutSet registers_to_pop;
+  OutSet registers_to_clear;
+  PerformDeferredActions(assembler,
+                         max_register,
+                         affected_registers,
+                         &registers_to_pop,
+                         &registers_to_clear);
+  if (cp_offset_ != 0) {
+    assembler->AdvanceCurrentPosition(cp_offset_);
+  }
+
+  // Create a new trivial state and generate the node with that.
+  Label undo;
+  assembler->PushBacktrack(&undo);
+  Trace new_state;
+  successor->Emit(compiler, &new_state);
+
+  // On backtrack we need to restore state.
+  assembler->Bind(&undo);
+  RestoreAffectedRegisters(assembler,
+                           max_register,
+                           registers_to_pop,
+                           registers_to_clear);
+  if (backtrack() == NULL) {
+    assembler->Backtrack();
+  } else {
+    assembler->PopCurrentPosition();
+    assembler->GoTo(backtrack());
+  }
+}
+
+
+void NegativeSubmatchSuccess::Emit(RegExpCompiler* compiler, Trace* trace) {
+  RegExpMacroAssembler* assembler = compiler->macro_assembler();
+
+  // Omit flushing the trace. We discard the entire stack frame anyway.
+
+  if (!label()->is_bound()) {
+    // We are completely independent of the trace, since we ignore it,
+    // so this code can be used as the generic version.
+    assembler->Bind(label());
+  }
+
+  // Throw away everything on the backtrack stack since the start
+  // of the negative submatch and restore the character position.
+  assembler->ReadCurrentPositionFromRegister(current_position_register_);
+  assembler->ReadStackPointerFromRegister(stack_pointer_register_);
+  if (clear_capture_count_ > 0) {
+    // Clear any captures that might have been performed during the success
+    // of the body of the negative look-ahead.
+    int clear_capture_end = clear_capture_start_ + clear_capture_count_ - 1;
+    assembler->ClearRegisters(clear_capture_start_, clear_capture_end);
+  }
+  // Now that we have unwound the stack we find at the top of the stack the
+  // backtrack that the BeginSubmatch node got.
+  assembler->Backtrack();
+}
+
+
+void EndNode::Emit(RegExpCompiler* compiler, Trace* trace) {
+  if (!trace->is_trivial()) {
+    trace->Flush(compiler, this);
+    return;
+  }
+  RegExpMacroAssembler* assembler = compiler->macro_assembler();
+  if (!label()->is_bound()) {
+    assembler->Bind(label());
+  }
+  switch (action_) {
+    case ACCEPT:
+      assembler->Succeed();
+      return;
+    case BACKTRACK:
+      assembler->GoTo(trace->backtrack());
+      return;
+    case NEGATIVE_SUBMATCH_SUCCESS:
+      // This case is handled in a different virtual method.
+      UNREACHABLE();
+  }
+  UNIMPLEMENTED();
+}
+
+
+void GuardedAlternative::AddGuard(Guard* guard) {
+  if (guards_ == NULL)
+    guards_ = new ZoneList<Guard*>(1);
+  guards_->Add(guard);
+}
+
+
+ActionNode* ActionNode::SetRegister(int reg,
+                                    int val,
+                                    RegExpNode* on_success) {
+  ActionNode* result = new ActionNode(SET_REGISTER, on_success);
+  result->data_.u_store_register.reg = reg;
+  result->data_.u_store_register.value = val;
+  return result;
+}
+
+
+ActionNode* ActionNode::IncrementRegister(int reg, RegExpNode* on_success) {
+  ActionNode* result = new ActionNode(INCREMENT_REGISTER, on_success);
+  result->data_.u_increment_register.reg = reg;
+  return result;
+}
+
+
+ActionNode* ActionNode::StorePosition(int reg,
+                                      bool is_capture,
+                                      RegExpNode* on_success) {
+  ActionNode* result = new ActionNode(STORE_POSITION, on_success);
+  result->data_.u_position_register.reg = reg;
+  result->data_.u_position_register.is_capture = is_capture;
+  return result;
+}
+
+
+ActionNode* ActionNode::ClearCaptures(Interval range,
+                                      RegExpNode* on_success) {
+  ActionNode* result = new ActionNode(CLEAR_CAPTURES, on_success);
+  result->data_.u_clear_captures.range_from = range.from();
+  result->data_.u_clear_captures.range_to = range.to();
+  return result;
+}
+
+
+ActionNode* ActionNode::BeginSubmatch(int stack_reg,
+                                      int position_reg,
+                                      RegExpNode* on_success) {
+  ActionNode* result = new ActionNode(BEGIN_SUBMATCH, on_success);
+  result->data_.u_submatch.stack_pointer_register = stack_reg;
+  result->data_.u_submatch.current_position_register = position_reg;
+  return result;
+}
+
+
+ActionNode* ActionNode::PositiveSubmatchSuccess(int stack_reg,
+                                                int position_reg,
+                                                int clear_register_count,
+                                                int clear_register_from,
+                                                RegExpNode* on_success) {
+  ActionNode* result = new ActionNode(POSITIVE_SUBMATCH_SUCCESS, on_success);
+  result->data_.u_submatch.stack_pointer_register = stack_reg;
+  result->data_.u_submatch.current_position_register = position_reg;
+  result->data_.u_submatch.clear_register_count = clear_register_count;
+  result->data_.u_submatch.clear_register_from = clear_register_from;
+  return result;
+}
+
+
+ActionNode* ActionNode::EmptyMatchCheck(int start_register,
+                                        int repetition_register,
+                                        int repetition_limit,
+                                        RegExpNode* on_success) {
+  ActionNode* result = new ActionNode(EMPTY_MATCH_CHECK, on_success);
+  result->data_.u_empty_match_check.start_register = start_register;
+  result->data_.u_empty_match_check.repetition_register = repetition_register;
+  result->data_.u_empty_match_check.repetition_limit = repetition_limit;
+  return result;
+}
+
+
+#define DEFINE_ACCEPT(Type)                                          \
+  void Type##Node::Accept(NodeVisitor* visitor) {                    \
+    visitor->Visit##Type(this);                                      \
+  }
+FOR_EACH_NODE_TYPE(DEFINE_ACCEPT)
+#undef DEFINE_ACCEPT
+
+
+void LoopChoiceNode::Accept(NodeVisitor* visitor) {
+  visitor->VisitLoopChoice(this);
+}
+
+
+// -------------------------------------------------------------------
+// Emit code.
+
+
+void ChoiceNode::GenerateGuard(RegExpMacroAssembler* macro_assembler,
+                               Guard* guard,
+                               Trace* trace) {
+  switch (guard->op()) {
+    case Guard::LT:
+      ASSERT(!trace->mentions_reg(guard->reg()));
+      macro_assembler->IfRegisterGE(guard->reg(),
+                                    guard->value(),
+                                    trace->backtrack());
+      break;
+    case Guard::GEQ:
+      ASSERT(!trace->mentions_reg(guard->reg()));
+      macro_assembler->IfRegisterLT(guard->reg(),
+                                    guard->value(),
+                                    trace->backtrack());
+      break;
+  }
+}
+
+
+static unibrow::Mapping<unibrow::Ecma262UnCanonicalize> uncanonicalize;
+static unibrow::Mapping<unibrow::CanonicalizationRange> canonrange;
+
+
+// Returns the number of characters in the equivalence class, omitting those
+// that cannot occur in the source string because it is ASCII.
+static int GetCaseIndependentLetters(uc16 character,
+                                     bool ascii_subject,
+                                     unibrow::uchar* letters) {
+  int length = uncanonicalize.get(character, '\0', letters);
+  // Unibrow returns 0 or 1 for characters where case independependence is
+  // trivial.
+  if (length == 0) {
+    letters[0] = character;
+    length = 1;
+  }
+  if (!ascii_subject || character <= String::kMaxAsciiCharCode) {
+    return length;
+  }
+  // The standard requires that non-ASCII characters cannot have ASCII
+  // character codes in their equivalence class.
+  return 0;
+}
+
+
+static inline bool EmitSimpleCharacter(RegExpCompiler* compiler,
+                                       uc16 c,
+                                       Label* on_failure,
+                                       int cp_offset,
+                                       bool check,
+                                       bool preloaded) {
+  RegExpMacroAssembler* assembler = compiler->macro_assembler();
+  bool bound_checked = false;
+  if (!preloaded) {
+    assembler->LoadCurrentCharacter(
+        cp_offset,
+        on_failure,
+        check);
+    bound_checked = true;
+  }
+  assembler->CheckNotCharacter(c, on_failure);
+  return bound_checked;
+}
+
+
+// Only emits non-letters (things that don't have case).  Only used for case
+// independent matches.
+static inline bool EmitAtomNonLetter(RegExpCompiler* compiler,
+                                     uc16 c,
+                                     Label* on_failure,
+                                     int cp_offset,
+                                     bool check,
+                                     bool preloaded) {
+  RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
+  bool ascii = compiler->ascii();
+  unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
+  int length = GetCaseIndependentLetters(c, ascii, chars);
+  if (length < 1) {
+    // This can't match.  Must be an ASCII subject and a non-ASCII character.
+    // We do not need to do anything since the ASCII pass already handled this.
+    return false;  // Bounds not checked.
+  }
+  bool checked = false;
+  // We handle the length > 1 case in a later pass.
+  if (length == 1) {
+    if (ascii && c > String::kMaxAsciiCharCodeU) {
+      // Can't match - see above.
+      return false;  // Bounds not checked.
+    }
+    if (!preloaded) {
+      macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check);
+      checked = check;
+    }
+    macro_assembler->CheckNotCharacter(c, on_failure);
+  }
+  return checked;
+}
+
+
+static bool ShortCutEmitCharacterPair(RegExpMacroAssembler* macro_assembler,
+                                      bool ascii,
+                                      uc16 c1,
+                                      uc16 c2,
+                                      Label* on_failure) {
+  uc16 char_mask;
+  if (ascii) {
+    char_mask = String::kMaxAsciiCharCode;
+  } else {
+    char_mask = String::kMaxUC16CharCode;
+  }
+  uc16 exor = c1 ^ c2;
+  // Check whether exor has only one bit set.
+  if (((exor - 1) & exor) == 0) {
+    // If c1 and c2 differ only by one bit.
+    // Ecma262UnCanonicalize always gives the highest number last.
+    ASSERT(c2 > c1);
+    uc16 mask = char_mask ^ exor;
+    macro_assembler->CheckNotCharacterAfterAnd(c1, mask, on_failure);
+    return true;
+  }
+  ASSERT(c2 > c1);
+  uc16 diff = c2 - c1;
+  if (((diff - 1) & diff) == 0 && c1 >= diff) {
+    // If the characters differ by 2^n but don't differ by one bit then
+    // subtract the difference from the found character, then do the or
+    // trick.  We avoid the theoretical case where negative numbers are
+    // involved in order to simplify code generation.
+    uc16 mask = char_mask ^ diff;
+    macro_assembler->CheckNotCharacterAfterMinusAnd(c1 - diff,
+                                                    diff,
+                                                    mask,
+                                                    on_failure);
+    return true;
+  }
+  return false;
+}
+
+
+typedef bool EmitCharacterFunction(RegExpCompiler* compiler,
+                                   uc16 c,
+                                   Label* on_failure,
+                                   int cp_offset,
+                                   bool check,
+                                   bool preloaded);
+
+// Only emits letters (things that have case).  Only used for case independent
+// matches.
+static inline bool EmitAtomLetter(RegExpCompiler* compiler,
+                                  uc16 c,
+                                  Label* on_failure,
+                                  int cp_offset,
+                                  bool check,
+                                  bool preloaded) {
+  RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
+  bool ascii = compiler->ascii();
+  unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
+  int length = GetCaseIndependentLetters(c, ascii, chars);
+  if (length <= 1) return false;
+  // We may not need to check against the end of the input string
+  // if this character lies before a character that matched.
+  if (!preloaded) {
+    macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check);
+  }
+  Label ok;
+  ASSERT(unibrow::Ecma262UnCanonicalize::kMaxWidth == 4);
+  switch (length) {
+    case 2: {
+      if (ShortCutEmitCharacterPair(macro_assembler,
+                                    ascii,
+                                    chars[0],
+                                    chars[1],
+                                    on_failure)) {
+      } else {
+        macro_assembler->CheckCharacter(chars[0], &ok);
+        macro_assembler->CheckNotCharacter(chars[1], on_failure);
+        macro_assembler->Bind(&ok);
+      }
+      break;
+    }
+    case 4:
+      macro_assembler->CheckCharacter(chars[3], &ok);
+      // Fall through!
+    case 3:
+      macro_assembler->CheckCharacter(chars[0], &ok);
+      macro_assembler->CheckCharacter(chars[1], &ok);
+      macro_assembler->CheckNotCharacter(chars[2], on_failure);
+      macro_assembler->Bind(&ok);
+      break;
+    default:
+      UNREACHABLE();
+      break;
+  }
+  return true;
+}
+
+
+static void EmitCharClass(RegExpMacroAssembler* macro_assembler,
+                          RegExpCharacterClass* cc,
+                          bool ascii,
+                          Label* on_failure,
+                          int cp_offset,
+                          bool check_offset,
+                          bool preloaded) {
+  if (cc->is_standard() &&
+      macro_assembler->CheckSpecialCharacterClass(cc->standard_type(),
+                                                  cp_offset,
+                                                  check_offset,
+                                                  on_failure)) {
+    return;
+  }
+
+  ZoneList<CharacterRange>* ranges = cc->ranges();
+  int max_char;
+  if (ascii) {
+    max_char = String::kMaxAsciiCharCode;
+  } else {
+    max_char = String::kMaxUC16CharCode;
+  }
+
+  Label success;
+
+  Label* char_is_in_class =
+      cc->is_negated() ? on_failure : &success;
+
+  int range_count = ranges->length();
+
+  int last_valid_range = range_count - 1;
+  while (last_valid_range >= 0) {
+    CharacterRange& range = ranges->at(last_valid_range);
+    if (range.from() <= max_char) {
+      break;
+    }
+    last_valid_range--;
+  }
+
+  if (last_valid_range < 0) {
+    if (!cc->is_negated()) {
+      // TODO(plesner): We can remove this when the node level does our
+      // ASCII optimizations for us.
+      macro_assembler->GoTo(on_failure);
+    }
+    if (check_offset) {
+      macro_assembler->CheckPosition(cp_offset, on_failure);
+    }
+    return;
+  }
+
+  if (last_valid_range == 0 &&
+      !cc->is_negated() &&
+      ranges->at(0).IsEverything(max_char)) {
+    // This is a common case hit by non-anchored expressions.
+    if (check_offset) {
+      macro_assembler->CheckPosition(cp_offset, on_failure);
+    }
+    return;
+  }
+
+  if (!preloaded) {
+    macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check_offset);
+  }
+
+  for (int i = 0; i < last_valid_range; i++) {
+    CharacterRange& range = ranges->at(i);
+    Label next_range;
+    uc16 from = range.from();
+    uc16 to = range.to();
+    if (from > max_char) {
+      continue;
+    }
+    if (to > max_char) to = max_char;
+    if (to == from) {
+      macro_assembler->CheckCharacter(to, char_is_in_class);
+    } else {
+      if (from != 0) {
+        macro_assembler->CheckCharacterLT(from, &next_range);
+      }
+      if (to != max_char) {
+        macro_assembler->CheckCharacterLT(to + 1, char_is_in_class);
+      } else {
+        macro_assembler->GoTo(char_is_in_class);
+      }
+    }
+    macro_assembler->Bind(&next_range);
+  }
+
+  CharacterRange& range = ranges->at(last_valid_range);
+  uc16 from = range.from();
+  uc16 to = range.to();
+
+  if (to > max_char) to = max_char;
+  ASSERT(to >= from);
+
+  if (to == from) {
+    if (cc->is_negated()) {
+      macro_assembler->CheckCharacter(to, on_failure);
+    } else {
+      macro_assembler->CheckNotCharacter(to, on_failure);
+    }
+  } else {
+    if (from != 0) {
+      if (cc->is_negated()) {
+        macro_assembler->CheckCharacterLT(from, &success);
+      } else {
+        macro_assembler->CheckCharacterLT(from, on_failure);
+      }
+    }
+    if (to != String::kMaxUC16CharCode) {
+      if (cc->is_negated()) {
+        macro_assembler->CheckCharacterLT(to + 1, on_failure);
+      } else {
+        macro_assembler->CheckCharacterGT(to, on_failure);
+      }
+    } else {
+      if (cc->is_negated()) {
+        macro_assembler->GoTo(on_failure);
+      }
+    }
+  }
+  macro_assembler->Bind(&success);
+}
+
+
+RegExpNode::~RegExpNode() {
+}
+
+
+RegExpNode::LimitResult RegExpNode::LimitVersions(RegExpCompiler* compiler,
+                                                  Trace* trace) {
+  // If we are generating a greedy loop then don't stop and don't reuse code.
+  if (trace->stop_node() != NULL) {
+    return CONTINUE;
+  }
+
+  RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
+  if (trace->is_trivial()) {
+    if (label_.is_bound()) {
+      // We are being asked to generate a generic version, but that's already
+      // been done so just go to it.
+      macro_assembler->GoTo(&label_);
+      return DONE;
+    }
+    if (compiler->recursion_depth() >= RegExpCompiler::kMaxRecursion) {
+      // To avoid too deep recursion we push the node to the work queue and just
+      // generate a goto here.
+      compiler->AddWork(this);
+      macro_assembler->GoTo(&label_);
+      return DONE;
+    }
+    // Generate generic version of the node and bind the label for later use.
+    macro_assembler->Bind(&label_);
+    return CONTINUE;
+  }
+
+  // We are being asked to make a non-generic version.  Keep track of how many
+  // non-generic versions we generate so as not to overdo it.
+  trace_count_++;
+  if (FLAG_regexp_optimization &&
+      trace_count_ < kMaxCopiesCodeGenerated &&
+      compiler->recursion_depth() <= RegExpCompiler::kMaxRecursion) {
+    return CONTINUE;
+  }
+
+  // If we get here code has been generated for this node too many times or
+  // recursion is too deep.  Time to switch to a generic version.  The code for
+  // generic versions above can handle deep recursion properly.
+  trace->Flush(compiler, this);
+  return DONE;
+}
+
+
+int ActionNode::EatsAtLeast(int still_to_find, int recursion_depth) {
+  if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0;
+  if (type_ == POSITIVE_SUBMATCH_SUCCESS) return 0;  // Rewinds input!
+  return on_success()->EatsAtLeast(still_to_find, recursion_depth + 1);
+}
+
+
+int AssertionNode::EatsAtLeast(int still_to_find, int recursion_depth) {
+  if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0;
+  return on_success()->EatsAtLeast(still_to_find, recursion_depth + 1);
+}
+
+
+int BackReferenceNode::EatsAtLeast(int still_to_find, int recursion_depth) {
+  if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0;
+  return on_success()->EatsAtLeast(still_to_find, recursion_depth + 1);
+}
+
+
+int TextNode::EatsAtLeast(int still_to_find, int recursion_depth) {
+  int answer = Length();
+  if (answer >= still_to_find) return answer;
+  if (recursion_depth > RegExpCompiler::kMaxRecursion) return answer;
+  return answer + on_success()->EatsAtLeast(still_to_find - answer,
+                                            recursion_depth + 1);
+}
+
+
+int NegativeLookaheadChoiceNode:: EatsAtLeast(int still_to_find,
+                                              int recursion_depth) {
+  if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0;
+  // Alternative 0 is the negative lookahead, alternative 1 is what comes
+  // afterwards.
+  RegExpNode* node = alternatives_->at(1).node();
+  return node->EatsAtLeast(still_to_find, recursion_depth + 1);
+}
+
+
+void NegativeLookaheadChoiceNode::GetQuickCheckDetails(
+    QuickCheckDetails* details,
+    RegExpCompiler* compiler,
+    int filled_in,
+    bool not_at_start) {
+  // Alternative 0 is the negative lookahead, alternative 1 is what comes
+  // afterwards.
+  RegExpNode* node = alternatives_->at(1).node();
+  return node->GetQuickCheckDetails(details, compiler, filled_in, not_at_start);
+}
+
+
+int ChoiceNode::EatsAtLeastHelper(int still_to_find,
+                                  int recursion_depth,
+                                  RegExpNode* ignore_this_node) {
+  if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0;
+  int min = 100;
+  int choice_count = alternatives_->length();
+  for (int i = 0; i < choice_count; i++) {
+    RegExpNode* node = alternatives_->at(i).node();
+    if (node == ignore_this_node) continue;
+    int node_eats_at_least = node->EatsAtLeast(still_to_find,
+                                               recursion_depth + 1);
+    if (node_eats_at_least < min) min = node_eats_at_least;
+  }
+  return min;
+}
+
+
+int LoopChoiceNode::EatsAtLeast(int still_to_find, int recursion_depth) {
+  return EatsAtLeastHelper(still_to_find, recursion_depth, loop_node_);
+}
+
+
+int ChoiceNode::EatsAtLeast(int still_to_find, int recursion_depth) {
+  return EatsAtLeastHelper(still_to_find, recursion_depth, NULL);
+}
+
+
+// Takes the left-most 1-bit and smears it out, setting all bits to its right.
+static inline uint32_t SmearBitsRight(uint32_t v) {
+  v |= v >> 1;
+  v |= v >> 2;
+  v |= v >> 4;
+  v |= v >> 8;
+  v |= v >> 16;
+  return v;
+}
+
+
+bool QuickCheckDetails::Rationalize(bool asc) {
+  bool found_useful_op = false;
+  uint32_t char_mask;
+  if (asc) {
+    char_mask = String::kMaxAsciiCharCode;
+  } else {
+    char_mask = String::kMaxUC16CharCode;
+  }
+  mask_ = 0;
+  value_ = 0;
+  int char_shift = 0;
+  for (int i = 0; i < characters_; i++) {
+    Position* pos = &positions_[i];
+    if ((pos->mask & String::kMaxAsciiCharCode) != 0) {
+      found_useful_op = true;
+    }
+    mask_ |= (pos->mask & char_mask) << char_shift;
+    value_ |= (pos->value & char_mask) << char_shift;
+    char_shift += asc ? 8 : 16;
+  }
+  return found_useful_op;
+}
+
+
+bool RegExpNode::EmitQuickCheck(RegExpCompiler* compiler,
+                                Trace* trace,
+                                bool preload_has_checked_bounds,
+                                Label* on_possible_success,
+                                QuickCheckDetails* details,
+                                bool fall_through_on_failure) {
+  if (details->characters() == 0) return false;
+  GetQuickCheckDetails(details, compiler, 0, trace->at_start() == Trace::FALSE);
+  if (details->cannot_match()) return false;
+  if (!details->Rationalize(compiler->ascii())) return false;
+  uint32_t mask = details->mask();
+  uint32_t value = details->value();
+
+  RegExpMacroAssembler* assembler = compiler->macro_assembler();
+
+  if (trace->characters_preloaded() != details->characters()) {
+    assembler->LoadCurrentCharacter(trace->cp_offset(),
+                                    trace->backtrack(),
+                                    !preload_has_checked_bounds,
+                                    details->characters());
+  }
+
+
+  bool need_mask = true;
+
+  if (details->characters() == 1) {
+    // If number of characters preloaded is 1 then we used a byte or 16 bit
+    // load so the value is already masked down.
+    uint32_t char_mask;
+    if (compiler->ascii()) {
+      char_mask = String::kMaxAsciiCharCode;
+    } else {
+      char_mask = String::kMaxUC16CharCode;
+    }
+    if ((mask & char_mask) == char_mask) need_mask = false;
+    mask &= char_mask;
+  } else {
+    // For 2-character preloads in ASCII mode we also use a 16 bit load with
+    // zero extend.
+    if (details->characters() == 2 && compiler->ascii()) {
+      if ((mask & 0xffff) == 0xffff) need_mask = false;
+    } else {
+      if (mask == 0xffffffff) need_mask = false;
+    }
+  }
+
+  if (fall_through_on_failure) {
+    if (need_mask) {
+      assembler->CheckCharacterAfterAnd(value, mask, on_possible_success);
+    } else {
+      assembler->CheckCharacter(value, on_possible_success);
+    }
+  } else {
+    if (need_mask) {
+      assembler->CheckNotCharacterAfterAnd(value, mask, trace->backtrack());
+    } else {
+      assembler->CheckNotCharacter(value, trace->backtrack());
+    }
+  }
+  return true;
+}
+
+
+// Here is the meat of GetQuickCheckDetails (see also the comment on the
+// super-class in the .h file).
+//
+// We iterate along the text object, building up for each character a
+// mask and value that can be used to test for a quick failure to match.
+// The masks and values for the positions will be combined into a single
+// machine word for the current character width in order to be used in
+// generating a quick check.
+void TextNode::GetQuickCheckDetails(QuickCheckDetails* details,
+                                    RegExpCompiler* compiler,
+                                    int characters_filled_in,
+                                    bool not_at_start) {
+  ASSERT(characters_filled_in < details->characters());
+  int characters = details->characters();
+  int char_mask;
+  int char_shift;
+  if (compiler->ascii()) {
+    char_mask = String::kMaxAsciiCharCode;
+    char_shift = 8;
+  } else {
+    char_mask = String::kMaxUC16CharCode;
+    char_shift = 16;
+  }
+  for (int k = 0; k < elms_->length(); k++) {
+    TextElement elm = elms_->at(k);
+    if (elm.type == TextElement::ATOM) {
+      Vector<const uc16> quarks = elm.data.u_atom->data();
+      for (int i = 0; i < characters && i < quarks.length(); i++) {
+        QuickCheckDetails::Position* pos =
+            details->positions(characters_filled_in);
+        uc16 c = quarks[i];
+        if (c > char_mask) {
+          // If we expect a non-ASCII character from an ASCII string,
+          // there is no way we can match. Not even case independent
+          // matching can turn an ASCII character into non-ASCII or
+          // vice versa.
+          details->set_cannot_match();
+          pos->determines_perfectly = false;
+          return;
+        }
+        if (compiler->ignore_case()) {
+          unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
+          int length = GetCaseIndependentLetters(c, compiler->ascii(), chars);
+          ASSERT(length != 0);  // Can only happen if c > char_mask (see above).
+          if (length == 1) {
+            // This letter has no case equivalents, so it's nice and simple
+            // and the mask-compare will determine definitely whether we have
+            // a match at this character position.
+            pos->mask = char_mask;
+            pos->value = c;
+            pos->determines_perfectly = true;
+          } else {
+            uint32_t common_bits = char_mask;
+            uint32_t bits = chars[0];
+            for (int j = 1; j < length; j++) {
+              uint32_t differing_bits = ((chars[j] & common_bits) ^ bits);
+              common_bits ^= differing_bits;
+              bits &= common_bits;
+            }
+            // If length is 2 and common bits has only one zero in it then
+            // our mask and compare instruction will determine definitely
+            // whether we have a match at this character position.  Otherwise
+            // it can only be an approximate check.
+            uint32_t one_zero = (common_bits | ~char_mask);
+            if (length == 2 && ((~one_zero) & ((~one_zero) - 1)) == 0) {
+              pos->determines_perfectly = true;
+            }
+            pos->mask = common_bits;
+            pos->value = bits;
+          }
+        } else {
+          // Don't ignore case.  Nice simple case where the mask-compare will
+          // determine definitely whether we have a match at this character
+          // position.
+          pos->mask = char_mask;
+          pos->value = c;
+          pos->determines_perfectly = true;
+        }
+        characters_filled_in++;
+        ASSERT(characters_filled_in <= details->characters());
+        if (characters_filled_in == details->characters()) {
+          return;
+        }
+      }
+    } else {
+      QuickCheckDetails::Position* pos =
+          details->positions(characters_filled_in);
+      RegExpCharacterClass* tree = elm.data.u_char_class;
+      ZoneList<CharacterRange>* ranges = tree->ranges();
+      if (tree->is_negated()) {
+        // A quick check uses multi-character mask and compare.  There is no
+        // useful way to incorporate a negative char class into this scheme
+        // so we just conservatively create a mask and value that will always
+        // succeed.
+        pos->mask = 0;
+        pos->value = 0;
+      } else {
+        int first_range = 0;
+        while (ranges->at(first_range).from() > char_mask) {
+          first_range++;
+          if (first_range == ranges->length()) {
+            details->set_cannot_match();
+            pos->determines_perfectly = false;
+            return;
+          }
+        }
+        CharacterRange range = ranges->at(first_range);
+        uc16 from = range.from();
+        uc16 to = range.to();
+        if (to > char_mask) {
+          to = char_mask;
+        }
+        uint32_t differing_bits = (from ^ to);
+        // A mask and compare is only perfect if the differing bits form a
+        // number like 00011111 with one single block of trailing 1s.
+        if ((differing_bits & (differing_bits + 1)) == 0) {
+          pos->determines_perfectly = true;
+        }
+        uint32_t common_bits = ~SmearBitsRight(differing_bits);
+        uint32_t bits = (from & common_bits);
+        for (int i = first_range + 1; i < ranges->length(); i++) {
+          CharacterRange range = ranges->at(i);
+          uc16 from = range.from();
+          uc16 to = range.to();
+          if (from > char_mask) continue;
+          if (to > char_mask) to = char_mask;
+          // Here we are combining more ranges into the mask and compare
+          // value.  With each new range the mask becomes more sparse and
+          // so the chances of a false positive rise.  A character class
+          // with multiple ranges is assumed never to be equivalent to a
+          // mask and compare operation.
+          pos->determines_perfectly = false;
+          uint32_t new_common_bits = (from ^ to);
+          new_common_bits = ~SmearBitsRight(new_common_bits);
+          common_bits &= new_common_bits;
+          bits &= new_common_bits;
+          uint32_t differing_bits = (from & common_bits) ^ bits;
+          common_bits ^= differing_bits;
+          bits &= common_bits;
+        }
+        pos->mask = common_bits;
+        pos->value = bits;
+      }
+      characters_filled_in++;
+      ASSERT(characters_filled_in <= details->characters());
+      if (characters_filled_in == details->characters()) {
+        return;
+      }
+    }
+  }
+  ASSERT(characters_filled_in != details->characters());
+  on_success()-> GetQuickCheckDetails(details,
+                                      compiler,
+                                      characters_filled_in,
+                                      true);
+}
+
+
+void QuickCheckDetails::Clear() {
+  for (int i = 0; i < characters_; i++) {
+    positions_[i].mask = 0;
+    positions_[i].value = 0;
+    positions_[i].determines_perfectly = false;
+  }
+  characters_ = 0;
+}
+
+
+void QuickCheckDetails::Advance(int by, bool ascii) {
+  ASSERT(by >= 0);
+  if (by >= characters_) {
+    Clear();
+    return;
+  }
+  for (int i = 0; i < characters_ - by; i++) {
+    positions_[i] = positions_[by + i];
+  }
+  for (int i = characters_ - by; i < characters_; i++) {
+    positions_[i].mask = 0;
+    positions_[i].value = 0;
+    positions_[i].determines_perfectly = false;
+  }
+  characters_ -= by;
+  // We could change mask_ and value_ here but we would never advance unless
+  // they had already been used in a check and they won't be used again because
+  // it would gain us nothing.  So there's no point.
+}
+
+
+void QuickCheckDetails::Merge(QuickCheckDetails* other, int from_index) {
+  ASSERT(characters_ == other->characters_);
+  if (other->cannot_match_) {
+    return;
+  }
+  if (cannot_match_) {
+    *this = *other;
+    return;
+  }
+  for (int i = from_index; i < characters_; i++) {
+    QuickCheckDetails::Position* pos = positions(i);
+    QuickCheckDetails::Position* other_pos = other->positions(i);
+    if (pos->mask != other_pos->mask ||
+        pos->value != other_pos->value ||
+        !other_pos->determines_perfectly) {
+      // Our mask-compare operation will be approximate unless we have the
+      // exact same operation on both sides of the alternation.
+      pos->determines_perfectly = false;
+    }
+    pos->mask &= other_pos->mask;
+    pos->value &= pos->mask;
+    other_pos->value &= pos->mask;
+    uc16 differing_bits = (pos->value ^ other_pos->value);
+    pos->mask &= ~differing_bits;
+    pos->value &= pos->mask;
+  }
+}
+
+
+class VisitMarker {
+ public:
+  explicit VisitMarker(NodeInfo* info) : info_(info) {
+    ASSERT(!info->visited);
+    info->visited = true;
+  }
+  ~VisitMarker() {
+    info_->visited = false;
+  }
+ private:
+  NodeInfo* info_;
+};
+
+
+void LoopChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details,
+                                          RegExpCompiler* compiler,
+                                          int characters_filled_in,
+                                          bool not_at_start) {
+  if (body_can_be_zero_length_ || info()->visited) return;
+  VisitMarker marker(info());
+  return ChoiceNode::GetQuickCheckDetails(details,
+                                          compiler,
+                                          characters_filled_in,
+                                          not_at_start);
+}
+
+
+void ChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details,
+                                      RegExpCompiler* compiler,
+                                      int characters_filled_in,
+                                      bool not_at_start) {
+  not_at_start = (not_at_start || not_at_start_);
+  int choice_count = alternatives_->length();
+  ASSERT(choice_count > 0);
+  alternatives_->at(0).node()->GetQuickCheckDetails(details,
+                                                    compiler,
+                                                    characters_filled_in,
+                                                    not_at_start);
+  for (int i = 1; i < choice_count; i++) {
+    QuickCheckDetails new_details(details->characters());
+    RegExpNode* node = alternatives_->at(i).node();
+    node->GetQuickCheckDetails(&new_details, compiler,
+                               characters_filled_in,
+                               not_at_start);
+    // Here we merge the quick match details of the two branches.
+    details->Merge(&new_details, characters_filled_in);
+  }
+}
+
+
+// Check for [0-9A-Z_a-z].
+static void EmitWordCheck(RegExpMacroAssembler* assembler,
+                          Label* word,
+                          Label* non_word,
+                          bool fall_through_on_word) {
+  assembler->CheckCharacterGT('z', non_word);
+  assembler->CheckCharacterLT('0', non_word);
+  assembler->CheckCharacterGT('a' - 1, word);
+  assembler->CheckCharacterLT('9' + 1, word);
+  assembler->CheckCharacterLT('A', non_word);
+  assembler->CheckCharacterLT('Z' + 1, word);
+  if (fall_through_on_word) {
+    assembler->CheckNotCharacter('_', non_word);
+  } else {
+    assembler->CheckCharacter('_', word);
+  }
+}
+
+
+// Emit the code to check for a ^ in multiline mode (1-character lookbehind
+// that matches newline or the start of input).
+static void EmitHat(RegExpCompiler* compiler,
+                    RegExpNode* on_success,
+                    Trace* trace) {
+  RegExpMacroAssembler* assembler = compiler->macro_assembler();
+  // We will be loading the previous character into the current character
+  // register.
+  Trace new_trace(*trace);
+  new_trace.InvalidateCurrentCharacter();
+
+  Label ok;
+  if (new_trace.cp_offset() == 0) {
+    // The start of input counts as a newline in this context, so skip to
+    // ok if we are at the start.
+    assembler->CheckAtStart(&ok);
+  }
+  // We already checked that we are not at the start of input so it must be
+  // OK to load the previous character.
+  assembler->LoadCurrentCharacter(new_trace.cp_offset() -1,
+                                  new_trace.backtrack(),
+                                  false);
+  // Newline means \n, \r, 0x2028 or 0x2029.
+  if (!compiler->ascii()) {
+    assembler->CheckCharacterAfterAnd(0x2028, 0xfffe, &ok);
+  }
+  assembler->CheckCharacter('\n', &ok);
+  assembler->CheckNotCharacter('\r', new_trace.backtrack());
+  assembler->Bind(&ok);
+  on_success->Emit(compiler, &new_trace);
+}
+
+
+// Emit the code to handle \b and \B (word-boundary or non-word-boundary).
+static void EmitBoundaryCheck(AssertionNode::AssertionNodeType type,
+                              RegExpCompiler* compiler,
+                              RegExpNode* on_success,
+                              Trace* trace) {
+  RegExpMacroAssembler* assembler = compiler->macro_assembler();
+  Label before_non_word;
+  Label before_word;
+  if (trace->characters_preloaded() != 1) {
+    assembler->LoadCurrentCharacter(trace->cp_offset(), &before_non_word);
+  }
+  // Fall through on non-word.
+  EmitWordCheck(assembler, &before_word, &before_non_word, false);
+
+  // We will be loading the previous character into the current character
+  // register.
+  Trace new_trace(*trace);
+  new_trace.InvalidateCurrentCharacter();
+
+  Label ok;
+  Label* boundary;
+  Label* not_boundary;
+  if (type == AssertionNode::AT_BOUNDARY) {
+    boundary = &ok;
+    not_boundary = new_trace.backtrack();
+  } else {
+    not_boundary = &ok;
+    boundary = new_trace.backtrack();
+  }
+
+  // Next character is not a word character.
+  assembler->Bind(&before_non_word);
+  if (new_trace.cp_offset() == 0) {
+    // The start of input counts as a non-word character, so the question is
+    // decided if we are at the start.
+    assembler->CheckAtStart(not_boundary);
+  }
+  // We already checked that we are not at the start of input so it must be
+  // OK to load the previous character.
+  assembler->LoadCurrentCharacter(new_trace.cp_offset() - 1,
+                                  &ok,  // Unused dummy label in this call.
+                                  false);
+  // Fall through on non-word.
+  EmitWordCheck(assembler, boundary, not_boundary, false);
+  assembler->GoTo(not_boundary);
+
+  // Next character is a word character.
+  assembler->Bind(&before_word);
+  if (new_trace.cp_offset() == 0) {
+    // The start of input counts as a non-word character, so the question is
+    // decided if we are at the start.
+    assembler->CheckAtStart(boundary);
+  }
+  // We already checked that we are not at the start of input so it must be
+  // OK to load the previous character.
+  assembler->LoadCurrentCharacter(new_trace.cp_offset() - 1,
+                                  &ok,  // Unused dummy label in this call.
+                                  false);
+  bool fall_through_on_word = (type == AssertionNode::AT_NON_BOUNDARY);
+  EmitWordCheck(assembler, not_boundary, boundary, fall_through_on_word);
+
+  assembler->Bind(&ok);
+
+  on_success->Emit(compiler, &new_trace);
+}
+
+
+void AssertionNode::GetQuickCheckDetails(QuickCheckDetails* details,
+                                         RegExpCompiler* compiler,
+                                         int filled_in,
+                                         bool not_at_start) {
+  if (type_ == AT_START && not_at_start) {
+    details->set_cannot_match();
+    return;
+  }
+  return on_success()->GetQuickCheckDetails(details,
+                                            compiler,
+                                            filled_in,
+                                            not_at_start);
+}
+
+
+void AssertionNode::Emit(RegExpCompiler* compiler, Trace* trace) {
+  RegExpMacroAssembler* assembler = compiler->macro_assembler();
+  switch (type_) {
+    case AT_END: {
+      Label ok;
+      assembler->CheckPosition(trace->cp_offset(), &ok);
+      assembler->GoTo(trace->backtrack());
+      assembler->Bind(&ok);
+      break;
+    }
+    case AT_START: {
+      if (trace->at_start() == Trace::FALSE) {
+        assembler->GoTo(trace->backtrack());
+        return;
+      }
+      if (trace->at_start() == Trace::UNKNOWN) {
+        assembler->CheckNotAtStart(trace->backtrack());
+        Trace at_start_trace = *trace;
+        at_start_trace.set_at_start(true);
+        on_success()->Emit(compiler, &at_start_trace);
+        return;
+      }
+    }
+    break;
+    case AFTER_NEWLINE:
+      EmitHat(compiler, on_success(), trace);
+      return;
+    case AT_NON_BOUNDARY:
+    case AT_BOUNDARY:
+      EmitBoundaryCheck(type_, compiler, on_success(), trace);
+      return;
+  }
+  on_success()->Emit(compiler, trace);
+}
+
+
+static bool DeterminedAlready(QuickCheckDetails* quick_check, int offset) {
+  if (quick_check == NULL) return false;
+  if (offset >= quick_check->characters()) return false;
+  return quick_check->positions(offset)->determines_perfectly;
+}
+
+
+static void UpdateBoundsCheck(int index, int* checked_up_to) {
+  if (index > *checked_up_to) {
+    *checked_up_to = index;
+  }
+}
+
+
+// We call this repeatedly to generate code for each pass over the text node.
+// The passes are in increasing order of difficulty because we hope one
+// of the first passes will fail in which case we are saved the work of the
+// later passes.  for example for the case independent regexp /%[asdfghjkl]a/
+// we will check the '%' in the first pass, the case independent 'a' in the
+// second pass and the character class in the last pass.
+//
+// The passes are done from right to left, so for example to test for /bar/
+// we will first test for an 'r' with offset 2, then an 'a' with offset 1
+// and then a 'b' with offset 0.  This means we can avoid the end-of-input
+// bounds check most of the time.  In the example we only need to check for
+// end-of-input when loading the putative 'r'.
+//
+// A slight complication involves the fact that the first character may already
+// be fetched into a register by the previous node.  In this case we want to
+// do the test for that character first.  We do this in separate passes.  The
+// 'preloaded' argument indicates that we are doing such a 'pass'.  If such a
+// pass has been performed then subsequent passes will have true in
+// first_element_checked to indicate that that character does not need to be
+// checked again.
+//
+// In addition to all this we are passed a Trace, which can
+// contain an AlternativeGeneration object.  In this AlternativeGeneration
+// object we can see details of any quick check that was already passed in
+// order to get to the code we are now generating.  The quick check can involve
+// loading characters, which means we do not need to recheck the bounds
+// up to the limit the quick check already checked.  In addition the quick
+// check can have involved a mask and compare operation which may simplify
+// or obviate the need for further checks at some character positions.
+void TextNode::TextEmitPass(RegExpCompiler* compiler,
+                            TextEmitPassType pass,
+                            bool preloaded,
+                            Trace* trace,
+                            bool first_element_checked,
+                            int* checked_up_to) {
+  RegExpMacroAssembler* assembler = compiler->macro_assembler();
+  bool ascii = compiler->ascii();
+  Label* backtrack = trace->backtrack();
+  QuickCheckDetails* quick_check = trace->quick_check_performed();
+  int element_count = elms_->length();
+  for (int i = preloaded ? 0 : element_count - 1; i >= 0; i--) {
+    TextElement elm = elms_->at(i);
+    int cp_offset = trace->cp_offset() + elm.cp_offset;
+    if (elm.type == TextElement::ATOM) {
+      Vector<const uc16> quarks = elm.data.u_atom->data();
+      for (int j = preloaded ? 0 : quarks.length() - 1; j >= 0; j--) {
+        if (first_element_checked && i == 0 && j == 0) continue;
+        if (DeterminedAlready(quick_check, elm.cp_offset + j)) continue;
+        EmitCharacterFunction* emit_function = NULL;
+        switch (pass) {
+          case NON_ASCII_MATCH:
+            ASSERT(ascii);
+            if (quarks[j] > String::kMaxAsciiCharCode) {
+              assembler->GoTo(backtrack);
+              return;
+            }
+            break;
+          case NON_LETTER_CHARACTER_MATCH:
+            emit_function = &EmitAtomNonLetter;
+            break;
+          case SIMPLE_CHARACTER_MATCH:
+            emit_function = &EmitSimpleCharacter;
+            break;
+          case CASE_CHARACTER_MATCH:
+            emit_function = &EmitAtomLetter;
+            break;
+          default:
+            break;
+        }
+        if (emit_function != NULL) {
+          bool bound_checked = emit_function(compiler,
+                                             quarks[j],
+                                             backtrack,
+                                             cp_offset + j,
+                                             *checked_up_to < cp_offset + j,
+                                             preloaded);
+          if (bound_checked) UpdateBoundsCheck(cp_offset + j, checked_up_to);
+        }
+      }
+    } else {
+      ASSERT_EQ(elm.type, TextElement::CHAR_CLASS);
+      if (pass == CHARACTER_CLASS_MATCH) {
+        if (first_element_checked && i == 0) continue;
+        if (DeterminedAlready(quick_check, elm.cp_offset)) continue;
+        RegExpCharacterClass* cc = elm.data.u_char_class;
+        EmitCharClass(assembler,
+                      cc,
+                      ascii,
+                      backtrack,
+                      cp_offset,
+                      *checked_up_to < cp_offset,
+                      preloaded);
+        UpdateBoundsCheck(cp_offset, checked_up_to);
+      }
+    }
+  }
+}
+
+
+int TextNode::Length() {
+  TextElement elm = elms_->last();
+  ASSERT(elm.cp_offset >= 0);
+  if (elm.type == TextElement::ATOM) {
+    return elm.cp_offset + elm.data.u_atom->data().length();
+  } else {
+    return elm.cp_offset + 1;
+  }
+}
+
+
+bool TextNode::SkipPass(int int_pass, bool ignore_case) {
+  TextEmitPassType pass = static_cast<TextEmitPassType>(int_pass);
+  if (ignore_case) {
+    return pass == SIMPLE_CHARACTER_MATCH;
+  } else {
+    return pass == NON_LETTER_CHARACTER_MATCH || pass == CASE_CHARACTER_MATCH;
+  }
+}
+
+
+// This generates the code to match a text node.  A text node can contain
+// straight character sequences (possibly to be matched in a case-independent
+// way) and character classes.  For efficiency we do not do this in a single
+// pass from left to right.  Instead we pass over the text node several times,
+// emitting code for some character positions every time.  See the comment on
+// TextEmitPass for details.
+void TextNode::Emit(RegExpCompiler* compiler, Trace* trace) {
+  LimitResult limit_result = LimitVersions(compiler, trace);
+  if (limit_result == DONE) return;
+  ASSERT(limit_result == CONTINUE);
+
+  if (trace->cp_offset() + Length() > RegExpMacroAssembler::kMaxCPOffset) {
+    compiler->SetRegExpTooBig();
+    return;
+  }
+
+  if (compiler->ascii()) {
+    int dummy = 0;
+    TextEmitPass(compiler, NON_ASCII_MATCH, false, trace, false, &dummy);
+  }
+
+  bool first_elt_done = false;
+  int bound_checked_to = trace->cp_offset() - 1;
+  bound_checked_to += trace->bound_checked_up_to();
+
+  // If a character is preloaded into the current character register then
+  // check that now.
+  if (trace->characters_preloaded() == 1) {
+    for (int pass = kFirstRealPass; pass <= kLastPass; pass++) {
+      if (!SkipPass(pass, compiler->ignore_case())) {
+        TextEmitPass(compiler,
+                     static_cast<TextEmitPassType>(pass),
+                     true,
+                     trace,
+                     false,
+                     &bound_checked_to);
+      }
+    }
+    first_elt_done = true;
+  }
+
+  for (int pass = kFirstRealPass; pass <= kLastPass; pass++) {
+    if (!SkipPass(pass, compiler->ignore_case())) {
+      TextEmitPass(compiler,
+                   static_cast<TextEmitPassType>(pass),
+                   false,
+                   trace,
+                   first_elt_done,
+                   &bound_checked_to);
+    }
+  }
+
+  Trace successor_trace(*trace);
+  successor_trace.set_at_start(false);
+  successor_trace.AdvanceCurrentPositionInTrace(Length(), compiler);
+  RecursionCheck rc(compiler);
+  on_success()->Emit(compiler, &successor_trace);
+}
+
+
+void Trace::InvalidateCurrentCharacter() {
+  characters_preloaded_ = 0;
+}
+
+
+void Trace::AdvanceCurrentPositionInTrace(int by, RegExpCompiler* compiler) {
+  ASSERT(by > 0);
+  // We don't have an instruction for shifting the current character register
+  // down or for using a shifted value for anything so lets just forget that
+  // we preloaded any characters into it.
+  characters_preloaded_ = 0;
+  // Adjust the offsets of the quick check performed information.  This
+  // information is used to find out what we already determined about the
+  // characters by means of mask and compare.
+  quick_check_performed_.Advance(by, compiler->ascii());
+  cp_offset_ += by;
+  if (cp_offset_ > RegExpMacroAssembler::kMaxCPOffset) {
+    compiler->SetRegExpTooBig();
+    cp_offset_ = 0;
+  }
+  bound_checked_up_to_ = Max(0, bound_checked_up_to_ - by);
+}
+
+
+void TextNode::MakeCaseIndependent() {
+  int element_count = elms_->length();
+  for (int i = 0; i < element_count; i++) {
+    TextElement elm = elms_->at(i);
+    if (elm.type == TextElement::CHAR_CLASS) {
+      RegExpCharacterClass* cc = elm.data.u_char_class;
+      ZoneList<CharacterRange>* ranges = cc->ranges();
+      int range_count = ranges->length();
+      for (int i = 0; i < range_count; i++) {
+        ranges->at(i).AddCaseEquivalents(ranges);
+      }
+    }
+  }
+}
+
+
+int TextNode::GreedyLoopTextLength() {
+  TextElement elm = elms_->at(elms_->length() - 1);
+  if (elm.type == TextElement::CHAR_CLASS) {
+    return elm.cp_offset + 1;
+  } else {
+    return elm.cp_offset + elm.data.u_atom->data().length();
+  }
+}
+
+
+// Finds the fixed match length of a sequence of nodes that goes from
+// this alternative and back to this choice node.  If there are variable
+// length nodes or other complications in the way then return a sentinel
+// value indicating that a greedy loop cannot be constructed.
+int ChoiceNode::GreedyLoopTextLength(GuardedAlternative* alternative) {
+  int length = 0;
+  RegExpNode* node = alternative->node();
+  // Later we will generate code for all these text nodes using recursion
+  // so we have to limit the max number.
+  int recursion_depth = 0;
+  while (node != this) {
+    if (recursion_depth++ > RegExpCompiler::kMaxRecursion) {
+      return kNodeIsTooComplexForGreedyLoops;
+    }
+    int node_length = node->GreedyLoopTextLength();
+    if (node_length == kNodeIsTooComplexForGreedyLoops) {
+      return kNodeIsTooComplexForGreedyLoops;
+    }
+    length += node_length;
+    SeqRegExpNode* seq_node = static_cast<SeqRegExpNode*>(node);
+    node = seq_node->on_success();
+  }
+  return length;
+}
+
+
+void LoopChoiceNode::AddLoopAlternative(GuardedAlternative alt) {
+  ASSERT_EQ(loop_node_, NULL);
+  AddAlternative(alt);
+  loop_node_ = alt.node();
+}
+
+
+void LoopChoiceNode::AddContinueAlternative(GuardedAlternative alt) {
+  ASSERT_EQ(continue_node_, NULL);
+  AddAlternative(alt);
+  continue_node_ = alt.node();
+}
+
+
+void LoopChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
+  RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
+  if (trace->stop_node() == this) {
+    int text_length = GreedyLoopTextLength(&(alternatives_->at(0)));
+    ASSERT(text_length != kNodeIsTooComplexForGreedyLoops);
+    // Update the counter-based backtracking info on the stack.  This is an
+    // optimization for greedy loops (see below).
+    ASSERT(trace->cp_offset() == text_length);
+    macro_assembler->AdvanceCurrentPosition(text_length);
+    macro_assembler->GoTo(trace->loop_label());
+    return;
+  }
+  ASSERT(trace->stop_node() == NULL);
+  if (!trace->is_trivial()) {
+    trace->Flush(compiler, this);
+    return;
+  }
+  ChoiceNode::Emit(compiler, trace);
+}
+
+
+int ChoiceNode::CalculatePreloadCharacters(RegExpCompiler* compiler) {
+  int preload_characters = EatsAtLeast(4, 0);
+#ifdef CAN_READ_UNALIGNED
+  bool ascii = compiler->ascii();
+  if (ascii) {
+    if (preload_characters > 4) preload_characters = 4;
+    // We can't preload 3 characters because there is no machine instruction
+    // to do that.  We can't just load 4 because we could be reading
+    // beyond the end of the string, which could cause a memory fault.
+    if (preload_characters == 3) preload_characters = 2;
+  } else {
+    if (preload_characters > 2) preload_characters = 2;
+  }
+#else
+  if (preload_characters > 1) preload_characters = 1;
+#endif
+  return preload_characters;
+}
+
+
+// This class is used when generating the alternatives in a choice node.  It
+// records the way the alternative is being code generated.
+class AlternativeGeneration: public Malloced {
+ public:
+  AlternativeGeneration()
+      : possible_success(),
+        expects_preload(false),
+        after(),
+        quick_check_details() { }
+  Label possible_success;
+  bool expects_preload;
+  Label after;
+  QuickCheckDetails quick_check_details;
+};
+
+
+// Creates a list of AlternativeGenerations.  If the list has a reasonable
+// size then it is on the stack, otherwise the excess is on the heap.
+class AlternativeGenerationList {
+ public:
+  explicit AlternativeGenerationList(int count)
+      : alt_gens_(count) {
+    for (int i = 0; i < count && i < kAFew; i++) {
+      alt_gens_.Add(a_few_alt_gens_ + i);
+    }
+    for (int i = kAFew; i < count; i++) {
+      alt_gens_.Add(new AlternativeGeneration());
+    }
+  }
+  ~AlternativeGenerationList() {
+    for (int i = kAFew; i < alt_gens_.length(); i++) {
+      delete alt_gens_[i];
+      alt_gens_[i] = NULL;
+    }
+  }
+
+  AlternativeGeneration* at(int i) {
+    return alt_gens_[i];
+  }
+ private:
+  static const int kAFew = 10;
+  ZoneList<AlternativeGeneration*> alt_gens_;
+  AlternativeGeneration a_few_alt_gens_[kAFew];
+};
+
+
+/* Code generation for choice nodes.
+ *
+ * We generate quick checks that do a mask and compare to eliminate a
+ * choice.  If the quick check succeeds then it jumps to the continuation to
+ * do slow checks and check subsequent nodes.  If it fails (the common case)
+ * it falls through to the next choice.
+ *
+ * Here is the desired flow graph.  Nodes directly below each other imply
+ * fallthrough.  Alternatives 1 and 2 have quick checks.  Alternative
+ * 3 doesn't have a quick check so we have to call the slow check.
+ * Nodes are marked Qn for quick checks and Sn for slow checks.  The entire
+ * regexp continuation is generated directly after the Sn node, up to the
+ * next GoTo if we decide to reuse some already generated code.  Some
+ * nodes expect preload_characters to be preloaded into the current
+ * character register.  R nodes do this preloading.  Vertices are marked
+ * F for failures and S for success (possible success in the case of quick
+ * nodes).  L, V, < and > are used as arrow heads.
+ *
+ * ----------> R
+ *             |
+ *             V
+ *            Q1 -----> S1
+ *             |   S   /
+ *            F|      /
+ *             |    F/
+ *             |    /
+ *             |   R
+ *             |  /
+ *             V L
+ *            Q2 -----> S2
+ *             |   S   /
+ *            F|      /
+ *             |    F/
+ *             |    /
+ *             |   R
+ *             |  /
+ *             V L
+ *            S3
+ *             |
+ *            F|
+ *             |
+ *             R
+ *             |
+ * backtrack   V
+ * <----------Q4
+ *   \    F    |
+ *    \        |S
+ *     \   F   V
+ *      \-----S4
+ *
+ * For greedy loops we reverse our expectation and expect to match rather
+ * than fail. Therefore we want the loop code to look like this (U is the
+ * unwind code that steps back in the greedy loop).  The following alternatives
+ * look the same as above.
+ *              _____
+ *             /     \
+ *             V     |
+ * ----------> S1    |
+ *            /|     |
+ *           / |S    |
+ *         F/  \_____/
+ *         /
+ *        |<-----------
+ *        |            \
+ *        V             \
+ *        Q2 ---> S2     \
+ *        |  S   /       |
+ *       F|     /        |
+ *        |   F/         |
+ *        |   /          |
+ *        |  R           |
+ *        | /            |
+ *   F    VL             |
+ * <------U              |
+ * back   |S             |
+ *        \______________/
+ */
+
+
+void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
+  RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
+  int choice_count = alternatives_->length();
+#ifdef DEBUG
+  for (int i = 0; i < choice_count - 1; i++) {
+    GuardedAlternative alternative = alternatives_->at(i);
+    ZoneList<Guard*>* guards = alternative.guards();
+    int guard_count = (guards == NULL) ? 0 : guards->length();
+    for (int j = 0; j < guard_count; j++) {
+      ASSERT(!trace->mentions_reg(guards->at(j)->reg()));
+    }
+  }
+#endif
+
+  LimitResult limit_result = LimitVersions(compiler, trace);
+  if (limit_result == DONE) return;
+  ASSERT(limit_result == CONTINUE);
+
+  int new_flush_budget = trace->flush_budget() / choice_count;
+  if (trace->flush_budget() == 0 && trace->actions() != NULL) {
+    trace->Flush(compiler, this);
+    return;
+  }
+
+  RecursionCheck rc(compiler);
+
+  Trace* current_trace = trace;
+
+  int text_length = GreedyLoopTextLength(&(alternatives_->at(0)));
+  bool greedy_loop = false;
+  Label greedy_loop_label;
+  Trace counter_backtrack_trace;
+  counter_backtrack_trace.set_backtrack(&greedy_loop_label);
+  if (not_at_start()) counter_backtrack_trace.set_at_start(false);
+
+  if (choice_count > 1 && text_length != kNodeIsTooComplexForGreedyLoops) {
+    // Here we have special handling for greedy loops containing only text nodes
+    // and other simple nodes.  These are handled by pushing the current
+    // position on the stack and then incrementing the current position each
+    // time around the switch.  On backtrack we decrement the current position
+    // and check it against the pushed value.  This avoids pushing backtrack
+    // information for each iteration of the loop, which could take up a lot of
+    // space.
+    greedy_loop = true;
+    ASSERT(trace->stop_node() == NULL);
+    macro_assembler->PushCurrentPosition();
+    current_trace = &counter_backtrack_trace;
+    Label greedy_match_failed;
+    Trace greedy_match_trace;
+    if (not_at_start()) greedy_match_trace.set_at_start(false);
+    greedy_match_trace.set_backtrack(&greedy_match_failed);
+    Label loop_label;
+    macro_assembler->Bind(&loop_label);
+    greedy_match_trace.set_stop_node(this);
+    greedy_match_trace.set_loop_label(&loop_label);
+    alternatives_->at(0).node()->Emit(compiler, &greedy_match_trace);
+    macro_assembler->Bind(&greedy_match_failed);
+  }
+
+  Label second_choice;  // For use in greedy matches.
+  macro_assembler->Bind(&second_choice);
+
+  int first_normal_choice = greedy_loop ? 1 : 0;
+
+  int preload_characters = CalculatePreloadCharacters(compiler);
+  bool preload_is_current =
+      (current_trace->characters_preloaded() == preload_characters);
+  bool preload_has_checked_bounds = preload_is_current;
+
+  AlternativeGenerationList alt_gens(choice_count);
+
+  // For now we just call all choices one after the other.  The idea ultimately
+  // is to use the Dispatch table to try only the relevant ones.
+  for (int i = first_normal_choice; i < choice_count; i++) {
+    GuardedAlternative alternative = alternatives_->at(i);
+    AlternativeGeneration* alt_gen = alt_gens.at(i);
+    alt_gen->quick_check_details.set_characters(preload_characters);
+    ZoneList<Guard*>* guards = alternative.guards();
+    int guard_count = (guards == NULL) ? 0 : guards->length();
+    Trace new_trace(*current_trace);
+    new_trace.set_characters_preloaded(preload_is_current ?
+                                         preload_characters :
+                                         0);
+    if (preload_has_checked_bounds) {
+      new_trace.set_bound_checked_up_to(preload_characters);
+    }
+    new_trace.quick_check_performed()->Clear();
+    if (not_at_start_) new_trace.set_at_start(Trace::FALSE);
+    alt_gen->expects_preload = preload_is_current;
+    bool generate_full_check_inline = false;
+    if (FLAG_regexp_optimization &&
+        try_to_emit_quick_check_for_alternative(i) &&
+        alternative.node()->EmitQuickCheck(compiler,
+                                           &new_trace,
+                                           preload_has_checked_bounds,
+                                           &alt_gen->possible_success,
+                                           &alt_gen->quick_check_details,
+                                           i < choice_count - 1)) {
+      // Quick check was generated for this choice.
+      preload_is_current = true;
+      preload_has_checked_bounds = true;
+      // On the last choice in the ChoiceNode we generated the quick
+      // check to fall through on possible success.  So now we need to
+      // generate the full check inline.
+      if (i == choice_count - 1) {
+        macro_assembler->Bind(&alt_gen->possible_success);
+        new_trace.set_quick_check_performed(&alt_gen->quick_check_details);
+        new_trace.set_characters_preloaded(preload_characters);
+        new_trace.set_bound_checked_up_to(preload_characters);
+        generate_full_check_inline = true;
+      }
+    } else if (alt_gen->quick_check_details.cannot_match()) {
+      if (i == choice_count - 1 && !greedy_loop) {
+        macro_assembler->GoTo(trace->backtrack());
+      }
+      continue;
+    } else {
+      // No quick check was generated.  Put the full code here.
+      // If this is not the first choice then there could be slow checks from
+      // previous cases that go here when they fail.  There's no reason to
+      // insist that they preload characters since the slow check we are about
+      // to generate probably can't use it.
+      if (i != first_normal_choice) {
+        alt_gen->expects_preload = false;
+        new_trace.set_characters_preloaded(0);
+      }
+      if (i < choice_count - 1) {
+        new_trace.set_backtrack(&alt_gen->after);
+      }
+      generate_full_check_inline = true;
+    }
+    if (generate_full_check_inline) {
+      if (new_trace.actions() != NULL) {
+        new_trace.set_flush_budget(new_flush_budget);
+      }
+      for (int j = 0; j < guard_count; j++) {
+        GenerateGuard(macro_assembler, guards->at(j), &new_trace);
+      }
+      alternative.node()->Emit(compiler, &new_trace);
+      preload_is_current = false;
+    }
+    macro_assembler->Bind(&alt_gen->after);
+  }
+  if (greedy_loop) {
+    macro_assembler->Bind(&greedy_loop_label);
+    // If we have unwound to the bottom then backtrack.
+    macro_assembler->CheckGreedyLoop(trace->backtrack());
+    // Otherwise try the second priority at an earlier position.
+    macro_assembler->AdvanceCurrentPosition(-text_length);
+    macro_assembler->GoTo(&second_choice);
+  }
+
+  // At this point we need to generate slow checks for the alternatives where
+  // the quick check was inlined.  We can recognize these because the associated
+  // label was bound.
+  for (int i = first_normal_choice; i < choice_count - 1; i++) {
+    AlternativeGeneration* alt_gen = alt_gens.at(i);
+    Trace new_trace(*current_trace);
+    // If there are actions to be flushed we have to limit how many times
+    // they are flushed.  Take the budget of the parent trace and distribute
+    // it fairly amongst the children.
+    if (new_trace.actions() != NULL) {
+      new_trace.set_flush_budget(new_flush_budget);
+    }
+    EmitOutOfLineContinuation(compiler,
+                              &new_trace,
+                              alternatives_->at(i),
+                              alt_gen,
+                              preload_characters,
+                              alt_gens.at(i + 1)->expects_preload);
+  }
+}
+
+
+void ChoiceNode::EmitOutOfLineContinuation(RegExpCompiler* compiler,
+                                           Trace* trace,
+                                           GuardedAlternative alternative,
+                                           AlternativeGeneration* alt_gen,
+                                           int preload_characters,
+                                           bool next_expects_preload) {
+  if (!alt_gen->possible_success.is_linked()) return;
+
+  RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
+  macro_assembler->Bind(&alt_gen->possible_success);
+  Trace out_of_line_trace(*trace);
+  out_of_line_trace.set_characters_preloaded(preload_characters);
+  out_of_line_trace.set_quick_check_performed(&alt_gen->quick_check_details);
+  if (not_at_start_) out_of_line_trace.set_at_start(Trace::FALSE);
+  ZoneList<Guard*>* guards = alternative.guards();
+  int guard_count = (guards == NULL) ? 0 : guards->length();
+  if (next_expects_preload) {
+    Label reload_current_char;
+    out_of_line_trace.set_backtrack(&reload_current_char);
+    for (int j = 0; j < guard_count; j++) {
+      GenerateGuard(macro_assembler, guards->at(j), &out_of_line_trace);
+    }
+    alternative.node()->Emit(compiler, &out_of_line_trace);
+    macro_assembler->Bind(&reload_current_char);
+    // Reload the current character, since the next quick check expects that.
+    // We don't need to check bounds here because we only get into this
+    // code through a quick check which already did the checked load.
+    macro_assembler->LoadCurrentCharacter(trace->cp_offset(),
+                                          NULL,
+                                          false,
+                                          preload_characters);
+    macro_assembler->GoTo(&(alt_gen->after));
+  } else {
+    out_of_line_trace.set_backtrack(&(alt_gen->after));
+    for (int j = 0; j < guard_count; j++) {
+      GenerateGuard(macro_assembler, guards->at(j), &out_of_line_trace);
+    }
+    alternative.node()->Emit(compiler, &out_of_line_trace);
+  }
+}
+
+
+void ActionNode::Emit(RegExpCompiler* compiler, Trace* trace) {
+  RegExpMacroAssembler* assembler = compiler->macro_assembler();
+  LimitResult limit_result = LimitVersions(compiler, trace);
+  if (limit_result == DONE) return;
+  ASSERT(limit_result == CONTINUE);
+
+  RecursionCheck rc(compiler);
+
+  switch (type_) {
+    case STORE_POSITION: {
+      Trace::DeferredCapture
+          new_capture(data_.u_position_register.reg,
+                      data_.u_position_register.is_capture,
+                      trace);
+      Trace new_trace = *trace;
+      new_trace.add_action(&new_capture);
+      on_success()->Emit(compiler, &new_trace);
+      break;
+    }
+    case INCREMENT_REGISTER: {
+      Trace::DeferredIncrementRegister
+          new_increment(data_.u_increment_register.reg);
+      Trace new_trace = *trace;
+      new_trace.add_action(&new_increment);
+      on_success()->Emit(compiler, &new_trace);
+      break;
+    }
+    case SET_REGISTER: {
+      Trace::DeferredSetRegister
+          new_set(data_.u_store_register.reg, data_.u_store_register.value);
+      Trace new_trace = *trace;
+      new_trace.add_action(&new_set);
+      on_success()->Emit(compiler, &new_trace);
+      break;
+    }
+    case CLEAR_CAPTURES: {
+      Trace::DeferredClearCaptures
+        new_capture(Interval(data_.u_clear_captures.range_from,
+                             data_.u_clear_captures.range_to));
+      Trace new_trace = *trace;
+      new_trace.add_action(&new_capture);
+      on_success()->Emit(compiler, &new_trace);
+      break;
+    }
+    case BEGIN_SUBMATCH:
+      if (!trace->is_trivial()) {
+        trace->Flush(compiler, this);
+      } else {
+        assembler->WriteCurrentPositionToRegister(
+            data_.u_submatch.current_position_register, 0);
+        assembler->WriteStackPointerToRegister(
+            data_.u_submatch.stack_pointer_register);
+        on_success()->Emit(compiler, trace);
+      }
+      break;
+    case EMPTY_MATCH_CHECK: {
+      int start_pos_reg = data_.u_empty_match_check.start_register;
+      int stored_pos = 0;
+      int rep_reg = data_.u_empty_match_check.repetition_register;
+      bool has_minimum = (rep_reg != RegExpCompiler::kNoRegister);
+      bool know_dist = trace->GetStoredPosition(start_pos_reg, &stored_pos);
+      if (know_dist && !has_minimum && stored_pos == trace->cp_offset()) {
+        // If we know we haven't advanced and there is no minimum we
+        // can just backtrack immediately.
+        assembler->GoTo(trace->backtrack());
+      } else if (know_dist && stored_pos < trace->cp_offset()) {
+        // If we know we've advanced we can generate the continuation
+        // immediately.
+        on_success()->Emit(compiler, trace);
+      } else if (!trace->is_trivial()) {
+        trace->Flush(compiler, this);
+      } else {
+        Label skip_empty_check;
+        // If we have a minimum number of repetitions we check the current
+        // number first and skip the empty check if it's not enough.
+        if (has_minimum) {
+          int limit = data_.u_empty_match_check.repetition_limit;
+          assembler->IfRegisterLT(rep_reg, limit, &skip_empty_check);
+        }
+        // If the match is empty we bail out, otherwise we fall through
+        // to the on-success continuation.
+        assembler->IfRegisterEqPos(data_.u_empty_match_check.start_register,
+                                   trace->backtrack());
+        assembler->Bind(&skip_empty_check);
+        on_success()->Emit(compiler, trace);
+      }
+      break;
+    }
+    case POSITIVE_SUBMATCH_SUCCESS: {
+      if (!trace->is_trivial()) {
+        trace->Flush(compiler, this);
+        return;
+      }
+      assembler->ReadCurrentPositionFromRegister(
+          data_.u_submatch.current_position_register);
+      assembler->ReadStackPointerFromRegister(
+          data_.u_submatch.stack_pointer_register);
+      int clear_register_count = data_.u_submatch.clear_register_count;
+      if (clear_register_count == 0) {
+        on_success()->Emit(compiler, trace);
+        return;
+      }
+      int clear_registers_from = data_.u_submatch.clear_register_from;
+      Label clear_registers_backtrack;
+      Trace new_trace = *trace;
+      new_trace.set_backtrack(&clear_registers_backtrack);
+      on_success()->Emit(compiler, &new_trace);
+
+      assembler->Bind(&clear_registers_backtrack);
+      int clear_registers_to = clear_registers_from + clear_register_count - 1;
+      assembler->ClearRegisters(clear_registers_from, clear_registers_to);
+
+      ASSERT(trace->backtrack() == NULL);
+      assembler->Backtrack();
+      return;
+    }
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void BackReferenceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
+  RegExpMacroAssembler* assembler = compiler->macro_assembler();
+  if (!trace->is_trivial()) {
+    trace->Flush(compiler, this);
+    return;
+  }
+
+  LimitResult limit_result = LimitVersions(compiler, trace);
+  if (limit_result == DONE) return;
+  ASSERT(limit_result == CONTINUE);
+
+  RecursionCheck rc(compiler);
+
+  ASSERT_EQ(start_reg_ + 1, end_reg_);
+  if (compiler->ignore_case()) {
+    assembler->CheckNotBackReferenceIgnoreCase(start_reg_,
+                                               trace->backtrack());
+  } else {
+    assembler->CheckNotBackReference(start_reg_, trace->backtrack());
+  }
+  on_success()->Emit(compiler, trace);
+}
+
+
+// -------------------------------------------------------------------
+// Dot/dotty output
+
+
+#ifdef DEBUG
+
+
+class DotPrinter: public NodeVisitor {
+ public:
+  explicit DotPrinter(bool ignore_case)
+      : ignore_case_(ignore_case),
+        stream_(&alloc_) { }
+  void PrintNode(const char* label, RegExpNode* node);
+  void Visit(RegExpNode* node);
+  void PrintAttributes(RegExpNode* from);
+  StringStream* stream() { return &stream_; }
+  void PrintOnFailure(RegExpNode* from, RegExpNode* to);
+#define DECLARE_VISIT(Type)                                          \
+  virtual void Visit##Type(Type##Node* that);
+FOR_EACH_NODE_TYPE(DECLARE_VISIT)
+#undef DECLARE_VISIT
+ private:
+  bool ignore_case_;
+  HeapStringAllocator alloc_;
+  StringStream stream_;
+};
+
+
+void DotPrinter::PrintNode(const char* label, RegExpNode* node) {
+  stream()->Add("digraph G {\n  graph [label=\"");
+  for (int i = 0; label[i]; i++) {
+    switch (label[i]) {
+      case '\\':
+        stream()->Add("\\\\");
+        break;
+      case '"':
+        stream()->Add("\"");
+        break;
+      default:
+        stream()->Put(label[i]);
+        break;
+    }
+  }
+  stream()->Add("\"];\n");
+  Visit(node);
+  stream()->Add("}\n");
+  printf("%s", *(stream()->ToCString()));
+}
+
+
+void DotPrinter::Visit(RegExpNode* node) {
+  if (node->info()->visited) return;
+  node->info()->visited = true;
+  node->Accept(this);
+}
+
+
+void DotPrinter::PrintOnFailure(RegExpNode* from, RegExpNode* on_failure) {
+  stream()->Add("  n%p -> n%p [style=dotted];\n", from, on_failure);
+  Visit(on_failure);
+}
+
+
+class TableEntryBodyPrinter {
+ public:
+  TableEntryBodyPrinter(StringStream* stream, ChoiceNode* choice)
+      : stream_(stream), choice_(choice) { }
+  void Call(uc16 from, DispatchTable::Entry entry) {
+    OutSet* out_set = entry.out_set();
+    for (unsigned i = 0; i < OutSet::kFirstLimit; i++) {
+      if (out_set->Get(i)) {
+        stream()->Add("    n%p:s%io%i -> n%p;\n",
+                      choice(),
+                      from,
+                      i,
+                      choice()->alternatives()->at(i).node());
+      }
+    }
+  }
+ private:
+  StringStream* stream() { return stream_; }
+  ChoiceNode* choice() { return choice_; }
+  StringStream* stream_;
+  ChoiceNode* choice_;
+};
+
+
+class TableEntryHeaderPrinter {
+ public:
+  explicit TableEntryHeaderPrinter(StringStream* stream)
+      : first_(true), stream_(stream) { }
+  void Call(uc16 from, DispatchTable::Entry entry) {
+    if (first_) {
+      first_ = false;
+    } else {
+      stream()->Add("|");
+    }
+    stream()->Add("{\\%k-\\%k|{", from, entry.to());
+    OutSet* out_set = entry.out_set();
+    int priority = 0;
+    for (unsigned i = 0; i < OutSet::kFirstLimit; i++) {
+      if (out_set->Get(i)) {
+        if (priority > 0) stream()->Add("|");
+        stream()->Add("<s%io%i> %i", from, i, priority);
+        priority++;
+      }
+    }
+    stream()->Add("}}");
+  }
+ private:
+  bool first_;
+  StringStream* stream() { return stream_; }
+  StringStream* stream_;
+};
+
+
+class AttributePrinter {
+ public:
+  explicit AttributePrinter(DotPrinter* out)
+      : out_(out), first_(true) { }
+  void PrintSeparator() {
+    if (first_) {
+      first_ = false;
+    } else {
+      out_->stream()->Add("|");
+    }
+  }
+  void PrintBit(const char* name, bool value) {
+    if (!value) return;
+    PrintSeparator();
+    out_->stream()->Add("{%s}", name);
+  }
+  void PrintPositive(const char* name, int value) {
+    if (value < 0) return;
+    PrintSeparator();
+    out_->stream()->Add("{%s|%x}", name, value);
+  }
+ private:
+  DotPrinter* out_;
+  bool first_;
+};
+
+
+void DotPrinter::PrintAttributes(RegExpNode* that) {
+  stream()->Add("  a%p [shape=Mrecord, color=grey, fontcolor=grey, "
+                "margin=0.1, fontsize=10, label=\"{",
+                that);
+  AttributePrinter printer(this);
+  NodeInfo* info = that->info();
+  printer.PrintBit("NI", info->follows_newline_interest);
+  printer.PrintBit("WI", info->follows_word_interest);
+  printer.PrintBit("SI", info->follows_start_interest);
+  Label* label = that->label();
+  if (label->is_bound())
+    printer.PrintPositive("@", label->pos());
+  stream()->Add("}\"];\n");
+  stream()->Add("  a%p -> n%p [style=dashed, color=grey, "
+                "arrowhead=none];\n", that, that);
+}
+
+
+static const bool kPrintDispatchTable = false;
+void DotPrinter::VisitChoice(ChoiceNode* that) {
+  if (kPrintDispatchTable) {
+    stream()->Add("  n%p [shape=Mrecord, label=\"", that);
+    TableEntryHeaderPrinter header_printer(stream());
+    that->GetTable(ignore_case_)->ForEach(&header_printer);
+    stream()->Add("\"]\n", that);
+    PrintAttributes(that);
+    TableEntryBodyPrinter body_printer(stream(), that);
+    that->GetTable(ignore_case_)->ForEach(&body_printer);
+  } else {
+    stream()->Add("  n%p [shape=Mrecord, label=\"?\"];\n", that);
+    for (int i = 0; i < that->alternatives()->length(); i++) {
+      GuardedAlternative alt = that->alternatives()->at(i);
+      stream()->Add("  n%p -> n%p;\n", that, alt.node());
+    }
+  }
+  for (int i = 0; i < that->alternatives()->length(); i++) {
+    GuardedAlternative alt = that->alternatives()->at(i);
+    alt.node()->Accept(this);
+  }
+}
+
+
+void DotPrinter::VisitText(TextNode* that) {
+  stream()->Add("  n%p [label=\"", that);
+  for (int i = 0; i < that->elements()->length(); i++) {
+    if (i > 0) stream()->Add(" ");
+    TextElement elm = that->elements()->at(i);
+    switch (elm.type) {
+      case TextElement::ATOM: {
+        stream()->Add("'%w'", elm.data.u_atom->data());
+        break;
+      }
+      case TextElement::CHAR_CLASS: {
+        RegExpCharacterClass* node = elm.data.u_char_class;
+        stream()->Add("[");
+        if (node->is_negated())
+          stream()->Add("^");
+        for (int j = 0; j < node->ranges()->length(); j++) {
+          CharacterRange range = node->ranges()->at(j);
+          stream()->Add("%k-%k", range.from(), range.to());
+        }
+        stream()->Add("]");
+        break;
+      }
+      default:
+        UNREACHABLE();
+    }
+  }
+  stream()->Add("\", shape=box, peripheries=2];\n");
+  PrintAttributes(that);
+  stream()->Add("  n%p -> n%p;\n", that, that->on_success());
+  Visit(that->on_success());
+}
+
+
+void DotPrinter::VisitBackReference(BackReferenceNode* that) {
+  stream()->Add("  n%p [label=\"$%i..$%i\", shape=doubleoctagon];\n",
+                that,
+                that->start_register(),
+                that->end_register());
+  PrintAttributes(that);
+  stream()->Add("  n%p -> n%p;\n", that, that->on_success());
+  Visit(that->on_success());
+}
+
+
+void DotPrinter::VisitEnd(EndNode* that) {
+  stream()->Add("  n%p [style=bold, shape=point];\n", that);
+  PrintAttributes(that);
+}
+
+
+void DotPrinter::VisitAssertion(AssertionNode* that) {
+  stream()->Add("  n%p [", that);
+  switch (that->type()) {
+    case AssertionNode::AT_END:
+      stream()->Add("label=\"$\", shape=septagon");
+      break;
+    case AssertionNode::AT_START:
+      stream()->Add("label=\"^\", shape=septagon");
+      break;
+    case AssertionNode::AT_BOUNDARY:
+      stream()->Add("label=\"\\b\", shape=septagon");
+      break;
+    case AssertionNode::AT_NON_BOUNDARY:
+      stream()->Add("label=\"\\B\", shape=septagon");
+      break;
+    case AssertionNode::AFTER_NEWLINE:
+      stream()->Add("label=\"(?<=\\n)\", shape=septagon");
+      break;
+  }
+  stream()->Add("];\n");
+  PrintAttributes(that);
+  RegExpNode* successor = that->on_success();
+  stream()->Add("  n%p -> n%p;\n", that, successor);
+  Visit(successor);
+}
+
+
+void DotPrinter::VisitAction(ActionNode* that) {
+  stream()->Add("  n%p [", that);
+  switch (that->type_) {
+    case ActionNode::SET_REGISTER:
+      stream()->Add("label=\"$%i:=%i\", shape=octagon",
+                    that->data_.u_store_register.reg,
+                    that->data_.u_store_register.value);
+      break;
+    case ActionNode::INCREMENT_REGISTER:
+      stream()->Add("label=\"$%i++\", shape=octagon",
+                    that->data_.u_increment_register.reg);
+      break;
+    case ActionNode::STORE_POSITION:
+      stream()->Add("label=\"$%i:=$pos\", shape=octagon",
+                    that->data_.u_position_register.reg);
+      break;
+    case ActionNode::BEGIN_SUBMATCH:
+      stream()->Add("label=\"$%i:=$pos,begin\", shape=septagon",
+                    that->data_.u_submatch.current_position_register);
+      break;
+    case ActionNode::POSITIVE_SUBMATCH_SUCCESS:
+      stream()->Add("label=\"escape\", shape=septagon");
+      break;
+    case ActionNode::EMPTY_MATCH_CHECK:
+      stream()->Add("label=\"$%i=$pos?,$%i<%i?\", shape=septagon",
+                    that->data_.u_empty_match_check.start_register,
+                    that->data_.u_empty_match_check.repetition_register,
+                    that->data_.u_empty_match_check.repetition_limit);
+      break;
+    case ActionNode::CLEAR_CAPTURES: {
+      stream()->Add("label=\"clear $%i to $%i\", shape=septagon",
+                    that->data_.u_clear_captures.range_from,
+                    that->data_.u_clear_captures.range_to);
+      break;
+    }
+  }
+  stream()->Add("];\n");
+  PrintAttributes(that);
+  RegExpNode* successor = that->on_success();
+  stream()->Add("  n%p -> n%p;\n", that, successor);
+  Visit(successor);
+}
+
+
+class DispatchTableDumper {
+ public:
+  explicit DispatchTableDumper(StringStream* stream) : stream_(stream) { }
+  void Call(uc16 key, DispatchTable::Entry entry);
+  StringStream* stream() { return stream_; }
+ private:
+  StringStream* stream_;
+};
+
+
+void DispatchTableDumper::Call(uc16 key, DispatchTable::Entry entry) {
+  stream()->Add("[%k-%k]: {", key, entry.to());
+  OutSet* set = entry.out_set();
+  bool first = true;
+  for (unsigned i = 0; i < OutSet::kFirstLimit; i++) {
+    if (set->Get(i)) {
+      if (first) {
+        first = false;
+      } else {
+        stream()->Add(", ");
+      }
+      stream()->Add("%i", i);
+    }
+  }
+  stream()->Add("}\n");
+}
+
+
+void DispatchTable::Dump() {
+  HeapStringAllocator alloc;
+  StringStream stream(&alloc);
+  DispatchTableDumper dumper(&stream);
+  tree()->ForEach(&dumper);
+  OS::PrintError("%s", *stream.ToCString());
+}
+
+
+void RegExpEngine::DotPrint(const char* label,
+                            RegExpNode* node,
+                            bool ignore_case) {
+  DotPrinter printer(ignore_case);
+  printer.PrintNode(label, node);
+}
+
+
+#endif  // DEBUG
+
+
+// -------------------------------------------------------------------
+// Tree to graph conversion
+
+static const int kSpaceRangeCount = 20;
+static const int kSpaceRangeAsciiCount = 4;
+static const uc16 kSpaceRanges[kSpaceRangeCount] = { 0x0009, 0x000D, 0x0020,
+    0x0020, 0x00A0, 0x00A0, 0x1680, 0x1680, 0x180E, 0x180E, 0x2000, 0x200A,
+    0x2028, 0x2029, 0x202F, 0x202F, 0x205F, 0x205F, 0x3000, 0x3000 };
+
+static const int kWordRangeCount = 8;
+static const uc16 kWordRanges[kWordRangeCount] = { '0', '9', 'A', 'Z', '_',
+    '_', 'a', 'z' };
+
+static const int kDigitRangeCount = 2;
+static const uc16 kDigitRanges[kDigitRangeCount] = { '0', '9' };
+
+static const int kLineTerminatorRangeCount = 6;
+static const uc16 kLineTerminatorRanges[kLineTerminatorRangeCount] = { 0x000A,
+    0x000A, 0x000D, 0x000D, 0x2028, 0x2029 };
+
+RegExpNode* RegExpAtom::ToNode(RegExpCompiler* compiler,
+                               RegExpNode* on_success) {
+  ZoneList<TextElement>* elms = new ZoneList<TextElement>(1);
+  elms->Add(TextElement::Atom(this));
+  return new TextNode(elms, on_success);
+}
+
+
+RegExpNode* RegExpText::ToNode(RegExpCompiler* compiler,
+                               RegExpNode* on_success) {
+  return new TextNode(elements(), on_success);
+}
+
+static bool CompareInverseRanges(ZoneList<CharacterRange>* ranges,
+                                 const uc16* special_class,
+                                 int length) {
+  ASSERT(ranges->length() != 0);
+  ASSERT(length != 0);
+  ASSERT(special_class[0] != 0);
+  if (ranges->length() != (length >> 1) + 1) {
+    return false;
+  }
+  CharacterRange range = ranges->at(0);
+  if (range.from() != 0) {
+    return false;
+  }
+  for (int i = 0; i < length; i += 2) {
+    if (special_class[i] != (range.to() + 1)) {
+      return false;
+    }
+    range = ranges->at((i >> 1) + 1);
+    if (special_class[i+1] != range.from() - 1) {
+      return false;
+    }
+  }
+  if (range.to() != 0xffff) {
+    return false;
+  }
+  return true;
+}
+
+
+static bool CompareRanges(ZoneList<CharacterRange>* ranges,
+                          const uc16* special_class,
+                          int length) {
+  if (ranges->length() * 2 != length) {
+    return false;
+  }
+  for (int i = 0; i < length; i += 2) {
+    CharacterRange range = ranges->at(i >> 1);
+    if (range.from() != special_class[i] || range.to() != special_class[i+1]) {
+      return false;
+    }
+  }
+  return true;
+}
+
+
+bool RegExpCharacterClass::is_standard() {
+  // TODO(lrn): Remove need for this function, by not throwing away information
+  // along the way.
+  if (is_negated_) {
+    return false;
+  }
+  if (set_.is_standard()) {
+    return true;
+  }
+  if (CompareRanges(set_.ranges(), kSpaceRanges, kSpaceRangeCount)) {
+    set_.set_standard_set_type('s');
+    return true;
+  }
+  if (CompareInverseRanges(set_.ranges(), kSpaceRanges, kSpaceRangeCount)) {
+    set_.set_standard_set_type('S');
+    return true;
+  }
+  if (CompareInverseRanges(set_.ranges(),
+                           kLineTerminatorRanges,
+                           kLineTerminatorRangeCount)) {
+    set_.set_standard_set_type('.');
+    return true;
+  }
+  return false;
+}
+
+
+RegExpNode* RegExpCharacterClass::ToNode(RegExpCompiler* compiler,
+                                         RegExpNode* on_success) {
+  return new TextNode(this, on_success);
+}
+
+
+RegExpNode* RegExpDisjunction::ToNode(RegExpCompiler* compiler,
+                                      RegExpNode* on_success) {
+  ZoneList<RegExpTree*>* alternatives = this->alternatives();
+  int length = alternatives->length();
+  ChoiceNode* result = new ChoiceNode(length);
+  for (int i = 0; i < length; i++) {
+    GuardedAlternative alternative(alternatives->at(i)->ToNode(compiler,
+                                                               on_success));
+    result->AddAlternative(alternative);
+  }
+  return result;
+}
+
+
+RegExpNode* RegExpQuantifier::ToNode(RegExpCompiler* compiler,
+                                     RegExpNode* on_success) {
+  return ToNode(min(),
+                max(),
+                is_greedy(),
+                body(),
+                compiler,
+                on_success);
+}
+
+
+RegExpNode* RegExpQuantifier::ToNode(int min,
+                                     int max,
+                                     bool is_greedy,
+                                     RegExpTree* body,
+                                     RegExpCompiler* compiler,
+                                     RegExpNode* on_success,
+                                     bool not_at_start) {
+  // x{f, t} becomes this:
+  //
+  //             (r++)<-.
+  //               |     `
+  //               |     (x)
+  //               v     ^
+  //      (r=0)-->(?)---/ [if r < t]
+  //               |
+  //   [if r >= f] \----> ...
+  //
+
+  // 15.10.2.5 RepeatMatcher algorithm.
+  // The parser has already eliminated the case where max is 0.  In the case
+  // where max_match is zero the parser has removed the quantifier if min was
+  // > 0 and removed the atom if min was 0.  See AddQuantifierToAtom.
+
+  // If we know that we cannot match zero length then things are a little
+  // simpler since we don't need to make the special zero length match check
+  // from step 2.1.  If the min and max are small we can unroll a little in
+  // this case.
+  static const int kMaxUnrolledMinMatches = 3;  // Unroll (foo)+ and (foo){3,}
+  static const int kMaxUnrolledMaxMatches = 3;  // Unroll (foo)? and (foo){x,3}
+  if (max == 0) return on_success;  // This can happen due to recursion.
+  bool body_can_be_empty = (body->min_match() == 0);
+  int body_start_reg = RegExpCompiler::kNoRegister;
+  Interval capture_registers = body->CaptureRegisters();
+  bool needs_capture_clearing = !capture_registers.is_empty();
+  if (body_can_be_empty) {
+    body_start_reg = compiler->AllocateRegister();
+  } else if (FLAG_regexp_optimization && !needs_capture_clearing) {
+    // Only unroll if there are no captures and the body can't be
+    // empty.
+    if (min > 0 && min <= kMaxUnrolledMinMatches) {
+      int new_max = (max == kInfinity) ? max : max - min;
+      // Recurse once to get the loop or optional matches after the fixed ones.
+      RegExpNode* answer = ToNode(
+          0, new_max, is_greedy, body, compiler, on_success, true);
+      // Unroll the forced matches from 0 to min.  This can cause chains of
+      // TextNodes (which the parser does not generate).  These should be
+      // combined if it turns out they hinder good code generation.
+      for (int i = 0; i < min; i++) {
+        answer = body->ToNode(compiler, answer);
+      }
+      return answer;
+    }
+    if (max <= kMaxUnrolledMaxMatches) {
+      ASSERT(min == 0);
+      // Unroll the optional matches up to max.
+      RegExpNode* answer = on_success;
+      for (int i = 0; i < max; i++) {
+        ChoiceNode* alternation = new ChoiceNode(2);
+        if (is_greedy) {
+          alternation->AddAlternative(GuardedAlternative(body->ToNode(compiler,
+                                                                      answer)));
+          alternation->AddAlternative(GuardedAlternative(on_success));
+        } else {
+          alternation->AddAlternative(GuardedAlternative(on_success));
+          alternation->AddAlternative(GuardedAlternative(body->ToNode(compiler,
+                                                                      answer)));
+        }
+        answer = alternation;
+        if (not_at_start) alternation->set_not_at_start();
+      }
+      return answer;
+    }
+  }
+  bool has_min = min > 0;
+  bool has_max = max < RegExpTree::kInfinity;
+  bool needs_counter = has_min || has_max;
+  int reg_ctr = needs_counter
+      ? compiler->AllocateRegister()
+      : RegExpCompiler::kNoRegister;
+  LoopChoiceNode* center = new LoopChoiceNode(body->min_match() == 0);
+  if (not_at_start) center->set_not_at_start();
+  RegExpNode* loop_return = needs_counter
+      ? static_cast<RegExpNode*>(ActionNode::IncrementRegister(reg_ctr, center))
+      : static_cast<RegExpNode*>(center);
+  if (body_can_be_empty) {
+    // If the body can be empty we need to check if it was and then
+    // backtrack.
+    loop_return = ActionNode::EmptyMatchCheck(body_start_reg,
+                                              reg_ctr,
+                                              min,
+                                              loop_return);
+  }
+  RegExpNode* body_node = body->ToNode(compiler, loop_return);
+  if (body_can_be_empty) {
+    // If the body can be empty we need to store the start position
+    // so we can bail out if it was empty.
+    body_node = ActionNode::StorePosition(body_start_reg, false, body_node);
+  }
+  if (needs_capture_clearing) {
+    // Before entering the body of this loop we need to clear captures.
+    body_node = ActionNode::ClearCaptures(capture_registers, body_node);
+  }
+  GuardedAlternative body_alt(body_node);
+  if (has_max) {
+    Guard* body_guard = new Guard(reg_ctr, Guard::LT, max);
+    body_alt.AddGuard(body_guard);
+  }
+  GuardedAlternative rest_alt(on_success);
+  if (has_min) {
+    Guard* rest_guard = new Guard(reg_ctr, Guard::GEQ, min);
+    rest_alt.AddGuard(rest_guard);
+  }
+  if (is_greedy) {
+    center->AddLoopAlternative(body_alt);
+    center->AddContinueAlternative(rest_alt);
+  } else {
+    center->AddContinueAlternative(rest_alt);
+    center->AddLoopAlternative(body_alt);
+  }
+  if (needs_counter) {
+    return ActionNode::SetRegister(reg_ctr, 0, center);
+  } else {
+    return center;
+  }
+}
+
+
+RegExpNode* RegExpAssertion::ToNode(RegExpCompiler* compiler,
+                                    RegExpNode* on_success) {
+  NodeInfo info;
+  switch (type()) {
+    case START_OF_LINE:
+      return AssertionNode::AfterNewline(on_success);
+    case START_OF_INPUT:
+      return AssertionNode::AtStart(on_success);
+    case BOUNDARY:
+      return AssertionNode::AtBoundary(on_success);
+    case NON_BOUNDARY:
+      return AssertionNode::AtNonBoundary(on_success);
+    case END_OF_INPUT:
+      return AssertionNode::AtEnd(on_success);
+    case END_OF_LINE: {
+      // Compile $ in multiline regexps as an alternation with a positive
+      // lookahead in one side and an end-of-input on the other side.
+      // We need two registers for the lookahead.
+      int stack_pointer_register = compiler->AllocateRegister();
+      int position_register = compiler->AllocateRegister();
+      // The ChoiceNode to distinguish between a newline and end-of-input.
+      ChoiceNode* result = new ChoiceNode(2);
+      // Create a newline atom.
+      ZoneList<CharacterRange>* newline_ranges =
+          new ZoneList<CharacterRange>(3);
+      CharacterRange::AddClassEscape('n', newline_ranges);
+      RegExpCharacterClass* newline_atom = new RegExpCharacterClass('n');
+      TextNode* newline_matcher = new TextNode(
+         newline_atom,
+         ActionNode::PositiveSubmatchSuccess(stack_pointer_register,
+                                             position_register,
+                                             0,  // No captures inside.
+                                             -1,  // Ignored if no captures.
+                                             on_success));
+      // Create an end-of-input matcher.
+      RegExpNode* end_of_line = ActionNode::BeginSubmatch(
+          stack_pointer_register,
+          position_register,
+          newline_matcher);
+      // Add the two alternatives to the ChoiceNode.
+      GuardedAlternative eol_alternative(end_of_line);
+      result->AddAlternative(eol_alternative);
+      GuardedAlternative end_alternative(AssertionNode::AtEnd(on_success));
+      result->AddAlternative(end_alternative);
+      return result;
+    }
+    default:
+      UNREACHABLE();
+  }
+  return on_success;
+}
+
+
+RegExpNode* RegExpBackReference::ToNode(RegExpCompiler* compiler,
+                                        RegExpNode* on_success) {
+  return new BackReferenceNode(RegExpCapture::StartRegister(index()),
+                               RegExpCapture::EndRegister(index()),
+                               on_success);
+}
+
+
+RegExpNode* RegExpEmpty::ToNode(RegExpCompiler* compiler,
+                                RegExpNode* on_success) {
+  return on_success;
+}
+
+
+RegExpNode* RegExpLookahead::ToNode(RegExpCompiler* compiler,
+                                    RegExpNode* on_success) {
+  int stack_pointer_register = compiler->AllocateRegister();
+  int position_register = compiler->AllocateRegister();
+
+  const int registers_per_capture = 2;
+  const int register_of_first_capture = 2;
+  int register_count = capture_count_ * registers_per_capture;
+  int register_start =
+    register_of_first_capture + capture_from_ * registers_per_capture;
+
+  RegExpNode* success;
+  if (is_positive()) {
+    RegExpNode* node = ActionNode::BeginSubmatch(
+        stack_pointer_register,
+        position_register,
+        body()->ToNode(
+            compiler,
+            ActionNode::PositiveSubmatchSuccess(stack_pointer_register,
+                                                position_register,
+                                                register_count,
+                                                register_start,
+                                                on_success)));
+    return node;
+  } else {
+    // We use a ChoiceNode for a negative lookahead because it has most of
+    // the characteristics we need.  It has the body of the lookahead as its
+    // first alternative and the expression after the lookahead of the second
+    // alternative.  If the first alternative succeeds then the
+    // NegativeSubmatchSuccess will unwind the stack including everything the
+    // choice node set up and backtrack.  If the first alternative fails then
+    // the second alternative is tried, which is exactly the desired result
+    // for a negative lookahead.  The NegativeLookaheadChoiceNode is a special
+    // ChoiceNode that knows to ignore the first exit when calculating quick
+    // checks.
+    GuardedAlternative body_alt(
+        body()->ToNode(
+            compiler,
+            success = new NegativeSubmatchSuccess(stack_pointer_register,
+                                                  position_register,
+                                                  register_count,
+                                                  register_start)));
+    ChoiceNode* choice_node =
+        new NegativeLookaheadChoiceNode(body_alt,
+                                        GuardedAlternative(on_success));
+    return ActionNode::BeginSubmatch(stack_pointer_register,
+                                     position_register,
+                                     choice_node);
+  }
+}
+
+
+RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler,
+                                  RegExpNode* on_success) {
+  return ToNode(body(), index(), compiler, on_success);
+}
+
+
+RegExpNode* RegExpCapture::ToNode(RegExpTree* body,
+                                  int index,
+                                  RegExpCompiler* compiler,
+                                  RegExpNode* on_success) {
+  int start_reg = RegExpCapture::StartRegister(index);
+  int end_reg = RegExpCapture::EndRegister(index);
+  RegExpNode* store_end = ActionNode::StorePosition(end_reg, true, on_success);
+  RegExpNode* body_node = body->ToNode(compiler, store_end);
+  return ActionNode::StorePosition(start_reg, true, body_node);
+}
+
+
+RegExpNode* RegExpAlternative::ToNode(RegExpCompiler* compiler,
+                                      RegExpNode* on_success) {
+  ZoneList<RegExpTree*>* children = nodes();
+  RegExpNode* current = on_success;
+  for (int i = children->length() - 1; i >= 0; i--) {
+    current = children->at(i)->ToNode(compiler, current);
+  }
+  return current;
+}
+
+
+static void AddClass(const uc16* elmv,
+                     int elmc,
+                     ZoneList<CharacterRange>* ranges) {
+  for (int i = 0; i < elmc; i += 2) {
+    ASSERT(elmv[i] <= elmv[i + 1]);
+    ranges->Add(CharacterRange(elmv[i], elmv[i + 1]));
+  }
+}
+
+
+static void AddClassNegated(const uc16 *elmv,
+                            int elmc,
+                            ZoneList<CharacterRange>* ranges) {
+  ASSERT(elmv[0] != 0x0000);
+  ASSERT(elmv[elmc-1] != String::kMaxUC16CharCode);
+  uc16 last = 0x0000;
+  for (int i = 0; i < elmc; i += 2) {
+    ASSERT(last <= elmv[i] - 1);
+    ASSERT(elmv[i] <= elmv[i + 1]);
+    ranges->Add(CharacterRange(last, elmv[i] - 1));
+    last = elmv[i + 1] + 1;
+  }
+  ranges->Add(CharacterRange(last, String::kMaxUC16CharCode));
+}
+
+
+void CharacterRange::AddClassEscape(uc16 type,
+                                    ZoneList<CharacterRange>* ranges) {
+  switch (type) {
+    case 's':
+      AddClass(kSpaceRanges, kSpaceRangeCount, ranges);
+      break;
+    case 'S':
+      AddClassNegated(kSpaceRanges, kSpaceRangeCount, ranges);
+      break;
+    case 'w':
+      AddClass(kWordRanges, kWordRangeCount, ranges);
+      break;
+    case 'W':
+      AddClassNegated(kWordRanges, kWordRangeCount, ranges);
+      break;
+    case 'd':
+      AddClass(kDigitRanges, kDigitRangeCount, ranges);
+      break;
+    case 'D':
+      AddClassNegated(kDigitRanges, kDigitRangeCount, ranges);
+      break;
+    case '.':
+      AddClassNegated(kLineTerminatorRanges,
+                      kLineTerminatorRangeCount,
+                      ranges);
+      break;
+    // This is not a character range as defined by the spec but a
+    // convenient shorthand for a character class that matches any
+    // character.
+    case '*':
+      ranges->Add(CharacterRange::Everything());
+      break;
+    // This is the set of characters matched by the $ and ^ symbols
+    // in multiline mode.
+    case 'n':
+      AddClass(kLineTerminatorRanges,
+               kLineTerminatorRangeCount,
+               ranges);
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+Vector<const uc16> CharacterRange::GetWordBounds() {
+  return Vector<const uc16>(kWordRanges, kWordRangeCount);
+}
+
+
+class CharacterRangeSplitter {
+ public:
+  CharacterRangeSplitter(ZoneList<CharacterRange>** included,
+                          ZoneList<CharacterRange>** excluded)
+      : included_(included),
+        excluded_(excluded) { }
+  void Call(uc16 from, DispatchTable::Entry entry);
+
+  static const int kInBase = 0;
+  static const int kInOverlay = 1;
+
+ private:
+  ZoneList<CharacterRange>** included_;
+  ZoneList<CharacterRange>** excluded_;
+};
+
+
+void CharacterRangeSplitter::Call(uc16 from, DispatchTable::Entry entry) {
+  if (!entry.out_set()->Get(kInBase)) return;
+  ZoneList<CharacterRange>** target = entry.out_set()->Get(kInOverlay)
+    ? included_
+    : excluded_;
+  if (*target == NULL) *target = new ZoneList<CharacterRange>(2);
+  (*target)->Add(CharacterRange(entry.from(), entry.to()));
+}
+
+
+void CharacterRange::Split(ZoneList<CharacterRange>* base,
+                           Vector<const uc16> overlay,
+                           ZoneList<CharacterRange>** included,
+                           ZoneList<CharacterRange>** excluded) {
+  ASSERT_EQ(NULL, *included);
+  ASSERT_EQ(NULL, *excluded);
+  DispatchTable table;
+  for (int i = 0; i < base->length(); i++)
+    table.AddRange(base->at(i), CharacterRangeSplitter::kInBase);
+  for (int i = 0; i < overlay.length(); i += 2) {
+    table.AddRange(CharacterRange(overlay[i], overlay[i+1]),
+                   CharacterRangeSplitter::kInOverlay);
+  }
+  CharacterRangeSplitter callback(included, excluded);
+  table.ForEach(&callback);
+}
+
+
+void CharacterRange::AddCaseEquivalents(ZoneList<CharacterRange>* ranges) {
+  unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
+  if (IsSingleton()) {
+    // If this is a singleton we just expand the one character.
+    int length = uncanonicalize.get(from(), '\0', chars);
+    for (int i = 0; i < length; i++) {
+      uc32 chr = chars[i];
+      if (chr != from()) {
+        ranges->Add(CharacterRange::Singleton(chars[i]));
+      }
+    }
+  } else if (from() <= kRangeCanonicalizeMax &&
+             to() <= kRangeCanonicalizeMax) {
+    // If this is a range we expand the characters block by block,
+    // expanding contiguous subranges (blocks) one at a time.
+    // The approach is as follows.  For a given start character we
+    // look up the block that contains it, for instance 'a' if the
+    // start character is 'c'.  A block is characterized by the property
+    // that all characters uncanonicalize in the same way as the first
+    // element, except that each entry in the result is incremented
+    // by the distance from the first element.  So a-z is a block
+    // because 'a' uncanonicalizes to ['a', 'A'] and the k'th letter
+    // uncanonicalizes to ['a' + k, 'A' + k].
+    // Once we've found the start point we look up its uncanonicalization
+    // and produce a range for each element.  For instance for [c-f]
+    // we look up ['a', 'A'] and produce [c-f] and [C-F].  We then only
+    // add a range if it is not already contained in the input, so [c-f]
+    // will be skipped but [C-F] will be added.  If this range is not
+    // completely contained in a block we do this for all the blocks
+    // covered by the range.
+    unibrow::uchar range[unibrow::Ecma262UnCanonicalize::kMaxWidth];
+    // First, look up the block that contains the 'from' character.
+    int length = canonrange.get(from(), '\0', range);
+    if (length == 0) {
+      range[0] = from();
+    } else {
+      ASSERT_EQ(1, length);
+    }
+    int pos = from();
+    // The start of the current block.  Note that except for the first
+    // iteration 'start' is always equal to 'pos'.
+    int start;
+    // If it is not the start point of a block the entry contains the
+    // offset of the character from the start point.
+    if ((range[0] & kStartMarker) == 0) {
+      start = pos - range[0];
+    } else {
+      start = pos;
+    }
+    // Then we add the ranges on at a time, incrementing the current
+    // position to be after the last block each time.  The position
+    // always points to the start of a block.
+    while (pos < to()) {
+      length = canonrange.get(start, '\0', range);
+      if (length == 0) {
+        range[0] = start;
+      } else {
+        ASSERT_EQ(1, length);
+      }
+      ASSERT((range[0] & kStartMarker) != 0);
+      // The start point of a block contains the distance to the end
+      // of the range.
+      int block_end = start + (range[0] & kPayloadMask) - 1;
+      int end = (block_end > to()) ? to() : block_end;
+      length = uncanonicalize.get(start, '\0', range);
+      for (int i = 0; i < length; i++) {
+        uc32 c = range[i];
+        uc16 range_from = c + (pos - start);
+        uc16 range_to = c + (end - start);
+        if (!(from() <= range_from && range_to <= to())) {
+          ranges->Add(CharacterRange(range_from, range_to));
+        }
+      }
+      start = pos = block_end + 1;
+    }
+  } else {
+    // TODO(plesner) when we've fixed the 2^11 bug in unibrow.
+  }
+}
+
+
+ZoneList<CharacterRange>* CharacterSet::ranges() {
+  if (ranges_ == NULL) {
+    ranges_ = new ZoneList<CharacterRange>(2);
+    CharacterRange::AddClassEscape(standard_set_type_, ranges_);
+  }
+  return ranges_;
+}
+
+
+
+// -------------------------------------------------------------------
+// Interest propagation
+
+
+RegExpNode* RegExpNode::TryGetSibling(NodeInfo* info) {
+  for (int i = 0; i < siblings_.length(); i++) {
+    RegExpNode* sibling = siblings_.Get(i);
+    if (sibling->info()->Matches(info))
+      return sibling;
+  }
+  return NULL;
+}
+
+
+RegExpNode* RegExpNode::EnsureSibling(NodeInfo* info, bool* cloned) {
+  ASSERT_EQ(false, *cloned);
+  siblings_.Ensure(this);
+  RegExpNode* result = TryGetSibling(info);
+  if (result != NULL) return result;
+  result = this->Clone();
+  NodeInfo* new_info = result->info();
+  new_info->ResetCompilationState();
+  new_info->AddFromPreceding(info);
+  AddSibling(result);
+  *cloned = true;
+  return result;
+}
+
+
+template <class C>
+static RegExpNode* PropagateToEndpoint(C* node, NodeInfo* info) {
+  NodeInfo full_info(*node->info());
+  full_info.AddFromPreceding(info);
+  bool cloned = false;
+  return RegExpNode::EnsureSibling(node, &full_info, &cloned);
+}
+
+
+// -------------------------------------------------------------------
+// Splay tree
+
+
+OutSet* OutSet::Extend(unsigned value) {
+  if (Get(value))
+    return this;
+  if (successors() != NULL) {
+    for (int i = 0; i < successors()->length(); i++) {
+      OutSet* successor = successors()->at(i);
+      if (successor->Get(value))
+        return successor;
+    }
+  } else {
+    successors_ = new ZoneList<OutSet*>(2);
+  }
+  OutSet* result = new OutSet(first_, remaining_);
+  result->Set(value);
+  successors()->Add(result);
+  return result;
+}
+
+
+void OutSet::Set(unsigned value) {
+  if (value < kFirstLimit) {
+    first_ |= (1 << value);
+  } else {
+    if (remaining_ == NULL)
+      remaining_ = new ZoneList<unsigned>(1);
+    if (remaining_->is_empty() || !remaining_->Contains(value))
+      remaining_->Add(value);
+  }
+}
+
+
+bool OutSet::Get(unsigned value) {
+  if (value < kFirstLimit) {
+    return (first_ & (1 << value)) != 0;
+  } else if (remaining_ == NULL) {
+    return false;
+  } else {
+    return remaining_->Contains(value);
+  }
+}
+
+
+const uc16 DispatchTable::Config::kNoKey = unibrow::Utf8::kBadChar;
+const DispatchTable::Entry DispatchTable::Config::kNoValue;
+
+
+void DispatchTable::AddRange(CharacterRange full_range, int value) {
+  CharacterRange current = full_range;
+  if (tree()->is_empty()) {
+    // If this is the first range we just insert into the table.
+    ZoneSplayTree<Config>::Locator loc;
+    ASSERT_RESULT(tree()->Insert(current.from(), &loc));
+    loc.set_value(Entry(current.from(), current.to(), empty()->Extend(value)));
+    return;
+  }
+  // First see if there is a range to the left of this one that
+  // overlaps.
+  ZoneSplayTree<Config>::Locator loc;
+  if (tree()->FindGreatestLessThan(current.from(), &loc)) {
+    Entry* entry = &loc.value();
+    // If we've found a range that overlaps with this one, and it
+    // starts strictly to the left of this one, we have to fix it
+    // because the following code only handles ranges that start on
+    // or after the start point of the range we're adding.
+    if (entry->from() < current.from() && entry->to() >= current.from()) {
+      // Snap the overlapping range in half around the start point of
+      // the range we're adding.
+      CharacterRange left(entry->from(), current.from() - 1);
+      CharacterRange right(current.from(), entry->to());
+      // The left part of the overlapping range doesn't overlap.
+      // Truncate the whole entry to be just the left part.
+      entry->set_to(left.to());
+      // The right part is the one that overlaps.  We add this part
+      // to the map and let the next step deal with merging it with
+      // the range we're adding.
+      ZoneSplayTree<Config>::Locator loc;
+      ASSERT_RESULT(tree()->Insert(right.from(), &loc));
+      loc.set_value(Entry(right.from(),
+                          right.to(),
+                          entry->out_set()));
+    }
+  }
+  while (current.is_valid()) {
+    if (tree()->FindLeastGreaterThan(current.from(), &loc) &&
+        (loc.value().from() <= current.to()) &&
+        (loc.value().to() >= current.from())) {
+      Entry* entry = &loc.value();
+      // We have overlap.  If there is space between the start point of
+      // the range we're adding and where the overlapping range starts
+      // then we have to add a range covering just that space.
+      if (current.from() < entry->from()) {
+        ZoneSplayTree<Config>::Locator ins;
+        ASSERT_RESULT(tree()->Insert(current.from(), &ins));
+        ins.set_value(Entry(current.from(),
+                            entry->from() - 1,
+                            empty()->Extend(value)));
+        current.set_from(entry->from());
+      }
+      ASSERT_EQ(current.from(), entry->from());
+      // If the overlapping range extends beyond the one we want to add
+      // we have to snap the right part off and add it separately.
+      if (entry->to() > current.to()) {
+        ZoneSplayTree<Config>::Locator ins;
+        ASSERT_RESULT(tree()->Insert(current.to() + 1, &ins));
+        ins.set_value(Entry(current.to() + 1,
+                            entry->to(),
+                            entry->out_set()));
+        entry->set_to(current.to());
+      }
+      ASSERT(entry->to() <= current.to());
+      // The overlapping range is now completely contained by the range
+      // we're adding so we can just update it and move the start point
+      // of the range we're adding just past it.
+      entry->AddValue(value);
+      // Bail out if the last interval ended at 0xFFFF since otherwise
+      // adding 1 will wrap around to 0.
+      if (entry->to() == String::kMaxUC16CharCode)
+        break;
+      ASSERT(entry->to() + 1 > current.from());
+      current.set_from(entry->to() + 1);
+    } else {
+      // There is no overlap so we can just add the range
+      ZoneSplayTree<Config>::Locator ins;
+      ASSERT_RESULT(tree()->Insert(current.from(), &ins));
+      ins.set_value(Entry(current.from(),
+                          current.to(),
+                          empty()->Extend(value)));
+      break;
+    }
+  }
+}
+
+
+OutSet* DispatchTable::Get(uc16 value) {
+  ZoneSplayTree<Config>::Locator loc;
+  if (!tree()->FindGreatestLessThan(value, &loc))
+    return empty();
+  Entry* entry = &loc.value();
+  if (value <= entry->to())
+    return entry->out_set();
+  else
+    return empty();
+}
+
+
+// -------------------------------------------------------------------
+// Analysis
+
+
+void Analysis::EnsureAnalyzed(RegExpNode* that) {
+  if (that->info()->been_analyzed || that->info()->being_analyzed)
+    return;
+  that->info()->being_analyzed = true;
+  that->Accept(this);
+  that->info()->being_analyzed = false;
+  that->info()->been_analyzed = true;
+}
+
+
+void Analysis::VisitEnd(EndNode* that) {
+  // nothing to do
+}
+
+
+void TextNode::CalculateOffsets() {
+  int element_count = elements()->length();
+  // Set up the offsets of the elements relative to the start.  This is a fixed
+  // quantity since a TextNode can only contain fixed-width things.
+  int cp_offset = 0;
+  for (int i = 0; i < element_count; i++) {
+    TextElement& elm = elements()->at(i);
+    elm.cp_offset = cp_offset;
+    if (elm.type == TextElement::ATOM) {
+      cp_offset += elm.data.u_atom->data().length();
+    } else {
+      cp_offset++;
+      Vector<const uc16> quarks = elm.data.u_atom->data();
+    }
+  }
+}
+
+
+void Analysis::VisitText(TextNode* that) {
+  if (ignore_case_) {
+    that->MakeCaseIndependent();
+  }
+  EnsureAnalyzed(that->on_success());
+  that->CalculateOffsets();
+}
+
+
+void Analysis::VisitAction(ActionNode* that) {
+  RegExpNode* target = that->on_success();
+  EnsureAnalyzed(target);
+  // If the next node is interested in what it follows then this node
+  // has to be interested too so it can pass the information on.
+  that->info()->AddFromFollowing(target->info());
+}
+
+
+void Analysis::VisitChoice(ChoiceNode* that) {
+  NodeInfo* info = that->info();
+  for (int i = 0; i < that->alternatives()->length(); i++) {
+    RegExpNode* node = that->alternatives()->at(i).node();
+    EnsureAnalyzed(node);
+    // Anything the following nodes need to know has to be known by
+    // this node also, so it can pass it on.
+    info->AddFromFollowing(node->info());
+  }
+}
+
+
+void Analysis::VisitLoopChoice(LoopChoiceNode* that) {
+  NodeInfo* info = that->info();
+  for (int i = 0; i < that->alternatives()->length(); i++) {
+    RegExpNode* node = that->alternatives()->at(i).node();
+    if (node != that->loop_node()) {
+      EnsureAnalyzed(node);
+      info->AddFromFollowing(node->info());
+    }
+  }
+  // Check the loop last since it may need the value of this node
+  // to get a correct result.
+  EnsureAnalyzed(that->loop_node());
+  info->AddFromFollowing(that->loop_node()->info());
+}
+
+
+void Analysis::VisitBackReference(BackReferenceNode* that) {
+  EnsureAnalyzed(that->on_success());
+}
+
+
+void Analysis::VisitAssertion(AssertionNode* that) {
+  EnsureAnalyzed(that->on_success());
+}
+
+
+// -------------------------------------------------------------------
+// Dispatch table construction
+
+
+void DispatchTableConstructor::VisitEnd(EndNode* that) {
+  AddRange(CharacterRange::Everything());
+}
+
+
+void DispatchTableConstructor::BuildTable(ChoiceNode* node) {
+  node->set_being_calculated(true);
+  ZoneList<GuardedAlternative>* alternatives = node->alternatives();
+  for (int i = 0; i < alternatives->length(); i++) {
+    set_choice_index(i);
+    alternatives->at(i).node()->Accept(this);
+  }
+  node->set_being_calculated(false);
+}
+
+
+class AddDispatchRange {
+ public:
+  explicit AddDispatchRange(DispatchTableConstructor* constructor)
+    : constructor_(constructor) { }
+  void Call(uc32 from, DispatchTable::Entry entry);
+ private:
+  DispatchTableConstructor* constructor_;
+};
+
+
+void AddDispatchRange::Call(uc32 from, DispatchTable::Entry entry) {
+  CharacterRange range(from, entry.to());
+  constructor_->AddRange(range);
+}
+
+
+void DispatchTableConstructor::VisitChoice(ChoiceNode* node) {
+  if (node->being_calculated())
+    return;
+  DispatchTable* table = node->GetTable(ignore_case_);
+  AddDispatchRange adder(this);
+  table->ForEach(&adder);
+}
+
+
+void DispatchTableConstructor::VisitBackReference(BackReferenceNode* that) {
+  // TODO(160): Find the node that we refer back to and propagate its start
+  // set back to here.  For now we just accept anything.
+  AddRange(CharacterRange::Everything());
+}
+
+
+void DispatchTableConstructor::VisitAssertion(AssertionNode* that) {
+  RegExpNode* target = that->on_success();
+  target->Accept(this);
+}
+
+
+
+static int CompareRangeByFrom(const CharacterRange* a,
+                              const CharacterRange* b) {
+  return Compare<uc16>(a->from(), b->from());
+}
+
+
+void DispatchTableConstructor::AddInverse(ZoneList<CharacterRange>* ranges) {
+  ranges->Sort(CompareRangeByFrom);
+  uc16 last = 0;
+  for (int i = 0; i < ranges->length(); i++) {
+    CharacterRange range = ranges->at(i);
+    if (last < range.from())
+      AddRange(CharacterRange(last, range.from() - 1));
+    if (range.to() >= last) {
+      if (range.to() == String::kMaxUC16CharCode) {
+        return;
+      } else {
+        last = range.to() + 1;
+      }
+    }
+  }
+  AddRange(CharacterRange(last, String::kMaxUC16CharCode));
+}
+
+
+void DispatchTableConstructor::VisitText(TextNode* that) {
+  TextElement elm = that->elements()->at(0);
+  switch (elm.type) {
+    case TextElement::ATOM: {
+      uc16 c = elm.data.u_atom->data()[0];
+      AddRange(CharacterRange(c, c));
+      break;
+    }
+    case TextElement::CHAR_CLASS: {
+      RegExpCharacterClass* tree = elm.data.u_char_class;
+      ZoneList<CharacterRange>* ranges = tree->ranges();
+      if (tree->is_negated()) {
+        AddInverse(ranges);
+      } else {
+        for (int i = 0; i < ranges->length(); i++)
+          AddRange(ranges->at(i));
+      }
+      break;
+    }
+    default: {
+      UNIMPLEMENTED();
+    }
+  }
+}
+
+
+void DispatchTableConstructor::VisitAction(ActionNode* that) {
+  RegExpNode* target = that->on_success();
+  target->Accept(this);
+}
+
+
+RegExpEngine::CompilationResult RegExpEngine::Compile(RegExpCompileData* data,
+                                                      bool ignore_case,
+                                                      bool is_multiline,
+                                                      Handle<String> pattern,
+                                                      bool is_ascii) {
+  if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) {
+    return IrregexpRegExpTooBig();
+  }
+  RegExpCompiler compiler(data->capture_count, ignore_case, is_ascii);
+  // Wrap the body of the regexp in capture #0.
+  RegExpNode* captured_body = RegExpCapture::ToNode(data->tree,
+                                                    0,
+                                                    &compiler,
+                                                    compiler.accept());
+  RegExpNode* node = captured_body;
+  if (!data->tree->IsAnchored()) {
+    // Add a .*? at the beginning, outside the body capture, unless
+    // this expression is anchored at the beginning.
+    RegExpNode* loop_node =
+        RegExpQuantifier::ToNode(0,
+                                 RegExpTree::kInfinity,
+                                 false,
+                                 new RegExpCharacterClass('*'),
+                                 &compiler,
+                                 captured_body,
+                                 data->contains_anchor);
+
+    if (data->contains_anchor) {
+      // Unroll loop once, to take care of the case that might start
+      // at the start of input.
+      ChoiceNode* first_step_node = new ChoiceNode(2);
+      first_step_node->AddAlternative(GuardedAlternative(captured_body));
+      first_step_node->AddAlternative(GuardedAlternative(
+          new TextNode(new RegExpCharacterClass('*'), loop_node)));
+      node = first_step_node;
+    } else {
+      node = loop_node;
+    }
+  }
+  data->node = node;
+  Analysis analysis(ignore_case);
+  analysis.EnsureAnalyzed(node);
+
+  NodeInfo info = *node->info();
+
+  if (RegExpImpl::UseNativeRegexp()) {
+#ifdef ARM
+    UNREACHABLE();
+#else  // IA32
+    RegExpMacroAssemblerIA32::Mode mode;
+    if (is_ascii) {
+      mode = RegExpMacroAssemblerIA32::ASCII;
+    } else {
+      mode = RegExpMacroAssemblerIA32::UC16;
+    }
+    RegExpMacroAssemblerIA32 macro_assembler(mode,
+                                             (data->capture_count + 1) * 2);
+    return compiler.Assemble(&macro_assembler,
+                             node,
+                             data->capture_count,
+                             pattern);
+#endif
+  }
+  EmbeddedVector<byte, 1024> codes;
+  RegExpMacroAssemblerIrregexp macro_assembler(codes);
+  return compiler.Assemble(&macro_assembler,
+                           node,
+                           data->capture_count,
+                           pattern);
+}
+
+
+}}  // namespace v8::internal
diff --git a/deps/v8/src/jsregexp.h b/deps/v8/src/jsregexp.h
new file mode 100644
index 0000000..e824974
--- /dev/null
+++ b/deps/v8/src/jsregexp.h
@@ -0,0 +1,1372 @@
+// 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_JSREGEXP_H_
+#define V8_JSREGEXP_H_
+
+namespace v8 { namespace internal {
+
+
+class RegExpMacroAssembler;
+
+
+class RegExpImpl {
+ public:
+  static inline bool UseNativeRegexp() {
+#ifdef ARM
+    return false;
+#else
+    return FLAG_regexp_native;
+#endif
+  }
+  // Creates a regular expression literal in the old space.
+  // This function calls the garbage collector if necessary.
+  static Handle<Object> CreateRegExpLiteral(Handle<JSFunction> constructor,
+                                            Handle<String> pattern,
+                                            Handle<String> flags,
+                                            bool* has_pending_exception);
+
+  // Returns a string representation of a regular expression.
+  // Implements RegExp.prototype.toString, see ECMA-262 section 15.10.6.4.
+  // This function calls the garbage collector if necessary.
+  static Handle<String> ToString(Handle<Object> value);
+
+  // Parses the RegExp pattern and prepares the JSRegExp object with
+  // generic data and choice of implementation - as well as what
+  // the implementation wants to store in the data field.
+  // Returns false if compilation fails.
+  static Handle<Object> Compile(Handle<JSRegExp> re,
+                                Handle<String> pattern,
+                                Handle<String> flags);
+
+  // See ECMA-262 section 15.10.6.2.
+  // This function calls the garbage collector if necessary.
+  static Handle<Object> Exec(Handle<JSRegExp> regexp,
+                             Handle<String> subject,
+                             int index,
+                             Handle<JSArray> lastMatchInfo);
+
+  // Call RegExp.prototyp.exec(string) in a loop.
+  // Used by String.prototype.match and String.prototype.replace.
+  // This function calls the garbage collector if necessary.
+  static Handle<Object> ExecGlobal(Handle<JSRegExp> regexp,
+                                   Handle<String> subject,
+                                   Handle<JSArray> lastMatchInfo);
+
+  // Prepares a JSRegExp object with Irregexp-specific data.
+  static void IrregexpPrepare(Handle<JSRegExp> re,
+                              Handle<String> pattern,
+                              JSRegExp::Flags flags,
+                              int capture_register_count);
+
+
+  static void AtomCompile(Handle<JSRegExp> re,
+                          Handle<String> pattern,
+                          JSRegExp::Flags flags,
+                          Handle<String> match_pattern);
+
+  static Handle<Object> AtomExec(Handle<JSRegExp> regexp,
+                                 Handle<String> subject,
+                                 int index,
+                                 Handle<JSArray> lastMatchInfo);
+
+  // Execute an Irregexp bytecode pattern.
+  // On a successful match, the result is a JSArray containing
+  // captured positions. On a failure, the result is the null value.
+  // Returns an empty handle in case of an exception.
+  static Handle<Object> IrregexpExec(Handle<JSRegExp> regexp,
+                                     Handle<String> subject,
+                                     int index,
+                                     Handle<JSArray> lastMatchInfo);
+
+  // Offsets in the lastMatchInfo array.
+  static const int kLastCaptureCount = 0;
+  static const int kLastSubject = 1;
+  static const int kLastInput = 2;
+  static const int kFirstCapture = 3;
+  static const int kLastMatchOverhead = 3;
+
+  // Used to access the lastMatchInfo array.
+  static int GetCapture(FixedArray* array, int index) {
+    return Smi::cast(array->get(index + kFirstCapture))->value();
+  }
+
+  static void SetLastCaptureCount(FixedArray* array, int to) {
+    array->set(kLastCaptureCount, Smi::FromInt(to));
+  }
+
+  static void SetLastSubject(FixedArray* array, String* to) {
+    array->set(kLastSubject, to);
+  }
+
+  static void SetLastInput(FixedArray* array, String* to) {
+    array->set(kLastInput, to);
+  }
+
+  static void SetCapture(FixedArray* array, int index, int to) {
+    array->set(index + kFirstCapture, Smi::FromInt(to));
+  }
+
+  static int GetLastCaptureCount(FixedArray* array) {
+    return Smi::cast(array->get(kLastCaptureCount))->value();
+  }
+
+  // For acting on the JSRegExp data FixedArray.
+  static int IrregexpMaxRegisterCount(FixedArray* re);
+  static void SetIrregexpMaxRegisterCount(FixedArray* re, int value);
+  static int IrregexpNumberOfCaptures(FixedArray* re);
+  static int IrregexpNumberOfRegisters(FixedArray* re);
+  static ByteArray* IrregexpByteCode(FixedArray* re, bool is_ascii);
+  static Code* IrregexpNativeCode(FixedArray* re, bool is_ascii);
+
+ private:
+  static String* last_ascii_string_;
+  static String* two_byte_cached_string_;
+
+  static bool EnsureCompiledIrregexp(Handle<JSRegExp> re, bool is_ascii);
+
+
+  // Set the subject cache.  The previous string buffer is not deleted, so the
+  // caller should ensure that it doesn't leak.
+  static void SetSubjectCache(String* subject,
+                              char* utf8_subject,
+                              int uft8_length,
+                              int character_position,
+                              int utf8_position);
+
+  // A one element cache of the last utf8_subject string and its length.  The
+  // subject JS String object is cached in the heap.  We also cache a
+  // translation between position and utf8 position.
+  static char* utf8_subject_cache_;
+  static int utf8_length_cache_;
+  static int utf8_position_;
+  static int character_position_;
+};
+
+
+class CharacterRange {
+ public:
+  CharacterRange() : from_(0), to_(0) { }
+  // For compatibility with the CHECK_OK macro
+  CharacterRange(void* null) { ASSERT_EQ(NULL, null); }  //NOLINT
+  CharacterRange(uc16 from, uc16 to) : from_(from), to_(to) { }
+  static void AddClassEscape(uc16 type, ZoneList<CharacterRange>* ranges);
+  static Vector<const uc16> GetWordBounds();
+  static inline CharacterRange Singleton(uc16 value) {
+    return CharacterRange(value, value);
+  }
+  static inline CharacterRange Range(uc16 from, uc16 to) {
+    ASSERT(from <= to);
+    return CharacterRange(from, to);
+  }
+  static inline CharacterRange Everything() {
+    return CharacterRange(0, 0xFFFF);
+  }
+  bool Contains(uc16 i) { return from_ <= i && i <= to_; }
+  uc16 from() const { return from_; }
+  void set_from(uc16 value) { from_ = value; }
+  uc16 to() const { return to_; }
+  void set_to(uc16 value) { to_ = value; }
+  bool is_valid() { return from_ <= to_; }
+  bool IsEverything(uc16 max) { return from_ == 0 && to_ >= max; }
+  bool IsSingleton() { return (from_ == to_); }
+  void AddCaseEquivalents(ZoneList<CharacterRange>* ranges);
+  static void Split(ZoneList<CharacterRange>* base,
+                    Vector<const uc16> overlay,
+                    ZoneList<CharacterRange>** included,
+                    ZoneList<CharacterRange>** excluded);
+
+  static const int kRangeCanonicalizeMax = 0x346;
+  static const int kStartMarker = (1 << 24);
+  static const int kPayloadMask = (1 << 24) - 1;
+
+ private:
+  uc16 from_;
+  uc16 to_;
+};
+
+
+template <typename Node, class Callback>
+static void DoForEach(Node* node, Callback* callback);
+
+
+// A zone splay tree.  The config type parameter encapsulates the
+// different configurations of a concrete splay tree:
+//
+//   typedef Key: the key type
+//   typedef Value: the value type
+//   static const kNoKey: the dummy key used when no key is set
+//   static const kNoValue: the dummy value used to initialize nodes
+//   int (Compare)(Key& a, Key& b) -> {-1, 0, 1}: comparison function
+//
+template <typename Config>
+class ZoneSplayTree : public ZoneObject {
+ public:
+  typedef typename Config::Key Key;
+  typedef typename Config::Value Value;
+
+  class Locator;
+
+  ZoneSplayTree() : root_(NULL) { }
+
+  // Inserts the given key in this tree with the given value.  Returns
+  // true if a node was inserted, otherwise false.  If found the locator
+  // is enabled and provides access to the mapping for the key.
+  bool Insert(const Key& key, Locator* locator);
+
+  // Looks up the key in this tree and returns true if it was found,
+  // otherwise false.  If the node is found the locator is enabled and
+  // provides access to the mapping for the key.
+  bool Find(const Key& key, Locator* locator);
+
+  // Finds the mapping with the greatest key less than or equal to the
+  // given key.
+  bool FindGreatestLessThan(const Key& key, Locator* locator);
+
+  // Find the mapping with the greatest key in this tree.
+  bool FindGreatest(Locator* locator);
+
+  // Finds the mapping with the least key greater than or equal to the
+  // given key.
+  bool FindLeastGreaterThan(const Key& key, Locator* locator);
+
+  // Find the mapping with the least key in this tree.
+  bool FindLeast(Locator* locator);
+
+  // Remove the node with the given key from the tree.
+  bool Remove(const Key& key);
+
+  bool is_empty() { return root_ == NULL; }
+
+  // Perform the splay operation for the given key. Moves the node with
+  // the given key to the top of the tree.  If no node has the given
+  // key, the last node on the search path is moved to the top of the
+  // tree.
+  void Splay(const Key& key);
+
+  class Node : public ZoneObject {
+   public:
+    Node(const Key& key, const Value& value)
+        : key_(key),
+          value_(value),
+          left_(NULL),
+          right_(NULL) { }
+    Key key() { return key_; }
+    Value value() { return value_; }
+    Node* left() { return left_; }
+    Node* right() { return right_; }
+   private:
+    friend class ZoneSplayTree;
+    friend class Locator;
+    Key key_;
+    Value value_;
+    Node* left_;
+    Node* right_;
+  };
+
+  // A locator provides access to a node in the tree without actually
+  // exposing the node.
+  class Locator {
+   public:
+    explicit Locator(Node* node) : node_(node) { }
+    Locator() : node_(NULL) { }
+    const Key& key() { return node_->key_; }
+    Value& value() { return node_->value_; }
+    void set_value(const Value& value) { node_->value_ = value; }
+    inline void bind(Node* node) { node_ = node; }
+   private:
+    Node* node_;
+  };
+
+  template <class Callback>
+  void ForEach(Callback* c) {
+    DoForEach<typename ZoneSplayTree<Config>::Node, Callback>(root_, c);
+  }
+
+ private:
+  Node* root_;
+};
+
+
+// A set of unsigned integers that behaves especially well on small
+// integers (< 32).  May do zone-allocation.
+class OutSet: public ZoneObject {
+ public:
+  OutSet() : first_(0), remaining_(NULL), successors_(NULL) { }
+  OutSet* Extend(unsigned value);
+  bool Get(unsigned value);
+  static const unsigned kFirstLimit = 32;
+
+ private:
+  // Destructively set a value in this set.  In most cases you want
+  // to use Extend instead to ensure that only one instance exists
+  // that contains the same values.
+  void Set(unsigned value);
+
+  // The successors are a list of sets that contain the same values
+  // as this set and the one more value that is not present in this
+  // set.
+  ZoneList<OutSet*>* successors() { return successors_; }
+
+  OutSet(uint32_t first, ZoneList<unsigned>* remaining)
+      : first_(first), remaining_(remaining), successors_(NULL) { }
+  uint32_t first_;
+  ZoneList<unsigned>* remaining_;
+  ZoneList<OutSet*>* successors_;
+  friend class Trace;
+};
+
+
+// A mapping from integers, specified as ranges, to a set of integers.
+// Used for mapping character ranges to choices.
+class DispatchTable : public ZoneObject {
+ public:
+  class Entry {
+   public:
+    Entry() : from_(0), to_(0), out_set_(NULL) { }
+    Entry(uc16 from, uc16 to, OutSet* out_set)
+        : from_(from), to_(to), out_set_(out_set) { }
+    uc16 from() { return from_; }
+    uc16 to() { return to_; }
+    void set_to(uc16 value) { to_ = value; }
+    void AddValue(int value) { out_set_ = out_set_->Extend(value); }
+    OutSet* out_set() { return out_set_; }
+   private:
+    uc16 from_;
+    uc16 to_;
+    OutSet* out_set_;
+  };
+
+  class Config {
+   public:
+    typedef uc16 Key;
+    typedef Entry Value;
+    static const uc16 kNoKey;
+    static const Entry kNoValue;
+    static inline int Compare(uc16 a, uc16 b) {
+      if (a == b)
+        return 0;
+      else if (a < b)
+        return -1;
+      else
+        return 1;
+    }
+  };
+
+  void AddRange(CharacterRange range, int value);
+  OutSet* Get(uc16 value);
+  void Dump();
+
+  template <typename Callback>
+  void ForEach(Callback* callback) { return tree()->ForEach(callback); }
+ private:
+  // There can't be a static empty set since it allocates its
+  // successors in a zone and caches them.
+  OutSet* empty() { return &empty_; }
+  OutSet empty_;
+  ZoneSplayTree<Config>* tree() { return &tree_; }
+  ZoneSplayTree<Config> tree_;
+};
+
+
+#define FOR_EACH_NODE_TYPE(VISIT)                                    \
+  VISIT(End)                                                         \
+  VISIT(Action)                                                      \
+  VISIT(Choice)                                                      \
+  VISIT(BackReference)                                               \
+  VISIT(Assertion)                                                   \
+  VISIT(Text)
+
+
+#define FOR_EACH_REG_EXP_TREE_TYPE(VISIT)                            \
+  VISIT(Disjunction)                                                 \
+  VISIT(Alternative)                                                 \
+  VISIT(Assertion)                                                   \
+  VISIT(CharacterClass)                                              \
+  VISIT(Atom)                                                        \
+  VISIT(Quantifier)                                                  \
+  VISIT(Capture)                                                     \
+  VISIT(Lookahead)                                                   \
+  VISIT(BackReference)                                               \
+  VISIT(Empty)                                                       \
+  VISIT(Text)
+
+
+#define FORWARD_DECLARE(Name) class RegExp##Name;
+FOR_EACH_REG_EXP_TREE_TYPE(FORWARD_DECLARE)
+#undef FORWARD_DECLARE
+
+
+class TextElement {
+ public:
+  enum Type {UNINITIALIZED, ATOM, CHAR_CLASS};
+  TextElement() : type(UNINITIALIZED) { }
+  explicit TextElement(Type t) : type(t), cp_offset(-1) { }
+  static TextElement Atom(RegExpAtom* atom);
+  static TextElement CharClass(RegExpCharacterClass* char_class);
+  int length();
+  Type type;
+  union {
+    RegExpAtom* u_atom;
+    RegExpCharacterClass* u_char_class;
+  } data;
+  int cp_offset;
+};
+
+
+class Trace;
+
+
+struct NodeInfo {
+  NodeInfo()
+      : being_analyzed(false),
+        been_analyzed(false),
+        follows_word_interest(false),
+        follows_newline_interest(false),
+        follows_start_interest(false),
+        at_end(false),
+        visited(false) { }
+
+  // Returns true if the interests and assumptions of this node
+  // matches the given one.
+  bool Matches(NodeInfo* that) {
+    return (at_end == that->at_end) &&
+           (follows_word_interest == that->follows_word_interest) &&
+           (follows_newline_interest == that->follows_newline_interest) &&
+           (follows_start_interest == that->follows_start_interest);
+  }
+
+  // Updates the interests of this node given the interests of the
+  // node preceding it.
+  void AddFromPreceding(NodeInfo* that) {
+    at_end |= that->at_end;
+    follows_word_interest |= that->follows_word_interest;
+    follows_newline_interest |= that->follows_newline_interest;
+    follows_start_interest |= that->follows_start_interest;
+  }
+
+  bool HasLookbehind() {
+    return follows_word_interest ||
+           follows_newline_interest ||
+           follows_start_interest;
+  }
+
+  // Sets the interests of this node to include the interests of the
+  // following node.
+  void AddFromFollowing(NodeInfo* that) {
+    follows_word_interest |= that->follows_word_interest;
+    follows_newline_interest |= that->follows_newline_interest;
+    follows_start_interest |= that->follows_start_interest;
+  }
+
+  void ResetCompilationState() {
+    being_analyzed = false;
+    been_analyzed = false;
+  }
+
+  bool being_analyzed: 1;
+  bool been_analyzed: 1;
+
+  // These bits are set of this node has to know what the preceding
+  // character was.
+  bool follows_word_interest: 1;
+  bool follows_newline_interest: 1;
+  bool follows_start_interest: 1;
+
+  bool at_end: 1;
+  bool visited: 1;
+};
+
+
+class SiblingList {
+ public:
+  SiblingList() : list_(NULL) { }
+  int length() {
+    return list_ == NULL ? 0 : list_->length();
+  }
+  void Ensure(RegExpNode* parent) {
+    if (list_ == NULL) {
+      list_ = new ZoneList<RegExpNode*>(2);
+      list_->Add(parent);
+    }
+  }
+  void Add(RegExpNode* node) { list_->Add(node); }
+  RegExpNode* Get(int index) { return list_->at(index); }
+ private:
+  ZoneList<RegExpNode*>* list_;
+};
+
+
+// Details of a quick mask-compare check that can look ahead in the
+// input stream.
+class QuickCheckDetails {
+ public:
+  QuickCheckDetails()
+      : characters_(0),
+        mask_(0),
+        value_(0),
+        cannot_match_(false) { }
+  explicit QuickCheckDetails(int characters)
+      : characters_(characters),
+        mask_(0),
+        value_(0),
+        cannot_match_(false) { }
+  bool Rationalize(bool ascii);
+  // Merge in the information from another branch of an alternation.
+  void Merge(QuickCheckDetails* other, int from_index);
+  // Advance the current position by some amount.
+  void Advance(int by, bool ascii);
+  void Clear();
+  bool cannot_match() { return cannot_match_; }
+  void set_cannot_match() { cannot_match_ = true; }
+  struct Position {
+    Position() : mask(0), value(0), determines_perfectly(false) { }
+    uc16 mask;
+    uc16 value;
+    bool determines_perfectly;
+  };
+  int characters() { return characters_; }
+  void set_characters(int characters) { characters_ = characters; }
+  Position* positions(int index) {
+    ASSERT(index >= 0);
+    ASSERT(index < characters_);
+    return positions_ + index;
+  }
+  uint32_t mask() { return mask_; }
+  uint32_t value() { return value_; }
+
+ private:
+  // How many characters do we have quick check information from.  This is
+  // the same for all branches of a choice node.
+  int characters_;
+  Position positions_[4];
+  // These values are the condensate of the above array after Rationalize().
+  uint32_t mask_;
+  uint32_t value_;
+  // If set to true, there is no way this quick check can match at all.
+  // E.g., if it requires to be at the start of the input, and isn't.
+  bool cannot_match_;
+};
+
+
+class RegExpNode: public ZoneObject {
+ public:
+  RegExpNode() : trace_count_(0) { }
+  virtual ~RegExpNode();
+  virtual void Accept(NodeVisitor* visitor) = 0;
+  // Generates a goto to this node or actually generates the code at this point.
+  virtual void Emit(RegExpCompiler* compiler, Trace* trace) = 0;
+  // How many characters must this node consume at a minimum in order to
+  // succeed.  If we have found at least 'still_to_find' characters that
+  // must be consumed there is no need to ask any following nodes whether
+  // they are sure to eat any more characters.
+  virtual int EatsAtLeast(int still_to_find, int recursion_depth) = 0;
+  // Emits some quick code that checks whether the preloaded characters match.
+  // Falls through on certain failure, jumps to the label on possible success.
+  // If the node cannot make a quick check it does nothing and returns false.
+  bool EmitQuickCheck(RegExpCompiler* compiler,
+                      Trace* trace,
+                      bool preload_has_checked_bounds,
+                      Label* on_possible_success,
+                      QuickCheckDetails* details_return,
+                      bool fall_through_on_failure);
+  // For a given number of characters this returns a mask and a value.  The
+  // next n characters are anded with the mask and compared with the value.
+  // A comparison failure indicates the node cannot match the next n characters.
+  // A comparison success indicates the node may match.
+  virtual void GetQuickCheckDetails(QuickCheckDetails* details,
+                                    RegExpCompiler* compiler,
+                                    int characters_filled_in,
+                                    bool not_at_start) = 0;
+  static const int kNodeIsTooComplexForGreedyLoops = -1;
+  virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; }
+  Label* label() { return &label_; }
+  // If non-generic code is generated for a node (ie the node is not at the
+  // start of the trace) then it cannot be reused.  This variable sets a limit
+  // on how often we allow that to happen before we insist on starting a new
+  // trace and generating generic code for a node that can be reused by flushing
+  // the deferred actions in the current trace and generating a goto.
+  static const int kMaxCopiesCodeGenerated = 10;
+
+  NodeInfo* info() { return &info_; }
+
+  void AddSibling(RegExpNode* node) { siblings_.Add(node); }
+
+  // Static version of EnsureSibling that expresses the fact that the
+  // result has the same type as the input.
+  template <class C>
+  static C* EnsureSibling(C* node, NodeInfo* info, bool* cloned) {
+    return static_cast<C*>(node->EnsureSibling(info, cloned));
+  }
+
+  SiblingList* siblings() { return &siblings_; }
+  void set_siblings(SiblingList* other) { siblings_ = *other; }
+
+ protected:
+  enum LimitResult { DONE, CONTINUE };
+  LimitResult LimitVersions(RegExpCompiler* compiler, Trace* trace);
+
+  // Returns a sibling of this node whose interests and assumptions
+  // match the ones in the given node info.  If no sibling exists NULL
+  // is returned.
+  RegExpNode* TryGetSibling(NodeInfo* info);
+
+  // Returns a sibling of this node whose interests match the ones in
+  // the given node info.  The info must not contain any assertions.
+  // If no node exists a new one will be created by cloning the current
+  // node.  The result will always be an instance of the same concrete
+  // class as this node.
+  RegExpNode* EnsureSibling(NodeInfo* info, bool* cloned);
+
+  // Returns a clone of this node initialized using the copy constructor
+  // of its concrete class.  Note that the node may have to be pre-
+  // processed before it is on a usable state.
+  virtual RegExpNode* Clone() = 0;
+
+ private:
+  Label label_;
+  NodeInfo info_;
+  SiblingList siblings_;
+  // This variable keeps track of how many times code has been generated for
+  // this node (in different traces).  We don't keep track of where the
+  // generated code is located unless the code is generated at the start of
+  // a trace, in which case it is generic and can be reused by flushing the
+  // deferred operations in the current trace and generating a goto.
+  int trace_count_;
+};
+
+
+// A simple closed interval.
+class Interval {
+ public:
+  Interval() : from_(kNone), to_(kNone) { }
+  Interval(int from, int to) : from_(from), to_(to) { }
+  Interval Union(Interval that) {
+    if (that.from_ == kNone)
+      return *this;
+    else if (from_ == kNone)
+      return that;
+    else
+      return Interval(Min(from_, that.from_), Max(to_, that.to_));
+  }
+  bool Contains(int value) {
+    return (from_ <= value) && (value <= to_);
+  }
+  bool is_empty() { return from_ == kNone; }
+  int from() { return from_; }
+  int to() { return to_; }
+  static Interval Empty() { return Interval(); }
+  static const int kNone = -1;
+ private:
+  int from_;
+  int to_;
+};
+
+
+class SeqRegExpNode: public RegExpNode {
+ public:
+  explicit SeqRegExpNode(RegExpNode* on_success)
+      : on_success_(on_success) { }
+  RegExpNode* on_success() { return on_success_; }
+  void set_on_success(RegExpNode* node) { on_success_ = node; }
+ private:
+  RegExpNode* on_success_;
+};
+
+
+class ActionNode: public SeqRegExpNode {
+ public:
+  enum Type {
+    SET_REGISTER,
+    INCREMENT_REGISTER,
+    STORE_POSITION,
+    BEGIN_SUBMATCH,
+    POSITIVE_SUBMATCH_SUCCESS,
+    EMPTY_MATCH_CHECK,
+    CLEAR_CAPTURES
+  };
+  static ActionNode* SetRegister(int reg, int val, RegExpNode* on_success);
+  static ActionNode* IncrementRegister(int reg, RegExpNode* on_success);
+  static ActionNode* StorePosition(int reg,
+                                   bool is_capture,
+                                   RegExpNode* on_success);
+  static ActionNode* ClearCaptures(Interval range, RegExpNode* on_success);
+  static ActionNode* BeginSubmatch(int stack_pointer_reg,
+                                   int position_reg,
+                                   RegExpNode* on_success);
+  static ActionNode* PositiveSubmatchSuccess(int stack_pointer_reg,
+                                             int restore_reg,
+                                             int clear_capture_count,
+                                             int clear_capture_from,
+                                             RegExpNode* on_success);
+  static ActionNode* EmptyMatchCheck(int start_register,
+                                     int repetition_register,
+                                     int repetition_limit,
+                                     RegExpNode* on_success);
+  virtual void Accept(NodeVisitor* visitor);
+  virtual void Emit(RegExpCompiler* compiler, Trace* trace);
+  virtual int EatsAtLeast(int still_to_find, int recursion_depth);
+  virtual void GetQuickCheckDetails(QuickCheckDetails* details,
+                                    RegExpCompiler* compiler,
+                                    int filled_in,
+                                    bool not_at_start) {
+    return on_success()->GetQuickCheckDetails(
+        details, compiler, filled_in, not_at_start);
+  }
+  Type type() { return type_; }
+  // TODO(erikcorry): We should allow some action nodes in greedy loops.
+  virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; }
+  virtual ActionNode* Clone() { return new ActionNode(*this); }
+
+ private:
+  union {
+    struct {
+      int reg;
+      int value;
+    } u_store_register;
+    struct {
+      int reg;
+    } u_increment_register;
+    struct {
+      int reg;
+      bool is_capture;
+    } u_position_register;
+    struct {
+      int stack_pointer_register;
+      int current_position_register;
+      int clear_register_count;
+      int clear_register_from;
+    } u_submatch;
+    struct {
+      int start_register;
+      int repetition_register;
+      int repetition_limit;
+    } u_empty_match_check;
+    struct {
+      int range_from;
+      int range_to;
+    } u_clear_captures;
+  } data_;
+  ActionNode(Type type, RegExpNode* on_success)
+      : SeqRegExpNode(on_success),
+        type_(type) { }
+  Type type_;
+  friend class DotPrinter;
+};
+
+
+class TextNode: public SeqRegExpNode {
+ public:
+  TextNode(ZoneList<TextElement>* elms,
+           RegExpNode* on_success)
+      : SeqRegExpNode(on_success),
+        elms_(elms) { }
+  TextNode(RegExpCharacterClass* that,
+           RegExpNode* on_success)
+      : SeqRegExpNode(on_success),
+        elms_(new ZoneList<TextElement>(1)) {
+    elms_->Add(TextElement::CharClass(that));
+  }
+  virtual void Accept(NodeVisitor* visitor);
+  virtual void Emit(RegExpCompiler* compiler, Trace* trace);
+  virtual int EatsAtLeast(int still_to_find, int recursion_depth);
+  virtual void GetQuickCheckDetails(QuickCheckDetails* details,
+                                    RegExpCompiler* compiler,
+                                    int characters_filled_in,
+                                    bool not_at_start);
+  ZoneList<TextElement>* elements() { return elms_; }
+  void MakeCaseIndependent();
+  virtual int GreedyLoopTextLength();
+  virtual TextNode* Clone() {
+    TextNode* result = new TextNode(*this);
+    result->CalculateOffsets();
+    return result;
+  }
+  void CalculateOffsets();
+
+ private:
+  enum TextEmitPassType {
+    NON_ASCII_MATCH,             // Check for characters that can't match.
+    SIMPLE_CHARACTER_MATCH,      // Case-dependent single character check.
+    NON_LETTER_CHARACTER_MATCH,  // Check characters that have no case equivs.
+    CASE_CHARACTER_MATCH,        // Case-independent single character check.
+    CHARACTER_CLASS_MATCH        // Character class.
+  };
+  static bool SkipPass(int pass, bool ignore_case);
+  static const int kFirstRealPass = SIMPLE_CHARACTER_MATCH;
+  static const int kLastPass = CHARACTER_CLASS_MATCH;
+  void TextEmitPass(RegExpCompiler* compiler,
+                    TextEmitPassType pass,
+                    bool preloaded,
+                    Trace* trace,
+                    bool first_element_checked,
+                    int* checked_up_to);
+  int Length();
+  ZoneList<TextElement>* elms_;
+};
+
+
+class AssertionNode: public SeqRegExpNode {
+ public:
+  enum AssertionNodeType {
+    AT_END,
+    AT_START,
+    AT_BOUNDARY,
+    AT_NON_BOUNDARY,
+    AFTER_NEWLINE
+  };
+  static AssertionNode* AtEnd(RegExpNode* on_success) {
+    return new AssertionNode(AT_END, on_success);
+  }
+  static AssertionNode* AtStart(RegExpNode* on_success) {
+    return new AssertionNode(AT_START, on_success);
+  }
+  static AssertionNode* AtBoundary(RegExpNode* on_success) {
+    return new AssertionNode(AT_BOUNDARY, on_success);
+  }
+  static AssertionNode* AtNonBoundary(RegExpNode* on_success) {
+    return new AssertionNode(AT_NON_BOUNDARY, on_success);
+  }
+  static AssertionNode* AfterNewline(RegExpNode* on_success) {
+    return new AssertionNode(AFTER_NEWLINE, on_success);
+  }
+  virtual void Accept(NodeVisitor* visitor);
+  virtual void Emit(RegExpCompiler* compiler, Trace* trace);
+  virtual int EatsAtLeast(int still_to_find, int recursion_depth);
+  virtual void GetQuickCheckDetails(QuickCheckDetails* details,
+                                    RegExpCompiler* compiler,
+                                    int filled_in,
+                                    bool not_at_start);
+  virtual AssertionNode* Clone() { return new AssertionNode(*this); }
+  AssertionNodeType type() { return type_; }
+ private:
+  AssertionNode(AssertionNodeType t, RegExpNode* on_success)
+      : SeqRegExpNode(on_success), type_(t) { }
+  AssertionNodeType type_;
+};
+
+
+class BackReferenceNode: public SeqRegExpNode {
+ public:
+  BackReferenceNode(int start_reg,
+                    int end_reg,
+                    RegExpNode* on_success)
+      : SeqRegExpNode(on_success),
+        start_reg_(start_reg),
+        end_reg_(end_reg) { }
+  virtual void Accept(NodeVisitor* visitor);
+  int start_register() { return start_reg_; }
+  int end_register() { return end_reg_; }
+  virtual void Emit(RegExpCompiler* compiler, Trace* trace);
+  virtual int EatsAtLeast(int still_to_find, int recursion_depth);
+  virtual void GetQuickCheckDetails(QuickCheckDetails* details,
+                                    RegExpCompiler* compiler,
+                                    int characters_filled_in,
+                                    bool not_at_start) {
+    return;
+  }
+  virtual BackReferenceNode* Clone() { return new BackReferenceNode(*this); }
+
+ private:
+  int start_reg_;
+  int end_reg_;
+};
+
+
+class EndNode: public RegExpNode {
+ public:
+  enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS };
+  explicit EndNode(Action action) : action_(action) { }
+  virtual void Accept(NodeVisitor* visitor);
+  virtual void Emit(RegExpCompiler* compiler, Trace* trace);
+  virtual int EatsAtLeast(int still_to_find, int recursion_depth) { return 0; }
+  virtual void GetQuickCheckDetails(QuickCheckDetails* details,
+                                    RegExpCompiler* compiler,
+                                    int characters_filled_in,
+                                    bool not_at_start) {
+    // Returning 0 from EatsAtLeast should ensure we never get here.
+    UNREACHABLE();
+  }
+  virtual EndNode* Clone() { return new EndNode(*this); }
+
+ private:
+  Action action_;
+};
+
+
+class NegativeSubmatchSuccess: public EndNode {
+ public:
+  NegativeSubmatchSuccess(int stack_pointer_reg,
+                          int position_reg,
+                          int clear_capture_count,
+                          int clear_capture_start)
+      : EndNode(NEGATIVE_SUBMATCH_SUCCESS),
+        stack_pointer_register_(stack_pointer_reg),
+        current_position_register_(position_reg),
+        clear_capture_count_(clear_capture_count),
+        clear_capture_start_(clear_capture_start) { }
+  virtual void Emit(RegExpCompiler* compiler, Trace* trace);
+
+ private:
+  int stack_pointer_register_;
+  int current_position_register_;
+  int clear_capture_count_;
+  int clear_capture_start_;
+};
+
+
+class Guard: public ZoneObject {
+ public:
+  enum Relation { LT, GEQ };
+  Guard(int reg, Relation op, int value)
+      : reg_(reg),
+        op_(op),
+        value_(value) { }
+  int reg() { return reg_; }
+  Relation op() { return op_; }
+  int value() { return value_; }
+
+ private:
+  int reg_;
+  Relation op_;
+  int value_;
+};
+
+
+class GuardedAlternative {
+ public:
+  explicit GuardedAlternative(RegExpNode* node) : node_(node), guards_(NULL) { }
+  void AddGuard(Guard* guard);
+  RegExpNode* node() { return node_; }
+  void set_node(RegExpNode* node) { node_ = node; }
+  ZoneList<Guard*>* guards() { return guards_; }
+
+ private:
+  RegExpNode* node_;
+  ZoneList<Guard*>* guards_;
+};
+
+
+class AlternativeGeneration;
+
+
+class ChoiceNode: public RegExpNode {
+ public:
+  explicit ChoiceNode(int expected_size)
+      : alternatives_(new ZoneList<GuardedAlternative>(expected_size)),
+        table_(NULL),
+        not_at_start_(false),
+        being_calculated_(false) { }
+  virtual void Accept(NodeVisitor* visitor);
+  void AddAlternative(GuardedAlternative node) { alternatives()->Add(node); }
+  ZoneList<GuardedAlternative>* alternatives() { return alternatives_; }
+  DispatchTable* GetTable(bool ignore_case);
+  virtual void Emit(RegExpCompiler* compiler, Trace* trace);
+  virtual int EatsAtLeast(int still_to_find, int recursion_depth);
+  int EatsAtLeastHelper(int still_to_find,
+                        int recursion_depth,
+                        RegExpNode* ignore_this_node);
+  virtual void GetQuickCheckDetails(QuickCheckDetails* details,
+                                    RegExpCompiler* compiler,
+                                    int characters_filled_in,
+                                    bool not_at_start);
+  virtual ChoiceNode* Clone() { return new ChoiceNode(*this); }
+
+  bool being_calculated() { return being_calculated_; }
+  bool not_at_start() { return not_at_start_; }
+  void set_not_at_start() { not_at_start_ = true; }
+  void set_being_calculated(bool b) { being_calculated_ = b; }
+  virtual bool try_to_emit_quick_check_for_alternative(int i) { return true; }
+
+ protected:
+  int GreedyLoopTextLength(GuardedAlternative *alternative);
+  ZoneList<GuardedAlternative>* alternatives_;
+
+ private:
+  friend class DispatchTableConstructor;
+  friend class Analysis;
+  void GenerateGuard(RegExpMacroAssembler* macro_assembler,
+                     Guard *guard,
+                     Trace* trace);
+  int CalculatePreloadCharacters(RegExpCompiler* compiler);
+  void EmitOutOfLineContinuation(RegExpCompiler* compiler,
+                                 Trace* trace,
+                                 GuardedAlternative alternative,
+                                 AlternativeGeneration* alt_gen,
+                                 int preload_characters,
+                                 bool next_expects_preload);
+  DispatchTable* table_;
+  // If true, this node is never checked at the start of the input.
+  // Allows a new trace to start with at_start() set to false.
+  bool not_at_start_;
+  bool being_calculated_;
+};
+
+
+class NegativeLookaheadChoiceNode: public ChoiceNode {
+ public:
+  explicit NegativeLookaheadChoiceNode(GuardedAlternative this_must_fail,
+                                       GuardedAlternative then_do_this)
+      : ChoiceNode(2) {
+    AddAlternative(this_must_fail);
+    AddAlternative(then_do_this);
+  }
+  virtual int EatsAtLeast(int still_to_find, int recursion_depth);
+  virtual void GetQuickCheckDetails(QuickCheckDetails* details,
+                                    RegExpCompiler* compiler,
+                                    int characters_filled_in,
+                                    bool not_at_start);
+  // For a negative lookahead we don't emit the quick check for the
+  // alternative that is expected to fail.  This is because quick check code
+  // starts by loading enough characters for the alternative that takes fewest
+  // characters, but on a negative lookahead the negative branch did not take
+  // part in that calculation (EatsAtLeast) so the assumptions don't hold.
+  virtual bool try_to_emit_quick_check_for_alternative(int i) { return i != 0; }
+};
+
+
+class LoopChoiceNode: public ChoiceNode {
+ public:
+  explicit LoopChoiceNode(bool body_can_be_zero_length)
+      : ChoiceNode(2),
+        loop_node_(NULL),
+        continue_node_(NULL),
+        body_can_be_zero_length_(body_can_be_zero_length) { }
+  void AddLoopAlternative(GuardedAlternative alt);
+  void AddContinueAlternative(GuardedAlternative alt);
+  virtual void Emit(RegExpCompiler* compiler, Trace* trace);
+  virtual int EatsAtLeast(int still_to_find, int recursion_depth);
+  virtual void GetQuickCheckDetails(QuickCheckDetails* details,
+                                    RegExpCompiler* compiler,
+                                    int characters_filled_in,
+                                    bool not_at_start);
+  virtual LoopChoiceNode* Clone() { return new LoopChoiceNode(*this); }
+  RegExpNode* loop_node() { return loop_node_; }
+  RegExpNode* continue_node() { return continue_node_; }
+  bool body_can_be_zero_length() { return body_can_be_zero_length_; }
+  virtual void Accept(NodeVisitor* visitor);
+
+ private:
+  // AddAlternative is made private for loop nodes because alternatives
+  // should not be added freely, we need to keep track of which node
+  // goes back to the node itself.
+  void AddAlternative(GuardedAlternative node) {
+    ChoiceNode::AddAlternative(node);
+  }
+
+  RegExpNode* loop_node_;
+  RegExpNode* continue_node_;
+  bool body_can_be_zero_length_;
+};
+
+
+// There are many ways to generate code for a node.  This class encapsulates
+// the current way we should be generating.  In other words it encapsulates
+// the current state of the code generator.  The effect of this is that we
+// generate code for paths that the matcher can take through the regular
+// expression.  A given node in the regexp can be code-generated several times
+// as it can be part of several traces.  For example for the regexp:
+// /foo(bar|ip)baz/ the code to match baz will be generated twice, once as part
+// of the foo-bar-baz trace and once as part of the foo-ip-baz trace.  The code
+// to match foo is generated only once (the traces have a common prefix).  The
+// code to store the capture is deferred and generated (twice) after the places
+// where baz has been matched.
+class Trace {
+ public:
+  // A value for a property that is either known to be true, know to be false,
+  // or not known.
+  enum TriBool {
+    UNKNOWN = -1, FALSE = 0, TRUE = 1
+  };
+
+  class DeferredAction {
+   public:
+    DeferredAction(ActionNode::Type type, int reg)
+        : type_(type), reg_(reg), next_(NULL) { }
+    DeferredAction* next() { return next_; }
+    bool Mentions(int reg);
+    int reg() { return reg_; }
+    ActionNode::Type type() { return type_; }
+   private:
+    ActionNode::Type type_;
+    int reg_;
+    DeferredAction* next_;
+    friend class Trace;
+  };
+
+  class DeferredCapture : public DeferredAction {
+   public:
+    DeferredCapture(int reg, bool is_capture, Trace* trace)
+        : DeferredAction(ActionNode::STORE_POSITION, reg),
+          cp_offset_(trace->cp_offset()),
+          is_capture_(is_capture) { }
+    int cp_offset() { return cp_offset_; }
+    bool is_capture() { return is_capture_; }
+   private:
+    int cp_offset_;
+    bool is_capture_;
+    void set_cp_offset(int cp_offset) { cp_offset_ = cp_offset; }
+  };
+
+  class DeferredSetRegister : public DeferredAction {
+   public:
+    DeferredSetRegister(int reg, int value)
+        : DeferredAction(ActionNode::SET_REGISTER, reg),
+          value_(value) { }
+    int value() { return value_; }
+   private:
+    int value_;
+  };
+
+  class DeferredClearCaptures : public DeferredAction {
+   public:
+    explicit DeferredClearCaptures(Interval range)
+        : DeferredAction(ActionNode::CLEAR_CAPTURES, -1),
+          range_(range) { }
+    Interval range() { return range_; }
+   private:
+    Interval range_;
+  };
+
+  class DeferredIncrementRegister : public DeferredAction {
+   public:
+    explicit DeferredIncrementRegister(int reg)
+        : DeferredAction(ActionNode::INCREMENT_REGISTER, reg) { }
+  };
+
+  Trace()
+      : cp_offset_(0),
+        actions_(NULL),
+        backtrack_(NULL),
+        stop_node_(NULL),
+        loop_label_(NULL),
+        characters_preloaded_(0),
+        bound_checked_up_to_(0),
+        flush_budget_(100),
+        at_start_(UNKNOWN) { }
+
+  // End the trace.  This involves flushing the deferred actions in the trace
+  // and pushing a backtrack location onto the backtrack stack.  Once this is
+  // done we can start a new trace or go to one that has already been
+  // generated.
+  void Flush(RegExpCompiler* compiler, RegExpNode* successor);
+  int cp_offset() { return cp_offset_; }
+  DeferredAction* actions() { return actions_; }
+  // A trivial trace is one that has no deferred actions or other state that
+  // affects the assumptions used when generating code.  There is no recorded
+  // backtrack location in a trivial trace, so with a trivial trace we will
+  // generate code that, on a failure to match, gets the backtrack location
+  // from the backtrack stack rather than using a direct jump instruction.  We
+  // always start code generation with a trivial trace and non-trivial traces
+  // are created as we emit code for nodes or add to the list of deferred
+  // actions in the trace.  The location of the code generated for a node using
+  // a trivial trace is recorded in a label in the node so that gotos can be
+  // generated to that code.
+  bool is_trivial() {
+    return backtrack_ == NULL &&
+           actions_ == NULL &&
+           cp_offset_ == 0 &&
+           characters_preloaded_ == 0 &&
+           bound_checked_up_to_ == 0 &&
+           quick_check_performed_.characters() == 0 &&
+           at_start_ == UNKNOWN;
+  }
+  TriBool at_start() { return at_start_; }
+  void set_at_start(bool at_start) { at_start_ = at_start ? TRUE : FALSE; }
+  Label* backtrack() { return backtrack_; }
+  Label* loop_label() { return loop_label_; }
+  RegExpNode* stop_node() { return stop_node_; }
+  int characters_preloaded() { return characters_preloaded_; }
+  int bound_checked_up_to() { return bound_checked_up_to_; }
+  int flush_budget() { return flush_budget_; }
+  QuickCheckDetails* quick_check_performed() { return &quick_check_performed_; }
+  bool mentions_reg(int reg);
+  // Returns true if a deferred position store exists to the specified
+  // register and stores the offset in the out-parameter.  Otherwise
+  // returns false.
+  bool GetStoredPosition(int reg, int* cp_offset);
+  // These set methods and AdvanceCurrentPositionInTrace should be used only on
+  // new traces - the intention is that traces are immutable after creation.
+  void add_action(DeferredAction* new_action) {
+    ASSERT(new_action->next_ == NULL);
+    new_action->next_ = actions_;
+    actions_ = new_action;
+  }
+  void set_backtrack(Label* backtrack) { backtrack_ = backtrack; }
+  void set_stop_node(RegExpNode* node) { stop_node_ = node; }
+  void set_loop_label(Label* label) { loop_label_ = label; }
+  void set_characters_preloaded(int cpre) { characters_preloaded_ = cpre; }
+  void set_bound_checked_up_to(int to) { bound_checked_up_to_ = to; }
+  void set_flush_budget(int to) { flush_budget_ = to; }
+  void set_quick_check_performed(QuickCheckDetails* d) {
+    quick_check_performed_ = *d;
+  }
+  void InvalidateCurrentCharacter();
+  void AdvanceCurrentPositionInTrace(int by, RegExpCompiler* compiler);
+ private:
+  int FindAffectedRegisters(OutSet* affected_registers);
+  void PerformDeferredActions(RegExpMacroAssembler* macro,
+                               int max_register,
+                               OutSet& affected_registers,
+                               OutSet* registers_to_pop,
+                               OutSet* registers_to_clear);
+  void RestoreAffectedRegisters(RegExpMacroAssembler* macro,
+                                int max_register,
+                                OutSet& registers_to_pop,
+                                OutSet& registers_to_clear);
+  int cp_offset_;
+  DeferredAction* actions_;
+  Label* backtrack_;
+  RegExpNode* stop_node_;
+  Label* loop_label_;
+  int characters_preloaded_;
+  int bound_checked_up_to_;
+  QuickCheckDetails quick_check_performed_;
+  int flush_budget_;
+  TriBool at_start_;
+};
+
+
+class NodeVisitor {
+ public:
+  virtual ~NodeVisitor() { }
+#define DECLARE_VISIT(Type)                                          \
+  virtual void Visit##Type(Type##Node* that) = 0;
+FOR_EACH_NODE_TYPE(DECLARE_VISIT)
+#undef DECLARE_VISIT
+  virtual void VisitLoopChoice(LoopChoiceNode* that) { VisitChoice(that); }
+};
+
+
+// Node visitor used to add the start set of the alternatives to the
+// dispatch table of a choice node.
+class DispatchTableConstructor: public NodeVisitor {
+ public:
+  DispatchTableConstructor(DispatchTable* table, bool ignore_case)
+      : table_(table),
+        choice_index_(-1),
+        ignore_case_(ignore_case) { }
+
+  void BuildTable(ChoiceNode* node);
+
+  void AddRange(CharacterRange range) {
+    table()->AddRange(range, choice_index_);
+  }
+
+  void AddInverse(ZoneList<CharacterRange>* ranges);
+
+#define DECLARE_VISIT(Type)                                          \
+  virtual void Visit##Type(Type##Node* that);
+FOR_EACH_NODE_TYPE(DECLARE_VISIT)
+#undef DECLARE_VISIT
+
+  DispatchTable* table() { return table_; }
+  void set_choice_index(int value) { choice_index_ = value; }
+
+ protected:
+  DispatchTable *table_;
+  int choice_index_;
+  bool ignore_case_;
+};
+
+
+// Assertion propagation moves information about assertions such as
+// \b to the affected nodes.  For instance, in /.\b./ information must
+// be propagated to the first '.' that whatever follows needs to know
+// if it matched a word or a non-word, and to the second '.' that it
+// has to check if it succeeds a word or non-word.  In this case the
+// result will be something like:
+//
+//   +-------+        +------------+
+//   |   .   |        |      .     |
+//   +-------+  --->  +------------+
+//   | word? |        | check word |
+//   +-------+        +------------+
+class Analysis: public NodeVisitor {
+ public:
+  explicit Analysis(bool ignore_case)
+      : ignore_case_(ignore_case) { }
+  void EnsureAnalyzed(RegExpNode* node);
+
+#define DECLARE_VISIT(Type)                                          \
+  virtual void Visit##Type(Type##Node* that);
+FOR_EACH_NODE_TYPE(DECLARE_VISIT)
+#undef DECLARE_VISIT
+  virtual void VisitLoopChoice(LoopChoiceNode* that);
+
+ private:
+  bool ignore_case_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Analysis);
+};
+
+
+struct RegExpCompileData {
+  RegExpCompileData()
+    : tree(NULL),
+      node(NULL),
+      simple(true),
+      contains_anchor(false),
+      capture_count(0) { }
+  RegExpTree* tree;
+  RegExpNode* node;
+  bool simple;
+  bool contains_anchor;
+  Handle<String> error;
+  int capture_count;
+};
+
+
+class RegExpEngine: public AllStatic {
+ public:
+  struct CompilationResult {
+    explicit CompilationResult(const char* error_message)
+        : error_message(error_message),
+          code(Heap::the_hole_value()),
+          num_registers(0) {}
+    CompilationResult(Object* code, int registers)
+      : error_message(NULL),
+        code(code),
+        num_registers(registers) {}
+    const char* error_message;
+    Object* code;
+    int num_registers;
+  };
+
+  static CompilationResult Compile(RegExpCompileData* input,
+                                   bool ignore_case,
+                                   bool multiline,
+                                   Handle<String> pattern,
+                                   bool is_ascii);
+
+  static void DotPrint(const char* label, RegExpNode* node, bool ignore_case);
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_JSREGEXP_H_
diff --git a/deps/v8/src/jump-target-arm.cc b/deps/v8/src/jump-target-arm.cc
new file mode 100644
index 0000000..3ce5f30
--- /dev/null
+++ b/deps/v8/src/jump-target-arm.cc
@@ -0,0 +1,335 @@
+// Copyright 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.
+
+#include "v8.h"
+
+#include "codegen-inl.h"
+#include "register-allocator-inl.h"
+
+namespace v8 { namespace internal {
+
+// -------------------------------------------------------------------------
+// JumpTarget implementation.
+
+#define __ masm_->
+
+void JumpTarget::DoJump() {
+  ASSERT(cgen_ != NULL);
+  ASSERT(cgen_->has_valid_frame());
+  // Live non-frame registers are not allowed at unconditional jumps
+  // because we have no way of invalidating the corresponding results
+  // which are still live in the C++ code.
+  ASSERT(cgen_->HasValidEntryRegisters());
+
+  if (is_bound()) {
+    // Backward jump.  There is an expected frame to merge to.
+    ASSERT(direction_ == BIDIRECTIONAL);
+    cgen_->frame()->MergeTo(entry_frame_);
+    cgen_->DeleteFrame();
+    __ jmp(&entry_label_);
+  } else {
+    // Forward jump.  The current frame is added to the end of the list
+    // of frames reaching the target block and a jump to the merge code
+    // is emitted.
+    AddReachingFrame(cgen_->frame());
+    RegisterFile empty;
+    cgen_->SetFrame(NULL, &empty);
+    __ jmp(&merge_labels_.last());
+  }
+
+  is_linked_ = !is_bound_;
+}
+
+
+void JumpTarget::DoBranch(Condition cc, Hint ignored) {
+  ASSERT(cgen_ != NULL);
+  ASSERT(cgen_->has_valid_frame());
+
+  if (is_bound()) {
+    ASSERT(direction_ == BIDIRECTIONAL);
+    // Backward branch.  We have an expected frame to merge to on the
+    // backward edge.
+
+    // Swap the current frame for a copy (we do the swapping to get
+    // the off-frame registers off the fall through) to use for the
+    // branch.
+    VirtualFrame* fall_through_frame = cgen_->frame();
+    VirtualFrame* branch_frame = new VirtualFrame(fall_through_frame);
+    RegisterFile non_frame_registers = RegisterAllocator::Reserved();
+    cgen_->SetFrame(branch_frame, &non_frame_registers);
+
+    // Check if we can avoid merge code.
+    cgen_->frame()->PrepareMergeTo(entry_frame_);
+    if (cgen_->frame()->Equals(entry_frame_)) {
+      // Branch right in to the block.
+      cgen_->DeleteFrame();
+      __ b(cc, &entry_label_);
+      cgen_->SetFrame(fall_through_frame, &non_frame_registers);
+      return;
+    }
+
+    // Check if we can reuse existing merge code.
+    for (int i = 0; i < reaching_frames_.length(); i++) {
+      if (reaching_frames_[i] != NULL &&
+          cgen_->frame()->Equals(reaching_frames_[i])) {
+        // Branch to the merge code.
+        cgen_->DeleteFrame();
+        __ b(cc, &merge_labels_[i]);
+        cgen_->SetFrame(fall_through_frame, &non_frame_registers);
+        return;
+      }
+    }
+
+    // To emit the merge code here, we negate the condition and branch
+    // around the merge code on the fall through path.
+    Label original_fall_through;
+    __ b(NegateCondition(cc), &original_fall_through);
+    cgen_->frame()->MergeTo(entry_frame_);
+    cgen_->DeleteFrame();
+    __ b(&entry_label_);
+    cgen_->SetFrame(fall_through_frame, &non_frame_registers);
+    __ bind(&original_fall_through);
+
+  } else {
+    // Forward branch.  A copy of the current frame is added to the end
+    // of the list of frames reaching the target block and a branch to
+    // the merge code is emitted.
+    AddReachingFrame(new VirtualFrame(cgen_->frame()));
+    __ b(cc, &merge_labels_.last());
+    is_linked_ = true;
+  }
+}
+
+
+void JumpTarget::Call() {
+  // Call is used to push the address of the catch block on the stack as
+  // a return address when compiling try/catch and try/finally.  We
+  // fully spill the frame before making the call.  The expected frame
+  // at the label (which should be the only one) is the spilled current
+  // frame plus an in-memory return address.  The "fall-through" frame
+  // at the return site is the spilled current frame.
+  ASSERT(cgen_ != NULL);
+  ASSERT(cgen_->has_valid_frame());
+  // There are no non-frame references across the call.
+  ASSERT(cgen_->HasValidEntryRegisters());
+  ASSERT(!is_linked());
+
+  cgen_->frame()->SpillAll();
+  VirtualFrame* target_frame = new VirtualFrame(cgen_->frame());
+  target_frame->Adjust(1);
+  AddReachingFrame(target_frame);
+  __ bl(&merge_labels_.last());
+
+  is_linked_ = !is_bound_;
+}
+
+
+void JumpTarget::DoBind(int mergable_elements) {
+  ASSERT(cgen_ != NULL);
+  ASSERT(!is_bound());
+
+  // Live non-frame registers are not allowed at the start of a basic
+  // block.
+  ASSERT(!cgen_->has_valid_frame() || cgen_->HasValidEntryRegisters());
+
+  if (direction_ == FORWARD_ONLY) {
+    // A simple case: no forward jumps and no possible backward jumps.
+    if (!is_linked()) {
+      // The stack pointer can be floating above the top of the
+      // virtual frame before the bind.  Afterward, it should not.
+      ASSERT(cgen_->has_valid_frame());
+      VirtualFrame* frame = cgen_->frame();
+      int difference =
+          frame->stack_pointer_ - (frame->elements_.length() - 1);
+      if (difference > 0) {
+        frame->stack_pointer_ -= difference;
+        __ add(sp, sp, Operand(difference * kPointerSize));
+      }
+
+      is_bound_ = true;
+      return;
+    }
+
+    // Another simple case: no fall through, a single forward jump,
+    // and no possible backward jumps.
+    if (!cgen_->has_valid_frame() && reaching_frames_.length() == 1) {
+      // Pick up the only reaching frame, take ownership of it, and
+      // use it for the block about to be emitted.
+      VirtualFrame* frame = reaching_frames_[0];
+      RegisterFile reserved = RegisterAllocator::Reserved();
+      cgen_->SetFrame(frame, &reserved);
+      reaching_frames_[0] = NULL;
+      __ bind(&merge_labels_[0]);
+
+      // The stack pointer can be floating above the top of the
+      // virtual frame before the bind.  Afterward, it should not.
+      int difference =
+          frame->stack_pointer_ - (frame->elements_.length() - 1);
+      if (difference > 0) {
+        frame->stack_pointer_ -= difference;
+        __ add(sp, sp, Operand(difference * kPointerSize));
+      }
+
+      is_linked_ = false;
+      is_bound_ = true;
+      return;
+    }
+  }
+
+  // If there is a current frame, record it as the fall-through.  It
+  // is owned by the reaching frames for now.
+  bool had_fall_through = false;
+  if (cgen_->has_valid_frame()) {
+    had_fall_through = true;
+    AddReachingFrame(cgen_->frame());
+    RegisterFile empty;
+    cgen_->SetFrame(NULL, &empty);
+  }
+
+  // Compute the frame to use for entry to the block.
+  ComputeEntryFrame(mergable_elements);
+
+  // Some moves required to merge to an expected frame require purely
+  // frame state changes, and do not require any code generation.
+  // Perform those first to increase the possibility of finding equal
+  // frames below.
+  for (int i = 0; i < reaching_frames_.length(); i++) {
+    if (reaching_frames_[i] != NULL) {
+      reaching_frames_[i]->PrepareMergeTo(entry_frame_);
+    }
+  }
+
+  if (is_linked()) {
+    // There were forward jumps.  Handle merging the reaching frames
+    // and possible fall through to the entry frame.
+
+    // Loop over the (non-null) reaching frames and process any that
+    // need merge code.  Iterate backwards through the list to handle
+    // the fall-through frame first.  Set frames that will be
+    // processed after 'i' to NULL if we want to avoid processing
+    // them.
+    for (int i = reaching_frames_.length() - 1; i >= 0; i--) {
+      VirtualFrame* frame = reaching_frames_[i];
+
+      if (frame != NULL) {
+        // Does the frame (probably) need merge code?
+        if (!frame->Equals(entry_frame_)) {
+          // We could have a valid frame as the fall through to the
+          // binding site or as the fall through from a previous merge
+          // code block.  Jump around the code we are about to
+          // generate.
+          if (cgen_->has_valid_frame()) {
+            cgen_->DeleteFrame();
+            __ b(&entry_label_);
+          }
+          // Pick up the frame for this block.  Assume ownership if
+          // there cannot be backward jumps.
+          RegisterFile reserved = RegisterAllocator::Reserved();
+          if (direction_ == BIDIRECTIONAL) {
+            cgen_->SetFrame(new VirtualFrame(frame), &reserved);
+          } else {
+            cgen_->SetFrame(frame, &reserved);
+            reaching_frames_[i] = NULL;
+          }
+          __ bind(&merge_labels_[i]);
+
+          // Loop over the remaining (non-null) reaching frames,
+          // looking for any that can share merge code with this one.
+          for (int j = 0; j < i; j++) {
+            VirtualFrame* other = reaching_frames_[j];
+            if (other != NULL && other->Equals(cgen_->frame())) {
+              // Set the reaching frame element to null to avoid
+              // processing it later, and then bind its entry label.
+              delete other;
+              reaching_frames_[j] = NULL;
+              __ bind(&merge_labels_[j]);
+            }
+          }
+
+          // Emit the merge code.
+          cgen_->frame()->MergeTo(entry_frame_);
+        } else if (i == reaching_frames_.length() - 1 && had_fall_through) {
+          // If this is the fall through, and it didn't need merge
+          // code, we need to pick up the frame so we can jump around
+          // subsequent merge blocks if necessary.
+          RegisterFile reserved = RegisterAllocator::Reserved();
+          cgen_->SetFrame(frame, &reserved);
+          reaching_frames_[i] = NULL;
+        }
+      }
+    }
+
+    // The code generator may not have a current frame if there was no
+    // fall through and none of the reaching frames needed merging.
+    // In that case, clone the entry frame as the current frame.
+    if (!cgen_->has_valid_frame()) {
+      RegisterFile reserved_registers = RegisterAllocator::Reserved();
+      cgen_->SetFrame(new VirtualFrame(entry_frame_), &reserved_registers);
+    }
+
+    // There is certainly a current frame equal to the entry frame.
+    // Bind the entry frame label.
+    __ bind(&entry_label_);
+
+    // There may be unprocessed reaching frames that did not need
+    // merge code.  They will have unbound merge labels.  Bind their
+    // merge labels to be the same as the entry label and deallocate
+    // them.
+    for (int i = 0; i < reaching_frames_.length(); i++) {
+      if (!merge_labels_[i].is_bound()) {
+        delete reaching_frames_[i];
+        reaching_frames_[i] = NULL;
+        __ bind(&merge_labels_[i]);
+      }
+    }
+
+    // There are non-NULL reaching frames with bound labels for each
+    // merge block, but only on backward targets.
+  } else {
+    // There were no forward jumps.  There must be a current frame and
+    // this must be a bidirectional target.
+    ASSERT(reaching_frames_.length() == 1);
+    ASSERT(reaching_frames_[0] != NULL);
+    ASSERT(direction_ == BIDIRECTIONAL);
+
+    // Use a copy of the reaching frame so the original can be saved
+    // for possible reuse as a backward merge block.
+    RegisterFile reserved = RegisterAllocator::Reserved();
+    cgen_->SetFrame(new VirtualFrame(reaching_frames_[0]), &reserved);
+    __ bind(&merge_labels_[0]);
+    cgen_->frame()->MergeTo(entry_frame_);
+    __ bind(&entry_label_);
+  }
+
+  is_linked_ = false;
+  is_bound_ = true;
+}
+
+#undef __
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/jump-target-ia32.cc b/deps/v8/src/jump-target-ia32.cc
new file mode 100644
index 0000000..8afb0a8
--- /dev/null
+++ b/deps/v8/src/jump-target-ia32.cc
@@ -0,0 +1,335 @@
+// Copyright 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.
+
+#include "v8.h"
+
+#include "codegen-inl.h"
+#include "register-allocator-inl.h"
+
+namespace v8 { namespace internal {
+
+// -------------------------------------------------------------------------
+// JumpTarget implementation.
+
+#define __ masm_->
+
+void JumpTarget::DoJump() {
+  ASSERT(cgen_ != NULL);
+  ASSERT(cgen_->has_valid_frame());
+  // Live non-frame registers are not allowed at unconditional jumps
+  // because we have no way of invalidating the corresponding results
+  // which are still live in the C++ code.
+  ASSERT(cgen_->HasValidEntryRegisters());
+
+  if (is_bound()) {
+    // Backward jump.  There is an expected frame to merge to.
+    ASSERT(direction_ == BIDIRECTIONAL);
+    cgen_->frame()->MergeTo(entry_frame_);
+    cgen_->DeleteFrame();
+    __ jmp(&entry_label_);
+  } else {
+    // Forward jump.  The current frame is added to the end of the list
+    // of frames reaching the target block and a jump to the merge code
+    // is emitted.
+    AddReachingFrame(cgen_->frame());
+    RegisterFile empty;
+    cgen_->SetFrame(NULL, &empty);
+    __ jmp(&merge_labels_.last());
+  }
+
+  is_linked_ = !is_bound_;
+}
+
+
+void JumpTarget::DoBranch(Condition cc, Hint hint) {
+  ASSERT(cgen_ != NULL);
+  ASSERT(cgen_->has_valid_frame());
+
+  if (is_bound()) {
+    ASSERT(direction_ == BIDIRECTIONAL);
+    // Backward branch.  We have an expected frame to merge to on the
+    // backward edge.
+
+    // Swap the current frame for a copy (we do the swapping to get
+    // the off-frame registers off the fall through) to use for the
+    // branch.
+    VirtualFrame* fall_through_frame = cgen_->frame();
+    VirtualFrame* branch_frame = new VirtualFrame(fall_through_frame);
+    RegisterFile non_frame_registers = RegisterAllocator::Reserved();
+    cgen_->SetFrame(branch_frame, &non_frame_registers);
+
+    // Check if we can avoid merge code.
+    cgen_->frame()->PrepareMergeTo(entry_frame_);
+    if (cgen_->frame()->Equals(entry_frame_)) {
+      // Branch right in to the block.
+      cgen_->DeleteFrame();
+      __ j(cc, &entry_label_, hint);
+      cgen_->SetFrame(fall_through_frame, &non_frame_registers);
+      return;
+    }
+
+    // Check if we can reuse existing merge code.
+    for (int i = 0; i < reaching_frames_.length(); i++) {
+      if (reaching_frames_[i] != NULL &&
+          cgen_->frame()->Equals(reaching_frames_[i])) {
+        // Branch to the merge code.
+        cgen_->DeleteFrame();
+        __ j(cc, &merge_labels_[i], hint);
+        cgen_->SetFrame(fall_through_frame, &non_frame_registers);
+        return;
+      }
+    }
+
+    // To emit the merge code here, we negate the condition and branch
+    // around the merge code on the fall through path.
+    Label original_fall_through;
+    __ j(NegateCondition(cc), &original_fall_through, NegateHint(hint));
+    cgen_->frame()->MergeTo(entry_frame_);
+    cgen_->DeleteFrame();
+    __ jmp(&entry_label_);
+    cgen_->SetFrame(fall_through_frame, &non_frame_registers);
+    __ bind(&original_fall_through);
+
+  } else {
+    // Forward branch.  A copy of the current frame is added to the end
+    // of the list of frames reaching the target block and a branch to
+    // the merge code is emitted.
+    AddReachingFrame(new VirtualFrame(cgen_->frame()));
+    __ j(cc, &merge_labels_.last(), hint);
+    is_linked_ = true;
+  }
+}
+
+
+void JumpTarget::Call() {
+  // Call is used to push the address of the catch block on the stack as
+  // a return address when compiling try/catch and try/finally.  We
+  // fully spill the frame before making the call.  The expected frame
+  // at the label (which should be the only one) is the spilled current
+  // frame plus an in-memory return address.  The "fall-through" frame
+  // at the return site is the spilled current frame.
+  ASSERT(cgen_ != NULL);
+  ASSERT(cgen_->has_valid_frame());
+  // There are no non-frame references across the call.
+  ASSERT(cgen_->HasValidEntryRegisters());
+  ASSERT(!is_linked());
+
+  cgen_->frame()->SpillAll();
+  VirtualFrame* target_frame = new VirtualFrame(cgen_->frame());
+  target_frame->Adjust(1);
+  AddReachingFrame(target_frame);
+  __ call(&merge_labels_.last());
+
+  is_linked_ = !is_bound_;
+}
+
+
+void JumpTarget::DoBind(int mergable_elements) {
+  ASSERT(cgen_ != NULL);
+  ASSERT(!is_bound());
+
+  // Live non-frame registers are not allowed at the start of a basic
+  // block.
+  ASSERT(!cgen_->has_valid_frame() || cgen_->HasValidEntryRegisters());
+
+  if (direction_ == FORWARD_ONLY) {
+    // A simple case: no forward jumps and no possible backward jumps.
+    if (!is_linked()) {
+      // The stack pointer can be floating above the top of the
+      // virtual frame before the bind.  Afterward, it should not.
+      ASSERT(cgen_->has_valid_frame());
+      VirtualFrame* frame = cgen_->frame();
+      int difference =
+          frame->stack_pointer_ - (frame->elements_.length() - 1);
+      if (difference > 0) {
+        frame->stack_pointer_ -= difference;
+        __ add(Operand(esp), Immediate(difference * kPointerSize));
+      }
+
+      is_bound_ = true;
+      return;
+    }
+
+    // Another simple case: no fall through, a single forward jump,
+    // and no possible backward jumps.
+    if (!cgen_->has_valid_frame() && reaching_frames_.length() == 1) {
+      // Pick up the only reaching frame, take ownership of it, and
+      // use it for the block about to be emitted.
+      VirtualFrame* frame = reaching_frames_[0];
+      RegisterFile reserved = RegisterAllocator::Reserved();
+      cgen_->SetFrame(frame, &reserved);
+      reaching_frames_[0] = NULL;
+      __ bind(&merge_labels_[0]);
+
+      // The stack pointer can be floating above the top of the
+      // virtual frame before the bind.  Afterward, it should not.
+      int difference =
+          frame->stack_pointer_ - (frame->elements_.length() - 1);
+      if (difference > 0) {
+        frame->stack_pointer_ -= difference;
+        __ add(Operand(esp), Immediate(difference * kPointerSize));
+      }
+
+      is_linked_ = false;
+      is_bound_ = true;
+      return;
+    }
+  }
+
+  // If there is a current frame, record it as the fall-through.  It
+  // is owned by the reaching frames for now.
+  bool had_fall_through = false;
+  if (cgen_->has_valid_frame()) {
+    had_fall_through = true;
+    AddReachingFrame(cgen_->frame());
+    RegisterFile empty;
+    cgen_->SetFrame(NULL, &empty);
+  }
+
+  // Compute the frame to use for entry to the block.
+  ComputeEntryFrame(mergable_elements);
+
+  // Some moves required to merge to an expected frame require purely
+  // frame state changes, and do not require any code generation.
+  // Perform those first to increase the possibility of finding equal
+  // frames below.
+  for (int i = 0; i < reaching_frames_.length(); i++) {
+    if (reaching_frames_[i] != NULL) {
+      reaching_frames_[i]->PrepareMergeTo(entry_frame_);
+    }
+  }
+
+  if (is_linked()) {
+    // There were forward jumps.  Handle merging the reaching frames
+    // to the entry frame.
+
+    // Loop over the (non-null) reaching frames and process any that
+    // need merge code.  Iterate backwards through the list to handle
+    // the fall-through frame first.  Set frames that will be
+    // processed after 'i' to NULL if we want to avoid processing
+    // them.
+    for (int i = reaching_frames_.length() - 1; i >= 0; i--) {
+      VirtualFrame* frame = reaching_frames_[i];
+
+      if (frame != NULL) {
+        // Does the frame (probably) need merge code?
+        if (!frame->Equals(entry_frame_)) {
+          // We could have a valid frame as the fall through to the
+          // binding site or as the fall through from a previous merge
+          // code block.  Jump around the code we are about to
+          // generate.
+          if (cgen_->has_valid_frame()) {
+            cgen_->DeleteFrame();
+            __ jmp(&entry_label_);
+          }
+          // Pick up the frame for this block.  Assume ownership if
+          // there cannot be backward jumps.
+          RegisterFile reserved = RegisterAllocator::Reserved();
+          if (direction_ == BIDIRECTIONAL) {
+            cgen_->SetFrame(new VirtualFrame(frame), &reserved);
+          } else {
+            cgen_->SetFrame(frame, &reserved);
+            reaching_frames_[i] = NULL;
+          }
+          __ bind(&merge_labels_[i]);
+
+          // Loop over the remaining (non-null) reaching frames,
+          // looking for any that can share merge code with this one.
+          for (int j = 0; j < i; j++) {
+            VirtualFrame* other = reaching_frames_[j];
+            if (other != NULL && other->Equals(cgen_->frame())) {
+              // Set the reaching frame element to null to avoid
+              // processing it later, and then bind its entry label.
+              delete other;
+              reaching_frames_[j] = NULL;
+              __ bind(&merge_labels_[j]);
+            }
+          }
+
+          // Emit the merge code.
+          cgen_->frame()->MergeTo(entry_frame_);
+        } else if (i == reaching_frames_.length() - 1 && had_fall_through) {
+          // If this is the fall through frame, and it didn't need
+          // merge code, we need to pick up the frame so we can jump
+          // around subsequent merge blocks if necessary.
+          RegisterFile reserved = RegisterAllocator::Reserved();
+          cgen_->SetFrame(frame, &reserved);
+          reaching_frames_[i] = NULL;
+        }
+      }
+    }
+
+    // The code generator may not have a current frame if there was no
+    // fall through and none of the reaching frames needed merging.
+    // In that case, clone the entry frame as the current frame.
+    if (!cgen_->has_valid_frame()) {
+      RegisterFile reserved_registers = RegisterAllocator::Reserved();
+      cgen_->SetFrame(new VirtualFrame(entry_frame_), &reserved_registers);
+    }
+
+    // There is certainly a current frame equal to the entry frame.
+    // Bind the entry frame label.
+    __ bind(&entry_label_);
+
+    // There may be unprocessed reaching frames that did not need
+    // merge code.  They will have unbound merge labels.  Bind their
+    // merge labels to be the same as the entry label and deallocate
+    // them.
+    for (int i = 0; i < reaching_frames_.length(); i++) {
+      if (!merge_labels_[i].is_bound()) {
+        delete reaching_frames_[i];
+        reaching_frames_[i] = NULL;
+        __ bind(&merge_labels_[i]);
+      }
+    }
+
+    // There are non-NULL reaching frames with bound labels for each
+    // merge block, but only on backward targets.
+  } else {
+    // There were no forward jumps.  There must be a current frame and
+    // this must be a bidirectional target.
+    ASSERT(reaching_frames_.length() == 1);
+    ASSERT(reaching_frames_[0] != NULL);
+    ASSERT(direction_ == BIDIRECTIONAL);
+
+    // Use a copy of the reaching frame so the original can be saved
+    // for possible reuse as a backward merge block.
+    RegisterFile reserved = RegisterAllocator::Reserved();
+    cgen_->SetFrame(new VirtualFrame(reaching_frames_[0]), &reserved);
+    __ bind(&merge_labels_[0]);
+    cgen_->frame()->MergeTo(entry_frame_);
+    __ bind(&entry_label_);
+  }
+
+  is_linked_ = false;
+  is_bound_ = true;
+}
+
+#undef __
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/jump-target.cc b/deps/v8/src/jump-target.cc
new file mode 100644
index 0000000..047588b
--- /dev/null
+++ b/deps/v8/src/jump-target.cc
@@ -0,0 +1,731 @@
+// 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.
+
+#include "v8.h"
+
+#include "codegen-inl.h"
+#include "register-allocator-inl.h"
+
+namespace v8 { namespace internal {
+
+// -------------------------------------------------------------------------
+// JumpTarget implementation.
+
+JumpTarget::JumpTarget(CodeGenerator* cgen, Directionality direction)
+    : cgen_(cgen),
+      direction_(direction),
+      reaching_frames_(0),
+      merge_labels_(0),
+      entry_frame_(NULL),
+      is_bound_(false),
+      is_linked_(false) {
+  ASSERT(cgen != NULL);
+  masm_ = cgen->masm();
+}
+
+
+JumpTarget::JumpTarget()
+    : cgen_(NULL),
+      masm_(NULL),
+      direction_(FORWARD_ONLY),
+      reaching_frames_(0),
+      merge_labels_(0),
+      entry_frame_(NULL),
+      is_bound_(false),
+      is_linked_(false) {
+}
+
+
+void JumpTarget::Initialize(CodeGenerator* cgen, Directionality direction) {
+  ASSERT(cgen != NULL);
+  ASSERT(cgen_ == NULL);
+  cgen_ = cgen;
+  masm_ = cgen->masm();
+  direction_ = direction;
+}
+
+
+void JumpTarget::Unuse() {
+  // We should not deallocate jump targets that have unresolved jumps
+  // to them.  In the event of a compile-time stack overflow or an
+  // uninitialized jump target, we don't care.
+  ASSERT(!is_linked() || cgen_ == NULL || cgen_->HasStackOverflow());
+  for (int i = 0; i < reaching_frames_.length(); i++) {
+    delete reaching_frames_[i];
+  }
+  delete entry_frame_;
+  Reset();
+}
+
+
+void JumpTarget::Reset() {
+  reaching_frames_.Clear();
+  merge_labels_.Clear();
+  entry_frame_ = NULL;
+  entry_label_.Unuse();
+  is_bound_ = false;
+  is_linked_ = false;
+}
+
+
+FrameElement* JumpTarget::Combine(FrameElement* left, FrameElement* right) {
+  // Given a pair of non-null frame element pointers, return one of
+  // them as an entry frame candidate or null if they are
+  // incompatible.
+
+  // If either is invalid, the result is.
+  if (!left->is_valid()) return left;
+  if (!right->is_valid()) return right;
+
+  // If they have the same value, the result is the same.  If either
+  // is unsynced, the result is.
+
+  if (left->is_memory() && right->is_memory()) return left;
+
+  if (left->is_register() && right->is_register() &&
+      left->reg().is(right->reg())) {
+    if (!left->is_synced()) {
+      return left;
+    } else {
+      return right;
+    }
+  }
+
+  if (left->is_constant() &&
+      right->is_constant() &&
+      left->handle().is_identical_to(right->handle())) {
+    if (!left->is_synced()) {
+      return left;
+    } else {
+      return right;
+    }
+  }
+
+  if (left->is_copy() &&
+      right->is_copy() &&
+      left->index() == right->index()) {
+    if (!left->is_synced()) {
+      return left;
+    } else {
+      return right;
+    }
+  }
+
+  // Otherwise they are incompatible and we will reallocate them.
+  return NULL;
+}
+
+
+void JumpTarget::ComputeEntryFrame(int mergable_elements) {
+  // Given: a collection of frames reaching by forward CFG edges and
+  // the directionality of the block.  Compute: an entry frame for the
+  // block.
+
+  // Choose an initial frame.
+  VirtualFrame* initial_frame = reaching_frames_[0];
+
+  // A list of pointers to frame elements in the entry frame.  NULL
+  // indicates that the element has not yet been determined.
+  int length = initial_frame->elements_.length();
+  List<FrameElement*> elements(length);
+
+  // Convert the number of mergable elements (counted from the top
+  // down) to a frame high-water mark (counted from the bottom up).
+  // Elements strictly above the high-water index will be mergable in
+  // entry frames for bidirectional jump targets.
+  int high_water_mark = (mergable_elements == kAllElements)
+      ? VirtualFrame::kIllegalIndex  // All frame indices are above this.
+      : length - mergable_elements - 1;  // Top index if m_e == 0.
+
+  // Initially populate the list of elements based on the initial
+  // frame.
+  for (int i = 0; i < length; i++) {
+    FrameElement element = initial_frame->elements_[i];
+    // We do not allow copies or constants in bidirectional frames.
+    if (direction_ == BIDIRECTIONAL && i > high_water_mark &&
+        (element.is_constant() || element.is_copy())) {
+      elements.Add(NULL);
+    } else {
+      elements.Add(&initial_frame->elements_[i]);
+    }
+  }
+
+  // Compute elements based on the other reaching frames.
+  if (reaching_frames_.length() > 1) {
+    for (int i = 0; i < length; i++) {
+      for (int j = 1; j < reaching_frames_.length(); j++) {
+        FrameElement* element = elements[i];
+
+        // Element computation is monotonic: new information will not
+        // change our decision about undetermined or invalid elements.
+        if (element == NULL || !element->is_valid()) break;
+
+        elements[i] = Combine(element, &reaching_frames_[j]->elements_[i]);
+      }
+    }
+  }
+
+  // Compute the registers already reserved by values in the frame.
+  // Count the reserved registers to avoid using them.
+  RegisterFile frame_registers = RegisterAllocator::Reserved();
+  for (int i = 0; i < length; i++) {
+    FrameElement* element = elements[i];
+    if (element != NULL && element->is_register()) {
+      frame_registers.Use(element->reg());
+    }
+  }
+
+  // Build the new frame.  The frame already has memory elements for
+  // the parameters (including the receiver) and the return address.
+  // We will fill it up with memory elements.
+  entry_frame_ = new VirtualFrame(cgen_);
+  while (entry_frame_->elements_.length() < length) {
+    entry_frame_->elements_.Add(FrameElement::MemoryElement());
+  }
+
+
+  // Copy the already-determined frame elements to the entry frame,
+  // and allocate any still-undetermined frame elements to registers
+  // or memory, from the top down.
+  for (int i = length - 1; i >= 0; i--) {
+    if (elements[i] == NULL) {
+      // If the value is synced on all frames, put it in memory.  This
+      // costs nothing at the merge code but will incur a
+      // memory-to-register move when the value is needed later.
+      bool is_synced = true;
+      for (int j = 0; is_synced && j < reaching_frames_.length(); j++) {
+        is_synced = reaching_frames_[j]->elements_[i].is_synced();
+      }
+
+      // There is nothing to be done if the elements are all synced.
+      // It is already recorded as a memory element.
+      if (is_synced) continue;
+
+      // Choose an available register.  Prefer ones that the element
+      // is already occupying on some reaching frame.
+      RegisterFile candidate_registers;
+      int max_count = kMinInt;
+      int best_reg_code = no_reg.code_;
+
+      for (int j = 0; j < reaching_frames_.length(); j++) {
+        FrameElement element = reaching_frames_[j]->elements_[i];
+        if (element.is_register() &&
+            !frame_registers.is_used(element.reg())) {
+          candidate_registers.Use(element.reg());
+          if (candidate_registers.count(element.reg()) > max_count) {
+            max_count = candidate_registers.count(element.reg());
+            best_reg_code = element.reg().code();
+          }
+        }
+      }
+      // If there was no preferred choice consider any free register.
+      if (best_reg_code == no_reg.code_) {
+        for (int j = 0; j < kNumRegisters; j++) {
+          if (!frame_registers.is_used(j)) {
+            best_reg_code = j;
+            break;
+          }
+        }
+      }
+
+      // If there was a register choice, use it.  If not do nothing
+      // (the element is already recorded as in memory)
+      if (best_reg_code != no_reg.code_) {
+        Register reg = { best_reg_code };
+        frame_registers.Use(reg);
+        entry_frame_->elements_[i] =
+            FrameElement::RegisterElement(reg,
+                                          FrameElement::NOT_SYNCED);
+      }
+    } else {
+      // The element is already determined.
+      entry_frame_->elements_[i] = *elements[i];
+    }
+  }
+
+  // Set the copied flags in the frame to be exact.  This assumes that
+  // the backing store of copies is always lower in the frame.
+  // Set the register locations to their index in the frame.
+  for (int i = 0; i < length; i++) {
+    FrameElement* current = &entry_frame_->elements_[i];
+    current->clear_copied();
+    if (current->is_copy()) {
+      entry_frame_->elements_[current->index()].set_copied();
+    } else if (current->is_register()) {
+      entry_frame_->register_locations_[current->reg().code()] = i;
+    }
+
+    if (direction_ == BIDIRECTIONAL && i >= high_water_mark) {
+      current->set_static_type(StaticType::unknown());
+    } else {
+      StaticType merged_type = reaching_frames_[0]->elements_[i].static_type();
+      for (int j = 1, n = reaching_frames_.length();
+           !merged_type.is_unknown() && j < n;
+           j++) {
+        merged_type =
+            merged_type.merge(reaching_frames_[j]->elements_[i].static_type());
+      }
+      current->set_static_type(merged_type);
+    }
+  }
+
+  // Fill in the other fields of the entry frame.
+  entry_frame_->local_count_ = initial_frame->local_count_;
+  entry_frame_->frame_pointer_ = initial_frame->frame_pointer_;
+
+  // The stack pointer is at the highest synced element or the base of
+  // the expression stack.
+  int stack_pointer = length - 1;
+  while (stack_pointer >= entry_frame_->expression_base_index() &&
+         !entry_frame_->elements_[stack_pointer].is_synced()) {
+    stack_pointer--;
+  }
+  entry_frame_->stack_pointer_ = stack_pointer;
+}
+
+
+void JumpTarget::Jump() {
+  DoJump();
+}
+
+
+void JumpTarget::Jump(Result* arg) {
+  ASSERT(cgen_ != NULL);
+  ASSERT(cgen_->has_valid_frame());
+
+  cgen_->frame()->Push(arg);
+  DoJump();
+}
+
+
+void JumpTarget::Jump(Result* arg0, Result* arg1) {
+  ASSERT(cgen_ != NULL);
+  ASSERT(cgen_->has_valid_frame());
+
+  cgen_->frame()->Push(arg0);
+  cgen_->frame()->Push(arg1);
+  DoJump();
+}
+
+
+void JumpTarget::Jump(Result* arg0, Result* arg1, Result* arg2) {
+  ASSERT(cgen_ != NULL);
+  ASSERT(cgen_->has_valid_frame());
+
+  cgen_->frame()->Push(arg0);
+  cgen_->frame()->Push(arg1);
+  cgen_->frame()->Push(arg2);
+  DoJump();
+}
+
+
+void JumpTarget::Branch(Condition cc, Hint hint) {
+  DoBranch(cc, hint);
+}
+
+
+#ifdef DEBUG
+#define DECLARE_ARGCHECK_VARS(name)                                \
+  Result::Type name##_type = name->type();                         \
+  Register name##_reg = name->is_register() ? name->reg() : no_reg
+
+#define ASSERT_ARGCHECK(name)                                \
+  ASSERT(name->type() == name##_type);                       \
+  ASSERT(!name->is_register() || name->reg().is(name##_reg))
+
+#else
+#define DECLARE_ARGCHECK_VARS(name) do {} while (false)
+
+#define ASSERT_ARGCHECK(name) do {} while (false)
+#endif
+
+void JumpTarget::Branch(Condition cc, Result* arg, Hint hint) {
+  ASSERT(cgen_ != NULL);
+  ASSERT(cgen_->has_valid_frame());
+
+  // We want to check that non-frame registers at the call site stay in
+  // the same registers on the fall-through branch.
+  DECLARE_ARGCHECK_VARS(arg);
+
+  cgen_->frame()->Push(arg);
+  DoBranch(cc, hint);
+  *arg = cgen_->frame()->Pop();
+
+  ASSERT_ARGCHECK(arg);
+}
+
+
+void JumpTarget::Branch(Condition cc, Result* arg0, Result* arg1, Hint hint) {
+  ASSERT(cgen_ != NULL);
+  ASSERT(cgen_->frame() != NULL);
+
+  // We want to check that non-frame registers at the call site stay in
+  // the same registers on the fall-through branch.
+  DECLARE_ARGCHECK_VARS(arg0);
+  DECLARE_ARGCHECK_VARS(arg1);
+
+  cgen_->frame()->Push(arg0);
+  cgen_->frame()->Push(arg1);
+  DoBranch(cc, hint);
+  *arg1 = cgen_->frame()->Pop();
+  *arg0 = cgen_->frame()->Pop();
+
+  ASSERT_ARGCHECK(arg0);
+  ASSERT_ARGCHECK(arg1);
+}
+
+
+void JumpTarget::Branch(Condition cc,
+                        Result* arg0,
+                        Result* arg1,
+                        Result* arg2,
+                        Hint hint) {
+  ASSERT(cgen_ != NULL);
+  ASSERT(cgen_->frame() != NULL);
+
+  // We want to check that non-frame registers at the call site stay in
+  // the same registers on the fall-through branch.
+  DECLARE_ARGCHECK_VARS(arg0);
+  DECLARE_ARGCHECK_VARS(arg1);
+  DECLARE_ARGCHECK_VARS(arg2);
+
+  cgen_->frame()->Push(arg0);
+  cgen_->frame()->Push(arg1);
+  cgen_->frame()->Push(arg2);
+  DoBranch(cc, hint);
+  *arg2 = cgen_->frame()->Pop();
+  *arg1 = cgen_->frame()->Pop();
+  *arg0 = cgen_->frame()->Pop();
+
+  ASSERT_ARGCHECK(arg0);
+  ASSERT_ARGCHECK(arg1);
+  ASSERT_ARGCHECK(arg2);
+}
+
+
+void JumpTarget::Branch(Condition cc,
+                        Result* arg0,
+                        Result* arg1,
+                        Result* arg2,
+                        Result* arg3,
+                        Hint hint) {
+  ASSERT(cgen_ != NULL);
+  ASSERT(cgen_->frame() != NULL);
+
+  // We want to check that non-frame registers at the call site stay in
+  // the same registers on the fall-through branch.
+  DECLARE_ARGCHECK_VARS(arg0);
+  DECLARE_ARGCHECK_VARS(arg1);
+  DECLARE_ARGCHECK_VARS(arg2);
+  DECLARE_ARGCHECK_VARS(arg3);
+
+  cgen_->frame()->Push(arg0);
+  cgen_->frame()->Push(arg1);
+  cgen_->frame()->Push(arg2);
+  cgen_->frame()->Push(arg3);
+  DoBranch(cc, hint);
+  *arg3 = cgen_->frame()->Pop();
+  *arg2 = cgen_->frame()->Pop();
+  *arg1 = cgen_->frame()->Pop();
+  *arg0 = cgen_->frame()->Pop();
+
+  ASSERT_ARGCHECK(arg0);
+  ASSERT_ARGCHECK(arg1);
+  ASSERT_ARGCHECK(arg2);
+  ASSERT_ARGCHECK(arg3);
+}
+
+
+void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) {
+  ASSERT(cgen_ != NULL);
+  ASSERT(cgen_->has_valid_frame());
+
+  int count = cgen_->frame()->height() - expected_height_;
+  if (count > 0) {
+    // We negate and branch here rather than using DoBranch's negate
+    // and branch.  This gives us a hook to remove statement state
+    // from the frame.
+    JumpTarget fall_through(cgen_);
+    // Branch to fall through will not negate, because it is a
+    // forward-only target.
+    fall_through.Branch(NegateCondition(cc), NegateHint(hint));
+    Jump(arg);  // May emit merge code here.
+    fall_through.Bind();
+  } else {
+    DECLARE_ARGCHECK_VARS(arg);
+    cgen_->frame()->Push(arg);
+    DoBranch(cc, hint);
+    *arg = cgen_->frame()->Pop();
+    ASSERT_ARGCHECK(arg);
+  }
+}
+
+#undef DECLARE_ARGCHECK_VARS
+#undef ASSERT_ARGCHECK
+
+
+void JumpTarget::Bind(int mergable_elements) {
+  DoBind(mergable_elements);
+}
+
+
+void JumpTarget::Bind(Result* arg, int mergable_elements) {
+  ASSERT(cgen_ != NULL);
+
+  if (cgen_->has_valid_frame()) {
+    cgen_->frame()->Push(arg);
+  }
+  DoBind(mergable_elements);
+  *arg = cgen_->frame()->Pop();
+}
+
+
+void JumpTarget::Bind(Result* arg0, Result* arg1, int mergable_elements) {
+  ASSERT(cgen_ != NULL);
+
+  if (cgen_->has_valid_frame()) {
+    cgen_->frame()->Push(arg0);
+    cgen_->frame()->Push(arg1);
+  }
+  DoBind(mergable_elements);
+  *arg1 = cgen_->frame()->Pop();
+  *arg0 = cgen_->frame()->Pop();
+}
+
+
+void JumpTarget::Bind(Result* arg0,
+                      Result* arg1,
+                      Result* arg2,
+                      int mergable_elements) {
+  ASSERT(cgen_ != NULL);
+
+  if (cgen_->has_valid_frame()) {
+    cgen_->frame()->Push(arg0);
+    cgen_->frame()->Push(arg1);
+    cgen_->frame()->Push(arg2);
+  }
+  DoBind(mergable_elements);
+  *arg2 = cgen_->frame()->Pop();
+  *arg1 = cgen_->frame()->Pop();
+  *arg0 = cgen_->frame()->Pop();
+}
+
+
+void JumpTarget::Bind(Result* arg0,
+                      Result* arg1,
+                      Result* arg2,
+                      Result* arg3,
+                      int mergable_elements) {
+  ASSERT(cgen_ != NULL);
+
+  if (cgen_->has_valid_frame()) {
+    cgen_->frame()->Push(arg0);
+    cgen_->frame()->Push(arg1);
+    cgen_->frame()->Push(arg2);
+    cgen_->frame()->Push(arg3);
+  }
+  DoBind(mergable_elements);
+  *arg3 = cgen_->frame()->Pop();
+  *arg2 = cgen_->frame()->Pop();
+  *arg1 = cgen_->frame()->Pop();
+  *arg0 = cgen_->frame()->Pop();
+}
+
+
+void JumpTarget::AddReachingFrame(VirtualFrame* frame) {
+  ASSERT(reaching_frames_.length() == merge_labels_.length());
+  Label fresh;
+  merge_labels_.Add(fresh);
+  reaching_frames_.Add(frame);
+}
+
+
+// -------------------------------------------------------------------------
+// BreakTarget implementation.
+
+void BreakTarget::Initialize(CodeGenerator* cgen, Directionality direction) {
+  JumpTarget::Initialize(cgen, direction);
+  ASSERT(cgen_->has_valid_frame());
+  expected_height_ = cgen_->frame()->height();
+}
+
+
+void BreakTarget::CopyTo(BreakTarget* destination) {
+  ASSERT(destination != NULL);
+  destination->cgen_ = cgen_;
+  destination->masm_ = masm_;
+  destination->direction_ = direction_;
+  destination->reaching_frames_.Clear();
+  destination->merge_labels_.Clear();
+  ASSERT(reaching_frames_.length() == merge_labels_.length());
+  for (int i = 0; i < reaching_frames_.length(); i++) {
+    destination->reaching_frames_.Add(reaching_frames_[i]);
+    destination->merge_labels_.Add(merge_labels_[i]);
+  }
+  destination->entry_frame_ = entry_frame_;
+  destination->entry_label_ = entry_label_;
+  destination->is_bound_ = is_bound_;
+  destination->is_linked_ = is_linked_;
+  destination->expected_height_ = expected_height_;
+}
+
+
+void BreakTarget::Jump() {
+  ASSERT(cgen_ != NULL);
+  ASSERT(cgen_->has_valid_frame());
+
+  // Drop leftover statement state from the frame before merging.
+  cgen_->frame()->ForgetElements(cgen_->frame()->height() - expected_height_);
+  DoJump();
+}
+
+
+void BreakTarget::Jump(Result* arg) {
+  ASSERT(cgen_ != NULL);
+  ASSERT(cgen_->has_valid_frame());
+
+  // Drop leftover statement state from the frame before merging.
+  cgen_->frame()->ForgetElements(cgen_->frame()->height() - expected_height_);
+  cgen_->frame()->Push(arg);
+  DoJump();
+}
+
+
+void BreakTarget::Branch(Condition cc, Hint hint) {
+  ASSERT(cgen_ != NULL);
+  ASSERT(cgen_->has_valid_frame());
+
+  int count = cgen_->frame()->height() - expected_height_;
+  if (count > 0) {
+    // We negate and branch here rather than using DoBranch's negate
+    // and branch.  This gives us a hook to remove statement state
+    // from the frame.
+    JumpTarget fall_through(cgen_);
+    // Branch to fall through will not negate, because it is a
+    // forward-only target.
+    fall_through.Branch(NegateCondition(cc), NegateHint(hint));
+    Jump();  // May emit merge code here.
+    fall_through.Bind();
+  } else {
+    DoBranch(cc, hint);
+  }
+}
+
+
+void BreakTarget::Bind(int mergable_elements) {
+#ifdef DEBUG
+  ASSERT(cgen_ != NULL);
+  // All the forward-reaching frames should have been adjusted at the
+  // jumps to this target.
+  for (int i = 0; i < reaching_frames_.length(); i++) {
+    ASSERT(reaching_frames_[i] == NULL ||
+           reaching_frames_[i]->height() == expected_height_);
+  }
+#endif
+  // Drop leftover statement state from the frame before merging, even
+  // on the fall through.  This is so we can bind the return target
+  // with state on the frame.
+  if (cgen_->has_valid_frame()) {
+    cgen_->frame()->ForgetElements(cgen_->frame()->height() - expected_height_);
+  }
+  DoBind(mergable_elements);
+}
+
+
+void BreakTarget::Bind(Result* arg, int mergable_elements) {
+#ifdef DEBUG
+  ASSERT(cgen_ != NULL);
+  // All the forward-reaching frames should have been adjusted at the
+  // jumps to this target.
+  for (int i = 0; i < reaching_frames_.length(); i++) {
+    ASSERT(reaching_frames_[i] == NULL ||
+           reaching_frames_[i]->height() == expected_height_ + 1);
+  }
+#endif
+  // Drop leftover statement state from the frame before merging, even
+  // on the fall through.  This is so we can bind the return target
+  // with state on the frame.
+  if (cgen_->has_valid_frame()) {
+    cgen_->frame()->ForgetElements(cgen_->frame()->height() - expected_height_);
+    cgen_->frame()->Push(arg);
+  }
+  DoBind(mergable_elements);
+  *arg = cgen_->frame()->Pop();
+}
+
+
+// -------------------------------------------------------------------------
+// ShadowTarget implementation.
+
+ShadowTarget::ShadowTarget(BreakTarget* shadowed) {
+  ASSERT(shadowed != NULL);
+  other_target_ = shadowed;
+
+#ifdef DEBUG
+  is_shadowing_ = true;
+#endif
+  // While shadowing this shadow target saves the state of the original.
+  shadowed->CopyTo(this);
+
+  // The original's state is reset.  We do not Unuse it because that
+  // would delete the expected frame and assert that the target is not
+  // linked.
+  shadowed->Reset();
+  ASSERT(cgen_ != NULL);
+  ASSERT(cgen_->has_valid_frame());
+  shadowed->set_expected_height(cgen_->frame()->height());
+
+  // Setting the code generator to null prevents the shadow target from
+  // being used until shadowing stops.
+  cgen_ = NULL;
+  masm_ = NULL;
+}
+
+
+void ShadowTarget::StopShadowing() {
+  ASSERT(is_shadowing_);
+
+  // This target does not have a valid code generator yet.
+  cgen_ = other_target_->code_generator();
+  ASSERT(cgen_ != NULL);
+  masm_ = cgen_->masm();
+
+  // The states of this target, which was shadowed, and the original
+  // target, which was shadowing, are swapped.
+  BreakTarget temp;
+  other_target_->CopyTo(&temp);
+  CopyTo(other_target_);
+  temp.CopyTo(this);
+  temp.Reset();  // So the destructor does not deallocate virtual frames.
+
+#ifdef DEBUG
+  is_shadowing_ = false;
+#endif
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/jump-target.h b/deps/v8/src/jump-target.h
new file mode 100644
index 0000000..1cfbe29
--- /dev/null
+++ b/deps/v8/src/jump-target.h
@@ -0,0 +1,325 @@
+// Copyright 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_JUMP_TARGET_H_
+#define V8_JUMP_TARGET_H_
+
+namespace v8 { namespace internal {
+
+// Forward declarations.
+class FrameElement;
+class Result;
+class VirtualFrame;
+
+
+// -------------------------------------------------------------------------
+// Jump targets
+//
+// A jump target is an abstraction of a basic-block entry in generated
+// code.  It collects all the virtual frames reaching the block by
+// forward jumps and pairs them with labels for the merge code along
+// all forward-reaching paths.  When bound, an expected frame for the
+// block is determined and code is generated to merge to the expected
+// frame.  For backward jumps, the merge code is generated at the edge
+// leaving the predecessor block.
+//
+// A jump target must have been reached via control flow (either by
+// jumping, branching, or falling through) at the time it is bound.
+// In particular, this means that at least one of the control-flow
+// graph edges reaching the target must be a forward edge.
+
+class JumpTarget : public Malloced {  // Shadows are dynamically allocated.
+ public:
+  // Forward-only jump targets can only be reached by forward CFG edges.
+  enum Directionality { FORWARD_ONLY, BIDIRECTIONAL };
+
+  // Construct a jump target with a given code generator used to generate
+  // code and to provide access to a current frame.
+  explicit JumpTarget(CodeGenerator* cgen,
+                      Directionality direction = FORWARD_ONLY);
+
+  // Construct a jump target without a code generator.  A code
+  // generator must be supplied before using the jump target as a
+  // label.  This is useful, eg, when break targets are embedded in
+  // AST nodes.
+  JumpTarget();
+
+  // Supply a code generator and directionality to an already
+  // constructed jump target.  This function expects to be given a
+  // non-null code generator, and to be called only when the code
+  // generator is not yet set.
+  virtual void Initialize(CodeGenerator* cgen,
+                          Directionality direction = FORWARD_ONLY);
+
+  virtual ~JumpTarget() { Unuse(); }
+
+  // Treat the jump target as a fresh one.  The state is reset and
+  // pointed-to virtual frames are deallocated.  There should be no
+  // dangling jumps to the target.
+  void Unuse();
+
+  // Reset the internal state of this jump target.  Pointed-to virtual
+  // frames are not deallocated and dangling jumps to the target are
+  // left dangling.
+  void Reset();
+
+  // Accessors.
+  CodeGenerator* code_generator() const { return cgen_; }
+
+  Label* entry_label() { return &entry_label_; }
+
+  VirtualFrame* entry_frame() const { return entry_frame_; }
+  void set_entry_frame(VirtualFrame* frame) {
+    entry_frame_ = frame;
+  }
+
+  // Predicates testing the state of the encapsulated label.
+  bool is_bound() const { return is_bound_; }
+  bool is_linked() const { return is_linked_; }
+  bool is_unused() const { return !is_bound() && !is_linked(); }
+
+  // Emit a jump to the target.  There must be a current frame at the
+  // jump and there will be no current frame after the jump.
+  virtual void Jump();
+  virtual void Jump(Result* arg);
+  void Jump(Result* arg0, Result* arg1);
+  void Jump(Result* arg0, Result* arg1, Result* arg2);
+
+  // Emit a conditional branch to the target.  There must be a current
+  // frame at the branch.  The current frame will fall through to the
+  // code after the branch.
+  virtual void Branch(Condition cc, Hint hint = no_hint);
+  virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint);
+  void Branch(Condition cc, Result* arg0, Result* arg1, Hint hint = no_hint);
+  void Branch(Condition cc,
+              Result* arg0,
+              Result* arg1,
+              Result* arg2,
+              Hint hint = no_hint);
+  void Branch(Condition cc,
+              Result* arg0,
+              Result* arg1,
+              Result* arg2,
+              Result* arg3,
+              Hint hint = no_hint);
+
+  // Bind a jump target.  If there is no current frame at the binding
+  // site, there must be at least one frame reaching via a forward
+  // jump.
+  //
+  // The number of mergable elements is a number of frame elements
+  // counting from the top down which must be "mergable" (not
+  // constants or copies) in the entry frame at the jump target.
+  // Backward jumps to the target must contain the same constants and
+  // sharing as the entry frame, except for the mergable elements.
+  //
+  // A mergable elements argument of kAllElements indicates that all
+  // frame elements must be mergable.  Mergable elements are ignored
+  // completely for forward-only jump targets.
+  virtual void Bind(int mergable_elements = kAllElements);
+  virtual void Bind(Result* arg, int mergable_elements = kAllElements);
+  void Bind(Result* arg0, Result* arg1, int mergable_elements = kAllElements);
+  void Bind(Result* arg0,
+            Result* arg1,
+            Result* arg2,
+            int mergable_elements = kAllElements);
+  void Bind(Result* arg0,
+            Result* arg1,
+            Result* arg2,
+            Result* arg3,
+            int mergable_elements = kAllElements);
+
+  // Emit a call to a jump target.  There must be a current frame at
+  // the call.  The frame at the target is the same as the current
+  // frame except for an extra return address on top of it.  The frame
+  // after the call is the same as the frame before the call.
+  void Call();
+
+  static const int kAllElements = -1;  // Not a valid number of elements.
+
+ protected:
+  // The code generator gives access to its current frame.
+  CodeGenerator* cgen_;
+
+  // Used to emit code.
+  MacroAssembler* masm_;
+
+  // Directionality flag set at initialization time.
+  Directionality direction_;
+
+  // A list of frames reaching this block via forward jumps.
+  List<VirtualFrame*> reaching_frames_;
+
+  // A parallel list of labels for merge code.
+  List<Label> merge_labels_;
+
+  // The frame used on entry to the block and expected at backward
+  // jumps to the block.  Set when the jump target is bound, but may
+  // or may not be set for forward-only blocks.
+  VirtualFrame* entry_frame_;
+
+  // The actual entry label of the block.
+  Label entry_label_;
+
+  // A target is bound if its Bind member function has been called.
+  // It is linked if it is not bound but its Jump, Branch, or Call
+  // member functions have been called.
+  bool is_bound_;
+  bool is_linked_;
+
+  // Implementations of Jump, Branch, and Bind with all arguments and
+  // return values using the virtual frame.
+  void DoJump();
+  void DoBranch(Condition cc, Hint hint);
+  void DoBind(int mergable_elements);
+
+ private:
+  // Add a virtual frame reaching this labeled block via a forward
+  // jump, and a fresh label for its merge code.
+  void AddReachingFrame(VirtualFrame* frame);
+
+  // Choose an element from a pair of frame elements to be in the
+  // expected frame.  Return null if they are incompatible.
+  FrameElement* Combine(FrameElement* left, FrameElement* right);
+
+  // Compute a frame to use for entry to this block.  Mergable
+  // elements is as described for the Bind function.
+  void ComputeEntryFrame(int mergable_elements);
+
+  DISALLOW_COPY_AND_ASSIGN(JumpTarget);
+};
+
+
+// -------------------------------------------------------------------------
+// Break targets
+//
+// A break target is a jump target that can be used to break out of a
+// statement that keeps extra state on the stack (eg, for/in or
+// try/finally).  They know the expected stack height at the target
+// and will drop state from nested statements as part of merging.
+//
+// Break targets are used for return, break, and continue targets.
+
+class BreakTarget : public JumpTarget {
+ public:
+  // Construct a break target without a code generator.  A code
+  // generator must be supplied before using the break target as a
+  // label.  This is useful, eg, when break targets are embedded in AST
+  // nodes.
+  BreakTarget() {}
+
+  // Supply a code generator, expected expression stack height, and
+  // directionality to an already constructed break target.  This
+  // function expects to be given a non-null code generator, and to be
+  // called only when the code generator is not yet set.
+  virtual void Initialize(CodeGenerator* cgen,
+                          Directionality direction = FORWARD_ONLY);
+
+  // Copy the state of this break target to the destination.  The
+  // lists of forward-reaching frames and merge-point labels are
+  // copied.  All virtual frame pointers are copied, not the
+  // pointed-to frames.  The previous state of the destination is
+  // overwritten, without deallocating pointed-to virtual frames.
+  void CopyTo(BreakTarget* destination);
+
+  // Emit a jump to the target.  There must be a current frame at the
+  // jump and there will be no current frame after the jump.
+  virtual void Jump();
+  virtual void Jump(Result* arg);
+
+  // Emit a conditional branch to the target.  There must be a current
+  // frame at the branch.  The current frame will fall through to the
+  // code after the branch.
+  virtual void Branch(Condition cc, Hint hint = no_hint);
+  virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint);
+
+  // Bind a break target.  If there is no current frame at the binding
+  // site, there must be at least one frame reaching via a forward
+  // jump.
+  virtual void Bind(int mergable_elements = kAllElements);
+  virtual void Bind(Result* arg, int mergable_elements = kAllElements);
+
+  // Setter for expected height.
+  void set_expected_height(int expected) { expected_height_ = expected; }
+
+ private:
+  // The expected height of the expression stack where the target will
+  // be bound, statically known at initialization time.
+  int expected_height_;
+
+  DISALLOW_COPY_AND_ASSIGN(BreakTarget);
+};
+
+
+// -------------------------------------------------------------------------
+// Shadow break targets
+//
+// A shadow break target represents a break target that is temporarily
+// shadowed by another one (represented by the original during
+// shadowing).  They are used to catch jumps to labels in certain
+// contexts, e.g. try blocks.  After shadowing ends, the formerly
+// shadowed target is again represented by the original and the
+// ShadowTarget can be used as a jump target in its own right,
+// representing the formerly shadowing target.
+
+class ShadowTarget : public BreakTarget {
+ public:
+  // Construct a shadow jump target.  After construction the shadow
+  // target object holds the state of the original target, and the
+  // original target is actually a fresh one that intercepts control
+  // flow intended for the shadowed one.
+  explicit ShadowTarget(BreakTarget* shadowed);
+
+  virtual ~ShadowTarget() {
+    ASSERT(!is_shadowing_);
+  }
+
+  // End shadowing.  After shadowing ends, the original jump target
+  // again gives access to the formerly shadowed target and the shadow
+  // target object gives access to the formerly shadowing target.
+  void StopShadowing();
+
+  // During shadowing, the currently shadowing target.  After
+  // shadowing, the target that was shadowed.
+  BreakTarget* other_target() const { return other_target_; }
+
+ private:
+  // During shadowing, the currently shadowing target.  After
+  // shadowing, the target that was shadowed.
+  BreakTarget* other_target_;
+
+#ifdef DEBUG
+  bool is_shadowing_;
+#endif
+
+  DISALLOW_COPY_AND_ASSIGN(ShadowTarget);
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_JUMP_TARGET_H_
diff --git a/deps/v8/src/list-inl.h b/deps/v8/src/list-inl.h
new file mode 100644
index 0000000..6dbd214
--- /dev/null
+++ b/deps/v8/src/list-inl.h
@@ -0,0 +1,132 @@
+// 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_LIST_INL_H_
+#define V8_LIST_INL_H_
+
+#include "list.h"
+
+namespace v8 { namespace internal {
+
+
+template<typename T, class P>
+void List<T, P>::Add(const T& element) {
+  if (length_ < capacity_) {
+    data_[length_++] = element;
+  } else {
+    // Grow the list capacity by 50%, but make sure to let it grow
+    // even when the capacity is zero (possible initial case).
+    int new_capacity = 1 + capacity_ + (capacity_ >> 1);
+    T* new_data = NewData(new_capacity);
+    memcpy(new_data, data_, capacity_ * sizeof(T));
+    // Since the element reference could be an element of the list,
+    // assign it to the new backing store before deleting the old.
+    new_data[length_++] = element;
+    DeleteData(data_);
+    data_ = new_data;
+    capacity_ = new_capacity;
+  }
+}
+
+
+template<typename T, class P>
+Vector<T> List<T, P>::AddBlock(T value, int count) {
+  int start = length_;
+  for (int i = 0; i < count; i++) Add(value);
+  return Vector<T>(&data_[start], count);
+}
+
+
+template<typename T, class P>
+T List<T, P>::Remove(int i) {
+  T element = at(i);
+  length_--;
+  while (i < length_) {
+    data_[i] = data_[i + 1];
+    i++;
+  }
+  return element;
+}
+
+
+template<typename T, class P>
+void List<T, P>::Clear() {
+  DeleteData(data_);
+  Initialize(0);
+}
+
+
+template<typename T, class P>
+void List<T, P>::Rewind(int pos) {
+  length_ = pos;
+}
+
+
+template<typename T, class P>
+void List<T, P>::Iterate(void (*callback)(T* x)) {
+  for (int i = 0; i < length_; i++) callback(&data_[i]);
+}
+
+
+template<typename T, class P>
+bool List<T, P>::Contains(const T& elm) {
+  for (int i = 0; i < length_; i++) {
+    if (data_[i] == elm)
+      return true;
+  }
+  return false;
+}
+
+
+template<typename T, class P>
+void List<T, P>::Sort(int (*cmp)(const T* x, const T* y)) {
+  ToVector().Sort(cmp);
+#ifdef DEBUG
+  for (int i = 1; i < length_; i++)
+    ASSERT(cmp(&data_[i - 1], &data_[i]) <= 0);
+#endif
+}
+
+
+template<typename T, class P>
+void List<T, P>::Sort() {
+  Sort(PointerValueCompare<T>);
+}
+
+
+template<typename T, class P>
+void List<T, P>::Initialize(int capacity) {
+  ASSERT(capacity >= 0);
+  data_ = (capacity > 0) ? NewData(capacity) : NULL;
+  capacity_ = capacity;
+  length_ = 0;
+}
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_LIST_INL_H_
diff --git a/deps/v8/src/list.h b/deps/v8/src/list.h
new file mode 100644
index 0000000..dc2f115
--- /dev/null
+++ b/deps/v8/src/list.h
@@ -0,0 +1,127 @@
+// Copyright 2006-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.
+
+#ifndef V8_LIST_H_
+#define V8_LIST_H_
+
+namespace v8 { namespace internal {
+
+
+// ----------------------------------------------------------------------------
+// The list is a template for very light-weight lists. We are not
+// using the STL because we want full control over space and speed of
+// the code. This implementation is based on code by Robert Griesemer
+// and Rob Pike.
+//
+// The list is parameterized by the type of its elements (T) and by an
+// allocation policy (P). The policy is used for allocating lists in
+// the C free store or the zone; see zone.h.
+
+// Forward defined as
+// template <typename T, class P = FreeStoreAllocationPolicy> class List;
+template <typename T, class P>
+class List {
+ public:
+
+  INLINE(explicit List(int capacity)) { Initialize(capacity); }
+  INLINE(~List()) { DeleteData(data_); }
+
+  INLINE(void* operator new(size_t size)) { return P::New(size); }
+  INLINE(void operator delete(void* p, size_t)) { return P::Delete(p); }
+
+  // Returns a reference to the element at index i.  This reference is
+  // not safe to use after operations that can change the list's
+  // backing store (eg, Add).
+  inline T& operator[](int i) const  {
+    ASSERT(0 <= i && i < length_);
+    return data_[i];
+  }
+  inline T& at(int i) const  { return operator[](i); }
+  inline T& last() const {
+    return at(length_ - 1);
+  }
+
+  INLINE(bool is_empty() const) { return length_ == 0; }
+  INLINE(int length() const) { return length_; }
+  INLINE(int capacity() const) { return capacity_; }
+
+  Vector<T> ToVector() { return Vector<T>(data_, length_); }
+
+  Vector<const T> ToConstVector() { return Vector<const T>(data_, length_); }
+
+  // Adds a copy of the given 'element' to the end of the list,
+  // expanding the list if necessary.
+  void Add(const T& element);
+
+  // Added 'count' elements with the value 'value' and returns a
+  // vector that allows access to the elements.  The vector is valid
+  // until the next change is made to this list.
+  Vector<T> AddBlock(T value, int count);
+
+  // Removes the i'th element without deleting it even if T is a
+  // pointer type; moves all elements above i "down". Returns the
+  // removed element.  This function's complexity is linear in the
+  // size of the list.
+  T Remove(int i);
+
+  // Removes the last element without deleting it even if T is a
+  // pointer type. Returns the removed element.
+  INLINE(T RemoveLast()) { return Remove(length_ - 1); }
+
+  // Clears the list by setting the length to zero. Even if T is a
+  // pointer type, clearing the list doesn't delete the entries.
+  INLINE(void Clear());
+
+  // Drops all but the first 'pos' elements from the list.
+  INLINE(void Rewind(int pos));
+
+  bool Contains(const T& elm);
+
+  // Iterate through all list entries, starting at index 0.
+  void Iterate(void (*callback)(T* x));
+
+  // Sort all list entries (using QuickSort)
+  void Sort(int (*cmp)(const T* x, const T* y));
+  void Sort();
+
+  INLINE(void Initialize(int capacity));
+
+ private:
+  T* data_;
+  int capacity_;
+  int length_;
+
+  INLINE(T* NewData(int n))  { return static_cast<T*>(P::New(n * sizeof(T))); }
+  INLINE(void DeleteData(T* data))  { P::Delete(data); }
+
+  DISALLOW_COPY_AND_ASSIGN(List);
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_LIST_H_
diff --git a/deps/v8/src/log.cc b/deps/v8/src/log.cc
new file mode 100644
index 0000000..d9e304d
--- /dev/null
+++ b/deps/v8/src/log.cc
@@ -0,0 +1,1193 @@
+// 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.
+
+#include <stdarg.h>
+
+#include "v8.h"
+
+#include "bootstrapper.h"
+#include "log.h"
+#include "macro-assembler.h"
+#include "platform.h"
+#include "serialize.h"
+#include "string-stream.h"
+
+namespace v8 { namespace internal {
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+
+//
+// Sliding state window.  Updates counters to keep track of the last
+// window of kBufferSize states.  This is useful to track where we
+// spent our time.
+//
+class SlidingStateWindow {
+ public:
+  SlidingStateWindow();
+  ~SlidingStateWindow();
+  void AddState(StateTag state);
+
+ private:
+  static const int kBufferSize = 256;
+  int current_index_;
+  bool is_full_;
+  byte buffer_[kBufferSize];
+
+
+  void IncrementStateCounter(StateTag state) {
+    Counters::state_counters[state].Increment();
+  }
+
+
+  void DecrementStateCounter(StateTag state) {
+    Counters::state_counters[state].Decrement();
+  }
+};
+
+
+//
+// The Profiler samples pc and sp values for the main thread.
+// Each sample is appended to a circular buffer.
+// An independent thread removes data and writes it to the log.
+// This design minimizes the time spent in the sampler.
+//
+class Profiler: public Thread {
+ public:
+  Profiler();
+  void Engage();
+  void Disengage();
+
+  // Inserts collected profiling data into buffer.
+  void Insert(TickSample* sample) {
+    if (paused_)
+      return;
+
+    if (Succ(head_) == tail_) {
+      overflow_ = true;
+    } else {
+      buffer_[head_] = *sample;
+      head_ = Succ(head_);
+      buffer_semaphore_->Signal();  // Tell we have an element.
+    }
+  }
+
+  // Waits for a signal and removes profiling data.
+  bool Remove(TickSample* sample) {
+    buffer_semaphore_->Wait();  // Wait for an element.
+    *sample = buffer_[tail_];
+    bool result = overflow_;
+    tail_ = Succ(tail_);
+    overflow_ = false;
+    return result;
+  }
+
+  void Run();
+
+  // Pause and Resume TickSample data collection.
+  static bool paused() { return paused_; }
+  static void pause() { paused_ = true; }
+  static void resume() { paused_ = false; }
+
+ private:
+  // Returns the next index in the cyclic buffer.
+  int Succ(int index) { return (index + 1) % kBufferSize; }
+
+  // Cyclic buffer for communicating profiling samples
+  // between the signal handler and the worker thread.
+  static const int kBufferSize = 128;
+  TickSample buffer_[kBufferSize];  // Buffer storage.
+  int head_;  // Index to the buffer head.
+  int tail_;  // Index to the buffer tail.
+  bool overflow_;  // Tell whether a buffer overflow has occurred.
+  Semaphore* buffer_semaphore_;  // Sempahore used for buffer synchronization.
+
+  // Tells whether worker thread should continue running.
+  bool running_;
+
+  // Tells whether we are currently recording tick samples.
+  static bool paused_;
+};
+
+bool Profiler::paused_ = false;
+
+
+//
+// StackTracer implementation
+//
+void StackTracer::Trace(TickSample* sample) {
+  if (sample->state == GC) {
+    sample->frames_count = 0;
+    return;
+  }
+
+  SafeStackTraceFrameIterator it(
+      reinterpret_cast<Address>(sample->fp),
+      reinterpret_cast<Address>(sample->sp),
+      reinterpret_cast<Address>(sample->sp),
+      reinterpret_cast<Address>(low_stack_bound_));
+  int i = 0;
+  while (!it.done() && i < TickSample::kMaxFramesCount) {
+    sample->stack[i++] = it.frame()->pc();
+    it.Advance();
+  }
+  sample->frames_count = i;
+}
+
+
+//
+// Ticker used to provide ticks to the profiler and the sliding state
+// window.
+//
+class Ticker: public Sampler {
+ public:
+  explicit Ticker(int interval, unsigned int low_stack_bound):
+      Sampler(interval, FLAG_prof), window_(NULL), profiler_(NULL),
+      stack_tracer_(low_stack_bound) {}
+
+  ~Ticker() { if (IsActive()) Stop(); }
+
+  void Tick(TickSample* sample) {
+    if (IsProfiling()) stack_tracer_.Trace(sample);
+    if (profiler_) profiler_->Insert(sample);
+    if (window_) window_->AddState(sample->state);
+  }
+
+  void SetWindow(SlidingStateWindow* window) {
+    window_ = window;
+    if (!IsActive()) Start();
+  }
+
+  void ClearWindow() {
+    window_ = NULL;
+    if (!profiler_ && IsActive()) Stop();
+  }
+
+  void SetProfiler(Profiler* profiler) {
+    profiler_ = profiler;
+    if (!IsActive()) Start();
+  }
+
+  void ClearProfiler() {
+    profiler_ = NULL;
+    if (!window_ && IsActive()) Stop();
+  }
+
+ private:
+  SlidingStateWindow* window_;
+  Profiler* profiler_;
+  StackTracer stack_tracer_;
+};
+
+
+//
+// SlidingStateWindow implementation.
+//
+SlidingStateWindow::SlidingStateWindow(): current_index_(0), is_full_(false) {
+  for (int i = 0; i < kBufferSize; i++) {
+    buffer_[i] = static_cast<byte>(OTHER);
+  }
+  Logger::ticker_->SetWindow(this);
+}
+
+
+SlidingStateWindow::~SlidingStateWindow() {
+  Logger::ticker_->ClearWindow();
+}
+
+
+void SlidingStateWindow::AddState(StateTag state) {
+  if (is_full_) {
+    DecrementStateCounter(static_cast<StateTag>(buffer_[current_index_]));
+  } else if (current_index_ == kBufferSize - 1) {
+    is_full_ = true;
+  }
+  buffer_[current_index_] = static_cast<byte>(state);
+  IncrementStateCounter(state);
+  ASSERT(IsPowerOf2(kBufferSize));
+  current_index_ = (current_index_ + 1) & (kBufferSize - 1);
+}
+
+
+//
+// Profiler implementation.
+//
+Profiler::Profiler() {
+  buffer_semaphore_ = OS::CreateSemaphore(0);
+  head_ = 0;
+  tail_ = 0;
+  overflow_ = false;
+  running_ = false;
+}
+
+
+void Profiler::Engage() {
+  OS::LogSharedLibraryAddresses();
+
+  // Start thread processing the profiler buffer.
+  running_ = true;
+  Start();
+
+  // Register to get ticks.
+  Logger::ticker_->SetProfiler(this);
+
+  LOG(UncheckedStringEvent("profiler", "begin"));
+}
+
+
+void Profiler::Disengage() {
+  // Stop receiving ticks.
+  Logger::ticker_->ClearProfiler();
+
+  // Terminate the worker thread by setting running_ to false,
+  // inserting a fake element in the queue and then wait for
+  // the thread to terminate.
+  running_ = false;
+  TickSample sample;
+  Insert(&sample);
+  Join();
+
+  LOG(UncheckedStringEvent("profiler", "end"));
+}
+
+
+void Profiler::Run() {
+  TickSample sample;
+  bool overflow = Logger::profiler_->Remove(&sample);
+  while (running_) {
+    LOG(TickEvent(&sample, overflow));
+    overflow = Logger::profiler_->Remove(&sample);
+  }
+}
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+// Utility class for formatting log messages. It fills the message into the
+// static buffer in Logger.
+class LogMessageBuilder BASE_EMBEDDED {
+ public:
+  explicit LogMessageBuilder();
+  ~LogMessageBuilder() { }
+
+  void Append(const char* format, ...);
+  void Append(const char* format, va_list args);
+  void Append(const char c);
+  void Append(String *str);
+  void AppendDetailed(String* str, bool show_impl_info);
+
+  void WriteToLogFile();
+  void WriteCStringToLogFile(const char* str);
+
+ private:
+  ScopedLock sl;
+  int pos_;
+};
+
+
+// Create a message builder starting from position 0. This acquires the mutex
+// in the logger as well.
+LogMessageBuilder::LogMessageBuilder(): sl(Logger::mutex_), pos_(0) {
+  ASSERT(Logger::message_buffer_ != NULL);
+}
+
+
+// Append string data to the log message.
+void LogMessageBuilder::Append(const char* format, ...) {
+  Vector<char> buf(Logger::message_buffer_ + pos_,
+                   Logger::kMessageBufferSize - pos_);
+  va_list args;
+  va_start(args, format);
+  Append(format, args);
+  va_end(args);
+  ASSERT(pos_ <= Logger::kMessageBufferSize);
+}
+
+
+// Append string data to the log message.
+void LogMessageBuilder::Append(const char* format, va_list args) {
+  Vector<char> buf(Logger::message_buffer_ + pos_,
+                   Logger::kMessageBufferSize - pos_);
+  int result = v8::internal::OS::VSNPrintF(buf, format, args);
+
+  // Result is -1 if output was truncated.
+  if (result >= 0) {
+    pos_ += result;
+  } else {
+    pos_ = Logger::kMessageBufferSize;
+  }
+  ASSERT(pos_ <= Logger::kMessageBufferSize);
+}
+
+
+// Append a character to the log message.
+void LogMessageBuilder::Append(const char c) {
+  if (pos_ < Logger::kMessageBufferSize) {
+    Logger::message_buffer_[pos_++] = c;
+  }
+  ASSERT(pos_ <= Logger::kMessageBufferSize);
+}
+
+
+// Append a heap string.
+void LogMessageBuilder::Append(String* str) {
+  AssertNoAllocation no_heap_allocation;  // Ensure string stay valid.
+  int length = str->length();
+  for (int i = 0; i < length; i++) {
+    Append(static_cast<char>(str->Get(i)));
+  }
+}
+
+void LogMessageBuilder::AppendDetailed(String* str, bool show_impl_info) {
+  AssertNoAllocation no_heap_allocation;  // Ensure string stay valid.
+  int len = str->length();
+  if (len > 0x1000)
+    len = 0x1000;
+  if (show_impl_info) {
+    Append(StringShape(str).IsAsciiRepresentation() ? 'a' : '2');
+    if (StringShape(str).IsExternal())
+      Append('e');
+    if (StringShape(str).IsSymbol())
+      Append('#');
+    Append(":%i:", str->length());
+  }
+  for (int i = 0; i < len; i++) {
+    uc32 c = str->Get(i);
+    if (c > 0xff) {
+      Append("\\u%04x", c);
+    } else if (c < 32 || c > 126) {
+      Append("\\x%02x", c);
+    } else if (c == ',') {
+      Append("\\,");
+    } else if (c == '\\') {
+      Append("\\\\");
+    } else {
+      Append("%lc", c);
+    }
+  }
+}
+
+// Write the log message to the log file currently opened.
+void LogMessageBuilder::WriteToLogFile() {
+  ASSERT(pos_ <= Logger::kMessageBufferSize);
+  size_t rv = fwrite(Logger::message_buffer_, 1, pos_, Logger::logfile_);
+  ASSERT(rv == static_cast<size_t>(pos_));
+  USE(rv);
+}
+
+// Write a null-terminated string to to the log file currently opened.
+void LogMessageBuilder::WriteCStringToLogFile(const char* str) {
+  size_t len = strlen(str);
+  size_t rv = fwrite(str, 1, len, Logger::logfile_);
+  ASSERT(rv == len);
+  USE(rv);
+}
+#endif
+
+
+//
+// Logger class implementation.
+//
+Ticker* Logger::ticker_ = NULL;
+char* Logger::message_buffer_ = NULL;
+FILE* Logger::logfile_ = NULL;
+Profiler* Logger::profiler_ = NULL;
+Mutex* Logger::mutex_ = NULL;
+VMState* Logger::current_state_ = NULL;
+VMState Logger::bottom_state_(EXTERNAL);
+SlidingStateWindow* Logger::sliding_state_window_ = NULL;
+
+#endif  // ENABLE_LOGGING_AND_PROFILING
+
+
+void Logger::Preamble(const char* content) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_code) return;
+  LogMessageBuilder msg;
+  msg.WriteCStringToLogFile(content);
+#endif
+}
+
+
+void Logger::StringEvent(const char* name, const char* value) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (FLAG_log) UncheckedStringEvent(name, value);
+#endif
+}
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+void Logger::UncheckedStringEvent(const char* name, const char* value) {
+  if (logfile_ == NULL) return;
+  LogMessageBuilder msg;
+  msg.Append("%s,\"%s\"\n", name, value);
+  msg.WriteToLogFile();
+}
+#endif
+
+
+void Logger::IntEvent(const char* name, int value) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log) return;
+  LogMessageBuilder msg;
+  msg.Append("%s,%d\n", name, value);
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::HandleEvent(const char* name, Object** location) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_handles) return;
+  LogMessageBuilder msg;
+  msg.Append("%s,0x%x\n", name,
+             reinterpret_cast<unsigned int>(location));
+  msg.WriteToLogFile();
+#endif
+}
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+// ApiEvent is private so all the calls come from the Logger class.  It is the
+// caller's responsibility to ensure that logfile_ is not NULL and that
+// FLAG_log_api is true.
+void Logger::ApiEvent(const char* format, ...) {
+  ASSERT(logfile_ != NULL && FLAG_log_api);
+  LogMessageBuilder msg;
+  va_list ap;
+  va_start(ap, format);
+  msg.Append(format, ap);
+  va_end(ap);
+  msg.WriteToLogFile();
+}
+#endif
+
+
+void Logger::ApiNamedSecurityCheck(Object* key) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_api) return;
+  if (key->IsString()) {
+    SmartPointer<char> str =
+        String::cast(key)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+    ApiEvent("api,check-security,\"%s\"\n", *str);
+  } else if (key->IsUndefined()) {
+    ApiEvent("api,check-security,undefined\n");
+  } else {
+    ApiEvent("api,check-security,['no-name']\n");
+  }
+#endif
+}
+
+
+void Logger::SharedLibraryEvent(const char* library_path,
+                                unsigned start,
+                                unsigned end) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_prof) return;
+  LogMessageBuilder msg;
+  msg.Append("shared-library,\"%s\",0x%08x,0x%08x\n", library_path,
+             start, end);
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::SharedLibraryEvent(const wchar_t* library_path,
+                                unsigned start,
+                                unsigned end) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_prof) return;
+  LogMessageBuilder msg;
+  msg.Append("shared-library,\"%ls\",0x%08x,0x%08x\n", library_path,
+             start, end);
+  msg.WriteToLogFile();
+#endif
+}
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+void Logger::LogRegExpSource(Handle<JSRegExp> regexp) {
+  // Prints "/" + re.source + "/" +
+  //      (re.global?"g":"") + (re.ignorecase?"i":"") + (re.multiline?"m":"")
+  LogMessageBuilder msg;
+
+  Handle<Object> source = GetProperty(regexp, "source");
+  if (!source->IsString()) {
+    msg.Append("no source");
+    return;
+  }
+
+  switch (regexp->TypeTag()) {
+    case JSRegExp::ATOM:
+      msg.Append('a');
+      break;
+    default:
+      break;
+  }
+  msg.Append('/');
+  msg.AppendDetailed(*Handle<String>::cast(source), false);
+  msg.Append('/');
+
+  // global flag
+  Handle<Object> global = GetProperty(regexp, "global");
+  if (global->IsTrue()) {
+    msg.Append('g');
+  }
+  // ignorecase flag
+  Handle<Object> ignorecase = GetProperty(regexp, "ignoreCase");
+  if (ignorecase->IsTrue()) {
+    msg.Append('i');
+  }
+  // multiline flag
+  Handle<Object> multiline = GetProperty(regexp, "multiline");
+  if (multiline->IsTrue()) {
+    msg.Append('m');
+  }
+
+  msg.WriteToLogFile();
+}
+#endif  // ENABLE_LOGGING_AND_PROFILING
+
+
+void Logger::RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_regexp) return;
+  LogMessageBuilder msg;
+  msg.Append("regexp-compile,");
+  LogRegExpSource(regexp);
+  msg.Append(in_cache ? ",hit\n" : ",miss\n");
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::LogRuntime(Vector<const char> format, JSArray* args) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_runtime) return;
+  HandleScope scope;
+  LogMessageBuilder msg;
+  for (int i = 0; i < format.length(); i++) {
+    char c = format[i];
+    if (c == '%' && i <= format.length() - 2) {
+      i++;
+      ASSERT('0' <= format[i] && format[i] <= '9');
+      Object* obj = args->GetElement(format[i] - '0');
+      i++;
+      switch (format[i]) {
+        case 's':
+          msg.AppendDetailed(String::cast(obj), false);
+          break;
+        case 'S':
+          msg.AppendDetailed(String::cast(obj), true);
+          break;
+        case 'r':
+          Logger::LogRegExpSource(Handle<JSRegExp>(JSRegExp::cast(obj)));
+          break;
+        case 'x':
+          msg.Append("0x%x", Smi::cast(obj)->value());
+          break;
+        case 'i':
+          msg.Append("%i", Smi::cast(obj)->value());
+          break;
+        default:
+          UNREACHABLE();
+      }
+    } else {
+      msg.Append(c);
+    }
+  }
+  msg.Append('\n');
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::ApiIndexedSecurityCheck(uint32_t index) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_api) return;
+  ApiEvent("api,check-security,%u\n", index);
+#endif
+}
+
+
+void Logger::ApiNamedPropertyAccess(const char* tag,
+                                    JSObject* holder,
+                                    Object* name) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  ASSERT(name->IsString());
+  if (logfile_ == NULL || !FLAG_log_api) return;
+  String* class_name_obj = holder->class_name();
+  SmartPointer<char> class_name =
+      class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+  SmartPointer<char> property_name =
+      String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+  Logger::ApiEvent("api,%s,\"%s\",\"%s\"\n", tag, *class_name, *property_name);
+#endif
+}
+
+void Logger::ApiIndexedPropertyAccess(const char* tag,
+                                      JSObject* holder,
+                                      uint32_t index) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_api) return;
+  String* class_name_obj = holder->class_name();
+  SmartPointer<char> class_name =
+      class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+  Logger::ApiEvent("api,%s,\"%s\",%u\n", tag, *class_name, index);
+#endif
+}
+
+void Logger::ApiObjectAccess(const char* tag, JSObject* object) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_api) return;
+  String* class_name_obj = object->class_name();
+  SmartPointer<char> class_name =
+      class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+  Logger::ApiEvent("api,%s,\"%s\"\n", tag, *class_name);
+#endif
+}
+
+
+void Logger::ApiEntryCall(const char* name) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_api) return;
+  Logger::ApiEvent("api,%s\n", name);
+#endif
+}
+
+
+void Logger::NewEvent(const char* name, void* object, size_t size) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log) return;
+  LogMessageBuilder msg;
+  msg.Append("new,%s,0x%x,%u\n", name,
+             reinterpret_cast<unsigned int>(object),
+             static_cast<unsigned int>(size));
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::DeleteEvent(const char* name, void* object) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log) return;
+  LogMessageBuilder msg;
+  msg.Append("delete,%s,0x%x\n", name,
+             reinterpret_cast<unsigned int>(object));
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::CodeCreateEvent(const char* tag, Code* code, const char* comment) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_code) return;
+  LogMessageBuilder msg;
+  msg.Append("code-creation,%s,0x%x,%d,\"", tag,
+             reinterpret_cast<unsigned int>(code->address()),
+             code->ExecutableSize());
+  for (const char* p = comment; *p != '\0'; p++) {
+    if (*p == '"') {
+      msg.Append('\\');
+    }
+    msg.Append(*p);
+  }
+  msg.Append('"');
+  msg.Append('\n');
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::CodeCreateEvent(const char* tag, Code* code, String* name) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_code) return;
+  LogMessageBuilder msg;
+  SmartPointer<char> str =
+      name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+  msg.Append("code-creation,%s,0x%x,%d,\"%s\"\n", tag,
+             reinterpret_cast<unsigned int>(code->address()),
+             code->ExecutableSize(), *str);
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::CodeCreateEvent(const char* tag, Code* code, String* name,
+                             String* source, int line) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_code) return;
+  LogMessageBuilder msg;
+  SmartPointer<char> str =
+      name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+  SmartPointer<char> sourcestr =
+      source->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+  msg.Append("code-creation,%s,0x%x,%d,\"%s %s:%d\"\n", tag,
+             reinterpret_cast<unsigned int>(code->address()),
+             code->ExecutableSize(),
+             *str, *sourcestr, line);
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::CodeCreateEvent(const char* tag, Code* code, int args_count) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_code) return;
+  LogMessageBuilder msg;
+  msg.Append("code-creation,%s,0x%x,%d,\"args_count: %d\"\n", tag,
+             reinterpret_cast<unsigned int>(code->address()),
+             code->ExecutableSize(),
+             args_count);
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::RegExpCodeCreateEvent(Code* code, String* source) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_code) return;
+  LogMessageBuilder msg;
+  msg.Append("code-creation,%s,0x%x,%d,\"", "RegExp",
+             reinterpret_cast<unsigned int>(code->address()),
+             code->ExecutableSize());
+  msg.AppendDetailed(source, false);
+  msg.Append("\"\n");
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::CodeAllocateEvent(Code* code, Assembler* assem) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_code) return;
+  LogMessageBuilder msg;
+  msg.Append("code-allocate,0x%x,0x%x\n",
+             reinterpret_cast<unsigned int>(code->address()),
+             reinterpret_cast<unsigned int>(assem));
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::CodeMoveEvent(Address from, Address to) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_code) return;
+  LogMessageBuilder msg;
+  msg.Append("code-move,0x%x,0x%x\n",
+             reinterpret_cast<unsigned int>(from),
+             reinterpret_cast<unsigned int>(to));
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::CodeDeleteEvent(Address from) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_code) return;
+  LogMessageBuilder msg;
+  msg.Append("code-delete,0x%x\n", reinterpret_cast<unsigned int>(from));
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::BeginCodeRegionEvent(CodeRegion* region,
+                                  Assembler* masm,
+                                  const char* name) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_code) return;
+  LogMessageBuilder msg;
+  msg.Append("begin-code-region,0x%x,0x%x,0x%x,%s\n",
+             reinterpret_cast<unsigned int>(region),
+             reinterpret_cast<unsigned int>(masm),
+             masm->pc_offset(),
+             name);
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::EndCodeRegionEvent(CodeRegion* region, Assembler* masm) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_code) return;
+  LogMessageBuilder msg;
+  msg.Append("end-code-region,0x%x,0x%x,0x%x\n",
+             reinterpret_cast<unsigned int>(region),
+             reinterpret_cast<unsigned int>(masm),
+             masm->pc_offset());
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::ResourceEvent(const char* name, const char* tag) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log) return;
+  LogMessageBuilder msg;
+  msg.Append("%s,%s,", name, tag);
+
+  uint32_t sec, usec;
+  if (OS::GetUserTime(&sec, &usec) != -1) {
+    msg.Append("%d,%d,", sec, usec);
+  }
+  msg.Append("%.0f", OS::TimeCurrentMillis());
+
+  msg.Append('\n');
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::SuspectReadEvent(String* name, Object* obj) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_suspect) return;
+  LogMessageBuilder msg;
+  String* class_name = obj->IsJSObject()
+                       ? JSObject::cast(obj)->class_name()
+                       : Heap::empty_string();
+  ScopedLock sl(mutex_);
+  msg.Append("suspect-read,");
+  msg.Append(class_name);
+  msg.Append(',');
+  msg.Append('"');
+  msg.Append(name);
+  msg.Append('"');
+  msg.Append('\n');
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::HeapSampleBeginEvent(const char* space, const char* kind) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_gc) return;
+  LogMessageBuilder msg;
+  msg.Append("heap-sample-begin,\"%s\",\"%s\"\n", space, kind);
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::HeapSampleEndEvent(const char* space, const char* kind) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_gc) return;
+  LogMessageBuilder msg;
+  msg.Append("heap-sample-end,\"%s\",\"%s\"\n", space, kind);
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::HeapSampleItemEvent(const char* type, int number, int bytes) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log_gc) return;
+  LogMessageBuilder msg;
+  msg.Append("heap-sample-item,%s,%d,%d\n", type, number, bytes);
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::DebugTag(const char* call_site_tag) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log) return;
+  LogMessageBuilder msg;
+  msg.Append("debug-tag,%s\n", call_site_tag);
+  msg.WriteToLogFile();
+#endif
+}
+
+
+void Logger::DebugEvent(const char* event_type, Vector<uint16_t> parameter) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL || !FLAG_log) return;
+  StringBuilder s(parameter.length() + 1);
+  for (int i = 0; i < parameter.length(); ++i) {
+    s.AddCharacter(static_cast<char>(parameter[i]));
+  }
+  char* parameter_string = s.Finalize();
+  LogMessageBuilder msg;
+  msg.Append("debug-queue-event,%s,%15.3f,%s\n",
+             event_type,
+             OS::TimeCurrentMillis(),
+             parameter_string);
+  DeleteArray(parameter_string);
+  msg.WriteToLogFile();
+#endif
+}
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+void Logger::TickEvent(TickSample* sample, bool overflow) {
+  if (logfile_ == NULL || !FLAG_prof) return;
+  LogMessageBuilder msg;
+  msg.Append("tick,0x%x,0x%x,%d", sample->pc, sample->sp,
+             static_cast<int>(sample->state));
+  if (overflow) {
+    msg.Append(",overflow");
+  }
+  for (int i = 0; i < sample->frames_count; ++i) {
+    msg.Append(",0x%x", reinterpret_cast<uint32_t>(sample->stack[i]));
+  }
+  msg.Append('\n');
+  msg.WriteToLogFile();
+}
+
+
+bool Logger::IsProfilerPaused() {
+  return profiler_->paused();
+}
+
+
+void Logger::PauseProfiler() {
+  profiler_->pause();
+}
+
+
+void Logger::ResumeProfiler() {
+  profiler_->resume();
+}
+#endif
+
+
+bool Logger::Setup() {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  // --log-all enables all the log flags.
+  if (FLAG_log_all) {
+    FLAG_log_runtime = true;
+    FLAG_log_api = true;
+    FLAG_log_code = true;
+    FLAG_log_gc = true;
+    FLAG_log_suspect = true;
+    FLAG_log_handles = true;
+    FLAG_log_regexp = true;
+  }
+
+  // --prof implies --log-code.
+  if (FLAG_prof) FLAG_log_code = true;
+
+  bool open_log_file = FLAG_log || FLAG_log_runtime || FLAG_log_api
+      || FLAG_log_code || FLAG_log_gc || FLAG_log_handles || FLAG_log_suspect
+      || FLAG_log_regexp || FLAG_log_state_changes;
+
+  // If we're logging anything, we need to open the log file.
+  if (open_log_file) {
+    if (strcmp(FLAG_logfile, "-") == 0) {
+      logfile_ = stdout;
+    } else if (strchr(FLAG_logfile, '%') != NULL) {
+      // If there's a '%' in the log file name we have to expand
+      // placeholders.
+      HeapStringAllocator allocator;
+      StringStream stream(&allocator);
+      for (const char* p = FLAG_logfile; *p; p++) {
+        if (*p == '%') {
+          p++;
+          switch (*p) {
+            case '\0':
+              // If there's a % at the end of the string we back up
+              // one character so we can escape the loop properly.
+              p--;
+              break;
+            case 't': {
+              // %t expands to the current time in milliseconds.
+              uint32_t time = static_cast<uint32_t>(OS::TimeCurrentMillis());
+              stream.Add("%u", time);
+              break;
+            }
+            case '%':
+              // %% expands (contracts really) to %.
+              stream.Put('%');
+              break;
+            default:
+              // All other %'s expand to themselves.
+              stream.Put('%');
+              stream.Put(*p);
+              break;
+          }
+        } else {
+          stream.Put(*p);
+        }
+      }
+      SmartPointer<const char> expanded = stream.ToCString();
+      logfile_ = OS::FOpen(*expanded, OS::LogFileOpenMode);
+    } else {
+      logfile_ = OS::FOpen(FLAG_logfile, OS::LogFileOpenMode);
+    }
+    message_buffer_ = NewArray<char>(kMessageBufferSize);
+    mutex_ = OS::CreateMutex();
+  }
+
+  current_state_ = &bottom_state_;
+
+  // as log is initialized early with V8, we can assume that JS execution
+  // frames can never reach this point on stack
+  int stack_var;
+  ticker_ = new Ticker(1, reinterpret_cast<unsigned int>(&stack_var));
+
+  if (FLAG_sliding_state_window && sliding_state_window_ == NULL) {
+    sliding_state_window_ = new SlidingStateWindow();
+  }
+
+  if (FLAG_prof) {
+    profiler_ = new Profiler();
+    if (!FLAG_prof_auto)
+      profiler_->pause();
+    profiler_->Engage();
+  }
+
+  return true;
+
+#else
+  return false;
+#endif
+}
+
+
+void Logger::TearDown() {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  // Stop the profiler before closing the file.
+  if (profiler_ != NULL) {
+    profiler_->Disengage();
+    delete profiler_;
+    profiler_ = NULL;
+  }
+
+  delete sliding_state_window_;
+
+  delete ticker_;
+
+  if (logfile_ != NULL) {
+    fclose(logfile_);
+    logfile_ = NULL;
+    delete mutex_;
+    mutex_ = NULL;
+    DeleteArray(message_buffer_);
+  }
+#endif
+}
+
+
+void Logger::EnableSlidingStateWindow() {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  // If the ticker is NULL, Logger::Setup has not been called yet.  In
+  // that case, we set the sliding_state_window flag so that the
+  // sliding window computation will be started when Logger::Setup is
+  // called.
+  if (ticker_ == NULL) {
+    FLAG_sliding_state_window = true;
+    return;
+  }
+  // Otherwise, if the sliding state window computation has not been
+  // started we do it now.
+  if (sliding_state_window_ == NULL) {
+    sliding_state_window_ = new SlidingStateWindow();
+  }
+#endif
+}
+
+
+//
+// VMState class implementation.  A simple stack of VM states held by the
+// logger and partially threaded through the call stack.  States are pushed by
+// VMState construction and popped by destruction.
+//
+#ifdef ENABLE_LOGGING_AND_PROFILING
+static const char* StateToString(StateTag state) {
+  switch (state) {
+    case JS:
+      return "JS";
+    case GC:
+      return "GC";
+    case COMPILER:
+      return "COMPILER";
+    case OTHER:
+      return "OTHER";
+    default:
+      UNREACHABLE();
+      return NULL;
+  }
+}
+
+VMState::VMState(StateTag state) {
+#if !defined(ENABLE_HEAP_PROTECTION)
+  // When not protecting the heap, there is no difference between
+  // EXTERNAL and OTHER.  As an optimizatin in that case, we will not
+  // perform EXTERNAL->OTHER transitions through the API.  We thus
+  // compress the two states into one.
+  if (state == EXTERNAL) state = OTHER;
+#endif
+  state_ = state;
+  previous_ = Logger::current_state_;
+  Logger::current_state_ = this;
+
+  if (FLAG_log_state_changes) {
+    LOG(UncheckedStringEvent("Entering", StateToString(state_)));
+    if (previous_ != NULL) {
+      LOG(UncheckedStringEvent("From", StateToString(previous_->state_)));
+    }
+  }
+
+#ifdef ENABLE_HEAP_PROTECTION
+  if (FLAG_protect_heap && previous_ != NULL) {
+    if (state_ == EXTERNAL) {
+      // We are leaving V8.
+      ASSERT(previous_->state_ != EXTERNAL);
+      Heap::Protect();
+    } else if (previous_->state_ == EXTERNAL) {
+      // We are entering V8.
+      Heap::Unprotect();
+    }
+  }
+#endif
+}
+
+
+VMState::~VMState() {
+  Logger::current_state_ = previous_;
+
+  if (FLAG_log_state_changes) {
+    LOG(UncheckedStringEvent("Leaving", StateToString(state_)));
+    if (previous_ != NULL) {
+      LOG(UncheckedStringEvent("To", StateToString(previous_->state_)));
+    }
+  }
+
+#ifdef ENABLE_HEAP_PROTECTION
+  if (FLAG_protect_heap && previous_ != NULL) {
+    if (state_ == EXTERNAL) {
+      // We are reentering V8.
+      ASSERT(previous_->state_ != EXTERNAL);
+      Heap::Unprotect();
+    } else if (previous_->state_ == EXTERNAL) {
+      // We are leaving V8.
+      Heap::Protect();
+    }
+  }
+#endif
+}
+#endif
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/log.h b/deps/v8/src/log.h
new file mode 100644
index 0000000..bbcfa42
--- /dev/null
+++ b/deps/v8/src/log.h
@@ -0,0 +1,292 @@
+// 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_LOG_H_
+#define V8_LOG_H_
+
+namespace v8 { namespace internal {
+
+// Logger is used for collecting logging information from V8 during
+// execution. The result is dumped to a file.
+//
+// Available command line flags:
+//
+//  --log
+// Minimal logging (no API, code, or GC sample events), default is off.
+//
+// --log-all
+// Log all events to the file, default is off.  This is the same as combining
+// --log-api, --log-code, --log-gc, and --log-regexp.
+//
+// --log-api
+// Log API events to the logfile, default is off.  --log-api implies --log.
+//
+// --log-code
+// Log code (create, move, and delete) events to the logfile, default is off.
+// --log-code implies --log.
+//
+// --log-gc
+// Log GC heap samples after each GC that can be processed by hp2ps, default
+// is off.  --log-gc implies --log.
+//
+// --log-regexp
+// Log creation and use of regular expressions, Default is off.
+// --log-regexp implies --log.
+//
+// --logfile <filename>
+// Specify the name of the logfile, default is "v8.log".
+//
+// --prof
+// Collect statistical profiling information (ticks), default is off.  The
+// tick profiler requires code events, so --prof implies --log-code.
+
+// Forward declarations.
+class Ticker;
+class Profiler;
+class Semaphore;
+class SlidingStateWindow;
+class LogMessageBuilder;
+
+#undef LOG
+#ifdef ENABLE_LOGGING_AND_PROFILING
+#define LOG(Call)                           \
+  do {                                      \
+    if (v8::internal::Logger::is_enabled()) \
+      v8::internal::Logger::Call;           \
+  } while (false)
+#else
+#define LOG(Call) ((void) 0)
+#endif
+
+
+class VMState BASE_EMBEDDED {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+ public:
+  explicit VMState(StateTag state);
+  ~VMState();
+
+  StateTag state() { return state_; }
+
+ private:
+  StateTag state_;
+  VMState* previous_;
+#else
+ public:
+  explicit VMState(StateTag state) {}
+#endif
+};
+
+
+class Logger {
+ public:
+  // Opens the file for logging if the right flags are set.
+  static bool Setup();
+
+  // Closes file opened in Setup.
+  static void TearDown();
+
+  // Enable the computation of a sliding window of states.
+  static void EnableSlidingStateWindow();
+
+  // Write a raw string to the log to be used as a preamble.
+  // No check is made that the 'preamble' is actually at the beginning
+  // of the log. The preample is used to write code events saved in the
+  // snapshot.
+  static void Preamble(const char* content);
+
+  // Emits an event with a string value -> (name, value).
+  static void StringEvent(const char* name, const char* value);
+
+  // Emits an event with an int value -> (name, value).
+  static void IntEvent(const char* name, int value);
+
+  // Emits an event with an handle value -> (name, location).
+  static void HandleEvent(const char* name, Object** location);
+
+  // Emits memory management events for C allocated structures.
+  static void NewEvent(const char* name, void* object, size_t size);
+  static void DeleteEvent(const char* name, void* object);
+
+  // Emits an event with a tag, and some resource usage information.
+  // -> (name, tag, <rusage information>).
+  // Currently, the resource usage information is a process time stamp
+  // and a real time timestamp.
+  static void ResourceEvent(const char* name, const char* tag);
+
+  // Emits an event that an undefined property was read from an
+  // object.
+  static void SuspectReadEvent(String* name, Object* obj);
+
+  // Emits an event when a message is put on or read from a debugging queue.
+  // DebugTag lets us put a call-site specific label on the event.
+  static void DebugTag(const char* call_site_tag);
+  static void DebugEvent(const char* event_type, Vector<uint16_t> parameter);
+
+
+  // ==== Events logged by --log-api. ====
+  static void ApiNamedSecurityCheck(Object* key);
+  static void ApiIndexedSecurityCheck(uint32_t index);
+  static void ApiNamedPropertyAccess(const char* tag,
+                                     JSObject* holder,
+                                     Object* name);
+  static void ApiIndexedPropertyAccess(const char* tag,
+                                       JSObject* holder,
+                                       uint32_t index);
+  static void ApiObjectAccess(const char* tag, JSObject* obj);
+  static void ApiEntryCall(const char* name);
+
+
+  // ==== Events logged by --log-code. ====
+  // Emits a code create event.
+  static void CodeCreateEvent(const char* tag, Code* code, const char* source);
+  static void CodeCreateEvent(const char* tag, Code* code, String* name);
+  static void CodeCreateEvent(const char* tag, Code* code, String* name,
+                              String* source, int line);
+  static void CodeCreateEvent(const char* tag, Code* code, int args_count);
+  // Emits a code create event for a RegExp.
+  static void RegExpCodeCreateEvent(Code* code, String* source);
+  static void CodeAllocateEvent(Code* code, Assembler* assem);
+  // Emits a code move event.
+  static void CodeMoveEvent(Address from, Address to);
+  // Emits a code delete event.
+  static void CodeDeleteEvent(Address from);
+  // Emits region delimiters
+  static void BeginCodeRegionEvent(CodeRegion* region,
+                                   Assembler* masm,
+                                   const char* name);
+  static void EndCodeRegionEvent(CodeRegion* region, Assembler* masm);
+
+  // ==== Events logged by --log-gc. ====
+  // Heap sampling events: start, end, and individual types.
+  static void HeapSampleBeginEvent(const char* space, const char* kind);
+  static void HeapSampleEndEvent(const char* space, const char* kind);
+  static void HeapSampleItemEvent(const char* type, int number, int bytes);
+
+  static void SharedLibraryEvent(const char* library_path,
+                                 unsigned start,
+                                 unsigned end);
+  static void SharedLibraryEvent(const wchar_t* library_path,
+                                 unsigned start,
+                                 unsigned end);
+
+  // ==== Events logged by --log-regexp ====
+  // Regexp compilation and execution events.
+
+  static void RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache);
+
+  // Log an event reported from generated code
+  static void LogRuntime(Vector<const char> format, JSArray* args);
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  static StateTag state() {
+    return current_state_ ? current_state_->state() : OTHER;
+  }
+
+  static bool is_enabled() { return logfile_ != NULL; }
+
+  // Pause/Resume collection of profiling data.
+  // When data collection is paused, Tick events are discarded until
+  // data collection is Resumed.
+  static bool IsProfilerPaused();
+  static void PauseProfiler();
+  static void ResumeProfiler();
+
+ private:
+
+  // Emits the source code of a regexp. Used by regexp events.
+  static void LogRegExpSource(Handle<JSRegExp> regexp);
+
+  // Emits a profiler tick event. Used by the profiler thread.
+  static void TickEvent(TickSample* sample, bool overflow);
+
+  static void ApiEvent(const char* name, ...);
+
+  // Logs a StringEvent regardless of whether FLAG_log is true.
+  static void UncheckedStringEvent(const char* name, const char* value);
+
+  // Size of buffer used for formatting log messages.
+  static const int kMessageBufferSize = 2048;
+
+  // Buffer used for formatting log messages. This is a singleton buffer and
+  // mutex_ should be acquired before using it.
+  static char* message_buffer_;
+
+  // When logging is active, logfile_ refers the file events are written to.
+  // mutex_ should be acquired before using logfile_.
+  static FILE* logfile_;
+
+  // The sampler used by the profiler and the sliding state window.
+  static Ticker* ticker_;
+
+  // When the statistical profile is active, profiler_
+  // points to a Profiler, that handles collection
+  // of samples.
+  static Profiler* profiler_;
+
+  // mutex_ is a Mutex used for enforcing exclusive
+  // access to the formatting buffer and the log file.
+  static Mutex* mutex_;
+
+  // A stack of VM states.
+  static VMState* current_state_;
+
+  // Singleton bottom or default vm state.
+  static VMState bottom_state_;
+
+  // SlidingStateWindow instance keeping a sliding window of the most
+  // recent VM states.
+  static SlidingStateWindow* sliding_state_window_;
+
+  // Internal implementation classes with access to
+  // private members.
+  friend class LogMessageBuilder;
+  friend class EventLog;
+  friend class TimeLog;
+  friend class Profiler;
+  friend class SlidingStateWindow;
+  friend class VMState;
+#else
+  static bool is_enabled() { return false; }
+#endif
+};
+
+
+// Class that extracts stack trace, used for profiling.
+class StackTracer BASE_EMBEDDED {
+ public:
+  explicit StackTracer(unsigned int low_stack_bound)
+      : low_stack_bound_(low_stack_bound) { }
+  void Trace(TickSample* sample);
+ private:
+
+  unsigned int low_stack_bound_;
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_LOG_H_
diff --git a/deps/v8/src/macro-assembler-arm.cc b/deps/v8/src/macro-assembler-arm.cc
new file mode 100644
index 0000000..88a300b
--- /dev/null
+++ b/deps/v8/src/macro-assembler-arm.cc
@@ -0,0 +1,936 @@
+// 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.
+
+#include "v8.h"
+
+#include "bootstrapper.h"
+#include "codegen-inl.h"
+#include "debug.h"
+#include "runtime.h"
+
+namespace v8 { namespace internal {
+
+// Give alias names to registers
+Register cp = {  8 };  // JavaScript context pointer
+Register pp = { 10 };  // parameter pointer
+
+
+MacroAssembler::MacroAssembler(void* buffer, int size)
+    : Assembler(buffer, size),
+      unresolved_(0),
+      generating_stub_(false),
+      allow_stub_calls_(true),
+      code_object_(Heap::undefined_value()) {
+}
+
+
+// We always generate arm code, never thumb code, even if V8 is compiled to
+// thumb, so we require inter-working support
+#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
+#error "flag -mthumb-interwork missing"
+#endif
+
+
+// We do not support thumb inter-working with an arm architecture not supporting
+// the blx instruction (below v5t)
+#if defined(__THUMB_INTERWORK__)
+#if !defined(__ARM_ARCH_5T__) && !defined(__ARM_ARCH_5TE__)
+// add tests for other versions above v5t as required
+#error "for thumb inter-working we require architecture v5t or above"
+#endif
+#endif
+
+
+// Using blx may yield better code, so use it when required or when available
+#if defined(__THUMB_INTERWORK__) || defined(__ARM_ARCH_5__)
+#define USE_BLX 1
+#endif
+
+// Using bx does not yield better code, so use it only when required
+#if defined(__THUMB_INTERWORK__)
+#define USE_BX 1
+#endif
+
+
+void MacroAssembler::Jump(Register target, Condition cond) {
+#if USE_BX
+  bx(target, cond);
+#else
+  mov(pc, Operand(target), LeaveCC, cond);
+#endif
+}
+
+
+void MacroAssembler::Jump(intptr_t target, RelocInfo::Mode rmode,
+                          Condition cond) {
+#if USE_BX
+  mov(ip, Operand(target, rmode), LeaveCC, cond);
+  bx(ip, cond);
+#else
+  mov(pc, Operand(target, rmode), LeaveCC, cond);
+#endif
+}
+
+
+void MacroAssembler::Jump(byte* target, RelocInfo::Mode rmode,
+                          Condition cond) {
+  ASSERT(!RelocInfo::IsCodeTarget(rmode));
+  Jump(reinterpret_cast<intptr_t>(target), rmode, cond);
+}
+
+
+void MacroAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode,
+                          Condition cond) {
+  ASSERT(RelocInfo::IsCodeTarget(rmode));
+  // 'code' is always generated ARM code, never THUMB code
+  Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond);
+}
+
+
+void MacroAssembler::Call(Register target, Condition cond) {
+#if USE_BLX
+  blx(target, cond);
+#else
+  // set lr for return at current pc + 8
+  mov(lr, Operand(pc), LeaveCC, cond);
+  mov(pc, Operand(target), LeaveCC, cond);
+#endif
+}
+
+
+void MacroAssembler::Call(intptr_t target, RelocInfo::Mode rmode,
+                          Condition cond) {
+#if !defined(__arm__)
+  if (rmode == RelocInfo::RUNTIME_ENTRY) {
+    mov(r2, Operand(target, rmode), LeaveCC, cond);
+    // Set lr for return at current pc + 8.
+    mov(lr, Operand(pc), LeaveCC, cond);
+    // Emit a ldr<cond> pc, [pc + offset of target in constant pool].
+    // Notify the simulator of the transition to C code.
+    swi(assembler::arm::call_rt_r2);
+  } else {
+    // set lr for return at current pc + 8
+    mov(lr, Operand(pc), LeaveCC, cond);
+    // emit a ldr<cond> pc, [pc + offset of target in constant pool]
+    mov(pc, Operand(target, rmode), LeaveCC, cond);
+  }
+#else
+  // Set lr for return at current pc + 8.
+  mov(lr, Operand(pc), LeaveCC, cond);
+  // Emit a ldr<cond> pc, [pc + offset of target in constant pool].
+  mov(pc, Operand(target, rmode), LeaveCC, cond);
+#endif  // !defined(__arm__)
+  // If USE_BLX is defined, we could emit a 'mov ip, target', followed by a
+  // 'blx ip'; however, the code would not be shorter than the above sequence
+  // and the target address of the call would be referenced by the first
+  // instruction rather than the second one, which would make it harder to patch
+  // (two instructions before the return address, instead of one).
+  ASSERT(kTargetAddrToReturnAddrDist == sizeof(Instr));
+}
+
+
+void MacroAssembler::Call(byte* target, RelocInfo::Mode rmode,
+                          Condition cond) {
+  ASSERT(!RelocInfo::IsCodeTarget(rmode));
+  Call(reinterpret_cast<intptr_t>(target), rmode, cond);
+}
+
+
+void MacroAssembler::Call(Handle<Code> code, RelocInfo::Mode rmode,
+                          Condition cond) {
+  ASSERT(RelocInfo::IsCodeTarget(rmode));
+  // 'code' is always generated ARM code, never THUMB code
+  Call(reinterpret_cast<intptr_t>(code.location()), rmode, cond);
+}
+
+
+void MacroAssembler::Ret() {
+#if USE_BX
+  bx(lr);
+#else
+  mov(pc, Operand(lr));
+#endif
+}
+
+
+void MacroAssembler::SmiJumpTable(Register index, Vector<Label*> targets) {
+  // Empty the const pool.
+  CheckConstPool(true, true);
+  add(pc, pc, Operand(index,
+                      LSL,
+                      assembler::arm::Instr::kInstrSizeLog2 - kSmiTagSize));
+  BlockConstPoolBefore(pc_offset() + (targets.length() + 1) * sizeof(Instr));
+  nop();  // Jump table alignment.
+  for (int i = 0; i < targets.length(); i++) {
+    b(targets[i]);
+  }
+}
+
+
+// Will clobber 4 registers: object, offset, scratch, ip.  The
+// register 'object' contains a heap object pointer.  The heap object
+// tag is shifted away.
+void MacroAssembler::RecordWrite(Register object, Register offset,
+                                 Register scratch) {
+  // This is how much we shift the remembered set bit offset to get the
+  // offset of the word in the remembered set.  We divide by kBitsPerInt (32,
+  // shift right 5) and then multiply by kIntSize (4, shift left 2).
+  const int kRSetWordShift = 3;
+
+  Label fast, done;
+
+  // First, test that the object is not in the new space.  We cannot set
+  // remembered set bits in the new space.
+  // object: heap object pointer (with tag)
+  // offset: offset to store location from the object
+  and_(scratch, object, Operand(Heap::NewSpaceMask()));
+  cmp(scratch, Operand(ExternalReference::new_space_start()));
+  b(eq, &done);
+
+  // Compute the bit offset in the remembered set.
+  // object: heap object pointer (with tag)
+  // offset: offset to store location from the object
+  mov(ip, Operand(Page::kPageAlignmentMask));  // load mask only once
+  and_(scratch, object, Operand(ip));  // offset into page of the object
+  add(offset, scratch, Operand(offset));  // add offset into the object
+  mov(offset, Operand(offset, LSR, kObjectAlignmentBits));
+
+  // Compute the page address from the heap object pointer.
+  // object: heap object pointer (with tag)
+  // offset: bit offset of store position in the remembered set
+  bic(object, object, Operand(ip));
+
+  // If the bit offset lies beyond the normal remembered set range, it is in
+  // the extra remembered set area of a large object.
+  // object: page start
+  // offset: bit offset of store position in the remembered set
+  cmp(offset, Operand(Page::kPageSize / kPointerSize));
+  b(lt, &fast);
+
+  // Adjust the bit offset to be relative to the start of the extra
+  // remembered set and the start address to be the address of the extra
+  // remembered set.
+  sub(offset, offset, Operand(Page::kPageSize / kPointerSize));
+  // Load the array length into 'scratch' and multiply by four to get the
+  // size in bytes of the elements.
+  ldr(scratch, MemOperand(object, Page::kObjectStartOffset
+                                  + FixedArray::kLengthOffset));
+  mov(scratch, Operand(scratch, LSL, kObjectAlignmentBits));
+  // Add the page header (including remembered set), array header, and array
+  // body size to the page address.
+  add(object, object, Operand(Page::kObjectStartOffset
+                              + Array::kHeaderSize));
+  add(object, object, Operand(scratch));
+
+  bind(&fast);
+  // Get address of the rset word.
+  // object: start of the remembered set (page start for the fast case)
+  // offset: bit offset of store position in the remembered set
+  bic(scratch, offset, Operand(kBitsPerInt - 1));  // clear the bit offset
+  add(object, object, Operand(scratch, LSR, kRSetWordShift));
+  // Get bit offset in the rset word.
+  // object: address of remembered set word
+  // offset: bit offset of store position
+  and_(offset, offset, Operand(kBitsPerInt - 1));
+
+  ldr(scratch, MemOperand(object));
+  mov(ip, Operand(1));
+  orr(scratch, scratch, Operand(ip, LSL, offset));
+  str(scratch, MemOperand(object));
+
+  bind(&done);
+}
+
+
+void MacroAssembler::EnterFrame(StackFrame::Type type) {
+  // r0-r3: preserved
+  stm(db_w, sp, cp.bit() | fp.bit() | lr.bit());
+  mov(ip, Operand(Smi::FromInt(type)));
+  push(ip);
+  mov(ip, Operand(CodeObject()));
+  push(ip);
+  add(fp, sp, Operand(3 * kPointerSize));  // Adjust FP to point to saved FP.
+}
+
+
+void MacroAssembler::LeaveFrame(StackFrame::Type type) {
+  // r0: preserved
+  // r1: preserved
+  // r2: preserved
+
+  // Drop the execution stack down to the frame pointer and restore
+  // the caller frame pointer and return address.
+  mov(sp, fp);
+  ldm(ia_w, sp, fp.bit() | lr.bit());
+}
+
+
+void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
+  ASSERT(type == StackFrame::EXIT || type == StackFrame::EXIT_DEBUG);
+  // Compute parameter pointer before making changes and save it as ip
+  // register so that it is restored as sp register on exit, thereby
+  // popping the args.
+
+  // ip = sp + kPointerSize * #args;
+  add(ip, sp, Operand(r0, LSL, kPointerSizeLog2));
+
+  // Push in reverse order: caller_fp, sp_on_exit, and caller_pc.
+  stm(db_w, sp, fp.bit() | ip.bit() | lr.bit());
+  mov(fp, Operand(sp));  // setup new frame pointer
+
+  // Push debug marker.
+  mov(ip, Operand(type == StackFrame::EXIT_DEBUG ? 1 : 0));
+  push(ip);
+
+  // Save the frame pointer and the context in top.
+  mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address)));
+  str(fp, MemOperand(ip));
+  mov(ip, Operand(ExternalReference(Top::k_context_address)));
+  str(cp, MemOperand(ip));
+
+  // Setup argc and the builtin function in callee-saved registers.
+  mov(r4, Operand(r0));
+  mov(r5, Operand(r1));
+
+  // Compute the argv pointer and keep it in a callee-saved register.
+  add(r6, fp, Operand(r4, LSL, kPointerSizeLog2));
+  add(r6, r6, Operand(ExitFrameConstants::kPPDisplacement - kPointerSize));
+
+  // Save the state of all registers to the stack from the memory
+  // location. This is needed to allow nested break points.
+  if (type == StackFrame::EXIT_DEBUG) {
+    // Use sp as base to push.
+    CopyRegistersFromMemoryToStack(sp, kJSCallerSaved);
+  }
+}
+
+
+void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
+  // Restore the memory copy of the registers by digging them out from
+  // the stack. This is needed to allow nested break points.
+  if (type == StackFrame::EXIT_DEBUG) {
+    // This code intentionally clobbers r2 and r3.
+    const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize;
+    const int kOffset = ExitFrameConstants::kDebugMarkOffset - kCallerSavedSize;
+    add(r3, fp, Operand(kOffset));
+    CopyRegistersFromStackToMemory(r3, r2, kJSCallerSaved);
+  }
+
+  // Clear top frame.
+  mov(r3, Operand(0));
+  mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address)));
+  str(r3, MemOperand(ip));
+
+  // Restore current context from top and clear it in debug mode.
+  mov(ip, Operand(ExternalReference(Top::k_context_address)));
+  ldr(cp, MemOperand(ip));
+  if (kDebug) {
+    str(r3, MemOperand(ip));
+  }
+
+  // Pop the arguments, restore registers, and return.
+  mov(sp, Operand(fp));  // respect ABI stack constraint
+  ldm(ia, sp, fp.bit() | sp.bit() | pc.bit());
+}
+
+
+void MacroAssembler::InvokePrologue(const ParameterCount& expected,
+                                    const ParameterCount& actual,
+                                    Handle<Code> code_constant,
+                                    Register code_reg,
+                                    Label* done,
+                                    InvokeFlag flag) {
+  bool definitely_matches = false;
+  Label regular_invoke;
+
+  // Check whether the expected and actual arguments count match. If not,
+  // setup registers according to contract with ArgumentsAdaptorTrampoline:
+  //  r0: actual arguments count
+  //  r1: function (passed through to callee)
+  //  r2: expected arguments count
+  //  r3: callee code entry
+
+  // The code below is made a lot easier because the calling code already sets
+  // up actual and expected registers according to the contract if values are
+  // passed in registers.
+  ASSERT(actual.is_immediate() || actual.reg().is(r0));
+  ASSERT(expected.is_immediate() || expected.reg().is(r2));
+  ASSERT((!code_constant.is_null() && code_reg.is(no_reg)) || code_reg.is(r3));
+
+  if (expected.is_immediate()) {
+    ASSERT(actual.is_immediate());
+    if (expected.immediate() == actual.immediate()) {
+      definitely_matches = true;
+    } else {
+      mov(r0, Operand(actual.immediate()));
+      const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
+      if (expected.immediate() == sentinel) {
+        // Don't worry about adapting arguments for builtins that
+        // don't want that done. Skip adaption code by making it look
+        // like we have a match between expected and actual number of
+        // arguments.
+        definitely_matches = true;
+      } else {
+        mov(r2, Operand(expected.immediate()));
+      }
+    }
+  } else {
+    if (actual.is_immediate()) {
+      cmp(expected.reg(), Operand(actual.immediate()));
+      b(eq, &regular_invoke);
+      mov(r0, Operand(actual.immediate()));
+    } else {
+      cmp(expected.reg(), Operand(actual.reg()));
+      b(eq, &regular_invoke);
+    }
+  }
+
+  if (!definitely_matches) {
+    if (!code_constant.is_null()) {
+      mov(r3, Operand(code_constant));
+      add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
+    }
+
+    Handle<Code> adaptor =
+        Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
+    if (flag == CALL_FUNCTION) {
+      Call(adaptor, RelocInfo::CODE_TARGET);
+      b(done);
+    } else {
+      Jump(adaptor, RelocInfo::CODE_TARGET);
+    }
+    bind(&regular_invoke);
+  }
+}
+
+
+void MacroAssembler::InvokeCode(Register code,
+                                const ParameterCount& expected,
+                                const ParameterCount& actual,
+                                InvokeFlag flag) {
+  Label done;
+
+  InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag);
+  if (flag == CALL_FUNCTION) {
+    Call(code);
+  } else {
+    ASSERT(flag == JUMP_FUNCTION);
+    Jump(code);
+  }
+
+  // Continue here if InvokePrologue does handle the invocation due to
+  // mismatched parameter counts.
+  bind(&done);
+}
+
+
+void MacroAssembler::InvokeCode(Handle<Code> code,
+                                const ParameterCount& expected,
+                                const ParameterCount& actual,
+                                RelocInfo::Mode rmode,
+                                InvokeFlag flag) {
+  Label done;
+
+  InvokePrologue(expected, actual, code, no_reg, &done, flag);
+  if (flag == CALL_FUNCTION) {
+    Call(code, rmode);
+  } else {
+    Jump(code, rmode);
+  }
+
+  // Continue here if InvokePrologue does handle the invocation due to
+  // mismatched parameter counts.
+  bind(&done);
+}
+
+
+void MacroAssembler::InvokeFunction(Register fun,
+                                    const ParameterCount& actual,
+                                    InvokeFlag flag) {
+  // Contract with called JS functions requires that function is passed in r1.
+  ASSERT(fun.is(r1));
+
+  Register expected_reg = r2;
+  Register code_reg = r3;
+
+  ldr(code_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
+  ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
+  ldr(expected_reg,
+      FieldMemOperand(code_reg,
+                      SharedFunctionInfo::kFormalParameterCountOffset));
+  ldr(code_reg,
+      MemOperand(code_reg, SharedFunctionInfo::kCodeOffset - kHeapObjectTag));
+  add(code_reg, code_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
+
+  ParameterCount expected(expected_reg);
+  InvokeCode(code_reg, expected, actual, flag);
+}
+
+
+void MacroAssembler::SaveRegistersToMemory(RegList regs) {
+  ASSERT((regs & ~kJSCallerSaved) == 0);
+  // Copy the content of registers to memory location.
+  for (int i = 0; i < kNumJSCallerSaved; i++) {
+    int r = JSCallerSavedCode(i);
+    if ((regs & (1 << r)) != 0) {
+      Register reg = { r };
+      mov(ip, Operand(ExternalReference(Debug_Address::Register(i))));
+      str(reg, MemOperand(ip));
+    }
+  }
+}
+
+
+void MacroAssembler::RestoreRegistersFromMemory(RegList regs) {
+  ASSERT((regs & ~kJSCallerSaved) == 0);
+  // Copy the content of memory location to registers.
+  for (int i = kNumJSCallerSaved; --i >= 0;) {
+    int r = JSCallerSavedCode(i);
+    if ((regs & (1 << r)) != 0) {
+      Register reg = { r };
+      mov(ip, Operand(ExternalReference(Debug_Address::Register(i))));
+      ldr(reg, MemOperand(ip));
+    }
+  }
+}
+
+
+void MacroAssembler::CopyRegistersFromMemoryToStack(Register base,
+                                                    RegList regs) {
+  ASSERT((regs & ~kJSCallerSaved) == 0);
+  // Copy the content of the memory location to the stack and adjust base.
+  for (int i = kNumJSCallerSaved; --i >= 0;) {
+    int r = JSCallerSavedCode(i);
+    if ((regs & (1 << r)) != 0) {
+      mov(ip, Operand(ExternalReference(Debug_Address::Register(i))));
+      ldr(ip, MemOperand(ip));
+      str(ip, MemOperand(base, 4, NegPreIndex));
+    }
+  }
+}
+
+
+void MacroAssembler::CopyRegistersFromStackToMemory(Register base,
+                                                    Register scratch,
+                                                    RegList regs) {
+  ASSERT((regs & ~kJSCallerSaved) == 0);
+  // Copy the content of the stack to the memory location and adjust base.
+  for (int i = 0; i < kNumJSCallerSaved; i++) {
+    int r = JSCallerSavedCode(i);
+    if ((regs & (1 << r)) != 0) {
+      mov(ip, Operand(ExternalReference(Debug_Address::Register(i))));
+      ldr(scratch, MemOperand(base, 4, PostIndex));
+      str(scratch, MemOperand(ip));
+    }
+  }
+}
+
+
+void MacroAssembler::PushTryHandler(CodeLocation try_location,
+                                    HandlerType type) {
+  ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize);  // adjust this code
+  // The pc (return address) is passed in register lr.
+  if (try_location == IN_JAVASCRIPT) {
+    stm(db_w, sp, pp.bit() | fp.bit() | lr.bit());
+    if (type == TRY_CATCH_HANDLER) {
+      mov(r3, Operand(StackHandler::TRY_CATCH));
+    } else {
+      mov(r3, Operand(StackHandler::TRY_FINALLY));
+    }
+    push(r3);  // state
+    mov(r3, Operand(ExternalReference(Top::k_handler_address)));
+    ldr(r1, MemOperand(r3));
+    push(r1);  // next sp
+    str(sp, MemOperand(r3));  // chain handler
+    mov(r0, Operand(Smi::FromInt(StackHandler::kCodeNotPresent)));  // new TOS
+    push(r0);
+  } else {
+    // Must preserve r0-r4, r5-r7 are available.
+    ASSERT(try_location == IN_JS_ENTRY);
+    // The parameter pointer is meaningless here and fp does not point to a JS
+    // frame. So we save NULL for both pp and fp. We expect the code throwing an
+    // exception to check fp before dereferencing it to restore the context.
+    mov(pp, Operand(0));  // set pp to NULL
+    mov(ip, Operand(0));  // to save a NULL fp
+    stm(db_w, sp, pp.bit() | ip.bit() | lr.bit());
+    mov(r6, Operand(StackHandler::ENTRY));
+    push(r6);  // state
+    mov(r7, Operand(ExternalReference(Top::k_handler_address)));
+    ldr(r6, MemOperand(r7));
+    push(r6);  // next sp
+    str(sp, MemOperand(r7));  // chain handler
+    mov(r5, Operand(Smi::FromInt(StackHandler::kCodeNotPresent)));  // new TOS
+    push(r5);  // flush TOS
+  }
+}
+
+
+Register MacroAssembler::CheckMaps(JSObject* object, Register object_reg,
+                                   JSObject* holder, Register holder_reg,
+                                   Register scratch,
+                                   Label* miss) {
+  // Make sure there's no overlap between scratch and the other
+  // registers.
+  ASSERT(!scratch.is(object_reg) && !scratch.is(holder_reg));
+
+  // Keep track of the current object in register reg.
+  Register reg = object_reg;
+  int depth = 1;
+
+  // Check the maps in the prototype chain.
+  // Traverse the prototype chain from the object and do map checks.
+  while (object != holder) {
+    depth++;
+
+    // Only global objects and objects that do not require access
+    // checks are allowed in stubs.
+    ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
+
+    // Get the map of the current object.
+    ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
+    cmp(scratch, Operand(Handle<Map>(object->map())));
+
+    // Branch on the result of the map check.
+    b(ne, miss);
+
+    // Check access rights to the global object.  This has to happen
+    // after the map check so that we know that the object is
+    // actually a global object.
+    if (object->IsJSGlobalProxy()) {
+      CheckAccessGlobalProxy(reg, scratch, miss);
+      // Restore scratch register to be the map of the object.  In the
+      // new space case below, we load the prototype from the map in
+      // the scratch register.
+      ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
+    }
+
+    reg = holder_reg;  // from now the object is in holder_reg
+    JSObject* prototype = JSObject::cast(object->GetPrototype());
+    if (Heap::InNewSpace(prototype)) {
+      // The prototype is in new space; we cannot store a reference
+      // to it in the code. Load it from the map.
+      ldr(reg, FieldMemOperand(scratch, Map::kPrototypeOffset));
+    } else {
+      // The prototype is in old space; load it directly.
+      mov(reg, Operand(Handle<JSObject>(prototype)));
+    }
+
+    // Go to the next object in the prototype chain.
+    object = prototype;
+  }
+
+  // Check the holder map.
+  ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
+  cmp(scratch, Operand(Handle<Map>(object->map())));
+  b(ne, miss);
+
+  // Log the check depth.
+  LOG(IntEvent("check-maps-depth", depth));
+
+  // Perform security check for access to the global object and return
+  // the holder register.
+  ASSERT(object == holder);
+  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
+  if (object->IsJSGlobalProxy()) {
+    CheckAccessGlobalProxy(reg, scratch, miss);
+  }
+  return reg;
+}
+
+
+void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
+                                            Register scratch,
+                                            Label* miss) {
+  Label same_contexts;
+
+  ASSERT(!holder_reg.is(scratch));
+  ASSERT(!holder_reg.is(ip));
+  ASSERT(!scratch.is(ip));
+
+  // Load current lexical context from the stack frame.
+  ldr(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  // In debug mode, make sure the lexical context is set.
+  if (kDebug) {
+    cmp(scratch, Operand(0));
+    Check(ne, "we should not have an empty lexical context");
+  }
+
+  // Load the global context of the current context.
+  int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
+  ldr(scratch, FieldMemOperand(scratch, offset));
+  ldr(scratch, FieldMemOperand(scratch, GlobalObject::kGlobalContextOffset));
+
+  // Check the context is a global context.
+  if (FLAG_debug_code) {
+    // TODO(119): avoid push(holder_reg)/pop(holder_reg)
+    // Cannot use ip as a temporary in this verification code. Due to the fact
+    // that ip is clobbered as part of cmp with an object Operand.
+    push(holder_reg);  // Temporarily save holder on the stack.
+    // Read the first word and compare to the global_context_map.
+    ldr(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset));
+    cmp(holder_reg, Operand(Factory::global_context_map()));
+    Check(eq, "JSGlobalObject::global_context should be a global context.");
+    pop(holder_reg);  // Restore holder.
+  }
+
+  // Check if both contexts are the same.
+  ldr(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kContextOffset));
+  cmp(scratch, Operand(ip));
+  b(eq, &same_contexts);
+
+  // Check the context is a global context.
+  if (FLAG_debug_code) {
+    // TODO(119): avoid push(holder_reg)/pop(holder_reg)
+    // Cannot use ip as a temporary in this verification code. Due to the fact
+    // that ip is clobbered as part of cmp with an object Operand.
+    push(holder_reg);  // Temporarily save holder on the stack.
+    mov(holder_reg, ip);  // Move ip to its holding place.
+    cmp(holder_reg, Operand(Factory::null_value()));
+    Check(ne, "JSGlobalProxy::context() should not be null.");
+
+    ldr(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset));
+    cmp(holder_reg, Operand(Factory::global_context_map()));
+    Check(eq, "JSGlobalObject::global_context should be a global context.");
+    // Restore ip is not needed. ip is reloaded below.
+    pop(holder_reg);  // Restore holder.
+    // Restore ip to holder's context.
+    ldr(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kContextOffset));
+  }
+
+  // Check that the security token in the calling global object is
+  // compatible with the security token in the receiving global
+  // object.
+  int token_offset = Context::kHeaderSize +
+                     Context::SECURITY_TOKEN_INDEX * kPointerSize;
+
+  ldr(scratch, FieldMemOperand(scratch, token_offset));
+  ldr(ip, FieldMemOperand(ip, token_offset));
+  cmp(scratch, Operand(ip));
+  b(ne, miss);
+
+  bind(&same_contexts);
+}
+
+
+void MacroAssembler::CallStub(CodeStub* stub) {
+  ASSERT(allow_stub_calls());  // stub calls are not allowed in some stubs
+  Call(stub->GetCode(), RelocInfo::CODE_TARGET);
+}
+
+
+void MacroAssembler::StubReturn(int argc) {
+  ASSERT(argc >= 1 && generating_stub());
+  if (argc > 1)
+    add(sp, sp, Operand((argc - 1) * kPointerSize));
+  Ret();
+}
+
+
+void MacroAssembler::IllegalOperation(int num_arguments) {
+  if (num_arguments > 0) {
+    add(sp, sp, Operand(num_arguments * kPointerSize));
+  }
+  mov(r0, Operand(Factory::undefined_value()));
+}
+
+
+void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
+  // All parameters are on the stack.  r0 has the return value after call.
+
+  // If the expected number of arguments of the runtime function is
+  // constant, we check that the actual number of arguments match the
+  // expectation.
+  if (f->nargs >= 0 && f->nargs != num_arguments) {
+    IllegalOperation(num_arguments);
+    return;
+  }
+
+  Runtime::FunctionId function_id =
+      static_cast<Runtime::FunctionId>(f->stub_id);
+  RuntimeStub stub(function_id, num_arguments);
+  CallStub(&stub);
+}
+
+
+void MacroAssembler::CallRuntime(Runtime::FunctionId fid, int num_arguments) {
+  CallRuntime(Runtime::FunctionForId(fid), num_arguments);
+}
+
+
+void MacroAssembler::TailCallRuntime(const ExternalReference& ext,
+                                     int num_arguments) {
+  // 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.
+  mov(r0, Operand(num_arguments));
+  JumpToBuiltin(ext);
+}
+
+
+void MacroAssembler::JumpToBuiltin(const ExternalReference& builtin) {
+#if defined(__thumb__)
+  // Thumb mode builtin.
+  ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1);
+#endif
+  mov(r1, Operand(builtin));
+  CEntryStub stub;
+  Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
+}
+
+
+Handle<Code> MacroAssembler::ResolveBuiltin(Builtins::JavaScript id,
+                                            bool* resolved) {
+  // Contract with compiled functions is that the function is passed in r1.
+  int builtins_offset =
+      JSBuiltinsObject::kJSBuiltinsOffset + (id * kPointerSize);
+  ldr(r1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
+  ldr(r1, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset));
+  ldr(r1, FieldMemOperand(r1, builtins_offset));
+
+  return Builtins::GetCode(id, resolved);
+}
+
+
+void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
+                                   InvokeJSFlags flags) {
+  bool resolved;
+  Handle<Code> code = ResolveBuiltin(id, &resolved);
+
+  if (flags == CALL_JS) {
+    Call(code, RelocInfo::CODE_TARGET);
+  } else {
+    ASSERT(flags == JUMP_JS);
+    Jump(code, RelocInfo::CODE_TARGET);
+  }
+
+  if (!resolved) {
+    const char* name = Builtins::GetName(id);
+    int argc = Builtins::GetArgumentsCount(id);
+    uint32_t flags =
+        Bootstrapper::FixupFlagsArgumentsCount::encode(argc) |
+        Bootstrapper::FixupFlagsIsPCRelative::encode(true) |
+        Bootstrapper::FixupFlagsUseCodeObject::encode(false);
+    Unresolved entry = { pc_offset() - sizeof(Instr), flags, name };
+    unresolved_.Add(entry);
+  }
+}
+
+
+void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
+  bool resolved;
+  Handle<Code> code = ResolveBuiltin(id, &resolved);
+
+  mov(target, Operand(code));
+  if (!resolved) {
+    const char* name = Builtins::GetName(id);
+    int argc = Builtins::GetArgumentsCount(id);
+    uint32_t flags =
+        Bootstrapper::FixupFlagsArgumentsCount::encode(argc) |
+        Bootstrapper::FixupFlagsIsPCRelative::encode(true) |
+        Bootstrapper::FixupFlagsUseCodeObject::encode(true);
+    Unresolved entry = { pc_offset() - sizeof(Instr), flags, name };
+    unresolved_.Add(entry);
+  }
+
+  add(target, target, Operand(Code::kHeaderSize - kHeapObjectTag));
+}
+
+
+void MacroAssembler::SetCounter(StatsCounter* counter, int value,
+                                Register scratch1, Register scratch2) {
+  if (FLAG_native_code_counters && counter->Enabled()) {
+    mov(scratch1, Operand(value));
+    mov(scratch2, Operand(ExternalReference(counter)));
+    str(scratch1, MemOperand(scratch2));
+  }
+}
+
+
+void MacroAssembler::IncrementCounter(StatsCounter* counter, int value,
+                                      Register scratch1, Register scratch2) {
+  ASSERT(value > 0);
+  if (FLAG_native_code_counters && counter->Enabled()) {
+    mov(scratch2, Operand(ExternalReference(counter)));
+    ldr(scratch1, MemOperand(scratch2));
+    add(scratch1, scratch1, Operand(value));
+    str(scratch1, MemOperand(scratch2));
+  }
+}
+
+
+void MacroAssembler::DecrementCounter(StatsCounter* counter, int value,
+                                      Register scratch1, Register scratch2) {
+  ASSERT(value > 0);
+  if (FLAG_native_code_counters && counter->Enabled()) {
+    mov(scratch2, Operand(ExternalReference(counter)));
+    ldr(scratch1, MemOperand(scratch2));
+    sub(scratch1, scratch1, Operand(value));
+    str(scratch1, MemOperand(scratch2));
+  }
+}
+
+
+void MacroAssembler::Assert(Condition cc, const char* msg) {
+  if (FLAG_debug_code)
+    Check(cc, msg);
+}
+
+
+void MacroAssembler::Check(Condition cc, const char* msg) {
+  Label L;
+  b(cc, &L);
+  Abort(msg);
+  // will not return here
+  bind(&L);
+}
+
+
+void MacroAssembler::Abort(const char* msg) {
+  // We want to pass the msg string like a smi to avoid GC
+  // problems, however msg is not guaranteed to be aligned
+  // properly. Instead, we pass an aligned pointer that is
+  // a proper v8 smi, but also pass the alignment difference
+  // from the real pointer as a smi.
+  intptr_t p1 = reinterpret_cast<intptr_t>(msg);
+  intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag;
+  ASSERT(reinterpret_cast<Object*>(p0)->IsSmi());
+#ifdef DEBUG
+  if (msg != NULL) {
+    RecordComment("Abort message: ");
+    RecordComment(msg);
+  }
+#endif
+  mov(r0, Operand(p0));
+  push(r0);
+  mov(r0, Operand(Smi::FromInt(p1 - p0)));
+  push(r0);
+  CallRuntime(Runtime::kAbort, 2);
+  // will not return here
+}
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/macro-assembler-arm.h b/deps/v8/src/macro-assembler-arm.h
new file mode 100644
index 0000000..4b999fd
--- /dev/null
+++ b/deps/v8/src/macro-assembler-arm.h
@@ -0,0 +1,303 @@
+// 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_MACRO_ASSEMBLER_ARM_H_
+#define V8_MACRO_ASSEMBLER_ARM_H_
+
+#include "assembler.h"
+
+namespace v8 { namespace internal {
+
+
+// Give alias names to registers
+extern Register cp;  // JavaScript context pointer
+extern Register pp;  // parameter pointer
+
+
+// Helper types to make boolean flag easier to read at call-site.
+enum InvokeFlag {
+  CALL_FUNCTION,
+  JUMP_FUNCTION
+};
+
+enum InvokeJSFlags {
+  CALL_JS,
+  JUMP_JS
+};
+
+enum ExitJSFlag {
+  RETURN,
+  DO_NOT_RETURN
+};
+
+enum CodeLocation {
+  IN_JAVASCRIPT,
+  IN_JS_ENTRY,
+  IN_C_ENTRY
+};
+
+enum HandlerType {
+  TRY_CATCH_HANDLER,
+  TRY_FINALLY_HANDLER,
+  JS_ENTRY_HANDLER
+};
+
+
+// MacroAssembler implements a collection of frequently used macros.
+class MacroAssembler: public Assembler {
+ public:
+  MacroAssembler(void* buffer, int size);
+
+  // ---------------------------------------------------------------------------
+  // Low-level helpers for compiler
+
+  // Jump, Call, and Ret pseudo instructions implementing inter-working
+ private:
+  void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al);
+  void Call(intptr_t target, RelocInfo::Mode rmode, Condition cond = al);
+ public:
+  void Jump(Register target, Condition cond = al);
+  void Jump(byte* target, RelocInfo::Mode rmode, Condition cond = al);
+  void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
+  void Call(Register target, Condition cond = al);
+  void Call(byte* target, RelocInfo::Mode rmode, Condition cond = al);
+  void Call(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
+  void Ret();
+  // Jumps to the label at the index given by the Smi in "index".
+  void SmiJumpTable(Register index, Vector<Label*> targets);
+
+  // Sets the remembered set bit for [address+offset], where address is the
+  // address of the heap object 'object'.  The address must be in the first 8K
+  // of an allocated page. The 'scratch' register is used in the
+  // implementation and all 3 registers are clobbered by the operation, as
+  // well as the ip register.
+  void RecordWrite(Register object, Register offset, Register scratch);
+
+  // ---------------------------------------------------------------------------
+  // Activation frames
+
+  void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); }
+  void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); }
+
+  void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
+  void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
+
+  // Enter specific kind of exit frame; either EXIT or
+  // EXIT_DEBUG. Expects the number of arguments in register r0 and
+  // the builtin function to call in register r1. Exits with argc in
+  // r4, argv in r6, and and the builtin function to call in r5.
+  void EnterExitFrame(StackFrame::Type type);
+
+  // Leave the current exit frame. Expects the return value in r0.
+  void LeaveExitFrame(StackFrame::Type type);
+
+
+  // ---------------------------------------------------------------------------
+  // JavaScript invokes
+
+  // Invoke the JavaScript function code by either calling or jumping.
+  void InvokeCode(Register code,
+                  const ParameterCount& expected,
+                  const ParameterCount& actual,
+                  InvokeFlag flag);
+
+  void InvokeCode(Handle<Code> code,
+                  const ParameterCount& expected,
+                  const ParameterCount& actual,
+                  RelocInfo::Mode rmode,
+                  InvokeFlag flag);
+
+  // Invoke the JavaScript function in the given register. Changes the
+  // current context to the context in the function before invoking.
+  void InvokeFunction(Register function,
+                      const ParameterCount& actual,
+                      InvokeFlag flag);
+
+
+  // ---------------------------------------------------------------------------
+  // Debugger Support
+
+  void SaveRegistersToMemory(RegList regs);
+  void RestoreRegistersFromMemory(RegList regs);
+  void CopyRegistersFromMemoryToStack(Register base, RegList regs);
+  void CopyRegistersFromStackToMemory(Register base,
+                                      Register scratch,
+                                      RegList regs);
+
+
+  // ---------------------------------------------------------------------------
+  // Exception handling
+
+  // Push a new try handler and link into try handler chain.
+  // The return address must be passed in register lr.
+  // On exit, r0 contains TOS (code slot).
+  void PushTryHandler(CodeLocation try_location, HandlerType type);
+
+
+  // ---------------------------------------------------------------------------
+  // Inline caching support
+
+  // Generates code that verifies that the maps of objects in the
+  // prototype chain of object hasn't changed since the code was
+  // generated and branches to the miss label if any map has. If
+  // necessary the function also generates code for security check
+  // in case of global object holders. The scratch and holder
+  // registers are always clobbered, but the object register is only
+  // clobbered if it the same as the holder register. The function
+  // returns a register containing the holder - either object_reg or
+  // holder_reg.
+  Register CheckMaps(JSObject* object, Register object_reg,
+                     JSObject* holder, Register holder_reg,
+                     Register scratch, Label* miss);
+
+  // Generate code for checking access rights - used for security checks
+  // on access to global objects across environments. The holder register
+  // is left untouched, whereas both scratch registers are clobbered.
+  void CheckAccessGlobalProxy(Register holder_reg,
+                              Register scratch,
+                              Label* miss);
+
+
+  // ---------------------------------------------------------------------------
+  // Support functions.
+
+  // Generates code for reporting that an illegal operation has
+  // occurred.
+  void IllegalOperation(int num_arguments);
+
+
+  // ---------------------------------------------------------------------------
+  // Runtime calls
+
+  // Call a code stub.
+  void CallStub(CodeStub* stub);
+  void CallJSExitStub(CodeStub* stub);
+
+  // Return from a code stub after popping its arguments.
+  void StubReturn(int argc);
+
+  // Call a runtime routine.
+  // Eventually this should be used for all C calls.
+  void CallRuntime(Runtime::Function* f, int num_arguments);
+
+  // Convenience function: Same as above, but takes the fid instead.
+  void CallRuntime(Runtime::FunctionId fid, int num_arguments);
+
+  // Tail call of a runtime routine (jump).
+  // Like JumpToBuiltin, but also takes care of passing the number
+  // of parameters.
+  void TailCallRuntime(const ExternalReference& ext, int num_arguments);
+
+  // Jump to the builtin routine.
+  void JumpToBuiltin(const ExternalReference& builtin);
+
+  // Invoke specified builtin JavaScript function. Adds an entry to
+  // the unresolved list if the name does not resolve.
+  void InvokeBuiltin(Builtins::JavaScript id, InvokeJSFlags flags);
+
+  // Store the code object for the given builtin in the target register and
+  // setup the function in r1.
+  void GetBuiltinEntry(Register target, Builtins::JavaScript id);
+
+  struct Unresolved {
+    int pc;
+    uint32_t flags;  // see Bootstrapper::FixupFlags decoders/encoders.
+    const char* name;
+  };
+  List<Unresolved>* unresolved() { return &unresolved_; }
+
+  Handle<Object> CodeObject() { return code_object_; }
+
+
+  // ---------------------------------------------------------------------------
+  // StatsCounter support
+
+  void SetCounter(StatsCounter* counter, int value,
+                  Register scratch1, Register scratch2);
+  void IncrementCounter(StatsCounter* counter, int value,
+                        Register scratch1, Register scratch2);
+  void DecrementCounter(StatsCounter* counter, int value,
+                        Register scratch1, Register scratch2);
+
+
+  // ---------------------------------------------------------------------------
+  // Debugging
+
+  // Calls Abort(msg) if the condition cc is not satisfied.
+  // Use --debug_code to enable.
+  void Assert(Condition cc, const char* msg);
+
+  // Like Assert(), but always enabled.
+  void Check(Condition cc, const char* msg);
+
+  // Print a message to stdout and abort execution.
+  void Abort(const char* msg);
+
+  // Verify restrictions about code generated in stubs.
+  void set_generating_stub(bool value) { generating_stub_ = value; }
+  bool generating_stub() { return generating_stub_; }
+  void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
+  bool allow_stub_calls() { return allow_stub_calls_; }
+
+ private:
+  List<Unresolved> unresolved_;
+  bool generating_stub_;
+  bool allow_stub_calls_;
+  Handle<Object> code_object_;  // This handle will be patched with the code
+                                // object on installation.
+
+  // Helper functions for generating invokes.
+  void InvokePrologue(const ParameterCount& expected,
+                      const ParameterCount& actual,
+                      Handle<Code> code_constant,
+                      Register code_reg,
+                      Label* done,
+                      InvokeFlag flag);
+
+  // Get the code for the given builtin. Returns if able to resolve
+  // the function in the 'resolved' flag.
+  Handle<Code> ResolveBuiltin(Builtins::JavaScript id, bool* resolved);
+
+  // Activation support.
+  void EnterFrame(StackFrame::Type type);
+  void LeaveFrame(StackFrame::Type type);
+};
+
+
+// -----------------------------------------------------------------------------
+// Static helper functions.
+
+// Generate a MemOperand for loading a field from an object.
+static inline MemOperand FieldMemOperand(Register object, int offset) {
+  return MemOperand(object, offset - kHeapObjectTag);
+}
+
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_MACRO_ASSEMBLER_ARM_H_
diff --git a/deps/v8/src/macro-assembler-ia32.cc b/deps/v8/src/macro-assembler-ia32.cc
new file mode 100644
index 0000000..4fad3be
--- /dev/null
+++ b/deps/v8/src/macro-assembler-ia32.cc
@@ -0,0 +1,1046 @@
+// 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.
+
+#include "v8.h"
+
+#include "bootstrapper.h"
+#include "codegen-inl.h"
+#include "debug.h"
+#include "runtime.h"
+#include "serialize.h"
+
+namespace v8 { namespace internal {
+
+// -------------------------------------------------------------------------
+// MacroAssembler implementation.
+
+MacroAssembler::MacroAssembler(void* buffer, int size)
+    : Assembler(buffer, size),
+      unresolved_(0),
+      generating_stub_(false),
+      allow_stub_calls_(true),
+      code_object_(Heap::undefined_value()) {
+}
+
+
+static void RecordWriteHelper(MacroAssembler* masm,
+                              Register object,
+                              Register addr,
+                              Register scratch) {
+  Label fast;
+
+  // Compute the page address from the heap object pointer, leave it
+  // in 'object'.
+  masm->and_(object, ~Page::kPageAlignmentMask);
+
+  // Compute the bit addr in the remembered set, leave it in "addr".
+  masm->sub(addr, Operand(object));
+  masm->shr(addr, kObjectAlignmentBits);
+
+  // If the bit offset lies beyond the normal remembered set range, it is in
+  // the extra remembered set area of a large object.
+  masm->cmp(addr, Page::kPageSize / kPointerSize);
+  masm->j(less, &fast);
+
+  // Adjust 'addr' to be relative to the start of the extra remembered set
+  // and the page address in 'object' to be the address of the extra
+  // remembered set.
+  masm->sub(Operand(addr), Immediate(Page::kPageSize / kPointerSize));
+  // Load the array length into 'scratch' and multiply by four to get the
+  // size in bytes of the elements.
+  masm->mov(scratch, Operand(object, Page::kObjectStartOffset
+                                     + FixedArray::kLengthOffset));
+  masm->shl(scratch, kObjectAlignmentBits);
+  // Add the page header, array header, and array body size to the page
+  // address.
+  masm->add(Operand(object), Immediate(Page::kObjectStartOffset
+                                       + Array::kHeaderSize));
+  masm->add(object, Operand(scratch));
+
+
+  // NOTE: For now, we use the bit-test-and-set (bts) x86 instruction
+  // to limit code size. We should probably evaluate this decision by
+  // measuring the performance of an equivalent implementation using
+  // "simpler" instructions
+  masm->bind(&fast);
+  masm->bts(Operand(object, 0), addr);
+}
+
+
+class RecordWriteStub : public CodeStub {
+ public:
+  RecordWriteStub(Register object, Register addr, Register scratch)
+      : object_(object), addr_(addr), scratch_(scratch) { }
+
+  void Generate(MacroAssembler* masm);
+
+ private:
+  Register object_;
+  Register addr_;
+  Register scratch_;
+
+#ifdef DEBUG
+  void Print() {
+    PrintF("RecordWriteStub (object reg %d), (addr reg %d), (scratch reg %d)\n",
+           object_.code(), addr_.code(), scratch_.code());
+  }
+#endif
+
+  // Minor key encoding in 12 bits of three registers (object, address and
+  // scratch) OOOOAAAASSSS.
+  class ScratchBits: public BitField<uint32_t, 0, 4> {};
+  class AddressBits: public BitField<uint32_t, 4, 4> {};
+  class ObjectBits: public BitField<uint32_t, 8, 4> {};
+
+  Major MajorKey() { return RecordWrite; }
+
+  int MinorKey() {
+    // Encode the registers.
+    return ObjectBits::encode(object_.code()) |
+           AddressBits::encode(addr_.code()) |
+           ScratchBits::encode(scratch_.code());
+  }
+};
+
+
+void RecordWriteStub::Generate(MacroAssembler* masm) {
+  RecordWriteHelper(masm, object_, addr_, scratch_);
+  masm->ret(0);
+}
+
+
+// Set the remembered set bit for [object+offset].
+// object is the object being stored into, value is the object being stored.
+// If offset is zero, then the scratch register contains the array index into
+// the elements array represented as a Smi.
+// All registers are clobbered by the operation.
+void MacroAssembler::RecordWrite(Register object, int offset,
+                                 Register value, Register scratch) {
+  // First, check if a remembered set write is even needed. The tests below
+  // catch stores of Smis and stores into young gen (which does not have space
+  // for the remembered set bits.
+  Label done;
+
+  // This optimization cannot survive serialization and deserialization,
+  // so we disable as long as serialization can take place.
+  int32_t new_space_start =
+      reinterpret_cast<int32_t>(ExternalReference::new_space_start().address());
+  if (Serializer::enabled() || new_space_start < 0) {
+    // Cannot do smart bit-twiddling. Need to do two consecutive checks.
+    // Check for Smi first.
+    test(value, Immediate(kSmiTagMask));
+    j(zero, &done);
+    // Test that the object address is not in the new space.  We cannot
+    // set remembered set bits in the new space.
+    mov(value, Operand(object));
+    and_(value, Heap::NewSpaceMask());
+    cmp(Operand(value), Immediate(ExternalReference::new_space_start()));
+    j(equal, &done);
+  } else {
+    // move the value SmiTag into the sign bit
+    shl(value, 31);
+    // combine the object with value SmiTag
+    or_(value, Operand(object));
+    // remove the uninteresing bits inside the page
+    and_(value, Heap::NewSpaceMask() | (1 << 31));
+    // xor has two effects:
+    // - if the value was a smi, then the result will be negative
+    // - if the object is pointing into new space area the page bits will
+    //   all be zero
+    xor_(value, new_space_start | (1 << 31));
+    // Check for both conditions in one branch
+    j(less_equal, &done);
+  }
+
+  if ((offset > 0) && (offset < Page::kMaxHeapObjectSize)) {
+    // Compute the bit offset in the remembered set, leave it in 'value'.
+    mov(value, Operand(object));
+    and_(value, Page::kPageAlignmentMask);
+    add(Operand(value), Immediate(offset));
+    shr(value, kObjectAlignmentBits);
+
+    // Compute the page address from the heap object pointer, leave it in
+    // 'object'.
+    and_(object, ~Page::kPageAlignmentMask);
+
+    // NOTE: For now, we use the bit-test-and-set (bts) x86 instruction
+    // to limit code size. We should probably evaluate this decision by
+    // measuring the performance of an equivalent implementation using
+    // "simpler" instructions
+    bts(Operand(object, 0), value);
+  } else {
+    Register dst = scratch;
+    if (offset != 0) {
+      lea(dst, Operand(object, offset));
+    } else {
+      // array access: calculate the destination address in the same manner as
+      // KeyedStoreIC::GenerateGeneric
+      lea(dst,
+          Operand(object, dst, times_2, Array::kHeaderSize - kHeapObjectTag));
+    }
+    // If we are already generating a shared stub, not inlining the
+    // record write code isn't going to save us any memory.
+    if (generating_stub()) {
+      RecordWriteHelper(this, object, dst, value);
+    } else {
+      RecordWriteStub stub(object, dst, value);
+      CallStub(&stub);
+    }
+  }
+
+  bind(&done);
+}
+
+
+void MacroAssembler::SaveRegistersToMemory(RegList regs) {
+  ASSERT((regs & ~kJSCallerSaved) == 0);
+  // Copy the content of registers to memory location.
+  for (int i = 0; i < kNumJSCallerSaved; i++) {
+    int r = JSCallerSavedCode(i);
+    if ((regs & (1 << r)) != 0) {
+      Register reg = { r };
+      ExternalReference reg_addr =
+          ExternalReference(Debug_Address::Register(i));
+      mov(Operand::StaticVariable(reg_addr), reg);
+    }
+  }
+}
+
+
+void MacroAssembler::RestoreRegistersFromMemory(RegList regs) {
+  ASSERT((regs & ~kJSCallerSaved) == 0);
+  // Copy the content of memory location to registers.
+  for (int i = kNumJSCallerSaved; --i >= 0;) {
+    int r = JSCallerSavedCode(i);
+    if ((regs & (1 << r)) != 0) {
+      Register reg = { r };
+      ExternalReference reg_addr =
+          ExternalReference(Debug_Address::Register(i));
+      mov(reg, Operand::StaticVariable(reg_addr));
+    }
+  }
+}
+
+
+void MacroAssembler::PushRegistersFromMemory(RegList regs) {
+  ASSERT((regs & ~kJSCallerSaved) == 0);
+  // Push the content of the memory location to the stack.
+  for (int i = 0; i < kNumJSCallerSaved; i++) {
+    int r = JSCallerSavedCode(i);
+    if ((regs & (1 << r)) != 0) {
+      ExternalReference reg_addr =
+          ExternalReference(Debug_Address::Register(i));
+      push(Operand::StaticVariable(reg_addr));
+    }
+  }
+}
+
+
+void MacroAssembler::PopRegistersToMemory(RegList regs) {
+  ASSERT((regs & ~kJSCallerSaved) == 0);
+  // Pop the content from the stack to the memory location.
+  for (int i = kNumJSCallerSaved; --i >= 0;) {
+    int r = JSCallerSavedCode(i);
+    if ((regs & (1 << r)) != 0) {
+      ExternalReference reg_addr =
+          ExternalReference(Debug_Address::Register(i));
+      pop(Operand::StaticVariable(reg_addr));
+    }
+  }
+}
+
+
+void MacroAssembler::CopyRegistersFromStackToMemory(Register base,
+                                                    Register scratch,
+                                                    RegList regs) {
+  ASSERT((regs & ~kJSCallerSaved) == 0);
+  // Copy the content of the stack to the memory location and adjust base.
+  for (int i = kNumJSCallerSaved; --i >= 0;) {
+    int r = JSCallerSavedCode(i);
+    if ((regs & (1 << r)) != 0) {
+      mov(scratch, Operand(base, 0));
+      ExternalReference reg_addr =
+          ExternalReference(Debug_Address::Register(i));
+      mov(Operand::StaticVariable(reg_addr), scratch);
+      lea(base, Operand(base, kPointerSize));
+    }
+  }
+}
+
+
+void MacroAssembler::Set(Register dst, const Immediate& x) {
+  if (x.is_zero()) {
+    xor_(dst, Operand(dst));  // shorter than mov
+  } else {
+    mov(dst, x);
+  }
+}
+
+
+void MacroAssembler::Set(const Operand& dst, const Immediate& x) {
+  mov(dst, x);
+}
+
+
+void MacroAssembler::CmpObjectType(Register heap_object,
+                                   InstanceType type,
+                                   Register map) {
+  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
+  CmpInstanceType(map, type);
+}
+
+
+void MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
+  cmpb(FieldOperand(map, Map::kInstanceTypeOffset),
+       static_cast<int8_t>(type));
+}
+
+
+void MacroAssembler::FCmp() {
+  fcompp();
+  push(eax);
+  fnstsw_ax();
+  sahf();
+  pop(eax);
+}
+
+
+void MacroAssembler::EnterFrame(StackFrame::Type type) {
+  push(ebp);
+  mov(ebp, Operand(esp));
+  push(esi);
+  push(Immediate(Smi::FromInt(type)));
+  push(Immediate(CodeObject()));
+  if (FLAG_debug_code) {
+    cmp(Operand(esp, 0), Immediate(Factory::undefined_value()));
+    Check(not_equal, "code object not properly patched");
+  }
+}
+
+
+void MacroAssembler::LeaveFrame(StackFrame::Type type) {
+  if (FLAG_debug_code) {
+    cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset),
+        Immediate(Smi::FromInt(type)));
+    Check(equal, "stack frame types must match");
+  }
+  leave();
+}
+
+
+void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
+  ASSERT(type == StackFrame::EXIT || type == StackFrame::EXIT_DEBUG);
+
+  // Setup the frame structure on the stack.
+  ASSERT(ExitFrameConstants::kPPDisplacement == +2 * kPointerSize);
+  ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize);
+  ASSERT(ExitFrameConstants::kCallerFPOffset ==  0 * kPointerSize);
+  push(ebp);
+  mov(ebp, Operand(esp));
+
+  // Reserve room for entry stack pointer and push the debug marker.
+  ASSERT(ExitFrameConstants::kSPOffset  == -1 * kPointerSize);
+  push(Immediate(0));  // saved entry sp, patched before call
+  push(Immediate(type == StackFrame::EXIT_DEBUG ? 1 : 0));
+
+  // Save the frame pointer and the context in top.
+  ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
+  ExternalReference context_address(Top::k_context_address);
+  mov(Operand::StaticVariable(c_entry_fp_address), ebp);
+  mov(Operand::StaticVariable(context_address), esi);
+
+  // Setup argc and argv in callee-saved registers.
+  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
+  mov(edi, Operand(eax));
+  lea(esi, Operand(ebp, eax, times_4, offset));
+
+  // Save the state of all registers to the stack from the memory
+  // location. This is needed to allow nested break points.
+  if (type == StackFrame::EXIT_DEBUG) {
+    // TODO(1243899): This should be symmetric to
+    // CopyRegistersFromStackToMemory() but it isn't! esp is assumed
+    // correct here, but computed for the other call. Very error
+    // prone! FIX THIS.  Actually there are deeper problems with
+    // register saving than this asymmetry (see the bug report
+    // associated with this issue).
+    PushRegistersFromMemory(kJSCallerSaved);
+  }
+
+  // Reserve space for two arguments: argc and argv.
+  sub(Operand(esp), Immediate(2 * kPointerSize));
+
+  // Get the required frame alignment for the OS.
+  static const int kFrameAlignment = OS::ActivationFrameAlignment();
+  if (kFrameAlignment > 0) {
+    ASSERT(IsPowerOf2(kFrameAlignment));
+    and_(esp, -kFrameAlignment);
+  }
+
+  // Patch the saved entry sp.
+  mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp);
+}
+
+
+void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
+  // Restore the memory copy of the registers by digging them out from
+  // the stack. This is needed to allow nested break points.
+  if (type == StackFrame::EXIT_DEBUG) {
+    // It's okay to clobber register ebx below because we don't need
+    // the function pointer after this.
+    const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize;
+    int kOffset = ExitFrameConstants::kDebugMarkOffset - kCallerSavedSize;
+    lea(ebx, Operand(ebp, kOffset));
+    CopyRegistersFromStackToMemory(ebx, ecx, kJSCallerSaved);
+  }
+
+  // Get the return address from the stack and restore the frame pointer.
+  mov(ecx, Operand(ebp, 1 * kPointerSize));
+  mov(ebp, Operand(ebp, 0 * kPointerSize));
+
+  // Pop the arguments and the receiver from the caller stack.
+  lea(esp, Operand(esi, 1 * kPointerSize));
+
+  // Restore current context from top and clear it in debug mode.
+  ExternalReference context_address(Top::k_context_address);
+  mov(esi, Operand::StaticVariable(context_address));
+  if (kDebug) {
+    mov(Operand::StaticVariable(context_address), Immediate(0));
+  }
+
+  // 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::PushTryHandler(CodeLocation try_location,
+                                    HandlerType type) {
+  ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize);  // adjust this code
+  // The pc (return address) is already on TOS.
+  if (try_location == IN_JAVASCRIPT) {
+    if (type == TRY_CATCH_HANDLER) {
+      push(Immediate(StackHandler::TRY_CATCH));
+    } else {
+      push(Immediate(StackHandler::TRY_FINALLY));
+    }
+    push(Immediate(Smi::FromInt(StackHandler::kCodeNotPresent)));
+    push(ebp);
+    push(edi);
+  } else {
+    ASSERT(try_location == IN_JS_ENTRY);
+    // The parameter pointer is meaningless here and ebp does not
+    // point to a JS frame. So we save NULL for both pp and ebp. We
+    // expect the code throwing an exception to check ebp before
+    // dereferencing it to restore the context.
+    push(Immediate(StackHandler::ENTRY));
+    push(Immediate(Smi::FromInt(StackHandler::kCodeNotPresent)));
+    push(Immediate(0));  // NULL frame pointer
+    push(Immediate(0));  // NULL parameter pointer
+  }
+  // Cached TOS.
+  mov(eax, Operand::StaticVariable(ExternalReference(Top::k_handler_address)));
+  // Link this handler.
+  mov(Operand::StaticVariable(ExternalReference(Top::k_handler_address)), esp);
+}
+
+
+Register MacroAssembler::CheckMaps(JSObject* object, Register object_reg,
+                                   JSObject* holder, Register holder_reg,
+                                   Register scratch,
+                                   Label* miss) {
+  // Make sure there's no overlap between scratch and the other
+  // registers.
+  ASSERT(!scratch.is(object_reg) && !scratch.is(holder_reg));
+
+  // Keep track of the current object in register reg.
+  Register reg = object_reg;
+  int depth = 1;
+
+  // Check the maps in the prototype chain.
+  // Traverse the prototype chain from the object and do map checks.
+  while (object != holder) {
+    depth++;
+
+    // Only global objects and objects that do not require access
+    // checks are allowed in stubs.
+    ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
+
+    JSObject* prototype = JSObject::cast(object->GetPrototype());
+    if (Heap::InNewSpace(prototype)) {
+      // Get the map of the current object.
+      mov(scratch, FieldOperand(reg, HeapObject::kMapOffset));
+      cmp(Operand(scratch), Immediate(Handle<Map>(object->map())));
+      // Branch on the result of the map check.
+      j(not_equal, miss, not_taken);
+      // Check access rights to the global object.  This has to happen
+      // after the map check so that we know that the object is
+      // actually a global object.
+      if (object->IsJSGlobalProxy()) {
+        CheckAccessGlobalProxy(reg, scratch, miss);
+
+        // Restore scratch register to be the map of the object.
+        // We load the prototype from the map in the scratch register.
+        mov(scratch, FieldOperand(reg, HeapObject::kMapOffset));
+      }
+      // The prototype is in new space; we cannot store a reference
+      // to it in the code. Load it from the map.
+      reg = holder_reg;  // from now the object is in holder_reg
+      mov(reg, FieldOperand(scratch, Map::kPrototypeOffset));
+
+    } else {
+      // Check the map of the current object.
+      cmp(FieldOperand(reg, HeapObject::kMapOffset),
+          Immediate(Handle<Map>(object->map())));
+      // Branch on the result of the map check.
+      j(not_equal, miss, not_taken);
+      // Check access rights to the global object.  This has to happen
+      // after the map check so that we know that the object is
+      // actually a global object.
+      if (object->IsJSGlobalProxy()) {
+        CheckAccessGlobalProxy(reg, scratch, miss);
+      }
+      // The prototype is in old space; load it directly.
+      reg = holder_reg;  // from now the object is in holder_reg
+      mov(reg, Handle<JSObject>(prototype));
+    }
+
+    // Go to the next object in the prototype chain.
+    object = prototype;
+  }
+
+  // Check the holder map.
+  cmp(FieldOperand(reg, HeapObject::kMapOffset),
+      Immediate(Handle<Map>(holder->map())));
+  j(not_equal, miss, not_taken);
+
+  // Log the check depth.
+  LOG(IntEvent("check-maps-depth", depth));
+
+  // Perform security check for access to the global object and return
+  // the holder register.
+  ASSERT(object == holder);
+  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
+  if (object->IsJSGlobalProxy()) {
+    CheckAccessGlobalProxy(reg, scratch, miss);
+  }
+  return reg;
+}
+
+
+void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
+                                          Register scratch,
+                                          Label* miss) {
+  Label same_contexts;
+
+  ASSERT(!holder_reg.is(scratch));
+
+  // Load current lexical context from the stack frame.
+  mov(scratch, Operand(ebp, StandardFrameConstants::kContextOffset));
+
+  // When generating debug code, make sure the lexical context is set.
+  if (FLAG_debug_code) {
+    cmp(Operand(scratch), Immediate(0));
+    Check(not_equal, "we should not have an empty lexical context");
+  }
+  // Load the global context of the current context.
+  int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
+  mov(scratch, FieldOperand(scratch, offset));
+  mov(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset));
+
+  // Check the context is a global context.
+  if (FLAG_debug_code) {
+    push(scratch);
+    // Read the first word and compare to global_context_map.
+    mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
+    cmp(scratch, Factory::global_context_map());
+    Check(equal, "JSGlobalObject::global_context should be a global context.");
+    pop(scratch);
+  }
+
+  // Check if both contexts are the same.
+  cmp(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
+  j(equal, &same_contexts, taken);
+
+  // Compare security tokens, save holder_reg on the stack so we can use it
+  // as a temporary register.
+  //
+  // TODO(119): avoid push(holder_reg)/pop(holder_reg)
+  push(holder_reg);
+  // Check that the security token in the calling global object is
+  // compatible with the security token in the receiving global
+  // object.
+  mov(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
+
+  // Check the context is a global context.
+  if (FLAG_debug_code) {
+    cmp(holder_reg, Factory::null_value());
+    Check(not_equal, "JSGlobalProxy::context() should not be null.");
+
+    push(holder_reg);
+    // Read the first word and compare to global_context_map(),
+    mov(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset));
+    cmp(holder_reg, Factory::global_context_map());
+    Check(equal, "JSGlobalObject::global_context should be a global context.");
+    pop(holder_reg);
+  }
+
+  int token_offset = Context::kHeaderSize +
+                     Context::SECURITY_TOKEN_INDEX * kPointerSize;
+  mov(scratch, FieldOperand(scratch, token_offset));
+  cmp(scratch, FieldOperand(holder_reg, token_offset));
+  pop(holder_reg);
+  j(not_equal, miss, not_taken);
+
+  bind(&same_contexts);
+}
+
+
+void MacroAssembler::NegativeZeroTest(CodeGenerator* cgen,
+                                      Register result,
+                                      Register op,
+                                      JumpTarget* then_target) {
+  JumpTarget ok(cgen);
+  test(result, Operand(result));
+  ok.Branch(not_zero, taken);
+  test(op, Operand(op));
+  then_target->Branch(sign, not_taken);
+  ok.Bind();
+}
+
+
+void MacroAssembler::NegativeZeroTest(Register result,
+                                      Register op,
+                                      Label* then_label) {
+  Label ok;
+  test(result, Operand(result));
+  j(not_zero, &ok, taken);
+  test(op, Operand(op));
+  j(sign, then_label, not_taken);
+  bind(&ok);
+}
+
+
+void MacroAssembler::NegativeZeroTest(Register result,
+                                      Register op1,
+                                      Register op2,
+                                      Register scratch,
+                                      Label* then_label) {
+  Label ok;
+  test(result, Operand(result));
+  j(not_zero, &ok, taken);
+  mov(scratch, Operand(op1));
+  or_(scratch, Operand(op2));
+  j(sign, then_label, not_taken);
+  bind(&ok);
+}
+
+
+void MacroAssembler::TryGetFunctionPrototype(Register function,
+                                             Register result,
+                                             Register scratch,
+                                             Label* miss) {
+  // Check that the receiver isn't a smi.
+  test(function, Immediate(kSmiTagMask));
+  j(zero, miss, not_taken);
+
+  // Check that the function really is a function.
+  CmpObjectType(function, JS_FUNCTION_TYPE, result);
+  j(not_equal, miss, not_taken);
+
+  // Make sure that the function has an instance prototype.
+  Label non_instance;
+  movzx_b(scratch, FieldOperand(result, Map::kBitFieldOffset));
+  test(scratch, Immediate(1 << Map::kHasNonInstancePrototype));
+  j(not_zero, &non_instance, not_taken);
+
+  // Get the prototype or initial map from the function.
+  mov(result,
+      FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
+
+  // If the prototype or initial map is the hole, don't return it and
+  // simply miss the cache instead. This will allow us to allocate a
+  // prototype object on-demand in the runtime system.
+  cmp(Operand(result), Immediate(Factory::the_hole_value()));
+  j(equal, miss, not_taken);
+
+  // If the function does not have an initial map, we're done.
+  Label done;
+  CmpObjectType(result, MAP_TYPE, scratch);
+  j(not_equal, &done);
+
+  // Get the prototype from the initial map.
+  mov(result, FieldOperand(result, Map::kPrototypeOffset));
+  jmp(&done);
+
+  // Non-instance prototype: Fetch prototype from constructor field
+  // in initial map.
+  bind(&non_instance);
+  mov(result, FieldOperand(result, Map::kConstructorOffset));
+
+  // All done.
+  bind(&done);
+}
+
+
+void MacroAssembler::CallStub(CodeStub* stub) {
+  ASSERT(allow_stub_calls());  // calls are not allowed in some stubs
+  call(stub->GetCode(), RelocInfo::CODE_TARGET);
+}
+
+
+void MacroAssembler::StubReturn(int argc) {
+  ASSERT(argc >= 1 && generating_stub());
+  ret((argc - 1) * kPointerSize);
+}
+
+
+void MacroAssembler::IllegalOperation(int num_arguments) {
+  if (num_arguments > 0) {
+    add(Operand(esp), Immediate(num_arguments * kPointerSize));
+  }
+  mov(eax, Immediate(Factory::undefined_value()));
+}
+
+
+void MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) {
+  CallRuntime(Runtime::FunctionForId(id), num_arguments);
+}
+
+
+void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
+  // If the expected number of arguments of the runtime function is
+  // constant, we check that the actual number of arguments match the
+  // expectation.
+  if (f->nargs >= 0 && f->nargs != num_arguments) {
+    IllegalOperation(num_arguments);
+    return;
+  }
+
+  Runtime::FunctionId function_id =
+      static_cast<Runtime::FunctionId>(f->stub_id);
+  RuntimeStub stub(function_id, num_arguments);
+  CallStub(&stub);
+}
+
+
+void MacroAssembler::TailCallRuntime(const ExternalReference& ext,
+                                     int num_arguments) {
+  // 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));
+  JumpToBuiltin(ext);
+}
+
+
+void MacroAssembler::JumpToBuiltin(const ExternalReference& ext) {
+  // Set the entry point and jump to the C entry runtime stub.
+  mov(ebx, Immediate(ext));
+  CEntryStub ces;
+  jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
+}
+
+
+void MacroAssembler::InvokePrologue(const ParameterCount& expected,
+                                    const ParameterCount& actual,
+                                    Handle<Code> code_constant,
+                                    const Operand& code_operand,
+                                    Label* done,
+                                    InvokeFlag flag) {
+  bool definitely_matches = false;
+  Label invoke;
+  if (expected.is_immediate()) {
+    ASSERT(actual.is_immediate());
+    if (expected.immediate() == actual.immediate()) {
+      definitely_matches = true;
+    } else {
+      mov(eax, actual.immediate());
+      const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
+      if (expected.immediate() == sentinel) {
+        // Don't worry about adapting arguments for builtins that
+        // don't want that done. Skip adaption code by making it look
+        // like we have a match between expected and actual number of
+        // arguments.
+        definitely_matches = true;
+      } else {
+        mov(ebx, expected.immediate());
+      }
+    }
+  } else {
+    if (actual.is_immediate()) {
+      // Expected is in register, actual is immediate. This is the
+      // case when we invoke function values without going through the
+      // IC mechanism.
+      cmp(expected.reg(), actual.immediate());
+      j(equal, &invoke);
+      ASSERT(expected.reg().is(ebx));
+      mov(eax, actual.immediate());
+    } else if (!expected.reg().is(actual.reg())) {
+      // Both expected and actual are in (different) registers. This
+      // is the case when we invoke functions using call and apply.
+      cmp(expected.reg(), Operand(actual.reg()));
+      j(equal, &invoke);
+      ASSERT(actual.reg().is(eax));
+      ASSERT(expected.reg().is(ebx));
+    }
+  }
+
+  if (!definitely_matches) {
+    Handle<Code> adaptor =
+        Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
+    if (!code_constant.is_null()) {
+      mov(edx, Immediate(code_constant));
+      add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag));
+    } else if (!code_operand.is_reg(edx)) {
+      mov(edx, code_operand);
+    }
+
+    if (flag == CALL_FUNCTION) {
+      call(adaptor, RelocInfo::CODE_TARGET);
+      jmp(done);
+    } else {
+      jmp(adaptor, RelocInfo::CODE_TARGET);
+    }
+    bind(&invoke);
+  }
+}
+
+
+void MacroAssembler::InvokeCode(const Operand& code,
+                                const ParameterCount& expected,
+                                const ParameterCount& actual,
+                                InvokeFlag flag) {
+  Label done;
+  InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag);
+  if (flag == CALL_FUNCTION) {
+    call(code);
+  } else {
+    ASSERT(flag == JUMP_FUNCTION);
+    jmp(code);
+  }
+  bind(&done);
+}
+
+
+void MacroAssembler::InvokeCode(Handle<Code> code,
+                                const ParameterCount& expected,
+                                const ParameterCount& actual,
+                                RelocInfo::Mode rmode,
+                                InvokeFlag flag) {
+  Label done;
+  Operand dummy(eax);
+  InvokePrologue(expected, actual, code, dummy, &done, flag);
+  if (flag == CALL_FUNCTION) {
+    call(code, rmode);
+  } else {
+    ASSERT(flag == JUMP_FUNCTION);
+    jmp(code, rmode);
+  }
+  bind(&done);
+}
+
+
+void MacroAssembler::InvokeFunction(Register fun,
+                                    const ParameterCount& actual,
+                                    InvokeFlag flag) {
+  ASSERT(fun.is(edi));
+  mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
+  mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
+  mov(ebx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
+  mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset));
+  lea(edx, FieldOperand(edx, Code::kHeaderSize));
+
+  ParameterCount expected(ebx);
+  InvokeCode(Operand(edx), expected, actual, flag);
+}
+
+
+void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) {
+  bool resolved;
+  Handle<Code> code = ResolveBuiltin(id, &resolved);
+
+  // Calls are not allowed in some stubs.
+  ASSERT(flag == JUMP_FUNCTION || allow_stub_calls());
+
+  // Rely on the assertion to check that the number of provided
+  // arguments match the expected number of arguments. Fake a
+  // parameter count to avoid emitting code to do the check.
+  ParameterCount expected(0);
+  InvokeCode(Handle<Code>(code), expected, expected,
+             RelocInfo::CODE_TARGET, flag);
+
+  const char* name = Builtins::GetName(id);
+  int argc = Builtins::GetArgumentsCount(id);
+
+  if (!resolved) {
+    uint32_t flags =
+        Bootstrapper::FixupFlagsArgumentsCount::encode(argc) |
+        Bootstrapper::FixupFlagsIsPCRelative::encode(true) |
+        Bootstrapper::FixupFlagsUseCodeObject::encode(false);
+    Unresolved entry = { pc_offset() - sizeof(int32_t), flags, name };
+    unresolved_.Add(entry);
+  }
+}
+
+
+void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
+  bool resolved;
+  Handle<Code> code = ResolveBuiltin(id, &resolved);
+
+  const char* name = Builtins::GetName(id);
+  int argc = Builtins::GetArgumentsCount(id);
+
+  mov(Operand(target), Immediate(code));
+  if (!resolved) {
+    uint32_t flags =
+        Bootstrapper::FixupFlagsArgumentsCount::encode(argc) |
+        Bootstrapper::FixupFlagsIsPCRelative::encode(false) |
+        Bootstrapper::FixupFlagsUseCodeObject::encode(true);
+    Unresolved entry = { pc_offset() - sizeof(int32_t), flags, name };
+    unresolved_.Add(entry);
+  }
+  add(Operand(target), Immediate(Code::kHeaderSize - kHeapObjectTag));
+}
+
+
+Handle<Code> MacroAssembler::ResolveBuiltin(Builtins::JavaScript id,
+                                            bool* resolved) {
+  // Move the builtin function into the temporary function slot by
+  // reading it from the builtins object. NOTE: We should be able to
+  // reduce this to two instructions by putting the function table in
+  // the global object instead of the "builtins" object and by using a
+  // real register for the function.
+  mov(edx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
+  mov(edx, FieldOperand(edx, GlobalObject::kBuiltinsOffset));
+  int builtins_offset =
+      JSBuiltinsObject::kJSBuiltinsOffset + (id * kPointerSize);
+  mov(edi, FieldOperand(edx, builtins_offset));
+
+
+  return Builtins::GetCode(id, resolved);
+}
+
+
+void MacroAssembler::Ret() {
+  ret(0);
+}
+
+
+void MacroAssembler::SetCounter(StatsCounter* counter, int value) {
+  if (FLAG_native_code_counters && counter->Enabled()) {
+    mov(Operand::StaticVariable(ExternalReference(counter)), Immediate(value));
+  }
+}
+
+
+void MacroAssembler::IncrementCounter(StatsCounter* counter, int value) {
+  ASSERT(value > 0);
+  if (FLAG_native_code_counters && counter->Enabled()) {
+    Operand operand = Operand::StaticVariable(ExternalReference(counter));
+    if (value == 1) {
+      inc(operand);
+    } else {
+      add(operand, Immediate(value));
+    }
+  }
+}
+
+
+void MacroAssembler::DecrementCounter(StatsCounter* counter, int value) {
+  ASSERT(value > 0);
+  if (FLAG_native_code_counters && counter->Enabled()) {
+    Operand operand = Operand::StaticVariable(ExternalReference(counter));
+    if (value == 1) {
+      dec(operand);
+    } else {
+      sub(operand, Immediate(value));
+    }
+  }
+}
+
+
+void MacroAssembler::Assert(Condition cc, const char* msg) {
+  if (FLAG_debug_code) Check(cc, msg);
+}
+
+
+void MacroAssembler::Check(Condition cc, const char* msg) {
+  Label L;
+  j(cc, &L, taken);
+  Abort(msg);
+  // will not return here
+  bind(&L);
+}
+
+
+void MacroAssembler::Abort(const char* msg) {
+  // We want to pass the msg string like a smi to avoid GC
+  // problems, however msg is not guaranteed to be aligned
+  // properly. Instead, we pass an aligned pointer that is
+  // a proper v8 smi, but also pass the alignment difference
+  // from the real pointer as a smi.
+  intptr_t p1 = reinterpret_cast<intptr_t>(msg);
+  intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag;
+  ASSERT(reinterpret_cast<Object*>(p0)->IsSmi());
+#ifdef DEBUG
+  if (msg != NULL) {
+    RecordComment("Abort message: ");
+    RecordComment(msg);
+  }
+#endif
+  push(eax);
+  push(Immediate(p0));
+  push(Immediate(reinterpret_cast<intptr_t>(Smi::FromInt(p1 - p0))));
+  CallRuntime(Runtime::kAbort, 2);
+  // will not return here
+}
+
+
+CodePatcher::CodePatcher(byte* address, int size)
+  : address_(address), size_(size), masm_(address, size + Assembler::kGap) {
+  // Create a new macro assembler pointing to the address of the code to patch.
+  // The size is adjusted with kGap on order for the assembler to generate size
+  // bytes of instructions without failing with buffer size constraints.
+  ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
+}
+
+
+CodePatcher::~CodePatcher() {
+  // Indicate that code has changed.
+  CPU::FlushICache(address_, size_);
+
+  // Check that the code was patched as expected.
+  ASSERT(masm_.pc_ == address_ + size_);
+  ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/macro-assembler-ia32.h b/deps/v8/src/macro-assembler-ia32.h
new file mode 100644
index 0000000..40aa84a
--- /dev/null
+++ b/deps/v8/src/macro-assembler-ia32.h
@@ -0,0 +1,348 @@
+// 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_MACRO_ASSEMBLER_IA32_H_
+#define V8_MACRO_ASSEMBLER_IA32_H_
+
+#include "assembler.h"
+
+namespace v8 { namespace internal {
+
+// Forward declaration.
+class JumpTarget;
+
+
+// Helper types to make flags easier to read at call sites.
+enum InvokeFlag {
+  CALL_FUNCTION,
+  JUMP_FUNCTION
+};
+
+enum CodeLocation {
+  IN_JAVASCRIPT,
+  IN_JS_ENTRY,
+  IN_C_ENTRY
+};
+
+enum HandlerType {
+  TRY_CATCH_HANDLER,
+  TRY_FINALLY_HANDLER,
+  JS_ENTRY_HANDLER
+};
+
+
+// MacroAssembler implements a collection of frequently used macros.
+class MacroAssembler: public Assembler {
+ public:
+  MacroAssembler(void* buffer, int size);
+
+  // ---------------------------------------------------------------------------
+  // GC Support
+
+  // Set the remembered set bit for [object+offset].
+  // object is the object being stored into, value is the object being stored.
+  // If offset is zero, then the scratch register contains the array index into
+  // the elements array represented as a Smi.
+  // All registers are clobbered by the operation.
+  void RecordWrite(Register object,
+                   int offset,
+                   Register value,
+                   Register scratch);
+
+
+  // ---------------------------------------------------------------------------
+  // Debugger Support
+
+  void SaveRegistersToMemory(RegList regs);
+  void RestoreRegistersFromMemory(RegList regs);
+  void PushRegistersFromMemory(RegList regs);
+  void PopRegistersToMemory(RegList regs);
+  void CopyRegistersFromStackToMemory(Register base,
+                                      Register scratch,
+                                      RegList regs);
+
+
+  // ---------------------------------------------------------------------------
+  // Activation frames
+
+  void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); }
+  void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); }
+
+  void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
+  void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
+
+  // Enter specific kind of exit frame; either EXIT or
+  // EXIT_DEBUG. Expects the number of arguments in register eax and
+  // sets up the number of arguments in register edi and the pointer
+  // to the first argument in register esi.
+  void EnterExitFrame(StackFrame::Type type);
+
+  // 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(StackFrame::Type type);
+
+
+  // ---------------------------------------------------------------------------
+  // JavaScript invokes
+
+  // Invoke the JavaScript function code by either calling or jumping.
+  void InvokeCode(const Operand& code,
+                  const ParameterCount& expected,
+                  const ParameterCount& actual,
+                  InvokeFlag flag);
+
+  void InvokeCode(Handle<Code> code,
+                  const ParameterCount& expected,
+                  const ParameterCount& actual,
+                  RelocInfo::Mode rmode,
+                  InvokeFlag flag);
+
+  // Invoke the JavaScript function in the given register. Changes the
+  // current context to the context in the function before invoking.
+  void InvokeFunction(Register function,
+                      const ParameterCount& actual,
+                      InvokeFlag flag);
+
+  // Invoke specified builtin JavaScript function. Adds an entry to
+  // the unresolved list if the name does not resolve.
+  void InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag);
+
+  // Store the code object for the given builtin in the target register.
+  void GetBuiltinEntry(Register target, Builtins::JavaScript id);
+
+  // Expression support
+  void Set(Register dst, const Immediate& x);
+  void Set(const Operand& dst, const Immediate& x);
+
+  // Compare object type for heap object.
+  // Incoming register is heap_object and outgoing register is map.
+  void CmpObjectType(Register heap_object, InstanceType type, Register map);
+
+  // Compare instance type for map.
+  void CmpInstanceType(Register map, InstanceType type);
+
+  // FCmp is similar to integer cmp, but requires unsigned
+  // jcc instructions (je, ja, jae, jb, jbe, je, and jz).
+  void FCmp();
+
+  // ---------------------------------------------------------------------------
+  // Exception handling
+
+  // Push a new try handler and link into try handler chain.
+  // The return address must be pushed before calling this helper.
+  // On exit, eax contains TOS (next_sp).
+  void PushTryHandler(CodeLocation try_location, HandlerType type);
+
+
+  // ---------------------------------------------------------------------------
+  // Inline caching support
+
+  // Generates code that verifies that the maps of objects in the
+  // prototype chain of object hasn't changed since the code was
+  // generated and branches to the miss label if any map has. If
+  // necessary the function also generates code for security check
+  // in case of global object holders. The scratch and holder
+  // registers are always clobbered, but the object register is only
+  // clobbered if it the same as the holder register. The function
+  // returns a register containing the holder - either object_reg or
+  // holder_reg.
+  Register CheckMaps(JSObject* object, Register object_reg,
+                     JSObject* holder, Register holder_reg,
+                     Register scratch, Label* miss);
+
+  // Generate code for checking access rights - used for security checks
+  // on access to global objects across environments. The holder register
+  // is left untouched, but the scratch register is clobbered.
+  void CheckAccessGlobalProxy(Register holder_reg,
+                              Register scratch,
+                              Label* miss);
+
+
+  // ---------------------------------------------------------------------------
+  // Support functions.
+
+  // Check if result is zero and op is negative.
+  void NegativeZeroTest(Register result, Register op, Label* then_label);
+
+  // Check if result is zero and op is negative in code using jump targets.
+  void NegativeZeroTest(CodeGenerator* cgen,
+                        Register result,
+                        Register op,
+                        JumpTarget* then_target);
+
+  // Check if result is zero and any of op1 and op2 are negative.
+  // Register scratch is destroyed, and it must be different from op2.
+  void NegativeZeroTest(Register result, Register op1, Register op2,
+                        Register scratch, Label* then_label);
+
+  // Try to get function prototype of a function and puts the value in
+  // the result register. Checks that the function really is a
+  // function and jumps to the miss label if the fast checks fail. The
+  // function register will be untouched; the other registers may be
+  // clobbered.
+  void TryGetFunctionPrototype(Register function,
+                               Register result,
+                               Register scratch,
+                               Label* miss);
+
+  // Generates code for reporting that an illegal operation has
+  // occurred.
+  void IllegalOperation(int num_arguments);
+
+  // ---------------------------------------------------------------------------
+  // Runtime calls
+
+  // Call a code stub.
+  void CallStub(CodeStub* stub);
+
+  // Return from a code stub after popping its arguments.
+  void StubReturn(int argc);
+
+  // Call a runtime routine.
+  // Eventually this should be used for all C calls.
+  void CallRuntime(Runtime::Function* f, int num_arguments);
+
+  // Convenience function: Same as above, but takes the fid instead.
+  void CallRuntime(Runtime::FunctionId id, int num_arguments);
+
+  // Tail call of a runtime routine (jump).
+  // Like JumpToBuiltin, but also takes care of passing the number
+  // of arguments.
+  void TailCallRuntime(const ExternalReference& ext, int num_arguments);
+
+  // Jump to the builtin routine.
+  void JumpToBuiltin(const ExternalReference& ext);
+
+
+  // ---------------------------------------------------------------------------
+  // Utilities
+
+  void Ret();
+
+  struct Unresolved {
+    int pc;
+    uint32_t flags;  // see Bootstrapper::FixupFlags decoders/encoders.
+    const char* name;
+  };
+  List<Unresolved>* unresolved() { return &unresolved_; }
+
+  Handle<Object> CodeObject() { return code_object_; }
+
+
+  // ---------------------------------------------------------------------------
+  // StatsCounter support
+
+  void SetCounter(StatsCounter* counter, int value);
+  void IncrementCounter(StatsCounter* counter, int value);
+  void DecrementCounter(StatsCounter* counter, int value);
+
+
+  // ---------------------------------------------------------------------------
+  // Debugging
+
+  // Calls Abort(msg) if the condition cc is not satisfied.
+  // Use --debug_code to enable.
+  void Assert(Condition cc, const char* msg);
+
+  // Like Assert(), but always enabled.
+  void Check(Condition cc, const char* msg);
+
+  // Print a message to stdout and abort execution.
+  void Abort(const char* msg);
+
+  // Verify restrictions about code generated in stubs.
+  void set_generating_stub(bool value) { generating_stub_ = value; }
+  bool generating_stub() { return generating_stub_; }
+  void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
+  bool allow_stub_calls() { return allow_stub_calls_; }
+
+ private:
+  List<Unresolved> unresolved_;
+  bool generating_stub_;
+  bool allow_stub_calls_;
+  Handle<Object> code_object_;  // This handle will be patched with the code
+                                // code object on installation.
+
+  // Helper functions for generating invokes.
+  void InvokePrologue(const ParameterCount& expected,
+                      const ParameterCount& actual,
+                      Handle<Code> code_constant,
+                      const Operand& code_operand,
+                      Label* done,
+                      InvokeFlag flag);
+
+  // Get the code for the given builtin. Returns if able to resolve
+  // the function in the 'resolved' flag.
+  Handle<Code> ResolveBuiltin(Builtins::JavaScript id, bool* resolved);
+
+  // Activation support.
+  void EnterFrame(StackFrame::Type type);
+  void LeaveFrame(StackFrame::Type type);
+};
+
+
+// The code patcher is used to patch (typically) small parts of code e.g. for
+// debugging and other types of instrumentation. When using the code patcher
+// the exact number of bytes specified must be emitted. Is not legal to emit
+// relocation information. If any of these constraints are violated it causes
+// an assertion.
+class CodePatcher {
+ public:
+  CodePatcher(byte* address, int size);
+  virtual ~CodePatcher();
+
+  // Macro assembler to emit code.
+  MacroAssembler* masm() { return &masm_; }
+
+ private:
+  byte* address_;  // The address of the code being patched.
+  int size_;  // Number of bytes of the expected patch size.
+  MacroAssembler masm_;  // Macro assembler used to generate the code.
+};
+
+
+// -----------------------------------------------------------------------------
+// Static helper functions.
+
+// Generate an Operand for loading a field from an object.
+static inline Operand FieldOperand(Register object, int offset) {
+  return Operand(object, offset - kHeapObjectTag);
+}
+
+
+// Generate an Operand for loading an indexed field from an object.
+static inline Operand FieldOperand(Register object,
+                                   Register index,
+                                   ScaleFactor scale,
+                                   int offset) {
+  return Operand(object, index, scale, offset - kHeapObjectTag);
+}
+
+} }  // namespace v8::internal
+
+#endif  // V8_MACRO_ASSEMBLER_IA32_H_
diff --git a/deps/v8/src/macro-assembler.h b/deps/v8/src/macro-assembler.h
new file mode 100644
index 0000000..84a1eef
--- /dev/null
+++ b/deps/v8/src/macro-assembler.h
@@ -0,0 +1,50 @@
+// 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_MACRO_ASSEMBLER_H_
+#define V8_MACRO_ASSEMBLER_H_
+
+#ifdef ARM
+
+#include "constants-arm.h"
+#include "assembler.h"
+#include "assembler-arm.h"
+#include "assembler-arm-inl.h"
+#include "code.h"  // must be after assembler_*.h
+#include "macro-assembler-arm.h"
+
+#else  // ia32
+
+#include "assembler.h"
+#include "assembler-ia32.h"
+#include "assembler-ia32-inl.h"
+#include "code.h"  // must be after assembler_*.h
+#include "macro-assembler-ia32.h"
+
+#endif
+
+#endif  // V8_MACRO_ASSEMBLER_H_
diff --git a/deps/v8/src/macros.py b/deps/v8/src/macros.py
new file mode 100644
index 0000000..d78ecd9
--- /dev/null
+++ b/deps/v8/src/macros.py
@@ -0,0 +1,120 @@
+# Copyright 2006-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.
+
+# Dictionary that is passed as defines for js2c.py.
+# Used for defines that must be defined for all native js files.
+
+const NONE        = 0;
+const READ_ONLY   = 1;
+const DONT_ENUM   = 2;
+const DONT_DELETE = 4;
+
+# Constants used for getter and setter operations.
+const GETTER = 0;
+const SETTER = 1;
+
+# These definitions must match the index of the properties in objects.h.
+const kApiTagOffset               = 0;
+const kApiPropertyListOffset      = 1;
+const kApiSerialNumberOffset      = 2;
+const kApiConstructorOffset       = 2;
+const kApiPrototypeTemplateOffset = 5;
+const kApiParentTemplateOffset    = 6;
+
+const NO_HINT     = 0;
+const NUMBER_HINT = 1;
+const STRING_HINT = 2;
+
+const kFunctionTag  = 0;
+const kNewObjectTag = 1;
+
+# For date.js.
+const HoursPerDay      = 24;
+const MinutesPerHour   = 60;
+const SecondsPerMinute = 60;
+const msPerSecond      = 1000;
+const msPerMinute      = 60000;
+const msPerHour        = 3600000;
+const msPerDay         = 86400000;
+
+# For apinatives.js
+const kUninitialized = -1;
+
+# Note: kDayZeroInJulianDay = ToJulianDay(1970, 0, 1).
+const kInvalidDate        = 'Invalid Date';
+const kDayZeroInJulianDay = 2440588;
+const kMonthMask          = 0x1e0;
+const kDayMask            = 0x01f;
+const kYearShift          = 9;
+const kMonthShift         = 5;
+
+# Type query macros.
+macro IS_NULL(arg)              = (arg === null);
+macro IS_NULL_OR_UNDEFINED(arg) = (arg == null);
+macro IS_UNDEFINED(arg)         = (typeof(arg) === 'undefined');
+macro IS_FUNCTION(arg)          = (typeof(arg) === 'function');
+macro IS_NUMBER(arg)            = (typeof(arg) === 'number');
+macro IS_STRING(arg)            = (typeof(arg) === 'string');
+macro IS_OBJECT(arg)            = (typeof(arg) === 'object');
+macro IS_BOOLEAN(arg)           = (typeof(arg) === 'boolean');
+macro IS_REGEXP(arg)            = %HasRegExpClass(arg);
+macro IS_ARRAY(arg)             = %HasArrayClass(arg);
+macro IS_DATE(arg)              = %HasDateClass(arg);
+macro IS_ERROR(arg)             = (%ClassOf(arg) === 'Error');
+macro IS_SCRIPT(arg)            = (%ClassOf(arg) === 'Script');
+macro FLOOR(arg)                = %Math_floor(arg);
+
+# Inline macros. Use %IS_VAR to make sure arg is evaluated only once.
+macro NUMBER_IS_NAN(arg) = (!%_IsSmi(%IS_VAR(arg)) && !(arg == arg));
+macro TO_INTEGER(arg)    = (%_IsSmi(%IS_VAR(arg)) ? arg : ToInteger(arg));
+macro TO_INT32(arg)      = (%_IsSmi(%IS_VAR(arg)) ? arg : ToInt32(arg));
+
+# Macros implemented in Python.
+python macro CHAR_CODE(str) = ord(str[1]);
+
+# Accessors for original global properties that ensure they have been loaded.
+const ORIGINAL_REGEXP = (global.RegExp, $RegExp);
+const ORIGINAL_DATE   = (global.Date, $Date);
+
+# Constants used on an array to implement the properties of the RegExp object.
+const REGEXP_NUMBER_OF_CAPTURES = 0;
+const REGEXP_FIRST_CAPTURE = 3;
+
+# We can't put macros in macros so we use constants here.
+# REGEXP_NUMBER_OF_CAPTURES
+macro NUMBER_OF_CAPTURES(array) = ((array)[0]);
+
+# Last input and last subject are after the captures so we can omit them on
+# results returned from global searches.  Beware - these evaluate their
+# arguments twice.
+macro LAST_SUBJECT(array) = ((array)[1]);
+macro LAST_INPUT(array) = ((array)[2]);
+
+# REGEXP_FIRST_CAPTURE
+macro CAPTURE(index) = (3 + (index));
+const CAPTURE0 = 3;
+const CAPTURE1 = 4;
diff --git a/deps/v8/src/mark-compact.cc b/deps/v8/src/mark-compact.cc
new file mode 100644
index 0000000..c55345d
--- /dev/null
+++ b/deps/v8/src/mark-compact.cc
@@ -0,0 +1,1765 @@
+// 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.
+
+#include "v8.h"
+
+#include "execution.h"
+#include "global-handles.h"
+#include "ic-inl.h"
+#include "mark-compact.h"
+#include "stub-cache.h"
+
+namespace v8 { namespace internal {
+
+// -------------------------------------------------------------------------
+// MarkCompactCollector
+
+bool MarkCompactCollector::compacting_collection_ = false;
+
+int MarkCompactCollector::previous_marked_count_ = 0;
+GCTracer* MarkCompactCollector::tracer_ = NULL;
+
+
+#ifdef DEBUG
+MarkCompactCollector::CollectorState MarkCompactCollector::state_ = IDLE;
+
+// Counters used for debugging the marking phase of mark-compact or mark-sweep
+// collection.
+int MarkCompactCollector::live_bytes_ = 0;
+int MarkCompactCollector::live_young_objects_ = 0;
+int MarkCompactCollector::live_old_data_objects_ = 0;
+int MarkCompactCollector::live_old_pointer_objects_ = 0;
+int MarkCompactCollector::live_code_objects_ = 0;
+int MarkCompactCollector::live_map_objects_ = 0;
+int MarkCompactCollector::live_lo_objects_ = 0;
+#endif
+
+void MarkCompactCollector::CollectGarbage() {
+  // Make sure that Prepare() has been called. The individual steps below will
+  // update the state as they proceed.
+  ASSERT(state_ == PREPARE_GC);
+
+  // Prepare has selected whether to compact the old generation or not.
+  // Tell the tracer.
+  if (IsCompacting()) tracer_->set_is_compacting();
+
+  MarkLiveObjects();
+
+  if (FLAG_collect_maps) ClearNonLiveTransitions();
+
+  SweepLargeObjectSpace();
+
+  if (compacting_collection_) {
+    EncodeForwardingAddresses();
+
+    UpdatePointers();
+
+    RelocateObjects();
+
+    RebuildRSets();
+
+  } else {
+    SweepSpaces();
+  }
+
+  Finish();
+
+  // Save the count of marked objects remaining after the collection and
+  // null out the GC tracer.
+  previous_marked_count_ = tracer_->marked_count();
+  ASSERT(previous_marked_count_ == 0);
+  tracer_ = NULL;
+}
+
+
+void MarkCompactCollector::Prepare(GCTracer* tracer) {
+  // Rather than passing the tracer around we stash it in a static member
+  // variable.
+  tracer_ = tracer;
+
+  static const int kFragmentationLimit = 50;  // Percent.
+#ifdef DEBUG
+  ASSERT(state_ == IDLE);
+  state_ = PREPARE_GC;
+#endif
+  ASSERT(!FLAG_always_compact || !FLAG_never_compact);
+
+  compacting_collection_ = FLAG_always_compact;
+
+  // We compact the old generation if it gets too fragmented (ie, we could
+  // recover an expected amount of space by reclaiming the waste and free
+  // list blocks).  We always compact when the flag --gc-global is true
+  // because objects do not get promoted out of new space on non-compacting
+  // GCs.
+  if (!compacting_collection_) {
+    int old_gen_recoverable = 0;
+    int old_gen_used = 0;
+
+    OldSpaces spaces;
+    while (OldSpace* space = spaces.next()) {
+      old_gen_recoverable += space->Waste() + space->AvailableFree();
+      old_gen_used += space->Size();
+    }
+    int old_gen_fragmentation =
+      static_cast<int>((old_gen_recoverable * 100.0) / old_gen_used);
+    if (old_gen_fragmentation > kFragmentationLimit) {
+      compacting_collection_ = true;
+    }
+  }
+
+  if (FLAG_never_compact) compacting_collection_ = false;
+  if (FLAG_collect_maps) CreateBackPointers();
+
+#ifdef DEBUG
+  if (compacting_collection_) {
+    // We will write bookkeeping information to the remembered set area
+    // starting now.
+    Page::set_rset_state(Page::NOT_IN_USE);
+  }
+#endif
+
+  PagedSpaces spaces;
+  while (PagedSpace* space = spaces.next()) {
+    space->PrepareForMarkCompact(compacting_collection_);
+  }
+
+#ifdef DEBUG
+  live_bytes_ = 0;
+  live_young_objects_ = 0;
+  live_old_pointer_objects_ = 0;
+  live_old_data_objects_ = 0;
+  live_code_objects_ = 0;
+  live_map_objects_ = 0;
+  live_lo_objects_ = 0;
+#endif
+}
+
+
+void MarkCompactCollector::Finish() {
+#ifdef DEBUG
+  ASSERT(state_ == SWEEP_SPACES || state_ == REBUILD_RSETS);
+  state_ = IDLE;
+#endif
+  // The stub cache is not traversed during GC; clear the cache to
+  // force lazy re-initialization of it. This must be done after the
+  // GC, because it relies on the new address of certain old space
+  // objects (empty string, illegal builtin).
+  StubCache::Clear();
+}
+
+
+// -------------------------------------------------------------------------
+// Phase 1: tracing and marking live objects.
+//   before: all objects are in normal state.
+//   after: a live object's map pointer is marked as '00'.
+
+// Marking all live objects in the heap as part of mark-sweep or mark-compact
+// collection.  Before marking, all objects are in their normal state.  After
+// marking, live objects' map pointers are marked indicating that the object
+// has been found reachable.
+//
+// The marking algorithm is a (mostly) depth-first (because of possible stack
+// overflow) traversal of the graph of objects reachable from the roots.  It
+// uses an explicit stack of pointers rather than recursion.  The young
+// generation's inactive ('from') space is used as a marking stack.  The
+// objects in the marking stack are the ones that have been reached and marked
+// but their children have not yet been visited.
+//
+// The marking stack can overflow during traversal.  In that case, we set an
+// overflow flag.  When the overflow flag is set, we continue marking objects
+// reachable from the objects on the marking stack, but no longer push them on
+// the marking stack.  Instead, we mark them as both marked and overflowed.
+// When the stack is in the overflowed state, objects marked as overflowed
+// have been reached and marked but their children have not been visited yet.
+// After emptying the marking stack, we clear the overflow flag and traverse
+// the heap looking for objects marked as overflowed, push them on the stack,
+// and continue with marking.  This process repeats until all reachable
+// objects have been marked.
+
+static MarkingStack marking_stack;
+
+
+static inline HeapObject* ShortCircuitConsString(Object** p) {
+  // Optimization: If the heap object pointed to by p is a non-symbol
+  // cons string whose right substring is Heap::empty_string, update
+  // it in place to its left substring.  Return the updated value.
+  //
+  // Here we assume that if we change *p, we replace it with a heap object
+  // (ie, the left substring of a cons string is always a heap object).
+  //
+  // The check performed is:
+  //   object->IsConsString() && !object->IsSymbol() &&
+  //   (ConsString::cast(object)->second() == Heap::empty_string())
+  // except the maps for the object and its possible substrings might be
+  // marked.
+  HeapObject* object = HeapObject::cast(*p);
+  MapWord map_word = object->map_word();
+  map_word.ClearMark();
+  InstanceType type = map_word.ToMap()->instance_type();
+  if ((type & kShortcutTypeMask) != kShortcutTypeTag) return object;
+
+  Object* second = reinterpret_cast<ConsString*>(object)->unchecked_second();
+  if (reinterpret_cast<String*>(second) != Heap::empty_string()) return object;
+
+  // Since we don't have the object's start, it is impossible to update the
+  // remembered set.  Therefore, we only replace the string with its left
+  // substring when the remembered set does not change.
+  Object* first = reinterpret_cast<ConsString*>(object)->unchecked_first();
+  if (!Heap::InNewSpace(object) && Heap::InNewSpace(first)) return object;
+
+  *p = first;
+  return HeapObject::cast(first);
+}
+
+
+// Helper class for marking pointers in HeapObjects.
+class MarkingVisitor : public ObjectVisitor {
+ public:
+  void VisitPointer(Object** p) {
+    MarkObjectByPointer(p);
+  }
+
+  void VisitPointers(Object** start, Object** end) {
+    // Mark all objects pointed to in [start, end).
+    const int kMinRangeForMarkingRecursion = 64;
+    if (end - start >= kMinRangeForMarkingRecursion) {
+      if (VisitUnmarkedObjects(start, end)) return;
+      // We are close to a stack overflow, so just mark the objects.
+    }
+    for (Object** p = start; p < end; p++) MarkObjectByPointer(p);
+  }
+
+  void BeginCodeIteration(Code* code) {
+    // When iterating over a code object during marking
+    // ic targets are derived pointers.
+    ASSERT(code->ic_flag() == Code::IC_TARGET_IS_ADDRESS);
+  }
+
+  void EndCodeIteration(Code* code) {
+    // If this is a compacting collection, set ic targets
+    // are pointing to object headers.
+    if (IsCompacting()) code->set_ic_flag(Code::IC_TARGET_IS_OBJECT);
+  }
+
+  void VisitCodeTarget(RelocInfo* rinfo) {
+    ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
+    Code* code = CodeFromDerivedPointer(rinfo->target_address());
+    if (FLAG_cleanup_ics_at_gc && code->is_inline_cache_stub()) {
+      IC::Clear(rinfo->pc());
+      // Please note targets for cleared inline cached do not have to be
+      // marked since they are contained in Heap::non_monomorphic_cache().
+    } else {
+      MarkCompactCollector::MarkObject(code);
+    }
+    if (IsCompacting()) {
+      // When compacting we convert the target to a real object pointer.
+      code = CodeFromDerivedPointer(rinfo->target_address());
+      rinfo->set_target_object(code);
+    }
+  }
+
+  void VisitDebugTarget(RelocInfo* rinfo) {
+    ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()) &&
+           rinfo->IsCallInstruction());
+    HeapObject* code = CodeFromDerivedPointer(rinfo->call_address());
+    MarkCompactCollector::MarkObject(code);
+    // When compacting we convert the call to a real object pointer.
+    if (IsCompacting()) rinfo->set_call_object(code);
+  }
+
+ private:
+  // Mark object pointed to by p.
+  void MarkObjectByPointer(Object** p) {
+    if (!(*p)->IsHeapObject()) return;
+    HeapObject* object = ShortCircuitConsString(p);
+    MarkCompactCollector::MarkObject(object);
+  }
+
+  // Tells whether the mark sweep collection will perform compaction.
+  bool IsCompacting() { return MarkCompactCollector::IsCompacting(); }
+
+  // Retrieves the Code pointer from derived code entry.
+  Code* CodeFromDerivedPointer(Address addr) {
+    ASSERT(addr != NULL);
+    return reinterpret_cast<Code*>(
+        HeapObject::FromAddress(addr - Code::kHeaderSize));
+  }
+
+  // Visit an unmarked object.
+  void VisitUnmarkedObject(HeapObject* obj) {
+#ifdef DEBUG
+    ASSERT(Heap::Contains(obj));
+    ASSERT(!obj->IsMarked());
+#endif
+    Map* map = obj->map();
+    MarkCompactCollector::SetMark(obj);
+    // Mark the map pointer and the body.
+    MarkCompactCollector::MarkObject(map);
+    obj->IterateBody(map->instance_type(), obj->SizeFromMap(map), this);
+  }
+
+  // Visit all unmarked objects pointed to by [start, end).
+  // Returns false if the operation fails (lack of stack space).
+  inline bool VisitUnmarkedObjects(Object** start, Object** end) {
+    // Return false is we are close to the stack limit.
+    StackLimitCheck check;
+    if (check.HasOverflowed()) return false;
+
+    // Visit the unmarked objects.
+    for (Object** p = start; p < end; p++) {
+      if (!(*p)->IsHeapObject()) continue;
+      HeapObject* obj = HeapObject::cast(*p);
+      if (obj->IsMarked()) continue;
+      VisitUnmarkedObject(obj);
+    }
+    return true;
+  }
+};
+
+
+// Visitor class for marking heap roots.
+class RootMarkingVisitor : public ObjectVisitor {
+ public:
+  void VisitPointer(Object** p) {
+    MarkObjectByPointer(p);
+  }
+
+  void VisitPointers(Object** start, Object** end) {
+    for (Object** p = start; p < end; p++) MarkObjectByPointer(p);
+  }
+
+  MarkingVisitor* stack_visitor() { return &stack_visitor_; }
+
+ private:
+  MarkingVisitor stack_visitor_;
+
+  void MarkObjectByPointer(Object** p) {
+    if (!(*p)->IsHeapObject()) return;
+
+    // Replace flat cons strings in place.
+    HeapObject* object = ShortCircuitConsString(p);
+    if (object->IsMarked()) return;
+
+    Map* map = object->map();
+    // Mark the object.
+    MarkCompactCollector::SetMark(object);
+    // Mark the map pointer and body, and push them on the marking stack.
+    MarkCompactCollector::MarkObject(map);
+    object->IterateBody(map->instance_type(), object->SizeFromMap(map),
+                        &stack_visitor_);
+
+    // Mark all the objects reachable from the map and body.  May leave
+    // overflowed objects in the heap.
+    MarkCompactCollector::EmptyMarkingStack(&stack_visitor_);
+  }
+};
+
+
+// Helper class for pruning the symbol table.
+class SymbolTableCleaner : public ObjectVisitor {
+ public:
+  SymbolTableCleaner() : pointers_removed_(0) { }
+  void VisitPointers(Object** start, Object** end) {
+    // Visit all HeapObject pointers in [start, end).
+    for (Object** p = start; p < end; p++) {
+      if ((*p)->IsHeapObject() && !HeapObject::cast(*p)->IsMarked()) {
+        // Check if the symbol being pruned is an external symbol. We need to
+        // delete the associated external data as this symbol is going away.
+
+        // Since the object is not marked we can access its map word safely
+        // without having to worry about marking bits in the object header.
+        Map* map = HeapObject::cast(*p)->map();
+        // Since no objects have yet been moved we can safely access the map of
+        // the object.
+        uint32_t type = map->instance_type();
+        bool is_external = (type & kStringRepresentationMask) ==
+                           kExternalStringTag;
+        if (is_external) {
+          bool is_two_byte = (type & kStringEncodingMask) == kTwoByteStringTag;
+          byte* resource_addr = reinterpret_cast<byte*>(*p) +
+                                ExternalString::kResourceOffset -
+                                kHeapObjectTag;
+          if (is_two_byte) {
+            v8::String::ExternalStringResource** resource =
+                reinterpret_cast<v8::String::ExternalStringResource**>
+                (resource_addr);
+            delete *resource;
+            // Clear the resource pointer in the symbol.
+            *resource = NULL;
+          } else {
+            v8::String::ExternalAsciiStringResource** resource =
+                reinterpret_cast<v8::String::ExternalAsciiStringResource**>
+                (resource_addr);
+            delete *resource;
+            // Clear the resource pointer in the symbol.
+            *resource = NULL;
+          }
+        }
+        // Set the entry to null_value (as deleted).
+        *p = Heap::null_value();
+        pointers_removed_++;
+      }
+    }
+  }
+
+  int PointersRemoved() {
+    return pointers_removed_;
+  }
+ private:
+  int pointers_removed_;
+};
+
+
+void MarkCompactCollector::MarkUnmarkedObject(HeapObject* object) {
+  ASSERT(!object->IsMarked());
+  ASSERT(Heap::Contains(object));
+  if (object->IsMap()) {
+    Map* map = Map::cast(object);
+    if (FLAG_cleanup_caches_in_maps_at_gc) {
+      map->ClearCodeCache();
+    }
+    SetMark(map);
+    if (FLAG_collect_maps &&
+        map->instance_type() >= FIRST_JS_OBJECT_TYPE &&
+        map->instance_type() <= JS_FUNCTION_TYPE) {
+      MarkMapContents(map);
+    } else {
+      marking_stack.Push(map);
+    }
+  } else {
+    SetMark(object);
+    marking_stack.Push(object);
+  }
+}
+
+
+void MarkCompactCollector::MarkMapContents(Map* map) {
+  MarkDescriptorArray(reinterpret_cast<DescriptorArray*>(
+      *HeapObject::RawField(map, Map::kInstanceDescriptorsOffset)));
+
+  // Mark the Object* fields of the Map.
+  // Since the descriptor array has been marked already, it is fine
+  // that one of these fields contains a pointer to it.
+  MarkingVisitor visitor;  // Has no state or contents.
+  visitor.VisitPointers(HeapObject::RawField(map, Map::kPrototypeOffset),
+                        HeapObject::RawField(map, Map::kSize));
+}
+
+
+void MarkCompactCollector::MarkDescriptorArray(
+    DescriptorArray *descriptors) {
+  if (descriptors->IsMarked()) return;
+  // Empty descriptor array is marked as a root before any maps are marked.
+  ASSERT(descriptors != Heap::empty_descriptor_array());
+  SetMark(descriptors);
+
+  FixedArray* contents = reinterpret_cast<FixedArray*>(
+      descriptors->get(DescriptorArray::kContentArrayIndex));
+  ASSERT(contents->IsHeapObject());
+  ASSERT(!contents->IsMarked());
+  ASSERT(contents->IsFixedArray());
+  ASSERT(contents->length() >= 2);
+  SetMark(contents);
+  // Contents contains (value, details) pairs.  If the details say
+  // that the type of descriptor is MAP_TRANSITION, CONSTANT_TRANSITION,
+  // or NULL_DESCRIPTOR, we don't mark the value as live.  Only for
+  // type MAP_TRANSITION is the value a Object* (a Map*).
+  for (int i = 0; i < contents->length(); i += 2) {
+    // If the pair (value, details) at index i, i+1 is not
+    // a transition or null descriptor, mark the value.
+    PropertyDetails details(Smi::cast(contents->get(i + 1)));
+    if (details.type() < FIRST_PHANTOM_PROPERTY_TYPE) {
+      HeapObject* object = reinterpret_cast<HeapObject*>(contents->get(i));
+      if (object->IsHeapObject() && !object->IsMarked()) {
+        SetMark(object);
+        marking_stack.Push(object);
+      }
+    }
+  }
+  // The DescriptorArray descriptors contains a pointer to its contents array,
+  // but the contents array is already marked.
+  marking_stack.Push(descriptors);
+}
+
+
+void MarkCompactCollector::CreateBackPointers() {
+  HeapObjectIterator iterator(Heap::map_space());
+  while (iterator.has_next()) {
+    Object* next_object = iterator.next();
+    if (next_object->IsMap()) {  // Could also be ByteArray on free list.
+      Map* map = Map::cast(next_object);
+      if (map->instance_type() >= FIRST_JS_OBJECT_TYPE &&
+          map->instance_type() <= JS_FUNCTION_TYPE) {
+        map->CreateBackPointers();
+      } else {
+        ASSERT(map->instance_descriptors() == Heap::empty_descriptor_array());
+      }
+    }
+  }
+}
+
+
+static int OverflowObjectSize(HeapObject* obj) {
+  // Recover the normal map pointer, it might be marked as live and
+  // overflowed.
+  MapWord map_word = obj->map_word();
+  map_word.ClearMark();
+  map_word.ClearOverflow();
+  return obj->SizeFromMap(map_word.ToMap());
+}
+
+
+// Fill the marking stack with overflowed objects returned by the given
+// iterator.  Stop when the marking stack is filled or the end of the space
+// is reached, whichever comes first.
+template<class T>
+static void ScanOverflowedObjects(T* it) {
+  // The caller should ensure that the marking stack is initially not full,
+  // so that we don't waste effort pointlessly scanning for objects.
+  ASSERT(!marking_stack.is_full());
+
+  while (it->has_next()) {
+    HeapObject* object = it->next();
+    if (object->IsOverflowed()) {
+      object->ClearOverflow();
+      ASSERT(object->IsMarked());
+      ASSERT(Heap::Contains(object));
+      marking_stack.Push(object);
+      if (marking_stack.is_full()) return;
+    }
+  }
+}
+
+
+bool MarkCompactCollector::MustBeMarked(Object** p) {
+  // Check whether *p is a HeapObject pointer.
+  if (!(*p)->IsHeapObject()) return false;
+  return !HeapObject::cast(*p)->IsMarked();
+}
+
+
+void MarkCompactCollector::ProcessRoots(RootMarkingVisitor* visitor) {
+  // Mark the heap roots gray, including global variables, stack variables,
+  // etc.
+  Heap::IterateStrongRoots(visitor);
+
+  // Take care of the symbol table specially.
+  SymbolTable* symbol_table = SymbolTable::cast(Heap::symbol_table());
+  // 1. Mark the prefix of the symbol table gray.
+  symbol_table->IteratePrefix(visitor);
+  // 2. Mark the symbol table black (ie, do not push it on the marking stack
+  // or mark it overflowed).
+  SetMark(symbol_table);
+
+  // There may be overflowed objects in the heap.  Visit them now.
+  while (marking_stack.overflowed()) {
+    RefillMarkingStack();
+    EmptyMarkingStack(visitor->stack_visitor());
+  }
+}
+
+
+void MarkCompactCollector::MarkObjectGroups() {
+  List<ObjectGroup*>* object_groups = GlobalHandles::ObjectGroups();
+
+  for (int i = 0; i < object_groups->length(); i++) {
+    ObjectGroup* entry = object_groups->at(i);
+    if (entry == NULL) continue;
+
+    List<Object**>& objects = entry->objects_;
+    bool group_marked = false;
+    for (int j = 0; j < objects.length(); j++) {
+      Object* object = *objects[j];
+      if (object->IsHeapObject() && HeapObject::cast(object)->IsMarked()) {
+        group_marked = true;
+        break;
+      }
+    }
+
+    if (!group_marked) continue;
+
+    // An object in the group is marked, so mark as gray all white heap
+    // objects in the group.
+    for (int j = 0; j < objects.length(); ++j) {
+      if ((*objects[j])->IsHeapObject()) {
+        MarkObject(HeapObject::cast(*objects[j]));
+      }
+    }
+    // Once the entire group has been colored gray, set the object group
+    // to NULL so it won't be processed again.
+    delete object_groups->at(i);
+    object_groups->at(i) = NULL;
+  }
+}
+
+
+// Mark all objects reachable from the objects on the marking stack.
+// Before: the marking stack contains zero or more heap object pointers.
+// After: the marking stack is empty, and all objects reachable from the
+// marking stack have been marked, or are overflowed in the heap.
+void MarkCompactCollector::EmptyMarkingStack(MarkingVisitor* visitor) {
+  while (!marking_stack.is_empty()) {
+    HeapObject* object = marking_stack.Pop();
+    ASSERT(object->IsHeapObject());
+    ASSERT(Heap::Contains(object));
+    ASSERT(object->IsMarked());
+    ASSERT(!object->IsOverflowed());
+
+    // Because the object is marked, we have to recover the original map
+    // pointer and use it to mark the object's body.
+    MapWord map_word = object->map_word();
+    map_word.ClearMark();
+    Map* map = map_word.ToMap();
+    MarkObject(map);
+    object->IterateBody(map->instance_type(), object->SizeFromMap(map),
+                        visitor);
+  }
+}
+
+
+// Sweep the heap for overflowed objects, clear their overflow bits, and
+// push them on the marking stack.  Stop early if the marking stack fills
+// before sweeping completes.  If sweeping completes, there are no remaining
+// overflowed objects in the heap so the overflow flag on the markings stack
+// is cleared.
+void MarkCompactCollector::RefillMarkingStack() {
+  ASSERT(marking_stack.overflowed());
+
+  SemiSpaceIterator new_it(Heap::new_space(), &OverflowObjectSize);
+  ScanOverflowedObjects(&new_it);
+  if (marking_stack.is_full()) return;
+
+  HeapObjectIterator old_pointer_it(Heap::old_pointer_space(),
+                                    &OverflowObjectSize);
+  ScanOverflowedObjects(&old_pointer_it);
+  if (marking_stack.is_full()) return;
+
+  HeapObjectIterator old_data_it(Heap::old_data_space(), &OverflowObjectSize);
+  ScanOverflowedObjects(&old_data_it);
+  if (marking_stack.is_full()) return;
+
+  HeapObjectIterator code_it(Heap::code_space(), &OverflowObjectSize);
+  ScanOverflowedObjects(&code_it);
+  if (marking_stack.is_full()) return;
+
+  HeapObjectIterator map_it(Heap::map_space(), &OverflowObjectSize);
+  ScanOverflowedObjects(&map_it);
+  if (marking_stack.is_full()) return;
+
+  LargeObjectIterator lo_it(Heap::lo_space(), &OverflowObjectSize);
+  ScanOverflowedObjects(&lo_it);
+  if (marking_stack.is_full()) return;
+
+  marking_stack.clear_overflowed();
+}
+
+
+// Mark all objects reachable (transitively) from objects on the marking
+// stack.  Before: the marking stack contains zero or more heap object
+// pointers.  After: the marking stack is empty and there are no overflowed
+// objects in the heap.
+void MarkCompactCollector::ProcessMarkingStack(MarkingVisitor* visitor) {
+  EmptyMarkingStack(visitor);
+  while (marking_stack.overflowed()) {
+    RefillMarkingStack();
+    EmptyMarkingStack(visitor);
+  }
+}
+
+
+void MarkCompactCollector::ProcessObjectGroups(MarkingVisitor* visitor) {
+  bool work_to_do = true;
+  ASSERT(marking_stack.is_empty());
+  while (work_to_do) {
+    MarkObjectGroups();
+    work_to_do = !marking_stack.is_empty();
+    ProcessMarkingStack(visitor);
+  }
+}
+
+
+void MarkCompactCollector::MarkLiveObjects() {
+#ifdef DEBUG
+  ASSERT(state_ == PREPARE_GC);
+  state_ = MARK_LIVE_OBJECTS;
+#endif
+  // The to space contains live objects, the from space is used as a marking
+  // stack.
+  marking_stack.Initialize(Heap::new_space()->FromSpaceLow(),
+                           Heap::new_space()->FromSpaceHigh());
+
+  ASSERT(!marking_stack.overflowed());
+
+  RootMarkingVisitor root_visitor;
+  ProcessRoots(&root_visitor);
+
+  // The objects reachable from the roots are marked black, unreachable
+  // objects are white.  Mark objects reachable from object groups with at
+  // least one marked object, and continue until no new objects are
+  // reachable from the object groups.
+  ProcessObjectGroups(root_visitor.stack_visitor());
+
+  // The objects reachable from the roots or object groups are marked black,
+  // unreachable objects are white.  Process objects reachable only from
+  // weak global handles.
+  //
+  // First we mark weak pointers not yet reachable.
+  GlobalHandles::MarkWeakRoots(&MustBeMarked);
+  // Then we process weak pointers and process the transitive closure.
+  GlobalHandles::IterateWeakRoots(&root_visitor);
+  while (marking_stack.overflowed()) {
+    RefillMarkingStack();
+    EmptyMarkingStack(root_visitor.stack_visitor());
+  }
+
+  // Repeat the object groups to mark unmarked groups reachable from the
+  // weak roots.
+  ProcessObjectGroups(root_visitor.stack_visitor());
+
+  // Prune the symbol table removing all symbols only pointed to by the
+  // symbol table.  Cannot use SymbolTable::cast here because the symbol
+  // table is marked.
+  SymbolTable* symbol_table =
+      reinterpret_cast<SymbolTable*>(Heap::symbol_table());
+  SymbolTableCleaner v;
+  symbol_table->IterateElements(&v);
+  symbol_table->ElementsRemoved(v.PointersRemoved());
+
+  // Remove object groups after marking phase.
+  GlobalHandles::RemoveObjectGroups();
+}
+
+
+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();
+  if (Heap::new_space()->Contains(obj)) {
+    live_young_objects_++;
+  } else if (Heap::map_space()->Contains(obj)) {
+    ASSERT(obj->IsMap());
+    live_map_objects_++;
+  } else if (Heap::old_pointer_space()->Contains(obj)) {
+    live_old_pointer_objects_++;
+  } else if (Heap::old_data_space()->Contains(obj)) {
+    live_old_data_objects_++;
+  } else if (Heap::code_space()->Contains(obj)) {
+    live_code_objects_++;
+  } else if (Heap::lo_space()->Contains(obj)) {
+    live_lo_objects_++;
+  } else {
+    UNREACHABLE();
+  }
+}
+#endif  // DEBUG
+
+
+void MarkCompactCollector::SweepLargeObjectSpace() {
+#ifdef DEBUG
+  ASSERT(state_ == MARK_LIVE_OBJECTS);
+  state_ =
+      compacting_collection_ ? ENCODE_FORWARDING_ADDRESSES : SWEEP_SPACES;
+#endif
+  // Deallocate unmarked objects and clear marked bits for marked objects.
+  Heap::lo_space()->FreeUnmarkedObjects();
+}
+
+// Safe to use during marking phase only.
+bool MarkCompactCollector::SafeIsMap(HeapObject* object) {
+  MapWord metamap = object->map_word();
+  metamap.ClearMark();
+  return metamap.ToMap()->instance_type() == MAP_TYPE;
+}
+
+void MarkCompactCollector::ClearNonLiveTransitions() {
+  HeapObjectIterator map_iterator(Heap::map_space(), &CountMarkedCallback);
+  // 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,
+  // dropping the back pointers temporarily stored in the prototype field.
+  // Setting the prototype field requires following the linked list of
+  // back pointers, reversing them all at once.  This allows us to find
+  // those maps with map transitions that need to be nulled, and only
+  // scan the descriptor arrays of those maps, not all maps.
+  // All of these actions are carried out only on maps of JSObects
+  // and related subtypes.
+  while (map_iterator.has_next()) {
+    Map* map = reinterpret_cast<Map*>(map_iterator.next());
+    if (!map->IsMarked() && map->IsByteArray()) continue;
+
+    ASSERT(SafeIsMap(map));
+    // Only JSObject and subtypes have map transitions and back pointers.
+    if (map->instance_type() < FIRST_JS_OBJECT_TYPE) continue;
+    if (map->instance_type() > JS_FUNCTION_TYPE) continue;
+    // Follow the chain of back pointers to find the prototype.
+    Map* current = map;
+    while (SafeIsMap(current)) {
+      current = reinterpret_cast<Map*>(current->prototype());
+      ASSERT(current->IsHeapObject());
+    }
+    Object* real_prototype = current;
+
+    // Follow back pointers, setting them to prototype,
+    // clearing map transitions when necessary.
+    current = map;
+    bool on_dead_path = !current->IsMarked();
+    Object *next;
+    while (SafeIsMap(current)) {
+      next = current->prototype();
+      // There should never be a dead map above a live map.
+      ASSERT(on_dead_path || current->IsMarked());
+
+      // A live map above a dead map indicates a dead transition.
+      // This test will always be false on the first iteration.
+      if (on_dead_path && current->IsMarked()) {
+        on_dead_path = false;
+        current->ClearNonLiveTransitions(real_prototype);
+      }
+      *HeapObject::RawField(current, Map::kPrototypeOffset) =
+          real_prototype;
+      current = reinterpret_cast<Map*>(next);
+    }
+  }
+}
+
+// -------------------------------------------------------------------------
+// Phase 2: Encode forwarding addresses.
+// When compacting, forwarding addresses for objects in old space and map
+// space are encoded in their map pointer word (along with an encoding of
+// their map pointers).
+//
+//  31             21 20              10 9               0
+// +-----------------+------------------+-----------------+
+// |forwarding offset|page offset of map|page index of map|
+// +-----------------+------------------+-----------------+
+//  11 bits           11 bits            10 bits
+//
+// An address range [start, end) can have both live and non-live objects.
+// Maximal non-live regions are marked so they can be skipped on subsequent
+// sweeps of the heap.  A distinguished map-pointer encoding is used to mark
+// free regions of one-word size (in which case the next word is the start
+// of a live object).  A second distinguished map-pointer encoding is used
+// to mark free regions larger than one word, and the size of the free
+// region (including the first word) is written to the second word of the
+// region.
+//
+// Any valid map page offset must lie in the object area of the page, so map
+// page offsets less than Page::kObjectStartOffset are invalid.  We use a
+// pair of distinguished invalid map encodings (for single word and multiple
+// words) to indicate free regions in the page found during computation of
+// forwarding addresses and skipped over in subsequent sweeps.
+static const uint32_t kSingleFreeEncoding = 0;
+static const uint32_t kMultiFreeEncoding = 1;
+
+
+// Encode a free region, defined by the given start address and size, in the
+// first word or two of the region.
+void EncodeFreeRegion(Address free_start, int free_size) {
+  ASSERT(free_size >= kIntSize);
+  if (free_size == kIntSize) {
+    Memory::uint32_at(free_start) = kSingleFreeEncoding;
+  } else {
+    ASSERT(free_size >= 2 * kIntSize);
+    Memory::uint32_at(free_start) = kMultiFreeEncoding;
+    Memory::int_at(free_start + kIntSize) = free_size;
+  }
+
+#ifdef DEBUG
+  // Zap the body of the free region.
+  if (FLAG_enable_slow_asserts) {
+    for (int offset = 2 * kIntSize;
+         offset < free_size;
+         offset += kPointerSize) {
+      Memory::Address_at(free_start + offset) = kZapValue;
+    }
+  }
+#endif
+}
+
+
+// Try to promote all objects in new space.  Heap numbers and sequential
+// strings are promoted to the code space, all others to the old space.
+inline Object* MCAllocateFromNewSpace(HeapObject* object, int object_size) {
+  OldSpace* target_space = Heap::TargetSpace(object);
+  ASSERT(target_space == Heap::old_pointer_space() ||
+         target_space == Heap::old_data_space());
+  Object* forwarded = target_space->MCAllocateRaw(object_size);
+
+  if (forwarded->IsFailure()) {
+    forwarded = Heap::new_space()->MCAllocateRaw(object_size);
+  }
+  return forwarded;
+}
+
+
+// Allocation functions for the paged spaces call the space's MCAllocateRaw.
+inline Object* MCAllocateFromOldPointerSpace(HeapObject* object,
+                                             int object_size) {
+  return Heap::old_pointer_space()->MCAllocateRaw(object_size);
+}
+
+
+inline Object* MCAllocateFromOldDataSpace(HeapObject* object, int object_size) {
+  return Heap::old_data_space()->MCAllocateRaw(object_size);
+}
+
+
+inline Object* MCAllocateFromCodeSpace(HeapObject* object, int object_size) {
+  return Heap::code_space()->MCAllocateRaw(object_size);
+}
+
+
+inline Object* MCAllocateFromMapSpace(HeapObject* object, int object_size) {
+  return Heap::map_space()->MCAllocateRaw(object_size);
+}
+
+
+// The forwarding address is encoded at the same offset as the current
+// to-space object, but in from space.
+inline void EncodeForwardingAddressInNewSpace(HeapObject* old_object,
+                                              int object_size,
+                                              Object* new_object,
+                                              int* ignored) {
+  int offset =
+      Heap::new_space()->ToSpaceOffsetForAddress(old_object->address());
+  Memory::Address_at(Heap::new_space()->FromSpaceLow() + offset) =
+      HeapObject::cast(new_object)->address();
+}
+
+
+// The forwarding address is encoded in the map pointer of the object as an
+// offset (in terms of live bytes) from the address of the first live object
+// in the page.
+inline void EncodeForwardingAddressInPagedSpace(HeapObject* old_object,
+                                                int object_size,
+                                                Object* new_object,
+                                                int* offset) {
+  // Record the forwarding address of the first live object if necessary.
+  if (*offset == 0) {
+    Page::FromAddress(old_object->address())->mc_first_forwarded =
+        HeapObject::cast(new_object)->address();
+  }
+
+  MapWord encoding =
+      MapWord::EncodeAddress(old_object->map()->address(), *offset);
+  old_object->set_map_word(encoding);
+  *offset += object_size;
+  ASSERT(*offset <= Page::kObjectAreaSize);
+}
+
+
+// Most non-live objects are ignored.
+inline void IgnoreNonLiveObject(HeapObject* object) {}
+
+
+// A code deletion event is logged for non-live code objects.
+inline void LogNonLiveCodeObject(HeapObject* object) {
+  if (object->IsCode()) LOG(CodeDeleteEvent(object->address()));
+}
+
+
+// Function template that, given a range of addresses (eg, a semispace or a
+// paged space page), iterates through the objects in the range to clear
+// mark bits and compute and encode forwarding addresses.  As a side effect,
+// maximal free chunks are marked so that they can be skipped on subsequent
+// sweeps.
+//
+// The template parameters are an allocation function, a forwarding address
+// encoding function, and a function to process non-live objects.
+template<MarkCompactCollector::AllocationFunction Alloc,
+         MarkCompactCollector::EncodingFunction Encode,
+         MarkCompactCollector::ProcessNonLiveFunction ProcessNonLive>
+inline void EncodeForwardingAddressesInRange(Address start,
+                                             Address end,
+                                             int* offset) {
+  // The start address of the current free region while sweeping the space.
+  // This address is set when a transition from live to non-live objects is
+  // encountered.  A value (an encoding of the 'next free region' pointer)
+  // is written to memory at this address when a transition from non-live to
+  // live objects is encountered.
+  Address free_start = NULL;
+
+  // A flag giving the state of the previously swept object.  Initially true
+  // to ensure that free_start is initialized to a proper address before
+  // trying to write to it.
+  bool is_prev_alive = true;
+
+  int object_size;  // Will be set on each iteration of the loop.
+  for (Address current = start; current < end; current += object_size) {
+    HeapObject* object = HeapObject::FromAddress(current);
+    if (object->IsMarked()) {
+      object->ClearMark();
+      MarkCompactCollector::tracer()->decrement_marked_count();
+      object_size = object->Size();
+
+      Object* forwarded = Alloc(object, object_size);
+      // Allocation cannot fail, because we are compacting the space.
+      ASSERT(!forwarded->IsFailure());
+      Encode(object, object_size, forwarded, offset);
+
+#ifdef DEBUG
+      if (FLAG_gc_verbose) {
+        PrintF("forward %p -> %p.\n", object->address(),
+               HeapObject::cast(forwarded)->address());
+      }
+#endif
+      if (!is_prev_alive) {  // Transition from non-live to live.
+        EncodeFreeRegion(free_start, current - free_start);
+        is_prev_alive = true;
+      }
+    } else {  // Non-live object.
+      object_size = object->Size();
+      ProcessNonLive(object);
+      if (is_prev_alive) {  // Transition from live to non-live.
+        free_start = current;
+        is_prev_alive = false;
+      }
+    }
+  }
+
+  // If we ended on a free region, mark it.
+  if (!is_prev_alive) EncodeFreeRegion(free_start, end - free_start);
+}
+
+
+// Functions to encode the forwarding pointers in each compactable space.
+void MarkCompactCollector::EncodeForwardingAddressesInNewSpace() {
+  int ignored;
+  EncodeForwardingAddressesInRange<MCAllocateFromNewSpace,
+                                   EncodeForwardingAddressInNewSpace,
+                                   IgnoreNonLiveObject>(
+      Heap::new_space()->bottom(),
+      Heap::new_space()->top(),
+      &ignored);
+}
+
+
+template<MarkCompactCollector::AllocationFunction Alloc,
+         MarkCompactCollector::ProcessNonLiveFunction ProcessNonLive>
+void MarkCompactCollector::EncodeForwardingAddressesInPagedSpace(
+    PagedSpace* space) {
+  PageIterator it(space, PageIterator::PAGES_IN_USE);
+  while (it.has_next()) {
+    Page* p = it.next();
+    // The offset of each live object in the page from the first live object
+    // in the page.
+    int offset = 0;
+    EncodeForwardingAddressesInRange<Alloc,
+                                     EncodeForwardingAddressInPagedSpace,
+                                     ProcessNonLive>(
+        p->ObjectAreaStart(),
+        p->AllocationTop(),
+        &offset);
+  }
+}
+
+
+static void SweepSpace(NewSpace* space) {
+  HeapObject* object;
+  for (Address current = space->bottom();
+       current < space->top();
+       current += object->Size()) {
+    object = HeapObject::FromAddress(current);
+    if (object->IsMarked()) {
+      object->ClearMark();
+      MarkCompactCollector::tracer()->decrement_marked_count();
+    } else {
+      // We give non-live objects a map that will correctly give their size,
+      // since their existing map might not be live after the collection.
+      int size = object->Size();
+      if (size >= Array::kHeaderSize) {
+        object->set_map(Heap::byte_array_map());
+        ByteArray::cast(object)->set_length(ByteArray::LengthFor(size));
+      } else {
+        ASSERT(size == kPointerSize);
+        object->set_map(Heap::one_word_filler_map());
+      }
+      ASSERT(object->Size() == size);
+    }
+    // The object is now unmarked for the call to Size() at the top of the
+    // loop.
+  }
+}
+
+
+static void SweepSpace(PagedSpace* space, DeallocateFunction dealloc) {
+  PageIterator it(space, PageIterator::PAGES_IN_USE);
+  while (it.has_next()) {
+    Page* p = it.next();
+
+    bool is_previous_alive = true;
+    Address free_start = NULL;
+    HeapObject* object;
+
+    for (Address current = p->ObjectAreaStart();
+         current < p->AllocationTop();
+         current += object->Size()) {
+      object = HeapObject::FromAddress(current);
+      if (object->IsMarked()) {
+        object->ClearMark();
+        MarkCompactCollector::tracer()->decrement_marked_count();
+        if (MarkCompactCollector::IsCompacting() && object->IsCode()) {
+          // If this is compacting collection marked code objects have had
+          // their IC targets converted to objects.
+          // They need to be converted back to addresses.
+          Code::cast(object)->ConvertICTargetsFromObjectToAddress();
+        }
+        if (!is_previous_alive) {  // Transition from free to live.
+          dealloc(free_start, current - free_start);
+          is_previous_alive = true;
+        }
+      } else {
+        if (object->IsCode()) {
+          // Notify the logger that compiled code has been collected.
+          LOG(CodeDeleteEvent(Code::cast(object)->address()));
+        }
+        if (is_previous_alive) {  // Transition from live to free.
+          free_start = current;
+          is_previous_alive = false;
+        }
+      }
+      // The object is now unmarked for the call to Size() at the top of the
+      // loop.
+    }
+
+    // If the last region was not live we need to from free_start to the
+    // allocation top in the page.
+    if (!is_previous_alive) {
+      int free_size = p->AllocationTop() - free_start;
+      if (free_size > 0) {
+        dealloc(free_start, free_size);
+      }
+    }
+  }
+}
+
+
+void MarkCompactCollector::DeallocateOldPointerBlock(Address start,
+                                                     int size_in_bytes) {
+  Heap::ClearRSetRange(start, size_in_bytes);
+  Heap::old_pointer_space()->Free(start, size_in_bytes);
+}
+
+
+void MarkCompactCollector::DeallocateOldDataBlock(Address start,
+                                                  int size_in_bytes) {
+  Heap::old_data_space()->Free(start, size_in_bytes);
+}
+
+
+void MarkCompactCollector::DeallocateCodeBlock(Address start,
+                                               int size_in_bytes) {
+  Heap::code_space()->Free(start, size_in_bytes);
+}
+
+
+void MarkCompactCollector::DeallocateMapBlock(Address start,
+                                              int size_in_bytes) {
+  // Objects in map space are frequently assumed to have size Map::kSize and a
+  // valid map in their first word.  Thus, we break the free block up into
+  // chunks and free them separately.
+  ASSERT(size_in_bytes % Map::kSize == 0);
+  Heap::ClearRSetRange(start, size_in_bytes);
+  Address end = start + size_in_bytes;
+  for (Address a = start; a < end; a += Map::kSize) {
+    Heap::map_space()->Free(a);
+  }
+}
+
+
+void MarkCompactCollector::EncodeForwardingAddresses() {
+  ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES);
+  // Objects in the active semispace of the young generation may be
+  // relocated to the inactive semispace (if not promoted).  Set the
+  // relocation info to the beginning of the inactive semispace.
+  Heap::new_space()->MCResetRelocationInfo();
+
+  // Compute the forwarding pointers in each space.
+  EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldPointerSpace,
+                                        IgnoreNonLiveObject>(
+      Heap::old_pointer_space());
+
+  EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldDataSpace,
+                                        IgnoreNonLiveObject>(
+      Heap::old_data_space());
+
+  EncodeForwardingAddressesInPagedSpace<MCAllocateFromCodeSpace,
+                                        LogNonLiveCodeObject>(
+      Heap::code_space());
+
+  // Compute new space next to last after the old and code spaces have been
+  // compacted.  Objects in new space can be promoted to old or code space.
+  EncodeForwardingAddressesInNewSpace();
+
+  // Compute map space last because computing forwarding addresses
+  // overwrites non-live objects.  Objects in the other spaces rely on
+  // non-live map pointers to get the sizes of non-live objects.
+  EncodeForwardingAddressesInPagedSpace<MCAllocateFromMapSpace,
+                                        IgnoreNonLiveObject>(
+      Heap::map_space());
+
+  // Write relocation info to the top page, so we can use it later.  This is
+  // done after promoting objects from the new space so we get the correct
+  // allocation top.
+  Heap::old_pointer_space()->MCWriteRelocationInfoToPage();
+  Heap::old_data_space()->MCWriteRelocationInfoToPage();
+  Heap::code_space()->MCWriteRelocationInfoToPage();
+  Heap::map_space()->MCWriteRelocationInfoToPage();
+}
+
+
+void MarkCompactCollector::SweepSpaces() {
+  ASSERT(state_ == SWEEP_SPACES);
+  ASSERT(!IsCompacting());
+  // Noncompacting collections simply sweep the spaces to clear the mark
+  // bits and free the nonlive blocks (for old and map spaces).  We sweep
+  // the map space last because freeing non-live maps overwrites them and
+  // the other spaces rely on possibly non-live maps to get the sizes for
+  // non-live objects.
+  SweepSpace(Heap::old_pointer_space(), &DeallocateOldPointerBlock);
+  SweepSpace(Heap::old_data_space(), &DeallocateOldDataBlock);
+  SweepSpace(Heap::code_space(), &DeallocateCodeBlock);
+  SweepSpace(Heap::new_space());
+  SweepSpace(Heap::map_space(), &DeallocateMapBlock);
+}
+
+
+// Iterate the live objects in a range of addresses (eg, a page or a
+// semispace).  The live regions of the range have been linked into a list.
+// The first live region is [first_live_start, first_live_end), and the last
+// address in the range is top.  The callback function is used to get the
+// size of each live object.
+int MarkCompactCollector::IterateLiveObjectsInRange(
+    Address start,
+    Address end,
+    HeapObjectCallback size_func) {
+  int live_objects = 0;
+  Address current = start;
+  while (current < end) {
+    uint32_t encoded_map = Memory::uint32_at(current);
+    if (encoded_map == kSingleFreeEncoding) {
+      current += kPointerSize;
+    } else if (encoded_map == kMultiFreeEncoding) {
+      current += Memory::int_at(current + kIntSize);
+    } else {
+      live_objects++;
+      current += size_func(HeapObject::FromAddress(current));
+    }
+  }
+  return live_objects;
+}
+
+
+int MarkCompactCollector::IterateLiveObjects(NewSpace* space,
+                                             HeapObjectCallback size_f) {
+  ASSERT(MARK_LIVE_OBJECTS < state_ && state_ <= RELOCATE_OBJECTS);
+  return IterateLiveObjectsInRange(space->bottom(), space->top(), size_f);
+}
+
+
+int MarkCompactCollector::IterateLiveObjects(PagedSpace* space,
+                                             HeapObjectCallback size_f) {
+  ASSERT(MARK_LIVE_OBJECTS < state_ && state_ <= RELOCATE_OBJECTS);
+  int total = 0;
+  PageIterator it(space, PageIterator::PAGES_IN_USE);
+  while (it.has_next()) {
+    Page* p = it.next();
+    total += IterateLiveObjectsInRange(p->ObjectAreaStart(),
+                                       p->AllocationTop(),
+                                       size_f);
+  }
+  return total;
+}
+
+
+// -------------------------------------------------------------------------
+// Phase 3: Update pointers
+
+// Helper class for updating pointers in HeapObjects.
+class UpdatingVisitor: public ObjectVisitor {
+ public:
+  void VisitPointer(Object** p) {
+    UpdatePointer(p);
+  }
+
+  void VisitPointers(Object** start, Object** end) {
+    // Mark all HeapObject pointers in [start, end)
+    for (Object** p = start; p < end; p++) UpdatePointer(p);
+  }
+
+ private:
+  void UpdatePointer(Object** p) {
+    if (!(*p)->IsHeapObject()) return;
+
+    HeapObject* obj = HeapObject::cast(*p);
+    Address old_addr = obj->address();
+    Address new_addr;
+    ASSERT(!Heap::InFromSpace(obj));
+
+    if (Heap::new_space()->Contains(obj)) {
+      Address f_addr = Heap::new_space()->FromSpaceLow() +
+                       Heap::new_space()->ToSpaceOffsetForAddress(old_addr);
+      new_addr = Memory::Address_at(f_addr);
+
+#ifdef DEBUG
+      ASSERT(Heap::old_pointer_space()->Contains(new_addr) ||
+             Heap::old_data_space()->Contains(new_addr) ||
+             Heap::code_space()->Contains(new_addr) ||
+             Heap::new_space()->FromSpaceContains(new_addr));
+
+      if (Heap::new_space()->FromSpaceContains(new_addr)) {
+        ASSERT(Heap::new_space()->FromSpaceOffsetForAddress(new_addr) <=
+               Heap::new_space()->ToSpaceOffsetForAddress(old_addr));
+      }
+#endif
+
+    } else if (Heap::lo_space()->Contains(obj)) {
+      // Don't move objects in the large object space.
+      return;
+
+    } else {
+      ASSERT(Heap::old_pointer_space()->Contains(obj) ||
+             Heap::old_data_space()->Contains(obj) ||
+             Heap::code_space()->Contains(obj) ||
+             Heap::map_space()->Contains(obj));
+
+      new_addr = MarkCompactCollector::GetForwardingAddressInOldSpace(obj);
+      ASSERT(Heap::old_pointer_space()->Contains(new_addr) ||
+             Heap::old_data_space()->Contains(new_addr) ||
+             Heap::code_space()->Contains(new_addr) ||
+             Heap::map_space()->Contains(new_addr));
+
+#ifdef DEBUG
+      if (Heap::old_pointer_space()->Contains(obj)) {
+        ASSERT(Heap::old_pointer_space()->MCSpaceOffsetForAddress(new_addr) <=
+               Heap::old_pointer_space()->MCSpaceOffsetForAddress(old_addr));
+      } else if (Heap::old_data_space()->Contains(obj)) {
+        ASSERT(Heap::old_data_space()->MCSpaceOffsetForAddress(new_addr) <=
+               Heap::old_data_space()->MCSpaceOffsetForAddress(old_addr));
+      } else if (Heap::code_space()->Contains(obj)) {
+        ASSERT(Heap::code_space()->MCSpaceOffsetForAddress(new_addr) <=
+               Heap::code_space()->MCSpaceOffsetForAddress(old_addr));
+      } else {
+        ASSERT(Heap::map_space()->MCSpaceOffsetForAddress(new_addr) <=
+               Heap::map_space()->MCSpaceOffsetForAddress(old_addr));
+      }
+#endif
+    }
+
+    *p = HeapObject::FromAddress(new_addr);
+
+#ifdef DEBUG
+    if (FLAG_gc_verbose) {
+      PrintF("update %p : %p -> %p\n",
+             reinterpret_cast<Address>(p), old_addr, new_addr);
+    }
+#endif
+  }
+};
+
+
+void MarkCompactCollector::UpdatePointers() {
+#ifdef DEBUG
+  ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES);
+  state_ = UPDATE_POINTERS;
+#endif
+  UpdatingVisitor updating_visitor;
+  Heap::IterateRoots(&updating_visitor);
+  GlobalHandles::IterateWeakRoots(&updating_visitor);
+
+  int live_maps = IterateLiveObjects(Heap::map_space(),
+                                     &UpdatePointersInOldObject);
+  int live_pointer_olds = IterateLiveObjects(Heap::old_pointer_space(),
+                                             &UpdatePointersInOldObject);
+  int live_data_olds = IterateLiveObjects(Heap::old_data_space(),
+                                          &UpdatePointersInOldObject);
+  int live_codes = IterateLiveObjects(Heap::code_space(),
+                                      &UpdatePointersInOldObject);
+  int live_news = IterateLiveObjects(Heap::new_space(),
+                                     &UpdatePointersInNewObject);
+
+  // Large objects do not move, the map word can be updated directly.
+  LargeObjectIterator it(Heap::lo_space());
+  while (it.has_next()) UpdatePointersInNewObject(it.next());
+
+  USE(live_maps);
+  USE(live_pointer_olds);
+  USE(live_data_olds);
+  USE(live_codes);
+  USE(live_news);
+
+#ifdef DEBUG
+  ASSERT(live_maps == live_map_objects_);
+  ASSERT(live_data_olds == live_old_data_objects_);
+  ASSERT(live_pointer_olds == live_old_pointer_objects_);
+  ASSERT(live_codes == live_code_objects_);
+  ASSERT(live_news == live_young_objects_);
+#endif
+}
+
+
+int MarkCompactCollector::UpdatePointersInNewObject(HeapObject* obj) {
+  // Keep old map pointers
+  Map* old_map = obj->map();
+  ASSERT(old_map->IsHeapObject());
+
+  Address forwarded = GetForwardingAddressInOldSpace(old_map);
+
+  ASSERT(Heap::map_space()->Contains(old_map));
+  ASSERT(Heap::map_space()->Contains(forwarded));
+#ifdef DEBUG
+  if (FLAG_gc_verbose) {
+    PrintF("update %p : %p -> %p\n", obj->address(), old_map->address(),
+           forwarded);
+  }
+#endif
+  // Update the map pointer.
+  obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(forwarded)));
+
+  // We have to compute the object size relying on the old map because
+  // map objects are not relocated yet.
+  int obj_size = obj->SizeFromMap(old_map);
+
+  // Update pointers in the object body.
+  UpdatingVisitor updating_visitor;
+  obj->IterateBody(old_map->instance_type(), obj_size, &updating_visitor);
+  return obj_size;
+}
+
+
+int MarkCompactCollector::UpdatePointersInOldObject(HeapObject* obj) {
+  // Decode the map pointer.
+  MapWord encoding = obj->map_word();
+  Address map_addr = encoding.DecodeMapAddress(Heap::map_space());
+  ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr)));
+
+  // At this point, the first word of map_addr is also encoded, cannot
+  // cast it to Map* using Map::cast.
+  Map* map = reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr));
+  int obj_size = obj->SizeFromMap(map);
+  InstanceType type = map->instance_type();
+
+  // Update map pointer.
+  Address new_map_addr = GetForwardingAddressInOldSpace(map);
+  int offset = encoding.DecodeOffset();
+  obj->set_map_word(MapWord::EncodeAddress(new_map_addr, offset));
+
+#ifdef DEBUG
+  if (FLAG_gc_verbose) {
+    PrintF("update %p : %p -> %p\n", obj->address(),
+           map_addr, new_map_addr);
+  }
+#endif
+
+  // Update pointers in the object body.
+  UpdatingVisitor updating_visitor;
+  obj->IterateBody(type, obj_size, &updating_visitor);
+  return obj_size;
+}
+
+
+Address MarkCompactCollector::GetForwardingAddressInOldSpace(HeapObject* obj) {
+  // Object should either in old or map space.
+  MapWord encoding = obj->map_word();
+
+  // Offset to the first live object's forwarding address.
+  int offset = encoding.DecodeOffset();
+  Address obj_addr = obj->address();
+
+  // Find the first live object's forwarding address.
+  Page* p = Page::FromAddress(obj_addr);
+  Address first_forwarded = p->mc_first_forwarded;
+
+  // Page start address of forwarded address.
+  Page* forwarded_page = Page::FromAddress(first_forwarded);
+  int forwarded_offset = forwarded_page->Offset(first_forwarded);
+
+  // Find end of allocation of in the page of first_forwarded.
+  Address mc_top = forwarded_page->mc_relocation_top;
+  int mc_top_offset = forwarded_page->Offset(mc_top);
+
+  // Check if current object's forward pointer is in the same page
+  // as the first live object's forwarding pointer
+  if (forwarded_offset + offset < mc_top_offset) {
+    // In the same page.
+    return first_forwarded + offset;
+  }
+
+  // Must be in the next page, NOTE: this may cross chunks.
+  Page* next_page = forwarded_page->next_page();
+  ASSERT(next_page->is_valid());
+
+  offset -= (mc_top_offset - forwarded_offset);
+  offset += Page::kObjectStartOffset;
+
+  ASSERT_PAGE_OFFSET(offset);
+  ASSERT(next_page->OffsetToAddress(offset) < next_page->mc_relocation_top);
+
+  return next_page->OffsetToAddress(offset);
+}
+
+
+// -------------------------------------------------------------------------
+// Phase 4: Relocate objects
+
+void MarkCompactCollector::RelocateObjects() {
+#ifdef DEBUG
+  ASSERT(state_ == UPDATE_POINTERS);
+  state_ = RELOCATE_OBJECTS;
+#endif
+  // Relocates objects, always relocate map objects first. Relocating
+  // objects in other space relies on map objects to get object size.
+  int live_maps = IterateLiveObjects(Heap::map_space(), &RelocateMapObject);
+  int live_pointer_olds = IterateLiveObjects(Heap::old_pointer_space(),
+                                             &RelocateOldPointerObject);
+  int live_data_olds = IterateLiveObjects(Heap::old_data_space(),
+                                          &RelocateOldDataObject);
+  int live_codes = IterateLiveObjects(Heap::code_space(), &RelocateCodeObject);
+  int live_news = IterateLiveObjects(Heap::new_space(), &RelocateNewObject);
+
+  USE(live_maps);
+  USE(live_data_olds);
+  USE(live_pointer_olds);
+  USE(live_codes);
+  USE(live_news);
+#ifdef DEBUG
+  ASSERT(live_maps == live_map_objects_);
+  ASSERT(live_data_olds == live_old_data_objects_);
+  ASSERT(live_pointer_olds == live_old_pointer_objects_);
+  ASSERT(live_codes == live_code_objects_);
+  ASSERT(live_news == live_young_objects_);
+#endif
+
+  // Notify code object in LO to convert IC target to address
+  // This must happen after lo_space_->Compact
+  LargeObjectIterator it(Heap::lo_space());
+  while (it.has_next()) { ConvertCodeICTargetToAddress(it.next()); }
+
+  // Flips from and to spaces
+  Heap::new_space()->Flip();
+
+  // Sets age_mark to bottom in to space
+  Address mark = Heap::new_space()->bottom();
+  Heap::new_space()->set_age_mark(mark);
+
+  Heap::new_space()->MCCommitRelocationInfo();
+#ifdef DEBUG
+  // It is safe to write to the remembered sets as remembered sets on a
+  // page-by-page basis after committing the m-c forwarding pointer.
+  Page::set_rset_state(Page::IN_USE);
+#endif
+  PagedSpaces spaces;
+  while (PagedSpace* space = spaces.next()) space->MCCommitRelocationInfo();
+}
+
+
+int MarkCompactCollector::ConvertCodeICTargetToAddress(HeapObject* obj) {
+  if (obj->IsCode()) {
+    Code::cast(obj)->ConvertICTargetsFromObjectToAddress();
+  }
+  return obj->Size();
+}
+
+
+int MarkCompactCollector::RelocateMapObject(HeapObject* obj) {
+  // decode map pointer (forwarded address)
+  MapWord encoding = obj->map_word();
+  Address map_addr = encoding.DecodeMapAddress(Heap::map_space());
+  ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr)));
+
+  // Get forwarding address before resetting map pointer
+  Address new_addr = GetForwardingAddressInOldSpace(obj);
+
+  // recover map pointer
+  obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr)));
+
+  // The meta map object may not be copied yet.
+  Address old_addr = obj->address();
+
+  if (new_addr != old_addr) {
+    memmove(new_addr, old_addr, Map::kSize);  // copy contents
+  }
+
+#ifdef DEBUG
+  if (FLAG_gc_verbose) {
+    PrintF("relocate %p -> %p\n", old_addr, new_addr);
+  }
+#endif
+
+  return Map::kSize;
+}
+
+
+static inline int RelocateOldObject(HeapObject* obj,
+                                    OldSpace* space,
+                                    Address new_addr,
+                                    Address map_addr) {
+  // recover map pointer
+  obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr)));
+
+  // This is a non-map object, it relies on the assumption that the Map space
+  // is compacted before the Old space (see RelocateObjects).
+  int obj_size = obj->Size();
+  ASSERT_OBJECT_SIZE(obj_size);
+
+  ASSERT(space->MCSpaceOffsetForAddress(new_addr) <=
+         space->MCSpaceOffsetForAddress(obj->address()));
+
+  space->MCAdjustRelocationEnd(new_addr, obj_size);
+
+#ifdef DEBUG
+  if (FLAG_gc_verbose) {
+    PrintF("relocate %p -> %p\n", obj->address(), new_addr);
+  }
+#endif
+
+  return obj_size;
+}
+
+
+int MarkCompactCollector::RelocateOldNonCodeObject(HeapObject* obj,
+                                                   OldSpace* space) {
+  // decode map pointer (forwarded address)
+  MapWord encoding = obj->map_word();
+  Address map_addr = encoding.DecodeMapAddress(Heap::map_space());
+  ASSERT(Heap::map_space()->Contains(map_addr));
+
+  // Get forwarding address before resetting map pointer
+  Address new_addr = GetForwardingAddressInOldSpace(obj);
+
+  int obj_size = RelocateOldObject(obj, space, new_addr, map_addr);
+
+  Address old_addr = obj->address();
+
+  if (new_addr != old_addr) {
+    memmove(new_addr, old_addr, obj_size);  // copy contents
+  }
+
+  ASSERT(!HeapObject::FromAddress(new_addr)->IsCode());
+
+  return obj_size;
+}
+
+
+int MarkCompactCollector::RelocateOldPointerObject(HeapObject* obj) {
+  return RelocateOldNonCodeObject(obj, Heap::old_pointer_space());
+}
+
+
+int MarkCompactCollector::RelocateOldDataObject(HeapObject* obj) {
+  return RelocateOldNonCodeObject(obj, Heap::old_data_space());
+}
+
+
+int MarkCompactCollector::RelocateCodeObject(HeapObject* obj) {
+  // decode map pointer (forwarded address)
+  MapWord encoding = obj->map_word();
+  Address map_addr = encoding.DecodeMapAddress(Heap::map_space());
+  ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr)));
+
+  // Get forwarding address before resetting map pointer
+  Address new_addr = GetForwardingAddressInOldSpace(obj);
+
+  int obj_size = RelocateOldObject(obj, Heap::code_space(), new_addr, map_addr);
+
+  // convert inline cache target to address using old address
+  if (obj->IsCode()) {
+    // convert target to address first related to old_address
+    Code::cast(obj)->ConvertICTargetsFromObjectToAddress();
+  }
+
+  Address old_addr = obj->address();
+
+  if (new_addr != old_addr) {
+    memmove(new_addr, old_addr, obj_size);  // copy contents
+  }
+
+  HeapObject* copied_to = HeapObject::FromAddress(new_addr);
+  if (copied_to->IsCode()) {
+    // may also update inline cache target.
+    Code::cast(copied_to)->Relocate(new_addr - old_addr);
+    // Notify the logger that compiled code has moved.
+    LOG(CodeMoveEvent(old_addr, new_addr));
+  }
+
+  return obj_size;
+}
+
+
+int MarkCompactCollector::RelocateNewObject(HeapObject* obj) {
+  int obj_size = obj->Size();
+
+  // Get forwarding address
+  Address old_addr = obj->address();
+  int offset = Heap::new_space()->ToSpaceOffsetForAddress(old_addr);
+
+  Address new_addr =
+    Memory::Address_at(Heap::new_space()->FromSpaceLow() + offset);
+
+  if (Heap::new_space()->FromSpaceContains(new_addr)) {
+    ASSERT(Heap::new_space()->FromSpaceOffsetForAddress(new_addr) <=
+           Heap::new_space()->ToSpaceOffsetForAddress(old_addr));
+  } else {
+    OldSpace* target_space = Heap::TargetSpace(obj);
+    ASSERT(target_space == Heap::old_pointer_space() ||
+           target_space == Heap::old_data_space());
+    target_space->MCAdjustRelocationEnd(new_addr, obj_size);
+  }
+
+  // New and old addresses cannot overlap.
+  memcpy(reinterpret_cast<void*>(new_addr),
+         reinterpret_cast<void*>(old_addr),
+         obj_size);
+
+#ifdef DEBUG
+  if (FLAG_gc_verbose) {
+    PrintF("relocate %p -> %p\n", old_addr, new_addr);
+  }
+#endif
+
+  return obj_size;
+}
+
+
+// -------------------------------------------------------------------------
+// Phase 5: rebuild remembered sets
+
+void MarkCompactCollector::RebuildRSets() {
+#ifdef DEBUG
+  ASSERT(state_ == RELOCATE_OBJECTS);
+  state_ = REBUILD_RSETS;
+#endif
+  Heap::RebuildRSets();
+}
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/mark-compact.h b/deps/v8/src/mark-compact.h
new file mode 100644
index 0000000..9a92ade
--- /dev/null
+++ b/deps/v8/src/mark-compact.h
@@ -0,0 +1,407 @@
+// 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_MARK_COMPACT_H_
+#define V8_MARK_COMPACT_H_
+
+namespace v8 { namespace internal {
+
+// Callback function, returns whether an object is alive. The heap size
+// of the object is returned in size. It optionally updates the offset
+// to the first live object in the page (only used for old and map objects).
+typedef bool (*IsAliveFunction)(HeapObject* obj, int* size, int* offset);
+
+// Callback function for non-live blocks in the old generation.
+typedef void (*DeallocateFunction)(Address start, int size_in_bytes);
+
+
+// Forward declarations.
+class RootMarkingVisitor;
+class MarkingVisitor;
+
+
+// -------------------------------------------------------------------------
+// Mark-Compact collector
+//
+// All methods are static.
+
+class MarkCompactCollector: public AllStatic {
+ public:
+  // Type of functions to compute forwarding addresses of objects in
+  // compacted spaces.  Given an object and its size, return a (non-failure)
+  // Object* that will be the object after forwarding.  There is a separate
+  // allocation function for each (compactable) space based on the location
+  // of the object before compaction.
+  typedef Object* (*AllocationFunction)(HeapObject* object, int object_size);
+
+  // Type of functions to encode the forwarding address for an object.
+  // Given the object, its size, and the new (non-failure) object it will be
+  // forwarded to, encode the forwarding address.  For paged spaces, the
+  // 'offset' input/output parameter contains the offset of the forwarded
+  // object from the forwarding address of the previous live object in the
+  // page as input, and is updated to contain the offset to be used for the
+  // next live object in the same page.  For spaces using a different
+  // encoding (ie, contiguous spaces), the offset parameter is ignored.
+  typedef void (*EncodingFunction)(HeapObject* old_object,
+                                   int object_size,
+                                   Object* new_object,
+                                   int* offset);
+
+  // Type of functions to process non-live objects.
+  typedef void (*ProcessNonLiveFunction)(HeapObject* object);
+
+  // Prepares for GC by resetting relocation info in old and map spaces and
+  // choosing spaces to compact.
+  static void Prepare(GCTracer* tracer);
+
+  // Performs a global garbage collection.
+  static void CollectGarbage();
+
+  // True if the last full GC performed heap compaction.
+  static bool HasCompacted() { return compacting_collection_; }
+
+  // True after the Prepare phase if the compaction is taking place.
+  static bool IsCompacting() { return compacting_collection_; }
+
+  // The count of the number of objects left marked at the end of the last
+  // completed full GC (expected to be zero).
+  static int previous_marked_count() { return previous_marked_count_; }
+
+  // During a full GC, there is a stack-allocated GCTracer that is used for
+  // bookkeeping information.  Return a pointer to that tracer.
+  static GCTracer* tracer() { return tracer_; }
+
+#ifdef DEBUG
+  // Checks whether performing mark-compact collection.
+  static bool in_use() { return state_ > PREPARE_GC; }
+#endif
+
+ private:
+#ifdef DEBUG
+  enum CollectorState {
+    IDLE,
+    PREPARE_GC,
+    MARK_LIVE_OBJECTS,
+    SWEEP_SPACES,
+    ENCODE_FORWARDING_ADDRESSES,
+    UPDATE_POINTERS,
+    RELOCATE_OBJECTS,
+    REBUILD_RSETS
+  };
+
+  // The current stage of the collector.
+  static CollectorState state_;
+#endif
+  // Global flag indicating whether spaces were compacted on the last GC.
+  static bool compacting_collection_;
+
+  // The number of objects left marked at the end of the last completed full
+  // GC (expected to be zero).
+  static int previous_marked_count_;
+
+  // A pointer to the current stack-allocated GC tracer object during a full
+  // collection (NULL before and after).
+  static GCTracer* tracer_;
+
+  // Finishes GC, performs heap verification if enabled.
+  static void Finish();
+
+  // -----------------------------------------------------------------------
+  // Phase 1: Marking live objects.
+  //
+  //  Before: The heap has been prepared for garbage collection by
+  //          MarkCompactCollector::Prepare() and is otherwise in its
+  //          normal state.
+  //
+  //   After: Live objects are marked and non-live objects are unmarked.
+
+
+  friend class RootMarkingVisitor;
+  friend class MarkingVisitor;
+
+  // Marking operations for objects reachable from roots.
+  static void MarkLiveObjects();
+
+  static void MarkUnmarkedObject(HeapObject* obj);
+
+  static inline void MarkObject(HeapObject* obj) {
+    if (!obj->IsMarked()) MarkUnmarkedObject(obj);
+  }
+
+  static inline void SetMark(HeapObject* obj) {
+    tracer_->increment_marked_count();
+#ifdef DEBUG
+    UpdateLiveObjectCount(obj);
+#endif
+    obj->SetMark();
+  }
+
+  // Creates back pointers for all map transitions, stores them in
+  // the prototype field.  The original prototype pointers are restored
+  // in ClearNonLiveTransitions().  All JSObject maps
+  // connected by map transitions have the same prototype object, which
+  // is why we can use this field temporarily for back pointers.
+  static void CreateBackPointers();
+
+  // Mark a Map and its DescriptorArray together, skipping transitions.
+  static void MarkMapContents(Map* map);
+  static void MarkDescriptorArray(DescriptorArray* descriptors);
+
+  // Mark the heap roots and all objects reachable from them.
+  static void ProcessRoots(RootMarkingVisitor* visitor);
+
+  // Mark objects in object groups that have at least one object in the
+  // group marked.
+  static void MarkObjectGroups();
+
+  // Mark all objects in an object group with at least one marked
+  // object, then all objects reachable from marked objects in object
+  // groups, and repeat.
+  static void ProcessObjectGroups(MarkingVisitor* visitor);
+
+  // Mark objects reachable (transitively) from objects in the marking stack
+  // or overflowed in the heap.
+  static void ProcessMarkingStack(MarkingVisitor* visitor);
+
+  // Mark objects reachable (transitively) from objects in the marking
+  // stack.  This function empties the marking stack, but may leave
+  // overflowed objects in the heap, in which case the marking stack's
+  // overflow flag will be set.
+  static void EmptyMarkingStack(MarkingVisitor* visitor);
+
+  // Refill the marking stack with overflowed objects from the heap.  This
+  // function either leaves the marking stack full or clears the overflow
+  // flag on the marking stack.
+  static void RefillMarkingStack();
+
+  // Callback function for telling whether the object *p must be marked.
+  static bool MustBeMarked(Object** p);
+
+#ifdef DEBUG
+  static void UpdateLiveObjectCount(HeapObject* obj);
+#endif
+
+  // We sweep the large object space in the same way whether we are
+  // compacting or not, because the large object space is never compacted.
+  static void SweepLargeObjectSpace();
+
+  // Test whether a (possibly marked) object is a Map.
+  static inline bool SafeIsMap(HeapObject* object);
+
+  // Map transitions from a live map to a dead map must be killed.
+  // We replace them with a null descriptor, with the same key.
+  static void ClearNonLiveTransitions();
+
+  // -----------------------------------------------------------------------
+  // Phase 2: Sweeping to clear mark bits and free non-live objects for
+  // a non-compacting collection, or else computing and encoding
+  // forwarding addresses for a compacting collection.
+  //
+  //  Before: Live objects are marked and non-live objects are unmarked.
+  //
+  //   After: (Non-compacting collection.)  Live objects are unmarked,
+  //          non-live regions have been added to their space's free
+  //          list.
+  //
+  //   After: (Compacting collection.)  The forwarding address of live
+  //          objects in the paged spaces is encoded in their map word
+  //          along with their (non-forwarded) map pointer.
+  //
+  //          The forwarding address of live objects in the new space is
+  //          written to their map word's offset in the inactive
+  //          semispace.
+  //
+  //          Bookkeeping data is written to the remembered-set are of
+  //          eached paged-space page that contains live objects after
+  //          compaction:
+  //
+  //          The 3rd word of the page (first word of the remembered
+  //          set) contains the relocation top address, the address of
+  //          the first word after the end of the last live object in
+  //          the page after compaction.
+  //
+  //          The 4th word contains the zero-based index of the page in
+  //          its space.  This word is only used for map space pages, in
+  //          order to encode the map addresses in 21 bits to free 11
+  //          bits per map word for the forwarding address.
+  //
+  //          The 5th word contains the (nonencoded) forwarding address
+  //          of the first live object in the page.
+  //
+  //          In both the new space and the paged spaces, a linked list
+  //          of live regions is constructructed (linked through
+  //          pointers in the non-live region immediately following each
+  //          live region) to speed further passes of the collector.
+
+  // Encodes forwarding addresses of objects in compactable parts of the
+  // heap.
+  static void EncodeForwardingAddresses();
+
+  // Encodes the forwarding addresses of objects in new space.
+  static void EncodeForwardingAddressesInNewSpace();
+
+  // Function template to encode the forwarding addresses of objects in
+  // paged spaces, parameterized by allocation and non-live processing
+  // functions.
+  template<AllocationFunction Alloc, ProcessNonLiveFunction ProcessNonLive>
+  static void EncodeForwardingAddressesInPagedSpace(PagedSpace* space);
+
+  // Iterates live objects in a space, passes live objects
+  // to a callback function which returns the heap size of the object.
+  // Returns the number of live objects iterated.
+  static int IterateLiveObjects(NewSpace* space, HeapObjectCallback size_f);
+  static int IterateLiveObjects(PagedSpace* space, HeapObjectCallback size_f);
+
+  // Iterates the live objects between a range of addresses, returning the
+  // number of live objects.
+  static int IterateLiveObjectsInRange(Address start, Address end,
+                                       HeapObjectCallback size_func);
+
+  // Callback functions for deallocating non-live blocks in the old
+  // generation.
+  static void DeallocateOldPointerBlock(Address start, int size_in_bytes);
+  static void DeallocateOldDataBlock(Address start, int size_in_bytes);
+  static void DeallocateCodeBlock(Address start, int size_in_bytes);
+  static void DeallocateMapBlock(Address start, int size_in_bytes);
+
+  // If we are not compacting the heap, we simply sweep the spaces except
+  // for the large object space, clearing mark bits and adding unmarked
+  // regions to each space's free list.
+  static void SweepSpaces();
+
+  // -----------------------------------------------------------------------
+  // Phase 3: Updating pointers in live objects.
+  //
+  //  Before: Same as after phase 2 (compacting collection).
+  //
+  //   After: All pointers in live objects, including encoded map
+  //          pointers, are updated to point to their target's new
+  //          location.  The remembered set area of each paged-space
+  //          page containing live objects still contains bookkeeping
+  //          information.
+
+  friend class UpdatingVisitor;  // helper for updating visited objects
+
+  // Updates pointers in all spaces.
+  static void UpdatePointers();
+
+  // Updates pointers in an object in new space.
+  // Returns the heap size of the object.
+  static int UpdatePointersInNewObject(HeapObject* obj);
+
+  // Updates pointers in an object in old spaces.
+  // Returns the heap size of the object.
+  static int UpdatePointersInOldObject(HeapObject* obj);
+
+  // Calculates the forwarding address of an object in an old space.
+  static Address GetForwardingAddressInOldSpace(HeapObject* obj);
+
+  // -----------------------------------------------------------------------
+  // Phase 4: Relocating objects.
+  //
+  //  Before: Pointers to live objects are updated to point to their
+  //          target's new location.  The remembered set area of each
+  //          paged-space page containing live objects still contains
+  //          bookkeeping information.
+  //
+  //   After: Objects have been moved to their new addresses. The
+  //          remembered set area of each paged-space page containing
+  //          live objects still contains bookkeeping information.
+
+  // Relocates objects in all spaces.
+  static void RelocateObjects();
+
+  // Converts a code object's inline target to addresses, convention from
+  // address to target happens in the marking phase.
+  static int ConvertCodeICTargetToAddress(HeapObject* obj);
+
+  // Relocate a map object.
+  static int RelocateMapObject(HeapObject* obj);
+
+  // Relocates an old object.
+  static int RelocateOldPointerObject(HeapObject* obj);
+  static int RelocateOldDataObject(HeapObject* obj);
+
+  // Helper function.
+  static inline int RelocateOldNonCodeObject(HeapObject* obj, OldSpace* space);
+
+  // Relocates an object in the code space.
+  static int RelocateCodeObject(HeapObject* obj);
+
+  // Copy a new object.
+  static int RelocateNewObject(HeapObject* obj);
+
+  // -----------------------------------------------------------------------
+  // Phase 5: Rebuilding remembered sets.
+  //
+  //  Before: The heap is in a normal state except that remembered sets
+  //          in the paged spaces are not correct.
+  //
+  //   After: The heap is in a normal state.
+
+  // Rebuild remembered set in old and map spaces.
+  static void RebuildRSets();
+
+#ifdef DEBUG
+  // -----------------------------------------------------------------------
+  // Debugging variables, functions and classes
+  // Counters used for debugging the marking phase of mark-compact or
+  // mark-sweep collection.
+
+  // Number of live objects in Heap::to_space_.
+  static int live_young_objects_;
+
+  // Number of live objects in Heap::old_pointer_space_.
+  static int live_old_pointer_objects_;
+
+  // Number of live objects in Heap::old_data_space_.
+  static int live_old_data_objects_;
+
+  // Number of live objects in Heap::code_space_.
+  static int live_code_objects_;
+
+  // Number of live objects in Heap::map_space_.
+  static int live_map_objects_;
+
+  // Number of live objects in Heap::lo_space_.
+  static int live_lo_objects_;
+
+  // Number of live bytes in this collection.
+  static int live_bytes_;
+
+  friend class MarkObjectVisitor;
+  static void VisitObject(HeapObject* obj);
+
+  friend class UnmarkObjectVisitor;
+  static void UnmarkObject(HeapObject* obj);
+#endif
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_MARK_COMPACT_H_
diff --git a/deps/v8/src/math.js b/deps/v8/src/math.js
new file mode 100644
index 0000000..5b7c396
--- /dev/null
+++ b/deps/v8/src/math.js
@@ -0,0 +1,190 @@
+// 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.
+
+
+// Keep reference to original values of some global properties.  This
+// has the added benefit that the code in this file is isolated from
+// changes to these properties.
+const $Infinity = global.Infinity;
+const $floor = MathFloor;
+const $random = MathRandom;
+const $abs = MathAbs;
+
+// Instance class name can only be set on functions. That is the only
+// purpose for MathConstructor.
+function MathConstructor() {}
+%FunctionSetInstanceClassName(MathConstructor, 'Math');
+const $Math = new MathConstructor();
+$Math.__proto__ = global.Object.prototype;
+%SetProperty(global, "Math", $Math, DONT_ENUM);
+
+// ECMA 262 - 15.8.2.1
+function MathAbs(x) {
+  if (%_IsSmi(x)) {
+    return x >= 0 ? x : -x;
+  } else {
+    return %Math_abs(ToNumber(x));
+  }
+}
+
+// ECMA 262 - 15.8.2.2
+function MathAcos(x) { return %Math_acos(ToNumber(x)); }
+
+// ECMA 262 - 15.8.2.3
+function MathAsin(x) { return %Math_asin(ToNumber(x)); }
+
+// ECMA 262 - 15.8.2.4
+function MathAtan(x) { return %Math_atan(ToNumber(x)); }
+
+// ECMA 262 - 15.8.2.5
+function MathAtan2(x, y) { return %Math_atan2(ToNumber(x), ToNumber(y)); }
+
+// ECMA 262 - 15.8.2.6
+function MathCeil(x) { return %Math_ceil(ToNumber(x)); }
+
+// ECMA 262 - 15.8.2.7
+function MathCos(x) { return %Math_cos(ToNumber(x)); }
+
+// ECMA 262 - 15.8.2.8
+function MathExp(x) { return %Math_exp(ToNumber(x)); }
+
+// ECMA 262 - 15.8.2.9
+function MathFloor(x) { return %Math_floor(ToNumber(x)); }
+
+// ECMA 262 - 15.8.2.10
+function MathLog(x) { return %Math_log(ToNumber(x)); }
+
+// ECMA 262 - 15.8.2.11
+function MathMax(arg1, arg2) {  // length == 2
+  var r = -$Infinity;
+  for (var i = %_ArgumentsLength() - 1; i >= 0; --i) {
+    var n = ToNumber(%_Arguments(i));
+    if (NUMBER_IS_NAN(n)) return n;
+    // Make sure +0 is consider greater than -0.
+    if (n > r || (n === 0 && r === 0 && (1 / n) > (1 / r))) r = n;
+  }
+  return r;
+}
+
+// ECMA 262 - 15.8.2.12
+function MathMin(arg1, arg2) {  // length == 2
+  var r = $Infinity;
+  for (var i = %_ArgumentsLength() - 1; i >= 0; --i) {
+    var n = ToNumber(%_Arguments(i));
+    if (NUMBER_IS_NAN(n)) return n;
+    // Make sure -0 is consider less than +0.
+    if (n < r || (n === 0 && r === 0 && (1 / n) < (1 / r))) r = n;
+  }
+  return r;
+}
+
+// ECMA 262 - 15.8.2.13
+function MathPow(x, y) { return %Math_pow(ToNumber(x), ToNumber(y)); }
+
+// ECMA 262 - 15.8.2.14
+function MathRandom() { return %Math_random(); }
+
+// ECMA 262 - 15.8.2.15
+function MathRound(x) { return %Math_round(ToNumber(x)); }
+
+// ECMA 262 - 15.8.2.16
+function MathSin(x) { return %Math_sin(ToNumber(x)); }
+
+// ECMA 262 - 15.8.2.17
+function MathSqrt(x) { return %Math_sqrt(ToNumber(x)); }
+
+// ECMA 262 - 15.8.2.18
+function MathTan(x) { return %Math_tan(ToNumber(x)); }
+
+
+// -------------------------------------------------------------------
+
+function SetupMath() {
+  // Setup math constants.
+  // ECMA-262, section 15.8.1.1.
+  %SetProperty($Math,
+               "E",
+               2.7182818284590452354,
+               DONT_ENUM |  DONT_DELETE | READ_ONLY);
+  // ECMA-262, section 15.8.1.2.
+  %SetProperty($Math,
+               "LN10",
+               2.302585092994046,
+               DONT_ENUM |  DONT_DELETE | READ_ONLY);
+  // ECMA-262, section 15.8.1.3.
+  %SetProperty($Math,
+               "LN2",
+               0.6931471805599453,
+               DONT_ENUM |  DONT_DELETE | READ_ONLY);
+  // ECMA-262, section 15.8.1.4.
+  %SetProperty($Math,
+               "LOG2E",
+               1.4426950408889634,
+               DONT_ENUM |  DONT_DELETE | READ_ONLY);
+  %SetProperty($Math,
+               "LOG10E",
+               0.43429448190325176,
+               DONT_ENUM |  DONT_DELETE | READ_ONLY);
+  %SetProperty($Math,
+               "PI",
+               3.1415926535897932,
+               DONT_ENUM |  DONT_DELETE | READ_ONLY);
+  %SetProperty($Math,
+               "SQRT1_2",
+               0.7071067811865476,
+               DONT_ENUM |  DONT_DELETE | READ_ONLY);
+  %SetProperty($Math,
+               "SQRT2",
+               1.4142135623730951,
+               DONT_ENUM |  DONT_DELETE | READ_ONLY);
+
+  // Setup non-enumerable functions of the Math object and
+  // set their names.
+  InstallFunctions($Math, DONT_ENUM, $Array(
+    "random", MathRandom,
+    "abs", MathAbs,
+    "acos", MathAcos,
+    "asin", MathAsin,
+    "atan", MathAtan,
+    "ceil", MathCeil,
+    "cos", MathCos,
+    "exp", MathExp,
+    "floor", MathFloor,
+    "log", MathLog,
+    "round", MathRound,
+    "sin", MathSin,
+    "sqrt", MathSqrt,
+    "tan", MathTan,
+    "atan2", MathAtan2,
+    "pow", MathPow,
+    "max", MathMax,
+    "min", MathMin
+  ));
+};
+
+
+SetupMath();
diff --git a/deps/v8/src/memory.h b/deps/v8/src/memory.h
new file mode 100644
index 0000000..2397bc6
--- /dev/null
+++ b/deps/v8/src/memory.h
@@ -0,0 +1,61 @@
+// 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_MEMORY_H_
+#define V8_MEMORY_H_
+
+namespace v8 { namespace internal {
+
+// Memory provides an interface to 'raw' memory. It encapsulates the casts
+// that typically are needed when incompatible pointer types are used.
+
+class Memory {
+ public:
+  static uint32_t& uint32_at(Address addr)  {
+    return *reinterpret_cast<uint32_t*>(addr);
+  }
+
+  static int32_t& int32_at(Address addr)  {
+    return *reinterpret_cast<int32_t*>(addr);
+  }
+
+  static int& int_at(Address addr)  {
+    return *reinterpret_cast<int*>(addr);
+  }
+
+  static Address& Address_at(Address addr)  {
+    return *reinterpret_cast<Address*>(addr);
+  }
+
+  static Object*& Object_at(Address addr)  {
+    return *reinterpret_cast<Object**>(addr);
+  }
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_MEMORY_H_
diff --git a/deps/v8/src/messages.cc b/deps/v8/src/messages.cc
new file mode 100644
index 0000000..ca0ce2a
--- /dev/null
+++ b/deps/v8/src/messages.cc
@@ -0,0 +1,178 @@
+
+// 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.
+
+#include "v8.h"
+
+#include "api.h"
+#include "execution.h"
+#include "spaces-inl.h"
+#include "top.h"
+
+namespace v8 { namespace internal {
+
+
+// If no message listeners have been registered this one is called
+// by default.
+void MessageHandler::DefaultMessageReport(const MessageLocation* loc,
+                                          Handle<Object> message_obj) {
+  SmartPointer<char> str = GetLocalizedMessage(message_obj);
+  if (loc == NULL) {
+    PrintF("%s\n", *str);
+  } else {
+    HandleScope scope;
+    Handle<Object> data(loc->script()->name());
+    SmartPointer<char> data_str;
+    if (data->IsString())
+      data_str = Handle<String>::cast(data)->ToCString(DISALLOW_NULLS);
+    PrintF("%s:%i: %s\n", *data_str ? *data_str : "<unknown>",
+           loc->start_pos(), *str);
+  }
+}
+
+
+void MessageHandler::ReportMessage(const char* msg) {
+  PrintF("%s\n", msg);
+}
+
+
+Handle<Object> MessageHandler::MakeMessageObject(
+    const char* type,
+    MessageLocation* loc,
+    Vector< Handle<Object> > args,
+    Handle<String> stack_trace) {
+  // Build error message object
+  v8::HandleScope scope;  // Instantiate a closeable HandleScope for EscapeFrom.
+  Handle<Object> type_str = Factory::LookupAsciiSymbol(type);
+  Handle<Object> array = Factory::NewJSArray(args.length());
+  for (int i = 0; i < args.length(); i++)
+    SetElement(Handle<JSArray>::cast(array), i, args[i]);
+
+  Handle<JSFunction> fun(Top::global_context()->make_message_fun());
+  int start, end;
+  Handle<Object> script;
+  if (loc) {
+    start = loc->start_pos();
+    end = loc->end_pos();
+    script = GetScriptWrapper(loc->script());
+  } else {
+    start = end = 0;
+    script = Factory::undefined_value();
+  }
+  Handle<Object> start_handle(Smi::FromInt(start));
+  Handle<Object> end_handle(Smi::FromInt(end));
+  Handle<Object> stack_trace_val = stack_trace.is_null()
+    ? Factory::undefined_value()
+    : Handle<Object>::cast(stack_trace);
+  const int argc = 6;
+  Object** argv[argc] = { type_str.location(),
+                          array.location(),
+                          start_handle.location(),
+                          end_handle.location(),
+                          script.location(),
+                          stack_trace_val.location() };
+
+  // Setup a catch handler to catch exceptions in creating the message. This
+  // handler is non-verbose to avoid calling MakeMessage recursively in case of
+  // an exception.
+  v8::TryCatch catcher;
+  catcher.SetVerbose(false);
+  catcher.SetCaptureMessage(false);
+
+  // Format the message.
+  bool caught_exception = false;
+  Handle<Object> message =
+      Execution::Call(fun, Factory::undefined_value(), argc, argv,
+                      &caught_exception);
+
+  // If creating the message (in JS code) resulted in an exception, we
+  // skip doing the callback. This usually only happens in case of
+  // stack overflow exceptions being thrown by the parser when the
+  // stack is almost full.
+  if (caught_exception) return Handle<Object>();
+
+  return message.EscapeFrom(&scope);
+}
+
+
+void MessageHandler::ReportMessage(MessageLocation* loc,
+                                   Handle<Object> message) {
+  v8::Local<v8::Message> api_message_obj = v8::Utils::MessageToLocal(message);
+
+  v8::NeanderArray global_listeners(Factory::message_listeners());
+  int global_length = global_listeners.length();
+  if (global_length == 0) {
+    DefaultMessageReport(loc, message);
+  } else {
+    for (int i = 0; i < global_length; i++) {
+      HandleScope scope;
+      if (global_listeners.get(i)->IsUndefined()) continue;
+      v8::NeanderObject listener(JSObject::cast(global_listeners.get(i)));
+      Handle<Proxy> callback_obj(Proxy::cast(listener.get(0)));
+      v8::MessageCallback callback =
+          FUNCTION_CAST<v8::MessageCallback>(callback_obj->proxy());
+      Handle<Object> callback_data(listener.get(1));
+      callback(api_message_obj, v8::Utils::ToLocal(callback_data));
+    }
+  }
+}
+
+
+Handle<String> MessageHandler::GetMessage(Handle<Object> data) {
+  Handle<String> fmt_str = Factory::LookupAsciiSymbol("FormatMessage");
+  Handle<JSFunction> fun =
+      Handle<JSFunction>(
+          JSFunction::cast(
+              Top::builtins()->GetProperty(*fmt_str)));
+  Object** argv[1] = { data.location() };
+
+  bool caught_exception;
+  Handle<Object> result =
+      Execution::TryCall(fun, Top::builtins(), 1, argv,
+                         &caught_exception);
+
+  if (caught_exception || !result->IsString()) {
+    return Factory::LookupAsciiSymbol("<error>");
+  }
+  Handle<String> result_string = Handle<String>::cast(result);
+  // A string that has been obtained from JS code in this way is
+  // likely to be a complicated ConsString of some sort.  We flatten it
+  // here to improve the efficiency of converting it to a C string and
+  // other operations that are likely to take place (see GetLocalizedMessage
+  // for example).
+  FlattenString(result_string);
+  return result_string;
+}
+
+
+SmartPointer<char> MessageHandler::GetLocalizedMessage(Handle<Object> data) {
+  HandleScope scope;
+  return GetMessage(data)->ToCString(DISALLOW_NULLS);
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/messages.h b/deps/v8/src/messages.h
new file mode 100644
index 0000000..1ff10aa
--- /dev/null
+++ b/deps/v8/src/messages.h
@@ -0,0 +1,110 @@
+// 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.
+
+// The infrastructure used for (localized) message reporting in V8.
+//
+// Note: there's a big unresolved issue about ownership of the data
+// structures used by this framework.
+
+#ifndef V8_MESSAGES_H_
+#define V8_MESSAGES_H_
+
+#include "handles-inl.h"
+
+// Forward declaration of MessageLocation.
+namespace v8 { namespace internal {
+class MessageLocation;
+} }  // namespace v8::internal
+
+
+class V8Message {
+ public:
+  V8Message(char* type,
+            v8::internal::Handle<v8::internal::JSArray> args,
+            const v8::internal::MessageLocation* loc) :
+      type_(type), args_(args), loc_(loc) { }
+  char* type() const { return type_; }
+  v8::internal::Handle<v8::internal::JSArray> args() const { return args_; }
+  const v8::internal::MessageLocation* loc() const { return loc_; }
+ private:
+  char* type_;
+  v8::internal::Handle<v8::internal::JSArray> const args_;
+  const v8::internal::MessageLocation* loc_;
+};
+
+
+namespace v8 { namespace internal {
+
+struct Language;
+class SourceInfo;
+
+class MessageLocation {
+ public:
+  MessageLocation(Handle<Script> script,
+                  int start_pos,
+                  int end_pos)
+      : script_(script),
+        start_pos_(start_pos),
+        end_pos_(end_pos) { }
+  MessageLocation() : start_pos_(-1), end_pos_(-1) { }
+
+  Handle<Script> script() const { return script_; }
+  int start_pos() const { return start_pos_; }
+  int end_pos() const { return end_pos_; }
+
+ private:
+  Handle<Script> script_;
+  int start_pos_;
+  int end_pos_;
+};
+
+
+// A message handler is a convenience interface for accessing the list
+// of message listeners registered in an environment
+class MessageHandler {
+ public:
+  // Report a message (w/o JS heap allocation).
+  static void ReportMessage(const char* msg);
+
+  // Returns a message object for the API to use.
+  static Handle<Object> MakeMessageObject(const char* type,
+                                          MessageLocation* loc,
+                                          Vector< Handle<Object> > args,
+                                          Handle<String> stack_trace);
+
+  // Report a formatted message (needs JS allocation).
+  static void ReportMessage(MessageLocation* loc, Handle<Object> message);
+
+  static void DefaultMessageReport(const MessageLocation* loc,
+                                   Handle<Object> message_obj);
+  static Handle<String> GetMessage(Handle<Object> data);
+  static SmartPointer<char> GetLocalizedMessage(Handle<Object> data);
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_MESSAGES_H_
diff --git a/deps/v8/src/messages.js b/deps/v8/src/messages.js
new file mode 100644
index 0000000..cd9a1e8
--- /dev/null
+++ b/deps/v8/src/messages.js
@@ -0,0 +1,686 @@
+// 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.
+
+
+// -------------------------------------------------------------------
+
+const kVowelSounds = {a: true, e: true, i: true, o: true, u: true, y: true};
+const kCapitalVowelSounds = {a: true, e: true, i: true, o: true, u: true,
+    h: true, f: true, l: true, m: true, n: true, r: true, s: true, x: true,
+    y: true};
+
+function GetInstanceName(cons) {
+  if (cons.length == 0) {
+    return "";
+  }
+  var first = cons.charAt(0).toLowerCase();
+  var mapping = kVowelSounds;
+  if (cons.length > 1 && (cons.charAt(0) != first)) {
+    // First char is upper case
+    var second = cons.charAt(1).toLowerCase();
+    // Second char is upper case
+    if (cons.charAt(1) != second)
+      mapping = kCapitalVowelSounds;
+  }
+  var s = mapping[first] ? "an " : "a ";
+  return s + cons;
+}
+
+
+const kMessages = {
+  // Error
+  cyclic_proto:                 "Cyclic __proto__ value",
+  // TypeError
+  unexpected_token:             "Unexpected token %0",
+  unexpected_token_number:      "Unexpected number",
+  unexpected_token_string:      "Unexpected string",
+  unexpected_token_identifier:  "Unexpected identifier",
+  unexpected_eos:               "Unexpected end of input",
+  expected_label:               "Expected label",
+  malformed_regexp:             "Invalid regular expression: /%0/: %1",
+  unterminated_regexp:          "Invalid regular expression: missing /",
+  pcre_error:                   "PCRE function %0, error code %1",
+  regexp_flags:                 "Cannot supply flags when constructing one RegExp from another",
+  invalid_lhs_in_assignment:    "Invalid left-hand side in assignment",
+  invalid_lhs_in_for_in:        "Invalid left-hand side in for-in",
+  invalid_lhs_in_postfix_op:    "Invalid left-hand side expression in postfix operation",
+  invalid_lhs_in_prefix_op:     "Invalid left-hand side expression in prefix operation",
+  multiple_defaults_in_switch:  "More than one default clause in switch statement",
+  newline_after_throw:          "Illegal newline after throw",
+  redeclaration:                "%0 '%1' has already been declared",
+  no_catch_or_finally:          "Missing catch or finally after try",
+  unknown_label:                "Undefined label '%0'",
+  invalid_break:                "Invalid break statement",
+  invalid_continue:             "Invalid continue statement",
+  uncaught_exception:           "Uncaught %0",
+  stack_trace:                  "Stack Trace:\n%0",
+  called_non_callable:          "%0 is not a function",
+  undefined_method:             "Object %1 has no method '%0'",
+  property_not_function:        "Property '%0' of object %1 is not a function",
+  null_or_undefined:            "Cannot access property of null or undefined",
+  cannot_convert_to_primitive:  "Cannot convert object to primitive value",
+  not_constructor:              "%0 is not a constructor",
+  not_defined:                  "%0 is not defined",
+  non_object_property_load:     "Cannot read property '%0' of %1",
+  non_object_property_store:    "Cannot set property '%0' of %1",
+  non_object_property_call:     "Cannot call method '%0' of %1",
+  illegal_eval:                 "Unsupported indirect eval() call",
+  with_expression:              "%0 has no properties",
+  illegal_invocation:           "Illegal invocation",
+  no_setter_in_callback:        "Cannot set property %0 of %1 which has only a getter",
+  apply_non_function:           "Function.prototype.apply was called on %0, which is a %1 and not a function",
+  apply_wrong_args:             "Function.prototype.apply: Arguments list has wrong type",
+  invalid_in_operator_use:      "Cannot use 'in' operator to search for '%0' in %1",
+  instanceof_function_expected: "Expecting a function in instanceof check, but got %0",
+  instanceof_nonobject_proto:   "Function has non-object prototype '%0' in instanceof check",
+  null_to_object:               "Cannot convert null to object",
+  // RangeError
+  invalid_array_length:         "Invalid array length",
+  invalid_array_apply_length:   "Function.prototype.apply supports only up to 1024 arguments",
+  stack_overflow:               "Maximum call stack size exceeded",
+  apply_overflow:               "Function.prototype.apply cannot support %0 arguments",
+  // SyntaxError
+  unable_to_parse:              "Parse error",
+  duplicate_regexp_flag:        "Duplicate RegExp flag %0",
+  unrecognized_regexp_flag:     "Unrecognized RegExp flag %0",
+  invalid_regexp:               "Invalid RegExp pattern /%0/",
+  illegal_break:                "Illegal break statement",
+  illegal_continue:             "Illegal continue statement",
+  illegal_return:               "Illegal return statement",
+  error_loading_debugger:       "Error loading debugger %0",
+  no_input_to_regexp:           "No input to %0",
+};
+
+
+function FormatString(format, args) {
+  var result = format;
+  for (var i = 0; i < args.length; i++) {
+    var str;
+    try { str = ToDetailString(args[i]); }
+    catch (e) { str = "#<error>"; }
+    result = result.split("%" + i).join(str);
+  }
+  return result;
+}
+
+
+function ToDetailString(obj) {
+  if (obj != null && IS_OBJECT(obj) && obj.toString === $Object.prototype.toString) {
+    var constructor = obj.constructor;
+    if (!constructor) return ToString(obj);
+    var constructorName = constructor.name;
+    if (!constructorName) return ToString(obj);
+    return "#<" + GetInstanceName(constructorName) + ">";
+  } else {
+    return ToString(obj);
+  }
+}
+
+
+function MakeGenericError(constructor, type, args) {
+  if (args instanceof $Array) {
+    for (var i = 0; i < args.length; i++) {
+      var elem = args[i];
+      if (elem instanceof $Array && elem.length > 100) { // arbitrary limit, grab a reasonable slice to report
+        args[i] = elem.slice(0,20).concat("...");
+      }
+    }
+  } else if (IS_UNDEFINED(args)) {
+    args = [];
+  }
+
+  var e = new constructor(kAddMessageAccessorsMarker);
+  e.type = type;
+  e.arguments = args;
+  return e;
+}
+
+
+/**
+ * Setup the Script function and constructor.
+ */
+%FunctionSetInstanceClassName(Script, 'Script');
+%SetProperty(Script.prototype, 'constructor', Script, DONT_ENUM);
+%SetCode(Script, function(x) {
+  // Script objects can only be created by the VM.
+  throw new $Error("Not supported");
+});
+
+
+// Helper functions; called from the runtime system.
+function FormatMessage(message) {
+  var format = kMessages[message.type];
+  if (!format) return "<unknown message " + message.type + ">";
+  return FormatString(format, message.args);
+}
+
+
+function GetLineNumber(message) {
+  if (message.startPos == -1) return -1;
+  var location = message.script.locationFromPosition(message.startPos, true);
+  if (location == null) return -1;
+  return location.line + 1;
+}
+
+
+// Returns the source code line containing the given source
+// position, or the empty string if the position is invalid.
+function GetSourceLine(message) {
+  var location = message.script.locationFromPosition(message.startPos, true);
+  if (location == null) return "";
+  location.restrict();
+  return location.sourceText();
+}
+
+
+function MakeTypeError(type, args) {
+  return MakeGenericError($TypeError, type, args);
+}
+
+
+function MakeRangeError(type, args) {
+  return MakeGenericError($RangeError, type, args);
+}
+
+
+function MakeSyntaxError(type, args) {
+  return MakeGenericError($SyntaxError, type, args);
+}
+
+
+function MakeReferenceError(type, args) {
+  return MakeGenericError($ReferenceError, type, args);
+}
+
+
+function MakeEvalError(type, args) {
+  return MakeGenericError($EvalError, type, args);
+}
+
+
+function MakeError(type, args) {
+  return MakeGenericError($Error, type, args);
+}
+
+
+/**
+ * Get information on a specific source position.
+ * @param {number} position The source position
+ * @param {boolean} include_resource_offset Set to true to have the resource
+ *     offset added to the location
+ * @return {SourceLocation}
+ *     If line is negative or not in the source null is returned.
+ */
+Script.prototype.locationFromPosition = function (position,
+                                                  include_resource_offset) {
+  var lineCount = this.lineCount();
+  var line = -1;
+  if (position <= this.line_ends[0]) {
+    line = 0;
+  } else {
+    for (var i = 1; i < lineCount; i++) {
+      if (this.line_ends[i - 1] < position && position <= this.line_ends[i]) {
+        line = i;
+        break;
+      }
+    }
+  }
+
+  if (line == -1) return null;
+
+  // Determine start, end and column.
+  var start = line == 0 ? 0 : this.line_ends[line - 1] + 1;
+  var end = this.line_ends[line];
+  if (end > 0 && this.source.charAt(end - 1) == '\r') end--;
+  var column = position - start;
+
+  // Adjust according to the offset within the resource.
+  if (include_resource_offset) {
+    line += this.line_offset;
+    if (line == this.line_offset) {
+      column += this.column_offset;
+    }
+  }
+
+  return new SourceLocation(this, position, line, column, start, end);
+};
+
+
+/**
+ * Get information on a specific source line and column possibly offset by a
+ * fixed source position. This function is used to find a source position from
+ * a line and column position. The fixed source position offset is typically
+ * used to find a source position in a function based on a line and column in
+ * the source for the function alone. The offset passed will then be the
+ * start position of the source for the function within the full script source.
+ * @param {number} opt_line The line within the source. Default value is 0
+ * @param {number} opt_column The column in within the line. Default value is 0
+ * @param {number} opt_offset_position The offset from the begining of the
+ *     source from where the line and column calculation starts. Default value is 0
+ * @return {SourceLocation}
+ *     If line is negative or not in the source null is returned.
+ */
+Script.prototype.locationFromLine = function (opt_line, opt_column, opt_offset_position) {
+  // Default is the first line in the script. Lines in the script is relative
+  // to the offset within the resource.
+  var line = 0;
+  if (!IS_UNDEFINED(opt_line)) {
+    line = opt_line - this.line_offset;
+  }
+
+  // Default is first column. If on the first line add the offset within the
+  // resource.
+  var column = opt_column || 0;
+  if (line == 0) {
+    column -= this.column_offset
+  }
+
+  var offset_position = opt_offset_position || 0;
+  if (line < 0 || column < 0 || offset_position < 0) return null;
+  if (line == 0) {
+    return this.locationFromPosition(offset_position + column, false);
+  } else {
+    // Find the line where the offset position is located
+    var lineCount = this.lineCount();
+    var offset_line;
+    for (var i = 0; i < lineCount; i++) {
+      if (offset_position <= this.line_ends[i]) {
+        offset_line = i;
+        break;
+      }
+    }
+    if (offset_line + line >= lineCount) return null;
+    return this.locationFromPosition(this.line_ends[offset_line + line - 1] + 1 + column);  // line > 0 here.
+  }
+}
+
+
+/**
+ * Get a slice of source code from the script. The boundaries for the slice is
+ * specified in lines.
+ * @param {number} opt_from_line The first line (zero bound) in the slice.
+ *     Default is 0
+ * @param {number} opt_to_column The last line (zero bound) in the slice (non
+ *     inclusive). Default is the number of lines in the script
+ * @return {SourceSlice} The source slice or null of the parameters where
+ *     invalid
+ */
+Script.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
+  var from_line = IS_UNDEFINED(opt_from_line) ? this.line_offset : opt_from_line;
+  var to_line = IS_UNDEFINED(opt_to_line) ? this.line_offset + this.lineCount() : opt_to_line
+
+  // Adjust according to the offset within the resource.
+  from_line -= this.line_offset;
+  to_line -= this.line_offset;
+  if (from_line < 0) from_line = 0;
+  if (to_line > this.lineCount()) to_line = this.lineCount();
+
+  // Check parameters.
+  if (from_line >= this.lineCount() ||
+      to_line < 0 ||
+      from_line > to_line) {
+    return null;
+  }
+
+  var from_position = from_line == 0 ? 0 : this.line_ends[from_line - 1] + 1;
+  var to_position = to_line == 0 ? 0 : this.line_ends[to_line - 1] + 1;
+
+  // Return a source slice with line numbers re-adjusted to the resource.
+  return new SourceSlice(this, from_line + this.line_offset, to_line + this.line_offset,
+                         from_position, to_position);
+}
+
+
+Script.prototype.sourceLine = function (opt_line) {
+  // Default is the first line in the script. Lines in the script are relative
+  // to the offset within the resource.
+  var line = 0;
+  if (!IS_UNDEFINED(opt_line)) {
+    line = opt_line - this.line_offset;
+  }
+
+  // Check parameter.
+  if (line < 0 || this.lineCount() <= line) {
+    return null;
+  }
+
+  // Return the source line.
+  var start = line == 0 ? 0 : this.line_ends[line - 1] + 1;
+  var end = this.line_ends[line];
+  return this.source.substring(start, end);
+}
+
+
+/**
+ * Returns the number of source lines.
+ * @return {number}
+ *     Number of source lines.
+ */
+Script.prototype.lineCount = function() {
+  // Return number of source lines.
+  return this.line_ends.length;
+};
+
+
+/**
+ * Class for source location. A source location is a position within some
+ * source with the following properties:
+ *   script   : script object for the source
+ *   line     : source line number
+ *   column   : source column within the line
+ *   position : position within the source
+ *   start    : position of start of source context (inclusive)
+ *   end      : position of end of source context (not inclusive)
+ * Source text for the source context is the character interval [start, end[. In
+ * most cases end will point to a newline character. It might point just past
+ * the final position of the source if the last source line does not end with a
+ * newline character.
+ * @param {Script} script The Script object for which this is a location
+ * @param {number} position Source position for the location
+ * @param {number} line The line number for the location
+ * @param {number} column The column within the line for the location
+ * @param {number} start Source position for start of source context
+ * @param {number} end Source position for end of source context
+ * @constructor
+ */
+function SourceLocation(script, position, line, column, start, end) {
+  this.script = script;
+  this.position = position;
+  this.line = line;
+  this.column = column;
+  this.start = start;
+  this.end = end;
+}
+
+
+const kLineLengthLimit = 78;
+
+/**
+ * Restrict source location start and end positions to make the source slice
+ * no more that a certain number of characters wide.
+ * @param {number} opt_limit The with limit of the source text with a default
+ *     of 78
+ * @param {number} opt_before The number of characters to prefer before the
+ *     position with a default value of 10 less that the limit
+ */
+SourceLocation.prototype.restrict = function (opt_limit, opt_before) {
+  // Find the actual limit to use.
+  var limit;
+  var before;
+  if (!IS_UNDEFINED(opt_limit)) {
+    limit = opt_limit;
+  } else {
+    limit = kLineLengthLimit;
+  }
+  if (!IS_UNDEFINED(opt_before)) {
+    before = opt_before;
+  } else {
+    // If no before is specified center for small limits and perfer more source
+    // before the the position that after for longer limits.
+    if (limit <= 20) {
+      before = $floor(limit / 2);
+    } else {
+      before = limit - 10;
+    }
+  }
+  if (before >= limit) {
+    before = limit - 1;
+  }
+
+  // If the [start, end[ interval is too big we restrict
+  // it in one or both ends. We make sure to always produce
+  // restricted intervals of maximum allowed size.
+  if (this.end - this.start > limit) {
+    var start_limit = this.position - before;
+    var end_limit = this.position + limit - before;
+    if (this.start < start_limit && end_limit < this.end) {
+      this.start = start_limit;
+      this.end = end_limit;
+    } else if (this.start < start_limit) {
+      this.start = this.end - limit;
+    } else {
+      this.end = this.start + limit;
+    }
+  }
+};
+
+
+/**
+ * Get the source text for a SourceLocation
+ * @return {String}
+ *     Source text for this location.
+ */
+SourceLocation.prototype.sourceText = function () {
+  return this.script.source.substring(this.start, this.end);
+};
+
+
+/**
+ * Class for a source slice. A source slice is a part of a script source with
+ * the following properties:
+ *   script        : script object for the source
+ *   from_line     : line number for the first line in the slice
+ *   to_line       : source line number for the last line in the slice
+ *   from_position : position of the first character in the slice
+ *   to_position   : position of the last character in the slice
+ * The to_line and to_position are not included in the slice, that is the lines
+ * in the slice are [from_line, to_line[. Likewise the characters in the slice
+ * are [from_position, to_position[.
+ * @param {Script} script The Script object for the source slice
+ * @param {number} from_line
+ * @param {number} to_line
+ * @param {number} from_position
+ * @param {number} to_position
+ * @constructor
+ */
+function SourceSlice(script, from_line, to_line, from_position, to_position) {
+  this.script = script;
+  this.from_line = from_line;
+  this.to_line = to_line;
+  this.from_position = from_position;
+  this.to_position = to_position;
+}
+
+
+/**
+ * Get the source text for a SourceSlice
+ * @return {String} Source text for this slice. The last line will include
+ *     the line terminating characters (if any)
+ */
+SourceSlice.prototype.sourceText = function () {
+  return this.script.source.substring(this.from_position, this.to_position);
+};
+
+
+// Returns the offset of the given position within the containing
+// line.
+function GetPositionInLine(message) {
+  var location = message.script.locationFromPosition(message.startPos, false);
+  if (location == null) return -1;
+  location.restrict();
+  return message.startPos - location.start;
+}
+
+
+function ErrorMessage(type, args, startPos, endPos, script, stackTrace) {
+  this.startPos = startPos;
+  this.endPos = endPos;
+  this.type = type;
+  this.args = args;
+  this.script = script;
+  this.stackTrace = stackTrace;
+}
+
+
+function MakeMessage(type, args, startPos, endPos, script, stackTrace) {
+  return new ErrorMessage(type, args, startPos, endPos, script, stackTrace);
+}
+
+
+function GetStackTraceLine(recv, fun, pos, isGlobal) {
+  try {
+    return UnsafeGetStackTraceLine(recv, fun, pos, isGlobal);
+  } catch (e) {
+    return "<error: " + e + ">";
+  }
+}
+
+
+function GetFunctionName(fun, recv) {
+  var name = %FunctionGetName(fun);
+  if (name) return name;
+  for (var prop in recv) {
+    if (recv[prop] === fun)
+      return prop;
+  }
+  return "[anonymous]";
+}
+
+
+function UnsafeGetStackTraceLine(recv, fun, pos, isTopLevel) {
+  var result = "";
+  // The global frame has no meaningful function or receiver
+  if (!isTopLevel) {
+    // If the receiver is not the global object then prefix the
+    // message send
+    if (recv !== global)
+      result += ToDetailString(recv) + ".";
+    result += GetFunctionName(fun, recv);
+  }
+  if (pos != -1) {
+    var script = %FunctionGetScript(fun);
+    var file;
+    if (script) {
+      file = %FunctionGetScript(fun).data;
+    }
+    if (file) {
+      var location = %FunctionGetScript(fun).locationFromPosition(pos, true);
+      if (!isTopLevel) result += "(";
+      result += file;
+      if (location != null) {
+        result += ":" + (location.line + 1) + ":" + (location.column + 1);
+      }
+      if (!isTopLevel) result += ")";
+    }
+  }
+  return (result) ? "    at " + result : result;
+}
+
+
+// ----------------------------------------------------------------------------
+// Error implementation
+
+// If this object gets passed to an error constructor the error will
+// get an accessor for .message that constructs a descriptive error
+// message on access.
+var kAddMessageAccessorsMarker = { };
+
+// Defines accessors for a property that is calculated the first time
+// the property is read and then replaces the accessor with the value.
+// Also, setting the property causes the accessors to be deleted.
+function DefineOneShotAccessor(obj, name, fun) {
+  // Note that the accessors consistently operate on 'obj', not 'this'.
+  // Since the object may occur in someone else's prototype chain we
+  // can't rely on 'this' being the same as 'obj'.
+  obj.__defineGetter__(name, function () {
+    var value = fun(obj);
+    obj[name] = value;
+    return value;
+  });
+  obj.__defineSetter__(name, function (v) {
+    delete obj[name];
+    obj[name] = v;
+  });
+}
+
+function DefineError(f) {
+  // Store the error function in both the global object
+  // and the runtime object. The function is fetched
+  // from the runtime object when throwing errors from
+  // within the runtime system to avoid strange side
+  // effects when overwriting the error functions from
+  // user code.
+  var name = f.name;
+  %SetProperty(global, name, f, DONT_ENUM);
+  this['$' + name] = f;
+  // Configure the error function.
+  if (name == 'Error') {
+    // The prototype of the Error object must itself be an error.
+    // However, it can't be an instance of the Error object because
+    // it hasn't been properly configured yet.  Instead we create a
+    // special not-a-true-error-but-close-enough object.
+    function ErrorPrototype() {}
+    %FunctionSetPrototype(ErrorPrototype, $Object.prototype);
+    %FunctionSetInstanceClassName(ErrorPrototype, 'Error');
+    %FunctionSetPrototype(f, new ErrorPrototype());
+  } else {
+    %FunctionSetPrototype(f, new $Error());
+  }
+  %FunctionSetInstanceClassName(f, 'Error');
+  %SetProperty(f.prototype, 'constructor', f, DONT_ENUM);
+  f.prototype.name = name;
+  %SetCode(f, function(m) {
+    if (%IsConstructCall()) {
+      if (m === kAddMessageAccessorsMarker) {
+        DefineOneShotAccessor(this, 'message', function (obj) {
+          return FormatMessage({type: obj.type, args: obj.arguments});
+        });
+      } else if (!IS_UNDEFINED(m)) {
+        this.message = ToString(m);
+      }
+    } else {
+      return new f(m);
+    }
+  });
+}
+
+$Math.__proto__ = global.Object.prototype;
+
+DefineError(function Error() { });
+DefineError(function TypeError() { });
+DefineError(function RangeError() { });
+DefineError(function SyntaxError() { });
+DefineError(function ReferenceError() { });
+DefineError(function EvalError() { });
+DefineError(function URIError() { });
+
+// Setup extra properties of the Error.prototype object.
+$Error.prototype.message = '';
+
+%SetProperty($Error.prototype, 'toString', function toString() {
+  var type = this.type;
+  if (type && !this.hasOwnProperty("message")) {
+    return this.name + ": " + FormatMessage({ type: type, args: this.arguments });
+  }
+  var message = this.message;
+  return this.name + (message ? (": " + message) : "");
+}, DONT_ENUM);
+
+
+// Boilerplate for exceptions for stack overflows. Used from
+// Top::StackOverflow().
+const kStackOverflowBoilerplate = MakeRangeError('stack_overflow', []);
diff --git a/deps/v8/src/mirror-delay.js b/deps/v8/src/mirror-delay.js
new file mode 100644
index 0000000..9c9d713
--- /dev/null
+++ b/deps/v8/src/mirror-delay.js
@@ -0,0 +1,2089 @@
+// 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.
+
+// jsminify this file, js2c: jsmin
+
+// Touch the RegExp and Date functions to make sure that date-delay.js and
+// regexp-delay.js has been loaded. This is required as the mirrors use
+// functions within these files through the builtins object. See the
+// function DateToISO8601_ as an example.
+RegExp;
+Date;
+
+
+var next_handle_ = 0;
+var mirror_cache_ = [];
+
+/**
+ * Clear the mirror handle cache.
+ */
+function ClearMirrorCache() {
+  next_handle_ = 0;
+  mirror_cache_ = [];
+}
+
+
+/**
+ * Returns the mirror for a specified value or object.
+ *
+ * @param {value or Object} value the value or object to retreive the mirror for
+ * @returns {Mirror} the mirror reflects the passed value or object
+ */
+function MakeMirror(value) {
+  var mirror;
+  for (id in mirror_cache_) {
+    mirror = mirror_cache_[id];
+    if (mirror.value() === value) {
+      return mirror;
+    }
+    // Special check for NaN as NaN == NaN is false.
+    if (mirror.isNumber() && isNaN(mirror.value()) &&
+        typeof value == 'number' && isNaN(value)) {
+      return mirror;
+    }
+  }
+  
+  if (IS_UNDEFINED(value)) {
+    mirror = new UndefinedMirror();
+  } else if (IS_NULL(value)) {
+    mirror = new NullMirror();
+  } else if (IS_BOOLEAN(value)) {
+    mirror = new BooleanMirror(value);
+  } else if (IS_NUMBER(value)) {
+    mirror = new NumberMirror(value);
+  } else if (IS_STRING(value)) {
+    mirror = new StringMirror(value);
+  } else if (IS_ARRAY(value)) {
+    mirror = new ArrayMirror(value);
+  } else if (IS_DATE(value)) {
+    mirror = new DateMirror(value);
+  } else if (IS_FUNCTION(value)) {
+    mirror = new FunctionMirror(value);
+  } else if (IS_REGEXP(value)) {
+    mirror = new RegExpMirror(value);
+  } else if (IS_ERROR(value)) {
+    mirror = new ErrorMirror(value);
+  } else if (IS_SCRIPT(value)) {
+    mirror = new ScriptMirror(value);
+  } else {
+    mirror = new ObjectMirror(value);
+  }
+
+  mirror_cache_[mirror.handle()] = mirror;
+  return mirror;
+}
+
+
+/**
+ * Returns the mirror for a specified mirror handle.
+ *
+ * @param {number} handle the handle to find the mirror for
+ * @returns {Mirror or undefiend} the mirror with the requested handle or
+ *     undefined if no mirror with the requested handle was found
+ */
+function LookupMirror(handle) {
+  return mirror_cache_[handle];
+}
+
+  
+/**
+ * Returns the mirror for the undefined value.
+ *
+ * @returns {Mirror} the mirror reflects the undefined value
+ */
+function GetUndefinedMirror() {
+  return MakeMirror(void 0);
+}
+
+
+/**
+ * Inherit the prototype methods from one constructor into another.
+ *
+ * The Function.prototype.inherits from lang.js rewritten as a standalone
+ * function (not on Function.prototype). NOTE: If this file is to be loaded
+ * during bootstrapping this function needs to be revritten using some native
+ * functions as prototype setup using normal JavaScript does not work as
+ * expected during bootstrapping (see mirror.js in r114903).
+ *
+ * @param {function} ctor Constructor function which needs to inherit the
+ *     prototype
+ * @param {function} superCtor Constructor function to inherit prototype from
+ */
+function inherits(ctor, superCtor) {
+  var tempCtor = function(){};
+  tempCtor.prototype = superCtor.prototype;
+  ctor.super_ = superCtor.prototype;
+  ctor.prototype = new tempCtor();
+  ctor.prototype.constructor = ctor;
+}
+
+
+// Type names of the different mirrors.
+const UNDEFINED_TYPE = 'undefined';
+const NULL_TYPE = 'null';
+const BOOLEAN_TYPE = 'boolean';
+const NUMBER_TYPE = 'number';
+const STRING_TYPE = 'string';
+const OBJECT_TYPE = 'object';
+const FUNCTION_TYPE = 'function';
+const REGEXP_TYPE = 'regexp';
+const ERROR_TYPE = 'error';
+const PROPERTY_TYPE = 'property';
+const FRAME_TYPE = 'frame';
+const SCRIPT_TYPE = 'script';
+
+// Maximum length when sending strings through the JSON protocol.
+const kMaxProtocolStringLength = 80;
+
+// Different kind of properties.
+PropertyKind = {};
+PropertyKind.Named   = 1;
+PropertyKind.Indexed = 2;
+
+
+// A copy of the PropertyType enum from global.h
+PropertyType = {};
+PropertyType.Normal             = 0;
+PropertyType.Field              = 1;
+PropertyType.ConstantFunction   = 2;
+PropertyType.Callbacks          = 3;
+PropertyType.Interceptor        = 4;
+PropertyType.MapTransition      = 5;
+PropertyType.ConstantTransition = 6;
+PropertyType.NullDescriptor     = 7;
+
+
+// Different attributes for a property.
+PropertyAttribute = {};
+PropertyAttribute.None       = NONE;
+PropertyAttribute.ReadOnly   = READ_ONLY;
+PropertyAttribute.DontEnum   = DONT_ENUM;
+PropertyAttribute.DontDelete = DONT_DELETE;
+
+
+// Mirror hierarchy:
+//   - Mirror
+//     - ValueMirror
+//       - UndefinedMirror
+//       - NullMirror
+//       - NumberMirror
+//       - StringMirror
+//       - ObjectMirror
+//         - FunctionMirror
+//           - UnresolvedFunctionMirror
+//         - ArrayMirror
+//         - DateMirror
+//         - RegExpMirror
+//         - ErrorMirror
+//     - PropertyMirror
+//     - FrameMirror
+//     - ScriptMirror
+
+
+/**
+ * Base class for all mirror objects.
+ * @param {string} type The type of the mirror
+ * @constructor
+ */
+function Mirror(type) {
+  this.type_ = type;
+};
+
+
+Mirror.prototype.type = function() {
+  return this.type_;
+};
+
+
+/**
+ * Check whether the mirror reflects a value.
+ * @returns {boolean} True if the mirror reflects a value.
+ */
+Mirror.prototype.isValue = function() {
+  return this instanceof ValueMirror;
+}
+
+
+/**
+ * Check whether the mirror reflects the undefined value.
+ * @returns {boolean} True if the mirror reflects the undefined value.
+ */
+Mirror.prototype.isUndefined = function() {
+  return this instanceof UndefinedMirror;
+}
+
+
+/**
+ * Check whether the mirror reflects the null value.
+ * @returns {boolean} True if the mirror reflects the null value
+ */
+Mirror.prototype.isNull = function() {
+  return this instanceof NullMirror;
+}
+
+
+/**
+ * Check whether the mirror reflects a boolean value.
+ * @returns {boolean} True if the mirror reflects a boolean value
+ */
+Mirror.prototype.isBoolean = function() {
+  return this instanceof BooleanMirror;
+}
+
+
+/**
+ * Check whether the mirror reflects a number value.
+ * @returns {boolean} True if the mirror reflects a number value
+ */
+Mirror.prototype.isNumber = function() {
+  return this instanceof NumberMirror;
+}
+
+
+/**
+ * Check whether the mirror reflects a string value.
+ * @returns {boolean} True if the mirror reflects a string value
+ */
+Mirror.prototype.isString = function() {
+  return this instanceof StringMirror;
+}
+
+
+/**
+ * Check whether the mirror reflects an object.
+ * @returns {boolean} True if the mirror reflects an object
+ */
+Mirror.prototype.isObject = function() {
+  return this instanceof ObjectMirror;
+}
+
+
+/**
+ * Check whether the mirror reflects a function.
+ * @returns {boolean} True if the mirror reflects a function
+ */
+Mirror.prototype.isFunction = function() {
+  return this instanceof FunctionMirror;
+}
+
+
+/**
+ * Check whether the mirror reflects an unresolved function.
+ * @returns {boolean} True if the mirror reflects an unresolved function
+ */
+Mirror.prototype.isUnresolvedFunction = function() {
+  return this instanceof UnresolvedFunctionMirror;
+}
+
+
+/**
+ * Check whether the mirror reflects an array.
+ * @returns {boolean} True if the mirror reflects an array
+ */
+Mirror.prototype.isArray = function() {
+  return this instanceof ArrayMirror;
+}
+
+
+/**
+ * Check whether the mirror reflects a date.
+ * @returns {boolean} True if the mirror reflects a date
+ */
+Mirror.prototype.isDate = function() {
+  return this instanceof DateMirror;
+}
+
+
+/**
+ * Check whether the mirror reflects a regular expression.
+ * @returns {boolean} True if the mirror reflects a regular expression
+ */
+Mirror.prototype.isRegExp = function() {
+  return this instanceof RegExpMirror;
+}
+
+
+/**
+ * Check whether the mirror reflects an error.
+ * @returns {boolean} True if the mirror reflects an error
+ */
+Mirror.prototype.isError = function() {
+  return this instanceof ErrorMirror;
+}
+
+
+/**
+ * Check whether the mirror reflects a property.
+ * @returns {boolean} True if the mirror reflects a property
+ */
+Mirror.prototype.isProperty = function() {
+  return this instanceof PropertyMirror;
+}
+
+
+/**
+ * Check whether the mirror reflects a stack frame.
+ * @returns {boolean} True if the mirror reflects a stack frame
+ */
+Mirror.prototype.isFrame = function() {
+  return this instanceof FrameMirror;
+}
+
+
+/**
+ * Check whether the mirror reflects a script.
+ * @returns {boolean} True if the mirror reflects a script
+ */
+Mirror.prototype.isScript = function() {
+  return this instanceof ScriptMirror;
+}
+
+
+/**
+ * Allocate a handle id for this object.
+ */
+Mirror.prototype.allocateHandle_ = function() {
+  this.handle_ = next_handle_++;
+}
+
+
+Mirror.prototype.toText = function() {
+  // Simpel to text which is used when on specialization in subclass.
+  return "#<" + builtins.GetInstanceName(this.constructor.name) + ">";
+}
+
+
+/**
+ * Base class for all value mirror objects.
+ * @param {string} type The type of the mirror
+ * @param {value} value The value reflected by this mirror
+ * @constructor
+ * @extends Mirror
+ */
+function ValueMirror(type, value) {
+  Mirror.call(this, type);
+  this.value_ = value;
+  this.allocateHandle_();
+}
+inherits(ValueMirror, Mirror);
+
+
+Mirror.prototype.handle = function() {
+  return this.handle_;
+};
+
+
+/**
+ * Check whether this is a primitive value.
+ * @return {boolean} True if the mirror reflects a primitive value
+ */
+ValueMirror.prototype.isPrimitive = function() {
+  var type = this.type();
+  return type === 'undefined' ||
+         type === 'null' ||
+         type === 'boolean' ||
+         type === 'number' ||
+         type === 'string';
+};
+
+
+/**
+ * Get the actual value reflected by this mirror.
+ * @return {value} The value reflected by this mirror
+ */
+ValueMirror.prototype.value = function() {
+  return this.value_;
+};
+
+
+/**
+ * Mirror object for Undefined.
+ * @constructor
+ * @extends ValueMirror
+ */
+function UndefinedMirror() {
+  ValueMirror.call(this, UNDEFINED_TYPE, void 0);
+}
+inherits(UndefinedMirror, ValueMirror);
+
+
+UndefinedMirror.prototype.toText = function() {
+  return 'undefined';
+}
+
+
+/**
+ * Mirror object for null.
+ * @constructor
+ * @extends ValueMirror
+ */
+function NullMirror() {
+  ValueMirror.call(this, NULL_TYPE, null);
+}
+inherits(NullMirror, ValueMirror);
+
+
+NullMirror.prototype.toText = function() {
+  return 'null';
+}
+
+
+/**
+ * Mirror object for boolean values.
+ * @param {boolean} value The boolean value reflected by this mirror
+ * @constructor
+ * @extends ValueMirror
+ */
+function BooleanMirror(value) {
+  ValueMirror.call(this, BOOLEAN_TYPE, value);
+}
+inherits(BooleanMirror, ValueMirror);
+
+
+BooleanMirror.prototype.toText = function() {
+  return this.value_ ? 'true' : 'false';
+}
+
+
+/**
+ * Mirror object for number values.
+ * @param {number} value The number value reflected by this mirror
+ * @constructor
+ * @extends ValueMirror
+ */
+function NumberMirror(value) {
+  ValueMirror.call(this, NUMBER_TYPE, value);
+}
+inherits(NumberMirror, ValueMirror);
+
+
+NumberMirror.prototype.toText = function() {
+  return %NumberToString(this.value_);
+}
+
+
+/**
+ * Mirror object for string values.
+ * @param {string} value The string value reflected by this mirror
+ * @constructor
+ * @extends ValueMirror
+ */
+function StringMirror(value) {
+  ValueMirror.call(this, STRING_TYPE, value);
+}
+inherits(StringMirror, ValueMirror);
+
+
+StringMirror.prototype.length = function() {
+  return this.value_.length;
+};
+
+
+StringMirror.prototype.toText = function() {
+  if (this.length() > kMaxProtocolStringLength) {
+    return this.value_.substring(0, kMaxProtocolStringLength) +
+           '... (length: ' + this.length() + ')';
+  } else {
+    return this.value_;
+  }
+}
+
+
+/**
+ * Mirror object for objects.
+ * @param {object} value The object reflected by this mirror
+ * @constructor
+ * @extends ValueMirror
+ */
+function ObjectMirror(value, type) {
+  ValueMirror.call(this, type || OBJECT_TYPE, value);
+}
+inherits(ObjectMirror, ValueMirror);
+
+
+ObjectMirror.prototype.className = function() {
+  return %ClassOf(this.value_);
+};
+
+
+ObjectMirror.prototype.constructorFunction = function() {
+  return MakeMirror(%DebugGetProperty(this.value_, 'constructor'));
+};
+
+
+ObjectMirror.prototype.prototypeObject = function() {
+  return MakeMirror(%DebugGetProperty(this.value_, 'prototype'));
+};
+
+
+ObjectMirror.prototype.protoObject = function() {
+  return MakeMirror(%DebugGetPrototype(this.value_));
+};
+
+
+ObjectMirror.prototype.hasNamedInterceptor = function() {
+  // Get information on interceptors for this object.
+  var x = %DebugInterceptorInfo(this.value_);
+  return (x & 2) != 0;
+};
+
+
+ObjectMirror.prototype.hasIndexedInterceptor = function() {
+  // Get information on interceptors for this object.
+  var x = %DebugInterceptorInfo(this.value_);
+  return (x & 1) != 0;
+};
+
+
+/**
+ * Return the property names for this object.
+ * @param {number} kind Indicate whether named, indexed or both kinds of
+ *     properties are requested
+ * @param {number} limit Limit the number of names returend to the specified
+       value
+ * @return {Array} Property names for this object
+ */
+ObjectMirror.prototype.propertyNames = function(kind, limit) {
+  // Find kind and limit and allocate array for the result
+  kind = kind || PropertyKind.Named | PropertyKind.Indexed;
+
+  var propertyNames;
+  var elementNames;
+  var total = 0;
+  
+  // Find all the named properties.
+  if (kind & PropertyKind.Named) {
+    // Get the local property names.
+    propertyNames = %DebugLocalPropertyNames(this.value_);
+    total += propertyNames.length;
+
+    // Get names for named interceptor properties if any.
+    if (this.hasNamedInterceptor() && (kind & PropertyKind.Named)) {
+      var namedInterceptorNames =
+          %DebugNamedInterceptorPropertyNames(this.value_);
+      if (namedInterceptorNames) {
+        propertyNames = propertyNames.concat(namedInterceptorNames);
+        total += namedInterceptorNames.length;
+      }
+    }
+  }
+
+  // Find all the indexed properties.
+  if (kind & PropertyKind.Indexed) {
+    // Get the local element names.
+    elementNames = %DebugLocalElementNames(this.value_);
+    total += elementNames.length;
+
+    // Get names for indexed interceptor properties.
+    if (this.hasIndexedInterceptor() && (kind & PropertyKind.Indexed)) {
+      var indexedInterceptorNames =
+          %DebugIndexedInterceptorElementNames(this.value_);
+      if (indexedInterceptorNames) {
+        elementNames = elementNames.concat(indexedInterceptorNames);
+        total += indexedInterceptorNames.length;
+      }
+    }
+  }
+  limit = Math.min(limit || total, total);
+
+  var names = new Array(limit);
+  var index = 0;
+
+  // Copy names for named properties.
+  if (kind & PropertyKind.Named) {
+    for (var i = 0; index < limit && i < propertyNames.length; i++) {
+      names[index++] = propertyNames[i];
+    }
+  }
+
+  // Copy names for indexed properties.
+  if (kind & PropertyKind.Indexed) {
+    for (var i = 0; index < limit && i < elementNames.length; i++) {
+      names[index++] = elementNames[i];
+    }
+  }
+
+  return names;
+};
+
+
+/**
+ * Return the properties for this object as an array of PropertyMirror objects.
+ * @param {number} kind Indicate whether named, indexed or both kinds of
+ *     properties are requested
+ * @param {number} limit Limit the number of properties returend to the
+       specified value
+ * @return {Array} Property mirrors for this object
+ */
+ObjectMirror.prototype.properties = function(kind, limit) {
+  var names = this.propertyNames(kind, limit);
+  var properties = new Array(names.length);
+  for (var i = 0; i < names.length; i++) {
+    properties[i] = this.property(names[i]);
+  }
+
+  return properties;
+};
+
+
+ObjectMirror.prototype.property = function(name) {
+  var details = %DebugGetPropertyDetails(this.value_, %ToString(name));
+  if (details) {
+    return new PropertyMirror(this, name, details);
+  }
+
+  // Nothing found.
+  return GetUndefinedMirror();
+};
+
+
+
+/**
+ * Try to find a property from its value.
+ * @param {Mirror} value The property value to look for
+ * @return {PropertyMirror} The property with the specified value. If no
+ *     property was found with the specified value UndefinedMirror is returned
+ */
+ObjectMirror.prototype.lookupProperty = function(value) {
+  var properties = this.properties();
+
+  // Look for property value in properties.
+  for (var i = 0; i < properties.length; i++) {
+
+    // Skip properties which are defined through assessors.
+    var property = properties[i];
+    if (property.propertyType() != PropertyType.Callbacks) {
+      if (%_ObjectEquals(property.value_, value.value_)) {
+        return property;
+      }
+    }
+  }
+
+  // Nothing found.
+  return GetUndefinedMirror();
+};
+
+
+/**
+ * Returns objects which has direct references to this object
+ * @param {number} opt_max_objects Optional parameter specifying the maximum
+ *     number of referencing objects to return.
+ * @return {Array} The objects which has direct references to this object.
+ */
+ObjectMirror.prototype.referencedBy = function(opt_max_objects) {
+  // Find all objects with direct references to this object.
+  var result = %DebugReferencedBy(this.value_,
+                                  Mirror.prototype, opt_max_objects || 0);
+
+  // Make mirrors for all the references found.
+  for (var i = 0; i < result.length; i++) {
+    result[i] = MakeMirror(result[i]);
+  }
+
+  return result;
+};
+
+
+ObjectMirror.prototype.toText = function() {
+  var name;
+  var ctor = this.constructorFunction();
+  if (ctor.isUndefined()) {
+    name = this.className();
+  } else {
+    name = ctor.name();
+    if (!name) {
+      name = this.className();
+    }
+  }
+  return '#<' + builtins.GetInstanceName(name) + '>';
+};
+
+
+/**
+ * Mirror object for functions.
+ * @param {function} value The function object reflected by this mirror.
+ * @constructor
+ * @extends ObjectMirror
+ */
+function FunctionMirror(value) {
+  ObjectMirror.call(this, value, FUNCTION_TYPE);
+  this.resolved_ = true;
+}
+inherits(FunctionMirror, ObjectMirror);
+
+
+/**
+ * Returns whether the function is resolved.
+ * @return {boolean} True if the function is resolved. Unresolved functions can
+ *     only originate as functions from stack frames
+ */
+FunctionMirror.prototype.resolved = function() {
+  return this.resolved_;
+};
+
+
+/**
+ * Returns the name of the function.
+ * @return {string} Name of the function
+ */
+FunctionMirror.prototype.name = function() {
+  return %FunctionGetName(this.value_);
+};
+
+
+/**
+ * Returns the source code for the function.
+ * @return {string or undefined} The source code for the function. If the
+ *     function is not resolved undefined will be returned.
+ */
+FunctionMirror.prototype.source = function() {
+  // Return source if function is resolved. Otherwise just fall through to
+  // return undefined.
+  if (this.resolved()) {
+    return builtins.FunctionSourceString(this.value_);
+  }
+};
+
+
+/**
+ * Returns the script object for the function.
+ * @return {ScriptMirror or undefined} Script object for the function or
+ *     undefined if the function has no script
+ */
+FunctionMirror.prototype.script = function() {
+  // Return script if function is resolved. Otherwise just fall through
+  // to return undefined.
+  if (this.resolved()) {
+    var script = %FunctionGetScript(this.value_);
+    if (script) {
+      return MakeMirror(script);
+    }
+  }
+};
+
+
+/**
+ * Returns objects constructed by this function.
+ * @param {number} opt_max_instances Optional parameter specifying the maximum
+ *     number of instances to return.
+ * @return {Array or undefined} The objects constructed by this function.
+ */
+FunctionMirror.prototype.constructedBy = function(opt_max_instances) {
+  if (this.resolved()) {
+    // Find all objects constructed from this function.
+    var result = %DebugConstructedBy(this.value_, opt_max_instances || 0);
+
+    // Make mirrors for all the instances found.
+    for (var i = 0; i < result.length; i++) {
+      result[i] = MakeMirror(result[i]);
+    }
+
+    return result;
+  } else {
+    return [];
+  }
+};
+
+
+FunctionMirror.prototype.toText = function() {
+  return this.source();
+}
+
+
+/**
+ * Mirror object for unresolved functions.
+ * @param {string} value The name for the unresolved function reflected by this
+ *     mirror.
+ * @constructor
+ * @extends ObjectMirror
+ */
+function UnresolvedFunctionMirror(value) {
+  // Construct this using the ValueMirror as an unresolved function is not a
+  // real object but just a string.
+  ValueMirror.call(this, FUNCTION_TYPE, value);
+  this.propertyCount_ = 0;
+  this.elementCount_ = 0;
+  this.resolved_ = false;
+}
+inherits(UnresolvedFunctionMirror, FunctionMirror);
+
+
+UnresolvedFunctionMirror.prototype.className = function() {
+  return 'Function';
+};
+
+
+UnresolvedFunctionMirror.prototype.constructorFunction = function() {
+  return GetUndefinedMirror();
+};
+
+
+UnresolvedFunctionMirror.prototype.prototypeObject = function() {
+  return GetUndefinedMirror();
+};
+
+
+UnresolvedFunctionMirror.prototype.protoObject = function() {
+  return GetUndefinedMirror();
+};
+
+
+UnresolvedFunctionMirror.prototype.name = function() {
+  return this.value_;
+};
+
+
+UnresolvedFunctionMirror.prototype.propertyNames = function(kind, limit) {
+  return [];
+}
+
+
+/**
+ * Mirror object for arrays.
+ * @param {Array} value The Array object reflected by this mirror
+ * @constructor
+ * @extends ObjectMirror
+ */
+function ArrayMirror(value) {
+  ObjectMirror.call(this, value);
+}
+inherits(ArrayMirror, ObjectMirror);
+
+
+ArrayMirror.prototype.length = function() {
+  return this.value_.length;
+};
+
+
+ArrayMirror.prototype.indexedPropertiesFromRange = function(opt_from_index, opt_to_index) {
+  var from_index = opt_from_index || 0;
+  var to_index = opt_to_index || this.length() - 1;
+  if (from_index > to_index) return new Array();
+  var values = new Array(to_index - from_index + 1);
+  for (var i = from_index; i <= to_index; i++) {
+    var details = %DebugGetPropertyDetails(this.value_, %ToString(i));
+    var value;
+    if (details) {
+      value = new PropertyMirror(this, i, details);
+    } else {
+      value = GetUndefinedMirror();
+    }
+    values[i - from_index] = value;
+  }
+  return values;
+}
+
+
+/**
+ * Mirror object for dates.
+ * @param {Date} value The Date object reflected by this mirror
+ * @constructor
+ * @extends ObjectMirror
+ */
+function DateMirror(value) {
+  ObjectMirror.call(this, value);
+}
+inherits(DateMirror, ObjectMirror);
+
+
+DateMirror.prototype.toText = function() {
+  return DateToISO8601_(this.value_);
+}
+
+
+/**
+ * Mirror object for regular expressions.
+ * @param {RegExp} value The RegExp object reflected by this mirror
+ * @constructor
+ * @extends ObjectMirror
+ */
+function RegExpMirror(value) {
+  ObjectMirror.call(this, value, REGEXP_TYPE);
+}
+inherits(RegExpMirror, ObjectMirror);
+
+
+/**
+ * Returns the source to the regular expression.
+ * @return {string or undefined} The source to the regular expression
+ */
+RegExpMirror.prototype.source = function() {
+  return this.value_.source;
+};
+
+
+/**
+ * Returns whether this regular expression has the global (g) flag set.
+ * @return {boolean} Value of the global flag
+ */
+RegExpMirror.prototype.global = function() {
+  return this.value_.global;
+};
+
+
+/**
+ * Returns whether this regular expression has the ignore case (i) flag set.
+ * @return {boolean} Value of the ignore case flag
+ */
+RegExpMirror.prototype.ignoreCase = function() {
+  return this.value_.ignoreCase;
+};
+
+
+/**
+ * Returns whether this regular expression has the multiline (m) flag set.
+ * @return {boolean} Value of the multiline flag
+ */
+RegExpMirror.prototype.multiline = function() {
+  return this.value_.multiline;
+};
+
+
+RegExpMirror.prototype.toText = function() {
+  // Simpel to text which is used when on specialization in subclass.
+  return "/" + this.source() + "/";
+}
+
+
+/**
+ * Mirror object for error objects.
+ * @param {Error} value The error object reflected by this mirror
+ * @constructor
+ * @extends ObjectMirror
+ */
+function ErrorMirror(value) {
+  ObjectMirror.call(this, value, ERROR_TYPE);
+}
+inherits(ErrorMirror, ObjectMirror);
+
+
+/**
+ * Returns the message for this eror object.
+ * @return {string or undefined} The message for this eror object
+ */
+ErrorMirror.prototype.message = function() {
+  return this.value_.message;
+};
+
+
+ErrorMirror.prototype.toText = function() {
+  // Use the same text representation as in messages.js.
+  var text;
+  try {
+    str = builtins.ToDetailString(this.value_);
+  } catch (e) {
+    str = '#<an Error>';
+  }
+  return str;
+}
+
+
+/**
+ * Base mirror object for properties.
+ * @param {ObjectMirror} mirror The mirror object having this property
+ * @param {string} name The name of the property
+ * @param {Array} details Details about the property
+ * @constructor
+ * @extends Mirror
+ */
+function PropertyMirror(mirror, name, details) {
+  Mirror.call(this, PROPERTY_TYPE);
+  this.mirror_ = mirror;
+  this.name_ = name;
+  this.value_ = details[0];
+  this.details_ = details[1];
+  if (details.length > 2) {
+    this.exception_ = details[2]
+    this.getter_ = details[3];
+    this.setter_ = details[4];
+  }
+}
+inherits(PropertyMirror, Mirror);
+
+
+PropertyMirror.prototype.isReadOnly = function() {
+  return (this.attributes() & PropertyAttribute.ReadOnly) != 0;
+}
+
+
+PropertyMirror.prototype.isEnum = function() {
+  return (this.attributes() & PropertyAttribute.DontEnum) == 0;
+}
+
+
+PropertyMirror.prototype.canDelete = function() {
+  return (this.attributes() & PropertyAttribute.DontDelete) == 0;
+}
+
+
+PropertyMirror.prototype.name = function() {
+  return this.name_;
+}
+
+
+PropertyMirror.prototype.isIndexed = function() {
+  for (var i = 0; i < this.name_.length; i++) {
+    if (this.name_[i] < '0' || '9' < this.name_[i]) {
+      return false;
+    }
+  }
+  return true;
+}
+
+
+PropertyMirror.prototype.value = function() {
+  return MakeMirror(this.value_);
+}
+
+
+/**
+ * Returns whether this property value is an exception.
+ * @return {booolean} True if this property value is an exception
+ */
+PropertyMirror.prototype.isException = function() {
+  return this.exception_ ? true : false;
+}
+
+
+PropertyMirror.prototype.attributes = function() {
+  return %DebugPropertyAttributesFromDetails(this.details_);
+}
+
+
+PropertyMirror.prototype.propertyType = function() {
+  return %DebugPropertyTypeFromDetails(this.details_);
+}
+
+
+PropertyMirror.prototype.insertionIndex = function() {
+  return %DebugPropertyIndexFromDetails(this.details_);
+}
+
+
+/**
+ * Returns whether this property has a getter defined through __defineGetter__.
+ * @return {booolean} True if this property has a getter
+ */
+PropertyMirror.prototype.hasGetter = function() {
+  return this.getter_ ? true : false;
+}
+
+
+/**
+ * Returns whether this property has a setter defined through __defineSetter__.
+ * @return {booolean} True if this property has a setter
+ */
+PropertyMirror.prototype.hasSetter = function() {
+  return this.setter_ ? true : false;
+}
+
+
+/**
+ * Returns the getter for this property defined through __defineGetter__.
+ * @return {Mirror} FunctionMirror reflecting the getter function or
+ *     UndefinedMirror if there is no getter for this property
+ */
+PropertyMirror.prototype.getter = function() {
+  if (this.hasGetter()) {
+    return MakeMirror(this.getter_);
+  } else {
+    return new UndefinedMirror();
+  }
+}
+
+
+/**
+ * Returns the setter for this property defined through __defineSetter__.
+ * @return {Mirror} FunctionMirror reflecting the setter function or
+ *     UndefinedMirror if there is no setter for this property
+ */
+PropertyMirror.prototype.setter = function() {
+  if (this.hasSetter()) {
+    return MakeMirror(this.setter_);
+  } else {
+    return new UndefinedMirror();
+  }
+}
+
+
+/**
+ * Returns whether this property is natively implemented by the host or a set
+ * through JavaScript code.
+ * @return {boolean} True if the property is 
+ *     UndefinedMirror if there is no setter for this property
+ */
+PropertyMirror.prototype.isNative = function() {
+  return (this.propertyType() == PropertyType.Interceptor) ||
+         ((this.propertyType() == PropertyType.Callbacks) &&
+          !this.hasGetter() && !this.hasSetter());
+}
+
+
+const kFrameDetailsFrameIdIndex = 0;
+const kFrameDetailsReceiverIndex = 1;
+const kFrameDetailsFunctionIndex = 2;
+const kFrameDetailsArgumentCountIndex = 3;
+const kFrameDetailsLocalCountIndex = 4;
+const kFrameDetailsSourcePositionIndex = 5;
+const kFrameDetailsConstructCallIndex = 6;
+const kFrameDetailsDebuggerFrameIndex = 7;
+const kFrameDetailsFirstDynamicIndex = 8;
+
+const kFrameDetailsNameIndex = 0;
+const kFrameDetailsValueIndex = 1;
+const kFrameDetailsNameValueSize = 2;
+
+/**
+ * Wrapper for the frame details information retreived from the VM. The frame
+ * details from the VM is an array with the following content. See runtime.cc
+ * Runtime_GetFrameDetails.
+ *     0: Id
+ *     1: Receiver
+ *     2: Function
+ *     3: Argument count
+ *     4: Local count
+ *     5: Source position
+ *     6: Construct call
+ *     Arguments name, value
+ *     Locals name, value
+ * @param {number} break_id Current break id
+ * @param {number} index Frame number
+ * @constructor
+ */
+function FrameDetails(break_id, index) {
+  this.break_id_ = break_id;
+  this.details_ = %GetFrameDetails(break_id, index);
+}
+
+
+FrameDetails.prototype.frameId = function() {
+  %CheckExecutionState(this.break_id_);
+  return this.details_[kFrameDetailsFrameIdIndex];
+}
+
+
+FrameDetails.prototype.receiver = function() {
+  %CheckExecutionState(this.break_id_);
+  return this.details_[kFrameDetailsReceiverIndex];
+}
+
+
+FrameDetails.prototype.func = function() {
+  %CheckExecutionState(this.break_id_);
+  return this.details_[kFrameDetailsFunctionIndex];
+}
+
+
+FrameDetails.prototype.isConstructCall = function() {
+  %CheckExecutionState(this.break_id_);
+  return this.details_[kFrameDetailsConstructCallIndex];
+}
+
+
+FrameDetails.prototype.isDebuggerFrame = function() {
+  %CheckExecutionState(this.break_id_);
+  return this.details_[kFrameDetailsDebuggerFrameIndex];
+}
+
+
+FrameDetails.prototype.argumentCount = function() {
+  %CheckExecutionState(this.break_id_);
+  return this.details_[kFrameDetailsArgumentCountIndex];
+}
+
+
+FrameDetails.prototype.argumentName = function(index) {
+  %CheckExecutionState(this.break_id_);
+  if (index >= 0 && index < this.argumentCount()) {
+    return this.details_[kFrameDetailsFirstDynamicIndex +
+                         index * kFrameDetailsNameValueSize +
+                         kFrameDetailsNameIndex]
+  }
+}
+
+
+FrameDetails.prototype.argumentValue = function(index) {
+  %CheckExecutionState(this.break_id_);
+  if (index >= 0 && index < this.argumentCount()) {
+    return this.details_[kFrameDetailsFirstDynamicIndex +
+                         index * kFrameDetailsNameValueSize +
+                         kFrameDetailsValueIndex]
+  }
+}
+
+
+FrameDetails.prototype.localCount = function() {
+  %CheckExecutionState(this.break_id_);
+  return this.details_[kFrameDetailsLocalCountIndex];
+}
+
+
+FrameDetails.prototype.sourcePosition = function() {
+  %CheckExecutionState(this.break_id_);
+  return this.details_[kFrameDetailsSourcePositionIndex];
+}
+
+
+FrameDetails.prototype.localName = function(index) {
+  %CheckExecutionState(this.break_id_);
+  if (index >= 0 && index < this.localCount()) {
+    var locals_offset = kFrameDetailsFirstDynamicIndex + this.argumentCount() * kFrameDetailsNameValueSize
+    return this.details_[locals_offset +
+                         index * kFrameDetailsNameValueSize +
+                         kFrameDetailsNameIndex]
+  }
+}
+
+
+FrameDetails.prototype.localValue = function(index) {
+  %CheckExecutionState(this.break_id_);
+  if (index >= 0 && index < this.localCount()) {
+    var locals_offset = kFrameDetailsFirstDynamicIndex + this.argumentCount() * kFrameDetailsNameValueSize
+    return this.details_[locals_offset +
+                         index * kFrameDetailsNameValueSize +
+                         kFrameDetailsValueIndex]
+  }
+}
+
+
+/**
+ * Mirror object for stack frames.
+ * @param {number} break_id The break id in the VM for which this frame is
+       valid
+ * @param {number} index The frame index (top frame is index 0)
+ * @constructor
+ * @extends Mirror
+ */
+function FrameMirror(break_id, index) {
+  Mirror.call(this, FRAME_TYPE);
+  this.break_id_ = break_id;
+  this.index_ = index;
+  this.details_ = new FrameDetails(break_id, index);
+}
+inherits(FrameMirror, Mirror);
+
+
+FrameMirror.prototype.index = function() {
+  return this.index_;
+};
+
+
+FrameMirror.prototype.func = function() {
+  // Get the function for this frame from the VM.
+  var f = this.details_.func();
+  
+  // Create a function mirror. NOTE: MakeMirror cannot be used here as the
+  // value returned from the VM might be a string if the function for the
+  // frame is unresolved.
+  if (IS_FUNCTION(f)) {
+    return MakeMirror(f);
+  } else {
+    return new UnresolvedFunctionMirror(f);
+  }
+};
+
+
+FrameMirror.prototype.receiver = function() {
+  return MakeMirror(this.details_.receiver());
+};
+
+
+FrameMirror.prototype.isConstructCall = function() {
+  return this.details_.isConstructCall();
+};
+
+
+FrameMirror.prototype.isDebuggerFrame = function() {
+  return this.details_.isDebuggerFrame();
+};
+
+
+FrameMirror.prototype.argumentCount = function() {
+  return this.details_.argumentCount();
+};
+
+
+FrameMirror.prototype.argumentName = function(index) {
+  return this.details_.argumentName(index);
+};
+
+
+FrameMirror.prototype.argumentValue = function(index) {
+  return MakeMirror(this.details_.argumentValue(index));
+};
+
+
+FrameMirror.prototype.localCount = function() {
+  return this.details_.localCount();
+};
+
+
+FrameMirror.prototype.localName = function(index) {
+  return this.details_.localName(index);
+};
+
+
+FrameMirror.prototype.localValue = function(index) {
+  return MakeMirror(this.details_.localValue(index));
+};
+
+
+FrameMirror.prototype.sourcePosition = function() {
+  return this.details_.sourcePosition();
+};
+
+
+FrameMirror.prototype.sourceLocation = function() {
+  if (this.func().resolved() && this.func().script()) {
+    return this.func().script().locationFromPosition(this.sourcePosition(),
+                                                     true);
+  }
+};
+
+
+FrameMirror.prototype.sourceLine = function() {
+  if (this.func().resolved()) {
+    var location = this.sourceLocation();
+    if (location) {
+      return location.line;
+    }
+  }
+};
+
+
+FrameMirror.prototype.sourceColumn = function() {
+  if (this.func().resolved()) {
+    var location = this.sourceLocation();
+    if (location) {
+      return location.column;
+    }
+  }
+};
+
+
+FrameMirror.prototype.sourceLineText = function() {
+  if (this.func().resolved()) {
+    var location = this.sourceLocation();
+    if (location) {
+      return location.sourceText();
+    }
+  }
+};
+
+
+FrameMirror.prototype.evaluate = function(source, disable_break) {
+  var result = %DebugEvaluate(this.break_id_, this.details_.frameId(),
+                              source, Boolean(disable_break));
+  return MakeMirror(result);
+};
+
+
+FrameMirror.prototype.invocationText = function() {
+  // Format frame invoaction (receiver, function and arguments).
+  var result = '';
+  var func = this.func();
+  var receiver = this.receiver();
+  if (this.isConstructCall()) {
+    // For constructor frames display new followed by the function name.
+    result += 'new ';
+    result += func.name() ? func.name() : '[anonymous]';
+  } else if (this.isDebuggerFrame()) {
+    result += '[debugger]';
+  } else {
+    // If the receiver has a className which is 'global' don't display it.
+    var display_receiver = !receiver.className || receiver.className() != 'global';
+    if (display_receiver) {
+      result += receiver.toText();
+    }
+    // Try to find the function as a property in the receiver. Include the
+    // prototype chain in the lookup.
+    var property = GetUndefinedMirror();
+    if (!receiver.isUndefined()) {
+      for (var r = receiver; !r.isNull() && property.isUndefined(); r = r.protoObject()) {
+        property = r.lookupProperty(func);
+      }
+    }
+    if (!property.isUndefined()) {
+      // The function invoked was found on the receiver. Use the property name
+      // for the backtrace.
+      if (!property.isIndexed()) {
+        if (display_receiver) {
+          result += '.';
+        }
+        result += property.name();
+      } else {
+        result += '[';
+        result += property.name();
+        result += ']';
+      }
+      // Also known as - if the name in the function doesn't match the name
+      // under which it was looked up.
+      if (func.name() && func.name() != property.name()) {
+        result += '(aka ' + func.name() + ')';
+      }
+    } else {
+      // The function invoked was not found on the receiver. Use the function
+      // name if available for the backtrace.
+      if (display_receiver) {
+        result += '.';
+      }
+      result += func.name() ? func.name() : '[anonymous]';
+    }
+  }
+
+  // Render arguments for normal frames.
+  if (!this.isDebuggerFrame()) {
+    result += '(';
+    for (var i = 0; i < this.argumentCount(); i++) {
+      if (i != 0) result += ', ';
+      if (this.argumentName(i)) {
+        result += this.argumentName(i);
+        result += '=';
+      }
+      result += this.argumentValue(i).toText();
+    }
+    result += ')';
+  }
+
+  return result;
+}
+
+
+FrameMirror.prototype.sourceAndPositionText = function() {
+  // Format source and position.
+  var result = '';
+  var func = this.func();
+  if (func.resolved()) {
+    if (func.script()) {
+      if (func.script().name()) {
+        result += func.script().name();
+      } else {
+        result += '[unnamed]';
+      }
+      if (!this.isDebuggerFrame()) {
+        var location = this.sourceLocation();
+        result += ' line ';
+        result += !IS_UNDEFINED(location) ? (location.line + 1) : '?';
+        result += ' column ';
+        result += !IS_UNDEFINED(location) ? (location.column + 1) : '?';
+        if (!IS_UNDEFINED(this.sourcePosition())) {
+          result += ' (position ' + (this.sourcePosition() + 1) + ')';
+        }
+      }
+    } else {
+      result += '[no source]';
+    }
+  } else {
+    result += '[unresolved]';
+  }
+
+  return result;
+}
+
+
+FrameMirror.prototype.localsText = function() {
+  // Format local variables.
+  var result = '';
+  var locals_count = this.localCount()
+  if (locals_count > 0) {
+    for (var i = 0; i < locals_count; ++i) {
+      result += '      var ';
+      result += this.localName(i);
+      result += ' = ';
+      result += this.localValue(i).toText();
+      if (i < locals_count - 1) result += '\n';
+    }
+  }
+
+  return result;
+}
+
+
+FrameMirror.prototype.toText = function(opt_locals) {
+  var result = '';
+  result += '#' + (this.index() <= 9 ? '0' : '') + this.index();
+  result += ' ';
+  result += this.invocationText();
+  result += ' ';
+  result += this.sourceAndPositionText();
+  if (opt_locals) {
+    result += '\n';
+    result += this.localsText();
+  }
+  return result;
+}
+
+
+/**
+ * Mirror object for script source.
+ * @param {Script} script The script object
+ * @constructor
+ * @extends Mirror
+ */
+function ScriptMirror(script) {
+  Mirror.call(this, SCRIPT_TYPE);
+  this.script_ = script;
+  this.allocateHandle_();
+}
+inherits(ScriptMirror, Mirror);
+
+
+ScriptMirror.prototype.value = function() {
+  return this.script_;
+};
+
+
+ScriptMirror.prototype.name = function() {
+  return this.script_.name;
+};
+
+
+ScriptMirror.prototype.id = function() {
+  return this.script_.id;
+};
+
+
+ScriptMirror.prototype.source = function() {
+  return this.script_.source;
+};
+
+
+ScriptMirror.prototype.lineOffset = function() {
+  return this.script_.line_offset;
+};
+
+
+ScriptMirror.prototype.columnOffset = function() {
+  return this.script_.column_offset;
+};
+
+
+ScriptMirror.prototype.scriptType = function() {
+  return this.script_.type;
+};
+
+
+ScriptMirror.prototype.lineCount = function() {
+  return this.script_.lineCount();
+};
+
+
+ScriptMirror.prototype.locationFromPosition = function(
+    position, include_resource_offset) {
+  return this.script_.locationFromPosition(position, include_resource_offset);
+}
+
+
+ScriptMirror.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
+  return this.script_.sourceSlice(opt_from_line, opt_to_line);
+}
+
+
+ScriptMirror.prototype.toText = function() {
+  var result = '';
+  result += this.name();
+  result += ' (lines: ';
+  if (this.lineOffset() > 0) {
+    result += this.lineOffset();
+    result += '-';
+    result += this.lineOffset() + this.lineCount() - 1;
+  } else {
+    result += this.lineCount();
+  }
+  result += ')';
+  return result;
+}
+
+
+/**
+ * Returns a mirror serializer
+ *
+ * @param {boolean} details Set to true to include details
+ * @returns {MirrorSerializer} mirror serializer
+ */
+function MakeMirrorSerializer(details) {
+  return new JSONProtocolSerializer(details);
+}
+
+
+/**
+ * Object for serializing a mirror objects and its direct references.
+ * @param {boolean} details Indicates whether to include details for the mirror
+ *     serialized
+ * @constructor
+ */
+function JSONProtocolSerializer(details) {
+  this.details_ = details;
+  this.mirrors_ = [ ];
+}
+
+
+/**
+ * Returns a serialization of an object reference. The referenced object are
+ * added to the serialization state.
+ *
+ * @param {Mirror} mirror The mirror to serialize
+ * @returns {String} JSON serialization
+ */
+JSONProtocolSerializer.prototype.serializeReference = function(mirror) {
+  return this.serialize_(mirror, true, true);
+}
+
+
+/**
+ * Returns a serialization of an object value. The referenced objects are
+ * added to the serialization state.
+ *
+ * @param {Mirror} mirror The mirror to serialize
+ * @returns {String} JSON serialization
+ */
+JSONProtocolSerializer.prototype.serializeValue = function(mirror) {
+  var json = this.serialize_(mirror, false, true);
+  return json;
+}
+
+
+/**
+ * Returns a serialization of all the objects referenced.
+ *
+ * @param {Mirror} mirror The mirror to serialize
+ * @returns {String} JSON serialization
+ */
+JSONProtocolSerializer.prototype.serializeReferencedObjects = function() {
+  // Collect the JSON serialization of the referenced objects in an array.
+  var content = new Array();
+  
+  // Get the number of referenced objects.
+  var count = this.mirrors_.length;
+  
+  for (var i = 0; i < count; i++) {
+    content.push(this.serialize_(this.mirrors_[i], false, false));
+  }
+
+  var json = ArrayToJSONArray_(content);
+  return json;
+}
+
+
+JSONProtocolSerializer.prototype.add_ = function(mirror) {
+  // If this mirror is already in the list just return.
+  for (var i = 0; i < this.mirrors_.length; i++) {
+    if (this.mirrors_[i] === mirror) {
+      return;
+    }
+  }
+  
+  // Add the mirror to the list of mirrors to be serialized.
+  this.mirrors_.push(mirror);
+}
+
+
+JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
+                                                       details) {
+  // If serializing a reference to a mirror just return the reference and add
+  // the mirror to the referenced mirrors.
+  if (reference &&
+      (mirror.isValue() || mirror.isScript())) {
+    this.add_(mirror);
+    return '{"ref":' + mirror.handle() + '}';
+  }
+  
+  // Collect the JSON property/value pairs in an array.
+  var content = new Array();
+
+  // Add the mirror handle.
+  if (mirror.isValue() || mirror.isScript()) {
+    content.push(MakeJSONPair_('handle', NumberToJSON_(mirror.handle())));
+  }
+
+  // Always add the type.
+  content.push(MakeJSONPair_('type', StringToJSON_(mirror.type())));
+
+  switch (mirror.type()) {
+    case UNDEFINED_TYPE:
+    case NULL_TYPE:
+      // Undefined and null are represented just by their type.
+      break;
+
+    case BOOLEAN_TYPE:
+      // Boolean values are simply represented by their value.
+      content.push(MakeJSONPair_('value', BooleanToJSON_(mirror.value())));
+      break;
+
+    case NUMBER_TYPE:
+      // Number values are simply represented by their value.
+      content.push(MakeJSONPair_('value', NumberToJSON_(mirror.value())));
+      break;
+
+    case STRING_TYPE:
+      // String values might have their value cropped to keep down size.
+      if (mirror.length() > kMaxProtocolStringLength) {
+        var str = mirror.value().substring(0, kMaxProtocolStringLength);
+        content.push(MakeJSONPair_('value', StringToJSON_(str)));
+        content.push(MakeJSONPair_('fromIndex', NumberToJSON_(0)));
+        content.push(MakeJSONPair_('toIndex',
+                                   NumberToJSON_(kMaxProtocolStringLength)));
+      } else {
+        content.push(MakeJSONPair_('value', StringToJSON_(mirror.value())));
+      }
+      content.push(MakeJSONPair_('length', NumberToJSON_(mirror.length())));
+      break;
+
+    case OBJECT_TYPE:
+    case FUNCTION_TYPE:
+    case ERROR_TYPE:
+    case REGEXP_TYPE:
+      // Add object representation.
+      this.serializeObject_(mirror, content, details);
+      break;
+
+    case PROPERTY_TYPE:
+      throw new Error('PropertyMirror cannot be serialized independeltly')
+      break;
+
+    case FRAME_TYPE:
+      // Add object representation.
+      this.serializeFrame_(mirror, content);
+      break;
+
+    case SCRIPT_TYPE:
+      // Script is represented by id, name and source attributes.
+      if (mirror.name()) {
+        content.push(MakeJSONPair_('name', StringToJSON_(mirror.name())));
+      }
+      content.push(MakeJSONPair_('id', NumberToJSON_(mirror.id())));
+      content.push(MakeJSONPair_('lineOffset',
+                                 NumberToJSON_(mirror.lineOffset())));
+      content.push(MakeJSONPair_('columnOffset',
+                                 NumberToJSON_(mirror.columnOffset())));
+      content.push(MakeJSONPair_('lineCount',
+                                 NumberToJSON_(mirror.lineCount())));
+      content.push(MakeJSONPair_('scriptType',
+                                 NumberToJSON_(mirror.scriptType())));
+      break;
+  }
+
+  // Always add the text representation.
+  content.push(MakeJSONPair_('text', StringToJSON_(mirror.toText())));
+  
+  // Create and return the JSON string.
+  return ArrayToJSONObject_(content);
+}
+
+
+/**
+ * Serialize object information to the following JSON format.
+ *
+ *   {"className":"<class name>",
+ *    "constructorFunction":{"ref":<number>},
+ *    "protoObject":{"ref":<number>},
+ *    "prototypeObject":{"ref":<number>},
+ *    "namedInterceptor":<boolean>,
+ *    "indexedInterceptor":<boolean>,
+ *    "properties":[<properties>]}
+ */
+JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content,
+                                                             details) {
+  // Add general object properties.
+  content.push(MakeJSONPair_('className',
+                             StringToJSON_(mirror.className())));
+  content.push(MakeJSONPair_('constructorFunction',
+      this.serializeReference(mirror.constructorFunction())));
+  content.push(MakeJSONPair_('protoObject',
+      this.serializeReference(mirror.protoObject())));
+  content.push(MakeJSONPair_('prototypeObject',
+      this.serializeReference(mirror.prototypeObject())));
+
+  // Add flags to indicate whether there are interceptors.
+  if (mirror.hasNamedInterceptor()) {
+    content.push(MakeJSONPair_('namedInterceptor', BooleanToJSON_(true)));
+  }
+  if (mirror.hasIndexedInterceptor()) {
+    content.push(MakeJSONPair_('indexedInterceptor', BooleanToJSON_(true)));
+  }
+  
+  // Add function specific properties.
+  if (mirror.isFunction()) {
+    // Add function specific properties.
+    content.push(MakeJSONPair_('name', StringToJSON_(mirror.name())));
+    content.push(MakeJSONPair_('resolved', BooleanToJSON_(mirror.resolved())));
+    if (mirror.resolved()) {
+      content.push(MakeJSONPair_('source', StringToJSON_(mirror.source())));
+    }
+    if (mirror.script()) {
+      content.push(MakeJSONPair_('script', this.serializeReference(mirror.script())));
+    }
+  }
+
+  // Add date specific properties.
+  if (mirror.isDate()) {
+    // Add date specific properties.
+    content.push(MakeJSONPair_('value', DateToJSON_(mirror.value())));
+  }
+
+  // Add actual properties - named properties followed by indexed properties.
+  var propertyNames = mirror.propertyNames(PropertyKind.Named);
+  var propertyIndexes = mirror.propertyNames(PropertyKind.Indexed);
+  var p = new Array(propertyNames.length + propertyIndexes.length);
+  for (var i = 0; i < propertyNames.length; i++) {
+    var property_mirror = mirror.property(propertyNames[i]);
+    p[i] = this.serializeProperty_(property_mirror);
+    if (details) {
+      this.add_(property_mirror.value());
+    }
+  }
+  for (var i = 0; i < propertyIndexes.length; i++) {
+    var property_mirror = mirror.property(propertyIndexes[i]);
+    p[propertyNames.length + i] = this.serializeProperty_(property_mirror);
+    if (details) {
+      this.add_(property_mirror.value());
+    }
+  }
+  content.push(MakeJSONPair_('properties', ArrayToJSONArray_(p)));
+}
+
+
+/**
+ * Serialize property information to the following JSON format for building the
+ * array of properties.
+ *
+ *   {"name":"<property name>",
+ *    "attributes":<number>,
+ *    "propertyType":<number>,
+ *    "ref":<number>}
+ *
+ * If the attribute for the property is PropertyAttribute.None it is not added.
+ * If the propertyType for the property is PropertyType.Normal it is not added.
+ * Here are a couple of examples.
+ *
+ *   {"name":"hello","ref":1}
+ *   {"name":"length","attributes":7,"propertyType":3,"ref":2}
+ *
+ * @param {PropertyMirror} property_mirror The property to serialize
+ * @returns {String} JSON serialization
+ */
+JSONProtocolSerializer.prototype.serializeProperty_ = function(property_mirror) {
+  var builder = new builtins.StringBuilder();
+  builder.add('{"name":');
+  builder.add(StringToJSON_(property_mirror.name()));
+  if (property_mirror.attributes() != PropertyAttribute.None) {
+    builder.add(',"attributes":');
+    builder.add(NumberToJSON_(property_mirror.attributes()));
+  }
+  if (property_mirror.propertyType() != PropertyType.Normal) {
+    builder.add(',"propertyType":');
+    builder.add(NumberToJSON_(property_mirror.propertyType()));
+  }
+  builder.add(',"ref":');
+  builder.add(NumberToJSON_(property_mirror.value().handle()));
+  builder.add('}');
+  return builder.generate();
+}
+
+
+JSONProtocolSerializer.prototype.serializeFrame_ = function(mirror, content) {
+  content.push(MakeJSONPair_('index', NumberToJSON_(mirror.index())));
+  content.push(MakeJSONPair_('receiver',
+                             this.serializeReference(mirror.receiver())));
+  var func = mirror.func();
+  content.push(MakeJSONPair_('func', this.serializeReference(func)));
+  if (func.script()) {
+    content.push(MakeJSONPair_('script',
+                               this.serializeReference(func.script())));
+  }
+  content.push(MakeJSONPair_('constructCall',
+                             BooleanToJSON_(mirror.isConstructCall())));
+  content.push(MakeJSONPair_('debuggerFrame',
+                             BooleanToJSON_(mirror.isDebuggerFrame())));
+  var x = new Array(mirror.argumentCount());
+  for (var i = 0; i < mirror.argumentCount(); i++) {
+    arg = new Array();
+    var argument_name = mirror.argumentName(i)
+    if (argument_name) {
+      arg.push(MakeJSONPair_('name', StringToJSON_(argument_name)));
+    }
+    arg.push(MakeJSONPair_('value',
+                           this.serializeReference(mirror.argumentValue(i))));
+    x[i] = ArrayToJSONObject_(arg);
+  }
+  content.push(MakeJSONPair_('arguments', ArrayToJSONArray_(x)));
+  var x = new Array(mirror.localCount());
+  for (var i = 0; i < mirror.localCount(); i++) {
+    var name = MakeJSONPair_('name', StringToJSON_(mirror.localName(i)));
+    var value = MakeJSONPair_('value',
+                              this.serializeReference(mirror.localValue(i)));
+    x[i] = '{' + name + ',' + value + '}';
+  }
+  content.push(MakeJSONPair_('locals', ArrayToJSONArray_(x)));
+  content.push(MakeJSONPair_('position',
+                             NumberToJSON_(mirror.sourcePosition())));
+  var line = mirror.sourceLine();
+  if (!IS_UNDEFINED(line)) {
+    content.push(MakeJSONPair_('line', NumberToJSON_(line)));
+  }
+  var column = mirror.sourceColumn();
+  if (!IS_UNDEFINED(column)) {
+    content.push(MakeJSONPair_('column', NumberToJSON_(column)));
+  }
+  var source_line_text = mirror.sourceLineText();
+  if (!IS_UNDEFINED(source_line_text)) {
+    content.push(MakeJSONPair_('sourceLineText',
+                               StringToJSON_(source_line_text)));
+  }
+}
+
+
+function MakeJSONPair_(name, value) {
+  return '"' + name + '":' + value;
+}
+
+
+function ArrayToJSONObject_(content) {
+  return '{' + content.join(',') + '}';
+}
+
+
+function ArrayToJSONArray_(content) {
+  return '[' + content.join(',') + ']';
+}
+
+
+function BooleanToJSON_(value) {
+  return String(value); 
+}
+
+
+/**
+ * Convert a number to a JSON string value. For all finite numbers the number
+ * literal representation is used. For non finite numbers NaN, Infinite and
+ * -Infinite the string representation "NaN", "Infinite" or "-Infinite"
+ * (including the quotes) is returned.
+ *
+ * @param {number} value The number value to convert to a JSON value
+ * @returns {String} JSON value
+ */
+function NumberToJSON_(value) {
+  if (isNaN(value)) {
+    return '"NaN"';
+  }
+  if (!isFinite(value)) {
+    if (value > 0) {
+      return '"Infinity"';
+    } else {
+      return '"-Infinity"';
+    }
+  }
+  return String(value); 
+}
+
+
+// Mapping of some control characters to avoid the \uXXXX syntax for most
+// commonly used control cahracters.
+const ctrlCharMap_ = {
+  '\b': '\\b',
+  '\t': '\\t',
+  '\n': '\\n',
+  '\f': '\\f',
+  '\r': '\\r',
+  '"' : '\\"',
+  '\\': '\\\\'
+};
+
+
+// Regular expression testing for ", \ and control characters (0x00 - 0x1F).
+const ctrlCharTest_ = new RegExp('["\\\\\x00-\x1F]');
+
+
+// Regular expression matching ", \ and control characters (0x00 - 0x1F)
+// globally.
+const ctrlCharMatch_ = new RegExp('["\\\\\x00-\x1F]', 'g');
+
+
+/**
+ * Convert a String to its JSON representation (see http://www.json.org/). To
+ * avoid depending on the String object this method calls the functions in
+ * string.js directly and not through the value.
+ * @param {String} value The String value to format as JSON
+ * @return {string} JSON formatted String value
+ */
+function StringToJSON_(value) {
+  // Check for" , \ and control characters (0x00 - 0x1F). No need to call
+  // RegExpTest as ctrlchar is constructed using RegExp.
+  if (ctrlCharTest_.test(value)) {
+    // Replace ", \ and control characters (0x00 - 0x1F).
+    return '"' +
+      value.replace(ctrlCharMatch_, function (char) {
+        // Use charmap if possible.
+        var mapped = ctrlCharMap_[char];
+        if (mapped) return mapped;
+        mapped = char.charCodeAt();
+        // Convert control character to unicode escape sequence.
+        return '\\u00' +
+          %NumberToRadixString(Math.floor(mapped / 16), 16) +
+          %NumberToRadixString(mapped % 16, 16);
+      })
+    + '"';
+  }
+
+  // Simple string with no special characters.
+  return '"' + value + '"';
+}
+
+
+/**
+ * Convert a Date to ISO 8601 format. To avoid depending on the Date object
+ * this method calls the functions in date.js directly and not through the
+ * value.
+ * @param {Date} value The Date value to format as JSON
+ * @return {string} JSON formatted Date value
+ */
+function DateToISO8601_(value) {
+  function f(n) {
+    return n < 10 ? '0' + n : n;
+  }
+  function g(n) {
+    return n < 10 ? '00' + n : n < 100 ? '0' + n : n;
+  }
+  return builtins.GetUTCFullYearFrom(value)         + '-' +
+          f(builtins.GetUTCMonthFrom(value) + 1)    + '-' +
+          f(builtins.GetUTCDateFrom(value))         + 'T' +
+          f(builtins.GetUTCHoursFrom(value))        + ':' +
+          f(builtins.GetUTCMinutesFrom(value))      + ':' +
+          f(builtins.GetUTCSecondsFrom(value))      + '.' +
+          g(builtins.GetUTCMillisecondsFrom(value)) + 'Z';
+}
+
+/**
+ * Convert a Date to ISO 8601 format. To avoid depending on the Date object
+ * this method calls the functions in date.js directly and not through the
+ * value.
+ * @param {Date} value The Date value to format as JSON
+ * @return {string} JSON formatted Date value
+ */
+function DateToJSON_(value) {
+  return '"' + DateToISO8601_(value) + '"';
+}
diff --git a/deps/v8/src/mksnapshot.cc b/deps/v8/src/mksnapshot.cc
new file mode 100644
index 0000000..4891f37
--- /dev/null
+++ b/deps/v8/src/mksnapshot.cc
@@ -0,0 +1,186 @@
+// 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.
+
+#include <signal.h>
+#include <string>
+#include <map>
+
+#include "v8.h"
+
+#include "bootstrapper.h"
+#include "natives.h"
+#include "platform.h"
+#include "serialize.h"
+
+// use explicit namespace to avoid clashing with types in namespace v8
+namespace i = v8::internal;
+using namespace v8;
+
+static const unsigned int kMaxCounters = 256;
+
+// A single counter in a counter collection.
+class Counter {
+ public:
+  static const int kMaxNameSize = 64;
+  int32_t* Bind(const char* name) {
+    int i;
+    for (i = 0; i < kMaxNameSize - 1 && name[i]; i++) {
+      name_[i] = name[i];
+    }
+    name_[i] = '\0';
+    return &counter_;
+  }
+ private:
+  int32_t counter_;
+  uint8_t name_[kMaxNameSize];
+};
+
+
+// A set of counters and associated information.  An instance of this
+// class is stored directly in the memory-mapped counters file if
+// the --save-counters options is used
+class CounterCollection {
+ public:
+  CounterCollection() {
+    magic_number_ = 0xDEADFACE;
+    max_counters_ = kMaxCounters;
+    max_name_size_ = Counter::kMaxNameSize;
+    counters_in_use_ = 0;
+  }
+  Counter* GetNextCounter() {
+    if (counters_in_use_ == kMaxCounters) return NULL;
+    return &counters_[counters_in_use_++];
+  }
+ private:
+  uint32_t magic_number_;
+  uint32_t max_counters_;
+  uint32_t max_name_size_;
+  uint32_t counters_in_use_;
+  Counter counters_[kMaxCounters];
+};
+
+
+// We statically allocate a set of local counters to be used if we
+// don't want to store the stats in a memory-mapped file
+static CounterCollection local_counters;
+static CounterCollection* counters = &local_counters;
+
+
+typedef std::map<std::string, int*> CounterMap;
+typedef std::map<std::string, int*>::iterator CounterMapIterator;
+static CounterMap counter_table_;
+
+// Callback receiver when v8 has a counter to track.
+static int* counter_callback(const char* name) {
+  std::string counter = name;
+  // See if this counter name is already known.
+  if (counter_table_.find(counter) != counter_table_.end())
+    return counter_table_[counter];
+
+  Counter* ctr = counters->GetNextCounter();
+  if (ctr == NULL) return NULL;
+  int* ptr = ctr->Bind(name);
+  counter_table_[counter] = ptr;
+  return ptr;
+}
+
+
+// Write C++ code that defines Snapshot::snapshot_ to contain the snapshot
+// to the file given by filename. Only the first size chars are written.
+static int WriteInternalSnapshotToFile(const char* filename,
+                                       const v8::internal::byte* bytes,
+                                       int size) {
+  FILE* f = i::OS::FOpen(filename, "wb");
+  if (f == NULL) {
+    i::OS::PrintError("Cannot open file %s for reading.\n", filename);
+    return 0;
+  }
+  fprintf(f, "// Autogenerated snapshot file. Do not edit.\n\n");
+  fprintf(f, "#include \"v8.h\"\n");
+  fprintf(f, "#include \"platform.h\"\n\n");
+  fprintf(f, "#include \"snapshot.h\"\n\n");
+  fprintf(f, "namespace v8 {\nnamespace internal {\n\n");
+  fprintf(f, "const byte Snapshot::data_[] = {");
+  int written = 0;
+  written += fprintf(f, "0x%x", bytes[0]);
+  for (int i = 1; i < size; ++i) {
+    written += fprintf(f, ",0x%x", bytes[i]);
+    // The following is needed to keep the line length low on Visual C++:
+    if (i % 512 == 0) fprintf(f, "\n");
+  }
+  fprintf(f, "};\n\n");
+  fprintf(f, "int Snapshot::size_ = %d;\n\n", size);
+  fprintf(f, "} }  // namespace v8::internal\n");
+  fclose(f);
+  return written;
+}
+
+
+int main(int argc, char** argv) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  // By default, log code create information in the snapshot.
+  i::FLAG_log_code = true;
+#endif
+  // Print the usage if an error occurs when parsing the command line
+  // flags or if the help flag is set.
+  int result = i::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
+  if (result > 0 || argc != 2 || i::FLAG_help) {
+    ::printf("Usage: %s [flag] ... outfile\n", argv[0]);
+    i::FlagList::PrintHelp();
+    return !i::FLAG_help;
+  }
+
+  v8::V8::SetCounterFunction(counter_callback);
+  v8::HandleScope scope;
+
+  const int kExtensionCount = 1;
+  const char* extension_list[kExtensionCount] = { "v8/gc" };
+  v8::ExtensionConfiguration extensions(kExtensionCount, extension_list);
+
+  i::Serializer::Enable();
+  v8::Context::New(&extensions);
+
+  // Make sure all builtin scripts are cached.
+  { HandleScope scope;
+    for (int i = 0; i < i::Natives::GetBuiltinsCount(); i++) {
+      i::Bootstrapper::NativesSourceLookup(i);
+    }
+  }
+  // Get rid of unreferenced scripts with a global GC.
+  i::Heap::CollectAllGarbage();
+  i::Serializer ser;
+  ser.Serialize();
+  v8::internal::byte* bytes;
+  int len;
+  ser.Finalize(&bytes, &len);
+
+  WriteInternalSnapshotToFile(argv[1], bytes, len);
+
+  i::DeleteArray(bytes);
+
+  return 0;
+}
diff --git a/deps/v8/src/natives.h b/deps/v8/src/natives.h
new file mode 100644
index 0000000..3eb8090
--- /dev/null
+++ b/deps/v8/src/natives.h
@@ -0,0 +1,62 @@
+// 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_NATIVES_H_
+#define V8_NATIVES_H_
+
+namespace v8 { namespace internal {
+
+typedef bool (*NativeSourceCallback)(Vector<const char> name,
+                                     Vector<const char> source,
+                                     int index);
+
+enum NativeType {
+  CORE, D8
+};
+
+template <NativeType type>
+class NativesCollection {
+ public:
+  // Number of built-in scripts.
+  static int GetBuiltinsCount();
+  // Number of delayed/lazy loading scripts.
+  static int GetDelayCount();
+
+  // These are used to access built-in scripts.
+  // The delayed script has an index in the interval [0, GetDelayCount()).
+  // The non-delayed script has an index in the interval
+  // [GetDelayCount(), GetNativesCount()).
+  static int GetIndex(const char* name);
+  static Vector<const char> GetScriptSource(int index);
+  static Vector<const char> GetScriptName(int index);
+};
+
+typedef NativesCollection<CORE> Natives;
+
+} }  // namespace v8::internal
+
+#endif  // V8_NATIVES_H_
diff --git a/deps/v8/src/objects-debug.cc b/deps/v8/src/objects-debug.cc
new file mode 100644
index 0000000..f40fd3e
--- /dev/null
+++ b/deps/v8/src/objects-debug.cc
@@ -0,0 +1,1094 @@
+// 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.
+
+#include "v8.h"
+
+#include "disassembler.h"
+#include "disasm.h"
+#include "macro-assembler.h"
+#include "jsregexp.h"
+
+namespace v8 { namespace internal {
+
+#ifdef DEBUG
+
+static const char* TypeToString(InstanceType type);
+
+
+void Object::Print() {
+  if (IsSmi()) {
+    Smi::cast(this)->SmiPrint();
+  } else if (IsFailure()) {
+    Failure::cast(this)->FailurePrint();
+  } else {
+    HeapObject::cast(this)->HeapObjectPrint();
+  }
+  Flush();
+}
+
+
+void Object::PrintLn() {
+  Print();
+  PrintF("\n");
+}
+
+
+void Object::Verify() {
+  if (IsSmi()) {
+    Smi::cast(this)->SmiVerify();
+  } else if (IsFailure()) {
+    Failure::cast(this)->FailureVerify();
+  } else {
+    HeapObject::cast(this)->HeapObjectVerify();
+  }
+}
+
+
+void Object::VerifyPointer(Object* p) {
+  if (p->IsHeapObject()) {
+    HeapObject::VerifyHeapPointer(p);
+  } else {
+    ASSERT(p->IsSmi());
+  }
+}
+
+
+void Smi::SmiVerify() {
+  ASSERT(IsSmi());
+}
+
+
+void Failure::FailureVerify() {
+  ASSERT(IsFailure());
+}
+
+
+void HeapObject::PrintHeader(const char* id) {
+  PrintF("%p: [%s]\n", this, id);
+}
+
+
+void HeapObject::HeapObjectPrint() {
+  InstanceType instance_type = map()->instance_type();
+
+  HandleScope scope;
+  if (instance_type < FIRST_NONSTRING_TYPE) {
+    String::cast(this)->StringPrint();
+    return;
+  }
+
+  switch (instance_type) {
+    case MAP_TYPE:
+      Map::cast(this)->MapPrint();
+      break;
+    case HEAP_NUMBER_TYPE:
+      HeapNumber::cast(this)->HeapNumberPrint();
+      break;
+    case FIXED_ARRAY_TYPE:
+      FixedArray::cast(this)->FixedArrayPrint();
+      break;
+    case BYTE_ARRAY_TYPE:
+      ByteArray::cast(this)->ByteArrayPrint();
+      break;
+    case FILLER_TYPE:
+      PrintF("filler");
+      break;
+    case JS_OBJECT_TYPE:  // fall through
+    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
+    case JS_ARRAY_TYPE:
+    case JS_REGEXP_TYPE:
+      JSObject::cast(this)->JSObjectPrint();
+      break;
+    case ODDBALL_TYPE:
+      Oddball::cast(this)->to_string()->Print();
+      break;
+    case JS_FUNCTION_TYPE:
+      JSFunction::cast(this)->JSFunctionPrint();
+      break;
+    case JS_GLOBAL_PROXY_TYPE:
+      JSGlobalProxy::cast(this)->JSGlobalProxyPrint();
+      break;
+    case JS_GLOBAL_OBJECT_TYPE:
+      JSGlobalObject::cast(this)->JSGlobalObjectPrint();
+      break;
+    case JS_BUILTINS_OBJECT_TYPE:
+      JSBuiltinsObject::cast(this)->JSBuiltinsObjectPrint();
+      break;
+    case JS_VALUE_TYPE:
+      PrintF("Value wrapper around:");
+      JSValue::cast(this)->value()->Print();
+      break;
+    case CODE_TYPE:
+      Code::cast(this)->CodePrint();
+      break;
+    case PROXY_TYPE:
+      Proxy::cast(this)->ProxyPrint();
+      break;
+    case SHARED_FUNCTION_INFO_TYPE:
+      SharedFunctionInfo::cast(this)->SharedFunctionInfoPrint();
+      break;
+
+#define MAKE_STRUCT_CASE(NAME, Name, name) \
+  case NAME##_TYPE:                        \
+    Name::cast(this)->Name##Print();       \
+    break;
+  STRUCT_LIST(MAKE_STRUCT_CASE)
+#undef MAKE_STRUCT_CASE
+
+    default:
+      PrintF("UNKNOWN TYPE %d", map()->instance_type());
+      UNREACHABLE();
+      break;
+  }
+}
+
+
+void HeapObject::HeapObjectVerify() {
+  InstanceType instance_type = map()->instance_type();
+
+  if (instance_type < FIRST_NONSTRING_TYPE) {
+    String::cast(this)->StringVerify();
+    return;
+  }
+
+  switch (instance_type) {
+    case MAP_TYPE:
+      Map::cast(this)->MapVerify();
+      break;
+    case HEAP_NUMBER_TYPE:
+      HeapNumber::cast(this)->HeapNumberVerify();
+      break;
+    case FIXED_ARRAY_TYPE:
+      FixedArray::cast(this)->FixedArrayVerify();
+      break;
+    case BYTE_ARRAY_TYPE:
+      ByteArray::cast(this)->ByteArrayVerify();
+      break;
+    case CODE_TYPE:
+      Code::cast(this)->CodeVerify();
+      break;
+    case ODDBALL_TYPE:
+      Oddball::cast(this)->OddballVerify();
+      break;
+    case JS_OBJECT_TYPE:
+    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
+      JSObject::cast(this)->JSObjectVerify();
+      break;
+    case JS_VALUE_TYPE:
+      JSValue::cast(this)->JSValueVerify();
+      break;
+    case JS_FUNCTION_TYPE:
+      JSFunction::cast(this)->JSFunctionVerify();
+      break;
+    case JS_GLOBAL_PROXY_TYPE:
+      JSGlobalProxy::cast(this)->JSGlobalProxyVerify();
+      break;
+    case JS_GLOBAL_OBJECT_TYPE:
+      JSGlobalObject::cast(this)->JSGlobalObjectVerify();
+      break;
+    case JS_BUILTINS_OBJECT_TYPE:
+      JSBuiltinsObject::cast(this)->JSBuiltinsObjectVerify();
+      break;
+    case JS_ARRAY_TYPE:
+      JSArray::cast(this)->JSArrayVerify();
+      break;
+    case JS_REGEXP_TYPE:
+      JSRegExp::cast(this)->JSRegExpVerify();
+      break;
+    case FILLER_TYPE:
+      break;
+    case PROXY_TYPE:
+      Proxy::cast(this)->ProxyVerify();
+      break;
+    case SHARED_FUNCTION_INFO_TYPE:
+      SharedFunctionInfo::cast(this)->SharedFunctionInfoVerify();
+      break;
+
+#define MAKE_STRUCT_CASE(NAME, Name, name) \
+  case NAME##_TYPE:                        \
+    Name::cast(this)->Name##Verify();      \
+    break;
+    STRUCT_LIST(MAKE_STRUCT_CASE)
+#undef MAKE_STRUCT_CASE
+
+    default:
+      UNREACHABLE();
+      break;
+  }
+}
+
+
+void HeapObject::VerifyHeapPointer(Object* p) {
+  ASSERT(p->IsHeapObject());
+  ASSERT(Heap::Contains(HeapObject::cast(p)));
+}
+
+
+void HeapNumber::HeapNumberVerify() {
+  ASSERT(IsHeapNumber());
+}
+
+
+void ByteArray::ByteArrayPrint() {
+  PrintF("byte array, data starts at %p", GetDataStartAddress());
+}
+
+
+void ByteArray::ByteArrayVerify() {
+  ASSERT(IsByteArray());
+}
+
+
+void JSObject::PrintProperties() {
+  if (HasFastProperties()) {
+    for (DescriptorReader r(map()->instance_descriptors());
+         !r.eos();
+         r.advance()) {
+      PrintF("   ");
+      r.GetKey()->StringPrint();
+      PrintF(": ");
+      if (r.type() == FIELD) {
+        FastPropertyAt(r.GetFieldIndex())->ShortPrint();
+        PrintF(" (field at offset %d)\n", r.GetFieldIndex());
+      } else if (r.type() ==  CONSTANT_FUNCTION) {
+        r.GetConstantFunction()->ShortPrint();
+        PrintF(" (constant function)\n");
+      } else if (r.type() == CALLBACKS) {
+        r.GetCallbacksObject()->ShortPrint();
+        PrintF(" (callback)\n");
+      } else if (r.type() == MAP_TRANSITION) {
+        PrintF(" (map transition)\n");
+      } else if (r.type() == CONSTANT_TRANSITION) {
+        PrintF(" (constant transition)\n");
+      } else if (r.type() == NULL_DESCRIPTOR) {
+        PrintF(" (null descriptor)\n");
+      } else {
+        UNREACHABLE();
+      }
+    }
+  } else {
+    property_dictionary()->Print();
+  }
+}
+
+
+void JSObject::PrintElements() {
+  if (HasFastElements()) {
+    FixedArray* p = FixedArray::cast(elements());
+    for (int i = 0; i < p->length(); i++) {
+      PrintF("   %d: ", i);
+      p->get(i)->ShortPrint();
+      PrintF("\n");
+    }
+  } else {
+    elements()->Print();
+  }
+}
+
+
+void JSObject::JSObjectPrint() {
+  PrintF("%p: [JSObject]\n", this);
+  PrintF(" - map = %p\n", map());
+  PrintF(" - prototype = %p\n", GetPrototype());
+  PrintF(" {\n");
+  PrintProperties();
+  PrintElements();
+  PrintF(" }\n");
+}
+
+
+void JSObject::JSObjectVerify() {
+  VerifyHeapPointer(properties());
+  VerifyHeapPointer(elements());
+  if (HasFastProperties()) {
+    CHECK(map()->unused_property_fields() ==
+          (map()->inobject_properties() + properties()->length() -
+           map()->NextFreePropertyIndex()));
+  }
+}
+
+
+static const char* TypeToString(InstanceType type) {
+  switch (type) {
+    case INVALID_TYPE: return "INVALID";
+    case MAP_TYPE: return "MAP";
+    case HEAP_NUMBER_TYPE: return "HEAP_NUMBER";
+    case SHORT_SYMBOL_TYPE:
+    case MEDIUM_SYMBOL_TYPE:
+    case LONG_SYMBOL_TYPE: return "SYMBOL";
+    case SHORT_ASCII_SYMBOL_TYPE:
+    case MEDIUM_ASCII_SYMBOL_TYPE:
+    case LONG_ASCII_SYMBOL_TYPE: return "ASCII_SYMBOL";
+    case SHORT_SLICED_SYMBOL_TYPE:
+    case MEDIUM_SLICED_SYMBOL_TYPE:
+    case LONG_SLICED_SYMBOL_TYPE: return "SLICED_SYMBOL";
+    case SHORT_SLICED_ASCII_SYMBOL_TYPE:
+    case MEDIUM_SLICED_ASCII_SYMBOL_TYPE:
+    case LONG_SLICED_ASCII_SYMBOL_TYPE: return "SLICED_ASCII_SYMBOL";
+    case SHORT_CONS_SYMBOL_TYPE:
+    case MEDIUM_CONS_SYMBOL_TYPE:
+    case LONG_CONS_SYMBOL_TYPE: return "CONS_SYMBOL";
+    case SHORT_CONS_ASCII_SYMBOL_TYPE:
+    case MEDIUM_CONS_ASCII_SYMBOL_TYPE:
+    case LONG_CONS_ASCII_SYMBOL_TYPE: return "CONS_ASCII_SYMBOL";
+    case SHORT_EXTERNAL_ASCII_SYMBOL_TYPE:
+    case MEDIUM_EXTERNAL_ASCII_SYMBOL_TYPE:
+    case LONG_EXTERNAL_ASCII_SYMBOL_TYPE:
+    case SHORT_EXTERNAL_SYMBOL_TYPE:
+    case MEDIUM_EXTERNAL_SYMBOL_TYPE:
+    case LONG_EXTERNAL_SYMBOL_TYPE: return "EXTERNAL_SYMBOL";
+    case SHORT_ASCII_STRING_TYPE:
+    case MEDIUM_ASCII_STRING_TYPE:
+    case LONG_ASCII_STRING_TYPE: return "ASCII_STRING";
+    case SHORT_STRING_TYPE:
+    case MEDIUM_STRING_TYPE:
+    case LONG_STRING_TYPE: return "TWO_BYTE_STRING";
+    case SHORT_CONS_STRING_TYPE:
+    case MEDIUM_CONS_STRING_TYPE:
+    case LONG_CONS_STRING_TYPE:
+    case SHORT_CONS_ASCII_STRING_TYPE:
+    case MEDIUM_CONS_ASCII_STRING_TYPE:
+    case LONG_CONS_ASCII_STRING_TYPE: return "CONS_STRING";
+    case SHORT_SLICED_STRING_TYPE:
+    case MEDIUM_SLICED_STRING_TYPE:
+    case LONG_SLICED_STRING_TYPE:
+    case SHORT_SLICED_ASCII_STRING_TYPE:
+    case MEDIUM_SLICED_ASCII_STRING_TYPE:
+    case LONG_SLICED_ASCII_STRING_TYPE: return "SLICED_STRING";
+    case SHORT_EXTERNAL_ASCII_STRING_TYPE:
+    case MEDIUM_EXTERNAL_ASCII_STRING_TYPE:
+    case LONG_EXTERNAL_ASCII_STRING_TYPE:
+    case SHORT_EXTERNAL_STRING_TYPE:
+    case MEDIUM_EXTERNAL_STRING_TYPE:
+    case LONG_EXTERNAL_STRING_TYPE: return "EXTERNAL_STRING";
+    case FIXED_ARRAY_TYPE: return "FIXED_ARRAY";
+    case BYTE_ARRAY_TYPE: return "BYTE_ARRAY";
+    case FILLER_TYPE: return "FILLER";
+    case JS_OBJECT_TYPE: return "JS_OBJECT";
+    case JS_CONTEXT_EXTENSION_OBJECT_TYPE: return "JS_CONTEXT_EXTENSION_OBJECT";
+    case ODDBALL_TYPE: return "ODDBALL";
+    case SHARED_FUNCTION_INFO_TYPE: return "SHARED_FUNCTION_INFO";
+    case JS_FUNCTION_TYPE: return "JS_FUNCTION";
+    case CODE_TYPE: return "CODE";
+    case JS_ARRAY_TYPE: return "JS_ARRAY";
+    case JS_REGEXP_TYPE: return "JS_REGEXP";
+    case JS_VALUE_TYPE: return "JS_VALUE";
+    case JS_GLOBAL_OBJECT_TYPE: return "JS_GLOBAL_OBJECT";
+    case JS_BUILTINS_OBJECT_TYPE: return "JS_BUILTINS_OBJECT";
+    case JS_GLOBAL_PROXY_TYPE: return "JS_GLOBAL_PROXY";
+    case PROXY_TYPE: return "PROXY";
+    case SMI_TYPE: return "SMI";
+#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return #NAME;
+  STRUCT_LIST(MAKE_STRUCT_CASE)
+#undef MAKE_STRUCT_CASE
+  }
+  return "UNKNOWN";
+}
+
+
+void Map::MapPrint() {
+  HeapObject::PrintHeader("Map");
+  PrintF(" - type: %s\n", TypeToString(instance_type()));
+  PrintF(" - instance size: %d\n", instance_size());
+  PrintF(" - unused property fields: %d\n", unused_property_fields());
+  if (is_hidden_prototype()) {
+    PrintF(" - hidden_prototype\n");
+  }
+  if (has_named_interceptor()) {
+    PrintF(" - named_interceptor\n");
+  }
+  if (has_indexed_interceptor()) {
+    PrintF(" - indexed_interceptor\n");
+  }
+  if (is_undetectable()) {
+    PrintF(" - undetectable\n");
+  }
+  if (has_instance_call_handler()) {
+    PrintF(" - instance_call_handler\n");
+  }
+  if (is_access_check_needed()) {
+    PrintF(" - access_check_needed\n");
+  }
+  PrintF(" - instance descriptors: ");
+  instance_descriptors()->ShortPrint();
+  PrintF("\n - prototype: ");
+  prototype()->ShortPrint();
+  PrintF("\n - constructor: ");
+  constructor()->ShortPrint();
+  PrintF("\n");
+}
+
+
+void Map::MapVerify() {
+  ASSERT(!Heap::InNewSpace(this));
+  ASSERT(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE);
+  ASSERT(kPointerSize <= instance_size()
+         && instance_size() < Heap::Capacity());
+  VerifyHeapPointer(prototype());
+  VerifyHeapPointer(instance_descriptors());
+}
+
+
+void FixedArray::FixedArrayPrint() {
+  HeapObject::PrintHeader("FixedArray");
+  PrintF(" - length: %d", length());
+  for (int i = 0; i < length(); i++) {
+    PrintF("\n  [%d]: ", i);
+    get(i)->ShortPrint();
+  }
+  PrintF("\n");
+}
+
+
+void FixedArray::FixedArrayVerify() {
+  for (int i = 0; i < length(); i++) {
+    Object* e = get(i);
+    if (e->IsHeapObject()) {
+      VerifyHeapPointer(e);
+    } else {
+      e->Verify();
+    }
+  }
+}
+
+
+void JSValue::JSValuePrint() {
+  HeapObject::PrintHeader("ValueObject");
+  value()->Print();
+}
+
+
+void JSValue::JSValueVerify() {
+  Object* v = value();
+  if (v->IsHeapObject()) {
+    VerifyHeapPointer(v);
+  }
+}
+
+
+void String::StringPrint() {
+  if (StringShape(this).IsSymbol()) {
+    PrintF("#");
+  } else if (StringShape(this).IsCons()) {
+    PrintF("c\"");
+  } else {
+    PrintF("\"");
+  }
+
+  for (int i = 0; i < length(); i++) {
+    PrintF("%c", Get(i));
+  }
+
+  if (!StringShape(this).IsSymbol()) PrintF("\"");
+}
+
+
+void String::StringVerify() {
+  CHECK(IsString());
+  CHECK(length() >= 0 && length() <= Smi::kMaxValue);
+  if (IsSymbol()) {
+    CHECK(!Heap::InNewSpace(this));
+  }
+}
+
+
+void JSFunction::JSFunctionPrint() {
+  HeapObject::PrintHeader("Function");
+  PrintF(" - map = 0x%p\n", map());
+  PrintF(" - is boilerplate: %s\n", IsBoilerplate() ? "yes" : "no");
+  PrintF(" - initial_map = ");
+  if (has_initial_map()) {
+    initial_map()->ShortPrint();
+  }
+  PrintF("\n - shared_info = ");
+  shared()->ShortPrint();
+  PrintF("\n   - name = ");
+  shared()->name()->Print();
+  PrintF("\n - context = ");
+  unchecked_context()->ShortPrint();
+  PrintF("\n - code = ");
+  code()->ShortPrint();
+  PrintF("\n");
+
+  PrintProperties();
+  PrintElements();
+
+  PrintF("\n");
+}
+
+
+void JSFunction::JSFunctionVerify() {
+  CHECK(IsJSFunction());
+  VerifyObjectField(kPrototypeOrInitialMapOffset);
+}
+
+
+void SharedFunctionInfo::SharedFunctionInfoPrint() {
+  HeapObject::PrintHeader("SharedFunctionInfo");
+  PrintF(" - name: ");
+  name()->ShortPrint();
+  PrintF("\n - expected_nof_properties: %d", expected_nof_properties());
+  PrintF("\n - instance class name = ");
+  instance_class_name()->Print();
+  PrintF("\n - code = ");
+  code()->ShortPrint();
+  PrintF("\n - source code = ");
+  GetSourceCode()->ShortPrint();
+  PrintF("\n - lazy load: %s",
+         lazy_load_data() == Heap::undefined_value() ? "no" : "yes");
+  // Script files are often large, hard to read.
+  // PrintF("\n - script =");
+  // script()->Print();
+  PrintF("\n - function token position = %d", function_token_position());
+  PrintF("\n - start position = %d", start_position());
+  PrintF("\n - end position = %d", end_position());
+  PrintF("\n - is expression = %d", is_expression());
+  PrintF("\n - debug info = ");
+  debug_info()->ShortPrint();
+  PrintF("\n - length = %d", length());
+  PrintF("\n");
+}
+
+void SharedFunctionInfo::SharedFunctionInfoVerify() {
+  CHECK(IsSharedFunctionInfo());
+  VerifyObjectField(kNameOffset);
+  VerifyObjectField(kCodeOffset);
+  VerifyObjectField(kInstanceClassNameOffset);
+  VerifyObjectField(kExternalReferenceDataOffset);
+  VerifyObjectField(kLazyLoadDataOffset);
+  VerifyObjectField(kScriptOffset);
+  VerifyObjectField(kDebugInfoOffset);
+}
+
+
+void JSGlobalProxy::JSGlobalProxyPrint() {
+  PrintF("global_proxy");
+  JSObjectPrint();
+  PrintF("context : ");
+  context()->ShortPrint();
+  PrintF("\n");
+}
+
+
+void JSGlobalProxy::JSGlobalProxyVerify() {
+  CHECK(IsJSGlobalProxy());
+  JSObjectVerify();
+  VerifyObjectField(JSGlobalProxy::kContextOffset);
+  // Make sure that this object has no properties, elements.
+  CHECK_EQ(0, properties()->length());
+  CHECK_EQ(0, elements()->length());
+}
+
+
+void JSGlobalObject::JSGlobalObjectPrint() {
+  PrintF("global ");
+  JSObjectPrint();
+  PrintF("global context : ");
+  global_context()->ShortPrint();
+  PrintF("\n");
+}
+
+
+void JSGlobalObject::JSGlobalObjectVerify() {
+  CHECK(IsJSGlobalObject());
+  JSObjectVerify();
+  for (int i = GlobalObject::kBuiltinsOffset;
+       i < JSGlobalObject::kSize;
+       i += kPointerSize) {
+    VerifyObjectField(i);
+  }
+}
+
+
+void JSBuiltinsObject::JSBuiltinsObjectPrint() {
+  PrintF("builtins ");
+  JSObjectPrint();
+}
+
+
+void JSBuiltinsObject::JSBuiltinsObjectVerify() {
+  CHECK(IsJSBuiltinsObject());
+  JSObjectVerify();
+  for (int i = GlobalObject::kBuiltinsOffset;
+       i < JSBuiltinsObject::kSize;
+       i += kPointerSize) {
+    VerifyObjectField(i);
+  }
+}
+
+
+void Oddball::OddballVerify() {
+  CHECK(IsOddball());
+  VerifyHeapPointer(to_string());
+  Object* number = to_number();
+  if (number->IsHeapObject()) {
+    ASSERT(number == Heap::nan_value());
+  } else {
+    ASSERT(number->IsSmi());
+    int value = Smi::cast(number)->value();
+    ASSERT(value == 0 || value == 1 || value == -1);
+  }
+}
+
+
+void Code::CodePrint() {
+  HeapObject::PrintHeader("Code");
+#ifdef ENABLE_DISASSEMBLER
+  Disassemble(NULL);
+#endif
+}
+
+
+void Code::CodeVerify() {
+  CHECK(ic_flag() == IC_TARGET_IS_ADDRESS);
+  CHECK(IsAligned(reinterpret_cast<intptr_t>(instruction_start()),
+                  static_cast<intptr_t>(kCodeAlignment)));
+  Address last_gc_pc = NULL;
+  for (RelocIterator it(this); !it.done(); it.next()) {
+    it.rinfo()->Verify();
+    // Ensure that GC will not iterate twice over the same pointer.
+    if (RelocInfo::IsGCRelocMode(it.rinfo()->rmode())) {
+      CHECK(it.rinfo()->pc() != last_gc_pc);
+      last_gc_pc = it.rinfo()->pc();
+    }
+  }
+}
+
+
+void JSArray::JSArrayVerify() {
+  JSObjectVerify();
+  ASSERT(length()->IsNumber() || length()->IsUndefined());
+  ASSERT(elements()->IsUndefined() || elements()->IsFixedArray());
+}
+
+
+void JSRegExp::JSRegExpVerify() {
+  JSObjectVerify();
+  ASSERT(data()->IsUndefined() || data()->IsFixedArray());
+  switch (TypeTag()) {
+    case JSRegExp::ATOM: {
+      FixedArray* arr = FixedArray::cast(data());
+      ASSERT(arr->get(JSRegExp::kAtomPatternIndex)->IsString());
+      break;
+    }
+    case JSRegExp::IRREGEXP: {
+      bool is_native = RegExpImpl::UseNativeRegexp();
+
+      FixedArray* arr = FixedArray::cast(data());
+      Object* ascii_data = arr->get(JSRegExp::kIrregexpASCIICodeIndex);
+      ASSERT(ascii_data->IsTheHole()
+          || (is_native ? ascii_data->IsCode() : ascii_data->IsByteArray()));
+      Object* uc16_data = arr->get(JSRegExp::kIrregexpUC16CodeIndex);
+      ASSERT(uc16_data->IsTheHole()
+          || (is_native ? uc16_data->IsCode() : uc16_data->IsByteArray()));
+      ASSERT(arr->get(JSRegExp::kIrregexpCaptureCountIndex)->IsSmi());
+      ASSERT(arr->get(JSRegExp::kIrregexpMaxRegisterCountIndex)->IsSmi());
+      break;
+    }
+    default:
+      ASSERT_EQ(JSRegExp::NOT_COMPILED, TypeTag());
+      ASSERT(data()->IsUndefined());
+      break;
+  }
+}
+
+
+void Proxy::ProxyPrint() {
+  PrintF("proxy to %p", proxy());
+}
+
+
+void Proxy::ProxyVerify() {
+  ASSERT(IsProxy());
+}
+
+
+void Dictionary::Print() {
+  int capacity = Capacity();
+  for (int i = 0; i < capacity; i++) {
+    Object* k = KeyAt(i);
+    if (IsKey(k)) {
+      PrintF(" ");
+      if (k->IsString()) {
+        String::cast(k)->StringPrint();
+      } else {
+        k->ShortPrint();
+      }
+      PrintF(": ");
+      ValueAt(i)->ShortPrint();
+      PrintF("\n");
+    }
+  }
+}
+
+
+void AccessorInfo::AccessorInfoVerify() {
+  CHECK(IsAccessorInfo());
+  VerifyPointer(getter());
+  VerifyPointer(setter());
+  VerifyPointer(name());
+  VerifyPointer(data());
+  VerifyPointer(flag());
+}
+
+void AccessorInfo::AccessorInfoPrint() {
+  HeapObject::PrintHeader("AccessorInfo");
+  PrintF("\n - getter: ");
+  getter()->ShortPrint();
+  PrintF("\n - setter: ");
+  setter()->ShortPrint();
+  PrintF("\n - name: ");
+  name()->ShortPrint();
+  PrintF("\n - data: ");
+  data()->ShortPrint();
+  PrintF("\n - flag: ");
+  flag()->ShortPrint();
+}
+
+void AccessCheckInfo::AccessCheckInfoVerify() {
+  CHECK(IsAccessCheckInfo());
+  VerifyPointer(named_callback());
+  VerifyPointer(indexed_callback());
+  VerifyPointer(data());
+}
+
+void AccessCheckInfo::AccessCheckInfoPrint() {
+  HeapObject::PrintHeader("AccessCheckInfo");
+  PrintF("\n - named_callback: ");
+  named_callback()->ShortPrint();
+  PrintF("\n - indexed_callback: ");
+  indexed_callback()->ShortPrint();
+  PrintF("\n - data: ");
+  data()->ShortPrint();
+}
+
+void InterceptorInfo::InterceptorInfoVerify() {
+  CHECK(IsInterceptorInfo());
+  VerifyPointer(getter());
+  VerifyPointer(setter());
+  VerifyPointer(query());
+  VerifyPointer(deleter());
+  VerifyPointer(enumerator());
+  VerifyPointer(data());
+}
+
+void InterceptorInfo::InterceptorInfoPrint() {
+  HeapObject::PrintHeader("InterceptorInfo");
+  PrintF("\n - getter: ");
+  getter()->ShortPrint();
+  PrintF("\n - setter: ");
+  setter()->ShortPrint();
+  PrintF("\n - query: ");
+  query()->ShortPrint();
+  PrintF("\n - deleter: ");
+  deleter()->ShortPrint();
+  PrintF("\n - enumerator: ");
+  enumerator()->ShortPrint();
+  PrintF("\n - data: ");
+  data()->ShortPrint();
+}
+
+void CallHandlerInfo::CallHandlerInfoVerify() {
+  CHECK(IsCallHandlerInfo());
+  VerifyPointer(callback());
+  VerifyPointer(data());
+}
+
+void CallHandlerInfo::CallHandlerInfoPrint() {
+  HeapObject::PrintHeader("CallHandlerInfo");
+  PrintF("\n - callback: ");
+  callback()->ShortPrint();
+  PrintF("\n - data: ");
+  data()->ShortPrint();
+}
+
+void TemplateInfo::TemplateInfoVerify() {
+  VerifyPointer(tag());
+  VerifyPointer(property_list());
+}
+
+void FunctionTemplateInfo::FunctionTemplateInfoVerify() {
+  CHECK(IsFunctionTemplateInfo());
+  TemplateInfoVerify();
+  VerifyPointer(serial_number());
+  VerifyPointer(call_code());
+  VerifyPointer(property_accessors());
+  VerifyPointer(prototype_template());
+  VerifyPointer(parent_template());
+  VerifyPointer(named_property_handler());
+  VerifyPointer(indexed_property_handler());
+  VerifyPointer(instance_template());
+  VerifyPointer(signature());
+  VerifyPointer(access_check_info());
+}
+
+void FunctionTemplateInfo::FunctionTemplateInfoPrint() {
+  HeapObject::PrintHeader("FunctionTemplateInfo");
+  PrintF("\n - tag: ");
+  tag()->ShortPrint();
+  PrintF("\n - property_list: ");
+  property_list()->ShortPrint();
+  PrintF("\n - serial_number: ");
+  serial_number()->ShortPrint();
+  PrintF("\n - call_code: ");
+  call_code()->ShortPrint();
+  PrintF("\n - property_accessors: ");
+  property_accessors()->ShortPrint();
+  PrintF("\n - prototype_template: ");
+  prototype_template()->ShortPrint();
+  PrintF("\n - parent_template: ");
+  parent_template()->ShortPrint();
+  PrintF("\n - named_property_handler: ");
+  named_property_handler()->ShortPrint();
+  PrintF("\n - indexed_property_handler: ");
+  indexed_property_handler()->ShortPrint();
+  PrintF("\n - instance_template: ");
+  instance_template()->ShortPrint();
+  PrintF("\n - signature: ");
+  signature()->ShortPrint();
+  PrintF("\n - access_check_info: ");
+  access_check_info()->ShortPrint();
+  PrintF("\n - hidden_prototype: %s", hidden_prototype() ? "true" : "false");
+  PrintF("\n - undetectable: %s", undetectable() ? "true" : "false");
+  PrintF("\n - need_access_check: %s", needs_access_check() ? "true" : "false");
+}
+
+void ObjectTemplateInfo::ObjectTemplateInfoVerify() {
+  CHECK(IsObjectTemplateInfo());
+  TemplateInfoVerify();
+  VerifyPointer(constructor());
+  VerifyPointer(internal_field_count());
+}
+
+void ObjectTemplateInfo::ObjectTemplateInfoPrint() {
+  HeapObject::PrintHeader("ObjectTemplateInfo");
+  PrintF("\n - constructor: ");
+  constructor()->ShortPrint();
+  PrintF("\n - internal_field_count: ");
+  internal_field_count()->ShortPrint();
+}
+
+void SignatureInfo::SignatureInfoVerify() {
+  CHECK(IsSignatureInfo());
+  VerifyPointer(receiver());
+  VerifyPointer(args());
+}
+
+void SignatureInfo::SignatureInfoPrint() {
+  HeapObject::PrintHeader("SignatureInfo");
+  PrintF("\n - receiver: ");
+  receiver()->ShortPrint();
+  PrintF("\n - args: ");
+  args()->ShortPrint();
+}
+
+void TypeSwitchInfo::TypeSwitchInfoVerify() {
+  CHECK(IsTypeSwitchInfo());
+  VerifyPointer(types());
+}
+
+void TypeSwitchInfo::TypeSwitchInfoPrint() {
+  HeapObject::PrintHeader("TypeSwitchInfo");
+  PrintF("\n - types: ");
+  types()->ShortPrint();
+}
+
+
+void Script::ScriptVerify() {
+  CHECK(IsScript());
+  VerifyPointer(source());
+  VerifyPointer(name());
+  line_offset()->SmiVerify();
+  column_offset()->SmiVerify();
+  type()->SmiVerify();
+}
+
+
+void Script::ScriptPrint() {
+  HeapObject::PrintHeader("Script");
+  PrintF("\n - source: ");
+  source()->ShortPrint();
+  PrintF("\n - name: ");
+  name()->ShortPrint();
+  PrintF("\n - line_offset: ");
+  line_offset()->ShortPrint();
+  PrintF("\n - column_offset: ");
+  column_offset()->ShortPrint();
+  PrintF("\n - type: ");
+  type()->ShortPrint();
+  PrintF("\n");
+}
+
+
+void DebugInfo::DebugInfoVerify() {
+  CHECK(IsDebugInfo());
+  VerifyPointer(shared());
+  VerifyPointer(original_code());
+  VerifyPointer(code());
+  VerifyPointer(break_points());
+}
+
+
+void DebugInfo::DebugInfoPrint() {
+  HeapObject::PrintHeader("DebugInfo");
+  PrintF("\n - shared: ");
+  shared()->ShortPrint();
+  PrintF("\n - original_code: ");
+  original_code()->ShortPrint();
+  PrintF("\n - code: ");
+  code()->ShortPrint();
+  PrintF("\n - break_points: ");
+  break_points()->Print();
+}
+
+
+void BreakPointInfo::BreakPointInfoVerify() {
+  CHECK(IsBreakPointInfo());
+  code_position()->SmiVerify();
+  source_position()->SmiVerify();
+  statement_position()->SmiVerify();
+  VerifyPointer(break_point_objects());
+}
+
+
+void BreakPointInfo::BreakPointInfoPrint() {
+  HeapObject::PrintHeader("BreakPointInfo");
+  PrintF("\n - code_position: %d", code_position());
+  PrintF("\n - source_position: %d", source_position());
+  PrintF("\n - statement_position: %d", statement_position());
+  PrintF("\n - break_point_objects: ");
+  break_point_objects()->ShortPrint();
+}
+
+
+void JSObject::IncrementSpillStatistics(SpillInformation* info) {
+  info->number_of_objects_++;
+  // Named properties
+  if (HasFastProperties()) {
+    info->number_of_objects_with_fast_properties_++;
+    info->number_of_fast_used_fields_   += map()->NextFreePropertyIndex();
+    info->number_of_fast_unused_fields_ += map()->unused_property_fields();
+  } else {
+    Dictionary* dict = property_dictionary();
+    info->number_of_slow_used_properties_ += dict->NumberOfElements();
+    info->number_of_slow_unused_properties_ +=
+        dict->Capacity() - dict->NumberOfElements();
+  }
+  // Indexed properties
+  if (HasFastElements()) {
+    info->number_of_objects_with_fast_elements_++;
+    int holes = 0;
+    FixedArray* e = FixedArray::cast(elements());
+    int len = e->length();
+    for (int i = 0; i < len; i++) {
+      if (e->get(i) == Heap::the_hole_value()) holes++;
+    }
+    info->number_of_fast_used_elements_   += len - holes;
+    info->number_of_fast_unused_elements_ += holes;
+  } else {
+    Dictionary* dict = element_dictionary();
+    info->number_of_slow_used_elements_ += dict->NumberOfElements();
+    info->number_of_slow_unused_elements_ +=
+        dict->Capacity() - dict->NumberOfElements();
+  }
+}
+
+
+void JSObject::SpillInformation::Clear() {
+  number_of_objects_ = 0;
+  number_of_objects_with_fast_properties_ = 0;
+  number_of_objects_with_fast_elements_ = 0;
+  number_of_fast_used_fields_ = 0;
+  number_of_fast_unused_fields_ = 0;
+  number_of_slow_used_properties_ = 0;
+  number_of_slow_unused_properties_ = 0;
+  number_of_fast_used_elements_ = 0;
+  number_of_fast_unused_elements_ = 0;
+  number_of_slow_used_elements_ = 0;
+  number_of_slow_unused_elements_ = 0;
+}
+
+void JSObject::SpillInformation::Print() {
+  PrintF("\n  JSObject Spill Statistics (#%d):\n", number_of_objects_);
+
+  PrintF("    - fast properties (#%d): %d (used) %d (unused)\n",
+         number_of_objects_with_fast_properties_,
+         number_of_fast_used_fields_, number_of_fast_unused_fields_);
+
+  PrintF("    - slow properties (#%d): %d (used) %d (unused)\n",
+         number_of_objects_ - number_of_objects_with_fast_properties_,
+         number_of_slow_used_properties_, number_of_slow_unused_properties_);
+
+  PrintF("    - fast elements (#%d): %d (used) %d (unused)\n",
+         number_of_objects_with_fast_elements_,
+         number_of_fast_used_elements_, number_of_fast_unused_elements_);
+
+  PrintF("    - slow elements (#%d): %d (used) %d (unused)\n",
+         number_of_objects_ - number_of_objects_with_fast_elements_,
+         number_of_slow_used_elements_, number_of_slow_unused_elements_);
+
+  PrintF("\n");
+}
+
+
+void DescriptorArray::PrintDescriptors() {
+  PrintF("Descriptor array  %d\n", number_of_descriptors());
+  int number = 0;
+  for (DescriptorReader r(this); !r.eos(); r.advance()) {
+    Descriptor desc;
+    r.Get(&desc);
+    PrintF(" %d: ", number++);
+    desc.Print();
+  }
+  PrintF("\n");
+}
+
+
+bool DescriptorArray::IsSortedNoDuplicates() {
+  String* current_key = NULL;
+  uint32_t current = 0;
+  for (DescriptorReader r(this); !r.eos(); r.advance()) {
+    String* key = r.GetKey();
+    if (key == current_key) {
+      PrintDescriptors();
+      return false;
+    }
+    current_key = key;
+    uint32_t hash = r.GetKey()->Hash();
+    if (hash < current) {
+      PrintDescriptors();
+      return false;
+    }
+    current = hash;
+  }
+  return true;
+}
+
+
+#endif  // DEBUG
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h
new file mode 100644
index 0000000..c2143ea
--- /dev/null
+++ b/deps/v8/src/objects-inl.h
@@ -0,0 +1,2597 @@
+// 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.
+//
+// Review notes:
+//
+// - The use of macros in these inline functions may seem superfluous
+// but it is absolutely needed to make sure gcc generates optimal
+// code. gcc is not happy when attempting to inline too deep.
+//
+
+#ifndef V8_OBJECTS_INL_H_
+#define V8_OBJECTS_INL_H_
+
+#include "objects.h"
+#include "contexts.h"
+#include "conversions-inl.h"
+#include "property.h"
+
+namespace v8 { namespace internal {
+
+PropertyDetails::PropertyDetails(Smi* smi) {
+  value_ = smi->value();
+}
+
+
+Smi* PropertyDetails::AsSmi() {
+  return Smi::FromInt(value_);
+}
+
+
+#define CAST_ACCESSOR(type)                     \
+  type* type::cast(Object* object) {            \
+    ASSERT(object->Is##type());                 \
+    return reinterpret_cast<type*>(object);     \
+  }
+
+
+#define INT_ACCESSORS(holder, name, offset)                             \
+  int holder::name() { return READ_INT_FIELD(this, offset); }           \
+  void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
+
+
+#define ACCESSORS(holder, name, type, offset)                           \
+  type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
+  void holder::set_##name(type* value, WriteBarrierMode mode) {         \
+    WRITE_FIELD(this, offset, value);                                   \
+    CONDITIONAL_WRITE_BARRIER(this, offset, mode);                      \
+  }
+
+
+
+#define SMI_ACCESSORS(holder, name, offset)             \
+  int holder::name() {                                  \
+    Object* value = READ_FIELD(this, offset);           \
+    return Smi::cast(value)->value();                   \
+  }                                                     \
+  void holder::set_##name(int value) {                  \
+    WRITE_FIELD(this, offset, Smi::FromInt(value));     \
+  }
+
+
+#define BOOL_ACCESSORS(holder, field, name, offset) \
+  bool holder::name() {                                    \
+    return BooleanBit::get(field(), offset);               \
+  }                                                        \
+  void holder::set_##name(bool value) {                    \
+    set_##field(BooleanBit::set(field(), offset, value));  \
+  }
+
+
+bool Object::IsSmi() {
+  return HAS_SMI_TAG(this);
+}
+
+
+bool Object::IsHeapObject() {
+  return HAS_HEAP_OBJECT_TAG(this);
+}
+
+
+bool Object::IsHeapNumber() {
+  return Object::IsHeapObject()
+    && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
+}
+
+
+bool Object::IsString() {
+  return Object::IsHeapObject()
+    && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
+}
+
+
+bool Object::IsSymbol() {
+  if (!this->IsHeapObject()) return false;
+  uint32_t type = HeapObject::cast(this)->map()->instance_type();
+  return (type & (kIsNotStringMask | kIsSymbolMask)) ==
+         (kStringTag | kSymbolTag);
+}
+
+
+bool Object::IsConsString() {
+  if (!this->IsHeapObject()) return false;
+  uint32_t type = HeapObject::cast(this)->map()->instance_type();
+  return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
+         (kStringTag | kConsStringTag);
+}
+
+
+#ifdef DEBUG
+// These are for cast checks.  If you need one of these in release
+// mode you should consider using a StringShape before moving it out
+// of the ifdef
+
+bool Object::IsSeqString() {
+  if (!IsString()) return false;
+  return StringShape(String::cast(this)).IsSequential();
+}
+
+
+bool Object::IsSeqAsciiString() {
+  if (!IsString()) return false;
+  return StringShape(String::cast(this)).IsSequential() &&
+         StringShape(String::cast(this)).IsAsciiRepresentation();
+}
+
+
+bool Object::IsSeqTwoByteString() {
+  if (!IsString()) return false;
+  return StringShape(String::cast(this)).IsSequential() &&
+         StringShape(String::cast(this)).IsTwoByteRepresentation();
+}
+
+
+bool Object::IsExternalString() {
+  if (!IsString()) return false;
+  return StringShape(String::cast(this)).IsExternal();
+}
+
+
+bool Object::IsExternalAsciiString() {
+  if (!IsString()) return false;
+  return StringShape(String::cast(this)).IsExternal() &&
+         StringShape(String::cast(this)).IsAsciiRepresentation();
+}
+
+
+bool Object::IsExternalTwoByteString() {
+  if (!IsString()) return false;
+  return StringShape(String::cast(this)).IsExternal() &&
+         StringShape(String::cast(this)).IsTwoByteRepresentation();
+}
+
+
+bool Object::IsSlicedString() {
+  if (!IsString()) return false;
+  return StringShape(String::cast(this)).IsSliced();
+}
+
+
+#endif  // DEBUG
+
+
+StringShape::StringShape(String* str)
+  : type_(str->map()->instance_type()) {
+  set_valid();
+  ASSERT((type_ & kIsNotStringMask) == kStringTag);
+}
+
+
+StringShape::StringShape(Map* map)
+  : type_(map->instance_type()) {
+  set_valid();
+  ASSERT((type_ & kIsNotStringMask) == kStringTag);
+}
+
+
+StringShape::StringShape(InstanceType t)
+  : type_(static_cast<uint32_t>(t)) {
+  set_valid();
+  ASSERT((type_ & kIsNotStringMask) == kStringTag);
+}
+
+
+bool StringShape::IsSymbol() {
+  ASSERT(valid());
+  return (type_ & kIsSymbolMask) == kSymbolTag;
+}
+
+
+bool StringShape::IsAsciiRepresentation() {
+  return (type_ & kStringEncodingMask) == kAsciiStringTag;
+}
+
+
+bool StringShape::IsTwoByteRepresentation() {
+  return (type_ & kStringEncodingMask) == kTwoByteStringTag;
+}
+
+
+bool StringShape::IsCons() {
+  return (type_ & kStringRepresentationMask) == kConsStringTag;
+}
+
+
+bool StringShape::IsSliced() {
+  return (type_ & kStringRepresentationMask) == kSlicedStringTag;
+}
+
+
+bool StringShape::IsExternal() {
+  return (type_ & kStringRepresentationMask) == kExternalStringTag;
+}
+
+
+bool StringShape::IsSequential() {
+  return (type_ & kStringRepresentationMask) == kSeqStringTag;
+}
+
+
+StringRepresentationTag StringShape::representation_tag() {
+  uint32_t tag = (type_ & kStringRepresentationMask);
+  return static_cast<StringRepresentationTag>(tag);
+}
+
+
+uint32_t StringShape::full_representation_tag() {
+  return (type_ & (kStringRepresentationMask | kStringEncodingMask));
+}
+
+
+uint32_t StringShape::size_tag() {
+  return (type_ & kStringSizeMask);
+}
+
+
+bool StringShape::IsSequentialAscii() {
+  return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
+}
+
+
+bool StringShape::IsSequentialTwoByte() {
+  return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
+}
+
+
+bool StringShape::IsExternalAscii() {
+  return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
+}
+
+
+bool StringShape::IsExternalTwoByte() {
+  return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
+}
+
+
+uc32 FlatStringReader::Get(int index) {
+  ASSERT(0 <= index && index <= length_);
+  if (is_ascii_) {
+    return static_cast<const byte*>(start_)[index];
+  } else {
+    return static_cast<const uc16*>(start_)[index];
+  }
+}
+
+
+bool Object::IsNumber() {
+  return IsSmi() || IsHeapNumber();
+}
+
+
+bool Object::IsByteArray() {
+  return Object::IsHeapObject()
+    && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
+}
+
+
+bool Object::IsFailure() {
+  return HAS_FAILURE_TAG(this);
+}
+
+
+bool Object::IsRetryAfterGC() {
+  return HAS_FAILURE_TAG(this)
+    && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
+}
+
+
+bool Object::IsOutOfMemoryFailure() {
+  return HAS_FAILURE_TAG(this)
+    && Failure::cast(this)->IsOutOfMemoryException();
+}
+
+
+bool Object::IsException() {
+  return this == Failure::Exception();
+}
+
+
+bool Object::IsJSObject() {
+  return IsHeapObject()
+    && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
+}
+
+
+bool Object::IsJSContextExtensionObject() {
+  return IsHeapObject()
+    && (HeapObject::cast(this)->map()->instance_type() ==
+        JS_CONTEXT_EXTENSION_OBJECT_TYPE);
+}
+
+
+bool Object::IsMap() {
+  return Object::IsHeapObject()
+    && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
+}
+
+
+bool Object::IsFixedArray() {
+  return Object::IsHeapObject()
+    && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
+}
+
+
+bool Object::IsDescriptorArray() {
+  return IsFixedArray();
+}
+
+
+bool Object::IsContext() {
+  return Object::IsHeapObject()
+    && (HeapObject::cast(this)->map() == Heap::context_map() ||
+        HeapObject::cast(this)->map() == Heap::catch_context_map() ||
+        HeapObject::cast(this)->map() == Heap::global_context_map());
+}
+
+
+bool Object::IsCatchContext() {
+  return Object::IsHeapObject()
+    && HeapObject::cast(this)->map() == Heap::catch_context_map();
+}
+
+
+bool Object::IsGlobalContext() {
+  return Object::IsHeapObject()
+    && HeapObject::cast(this)->map() == Heap::global_context_map();
+}
+
+
+bool Object::IsJSFunction() {
+  return Object::IsHeapObject()
+    && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
+}
+
+
+template <> inline bool Is<JSFunction>(Object* obj) {
+  return obj->IsJSFunction();
+}
+
+
+bool Object::IsCode() {
+  return Object::IsHeapObject()
+    && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
+}
+
+
+bool Object::IsOddball() {
+  return Object::IsHeapObject()
+    && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
+}
+
+
+bool Object::IsSharedFunctionInfo() {
+  return Object::IsHeapObject() &&
+      (HeapObject::cast(this)->map()->instance_type() ==
+       SHARED_FUNCTION_INFO_TYPE);
+}
+
+
+bool Object::IsJSValue() {
+  return Object::IsHeapObject()
+    && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
+}
+
+
+bool Object::IsStringWrapper() {
+  return IsJSValue() && JSValue::cast(this)->value()->IsString();
+}
+
+
+bool Object::IsProxy() {
+  return Object::IsHeapObject()
+    && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
+}
+
+
+bool Object::IsBoolean() {
+  return IsTrue() || IsFalse();
+}
+
+
+bool Object::IsJSArray() {
+  return Object::IsHeapObject()
+    && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
+}
+
+
+bool Object::IsJSRegExp() {
+  return Object::IsHeapObject()
+    && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
+}
+
+
+template <> inline bool Is<JSArray>(Object* obj) {
+  return obj->IsJSArray();
+}
+
+
+bool Object::IsHashTable() {
+  return Object::IsHeapObject()
+    && HeapObject::cast(this)->map() == Heap::hash_table_map();
+}
+
+
+bool Object::IsDictionary() {
+  return IsHashTable() && this != Heap::symbol_table();
+}
+
+
+bool Object::IsSymbolTable() {
+  return IsHashTable() && this == Heap::symbol_table();
+}
+
+
+bool Object::IsCompilationCacheTable() {
+  return IsHashTable();
+}
+
+
+bool Object::IsMapCache() {
+  return IsHashTable();
+}
+
+
+bool Object::IsLookupCache() {
+  return IsHashTable();
+}
+
+
+bool Object::IsPrimitive() {
+  return IsOddball() || IsNumber() || IsString();
+}
+
+
+bool Object::IsJSGlobalProxy() {
+  bool result = IsHeapObject() &&
+                (HeapObject::cast(this)->map()->instance_type() ==
+                 JS_GLOBAL_PROXY_TYPE);
+  ASSERT(!result || IsAccessCheckNeeded());
+  return result;
+}
+
+
+bool Object::IsGlobalObject() {
+  if (!IsHeapObject()) return false;
+
+  InstanceType type = HeapObject::cast(this)->map()->instance_type();
+  return type == JS_GLOBAL_OBJECT_TYPE ||
+         type == JS_BUILTINS_OBJECT_TYPE;
+}
+
+
+bool Object::IsJSGlobalObject() {
+  return IsHeapObject() &&
+      (HeapObject::cast(this)->map()->instance_type() ==
+       JS_GLOBAL_OBJECT_TYPE);
+}
+
+
+bool Object::IsJSBuiltinsObject() {
+  return IsHeapObject() &&
+      (HeapObject::cast(this)->map()->instance_type() ==
+       JS_BUILTINS_OBJECT_TYPE);
+}
+
+
+bool Object::IsUndetectableObject() {
+  return IsHeapObject()
+    && HeapObject::cast(this)->map()->is_undetectable();
+}
+
+
+bool Object::IsAccessCheckNeeded() {
+  return IsHeapObject()
+    && HeapObject::cast(this)->map()->is_access_check_needed();
+}
+
+
+bool Object::IsStruct() {
+  if (!IsHeapObject()) return false;
+  switch (HeapObject::cast(this)->map()->instance_type()) {
+#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
+  STRUCT_LIST(MAKE_STRUCT_CASE)
+#undef MAKE_STRUCT_CASE
+    default: return false;
+  }
+}
+
+
+#define MAKE_STRUCT_PREDICATE(NAME, Name, name)                  \
+  bool Object::Is##Name() {                                      \
+    return Object::IsHeapObject()                                \
+      && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
+  }
+  STRUCT_LIST(MAKE_STRUCT_PREDICATE)
+#undef MAKE_STRUCT_PREDICATE
+
+
+bool Object::IsUndefined() {
+  return this == Heap::undefined_value();
+}
+
+
+bool Object::IsTheHole() {
+  return this == Heap::the_hole_value();
+}
+
+
+bool Object::IsNull() {
+  return this == Heap::null_value();
+}
+
+
+bool Object::IsTrue() {
+  return this == Heap::true_value();
+}
+
+
+bool Object::IsFalse() {
+  return this == Heap::false_value();
+}
+
+
+double Object::Number() {
+  ASSERT(IsNumber());
+  return IsSmi()
+    ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
+    : reinterpret_cast<HeapNumber*>(this)->value();
+}
+
+
+
+Object* Object::ToSmi() {
+  if (IsSmi()) return this;
+  if (IsHeapNumber()) {
+    double value = HeapNumber::cast(this)->value();
+    int int_value = FastD2I(value);
+    if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
+      return Smi::FromInt(int_value);
+    }
+  }
+  return Failure::Exception();
+}
+
+
+bool Object::HasSpecificClassOf(String* name) {
+  return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
+}
+
+
+Object* Object::GetElement(uint32_t index) {
+  return GetElementWithReceiver(this, index);
+}
+
+
+Object* Object::GetProperty(String* key) {
+  PropertyAttributes attributes;
+  return GetPropertyWithReceiver(this, key, &attributes);
+}
+
+
+Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
+  return GetPropertyWithReceiver(this, key, attributes);
+}
+
+
+#define FIELD_ADDR(p, offset) \
+  (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
+
+#define READ_FIELD(p, offset) \
+  (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
+
+#define WRITE_FIELD(p, offset, value) \
+  (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
+
+
+#define WRITE_BARRIER(object, offset) \
+  Heap::RecordWrite(object->address(), offset);
+
+// CONDITIONAL_WRITE_BARRIER must be issued after the actual
+// write due to the assert validating the written value.
+#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
+  if (mode == UPDATE_WRITE_BARRIER) { \
+    Heap::RecordWrite(object->address(), offset); \
+  } else { \
+    ASSERT(mode == SKIP_WRITE_BARRIER); \
+    ASSERT(Heap::InNewSpace(object) || \
+           !Heap::InNewSpace(READ_FIELD(object, offset))); \
+  }
+
+#define READ_DOUBLE_FIELD(p, offset) \
+  (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
+
+#define WRITE_DOUBLE_FIELD(p, offset, value) \
+  (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
+
+#define READ_INT_FIELD(p, offset) \
+  (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
+
+#define WRITE_INT_FIELD(p, offset, value) \
+  (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
+
+#define READ_UINT32_FIELD(p, offset) \
+  (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
+
+#define WRITE_UINT32_FIELD(p, offset, value) \
+  (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
+
+#define READ_SHORT_FIELD(p, offset) \
+  (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
+
+#define WRITE_SHORT_FIELD(p, offset, value) \
+  (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
+
+#define READ_BYTE_FIELD(p, offset) \
+  (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
+
+#define WRITE_BYTE_FIELD(p, offset, value) \
+  (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
+
+
+Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
+  return &READ_FIELD(obj, byte_offset);
+}
+
+
+int Smi::value() {
+  return reinterpret_cast<int>(this) >> kSmiTagSize;
+}
+
+
+Smi* Smi::FromInt(int value) {
+  ASSERT(Smi::IsValid(value));
+  return reinterpret_cast<Smi*>((value << kSmiTagSize) | kSmiTag);
+}
+
+
+Failure::Type Failure::type() const {
+  return static_cast<Type>(value() & kFailureTypeTagMask);
+}
+
+
+bool Failure::IsInternalError() const {
+  return type() == INTERNAL_ERROR;
+}
+
+
+bool Failure::IsOutOfMemoryException() const {
+  return type() == OUT_OF_MEMORY_EXCEPTION;
+}
+
+
+int Failure::requested() const {
+  const int kShiftBits =
+      kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
+  STATIC_ASSERT(kShiftBits >= 0);
+  ASSERT(type() == RETRY_AFTER_GC);
+  return value() >> kShiftBits;
+}
+
+
+AllocationSpace Failure::allocation_space() const {
+  ASSERT_EQ(RETRY_AFTER_GC, type());
+  return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
+                                      & kSpaceTagMask);
+}
+
+
+Failure* Failure::InternalError() {
+  return Construct(INTERNAL_ERROR);
+}
+
+
+Failure* Failure::Exception() {
+  return Construct(EXCEPTION);
+}
+
+Failure* Failure::OutOfMemoryException() {
+  return Construct(OUT_OF_MEMORY_EXCEPTION);
+}
+
+
+int Failure::value() const {
+  return reinterpret_cast<int>(this) >> kFailureTagSize;
+}
+
+
+Failure* Failure::RetryAfterGC(int requested_bytes) {
+  int requested = requested_bytes >> kObjectAlignmentBits;
+  int value = (requested << kSpaceTagSize) | NEW_SPACE;
+  ASSERT(value >> kSpaceTagSize == requested);
+  ASSERT(Smi::IsValid(value));
+  ASSERT(value == ((value << kFailureTypeTagSize) >> kFailureTypeTagSize));
+  ASSERT(Smi::IsValid(value << kFailureTypeTagSize));
+  return Construct(RETRY_AFTER_GC, value);
+}
+
+
+Failure* Failure::Construct(Type type, int value) {
+  int info = (value << kFailureTypeTagSize) | type;
+  ASSERT(Smi::IsValid(info));  // Same validation check as in Smi
+  return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
+}
+
+
+bool Smi::IsValid(int value) {
+#ifdef DEBUG
+  bool in_range = (value >= kMinValue) && (value <= kMaxValue);
+#endif
+  // To be representable as an tagged small integer, the two
+  // most-significant bits of 'value' must be either 00 or 11 due to
+  // sign-extension. To check this we add 01 to the two
+  // most-significant bits, and check if the most-significant bit is 0
+  //
+  // CAUTION: The original code below:
+  // bool result = ((value + 0x40000000) & 0x80000000) == 0;
+  // may lead to incorrect results according to the C language spec, and
+  // in fact doesn't work correctly with gcc4.1.1 in some cases: The
+  // compiler may produce undefined results in case of signed integer
+  // overflow. The computation must be done w/ unsigned ints.
+  bool result =
+      ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0;
+  ASSERT(result == in_range);
+  return result;
+}
+
+
+MapWord MapWord::FromMap(Map* map) {
+  return MapWord(reinterpret_cast<uintptr_t>(map));
+}
+
+
+Map* MapWord::ToMap() {
+  return reinterpret_cast<Map*>(value_);
+}
+
+
+bool MapWord::IsForwardingAddress() {
+  return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
+}
+
+
+MapWord MapWord::FromForwardingAddress(HeapObject* object) {
+  Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
+  return MapWord(reinterpret_cast<uintptr_t>(raw));
+}
+
+
+HeapObject* MapWord::ToForwardingAddress() {
+  ASSERT(IsForwardingAddress());
+  return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
+}
+
+
+bool MapWord::IsMarked() {
+  return (value_ & kMarkingMask) == 0;
+}
+
+
+void MapWord::SetMark() {
+  value_ &= ~kMarkingMask;
+}
+
+
+void MapWord::ClearMark() {
+  value_ |= kMarkingMask;
+}
+
+
+bool MapWord::IsOverflowed() {
+  return (value_ & kOverflowMask) != 0;
+}
+
+
+void MapWord::SetOverflow() {
+  value_ |= kOverflowMask;
+}
+
+
+void MapWord::ClearOverflow() {
+  value_ &= ~kOverflowMask;
+}
+
+
+MapWord MapWord::EncodeAddress(Address map_address, int offset) {
+  // Offset is the distance in live bytes from the first live object in the
+  // same page. The offset between two objects in the same page should not
+  // exceed the object area size of a page.
+  ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
+
+  int compact_offset = offset >> kObjectAlignmentBits;
+  ASSERT(compact_offset < (1 << kForwardingOffsetBits));
+
+  Page* map_page = Page::FromAddress(map_address);
+  ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
+
+  int map_page_offset =
+      map_page->Offset(map_address) >> kObjectAlignmentBits;
+
+  uintptr_t encoding =
+      (compact_offset << kForwardingOffsetShift) |
+      (map_page_offset << kMapPageOffsetShift) |
+      (map_page->mc_page_index << kMapPageIndexShift);
+  return MapWord(encoding);
+}
+
+
+Address MapWord::DecodeMapAddress(MapSpace* map_space) {
+  int map_page_index = (value_ & kMapPageIndexMask) >> kMapPageIndexShift;
+  ASSERT_MAP_PAGE_INDEX(map_page_index);
+
+  int map_page_offset =
+      ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
+      << kObjectAlignmentBits;
+
+  return (map_space->PageAddress(map_page_index) + map_page_offset);
+}
+
+
+int MapWord::DecodeOffset() {
+  // The offset field is represented in the kForwardingOffsetBits
+  // most-significant bits.
+  int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
+  ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
+  return offset;
+}
+
+
+MapWord MapWord::FromEncodedAddress(Address address) {
+  return MapWord(reinterpret_cast<uintptr_t>(address));
+}
+
+
+Address MapWord::ToEncodedAddress() {
+  return reinterpret_cast<Address>(value_);
+}
+
+
+#ifdef DEBUG
+void HeapObject::VerifyObjectField(int offset) {
+  VerifyPointer(READ_FIELD(this, offset));
+}
+#endif
+
+
+Map* HeapObject::map() {
+  return map_word().ToMap();
+}
+
+
+void HeapObject::set_map(Map* value) {
+  set_map_word(MapWord::FromMap(value));
+}
+
+
+MapWord HeapObject::map_word() {
+  return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
+}
+
+
+void HeapObject::set_map_word(MapWord map_word) {
+  // WRITE_FIELD does not update the remembered set, but there is no need
+  // here.
+  WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
+}
+
+
+HeapObject* HeapObject::FromAddress(Address address) {
+  ASSERT_TAG_ALIGNED(address);
+  return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
+}
+
+
+Address HeapObject::address() {
+  return reinterpret_cast<Address>(this) - kHeapObjectTag;
+}
+
+
+int HeapObject::Size() {
+  return SizeFromMap(map());
+}
+
+
+void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
+  v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
+                   reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
+}
+
+
+void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
+  v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
+}
+
+
+bool HeapObject::IsMarked() {
+  return map_word().IsMarked();
+}
+
+
+void HeapObject::SetMark() {
+  ASSERT(!IsMarked());
+  MapWord first_word = map_word();
+  first_word.SetMark();
+  set_map_word(first_word);
+}
+
+
+void HeapObject::ClearMark() {
+  ASSERT(IsMarked());
+  MapWord first_word = map_word();
+  first_word.ClearMark();
+  set_map_word(first_word);
+}
+
+
+bool HeapObject::IsOverflowed() {
+  return map_word().IsOverflowed();
+}
+
+
+void HeapObject::SetOverflow() {
+  MapWord first_word = map_word();
+  first_word.SetOverflow();
+  set_map_word(first_word);
+}
+
+
+void HeapObject::ClearOverflow() {
+  ASSERT(IsOverflowed());
+  MapWord first_word = map_word();
+  first_word.ClearOverflow();
+  set_map_word(first_word);
+}
+
+
+double HeapNumber::value() {
+  return READ_DOUBLE_FIELD(this, kValueOffset);
+}
+
+
+void HeapNumber::set_value(double value) {
+  WRITE_DOUBLE_FIELD(this, kValueOffset, value);
+}
+
+
+ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
+ACCESSORS(JSObject, elements, FixedArray, kElementsOffset)
+
+
+void JSObject::initialize_properties() {
+  ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
+  WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
+}
+
+
+void JSObject::initialize_elements() {
+  ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
+  WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
+}
+
+
+ACCESSORS(Oddball, to_string, String, kToStringOffset)
+ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
+
+
+int JSObject::GetHeaderSize() {
+  switch (map()->instance_type()) {
+    case JS_GLOBAL_PROXY_TYPE:
+      return JSGlobalProxy::kSize;
+    case JS_GLOBAL_OBJECT_TYPE:
+      return JSGlobalObject::kSize;
+    case JS_BUILTINS_OBJECT_TYPE:
+      return JSBuiltinsObject::kSize;
+    case JS_FUNCTION_TYPE:
+      return JSFunction::kSize;
+    case JS_VALUE_TYPE:
+      return JSValue::kSize;
+    case JS_ARRAY_TYPE:
+      return JSValue::kSize;
+    case JS_REGEXP_TYPE:
+      return JSValue::kSize;
+    case JS_OBJECT_TYPE:
+    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
+      return JSObject::kHeaderSize;
+    default:
+      UNREACHABLE();
+      return 0;
+  }
+}
+
+
+int JSObject::GetInternalFieldCount() {
+  ASSERT(1 << kPointerSizeLog2 == kPointerSize);
+  // Make sure to adjust for the number of in-object properties. These
+  // properties do contribute to the size, but are not internal fields.
+  return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
+         map()->inobject_properties();
+}
+
+
+Object* JSObject::GetInternalField(int index) {
+  ASSERT(index < GetInternalFieldCount() && index >= 0);
+  // Internal objects do follow immediately after the header, whereas in-object
+  // properties are at the end of the object. Therefore there is no need
+  // to adjust the index here.
+  return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
+}
+
+
+void JSObject::SetInternalField(int index, Object* value) {
+  ASSERT(index < GetInternalFieldCount() && index >= 0);
+  // Internal objects do follow immediately after the header, whereas in-object
+  // properties are at the end of the object. Therefore there is no need
+  // to adjust the index here.
+  int offset = GetHeaderSize() + (kPointerSize * index);
+  WRITE_FIELD(this, offset, value);
+  WRITE_BARRIER(this, offset);
+}
+
+
+// Access fast-case object properties at index. The use of these routines
+// is needed to correctly distinguish between properties stored in-object and
+// properties stored in the properties array.
+Object* JSObject::FastPropertyAt(int index) {
+  // Adjust for the number of properties stored in the object.
+  index -= map()->inobject_properties();
+  if (index < 0) {
+    int offset = map()->instance_size() + (index * kPointerSize);
+    return READ_FIELD(this, offset);
+  } else {
+    ASSERT(index < properties()->length());
+    return properties()->get(index);
+  }
+}
+
+
+Object* JSObject::FastPropertyAtPut(int index, Object* value) {
+  // Adjust for the number of properties stored in the object.
+  index -= map()->inobject_properties();
+  if (index < 0) {
+    int offset = map()->instance_size() + (index * kPointerSize);
+    WRITE_FIELD(this, offset, value);
+    WRITE_BARRIER(this, offset);
+  } else {
+    ASSERT(index < properties()->length());
+    properties()->set(index, value);
+  }
+  return value;
+}
+
+
+Object* JSObject::InObjectPropertyAt(int index) {
+  // Adjust for the number of properties stored in the object.
+  index -= map()->inobject_properties();
+  ASSERT(index < 0);
+  int offset = map()->instance_size() + (index * kPointerSize);
+  return READ_FIELD(this, offset);
+}
+
+
+Object* JSObject::InObjectPropertyAtPut(int index,
+                                        Object* value,
+                                        WriteBarrierMode mode) {
+  // Adjust for the number of properties stored in the object.
+  index -= map()->inobject_properties();
+  ASSERT(index < 0);
+  int offset = map()->instance_size() + (index * kPointerSize);
+  WRITE_FIELD(this, offset, value);
+  CONDITIONAL_WRITE_BARRIER(this, offset, mode);
+  return value;
+}
+
+
+
+void JSObject::InitializeBody(int object_size) {
+  Object* value = Heap::undefined_value();
+  for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
+    WRITE_FIELD(this, offset, value);
+  }
+}
+
+
+void Struct::InitializeBody(int object_size) {
+  Object* value = Heap::undefined_value();
+  for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
+    WRITE_FIELD(this, offset, value);
+  }
+}
+
+
+bool JSObject::HasFastProperties() {
+  return !properties()->IsDictionary();
+}
+
+
+bool Array::IndexFromObject(Object* object, uint32_t* index) {
+  if (object->IsSmi()) {
+    int value = Smi::cast(object)->value();
+    if (value < 0) return false;
+    *index = value;
+    return true;
+  }
+  if (object->IsHeapNumber()) {
+    double value = HeapNumber::cast(object)->value();
+    uint32_t uint_value = static_cast<uint32_t>(value);
+    if (value == static_cast<double>(uint_value)) {
+      *index = uint_value;
+      return true;
+    }
+  }
+  return false;
+}
+
+
+bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
+  if (!this->IsJSValue()) return false;
+
+  JSValue* js_value = JSValue::cast(this);
+  if (!js_value->value()->IsString()) return false;
+
+  String* str = String::cast(js_value->value());
+  if (index >= (uint32_t)str->length()) return false;
+
+  return true;
+}
+
+
+Object* FixedArray::get(int index) {
+  ASSERT(index >= 0 && index < this->length());
+  return READ_FIELD(this, kHeaderSize + index * kPointerSize);
+}
+
+
+void FixedArray::set(int index, Smi* value) {
+  ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
+  int offset = kHeaderSize + index * kPointerSize;
+  WRITE_FIELD(this, offset, value);
+}
+
+
+void FixedArray::set(int index, Object* value) {
+  ASSERT(index >= 0 && index < this->length());
+  int offset = kHeaderSize + index * kPointerSize;
+  WRITE_FIELD(this, offset, value);
+  WRITE_BARRIER(this, offset);
+}
+
+
+WriteBarrierMode HeapObject::GetWriteBarrierMode() {
+  if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
+  return UPDATE_WRITE_BARRIER;
+}
+
+
+void FixedArray::set(int index,
+                     Object* value,
+                     WriteBarrierMode mode) {
+  ASSERT(index >= 0 && index < this->length());
+  int offset = kHeaderSize + index * kPointerSize;
+  WRITE_FIELD(this, offset, value);
+  CONDITIONAL_WRITE_BARRIER(this, offset, mode);
+}
+
+
+void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
+  ASSERT(index >= 0 && index < array->length());
+  WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
+}
+
+
+void FixedArray::set_undefined(int index) {
+  ASSERT(index >= 0 && index < this->length());
+  ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
+  WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
+              Heap::undefined_value());
+}
+
+
+void FixedArray::set_null(int index) {
+  ASSERT(index >= 0 && index < this->length());
+  ASSERT(!Heap::InNewSpace(Heap::null_value()));
+  WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
+}
+
+
+void FixedArray::set_the_hole(int index) {
+  ASSERT(index >= 0 && index < this->length());
+  ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
+  WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
+}
+
+
+bool DescriptorArray::IsEmpty() {
+  ASSERT(this == Heap::empty_descriptor_array() ||
+         this->length() > 2);
+  return this == Heap::empty_descriptor_array();
+}
+
+
+void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
+  Object* tmp = array->get(first);
+  fast_set(array, first, array->get(second));
+  fast_set(array, second, tmp);
+}
+
+
+int DescriptorArray::Search(String* name) {
+  SLOW_ASSERT(IsSortedNoDuplicates());
+
+  // Check for empty descriptor array.
+  int nof = number_of_descriptors();
+  if (nof == 0) return kNotFound;
+
+  // Fast case: do linear search for small arrays.
+  const int kMaxElementsForLinearSearch = 8;
+  if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
+    return LinearSearch(name, nof);
+  }
+
+  // Slow case: perform binary search.
+  return BinarySearch(name, 0, nof - 1);
+}
+
+
+
+String* DescriptorArray::GetKey(int descriptor_number) {
+  ASSERT(descriptor_number < number_of_descriptors());
+  return String::cast(get(ToKeyIndex(descriptor_number)));
+}
+
+
+Object* DescriptorArray::GetValue(int descriptor_number) {
+  ASSERT(descriptor_number < number_of_descriptors());
+  return GetContentArray()->get(ToValueIndex(descriptor_number));
+}
+
+
+Smi* DescriptorArray::GetDetails(int descriptor_number) {
+  ASSERT(descriptor_number < number_of_descriptors());
+  return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
+}
+
+
+void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
+  desc->Init(GetKey(descriptor_number),
+             GetValue(descriptor_number),
+             GetDetails(descriptor_number));
+}
+
+
+void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
+  // Range check.
+  ASSERT(descriptor_number < number_of_descriptors());
+
+  // Make sure non of the elements in desc are in new space.
+  ASSERT(!Heap::InNewSpace(desc->GetKey()));
+  ASSERT(!Heap::InNewSpace(desc->GetValue()));
+
+  fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
+  FixedArray* content_array = GetContentArray();
+  fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
+  fast_set(content_array, ToDetailsIndex(descriptor_number),
+           desc->GetDetails().AsSmi());
+}
+
+
+void DescriptorArray::Swap(int first, int second) {
+  fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
+  FixedArray* content_array = GetContentArray();
+  fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
+  fast_swap(content_array, ToDetailsIndex(first),  ToDetailsIndex(second));
+}
+
+
+bool Dictionary::requires_slow_elements() {
+  Object* max_index_object = get(kMaxNumberKeyIndex);
+  if (!max_index_object->IsSmi()) return false;
+  return 0 !=
+      (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
+}
+
+
+uint32_t Dictionary::max_number_key() {
+  ASSERT(!requires_slow_elements());
+  Object* max_index_object = get(kMaxNumberKeyIndex);
+  if (!max_index_object->IsSmi()) return 0;
+  uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
+  return value >> kRequiresSlowElementsTagSize;
+}
+
+
+void Dictionary::set_requires_slow_elements() {
+  set(kMaxNumberKeyIndex,
+      Smi::FromInt(kRequiresSlowElementsMask),
+      SKIP_WRITE_BARRIER);
+}
+
+
+// ------------------------------------
+// Cast operations
+
+
+CAST_ACCESSOR(FixedArray)
+CAST_ACCESSOR(DescriptorArray)
+CAST_ACCESSOR(Dictionary)
+CAST_ACCESSOR(SymbolTable)
+CAST_ACCESSOR(CompilationCacheTable)
+CAST_ACCESSOR(MapCache)
+CAST_ACCESSOR(LookupCache)
+CAST_ACCESSOR(String)
+CAST_ACCESSOR(SeqString)
+CAST_ACCESSOR(SeqAsciiString)
+CAST_ACCESSOR(SeqTwoByteString)
+CAST_ACCESSOR(ConsString)
+CAST_ACCESSOR(SlicedString)
+CAST_ACCESSOR(ExternalString)
+CAST_ACCESSOR(ExternalAsciiString)
+CAST_ACCESSOR(ExternalTwoByteString)
+CAST_ACCESSOR(JSObject)
+CAST_ACCESSOR(Smi)
+CAST_ACCESSOR(Failure)
+CAST_ACCESSOR(HeapObject)
+CAST_ACCESSOR(HeapNumber)
+CAST_ACCESSOR(Oddball)
+CAST_ACCESSOR(SharedFunctionInfo)
+CAST_ACCESSOR(Map)
+CAST_ACCESSOR(JSFunction)
+CAST_ACCESSOR(GlobalObject)
+CAST_ACCESSOR(JSGlobalProxy)
+CAST_ACCESSOR(JSGlobalObject)
+CAST_ACCESSOR(JSBuiltinsObject)
+CAST_ACCESSOR(Code)
+CAST_ACCESSOR(JSArray)
+CAST_ACCESSOR(JSRegExp)
+CAST_ACCESSOR(Proxy)
+CAST_ACCESSOR(ByteArray)
+CAST_ACCESSOR(Struct)
+
+
+#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
+  STRUCT_LIST(MAKE_STRUCT_CAST)
+#undef MAKE_STRUCT_CAST
+
+template <int prefix_size, int elem_size>
+HashTable<prefix_size, elem_size>* HashTable<prefix_size, elem_size>::cast(
+    Object* obj) {
+  ASSERT(obj->IsHashTable());
+  return reinterpret_cast<HashTable*>(obj);
+}
+
+
+INT_ACCESSORS(Array, length, kLengthOffset)
+
+
+bool String::Equals(String* other) {
+  if (other == this) return true;
+  if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
+    return false;
+  }
+  return SlowEquals(other);
+}
+
+
+int String::length() {
+  uint32_t len = READ_INT_FIELD(this, kLengthOffset);
+
+  ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
+  ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
+  ASSERT(kLongStringTag == 0);
+
+  return len >> (StringShape(this).size_tag() + kLongLengthShift);
+}
+
+
+void String::set_length(int value) {
+  ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
+  ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
+  ASSERT(kLongStringTag == 0);
+
+  WRITE_INT_FIELD(this,
+                  kLengthOffset,
+                  value << (StringShape(this).size_tag() + kLongLengthShift));
+}
+
+
+uint32_t String::length_field() {
+  return READ_UINT32_FIELD(this, kLengthOffset);
+}
+
+
+void String::set_length_field(uint32_t value) {
+  WRITE_UINT32_FIELD(this, kLengthOffset, value);
+}
+
+
+Object* String::TryFlattenIfNotFlat() {
+  // We don't need to flatten strings that are already flat.  Since this code
+  // is inlined, it can be helpful in the flat case to not call out to Flatten.
+  if (!IsFlat()) {
+    return TryFlatten();
+  }
+  return this;
+}
+
+
+uint16_t String::Get(int index) {
+  ASSERT(index >= 0 && index < length());
+  switch (StringShape(this).full_representation_tag()) {
+    case kSeqStringTag | kAsciiStringTag:
+      return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
+    case kSeqStringTag | kTwoByteStringTag:
+      return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
+    case kConsStringTag | kAsciiStringTag:
+    case kConsStringTag | kTwoByteStringTag:
+      return ConsString::cast(this)->ConsStringGet(index);
+    case kSlicedStringTag | kAsciiStringTag:
+    case kSlicedStringTag | kTwoByteStringTag:
+      return SlicedString::cast(this)->SlicedStringGet(index);
+    case kExternalStringTag | kAsciiStringTag:
+      return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
+    case kExternalStringTag | kTwoByteStringTag:
+      return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
+    default:
+      break;
+  }
+
+  UNREACHABLE();
+  return 0;
+}
+
+
+void String::Set(int index, uint16_t value) {
+  ASSERT(index >= 0 && index < length());
+  ASSERT(StringShape(this).IsSequential());
+
+  return StringShape(this).IsAsciiRepresentation()
+      ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
+      : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
+}
+
+
+bool String::IsFlat() {
+  switch (StringShape(this).representation_tag()) {
+    case kConsStringTag: {
+      String* second = ConsString::cast(this)->second();
+      // Only flattened strings have second part empty.
+      return second->length() == 0;
+    }
+    case kSlicedStringTag: {
+      StringRepresentationTag tag =
+          StringShape(SlicedString::cast(this)->buffer()).representation_tag();
+      return tag == kSeqStringTag || tag == kExternalStringTag;
+    }
+    default:
+      return true;
+  }
+}
+
+
+uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
+  ASSERT(index >= 0 && index < length());
+  return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
+}
+
+
+void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
+  ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
+  WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
+                   static_cast<byte>(value));
+}
+
+
+Address SeqAsciiString::GetCharsAddress() {
+  return FIELD_ADDR(this, kHeaderSize);
+}
+
+
+char* SeqAsciiString::GetChars() {
+  return reinterpret_cast<char*>(GetCharsAddress());
+}
+
+
+Address SeqTwoByteString::GetCharsAddress() {
+  return FIELD_ADDR(this, kHeaderSize);
+}
+
+
+uc16* SeqTwoByteString::GetChars() {
+  return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
+}
+
+
+uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
+  ASSERT(index >= 0 && index < length());
+  return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
+}
+
+
+void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
+  ASSERT(index >= 0 && index < length());
+  WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
+}
+
+
+int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
+  uint32_t length = READ_INT_FIELD(this, kLengthOffset);
+
+  ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
+  ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
+  ASSERT(kLongStringTag == 0);
+
+  // Use the map (and not 'this') to compute the size tag, since
+  // TwoByteStringSize is called during GC when maps are encoded.
+  length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
+
+  return SizeFor(length);
+}
+
+
+int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
+  uint32_t length = READ_INT_FIELD(this, kLengthOffset);
+
+  ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
+  ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
+  ASSERT(kLongStringTag == 0);
+
+  // Use the map (and not 'this') to compute the size tag, since
+  // AsciiStringSize is called during GC when maps are encoded.
+  length >>= StringShape(instance_type).size_tag() + kLongLengthShift;
+
+  return SizeFor(length);
+}
+
+
+String* ConsString::first() {
+  ASSERT(String::cast(READ_FIELD(this, kSecondOffset))->length() != 0 ||
+      StringShape(
+          String::cast(
+              READ_FIELD(this, kFirstOffset))).IsAsciiRepresentation()
+          == StringShape(this).IsAsciiRepresentation());
+  return String::cast(READ_FIELD(this, kFirstOffset));
+}
+
+
+Object* ConsString::unchecked_first() {
+  return READ_FIELD(this, kFirstOffset);
+}
+
+
+void ConsString::set_first(String* value, WriteBarrierMode mode) {
+  WRITE_FIELD(this, kFirstOffset, value);
+  CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
+}
+
+
+String* ConsString::second() {
+  return String::cast(READ_FIELD(this, kSecondOffset));
+}
+
+
+Object* ConsString::unchecked_second() {
+  return READ_FIELD(this, kSecondOffset);
+}
+
+
+void ConsString::set_second(String* value, WriteBarrierMode mode) {
+  WRITE_FIELD(this, kSecondOffset, value);
+  CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
+}
+
+
+String* SlicedString::buffer() {
+  ASSERT(
+      StringShape(
+          String::cast(READ_FIELD(this, kBufferOffset))).IsAsciiRepresentation()
+      == StringShape(this).IsAsciiRepresentation());
+  return String::cast(READ_FIELD(this, kBufferOffset));
+}
+
+
+void SlicedString::set_buffer(String* buffer) {
+  WRITE_FIELD(this, kBufferOffset, buffer);
+  WRITE_BARRIER(this, kBufferOffset);
+}
+
+
+int SlicedString::start() {
+  return READ_INT_FIELD(this, kStartOffset);
+}
+
+
+void SlicedString::set_start(int start) {
+  WRITE_INT_FIELD(this, kStartOffset, start);
+}
+
+
+ExternalAsciiString::Resource* ExternalAsciiString::resource() {
+  return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
+}
+
+
+void ExternalAsciiString::set_resource(
+    ExternalAsciiString::Resource* resource) {
+  *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
+}
+
+
+Map* ExternalAsciiString::StringMap(int length) {
+  Map* map;
+  // Number of characters: determines the map.
+  if (length <= String::kMaxShortStringSize) {
+    map = Heap::short_external_ascii_string_map();
+  } else if (length <= String::kMaxMediumStringSize) {
+    map = Heap::medium_external_ascii_string_map();
+  } else {
+    map = Heap::long_external_ascii_string_map();
+  }
+  return map;
+}
+
+
+Map* ExternalAsciiString::SymbolMap(int length) {
+  Map* map;
+  // Number of characters: determines the map.
+  if (length <= String::kMaxShortStringSize) {
+    map = Heap::short_external_ascii_symbol_map();
+  } else if (length <= String::kMaxMediumStringSize) {
+    map = Heap::medium_external_ascii_symbol_map();
+  } else {
+    map = Heap::long_external_ascii_symbol_map();
+  }
+  return map;
+}
+
+
+ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
+  return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
+}
+
+
+void ExternalTwoByteString::set_resource(
+    ExternalTwoByteString::Resource* resource) {
+  *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
+}
+
+
+Map* ExternalTwoByteString::StringMap(int length) {
+  Map* map;
+  // Number of characters: determines the map.
+  if (length <= String::kMaxShortStringSize) {
+    map = Heap::short_external_string_map();
+  } else if (length <= String::kMaxMediumStringSize) {
+    map = Heap::medium_external_string_map();
+  } else {
+    map = Heap::long_external_string_map();
+  }
+  return map;
+}
+
+
+Map* ExternalTwoByteString::SymbolMap(int length) {
+  Map* map;
+  // Number of characters: determines the map.
+  if (length <= String::kMaxShortStringSize) {
+    map = Heap::short_external_symbol_map();
+  } else if (length <= String::kMaxMediumStringSize) {
+    map = Heap::medium_external_symbol_map();
+  } else {
+    map = Heap::long_external_symbol_map();
+  }
+  return map;
+}
+
+
+byte ByteArray::get(int index) {
+  ASSERT(index >= 0 && index < this->length());
+  return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
+}
+
+
+void ByteArray::set(int index, byte value) {
+  ASSERT(index >= 0 && index < this->length());
+  WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
+}
+
+
+int ByteArray::get_int(int index) {
+  ASSERT(index >= 0 && (index * kIntSize) < this->length());
+  return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
+}
+
+
+ByteArray* ByteArray::FromDataStartAddress(Address address) {
+  ASSERT_TAG_ALIGNED(address);
+  return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
+}
+
+
+Address ByteArray::GetDataStartAddress() {
+  return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
+}
+
+
+int Map::instance_size() {
+  return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
+}
+
+
+int Map::inobject_properties() {
+  return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
+}
+
+
+int HeapObject::SizeFromMap(Map* map) {
+  InstanceType instance_type = map->instance_type();
+  // Only inline the two most frequent cases.
+  if (instance_type == JS_OBJECT_TYPE) return  map->instance_size();
+  if (instance_type == FIXED_ARRAY_TYPE) {
+    return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
+  }
+  // Otherwise do the general size computation.
+  return SlowSizeFromMap(map);
+}
+
+
+void Map::set_instance_size(int value) {
+  ASSERT((value & ~(kPointerSize - 1)) == value);
+  value >>= kPointerSizeLog2;
+  ASSERT(0 <= value && value < 256);
+  WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
+}
+
+
+void Map::set_inobject_properties(int value) {
+  ASSERT(0 <= value && value < 256);
+  WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
+}
+
+
+InstanceType Map::instance_type() {
+  return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
+}
+
+
+void Map::set_instance_type(InstanceType value) {
+  ASSERT(0 <= value && value < 256);
+  WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
+}
+
+
+int Map::unused_property_fields() {
+  return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
+}
+
+
+void Map::set_unused_property_fields(int value) {
+  WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
+}
+
+
+byte Map::bit_field() {
+  return READ_BYTE_FIELD(this, kBitFieldOffset);
+}
+
+
+void Map::set_bit_field(byte value) {
+  WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
+}
+
+
+void Map::set_non_instance_prototype(bool value) {
+  if (value) {
+    set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
+  } else {
+    set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
+  }
+}
+
+
+bool Map::has_non_instance_prototype() {
+  return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
+}
+
+
+void Map::set_is_access_check_needed(bool access_check_needed) {
+  if (access_check_needed) {
+    set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
+  } else {
+    set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
+  }
+}
+
+
+bool Map::is_access_check_needed() {
+  return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
+}
+
+
+Code::Flags Code::flags() {
+  return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
+}
+
+
+void Code::set_flags(Code::Flags flags) {
+  STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
+  // Make sure that all call stubs have an arguments count.
+  ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
+         ExtractArgumentsCountFromFlags(flags) >= 0);
+  WRITE_INT_FIELD(this, kFlagsOffset, flags);
+}
+
+
+Code::Kind Code::kind() {
+  return ExtractKindFromFlags(flags());
+}
+
+
+InlineCacheState Code::ic_state() {
+  InlineCacheState result = ExtractICStateFromFlags(flags());
+  // Only allow uninitialized or debugger states for non-IC code
+  // objects. This is used in the debugger to determine whether or not
+  // a call to code object has been replaced with a debug break call.
+  ASSERT(is_inline_cache_stub() ||
+         result == UNINITIALIZED ||
+         result == DEBUG_BREAK ||
+         result == DEBUG_PREPARE_STEP_IN);
+  return result;
+}
+
+
+PropertyType Code::type() {
+  ASSERT(ic_state() == MONOMORPHIC);
+  return ExtractTypeFromFlags(flags());
+}
+
+
+int Code::arguments_count() {
+  ASSERT(is_call_stub() || kind() == STUB);
+  return ExtractArgumentsCountFromFlags(flags());
+}
+
+
+CodeStub::Major Code::major_key() {
+  ASSERT(kind() == STUB);
+  return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
+                                                      kStubMajorKeyOffset));
+}
+
+
+void Code::set_major_key(CodeStub::Major major) {
+  ASSERT(kind() == STUB);
+  ASSERT(0 <= major && major < 256);
+  WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
+}
+
+
+bool Code::is_inline_cache_stub() {
+  Kind kind = this->kind();
+  return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
+}
+
+
+Code::Flags Code::ComputeFlags(Kind kind,
+                               InlineCacheState ic_state,
+                               PropertyType type,
+                               int argc) {
+  // Compute the bit mask.
+  int bits = kind << kFlagsKindShift;
+  bits |= ic_state << kFlagsICStateShift;
+  bits |= type << kFlagsTypeShift;
+  bits |= argc << kFlagsArgumentsCountShift;
+  // Cast to flags and validate result before returning it.
+  Flags result = static_cast<Flags>(bits);
+  ASSERT(ExtractKindFromFlags(result) == kind);
+  ASSERT(ExtractICStateFromFlags(result) == ic_state);
+  ASSERT(ExtractTypeFromFlags(result) == type);
+  ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
+  return result;
+}
+
+
+Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
+                                          PropertyType type,
+                                          int argc) {
+  return ComputeFlags(kind, MONOMORPHIC, type, argc);
+}
+
+
+Code::Kind Code::ExtractKindFromFlags(Flags flags) {
+  int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
+  return static_cast<Kind>(bits);
+}
+
+
+InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
+  int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
+  return static_cast<InlineCacheState>(bits);
+}
+
+
+PropertyType Code::ExtractTypeFromFlags(Flags flags) {
+  int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
+  return static_cast<PropertyType>(bits);
+}
+
+
+int Code::ExtractArgumentsCountFromFlags(Flags flags) {
+  return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
+}
+
+
+Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
+  int bits = flags & ~kFlagsTypeMask;
+  return static_cast<Flags>(bits);
+}
+
+
+Code* Code::GetCodeFromTargetAddress(Address address) {
+  HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
+  // GetCodeFromTargetAddress might be called when marking objects during mark
+  // sweep. reinterpret_cast is therefore used instead of the more appropriate
+  // Code::cast. Code::cast does not work when the object's map is
+  // marked.
+  Code* result = reinterpret_cast<Code*>(code);
+  return result;
+}
+
+
+Object* Map::prototype() {
+  return READ_FIELD(this, kPrototypeOffset);
+}
+
+
+void Map::set_prototype(Object* value, WriteBarrierMode mode) {
+  ASSERT(value->IsNull() || value->IsJSObject());
+  WRITE_FIELD(this, kPrototypeOffset, value);
+  CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
+}
+
+
+ACCESSORS(Map, instance_descriptors, DescriptorArray,
+          kInstanceDescriptorsOffset)
+ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
+ACCESSORS(Map, constructor, Object, kConstructorOffset)
+
+ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
+ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
+
+ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
+ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
+ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
+
+ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
+
+ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
+ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
+ACCESSORS(AccessorInfo, data, Object, kDataOffset)
+ACCESSORS(AccessorInfo, name, Object, kNameOffset)
+ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
+
+ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
+ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
+ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
+
+ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
+ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
+ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
+ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
+ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
+ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
+
+ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
+ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
+
+ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
+ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
+
+ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
+ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
+ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
+          kPropertyAccessorsOffset)
+ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
+          kPrototypeTemplateOffset)
+ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
+ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
+          kNamedPropertyHandlerOffset)
+ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
+          kIndexedPropertyHandlerOffset)
+ACCESSORS(FunctionTemplateInfo, instance_template, Object,
+          kInstanceTemplateOffset)
+ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
+ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
+ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
+          kInstanceCallHandlerOffset)
+ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
+          kAccessCheckInfoOffset)
+ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
+
+ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
+ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
+          kInternalFieldCountOffset)
+
+ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
+ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
+
+ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
+
+ACCESSORS(Script, source, Object, kSourceOffset)
+ACCESSORS(Script, name, Object, kNameOffset)
+ACCESSORS(Script, id, Object, kIdOffset)
+ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
+ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
+ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
+ACCESSORS(Script, type, Smi, kTypeOffset)
+ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
+
+ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
+ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
+ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
+ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
+
+ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
+ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
+ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
+ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
+
+ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
+ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
+          kInstanceClassNameOffset)
+ACCESSORS(SharedFunctionInfo, function_data, Object,
+          kExternalReferenceDataOffset)
+ACCESSORS(SharedFunctionInfo, lazy_load_data, Object, kLazyLoadDataOffset)
+ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
+ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
+ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
+
+BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
+               kHiddenPrototypeBit)
+BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
+BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
+               kNeedsAccessCheckBit)
+BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
+               kIsExpressionBit)
+BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
+               kIsTopLevelBit)
+
+INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
+INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
+              kFormalParameterCountOffset)
+INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
+              kExpectedNofPropertiesOffset)
+INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
+              kStartPositionAndTypeOffset)
+INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
+INT_ACCESSORS(SharedFunctionInfo, function_token_position,
+              kFunctionTokenPositionOffset)
+
+
+void SharedFunctionInfo::DontAdaptArguments() {
+  ASSERT(code()->kind() == Code::BUILTIN);
+  set_formal_parameter_count(kDontAdaptArgumentsSentinel);
+}
+
+
+int SharedFunctionInfo::start_position() {
+  return start_position_and_type() >> kStartPositionShift;
+}
+
+
+void SharedFunctionInfo::set_start_position(int start_position) {
+  set_start_position_and_type((start_position << kStartPositionShift)
+    | (start_position_and_type() & ~kStartPositionMask));
+}
+
+
+Code* SharedFunctionInfo::code() {
+  return Code::cast(READ_FIELD(this, kCodeOffset));
+}
+
+
+void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
+  WRITE_FIELD(this, kCodeOffset, value);
+  CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
+}
+
+
+bool SharedFunctionInfo::is_compiled() {
+  // TODO(1242782): Create a code kind for uncompiled code.
+  return code()->kind() != Code::STUB;
+}
+
+
+bool JSFunction::IsBoilerplate() {
+  return map() == Heap::boilerplate_function_map();
+}
+
+
+bool JSFunction::IsLoaded() {
+  return shared()->lazy_load_data() == Heap::undefined_value();
+}
+
+
+Code* JSFunction::code() {
+  return shared()->code();
+}
+
+
+void JSFunction::set_code(Code* value) {
+  shared()->set_code(value);
+}
+
+
+Context* JSFunction::context() {
+  return Context::cast(READ_FIELD(this, kContextOffset));
+}
+
+
+Object* JSFunction::unchecked_context() {
+  return READ_FIELD(this, kContextOffset);
+}
+
+
+void JSFunction::set_context(Object* value) {
+  ASSERT(value == Heap::undefined_value() || value->IsContext());
+  WRITE_FIELD(this, kContextOffset, value);
+  WRITE_BARRIER(this, kContextOffset);
+}
+
+ACCESSORS(JSFunction, prototype_or_initial_map, Object,
+          kPrototypeOrInitialMapOffset)
+
+
+Map* JSFunction::initial_map() {
+  return Map::cast(prototype_or_initial_map());
+}
+
+
+void JSFunction::set_initial_map(Map* value) {
+  set_prototype_or_initial_map(value);
+}
+
+
+bool JSFunction::has_initial_map() {
+  return prototype_or_initial_map()->IsMap();
+}
+
+
+bool JSFunction::has_instance_prototype() {
+  return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
+}
+
+
+bool JSFunction::has_prototype() {
+  return map()->has_non_instance_prototype() || has_instance_prototype();
+}
+
+
+Object* JSFunction::instance_prototype() {
+  ASSERT(has_instance_prototype());
+  if (has_initial_map()) return initial_map()->prototype();
+  // When there is no initial map and the prototype is a JSObject, the
+  // initial map field is used for the prototype field.
+  return prototype_or_initial_map();
+}
+
+
+Object* JSFunction::prototype() {
+  ASSERT(has_prototype());
+  // If the function's prototype property has been set to a non-JSObject
+  // value, that value is stored in the constructor field of the map.
+  if (map()->has_non_instance_prototype()) return map()->constructor();
+  return instance_prototype();
+}
+
+
+bool JSFunction::is_compiled() {
+  return shared()->is_compiled();
+}
+
+
+int JSFunction::NumberOfLiterals() {
+  return literals()->length();
+}
+
+
+Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
+  ASSERT(0 <= id && id < kJSBuiltinsCount);
+  return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
+}
+
+
+void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
+                                              Object* value) {
+  ASSERT(0 <= id && id < kJSBuiltinsCount);
+  WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
+  WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
+}
+
+
+Address Proxy::proxy() {
+  return AddressFrom<Address>(READ_INT_FIELD(this, kProxyOffset));
+}
+
+
+void Proxy::set_proxy(Address value) {
+  WRITE_INT_FIELD(this, kProxyOffset, OffsetFrom(value));
+}
+
+
+void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
+  visitor->VisitExternalReference(
+      reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
+}
+
+
+ACCESSORS(JSValue, value, Object, kValueOffset)
+
+
+JSValue* JSValue::cast(Object* obj) {
+  ASSERT(obj->IsJSValue());
+  ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
+  return reinterpret_cast<JSValue*>(obj);
+}
+
+
+INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
+INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
+INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
+
+
+Code::ICTargetState Code::ic_flag() {
+  return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
+}
+
+
+void Code::set_ic_flag(ICTargetState value) {
+  WRITE_BYTE_FIELD(this, kICFlagOffset, value);
+}
+
+
+byte* Code::instruction_start()  {
+  return FIELD_ADDR(this, kHeaderSize);
+}
+
+
+int Code::body_size() {
+  return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
+}
+
+
+byte* Code::relocation_start() {
+  return FIELD_ADDR(this, kHeaderSize + instruction_size());
+}
+
+
+byte* Code::entry() {
+  return instruction_start();
+}
+
+
+bool Code::contains(byte* pc) {
+  return (instruction_start() <= pc) &&
+      (pc < instruction_start() + instruction_size());
+}
+
+
+byte* Code::sinfo_start() {
+  return FIELD_ADDR(this, kHeaderSize + body_size());
+}
+
+
+ACCESSORS(JSArray, length, Object, kLengthOffset)
+
+
+ACCESSORS(JSRegExp, data, Object, kDataOffset)
+
+
+JSRegExp::Type JSRegExp::TypeTag() {
+  Object* data = this->data();
+  if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
+  Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
+  return static_cast<JSRegExp::Type>(smi->value());
+}
+
+
+int JSRegExp::CaptureCount() {
+  switch (TypeTag()) {
+    case ATOM:
+      return 0;
+    case IRREGEXP:
+      return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
+    default:
+      UNREACHABLE();
+      return -1;
+  }
+}
+
+
+JSRegExp::Flags JSRegExp::GetFlags() {
+  ASSERT(this->data()->IsFixedArray());
+  Object* data = this->data();
+  Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
+  return Flags(smi->value());
+}
+
+
+String* JSRegExp::Pattern() {
+  ASSERT(this->data()->IsFixedArray());
+  Object* data = this->data();
+  String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
+  return pattern;
+}
+
+
+Object* JSRegExp::DataAt(int index) {
+  ASSERT(TypeTag() != NOT_COMPILED);
+  return FixedArray::cast(data())->get(index);
+}
+
+
+void JSRegExp::SetDataAt(int index, Object* value) {
+  ASSERT(TypeTag() != NOT_COMPILED);
+  ASSERT(index >= kDataIndex);  // Only implementation data can be set this way.
+  FixedArray::cast(data())->set(index, value);
+}
+
+
+bool JSObject::HasFastElements() {
+  return !elements()->IsDictionary();
+}
+
+
+bool JSObject::HasNamedInterceptor() {
+  return map()->has_named_interceptor();
+}
+
+
+bool JSObject::HasIndexedInterceptor() {
+  return map()->has_indexed_interceptor();
+}
+
+
+Dictionary* JSObject::property_dictionary() {
+  ASSERT(!HasFastProperties());
+  return Dictionary::cast(properties());
+}
+
+
+Dictionary* JSObject::element_dictionary() {
+  ASSERT(!HasFastElements());
+  return Dictionary::cast(elements());
+}
+
+
+bool String::HasHashCode() {
+  return (length_field() & kHashComputedMask) != 0;
+}
+
+
+uint32_t String::Hash() {
+  // Fast case: has hash code already been computed?
+  uint32_t field = length_field();
+  if (field & kHashComputedMask) return field >> kHashShift;
+  // Slow case: compute hash code and set it.
+  return ComputeAndSetHash();
+}
+
+
+StringHasher::StringHasher(int length)
+  : length_(length),
+    raw_running_hash_(0),
+    array_index_(0),
+    is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
+    is_first_char_(true),
+    is_valid_(true) { }
+
+
+bool StringHasher::has_trivial_hash() {
+  return length_ > String::kMaxMediumStringSize;
+}
+
+
+void StringHasher::AddCharacter(uc32 c) {
+  // Use the Jenkins one-at-a-time hash function to update the hash
+  // for the given character.
+  raw_running_hash_ += c;
+  raw_running_hash_ += (raw_running_hash_ << 10);
+  raw_running_hash_ ^= (raw_running_hash_ >> 6);
+  // Incremental array index computation.
+  if (is_array_index_) {
+    if (c < '0' || c > '9') {
+      is_array_index_ = false;
+    } else {
+      int d = c - '0';
+      if (is_first_char_) {
+        is_first_char_ = false;
+        if (c == '0' && length_ > 1) {
+          is_array_index_ = false;
+          return;
+        }
+      }
+      if (array_index_ > 429496729U - ((d + 2) >> 3)) {
+        is_array_index_ = false;
+      } else {
+        array_index_ = array_index_ * 10 + d;
+      }
+    }
+  }
+}
+
+
+void StringHasher::AddCharacterNoIndex(uc32 c) {
+  ASSERT(!is_array_index());
+  raw_running_hash_ += c;
+  raw_running_hash_ += (raw_running_hash_ << 10);
+  raw_running_hash_ ^= (raw_running_hash_ >> 6);
+}
+
+
+uint32_t StringHasher::GetHash() {
+  // Get the calculated raw hash value and do some more bit ops to distribute
+  // the hash further. Ensure that we never return zero as the hash value.
+  uint32_t result = raw_running_hash_;
+  result += (result << 3);
+  result ^= (result >> 11);
+  result += (result << 15);
+  if (result == 0) {
+    result = 27;
+  }
+  return result;
+}
+
+
+bool String::AsArrayIndex(uint32_t* index) {
+  uint32_t field = length_field();
+  if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
+  return SlowAsArrayIndex(index);
+}
+
+
+Object* JSObject::GetPrototype() {
+  return JSObject::cast(this)->map()->prototype();
+}
+
+
+PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
+  return GetPropertyAttributeWithReceiver(this, key);
+}
+
+
+bool JSObject::HasElement(uint32_t index) {
+  return HasElementWithReceiver(this, index);
+}
+
+
+bool AccessorInfo::all_can_read() {
+  return BooleanBit::get(flag(), kAllCanReadBit);
+}
+
+
+void AccessorInfo::set_all_can_read(bool value) {
+  set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
+}
+
+
+bool AccessorInfo::all_can_write() {
+  return BooleanBit::get(flag(), kAllCanWriteBit);
+}
+
+
+void AccessorInfo::set_all_can_write(bool value) {
+  set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
+}
+
+
+bool AccessorInfo::prohibits_overwriting() {
+  return BooleanBit::get(flag(), kProhibitsOverwritingBit);
+}
+
+
+void AccessorInfo::set_prohibits_overwriting(bool value) {
+  set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
+}
+
+
+PropertyAttributes AccessorInfo::property_attributes() {
+  return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
+}
+
+
+void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
+  ASSERT(AttributesField::is_valid(attributes));
+  int rest_value = flag()->value() & ~AttributesField::mask();
+  set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
+}
+
+void Dictionary::SetEntry(int entry,
+                          Object* key,
+                          Object* value,
+                          PropertyDetails details) {
+  ASSERT(!key->IsString() || details.index() > 0);
+  int index = EntryToIndex(entry);
+  WriteBarrierMode mode = GetWriteBarrierMode();
+  set(index, key, mode);
+  set(index+1, value, mode);
+  fast_set(this, index+2, details.AsSmi());
+}
+
+
+void Map::ClearCodeCache() {
+  // No write barrier is needed since empty_fixed_array is not in new space.
+  // Please note this function is used during marking:
+  //  - MarkCompactCollector::MarkUnmarkedObject
+  ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
+  WRITE_FIELD(this, kCodeCacheOffset, Heap::empty_fixed_array());
+}
+
+
+void JSArray::SetContent(FixedArray* storage) {
+  set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
+  set_elements(storage);
+}
+
+
+Object* FixedArray::Copy() {
+  if (length() == 0) return this;
+  return Heap::CopyFixedArray(this);
+}
+
+
+#undef CAST_ACCESSOR
+#undef INT_ACCESSORS
+#undef SMI_ACCESSORS
+#undef ACCESSORS
+#undef FIELD_ADDR
+#undef READ_FIELD
+#undef WRITE_FIELD
+#undef WRITE_BARRIER
+#undef CONDITIONAL_WRITE_BARRIER
+#undef READ_MEMADDR_FIELD
+#undef WRITE_MEMADDR_FIELD
+#undef READ_DOUBLE_FIELD
+#undef WRITE_DOUBLE_FIELD
+#undef READ_INT_FIELD
+#undef WRITE_INT_FIELD
+#undef READ_SHORT_FIELD
+#undef WRITE_SHORT_FIELD
+#undef READ_BYTE_FIELD
+#undef WRITE_BYTE_FIELD
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_OBJECTS_INL_H_
diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc
new file mode 100644
index 0000000..9c640f4
--- /dev/null
+++ b/deps/v8/src/objects.cc
@@ -0,0 +1,7424 @@
+// Copyright 2006-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.
+
+#include "v8.h"
+
+#include "api.h"
+#include "bootstrapper.h"
+#include "debug.h"
+#include "execution.h"
+#include "objects-inl.h"
+#include "macro-assembler.h"
+#include "scanner.h"
+#include "scopeinfo.h"
+#include "string-stream.h"
+
+#ifdef ENABLE_DISASSEMBLER
+#include "disassembler.h"
+#endif
+
+namespace v8 { namespace internal {
+
+#define FIELD_ADDR(p, offset) \
+  (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
+
+
+#define WRITE_FIELD(p, offset, value) \
+  (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
+
+
+#define WRITE_INT_FIELD(p, offset, value) \
+  (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
+
+
+#define WRITE_BARRIER(object, offset) \
+  Heap::RecordWrite(object->address(), offset);
+
+
+// Getters and setters are stored in a fixed array property.  These are
+// constants for their indices.
+const int kGetterIndex = 0;
+const int kSetterIndex = 1;
+
+bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
+  // There is a constraint on the object; check
+  if (!this->IsJSObject()) return false;
+  // Fetch the constructor function of the object
+  Object* cons_obj = JSObject::cast(this)->map()->constructor();
+  if (!cons_obj->IsJSFunction()) return false;
+  JSFunction* fun = JSFunction::cast(cons_obj);
+  // Iterate through the chain of inheriting function templates to
+  // see if the required one occurs.
+  for (Object* type = fun->shared()->function_data();
+       type->IsFunctionTemplateInfo();
+       type = FunctionTemplateInfo::cast(type)->parent_template()) {
+    if (type == expected) return true;
+  }
+  // Didn't find the required type in the inheritance chain.
+  return false;
+}
+
+
+static Object* CreateJSValue(JSFunction* constructor, Object* value) {
+  Object* result = Heap::AllocateJSObject(constructor);
+  if (result->IsFailure()) return result;
+  JSValue::cast(result)->set_value(value);
+  return result;
+}
+
+
+Object* Object::ToObject(Context* global_context) {
+  if (IsNumber()) {
+    return CreateJSValue(global_context->number_function(), this);
+  } else if (IsBoolean()) {
+    return CreateJSValue(global_context->boolean_function(), this);
+  } else if (IsString()) {
+    return CreateJSValue(global_context->string_function(), this);
+  }
+  ASSERT(IsJSObject());
+  return this;
+}
+
+
+Object* Object::ToObject() {
+  Context* global_context = Top::context()->global_context();
+  if (IsJSObject()) {
+    return this;
+  } else if (IsNumber()) {
+    return CreateJSValue(global_context->number_function(), this);
+  } else if (IsBoolean()) {
+    return CreateJSValue(global_context->boolean_function(), this);
+  } else if (IsString()) {
+    return CreateJSValue(global_context->string_function(), this);
+  }
+
+  // Throw a type error.
+  return Failure::InternalError();
+}
+
+
+Object* Object::ToBoolean() {
+  if (IsTrue()) return Heap::true_value();
+  if (IsFalse()) return Heap::false_value();
+  if (IsSmi()) {
+    return Heap::ToBoolean(Smi::cast(this)->value() != 0);
+  }
+  if (IsUndefined() || IsNull()) return Heap::false_value();
+  // Undetectable object is false
+  if (IsUndetectableObject()) {
+    return Heap::false_value();
+  }
+  if (IsString()) {
+    return Heap::ToBoolean(String::cast(this)->length() != 0);
+  }
+  if (IsHeapNumber()) {
+    return HeapNumber::cast(this)->HeapNumberToBoolean();
+  }
+  return Heap::true_value();
+}
+
+
+void Object::Lookup(String* name, LookupResult* result) {
+  if (IsJSObject()) return JSObject::cast(this)->Lookup(name, result);
+  Object* holder = NULL;
+  Context* global_context = Top::context()->global_context();
+  if (IsString()) {
+    holder = global_context->string_function()->instance_prototype();
+  } else if (IsNumber()) {
+    holder = global_context->number_function()->instance_prototype();
+  } else if (IsBoolean()) {
+    holder = global_context->boolean_function()->instance_prototype();
+  }
+  ASSERT(holder != NULL);  // cannot handle null or undefined.
+  JSObject::cast(holder)->Lookup(name, result);
+}
+
+
+Object* Object::GetPropertyWithReceiver(Object* receiver,
+                                        String* name,
+                                        PropertyAttributes* attributes) {
+  LookupResult result;
+  Lookup(name, &result);
+  Object* value = GetProperty(receiver, &result, name, attributes);
+  ASSERT(*attributes <= ABSENT);
+  return value;
+}
+
+
+Object* Object::GetPropertyWithCallback(Object* receiver,
+                                        Object* structure,
+                                        String* name,
+                                        Object* holder) {
+  // To accommodate both the old and the new api we switch on the
+  // data structure used to store the callbacks.  Eventually proxy
+  // callbacks should be phased out.
+  if (structure->IsProxy()) {
+    AccessorDescriptor* callback =
+        reinterpret_cast<AccessorDescriptor*>(Proxy::cast(structure)->proxy());
+    Object* value = (callback->getter)(receiver, callback->data);
+    RETURN_IF_SCHEDULED_EXCEPTION();
+    return value;
+  }
+
+  // api style callbacks.
+  if (structure->IsAccessorInfo()) {
+    AccessorInfo* data = AccessorInfo::cast(structure);
+    Object* fun_obj = data->getter();
+    v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
+    HandleScope scope;
+    Handle<JSObject> self(JSObject::cast(receiver));
+    Handle<JSObject> holder_handle(JSObject::cast(holder));
+    Handle<String> key(name);
+    Handle<Object> fun_data(data->data());
+    LOG(ApiNamedPropertyAccess("load", *self, name));
+    v8::AccessorInfo info(v8::Utils::ToLocal(self),
+                          v8::Utils::ToLocal(fun_data),
+                          v8::Utils::ToLocal(holder_handle));
+    v8::Handle<v8::Value> result;
+    {
+      // Leaving JavaScript.
+      VMState state(EXTERNAL);
+      result = call_fun(v8::Utils::ToLocal(key), info);
+    }
+    RETURN_IF_SCHEDULED_EXCEPTION();
+    if (result.IsEmpty()) return Heap::undefined_value();
+    return *v8::Utils::OpenHandle(*result);
+  }
+
+  // __defineGetter__ callback
+  if (structure->IsFixedArray()) {
+    Object* getter = FixedArray::cast(structure)->get(kGetterIndex);
+    if (getter->IsJSFunction()) {
+      return Object::GetPropertyWithDefinedGetter(receiver,
+                                                  JSFunction::cast(getter));
+    }
+    // Getter is not a function.
+    return Heap::undefined_value();
+  }
+
+  UNREACHABLE();
+  return 0;
+}
+
+
+Object* Object::GetPropertyWithDefinedGetter(Object* receiver,
+                                             JSFunction* getter) {
+  HandleScope scope;
+  Handle<JSFunction> fun(JSFunction::cast(getter));
+  Handle<Object> self(receiver);
+  bool has_pending_exception;
+  Handle<Object> result =
+      Execution::Call(fun, self, 0, NULL, &has_pending_exception);
+  // Check for pending exception and return the result.
+  if (has_pending_exception) return Failure::Exception();
+  return *result;
+}
+
+
+// Only deal with CALLBACKS and INTERCEPTOR
+Object* JSObject::GetPropertyWithFailedAccessCheck(
+    Object* receiver,
+    LookupResult* result,
+    String* name,
+    PropertyAttributes* attributes) {
+  if (result->IsValid()) {
+    switch (result->type()) {
+      case CALLBACKS: {
+        // Only allow API accessors.
+        Object* obj = result->GetCallbackObject();
+        if (obj->IsAccessorInfo()) {
+          AccessorInfo* info = AccessorInfo::cast(obj);
+          if (info->all_can_read()) {
+            *attributes = result->GetAttributes();
+            return GetPropertyWithCallback(receiver,
+                                           result->GetCallbackObject(),
+                                           name,
+                                           result->holder());
+          }
+        }
+        break;
+      }
+      case NORMAL:
+      case FIELD:
+      case CONSTANT_FUNCTION: {
+        // Search ALL_CAN_READ accessors in prototype chain.
+        LookupResult r;
+        result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
+        if (r.IsValid()) {
+          return GetPropertyWithFailedAccessCheck(receiver,
+                                                  &r,
+                                                  name,
+                                                  attributes);
+        }
+        break;
+      }
+      case INTERCEPTOR: {
+        // If the object has an interceptor, try real named properties.
+        // No access check in GetPropertyAttributeWithInterceptor.
+        LookupResult r;
+        result->holder()->LookupRealNamedProperty(name, &r);
+        if (r.IsValid()) {
+          return GetPropertyWithFailedAccessCheck(receiver,
+                                                  &r,
+                                                  name,
+                                                  attributes);
+        }
+      }
+      default: {
+        break;
+      }
+    }
+  }
+
+  // No accessible property found.
+  *attributes = ABSENT;
+  Top::ReportFailedAccessCheck(this, v8::ACCESS_GET);
+  return Heap::undefined_value();
+}
+
+
+PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck(
+    Object* receiver,
+    LookupResult* result,
+    String* name,
+    bool continue_search) {
+  if (result->IsValid()) {
+    switch (result->type()) {
+      case CALLBACKS: {
+        // Only allow API accessors.
+        Object* obj = result->GetCallbackObject();
+        if (obj->IsAccessorInfo()) {
+          AccessorInfo* info = AccessorInfo::cast(obj);
+          if (info->all_can_read()) {
+            return result->GetAttributes();
+          }
+        }
+        break;
+      }
+
+      case NORMAL:
+      case FIELD:
+      case CONSTANT_FUNCTION: {
+        if (!continue_search) break;
+        // Search ALL_CAN_READ accessors in prototype chain.
+        LookupResult r;
+        result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
+        if (r.IsValid()) {
+          return GetPropertyAttributeWithFailedAccessCheck(receiver,
+                                                           &r,
+                                                           name,
+                                                           continue_search);
+        }
+        break;
+      }
+
+      case INTERCEPTOR: {
+        // If the object has an interceptor, try real named properties.
+        // No access check in GetPropertyAttributeWithInterceptor.
+        LookupResult r;
+        if (continue_search) {
+          result->holder()->LookupRealNamedProperty(name, &r);
+        } else {
+          result->holder()->LocalLookupRealNamedProperty(name, &r);
+        }
+        if (r.IsValid()) {
+          return GetPropertyAttributeWithFailedAccessCheck(receiver,
+                                                           &r,
+                                                           name,
+                                                           continue_search);
+        }
+        break;
+      }
+
+      default: {
+        break;
+      }
+    }
+  }
+
+  Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
+  return ABSENT;
+}
+
+
+Object* JSObject::GetLazyProperty(Object* receiver,
+                                  LookupResult* result,
+                                  String* name,
+                                  PropertyAttributes* attributes) {
+  HandleScope scope;
+  Handle<Object> this_handle(this);
+  Handle<Object> receiver_handle(receiver);
+  Handle<String> name_handle(name);
+  bool pending_exception;
+  LoadLazy(Handle<JSFunction>(JSFunction::cast(result->GetValue())),
+           &pending_exception);
+  if (pending_exception) return Failure::Exception();
+  return this_handle->GetPropertyWithReceiver(*receiver_handle,
+                                              *name_handle,
+                                              attributes);
+}
+
+
+Object* JSObject::SetLazyProperty(LookupResult* result,
+                                  String* name,
+                                  Object* value,
+                                  PropertyAttributes attributes) {
+  ASSERT(!IsJSGlobalProxy());
+  HandleScope scope;
+  Handle<JSObject> this_handle(this);
+  Handle<String> name_handle(name);
+  Handle<Object> value_handle(value);
+  bool pending_exception;
+  LoadLazy(Handle<JSFunction>(JSFunction::cast(result->GetValue())),
+           &pending_exception);
+  if (pending_exception) return Failure::Exception();
+  return this_handle->SetProperty(*name_handle, *value_handle, attributes);
+}
+
+
+Object* JSObject::DeleteLazyProperty(LookupResult* result, String* name) {
+  HandleScope scope;
+  Handle<JSObject> this_handle(this);
+  Handle<String> name_handle(name);
+  bool pending_exception;
+  LoadLazy(Handle<JSFunction>(JSFunction::cast(result->GetValue())),
+           &pending_exception);
+  if (pending_exception) return Failure::Exception();
+  return this_handle->DeleteProperty(*name_handle);
+}
+
+
+Object* Object::GetProperty(Object* receiver,
+                            LookupResult* result,
+                            String* name,
+                            PropertyAttributes* attributes) {
+  // Make sure that the top context does not change when doing
+  // callbacks or interceptor calls.
+  AssertNoContextChange ncc;
+
+  // Traverse the prototype chain from the current object (this) to
+  // the holder and check for access rights. This avoid traversing the
+  // objects more than once in case of interceptors, because the
+  // holder will always be the interceptor holder and the search may
+  // only continue with a current object just after the interceptor
+  // holder in the prototype chain.
+  Object* last = result->IsValid() ? result->holder() : Heap::null_value();
+  for (Object* current = this; true; current = current->GetPrototype()) {
+    if (current->IsAccessCheckNeeded()) {
+      // Check if we're allowed to read from the current object. Note
+      // that even though we may not actually end up loading the named
+      // property from the current object, we still check that we have
+      // access to it.
+      JSObject* checked = JSObject::cast(current);
+      if (!Top::MayNamedAccess(checked, name, v8::ACCESS_GET)) {
+        return checked->GetPropertyWithFailedAccessCheck(receiver,
+                                                         result,
+                                                         name,
+                                                         attributes);
+      }
+    }
+    // Stop traversing the chain once we reach the last object in the
+    // chain; either the holder of the result or null in case of an
+    // absent property.
+    if (current == last) break;
+  }
+
+  if (!result->IsProperty()) {
+    *attributes = ABSENT;
+    return Heap::undefined_value();
+  }
+  *attributes = result->GetAttributes();
+  if (!result->IsLoaded()) {
+    return JSObject::cast(this)->GetLazyProperty(receiver,
+                                                 result,
+                                                 name,
+                                                 attributes);
+  }
+  Object* value;
+  JSObject* holder = result->holder();
+  switch (result->type()) {
+    case NORMAL:
+      value =
+          holder->property_dictionary()->ValueAt(result->GetDictionaryEntry());
+      ASSERT(!value->IsTheHole() || result->IsReadOnly());
+      return value->IsTheHole() ? Heap::undefined_value() : value;
+    case FIELD:
+      value = holder->FastPropertyAt(result->GetFieldIndex());
+      ASSERT(!value->IsTheHole() || result->IsReadOnly());
+      return value->IsTheHole() ? Heap::undefined_value() : value;
+    case CONSTANT_FUNCTION:
+      return result->GetConstantFunction();
+    case CALLBACKS:
+      return GetPropertyWithCallback(receiver,
+                                     result->GetCallbackObject(),
+                                     name,
+                                     holder);
+    case INTERCEPTOR: {
+      JSObject* recvr = JSObject::cast(receiver);
+      return holder->GetPropertyWithInterceptor(recvr, name, attributes);
+    }
+    default:
+      UNREACHABLE();
+      return NULL;
+  }
+}
+
+
+Object* Object::GetElementWithReceiver(Object* receiver, uint32_t index) {
+  // Non-JS objects do not have integer indexed properties.
+  if (!IsJSObject()) return Heap::undefined_value();
+  return JSObject::cast(this)->GetElementWithReceiver(JSObject::cast(receiver),
+                                                      index);
+}
+
+
+Object* Object::GetPrototype() {
+  // The object is either a number, a string, a boolean, or a real JS object.
+  if (IsJSObject()) return JSObject::cast(this)->map()->prototype();
+  Context* context = Top::context()->global_context();
+
+  if (IsNumber()) return context->number_function()->instance_prototype();
+  if (IsString()) return context->string_function()->instance_prototype();
+  if (IsBoolean()) {
+    return context->boolean_function()->instance_prototype();
+  } else {
+    return Heap::null_value();
+  }
+}
+
+
+void Object::ShortPrint() {
+  HeapStringAllocator allocator;
+  StringStream accumulator(&allocator);
+  ShortPrint(&accumulator);
+  accumulator.OutputToStdOut();
+}
+
+
+void Object::ShortPrint(StringStream* accumulator) {
+  if (IsSmi()) {
+    Smi::cast(this)->SmiPrint(accumulator);
+  } else if (IsFailure()) {
+    Failure::cast(this)->FailurePrint(accumulator);
+  } else {
+    HeapObject::cast(this)->HeapObjectShortPrint(accumulator);
+  }
+}
+
+
+void Smi::SmiPrint() {
+  PrintF("%d", value());
+}
+
+
+void Smi::SmiPrint(StringStream* accumulator) {
+  accumulator->Add("%d", value());
+}
+
+
+void Failure::FailurePrint(StringStream* accumulator) {
+  accumulator->Add("Failure(%d)", value());
+}
+
+
+void Failure::FailurePrint() {
+  PrintF("Failure(%d)", value());
+}
+
+
+Failure* Failure::RetryAfterGC(int requested_bytes, AllocationSpace space) {
+  ASSERT((space & ~kSpaceTagMask) == 0);
+  int requested = requested_bytes >> kObjectAlignmentBits;
+  int value = (requested << kSpaceTagSize) | space;
+  // We can't very well allocate a heap number in this situation, and if the
+  // requested memory is so large it seems reasonable to say that this is an
+  // out of memory situation.  This fixes a crash in
+  // js1_5/Regress/regress-303213.js.
+  if (value >> kSpaceTagSize != requested ||
+      !Smi::IsValid(value) ||
+      value != ((value << kFailureTypeTagSize) >> kFailureTypeTagSize) ||
+      !Smi::IsValid(value << kFailureTypeTagSize)) {
+    Top::context()->mark_out_of_memory();
+    return Failure::OutOfMemoryException();
+  }
+  return Construct(RETRY_AFTER_GC, value);
+}
+
+
+// Should a word be prefixed by 'a' or 'an' in order to read naturally in
+// English?  Returns false for non-ASCII or words that don't start with
+// a capital letter.  The a/an rule follows pronunciation in English.
+// We don't use the BBC's overcorrect "an historic occasion" though if
+// you speak a dialect you may well say "an 'istoric occasion".
+static bool AnWord(String* str) {
+  if (str->length() == 0) return false;  // A nothing.
+  int c0 = str->Get(0);
+  int c1 = str->length() > 1 ? str->Get(1) : 0;
+  if (c0 == 'U') {
+    if (c1 > 'Z') {
+      return true;  // An Umpire, but a UTF8String, a U.
+    }
+  } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
+    return true;    // An Ape, an ABCBook.
+  } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
+           (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
+            c0 == 'S' || c0 == 'X')) {
+    return true;    // An MP3File, an M.
+  }
+  return false;
+}
+
+
+Object* String::TryFlatten() {
+#ifdef DEBUG
+  // Do not attempt to flatten in debug mode when allocation is not
+  // allowed.  This is to avoid an assertion failure when allocating.
+  // Flattening strings is the only case where we always allow
+  // allocation because no GC is performed if the allocation fails.
+  if (!Heap::IsAllocationAllowed()) return this;
+#endif
+
+  switch (StringShape(this).representation_tag()) {
+    case kSlicedStringTag: {
+      SlicedString* ss = SlicedString::cast(this);
+      // The SlicedString constructor should ensure that there are no
+      // SlicedStrings that are constructed directly on top of other
+      // SlicedStrings.
+      String* buf = ss->buffer();
+      ASSERT(!buf->IsSlicedString());
+      Object* ok = buf->TryFlatten();
+      if (ok->IsFailure()) return ok;
+      // Under certain circumstances (TryFlattenIfNotFlat fails in
+      // String::Slice) we can have a cons string under a slice.
+      // In this case we need to get the flat string out of the cons!
+      if (StringShape(String::cast(ok)).IsCons()) {
+        ss->set_buffer(ConsString::cast(ok)->first());
+      }
+      ASSERT(StringShape(this).IsAsciiRepresentation() ==
+          StringShape(ss->buffer()).IsAsciiRepresentation());
+      return this;
+    }
+    case kConsStringTag: {
+      ConsString* cs = ConsString::cast(this);
+      if (cs->second()->length() == 0) {
+        return this;
+      }
+      // There's little point in putting the flat string in new space if the
+      // cons string is in old space.  It can never get GCed until there is
+      // an old space GC.
+      PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED;
+      int len = length();
+      Object* object;
+      String* result;
+      if (StringShape(this).IsAsciiRepresentation()) {
+        object = Heap::AllocateRawAsciiString(len, tenure);
+        if (object->IsFailure()) return object;
+        result = String::cast(object);
+        String* first = cs->first();
+        int first_length = first->length();
+        char* dest = SeqAsciiString::cast(result)->GetChars();
+        WriteToFlat(first, dest, 0, first_length);
+        String* second = cs->second();
+        WriteToFlat(second,
+                    dest + first_length,
+                    0,
+                    len - first_length);
+      } else {
+        object = Heap::AllocateRawTwoByteString(len, tenure);
+        if (object->IsFailure()) return object;
+        result = String::cast(object);
+        uc16* dest = SeqTwoByteString::cast(result)->GetChars();
+        String* first = cs->first();
+        int first_length = first->length();
+        WriteToFlat(first, dest, 0, first_length);
+        String* second = cs->second();
+        WriteToFlat(second,
+                    dest + first_length,
+                    0,
+                    len - first_length);
+      }
+      cs->set_first(result);
+      cs->set_second(Heap::empty_string());
+      return this;
+    }
+    default:
+      return this;
+  }
+}
+
+
+bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
+#ifdef DEBUG
+  {  // NOLINT (presubmit.py gets confused about if and braces)
+    // Assert that the resource and the string are equivalent.
+    ASSERT(static_cast<size_t>(this->length()) == resource->length());
+    SmartPointer<uc16> smart_chars = this->ToWideCString();
+    ASSERT(memcmp(*smart_chars,
+                  resource->data(),
+                  resource->length() * sizeof(**smart_chars)) == 0);
+  }
+#endif  // DEBUG
+
+  int size = this->Size();  // Byte size of the original string.
+  if (size < ExternalString::kSize) {
+    // The string is too small to fit an external String in its place. This can
+    // only happen for zero length strings.
+    return false;
+  }
+  ASSERT(size >= ExternalString::kSize);
+  bool is_symbol = this->IsSymbol();
+  int length = this->length();
+
+  // Morph the object to an external string by adjusting the map and
+  // reinitializing the fields.
+  this->set_map(ExternalTwoByteString::StringMap(length));
+  ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
+  self->set_length(length);
+  self->set_resource(resource);
+  // Additionally make the object into an external symbol if the original string
+  // was a symbol to start with.
+  if (is_symbol) {
+    self->Hash();  // Force regeneration of the hash value.
+    // Now morph this external string into a external symbol.
+    self->set_map(ExternalTwoByteString::SymbolMap(length));
+  }
+
+  // Fill the remainder of the string with dead wood.
+  int new_size = this->Size();  // Byte size of the external String object.
+  Heap::CreateFillerObjectAt(this->address() + new_size, size - new_size);
+  return true;
+}
+
+
+bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) {
+#ifdef DEBUG
+  {  // NOLINT (presubmit.py gets confused about if and braces)
+    // Assert that the resource and the string are equivalent.
+    ASSERT(static_cast<size_t>(this->length()) == resource->length());
+    SmartPointer<char> smart_chars = this->ToCString();
+    ASSERT(memcmp(*smart_chars,
+                  resource->data(),
+                  resource->length()*sizeof(**smart_chars)) == 0);
+  }
+#endif  // DEBUG
+
+  int size = this->Size();  // Byte size of the original string.
+  if (size < ExternalString::kSize) {
+    // The string is too small to fit an external String in its place. This can
+    // only happen for zero length strings.
+    return false;
+  }
+  ASSERT(size >= ExternalString::kSize);
+  bool is_symbol = this->IsSymbol();
+  int length = this->length();
+
+  // Morph the object to an external string by adjusting the map and
+  // reinitializing the fields.
+  this->set_map(ExternalAsciiString::StringMap(length));
+  ExternalAsciiString* self = ExternalAsciiString::cast(this);
+  self->set_length(length);
+  self->set_resource(resource);
+  // Additionally make the object into an external symbol if the original string
+  // was a symbol to start with.
+  if (is_symbol) {
+    self->Hash();  // Force regeneration of the hash value.
+    // Now morph this external string into a external symbol.
+    self->set_map(ExternalAsciiString::SymbolMap(length));
+  }
+
+  // Fill the remainder of the string with dead wood.
+  int new_size = this->Size();  // Byte size of the external String object.
+  Heap::CreateFillerObjectAt(this->address() + new_size, size - new_size);
+  return true;
+}
+
+
+void String::StringShortPrint(StringStream* accumulator) {
+  int len = length();
+  if (len > kMaxMediumStringSize) {
+    accumulator->Add("<Very long string[%u]>", len);
+    return;
+  }
+
+  if (!LooksValid()) {
+    accumulator->Add("<Invalid String>");
+    return;
+  }
+
+  StringInputBuffer buf(this);
+
+  bool truncated = false;
+  if (len > kMaxShortPrintLength) {
+    len = kMaxShortPrintLength;
+    truncated = true;
+  }
+  bool ascii = true;
+  for (int i = 0; i < len; i++) {
+    int c = buf.GetNext();
+
+    if (c < 32 || c >= 127) {
+      ascii = false;
+    }
+  }
+  buf.Reset(this);
+  if (ascii) {
+    accumulator->Add("<String[%u]: ", length());
+    for (int i = 0; i < len; i++) {
+      accumulator->Put(buf.GetNext());
+    }
+    accumulator->Put('>');
+  } else {
+    // Backslash indicates that the string contains control
+    // characters and that backslashes are therefore escaped.
+    accumulator->Add("<String[%u]\\: ", length());
+    for (int i = 0; i < len; i++) {
+      int c = buf.GetNext();
+      if (c == '\n') {
+        accumulator->Add("\\n");
+      } else if (c == '\r') {
+        accumulator->Add("\\r");
+      } else if (c == '\\') {
+        accumulator->Add("\\\\");
+      } else if (c < 32 || c > 126) {
+        accumulator->Add("\\x%02x", c);
+      } else {
+        accumulator->Put(c);
+      }
+    }
+    if (truncated) {
+      accumulator->Put('.');
+      accumulator->Put('.');
+      accumulator->Put('.');
+    }
+    accumulator->Put('>');
+  }
+  return;
+}
+
+
+void JSObject::JSObjectShortPrint(StringStream* accumulator) {
+  switch (map()->instance_type()) {
+    case JS_ARRAY_TYPE: {
+      double length = JSArray::cast(this)->length()->Number();
+      accumulator->Add("<JS array[%u]>", static_cast<uint32_t>(length));
+      break;
+    }
+    case JS_REGEXP_TYPE: {
+      accumulator->Add("<JS RegExp>");
+      break;
+    }
+    case JS_FUNCTION_TYPE: {
+      Object* fun_name = JSFunction::cast(this)->shared()->name();
+      bool printed = false;
+      if (fun_name->IsString()) {
+        String* str = String::cast(fun_name);
+        if (str->length() > 0) {
+          accumulator->Add("<JS Function ");
+          accumulator->Put(str);
+          accumulator->Put('>');
+          printed = true;
+        }
+      }
+      if (!printed) {
+        accumulator->Add("<JS Function>");
+      }
+      break;
+    }
+    // All other JSObjects are rather similar to each other (JSObject,
+    // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue).
+    default: {
+      Object* constructor = map()->constructor();
+      bool printed = false;
+      if (constructor->IsHeapObject() &&
+          !Heap::Contains(HeapObject::cast(constructor))) {
+        accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
+      } else {
+        bool global_object = IsJSGlobalProxy();
+        if (constructor->IsJSFunction()) {
+          if (!Heap::Contains(JSFunction::cast(constructor)->shared())) {
+            accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
+          } else {
+            Object* constructor_name =
+                JSFunction::cast(constructor)->shared()->name();
+            if (constructor_name->IsString()) {
+              String* str = String::cast(constructor_name);
+              if (str->length() > 0) {
+                bool vowel = AnWord(str);
+                accumulator->Add("<%sa%s ",
+                       global_object ? "Global Object: " : "",
+                       vowel ? "n" : "");
+                accumulator->Put(str);
+                accumulator->Put('>');
+                printed = true;
+              }
+            }
+          }
+        }
+        if (!printed) {
+          accumulator->Add("<JS %sObject", global_object ? "Global " : "");
+        }
+      }
+      if (IsJSValue()) {
+        accumulator->Add(" value = ");
+        JSValue::cast(this)->value()->ShortPrint(accumulator);
+      }
+      accumulator->Put('>');
+      break;
+    }
+  }
+}
+
+
+void HeapObject::HeapObjectShortPrint(StringStream* accumulator) {
+  // if (!Heap::InNewSpace(this)) PrintF("*", this);
+  if (!Heap::Contains(this)) {
+    accumulator->Add("!!!INVALID POINTER!!!");
+    return;
+  }
+  if (!Heap::Contains(map())) {
+    accumulator->Add("!!!INVALID MAP!!!");
+    return;
+  }
+
+  accumulator->Add("%p ", this);
+
+  if (IsString()) {
+    String::cast(this)->StringShortPrint(accumulator);
+    return;
+  }
+  if (IsJSObject()) {
+    JSObject::cast(this)->JSObjectShortPrint(accumulator);
+    return;
+  }
+  switch (map()->instance_type()) {
+    case MAP_TYPE:
+      accumulator->Add("<Map>");
+      break;
+    case FIXED_ARRAY_TYPE:
+      accumulator->Add("<FixedArray[%u]>", FixedArray::cast(this)->length());
+      break;
+    case BYTE_ARRAY_TYPE:
+      accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length());
+      break;
+    case SHARED_FUNCTION_INFO_TYPE:
+      accumulator->Add("<SharedFunctionInfo>");
+      break;
+#define MAKE_STRUCT_CASE(NAME, Name, name) \
+  case NAME##_TYPE:                        \
+    accumulator->Put('<');                 \
+    accumulator->Add(#Name);               \
+    accumulator->Put('>');                 \
+    break;
+  STRUCT_LIST(MAKE_STRUCT_CASE)
+#undef MAKE_STRUCT_CASE
+    case CODE_TYPE:
+      accumulator->Add("<Code>");
+      break;
+    case ODDBALL_TYPE: {
+      if (IsUndefined())
+        accumulator->Add("<undefined>");
+      else if (IsTheHole())
+        accumulator->Add("<the hole>");
+      else if (IsNull())
+        accumulator->Add("<null>");
+      else if (IsTrue())
+        accumulator->Add("<true>");
+      else if (IsFalse())
+        accumulator->Add("<false>");
+      else
+        accumulator->Add("<Odd Oddball>");
+      break;
+    }
+    case HEAP_NUMBER_TYPE:
+      accumulator->Add("<Number: ");
+      HeapNumber::cast(this)->HeapNumberPrint(accumulator);
+      accumulator->Put('>');
+      break;
+    case PROXY_TYPE:
+      accumulator->Add("<Proxy>");
+      break;
+    default:
+      accumulator->Add("<Other heap object (%d)>", map()->instance_type());
+      break;
+  }
+}
+
+
+int HeapObject::SlowSizeFromMap(Map* map) {
+  // Avoid calling functions such as FixedArray::cast during GC, which
+  // read map pointer of this object again.
+  InstanceType instance_type = map->instance_type();
+
+  if (instance_type < FIRST_NONSTRING_TYPE
+      && (StringShape(instance_type).IsSequential())) {
+    if (StringShape(instance_type).IsAsciiRepresentation()) {
+      SeqAsciiString* seq_ascii_this = reinterpret_cast<SeqAsciiString*>(this);
+      return seq_ascii_this->SeqAsciiStringSize(instance_type);
+    } else {
+      SeqTwoByteString* self = reinterpret_cast<SeqTwoByteString*>(this);
+      return self->SeqTwoByteStringSize(instance_type);
+    }
+  }
+
+  switch (instance_type) {
+    case FIXED_ARRAY_TYPE:
+      return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
+    case BYTE_ARRAY_TYPE:
+      return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
+    case CODE_TYPE:
+      return reinterpret_cast<Code*>(this)->CodeSize();
+    case MAP_TYPE:
+      return Map::kSize;
+    default:
+      return map->instance_size();
+  }
+}
+
+
+void HeapObject::Iterate(ObjectVisitor* v) {
+  // Handle header
+  IteratePointer(v, kMapOffset);
+  // Handle object body
+  Map* m = map();
+  IterateBody(m->instance_type(), SizeFromMap(m), v);
+}
+
+
+void HeapObject::IterateBody(InstanceType type, int object_size,
+                             ObjectVisitor* v) {
+  // Avoiding <Type>::cast(this) because it accesses the map pointer field.
+  // During GC, the map pointer field is encoded.
+  if (type < FIRST_NONSTRING_TYPE) {
+    switch (type & kStringRepresentationMask) {
+      case kSeqStringTag:
+        break;
+      case kConsStringTag:
+        reinterpret_cast<ConsString*>(this)->ConsStringIterateBody(v);
+        break;
+      case kSlicedStringTag:
+        reinterpret_cast<SlicedString*>(this)->SlicedStringIterateBody(v);
+        break;
+    }
+    return;
+  }
+
+  switch (type) {
+    case FIXED_ARRAY_TYPE:
+      reinterpret_cast<FixedArray*>(this)->FixedArrayIterateBody(v);
+      break;
+    case JS_OBJECT_TYPE:
+    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
+    case JS_VALUE_TYPE:
+    case JS_ARRAY_TYPE:
+    case JS_REGEXP_TYPE:
+    case JS_FUNCTION_TYPE:
+    case JS_GLOBAL_PROXY_TYPE:
+    case JS_GLOBAL_OBJECT_TYPE:
+    case JS_BUILTINS_OBJECT_TYPE:
+      reinterpret_cast<JSObject*>(this)->JSObjectIterateBody(object_size, v);
+      break;
+    case ODDBALL_TYPE:
+      reinterpret_cast<Oddball*>(this)->OddballIterateBody(v);
+      break;
+    case PROXY_TYPE:
+      reinterpret_cast<Proxy*>(this)->ProxyIterateBody(v);
+      break;
+    case MAP_TYPE:
+      reinterpret_cast<Map*>(this)->MapIterateBody(v);
+      break;
+    case CODE_TYPE:
+      reinterpret_cast<Code*>(this)->CodeIterateBody(v);
+      break;
+    case HEAP_NUMBER_TYPE:
+    case FILLER_TYPE:
+    case BYTE_ARRAY_TYPE:
+      break;
+    case SHARED_FUNCTION_INFO_TYPE: {
+      SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(this);
+      shared->SharedFunctionInfoIterateBody(v);
+      break;
+    }
+#define MAKE_STRUCT_CASE(NAME, Name, name) \
+        case NAME##_TYPE:
+      STRUCT_LIST(MAKE_STRUCT_CASE)
+#undef MAKE_STRUCT_CASE
+      IterateStructBody(object_size, v);
+      break;
+    default:
+      PrintF("Unknown type: %d\n", type);
+      UNREACHABLE();
+  }
+}
+
+
+void HeapObject::IterateStructBody(int object_size, ObjectVisitor* v) {
+  IteratePointers(v, HeapObject::kHeaderSize, object_size);
+}
+
+
+Object* HeapNumber::HeapNumberToBoolean() {
+  // NaN, +0, and -0 should return the false object
+  switch (fpclassify(value())) {
+    case FP_NAN:  // fall through
+    case FP_ZERO: return Heap::false_value();
+    default: return Heap::true_value();
+  }
+}
+
+
+void HeapNumber::HeapNumberPrint() {
+  PrintF("%.16g", Number());
+}
+
+
+void HeapNumber::HeapNumberPrint(StringStream* accumulator) {
+  // The Windows version of vsnprintf can allocate when printing a %g string
+  // into a buffer that may not be big enough.  We don't want random memory
+  // allocation when producing post-crash stack traces, so we print into a
+  // buffer that is plenty big enough for any floating point number, then
+  // print that using vsnprintf (which may truncate but never allocate if
+  // there is no more space in the buffer).
+  EmbeddedVector<char, 100> buffer;
+  OS::SNPrintF(buffer, "%.16g", Number());
+  accumulator->Add("%s", buffer.start());
+}
+
+
+String* JSObject::class_name() {
+  if (IsJSFunction()) return Heap::function_class_symbol();
+  if (map()->constructor()->IsJSFunction()) {
+    JSFunction* constructor = JSFunction::cast(map()->constructor());
+    return String::cast(constructor->shared()->instance_class_name());
+  }
+  // If the constructor is not present, return "Object".
+  return Heap::Object_symbol();
+}
+
+
+void JSObject::JSObjectIterateBody(int object_size, ObjectVisitor* v) {
+  // Iterate over all fields in the body. Assumes all are Object*.
+  IteratePointers(v, kPropertiesOffset, object_size);
+}
+
+
+Object* JSObject::AddFastPropertyUsingMap(Map* new_map,
+                                          String* name,
+                                          Object* value) {
+  int index = new_map->PropertyIndexFor(name);
+  if (map()->unused_property_fields() == 0) {
+    ASSERT(map()->unused_property_fields() == 0);
+    int new_unused = new_map->unused_property_fields();
+    Object* values =
+        properties()->CopySize(properties()->length() + new_unused + 1);
+    if (values->IsFailure()) return values;
+    set_properties(FixedArray::cast(values));
+  }
+  set_map(new_map);
+  return FastPropertyAtPut(index, value);
+}
+
+
+Object* JSObject::AddFastProperty(String* name,
+                                  Object* value,
+                                  PropertyAttributes attributes) {
+  // 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()) {
+    Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
+    if (obj->IsFailure()) return obj;
+    return AddSlowProperty(name, value, attributes);
+  }
+
+  DescriptorArray* old_descriptors = map()->instance_descriptors();
+  // Compute the new index for new field.
+  int index = map()->NextFreePropertyIndex();
+
+  // Allocate new instance descriptors with (name, index) added
+  FieldDescriptor new_field(name, index, attributes);
+  Object* new_descriptors =
+      old_descriptors->CopyInsert(&new_field, REMOVE_TRANSITIONS);
+  if (new_descriptors->IsFailure()) return new_descriptors;
+
+  // Only allow map transition if the object's map is NOT equal to the
+  // global object_function's map and there is not a transition for name.
+  bool allow_map_transition =
+        !old_descriptors->Contains(name) &&
+        (Top::context()->global_context()->object_function()->map() != map());
+
+  ASSERT(index < map()->inobject_properties() ||
+         (index - map()->inobject_properties()) < properties()->length() ||
+         map()->unused_property_fields() == 0);
+  // Allocate a new map for the object.
+  Object* r = map()->Copy();
+  if (r->IsFailure()) return r;
+  Map* new_map = Map::cast(r);
+  if (allow_map_transition) {
+    // Allocate new instance descriptors for the old map with map transition.
+    MapTransitionDescriptor d(name, Map::cast(new_map), attributes);
+    Object* r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS);
+    if (r->IsFailure()) return r;
+    old_descriptors = DescriptorArray::cast(r);
+  }
+
+  if (map()->unused_property_fields() == 0) {
+    if (properties()->length() > kMaxFastProperties) {
+      Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
+      if (obj->IsFailure()) return obj;
+      return AddSlowProperty(name, value, attributes);
+    }
+    // Make room for the new value
+    Object* values =
+        properties()->CopySize(properties()->length() + kFieldsAdded);
+    if (values->IsFailure()) return values;
+    set_properties(FixedArray::cast(values));
+    new_map->set_unused_property_fields(kFieldsAdded - 1);
+  } else {
+    new_map->set_unused_property_fields(map()->unused_property_fields() - 1);
+  }
+  // We have now allocated all the necessary objects.
+  // All the changes can be applied at once, so they are atomic.
+  map()->set_instance_descriptors(old_descriptors);
+  new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
+  set_map(new_map);
+  return FastPropertyAtPut(index, value);
+}
+
+
+Object* JSObject::AddConstantFunctionProperty(String* name,
+                                              JSFunction* function,
+                                              PropertyAttributes attributes) {
+  // Allocate new instance descriptors with (name, function) added
+  ConstantFunctionDescriptor d(name, function, attributes);
+  Object* new_descriptors =
+      map()->instance_descriptors()->CopyInsert(&d, REMOVE_TRANSITIONS);
+  if (new_descriptors->IsFailure()) return new_descriptors;
+
+  // Allocate a new map for the object.
+  Object* new_map = map()->Copy();
+  if (new_map->IsFailure()) return new_map;
+
+  DescriptorArray* descriptors = DescriptorArray::cast(new_descriptors);
+  Map::cast(new_map)->set_instance_descriptors(descriptors);
+  Map* old_map = map();
+  set_map(Map::cast(new_map));
+
+  // If the old map is the global object map (from new Object()),
+  // then transitions are not added to it, so we are done.
+  if (old_map == Top::context()->global_context()->object_function()->map()) {
+    return function;
+  }
+
+  // Do not add CONSTANT_TRANSITIONS to global objects
+  if (IsGlobalObject()) {
+    return function;
+  }
+
+  // Add a CONSTANT_TRANSITION descriptor to the old map,
+  // so future assignments to this property on other objects
+  // of the same type will create a normal field, not a constant function.
+  // Don't do this for special properties, with non-trival attributes.
+  if (attributes != NONE) {
+    return function;
+  }
+  ConstTransitionDescriptor mark(name);
+  new_descriptors =
+      old_map->instance_descriptors()->CopyInsert(&mark, KEEP_TRANSITIONS);
+  if (new_descriptors->IsFailure()) {
+    return function;  // We have accomplished the main goal, so return success.
+  }
+  old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
+
+  return function;
+}
+
+
+// Add property in slow mode
+Object* JSObject::AddSlowProperty(String* name,
+                                  Object* value,
+                                  PropertyAttributes attributes) {
+  PropertyDetails details = PropertyDetails(attributes, NORMAL);
+  Object* result = property_dictionary()->AddStringEntry(name, value, details);
+  if (result->IsFailure()) return result;
+  if (property_dictionary() != result) {
+     set_properties(Dictionary::cast(result));
+  }
+  return value;
+}
+
+
+Object* JSObject::AddProperty(String* name,
+                              Object* value,
+                              PropertyAttributes attributes) {
+  ASSERT(!IsJSGlobalProxy());
+  if (HasFastProperties()) {
+    // Ensure the descriptor array does not get too big.
+    if (map()->instance_descriptors()->number_of_descriptors() <
+        DescriptorArray::kMaxNumberOfDescriptors) {
+      if (value->IsJSFunction()) {
+        return AddConstantFunctionProperty(name,
+                                           JSFunction::cast(value),
+                                           attributes);
+      } else {
+        return AddFastProperty(name, value, attributes);
+      }
+    } else {
+      // Normalize the object to prevent very large instance descriptors.
+      // This eliminates unwanted N^2 allocation and lookup behavior.
+      Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
+      if (obj->IsFailure()) return obj;
+    }
+  }
+  return AddSlowProperty(name, value, attributes);
+}
+
+
+Object* JSObject::SetPropertyPostInterceptor(String* name,
+                                             Object* value,
+                                             PropertyAttributes attributes) {
+  // Check local property, ignore interceptor.
+  LookupResult result;
+  LocalLookupRealNamedProperty(name, &result);
+  if (result.IsValid()) return SetProperty(&result, name, value, attributes);
+  // Add real property.
+  return AddProperty(name, value, attributes);
+}
+
+
+Object* JSObject::ReplaceSlowProperty(String* name,
+                                       Object* value,
+                                       PropertyAttributes attributes) {
+  Dictionary* dictionary = property_dictionary();
+  PropertyDetails old_details =
+      dictionary->DetailsAt(dictionary->FindStringEntry(name));
+  int new_index = old_details.index();
+  if (old_details.IsTransition()) new_index = 0;
+
+  PropertyDetails new_details(attributes, NORMAL, old_details.index());
+  Object* result =
+      property_dictionary()->SetOrAddStringEntry(name, value, new_details);
+  if (result->IsFailure()) return result;
+  if (property_dictionary() != result) {
+    set_properties(Dictionary::cast(result));
+  }
+  return value;
+}
+
+Object* JSObject::ConvertDescriptorToFieldAndMapTransition(
+    String* name,
+    Object* new_value,
+    PropertyAttributes attributes) {
+  Map* old_map = map();
+  Object* result = ConvertDescriptorToField(name, new_value, attributes);
+  if (result->IsFailure()) return result;
+  // If we get to this point we have succeeded - do not return failure
+  // after this point.  Later stuff is optional.
+  if (!HasFastProperties()) {
+    return result;
+  }
+  // Do not add transitions to the map of "new Object()".
+  if (map() == Top::context()->global_context()->object_function()->map()) {
+    return result;
+  }
+
+  MapTransitionDescriptor transition(name,
+                                     map(),
+                                     attributes);
+  Object* new_descriptors =
+      old_map->instance_descriptors()->
+          CopyInsert(&transition, KEEP_TRANSITIONS);
+  if (new_descriptors->IsFailure()) return result;  // Yes, return _result_.
+  old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
+  return result;
+}
+
+
+Object* JSObject::ConvertDescriptorToField(String* name,
+                                           Object* new_value,
+                                           PropertyAttributes attributes) {
+  if (map()->unused_property_fields() == 0 &&
+      properties()->length() > kMaxFastProperties) {
+    Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
+    if (obj->IsFailure()) return obj;
+    return ReplaceSlowProperty(name, new_value, attributes);
+  }
+
+  int index = map()->NextFreePropertyIndex();
+  FieldDescriptor new_field(name, index, attributes);
+  // Make a new DescriptorArray replacing an entry with FieldDescriptor.
+  Object* descriptors_unchecked = map()->instance_descriptors()->
+      CopyInsert(&new_field, REMOVE_TRANSITIONS);
+  if (descriptors_unchecked->IsFailure()) return descriptors_unchecked;
+  DescriptorArray* new_descriptors =
+      DescriptorArray::cast(descriptors_unchecked);
+
+  // Make a new map for the object.
+  Object* new_map_unchecked = map()->Copy();
+  if (new_map_unchecked->IsFailure()) return new_map_unchecked;
+  Map* new_map = Map::cast(new_map_unchecked);
+  new_map->set_instance_descriptors(new_descriptors);
+
+  // Make new properties array if necessary.
+  FixedArray* new_properties = 0;  // Will always be NULL or a valid pointer.
+  int new_unused_property_fields = map()->unused_property_fields() - 1;
+  if (map()->unused_property_fields() == 0) {
+     new_unused_property_fields = kFieldsAdded - 1;
+     Object* new_properties_unchecked =
+        properties()->CopySize(properties()->length() + kFieldsAdded);
+    if (new_properties_unchecked->IsFailure()) return new_properties_unchecked;
+    new_properties = FixedArray::cast(new_properties_unchecked);
+  }
+
+  // Update pointers to commit changes.
+  // Object points to the new map.
+  new_map->set_unused_property_fields(new_unused_property_fields);
+  set_map(new_map);
+  if (new_properties) {
+    set_properties(FixedArray::cast(new_properties));
+  }
+  return FastPropertyAtPut(index, new_value);
+}
+
+
+
+Object* JSObject::SetPropertyWithInterceptor(String* name,
+                                             Object* value,
+                                             PropertyAttributes attributes) {
+  HandleScope scope;
+  Handle<JSObject> this_handle(this);
+  Handle<String> name_handle(name);
+  Handle<Object> value_handle(value);
+  Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
+  if (!interceptor->setter()->IsUndefined()) {
+    Handle<Object> data_handle(interceptor->data());
+    LOG(ApiNamedPropertyAccess("interceptor-named-set", this, name));
+    v8::AccessorInfo info(v8::Utils::ToLocal(this_handle),
+                          v8::Utils::ToLocal(data_handle),
+                          v8::Utils::ToLocal(this_handle));
+    v8::NamedPropertySetter setter =
+        v8::ToCData<v8::NamedPropertySetter>(interceptor->setter());
+    v8::Handle<v8::Value> result;
+    {
+      // Leaving JavaScript.
+      VMState state(EXTERNAL);
+      Handle<Object> value_unhole(value->IsTheHole() ?
+                                  Heap::undefined_value() :
+                                  value);
+      result = setter(v8::Utils::ToLocal(name_handle),
+                      v8::Utils::ToLocal(value_unhole),
+                      info);
+    }
+    RETURN_IF_SCHEDULED_EXCEPTION();
+    if (!result.IsEmpty()) return *value_handle;
+  }
+  Object* raw_result = this_handle->SetPropertyPostInterceptor(*name_handle,
+                                                               *value_handle,
+                                                               attributes);
+  RETURN_IF_SCHEDULED_EXCEPTION();
+  return raw_result;
+}
+
+
+Object* JSObject::SetProperty(String* name,
+                              Object* value,
+                              PropertyAttributes attributes) {
+  LookupResult result;
+  LocalLookup(name, &result);
+  return SetProperty(&result, name, value, attributes);
+}
+
+
+Object* JSObject::SetPropertyWithCallback(Object* structure,
+                                          String* name,
+                                          Object* value,
+                                          JSObject* holder) {
+  HandleScope scope;
+
+  // We should never get here to initialize a const with the hole
+  // value since a const declaration would conflict with the setter.
+  ASSERT(!value->IsTheHole());
+  Handle<Object> value_handle(value);
+
+  // To accommodate both the old and the new api we switch on the
+  // data structure used to store the callbacks.  Eventually proxy
+  // callbacks should be phased out.
+  if (structure->IsProxy()) {
+    AccessorDescriptor* callback =
+        reinterpret_cast<AccessorDescriptor*>(Proxy::cast(structure)->proxy());
+    Object* obj = (callback->setter)(this,  value, callback->data);
+    RETURN_IF_SCHEDULED_EXCEPTION();
+    if (obj->IsFailure()) return obj;
+    return *value_handle;
+  }
+
+  if (structure->IsAccessorInfo()) {
+    // api style callbacks
+    AccessorInfo* data = AccessorInfo::cast(structure);
+    Object* call_obj = data->setter();
+    v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj);
+    if (call_fun == NULL) return value;
+    Handle<JSObject> self(this);
+    Handle<JSObject> holder_handle(JSObject::cast(holder));
+    Handle<String> key(name);
+    Handle<Object> fun_data(data->data());
+    LOG(ApiNamedPropertyAccess("store", this, name));
+    v8::AccessorInfo info(v8::Utils::ToLocal(self),
+                          v8::Utils::ToLocal(fun_data),
+                          v8::Utils::ToLocal(holder_handle));
+    {
+      // Leaving JavaScript.
+      VMState state(EXTERNAL);
+      call_fun(v8::Utils::ToLocal(key),
+               v8::Utils::ToLocal(value_handle),
+               info);
+    }
+    RETURN_IF_SCHEDULED_EXCEPTION();
+    return *value_handle;
+  }
+
+  if (structure->IsFixedArray()) {
+    Object* setter = FixedArray::cast(structure)->get(kSetterIndex);
+    if (setter->IsJSFunction()) {
+     return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value);
+    } else {
+      Handle<String> key(name);
+      Handle<Object> holder_handle(holder);
+      Handle<Object> args[2] = { key, holder_handle };
+      return Top::Throw(*Factory::NewTypeError("no_setter_in_callback",
+                                               HandleVector(args, 2)));
+    }
+  }
+
+  UNREACHABLE();
+  return 0;
+}
+
+
+Object* JSObject::SetPropertyWithDefinedSetter(JSFunction* setter,
+                                               Object* value) {
+  Handle<Object> value_handle(value);
+  Handle<JSFunction> fun(JSFunction::cast(setter));
+  Handle<JSObject> self(this);
+  bool has_pending_exception;
+  Object** argv[] = { value_handle.location() };
+  Execution::Call(fun, self, 1, argv, &has_pending_exception);
+  // Check for pending exception and return the result.
+  if (has_pending_exception) return Failure::Exception();
+  return *value_handle;
+}
+
+void JSObject::LookupCallbackSetterInPrototypes(String* name,
+                                                LookupResult* result) {
+  for (Object* pt = GetPrototype();
+       pt != Heap::null_value();
+       pt = pt->GetPrototype()) {
+    JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
+    if (result->IsValid()) {
+      if (!result->IsTransitionType() && result->IsReadOnly()) {
+        result->NotFound();
+        return;
+      }
+      if (result->type() == CALLBACKS) {
+        return;
+      }
+    }
+  }
+  result->NotFound();
+}
+
+
+Object* JSObject::LookupCallbackSetterInPrototypes(uint32_t index) {
+  for (Object* pt = GetPrototype();
+       pt != Heap::null_value();
+       pt = pt->GetPrototype()) {
+    if (JSObject::cast(pt)->HasFastElements()) continue;
+    Dictionary* dictionary = JSObject::cast(pt)->element_dictionary();
+    int entry = dictionary->FindNumberEntry(index);
+    if (entry != -1) {
+      Object* element = dictionary->ValueAt(entry);
+      PropertyDetails details = dictionary->DetailsAt(entry);
+      if (details.type() == CALLBACKS) {
+        // Only accessors allowed as elements.
+        return FixedArray::cast(element)->get(kSetterIndex);
+      }
+    }
+  }
+  return Heap::undefined_value();
+}
+
+
+void JSObject::LookupInDescriptor(String* name, LookupResult* result) {
+  DescriptorArray* descriptors = map()->instance_descriptors();
+  int number = descriptors->Search(name);
+  if (number != DescriptorArray::kNotFound) {
+    result->DescriptorResult(this, descriptors->GetDetails(number), number);
+  } else {
+    result->NotFound();
+  }
+}
+
+
+void JSObject::LocalLookupRealNamedProperty(String* name,
+                                            LookupResult* result) {
+  if (IsJSGlobalProxy()) {
+    Object* proto = GetPrototype();
+    if (proto->IsNull()) return result->NotFound();
+    ASSERT(proto->IsJSGlobalObject());
+    return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result);
+  }
+
+  if (HasFastProperties()) {
+    LookupInDescriptor(name, result);
+    if (result->IsValid()) {
+      ASSERT(result->holder() == this && result->type() != NORMAL);
+      // Disallow caching for uninitialized constants. These can only
+      // occur as fields.
+      if (result->IsReadOnly() && result->type() == FIELD &&
+          FastPropertyAt(result->GetFieldIndex())->IsTheHole()) {
+        result->DisallowCaching();
+      }
+      return;
+    }
+  } else {
+    int entry = property_dictionary()->FindStringEntry(name);
+    if (entry != DescriptorArray::kNotFound) {
+      // Make sure to disallow caching for uninitialized constants
+      // found in the dictionary-mode objects.
+      if (property_dictionary()->ValueAt(entry)->IsTheHole()) {
+        result->DisallowCaching();
+      }
+      result->DictionaryResult(this, entry);
+      return;
+    }
+    // Slow case object skipped during lookup. Do not use inline caching.
+    result->DisallowCaching();
+  }
+  result->NotFound();
+}
+
+
+void JSObject::LookupRealNamedProperty(String* name, LookupResult* result) {
+  LocalLookupRealNamedProperty(name, result);
+  if (result->IsProperty()) return;
+
+  LookupRealNamedPropertyInPrototypes(name, result);
+}
+
+
+void JSObject::LookupRealNamedPropertyInPrototypes(String* name,
+                                                   LookupResult* result) {
+  for (Object* pt = GetPrototype();
+       pt != Heap::null_value();
+       pt = JSObject::cast(pt)->GetPrototype()) {
+    JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
+    if (result->IsValid()) {
+      switch (result->type()) {
+        case NORMAL:
+        case FIELD:
+        case CONSTANT_FUNCTION:
+        case CALLBACKS:
+          return;
+        default: break;
+      }
+    }
+  }
+  result->NotFound();
+}
+
+
+// We only need to deal with CALLBACKS and INTERCEPTORS
+Object* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result,
+                                                   String* name,
+                                                   Object* value) {
+  if (!result->IsProperty()) {
+    LookupCallbackSetterInPrototypes(name, result);
+  }
+
+  if (result->IsProperty()) {
+    if (!result->IsReadOnly()) {
+      switch (result->type()) {
+        case CALLBACKS: {
+          Object* obj = result->GetCallbackObject();
+          if (obj->IsAccessorInfo()) {
+            AccessorInfo* info = AccessorInfo::cast(obj);
+            if (info->all_can_write()) {
+              return SetPropertyWithCallback(result->GetCallbackObject(),
+                                             name,
+                                             value,
+                                             result->holder());
+            }
+          }
+          break;
+        }
+        case INTERCEPTOR: {
+          // Try lookup real named properties. Note that only property can be
+          // set is callbacks marked as ALL_CAN_WRITE on the prototype chain.
+          LookupResult r;
+          LookupRealNamedProperty(name, &r);
+          if (r.IsProperty()) {
+            return SetPropertyWithFailedAccessCheck(&r, name, value);
+          }
+          break;
+        }
+        default: {
+          break;
+        }
+      }
+    }
+  }
+
+  Top::ReportFailedAccessCheck(this, v8::ACCESS_SET);
+  return value;
+}
+
+
+Object* JSObject::SetProperty(LookupResult* result,
+                              String* name,
+                              Object* value,
+                              PropertyAttributes attributes) {
+  // Make sure that the top context does not change when doing callbacks or
+  // interceptor calls.
+  AssertNoContextChange ncc;
+
+  // Check access rights if needed.
+  if (IsAccessCheckNeeded()
+    && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
+    return SetPropertyWithFailedAccessCheck(result, name, value);
+  }
+
+  if (IsJSGlobalProxy()) {
+    Object* proto = GetPrototype();
+    if (proto->IsNull()) return value;
+    ASSERT(proto->IsJSGlobalObject());
+    return JSObject::cast(proto)->SetProperty(result, name, value, attributes);
+  }
+
+  if (!result->IsProperty() && !IsJSContextExtensionObject()) {
+    // We could not find a local property so let's check whether there is an
+    // accessor that wants to handle the property.
+    LookupResult accessor_result;
+    LookupCallbackSetterInPrototypes(name, &accessor_result);
+    if (accessor_result.IsValid()) {
+      return SetPropertyWithCallback(accessor_result.GetCallbackObject(),
+                                     name,
+                                     value,
+                                     accessor_result.holder());
+    }
+  }
+  if (result->IsNotFound()) {
+    return AddProperty(name, value, attributes);
+  }
+  if (!result->IsLoaded()) {
+    return SetLazyProperty(result, name, value, attributes);
+  }
+  if (result->IsReadOnly() && result->IsProperty()) return value;
+  // This is a real property that is not read-only, or it is a
+  // transition or null descriptor and there are no setters in the prototypes.
+  switch (result->type()) {
+    case NORMAL:
+      property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value);
+      return value;
+    case FIELD:
+      return FastPropertyAtPut(result->GetFieldIndex(), value);
+    case MAP_TRANSITION:
+      if (attributes == result->GetAttributes()) {
+        // Only use map transition if the attributes match.
+        return AddFastPropertyUsingMap(result->GetTransitionMap(),
+                                       name,
+                                       value);
+      }
+      return ConvertDescriptorToField(name, value, attributes);
+    case CONSTANT_FUNCTION:
+      if (value == result->GetConstantFunction()) return value;
+      // Only replace the function if necessary.
+      return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
+    case CALLBACKS:
+      return SetPropertyWithCallback(result->GetCallbackObject(),
+                                     name,
+                                     value,
+                                     result->holder());
+    case INTERCEPTOR:
+      return SetPropertyWithInterceptor(name, value, attributes);
+    case CONSTANT_TRANSITION:
+      // Replace with a MAP_TRANSITION to a new map with a FIELD, even
+      // if the value is a function.
+      return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
+    case NULL_DESCRIPTOR:
+      return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
+    default:
+      UNREACHABLE();
+  }
+  UNREACHABLE();
+  return value;
+}
+
+
+// Set a real local property, even if it is READ_ONLY.  If the property is not
+// present, add it with attributes NONE.  This code is an exact clone of
+// SetProperty, with the check for IsReadOnly and the check for a
+// callback setter removed.  The two lines looking up the LookupResult
+// result are also added.  If one of the functions is changed, the other
+// should be.
+Object* JSObject::IgnoreAttributesAndSetLocalProperty(
+    String* name,
+    Object* value,
+    PropertyAttributes attributes) {
+  // Make sure that the top context does not change when doing callbacks or
+  // interceptor calls.
+  AssertNoContextChange ncc;
+  // ADDED TO CLONE
+  LookupResult result_struct;
+  LocalLookup(name, &result_struct);
+  LookupResult* result = &result_struct;
+  // END ADDED TO CLONE
+  // Check access rights if needed.
+  if (IsAccessCheckNeeded()
+    && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
+    return SetPropertyWithFailedAccessCheck(result, name, value);
+  }
+  // Check for accessor in prototype chain removed here in clone.
+  if (result->IsNotFound()) {
+    return AddProperty(name, value, attributes);
+  }
+  if (!result->IsLoaded()) {
+    return SetLazyProperty(result, name, value, attributes);
+  }
+  //  Check of IsReadOnly removed from here in clone.
+  switch (result->type()) {
+    case NORMAL:
+      property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value);
+      return value;
+    case FIELD:
+      return FastPropertyAtPut(result->GetFieldIndex(), value);
+    case MAP_TRANSITION:
+      if (attributes == result->GetAttributes()) {
+        // Only use map transition if the attributes match.
+        return AddFastPropertyUsingMap(result->GetTransitionMap(),
+                                       name,
+                                       value);
+      } else {
+        return ConvertDescriptorToField(name, value, attributes);
+      }
+    case CONSTANT_FUNCTION:
+      if (value == result->GetConstantFunction()) return value;
+      // Only replace the function if necessary.
+      return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
+    case CALLBACKS:
+      return SetPropertyWithCallback(result->GetCallbackObject(),
+                                     name,
+                                     value,
+                                     result->holder());
+    case INTERCEPTOR:
+      return SetPropertyWithInterceptor(name, value, attributes);
+    case CONSTANT_TRANSITION:
+      // Replace with a MAP_TRANSITION to a new map with a FIELD, even
+      // if the value is a function.
+      return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
+    case NULL_DESCRIPTOR:
+      return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
+    default:
+      UNREACHABLE();
+  }
+  UNREACHABLE();
+  return value;
+}
+
+
+PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
+      JSObject* receiver,
+      String* name,
+      bool continue_search) {
+  // Check local property, ignore interceptor.
+  LookupResult result;
+  LocalLookupRealNamedProperty(name, &result);
+  if (result.IsProperty()) return result.GetAttributes();
+
+  if (continue_search) {
+    // Continue searching via the prototype chain.
+    Object* pt = GetPrototype();
+    if (pt != Heap::null_value()) {
+      return JSObject::cast(pt)->
+        GetPropertyAttributeWithReceiver(receiver, name);
+    }
+  }
+  return ABSENT;
+}
+
+
+PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor(
+      JSObject* receiver,
+      String* name,
+      bool continue_search) {
+  // Make sure that the top context does not change when doing
+  // callbacks or interceptor calls.
+  AssertNoContextChange ncc;
+
+  HandleScope scope;
+  Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
+  Handle<JSObject> receiver_handle(receiver);
+  Handle<JSObject> holder_handle(this);
+  Handle<String> name_handle(name);
+  Handle<Object> data_handle(interceptor->data());
+  v8::AccessorInfo info(v8::Utils::ToLocal(receiver_handle),
+                        v8::Utils::ToLocal(data_handle),
+                        v8::Utils::ToLocal(holder_handle));
+  if (!interceptor->query()->IsUndefined()) {
+    v8::NamedPropertyQuery query =
+        v8::ToCData<v8::NamedPropertyQuery>(interceptor->query());
+    LOG(ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name));
+    v8::Handle<v8::Boolean> result;
+    {
+      // Leaving JavaScript.
+      VMState state(EXTERNAL);
+      result = query(v8::Utils::ToLocal(name_handle), info);
+    }
+    if (!result.IsEmpty()) {
+      // Convert the boolean result to a property attribute
+      // specification.
+      return result->IsTrue() ? NONE : ABSENT;
+    }
+  } else if (!interceptor->getter()->IsUndefined()) {
+    v8::NamedPropertyGetter getter =
+        v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
+    LOG(ApiNamedPropertyAccess("interceptor-named-get-has", this, name));
+    v8::Handle<v8::Value> result;
+    {
+      // Leaving JavaScript.
+      VMState state(EXTERNAL);
+      result = getter(v8::Utils::ToLocal(name_handle), info);
+    }
+    if (!result.IsEmpty()) return NONE;
+  }
+  return holder_handle->GetPropertyAttributePostInterceptor(*receiver_handle,
+                                                            *name_handle,
+                                                            continue_search);
+}
+
+
+PropertyAttributes JSObject::GetPropertyAttributeWithReceiver(
+      JSObject* receiver,
+      String* key) {
+  uint32_t index = 0;
+  if (key->AsArrayIndex(&index)) {
+    if (HasElementWithReceiver(receiver, index)) return NONE;
+    return ABSENT;
+  }
+  // Named property.
+  LookupResult result;
+  Lookup(key, &result);
+  return GetPropertyAttribute(receiver, &result, key, true);
+}
+
+
+PropertyAttributes JSObject::GetPropertyAttribute(JSObject* receiver,
+                                                  LookupResult* result,
+                                                  String* name,
+                                                  bool continue_search) {
+  // Check access rights if needed.
+  if (IsAccessCheckNeeded() &&
+      !Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) {
+    return GetPropertyAttributeWithFailedAccessCheck(receiver,
+                                                     result,
+                                                     name,
+                                                     continue_search);
+  }
+  if (result->IsValid()) {
+    switch (result->type()) {
+      case NORMAL:  // fall through
+      case FIELD:
+      case CONSTANT_FUNCTION:
+      case CALLBACKS:
+        return result->GetAttributes();
+      case INTERCEPTOR:
+        return result->holder()->
+          GetPropertyAttributeWithInterceptor(receiver, name, continue_search);
+      case MAP_TRANSITION:
+      case CONSTANT_TRANSITION:
+      case NULL_DESCRIPTOR:
+        return ABSENT;
+      default:
+        UNREACHABLE();
+        break;
+    }
+  }
+  return ABSENT;
+}
+
+
+PropertyAttributes JSObject::GetLocalPropertyAttribute(String* name) {
+  // Check whether the name is an array index.
+  uint32_t index = 0;
+  if (name->AsArrayIndex(&index)) {
+    if (HasLocalElement(index)) return NONE;
+    return ABSENT;
+  }
+  // Named property.
+  LookupResult result;
+  LocalLookup(name, &result);
+  return GetPropertyAttribute(this, &result, name, false);
+}
+
+
+Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode) {
+  if (!HasFastProperties()) return this;
+
+  // Allocate new content
+  Object* obj =
+      Dictionary::Allocate(map()->NumberOfDescribedProperties() * 2 + 4);
+  if (obj->IsFailure()) return obj;
+  Dictionary* dictionary = Dictionary::cast(obj);
+
+  for (DescriptorReader r(map()->instance_descriptors());
+       !r.eos();
+       r.advance()) {
+    PropertyDetails details = r.GetDetails();
+    switch (details.type()) {
+      case CONSTANT_FUNCTION: {
+        PropertyDetails d =
+            PropertyDetails(details.attributes(), NORMAL, details.index());
+        Object* value = r.GetConstantFunction();
+        Object* result = dictionary->AddStringEntry(r.GetKey(), value, d);
+        if (result->IsFailure()) return result;
+        dictionary = Dictionary::cast(result);
+        break;
+      }
+      case FIELD: {
+        PropertyDetails d =
+            PropertyDetails(details.attributes(), NORMAL, details.index());
+        Object* value = FastPropertyAt(r.GetFieldIndex());
+        Object* result = dictionary->AddStringEntry(r.GetKey(), value, d);
+        if (result->IsFailure()) return result;
+        dictionary = Dictionary::cast(result);
+        break;
+      }
+      case CALLBACKS: {
+        PropertyDetails d =
+            PropertyDetails(details.attributes(), CALLBACKS, details.index());
+        Object* value = r.GetCallbacksObject();
+        Object* result = dictionary->AddStringEntry(r.GetKey(), value, d);
+        if (result->IsFailure()) return result;
+        dictionary = Dictionary::cast(result);
+        break;
+      }
+      case MAP_TRANSITION:
+      case CONSTANT_TRANSITION:
+      case NULL_DESCRIPTOR:
+      case INTERCEPTOR:
+        break;
+      default:
+      case NORMAL:
+        UNREACHABLE();
+        break;
+    }
+  }
+
+  // Copy the next enumeration index from instance descriptor.
+  int index = map()->instance_descriptors()->NextEnumerationIndex();
+  dictionary->SetNextEnumerationIndex(index);
+
+  // Allocate new map.
+  obj = map()->Copy();
+  if (obj->IsFailure()) return obj;
+  Map* new_map = Map::cast(obj);
+
+  // Clear inobject properties if needed by adjusting the instance size and
+  // putting in a filler object instead of the inobject properties.
+  if (mode == CLEAR_INOBJECT_PROPERTIES && map()->inobject_properties() > 0) {
+    int instance_size_delta = map()->inobject_properties() * kPointerSize;
+    int new_instance_size = map()->instance_size() - instance_size_delta;
+    new_map->set_inobject_properties(0);
+    new_map->set_instance_size(new_instance_size);
+    Heap::CreateFillerObjectAt(this->address() + new_instance_size,
+                               instance_size_delta);
+  }
+  new_map->set_unused_property_fields(0);
+
+  // We have now successfully allocated all the necessary objects.
+  // Changes can now be made with the guarantee that all of them take effect.
+  set_map(new_map);
+  map()->set_instance_descriptors(Heap::empty_descriptor_array());
+
+  set_properties(dictionary);
+
+  Counters::props_to_dictionary.Increment();
+
+#ifdef DEBUG
+  if (FLAG_trace_normalization) {
+    PrintF("Object properties have been normalized:\n");
+    Print();
+  }
+#endif
+  return this;
+}
+
+
+Object* JSObject::TransformToFastProperties(int unused_property_fields) {
+  if (HasFastProperties()) return this;
+  return property_dictionary()->
+    TransformPropertiesToFastFor(this, unused_property_fields);
+}
+
+
+Object* JSObject::NormalizeElements() {
+  if (!HasFastElements()) return this;
+
+  // Get number of entries.
+  FixedArray* array = FixedArray::cast(elements());
+
+  // Compute the effective length.
+  int length = IsJSArray() ?
+               Smi::cast(JSArray::cast(this)->length())->value() :
+               array->length();
+  Object* obj = Dictionary::Allocate(length);
+  if (obj->IsFailure()) return obj;
+  Dictionary* dictionary = Dictionary::cast(obj);
+  // Copy entries.
+  for (int i = 0; i < length; i++) {
+    Object* value = array->get(i);
+    if (!value->IsTheHole()) {
+      PropertyDetails details = PropertyDetails(NONE, NORMAL);
+      Object* result = dictionary->AddNumberEntry(i, array->get(i), details);
+      if (result->IsFailure()) return result;
+      dictionary = Dictionary::cast(result);
+    }
+  }
+  // Switch to using the dictionary as the backing storage for elements.
+  set_elements(dictionary);
+
+  Counters::elements_to_dictionary.Increment();
+
+#ifdef DEBUG
+  if (FLAG_trace_normalization) {
+    PrintF("Object elements have been normalized:\n");
+    Print();
+  }
+#endif
+
+  return this;
+}
+
+
+Object* JSObject::DeletePropertyPostInterceptor(String* name) {
+  // Check local property, ignore interceptor.
+  LookupResult result;
+  LocalLookupRealNamedProperty(name, &result);
+  if (!result.IsValid()) return Heap::true_value();
+
+  // Normalize object if needed.
+  Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
+  if (obj->IsFailure()) return obj;
+
+  ASSERT(!HasFastProperties());
+  // Attempt to remove the property from the property dictionary.
+  Dictionary* dictionary = property_dictionary();
+  int entry = dictionary->FindStringEntry(name);
+  if (entry != -1) return dictionary->DeleteProperty(entry);
+  return Heap::true_value();
+}
+
+
+Object* JSObject::DeletePropertyWithInterceptor(String* name) {
+  HandleScope scope;
+  Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
+  Handle<String> name_handle(name);
+  Handle<JSObject> this_handle(this);
+  if (!interceptor->deleter()->IsUndefined()) {
+    v8::NamedPropertyDeleter deleter =
+        v8::ToCData<v8::NamedPropertyDeleter>(interceptor->deleter());
+    Handle<Object> data_handle(interceptor->data());
+    LOG(ApiNamedPropertyAccess("interceptor-named-delete", *this_handle, name));
+    v8::AccessorInfo info(v8::Utils::ToLocal(this_handle),
+                          v8::Utils::ToLocal(data_handle),
+                          v8::Utils::ToLocal(this_handle));
+    v8::Handle<v8::Boolean> result;
+    {
+      // Leaving JavaScript.
+      VMState state(EXTERNAL);
+      result = deleter(v8::Utils::ToLocal(name_handle), info);
+    }
+    RETURN_IF_SCHEDULED_EXCEPTION();
+    if (!result.IsEmpty()) {
+      ASSERT(result->IsBoolean());
+      return *v8::Utils::OpenHandle(*result);
+    }
+  }
+  Object* raw_result = this_handle->DeletePropertyPostInterceptor(*name_handle);
+  RETURN_IF_SCHEDULED_EXCEPTION();
+  return raw_result;
+}
+
+
+Object* JSObject::DeleteElementPostInterceptor(uint32_t index) {
+  if (HasFastElements()) {
+    uint32_t length = IsJSArray() ?
+      static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) :
+      static_cast<uint32_t>(FixedArray::cast(elements())->length());
+    if (index < length) {
+      FixedArray::cast(elements())->set_the_hole(index);
+    }
+    return Heap::true_value();
+  }
+  ASSERT(!HasFastElements());
+  Dictionary* dictionary = element_dictionary();
+  int entry = dictionary->FindNumberEntry(index);
+  if (entry != -1) return dictionary->DeleteProperty(entry);
+  return Heap::true_value();
+}
+
+
+Object* JSObject::DeleteElementWithInterceptor(uint32_t index) {
+  // Make sure that the top context does not change when doing
+  // callbacks or interceptor calls.
+  AssertNoContextChange ncc;
+  HandleScope scope;
+  Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
+  if (interceptor->deleter()->IsUndefined()) return Heap::false_value();
+  v8::IndexedPropertyDeleter deleter =
+      v8::ToCData<v8::IndexedPropertyDeleter>(interceptor->deleter());
+  Handle<JSObject> this_handle(this);
+  Handle<Object> data_handle(interceptor->data());
+  LOG(ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index));
+  v8::AccessorInfo info(v8::Utils::ToLocal(this_handle),
+                        v8::Utils::ToLocal(data_handle),
+                        v8::Utils::ToLocal(this_handle));
+  v8::Handle<v8::Boolean> result;
+  {
+    // Leaving JavaScript.
+    VMState state(EXTERNAL);
+    result = deleter(index, info);
+  }
+  RETURN_IF_SCHEDULED_EXCEPTION();
+  if (!result.IsEmpty()) {
+    ASSERT(result->IsBoolean());
+    return *v8::Utils::OpenHandle(*result);
+  }
+  Object* raw_result = this_handle->DeleteElementPostInterceptor(index);
+  RETURN_IF_SCHEDULED_EXCEPTION();
+  return raw_result;
+}
+
+
+Object* JSObject::DeleteElement(uint32_t index) {
+  // Check access rights if needed.
+  if (IsAccessCheckNeeded() &&
+      !Top::MayIndexedAccess(this, index, v8::ACCESS_DELETE)) {
+    Top::ReportFailedAccessCheck(this, v8::ACCESS_DELETE);
+    return Heap::false_value();
+  }
+
+  if (IsJSGlobalProxy()) {
+    Object* proto = GetPrototype();
+    if (proto->IsNull()) return Heap::false_value();
+    ASSERT(proto->IsJSGlobalObject());
+    return JSGlobalObject::cast(proto)->DeleteElement(index);
+  }
+
+  if (HasIndexedInterceptor()) {
+    return DeleteElementWithInterceptor(index);
+  }
+
+  if (HasFastElements()) {
+    uint32_t length = IsJSArray() ?
+      static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) :
+      static_cast<uint32_t>(FixedArray::cast(elements())->length());
+    if (index < length) {
+      FixedArray::cast(elements())->set_the_hole(index);
+    }
+    return Heap::true_value();
+  } else {
+    Dictionary* dictionary = element_dictionary();
+    int entry = dictionary->FindNumberEntry(index);
+    if (entry != -1) return dictionary->DeleteProperty(entry);
+  }
+  return Heap::true_value();
+}
+
+
+Object* JSObject::DeleteProperty(String* name) {
+  // ECMA-262, 3rd, 8.6.2.5
+  ASSERT(name->IsString());
+
+  // Check access rights if needed.
+  if (IsAccessCheckNeeded() &&
+      !Top::MayNamedAccess(this, name, v8::ACCESS_DELETE)) {
+    Top::ReportFailedAccessCheck(this, v8::ACCESS_DELETE);
+    return Heap::false_value();
+  }
+
+  if (IsJSGlobalProxy()) {
+    Object* proto = GetPrototype();
+    if (proto->IsNull()) return Heap::false_value();
+    ASSERT(proto->IsJSGlobalObject());
+    return JSGlobalObject::cast(proto)->DeleteProperty(name);
+  }
+
+  uint32_t index = 0;
+  if (name->AsArrayIndex(&index)) {
+    return DeleteElement(index);
+  } else {
+    LookupResult result;
+    LocalLookup(name, &result);
+    if (!result.IsValid()) return Heap::true_value();
+    if (result.IsDontDelete()) return Heap::false_value();
+    // Check for interceptor.
+    if (result.type() == INTERCEPTOR) {
+      return DeletePropertyWithInterceptor(name);
+    }
+    if (!result.IsLoaded()) {
+      return JSObject::cast(this)->DeleteLazyProperty(&result, name);
+    }
+    // Normalize object if needed.
+    Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
+    if (obj->IsFailure()) return obj;
+    // Make sure the properties are normalized before removing the entry.
+    Dictionary* dictionary = property_dictionary();
+    int entry = dictionary->FindStringEntry(name);
+    if (entry != -1) return dictionary->DeleteProperty(entry);
+    return Heap::true_value();
+  }
+}
+
+
+// Check whether this object references another object.
+bool JSObject::ReferencesObject(Object* obj) {
+  AssertNoAllocation no_alloc;
+
+  // Is the object the constructor for this object?
+  if (map()->constructor() == obj) {
+    return true;
+  }
+
+  // Is the object the prototype for this object?
+  if (map()->prototype() == obj) {
+    return true;
+  }
+
+  // Check if the object is among the named properties.
+  Object* key = SlowReverseLookup(obj);
+  if (key != Heap::undefined_value()) {
+    return true;
+  }
+
+  // Check if the object is among the indexed properties.
+  if (HasFastElements()) {
+    int length = IsJSArray()
+        ? Smi::cast(JSArray::cast(this)->length())->value()
+        : FixedArray::cast(elements())->length();
+    for (int i = 0; i < length; i++) {
+      Object* element = FixedArray::cast(elements())->get(i);
+      if (!element->IsTheHole() && element == obj) {
+        return true;
+      }
+    }
+  } else {
+    key = element_dictionary()->SlowReverseLookup(obj);
+    if (key != Heap::undefined_value()) {
+      return true;
+    }
+  }
+
+  // For functions check the context. Boilerplate functions do
+  // not have to be traversed since they have no real context.
+  if (IsJSFunction() && !JSFunction::cast(this)->IsBoilerplate()) {
+    // Get the constructor function for arguments array.
+    JSObject* arguments_boilerplate =
+        Top::context()->global_context()->arguments_boilerplate();
+    JSFunction* arguments_function =
+        JSFunction::cast(arguments_boilerplate->map()->constructor());
+
+    // Get the context and don't check if it is the global context.
+    JSFunction* f = JSFunction::cast(this);
+    Context* context = f->context();
+    if (context->IsGlobalContext()) {
+      return false;
+    }
+
+    // Check the non-special context slots.
+    for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
+      // Only check JS objects.
+      if (context->get(i)->IsJSObject()) {
+        JSObject* ctxobj = JSObject::cast(context->get(i));
+        // If it is an arguments array check the content.
+        if (ctxobj->map()->constructor() == arguments_function) {
+          if (ctxobj->ReferencesObject(obj)) {
+            return true;
+          }
+        } else if (ctxobj == obj) {
+          return true;
+        }
+      }
+    }
+
+    // Check the context extension if any.
+    if (context->has_extension()) {
+      return context->extension()->ReferencesObject(obj);
+    }
+  }
+
+  // No references to object.
+  return false;
+}
+
+
+// Tests for the fast common case for property enumeration:
+// - this object has an enum cache
+// - this object has no elements
+// - no prototype has enumerable properties/elements
+// - neither this object nor any prototype has interceptors
+bool JSObject::IsSimpleEnum() {
+  JSObject* arguments_boilerplate =
+      Top::context()->global_context()->arguments_boilerplate();
+  JSFunction* arguments_function =
+      JSFunction::cast(arguments_boilerplate->map()->constructor());
+  if (IsAccessCheckNeeded()) return false;
+  if (map()->constructor() == arguments_function) return false;
+
+  for (Object* o = this;
+       o != Heap::null_value();
+       o = JSObject::cast(o)->GetPrototype()) {
+    JSObject* curr = JSObject::cast(o);
+    if (!curr->HasFastProperties()) return false;
+    if (!curr->map()->instance_descriptors()->HasEnumCache()) return false;
+    if (curr->NumberOfEnumElements() > 0) return false;
+    if (curr->HasNamedInterceptor()) return false;
+    if (curr->HasIndexedInterceptor()) return false;
+    if (curr != this) {
+      FixedArray* curr_fixed_array =
+          FixedArray::cast(curr->map()->instance_descriptors()->GetEnumCache());
+      if (curr_fixed_array->length() > 0) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+
+int Map::NumberOfDescribedProperties() {
+  int result = 0;
+  for (DescriptorReader r(instance_descriptors()); !r.eos(); r.advance()) {
+    if (r.IsProperty()) result++;
+  }
+  return result;
+}
+
+
+int Map::PropertyIndexFor(String* name) {
+  for (DescriptorReader r(instance_descriptors()); !r.eos(); r.advance()) {
+    if (r.Equals(name) && !r.IsNullDescriptor()) return r.GetFieldIndex();
+  }
+  return -1;
+}
+
+
+int Map::NextFreePropertyIndex() {
+  int index = -1;
+  for (DescriptorReader r(instance_descriptors()); !r.eos(); r.advance()) {
+    if (r.type() == FIELD) {
+      if (r.GetFieldIndex() > index) index = r.GetFieldIndex();
+    }
+  }
+  return index+1;
+}
+
+
+AccessorDescriptor* Map::FindAccessor(String* name) {
+  for (DescriptorReader r(instance_descriptors()); !r.eos(); r.advance()) {
+    if (r.Equals(name) && r.type() == CALLBACKS) return r.GetCallbacks();
+  }
+  return NULL;
+}
+
+
+void JSObject::LocalLookup(String* name, LookupResult* result) {
+  ASSERT(name->IsString());
+
+  if (IsJSGlobalProxy()) {
+    Object* proto = GetPrototype();
+    if (proto->IsNull()) return result->NotFound();
+    ASSERT(proto->IsJSGlobalObject());
+    return JSObject::cast(proto)->LocalLookup(name, result);
+  }
+
+  // Do not use inline caching if the object is a non-global object
+  // that requires access checks.
+  if (!IsJSGlobalProxy() && IsAccessCheckNeeded()) {
+    result->DisallowCaching();
+  }
+
+  // Check __proto__ before interceptor.
+  if (name->Equals(Heap::Proto_symbol()) && !IsJSContextExtensionObject()) {
+    result->ConstantResult(this);
+    return;
+  }
+
+  // Check for lookup interceptor except when bootstrapping.
+  if (HasNamedInterceptor() && !Bootstrapper::IsActive()) {
+    result->InterceptorResult(this);
+    return;
+  }
+
+  LocalLookupRealNamedProperty(name, result);
+}
+
+
+void JSObject::Lookup(String* name, LookupResult* result) {
+  // Ecma-262 3rd 8.6.2.4
+  for (Object* current = this;
+       current != Heap::null_value();
+       current = JSObject::cast(current)->GetPrototype()) {
+    JSObject::cast(current)->LocalLookup(name, result);
+    if (result->IsValid() && !result->IsTransitionType()) return;
+  }
+  result->NotFound();
+}
+
+
+// Search object and it's prototype chain for callback properties.
+void JSObject::LookupCallback(String* name, LookupResult* result) {
+  for (Object* current = this;
+       current != Heap::null_value();
+       current = JSObject::cast(current)->GetPrototype()) {
+    JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
+    if (result->IsValid() && result->type() == CALLBACKS) return;
+  }
+  result->NotFound();
+}
+
+
+Object* JSObject::DefineGetterSetter(String* name,
+                                     PropertyAttributes attributes) {
+  // Make sure that the top context does not change when doing callbacks or
+  // interceptor calls.
+  AssertNoContextChange ncc;
+
+  // Check access rights if needed.
+  if (IsAccessCheckNeeded() &&
+      !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
+    Top::ReportFailedAccessCheck(this, v8::ACCESS_SET);
+    return Heap::undefined_value();
+  }
+
+  // Try to flatten before operating on the string.
+  name->TryFlattenIfNotFlat();
+
+  // Check if there is an API defined callback object which prohibits
+  // callback overwriting in this object or it's prototype chain.
+  // This mechanism is needed for instance in a browser setting, where
+  // certain accessors such as window.location should not be allowed
+  // to be overwritten because allowing overwriting could potentially
+  // cause security problems.
+  LookupResult callback_result;
+  LookupCallback(name, &callback_result);
+  if (callback_result.IsValid()) {
+    Object* obj = callback_result.GetCallbackObject();
+    if (obj->IsAccessorInfo() &&
+        AccessorInfo::cast(obj)->prohibits_overwriting()) {
+      return Heap::undefined_value();
+    }
+  }
+
+  uint32_t index;
+  bool is_element = name->AsArrayIndex(&index);
+  if (is_element && IsJSArray()) return Heap::undefined_value();
+
+  if (is_element) {
+    // Lookup the index.
+    if (!HasFastElements()) {
+      Dictionary* dictionary = element_dictionary();
+      int entry = dictionary->FindNumberEntry(index);
+      if (entry != -1) {
+        Object* result = dictionary->ValueAt(entry);
+        PropertyDetails details = dictionary->DetailsAt(entry);
+        if (details.IsReadOnly()) return Heap::undefined_value();
+        if (details.type() == CALLBACKS) {
+          // Only accessors allowed as elements.
+          ASSERT(result->IsFixedArray());
+          return result;
+        }
+      }
+    }
+  } else {
+    // Lookup the name.
+    LookupResult result;
+    LocalLookup(name, &result);
+    if (result.IsValid()) {
+      if (result.IsReadOnly()) return Heap::undefined_value();
+      if (result.type() == CALLBACKS) {
+        Object* obj = result.GetCallbackObject();
+        if (obj->IsFixedArray()) return obj;
+      }
+    }
+  }
+
+  // Allocate the fixed array to hold getter and setter.
+  Object* structure = Heap::AllocateFixedArray(2, TENURED);
+  if (structure->IsFailure()) return structure;
+  PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
+
+  if (is_element) {
+    // Normalize object to make this operation simple.
+    Object* ok = NormalizeElements();
+    if (ok->IsFailure()) return ok;
+
+    // Update the dictionary with the new CALLBACKS property.
+    Object* dict =
+        element_dictionary()->SetOrAddNumberEntry(index, structure, details);
+    if (dict->IsFailure()) return dict;
+
+    // If name is an index we need to stay in slow case.
+    Dictionary* elements = Dictionary::cast(dict);
+    elements->set_requires_slow_elements();
+    // Set the potential new dictionary on the object.
+    set_elements(Dictionary::cast(dict));
+  } else {
+    // Normalize object to make this operation simple.
+    Object* ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
+    if (ok->IsFailure()) return ok;
+
+    // Update the dictionary with the new CALLBACKS property.
+    Object* dict =
+        property_dictionary()->SetOrAddStringEntry(name, structure, details);
+    if (dict->IsFailure()) return dict;
+
+    // Set the potential new dictionary on the object.
+    set_properties(Dictionary::cast(dict));
+  }
+
+  return structure;
+}
+
+
+Object* JSObject::DefineAccessor(String* name, bool is_getter, JSFunction* fun,
+                                 PropertyAttributes attributes) {
+  // Check access rights if needed.
+  if (IsAccessCheckNeeded() &&
+      !Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) {
+    Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
+    return Heap::undefined_value();
+  }
+
+  if (IsJSGlobalProxy()) {
+    Object* proto = GetPrototype();
+    if (proto->IsNull()) return this;
+    ASSERT(proto->IsJSGlobalObject());
+    return JSObject::cast(proto)->DefineAccessor(name, is_getter,
+                                                 fun, attributes);
+  }
+
+  Object* array = DefineGetterSetter(name, attributes);
+  if (array->IsFailure() || array->IsUndefined()) return array;
+  FixedArray::cast(array)->set(is_getter ? 0 : 1, fun);
+  return this;
+}
+
+
+Object* JSObject::LookupAccessor(String* name, bool is_getter) {
+  // Make sure that the top context does not change when doing callbacks or
+  // interceptor calls.
+  AssertNoContextChange ncc;
+
+  // Check access rights if needed.
+  if (IsAccessCheckNeeded() &&
+      !Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) {
+    Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
+    return Heap::undefined_value();
+  }
+
+  // Make the lookup and include prototypes.
+  int accessor_index = is_getter ? kGetterIndex : kSetterIndex;
+  uint32_t index;
+  if (name->AsArrayIndex(&index)) {
+    for (Object* obj = this;
+         obj != Heap::null_value();
+         obj = JSObject::cast(obj)->GetPrototype()) {
+      JSObject* jsObject = JSObject::cast(obj);
+      if (!jsObject->HasFastElements()) {
+        Dictionary* dictionary = jsObject->element_dictionary();
+        int entry = dictionary->FindNumberEntry(index);
+        if (entry != -1) {
+          Object* element = dictionary->ValueAt(entry);
+          PropertyDetails details = dictionary->DetailsAt(entry);
+          if (details.type() == CALLBACKS) {
+            // Only accessors allowed as elements.
+            return FixedArray::cast(element)->get(accessor_index);
+          }
+        }
+      }
+    }
+  } else {
+    for (Object* obj = this;
+         obj != Heap::null_value();
+         obj = JSObject::cast(obj)->GetPrototype()) {
+      LookupResult result;
+      JSObject::cast(obj)->LocalLookup(name, &result);
+      if (result.IsValid()) {
+        if (result.IsReadOnly()) return Heap::undefined_value();
+        if (result.type() == CALLBACKS) {
+          Object* obj = result.GetCallbackObject();
+          if (obj->IsFixedArray()) {
+            return FixedArray::cast(obj)->get(accessor_index);
+          }
+        }
+      }
+    }
+  }
+  return Heap::undefined_value();
+}
+
+
+Object* JSObject::SlowReverseLookup(Object* value) {
+  if (HasFastProperties()) {
+    for (DescriptorReader r(map()->instance_descriptors());
+         !r.eos();
+         r.advance()) {
+      if (r.type() == FIELD) {
+        if (FastPropertyAt(r.GetFieldIndex()) == value) {
+          return r.GetKey();
+        }
+      } else if (r.type() == CONSTANT_FUNCTION) {
+        if (r.GetConstantFunction() == value) {
+          return r.GetKey();
+        }
+      }
+    }
+    return Heap::undefined_value();
+  } else {
+    return property_dictionary()->SlowReverseLookup(value);
+  }
+}
+
+
+Object* Map::Copy() {
+  Object* result = Heap::AllocateMap(instance_type(), instance_size());
+  if (result->IsFailure()) return result;
+  Map::cast(result)->set_prototype(prototype());
+  Map::cast(result)->set_constructor(constructor());
+  // Don't copy descriptors, so map transitions always remain a forest.
+  Map::cast(result)->set_instance_descriptors(Heap::empty_descriptor_array());
+  // Please note instance_type and instance_size are set when allocated.
+  Map::cast(result)->set_inobject_properties(inobject_properties());
+  Map::cast(result)->set_unused_property_fields(unused_property_fields());
+  Map::cast(result)->set_bit_field(bit_field());
+  Map::cast(result)->ClearCodeCache();
+  return result;
+}
+
+
+Object* Map::CopyDropTransitions() {
+  Object* new_map = Copy();
+  if (new_map->IsFailure()) return new_map;
+  Object* descriptors = instance_descriptors()->RemoveTransitions();
+  if (descriptors->IsFailure()) return descriptors;
+  cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors));
+  return cast(new_map);
+}
+
+
+Object* Map::UpdateCodeCache(String* name, Code* code) {
+  ASSERT(code->ic_state() == MONOMORPHIC);
+  FixedArray* cache = code_cache();
+
+  // When updating the code cache we disregard the type encoded in the
+  // flags. This allows call constant stubs to overwrite call field
+  // stubs, etc.
+  Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
+
+  // First check whether we can update existing code cache without
+  // extending it.
+  int length = cache->length();
+  int deleted_index = -1;
+  for (int i = 0; i < length; i += 2) {
+    Object* key = cache->get(i);
+    if (key->IsNull()) {
+      if (deleted_index < 0) deleted_index = i;
+      continue;
+    }
+    if (key->IsUndefined()) {
+      if (deleted_index >= 0) i = deleted_index;
+      cache->set(i + 0, name);
+      cache->set(i + 1, code);
+      return this;
+    }
+    if (name->Equals(String::cast(key))) {
+      Code::Flags found = Code::cast(cache->get(i + 1))->flags();
+      if (Code::RemoveTypeFromFlags(found) == flags) {
+        cache->set(i + 1, code);
+        return this;
+      }
+    }
+  }
+
+  // Reached the end of the code cache.  If there were deleted
+  // elements, reuse the space for the first of them.
+  if (deleted_index >= 0) {
+    cache->set(deleted_index + 0, name);
+    cache->set(deleted_index + 1, code);
+    return this;
+  }
+
+  // Extend the code cache with some new entries (at least one).
+  int new_length = length + ((length >> 1) & ~1) + 2;
+  ASSERT((new_length & 1) == 0);  // must be a multiple of two
+  Object* result = cache->CopySize(new_length);
+  if (result->IsFailure()) return result;
+
+  // Add the (name, code) pair to the new cache.
+  cache = FixedArray::cast(result);
+  cache->set(length + 0, name);
+  cache->set(length + 1, code);
+  set_code_cache(cache);
+  return this;
+}
+
+
+Object* Map::FindInCodeCache(String* name, Code::Flags flags) {
+  FixedArray* cache = code_cache();
+  int length = cache->length();
+  for (int i = 0; i < length; i += 2) {
+    Object* key = cache->get(i);
+    // Skip deleted elements.
+    if (key->IsNull()) continue;
+    if (key->IsUndefined()) return key;
+    if (name->Equals(String::cast(key))) {
+      Code* code = Code::cast(cache->get(i + 1));
+      if (code->flags() == flags) return code;
+    }
+  }
+  return Heap::undefined_value();
+}
+
+
+int Map::IndexInCodeCache(Code* code) {
+  FixedArray* array = code_cache();
+  int len = array->length();
+  for (int i = 0; i < len; i += 2) {
+    if (array->get(i + 1) == code) return i + 1;
+  }
+  return -1;
+}
+
+
+void Map::RemoveFromCodeCache(int index) {
+  FixedArray* array = code_cache();
+  ASSERT(array->length() >= index && array->get(index)->IsCode());
+  // Use null instead of undefined for deleted elements to distinguish
+  // deleted elements from unused elements.  This distinction is used
+  // when looking up in the cache and when updating the cache.
+  array->set_null(index - 1);  // key
+  array->set_null(index);  // code
+}
+
+
+void FixedArray::FixedArrayIterateBody(ObjectVisitor* v) {
+  IteratePointers(v, kHeaderSize, kHeaderSize + length() * kPointerSize);
+}
+
+
+static bool HasKey(FixedArray* array, Object* key) {
+  int len0 = array->length();
+  for (int i = 0; i < len0; i++) {
+    Object* element = array->get(i);
+    if (element->IsSmi() && key->IsSmi() && (element == key)) return true;
+    if (element->IsString() &&
+        key->IsString() && String::cast(element)->Equals(String::cast(key))) {
+      return true;
+    }
+  }
+  return false;
+}
+
+
+Object* FixedArray::AddKeysFromJSArray(JSArray* array) {
+  // Remove array holes from array if any.
+  Object* object = array->RemoveHoles();
+  if (object->IsFailure()) return object;
+  JSArray* compacted_array = JSArray::cast(object);
+
+  // Allocate a temporary fixed array.
+  int compacted_array_length = Smi::cast(compacted_array->length())->value();
+  object = Heap::AllocateFixedArray(compacted_array_length);
+  if (object->IsFailure()) return object;
+  FixedArray* key_array = FixedArray::cast(object);
+
+  // Copy the elements from the JSArray to the temporary fixed array.
+  for (int i = 0; i < compacted_array_length; i++) {
+    key_array->set(i, compacted_array->GetElement(i));
+  }
+
+  // Compute the union of this and the temporary fixed array.
+  return UnionOfKeys(key_array);
+}
+
+
+Object* FixedArray::UnionOfKeys(FixedArray* other) {
+  int len0 = length();
+  int len1 = other->length();
+  // Optimize if either is empty.
+  if (len0 == 0) return other;
+  if (len1 == 0) return this;
+
+  // Compute how many elements are not in this.
+  int extra = 0;
+  for (int y = 0; y < len1; y++) {
+    if (!HasKey(this, other->get(y))) extra++;
+  }
+
+  // Allocate the result
+  Object* obj = Heap::AllocateFixedArray(len0 + extra);
+  if (obj->IsFailure()) return obj;
+  // Fill in the content
+  FixedArray* result = FixedArray::cast(obj);
+  WriteBarrierMode mode = result->GetWriteBarrierMode();
+  for (int i = 0; i < len0; i++) {
+    result->set(i, get(i), mode);
+  }
+  // Fill in the extra keys.
+  int index = 0;
+  for (int y = 0; y < len1; y++) {
+    if (!HasKey(this, other->get(y))) {
+      result->set(len0 + index, other->get(y), mode);
+      index++;
+    }
+  }
+  ASSERT(extra == index);
+  return result;
+}
+
+
+Object* FixedArray::CopySize(int new_length) {
+  if (new_length == 0) return Heap::empty_fixed_array();
+  Object* obj = Heap::AllocateFixedArray(new_length);
+  if (obj->IsFailure()) return obj;
+  FixedArray* result = FixedArray::cast(obj);
+  // Copy the content
+  int len = length();
+  if (new_length < len) len = new_length;
+  result->set_map(map());
+  WriteBarrierMode mode = result->GetWriteBarrierMode();
+  for (int i = 0; i < len; i++) {
+    result->set(i, get(i), mode);
+  }
+  return result;
+}
+
+
+void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
+  WriteBarrierMode mode = dest->GetWriteBarrierMode();
+  for (int index = 0; index < len; index++) {
+    dest->set(dest_pos+index, get(pos+index), mode);
+  }
+}
+
+
+#ifdef DEBUG
+bool FixedArray::IsEqualTo(FixedArray* other) {
+  if (length() != other->length()) return false;
+  for (int i = 0 ; i < length(); ++i) {
+    if (get(i) != other->get(i)) return false;
+  }
+  return true;
+}
+#endif
+
+
+Object* DescriptorArray::Allocate(int number_of_descriptors) {
+  if (number_of_descriptors == 0) {
+    return Heap::empty_descriptor_array();
+  }
+  // Allocate the array of keys.
+  Object* array = Heap::AllocateFixedArray(ToKeyIndex(number_of_descriptors));
+  if (array->IsFailure()) return array;
+  // Do not use DescriptorArray::cast on incomplete object.
+  FixedArray* result = FixedArray::cast(array);
+
+  // Allocate the content array and set it in the descriptor array.
+  array = Heap::AllocateFixedArray(number_of_descriptors << 1);
+  if (array->IsFailure()) return array;
+  result->set(kContentArrayIndex, array);
+  result->set(kEnumerationIndexIndex,
+              Smi::FromInt(PropertyDetails::kInitialIndex),
+              SKIP_WRITE_BARRIER);
+  return result;
+}
+
+
+void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
+                                   FixedArray* new_cache) {
+  ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
+  if (HasEnumCache()) {
+    FixedArray::cast(get(kEnumerationIndexIndex))->
+      set(kEnumCacheBridgeCacheIndex, new_cache);
+  } else {
+    if (IsEmpty()) return;  // Do nothing for empty descriptor array.
+    FixedArray::cast(bridge_storage)->
+      set(kEnumCacheBridgeCacheIndex, new_cache);
+    fast_set(FixedArray::cast(bridge_storage),
+             kEnumCacheBridgeEnumIndex,
+             get(kEnumerationIndexIndex));
+    set(kEnumerationIndexIndex, bridge_storage);
+  }
+}
+
+
+Object* DescriptorArray::CopyInsert(Descriptor* descriptor,
+                                    TransitionFlag transition_flag) {
+  // Transitions are only kept when inserting another transition.
+  // This precondition is not required by this function's implementation, but
+  // is currently required by the semantics of maps, so we check it.
+  // Conversely, we filter after replacing, so replacing a transition and
+  // removing all other transitions is not supported.
+  bool remove_transitions = transition_flag == REMOVE_TRANSITIONS;
+  ASSERT(remove_transitions == !descriptor->GetDetails().IsTransition());
+  ASSERT(descriptor->GetDetails().type() != NULL_DESCRIPTOR);
+
+  // Ensure the key is a symbol.
+  Object* result = descriptor->KeyToSymbol();
+  if (result->IsFailure()) return result;
+
+  int transitions = 0;
+  int null_descriptors = 0;
+  if (remove_transitions) {
+    for (DescriptorReader r(this); !r.eos(); r.advance()) {
+      if (r.IsTransition()) transitions++;
+      if (r.IsNullDescriptor()) null_descriptors++;
+    }
+  } else {
+    for (DescriptorReader r(this); !r.eos(); r.advance()) {
+      if (r.IsNullDescriptor()) null_descriptors++;
+    }
+  }
+  int new_size = number_of_descriptors() - transitions - null_descriptors;
+
+  // If key is in descriptor, we replace it in-place when filtering.
+  // Count a null descriptor for key as inserted, not replaced.
+  int index = Search(descriptor->GetKey());
+  const bool inserting = (index == kNotFound);
+  const bool replacing = !inserting;
+  bool keep_enumeration_index = false;
+  if (inserting) {
+    ++new_size;
+  }
+  if (replacing) {
+    // We are replacing an existing descriptor.  We keep the enumeration
+    // index of a visible property.
+    PropertyType t = PropertyDetails(GetDetails(index)).type();
+    if (t == CONSTANT_FUNCTION ||
+        t == FIELD ||
+        t == CALLBACKS ||
+        t == INTERCEPTOR) {
+      keep_enumeration_index = true;
+    } else if (remove_transitions) {
+     // Replaced descriptor has been counted as removed if it is
+     // a transition that will be replaced.  Adjust count in this case.
+      ++new_size;
+    }
+  }
+  result = Allocate(new_size);
+  if (result->IsFailure()) return result;
+  DescriptorArray* new_descriptors = DescriptorArray::cast(result);
+  // Set the enumeration index in the descriptors and set the enumeration index
+  // in the result.
+  int enumeration_index = NextEnumerationIndex();
+  if (!descriptor->GetDetails().IsTransition()) {
+    if (keep_enumeration_index) {
+      descriptor->SetEnumerationIndex(
+          PropertyDetails(GetDetails(index)).index());
+    } else {
+      descriptor->SetEnumerationIndex(enumeration_index);
+      ++enumeration_index;
+    }
+  }
+  new_descriptors->SetNextEnumerationIndex(enumeration_index);
+
+  // Copy the descriptors, filtering out transitions and null descriptors,
+  // and inserting or replacing a descriptor.
+  DescriptorWriter w(new_descriptors);
+  DescriptorReader r(this);
+  uint32_t descriptor_hash = descriptor->GetKey()->Hash();
+
+  for (; !r.eos(); r.advance()) {
+    if (r.GetKey()->Hash() > descriptor_hash ||
+        r.GetKey() == descriptor->GetKey()) break;
+    if (r.IsNullDescriptor()) continue;
+    if (remove_transitions && r.IsTransition()) continue;
+    w.WriteFrom(&r);
+  }
+  w.Write(descriptor);
+  if (replacing) {
+    ASSERT(r.GetKey() == descriptor->GetKey());
+    r.advance();
+  } else {
+    ASSERT(r.eos() ||
+           r.GetKey()->Hash() > descriptor_hash ||
+           r.IsNullDescriptor());
+  }
+  for (; !r.eos(); r.advance()) {
+    if (r.IsNullDescriptor()) continue;
+    if (remove_transitions && r.IsTransition()) continue;
+    w.WriteFrom(&r);
+  }
+  ASSERT(w.eos());
+
+  return new_descriptors;
+}
+
+
+Object* DescriptorArray::RemoveTransitions() {
+  // Remove all transitions and null descriptors. Return a copy of the array
+  // with all transitions removed, or a Failure object if the new array could
+  // not be allocated.
+
+  // Compute the size of the map transition entries to be removed.
+  int num_removed = 0;
+  for (DescriptorReader r(this); !r.eos(); r.advance()) {
+    if (!r.IsProperty()) num_removed++;
+  }
+
+  // Allocate the new descriptor array.
+  Object* result = Allocate(number_of_descriptors() - num_removed);
+  if (result->IsFailure()) return result;
+  DescriptorArray* new_descriptors = DescriptorArray::cast(result);
+
+  // Copy the content.
+  DescriptorWriter w(new_descriptors);
+  for (DescriptorReader r(this); !r.eos(); r.advance()) {
+    if (r.IsProperty()) w.WriteFrom(&r);
+  }
+  ASSERT(w.eos());
+
+  return new_descriptors;
+}
+
+
+void DescriptorArray::Sort() {
+  // In-place heap sort.
+  int len = number_of_descriptors();
+
+  // Bottom-up max-heap construction.
+  for (int i = 1; i < len; ++i) {
+    int child_index = i;
+    while (child_index > 0) {
+      int parent_index = ((child_index + 1) >> 1) - 1;
+      uint32_t parent_hash = GetKey(parent_index)->Hash();
+      uint32_t child_hash = GetKey(child_index)->Hash();
+      if (parent_hash < child_hash) {
+        Swap(parent_index, child_index);
+      } else {
+        break;
+      }
+      child_index = parent_index;
+    }
+  }
+
+  // Extract elements and create sorted array.
+  for (int i = len - 1; i > 0; --i) {
+    // Put max element at the back of the array.
+    Swap(0, i);
+    // Sift down the new top element.
+    int parent_index = 0;
+    while (true) {
+      int child_index = ((parent_index + 1) << 1) - 1;
+      if (child_index >= i) break;
+      uint32_t child1_hash = GetKey(child_index)->Hash();
+      uint32_t child2_hash = GetKey(child_index + 1)->Hash();
+      uint32_t parent_hash = GetKey(parent_index)->Hash();
+      if (child_index + 1 >= i || child1_hash > child2_hash) {
+        if (parent_hash > child1_hash) break;
+        Swap(parent_index, child_index);
+        parent_index = child_index;
+      } else {
+        if (parent_hash > child2_hash) break;
+        Swap(parent_index, child_index + 1);
+        parent_index = child_index + 1;
+      }
+    }
+  }
+
+  SLOW_ASSERT(IsSortedNoDuplicates());
+}
+
+
+int DescriptorArray::BinarySearch(String* name, int low, int high) {
+  uint32_t hash = name->Hash();
+
+  while (low <= high) {
+    int mid = (low + high) / 2;
+    String* mid_name = GetKey(mid);
+    uint32_t mid_hash = mid_name->Hash();
+
+    if (mid_hash > hash) {
+      high = mid - 1;
+      continue;
+    }
+    if (mid_hash < hash) {
+      low = mid + 1;
+      continue;
+    }
+    // Found an element with the same hash-code.
+    ASSERT(hash == mid_hash);
+    // There might be more, so we find the first one and
+    // check them all to see if we have a match.
+    if (name == mid_name  && !is_null_descriptor(mid)) return mid;
+    while ((mid > low) && (GetKey(mid - 1)->Hash() == hash)) mid--;
+    for (; (mid <= high) && (GetKey(mid)->Hash() == hash); mid++) {
+      if (GetKey(mid)->Equals(name) && !is_null_descriptor(mid)) return mid;
+    }
+    break;
+  }
+  return kNotFound;
+}
+
+
+int DescriptorArray::LinearSearch(String* name, int len) {
+  uint32_t hash = name->Hash();
+  for (int number = 0; number < len; number++) {
+    String* entry = GetKey(number);
+    if ((entry->Hash() == hash) &&
+        name->Equals(entry) &&
+        !is_null_descriptor(number)) {
+      return number;
+    }
+  }
+  return kNotFound;
+}
+
+
+#ifdef DEBUG
+bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
+  if (IsEmpty()) return other->IsEmpty();
+  if (other->IsEmpty()) return false;
+  if (length() != other->length()) return false;
+  for (int i = 0; i < length(); ++i) {
+    if (get(i) != other->get(i) && i != kContentArrayIndex) return false;
+  }
+  return GetContentArray()->IsEqualTo(other->GetContentArray());
+}
+#endif
+
+
+static StaticResource<StringInputBuffer> string_input_buffer;
+
+
+bool String::LooksValid() {
+  if (!Heap::Contains(this)) return false;
+  return true;
+}
+
+
+int String::Utf8Length() {
+  if (StringShape(this).IsAsciiRepresentation()) return length();
+  // Attempt to flatten before accessing the string.  It probably
+  // doesn't make Utf8Length faster, but it is very likely that
+  // the string will be accessed later (for example by WriteUtf8)
+  // so it's still a good idea.
+  TryFlattenIfNotFlat();
+  Access<StringInputBuffer> buffer(&string_input_buffer);
+  buffer->Reset(0, this);
+  int result = 0;
+  while (buffer->has_more())
+    result += unibrow::Utf8::Length(buffer->GetNext());
+  return result;
+}
+
+
+Vector<const char> String::ToAsciiVector() {
+  ASSERT(StringShape(this).IsAsciiRepresentation());
+  ASSERT(IsFlat());
+
+  int offset = 0;
+  int length = this->length();
+  StringRepresentationTag string_tag = StringShape(this).representation_tag();
+  String* string = this;
+  if (string_tag == kSlicedStringTag) {
+    SlicedString* sliced = SlicedString::cast(string);
+    offset += sliced->start();
+    string = sliced->buffer();
+    string_tag = StringShape(string).representation_tag();
+  } else if (string_tag == kConsStringTag) {
+    ConsString* cons = ConsString::cast(string);
+    ASSERT(cons->second()->length() == 0);
+    string = cons->first();
+    string_tag = StringShape(string).representation_tag();
+  }
+  if (string_tag == kSeqStringTag) {
+    SeqAsciiString* seq = SeqAsciiString::cast(string);
+    char* start = seq->GetChars();
+    return Vector<const char>(start + offset, length);
+  }
+  ASSERT(string_tag == kExternalStringTag);
+  ExternalAsciiString* ext = ExternalAsciiString::cast(string);
+  const char* start = ext->resource()->data();
+  return Vector<const char>(start + offset, length);
+}
+
+
+Vector<const uc16> String::ToUC16Vector() {
+  ASSERT(StringShape(this).IsTwoByteRepresentation());
+  ASSERT(IsFlat());
+
+  int offset = 0;
+  int length = this->length();
+  StringRepresentationTag string_tag = StringShape(this).representation_tag();
+  String* string = this;
+  if (string_tag == kSlicedStringTag) {
+    SlicedString* sliced = SlicedString::cast(string);
+    offset += sliced->start();
+    string = String::cast(sliced->buffer());
+    string_tag = StringShape(string).representation_tag();
+  } else if (string_tag == kConsStringTag) {
+    ConsString* cons = ConsString::cast(string);
+    ASSERT(cons->second()->length() == 0);
+    string = cons->first();
+    string_tag = StringShape(string).representation_tag();
+  }
+  if (string_tag == kSeqStringTag) {
+    SeqTwoByteString* seq = SeqTwoByteString::cast(string);
+    return Vector<const uc16>(seq->GetChars() + offset, length);
+  }
+  ASSERT(string_tag == kExternalStringTag);
+  ExternalTwoByteString* ext = ExternalTwoByteString::cast(string);
+  // This is a workaround for Chromium bug 9746: http://crbug.com/9746
+  // For external strings with a deleted resource we return a special
+  // Vector which will not compare to any string when doing SymbolTable
+  // lookups.
+  if (ext->resource() == NULL) {
+    return Vector<const uc16>(NULL, length);
+  }
+  const uc16* start =
+      reinterpret_cast<const uc16*>(ext->resource()->data());
+  return Vector<const uc16>(start + offset, length);
+}
+
+
+SmartPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
+                                     RobustnessFlag robust_flag,
+                                     int offset,
+                                     int length,
+                                     int* length_return) {
+  ASSERT(NativeAllocationChecker::allocation_allowed());
+  if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
+    return SmartPointer<char>(NULL);
+  }
+
+  // Negative length means the to the end of the string.
+  if (length < 0) length = kMaxInt - offset;
+
+  // Compute the size of the UTF-8 string. Start at the specified offset.
+  Access<StringInputBuffer> buffer(&string_input_buffer);
+  buffer->Reset(offset, this);
+  int character_position = offset;
+  int utf8_bytes = 0;
+  while (buffer->has_more()) {
+    uint16_t character = buffer->GetNext();
+    if (character_position < offset + length) {
+      utf8_bytes += unibrow::Utf8::Length(character);
+    }
+    character_position++;
+  }
+
+  if (length_return) {
+    *length_return = utf8_bytes;
+  }
+
+  char* result = NewArray<char>(utf8_bytes + 1);
+
+  // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
+  buffer->Rewind();
+  buffer->Seek(offset);
+  character_position = offset;
+  int utf8_byte_position = 0;
+  while (buffer->has_more()) {
+    uint16_t character = buffer->GetNext();
+    if (character_position < offset + length) {
+      if (allow_nulls == DISALLOW_NULLS && character == 0) {
+        character = ' ';
+      }
+      utf8_byte_position +=
+          unibrow::Utf8::Encode(result + utf8_byte_position, character);
+    }
+    character_position++;
+  }
+  result[utf8_byte_position] = 0;
+  return SmartPointer<char>(result);
+}
+
+
+SmartPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
+                                     RobustnessFlag robust_flag,
+                                     int* length_return) {
+  return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
+}
+
+
+const uc16* String::GetTwoByteData() {
+  return GetTwoByteData(0);
+}
+
+
+const uc16* String::GetTwoByteData(unsigned start) {
+  ASSERT(!StringShape(this).IsAsciiRepresentation());
+  switch (StringShape(this).representation_tag()) {
+    case kSeqStringTag:
+      return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
+    case kExternalStringTag:
+      return ExternalTwoByteString::cast(this)->
+        ExternalTwoByteStringGetData(start);
+    case kSlicedStringTag: {
+      SlicedString* sliced_string = SlicedString::cast(this);
+      String* buffer = sliced_string->buffer();
+      if (StringShape(buffer).IsCons()) {
+        ConsString* cs = ConsString::cast(buffer);
+        // Flattened string.
+        ASSERT(cs->second()->length() == 0);
+        buffer = cs->first();
+      }
+      return buffer->GetTwoByteData(start + sliced_string->start());
+    }
+    case kConsStringTag:
+      UNREACHABLE();
+      return NULL;
+  }
+  UNREACHABLE();
+  return NULL;
+}
+
+
+SmartPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) {
+  ASSERT(NativeAllocationChecker::allocation_allowed());
+
+  if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
+    return SmartPointer<uc16>();
+  }
+
+  Access<StringInputBuffer> buffer(&string_input_buffer);
+  buffer->Reset(this);
+
+  uc16* result = NewArray<uc16>(length() + 1);
+
+  int i = 0;
+  while (buffer->has_more()) {
+    uint16_t character = buffer->GetNext();
+    result[i++] = character;
+  }
+  result[i] = 0;
+  return SmartPointer<uc16>(result);
+}
+
+
+const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
+  return reinterpret_cast<uc16*>(
+      reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
+}
+
+
+void SeqTwoByteString::SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
+                                                     unsigned* offset_ptr,
+                                                     unsigned max_chars) {
+  unsigned chars_read = 0;
+  unsigned offset = *offset_ptr;
+  while (chars_read < max_chars) {
+    uint16_t c = *reinterpret_cast<uint16_t*>(
+        reinterpret_cast<char*>(this) -
+            kHeapObjectTag + kHeaderSize + offset * kShortSize);
+    if (c <= kMaxAsciiCharCode) {
+      // Fast case for ASCII characters.   Cursor is an input output argument.
+      if (!unibrow::CharacterStream::EncodeAsciiCharacter(c,
+                                                          rbb->util_buffer,
+                                                          rbb->capacity,
+                                                          rbb->cursor)) {
+        break;
+      }
+    } else {
+      if (!unibrow::CharacterStream::EncodeNonAsciiCharacter(c,
+                                                             rbb->util_buffer,
+                                                             rbb->capacity,
+                                                             rbb->cursor)) {
+        break;
+      }
+    }
+    offset++;
+    chars_read++;
+  }
+  *offset_ptr = offset;
+  rbb->remaining += chars_read;
+}
+
+
+const unibrow::byte* SeqAsciiString::SeqAsciiStringReadBlock(
+    unsigned* remaining,
+    unsigned* offset_ptr,
+    unsigned max_chars) {
+  const unibrow::byte* b = reinterpret_cast<unibrow::byte*>(this) -
+      kHeapObjectTag + kHeaderSize + *offset_ptr * kCharSize;
+  *remaining = max_chars;
+  *offset_ptr += max_chars;
+  return b;
+}
+
+
+// This will iterate unless the block of string data spans two 'halves' of
+// a ConsString, in which case it will recurse.  Since the block of string
+// data to be read has a maximum size this limits the maximum recursion
+// depth to something sane.  Since C++ does not have tail call recursion
+// elimination, the iteration must be explicit. Since this is not an
+// -IntoBuffer method it can delegate to one of the efficient
+// *AsciiStringReadBlock routines.
+const unibrow::byte* ConsString::ConsStringReadBlock(ReadBlockBuffer* rbb,
+                                                     unsigned* offset_ptr,
+                                                     unsigned max_chars) {
+  ConsString* current = this;
+  unsigned offset = *offset_ptr;
+  int offset_correction = 0;
+
+  while (true) {
+    String* left = current->first();
+    unsigned left_length = (unsigned)left->length();
+    if (left_length > offset &&
+        (max_chars <= left_length - offset ||
+         (rbb->capacity <= left_length - offset &&
+          (max_chars = left_length - offset, true)))) {  // comma operator!
+      // Left hand side only - iterate unless we have reached the bottom of
+      // the cons tree.  The assignment on the left of the comma operator is
+      // in order to make use of the fact that the -IntoBuffer routines can
+      // produce at most 'capacity' characters.  This enables us to postpone
+      // the point where we switch to the -IntoBuffer routines (below) in order
+      // to maximize the chances of delegating a big chunk of work to the
+      // efficient *AsciiStringReadBlock routines.
+      if (StringShape(left).IsCons()) {
+        current = ConsString::cast(left);
+        continue;
+      } else {
+        const unibrow::byte* answer =
+            String::ReadBlock(left, rbb, &offset, max_chars);
+        *offset_ptr = offset + offset_correction;
+        return answer;
+      }
+    } else if (left_length <= offset) {
+      // Right hand side only - iterate unless we have reached the bottom of
+      // the cons tree.
+      String* right = current->second();
+      offset -= left_length;
+      offset_correction += left_length;
+      if (StringShape(right).IsCons()) {
+        current = ConsString::cast(right);
+        continue;
+      } else {
+        const unibrow::byte* answer =
+            String::ReadBlock(right, rbb, &offset, max_chars);
+        *offset_ptr = offset + offset_correction;
+        return answer;
+      }
+    } else {
+      // The block to be read spans two sides of the ConsString, so we call the
+      // -IntoBuffer version, which will recurse.  The -IntoBuffer methods
+      // are able to assemble data from several part strings because they use
+      // the util_buffer to store their data and never return direct pointers
+      // to their storage.  We don't try to read more than the buffer capacity
+      // here or we can get too much recursion.
+      ASSERT(rbb->remaining == 0);
+      ASSERT(rbb->cursor == 0);
+      current->ConsStringReadBlockIntoBuffer(
+          rbb,
+          &offset,
+          max_chars > rbb->capacity ? rbb->capacity : max_chars);
+      *offset_ptr = offset + offset_correction;
+      return rbb->util_buffer;
+    }
+  }
+}
+
+
+const unibrow::byte* SlicedString::SlicedStringReadBlock(ReadBlockBuffer* rbb,
+                                                         unsigned* offset_ptr,
+                                                         unsigned max_chars) {
+  String* backing = buffer();
+  unsigned offset = start() + *offset_ptr;
+  unsigned length = backing->length();
+  if (max_chars > length - offset) {
+    max_chars = length - offset;
+  }
+  const unibrow::byte* answer =
+      String::ReadBlock(backing, rbb, &offset, max_chars);
+  *offset_ptr = offset - start();
+  return answer;
+}
+
+
+uint16_t ExternalAsciiString::ExternalAsciiStringGet(int index) {
+  ASSERT(index >= 0 && index < length());
+  return resource()->data()[index];
+}
+
+
+const unibrow::byte* ExternalAsciiString::ExternalAsciiStringReadBlock(
+      unsigned* remaining,
+      unsigned* offset_ptr,
+      unsigned max_chars) {
+  // Cast const char* to unibrow::byte* (signedness difference).
+  const unibrow::byte* b =
+      reinterpret_cast<const unibrow::byte*>(resource()->data()) + *offset_ptr;
+  *remaining = max_chars;
+  *offset_ptr += max_chars;
+  return b;
+}
+
+
+const uc16* ExternalTwoByteString::ExternalTwoByteStringGetData(
+      unsigned start) {
+  return resource()->data() + start;
+}
+
+
+uint16_t ExternalTwoByteString::ExternalTwoByteStringGet(int index) {
+  ASSERT(index >= 0 && index < length());
+  return resource()->data()[index];
+}
+
+
+void ExternalTwoByteString::ExternalTwoByteStringReadBlockIntoBuffer(
+      ReadBlockBuffer* rbb,
+      unsigned* offset_ptr,
+      unsigned max_chars) {
+  unsigned chars_read = 0;
+  unsigned offset = *offset_ptr;
+  const uint16_t* data = resource()->data();
+  while (chars_read < max_chars) {
+    uint16_t c = data[offset];
+    if (c <= kMaxAsciiCharCode) {
+      // Fast case for ASCII characters. Cursor is an input output argument.
+      if (!unibrow::CharacterStream::EncodeAsciiCharacter(c,
+                                                          rbb->util_buffer,
+                                                          rbb->capacity,
+                                                          rbb->cursor))
+        break;
+    } else {
+      if (!unibrow::CharacterStream::EncodeNonAsciiCharacter(c,
+                                                             rbb->util_buffer,
+                                                             rbb->capacity,
+                                                             rbb->cursor))
+        break;
+    }
+    offset++;
+    chars_read++;
+  }
+  *offset_ptr = offset;
+  rbb->remaining += chars_read;
+}
+
+
+void SeqAsciiString::SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
+                                                 unsigned* offset_ptr,
+                                                 unsigned max_chars) {
+  unsigned capacity = rbb->capacity - rbb->cursor;
+  if (max_chars > capacity) max_chars = capacity;
+  memcpy(rbb->util_buffer + rbb->cursor,
+         reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize +
+             *offset_ptr * kCharSize,
+         max_chars);
+  rbb->remaining += max_chars;
+  *offset_ptr += max_chars;
+  rbb->cursor += max_chars;
+}
+
+
+void ExternalAsciiString::ExternalAsciiStringReadBlockIntoBuffer(
+      ReadBlockBuffer* rbb,
+      unsigned* offset_ptr,
+      unsigned max_chars) {
+  unsigned capacity = rbb->capacity - rbb->cursor;
+  if (max_chars > capacity) max_chars = capacity;
+  memcpy(rbb->util_buffer + rbb->cursor,
+         resource()->data() + *offset_ptr,
+         max_chars);
+  rbb->remaining += max_chars;
+  *offset_ptr += max_chars;
+  rbb->cursor += max_chars;
+}
+
+
+// This method determines the type of string involved and then copies
+// a whole chunk of characters into a buffer, or returns a pointer to a buffer
+// where they can be found.  The pointer is not necessarily valid across a GC
+// (see AsciiStringReadBlock).
+const unibrow::byte* String::ReadBlock(String* input,
+                                       ReadBlockBuffer* rbb,
+                                       unsigned* offset_ptr,
+                                       unsigned max_chars) {
+  ASSERT(*offset_ptr <= static_cast<unsigned>(input->length()));
+  if (max_chars == 0) {
+    rbb->remaining = 0;
+    return NULL;
+  }
+  switch (StringShape(input).representation_tag()) {
+    case kSeqStringTag:
+      if (StringShape(input).IsAsciiRepresentation()) {
+        SeqAsciiString* str = SeqAsciiString::cast(input);
+        return str->SeqAsciiStringReadBlock(&rbb->remaining,
+                                            offset_ptr,
+                                            max_chars);
+      } else {
+        SeqTwoByteString* str = SeqTwoByteString::cast(input);
+        str->SeqTwoByteStringReadBlockIntoBuffer(rbb,
+                                                 offset_ptr,
+                                                 max_chars);
+        return rbb->util_buffer;
+      }
+    case kConsStringTag:
+      return ConsString::cast(input)->ConsStringReadBlock(rbb,
+                                                          offset_ptr,
+                                                          max_chars);
+    case kSlicedStringTag:
+      return SlicedString::cast(input)->SlicedStringReadBlock(rbb,
+                                                              offset_ptr,
+                                                              max_chars);
+    case kExternalStringTag:
+      if (StringShape(input).IsAsciiRepresentation()) {
+        return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock(
+            &rbb->remaining,
+            offset_ptr,
+            max_chars);
+      } else {
+        ExternalTwoByteString::cast(input)->
+            ExternalTwoByteStringReadBlockIntoBuffer(rbb,
+                                                     offset_ptr,
+                                                     max_chars);
+        return rbb->util_buffer;
+      }
+    default:
+      break;
+  }
+
+  UNREACHABLE();
+  return 0;
+}
+
+
+FlatStringReader* FlatStringReader::top_ = NULL;
+
+
+FlatStringReader::FlatStringReader(Handle<String> str)
+    : str_(str.location()),
+      length_(str->length()),
+      prev_(top_) {
+  top_ = this;
+  RefreshState();
+}
+
+
+FlatStringReader::FlatStringReader(Vector<const char> input)
+    : str_(NULL),
+      is_ascii_(true),
+      length_(input.length()),
+      start_(input.start()),
+      prev_(top_) {
+  top_ = this;
+}
+
+
+FlatStringReader::~FlatStringReader() {
+  ASSERT_EQ(top_, this);
+  top_ = prev_;
+}
+
+
+void FlatStringReader::RefreshState() {
+  if (str_ == NULL) return;
+  Handle<String> str(str_);
+  ASSERT(str->IsFlat());
+  is_ascii_ = StringShape(*str).IsAsciiRepresentation();
+  if (is_ascii_) {
+    start_ = str->ToAsciiVector().start();
+  } else {
+    start_ = str->ToUC16Vector().start();
+  }
+}
+
+
+void FlatStringReader::PostGarbageCollectionProcessing() {
+  FlatStringReader* current = top_;
+  while (current != NULL) {
+    current->RefreshState();
+    current = current->prev_;
+  }
+}
+
+
+void StringInputBuffer::Seek(unsigned pos) {
+  Reset(pos, input_);
+}
+
+
+void SafeStringInputBuffer::Seek(unsigned pos) {
+  Reset(pos, input_);
+}
+
+
+// This method determines the type of string involved and then copies
+// a whole chunk of characters into a buffer.  It can be used with strings
+// that have been glued together to form a ConsString and which must cooperate
+// to fill up a buffer.
+void String::ReadBlockIntoBuffer(String* input,
+                                 ReadBlockBuffer* rbb,
+                                 unsigned* offset_ptr,
+                                 unsigned max_chars) {
+  ASSERT(*offset_ptr <= (unsigned)input->length());
+  if (max_chars == 0) return;
+
+  switch (StringShape(input).representation_tag()) {
+    case kSeqStringTag:
+      if (StringShape(input).IsAsciiRepresentation()) {
+        SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb,
+                                                                 offset_ptr,
+                                                                 max_chars);
+        return;
+      } else {
+        SeqTwoByteString::cast(input)->SeqTwoByteStringReadBlockIntoBuffer(rbb,
+                                                                     offset_ptr,
+                                                                     max_chars);
+        return;
+      }
+    case kConsStringTag:
+      ConsString::cast(input)->ConsStringReadBlockIntoBuffer(rbb,
+                                                             offset_ptr,
+                                                             max_chars);
+      return;
+    case kSlicedStringTag:
+      SlicedString::cast(input)->SlicedStringReadBlockIntoBuffer(rbb,
+                                                                 offset_ptr,
+                                                                 max_chars);
+      return;
+    case kExternalStringTag:
+      if (StringShape(input).IsAsciiRepresentation()) {
+         ExternalAsciiString::cast(input)->
+             ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
+       } else {
+         ExternalTwoByteString::cast(input)->
+             ExternalTwoByteStringReadBlockIntoBuffer(rbb,
+                                                      offset_ptr,
+                                                      max_chars);
+       }
+       return;
+    default:
+      break;
+  }
+
+  UNREACHABLE();
+  return;
+}
+
+
+const unibrow::byte* String::ReadBlock(String* input,
+                                       unibrow::byte* util_buffer,
+                                       unsigned capacity,
+                                       unsigned* remaining,
+                                       unsigned* offset_ptr) {
+  ASSERT(*offset_ptr <= (unsigned)input->length());
+  unsigned chars = input->length() - *offset_ptr;
+  ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
+  const unibrow::byte* answer = ReadBlock(input, &rbb, offset_ptr, chars);
+  ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
+  *remaining = rbb.remaining;
+  return answer;
+}
+
+
+const unibrow::byte* String::ReadBlock(String** raw_input,
+                                       unibrow::byte* util_buffer,
+                                       unsigned capacity,
+                                       unsigned* remaining,
+                                       unsigned* offset_ptr) {
+  Handle<String> input(raw_input);
+  ASSERT(*offset_ptr <= (unsigned)input->length());
+  unsigned chars = input->length() - *offset_ptr;
+  if (chars > capacity) chars = capacity;
+  ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
+  ReadBlockIntoBuffer(*input, &rbb, offset_ptr, chars);
+  ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
+  *remaining = rbb.remaining;
+  return rbb.util_buffer;
+}
+
+
+// This will iterate unless the block of string data spans two 'halves' of
+// a ConsString, in which case it will recurse.  Since the block of string
+// data to be read has a maximum size this limits the maximum recursion
+// depth to something sane.  Since C++ does not have tail call recursion
+// elimination, the iteration must be explicit.
+void ConsString::ConsStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
+                                               unsigned* offset_ptr,
+                                               unsigned max_chars) {
+  ConsString* current = this;
+  unsigned offset = *offset_ptr;
+  int offset_correction = 0;
+
+  while (true) {
+    String* left = current->first();
+    unsigned left_length = (unsigned)left->length();
+    if (left_length > offset &&
+      max_chars <= left_length - offset) {
+      // Left hand side only - iterate unless we have reached the bottom of
+      // the cons tree.
+      if (StringShape(left).IsCons()) {
+        current = ConsString::cast(left);
+        continue;
+      } else {
+        String::ReadBlockIntoBuffer(left, rbb, &offset, max_chars);
+        *offset_ptr = offset + offset_correction;
+        return;
+      }
+    } else if (left_length <= offset) {
+      // Right hand side only - iterate unless we have reached the bottom of
+      // the cons tree.
+      offset -= left_length;
+      offset_correction += left_length;
+      String* right = current->second();
+      if (StringShape(right).IsCons()) {
+        current = ConsString::cast(right);
+        continue;
+      } else {
+        String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
+        *offset_ptr = offset + offset_correction;
+        return;
+      }
+    } else {
+      // The block to be read spans two sides of the ConsString, so we recurse.
+      // First recurse on the left.
+      max_chars -= left_length - offset;
+      String::ReadBlockIntoBuffer(left, rbb, &offset, left_length - offset);
+      // We may have reached the max or there may not have been enough space
+      // in the buffer for the characters in the left hand side.
+      if (offset == left_length) {
+        // Recurse on the right.
+        String* right = String::cast(current->second());
+        offset -= left_length;
+        offset_correction += left_length;
+        String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
+      }
+      *offset_ptr = offset + offset_correction;
+      return;
+    }
+  }
+}
+
+
+void SlicedString::SlicedStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
+                                                   unsigned* offset_ptr,
+                                                   unsigned max_chars) {
+  String* backing = buffer();
+  unsigned offset = start() + *offset_ptr;
+  unsigned length = backing->length();
+  if (max_chars > length - offset) {
+    max_chars = length - offset;
+  }
+  String::ReadBlockIntoBuffer(backing, rbb, &offset, max_chars);
+  *offset_ptr = offset - start();
+}
+
+
+void ConsString::ConsStringIterateBody(ObjectVisitor* v) {
+  IteratePointers(v, kFirstOffset, kSecondOffset + kPointerSize);
+}
+
+
+uint16_t ConsString::ConsStringGet(int index) {
+  ASSERT(index >= 0 && index < this->length());
+
+  // Check for a flattened cons string
+  if (second()->length() == 0) {
+    String* left = first();
+    return left->Get(index);
+  }
+
+  String* string = String::cast(this);
+
+  while (true) {
+    if (StringShape(string).IsCons()) {
+      ConsString* cons_string = ConsString::cast(string);
+      String* left = cons_string->first();
+      if (left->length() > index) {
+        string = left;
+      } else {
+        index -= left->length();
+        string = cons_string->second();
+      }
+    } else {
+      return string->Get(index);
+    }
+  }
+
+  UNREACHABLE();
+  return 0;
+}
+
+
+template <typename sinkchar>
+void String::WriteToFlat(String* src,
+                         sinkchar* sink,
+                         int f,
+                         int t) {
+  String* source = src;
+  int from = f;
+  int to = t;
+  while (true) {
+    ASSERT(0 <= from && from <= to && to <= source->length());
+    switch (StringShape(source).full_representation_tag()) {
+      case kAsciiStringTag | kExternalStringTag: {
+        CopyChars(sink,
+                  ExternalAsciiString::cast(source)->resource()->data() + from,
+                  to - from);
+        return;
+      }
+      case kTwoByteStringTag | kExternalStringTag: {
+        const uc16* data =
+            ExternalTwoByteString::cast(source)->resource()->data();
+        CopyChars(sink,
+                  data + from,
+                  to - from);
+        return;
+      }
+      case kAsciiStringTag | kSeqStringTag: {
+        CopyChars(sink,
+                  SeqAsciiString::cast(source)->GetChars() + from,
+                  to - from);
+        return;
+      }
+      case kTwoByteStringTag | kSeqStringTag: {
+        CopyChars(sink,
+                  SeqTwoByteString::cast(source)->GetChars() + from,
+                  to - from);
+        return;
+      }
+      case kAsciiStringTag | kSlicedStringTag:
+      case kTwoByteStringTag | kSlicedStringTag: {
+        SlicedString* sliced_string = SlicedString::cast(source);
+        int start = sliced_string->start();
+        from += start;
+        to += start;
+        source = String::cast(sliced_string->buffer());
+        break;
+      }
+      case kAsciiStringTag | kConsStringTag:
+      case kTwoByteStringTag | kConsStringTag: {
+        ConsString* cons_string = ConsString::cast(source);
+        String* first = cons_string->first();
+        int boundary = first->length();
+        if (to - boundary >= boundary - from) {
+          // Right hand side is longer.  Recurse over left.
+          if (from < boundary) {
+            WriteToFlat(first, sink, from, boundary);
+            sink += boundary - from;
+            from = 0;
+          } else {
+            from -= boundary;
+          }
+          to -= boundary;
+          source = cons_string->second();
+        } else {
+          // Left hand side is longer.  Recurse over right.
+          if (to > boundary) {
+            String* second = cons_string->second();
+            WriteToFlat(second,
+                        sink + boundary - from,
+                        0,
+                        to - boundary);
+            to = boundary;
+          }
+          source = first;
+        }
+        break;
+      }
+    }
+  }
+}
+
+
+void SlicedString::SlicedStringIterateBody(ObjectVisitor* v) {
+  IteratePointer(v, kBufferOffset);
+}
+
+
+uint16_t SlicedString::SlicedStringGet(int index) {
+  ASSERT(index >= 0 && index < this->length());
+  // Delegate to the buffer string.
+  String* underlying = buffer();
+  return underlying->Get(start() + index);
+}
+
+
+template <typename IteratorA, typename IteratorB>
+static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) {
+  // General slow case check.  We know that the ia and ib iterators
+  // have the same length.
+  while (ia->has_more()) {
+    uc32 ca = ia->GetNext();
+    uc32 cb = ib->GetNext();
+    if (ca != cb)
+      return false;
+  }
+  return true;
+}
+
+
+// Compares the contents of two strings by reading and comparing
+// int-sized blocks of characters.
+template <typename Char>
+static inline bool CompareRawStringContents(Vector<Char> a, Vector<Char> b) {
+  int length = a.length();
+  ASSERT_EQ(length, b.length());
+  const Char* pa = a.start();
+  const Char* pb = b.start();
+  int i = 0;
+#ifndef CAN_READ_UNALIGNED
+  // If this architecture isn't comfortable reading unaligned ints
+  // then we have to check that the strings are aligned before
+  // comparing them blockwise.
+  const int kAlignmentMask = sizeof(uint32_t) - 1;  // NOLINT
+  uint32_t pa_addr = reinterpret_cast<uint32_t>(pa);
+  uint32_t pb_addr = reinterpret_cast<uint32_t>(pb);
+  if (((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask)) == 0) {
+#endif
+    const int kStepSize = sizeof(int) / sizeof(Char);  // NOLINT
+    int endpoint = length - kStepSize;
+    // Compare blocks until we reach near the end of the string.
+    for (; i <= endpoint; i += kStepSize) {
+      uint32_t wa = *reinterpret_cast<const uint32_t*>(pa + i);
+      uint32_t wb = *reinterpret_cast<const uint32_t*>(pb + i);
+      if (wa != wb) {
+        return false;
+      }
+    }
+#ifndef CAN_READ_UNALIGNED
+  }
+#endif
+  // Compare the remaining characters that didn't fit into a block.
+  for (; i < length; i++) {
+    if (a[i] != b[i]) {
+      return false;
+    }
+  }
+  return true;
+}
+
+
+// This is a workaround for Chromium bug 9746: http://crbug.com/9746
+// Returns true if this Vector matches the problem exposed in the bug.
+template <typename T>
+static bool CheckVectorForBug9746(Vector<T> vec) {
+  // The problem is that somehow external string entries in the symbol
+  // table can have their resources collected while they are still in the
+  // table. This should not happen according to the test in the function
+  // DisposeExternalString in api.cc, but we have evidence that it does.
+  return (vec.start() == NULL) ? true : false;
+}
+
+
+static StringInputBuffer string_compare_buffer_b;
+
+
+template <typename IteratorA>
+static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) {
+  if (b->IsFlat()) {
+    if (StringShape(b).IsAsciiRepresentation()) {
+      VectorIterator<char> ib(b->ToAsciiVector());
+      return CompareStringContents(ia, &ib);
+    } else {
+      Vector<const uc16> vb = b->ToUC16Vector();
+      if (CheckVectorForBug9746(vb)) return false;
+      VectorIterator<uc16> ib(vb);
+      return CompareStringContents(ia, &ib);
+    }
+  } else {
+    string_compare_buffer_b.Reset(0, b);
+    return CompareStringContents(ia, &string_compare_buffer_b);
+  }
+}
+
+
+static StringInputBuffer string_compare_buffer_a;
+
+
+bool String::SlowEquals(String* other) {
+  // Fast check: negative check with lengths.
+  int len = length();
+  if (len != other->length()) return false;
+  if (len == 0) return true;
+
+  // Fast check: if hash code is computed for both strings
+  // a fast negative check can be performed.
+  if (HasHashCode() && other->HasHashCode()) {
+    if (Hash() != other->Hash()) return false;
+  }
+
+  if (StringShape(this).IsSequentialAscii() &&
+      StringShape(other).IsSequentialAscii()) {
+    const char* str1 = SeqAsciiString::cast(this)->GetChars();
+    const char* str2 = SeqAsciiString::cast(other)->GetChars();
+    return CompareRawStringContents(Vector<const char>(str1, len),
+                                    Vector<const char>(str2, len));
+  }
+
+  if (this->IsFlat()) {
+    if (StringShape(this).IsAsciiRepresentation()) {
+      Vector<const char> vec1 = this->ToAsciiVector();
+      if (other->IsFlat()) {
+        if (StringShape(other).IsAsciiRepresentation()) {
+          Vector<const char> vec2 = other->ToAsciiVector();
+          return CompareRawStringContents(vec1, vec2);
+        } else {
+          VectorIterator<char> buf1(vec1);
+          Vector<const uc16> vec2 = other->ToUC16Vector();
+          if (CheckVectorForBug9746(vec2)) return false;
+          VectorIterator<uc16> ib(vec2);
+          return CompareStringContents(&buf1, &ib);
+        }
+      } else {
+        VectorIterator<char> buf1(vec1);
+        string_compare_buffer_b.Reset(0, other);
+        return CompareStringContents(&buf1, &string_compare_buffer_b);
+      }
+    } else {
+      Vector<const uc16> vec1 = this->ToUC16Vector();
+      if (CheckVectorForBug9746(vec1)) return false;
+      if (other->IsFlat()) {
+        if (StringShape(other).IsAsciiRepresentation()) {
+          VectorIterator<uc16> buf1(vec1);
+          VectorIterator<char> ib(other->ToAsciiVector());
+          return CompareStringContents(&buf1, &ib);
+        } else {
+          Vector<const uc16> vec2 = other->ToUC16Vector();
+          if (CheckVectorForBug9746(vec2)) return false;
+          return CompareRawStringContents(vec1, vec2);
+        }
+      } else {
+        VectorIterator<uc16> buf1(vec1);
+        string_compare_buffer_b.Reset(0, other);
+        return CompareStringContents(&buf1, &string_compare_buffer_b);
+      }
+    }
+  } else {
+    string_compare_buffer_a.Reset(0, this);
+    return CompareStringContentsPartial(&string_compare_buffer_a, other);
+  }
+}
+
+
+bool String::MarkAsUndetectable() {
+  if (StringShape(this).IsSymbol()) return false;
+
+  Map* map = this->map();
+  if (map == Heap::short_string_map()) {
+    this->set_map(Heap::undetectable_short_string_map());
+    return true;
+  } else if (map == Heap::medium_string_map()) {
+    this->set_map(Heap::undetectable_medium_string_map());
+    return true;
+  } else if (map == Heap::long_string_map()) {
+    this->set_map(Heap::undetectable_long_string_map());
+    return true;
+  } else if (map == Heap::short_ascii_string_map()) {
+    this->set_map(Heap::undetectable_short_ascii_string_map());
+    return true;
+  } else if (map == Heap::medium_ascii_string_map()) {
+    this->set_map(Heap::undetectable_medium_ascii_string_map());
+    return true;
+  } else if (map == Heap::long_ascii_string_map()) {
+    this->set_map(Heap::undetectable_long_ascii_string_map());
+    return true;
+  }
+  // Rest cannot be marked as undetectable
+  return false;
+}
+
+
+bool String::IsEqualTo(Vector<const char> str) {
+  // This is a workaround for Chromium bug 9746: http://crbug.com/9746
+  // The problem is that somehow external string entries in the symbol
+  // table can have their resources deleted while they are still in the
+  // table. This should not happen according to the test in the function
+  // DisposeExternalString in api.cc but we have evidence that it does.
+  // Thus we add this bailout here.
+  StringShape shape(this);
+  if (shape.IsExternalTwoByte()) {
+    ExternalTwoByteString* ext = ExternalTwoByteString::cast(this);
+    if (ext->resource() == NULL) return false;
+  }
+
+  int slen = length();
+  Access<Scanner::Utf8Decoder> decoder(Scanner::utf8_decoder());
+  decoder->Reset(str.start(), str.length());
+  int i;
+  for (i = 0; i < slen && decoder->has_more(); i++) {
+    uc32 r = decoder->GetNext();
+    if (Get(i) != r) return false;
+  }
+  return i == slen && !decoder->has_more();
+}
+
+
+uint32_t String::ComputeAndSetHash() {
+  // Should only be called if hash code has not yet been computed.
+  ASSERT(!(length_field() & kHashComputedMask));
+
+  // Compute the hash code.
+  StringInputBuffer buffer(this);
+  uint32_t field = ComputeLengthAndHashField(&buffer, length());
+
+  // Store the hash code in the object.
+  set_length_field(field);
+
+  // Check the hash code is there.
+  ASSERT(length_field() & kHashComputedMask);
+  uint32_t result = field >> kHashShift;
+  ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
+  return result;
+}
+
+
+bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer,
+                               uint32_t* index,
+                               int length) {
+  if (length == 0 || length > kMaxArrayIndexSize) return false;
+  uc32 ch = buffer->GetNext();
+
+  // If the string begins with a '0' character, it must only consist
+  // of it to be a legal array index.
+  if (ch == '0') {
+    *index = 0;
+    return length == 1;
+  }
+
+  // Convert string to uint32 array index; character by character.
+  int d = ch - '0';
+  if (d < 0 || d > 9) return false;
+  uint32_t result = d;
+  while (buffer->has_more()) {
+    d = buffer->GetNext() - '0';
+    if (d < 0 || d > 9) return false;
+    // Check that the new result is below the 32 bit limit.
+    if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
+    result = (result * 10) + d;
+  }
+
+  *index = result;
+  return true;
+}
+
+
+bool String::SlowAsArrayIndex(uint32_t* index) {
+  if (length() <= kMaxCachedArrayIndexLength) {
+    Hash();  // force computation of hash code
+    uint32_t field = length_field();
+    if ((field & kIsArrayIndexMask) == 0) return false;
+    *index = (field & ((1 << kShortLengthShift) - 1)) >> kLongLengthShift;
+    return true;
+  } else {
+    StringInputBuffer buffer(this);
+    return ComputeArrayIndex(&buffer, index, length());
+  }
+}
+
+
+static inline uint32_t HashField(uint32_t hash, bool is_array_index) {
+  uint32_t result =
+      (hash << String::kLongLengthShift) | String::kHashComputedMask;
+  if (is_array_index) result |= String::kIsArrayIndexMask;
+  return result;
+}
+
+
+uint32_t StringHasher::GetHashField() {
+  ASSERT(is_valid());
+  if (length_ <= String::kMaxShortStringSize) {
+    uint32_t payload;
+    if (is_array_index()) {
+      payload = v8::internal::HashField(array_index(), true);
+    } else {
+      payload = v8::internal::HashField(GetHash(), false);
+    }
+    return (payload & ((1 << String::kShortLengthShift) - 1)) |
+           (length_ << String::kShortLengthShift);
+  } else if (length_ <= String::kMaxMediumStringSize) {
+    uint32_t payload = v8::internal::HashField(GetHash(), false);
+    return (payload & ((1 << String::kMediumLengthShift) - 1)) |
+           (length_ << String::kMediumLengthShift);
+  } else {
+    return v8::internal::HashField(length_, false);
+  }
+}
+
+
+uint32_t String::ComputeLengthAndHashField(unibrow::CharacterStream* buffer,
+                                           int length) {
+  StringHasher hasher(length);
+
+  // Very long strings have a trivial hash that doesn't inspect the
+  // string contents.
+  if (hasher.has_trivial_hash()) {
+    return hasher.GetHashField();
+  }
+
+  // Do the iterative array index computation as long as there is a
+  // chance this is an array index.
+  while (buffer->has_more() && hasher.is_array_index()) {
+    hasher.AddCharacter(buffer->GetNext());
+  }
+
+  // Process the remaining characters without updating the array
+  // index.
+  while (buffer->has_more()) {
+    hasher.AddCharacterNoIndex(buffer->GetNext());
+  }
+
+  return hasher.GetHashField();
+}
+
+
+Object* String::Slice(int start, int end) {
+  if (start == 0 && end == length()) return this;
+  if (StringShape(this).representation_tag() == kSlicedStringTag) {
+    // Translate slices of a SlicedString into slices of the
+    // underlying string buffer.
+    SlicedString* str = SlicedString::cast(this);
+    String* buf = str->buffer();
+    return Heap::AllocateSlicedString(buf,
+                                      str->start() + start,
+                                      str->start() + end);
+  }
+  Object* result = Heap::AllocateSlicedString(this, start, end);
+  if (result->IsFailure()) {
+    return result;
+  }
+  // Due to the way we retry after GC on allocation failure we are not allowed
+  // to fail on allocation after this point.  This is the one-allocation rule.
+
+  // Try to flatten a cons string that is under the sliced string.
+  // This is to avoid memory leaks and possible stack overflows caused by
+  // building 'towers' of sliced strings on cons strings.
+  // This may fail due to an allocation failure (when a GC is needed), but it
+  // will succeed often enough to avoid the problem.  We only have to do this
+  // if Heap::AllocateSlicedString actually returned a SlicedString.  It will
+  // return flat strings for small slices for efficiency reasons.
+  String* answer = String::cast(result);
+  if (StringShape(answer).IsSliced() &&
+      StringShape(this).representation_tag() == kConsStringTag) {
+    TryFlatten();
+    // If the flatten succeeded we might as well make the sliced string point
+    // to the flat string rather than the cons string.
+    String* second = ConsString::cast(this)->second();
+    if (second->length() == 0) {
+      SlicedString::cast(answer)->set_buffer(ConsString::cast(this)->first());
+    }
+  }
+  return answer;
+}
+
+
+void String::PrintOn(FILE* file) {
+  int length = this->length();
+  for (int i = 0; i < length; i++) {
+    fprintf(file, "%c", Get(i));
+  }
+}
+
+
+void Map::CreateBackPointers() {
+  DescriptorArray* descriptors = instance_descriptors();
+  for (DescriptorReader r(descriptors); !r.eos(); r.advance()) {
+    if (r.type() == MAP_TRANSITION) {
+      // Get target.
+      Map* target = Map::cast(r.GetValue());
+#ifdef DEBUG
+      // Verify target.
+      Object* source_prototype = prototype();
+      Object* target_prototype = target->prototype();
+      ASSERT(source_prototype->IsJSObject() ||
+             source_prototype->IsMap() ||
+             source_prototype->IsNull());
+      ASSERT(target_prototype->IsJSObject() ||
+             target_prototype->IsNull());
+      ASSERT(source_prototype->IsMap() ||
+          source_prototype == target_prototype);
+#endif
+      // Point target back to source.  set_prototype() will not let us set
+      // the prototype to a map, as we do here.
+      *RawField(target, kPrototypeOffset) = this;
+    }
+  }
+}
+
+
+void Map::ClearNonLiveTransitions(Object* real_prototype) {
+  // Live DescriptorArray objects will be marked, so we must use
+  // low-level accessors to get and modify their data.
+  DescriptorArray* d = reinterpret_cast<DescriptorArray*>(
+      *RawField(this, Map::kInstanceDescriptorsOffset));
+  if (d == Heap::empty_descriptor_array()) return;
+  Smi* NullDescriptorDetails =
+    PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi();
+  FixedArray* contents = reinterpret_cast<FixedArray*>(
+      d->get(DescriptorArray::kContentArrayIndex));
+  ASSERT(contents->length() >= 2);
+  for (int i = 0; i < contents->length(); i += 2) {
+    // If the pair (value, details) is a map transition,
+    // check if the target is live.  If not, null the descriptor.
+    // Also drop the back pointer for that map transition, so that this
+    // map is not reached again by following a back pointer from a
+    // non-live object.
+    PropertyDetails details(Smi::cast(contents->get(i + 1)));
+    if (details.type() == MAP_TRANSITION) {
+      Map* target = reinterpret_cast<Map*>(contents->get(i));
+      ASSERT(target->IsHeapObject());
+      if (!target->IsMarked()) {
+        ASSERT(target->IsMap());
+        contents->set(i + 1, NullDescriptorDetails, SKIP_WRITE_BARRIER);
+        contents->set(i, Heap::null_value(), SKIP_WRITE_BARRIER);
+        ASSERT(target->prototype() == this ||
+               target->prototype() == real_prototype);
+        // Getter prototype() is read-only, set_prototype() has side effects.
+        *RawField(target, Map::kPrototypeOffset) = real_prototype;
+      }
+    }
+  }
+}
+
+
+void Map::MapIterateBody(ObjectVisitor* v) {
+  // Assumes all Object* members are contiguously allocated!
+  IteratePointers(v, kPrototypeOffset, kCodeCacheOffset + kPointerSize);
+}
+
+
+Object* JSFunction::SetInstancePrototype(Object* value) {
+  ASSERT(value->IsJSObject());
+
+  if (has_initial_map()) {
+    initial_map()->set_prototype(value);
+  } else {
+    // Put the value in the initial map field until an initial map is
+    // needed.  At that point, a new initial map is created and the
+    // prototype is put into the initial map where it belongs.
+    set_prototype_or_initial_map(value);
+  }
+  return value;
+}
+
+
+
+Object* JSFunction::SetPrototype(Object* value) {
+  Object* construct_prototype = value;
+
+  // If the value is not a JSObject, store the value in the map's
+  // constructor field so it can be accessed.  Also, set the prototype
+  // used for constructing objects to the original object prototype.
+  // See ECMA-262 13.2.2.
+  if (!value->IsJSObject()) {
+    // Copy the map so this does not affect unrelated functions.
+    // Remove map transitions because they point to maps with a
+    // different prototype.
+    Object* new_map = map()->CopyDropTransitions();
+    if (new_map->IsFailure()) return new_map;
+    set_map(Map::cast(new_map));
+    map()->set_constructor(value);
+    map()->set_non_instance_prototype(true);
+    construct_prototype =
+        Top::context()->global_context()->initial_object_prototype();
+  } else {
+    map()->set_non_instance_prototype(false);
+  }
+
+  return SetInstancePrototype(construct_prototype);
+}
+
+
+Object* JSFunction::SetInstanceClassName(String* name) {
+  shared()->set_instance_class_name(name);
+  return this;
+}
+
+
+Context* JSFunction::GlobalContextFromLiterals(FixedArray* literals) {
+  return Context::cast(literals->get(JSFunction::kLiteralGlobalContextIndex));
+}
+
+
+void Oddball::OddballIterateBody(ObjectVisitor* v) {
+  // Assumes all Object* members are contiguously allocated!
+  IteratePointers(v, kToStringOffset, kToNumberOffset + kPointerSize);
+}
+
+
+Object* Oddball::Initialize(const char* to_string, Object* to_number) {
+  Object* symbol = Heap::LookupAsciiSymbol(to_string);
+  if (symbol->IsFailure()) return symbol;
+  set_to_string(String::cast(symbol));
+  set_to_number(to_number);
+  return this;
+}
+
+
+bool SharedFunctionInfo::HasSourceCode() {
+  return !script()->IsUndefined() &&
+         !Script::cast(script())->source()->IsUndefined();
+}
+
+
+Object* SharedFunctionInfo::GetSourceCode() {
+  HandleScope scope;
+  if (script()->IsUndefined()) return Heap::undefined_value();
+  Object* source = Script::cast(script())->source();
+  if (source->IsUndefined()) return Heap::undefined_value();
+  return *SubString(Handle<String>(String::cast(source)),
+                    start_position(), end_position());
+}
+
+
+// Support function for printing the source code to a StringStream
+// without any allocation in the heap.
+void SharedFunctionInfo::SourceCodePrint(StringStream* accumulator,
+                                         int max_length) {
+  // For some native functions there is no source.
+  if (script()->IsUndefined() ||
+      Script::cast(script())->source()->IsUndefined()) {
+    accumulator->Add("<No Source>");
+    return;
+  }
+
+  // Get the slice of the source for this function.
+  // Don't use String::cast because we don't want more assertion errors while
+  // we are already creating a stack dump.
+  String* script_source =
+      reinterpret_cast<String*>(Script::cast(script())->source());
+
+  if (!script_source->LooksValid()) {
+    accumulator->Add("<Invalid Source>");
+    return;
+  }
+
+  if (!is_toplevel()) {
+    accumulator->Add("function ");
+    Object* name = this->name();
+    if (name->IsString() && String::cast(name)->length() > 0) {
+      accumulator->PrintName(name);
+    }
+  }
+
+  int len = end_position() - start_position();
+  if (len > max_length) {
+    accumulator->Put(script_source,
+                     start_position(),
+                     start_position() + max_length);
+    accumulator->Add("...\n");
+  } else {
+    accumulator->Put(script_source, start_position(), end_position());
+  }
+}
+
+
+void SharedFunctionInfo::SharedFunctionInfoIterateBody(ObjectVisitor* v) {
+  IteratePointers(v, kNameOffset, kCodeOffset + kPointerSize);
+  IteratePointers(v, kInstanceClassNameOffset, kScriptOffset + kPointerSize);
+  IteratePointers(v, kDebugInfoOffset, kInferredNameOffset + kPointerSize);
+}
+
+
+void ObjectVisitor::BeginCodeIteration(Code* code) {
+  ASSERT(code->ic_flag() == Code::IC_TARGET_IS_OBJECT);
+}
+
+
+void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
+  ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
+  VisitPointer(rinfo->target_object_address());
+}
+
+
+void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
+  ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()) && rinfo->IsCallInstruction());
+  VisitPointer(rinfo->call_object_address());
+}
+
+
+// Convert relocatable targets from address to code object address. This is
+// mainly IC call targets but for debugging straight-line code can be replaced
+// with a call instruction which also has to be relocated.
+void Code::ConvertICTargetsFromAddressToObject() {
+  ASSERT(ic_flag() == IC_TARGET_IS_ADDRESS);
+
+  for (RelocIterator it(this, RelocInfo::kCodeTargetMask);
+       !it.done(); it.next()) {
+    Address ic_addr = it.rinfo()->target_address();
+    ASSERT(ic_addr != NULL);
+    HeapObject* code = HeapObject::FromAddress(ic_addr - Code::kHeaderSize);
+    ASSERT(code->IsHeapObject());
+    it.rinfo()->set_target_object(code);
+  }
+
+  if (Debug::has_break_points()) {
+    for (RelocIterator it(this, RelocInfo::ModeMask(RelocInfo::JS_RETURN));
+         !it.done();
+         it.next()) {
+      if (it.rinfo()->IsCallInstruction()) {
+        Address addr = it.rinfo()->call_address();
+        ASSERT(addr != NULL);
+        HeapObject* code = HeapObject::FromAddress(addr - Code::kHeaderSize);
+        ASSERT(code->IsHeapObject());
+        it.rinfo()->set_call_object(code);
+      }
+    }
+  }
+  set_ic_flag(IC_TARGET_IS_OBJECT);
+}
+
+
+void Code::CodeIterateBody(ObjectVisitor* v) {
+  v->BeginCodeIteration(this);
+
+  int mode_mask = RelocInfo::kCodeTargetMask |
+                  RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
+                  RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
+                  RelocInfo::ModeMask(RelocInfo::JS_RETURN) |
+                  RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
+
+  for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
+    RelocInfo::Mode rmode = it.rinfo()->rmode();
+    if (rmode == RelocInfo::EMBEDDED_OBJECT) {
+      v->VisitPointer(it.rinfo()->target_object_address());
+    } else if (RelocInfo::IsCodeTarget(rmode)) {
+      v->VisitCodeTarget(it.rinfo());
+    } else if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
+      v->VisitExternalReference(it.rinfo()->target_reference_address());
+    } else if (Debug::has_break_points() &&
+               RelocInfo::IsJSReturn(rmode) &&
+               it.rinfo()->IsCallInstruction()) {
+      v->VisitDebugTarget(it.rinfo());
+    } else if (rmode == RelocInfo::RUNTIME_ENTRY) {
+      v->VisitRuntimeEntry(it.rinfo());
+    }
+  }
+
+  ScopeInfo<>::IterateScopeInfo(this, v);
+
+  v->EndCodeIteration(this);
+}
+
+
+void Code::ConvertICTargetsFromObjectToAddress() {
+  ASSERT(ic_flag() == IC_TARGET_IS_OBJECT);
+
+  for (RelocIterator it(this, RelocInfo::kCodeTargetMask);
+       !it.done(); it.next()) {
+    // We cannot use the safe cast (Code::cast) here, because we may be in
+    // the middle of relocating old objects during GC and the map pointer in
+    // the code object may be mangled
+    Code* code = reinterpret_cast<Code*>(it.rinfo()->target_object());
+    ASSERT((code != NULL) && code->IsHeapObject());
+    it.rinfo()->set_target_address(code->instruction_start());
+  }
+
+  if (Debug::has_break_points()) {
+    for (RelocIterator it(this, RelocInfo::ModeMask(RelocInfo::JS_RETURN));
+         !it.done();
+         it.next()) {
+      if (it.rinfo()->IsCallInstruction()) {
+        Code* code = reinterpret_cast<Code*>(it.rinfo()->call_object());
+        ASSERT((code != NULL) && code->IsHeapObject());
+        it.rinfo()->set_call_address(code->instruction_start());
+      }
+    }
+  }
+  set_ic_flag(IC_TARGET_IS_ADDRESS);
+}
+
+
+void Code::Relocate(int delta) {
+  for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
+    it.rinfo()->apply(delta);
+  }
+  CPU::FlushICache(instruction_start(), instruction_size());
+}
+
+
+void Code::CopyFrom(const CodeDesc& desc) {
+  // copy code
+  memmove(instruction_start(), desc.buffer, desc.instr_size);
+
+  // fill gap with zero bytes
+  { byte* p = instruction_start() + desc.instr_size;
+    byte* q = relocation_start();
+    while (p < q) {
+      *p++ = 0;
+    }
+  }
+
+  // copy reloc info
+  memmove(relocation_start(),
+          desc.buffer + desc.buffer_size - desc.reloc_size,
+          desc.reloc_size);
+
+  // unbox handles and relocate
+  int delta = instruction_start() - desc.buffer;
+  int mode_mask = RelocInfo::kCodeTargetMask |
+                  RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
+                  RelocInfo::kApplyMask;
+  for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
+    RelocInfo::Mode mode = it.rinfo()->rmode();
+    if (mode == RelocInfo::EMBEDDED_OBJECT) {
+      Object** p = reinterpret_cast<Object**>(it.rinfo()->target_object());
+      it.rinfo()->set_target_object(*p);
+    } else if (RelocInfo::IsCodeTarget(mode)) {
+      // rewrite code handles in inline cache targets to direct
+      // pointers to the first instruction in the code object
+      Object** p = reinterpret_cast<Object**>(it.rinfo()->target_object());
+      Code* code = Code::cast(*p);
+      it.rinfo()->set_target_address(code->instruction_start());
+    } else {
+      it.rinfo()->apply(delta);
+    }
+  }
+  CPU::FlushICache(instruction_start(), instruction_size());
+}
+
+
+// Locate the source position which is closest to the address in the code. This
+// is using the source position information embedded in the relocation info.
+// The position returned is relative to the beginning of the script where the
+// source for this function is found.
+int Code::SourcePosition(Address pc) {
+  int distance = kMaxInt;
+  int position = RelocInfo::kNoPosition;  // Initially no position found.
+  // Run through all the relocation info to find the best matching source
+  // position. All the code needs to be considered as the sequence of the
+  // instructions in the code does not necessarily follow the same order as the
+  // source.
+  RelocIterator it(this, RelocInfo::kPositionMask);
+  while (!it.done()) {
+    // Only look at positions after the current pc.
+    if (it.rinfo()->pc() < pc) {
+      // Get position and distance.
+      int dist = pc - it.rinfo()->pc();
+      int pos = it.rinfo()->data();
+      // If this position is closer than the current candidate or if it has the
+      // same distance as the current candidate and the position is higher then
+      // this position is the new candidate.
+      if ((dist < distance) ||
+          (dist == distance && pos > position)) {
+        position = pos;
+        distance = dist;
+      }
+    }
+    it.next();
+  }
+  return position;
+}
+
+
+// Same as Code::SourcePosition above except it only looks for statement
+// positions.
+int Code::SourceStatementPosition(Address pc) {
+  // First find the position as close as possible using all position
+  // information.
+  int position = SourcePosition(pc);
+  // Now find the closest statement position before the position.
+  int statement_position = 0;
+  RelocIterator it(this, RelocInfo::kPositionMask);
+  while (!it.done()) {
+    if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
+      int p = it.rinfo()->data();
+      if (statement_position < p && p <= position) {
+        statement_position = p;
+      }
+    }
+    it.next();
+  }
+  return statement_position;
+}
+
+
+#ifdef ENABLE_DISASSEMBLER
+// Identify kind of code.
+const char* Code::Kind2String(Kind kind) {
+  switch (kind) {
+    case FUNCTION: return "FUNCTION";
+    case STUB: return "STUB";
+    case BUILTIN: return "BUILTIN";
+    case LOAD_IC: return "LOAD_IC";
+    case KEYED_LOAD_IC: return "KEYED_LOAD_IC";
+    case STORE_IC: return "STORE_IC";
+    case KEYED_STORE_IC: return "KEYED_STORE_IC";
+    case CALL_IC: return "CALL_IC";
+  }
+  UNREACHABLE();
+  return NULL;
+}
+
+
+const char* Code::ICState2String(InlineCacheState state) {
+  switch (state) {
+    case UNINITIALIZED: return "UNINITIALIZED";
+    case UNINITIALIZED_IN_LOOP: return "UNINITIALIZED_IN_LOOP";
+    case PREMONOMORPHIC: return "PREMONOMORPHIC";
+    case MONOMORPHIC: return "MONOMORPHIC";
+    case MONOMORPHIC_PROTOTYPE_FAILURE: return "MONOMORPHIC_PROTOTYPE_FAILURE";
+    case MEGAMORPHIC: return "MEGAMORPHIC";
+    case DEBUG_BREAK: return "DEBUG_BREAK";
+    case DEBUG_PREPARE_STEP_IN: return "DEBUG_PREPARE_STEP_IN";
+  }
+  UNREACHABLE();
+  return NULL;
+}
+
+
+void Code::Disassemble(const char* name) {
+  PrintF("kind = %s\n", Kind2String(kind()));
+  if ((name != NULL) && (name[0] != '\0')) {
+    PrintF("name = %s\n", name);
+  }
+
+  PrintF("Instructions (size = %d)\n", instruction_size());
+  Disassembler::Decode(NULL, this);
+  PrintF("\n");
+
+  PrintF("RelocInfo (size = %d)\n", relocation_size());
+  for (RelocIterator it(this); !it.done(); it.next())
+    it.rinfo()->Print();
+  PrintF("\n");
+}
+#endif  // ENABLE_DISASSEMBLER
+
+
+void JSObject::SetFastElements(FixedArray* elems) {
+#ifdef DEBUG
+  // Check the provided array is filled with the_hole.
+  uint32_t len = static_cast<uint32_t>(elems->length());
+  for (uint32_t i = 0; i < len; i++) ASSERT(elems->get(i)->IsTheHole());
+#endif
+  WriteBarrierMode mode = elems->GetWriteBarrierMode();
+  if (HasFastElements()) {
+    FixedArray* old_elements = FixedArray::cast(elements());
+    uint32_t old_length = static_cast<uint32_t>(old_elements->length());
+    // Fill out the new array with this content and array holes.
+    for (uint32_t i = 0; i < old_length; i++) {
+      elems->set(i, old_elements->get(i), mode);
+    }
+  } else {
+    Dictionary* dictionary = Dictionary::cast(elements());
+    for (int i = 0; i < dictionary->Capacity(); i++) {
+      Object* key = dictionary->KeyAt(i);
+      if (key->IsNumber()) {
+        uint32_t entry = static_cast<uint32_t>(key->Number());
+        elems->set(entry, dictionary->ValueAt(i), mode);
+      }
+    }
+  }
+  set_elements(elems);
+}
+
+
+Object* JSObject::SetSlowElements(Object* len) {
+  uint32_t new_length = static_cast<uint32_t>(len->Number());
+
+  if (!HasFastElements()) {
+    if (IsJSArray()) {
+      uint32_t old_length =
+          static_cast<uint32_t>(JSArray::cast(this)->length()->Number());
+      element_dictionary()->RemoveNumberEntries(new_length, old_length),
+      JSArray::cast(this)->set_length(len);
+    }
+    return this;
+  }
+
+  // Make sure we never try to shrink dense arrays into sparse arrays.
+  ASSERT(static_cast<uint32_t>(FixedArray::cast(elements())->length()) <=
+                               new_length);
+  Object* obj = NormalizeElements();
+  if (obj->IsFailure()) return obj;
+
+  // Update length for JSArrays.
+  if (IsJSArray()) JSArray::cast(this)->set_length(len);
+  return this;
+}
+
+
+Object* JSArray::Initialize(int capacity) {
+  ASSERT(capacity >= 0);
+  set_length(Smi::FromInt(0), SKIP_WRITE_BARRIER);
+  FixedArray* new_elements;
+  if (capacity == 0) {
+    new_elements = Heap::empty_fixed_array();
+  } else {
+    Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
+    if (obj->IsFailure()) return obj;
+    new_elements = FixedArray::cast(obj);
+  }
+  set_elements(new_elements);
+  return this;
+}
+
+
+void JSArray::EnsureSize(int required_size) {
+  Handle<JSArray> self(this);
+  ASSERT(HasFastElements());
+  if (elements()->length() >= required_size) return;
+  Handle<FixedArray> old_backing(elements());
+  int old_size = old_backing->length();
+  // Doubling in size would be overkill, but leave some slack to avoid
+  // constantly growing.
+  int new_size = required_size + (required_size >> 3);
+  Handle<FixedArray> new_backing = Factory::NewFixedArray(new_size);
+  // Can't use this any more now because we may have had a GC!
+  for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i));
+  self->SetContent(*new_backing);
+}
+
+
+// Computes the new capacity when expanding the elements of a JSObject.
+static int NewElementsCapacity(int old_capacity) {
+  // (old_capacity + 50%) + 16
+  return old_capacity + (old_capacity >> 1) + 16;
+}
+
+
+static Object* ArrayLengthRangeError() {
+  HandleScope scope;
+  return Top::Throw(*Factory::NewRangeError("invalid_array_length",
+                                            HandleVector<Object>(NULL, 0)));
+}
+
+
+Object* JSObject::SetElementsLength(Object* len) {
+  Object* smi_length = len->ToSmi();
+  if (smi_length->IsSmi()) {
+    int value = Smi::cast(smi_length)->value();
+    if (value < 0) return ArrayLengthRangeError();
+    if (HasFastElements()) {
+      int old_capacity = FixedArray::cast(elements())->length();
+      if (value <= old_capacity) {
+        if (IsJSArray()) {
+          int old_length = FastD2I(JSArray::cast(this)->length()->Number());
+          // NOTE: We may be able to optimize this by removing the
+          // last part of the elements backing storage array and
+          // setting the capacity to the new size.
+          for (int i = value; i < old_length; i++) {
+            FixedArray::cast(elements())->set_the_hole(i);
+          }
+          JSArray::cast(this)->set_length(smi_length, SKIP_WRITE_BARRIER);
+        }
+        return this;
+      }
+      int min = NewElementsCapacity(old_capacity);
+      int new_capacity = value > min ? value : min;
+      if (new_capacity <= kMaxFastElementsLength ||
+          !ShouldConvertToSlowElements(new_capacity)) {
+        Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity);
+        if (obj->IsFailure()) return obj;
+        if (IsJSArray()) JSArray::cast(this)->set_length(smi_length,
+                                                         SKIP_WRITE_BARRIER);
+        SetFastElements(FixedArray::cast(obj));
+        return this;
+      }
+    } else {
+      if (IsJSArray()) {
+        if (value == 0) {
+          // If the length of a slow array is reset to zero, we clear
+          // the array and flush backing storage. This has the added
+          // benefit that the array returns to fast mode.
+          initialize_elements();
+        } else {
+          // Remove deleted elements.
+          uint32_t old_length =
+              static_cast<uint32_t>(JSArray::cast(this)->length()->Number());
+          element_dictionary()->RemoveNumberEntries(value, old_length);
+        }
+        JSArray::cast(this)->set_length(smi_length, SKIP_WRITE_BARRIER);
+      }
+      return this;
+    }
+  }
+
+  // General slow case.
+  if (len->IsNumber()) {
+    uint32_t length;
+    if (Array::IndexFromObject(len, &length)) {
+      return SetSlowElements(len);
+    } else {
+      return ArrayLengthRangeError();
+    }
+  }
+
+  // len is not a number so make the array size one and
+  // set only element to len.
+  Object* obj = Heap::AllocateFixedArray(1);
+  if (obj->IsFailure()) return obj;
+  FixedArray::cast(obj)->set(0, len);
+  if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1),
+                                                   SKIP_WRITE_BARRIER);
+  set_elements(FixedArray::cast(obj));
+  return this;
+}
+
+
+bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) {
+  if (HasFastElements()) {
+    uint32_t length = IsJSArray() ?
+        static_cast<uint32_t>(
+            Smi::cast(JSArray::cast(this)->length())->value()) :
+        static_cast<uint32_t>(FixedArray::cast(elements())->length());
+    if ((index < length) &&
+        !FixedArray::cast(elements())->get(index)->IsTheHole()) {
+      return true;
+    }
+  } else {
+    if (element_dictionary()->FindNumberEntry(index) != -1) return true;
+  }
+
+  // Handle [] on String objects.
+  if (this->IsStringObjectWithCharacterAt(index)) return true;
+
+  Object* pt = GetPrototype();
+  if (pt == Heap::null_value()) return false;
+  return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
+}
+
+
+bool JSObject::HasElementWithInterceptor(JSObject* receiver, uint32_t index) {
+  // Make sure that the top context does not change when doing
+  // callbacks or interceptor calls.
+  AssertNoContextChange ncc;
+  HandleScope scope;
+  Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
+  Handle<JSObject> receiver_handle(receiver);
+  Handle<JSObject> holder_handle(this);
+  Handle<Object> data_handle(interceptor->data());
+  v8::AccessorInfo info(v8::Utils::ToLocal(receiver_handle),
+                        v8::Utils::ToLocal(data_handle),
+                        v8::Utils::ToLocal(holder_handle));
+  if (!interceptor->query()->IsUndefined()) {
+    v8::IndexedPropertyQuery query =
+        v8::ToCData<v8::IndexedPropertyQuery>(interceptor->query());
+    LOG(ApiIndexedPropertyAccess("interceptor-indexed-has", this, index));
+    v8::Handle<v8::Boolean> result;
+    {
+      // Leaving JavaScript.
+      VMState state(EXTERNAL);
+      result = query(index, info);
+    }
+    if (!result.IsEmpty()) return result->IsTrue();
+  } else if (!interceptor->getter()->IsUndefined()) {
+    v8::IndexedPropertyGetter getter =
+        v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
+    LOG(ApiIndexedPropertyAccess("interceptor-indexed-has-get", this, index));
+    v8::Handle<v8::Value> result;
+    {
+      // Leaving JavaScript.
+      VMState state(EXTERNAL);
+      result = getter(index, info);
+    }
+    if (!result.IsEmpty()) return !result->IsUndefined();
+  }
+  return holder_handle->HasElementPostInterceptor(*receiver_handle, index);
+}
+
+
+bool JSObject::HasLocalElement(uint32_t index) {
+  // Check access rights if needed.
+  if (IsAccessCheckNeeded() &&
+      !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
+    Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
+    return false;
+  }
+
+  // Check for lookup interceptor
+  if (HasIndexedInterceptor()) {
+    return HasElementWithInterceptor(this, index);
+  }
+
+  // Handle [] on String objects.
+  if (this->IsStringObjectWithCharacterAt(index)) return true;
+
+  if (HasFastElements()) {
+    uint32_t length = IsJSArray() ?
+        static_cast<uint32_t>(
+            Smi::cast(JSArray::cast(this)->length())->value()) :
+        static_cast<uint32_t>(FixedArray::cast(elements())->length());
+    return (index < length) &&
+           !FixedArray::cast(elements())->get(index)->IsTheHole();
+  } else {
+    return element_dictionary()->FindNumberEntry(index) != -1;
+  }
+}
+
+
+Object* JSObject::GetHiddenProperties(bool create_if_needed) {
+  String* key = Heap::hidden_symbol();
+  if (this->HasFastProperties()) {
+    // If the object has fast properties, check whether the first slot
+    // in the descriptor array matches the hidden symbol. Since the
+    // hidden symbols hash code is zero (and no other string has hash
+    // code zero) it will always occupy the first entry if present.
+    DescriptorArray* descriptors = this->map()->instance_descriptors();
+    DescriptorReader r(descriptors);
+    if (!r.eos() && (r.GetKey() == key) && r.IsProperty()) {
+      ASSERT(r.type() == FIELD);
+      return FastPropertyAt(r.GetFieldIndex());
+    }
+  }
+
+  // Only attempt to find the hidden properties in the local object and not
+  // in the prototype chain.
+  if (!this->HasLocalProperty(key)) {
+    // Hidden properties object not found. Allocate a new hidden properties
+    // object if requested. Otherwise return the undefined value.
+    if (create_if_needed) {
+      Object* obj = Heap::AllocateJSObject(
+          Top::context()->global_context()->object_function());
+      if (obj->IsFailure()) {
+        return obj;
+      }
+      return this->SetProperty(key, obj, DONT_ENUM);
+    } else {
+      return Heap::undefined_value();
+    }
+  }
+  return this->GetProperty(key);
+}
+
+
+bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) {
+  // Check access rights if needed.
+  if (IsAccessCheckNeeded() &&
+      !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
+    Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
+    return false;
+  }
+
+  // Check for lookup interceptor
+  if (HasIndexedInterceptor()) {
+    return HasElementWithInterceptor(receiver, index);
+  }
+
+  if (HasFastElements()) {
+    uint32_t length = IsJSArray() ?
+        static_cast<uint32_t>(
+            Smi::cast(JSArray::cast(this)->length())->value()) :
+        static_cast<uint32_t>(FixedArray::cast(elements())->length());
+    if ((index < length) &&
+        !FixedArray::cast(elements())->get(index)->IsTheHole()) return true;
+  } else {
+    if (element_dictionary()->FindNumberEntry(index) != -1) return true;
+  }
+
+  // Handle [] on String objects.
+  if (this->IsStringObjectWithCharacterAt(index)) return true;
+
+  Object* pt = GetPrototype();
+  if (pt == Heap::null_value()) return false;
+  return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
+}
+
+
+Object* JSObject::SetElementPostInterceptor(uint32_t index, Object* value) {
+  if (HasFastElements()) return SetFastElement(index, value);
+
+  // Dictionary case.
+  ASSERT(!HasFastElements());
+
+  FixedArray* elms = FixedArray::cast(elements());
+  Object* result = Dictionary::cast(elms)->AtNumberPut(index, value);
+  if (result->IsFailure()) return result;
+  if (elms != FixedArray::cast(result)) {
+    set_elements(FixedArray::cast(result));
+  }
+
+  if (IsJSArray()) {
+    return JSArray::cast(this)->JSArrayUpdateLengthFromIndex(index, value);
+  }
+
+  return value;
+}
+
+
+Object* JSObject::SetElementWithInterceptor(uint32_t index, Object* value) {
+  // Make sure that the top context does not change when doing
+  // callbacks or interceptor calls.
+  AssertNoContextChange ncc;
+  HandleScope scope;
+  Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
+  Handle<JSObject> this_handle(this);
+  Handle<Object> value_handle(value);
+  if (!interceptor->setter()->IsUndefined()) {
+    v8::IndexedPropertySetter setter =
+        v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter());
+    Handle<Object> data_handle(interceptor->data());
+    LOG(ApiIndexedPropertyAccess("interceptor-indexed-set", this, index));
+    v8::AccessorInfo info(v8::Utils::ToLocal(this_handle),
+                          v8::Utils::ToLocal(data_handle),
+                          v8::Utils::ToLocal(this_handle));
+    v8::Handle<v8::Value> result;
+    {
+      // Leaving JavaScript.
+      VMState state(EXTERNAL);
+      result = setter(index, v8::Utils::ToLocal(value_handle), info);
+    }
+    RETURN_IF_SCHEDULED_EXCEPTION();
+    if (!result.IsEmpty()) return *value_handle;
+  }
+  Object* raw_result =
+      this_handle->SetElementPostInterceptor(index, *value_handle);
+  RETURN_IF_SCHEDULED_EXCEPTION();
+  return raw_result;
+}
+
+
+// Adding n elements in fast case is O(n*n).
+// Note: revisit design to have dual undefined values to capture absent
+// elements.
+Object* JSObject::SetFastElement(uint32_t index, Object* value) {
+  ASSERT(HasFastElements());
+
+  FixedArray* elms = FixedArray::cast(elements());
+  uint32_t elms_length = static_cast<uint32_t>(elms->length());
+
+  if (!IsJSArray() && (index >= elms_length || elms->get(index)->IsTheHole())) {
+    Object* setter = LookupCallbackSetterInPrototypes(index);
+    if (setter->IsJSFunction()) {
+      return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value);
+    }
+  }
+
+  // Check whether there is extra space in fixed array..
+  if (index < elms_length) {
+    elms->set(index, value);
+    if (IsJSArray()) {
+      // Update the length of the array if needed.
+      uint32_t array_length = 0;
+      CHECK(Array::IndexFromObject(JSArray::cast(this)->length(),
+                                   &array_length));
+      if (index >= array_length) {
+        JSArray::cast(this)->set_length(Smi::FromInt(index + 1),
+                                        SKIP_WRITE_BARRIER);
+      }
+    }
+    return value;
+  }
+
+  // Allow gap in fast case.
+  if ((index - elms_length) < kMaxGap) {
+    // Try allocating extra space.
+    int new_capacity = NewElementsCapacity(index+1);
+    if (new_capacity <= kMaxFastElementsLength ||
+        !ShouldConvertToSlowElements(new_capacity)) {
+      ASSERT(static_cast<uint32_t>(new_capacity) > index);
+      Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity);
+      if (obj->IsFailure()) return obj;
+      SetFastElements(FixedArray::cast(obj));
+      if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(index + 1),
+                                                       SKIP_WRITE_BARRIER);
+      FixedArray::cast(elements())->set(index, value);
+      return value;
+    }
+  }
+
+  // Otherwise default to slow case.
+  Object* obj = NormalizeElements();
+  if (obj->IsFailure()) return obj;
+  ASSERT(!HasFastElements());
+  return SetElement(index, value);
+}
+
+Object* JSObject::SetElement(uint32_t index, Object* value) {
+  // Check access rights if needed.
+  if (IsAccessCheckNeeded() &&
+      !Top::MayIndexedAccess(this, index, v8::ACCESS_SET)) {
+    Top::ReportFailedAccessCheck(this, v8::ACCESS_SET);
+    return value;
+  }
+
+  if (IsJSGlobalProxy()) {
+    Object* proto = GetPrototype();
+    if (proto->IsNull()) return value;
+    ASSERT(proto->IsJSGlobalObject());
+    return JSObject::cast(proto)->SetElement(index, value);
+  }
+
+  // Check for lookup interceptor
+  if (HasIndexedInterceptor()) {
+    return SetElementWithInterceptor(index, value);
+  }
+
+  // Fast case.
+  if (HasFastElements()) return SetFastElement(index, value);
+
+  // Dictionary case.
+  ASSERT(!HasFastElements());
+
+  // Insert element in the dictionary.
+  FixedArray* elms = FixedArray::cast(elements());
+  Dictionary* dictionary = Dictionary::cast(elms);
+
+  int entry = dictionary->FindNumberEntry(index);
+  if (entry != -1) {
+    Object* element = dictionary->ValueAt(entry);
+    PropertyDetails details = dictionary->DetailsAt(entry);
+    if (details.type() == CALLBACKS) {
+      // Only accessors allowed as elements.
+      FixedArray* structure = FixedArray::cast(element);
+      if (structure->get(kSetterIndex)->IsJSFunction()) {
+        JSFunction* setter = JSFunction::cast(structure->get(kSetterIndex));
+        return SetPropertyWithDefinedSetter(setter, value);
+      } else {
+        Handle<Object> self(this);
+        Handle<Object> key(Factory::NewNumberFromUint(index));
+        Handle<Object> args[2] = { key, self };
+        return Top::Throw(*Factory::NewTypeError("no_setter_in_callback",
+                                                 HandleVector(args, 2)));
+      }
+    } else {
+      dictionary->UpdateMaxNumberKey(index);
+      dictionary->ValueAtPut(entry, value);
+    }
+  } else {
+    // Index not already used. Look for an accessor in the prototype chain.
+    if (!IsJSArray()) {
+      Object* setter = LookupCallbackSetterInPrototypes(index);
+      if (setter->IsJSFunction()) {
+        return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value);
+      }
+    }
+    Object* result = dictionary->AtNumberPut(index, value);
+    if (result->IsFailure()) return result;
+    if (elms != FixedArray::cast(result)) {
+      set_elements(FixedArray::cast(result));
+    }
+  }
+
+  // Update the array length if this JSObject is an array.
+  if (IsJSArray()) {
+    JSArray* array = JSArray::cast(this);
+    Object* return_value = array->JSArrayUpdateLengthFromIndex(index, value);
+    if (return_value->IsFailure()) return return_value;
+  }
+
+  // Attempt to put this object back in fast case.
+  if (ShouldConvertToFastElements()) {
+    uint32_t new_length = 0;
+    if (IsJSArray()) {
+      CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), &new_length));
+      JSArray::cast(this)->set_length(Smi::FromInt(new_length));
+    } else {
+      new_length = Dictionary::cast(elements())->max_number_key() + 1;
+    }
+    Object* obj = Heap::AllocateFixedArrayWithHoles(new_length);
+    if (obj->IsFailure()) return obj;
+    SetFastElements(FixedArray::cast(obj));
+#ifdef DEBUG
+    if (FLAG_trace_normalization) {
+      PrintF("Object elements are fast case again:\n");
+      Print();
+    }
+#endif
+  }
+
+  return value;
+}
+
+
+Object* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, Object* value) {
+  uint32_t old_len = 0;
+  CHECK(Array::IndexFromObject(length(), &old_len));
+  // Check to see if we need to update the length. For now, we make
+  // sure that the length stays within 32-bits (unsigned).
+  if (index >= old_len && index != 0xffffffff) {
+    Object* len =
+        Heap::NumberFromDouble(static_cast<double>(index) + 1);
+    if (len->IsFailure()) return len;
+    set_length(len);
+  }
+  return value;
+}
+
+
+Object* JSObject::GetElementPostInterceptor(JSObject* receiver,
+                                            uint32_t index) {
+  // Get element works for both JSObject and JSArray since
+  // JSArray::length cannot change.
+  if (HasFastElements()) {
+    FixedArray* elms = FixedArray::cast(elements());
+    if (index < static_cast<uint32_t>(elms->length())) {
+      Object* value = elms->get(index);
+      if (!value->IsTheHole()) return value;
+    }
+  } else {
+    Dictionary* dictionary = element_dictionary();
+    int entry = dictionary->FindNumberEntry(index);
+    if (entry != -1) {
+      return dictionary->ValueAt(entry);
+    }
+  }
+
+  // Continue searching via the prototype chain.
+  Object* pt = GetPrototype();
+  if (pt == Heap::null_value()) return Heap::undefined_value();
+  return pt->GetElementWithReceiver(receiver, index);
+}
+
+
+Object* JSObject::GetElementWithInterceptor(JSObject* receiver,
+                                            uint32_t index) {
+  // Make sure that the top context does not change when doing
+  // callbacks or interceptor calls.
+  AssertNoContextChange ncc;
+  HandleScope scope;
+  Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
+  Handle<JSObject> this_handle(receiver);
+  Handle<JSObject> holder_handle(this);
+
+  if (!interceptor->getter()->IsUndefined()) {
+    Handle<Object> data_handle(interceptor->data());
+    v8::IndexedPropertyGetter getter =
+        v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
+    LOG(ApiIndexedPropertyAccess("interceptor-indexed-get", this, index));
+    v8::AccessorInfo info(v8::Utils::ToLocal(this_handle),
+                          v8::Utils::ToLocal(data_handle),
+                          v8::Utils::ToLocal(holder_handle));
+    v8::Handle<v8::Value> result;
+    {
+      // Leaving JavaScript.
+      VMState state(EXTERNAL);
+      result = getter(index, info);
+    }
+    RETURN_IF_SCHEDULED_EXCEPTION();
+    if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
+  }
+
+  Object* raw_result =
+      holder_handle->GetElementPostInterceptor(*this_handle, index);
+  RETURN_IF_SCHEDULED_EXCEPTION();
+  return raw_result;
+}
+
+
+Object* JSObject::GetElementWithReceiver(JSObject* receiver, uint32_t index) {
+  // Check access rights if needed.
+  if (IsAccessCheckNeeded() &&
+      !Top::MayIndexedAccess(this, index, v8::ACCESS_GET)) {
+    Top::ReportFailedAccessCheck(this, v8::ACCESS_GET);
+    return Heap::undefined_value();
+  }
+
+  if (HasIndexedInterceptor()) {
+    return GetElementWithInterceptor(receiver, index);
+  }
+
+  // Get element works for both JSObject and JSArray since
+  // JSArray::length cannot change.
+  if (HasFastElements()) {
+    FixedArray* elms = FixedArray::cast(elements());
+    if (index < static_cast<uint32_t>(elms->length())) {
+      Object* value = elms->get(index);
+      if (!value->IsTheHole()) return value;
+    }
+  } else {
+    Dictionary* dictionary = element_dictionary();
+    int entry = dictionary->FindNumberEntry(index);
+    if (entry != -1) {
+      Object* element = dictionary->ValueAt(entry);
+      PropertyDetails details = dictionary->DetailsAt(entry);
+      if (details.type() == CALLBACKS) {
+        // Only accessors allowed as elements.
+        FixedArray* structure = FixedArray::cast(element);
+        Object* getter = structure->get(kGetterIndex);
+        if (getter->IsJSFunction()) {
+          return GetPropertyWithDefinedGetter(receiver,
+                                              JSFunction::cast(getter));
+        } else {
+          // Getter is not a function.
+          return Heap::undefined_value();
+        }
+      }
+      return element;
+    }
+  }
+
+  Object* pt = GetPrototype();
+  if (pt == Heap::null_value()) return Heap::undefined_value();
+  return pt->GetElementWithReceiver(receiver, index);
+}
+
+
+bool JSObject::HasDenseElements() {
+  int capacity = 0;
+  int number_of_elements = 0;
+
+  if (HasFastElements()) {
+    FixedArray* elms = FixedArray::cast(elements());
+    capacity = elms->length();
+    for (int i = 0; i < capacity; i++) {
+      if (!elms->get(i)->IsTheHole()) number_of_elements++;
+    }
+  } else {
+    Dictionary* dictionary = Dictionary::cast(elements());
+    capacity = dictionary->Capacity();
+    number_of_elements = dictionary->NumberOfElements();
+  }
+
+  if (capacity == 0) return true;
+  return (number_of_elements > (capacity / 2));
+}
+
+
+bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
+  ASSERT(HasFastElements());
+  // Keep the array in fast case if the current backing storage is
+  // almost filled and if the new capacity is no more than twice the
+  // old capacity.
+  int elements_length = FixedArray::cast(elements())->length();
+  return !HasDenseElements() || ((new_capacity / 2) > elements_length);
+}
+
+
+bool JSObject::ShouldConvertToFastElements() {
+  ASSERT(!HasFastElements());
+  Dictionary* dictionary = Dictionary::cast(elements());
+  // If the elements are sparse, we should not go back to fast case.
+  if (!HasDenseElements()) return false;
+  // If an element has been added at a very high index in the elements
+  // dictionary, we cannot go back to fast case.
+  if (dictionary->requires_slow_elements()) return false;
+  // An object requiring access checks is never allowed to have fast
+  // elements.  If it had fast elements we would skip security checks.
+  if (IsAccessCheckNeeded()) return false;
+  // If the dictionary backing storage takes up roughly half as much
+  // space as a fast-case backing storage would the array should have
+  // fast elements.
+  uint32_t length = 0;
+  if (IsJSArray()) {
+    CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), &length));
+  } else {
+    length = dictionary->max_number_key();
+  }
+  return static_cast<uint32_t>(dictionary->Capacity()) >=
+      (length / (2 * Dictionary::kElementSize));
+}
+
+
+Object* Dictionary::RemoveHoles() {
+  int capacity = Capacity();
+  Object* obj = Allocate(NumberOfElements());
+  if (obj->IsFailure()) return obj;
+  Dictionary* dict = Dictionary::cast(obj);
+  uint32_t pos = 0;
+  for (int i = 0; i < capacity; i++) {
+    Object* k = KeyAt(i);
+    if (IsKey(k)) {
+      dict->AddNumberEntry(pos++, ValueAt(i), DetailsAt(i));
+    }
+  }
+  return dict;
+}
+
+
+void Dictionary::CopyValuesTo(FixedArray* elements) {
+  int pos = 0;
+  int capacity = Capacity();
+  for (int i = 0; i < capacity; i++) {
+    Object* k = KeyAt(i);
+    if (IsKey(k)) elements->set(pos++, ValueAt(i));
+  }
+  ASSERT(pos == elements->length());
+}
+
+
+Object* JSArray::RemoveHoles() {
+  if (HasFastElements()) {
+    int len = Smi::cast(length())->value();
+    int pos = 0;
+    FixedArray* elms = FixedArray::cast(elements());
+    for (int index = 0; index < len; index++) {
+      Object* e = elms->get(index);
+      if (!e->IsTheHole()) {
+        if (index != pos) elms->set(pos, e);
+        pos++;
+      }
+    }
+    set_length(Smi::FromInt(pos), SKIP_WRITE_BARRIER);
+    for (int index = pos; index < len; index++) {
+      elms->set_the_hole(index);
+    }
+    return this;
+  }
+
+  // Compact the sparse array if possible.
+  Dictionary* dict = element_dictionary();
+  int length = dict->NumberOfElements();
+
+  // Try to make this a fast array again.
+  if (length <= kMaxFastElementsLength) {
+    Object* obj = Heap::AllocateFixedArray(length);
+    if (obj->IsFailure()) return obj;
+    dict->CopyValuesTo(FixedArray::cast(obj));
+    set_length(Smi::FromInt(length), SKIP_WRITE_BARRIER);
+    set_elements(FixedArray::cast(obj));
+    return this;
+  }
+
+  // Make another dictionary with smaller indices.
+  Object* obj = dict->RemoveHoles();
+  if (obj->IsFailure()) return obj;
+  set_length(Smi::FromInt(length), SKIP_WRITE_BARRIER);
+  set_elements(Dictionary::cast(obj));
+  return this;
+}
+
+
+InterceptorInfo* JSObject::GetNamedInterceptor() {
+  ASSERT(map()->has_named_interceptor());
+  JSFunction* constructor = JSFunction::cast(map()->constructor());
+  Object* template_info = constructor->shared()->function_data();
+  Object* result =
+      FunctionTemplateInfo::cast(template_info)->named_property_handler();
+  return InterceptorInfo::cast(result);
+}
+
+
+InterceptorInfo* JSObject::GetIndexedInterceptor() {
+  ASSERT(map()->has_indexed_interceptor());
+  JSFunction* constructor = JSFunction::cast(map()->constructor());
+  Object* template_info = constructor->shared()->function_data();
+  Object* result =
+      FunctionTemplateInfo::cast(template_info)->indexed_property_handler();
+  return InterceptorInfo::cast(result);
+}
+
+
+Object* JSObject::GetPropertyPostInterceptor(JSObject* receiver,
+                                             String* name,
+                                             PropertyAttributes* attributes) {
+  // Check local property in holder, ignore interceptor.
+  LookupResult result;
+  LocalLookupRealNamedProperty(name, &result);
+  if (result.IsValid()) return GetProperty(receiver, &result, name, attributes);
+  // Continue searching via the prototype chain.
+  Object* pt = GetPrototype();
+  *attributes = ABSENT;
+  if (pt == Heap::null_value()) return Heap::undefined_value();
+  return pt->GetPropertyWithReceiver(receiver, name, attributes);
+}
+
+
+Object* JSObject::GetPropertyWithInterceptor(JSObject* receiver,
+                                             String* name,
+                                             PropertyAttributes* attributes) {
+  HandleScope scope;
+  Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
+  Handle<JSObject> receiver_handle(receiver);
+  Handle<JSObject> holder_handle(this);
+  Handle<String> name_handle(name);
+  Handle<Object> data_handle(interceptor->data());
+
+  if (!interceptor->getter()->IsUndefined()) {
+    v8::NamedPropertyGetter getter =
+        v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
+    LOG(ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name));
+    v8::AccessorInfo info(v8::Utils::ToLocal(receiver_handle),
+                          v8::Utils::ToLocal(data_handle),
+                          v8::Utils::ToLocal(holder_handle));
+    v8::Handle<v8::Value> result;
+    {
+      // Leaving JavaScript.
+      VMState state(EXTERNAL);
+      result = getter(v8::Utils::ToLocal(name_handle), info);
+    }
+    RETURN_IF_SCHEDULED_EXCEPTION();
+    if (!result.IsEmpty()) {
+      *attributes = NONE;
+      return *v8::Utils::OpenHandle(*result);
+    }
+  }
+
+  Object* raw_result = holder_handle->GetPropertyPostInterceptor(
+      *receiver_handle,
+      *name_handle,
+      attributes);
+  RETURN_IF_SCHEDULED_EXCEPTION();
+  return raw_result;
+}
+
+
+bool JSObject::HasRealNamedProperty(String* key) {
+  // Check access rights if needed.
+  if (IsAccessCheckNeeded() &&
+      !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) {
+    Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
+    return false;
+  }
+
+  LookupResult result;
+  LocalLookupRealNamedProperty(key, &result);
+  if (result.IsValid()) {
+    switch (result.type()) {
+      case NORMAL:    // fall through.
+      case FIELD:     // fall through.
+      case CALLBACKS:  // fall through.
+      case CONSTANT_FUNCTION:
+        return true;
+      case INTERCEPTOR:
+      case MAP_TRANSITION:
+      case CONSTANT_TRANSITION:
+      case NULL_DESCRIPTOR:
+        return false;
+      default:
+        UNREACHABLE();
+    }
+  }
+
+  return false;
+}
+
+
+bool JSObject::HasRealElementProperty(uint32_t index) {
+  // Check access rights if needed.
+  if (IsAccessCheckNeeded() &&
+      !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
+    Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
+    return false;
+  }
+
+  // Handle [] on String objects.
+  if (this->IsStringObjectWithCharacterAt(index)) return true;
+
+  if (HasFastElements()) {
+    uint32_t length = IsJSArray() ?
+        static_cast<uint32_t>(
+            Smi::cast(JSArray::cast(this)->length())->value()) :
+        static_cast<uint32_t>(FixedArray::cast(elements())->length());
+    return (index < length) &&
+        !FixedArray::cast(elements())->get(index)->IsTheHole();
+  }
+  return element_dictionary()->FindNumberEntry(index) != -1;
+}
+
+
+bool JSObject::HasRealNamedCallbackProperty(String* key) {
+  // Check access rights if needed.
+  if (IsAccessCheckNeeded() &&
+      !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) {
+    Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
+    return false;
+  }
+
+  LookupResult result;
+  LocalLookupRealNamedProperty(key, &result);
+  return result.IsValid() && (result.type() == CALLBACKS);
+}
+
+
+int JSObject::NumberOfLocalProperties(PropertyAttributes filter) {
+  if (HasFastProperties()) {
+    int result = 0;
+    for (DescriptorReader r(map()->instance_descriptors());
+         !r.eos();
+         r.advance()) {
+      PropertyDetails details = r.GetDetails();
+      if (details.IsProperty() &&
+          (details.attributes() & filter) == 0) {
+        result++;
+      }
+    }
+    return result;
+  } else {
+    return property_dictionary()->NumberOfElementsFilterAttributes(filter);
+  }
+}
+
+
+int JSObject::NumberOfEnumProperties() {
+  return NumberOfLocalProperties(static_cast<PropertyAttributes>(DONT_ENUM));
+}
+
+
+void FixedArray::Swap(int i, int j) {
+  Object* temp = get(i);
+  set(i, get(j));
+  set(j, temp);
+}
+
+
+static void InsertionSortPairs(FixedArray* content, FixedArray* smis) {
+  int len = smis->length();
+  for (int i = 1; i < len; i++) {
+    int j = i;
+    while (j > 0 &&
+           Smi::cast(smis->get(j-1))->value() >
+               Smi::cast(smis->get(j))->value()) {
+      smis->Swap(j-1, j);
+      content->Swap(j-1, j);
+      j--;
+    }
+  }
+}
+
+
+void HeapSortPairs(FixedArray* content, FixedArray* smis) {
+  // In-place heap sort.
+  ASSERT(content->length() == smis->length());
+  int len = smis->length();
+
+  // Bottom-up max-heap construction.
+  for (int i = 1; i < len; ++i) {
+    int child_index = i;
+    while (child_index > 0) {
+      int parent_index = ((child_index + 1) >> 1) - 1;
+      int parent_value = Smi::cast(smis->get(parent_index))->value();
+      int child_value = Smi::cast(smis->get(child_index))->value();
+      if (parent_value < child_value) {
+        content->Swap(parent_index, child_index);
+        smis->Swap(parent_index, child_index);
+      } else {
+        break;
+      }
+      child_index = parent_index;
+    }
+  }
+
+  // Extract elements and create sorted array.
+  for (int i = len - 1; i > 0; --i) {
+    // Put max element at the back of the array.
+    content->Swap(0, i);
+    smis->Swap(0, i);
+    // Sift down the new top element.
+    int parent_index = 0;
+    while (true) {
+      int child_index = ((parent_index + 1) << 1) - 1;
+      if (child_index >= i) break;
+      uint32_t child1_value = Smi::cast(smis->get(child_index))->value();
+      uint32_t child2_value = Smi::cast(smis->get(child_index + 1))->value();
+      uint32_t parent_value = Smi::cast(smis->get(parent_index))->value();
+      if (child_index + 1 >= i || child1_value > child2_value) {
+        if (parent_value > child1_value) break;
+        content->Swap(parent_index, child_index);
+        smis->Swap(parent_index, child_index);
+        parent_index = child_index;
+      } else {
+        if (parent_value > child2_value) break;
+        content->Swap(parent_index, child_index + 1);
+        smis->Swap(parent_index, child_index + 1);
+        parent_index = child_index + 1;
+      }
+    }
+  }
+}
+
+
+// Sort this array and the smis as pairs wrt. the (distinct) smis.
+void FixedArray::SortPairs(FixedArray* smis) {
+  ASSERT(this->length() == smis->length());
+  int len = smis->length();
+  // For small arrays, simply use insertion sort.
+  if (len <= 10) {
+    InsertionSortPairs(this, smis);
+    return;
+  }
+  // Check the range of indices.
+  int min_index = Smi::cast(smis->get(0))->value();
+  int max_index = min_index;
+  int i;
+  for (i = 1; i < len; i++) {
+    if (Smi::cast(smis->get(i))->value() < min_index) {
+      min_index = Smi::cast(smis->get(i))->value();
+    } else if (Smi::cast(smis->get(i))->value() > max_index) {
+      max_index = Smi::cast(smis->get(i))->value();
+    }
+  }
+  if (max_index - min_index + 1 == len) {
+    // Indices form a contiguous range, unless there are duplicates.
+    // Do an in-place linear time sort assuming distinct smis, but
+    // avoid hanging in case they are not.
+    for (i = 0; i < len; i++) {
+      int p;
+      int j = 0;
+      // While the current element at i is not at its correct position p,
+      // swap the elements at these two positions.
+      while ((p = Smi::cast(smis->get(i))->value() - min_index) != i &&
+             j++ < len) {
+        this->Swap(i, p);
+        smis->Swap(i, p);
+      }
+    }
+  } else {
+    HeapSortPairs(this, smis);
+    return;
+  }
+}
+
+
+// Fill in the names of local properties into the supplied storage. The main
+// purpose of this function is to provide reflection information for the object
+// mirrors.
+void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) {
+  ASSERT(storage->length() >=
+         NumberOfLocalProperties(static_cast<PropertyAttributes>(NONE)) -
+             index);
+  if (HasFastProperties()) {
+    for (DescriptorReader r(map()->instance_descriptors());
+         !r.eos();
+         r.advance()) {
+      if (r.IsProperty()) {
+        storage->set(index++, r.GetKey());
+      }
+    }
+    ASSERT(storage->length() >= index);
+  } else {
+    property_dictionary()->CopyKeysTo(storage);
+  }
+}
+
+
+int JSObject::NumberOfLocalElements(PropertyAttributes filter) {
+  return GetLocalElementKeys(NULL, filter);
+}
+
+
+int JSObject::NumberOfEnumElements() {
+  return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM));
+}
+
+
+int JSObject::GetLocalElementKeys(FixedArray* storage,
+                                  PropertyAttributes filter) {
+  int counter = 0;
+  if (HasFastElements()) {
+    int length = IsJSArray()
+        ? Smi::cast(JSArray::cast(this)->length())->value()
+        : FixedArray::cast(elements())->length();
+    for (int i = 0; i < length; i++) {
+      if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
+        if (storage) {
+          storage->set(counter, Smi::FromInt(i), SKIP_WRITE_BARRIER);
+        }
+        counter++;
+      }
+    }
+    ASSERT(!storage || storage->length() >= counter);
+  } else {
+    if (storage) {
+      element_dictionary()->CopyKeysTo(storage, filter);
+    }
+    counter = element_dictionary()->NumberOfElementsFilterAttributes(filter);
+  }
+
+  if (this->IsJSValue()) {
+    Object* val = JSValue::cast(this)->value();
+    if (val->IsString()) {
+      String* str = String::cast(val);
+      if (storage) {
+        for (int i = 0; i < str->length(); i++) {
+          storage->set(counter + i, Smi::FromInt(i), SKIP_WRITE_BARRIER);
+        }
+      }
+      counter += str->length();
+    }
+  }
+  ASSERT(!storage || storage->length() == counter);
+  return counter;
+}
+
+
+int JSObject::GetEnumElementKeys(FixedArray* storage) {
+  return GetLocalElementKeys(storage,
+                             static_cast<PropertyAttributes>(DONT_ENUM));
+}
+
+
+// Thomas Wang, Integer Hash Functions.
+// http://www.concentric.net/~Ttwang/tech/inthash.htm
+static uint32_t ComputeIntegerHash(uint32_t key) {
+  uint32_t hash = key;
+  hash = ~hash + (hash << 15);  // hash = (hash << 15) - hash - 1;
+  hash = hash ^ (hash >> 12);
+  hash = hash + (hash << 2);
+  hash = hash ^ (hash >> 4);
+  hash = hash * 2057;  // hash = (hash + (hash << 3)) + (hash << 11);
+  hash = hash ^ (hash >> 16);
+  return hash;
+}
+
+
+// The NumberKey uses carries the uint32_t as key.
+// This avoids allocation in HasProperty.
+class NumberKey : public HashTableKey {
+ public:
+  explicit NumberKey(uint32_t number) : number_(number) { }
+
+  bool IsMatch(Object* number) {
+    return number_ == ToUint32(number);
+  }
+
+  uint32_t Hash() { return ComputeIntegerHash(number_); }
+
+  HashFunction GetHashFunction() { return NumberHash; }
+
+  Object* GetObject() {
+    return Heap::NumberFromDouble(number_);
+  }
+
+  bool IsStringKey() { return false; }
+
+ private:
+  static uint32_t NumberHash(Object* obj) {
+    return ComputeIntegerHash(ToUint32(obj));
+  }
+
+  static uint32_t ToUint32(Object* obj) {
+    ASSERT(obj->IsNumber());
+    return static_cast<uint32_t>(obj->Number());
+  }
+
+  uint32_t number_;
+};
+
+
+// StringKey simply carries a string object as key.
+class StringKey : public HashTableKey {
+ public:
+  explicit StringKey(String* string) :
+      string_(string),
+      hash_(StringHash(string)) { }
+
+  bool IsMatch(Object* string) {
+    // We know that all entries in a hash table had their hash keys created.
+    // Use that knowledge to have fast failure.
+    if (hash_ != StringHash(string)) {
+      return false;
+    }
+    return string_->Equals(String::cast(string));
+  }
+
+  uint32_t Hash() { return hash_; }
+
+  HashFunction GetHashFunction() { return StringHash; }
+
+  Object* GetObject() { return string_; }
+
+  static uint32_t StringHash(Object* obj) {
+    return String::cast(obj)->Hash();
+  }
+
+  bool IsStringKey() { return true; }
+
+  String* string_;
+  uint32_t hash_;
+};
+
+
+// StringSharedKeys are used as keys in the eval cache.
+class StringSharedKey : public HashTableKey {
+ public:
+  StringSharedKey(String* source, SharedFunctionInfo* shared)
+      : source_(source), shared_(shared) { }
+
+  bool IsMatch(Object* other) {
+    if (!other->IsFixedArray()) return false;
+    FixedArray* pair = FixedArray::cast(other);
+    SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0));
+    if (shared != shared_) return false;
+    String* source = String::cast(pair->get(1));
+    return source->Equals(source_);
+  }
+
+  typedef uint32_t (*HashFunction)(Object* obj);
+
+  virtual HashFunction GetHashFunction() { return StringSharedHash; }
+
+  static uint32_t StringSharedHashHelper(String* source,
+                                         SharedFunctionInfo* shared) {
+    uint32_t hash = source->Hash();
+    if (shared->HasSourceCode()) {
+      // Instead of using the SharedFunctionInfo pointer in the hash
+      // code computation, we use a combination of the hash of the
+      // script source code and the start and end positions.  We do
+      // this to ensure that the cache entries can survive garbage
+      // collection.
+      Script* script = Script::cast(shared->script());
+      hash ^= String::cast(script->source())->Hash();
+      hash += shared->start_position();
+    }
+    return hash;
+  }
+
+  static uint32_t StringSharedHash(Object* obj) {
+    FixedArray* pair = FixedArray::cast(obj);
+    SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0));
+    String* source = String::cast(pair->get(1));
+    return StringSharedHashHelper(source, shared);
+  }
+
+  virtual uint32_t Hash() {
+    return StringSharedHashHelper(source_, shared_);
+  }
+
+  virtual Object* GetObject() {
+    Object* obj = Heap::AllocateFixedArray(2);
+    if (obj->IsFailure()) return obj;
+    FixedArray* pair = FixedArray::cast(obj);
+    pair->set(0, shared_);
+    pair->set(1, source_);
+    return pair;
+  }
+
+  virtual bool IsStringKey() { return false; }
+
+ private:
+  String* source_;
+  SharedFunctionInfo* shared_;
+};
+
+
+// RegExpKey carries the source and flags of a regular expression as key.
+class RegExpKey : public HashTableKey {
+ public:
+  RegExpKey(String* string, JSRegExp::Flags flags)
+      : string_(string),
+        flags_(Smi::FromInt(flags.value())) { }
+
+  bool IsMatch(Object* obj) {
+    FixedArray* val = FixedArray::cast(obj);
+    return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
+        && (flags_ == val->get(JSRegExp::kFlagsIndex));
+  }
+
+  uint32_t Hash() { return RegExpHash(string_, flags_); }
+
+  HashFunction GetHashFunction() { return RegExpObjectHash; }
+
+  Object* GetObject() {
+    // Plain hash maps, which is where regexp keys are used, don't
+    // use this function.
+    UNREACHABLE();
+    return NULL;
+  }
+
+  static uint32_t RegExpObjectHash(Object* obj) {
+    FixedArray* val = FixedArray::cast(obj);
+    return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
+                      Smi::cast(val->get(JSRegExp::kFlagsIndex)));
+  }
+
+  static uint32_t RegExpHash(String* string, Smi* flags) {
+    return string->Hash() + flags->value();
+  }
+
+  bool IsStringKey() { return false; }
+
+  String* string_;
+  Smi* flags_;
+};
+
+// Utf8SymbolKey carries a vector of chars as key.
+class Utf8SymbolKey : public HashTableKey {
+ public:
+  explicit Utf8SymbolKey(Vector<const char> string)
+      : string_(string), length_field_(0) { }
+
+  bool IsMatch(Object* string) {
+    return String::cast(string)->IsEqualTo(string_);
+  }
+
+  HashFunction GetHashFunction() {
+    return StringHash;
+  }
+
+  uint32_t Hash() {
+    if (length_field_ != 0) return length_field_ >> String::kHashShift;
+    unibrow::Utf8InputBuffer<> buffer(string_.start(),
+                                      static_cast<unsigned>(string_.length()));
+    chars_ = buffer.Length();
+    length_field_ = String::ComputeLengthAndHashField(&buffer, chars_);
+    uint32_t result = length_field_ >> String::kHashShift;
+    ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
+    return result;
+  }
+
+  Object* GetObject() {
+    if (length_field_ == 0) Hash();
+    return Heap::AllocateSymbol(string_, chars_, length_field_);
+  }
+
+  static uint32_t StringHash(Object* obj) {
+    return String::cast(obj)->Hash();
+  }
+
+  bool IsStringKey() { return true; }
+
+  Vector<const char> string_;
+  uint32_t length_field_;
+  int chars_;  // Caches the number of characters when computing the hash code.
+};
+
+
+// SymbolKey carries a string/symbol object as key.
+class SymbolKey : public HashTableKey {
+ public:
+  explicit SymbolKey(String* string) : string_(string) { }
+
+  HashFunction GetHashFunction() {
+    return StringHash;
+  }
+
+  bool IsMatch(Object* string) {
+    return String::cast(string)->Equals(string_);
+  }
+
+  uint32_t Hash() { return string_->Hash(); }
+
+  Object* GetObject() {
+    // If the string is a cons string, attempt to flatten it so that
+    // symbols will most often be flat strings.
+    if (StringShape(string_).IsCons()) {
+      ConsString* cons_string = ConsString::cast(string_);
+      cons_string->TryFlatten();
+      if (cons_string->second()->length() == 0) {
+        string_ = cons_string->first();
+      }
+    }
+    // Transform string to symbol if possible.
+    Map* map = Heap::SymbolMapForString(string_);
+    if (map != NULL) {
+      string_->set_map(map);
+      ASSERT(string_->IsSymbol());
+      return string_;
+    }
+    // Otherwise allocate a new symbol.
+    StringInputBuffer buffer(string_);
+    return Heap::AllocateInternalSymbol(&buffer,
+                                        string_->length(),
+                                        string_->length_field());
+  }
+
+  static uint32_t StringHash(Object* obj) {
+    return String::cast(obj)->Hash();
+  }
+
+  bool IsStringKey() { return true; }
+
+  String* string_;
+};
+
+
+template<int prefix_size, int element_size>
+void HashTable<prefix_size, element_size>::IteratePrefix(ObjectVisitor* v) {
+  IteratePointers(v, 0, kElementsStartOffset);
+}
+
+
+template<int prefix_size, int element_size>
+void HashTable<prefix_size, element_size>::IterateElements(ObjectVisitor* v) {
+  IteratePointers(v,
+                  kElementsStartOffset,
+                  kHeaderSize + length() * kPointerSize);
+}
+
+
+template<int prefix_size, int element_size>
+Object* HashTable<prefix_size, element_size>::Allocate(int at_least_space_for) {
+  int capacity = RoundUpToPowerOf2(at_least_space_for);
+  if (capacity < 4) capacity = 4;  // Guarantee min capacity.
+  Object* obj = Heap::AllocateHashTable(EntryToIndex(capacity));
+  if (!obj->IsFailure()) {
+    HashTable::cast(obj)->SetNumberOfElements(0);
+    HashTable::cast(obj)->SetCapacity(capacity);
+  }
+  return obj;
+}
+
+
+// Find entry for key otherwise return -1.
+template <int prefix_size, int element_size>
+int HashTable<prefix_size, element_size>::FindEntry(HashTableKey* key) {
+  uint32_t nof = NumberOfElements();
+  if (nof == 0) return -1;  // Bail out if empty.
+
+  uint32_t capacity = Capacity();
+  uint32_t hash = key->Hash();
+  uint32_t entry = GetProbe(hash, 0, capacity);
+
+  Object* element = KeyAt(entry);
+  uint32_t passed_elements = 0;
+  if (!element->IsNull()) {
+    if (!element->IsUndefined() && key->IsMatch(element)) return entry;
+    if (++passed_elements == nof) return -1;
+  }
+  for (uint32_t i = 1; !element->IsUndefined(); i++) {
+    entry = GetProbe(hash, i, capacity);
+    element = KeyAt(entry);
+    if (!element->IsNull()) {
+      if (!element->IsUndefined() && key->IsMatch(element)) return entry;
+      if (++passed_elements == nof) return -1;
+    }
+  }
+  return -1;
+}
+
+
+template<int prefix_size, int element_size>
+Object* HashTable<prefix_size, element_size>::EnsureCapacity(
+    int n, HashTableKey* key) {
+  int capacity = Capacity();
+  int nof = NumberOfElements() + n;
+  // Make sure 25% is free
+  if (nof + (nof >> 2) <= capacity) return this;
+
+  Object* obj = Allocate(nof * 2);
+  if (obj->IsFailure()) return obj;
+  HashTable* table = HashTable::cast(obj);
+  WriteBarrierMode mode = table->GetWriteBarrierMode();
+
+  // Copy prefix to new array.
+  for (int i = kPrefixStartIndex; i < kPrefixStartIndex + prefix_size; i++) {
+    table->set(i, get(i), mode);
+  }
+  // Rehash the elements.
+  uint32_t (*Hash)(Object* key) = key->GetHashFunction();
+  for (int i = 0; i < capacity; i++) {
+    uint32_t from_index = EntryToIndex(i);
+    Object* key = get(from_index);
+    if (IsKey(key)) {
+      uint32_t insertion_index =
+          EntryToIndex(table->FindInsertionEntry(key, Hash(key)));
+      for (int j = 0; j < element_size; j++) {
+        table->set(insertion_index + j, get(from_index + j), mode);
+      }
+    }
+  }
+  table->SetNumberOfElements(NumberOfElements());
+  return table;
+}
+
+
+template<int prefix_size, int element_size>
+uint32_t HashTable<prefix_size, element_size>::FindInsertionEntry(
+      Object* key,
+      uint32_t hash) {
+  uint32_t capacity = Capacity();
+  uint32_t entry = GetProbe(hash, 0, capacity);
+  Object* element = KeyAt(entry);
+
+  for (uint32_t i = 1; !(element->IsUndefined() || element->IsNull()); i++) {
+    entry = GetProbe(hash, i, capacity);
+    element = KeyAt(entry);
+  }
+
+  return entry;
+}
+
+
+// Force instantiation of SymbolTable's base class
+template class HashTable<0, 1>;
+
+
+// Force instantiation of Dictionary's base class
+template class HashTable<2, 3>;
+
+
+// Force instantiation of EvalCache's base class
+template class HashTable<0, 2>;
+
+
+Object* SymbolTable::LookupString(String* string, Object** s) {
+  SymbolKey key(string);
+  return LookupKey(&key, s);
+}
+
+
+bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) {
+  SymbolKey key(string);
+  int entry = FindEntry(&key);
+  if (entry == -1) {
+    return false;
+  } else {
+    String* result = String::cast(KeyAt(entry));
+    ASSERT(StringShape(result).IsSymbol());
+    *symbol = result;
+    return true;
+  }
+}
+
+
+Object* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) {
+  Utf8SymbolKey key(str);
+  return LookupKey(&key, s);
+}
+
+
+Object* SymbolTable::LookupKey(HashTableKey* key, Object** s) {
+  int entry = FindEntry(key);
+
+  // Symbol already in table.
+  if (entry != -1) {
+    *s = KeyAt(entry);
+    return this;
+  }
+
+  // Adding new symbol. Grow table if needed.
+  Object* obj = EnsureCapacity(1, key);
+  if (obj->IsFailure()) return obj;
+
+  // Create symbol object.
+  Object* symbol = key->GetObject();
+  if (symbol->IsFailure()) return symbol;
+
+  // If the symbol table grew as part of EnsureCapacity, obj is not
+  // the current symbol table and therefore we cannot use
+  // SymbolTable::cast here.
+  SymbolTable* table = reinterpret_cast<SymbolTable*>(obj);
+
+  // Add the new symbol and return it along with the symbol table.
+  entry = table->FindInsertionEntry(symbol, key->Hash());
+  table->set(EntryToIndex(entry), symbol);
+  table->ElementAdded();
+  *s = symbol;
+  return table;
+}
+
+
+Object* CompilationCacheTable::Lookup(String* src) {
+  StringKey key(src);
+  int entry = FindEntry(&key);
+  if (entry == -1) return Heap::undefined_value();
+  return get(EntryToIndex(entry) + 1);
+}
+
+
+Object* CompilationCacheTable::LookupEval(String* src, Context* context) {
+  StringSharedKey key(src, context->closure()->shared());
+  int entry = FindEntry(&key);
+  if (entry == -1) return Heap::undefined_value();
+  return get(EntryToIndex(entry) + 1);
+}
+
+
+Object* CompilationCacheTable::LookupRegExp(String* src,
+                                            JSRegExp::Flags flags) {
+  RegExpKey key(src, flags);
+  int entry = FindEntry(&key);
+  if (entry == -1) return Heap::undefined_value();
+  return get(EntryToIndex(entry) + 1);
+}
+
+
+Object* CompilationCacheTable::Put(String* src, Object* value) {
+  StringKey key(src);
+  Object* obj = EnsureCapacity(1, &key);
+  if (obj->IsFailure()) return obj;
+
+  CompilationCacheTable* cache =
+      reinterpret_cast<CompilationCacheTable*>(obj);
+  int entry = cache->FindInsertionEntry(src, key.Hash());
+  cache->set(EntryToIndex(entry), src);
+  cache->set(EntryToIndex(entry) + 1, value);
+  cache->ElementAdded();
+  return cache;
+}
+
+
+Object* CompilationCacheTable::PutEval(String* src,
+                                       Context* context,
+                                       Object* value) {
+  StringSharedKey key(src, context->closure()->shared());
+  Object* obj = EnsureCapacity(1, &key);
+  if (obj->IsFailure()) return obj;
+
+  CompilationCacheTable* cache =
+      reinterpret_cast<CompilationCacheTable*>(obj);
+  int entry = cache->FindInsertionEntry(src, key.Hash());
+
+  Object* k = key.GetObject();
+  if (k->IsFailure()) return k;
+
+  cache->set(EntryToIndex(entry), k);
+  cache->set(EntryToIndex(entry) + 1, value);
+  cache->ElementAdded();
+  return cache;
+}
+
+
+Object* CompilationCacheTable::PutRegExp(String* src,
+                                         JSRegExp::Flags flags,
+                                         FixedArray* value) {
+  RegExpKey key(src, flags);
+  Object* obj = EnsureCapacity(1, &key);
+  if (obj->IsFailure()) return obj;
+
+  CompilationCacheTable* cache =
+      reinterpret_cast<CompilationCacheTable*>(obj);
+  int entry = cache->FindInsertionEntry(value, key.Hash());
+  cache->set(EntryToIndex(entry), value);
+  cache->set(EntryToIndex(entry) + 1, value);
+  cache->ElementAdded();
+  return cache;
+}
+
+
+// SymbolsKey used for HashTable where key is array of symbols.
+class SymbolsKey : public HashTableKey {
+ public:
+  explicit SymbolsKey(FixedArray* symbols) : symbols_(symbols) { }
+
+  bool IsMatch(Object* symbols) {
+    FixedArray* o = FixedArray::cast(symbols);
+    int len = symbols_->length();
+    if (o->length() != len) return false;
+    for (int i = 0; i < len; i++) {
+      if (o->get(i) != symbols_->get(i)) return false;
+    }
+    return true;
+  }
+
+  uint32_t Hash() { return SymbolsHash(symbols_); }
+
+  HashFunction GetHashFunction() { return SymbolsHash; }
+
+  Object* GetObject() { return symbols_; }
+
+  static uint32_t SymbolsHash(Object* obj) {
+    FixedArray* symbols = FixedArray::cast(obj);
+    int len = symbols->length();
+    uint32_t hash = 0;
+    for (int i = 0; i < len; i++) {
+      hash ^= String::cast(symbols->get(i))->Hash();
+    }
+    return hash;
+  }
+
+  bool IsStringKey() { return false; }
+
+ private:
+  FixedArray* symbols_;
+};
+
+
+// MapNameKeys are used as keys in lookup caches.
+class MapNameKey : public HashTableKey {
+ public:
+  MapNameKey(Map* map, String* name)
+      : map_(map), name_(name) { }
+
+  bool IsMatch(Object* other) {
+    if (!other->IsFixedArray()) return false;
+    FixedArray* pair = FixedArray::cast(other);
+    Map* map = Map::cast(pair->get(0));
+    if (map != map_) return false;
+    String* name = String::cast(pair->get(1));
+    return name->Equals(name_);
+  }
+
+  typedef uint32_t (*HashFunction)(Object* obj);
+
+  virtual HashFunction GetHashFunction() { return MapNameHash; }
+
+  static uint32_t MapNameHashHelper(Map* map, String* name) {
+    return reinterpret_cast<uint32_t>(map) ^ name->Hash();
+  }
+
+  static uint32_t MapNameHash(Object* obj) {
+    FixedArray* pair = FixedArray::cast(obj);
+    Map* map = Map::cast(pair->get(0));
+    String* name = String::cast(pair->get(1));
+    return MapNameHashHelper(map, name);
+  }
+
+  virtual uint32_t Hash() {
+    return MapNameHashHelper(map_, name_);
+  }
+
+  virtual Object* GetObject() {
+    Object* obj = Heap::AllocateFixedArray(2);
+    if (obj->IsFailure()) return obj;
+    FixedArray* pair = FixedArray::cast(obj);
+    pair->set(0, map_);
+    pair->set(1, name_);
+    return pair;
+  }
+
+  virtual bool IsStringKey() { return false; }
+
+ private:
+  Map* map_;
+  String* name_;
+};
+
+
+Object* MapCache::Lookup(FixedArray* array) {
+  SymbolsKey key(array);
+  int entry = FindEntry(&key);
+  if (entry == -1) return Heap::undefined_value();
+  return get(EntryToIndex(entry) + 1);
+}
+
+
+Object* MapCache::Put(FixedArray* array, Map* value) {
+  SymbolsKey key(array);
+  Object* obj = EnsureCapacity(1, &key);
+  if (obj->IsFailure()) return obj;
+
+  MapCache* cache = reinterpret_cast<MapCache*>(obj);
+  int entry = cache->FindInsertionEntry(array, key.Hash());
+  cache->set(EntryToIndex(entry), array);
+  cache->set(EntryToIndex(entry) + 1, value);
+  cache->ElementAdded();
+  return cache;
+}
+
+
+int LookupCache::Lookup(Map* map, String* name) {
+  MapNameKey key(map, name);
+  int entry = FindEntry(&key);
+  if (entry == -1) return kNotFound;
+  return Smi::cast(get(EntryToIndex(entry) + 1))->value();
+}
+
+
+Object* LookupCache::Put(Map* map, String* name, int value) {
+  MapNameKey key(map, name);
+  Object* obj = EnsureCapacity(1, &key);
+  if (obj->IsFailure()) return obj;
+  Object* k = key.GetObject();
+  if (k->IsFailure()) return k;
+
+  LookupCache* cache = reinterpret_cast<LookupCache*>(obj);
+  int entry = cache->FindInsertionEntry(k, key.Hash());
+  int index = EntryToIndex(entry);
+  cache->set(index, k);
+  cache->set(index + 1, Smi::FromInt(value), SKIP_WRITE_BARRIER);
+  cache->ElementAdded();
+  return cache;
+}
+
+
+Object* Dictionary::Allocate(int at_least_space_for) {
+  Object* obj = DictionaryBase::Allocate(at_least_space_for);
+  // Initialize the next enumeration index.
+  if (!obj->IsFailure()) {
+    Dictionary::cast(obj)->
+        SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
+  }
+  return obj;
+}
+
+
+Object* Dictionary::GenerateNewEnumerationIndices() {
+  int length = NumberOfElements();
+
+  // Allocate and initialize iteration order array.
+  Object* obj = Heap::AllocateFixedArray(length);
+  if (obj->IsFailure()) return obj;
+  FixedArray* iteration_order = FixedArray::cast(obj);
+  for (int i = 0; i < length; i++) {
+    iteration_order->set(i, Smi::FromInt(i), SKIP_WRITE_BARRIER);
+  }
+
+  // Allocate array with enumeration order.
+  obj = Heap::AllocateFixedArray(length);
+  if (obj->IsFailure()) return obj;
+  FixedArray* enumeration_order = FixedArray::cast(obj);
+
+  // Fill the enumeration order array with property details.
+  int capacity = Capacity();
+  int pos = 0;
+  for (int i = 0; i < capacity; i++) {
+    if (IsKey(KeyAt(i))) {
+      enumeration_order->set(pos++,
+                             Smi::FromInt(DetailsAt(i).index()),
+                             SKIP_WRITE_BARRIER);
+    }
+  }
+
+  // Sort the arrays wrt. enumeration order.
+  iteration_order->SortPairs(enumeration_order);
+
+  // Overwrite the enumeration_order with the enumeration indices.
+  for (int i = 0; i < length; i++) {
+    int index = Smi::cast(iteration_order->get(i))->value();
+    int enum_index = PropertyDetails::kInitialIndex + i;
+    enumeration_order->set(index,
+                           Smi::FromInt(enum_index),
+                           SKIP_WRITE_BARRIER);
+  }
+
+  // Update the dictionary with new indices.
+  capacity = Capacity();
+  pos = 0;
+  for (int i = 0; i < capacity; i++) {
+    if (IsKey(KeyAt(i))) {
+      int enum_index = Smi::cast(enumeration_order->get(pos++))->value();
+      PropertyDetails details = DetailsAt(i);
+      PropertyDetails new_details =
+          PropertyDetails(details.attributes(), details.type(), enum_index);
+      DetailsAtPut(i, new_details);
+    }
+  }
+
+  // Set the next enumeration index.
+  SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
+  return this;
+}
+
+
+Object* Dictionary::EnsureCapacity(int n, HashTableKey* key) {
+  // Check whether there are enough enumeration indices to add n elements.
+  if (key->IsStringKey() &&
+      !PropertyDetails::IsValidIndex(NextEnumerationIndex() + n)) {
+    // If not, we generate new indices for the properties.
+    Object* result = GenerateNewEnumerationIndices();
+    if (result->IsFailure()) return result;
+  }
+  return DictionaryBase::EnsureCapacity(n, key);
+}
+
+
+void Dictionary::RemoveNumberEntries(uint32_t from, uint32_t to) {
+  // Do nothing if the interval [from, to) is empty.
+  if (from >= to) return;
+
+  int removed_entries = 0;
+  Object* sentinel = Heap::null_value();
+  int capacity = Capacity();
+  for (int i = 0; i < capacity; i++) {
+    Object* key = KeyAt(i);
+    if (key->IsNumber()) {
+      uint32_t number = static_cast<uint32_t>(key->Number());
+      if (from <= number && number < to) {
+        SetEntry(i, sentinel, sentinel, Smi::FromInt(0));
+        removed_entries++;
+      }
+    }
+  }
+
+  // Update the number of elements.
+  SetNumberOfElements(NumberOfElements() - removed_entries);
+}
+
+
+Object* Dictionary::DeleteProperty(int entry) {
+  PropertyDetails details = DetailsAt(entry);
+  if (details.IsDontDelete()) return Heap::false_value();
+  SetEntry(entry, Heap::null_value(), Heap::null_value(), Smi::FromInt(0));
+  ElementRemoved();
+  return Heap::true_value();
+}
+
+
+int Dictionary::FindStringEntry(String* key) {
+  StringKey k(key);
+  return FindEntry(&k);
+}
+
+
+int Dictionary::FindNumberEntry(uint32_t index) {
+  NumberKey k(index);
+  return FindEntry(&k);
+}
+
+
+Object* Dictionary::AtPut(HashTableKey* key, Object* value) {
+  int entry = FindEntry(key);
+
+  // If the entry is present set the value;
+  if (entry != -1) {
+    ValueAtPut(entry, value);
+    return this;
+  }
+
+  // Check whether the dictionary should be extended.
+  Object* obj = EnsureCapacity(1, key);
+  if (obj->IsFailure()) return obj;
+  Object* k = key->GetObject();
+  if (k->IsFailure()) return k;
+  PropertyDetails details = PropertyDetails(NONE, NORMAL);
+  Dictionary::cast(obj)->AddEntry(k, value, details, key->Hash());
+  return obj;
+}
+
+
+Object* Dictionary::Add(HashTableKey* key, Object* value,
+                        PropertyDetails details) {
+  // Check whether the dictionary should be extended.
+  Object* obj = EnsureCapacity(1, key);
+  if (obj->IsFailure()) return obj;
+  // Compute the key object.
+  Object* k = key->GetObject();
+  if (k->IsFailure()) return k;
+  Dictionary::cast(obj)->AddEntry(k, value, details, key->Hash());
+  return obj;
+}
+
+
+// Add a key, value pair to the dictionary.
+void Dictionary::AddEntry(Object* key,
+                          Object* value,
+                          PropertyDetails details,
+                          uint32_t hash) {
+  uint32_t entry = FindInsertionEntry(key, hash);
+  // Insert element at empty or deleted entry
+  if (details.index() == 0 && key->IsString()) {
+    // Assign an enumeration index to the property and update
+    // SetNextEnumerationIndex.
+    int index = NextEnumerationIndex();
+    details = PropertyDetails(details.attributes(), details.type(), index);
+    SetNextEnumerationIndex(index + 1);
+  }
+  SetEntry(entry, key, value, details);
+  ASSERT(KeyAt(entry)->IsNumber() || KeyAt(entry)->IsString());
+  ElementAdded();
+}
+
+
+void Dictionary::UpdateMaxNumberKey(uint32_t key) {
+  // If the dictionary requires slow elements an element has already
+  // been added at a high index.
+  if (requires_slow_elements()) return;
+  // Check if this index is high enough that we should require slow
+  // elements.
+  if (key > kRequiresSlowElementsLimit) {
+    set_requires_slow_elements();
+    return;
+  }
+  // Update max key value.
+  Object* max_index_object = get(kMaxNumberKeyIndex);
+  if (!max_index_object->IsSmi() || max_number_key() < key) {
+    set(kMaxNumberKeyIndex,
+        Smi::FromInt(key << kRequiresSlowElementsTagSize),
+        SKIP_WRITE_BARRIER);
+  }
+}
+
+
+Object* Dictionary::AddStringEntry(String* key,
+                                   Object* value,
+                                   PropertyDetails details) {
+  StringKey k(key);
+  SLOW_ASSERT(FindEntry(&k) == -1);
+  return Add(&k, value, details);
+}
+
+
+Object* Dictionary::AddNumberEntry(uint32_t key,
+                                   Object* value,
+                                   PropertyDetails details) {
+  NumberKey k(key);
+  UpdateMaxNumberKey(key);
+  SLOW_ASSERT(FindEntry(&k) == -1);
+  return Add(&k, value, details);
+}
+
+
+Object* Dictionary::AtStringPut(String* key, Object* value) {
+  StringKey k(key);
+  return AtPut(&k, value);
+}
+
+
+Object* Dictionary::AtNumberPut(uint32_t key, Object* value) {
+  NumberKey k(key);
+  UpdateMaxNumberKey(key);
+  return AtPut(&k, value);
+}
+
+
+Object* Dictionary::SetOrAddStringEntry(String* key,
+                                        Object* value,
+                                        PropertyDetails details) {
+  StringKey k(key);
+  int entry = FindEntry(&k);
+  if (entry == -1) return AddStringEntry(key, value, details);
+  // Preserve enumeration index.
+  details = PropertyDetails(details.attributes(),
+                            details.type(),
+                            DetailsAt(entry).index());
+  SetEntry(entry, key, value, details);
+  return this;
+}
+
+
+Object* Dictionary::SetOrAddNumberEntry(uint32_t key,
+                                        Object* value,
+                                        PropertyDetails details) {
+  NumberKey k(key);
+  int entry = FindEntry(&k);
+  if (entry == -1) return AddNumberEntry(key, value, details);
+  // Preserve enumeration index.
+  details = PropertyDetails(details.attributes(),
+                            details.type(),
+                            DetailsAt(entry).index());
+  SetEntry(entry, k.GetObject(), value, details);
+  return this;
+}
+
+
+int Dictionary::NumberOfElementsFilterAttributes(PropertyAttributes filter) {
+  int capacity = Capacity();
+  int result = 0;
+  for (int i = 0; i < capacity; i++) {
+    Object* k = KeyAt(i);
+    if (IsKey(k)) {
+      PropertyAttributes attr = DetailsAt(i).attributes();
+      if ((attr & filter) == 0) result++;
+    }
+  }
+  return result;
+}
+
+
+int Dictionary::NumberOfEnumElements() {
+  return NumberOfElementsFilterAttributes(
+      static_cast<PropertyAttributes>(DONT_ENUM));
+}
+
+
+void Dictionary::CopyKeysTo(FixedArray* storage, PropertyAttributes filter) {
+  ASSERT(storage->length() >= NumberOfEnumElements());
+  int capacity = Capacity();
+  int index = 0;
+  for (int i = 0; i < capacity; i++) {
+     Object* k = KeyAt(i);
+     if (IsKey(k)) {
+       PropertyAttributes attr = DetailsAt(i).attributes();
+       if ((attr & filter) == 0) storage->set(index++, k);
+     }
+  }
+  ASSERT(storage->length() >= index);
+}
+
+
+void Dictionary::CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array) {
+  ASSERT(storage->length() >= NumberOfEnumElements());
+  int capacity = Capacity();
+  int index = 0;
+  for (int i = 0; i < capacity; i++) {
+     Object* k = KeyAt(i);
+     if (IsKey(k)) {
+       PropertyDetails details = DetailsAt(i);
+       if (!details.IsDontEnum()) {
+         storage->set(index, k);
+         sort_array->set(index,
+                         Smi::FromInt(details.index()),
+                         SKIP_WRITE_BARRIER);
+         index++;
+       }
+     }
+  }
+  storage->SortPairs(sort_array);
+  ASSERT(storage->length() >= index);
+}
+
+
+void Dictionary::CopyKeysTo(FixedArray* storage) {
+  ASSERT(storage->length() >= NumberOfElementsFilterAttributes(
+      static_cast<PropertyAttributes>(NONE)));
+  int capacity = Capacity();
+  int index = 0;
+  for (int i = 0; i < capacity; i++) {
+    Object* k = KeyAt(i);
+    if (IsKey(k)) {
+      storage->set(index++, k);
+    }
+  }
+  ASSERT(storage->length() >= index);
+}
+
+
+// Backwards lookup (slow).
+Object* Dictionary::SlowReverseLookup(Object* value) {
+  int capacity = Capacity();
+  for (int i = 0; i < capacity; i++) {
+    Object* k = KeyAt(i);
+    if (IsKey(k) && ValueAt(i) == value) {
+      return k;
+    }
+  }
+  return Heap::undefined_value();
+}
+
+
+Object* Dictionary::TransformPropertiesToFastFor(JSObject* obj,
+                                                 int unused_property_fields) {
+  // Make sure we preserve dictionary representation if there are too many
+  // descriptors.
+  if (NumberOfElements() > DescriptorArray::kMaxNumberOfDescriptors) return obj;
+
+  // Figure out if it is necessary to generate new enumeration indices.
+  int max_enumeration_index =
+      NextEnumerationIndex() +
+          (DescriptorArray::kMaxNumberOfDescriptors - NumberOfElements());
+  if (!PropertyDetails::IsValidIndex(max_enumeration_index)) {
+    Object* result = GenerateNewEnumerationIndices();
+    if (result->IsFailure()) return result;
+  }
+
+  int instance_descriptor_length = 0;
+  int number_of_fields = 0;
+
+  // Compute the length of the instance descriptor.
+  int capacity = Capacity();
+  for (int i = 0; i < capacity; i++) {
+    Object* k = KeyAt(i);
+    if (IsKey(k)) {
+      Object* value = ValueAt(i);
+      PropertyType type = DetailsAt(i).type();
+      ASSERT(type != FIELD);
+      instance_descriptor_length++;
+      if (type == NORMAL && !value->IsJSFunction()) number_of_fields += 1;
+    }
+  }
+
+  // Allocate the instance descriptor.
+  Object* descriptors_unchecked =
+      DescriptorArray::Allocate(instance_descriptor_length);
+  if (descriptors_unchecked->IsFailure()) return descriptors_unchecked;
+  DescriptorArray* descriptors = DescriptorArray::cast(descriptors_unchecked);
+
+  int inobject_props = obj->map()->inobject_properties();
+  int number_of_allocated_fields =
+      number_of_fields + unused_property_fields - inobject_props;
+
+  // Allocate the fixed array for the fields.
+  Object* fields = Heap::AllocateFixedArray(number_of_allocated_fields);
+  if (fields->IsFailure()) return fields;
+
+  // Fill in the instance descriptor and the fields.
+  DescriptorWriter w(descriptors);
+  int current_offset = 0;
+  for (int i = 0; i < capacity; i++) {
+    Object* k = KeyAt(i);
+    if (IsKey(k)) {
+      Object* value = ValueAt(i);
+      // Ensure the key is a symbol before writing into the instance descriptor.
+      Object* key = Heap::LookupSymbol(String::cast(k));
+      if (key->IsFailure()) return key;
+      PropertyDetails details = DetailsAt(i);
+      PropertyType type = details.type();
+
+      if (value->IsJSFunction()) {
+        ConstantFunctionDescriptor d(String::cast(key),
+                                     JSFunction::cast(value),
+                                     details.attributes(),
+                                     details.index());
+        w.Write(&d);
+      } else if (type == NORMAL) {
+        if (current_offset < inobject_props) {
+          obj->InObjectPropertyAtPut(current_offset,
+                                     value,
+                                     UPDATE_WRITE_BARRIER);
+        } else {
+          int offset = current_offset - inobject_props;
+          FixedArray::cast(fields)->set(offset, value);
+        }
+        FieldDescriptor d(String::cast(key),
+                          current_offset++,
+                          details.attributes(),
+                          details.index());
+        w.Write(&d);
+      } else if (type == CALLBACKS) {
+        CallbacksDescriptor d(String::cast(key),
+                              value,
+                              details.attributes(),
+                              details.index());
+        w.Write(&d);
+      } else {
+        UNREACHABLE();
+      }
+    }
+  }
+  ASSERT(current_offset == number_of_fields);
+
+  descriptors->Sort();
+  // Allocate new map.
+  Object* new_map = obj->map()->Copy();
+  if (new_map->IsFailure()) return new_map;
+
+  // Transform the object.
+  obj->set_map(Map::cast(new_map));
+  obj->map()->set_instance_descriptors(descriptors);
+  obj->map()->set_unused_property_fields(unused_property_fields);
+
+  obj->set_properties(FixedArray::cast(fields));
+  ASSERT(obj->IsJSObject());
+
+  descriptors->SetNextEnumerationIndex(NextEnumerationIndex());
+  // Check that it really works.
+  ASSERT(obj->HasFastProperties());
+
+  return obj;
+}
+
+
+// Check if there is a break point at this code position.
+bool DebugInfo::HasBreakPoint(int code_position) {
+  // Get the break point info object for this code position.
+  Object* break_point_info = GetBreakPointInfo(code_position);
+
+  // If there is no break point info object or no break points in the break
+  // point info object there is no break point at this code position.
+  if (break_point_info->IsUndefined()) return false;
+  return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
+}
+
+
+// Get the break point info object for this code position.
+Object* DebugInfo::GetBreakPointInfo(int code_position) {
+  // Find the index of the break point info object for this code position.
+  int index = GetBreakPointInfoIndex(code_position);
+
+  // Return the break point info object if any.
+  if (index == kNoBreakPointInfo) return Heap::undefined_value();
+  return BreakPointInfo::cast(break_points()->get(index));
+}
+
+
+// Clear a break point at the specified code position.
+void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
+                                int code_position,
+                                Handle<Object> break_point_object) {
+  Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position));
+  if (break_point_info->IsUndefined()) return;
+  BreakPointInfo::ClearBreakPoint(
+      Handle<BreakPointInfo>::cast(break_point_info),
+      break_point_object);
+}
+
+
+void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
+                              int code_position,
+                              int source_position,
+                              int statement_position,
+                              Handle<Object> break_point_object) {
+  Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position));
+  if (!break_point_info->IsUndefined()) {
+    BreakPointInfo::SetBreakPoint(
+        Handle<BreakPointInfo>::cast(break_point_info),
+        break_point_object);
+    return;
+  }
+
+  // Adding a new break point for a code position which did not have any
+  // break points before. Try to find a free slot.
+  int index = kNoBreakPointInfo;
+  for (int i = 0; i < debug_info->break_points()->length(); i++) {
+    if (debug_info->break_points()->get(i)->IsUndefined()) {
+      index = i;
+      break;
+    }
+  }
+  if (index == kNoBreakPointInfo) {
+    // No free slot - extend break point info array.
+    Handle<FixedArray> old_break_points =
+        Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
+    debug_info->set_break_points(*Factory::NewFixedArray(
+        old_break_points->length() +
+            Debug::kEstimatedNofBreakPointsInFunction));
+    Handle<FixedArray> new_break_points =
+        Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
+    for (int i = 0; i < old_break_points->length(); i++) {
+      new_break_points->set(i, old_break_points->get(i));
+    }
+    index = old_break_points->length();
+  }
+  ASSERT(index != kNoBreakPointInfo);
+
+  // Allocate new BreakPointInfo object and set the break point.
+  Handle<BreakPointInfo> new_break_point_info =
+      Handle<BreakPointInfo>::cast(Factory::NewStruct(BREAK_POINT_INFO_TYPE));
+  new_break_point_info->set_code_position(Smi::FromInt(code_position));
+  new_break_point_info->set_source_position(Smi::FromInt(source_position));
+  new_break_point_info->
+      set_statement_position(Smi::FromInt(statement_position));
+  new_break_point_info->set_break_point_objects(Heap::undefined_value());
+  BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
+  debug_info->break_points()->set(index, *new_break_point_info);
+}
+
+
+// Get the break point objects for a code position.
+Object* DebugInfo::GetBreakPointObjects(int code_position) {
+  Object* break_point_info = GetBreakPointInfo(code_position);
+  if (break_point_info->IsUndefined()) {
+    return Heap::undefined_value();
+  }
+  return BreakPointInfo::cast(break_point_info)->break_point_objects();
+}
+
+
+// Get the total number of break points.
+int DebugInfo::GetBreakPointCount() {
+  if (break_points()->IsUndefined()) return 0;
+  int count = 0;
+  for (int i = 0; i < break_points()->length(); i++) {
+    if (!break_points()->get(i)->IsUndefined()) {
+      BreakPointInfo* break_point_info =
+          BreakPointInfo::cast(break_points()->get(i));
+      count += break_point_info->GetBreakPointCount();
+    }
+  }
+  return count;
+}
+
+
+Object* DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info,
+                                      Handle<Object> break_point_object) {
+  if (debug_info->break_points()->IsUndefined()) return Heap::undefined_value();
+  for (int i = 0; i < debug_info->break_points()->length(); i++) {
+    if (!debug_info->break_points()->get(i)->IsUndefined()) {
+      Handle<BreakPointInfo> break_point_info =
+          Handle<BreakPointInfo>(BreakPointInfo::cast(
+              debug_info->break_points()->get(i)));
+      if (BreakPointInfo::HasBreakPointObject(break_point_info,
+                                              break_point_object)) {
+        return *break_point_info;
+      }
+    }
+  }
+  return Heap::undefined_value();
+}
+
+
+// Find the index of the break point info object for the specified code
+// position.
+int DebugInfo::GetBreakPointInfoIndex(int code_position) {
+  if (break_points()->IsUndefined()) return kNoBreakPointInfo;
+  for (int i = 0; i < break_points()->length(); i++) {
+    if (!break_points()->get(i)->IsUndefined()) {
+      BreakPointInfo* break_point_info =
+          BreakPointInfo::cast(break_points()->get(i));
+      if (break_point_info->code_position()->value() == code_position) {
+        return i;
+      }
+    }
+  }
+  return kNoBreakPointInfo;
+}
+
+
+// Remove the specified break point object.
+void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
+                                     Handle<Object> break_point_object) {
+  // If there are no break points just ignore.
+  if (break_point_info->break_point_objects()->IsUndefined()) return;
+  // If there is a single break point clear it if it is the same.
+  if (!break_point_info->break_point_objects()->IsFixedArray()) {
+    if (break_point_info->break_point_objects() == *break_point_object) {
+      break_point_info->set_break_point_objects(Heap::undefined_value());
+    }
+    return;
+  }
+  // If there are multiple break points shrink the array
+  ASSERT(break_point_info->break_point_objects()->IsFixedArray());
+  Handle<FixedArray> old_array =
+      Handle<FixedArray>(
+          FixedArray::cast(break_point_info->break_point_objects()));
+  Handle<FixedArray> new_array =
+      Factory::NewFixedArray(old_array->length() - 1);
+  int found_count = 0;
+  for (int i = 0; i < old_array->length(); i++) {
+    if (old_array->get(i) == *break_point_object) {
+      ASSERT(found_count == 0);
+      found_count++;
+    } else {
+      new_array->set(i - found_count, old_array->get(i));
+    }
+  }
+  // If the break point was found in the list change it.
+  if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
+}
+
+
+// Add the specified break point object.
+void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
+                                   Handle<Object> break_point_object) {
+  // If there was no break point objects before just set it.
+  if (break_point_info->break_point_objects()->IsUndefined()) {
+    break_point_info->set_break_point_objects(*break_point_object);
+    return;
+  }
+  // If the break point object is the same as before just ignore.
+  if (break_point_info->break_point_objects() == *break_point_object) return;
+  // If there was one break point object before replace with array.
+  if (!break_point_info->break_point_objects()->IsFixedArray()) {
+    Handle<FixedArray> array = Factory::NewFixedArray(2);
+    array->set(0, break_point_info->break_point_objects());
+    array->set(1, *break_point_object);
+    break_point_info->set_break_point_objects(*array);
+    return;
+  }
+  // If there was more than one break point before extend array.
+  Handle<FixedArray> old_array =
+      Handle<FixedArray>(
+          FixedArray::cast(break_point_info->break_point_objects()));
+  Handle<FixedArray> new_array =
+      Factory::NewFixedArray(old_array->length() + 1);
+  for (int i = 0; i < old_array->length(); i++) {
+    // If the break point was there before just ignore.
+    if (old_array->get(i) == *break_point_object) return;
+    new_array->set(i, old_array->get(i));
+  }
+  // Add the new break point.
+  new_array->set(old_array->length(), *break_point_object);
+  break_point_info->set_break_point_objects(*new_array);
+}
+
+
+bool BreakPointInfo::HasBreakPointObject(
+    Handle<BreakPointInfo> break_point_info,
+    Handle<Object> break_point_object) {
+  // No break point.
+  if (break_point_info->break_point_objects()->IsUndefined()) return false;
+  // Single beak point.
+  if (!break_point_info->break_point_objects()->IsFixedArray()) {
+    return break_point_info->break_point_objects() == *break_point_object;
+  }
+  // Multiple break points.
+  FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
+  for (int i = 0; i < array->length(); i++) {
+    if (array->get(i) == *break_point_object) {
+      return true;
+    }
+  }
+  return false;
+}
+
+
+// Get the number of break points.
+int BreakPointInfo::GetBreakPointCount() {
+  // No break point.
+  if (break_point_objects()->IsUndefined()) return 0;
+  // Single beak point.
+  if (!break_point_objects()->IsFixedArray()) return 1;
+  // Multiple break points.
+  return FixedArray::cast(break_point_objects())->length();
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h
new file mode 100644
index 0000000..ade282b
--- /dev/null
+++ b/deps/v8/src/objects.h
@@ -0,0 +1,4337 @@
+// 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_OBJECTS_H_
+#define V8_OBJECTS_H_
+
+#include "builtins.h"
+#include "code-stubs.h"
+#include "smart-pointer.h"
+#include "unicode-inl.h"
+
+//
+// All object types in the V8 JavaScript are described in this file.
+//
+// Inheritance hierarchy:
+//   - Object
+//     - Smi          (immediate small integer)
+//     - Failure      (immediate for marking failed operation)
+//     - HeapObject   (superclass for everything allocated in the heap)
+//       - JSObject
+//         - JSArray
+//         - JSRegExp
+//         - JSFunction
+//         - GlobalObject
+//           - JSGlobalObject
+//           - JSBuiltinsObject
+//         - JSGlobalProxy
+//         - JSValue
+//         - Script
+//       - Array
+//         - ByteArray
+//         - FixedArray
+//           - DescriptorArray
+//           - HashTable
+//             - Dictionary
+//             - SymbolTable
+//             - CompilationCacheTable
+//             - MapCache
+//             - LookupCache
+//           - Context
+//           - GlobalContext
+//       - String
+//         - SeqString
+//           - SeqAsciiString
+//           - SeqTwoByteString
+//         - ConsString
+//         - SlicedString
+//         - ExternalString
+//           - ExternalAsciiString
+//           - ExternalTwoByteString
+//       - HeapNumber
+//       - Code
+//       - Map
+//       - Oddball
+//       - Proxy
+//       - SharedFunctionInfo
+//       - Struct
+//         - AccessorInfo
+//         - AccessCheckInfo
+//         - InterceptorInfo
+//         - CallHandlerInfo
+//         - FunctionTemplateInfo
+//         - ObjectTemplateInfo
+//         - SignatureInfo
+//         - TypeSwitchInfo
+//         - DebugInfo
+//         - BreakPointInfo
+//
+// Formats of Object*:
+//  Smi:        [31 bit signed int] 0
+//  HeapObject: [32 bit direct pointer] (4 byte aligned) | 01
+//  Failure:    [30 bit signed int] 11
+
+
+// Ecma-262 3rd 8.6.1
+enum PropertyAttributes {
+  NONE              = v8::None,
+  READ_ONLY         = v8::ReadOnly,
+  DONT_ENUM         = v8::DontEnum,
+  DONT_DELETE       = v8::DontDelete,
+  ABSENT            = 16  // Used in runtime to indicate a property is absent.
+  // ABSENT can never be stored in or returned from a descriptor's attributes
+  // bitfield.  It is only used as a return value meaning the attributes of
+  // a non-existent property.
+};
+
+namespace v8 { namespace internal {
+
+
+// PropertyDetails captures type and attributes for a property.
+// They are used both in property dictionaries and instance descriptors.
+class PropertyDetails BASE_EMBEDDED {
+ public:
+
+  PropertyDetails(PropertyAttributes attributes,
+                  PropertyType type,
+                  int index = 0) {
+    ASSERT(TypeField::is_valid(type));
+    ASSERT(AttributesField::is_valid(attributes));
+    ASSERT(IndexField::is_valid(index));
+
+    value_ = TypeField::encode(type)
+        | AttributesField::encode(attributes)
+        | IndexField::encode(index);
+
+    ASSERT(type == this->type());
+    ASSERT(attributes == this->attributes());
+    ASSERT(index == this->index());
+  }
+
+  // Conversion for storing details as Object*.
+  inline PropertyDetails(Smi* smi);
+  inline Smi* AsSmi();
+
+  PropertyType type() { return TypeField::decode(value_); }
+
+  bool IsTransition() {
+    PropertyType t = type();
+    ASSERT(t != INTERCEPTOR);
+    return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
+  }
+
+  bool IsProperty() {
+    return type() < FIRST_PHANTOM_PROPERTY_TYPE;
+  }
+
+  PropertyAttributes attributes() { return AttributesField::decode(value_); }
+
+  int index() { return IndexField::decode(value_); }
+
+  static bool IsValidIndex(int index) { return IndexField::is_valid(index); }
+
+  bool IsReadOnly() { return (attributes() & READ_ONLY) != 0; }
+  bool IsDontDelete() { return (attributes() & DONT_DELETE) != 0; }
+  bool IsDontEnum() { return (attributes() & DONT_ENUM) != 0; }
+
+  // Bit fields in value_ (type, shift, size). Must be public so the
+  // constants can be embedded in generated code.
+  class TypeField:       public BitField<PropertyType,       0, 3> {};
+  class AttributesField: public BitField<PropertyAttributes, 3, 3> {};
+  class IndexField:      public BitField<uint32_t,           6, 32-6> {};
+
+  static const int kInitialIndex = 1;
+
+ private:
+  uint32_t value_;
+};
+
+
+// Setter that skips the write barrier if mode is SKIP_WRITE_BARRIER.
+enum WriteBarrierMode { SKIP_WRITE_BARRIER, UPDATE_WRITE_BARRIER };
+
+
+// PropertyNormalizationMode is used to specify whether to keep
+// inobject properties when normalizing properties of a JSObject.
+enum PropertyNormalizationMode {
+  CLEAR_INOBJECT_PROPERTIES,
+  KEEP_INOBJECT_PROPERTIES
+};
+
+
+// All Maps have a field instance_type containing a InstanceType.
+// It describes the type of the instances.
+//
+// As an example, a JavaScript object is a heap object and its map
+// instance_type is JS_OBJECT_TYPE.
+//
+// The names of the string instance types are intended to systematically
+// mirror their encoding in the instance_type field of the map.  The length
+// (SHORT, MEDIUM, or LONG) is always mentioned.  The default encoding is
+// considered TWO_BYTE.  It is not mentioned in the name.  ASCII encoding is
+// mentioned explicitly in the name.  Likewise, the default representation is
+// considered sequential.  It is not mentioned in the name.  The other
+// representations (eg, CONS, SLICED, EXTERNAL) are explicitly mentioned.
+// Finally, the string is either a SYMBOL_TYPE (if it is a symbol) or a
+// STRING_TYPE (if it is not a symbol).
+//
+// NOTE: The following things are some that depend on the string types having
+// instance_types that are less than those of all other types:
+// HeapObject::Size, HeapObject::IterateBody, the typeof operator, and
+// Object::IsString.
+//
+// NOTE: Everything following JS_VALUE_TYPE is considered a
+// JSObject for GC purposes. The first four entries here have typeof
+// 'object', whereas JS_FUNCTION_TYPE has typeof 'function'.
+#define INSTANCE_TYPE_LIST(V)                   \
+  V(SHORT_SYMBOL_TYPE)                          \
+  V(MEDIUM_SYMBOL_TYPE)                         \
+  V(LONG_SYMBOL_TYPE)                           \
+  V(SHORT_ASCII_SYMBOL_TYPE)                    \
+  V(MEDIUM_ASCII_SYMBOL_TYPE)                   \
+  V(LONG_ASCII_SYMBOL_TYPE)                     \
+  V(SHORT_CONS_SYMBOL_TYPE)                     \
+  V(MEDIUM_CONS_SYMBOL_TYPE)                    \
+  V(LONG_CONS_SYMBOL_TYPE)                      \
+  V(SHORT_CONS_ASCII_SYMBOL_TYPE)               \
+  V(MEDIUM_CONS_ASCII_SYMBOL_TYPE)              \
+  V(LONG_CONS_ASCII_SYMBOL_TYPE)                \
+  V(SHORT_SLICED_SYMBOL_TYPE)                   \
+  V(MEDIUM_SLICED_SYMBOL_TYPE)                  \
+  V(LONG_SLICED_SYMBOL_TYPE)                    \
+  V(SHORT_SLICED_ASCII_SYMBOL_TYPE)             \
+  V(MEDIUM_SLICED_ASCII_SYMBOL_TYPE)            \
+  V(LONG_SLICED_ASCII_SYMBOL_TYPE)              \
+  V(SHORT_EXTERNAL_SYMBOL_TYPE)                 \
+  V(MEDIUM_EXTERNAL_SYMBOL_TYPE)                \
+  V(LONG_EXTERNAL_SYMBOL_TYPE)                  \
+  V(SHORT_EXTERNAL_ASCII_SYMBOL_TYPE)           \
+  V(MEDIUM_EXTERNAL_ASCII_SYMBOL_TYPE)          \
+  V(LONG_EXTERNAL_ASCII_SYMBOL_TYPE)            \
+  V(SHORT_STRING_TYPE)                          \
+  V(MEDIUM_STRING_TYPE)                         \
+  V(LONG_STRING_TYPE)                           \
+  V(SHORT_ASCII_STRING_TYPE)                    \
+  V(MEDIUM_ASCII_STRING_TYPE)                   \
+  V(LONG_ASCII_STRING_TYPE)                     \
+  V(SHORT_CONS_STRING_TYPE)                     \
+  V(MEDIUM_CONS_STRING_TYPE)                    \
+  V(LONG_CONS_STRING_TYPE)                      \
+  V(SHORT_CONS_ASCII_STRING_TYPE)               \
+  V(MEDIUM_CONS_ASCII_STRING_TYPE)              \
+  V(LONG_CONS_ASCII_STRING_TYPE)                \
+  V(SHORT_SLICED_STRING_TYPE)                   \
+  V(MEDIUM_SLICED_STRING_TYPE)                  \
+  V(LONG_SLICED_STRING_TYPE)                    \
+  V(SHORT_SLICED_ASCII_STRING_TYPE)             \
+  V(MEDIUM_SLICED_ASCII_STRING_TYPE)            \
+  V(LONG_SLICED_ASCII_STRING_TYPE)              \
+  V(SHORT_EXTERNAL_STRING_TYPE)                 \
+  V(MEDIUM_EXTERNAL_STRING_TYPE)                \
+  V(LONG_EXTERNAL_STRING_TYPE)                  \
+  V(SHORT_EXTERNAL_ASCII_STRING_TYPE)           \
+  V(MEDIUM_EXTERNAL_ASCII_STRING_TYPE)          \
+  V(LONG_EXTERNAL_ASCII_STRING_TYPE)            \
+  V(LONG_PRIVATE_EXTERNAL_ASCII_STRING_TYPE)    \
+                                                \
+  V(MAP_TYPE)                                   \
+  V(HEAP_NUMBER_TYPE)                           \
+  V(FIXED_ARRAY_TYPE)                           \
+  V(CODE_TYPE)                                  \
+  V(ODDBALL_TYPE)                               \
+  V(PROXY_TYPE)                                 \
+  V(BYTE_ARRAY_TYPE)                            \
+  V(FILLER_TYPE)                                \
+                                                \
+  V(ACCESSOR_INFO_TYPE)                         \
+  V(ACCESS_CHECK_INFO_TYPE)                     \
+  V(INTERCEPTOR_INFO_TYPE)                      \
+  V(SHARED_FUNCTION_INFO_TYPE)                  \
+  V(CALL_HANDLER_INFO_TYPE)                     \
+  V(FUNCTION_TEMPLATE_INFO_TYPE)                \
+  V(OBJECT_TEMPLATE_INFO_TYPE)                  \
+  V(SIGNATURE_INFO_TYPE)                        \
+  V(TYPE_SWITCH_INFO_TYPE)                      \
+  V(DEBUG_INFO_TYPE)                            \
+  V(BREAK_POINT_INFO_TYPE)                      \
+  V(SCRIPT_TYPE)                                \
+                                                \
+  V(JS_VALUE_TYPE)                              \
+  V(JS_OBJECT_TYPE)                             \
+  V(JS_CONTEXT_EXTENSION_OBJECT_TYPE)           \
+  V(JS_GLOBAL_OBJECT_TYPE)                      \
+  V(JS_BUILTINS_OBJECT_TYPE)                    \
+  V(JS_GLOBAL_PROXY_TYPE)                       \
+  V(JS_ARRAY_TYPE)                              \
+  V(JS_REGEXP_TYPE)                             \
+                                                \
+  V(JS_FUNCTION_TYPE)                           \
+
+
+// Since string types are not consecutive, this macro is used to
+// iterate over them.
+#define STRING_TYPE_LIST(V)                                                    \
+  V(SHORT_SYMBOL_TYPE, SeqTwoByteString::kHeaderSize, short_symbol)            \
+  V(MEDIUM_SYMBOL_TYPE, SeqTwoByteString::kHeaderSize, medium_symbol)          \
+  V(LONG_SYMBOL_TYPE, SeqTwoByteString::kHeaderSize, long_symbol)              \
+  V(SHORT_ASCII_SYMBOL_TYPE, SeqAsciiString::kHeaderSize, short_ascii_symbol)  \
+  V(MEDIUM_ASCII_SYMBOL_TYPE, SeqAsciiString::kHeaderSize, medium_ascii_symbol)\
+  V(LONG_ASCII_SYMBOL_TYPE, SeqAsciiString::kHeaderSize, long_ascii_symbol)    \
+  V(SHORT_CONS_SYMBOL_TYPE, ConsString::kSize, short_cons_symbol)              \
+  V(MEDIUM_CONS_SYMBOL_TYPE, ConsString::kSize, medium_cons_symbol)            \
+  V(LONG_CONS_SYMBOL_TYPE, ConsString::kSize, long_cons_symbol)                \
+  V(SHORT_CONS_ASCII_SYMBOL_TYPE, ConsString::kSize, short_cons_ascii_symbol)  \
+  V(MEDIUM_CONS_ASCII_SYMBOL_TYPE, ConsString::kSize, medium_cons_ascii_symbol)\
+  V(LONG_CONS_ASCII_SYMBOL_TYPE, ConsString::kSize, long_cons_ascii_symbol)    \
+  V(SHORT_SLICED_SYMBOL_TYPE, SlicedString::kSize, short_sliced_symbol)        \
+  V(MEDIUM_SLICED_SYMBOL_TYPE, SlicedString::kSize, medium_sliced_symbol)      \
+  V(LONG_SLICED_SYMBOL_TYPE, SlicedString::kSize, long_sliced_symbol)          \
+  V(SHORT_SLICED_ASCII_SYMBOL_TYPE,                                            \
+    SlicedString::kSize,                                                       \
+    short_sliced_ascii_symbol)                                                 \
+  V(MEDIUM_SLICED_ASCII_SYMBOL_TYPE,                                           \
+    SlicedString::kSize,                                                       \
+    medium_sliced_ascii_symbol)                                                \
+  V(LONG_SLICED_ASCII_SYMBOL_TYPE,                                             \
+    SlicedString::kSize,                                                       \
+    long_sliced_ascii_symbol)                                                  \
+  V(SHORT_EXTERNAL_SYMBOL_TYPE,                                                \
+    ExternalTwoByteString::kSize,                                              \
+    short_external_symbol)                                                     \
+  V(MEDIUM_EXTERNAL_SYMBOL_TYPE,                                               \
+    ExternalTwoByteString::kSize,                                              \
+    medium_external_symbol)                                                    \
+  V(LONG_EXTERNAL_SYMBOL_TYPE,                                                 \
+    ExternalTwoByteString::kSize,                                              \
+    long_external_symbol)                                                      \
+  V(SHORT_EXTERNAL_ASCII_SYMBOL_TYPE,                                          \
+    ExternalAsciiString::kSize,                                                \
+    short_external_ascii_symbol)                                               \
+  V(MEDIUM_EXTERNAL_ASCII_SYMBOL_TYPE,                                         \
+    ExternalAsciiString::kSize,                                                \
+    medium_external_ascii_symbol)                                              \
+  V(LONG_EXTERNAL_ASCII_SYMBOL_TYPE,                                           \
+    ExternalAsciiString::kSize,                                                \
+    long_external_ascii_symbol)                                                \
+  V(SHORT_STRING_TYPE, SeqTwoByteString::kHeaderSize, short_string)            \
+  V(MEDIUM_STRING_TYPE, SeqTwoByteString::kHeaderSize, medium_string)          \
+  V(LONG_STRING_TYPE, SeqTwoByteString::kHeaderSize, long_string)              \
+  V(SHORT_ASCII_STRING_TYPE, SeqAsciiString::kHeaderSize, short_ascii_string)  \
+  V(MEDIUM_ASCII_STRING_TYPE, SeqAsciiString::kHeaderSize, medium_ascii_string)\
+  V(LONG_ASCII_STRING_TYPE, SeqAsciiString::kHeaderSize, long_ascii_string)    \
+  V(SHORT_CONS_STRING_TYPE, ConsString::kSize, short_cons_string)              \
+  V(MEDIUM_CONS_STRING_TYPE, ConsString::kSize, medium_cons_string)            \
+  V(LONG_CONS_STRING_TYPE, ConsString::kSize, long_cons_string)                \
+  V(SHORT_CONS_ASCII_STRING_TYPE, ConsString::kSize, short_cons_ascii_string)  \
+  V(MEDIUM_CONS_ASCII_STRING_TYPE, ConsString::kSize, medium_cons_ascii_string)\
+  V(LONG_CONS_ASCII_STRING_TYPE, ConsString::kSize, long_cons_ascii_string)    \
+  V(SHORT_SLICED_STRING_TYPE, SlicedString::kSize, short_sliced_string)        \
+  V(MEDIUM_SLICED_STRING_TYPE, SlicedString::kSize, medium_sliced_string)      \
+  V(LONG_SLICED_STRING_TYPE, SlicedString::kSize, long_sliced_string)          \
+  V(SHORT_SLICED_ASCII_STRING_TYPE,                                            \
+    SlicedString::kSize,                                                       \
+    short_sliced_ascii_string)                                                 \
+  V(MEDIUM_SLICED_ASCII_STRING_TYPE,                                           \
+    SlicedString::kSize,                                                       \
+    medium_sliced_ascii_string)                                                \
+  V(LONG_SLICED_ASCII_STRING_TYPE,                                             \
+    SlicedString::kSize,                                                       \
+    long_sliced_ascii_string)                                                  \
+  V(SHORT_EXTERNAL_STRING_TYPE,                                                \
+    ExternalTwoByteString::kSize,                                              \
+    short_external_string)                                                     \
+  V(MEDIUM_EXTERNAL_STRING_TYPE,                                               \
+    ExternalTwoByteString::kSize,                                              \
+    medium_external_string)                                                    \
+  V(LONG_EXTERNAL_STRING_TYPE,                                                 \
+    ExternalTwoByteString::kSize,                                              \
+    long_external_string)                                                      \
+  V(SHORT_EXTERNAL_ASCII_STRING_TYPE,                                          \
+    ExternalAsciiString::kSize,                                                \
+    short_external_ascii_string)                                               \
+  V(MEDIUM_EXTERNAL_ASCII_STRING_TYPE,                                         \
+    ExternalAsciiString::kSize,                                                \
+    medium_external_ascii_string)                                              \
+  V(LONG_EXTERNAL_ASCII_STRING_TYPE,                                           \
+    ExternalAsciiString::kSize,                                                \
+    long_external_ascii_string)
+
+// A struct is a simple object a set of object-valued fields.  Including an
+// object type in this causes the compiler to generate most of the boilerplate
+// code for the class including allocation and garbage collection routines,
+// casts and predicates.  All you need to define is the class, methods and
+// object verification routines.  Easy, no?
+//
+// Note that for subtle reasons related to the ordering or numerical values of
+// type tags, elements in this list have to be added to the INSTANCE_TYPE_LIST
+// manually.
+#define STRUCT_LIST(V)                                                    \
+  V(ACCESSOR_INFO, AccessorInfo, accessor_info)                           \
+  V(ACCESS_CHECK_INFO, AccessCheckInfo, access_check_info)                \
+  V(INTERCEPTOR_INFO, InterceptorInfo, interceptor_info)                  \
+  V(CALL_HANDLER_INFO, CallHandlerInfo, call_handler_info)                \
+  V(FUNCTION_TEMPLATE_INFO, FunctionTemplateInfo, function_template_info) \
+  V(OBJECT_TEMPLATE_INFO, ObjectTemplateInfo, object_template_info)       \
+  V(SIGNATURE_INFO, SignatureInfo, signature_info)                        \
+  V(TYPE_SWITCH_INFO, TypeSwitchInfo, type_switch_info)                   \
+  V(DEBUG_INFO, DebugInfo, debug_info)                                    \
+  V(BREAK_POINT_INFO, BreakPointInfo, break_point_info)                   \
+  V(SCRIPT, Script, script)
+
+
+// We use the full 8 bits of the instance_type field to encode heap object
+// instance types.  The high-order bit (bit 7) is set if the object is not a
+// string, and cleared if it is a string.
+const uint32_t kIsNotStringMask = 0x80;
+const uint32_t kStringTag = 0x0;
+const uint32_t kNotStringTag = 0x80;
+
+// If bit 7 is clear, bit 5 indicates that the string is a symbol (if set) or
+// not (if cleared).
+const uint32_t kIsSymbolMask = 0x20;
+const uint32_t kNotSymbolTag = 0x0;
+const uint32_t kSymbolTag = 0x20;
+
+// If bit 7 is clear, bits 3 and 4 are the string's size (short, medium or
+// long).  These values are very special in that they are also used to shift
+// the length field to get the length, removing the hash value.  This avoids
+// using if or switch when getting the length of a string.
+const uint32_t kStringSizeMask = 0x18;
+const uint32_t kShortStringTag = 0x18;
+const uint32_t kMediumStringTag = 0x10;
+const uint32_t kLongStringTag = 0x00;
+
+// If bit 7 is clear then bit 2 indicates whether the string consists of
+// two-byte characters or one-byte characters.
+const uint32_t kStringEncodingMask = 0x4;
+const uint32_t kTwoByteStringTag = 0x0;
+const uint32_t kAsciiStringTag = 0x4;
+
+// If bit 7 is clear, the low-order 2 bits indicate the representation
+// of the string.
+const uint32_t kStringRepresentationMask = 0x03;
+enum StringRepresentationTag {
+  kSeqStringTag = 0x0,
+  kConsStringTag = 0x1,
+  kSlicedStringTag = 0x2,
+  kExternalStringTag = 0x3
+};
+
+
+// A ConsString with an empty string as the right side is a candidate
+// for being shortcut by the garbage collector unless it is a
+// symbol. It's not common to have non-flat symbols, so we do not
+// shortcut them thereby avoiding turning symbols into strings. See
+// heap.cc and mark-compact.cc.
+const uint32_t kShortcutTypeMask =
+    kIsNotStringMask |
+    kIsSymbolMask |
+    kStringRepresentationMask;
+const uint32_t kShortcutTypeTag = kConsStringTag;
+
+
+enum InstanceType {
+  SHORT_SYMBOL_TYPE = kShortStringTag | kSymbolTag | kSeqStringTag,
+  MEDIUM_SYMBOL_TYPE = kMediumStringTag | kSymbolTag | kSeqStringTag,
+  LONG_SYMBOL_TYPE = kLongStringTag | kSymbolTag | kSeqStringTag,
+  SHORT_ASCII_SYMBOL_TYPE =
+      kShortStringTag | kAsciiStringTag | kSymbolTag | kSeqStringTag,
+  MEDIUM_ASCII_SYMBOL_TYPE =
+      kMediumStringTag | kAsciiStringTag | kSymbolTag | kSeqStringTag,
+  LONG_ASCII_SYMBOL_TYPE =
+      kLongStringTag | kAsciiStringTag | kSymbolTag | kSeqStringTag,
+  SHORT_CONS_SYMBOL_TYPE = kShortStringTag | kSymbolTag | kConsStringTag,
+  MEDIUM_CONS_SYMBOL_TYPE = kMediumStringTag | kSymbolTag | kConsStringTag,
+  LONG_CONS_SYMBOL_TYPE = kLongStringTag | kSymbolTag | kConsStringTag,
+  SHORT_CONS_ASCII_SYMBOL_TYPE =
+      kShortStringTag | kAsciiStringTag | kSymbolTag | kConsStringTag,
+  MEDIUM_CONS_ASCII_SYMBOL_TYPE =
+      kMediumStringTag | kAsciiStringTag | kSymbolTag | kConsStringTag,
+  LONG_CONS_ASCII_SYMBOL_TYPE =
+      kLongStringTag | kAsciiStringTag | kSymbolTag | kConsStringTag,
+  SHORT_SLICED_SYMBOL_TYPE = kShortStringTag | kSymbolTag | kSlicedStringTag,
+  MEDIUM_SLICED_SYMBOL_TYPE = kMediumStringTag | kSymbolTag | kSlicedStringTag,
+  LONG_SLICED_SYMBOL_TYPE = kLongStringTag | kSymbolTag | kSlicedStringTag,
+  SHORT_SLICED_ASCII_SYMBOL_TYPE =
+      kShortStringTag | kAsciiStringTag | kSymbolTag | kSlicedStringTag,
+  MEDIUM_SLICED_ASCII_SYMBOL_TYPE =
+      kMediumStringTag | kAsciiStringTag | kSymbolTag | kSlicedStringTag,
+  LONG_SLICED_ASCII_SYMBOL_TYPE =
+      kLongStringTag | kAsciiStringTag | kSymbolTag | kSlicedStringTag,
+  SHORT_EXTERNAL_SYMBOL_TYPE =
+      kShortStringTag | kSymbolTag | kExternalStringTag,
+  MEDIUM_EXTERNAL_SYMBOL_TYPE =
+      kMediumStringTag | kSymbolTag | kExternalStringTag,
+  LONG_EXTERNAL_SYMBOL_TYPE = kLongStringTag | kSymbolTag | kExternalStringTag,
+  SHORT_EXTERNAL_ASCII_SYMBOL_TYPE =
+      kShortStringTag | kAsciiStringTag | kSymbolTag | kExternalStringTag,
+  MEDIUM_EXTERNAL_ASCII_SYMBOL_TYPE =
+      kMediumStringTag | kAsciiStringTag | kSymbolTag | kExternalStringTag,
+  LONG_EXTERNAL_ASCII_SYMBOL_TYPE =
+      kLongStringTag | kAsciiStringTag | kSymbolTag | kExternalStringTag,
+  SHORT_STRING_TYPE = kShortStringTag | kSeqStringTag,
+  MEDIUM_STRING_TYPE = kMediumStringTag | kSeqStringTag,
+  LONG_STRING_TYPE = kLongStringTag | kSeqStringTag,
+  SHORT_ASCII_STRING_TYPE = kShortStringTag | kAsciiStringTag | kSeqStringTag,
+  MEDIUM_ASCII_STRING_TYPE = kMediumStringTag | kAsciiStringTag | kSeqStringTag,
+  LONG_ASCII_STRING_TYPE = kLongStringTag | kAsciiStringTag | kSeqStringTag,
+  SHORT_CONS_STRING_TYPE = kShortStringTag | kConsStringTag,
+  MEDIUM_CONS_STRING_TYPE = kMediumStringTag | kConsStringTag,
+  LONG_CONS_STRING_TYPE = kLongStringTag | kConsStringTag,
+  SHORT_CONS_ASCII_STRING_TYPE =
+      kShortStringTag | kAsciiStringTag | kConsStringTag,
+  MEDIUM_CONS_ASCII_STRING_TYPE =
+      kMediumStringTag | kAsciiStringTag | kConsStringTag,
+  LONG_CONS_ASCII_STRING_TYPE =
+      kLongStringTag | kAsciiStringTag | kConsStringTag,
+  SHORT_SLICED_STRING_TYPE = kShortStringTag | kSlicedStringTag,
+  MEDIUM_SLICED_STRING_TYPE = kMediumStringTag | kSlicedStringTag,
+  LONG_SLICED_STRING_TYPE = kLongStringTag | kSlicedStringTag,
+  SHORT_SLICED_ASCII_STRING_TYPE =
+      kShortStringTag | kAsciiStringTag | kSlicedStringTag,
+  MEDIUM_SLICED_ASCII_STRING_TYPE =
+      kMediumStringTag | kAsciiStringTag | kSlicedStringTag,
+  LONG_SLICED_ASCII_STRING_TYPE =
+      kLongStringTag | kAsciiStringTag | kSlicedStringTag,
+  SHORT_EXTERNAL_STRING_TYPE = kShortStringTag | kExternalStringTag,
+  MEDIUM_EXTERNAL_STRING_TYPE = kMediumStringTag | kExternalStringTag,
+  LONG_EXTERNAL_STRING_TYPE = kLongStringTag | kExternalStringTag,
+  SHORT_EXTERNAL_ASCII_STRING_TYPE =
+      kShortStringTag | kAsciiStringTag | kExternalStringTag,
+  MEDIUM_EXTERNAL_ASCII_STRING_TYPE =
+      kMediumStringTag | kAsciiStringTag | kExternalStringTag,
+  LONG_EXTERNAL_ASCII_STRING_TYPE =
+      kLongStringTag | kAsciiStringTag | kExternalStringTag,
+  LONG_PRIVATE_EXTERNAL_ASCII_STRING_TYPE = LONG_EXTERNAL_ASCII_STRING_TYPE,
+
+  MAP_TYPE = kNotStringTag,
+  HEAP_NUMBER_TYPE,
+  FIXED_ARRAY_TYPE,
+  CODE_TYPE,
+  ODDBALL_TYPE,
+  PROXY_TYPE,
+  BYTE_ARRAY_TYPE,
+  FILLER_TYPE,
+  SMI_TYPE,
+
+  ACCESSOR_INFO_TYPE,
+  ACCESS_CHECK_INFO_TYPE,
+  INTERCEPTOR_INFO_TYPE,
+  SHARED_FUNCTION_INFO_TYPE,
+  CALL_HANDLER_INFO_TYPE,
+  FUNCTION_TEMPLATE_INFO_TYPE,
+  OBJECT_TEMPLATE_INFO_TYPE,
+  SIGNATURE_INFO_TYPE,
+  TYPE_SWITCH_INFO_TYPE,
+  DEBUG_INFO_TYPE,
+  BREAK_POINT_INFO_TYPE,
+  SCRIPT_TYPE,
+
+  JS_VALUE_TYPE,
+  JS_OBJECT_TYPE,
+  JS_CONTEXT_EXTENSION_OBJECT_TYPE,
+  JS_GLOBAL_OBJECT_TYPE,
+  JS_BUILTINS_OBJECT_TYPE,
+  JS_GLOBAL_PROXY_TYPE,
+  JS_ARRAY_TYPE,
+  JS_REGEXP_TYPE,
+
+  JS_FUNCTION_TYPE,
+
+  // Pseudo-types
+  FIRST_NONSTRING_TYPE = MAP_TYPE,
+  FIRST_TYPE = 0x0,
+  INVALID_TYPE = FIRST_TYPE - 1,
+  LAST_TYPE = JS_FUNCTION_TYPE,
+  // Boundaries for testing the type is a JavaScript "object".  Note that
+  // function objects are not counted as objects, even though they are
+  // implemented as such; only values whose typeof is "object" are included.
+  FIRST_JS_OBJECT_TYPE = JS_VALUE_TYPE,
+  LAST_JS_OBJECT_TYPE = JS_REGEXP_TYPE
+};
+
+
+enum CompareResult {
+  LESS      = -1,
+  EQUAL     =  0,
+  GREATER   =  1,
+
+  NOT_EQUAL = GREATER
+};
+
+
+#define DECL_BOOLEAN_ACCESSORS(name)   \
+  inline bool name();                  \
+  inline void set_##name(bool value);  \
+
+
+#define DECL_ACCESSORS(name, type)                                      \
+  inline type* name();                                                  \
+  inline void set_##name(type* value,                                   \
+                         WriteBarrierMode mode = UPDATE_WRITE_BARRIER); \
+
+
+class StringStream;
+class ObjectVisitor;
+
+struct ValueInfo : public Malloced {
+  ValueInfo() : type(FIRST_TYPE), ptr(NULL), str(NULL), number(0) { }
+  InstanceType type;
+  Object* ptr;
+  const char* str;
+  double number;
+};
+
+
+// A template-ized version of the IsXXX functions.
+template <class C> static inline bool Is(Object* obj);
+
+
+// Object is the abstract superclass for all classes in the
+// object hierarchy.
+// Object does not use any virtual functions to avoid the
+// allocation of the C++ vtable.
+// Since Smi and Failure are subclasses of Object no
+// data members can be present in Object.
+class Object BASE_EMBEDDED {
+ public:
+  // Type testing.
+  inline bool IsSmi();
+  inline bool IsHeapObject();
+  inline bool IsHeapNumber();
+  inline bool IsString();
+  inline bool IsSymbol();
+  inline bool IsSeqString();
+  inline bool IsSlicedString();
+  inline bool IsExternalString();
+  inline bool IsConsString();
+  inline bool IsExternalTwoByteString();
+  inline bool IsExternalAsciiString();
+  inline bool IsSeqTwoByteString();
+  inline bool IsSeqAsciiString();
+
+  inline bool IsNumber();
+  inline bool IsByteArray();
+  inline bool IsFailure();
+  inline bool IsRetryAfterGC();
+  inline bool IsOutOfMemoryFailure();
+  inline bool IsException();
+  inline bool IsJSObject();
+  inline bool IsJSContextExtensionObject();
+  inline bool IsMap();
+  inline bool IsFixedArray();
+  inline bool IsDescriptorArray();
+  inline bool IsContext();
+  inline bool IsCatchContext();
+  inline bool IsGlobalContext();
+  inline bool IsJSFunction();
+  inline bool IsCode();
+  inline bool IsOddball();
+  inline bool IsSharedFunctionInfo();
+  inline bool IsJSValue();
+  inline bool IsStringWrapper();
+  inline bool IsProxy();
+  inline bool IsBoolean();
+  inline bool IsJSArray();
+  inline bool IsJSRegExp();
+  inline bool IsHashTable();
+  inline bool IsDictionary();
+  inline bool IsSymbolTable();
+  inline bool IsCompilationCacheTable();
+  inline bool IsMapCache();
+  inline bool IsLookupCache();
+  inline bool IsPrimitive();
+  inline bool IsGlobalObject();
+  inline bool IsJSGlobalObject();
+  inline bool IsJSBuiltinsObject();
+  inline bool IsJSGlobalProxy();
+  inline bool IsUndetectableObject();
+  inline bool IsAccessCheckNeeded();
+
+  // Returns true if this object is an instance of the specified
+  // function template.
+  bool IsInstanceOf(FunctionTemplateInfo* type);
+
+  inline bool IsStruct();
+#define DECLARE_STRUCT_PREDICATE(NAME, Name, name) inline bool Is##Name();
+  STRUCT_LIST(DECLARE_STRUCT_PREDICATE)
+#undef DECLARE_STRUCT_PREDICATE
+
+  // Oddball testing.
+  INLINE(bool IsUndefined());
+  INLINE(bool IsTheHole());
+  INLINE(bool IsNull());
+  INLINE(bool IsTrue());
+  INLINE(bool IsFalse());
+
+  // Extract the number.
+  inline double Number();
+
+  inline bool HasSpecificClassOf(String* name);
+
+  Object* ToObject();             // ECMA-262 9.9.
+  Object* ToBoolean();            // ECMA-262 9.2.
+
+  // Convert to a JSObject if needed.
+  // global_context is used when creating wrapper object.
+  Object* ToObject(Context* global_context);
+
+  // Converts this to a Smi if possible.
+  // Failure is returned otherwise.
+  inline Object* ToSmi();
+
+  void Lookup(String* name, LookupResult* result);
+
+  // Property access.
+  inline Object* GetProperty(String* key);
+  inline Object* GetProperty(String* key, PropertyAttributes* attributes);
+  Object* GetPropertyWithReceiver(Object* receiver,
+                                  String* key,
+                                  PropertyAttributes* attributes);
+  Object* GetProperty(Object* receiver,
+                      LookupResult* result,
+                      String* key,
+                      PropertyAttributes* attributes);
+  Object* GetPropertyWithCallback(Object* receiver,
+                                  Object* structure,
+                                  String* name,
+                                  Object* holder);
+  Object* GetPropertyWithDefinedGetter(Object* receiver,
+                                       JSFunction* getter);
+
+  inline Object* GetElement(uint32_t index);
+  Object* GetElementWithReceiver(Object* receiver, uint32_t index);
+
+  // Return the object's prototype (might be Heap::null_value()).
+  Object* GetPrototype();
+
+  // Returns true if this is a JSValue containing a string and the index is
+  // < the length of the string.  Used to implement [] on strings.
+  inline bool IsStringObjectWithCharacterAt(uint32_t index);
+
+#ifdef DEBUG
+  // Prints this object with details.
+  void Print();
+  void PrintLn();
+  // Verifies the object.
+  void Verify();
+
+  // Verify a pointer is a valid object pointer.
+  static void VerifyPointer(Object* p);
+#endif
+
+  // Prints this object without details.
+  void ShortPrint();
+
+  // Prints this object without details to a message accumulator.
+  void ShortPrint(StringStream* accumulator);
+
+  // Casting: This cast is only needed to satisfy macros in objects-inl.h.
+  static Object* cast(Object* value) { return value; }
+
+  // Layout description.
+  static const int kHeaderSize = 0;  // Object does not take up any space.
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Object);
+};
+
+
+// Smi represents integer Numbers that can be stored in 31 bits.
+// Smis are immediate which means they are NOT allocated in the heap.
+// The this pointer has the following format: [31 bit signed int] 0
+// Smi stands for small integer.
+class Smi: public Object {
+ public:
+  // Returns the integer value.
+  inline int value();
+
+  // Convert a value to a Smi object.
+  static inline Smi* FromInt(int value);
+
+  // Returns whether value can be represented in a Smi.
+  static inline bool IsValid(int value);
+
+  // Casting.
+  static inline Smi* cast(Object* object);
+
+  // Dispatched behavior.
+  void SmiPrint();
+  void SmiPrint(StringStream* accumulator);
+#ifdef DEBUG
+  void SmiVerify();
+#endif
+
+  // Min and max limits for Smi values.
+  static const int kMinValue = -(1 << (kBitsPerPointer - (kSmiTagSize + 1)));
+  static const int kMaxValue = (1 << (kBitsPerPointer - (kSmiTagSize + 1))) - 1;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Smi);
+};
+
+
+// Failure is used for reporting out of memory situations and
+// propagating exceptions through the runtime system.  Failure objects
+// are transient and cannot occur as part of the objects graph.
+//
+// Failures are a single word, encoded as follows:
+// +-------------------------+---+--+--+
+// |rrrrrrrrrrrrrrrrrrrrrrrrr|sss|tt|11|
+// +-------------------------+---+--+--+
+//
+// The low two bits, 0-1, are the failure tag, 11.  The next two bits,
+// 2-3, are a failure type tag 'tt' with possible values:
+//   00 RETRY_AFTER_GC
+//   01 EXCEPTION
+//   10 INTERNAL_ERROR
+//   11 OUT_OF_MEMORY_EXCEPTION
+//
+// The next three bits, 4-6, are an allocation space tag 'sss'.  The
+// allocation space tag is 000 for all failure types except
+// RETRY_AFTER_GC.  For RETRY_AFTER_GC, the possible values are
+// (the encoding is found in globals.h):
+//   000 NEW_SPACE
+//   001 OLD_SPACE
+//   010 CODE_SPACE
+//   011 MAP_SPACE
+//   100 LO_SPACE
+//
+// The remaining bits is the number of words requested by the
+// allocation request that failed, and is zeroed except for
+// RETRY_AFTER_GC failures.  The 25 bits (on a 32 bit platform) gives
+// a representable range of 2^27 bytes (128MB).
+
+// Failure type tag info.
+const int kFailureTypeTagSize = 2;
+const int kFailureTypeTagMask = (1 << kFailureTypeTagSize) - 1;
+
+class Failure: public Object {
+ public:
+  // RuntimeStubs assumes EXCEPTION = 1 in the compiler-generated code.
+  enum Type {
+    RETRY_AFTER_GC = 0,
+    EXCEPTION = 1,       // Returning this marker tells the real exception
+                         // is in Top::pending_exception.
+    INTERNAL_ERROR = 2,
+    OUT_OF_MEMORY_EXCEPTION = 3
+  };
+
+  inline Type type() const;
+
+  // Returns the space that needs to be collected for RetryAfterGC failures.
+  inline AllocationSpace allocation_space() const;
+
+  // Returns the number of bytes requested (up to the representable maximum)
+  // for RetryAfterGC failures.
+  inline int requested() const;
+
+  inline bool IsInternalError() const;
+  inline bool IsOutOfMemoryException() const;
+
+  static Failure* RetryAfterGC(int requested_bytes, AllocationSpace space);
+  static inline Failure* RetryAfterGC(int requested_bytes);  // NEW_SPACE
+  static inline Failure* Exception();
+  static inline Failure* InternalError();
+  static inline Failure* OutOfMemoryException();
+  // Casting.
+  static inline Failure* cast(Object* object);
+
+  // Dispatched behavior.
+  void FailurePrint();
+  void FailurePrint(StringStream* accumulator);
+#ifdef DEBUG
+  void FailureVerify();
+#endif
+
+ private:
+  inline int value() const;
+  static inline Failure* Construct(Type type, int value = 0);
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Failure);
+};
+
+
+// Heap objects typically have a map pointer in their first word.  However,
+// during GC other data (eg, mark bits, forwarding addresses) is sometimes
+// encoded in the first word.  The class MapWord is an abstraction of the
+// value in a heap object's first word.
+class MapWord BASE_EMBEDDED {
+ public:
+  // Normal state: the map word contains a map pointer.
+
+  // Create a map word from a map pointer.
+  static inline MapWord FromMap(Map* map);
+
+  // View this map word as a map pointer.
+  inline Map* ToMap();
+
+
+  // Scavenge collection: the map word of live objects in the from space
+  // contains a forwarding address (a heap object pointer in the to space).
+
+  // True if this map word is a forwarding address for a scavenge
+  // collection.  Only valid during a scavenge collection (specifically,
+  // when all map words are heap object pointers, ie. not during a full GC).
+  inline bool IsForwardingAddress();
+
+  // Create a map word from a forwarding address.
+  static inline MapWord FromForwardingAddress(HeapObject* object);
+
+  // View this map word as a forwarding address.
+  inline HeapObject* ToForwardingAddress();
+
+
+  // Marking phase of full collection: the map word of live objects is
+  // marked, and may be marked as overflowed (eg, the object is live, its
+  // children have not been visited, and it does not fit in the marking
+  // stack).
+
+  // True if this map word's mark bit is set.
+  inline bool IsMarked();
+
+  // Return this map word but with its mark bit set.
+  inline void SetMark();
+
+  // Return this map word but with its mark bit cleared.
+  inline void ClearMark();
+
+  // True if this map word's overflow bit is set.
+  inline bool IsOverflowed();
+
+  // Return this map word but with its overflow bit set.
+  inline void SetOverflow();
+
+  // Return this map word but with its overflow bit cleared.
+  inline void ClearOverflow();
+
+
+  // Compacting phase of a full compacting collection: the map word of live
+  // objects contains an encoding of the original map address along with the
+  // forwarding address (represented as an offset from the first live object
+  // in the same page as the (old) object address).
+
+  // Create a map word from a map address and a forwarding address offset.
+  static inline MapWord EncodeAddress(Address map_address, int offset);
+
+  // Return the map address encoded in this map word.
+  inline Address DecodeMapAddress(MapSpace* map_space);
+
+  // Return the forwarding offset encoded in this map word.
+  inline int DecodeOffset();
+
+
+  // During serialization: the map word is used to hold an encoded
+  // address, and possibly a mark bit (set and cleared with SetMark
+  // and ClearMark).
+
+  // Create a map word from an encoded address.
+  static inline MapWord FromEncodedAddress(Address address);
+
+  inline Address ToEncodedAddress();
+
+ private:
+  // HeapObject calls the private constructor and directly reads the value.
+  friend class HeapObject;
+
+  explicit MapWord(uintptr_t value) : value_(value) {}
+
+  uintptr_t value_;
+
+  // Bits used by the marking phase of the garbage collector.
+  //
+  // The first word of a heap object is normally a map pointer. The last two
+  // bits are tagged as '01' (kHeapObjectTag). We reuse the last two bits to
+  // mark an object as live and/or overflowed:
+  //   last bit = 0, marked as alive
+  //   second bit = 1, overflowed
+  // An object is only marked as overflowed when it is marked as live while
+  // the marking stack is overflowed.
+  static const int kMarkingBit = 0;  // marking bit
+  static const int kMarkingMask = (1 << kMarkingBit);  // marking mask
+  static const int kOverflowBit = 1;  // overflow bit
+  static const int kOverflowMask = (1 << kOverflowBit);  // overflow mask
+
+  // Forwarding pointers and map pointer encoding
+  //  31             21 20              10 9               0
+  // +-----------------+------------------+-----------------+
+  // |forwarding offset|page offset of map|page index of map|
+  // +-----------------+------------------+-----------------+
+  //  11 bits           11 bits            10 bits
+  static const int kMapPageIndexBits = 10;
+  static const int kMapPageOffsetBits = 11;
+  static const int kForwardingOffsetBits = 11;
+
+  static const int kMapPageIndexShift = 0;
+  static const int kMapPageOffsetShift =
+      kMapPageIndexShift + kMapPageIndexBits;
+  static const int kForwardingOffsetShift =
+      kMapPageOffsetShift + kMapPageOffsetBits;
+
+  // 0x000003FF
+  static const uint32_t kMapPageIndexMask =
+      (1 << kMapPageOffsetShift) - 1;
+
+  // 0x001FFC00
+  static const uint32_t kMapPageOffsetMask =
+      ((1 << kForwardingOffsetShift) - 1) & ~kMapPageIndexMask;
+
+  // 0xFFE00000
+  static const uint32_t kForwardingOffsetMask =
+      ~(kMapPageIndexMask | kMapPageOffsetMask);
+};
+
+
+// HeapObject is the superclass for all classes describing heap allocated
+// objects.
+class HeapObject: public Object {
+ public:
+  // [map]: Contains a map which contains the object's reflective
+  // information.
+  inline Map* map();
+  inline void set_map(Map* value);
+
+  // During garbage collection, the map word of a heap object does not
+  // necessarily contain a map pointer.
+  inline MapWord map_word();
+  inline void set_map_word(MapWord map_word);
+
+  // Converts an address to a HeapObject pointer.
+  static inline HeapObject* FromAddress(Address address);
+
+  // Returns the address of this HeapObject.
+  inline Address address();
+
+  // Iterates over pointers contained in the object (including the Map)
+  void Iterate(ObjectVisitor* v);
+
+  // Iterates over all pointers contained in the object except the
+  // first map pointer.  The object type is given in the first
+  // parameter. This function does not access the map pointer in the
+  // object, and so is safe to call while the map pointer is modified.
+  void IterateBody(InstanceType type, int object_size, ObjectVisitor* v);
+
+  // This method only applies to struct objects.  Iterates over all the fields
+  // of this struct.
+  void IterateStructBody(int object_size, ObjectVisitor* v);
+
+  // Returns the heap object's size in bytes
+  inline int Size();
+
+  // Given a heap object's map pointer, returns the heap size in bytes
+  // Useful when the map pointer field is used for other purposes.
+  // GC internal.
+  inline int SizeFromMap(Map* map);
+
+  // Support for the marking heap objects during the marking phase of GC.
+  // True if the object is marked live.
+  inline bool IsMarked();
+
+  // Mutate this object's map pointer to indicate that the object is live.
+  inline void SetMark();
+
+  // Mutate this object's map pointer to remove the indication that the
+  // object is live (ie, partially restore the map pointer).
+  inline void ClearMark();
+
+  // True if this object is marked as overflowed.  Overflowed objects have
+  // been reached and marked during marking of the heap, but their children
+  // have not necessarily been marked and they have not been pushed on the
+  // marking stack.
+  inline bool IsOverflowed();
+
+  // Mutate this object's map pointer to indicate that the object is
+  // overflowed.
+  inline void SetOverflow();
+
+  // Mutate this object's map pointer to remove the indication that the
+  // object is overflowed (ie, partially restore the map pointer).
+  inline void ClearOverflow();
+
+  // Returns the field at offset in obj, as a read/write Object* reference.
+  // Does no checking, and is safe to use during GC, while maps are invalid.
+  // Does not update remembered sets, so should only be assigned to
+  // during marking GC.
+  static inline Object** RawField(HeapObject* obj, int offset);
+
+  // Casting.
+  static inline HeapObject* cast(Object* obj);
+
+  // Return the write barrier mode for this.
+  inline WriteBarrierMode GetWriteBarrierMode();
+
+  // Dispatched behavior.
+  void HeapObjectShortPrint(StringStream* accumulator);
+#ifdef DEBUG
+  void HeapObjectPrint();
+  void HeapObjectVerify();
+  inline void VerifyObjectField(int offset);
+
+  void PrintHeader(const char* id);
+
+  // Verify a pointer is a valid HeapObject pointer that points to object
+  // areas in the heap.
+  static void VerifyHeapPointer(Object* p);
+#endif
+
+  // Layout description.
+  // First field in a heap object is map.
+  static const int kMapOffset = Object::kHeaderSize;
+  static const int kHeaderSize = kMapOffset + kPointerSize;
+
+ protected:
+  // helpers for calling an ObjectVisitor to iterate over pointers in the
+  // half-open range [start, end) specified as integer offsets
+  inline void IteratePointers(ObjectVisitor* v, int start, int end);
+  // as above, for the single element at "offset"
+  inline void IteratePointer(ObjectVisitor* v, int offset);
+
+  // Computes the object size from the map.
+  // Should only be used from SizeFromMap.
+  int SlowSizeFromMap(Map* map);
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(HeapObject);
+};
+
+
+// The HeapNumber class describes heap allocated numbers that cannot be
+// represented in a Smi (small integer)
+class HeapNumber: public HeapObject {
+ public:
+  // [value]: number value.
+  inline double value();
+  inline void set_value(double value);
+
+  // Casting.
+  static inline HeapNumber* cast(Object* obj);
+
+  // Dispatched behavior.
+  Object* HeapNumberToBoolean();
+  void HeapNumberPrint();
+  void HeapNumberPrint(StringStream* accumulator);
+#ifdef DEBUG
+  void HeapNumberVerify();
+#endif
+
+  // Layout description.
+  static const int kValueOffset = HeapObject::kHeaderSize;
+  static const int kSize = kValueOffset + kDoubleSize;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(HeapNumber);
+};
+
+
+// The JSObject describes real heap allocated JavaScript objects with
+// properties.
+// Note that the map of JSObject changes during execution to enable inline
+// caching.
+class JSObject: public HeapObject {
+ public:
+  // [properties]: Backing storage for properties.
+  // properties is a FixedArray in the fast case, and a Dictionary in the
+  // slow case.
+  DECL_ACCESSORS(properties, FixedArray)  // Get and set fast properties.
+  inline void initialize_properties();
+  inline bool HasFastProperties();
+  inline Dictionary* property_dictionary();  // Gets slow properties.
+
+  // [elements]: The elements (properties with names that are integers).
+  // elements is a FixedArray in the fast case, and a Dictionary in the slow
+  // case.
+  DECL_ACCESSORS(elements, FixedArray)  // Get and set fast elements.
+  inline void initialize_elements();
+  inline bool HasFastElements();
+  inline Dictionary* element_dictionary();  // Gets slow elements.
+
+  Object* SetProperty(String* key,
+                      Object* value,
+                      PropertyAttributes attributes);
+  Object* SetProperty(LookupResult* result,
+                      String* key,
+                      Object* value,
+                      PropertyAttributes attributes);
+  Object* SetPropertyWithFailedAccessCheck(LookupResult* result,
+                                           String* name,
+                                           Object* value);
+  Object* SetPropertyWithCallback(Object* structure,
+                                  String* name,
+                                  Object* value,
+                                  JSObject* holder);
+  Object* SetPropertyWithDefinedSetter(JSFunction* setter,
+                                       Object* value);
+  Object* SetPropertyWithInterceptor(String* name,
+                                     Object* value,
+                                     PropertyAttributes attributes);
+  Object* SetPropertyPostInterceptor(String* name,
+                                     Object* value,
+                                     PropertyAttributes attributes);
+  Object* IgnoreAttributesAndSetLocalProperty(String* key,
+                                              Object* value,
+                                              PropertyAttributes attributes);
+
+  // Sets a property that currently has lazy loading.
+  Object* SetLazyProperty(LookupResult* result,
+                          String* name,
+                          Object* value,
+                          PropertyAttributes attributes);
+
+  // Returns the class name ([[Class]] property in the specification).
+  String* class_name();
+
+  // Retrieve interceptors.
+  InterceptorInfo* GetNamedInterceptor();
+  InterceptorInfo* GetIndexedInterceptor();
+
+  inline PropertyAttributes GetPropertyAttribute(String* name);
+  PropertyAttributes GetPropertyAttributeWithReceiver(JSObject* receiver,
+                                                      String* name);
+  PropertyAttributes GetLocalPropertyAttribute(String* name);
+
+  Object* DefineAccessor(String* name, bool is_getter, JSFunction* fun,
+                         PropertyAttributes attributes);
+  Object* LookupAccessor(String* name, bool is_getter);
+
+  // Used from Object::GetProperty().
+  Object* GetPropertyWithFailedAccessCheck(Object* receiver,
+                                           LookupResult* result,
+                                           String* name,
+                                           PropertyAttributes* attributes);
+  Object* GetPropertyWithInterceptor(JSObject* receiver,
+                                     String* name,
+                                     PropertyAttributes* attributes);
+  Object* GetPropertyPostInterceptor(JSObject* receiver,
+                                     String* name,
+                                     PropertyAttributes* attributes);
+  Object* GetLazyProperty(Object* receiver,
+                          LookupResult* result,
+                          String* name,
+                          PropertyAttributes* attributes);
+
+  bool HasProperty(String* name) {
+    return GetPropertyAttribute(name) != ABSENT;
+  }
+
+  bool HasLocalProperty(String* name) {
+    return GetLocalPropertyAttribute(name) != ABSENT;
+  }
+
+  Object* DeleteProperty(String* name);
+  Object* DeleteElement(uint32_t index);
+  Object* DeleteLazyProperty(LookupResult* result, String* name);
+
+  // Tests for the fast common case for property enumeration.
+  bool IsSimpleEnum();
+
+  // Do we want to keep the elements in fast case when increasing the
+  // capacity?
+  bool ShouldConvertToSlowElements(int new_capacity);
+  // Returns true if the backing storage for the slow-case elements of
+  // this object takes up nearly as much space as a fast-case backing
+  // storage would.  In that case the JSObject should have fast
+  // elements.
+  bool ShouldConvertToFastElements();
+
+  // Return the object's prototype (might be Heap::null_value()).
+  inline Object* GetPrototype();
+
+  // Return the object's hidden properties object. If the object has no hidden
+  // properties and create_if_needed is true, then a new hidden property object
+  // will be allocated. Otherwise the Heap::undefined_value is returned.
+  Object* GetHiddenProperties(bool create_if_needed);
+
+  // Tells whether the index'th element is present.
+  inline bool HasElement(uint32_t index);
+  bool HasElementWithReceiver(JSObject* receiver, uint32_t index);
+  bool HasLocalElement(uint32_t index);
+
+  bool HasElementWithInterceptor(JSObject* receiver, uint32_t index);
+  bool HasElementPostInterceptor(JSObject* receiver, uint32_t index);
+
+  Object* SetFastElement(uint32_t index, Object* value);
+
+  // Set the index'th array element.
+  // A Failure object is returned if GC is needed.
+  Object* SetElement(uint32_t index, Object* value);
+
+  // Returns the index'th element.
+  // The undefined object if index is out of bounds.
+  Object* GetElementWithReceiver(JSObject* receiver, uint32_t index);
+
+  void SetFastElements(FixedArray* elements);
+  Object* SetSlowElements(Object* length);
+
+  // Lookup interceptors are used for handling properties controlled by host
+  // objects.
+  inline bool HasNamedInterceptor();
+  inline bool HasIndexedInterceptor();
+
+  // Support functions for v8 api (needed for correct interceptor behavior).
+  bool HasRealNamedProperty(String* key);
+  bool HasRealElementProperty(uint32_t index);
+  bool HasRealNamedCallbackProperty(String* key);
+
+  // Initializes the array to a certain length
+  Object* SetElementsLength(Object* length);
+
+  // Get the header size for a JSObject.  Used to compute the index of
+  // internal fields as well as the number of internal fields.
+  inline int GetHeaderSize();
+
+  inline int GetInternalFieldCount();
+  inline Object* GetInternalField(int index);
+  inline void SetInternalField(int index, Object* value);
+
+  // Lookup a property.  If found, the result is valid and has
+  // detailed information.
+  void LocalLookup(String* name, LookupResult* result);
+  void Lookup(String* name, LookupResult* result);
+
+  // The following lookup functions skip interceptors.
+  void LocalLookupRealNamedProperty(String* name, LookupResult* result);
+  void LookupRealNamedProperty(String* name, LookupResult* result);
+  void LookupRealNamedPropertyInPrototypes(String* name, LookupResult* result);
+  void LookupCallbackSetterInPrototypes(String* name, LookupResult* result);
+  Object* LookupCallbackSetterInPrototypes(uint32_t index);
+  void LookupCallback(String* name, LookupResult* result);
+
+  // Returns the number of properties on this object filtering out properties
+  // with the specified attributes (ignoring interceptors).
+  int NumberOfLocalProperties(PropertyAttributes filter);
+  // Returns the number of enumerable properties (ignoring interceptors).
+  int NumberOfEnumProperties();
+  // Fill in details for properties into storage starting at the specified
+  // index.
+  void GetLocalPropertyNames(FixedArray* storage, int index);
+
+  // Returns the number of properties on this object filtering out properties
+  // with the specified attributes (ignoring interceptors).
+  int NumberOfLocalElements(PropertyAttributes filter);
+  // Returns the number of enumerable elements (ignoring interceptors).
+  int NumberOfEnumElements();
+  // Returns the number of elements on this object filtering out elements
+  // with the specified attributes (ignoring interceptors).
+  int GetLocalElementKeys(FixedArray* storage, PropertyAttributes filter);
+  // Count and fill in the enumerable elements into storage.
+  // (storage->length() == NumberOfEnumElements()).
+  // If storage is NULL, will count the elements without adding
+  // them to any storage.
+  // Returns the number of enumerable elements.
+  int GetEnumElementKeys(FixedArray* storage);
+
+  // Add a property to a fast-case object using a map transition to
+  // new_map.
+  Object* AddFastPropertyUsingMap(Map* new_map,
+                                  String* name,
+                                  Object* value);
+
+  // Add a constant function property to a fast-case object.
+  // This leaves a CONSTANT_TRANSITION in the old map, and
+  // if it is called on a second object with this map, a
+  // normal property is added instead, with a map transition.
+  // This avoids the creation of many maps with the same constant
+  // function, all orphaned.
+  Object* AddConstantFunctionProperty(String* name,
+                                      JSFunction* function,
+                                      PropertyAttributes attributes);
+
+  Object* ReplaceSlowProperty(String* name,
+                              Object* value,
+                              PropertyAttributes attributes);
+
+  // Converts a descriptor of any other type to a real field,
+  // backed by the properties array.  Descriptors of visible
+  // types, such as CONSTANT_FUNCTION, keep their enumeration order.
+  // Converts the descriptor on the original object's map to a
+  // map transition, and the the new field is on the object's new map.
+  Object* ConvertDescriptorToFieldAndMapTransition(
+      String* name,
+      Object* new_value,
+      PropertyAttributes attributes);
+
+  // Converts a descriptor of any other type to a real field,
+  // backed by the properties array.  Descriptors of visible
+  // types, such as CONSTANT_FUNCTION, keep their enumeration order.
+  Object* ConvertDescriptorToField(String* name,
+                                   Object* new_value,
+                                   PropertyAttributes attributes);
+
+  // Add a property to a fast-case object.
+  Object* AddFastProperty(String* name,
+                          Object* value,
+                          PropertyAttributes attributes);
+
+  // Add a property to a slow-case object.
+  Object* AddSlowProperty(String* name,
+                          Object* value,
+                          PropertyAttributes attributes);
+
+  // Add a property to an object.
+  Object* AddProperty(String* name,
+                      Object* value,
+                      PropertyAttributes attributes);
+
+  // Convert the object to use the canonical dictionary
+  // representation.
+  Object* NormalizeProperties(PropertyNormalizationMode mode);
+  Object* NormalizeElements();
+
+  // Transform slow named properties to fast variants.
+  // Returns failure if allocation failed.
+  Object* TransformToFastProperties(int unused_property_fields);
+
+  // Access fast-case object properties at index.
+  inline Object* FastPropertyAt(int index);
+  inline Object* FastPropertyAtPut(int index, Object* value);
+
+  // Access to in object properties.
+  inline Object* InObjectPropertyAt(int index);
+  inline Object* InObjectPropertyAtPut(int index,
+                                       Object* value,
+                                       WriteBarrierMode mode
+                                       = UPDATE_WRITE_BARRIER);
+
+  // initializes the body after properties slot, properties slot is
+  // initialized by set_properties
+  // Note: this call does not update write barrier, it is caller's
+  // reponsibility to ensure that *v* can be collected without WB here.
+  inline void InitializeBody(int object_size);
+
+  // Check whether this object references another object
+  bool ReferencesObject(Object* obj);
+
+  // Casting.
+  static inline JSObject* cast(Object* obj);
+
+  // Dispatched behavior.
+  void JSObjectIterateBody(int object_size, ObjectVisitor* v);
+  void JSObjectShortPrint(StringStream* accumulator);
+#ifdef DEBUG
+  void JSObjectPrint();
+  void JSObjectVerify();
+  void PrintProperties();
+  void PrintElements();
+
+  // Structure for collecting spill information about JSObjects.
+  class SpillInformation {
+   public:
+    void Clear();
+    void Print();
+    int number_of_objects_;
+    int number_of_objects_with_fast_properties_;
+    int number_of_objects_with_fast_elements_;
+    int number_of_fast_used_fields_;
+    int number_of_fast_unused_fields_;
+    int number_of_slow_used_properties_;
+    int number_of_slow_unused_properties_;
+    int number_of_fast_used_elements_;
+    int number_of_fast_unused_elements_;
+    int number_of_slow_used_elements_;
+    int number_of_slow_unused_elements_;
+  };
+
+  void IncrementSpillStatistics(SpillInformation* info);
+#endif
+  Object* SlowReverseLookup(Object* value);
+
+  static const uint32_t kMaxGap = 1024;
+  static const int kMaxFastElementsLength = 5000;
+  static const int kInitialMaxFastElementArray = 100000;
+  static const int kMaxFastProperties = 8;
+  static const int kMaxInstanceSize = 255 * kPointerSize;
+  // When extending the backing storage for property values, we increase
+  // its size by more than the 1 entry necessary, so sequentially adding fields
+  // to the same object requires fewer allocations and copies.
+  static const int kFieldsAdded = 3;
+
+  // Layout description.
+  static const int kPropertiesOffset = HeapObject::kHeaderSize;
+  static const int kElementsOffset = kPropertiesOffset + kPointerSize;
+  static const int kHeaderSize = kElementsOffset + kPointerSize;
+
+  Object* GetElementWithInterceptor(JSObject* receiver, uint32_t index);
+
+ private:
+  Object* SetElementWithInterceptor(uint32_t index, Object* value);
+  Object* SetElementPostInterceptor(uint32_t index, Object* value);
+
+  Object* GetElementPostInterceptor(JSObject* receiver, uint32_t index);
+
+  Object* DeletePropertyPostInterceptor(String* name);
+  Object* DeletePropertyWithInterceptor(String* name);
+
+  Object* DeleteElementPostInterceptor(uint32_t index);
+  Object* DeleteElementWithInterceptor(uint32_t index);
+
+  PropertyAttributes GetPropertyAttributePostInterceptor(JSObject* receiver,
+                                                         String* name,
+                                                         bool continue_search);
+  PropertyAttributes GetPropertyAttributeWithInterceptor(JSObject* receiver,
+                                                         String* name,
+                                                         bool continue_search);
+  PropertyAttributes GetPropertyAttributeWithFailedAccessCheck(
+      Object* receiver,
+      LookupResult* result,
+      String* name,
+      bool continue_search);
+  PropertyAttributes GetPropertyAttribute(JSObject* receiver,
+                                          LookupResult* result,
+                                          String* name,
+                                          bool continue_search);
+
+  // Returns true if most of the elements backing storage is used.
+  bool HasDenseElements();
+
+  Object* DefineGetterSetter(String* name, PropertyAttributes attributes);
+
+  void LookupInDescriptor(String* name, LookupResult* result);
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(JSObject);
+};
+
+
+// Abstract super class arrays. It provides length behavior.
+class Array: public HeapObject {
+ public:
+  // [length]: length of the array.
+  inline int length();
+  inline void set_length(int value);
+
+  // Convert an object to an array index.
+  // Returns true if the conversion succeeded.
+  static inline bool IndexFromObject(Object* object, uint32_t* index);
+
+  // Layout descriptor.
+  static const int kLengthOffset = HeapObject::kHeaderSize;
+  static const int kHeaderSize = kLengthOffset + kIntSize;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Array);
+};
+
+
+// FixedArray describes fixed sized arrays where element
+// type is Object*.
+
+class FixedArray: public Array {
+ public:
+
+  // Setter and getter for elements.
+  inline Object* get(int index);
+  // Setter that uses write barrier.
+  inline void set(int index, Object* value);
+
+  // Setter that doesn't need write barrier).
+  inline void set(int index, Smi* value);
+  // Setter with explicit barrier mode.
+  inline void set(int index, Object* value, WriteBarrierMode mode);
+
+  // Setters for frequently used oddballs located in old space.
+  inline void set_undefined(int index);
+  inline void set_null(int index);
+  inline void set_the_hole(int index);
+
+  // Copy operations.
+  inline Object* Copy();
+  Object* CopySize(int new_length);
+
+  // Add the elements of a JSArray to this FixedArray.
+  Object* AddKeysFromJSArray(JSArray* array);
+
+  // Compute the union of this and other.
+  Object* UnionOfKeys(FixedArray* other);
+
+  // Copy a sub array from the receiver to dest.
+  void CopyTo(int pos, FixedArray* dest, int dest_pos, int len);
+
+  // Garbage collection support.
+  static int SizeFor(int length) { return kHeaderSize + length * kPointerSize; }
+
+  // Casting.
+  static inline FixedArray* cast(Object* obj);
+
+  // Dispatched behavior.
+  int FixedArraySize() { return SizeFor(length()); }
+  void FixedArrayIterateBody(ObjectVisitor* v);
+#ifdef DEBUG
+  void FixedArrayPrint();
+  void FixedArrayVerify();
+  // Checks if two FixedArrays have identical contents.
+  bool IsEqualTo(FixedArray* other);
+#endif
+
+  // Swap two elements.
+  void Swap(int i, int j);
+
+  // Sort this array and the smis as pairs wrt. the smis.
+  void SortPairs(FixedArray* smis);
+
+ protected:
+  // Set operation on FixedArray without using write barriers.
+  static inline void fast_set(FixedArray* array, int index, Object* value);
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray);
+};
+
+
+// DescriptorArrays are fixed arrays used to hold instance descriptors.
+// The format of the these objects is:
+//   [0]: point to a fixed array with (value, detail) pairs.
+//   [1]: next enumeration index (Smi), or pointer to small fixed array:
+//          [0]: next enumeration index (Smi)
+//          [1]: pointer to fixed array with enum cache
+//   [2]: first key
+//   [length() - 1]: last key
+//
+class DescriptorArray: public FixedArray {
+ public:
+  // Is this the singleton empty_descriptor_array?
+  inline bool IsEmpty();
+  // Returns the number of descriptors in the array.
+  int number_of_descriptors() {
+    return IsEmpty() ? 0 : length() - kFirstIndex;
+  }
+
+  int NextEnumerationIndex() {
+    if (IsEmpty()) return PropertyDetails::kInitialIndex;
+    Object* obj = get(kEnumerationIndexIndex);
+    if (obj->IsSmi()) {
+      return Smi::cast(obj)->value();
+    } else {
+      Object* index = FixedArray::cast(obj)->get(kEnumCacheBridgeEnumIndex);
+      return Smi::cast(index)->value();
+    }
+  }
+
+  // Set next enumeration index and flush any enum cache.
+  void SetNextEnumerationIndex(int value) {
+    if (!IsEmpty()) {
+      fast_set(this, kEnumerationIndexIndex, Smi::FromInt(value));
+    }
+  }
+  bool HasEnumCache() {
+    return !IsEmpty() && !get(kEnumerationIndexIndex)->IsSmi();
+  }
+
+  Object* GetEnumCache() {
+    ASSERT(HasEnumCache());
+    FixedArray* bridge = FixedArray::cast(get(kEnumerationIndexIndex));
+    return bridge->get(kEnumCacheBridgeCacheIndex);
+  }
+
+  // Initialize or change the enum cache,
+  // using the supplied storage for the small "bridge".
+  void SetEnumCache(FixedArray* bridge_storage, FixedArray* new_cache);
+
+  // Accessors for fetching instance descriptor at descriptor number..
+  inline String* GetKey(int descriptor_number);
+  inline Object* GetValue(int descriptor_number);
+  inline Smi* GetDetails(int descriptor_number);
+
+  // Accessor for complete descriptor.
+  inline void Get(int descriptor_number, Descriptor* desc);
+  inline void Set(int descriptor_number, Descriptor* desc);
+
+  // Copy the descriptor array, insert a new descriptor and optionally
+  // remove map transitions.  If the descriptor is already present, it is
+  // replaced.  If a replaced descriptor is a real property (not a transition
+  // or null), its enumeration index is kept as is.
+  // If adding a real property, map transitions must be removed.  If adding
+  // a transition, they must not be removed.  All null descriptors are removed.
+  Object* CopyInsert(Descriptor* descriptor, TransitionFlag transition_flag);
+
+  // Remove all transitions.  Return  a copy of the array with all transitions
+  // removed, or a Failure object if the new array could not be allocated.
+  Object* RemoveTransitions();
+
+  // Sort the instance descriptors by the hash codes of their keys.
+  void Sort();
+
+  // Search the instance descriptors for given name.
+  inline int Search(String* name);
+
+  // Tells whether the name is present int the array.
+  bool Contains(String* name) { return kNotFound != Search(name); }
+
+  // Perform a binary search in the instance descriptors represented
+  // by this fixed array.  low and high are descriptor indices.  If there
+  // are three instance descriptors in this array it should be called
+  // with low=0 and high=2.
+  int BinarySearch(String* name, int low, int high);
+
+  // Perform a linear search in the instance descriptors represented
+  // by this fixed array.  len is the number of descriptor indices that are
+  // valid.  Does not require the descriptors to be sorted.
+  int LinearSearch(String* name, int len);
+
+  // Allocates a DescriptorArray, but returns the singleton
+  // empty descriptor array object if number_of_descriptors is 0.
+  static Object* Allocate(int number_of_descriptors);
+
+  // Casting.
+  static inline DescriptorArray* cast(Object* obj);
+
+  // Constant for denoting key was not found.
+  static const int kNotFound = -1;
+
+  static const int kContentArrayIndex = 0;
+  static const int kEnumerationIndexIndex = 1;
+  static const int kFirstIndex = 2;
+
+  // The length of the "bridge" to the enum cache.
+  static const int kEnumCacheBridgeLength = 2;
+  static const int kEnumCacheBridgeEnumIndex = 0;
+  static const int kEnumCacheBridgeCacheIndex = 1;
+
+  // Layout description.
+  static const int kContentArrayOffset = FixedArray::kHeaderSize;
+  static const int kEnumerationIndexOffset = kContentArrayOffset + kPointerSize;
+  static const int kFirstOffset = kEnumerationIndexOffset + kPointerSize;
+
+  // Layout description for the bridge array.
+  static const int kEnumCacheBridgeEnumOffset = FixedArray::kHeaderSize;
+  static const int kEnumCacheBridgeCacheOffset =
+    kEnumCacheBridgeEnumOffset + kPointerSize;
+
+#ifdef DEBUG
+  // Print all the descriptors.
+  void PrintDescriptors();
+
+  // Is the descriptor array sorted and without duplicates?
+  bool IsSortedNoDuplicates();
+
+  // Are two DescriptorArrays equal?
+  bool IsEqualTo(DescriptorArray* other);
+#endif
+
+  // The maximum number of descriptors we want in a descriptor array (should
+  // fit in a page).
+  static const int kMaxNumberOfDescriptors = 1024 + 512;
+
+ private:
+  // Conversion from descriptor number to array indices.
+  static int ToKeyIndex(int descriptor_number) {
+    return descriptor_number+kFirstIndex;
+  }
+  static int ToValueIndex(int descriptor_number) {
+    return descriptor_number << 1;
+  }
+  static int ToDetailsIndex(int descriptor_number) {
+    return( descriptor_number << 1) + 1;
+  }
+
+  bool is_null_descriptor(int descriptor_number) {
+    return PropertyDetails(GetDetails(descriptor_number)).type() ==
+        NULL_DESCRIPTOR;
+  }
+  // Swap operation on FixedArray without using write barriers.
+  static inline void fast_swap(FixedArray* array, int first, int second);
+
+  // Swap descriptor first and second.
+  inline void Swap(int first, int second);
+
+  FixedArray* GetContentArray() {
+    return FixedArray::cast(get(kContentArrayIndex));
+  }
+  DISALLOW_IMPLICIT_CONSTRUCTORS(DescriptorArray);
+};
+
+
+// HashTable is a subclass of FixedArray that implements a hash table
+// that uses open addressing and quadratic probing.
+//
+// In order for the quadratic probing to work, elements that have not
+// yet been used and elements that have been deleted are
+// distinguished.  Probing continues when deleted elements are
+// encountered and stops when unused elements are encountered.
+//
+// - Elements with key == undefined have not been used yet.
+// - Elements with key == null have been deleted.
+//
+// The hash table class is parameterized with a prefix size and with
+// the size, including the key size, of the elements held in the hash
+// table.  The prefix size indicates an amount of memory in the
+// beginning of the backing storage that can be used for non-element
+// information by subclasses.
+
+// HashTableKey is an abstract superclass keys.
+class HashTableKey {
+ public:
+  // Returns whether the other object matches this key.
+  virtual bool IsMatch(Object* other) = 0;
+  typedef uint32_t (*HashFunction)(Object* obj);
+  // Returns the hash function used for this key.
+  virtual HashFunction GetHashFunction() = 0;
+  // Returns the hash value for this key.
+  virtual uint32_t Hash() = 0;
+  // Returns the key object for storing into the dictionary.
+  // If allocations fails a failure object is returned.
+  virtual Object* GetObject() = 0;
+  virtual bool IsStringKey() = 0;
+  // Required.
+  virtual ~HashTableKey() {}
+};
+
+
+template<int prefix_size, int element_size>
+class HashTable: public FixedArray {
+ public:
+  // Returns the number of elements in the dictionary.
+  int NumberOfElements() {
+    return Smi::cast(get(kNumberOfElementsIndex))->value();
+  }
+
+  // Returns the capacity of the dictionary.
+  int Capacity() {
+    return Smi::cast(get(kCapacityIndex))->value();
+  }
+
+  // ElementAdded should be called whenever an element is added to a
+  // dictionary.
+  void ElementAdded() { SetNumberOfElements(NumberOfElements() + 1); }
+
+  // ElementRemoved should be called whenever an element is removed from
+  // a dictionary.
+  void ElementRemoved() { SetNumberOfElements(NumberOfElements() - 1); }
+  void ElementsRemoved(int n) { SetNumberOfElements(NumberOfElements() - n); }
+
+  // Returns a new array for dictionary usage. Might return Failure.
+  static Object* Allocate(int at_least_space_for);
+
+  // Returns the key at entry.
+  Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
+
+  // Tells whether k is a real key.  Null and undefined are not allowed
+  // as keys and can be used to indicate missing or deleted elements.
+  bool IsKey(Object* k) {
+    return !k->IsNull() && !k->IsUndefined();
+  }
+
+  // Garbage collection support.
+  void IteratePrefix(ObjectVisitor* visitor);
+  void IterateElements(ObjectVisitor* visitor);
+
+  // Casting.
+  static inline HashTable* cast(Object* obj);
+
+  // Compute the probe offset (quadratic probing).
+  INLINE(static uint32_t GetProbeOffset(uint32_t n)) {
+    return (n + n * n) >> 1;
+  }
+
+  static const int kNumberOfElementsIndex = 0;
+  static const int kCapacityIndex         = 1;
+  static const int kPrefixStartIndex      = 2;
+  static const int kElementsStartIndex    = kPrefixStartIndex + prefix_size;
+  static const int kElementSize           = element_size;
+  static const int kElementsStartOffset   =
+      kHeaderSize + kElementsStartIndex * kPointerSize;
+
+ protected:
+  // Find entry for key otherwise return -1.
+  int FindEntry(HashTableKey* key);
+
+  // Find the entry at which to insert element with the given key that
+  // has the given hash value.
+  uint32_t FindInsertionEntry(Object* key, uint32_t hash);
+
+  // Returns the index for an entry (of the key)
+  static inline int EntryToIndex(int entry) {
+    return (entry * kElementSize) + kElementsStartIndex;
+  }
+
+  // Update the number of elements in the dictionary.
+  void SetNumberOfElements(int nof) {
+    fast_set(this, kNumberOfElementsIndex, Smi::FromInt(nof));
+  }
+
+  // Sets the capacity of the hash table.
+  void SetCapacity(int capacity) {
+    // To scale a computed hash code to fit within the hash table, we
+    // use bit-wise AND with a mask, so the capacity must be positive
+    // and non-zero.
+    ASSERT(capacity > 0);
+    fast_set(this, kCapacityIndex, Smi::FromInt(capacity));
+  }
+
+
+  // Returns probe entry.
+  static uint32_t GetProbe(uint32_t hash, uint32_t number, uint32_t size) {
+    ASSERT(IsPowerOf2(size));
+    return (hash + GetProbeOffset(number)) & (size - 1);
+  }
+
+  // Ensure enough space for n additional elements.
+  Object* EnsureCapacity(int n, HashTableKey* key);
+};
+
+
+// SymbolTable.
+//
+// No special elements in the prefix and the element size is 1
+// because only the symbol itself (the key) needs to be stored.
+class SymbolTable: public HashTable<0, 1> {
+ public:
+  // Find symbol in the symbol table.  If it is not there yet, it is
+  // added.  The return value is the symbol table which might have
+  // been enlarged.  If the return value is not a failure, the symbol
+  // pointer *s is set to the symbol found.
+  Object* LookupSymbol(Vector<const char> str, Object** s);
+  Object* LookupString(String* key, Object** s);
+
+  // Looks up a symbol that is equal to the given string and returns
+  // true if it is found, assigning the symbol to the given output
+  // parameter.
+  bool LookupSymbolIfExists(String* str, String** symbol);
+
+  // Casting.
+  static inline SymbolTable* cast(Object* obj);
+
+ private:
+  Object* LookupKey(HashTableKey* key, Object** s);
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(SymbolTable);
+};
+
+
+// MapCache.
+//
+// Maps keys that are a fixed array of symbols to a map.
+// Used for canonicalize maps for object literals.
+class MapCache: public HashTable<0, 2> {
+ public:
+  // Find cached value for a string key, otherwise return null.
+  Object* Lookup(FixedArray* key);
+  Object* Put(FixedArray* key, Map* value);
+  static inline MapCache* cast(Object* obj);
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(MapCache);
+};
+
+
+// LookupCache.
+//
+// Maps a key consisting of a map and a name to an index within a
+// fast-case properties array.
+//
+// LookupCaches are used to avoid repeatedly searching instance
+// descriptors.
+class LookupCache: public HashTable<0, 2> {
+ public:
+  int Lookup(Map* map, String* name);
+  Object* Put(Map* map, String* name, int offset);
+  static inline LookupCache* cast(Object* obj);
+
+  // Constant returned by Lookup when the key was not found.
+  static const int kNotFound = -1;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(LookupCache);
+};
+
+
+// Dictionary for keeping properties and elements in slow case.
+//
+// One element in the prefix is used for storing non-element
+// information about the dictionary.
+//
+// The rest of the array embeds triples of (key, value, details).
+// if key == undefined the triple is empty.
+// if key == null the triple has been deleted.
+// otherwise key contains the name of a property.
+class DictionaryBase: public HashTable<2, 3> {};
+
+class Dictionary: public DictionaryBase {
+ public:
+  // Returns the value at entry.
+  Object* ValueAt(int entry) { return get(EntryToIndex(entry)+1); }
+
+  // Set the value for entry.
+  void ValueAtPut(int entry, Object* value) {
+    set(EntryToIndex(entry)+1, value);
+  }
+
+  // Returns the property details for the property at entry.
+  PropertyDetails DetailsAt(int entry) {
+    return PropertyDetails(Smi::cast(get(EntryToIndex(entry) + 2)));
+  }
+
+  // Set the details for entry.
+  void DetailsAtPut(int entry, PropertyDetails value) {
+    set(EntryToIndex(entry) + 2, value.AsSmi());
+  }
+
+  // Remove all entries were key is a number and (from <= key && key < to).
+  void RemoveNumberEntries(uint32_t from, uint32_t to);
+
+  // Sorting support
+  Object* RemoveHoles();
+  void CopyValuesTo(FixedArray* elements);
+
+  // Casting.
+  static inline Dictionary* cast(Object* obj);
+
+  // Find entry for string key otherwise return -1.
+  int FindStringEntry(String* key);
+
+  // Find entry for number key otherwise return -1.
+  int FindNumberEntry(uint32_t index);
+
+  // Delete a property from the dictionary.
+  Object* DeleteProperty(int entry);
+
+  // Type specific at put (default NONE attributes is used when adding).
+  Object* AtStringPut(String* key, Object* value);
+  Object* AtNumberPut(uint32_t key, Object* value);
+
+  Object* AddStringEntry(String* key, Object* value, PropertyDetails details);
+  Object* AddNumberEntry(uint32_t key, Object* value, PropertyDetails details);
+
+  // Set an existing entry or add a new one if needed.
+  Object* SetOrAddStringEntry(String* key,
+                              Object* value,
+                              PropertyDetails details);
+
+  Object* SetOrAddNumberEntry(uint32_t key,
+                              Object* value,
+                              PropertyDetails details);
+
+  // Returns the number of elements in the dictionary filtering out properties
+  // with the specified attributes.
+  int NumberOfElementsFilterAttributes(PropertyAttributes filter);
+
+  // Returns the number of enumerable elements in the dictionary.
+  int NumberOfEnumElements();
+
+  // Copies keys to preallocated fixed array.
+  void CopyKeysTo(FixedArray* storage, PropertyAttributes filter);
+  // Copies enumerable keys to preallocated fixed array.
+  void CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array);
+  // Fill in details for properties into storage.
+  void CopyKeysTo(FixedArray* storage);
+
+  // For transforming properties of a JSObject.
+  Object* TransformPropertiesToFastFor(JSObject* obj,
+                                       int unused_property_fields);
+
+  // If slow elements are required we will never go back to fast-case
+  // for the elements kept in this dictionary.  We require slow
+  // elements if an element has been added at an index larger than
+  // kRequiresSlowElementsLimit or set_requires_slow_elements() has been called
+  // when defining a getter or setter with a number key.
+  inline bool requires_slow_elements();
+  inline void set_requires_slow_elements();
+
+  // Get the value of the max number key that has been added to this
+  // dictionary.  max_number_key can only be called if
+  // requires_slow_elements returns false.
+  inline uint32_t max_number_key();
+
+  // Accessors for next enumeration index.
+  void SetNextEnumerationIndex(int index) {
+    fast_set(this, kNextEnumerationIndexIndex, Smi::FromInt(index));
+  }
+
+  int NextEnumerationIndex() {
+    return Smi::cast(get(kNextEnumerationIndexIndex))->value();
+  }
+
+  // Returns a new array for dictionary usage. Might return Failure.
+  static Object* Allocate(int at_least_space_for);
+
+  // Ensure enough space for n additional elements.
+  Object* EnsureCapacity(int n, HashTableKey* key);
+
+#ifdef DEBUG
+  void Print();
+#endif
+  // Returns the key (slow).
+  Object* SlowReverseLookup(Object* value);
+
+  // Bit masks.
+  static const int kRequiresSlowElementsMask = 1;
+  static const int kRequiresSlowElementsTagSize = 1;
+  static const uint32_t kRequiresSlowElementsLimit = (1 << 29) - 1;
+
+  void UpdateMaxNumberKey(uint32_t key);
+
+ private:
+  // Generic at put operation.
+  Object* AtPut(HashTableKey* key, Object* value);
+
+  Object* Add(HashTableKey* key, Object* value, PropertyDetails details);
+
+  // Add entry to dictionary.
+  void AddEntry(Object* key,
+                Object* value,
+                PropertyDetails details,
+                uint32_t hash);
+
+  // Sets the entry to (key, value) pair.
+  inline void SetEntry(int entry,
+                       Object* key,
+                       Object* value,
+                       PropertyDetails details);
+
+  // Generate new enumeration indices to avoid enumeration index overflow.
+  Object* GenerateNewEnumerationIndices();
+
+  static const int kMaxNumberKeyIndex = kPrefixStartIndex;
+  static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Dictionary);
+};
+
+
+// ByteArray represents fixed sized byte arrays.  Used by the outside world,
+// such as PCRE, and also by the memory allocator and garbage collector to
+// fill in free blocks in the heap.
+class ByteArray: public Array {
+ public:
+  // Setter and getter.
+  inline byte get(int index);
+  inline void set(int index, byte value);
+
+  // Treat contents as an int array.
+  inline int get_int(int index);
+
+  static int SizeFor(int length) {
+    return kHeaderSize + OBJECT_SIZE_ALIGN(length);
+  }
+  // We use byte arrays for free blocks in the heap.  Given a desired size in
+  // bytes that is a multiple of the word size and big enough to hold a byte
+  // array, this function returns the number of elements a byte array should
+  // have.
+  static int LengthFor(int size_in_bytes) {
+    ASSERT(IsAligned(size_in_bytes, kPointerSize));
+    ASSERT(size_in_bytes >= kHeaderSize);
+    return size_in_bytes - kHeaderSize;
+  }
+
+  // Returns data start address.
+  inline Address GetDataStartAddress();
+
+  // Returns a pointer to the ByteArray object for a given data start address.
+  static inline ByteArray* FromDataStartAddress(Address address);
+
+  // Casting.
+  static inline ByteArray* cast(Object* obj);
+
+  // Dispatched behavior.
+  int ByteArraySize() { return SizeFor(length()); }
+#ifdef DEBUG
+  void ByteArrayPrint();
+  void ByteArrayVerify();
+#endif
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArray);
+};
+
+
+// Code describes objects with on-the-fly generated machine code.
+class Code: public HeapObject {
+ public:
+  // Opaque data type for encapsulating code flags like kind, inline
+  // cache state, and arguments count.
+  enum Flags { };
+
+  enum Kind {
+    FUNCTION,
+    STUB,
+    BUILTIN,
+    LOAD_IC,
+    KEYED_LOAD_IC,
+    CALL_IC,
+    STORE_IC,
+    KEYED_STORE_IC,
+    // No more than eight kinds. The value currently encoded in three bits in
+    // Flags.
+
+    // Pseudo-kinds.
+    REGEXP = BUILTIN,
+    FIRST_IC_KIND = LOAD_IC,
+    LAST_IC_KIND = KEYED_STORE_IC
+  };
+
+  enum {
+    NUMBER_OF_KINDS = KEYED_STORE_IC + 1
+  };
+
+  // A state indicates that inline cache in this Code object contains
+  // objects or relative instruction addresses.
+  enum ICTargetState {
+    IC_TARGET_IS_ADDRESS,
+    IC_TARGET_IS_OBJECT
+  };
+
+#ifdef ENABLE_DISASSEMBLER
+  // Printing
+  static const char* Kind2String(Kind kind);
+  static const char* ICState2String(InlineCacheState state);
+  void Disassemble(const char* name);
+#endif  // ENABLE_DISASSEMBLER
+
+  // [instruction_size]: Size of the native instructions
+  inline int instruction_size();
+  inline void set_instruction_size(int value);
+
+  // [relocation_size]: Size of relocation information.
+  inline int relocation_size();
+  inline void set_relocation_size(int value);
+
+  // [sinfo_size]: Size of scope information.
+  inline int sinfo_size();
+  inline void set_sinfo_size(int value);
+
+  // [flags]: Various code flags.
+  inline Flags flags();
+  inline void set_flags(Flags flags);
+
+  // [flags]: Access to specific code flags.
+  inline Kind kind();
+  inline InlineCacheState ic_state();  // only valid for IC stubs
+  inline PropertyType type();  // only valid for monomorphic IC stubs
+  inline int arguments_count();  // only valid for call IC stubs
+
+  // Testers for IC stub kinds.
+  inline bool is_inline_cache_stub();
+  inline bool is_load_stub() { return kind() == LOAD_IC; }
+  inline bool is_keyed_load_stub() { return kind() == KEYED_LOAD_IC; }
+  inline bool is_store_stub() { return kind() == STORE_IC; }
+  inline bool is_keyed_store_stub() { return kind() == KEYED_STORE_IC; }
+  inline bool is_call_stub() { return kind() == CALL_IC; }
+
+  // [ic_flag]: State of inline cache targets. The flag is set to the
+  // object variant in ConvertICTargetsFromAddressToObject, and set to
+  // the address variant in ConvertICTargetsFromObjectToAddress.
+  inline ICTargetState ic_flag();
+  inline void set_ic_flag(ICTargetState value);
+
+  // [major_key]: For kind STUB, the major key.
+  inline CodeStub::Major major_key();
+  inline void set_major_key(CodeStub::Major major);
+
+  // Flags operations.
+  static inline Flags ComputeFlags(Kind kind,
+                                   InlineCacheState ic_state = UNINITIALIZED,
+                                   PropertyType type = NORMAL,
+                                   int argc = -1);
+
+  static inline Flags ComputeMonomorphicFlags(Kind kind,
+                                              PropertyType type,
+                                              int argc = -1);
+
+  static inline Kind ExtractKindFromFlags(Flags flags);
+  static inline InlineCacheState ExtractICStateFromFlags(Flags flags);
+  static inline PropertyType ExtractTypeFromFlags(Flags flags);
+  static inline int ExtractArgumentsCountFromFlags(Flags flags);
+  static inline Flags RemoveTypeFromFlags(Flags flags);
+
+  // Convert a target address into a code object.
+  static inline Code* GetCodeFromTargetAddress(Address address);
+
+  // Returns the address of the first instruction.
+  inline byte* instruction_start();
+
+  // Returns the size of the instructions, padding, and relocation information.
+  inline int body_size();
+
+  // Returns the address of the first relocation info (read backwards!).
+  inline byte* relocation_start();
+
+  // Code entry point.
+  inline byte* entry();
+
+  // Returns true if pc is inside this object's instructions.
+  inline bool contains(byte* pc);
+
+  // Returns the address of the scope information.
+  inline byte* sinfo_start();
+
+  // Convert inline cache target from address to code object before GC.
+  void ConvertICTargetsFromAddressToObject();
+
+  // Convert inline cache target from code object to address after GC
+  void ConvertICTargetsFromObjectToAddress();
+
+  // Relocate the code by delta bytes. Called to signal that this code
+  // object has been moved by delta bytes.
+  void Relocate(int delta);
+
+  // Migrate code described by desc.
+  void CopyFrom(const CodeDesc& desc);
+
+  // Returns the object size for a given body and sinfo size (Used for
+  // allocation).
+  static int SizeFor(int body_size, int sinfo_size) {
+    ASSERT_SIZE_TAG_ALIGNED(body_size);
+    ASSERT_SIZE_TAG_ALIGNED(sinfo_size);
+    return RoundUp(kHeaderSize + body_size + sinfo_size, kCodeAlignment);
+  }
+
+  // Calculate the size of the code object to report for log events. This takes
+  // the layout of the code object into account.
+  int ExecutableSize() {
+    // Check that the assumptions about the layout of the code object holds.
+    ASSERT_EQ(reinterpret_cast<unsigned int>(instruction_start()) -
+              reinterpret_cast<unsigned int>(address()),
+              Code::kHeaderSize);
+    return instruction_size() + Code::kHeaderSize;
+  }
+
+  // Locating source position.
+  int SourcePosition(Address pc);
+  int SourceStatementPosition(Address pc);
+
+  // Casting.
+  static inline Code* cast(Object* obj);
+
+  // Dispatched behavior.
+  int CodeSize() { return SizeFor(body_size(), sinfo_size()); }
+  void CodeIterateBody(ObjectVisitor* v);
+#ifdef DEBUG
+  void CodePrint();
+  void CodeVerify();
+#endif
+
+  // Layout description.
+  static const int kInstructionSizeOffset = HeapObject::kHeaderSize;
+  static const int kRelocationSizeOffset = kInstructionSizeOffset + kIntSize;
+  static const int kSInfoSizeOffset = kRelocationSizeOffset + kIntSize;
+  static const int kFlagsOffset = kSInfoSizeOffset + kIntSize;
+  static const int kKindSpecificFlagsOffset  = kFlagsOffset + kIntSize;
+  // Add filler objects to align the instruction start following right after
+  // the Code object header.
+  static const int kFiller6Offset = kKindSpecificFlagsOffset + kIntSize;
+  static const int kFiller7Offset = kFiller6Offset + kIntSize;
+  static const int kHeaderSize = kFiller7Offset + kIntSize;
+
+  // Code entry points are aligned to 32 bytes.
+  static const int kCodeAlignment = 32;
+
+  // Byte offsets within kKindSpecificFlagsOffset.
+  static const int kICFlagOffset = kKindSpecificFlagsOffset + 0;
+  static const int kStubMajorKeyOffset = kKindSpecificFlagsOffset + 1;
+
+  // Flags layout.
+  static const int kFlagsICStateShift        = 0;
+  static const int kFlagsKindShift           = 3;
+  static const int kFlagsTypeShift           = 6;
+  static const int kFlagsArgumentsCountShift = 9;
+
+  static const int kFlagsICStateMask        = 0x00000007;  // 000000111
+  static const int kFlagsKindMask           = 0x00000038;  // 000111000
+  static const int kFlagsTypeMask           = 0x000001C0;  // 111000000
+  static const int kFlagsArgumentsCountMask = 0xFFFFFE00;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Code);
+};
+
+
+// All heap objects have a Map that describes their structure.
+//  A Map contains information about:
+//  - Size information about the object
+//  - How to iterate over an object (for garbage collection)
+class Map: public HeapObject {
+ public:
+  // Instance size.
+  inline int instance_size();
+  inline void set_instance_size(int value);
+
+  // Count of properties allocated in the object.
+  inline int inobject_properties();
+  inline void set_inobject_properties(int value);
+
+  // Instance type.
+  inline InstanceType instance_type();
+  inline void set_instance_type(InstanceType value);
+
+  // Tells how many unused property fields are available in the
+  // instance (only used for JSObject in fast mode).
+  inline int unused_property_fields();
+  inline void set_unused_property_fields(int value);
+
+  // Bit field.
+  inline byte bit_field();
+  inline void set_bit_field(byte value);
+
+  // Tells whether the object in the prototype property will be used
+  // for instances created from this function.  If the prototype
+  // property is set to a value that is not a JSObject, the prototype
+  // property will not be used to create instances of the function.
+  // See ECMA-262, 13.2.2.
+  inline void set_non_instance_prototype(bool value);
+  inline bool has_non_instance_prototype();
+
+  // Tells whether the instance with this map should be ignored by the
+  // __proto__ accessor.
+  inline void set_is_hidden_prototype() {
+    set_bit_field(bit_field() | (1 << kIsHiddenPrototype));
+  }
+
+  inline bool is_hidden_prototype() {
+    return ((1 << kIsHiddenPrototype) & bit_field()) != 0;
+  }
+
+  // Tells whether the instance has a named interceptor.
+  inline void set_has_named_interceptor() {
+    set_bit_field(bit_field() | (1 << kHasNamedInterceptor));
+  }
+
+  inline bool has_named_interceptor() {
+    return ((1 << kHasNamedInterceptor) & bit_field()) != 0;
+  }
+
+  // Tells whether the instance has a named interceptor.
+  inline void set_has_indexed_interceptor() {
+    set_bit_field(bit_field() | (1 << kHasIndexedInterceptor));
+  }
+
+  inline bool has_indexed_interceptor() {
+    return ((1 << kHasIndexedInterceptor) & bit_field()) != 0;
+  }
+
+  // Tells whether the instance is undetectable.
+  // An undetectable object is a special class of JSObject: 'typeof' operator
+  // returns undefined, ToBoolean returns false. Otherwise it behaves like
+  // a normal JS object.  It is useful for implementing undetectable
+  // document.all in Firefox & Safari.
+  // See https://bugzilla.mozilla.org/show_bug.cgi?id=248549.
+  inline void set_is_undetectable() {
+    set_bit_field(bit_field() | (1 << kIsUndetectable));
+  }
+
+  inline bool is_undetectable() {
+    return ((1 << kIsUndetectable) & bit_field()) != 0;
+  }
+
+  // Tells whether the instance has a call-as-function handler.
+  inline void set_has_instance_call_handler() {
+    set_bit_field(bit_field() | (1 << kHasInstanceCallHandler));
+  }
+
+  inline bool has_instance_call_handler() {
+    return ((1 << kHasInstanceCallHandler) & bit_field()) != 0;
+  }
+
+  // Tells whether the instance needs security checks when accessing its
+  // properties.
+  inline void set_is_access_check_needed(bool access_check_needed);
+  inline bool is_access_check_needed();
+
+  // [prototype]: implicit prototype object.
+  DECL_ACCESSORS(prototype, Object)
+
+  // [constructor]: points back to the function responsible for this map.
+  DECL_ACCESSORS(constructor, Object)
+
+  // [instance descriptors]: describes the object.
+  DECL_ACCESSORS(instance_descriptors, DescriptorArray)
+
+  // [stub cache]: contains stubs compiled for this map.
+  DECL_ACCESSORS(code_cache, FixedArray)
+
+  // Returns a copy of the map.
+  Object* Copy();
+
+  // Returns a copy of the map, with all transitions dropped from the
+  // instance descriptors.
+  Object* CopyDropTransitions();
+
+  // Returns the property index for name (only valid for FAST MODE).
+  int PropertyIndexFor(String* name);
+
+  // Returns the next free property index (only valid for FAST MODE).
+  int NextFreePropertyIndex();
+
+  // Returns the number of properties described in instance_descriptors.
+  int NumberOfDescribedProperties();
+
+  // Casting.
+  static inline Map* cast(Object* obj);
+
+  // Locate an accessor in the instance descriptor.
+  AccessorDescriptor* FindAccessor(String* name);
+
+  // Code cache operations.
+
+  // Clears the code cache.
+  inline void ClearCodeCache();
+
+  // Update code cache.
+  Object* UpdateCodeCache(String* name, Code* code);
+
+  // Returns the found code or undefined if absent.
+  Object* FindInCodeCache(String* name, Code::Flags flags);
+
+  // Returns the non-negative index of the code object if it is in the
+  // cache and -1 otherwise.
+  int IndexInCodeCache(Code* code);
+
+  // Removes a code object from the code cache at the given index.
+  void RemoveFromCodeCache(int index);
+
+  // For every transition in this map, makes the transition's
+  // target's prototype pointer point back to this map.
+  // This is undone in MarkCompactCollector::ClearNonLiveTransitions().
+  void CreateBackPointers();
+
+  // Set all map transitions from this map to dead maps to null.
+  // Also, restore the original prototype on the targets of these
+  // transitions, so that we do not process this map again while
+  // following back pointers.
+  void ClearNonLiveTransitions(Object* real_prototype);
+
+  // Dispatched behavior.
+  void MapIterateBody(ObjectVisitor* v);
+#ifdef DEBUG
+  void MapPrint();
+  void MapVerify();
+#endif
+
+  // Layout description.
+  static const int kInstanceSizesOffset = HeapObject::kHeaderSize;
+  static const int kInstanceAttributesOffset = kInstanceSizesOffset + kIntSize;
+  static const int kPrototypeOffset = kInstanceAttributesOffset + kIntSize;
+  static const int kConstructorOffset = kPrototypeOffset + kPointerSize;
+  static const int kInstanceDescriptorsOffset =
+      kConstructorOffset + kPointerSize;
+  static const int kCodeCacheOffset = kInstanceDescriptorsOffset + kPointerSize;
+  static const int kSize = kCodeCacheOffset + kIntSize;
+
+  // Byte offsets within kInstanceSizesOffset.
+  static const int kInstanceSizeOffset = kInstanceSizesOffset + 0;
+  static const int kInObjectPropertiesOffset = kInstanceSizesOffset + 1;
+  // The bytes at positions 2 and 3 are not in use at the moment.
+
+  // Byte offsets within kInstanceAttributesOffset attributes.
+  static const int kInstanceTypeOffset = kInstanceAttributesOffset + 0;
+  static const int kUnusedPropertyFieldsOffset = kInstanceAttributesOffset + 1;
+  static const int kBitFieldOffset = kInstanceAttributesOffset + 2;
+  // The  byte at position 3 is not in use at the moment.
+
+  // Bit positions for bit field.
+  static const int kUnused = 0;  // To be used for marking recently used maps.
+  static const int kHasNonInstancePrototype = 1;
+  static const int kIsHiddenPrototype = 2;
+  static const int kHasNamedInterceptor = 3;
+  static const int kHasIndexedInterceptor = 4;
+  static const int kIsUndetectable = 5;
+  static const int kHasInstanceCallHandler = 6;
+  static const int kIsAccessCheckNeeded = 7;
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Map);
+};
+
+
+// An abstract superclass, a marker class really, for simple structure classes.
+// It doesn't carry much functionality but allows struct classes to me
+// identified in the type system.
+class Struct: public HeapObject {
+ public:
+  inline void InitializeBody(int object_size);
+  static inline Struct* cast(Object* that);
+};
+
+
+// Script types.
+enum ScriptType {
+  SCRIPT_TYPE_NATIVE,
+  SCRIPT_TYPE_EXTENSION,
+  SCRIPT_TYPE_NORMAL
+};
+
+
+// Script describes a script which has been added to the VM.
+class Script: public Struct {
+ public:
+  // [source]: the script source.
+  DECL_ACCESSORS(source, Object)
+
+  // [name]: the script name.
+  DECL_ACCESSORS(name, Object)
+
+  // [id]: the script id.
+  DECL_ACCESSORS(id, Object)
+
+  // [line_offset]: script line offset in resource from where it was extracted.
+  DECL_ACCESSORS(line_offset, Smi)
+
+  // [column_offset]: script column offset in resource from where it was
+  // extracted.
+  DECL_ACCESSORS(column_offset, Smi)
+
+  // [wrapper]: the wrapper cache.
+  DECL_ACCESSORS(wrapper, Proxy)
+
+  // [type]: the script type.
+  DECL_ACCESSORS(type, Smi)
+
+  // [line_ends]: array of line ends positions
+  DECL_ACCESSORS(line_ends, Object)
+
+  static inline Script* cast(Object* obj);
+
+#ifdef DEBUG
+  void ScriptPrint();
+  void ScriptVerify();
+#endif
+
+  static const int kSourceOffset = HeapObject::kHeaderSize;
+  static const int kNameOffset = kSourceOffset + kPointerSize;
+  static const int kLineOffsetOffset = kNameOffset + kPointerSize;
+  static const int kColumnOffsetOffset = kLineOffsetOffset + kPointerSize;
+  static const int kWrapperOffset = kColumnOffsetOffset + kPointerSize;
+  static const int kTypeOffset = kWrapperOffset + kPointerSize;
+  static const int kLineEndsOffset = kTypeOffset + kPointerSize;
+  static const int kIdOffset = kLineEndsOffset + kPointerSize;
+  static const int kSize = kIdOffset + kPointerSize;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Script);
+};
+
+
+// SharedFunctionInfo describes the JSFunction information that can be
+// shared by multiple instances of the function.
+class SharedFunctionInfo: public HeapObject {
+ public:
+  // [name]: Function name.
+  DECL_ACCESSORS(name, Object)
+
+  // [code]: Function code.
+  DECL_ACCESSORS(code, Code)
+
+  // Returns if this function has been compiled to native code yet.
+  inline bool is_compiled();
+
+  // [length]: The function length - usually the number of declared parameters.
+  // Use up to 2^30 parameters.
+  inline int length();
+  inline void set_length(int value);
+
+  // [formal parameter count]: The declared number of parameters.
+  inline int formal_parameter_count();
+  inline void set_formal_parameter_count(int value);
+
+  // Set the formal parameter count so the function code will be
+  // called without using argument adaptor frames.
+  inline void DontAdaptArguments();
+
+  // [expected_nof_properties]: Expected number of properties for the function.
+  inline int expected_nof_properties();
+  inline void set_expected_nof_properties(int value);
+
+  // [instance class name]: class name for instances.
+  DECL_ACCESSORS(instance_class_name, Object)
+
+  // [function data]: This field has been added for make benefit the API.
+  // In the long run we don't want all functions to have this field but
+  // we can fix that when we have a better model for storing hidden data
+  // on objects.
+  DECL_ACCESSORS(function_data, Object)
+
+  // [lazy load data]: If the function has lazy loading, this field
+  // contains contexts and other data needed to load it.
+  DECL_ACCESSORS(lazy_load_data, Object)
+
+  // [script info]: Script from which the function originates.
+  DECL_ACCESSORS(script, Object)
+
+  // [start_position_and_type]: Field used to store both the source code
+  // position, whether or not the function is a function expression,
+  // and whether or not the function is a toplevel function. The two
+  // least significants bit indicates whether the function is an
+  // expression and the rest contains the source code position.
+  inline int start_position_and_type();
+  inline void set_start_position_and_type(int value);
+
+  // [debug info]: Debug information.
+  DECL_ACCESSORS(debug_info, Object)
+
+  // [inferred name]: Name inferred from variable or property
+  // assignment of this function. Used to facilitate debugging and
+  // profiling of JavaScript code written in OO style, where almost
+  // all functions are anonymous but are assigned to object
+  // properties.
+  DECL_ACCESSORS(inferred_name, String)
+
+  // Position of the 'function' token in the script source.
+  inline int function_token_position();
+  inline void set_function_token_position(int function_token_position);
+
+  // Position of this function in the script source.
+  inline int start_position();
+  inline void set_start_position(int start_position);
+
+  // End position of this function in the script source.
+  inline int end_position();
+  inline void set_end_position(int end_position);
+
+  // Is this function a function expression in the source code.
+  inline bool is_expression();
+  inline void set_is_expression(bool value);
+
+  // Is this function a top-level function. Used for accessing the
+  // caller of functions. Top-level functions (scripts, evals) are
+  // returned as null; see JSFunction::GetCallerAccessor(...).
+  inline bool is_toplevel();
+  inline void set_is_toplevel(bool value);
+
+  // [source code]: Source code for the function.
+  bool HasSourceCode();
+  Object* GetSourceCode();
+
+  // Dispatched behavior.
+  void SharedFunctionInfoIterateBody(ObjectVisitor* v);
+  // Set max_length to -1 for unlimited length.
+  void SourceCodePrint(StringStream* accumulator, int max_length);
+#ifdef DEBUG
+  void SharedFunctionInfoPrint();
+  void SharedFunctionInfoVerify();
+#endif
+
+  // Casting.
+  static inline SharedFunctionInfo* cast(Object* obj);
+
+  // Constants.
+  static const int kDontAdaptArgumentsSentinel = -1;
+
+  // Layout description.
+  static const int kNameOffset = HeapObject::kHeaderSize;
+  static const int kCodeOffset = kNameOffset + kPointerSize;
+  static const int kLengthOffset = kCodeOffset + kPointerSize;
+  static const int kFormalParameterCountOffset = kLengthOffset + kIntSize;
+  static const int kExpectedNofPropertiesOffset =
+      kFormalParameterCountOffset + kIntSize;
+  static const int kInstanceClassNameOffset =
+      kExpectedNofPropertiesOffset + kIntSize;
+  static const int kExternalReferenceDataOffset =
+      kInstanceClassNameOffset + kPointerSize;
+  static const int kLazyLoadDataOffset =
+      kExternalReferenceDataOffset + kPointerSize;
+  static const int kScriptOffset = kLazyLoadDataOffset + kPointerSize;
+  static const int kStartPositionAndTypeOffset = kScriptOffset + kPointerSize;
+  static const int kEndPositionOffset = kStartPositionAndTypeOffset + kIntSize;
+  static const int kFunctionTokenPositionOffset = kEndPositionOffset + kIntSize;
+  static const int kDebugInfoOffset = kFunctionTokenPositionOffset + kIntSize;
+  static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize;
+  static const int kSize = kInferredNameOffset + kPointerSize;
+
+ private:
+  // Bit positions in length_and_flg.
+  // The least significant bit is used as the flag.
+  static const int kFlagBit         = 0;
+  static const int kLengthShift     = 1;
+  static const int kLengthMask      = ~((1 << kLengthShift) - 1);
+
+  // Bit positions in start_position_and_type.
+  // The source code start position is in the 30 most significant bits of
+  // the start_position_and_type field.
+  static const int kIsExpressionBit = 0;
+  static const int kIsTopLevelBit   = 1;
+  static const int kStartPositionShift = 2;
+  static const int kStartPositionMask = ~((1 << kStartPositionShift) - 1);
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);
+};
+
+
+// JSFunction describes JavaScript functions.
+class JSFunction: public JSObject {
+ public:
+  // [prototype_or_initial_map]:
+  DECL_ACCESSORS(prototype_or_initial_map, Object)
+
+  // [shared_function_info]: The information about the function that
+  // can be shared by instances.
+  DECL_ACCESSORS(shared, SharedFunctionInfo)
+
+  // [context]: The context for this function.
+  inline Context* context();
+  inline Object* unchecked_context();
+  inline void set_context(Object* context);
+
+  // [code]: The generated code object for this function.  Executed
+  // when the function is invoked, e.g. foo() or new foo(). See
+  // [[Call]] and [[Construct]] description in ECMA-262, section
+  // 8.6.2, page 27.
+  inline Code* code();
+  inline void set_code(Code* value);
+
+  // Tells whether this function is a context-independent boilerplate
+  // function.
+  inline bool IsBoilerplate();
+
+  // Tells whether this function needs to be loaded.
+  inline bool IsLoaded();
+
+  // [literals]: Fixed array holding the materialized literals.
+  //
+  // If the function contains object, regexp or array literals, the
+  // literals array prefix contains the object, regexp, and array
+  // function to be used when creating these literals.  This is
+  // necessary so that we do not dynamically lookup the object, regexp
+  // or array functions.  Performing a dynamic lookup, we might end up
+  // using the functions from a new context that we should not have
+  // access to.
+  DECL_ACCESSORS(literals, FixedArray)
+
+  // The initial map for an object created by this constructor.
+  inline Map* initial_map();
+  inline void set_initial_map(Map* value);
+  inline bool has_initial_map();
+
+  // Get and set the prototype property on a JSFunction. If the
+  // function has an initial map the prototype is set on the initial
+  // map. Otherwise, the prototype is put in the initial map field
+  // until an initial map is needed.
+  inline bool has_prototype();
+  inline bool has_instance_prototype();
+  inline Object* prototype();
+  inline Object* instance_prototype();
+  Object* SetInstancePrototype(Object* value);
+  Object* SetPrototype(Object* value);
+
+  // Accessor for this function's initial map's [[class]]
+  // property. This is primarily used by ECMA native functions.  This
+  // method sets the class_name field of this function's initial map
+  // to a given value. It creates an initial map if this function does
+  // not have one. Note that this method does not copy the initial map
+  // if it has one already, but simply replaces it with the new value.
+  // Instances created afterwards will have a map whose [[class]] is
+  // set to 'value', but there is no guarantees on instances created
+  // before.
+  Object* SetInstanceClassName(String* name);
+
+  // Returns if this function has been compiled to native code yet.
+  inline bool is_compiled();
+
+  // Casting.
+  static inline JSFunction* cast(Object* obj);
+
+  // Dispatched behavior.
+#ifdef DEBUG
+  void JSFunctionPrint();
+  void JSFunctionVerify();
+#endif
+
+  // Returns the number of allocated literals.
+  inline int NumberOfLiterals();
+
+  // Retrieve the global context from a function's literal array.
+  static Context* GlobalContextFromLiterals(FixedArray* literals);
+
+  // Layout descriptors.
+  static const int kPrototypeOrInitialMapOffset = JSObject::kHeaderSize;
+  static const int kSharedFunctionInfoOffset =
+      kPrototypeOrInitialMapOffset + kPointerSize;
+  static const int kContextOffset = kSharedFunctionInfoOffset + kPointerSize;
+  static const int kLiteralsOffset = kContextOffset + kPointerSize;
+  static const int kSize = kLiteralsOffset + kPointerSize;
+
+  // Layout of the literals array.
+  static const int kLiteralsPrefixSize = 1;
+  static const int kLiteralGlobalContextIndex = 0;
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunction);
+};
+
+
+// JSGlobalProxy's prototype must be a JSGlobalObject or null,
+// and the prototype is hidden. JSGlobalProxy always delegates
+// property accesses to its prototype if the prototype is not null.
+//
+// A JSGlobalProxy can be reinitialized which will preserve its identity.
+//
+// Accessing a JSGlobalProxy requires security check.
+
+class JSGlobalProxy : public JSObject {
+ public:
+  // [context]: the owner global context of this proxy object.
+  // It is null value if this object is not used by any context.
+  DECL_ACCESSORS(context, Object)
+
+  // Casting.
+  static inline JSGlobalProxy* cast(Object* obj);
+
+  // Dispatched behavior.
+#ifdef DEBUG
+  void JSGlobalProxyPrint();
+  void JSGlobalProxyVerify();
+#endif
+
+  // Layout description.
+  static const int kContextOffset = JSObject::kHeaderSize;
+  static const int kSize = kContextOffset + kPointerSize;
+
+ private:
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalProxy);
+};
+
+
+// Forward declaration.
+class JSBuiltinsObject;
+
+// Common super class for JavaScript global objects and the special
+// builtins global objects.
+class GlobalObject: public JSObject {
+ public:
+  // [builtins]: the object holding the runtime routines written in JS.
+  DECL_ACCESSORS(builtins, JSBuiltinsObject)
+
+  // [global context]: the global context corresponding to this global object.
+  DECL_ACCESSORS(global_context, Context)
+
+  // [global receiver]: the global receiver object of the context
+  DECL_ACCESSORS(global_receiver, JSObject)
+
+  // Casting.
+  static inline GlobalObject* cast(Object* obj);
+
+  // Layout description.
+  static const int kBuiltinsOffset = JSObject::kHeaderSize;
+  static const int kGlobalContextOffset = kBuiltinsOffset + kPointerSize;
+  static const int kGlobalReceiverOffset = kGlobalContextOffset + kPointerSize;
+  static const int kHeaderSize = kGlobalReceiverOffset + kPointerSize;
+
+ private:
+  friend class AGCCVersionRequiresThisClassToHaveAFriendSoHereItIs;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(GlobalObject);
+};
+
+
+// JavaScript global object.
+class JSGlobalObject: public GlobalObject {
+ public:
+  // Casting.
+  static inline JSGlobalObject* cast(Object* obj);
+
+  // Dispatched behavior.
+#ifdef DEBUG
+  void JSGlobalObjectPrint();
+  void JSGlobalObjectVerify();
+#endif
+
+  // Layout description.
+  static const int kSize = GlobalObject::kHeaderSize;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalObject);
+};
+
+
+// Builtins global object which holds the runtime routines written in
+// JavaScript.
+class JSBuiltinsObject: public GlobalObject {
+ public:
+  // Accessors for the runtime routines written in JavaScript.
+  inline Object* javascript_builtin(Builtins::JavaScript id);
+  inline void set_javascript_builtin(Builtins::JavaScript id, Object* value);
+
+  // Casting.
+  static inline JSBuiltinsObject* cast(Object* obj);
+
+  // Dispatched behavior.
+#ifdef DEBUG
+  void JSBuiltinsObjectPrint();
+  void JSBuiltinsObjectVerify();
+#endif
+
+  // Layout description.  The size of the builtins object includes
+  // room for one pointer per runtime routine written in javascript.
+  static const int kJSBuiltinsCount = Builtins::id_count;
+  static const int kJSBuiltinsOffset = GlobalObject::kHeaderSize;
+  static const int kSize =
+      kJSBuiltinsOffset + (kJSBuiltinsCount * kPointerSize);
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(JSBuiltinsObject);
+};
+
+
+// Representation for JS Wrapper objects, String, Number, Boolean, Date, etc.
+class JSValue: public JSObject {
+ public:
+  // [value]: the object being wrapped.
+  DECL_ACCESSORS(value, Object)
+
+  // Casting.
+  static inline JSValue* cast(Object* obj);
+
+  // Dispatched behavior.
+#ifdef DEBUG
+  void JSValuePrint();
+  void JSValueVerify();
+#endif
+
+  // Layout description.
+  static const int kValueOffset = JSObject::kHeaderSize;
+  static const int kSize = kValueOffset + kPointerSize;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(JSValue);
+};
+
+// Regular expressions
+// The regular expression holds a single reference to a FixedArray in
+// the kDataOffset field.
+// The FixedArray contains the following data:
+// - tag : type of regexp implementation (not compiled yet, atom or irregexp)
+// - reference to the original source string
+// - reference to the original flag string
+// If it is an atom regexp
+// - a reference to a literal string to search for
+// If it is an irregexp regexp:
+// - a reference to code for ASCII inputs (bytecode or compiled).
+// - a reference to code for UC16 inputs (bytecode or compiled).
+// - max number of registers used by irregexp implementations.
+// - number of capture registers (output values) of the regexp.
+class JSRegExp: public JSObject {
+ public:
+  // Meaning of Type:
+  // NOT_COMPILED: Initial value. No data has been stored in the JSRegExp yet.
+  // ATOM: A simple string to match against using an indexOf operation.
+  // IRREGEXP: Compiled with Irregexp.
+  // IRREGEXP_NATIVE: Compiled to native code with Irregexp.
+  enum Type { NOT_COMPILED, ATOM, IRREGEXP };
+  enum Flag { NONE = 0, GLOBAL = 1, IGNORE_CASE = 2, MULTILINE = 4 };
+
+  class Flags {
+   public:
+    explicit Flags(uint32_t value) : value_(value) { }
+    bool is_global() { return (value_ & GLOBAL) != 0; }
+    bool is_ignore_case() { return (value_ & IGNORE_CASE) != 0; }
+    bool is_multiline() { return (value_ & MULTILINE) != 0; }
+    uint32_t value() { return value_; }
+   private:
+    uint32_t value_;
+  };
+
+  DECL_ACCESSORS(data, Object)
+
+  inline Type TypeTag();
+  inline int CaptureCount();
+  inline Flags GetFlags();
+  inline String* Pattern();
+  inline Object* DataAt(int index);
+  // Set implementation data after the object has been prepared.
+  inline void SetDataAt(int index, Object* value);
+
+  static inline JSRegExp* cast(Object* obj);
+
+  // Dispatched behavior.
+#ifdef DEBUG
+  void JSRegExpVerify();
+#endif
+
+  static const int kDataOffset = JSObject::kHeaderSize;
+  static const int kSize = kDataOffset + kIntSize;
+
+  // Indices in the data array.
+  static const int kTagIndex = 0;
+  static const int kSourceIndex = kTagIndex + 1;
+  static const int kFlagsIndex = kSourceIndex + 1;
+  static const int kDataIndex = kFlagsIndex + 1;
+  // The data fields are used in different ways depending on the
+  // value of the tag.
+  // Atom regexps (literal strings).
+  static const int kAtomPatternIndex = kDataIndex;
+
+  static const int kAtomDataSize = kAtomPatternIndex + 1;
+
+  // Irregexp compiled code or bytecode for ASCII.
+  static const int kIrregexpASCIICodeIndex = kDataIndex;
+  // Irregexp compiled code or bytecode for UC16.
+  static const int kIrregexpUC16CodeIndex = kDataIndex + 1;
+  // Maximal number of registers used by either ASCII or UC16.
+  // Only used to check that there is enough stack space
+  static const int kIrregexpMaxRegisterCountIndex = kDataIndex + 2;
+  // Number of captures in the compiled regexp.
+  static const int kIrregexpCaptureCountIndex = kDataIndex + 3;
+
+  static const int kIrregexpDataSize = kIrregexpCaptureCountIndex + 1;
+};
+
+
+class CompilationCacheTable: public HashTable<0, 2> {
+ public:
+  // Find cached value for a string key, otherwise return null.
+  Object* Lookup(String* src);
+  Object* LookupEval(String* src, Context* context);
+  Object* LookupRegExp(String* source, JSRegExp::Flags flags);
+  Object* Put(String* src, Object* value);
+  Object* PutEval(String* src, Context* context, Object* value);
+  Object* PutRegExp(String* src, JSRegExp::Flags flags, FixedArray* value);
+
+  static inline CompilationCacheTable* cast(Object* obj);
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheTable);
+};
+
+
+enum AllowNullsFlag {ALLOW_NULLS, DISALLOW_NULLS};
+enum RobustnessFlag {ROBUST_STRING_TRAVERSAL, FAST_STRING_TRAVERSAL};
+
+
+class StringHasher {
+ public:
+  inline StringHasher(int length);
+
+  // Returns true if the hash of this string can be computed without
+  // looking at the contents.
+  inline bool has_trivial_hash();
+
+  // Add a character to the hash and update the array index calculation.
+  inline void AddCharacter(uc32 c);
+
+  // Adds a character to the hash but does not update the array index
+  // calculation.  This can only be called when it has been verified
+  // that the input is not an array index.
+  inline void AddCharacterNoIndex(uc32 c);
+
+  // Returns the value to store in the hash field of a string with
+  // the given length and contents.
+  uint32_t GetHashField();
+
+  // Returns true if the characters seen so far make up a legal array
+  // index.
+  bool is_array_index() { return is_array_index_; }
+
+  bool is_valid() { return is_valid_; }
+
+  void invalidate() { is_valid_ = false; }
+
+ private:
+
+  uint32_t array_index() {
+    ASSERT(is_array_index());
+    return array_index_;
+  }
+
+  inline uint32_t GetHash();
+
+  int length_;
+  uint32_t raw_running_hash_;
+  uint32_t array_index_;
+  bool is_array_index_;
+  bool is_first_char_;
+  bool is_valid_;
+};
+
+
+// The characteristics of a string are stored in its map.  Retrieving these
+// few bits of information is moderately expensive, involving two memory
+// loads where the second is dependent on the first.  To improve efficiency
+// the shape of the string is given its own class so that it can be retrieved
+// once and used for several string operations.  A StringShape is small enough
+// to be passed by value and is immutable, but be aware that flattening a
+// string can potentially alter its shape.  Also be aware that a GC caused by
+// something else can alter the shape of a string due to ConsString
+// shortcutting.  Keeping these restrictions in mind has proven to be error-
+// prone and so we no longer put StringShapes in variables unless there is a
+// concrete performance benefit at that particular point in the code.
+class StringShape BASE_EMBEDDED {
+ public:
+  inline explicit StringShape(String* s);
+  inline explicit StringShape(Map* s);
+  inline explicit StringShape(InstanceType t);
+  inline bool IsAsciiRepresentation();
+  inline bool IsTwoByteRepresentation();
+  inline bool IsSequential();
+  inline bool IsExternal();
+  inline bool IsCons();
+  inline bool IsSliced();
+  inline bool IsExternalAscii();
+  inline bool IsExternalTwoByte();
+  inline bool IsSequentialAscii();
+  inline bool IsSequentialTwoByte();
+  inline bool IsSymbol();
+  inline StringRepresentationTag representation_tag();
+  inline uint32_t full_representation_tag();
+  inline uint32_t size_tag();
+#ifdef DEBUG
+  inline uint32_t type() { return type_; }
+  inline void invalidate() { valid_ = false; }
+  inline bool valid() { return valid_; }
+#else
+  inline void invalidate() { }
+#endif
+ private:
+  uint32_t type_;
+#ifdef DEBUG
+  inline void set_valid() { valid_ = true; }
+  bool valid_;
+#else
+  inline void set_valid() { }
+#endif
+};
+
+
+// The String abstract class captures JavaScript string values:
+//
+// Ecma-262:
+//  4.3.16 String Value
+//    A string value is a member of the type String and is a finite
+//    ordered sequence of zero or more 16-bit unsigned integer values.
+//
+// All string values have a length field.
+class String: public HeapObject {
+ public:
+  // Get and set the length of the string.
+  inline int length();
+  inline void set_length(int value);
+
+  // Get and set the uninterpreted length field of the string.  Notice
+  // that the length field is also used to cache the hash value of
+  // strings.  In order to get or set the actual length of the string
+  // use the length() and set_length methods.
+  inline uint32_t length_field();
+  inline void set_length_field(uint32_t value);
+
+  // Get and set individual two byte chars in the string.
+  inline void Set(int index, uint16_t value);
+  // Get individual two byte char in the string.  Repeated calls
+  // to this method are not efficient unless the string is flat.
+  inline uint16_t Get(int index);
+
+  // Try to flatten the top level ConsString that is hiding behind this
+  // string.  This is a no-op unless the string is a ConsString or a
+  // SlicedString.  Flatten mutates the ConsString and might return a
+  // failure.
+  Object* TryFlatten();
+
+  // Try to flatten the string.  Checks first inline to see if it is necessary.
+  // Do not handle allocation failures.  After calling TryFlattenIfNotFlat, the
+  // string could still be a ConsString, in which case a failure is returned.
+  // Use FlattenString from Handles.cc to be sure to flatten.
+  inline Object* TryFlattenIfNotFlat();
+
+  Vector<const char> ToAsciiVector();
+  Vector<const uc16> ToUC16Vector();
+
+  // Mark the string as an undetectable object. It only applies to
+  // ascii and two byte string types.
+  bool MarkAsUndetectable();
+
+  // Slice the string and return a substring.
+  Object* Slice(int from, int to);
+
+  // String equality operations.
+  inline bool Equals(String* other);
+  bool IsEqualTo(Vector<const char> str);
+
+  // Return a UTF8 representation of the string.  The string is null
+  // terminated but may optionally contain nulls.  Length is returned
+  // in length_output if length_output is not a null pointer  The string
+  // should be nearly flat, otherwise the performance of this method may
+  // be very slow (quadratic in the length).  Setting robustness_flag to
+  // ROBUST_STRING_TRAVERSAL invokes behaviour that is robust  This means it
+  // handles unexpected data without causing assert failures and it does not
+  // do any heap allocations.  This is useful when printing stack traces.
+  SmartPointer<char> ToCString(AllowNullsFlag allow_nulls,
+                               RobustnessFlag robustness_flag,
+                               int offset,
+                               int length,
+                               int* length_output = 0);
+  SmartPointer<char> ToCString(
+      AllowNullsFlag allow_nulls = DISALLOW_NULLS,
+      RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL,
+      int* length_output = 0);
+
+  int Utf8Length();
+
+  // Return a 16 bit Unicode representation of the string.
+  // The string should be nearly flat, otherwise the performance of
+  // of this method may be very bad.  Setting robustness_flag to
+  // ROBUST_STRING_TRAVERSAL invokes behaviour that is robust  This means it
+  // handles unexpected data without causing assert failures and it does not
+  // do any heap allocations.  This is useful when printing stack traces.
+  SmartPointer<uc16> ToWideCString(
+      RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL);
+
+  // Tells whether the hash code has been computed.
+  inline bool HasHashCode();
+
+  // Returns a hash value used for the property table
+  inline uint32_t Hash();
+
+  static uint32_t ComputeLengthAndHashField(unibrow::CharacterStream* buffer,
+                                            int length);
+
+  static bool ComputeArrayIndex(unibrow::CharacterStream* buffer,
+                                uint32_t* index,
+                                int length);
+
+  // Externalization.
+  bool MakeExternal(v8::String::ExternalStringResource* resource);
+  bool MakeExternal(v8::String::ExternalAsciiStringResource* resource);
+
+  // Conversion.
+  inline bool AsArrayIndex(uint32_t* index);
+
+  // Casting.
+  static inline String* cast(Object* obj);
+
+  void PrintOn(FILE* out);
+
+  // For use during stack traces.  Performs rudimentary sanity check.
+  bool LooksValid();
+
+  // Dispatched behavior.
+  void StringShortPrint(StringStream* accumulator);
+#ifdef DEBUG
+  void StringPrint();
+  void StringVerify();
+#endif
+  inline bool IsFlat();
+
+  // Layout description.
+  static const int kLengthOffset = HeapObject::kHeaderSize;
+  static const int kSize = kLengthOffset + kIntSize;
+
+  // Limits on sizes of different types of strings.
+  static const int kMaxShortStringSize = 63;
+  static const int kMaxMediumStringSize = 16383;
+
+  static const int kMaxArrayIndexSize = 10;
+
+  // Max ascii char code.
+  static const int kMaxAsciiCharCode = unibrow::Utf8::kMaxOneByteChar;
+  static const unsigned kMaxAsciiCharCodeU = unibrow::Utf8::kMaxOneByteChar;
+  static const int kMaxUC16CharCode = 0xffff;
+
+  // Minimum length for a cons or sliced string.
+  static const int kMinNonFlatLength = 13;
+
+  // Mask constant for checking if a string has a computed hash code
+  // and if it is an array index.  The least significant bit indicates
+  // whether a hash code has been computed.  If the hash code has been
+  // computed the 2nd bit tells whether the string can be used as an
+  // array index.
+  static const int kHashComputedMask = 1;
+  static const int kIsArrayIndexMask = 1 << 1;
+  static const int kNofLengthBitFields = 2;
+
+  // Array index strings this short can keep their index in the hash
+  // field.
+  static const int kMaxCachedArrayIndexLength = 7;
+
+  // Shift constants for retriving length and hash code from
+  // length/hash field.
+  static const int kHashShift = kNofLengthBitFields;
+  static const int kShortLengthShift = kHashShift + kShortStringTag;
+  static const int kMediumLengthShift = kHashShift + kMediumStringTag;
+  static const int kLongLengthShift = kHashShift + kLongStringTag;
+
+  // Limit for truncation in short printing.
+  static const int kMaxShortPrintLength = 1024;
+
+  // Support for regular expressions.
+  const uc16* GetTwoByteData();
+  const uc16* GetTwoByteData(unsigned start);
+
+  // Support for StringInputBuffer
+  static const unibrow::byte* ReadBlock(String* input,
+                                        unibrow::byte* util_buffer,
+                                        unsigned capacity,
+                                        unsigned* remaining,
+                                        unsigned* offset);
+  static const unibrow::byte* ReadBlock(String** input,
+                                        unibrow::byte* util_buffer,
+                                        unsigned capacity,
+                                        unsigned* remaining,
+                                        unsigned* offset);
+
+  // Helper function for flattening strings.
+  template <typename sinkchar>
+  static void WriteToFlat(String* source,
+                          sinkchar* sink,
+                          int from,
+                          int to);
+
+ protected:
+  class ReadBlockBuffer {
+   public:
+    ReadBlockBuffer(unibrow::byte* util_buffer_,
+                    unsigned cursor_,
+                    unsigned capacity_,
+                    unsigned remaining_) :
+      util_buffer(util_buffer_),
+      cursor(cursor_),
+      capacity(capacity_),
+      remaining(remaining_) {
+    }
+    unibrow::byte* util_buffer;
+    unsigned       cursor;
+    unsigned       capacity;
+    unsigned       remaining;
+  };
+
+  // NOTE: If you call StringInputBuffer routines on strings that are
+  // too deeply nested trees of cons and slice strings, then this
+  // routine will overflow the stack. Strings that are merely deeply
+  // nested trees of cons strings do not have a problem apart from
+  // performance.
+
+  static inline const unibrow::byte* ReadBlock(String* input,
+                                               ReadBlockBuffer* buffer,
+                                               unsigned* offset,
+                                               unsigned max_chars);
+  static void ReadBlockIntoBuffer(String* input,
+                                  ReadBlockBuffer* buffer,
+                                  unsigned* offset_ptr,
+                                  unsigned max_chars);
+
+ private:
+  // Slow case of String::Equals.  This implementation works on any strings
+  // but it is most efficient on strings that are almost flat.
+  bool SlowEquals(String* other);
+
+  // Slow case of AsArrayIndex.
+  bool SlowAsArrayIndex(uint32_t* index);
+
+  // Compute and set the hash code.
+  uint32_t ComputeAndSetHash();
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(String);
+};
+
+
+// The SeqString abstract class captures sequential string values.
+class SeqString: public String {
+ public:
+
+  // Casting.
+  static inline SeqString* cast(Object* obj);
+
+  // Dispatched behaviour.
+  // For regexp code.
+  uint16_t* SeqStringGetTwoByteAddress();
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString);
+};
+
+
+// The AsciiString class captures sequential ascii string objects.
+// Each character in the AsciiString is an ascii character.
+class SeqAsciiString: public SeqString {
+ public:
+  // Dispatched behavior.
+  inline uint16_t SeqAsciiStringGet(int index);
+  inline void SeqAsciiStringSet(int index, uint16_t value);
+
+  // Get the address of the characters in this string.
+  inline Address GetCharsAddress();
+
+  inline char* GetChars();
+
+  // Casting
+  static inline SeqAsciiString* cast(Object* obj);
+
+  // Garbage collection support.  This method is called by the
+  // garbage collector to compute the actual size of an AsciiString
+  // instance.
+  inline int SeqAsciiStringSize(InstanceType instance_type);
+
+  // Computes the size for an AsciiString instance of a given length.
+  static int SizeFor(int length) {
+    return kHeaderSize + OBJECT_SIZE_ALIGN(length * kCharSize);
+  }
+
+  // Layout description.
+  static const int kHeaderSize = String::kSize;
+
+  // Support for StringInputBuffer.
+  inline void SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
+                                                unsigned* offset,
+                                                unsigned chars);
+  inline const unibrow::byte* SeqAsciiStringReadBlock(unsigned* remaining,
+                                                      unsigned* offset,
+                                                      unsigned chars);
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(SeqAsciiString);
+};
+
+
+// The TwoByteString class captures sequential unicode string objects.
+// Each character in the TwoByteString is a two-byte uint16_t.
+class SeqTwoByteString: public SeqString {
+ public:
+  // Dispatched behavior.
+  inline uint16_t SeqTwoByteStringGet(int index);
+  inline void SeqTwoByteStringSet(int index, uint16_t value);
+
+  // Get the address of the characters in this string.
+  inline Address GetCharsAddress();
+
+  inline uc16* GetChars();
+
+  // For regexp code.
+  const uint16_t* SeqTwoByteStringGetData(unsigned start);
+
+  // Casting
+  static inline SeqTwoByteString* cast(Object* obj);
+
+  // Garbage collection support.  This method is called by the
+  // garbage collector to compute the actual size of a TwoByteString
+  // instance.
+  inline int SeqTwoByteStringSize(InstanceType instance_type);
+
+  // Computes the size for a TwoByteString instance of a given length.
+  static int SizeFor(int length) {
+    return kHeaderSize + OBJECT_SIZE_ALIGN(length * kShortSize);
+  }
+
+  // Layout description.
+  static const int kHeaderSize = String::kSize;
+
+  // Support for StringInputBuffer.
+  inline void SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
+                                                  unsigned* offset_ptr,
+                                                  unsigned chars);
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(SeqTwoByteString);
+};
+
+
+// The ConsString class describes string values built by using the
+// addition operator on strings.  A ConsString is a pair where the
+// first and second components are pointers to other string values.
+// One or both components of a ConsString can be pointers to other
+// ConsStrings, creating a binary tree of ConsStrings where the leaves
+// are non-ConsString string values.  The string value represented by
+// a ConsString can be obtained by concatenating the leaf string
+// values in a left-to-right depth-first traversal of the tree.
+class ConsString: public String {
+ public:
+  // First string of the cons cell.
+  inline String* first();
+  // Doesn't check that the result is a string, even in debug mode.  This is
+  // useful during GC where the mark bits confuse the checks.
+  inline Object* unchecked_first();
+  inline void set_first(String* first,
+                        WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
+
+  // Second string of the cons cell.
+  inline String* second();
+  // Doesn't check that the result is a string, even in debug mode.  This is
+  // useful during GC where the mark bits confuse the checks.
+  inline Object* unchecked_second();
+  inline void set_second(String* second,
+                         WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
+
+  // Dispatched behavior.
+  uint16_t ConsStringGet(int index);
+
+  // Casting.
+  static inline ConsString* cast(Object* obj);
+
+  // Garbage collection support.  This method is called during garbage
+  // collection to iterate through the heap pointers in the body of
+  // the ConsString.
+  void ConsStringIterateBody(ObjectVisitor* v);
+
+  // Layout description.
+  static const int kFirstOffset = String::kSize;
+  static const int kSecondOffset = kFirstOffset + kPointerSize;
+  static const int kSize = kSecondOffset + kPointerSize;
+
+  // Support for StringInputBuffer.
+  inline const unibrow::byte* ConsStringReadBlock(ReadBlockBuffer* buffer,
+                                                  unsigned* offset_ptr,
+                                                  unsigned chars);
+  inline void ConsStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
+                                            unsigned* offset_ptr,
+                                            unsigned chars);
+
+  // Minimum length for a cons string.
+  static const int kMinLength = 13;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ConsString);
+};
+
+
+// The SlicedString class describes string values that are slices of
+// some other string.  SlicedStrings consist of a reference to an
+// underlying heap-allocated string value, a start index, and the
+// length field common to all strings.
+class SlicedString: public String {
+ public:
+  // The underlying string buffer.
+  inline String* buffer();
+  inline void set_buffer(String* buffer);
+
+  // The start index of the slice.
+  inline int start();
+  inline void set_start(int start);
+
+  // Dispatched behavior.
+  uint16_t SlicedStringGet(int index);
+
+  // Casting.
+  static inline SlicedString* cast(Object* obj);
+
+  // Garbage collection support.
+  void SlicedStringIterateBody(ObjectVisitor* v);
+
+  // Layout description
+  static const int kBufferOffset = String::kSize;
+  static const int kStartOffset = kBufferOffset + kPointerSize;
+  static const int kSize = kStartOffset + kIntSize;
+
+  // Support for StringInputBuffer.
+  inline const unibrow::byte* SlicedStringReadBlock(ReadBlockBuffer* buffer,
+                                                    unsigned* offset_ptr,
+                                                    unsigned chars);
+  inline void SlicedStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
+                                              unsigned* offset_ptr,
+                                              unsigned chars);
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(SlicedString);
+};
+
+
+// The ExternalString class describes string values that are backed by
+// a string resource that lies outside the V8 heap.  ExternalStrings
+// consist of the length field common to all strings, a pointer to the
+// external resource.  It is important to ensure (externally) that the
+// resource is not deallocated while the ExternalString is live in the
+// V8 heap.
+//
+// The API expects that all ExternalStrings are created through the
+// API.  Therefore, ExternalStrings should not be used internally.
+class ExternalString: public String {
+ public:
+  // Casting
+  static inline ExternalString* cast(Object* obj);
+
+  // Layout description.
+  static const int kResourceOffset = String::kSize;
+  static const int kSize = kResourceOffset + kPointerSize;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalString);
+};
+
+
+// The ExternalAsciiString class is an external string backed by an
+// ASCII string.
+class ExternalAsciiString: public ExternalString {
+ public:
+  typedef v8::String::ExternalAsciiStringResource Resource;
+
+  // The underlying resource.
+  inline Resource* resource();
+  inline void set_resource(Resource* buffer);
+
+  // Dispatched behavior.
+  uint16_t ExternalAsciiStringGet(int index);
+
+  // Casting.
+  static inline ExternalAsciiString* cast(Object* obj);
+
+  // Support for StringInputBuffer.
+  const unibrow::byte* ExternalAsciiStringReadBlock(unsigned* remaining,
+                                                    unsigned* offset,
+                                                    unsigned chars);
+  inline void ExternalAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
+                                                     unsigned* offset,
+                                                     unsigned chars);
+
+  // Identify the map for the external string/symbol with a particular length.
+  static inline Map* StringMap(int length);
+  static inline Map* SymbolMap(int length);
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalAsciiString);
+};
+
+
+// The ExternalTwoByteString class is an external string backed by a UTF-16
+// encoded string.
+class ExternalTwoByteString: public ExternalString {
+ public:
+  typedef v8::String::ExternalStringResource Resource;
+
+  // The underlying string resource.
+  inline Resource* resource();
+  inline void set_resource(Resource* buffer);
+
+  // Dispatched behavior.
+  uint16_t ExternalTwoByteStringGet(int index);
+
+  // For regexp code.
+  const uint16_t* ExternalTwoByteStringGetData(unsigned start);
+
+  // Casting.
+  static inline ExternalTwoByteString* cast(Object* obj);
+
+  // Support for StringInputBuffer.
+  void ExternalTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
+                                                unsigned* offset_ptr,
+                                                unsigned chars);
+
+  // Identify the map for the external string/symbol with a particular length.
+  static inline Map* StringMap(int length);
+  static inline Map* SymbolMap(int length);
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalTwoByteString);
+};
+
+
+// A flat string reader provides random access to the contents of a
+// string independent of the character width of the string.  The handle
+// must be valid as long as the reader is being used.
+class FlatStringReader BASE_EMBEDDED {
+ public:
+  explicit FlatStringReader(Handle<String> str);
+  explicit FlatStringReader(Vector<const char> input);
+  ~FlatStringReader();
+  void RefreshState();
+  inline uc32 Get(int index);
+  int length() { return length_; }
+  static void PostGarbageCollectionProcessing();
+ private:
+  String** str_;
+  bool is_ascii_;
+  int length_;
+  const void* start_;
+  FlatStringReader* prev_;
+  static FlatStringReader* top_;
+};
+
+
+// Note that StringInputBuffers are not valid across a GC!  To fix this
+// it would have to store a String Handle instead of a String* and
+// AsciiStringReadBlock would have to be modified to use memcpy.
+//
+// StringInputBuffer is able to traverse any string regardless of how
+// deeply nested a sequence of ConsStrings it is made of.  However,
+// performance will be better if deep strings are flattened before they
+// are traversed.  Since flattening requires memory allocation this is
+// not always desirable, however (esp. in debugging situations).
+class StringInputBuffer: public unibrow::InputBuffer<String, String*, 1024> {
+ public:
+  virtual void Seek(unsigned pos);
+  inline StringInputBuffer(): unibrow::InputBuffer<String, String*, 1024>() {}
+  inline StringInputBuffer(String* backing):
+      unibrow::InputBuffer<String, String*, 1024>(backing) {}
+};
+
+
+class SafeStringInputBuffer
+  : public unibrow::InputBuffer<String, String**, 256> {
+ public:
+  virtual void Seek(unsigned pos);
+  inline SafeStringInputBuffer()
+      : unibrow::InputBuffer<String, String**, 256>() {}
+  inline SafeStringInputBuffer(String** backing)
+      : unibrow::InputBuffer<String, String**, 256>(backing) {}
+};
+
+
+template <typename T>
+class VectorIterator {
+ public:
+  VectorIterator(T* d, int l) : data_(Vector<const T>(d, l)), index_(0) { }
+  explicit VectorIterator(Vector<const T> data) : data_(data), index_(0) { }
+  T GetNext() { return data_[index_++]; }
+  bool has_more() { return index_ < data_.length(); }
+ private:
+  Vector<const T> data_;
+  int index_;
+};
+
+
+// The Oddball describes objects null, undefined, true, and false.
+class Oddball: public HeapObject {
+ public:
+  // [to_string]: Cached to_string computed at startup.
+  DECL_ACCESSORS(to_string, String)
+
+  // [to_number]: Cached to_number computed at startup.
+  DECL_ACCESSORS(to_number, Object)
+
+  // Casting.
+  static inline Oddball* cast(Object* obj);
+
+  // Dispatched behavior.
+  void OddballIterateBody(ObjectVisitor* v);
+#ifdef DEBUG
+  void OddballVerify();
+#endif
+
+  // Initialize the fields.
+  Object* Initialize(const char* to_string, Object* to_number);
+
+  // Layout description.
+  static const int kToStringOffset = HeapObject::kHeaderSize;
+  static const int kToNumberOffset = kToStringOffset + kPointerSize;
+  static const int kSize = kToNumberOffset + kPointerSize;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Oddball);
+};
+
+
+// Proxy describes objects pointing from JavaScript to C structures.
+// Since they cannot contain references to JS HeapObjects they can be
+// placed in old_data_space.
+class Proxy: public HeapObject {
+ public:
+  // [proxy]: field containing the address.
+  inline Address proxy();
+  inline void set_proxy(Address value);
+
+  // Casting.
+  static inline Proxy* cast(Object* obj);
+
+  // Dispatched behavior.
+  inline void ProxyIterateBody(ObjectVisitor* v);
+#ifdef DEBUG
+  void ProxyPrint();
+  void ProxyVerify();
+#endif
+
+  // Layout description.
+
+  static const int kProxyOffset = HeapObject::kHeaderSize;
+  static const int kSize = kProxyOffset + kPointerSize;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Proxy);
+};
+
+
+// The JSArray describes JavaScript Arrays
+//  Such an array can be in one of two modes:
+//    - fast, backing storage is a FixedArray and length <= elements.length();
+//       Please note: push and pop can be used to grow and shrink the array.
+//    - slow, backing storage is a HashTable with numbers as keys.
+class JSArray: public JSObject {
+ public:
+  // [length]: The length property.
+  DECL_ACCESSORS(length, Object)
+
+  Object* JSArrayUpdateLengthFromIndex(uint32_t index, Object* value);
+
+  // Initialize the array with the given capacity. The function may
+  // fail due to out-of-memory situations, but only if the requested
+  // capacity is non-zero.
+  Object* Initialize(int capacity);
+
+  // Set the content of the array to the content of storage.
+  inline void SetContent(FixedArray* storage);
+
+  // Support for sorting
+  Object* RemoveHoles();
+
+  // Casting.
+  static inline JSArray* cast(Object* obj);
+
+  // Uses handles.  Ensures that the fixed array backing the JSArray has at
+  // least the stated size.
+  void EnsureSize(int minimum_size_of_backing_fixed_array);
+
+  // Dispatched behavior.
+#ifdef DEBUG
+  void JSArrayPrint();
+  void JSArrayVerify();
+#endif
+
+  // Layout description.
+  static const int kLengthOffset = JSObject::kHeaderSize;
+  static const int kSize = kLengthOffset + kPointerSize;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(JSArray);
+};
+
+
+// An accessor must have a getter, but can have no setter.
+//
+// When setting a property, V8 searches accessors in prototypes.
+// If an accessor was found and it does not have a setter,
+// the request is ignored.
+//
+// To allow shadow an accessor property, the accessor can
+// have READ_ONLY property attribute so that a new value
+// is added to the local object to shadow the accessor
+// in prototypes.
+class AccessorInfo: public Struct {
+ public:
+  DECL_ACCESSORS(getter, Object)
+  DECL_ACCESSORS(setter, Object)
+  DECL_ACCESSORS(data, Object)
+  DECL_ACCESSORS(name, Object)
+  DECL_ACCESSORS(flag, Smi)
+
+  inline bool all_can_read();
+  inline void set_all_can_read(bool value);
+
+  inline bool all_can_write();
+  inline void set_all_can_write(bool value);
+
+  inline bool prohibits_overwriting();
+  inline void set_prohibits_overwriting(bool value);
+
+  inline PropertyAttributes property_attributes();
+  inline void set_property_attributes(PropertyAttributes attributes);
+
+  static inline AccessorInfo* cast(Object* obj);
+
+#ifdef DEBUG
+  void AccessorInfoPrint();
+  void AccessorInfoVerify();
+#endif
+
+  static const int kGetterOffset = HeapObject::kHeaderSize;
+  static const int kSetterOffset = kGetterOffset + kPointerSize;
+  static const int kDataOffset = kSetterOffset + kPointerSize;
+  static const int kNameOffset = kDataOffset + kPointerSize;
+  static const int kFlagOffset = kNameOffset + kPointerSize;
+  static const int kSize = kFlagOffset + kPointerSize;
+
+ private:
+  // Bit positions in flag.
+  static const int kAllCanReadBit = 0;
+  static const int kAllCanWriteBit = 1;
+  static const int kProhibitsOverwritingBit = 2;
+  class AttributesField: public BitField<PropertyAttributes, 3, 3> {};
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorInfo);
+};
+
+
+class AccessCheckInfo: public Struct {
+ public:
+  DECL_ACCESSORS(named_callback, Object)
+  DECL_ACCESSORS(indexed_callback, Object)
+  DECL_ACCESSORS(data, Object)
+
+  static inline AccessCheckInfo* cast(Object* obj);
+
+#ifdef DEBUG
+  void AccessCheckInfoPrint();
+  void AccessCheckInfoVerify();
+#endif
+
+  static const int kNamedCallbackOffset   = HeapObject::kHeaderSize;
+  static const int kIndexedCallbackOffset = kNamedCallbackOffset + kPointerSize;
+  static const int kDataOffset = kIndexedCallbackOffset + kPointerSize;
+  static const int kSize = kDataOffset + kPointerSize;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(AccessCheckInfo);
+};
+
+
+class InterceptorInfo: public Struct {
+ public:
+  DECL_ACCESSORS(getter, Object)
+  DECL_ACCESSORS(setter, Object)
+  DECL_ACCESSORS(query, Object)
+  DECL_ACCESSORS(deleter, Object)
+  DECL_ACCESSORS(enumerator, Object)
+  DECL_ACCESSORS(data, Object)
+
+  static inline InterceptorInfo* cast(Object* obj);
+
+#ifdef DEBUG
+  void InterceptorInfoPrint();
+  void InterceptorInfoVerify();
+#endif
+
+  static const int kGetterOffset = HeapObject::kHeaderSize;
+  static const int kSetterOffset = kGetterOffset + kPointerSize;
+  static const int kQueryOffset = kSetterOffset + kPointerSize;
+  static const int kDeleterOffset = kQueryOffset + kPointerSize;
+  static const int kEnumeratorOffset = kDeleterOffset + kPointerSize;
+  static const int kDataOffset = kEnumeratorOffset + kPointerSize;
+  static const int kSize = kDataOffset + kPointerSize;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(InterceptorInfo);
+};
+
+
+class CallHandlerInfo: public Struct {
+ public:
+  DECL_ACCESSORS(callback, Object)
+  DECL_ACCESSORS(data, Object)
+
+  static inline CallHandlerInfo* cast(Object* obj);
+
+#ifdef DEBUG
+  void CallHandlerInfoPrint();
+  void CallHandlerInfoVerify();
+#endif
+
+  static const int kCallbackOffset = HeapObject::kHeaderSize;
+  static const int kDataOffset = kCallbackOffset + kPointerSize;
+  static const int kSize = kDataOffset + kPointerSize;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(CallHandlerInfo);
+};
+
+
+class TemplateInfo: public Struct {
+ public:
+  DECL_ACCESSORS(tag, Object)
+  DECL_ACCESSORS(property_list, Object)
+
+#ifdef DEBUG
+  void TemplateInfoVerify();
+#endif
+
+  static const int kTagOffset          = HeapObject::kHeaderSize;
+  static const int kPropertyListOffset = kTagOffset + kPointerSize;
+  static const int kHeaderSize         = kPropertyListOffset + kPointerSize;
+ protected:
+  friend class AGCCVersionRequiresThisClassToHaveAFriendSoHereItIs;
+  DISALLOW_IMPLICIT_CONSTRUCTORS(TemplateInfo);
+};
+
+
+class FunctionTemplateInfo: public TemplateInfo {
+ public:
+  DECL_ACCESSORS(serial_number, Object)
+  DECL_ACCESSORS(call_code, Object)
+  DECL_ACCESSORS(property_accessors, Object)
+  DECL_ACCESSORS(prototype_template, Object)
+  DECL_ACCESSORS(parent_template, Object)
+  DECL_ACCESSORS(named_property_handler, Object)
+  DECL_ACCESSORS(indexed_property_handler, Object)
+  DECL_ACCESSORS(instance_template, Object)
+  DECL_ACCESSORS(class_name, Object)
+  DECL_ACCESSORS(signature, Object)
+  DECL_ACCESSORS(instance_call_handler, Object)
+  DECL_ACCESSORS(access_check_info, Object)
+  DECL_ACCESSORS(flag, Smi)
+
+  // Following properties use flag bits.
+  DECL_BOOLEAN_ACCESSORS(hidden_prototype)
+  DECL_BOOLEAN_ACCESSORS(undetectable)
+  // If the bit is set, object instances created by this function
+  // requires access check.
+  DECL_BOOLEAN_ACCESSORS(needs_access_check)
+
+  static inline FunctionTemplateInfo* cast(Object* obj);
+
+#ifdef DEBUG
+  void FunctionTemplateInfoPrint();
+  void FunctionTemplateInfoVerify();
+#endif
+
+  static const int kSerialNumberOffset = TemplateInfo::kHeaderSize;
+  static const int kCallCodeOffset = kSerialNumberOffset + kPointerSize;
+  static const int kPropertyAccessorsOffset = kCallCodeOffset + kPointerSize;
+  static const int kPrototypeTemplateOffset =
+      kPropertyAccessorsOffset + kPointerSize;
+  static const int kParentTemplateOffset =
+      kPrototypeTemplateOffset + kPointerSize;
+  static const int kNamedPropertyHandlerOffset =
+      kParentTemplateOffset + kPointerSize;
+  static const int kIndexedPropertyHandlerOffset =
+      kNamedPropertyHandlerOffset + kPointerSize;
+  static const int kInstanceTemplateOffset =
+      kIndexedPropertyHandlerOffset + kPointerSize;
+  static const int kClassNameOffset = kInstanceTemplateOffset + kPointerSize;
+  static const int kSignatureOffset = kClassNameOffset + kPointerSize;
+  static const int kInstanceCallHandlerOffset = kSignatureOffset + kPointerSize;
+  static const int kAccessCheckInfoOffset =
+      kInstanceCallHandlerOffset + kPointerSize;
+  static const int kFlagOffset = kAccessCheckInfoOffset + kPointerSize;
+  static const int kSize = kFlagOffset + kPointerSize;
+
+ private:
+  // Bit position in the flag, from least significant bit position.
+  static const int kHiddenPrototypeBit   = 0;
+  static const int kUndetectableBit      = 1;
+  static const int kNeedsAccessCheckBit  = 2;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo);
+};
+
+
+class ObjectTemplateInfo: public TemplateInfo {
+ public:
+  DECL_ACCESSORS(constructor, Object)
+  DECL_ACCESSORS(internal_field_count, Object)
+
+  static inline ObjectTemplateInfo* cast(Object* obj);
+
+#ifdef DEBUG
+  void ObjectTemplateInfoPrint();
+  void ObjectTemplateInfoVerify();
+#endif
+
+  static const int kConstructorOffset = TemplateInfo::kHeaderSize;
+  static const int kInternalFieldCountOffset =
+      kConstructorOffset + kPointerSize;
+  static const int kSize = kInternalFieldCountOffset + kHeaderSize;
+};
+
+
+class SignatureInfo: public Struct {
+ public:
+  DECL_ACCESSORS(receiver, Object)
+  DECL_ACCESSORS(args, Object)
+
+  static inline SignatureInfo* cast(Object* obj);
+
+#ifdef DEBUG
+  void SignatureInfoPrint();
+  void SignatureInfoVerify();
+#endif
+
+  static const int kReceiverOffset = Struct::kHeaderSize;
+  static const int kArgsOffset     = kReceiverOffset + kPointerSize;
+  static const int kSize           = kArgsOffset + kPointerSize;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(SignatureInfo);
+};
+
+
+class TypeSwitchInfo: public Struct {
+ public:
+  DECL_ACCESSORS(types, Object)
+
+  static inline TypeSwitchInfo* cast(Object* obj);
+
+#ifdef DEBUG
+  void TypeSwitchInfoPrint();
+  void TypeSwitchInfoVerify();
+#endif
+
+  static const int kTypesOffset = Struct::kHeaderSize;
+  static const int kSize        = kTypesOffset + kPointerSize;
+};
+
+
+// The DebugInfo class holds additional information for a function being
+// debugged.
+class DebugInfo: public Struct {
+ public:
+  // The shared function info for the source being debugged.
+  DECL_ACCESSORS(shared, SharedFunctionInfo)
+  // Code object for the original code.
+  DECL_ACCESSORS(original_code, Code)
+  // Code object for the patched code. This code object is the code object
+  // currently active for the function.
+  DECL_ACCESSORS(code, Code)
+  // Fixed array holding status information for each active break point.
+  DECL_ACCESSORS(break_points, FixedArray)
+
+  // Check if there is a break point at a code position.
+  bool HasBreakPoint(int code_position);
+  // Get the break point info object for a code position.
+  Object* GetBreakPointInfo(int code_position);
+  // Clear a break point.
+  static void ClearBreakPoint(Handle<DebugInfo> debug_info,
+                              int code_position,
+                              Handle<Object> break_point_object);
+  // Set a break point.
+  static void SetBreakPoint(Handle<DebugInfo> debug_info, int code_position,
+                            int source_position, int statement_position,
+                            Handle<Object> break_point_object);
+  // Get the break point objects for a code position.
+  Object* GetBreakPointObjects(int code_position);
+  // Find the break point info holding this break point object.
+  static Object* FindBreakPointInfo(Handle<DebugInfo> debug_info,
+                                    Handle<Object> break_point_object);
+  // Get the number of break points for this function.
+  int GetBreakPointCount();
+
+  static inline DebugInfo* cast(Object* obj);
+
+#ifdef DEBUG
+  void DebugInfoPrint();
+  void DebugInfoVerify();
+#endif
+
+  static const int kSharedFunctionInfoIndex = Struct::kHeaderSize;
+  static const int kOriginalCodeIndex = kSharedFunctionInfoIndex + kPointerSize;
+  static const int kPatchedCodeIndex = kOriginalCodeIndex + kPointerSize;
+  static const int kActiveBreakPointsCountIndex =
+      kPatchedCodeIndex + kPointerSize;
+  static const int kBreakPointsStateIndex =
+      kActiveBreakPointsCountIndex + kPointerSize;
+  static const int kSize = kBreakPointsStateIndex + kPointerSize;
+
+ private:
+  static const int kNoBreakPointInfo = -1;
+
+  // Lookup the index in the break_points array for a code position.
+  int GetBreakPointInfoIndex(int code_position);
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(DebugInfo);
+};
+
+
+// The BreakPointInfo class holds information for break points set in a
+// function. The DebugInfo object holds a BreakPointInfo object for each code
+// position with one or more break points.
+class BreakPointInfo: public Struct {
+ public:
+  // The position in the code for the break point.
+  DECL_ACCESSORS(code_position, Smi)
+  // The position in the source for the break position.
+  DECL_ACCESSORS(source_position, Smi)
+  // The position in the source for the last statement before this break
+  // position.
+  DECL_ACCESSORS(statement_position, Smi)
+  // List of related JavaScript break points.
+  DECL_ACCESSORS(break_point_objects, Object)
+
+  // Removes a break point.
+  static void ClearBreakPoint(Handle<BreakPointInfo> info,
+                              Handle<Object> break_point_object);
+  // Set a break point.
+  static void SetBreakPoint(Handle<BreakPointInfo> info,
+                            Handle<Object> break_point_object);
+  // Check if break point info has this break point object.
+  static bool HasBreakPointObject(Handle<BreakPointInfo> info,
+                                  Handle<Object> break_point_object);
+  // Get the number of break points for this code position.
+  int GetBreakPointCount();
+
+  static inline BreakPointInfo* cast(Object* obj);
+
+#ifdef DEBUG
+  void BreakPointInfoPrint();
+  void BreakPointInfoVerify();
+#endif
+
+  static const int kCodePositionIndex = Struct::kHeaderSize;
+  static const int kSourcePositionIndex = kCodePositionIndex + kPointerSize;
+  static const int kStatementPositionIndex =
+      kSourcePositionIndex + kPointerSize;
+  static const int kBreakPointObjectsIndex =
+      kStatementPositionIndex + kPointerSize;
+  static const int kSize = kBreakPointObjectsIndex + kPointerSize;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(BreakPointInfo);
+};
+
+
+#undef DECL_BOOLEAN_ACCESSORS
+#undef DECL_ACCESSORS
+
+
+// Abstract base class for visiting, and optionally modifying, the
+// pointers contained in Objects. Used in GC and serialization/deserialization.
+class ObjectVisitor BASE_EMBEDDED {
+ public:
+  virtual ~ObjectVisitor() {}
+
+  // Visits a contiguous arrays of pointers in the half-open range
+  // [start, end). Any or all of the values may be modified on return.
+  virtual void VisitPointers(Object** start, Object** end) = 0;
+
+  // To allow lazy clearing of inline caches the visitor has
+  // a rich interface for iterating over Code objects..
+
+  // Called prior to visiting the body of a Code object.
+  virtual void BeginCodeIteration(Code* code);
+
+  // Visits a code target in the instruction stream.
+  virtual void VisitCodeTarget(RelocInfo* rinfo);
+
+  // Visits a runtime entry in the instruction stream.
+  virtual void VisitRuntimeEntry(RelocInfo* rinfo) {}
+
+  // Visits a debug call target in the instruction stream.
+  virtual void VisitDebugTarget(RelocInfo* rinfo);
+
+  // Called after completing  visiting the body of a Code object.
+  virtual void EndCodeIteration(Code* code) {}
+
+  // Handy shorthand for visiting a single pointer.
+  virtual void VisitPointer(Object** p) { VisitPointers(p, p + 1); }
+
+  // Visits a contiguous arrays of external references (references to the C++
+  // heap) in the half-open range [start, end). Any or all of the values
+  // may be modified on return.
+  virtual void VisitExternalReferences(Address* start, Address* end) {}
+
+  inline void VisitExternalReference(Address* p) {
+    VisitExternalReferences(p, p + 1);
+  }
+
+#ifdef DEBUG
+  // Intended for serialization/deserialization checking: insert, or
+  // check for the presence of, a tag at this position in the stream.
+  virtual void Synchronize(const char* tag) {}
+#endif
+};
+
+
+// BooleanBit is a helper class for setting and getting a bit in an
+// integer or Smi.
+class BooleanBit : public AllStatic {
+ public:
+  static inline bool get(Smi* smi, int bit_position) {
+    return get(smi->value(), bit_position);
+  }
+
+  static inline bool get(int value, int bit_position) {
+    return (value & (1 << bit_position)) != 0;
+  }
+
+  static inline Smi* set(Smi* smi, int bit_position, bool v) {
+    return Smi::FromInt(set(smi->value(), bit_position, v));
+  }
+
+  static inline int set(int value, int bit_position, bool v) {
+    if (v) {
+      value |= (1 << bit_position);
+    } else {
+      value &= ~(1 << bit_position);
+    }
+    return value;
+  }
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_OBJECTS_H_
diff --git a/deps/v8/src/oprofile-agent.cc b/deps/v8/src/oprofile-agent.cc
new file mode 100644
index 0000000..e9f7d3e
--- /dev/null
+++ b/deps/v8/src/oprofile-agent.cc
@@ -0,0 +1,111 @@
+// Copyright 2006-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.
+
+#include "v8.h"
+
+#include "oprofile-agent.h"
+
+namespace v8 { namespace internal {
+
+#ifdef ENABLE_OPROFILE_AGENT
+op_agent_t OProfileAgent::handle_ = NULL;
+#endif
+
+
+bool OProfileAgent::Initialize() {
+#ifdef ENABLE_OPROFILE_AGENT
+  if (FLAG_oprofile) {
+    if (handle_ != NULL) return false;
+
+    // Disable code moving by GC.
+    FLAG_always_compact = false;
+    FLAG_never_compact = true;
+
+    handle_ = op_open_agent();
+    return (handle_ != NULL);
+  } else {
+    return true;
+  }
+#else
+  return true;
+#endif
+}
+
+
+void OProfileAgent::TearDown() {
+#ifdef ENABLE_OPROFILE_AGENT
+  if (handle_ != NULL) {
+    op_close_agent(handle_);
+  }
+#endif
+}
+
+
+void OProfileAgent::CreateNativeCodeRegion(const char* name,
+    const void* ptr, unsigned int size) {
+#ifdef ENABLE_OPROFILE_AGENT
+  if (handle_ == NULL) return;
+  op_write_native_code(handle_, name, (uint64_t)ptr, ptr, size);
+#endif
+}
+
+
+void OProfileAgent::CreateNativeCodeRegion(String* name,
+    const void* ptr, unsigned int size) {
+#ifdef ENABLE_OPROFILE_AGENT
+  if (handle_ != NULL) {
+    const char* func_name;
+    SmartPointer<char> str =
+        name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+    func_name = name->length() > 0 ? *str : "<anonymous>";
+    CreateNativeCodeRegion(func_name, ptr, size);
+  }
+#endif
+}
+
+
+void OProfileAgent::CreateNativeCodeRegion(String* name, String* source,
+    int line_num, const void* ptr, unsigned int size) {
+#ifdef ENABLE_OPROFILE_AGENT
+  if (handle_ != NULL) {
+    Vector<char> buf = Vector<char>::New(OProfileAgent::kFormattingBufSize);
+    const char* func_name;
+    SmartPointer<char> str =
+        name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+    func_name = name->length() > 0 ? *str : "<anonymous>";
+    SmartPointer<char> source_str =
+        source->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+    if (v8::internal::OS::SNPrintF(buf, "%s %s:%d",
+                                   func_name, *source_str, line_num) != -1) {
+      CreateNativeCodeRegion(buf.start(), ptr, size);
+    } else {
+      CreateNativeCodeRegion("<script/func name too long>", ptr, size);
+    }
+  }
+#endif
+}
+} }
diff --git a/deps/v8/src/oprofile-agent.h b/deps/v8/src/oprofile-agent.h
new file mode 100644
index 0000000..75cfe18
--- /dev/null
+++ b/deps/v8/src/oprofile-agent.h
@@ -0,0 +1,68 @@
+// Copyright 2006-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.
+
+#ifndef V8_OPROFILE_AGENT_H_
+#define V8_OPROFILE_AGENT_H_
+
+#include <stdlib.h>
+
+#include "globals.h"
+
+#ifdef ENABLE_OPROFILE_AGENT
+// opagent.h uses uint64_t type, which can be missing in
+// system headers (they have __uint64_t), but is defined
+// in V8's headers.
+#include <opagent.h>  // NOLINT
+#endif
+
+namespace v8 { namespace internal {
+
+class OProfileAgent {
+ public:
+  static bool Initialize();
+  static void TearDown();
+  static void CreateNativeCodeRegion(const char* name,
+                                     const void* ptr, unsigned int size);
+  static void CreateNativeCodeRegion(String* name,
+                                     const void* ptr, unsigned int size);
+  static void CreateNativeCodeRegion(String* name, String* source, int line_num,
+                                     const void* ptr, unsigned int size);
+#ifdef ENABLE_OPROFILE_AGENT
+  static bool is_enabled() { return handle_ != NULL; }
+
+ private:
+  static op_agent_t handle_;
+
+  // Size of the buffer that is used for composing code areas names.
+  static const int kFormattingBufSize = 256;
+#else
+  static bool is_enabled() { return false; }
+#endif
+};
+} }
+
+#endif  // V8_OPROFILE_AGENT_H_
diff --git a/deps/v8/src/parser.cc b/deps/v8/src/parser.cc
new file mode 100644
index 0000000..9db10cf
--- /dev/null
+++ b/deps/v8/src/parser.cc
@@ -0,0 +1,4579 @@
+// 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.
+
+#include "v8.h"
+
+#include "api.h"
+#include "ast.h"
+#include "bootstrapper.h"
+#include "platform.h"
+#include "runtime.h"
+#include "parser.h"
+#include "scopes.h"
+#include "string-stream.h"
+
+namespace v8 { namespace internal {
+
+class ParserFactory;
+class ParserLog;
+class TemporaryScope;
+template <typename T> class ZoneListWrapper;
+
+
+class Parser {
+ public:
+  Parser(Handle<Script> script, bool allow_natives_syntax,
+         v8::Extension* extension, bool is_pre_parsing,
+         ParserFactory* factory, ParserLog* log, ScriptDataImpl* pre_data);
+  virtual ~Parser() { }
+
+  // Pre-parse the program from the character stream; returns true on
+  // success, false if a stack-overflow happened during parsing.
+  bool PreParseProgram(unibrow::CharacterStream* stream);
+
+  void ReportMessage(const char* message, Vector<const char*> args);
+  virtual void ReportMessageAt(Scanner::Location loc,
+                               const char* message,
+                               Vector<const char*> args) = 0;
+
+
+  // Returns NULL if parsing failed.
+  FunctionLiteral* ParseProgram(Handle<String> source,
+                                unibrow::CharacterStream* stream,
+                                bool in_global_context);
+  FunctionLiteral* ParseLazy(Handle<String> source,
+                             Handle<String> name,
+                             int start_position, bool is_expression);
+
+  // The minimum number of contiguous assignment that will
+  // be treated as an initialization block. Benchmarks show that
+  // the overhead exceeds the savings below this limit.
+  static const int kMinInitializationBlock = 3;
+
+ protected:
+
+  enum Mode {
+    PARSE_LAZILY,
+    PARSE_EAGERLY
+  };
+
+  // Report syntax error
+  void ReportUnexpectedToken(Token::Value token);
+
+  Handle<Script> script_;
+  Scanner scanner_;
+
+  Scope* top_scope_;
+  int with_nesting_level_;
+
+  TemporaryScope* temp_scope_;
+  Mode mode_;
+  List<Node*>* target_stack_;  // for break, continue statements
+  bool allow_natives_syntax_;
+  v8::Extension* extension_;
+  ParserFactory* factory_;
+  ParserLog* log_;
+  bool is_pre_parsing_;
+  ScriptDataImpl* pre_data_;
+
+  bool inside_with() const  { return with_nesting_level_ > 0; }
+  ParserFactory* factory() const  { return factory_; }
+  ParserLog* log() const { return log_; }
+  Scanner& scanner()  { return scanner_; }
+  Mode mode() const  { return mode_; }
+  ScriptDataImpl* pre_data() const  { return pre_data_; }
+
+  // All ParseXXX functions take as the last argument an *ok parameter
+  // which is set to false if parsing failed; it is unchanged otherwise.
+  // By making the 'exception handling' explicit, we are forced to check
+  // for failure at the call sites.
+  void* ParseSourceElements(ZoneListWrapper<Statement>* processor,
+                            int end_token, bool* ok);
+  Statement* ParseStatement(ZoneStringList* labels, bool* ok);
+  Statement* ParseFunctionDeclaration(bool* ok);
+  Statement* ParseNativeDeclaration(bool* ok);
+  Block* ParseBlock(ZoneStringList* labels, bool* ok);
+  Block* ParseVariableStatement(bool* ok);
+  Block* ParseVariableDeclarations(bool accept_IN, Expression** var, bool* ok);
+  Statement* ParseExpressionOrLabelledStatement(ZoneStringList* labels,
+                                                bool* ok);
+  IfStatement* ParseIfStatement(ZoneStringList* labels, bool* ok);
+  Statement* ParseContinueStatement(bool* ok);
+  Statement* ParseBreakStatement(ZoneStringList* labels, bool* ok);
+  Statement* ParseReturnStatement(bool* ok);
+  Block* WithHelper(Expression* obj,
+                    ZoneStringList* labels,
+                    bool is_catch_block,
+                    bool* ok);
+  Statement* ParseWithStatement(ZoneStringList* labels, bool* ok);
+  CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok);
+  SwitchStatement* ParseSwitchStatement(ZoneStringList* labels, bool* ok);
+  LoopStatement* ParseDoStatement(ZoneStringList* labels, bool* ok);
+  LoopStatement* ParseWhileStatement(ZoneStringList* labels, bool* ok);
+  Statement* ParseForStatement(ZoneStringList* labels, bool* ok);
+  Statement* ParseThrowStatement(bool* ok);
+  Expression* MakeCatchContext(Handle<String> id, VariableProxy* value);
+  TryStatement* ParseTryStatement(bool* ok);
+  DebuggerStatement* ParseDebuggerStatement(bool* ok);
+
+  Expression* ParseExpression(bool accept_IN, bool* ok);
+  Expression* ParseAssignmentExpression(bool accept_IN, bool* ok);
+  Expression* ParseConditionalExpression(bool accept_IN, bool* ok);
+  Expression* ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
+  Expression* ParseUnaryExpression(bool* ok);
+  Expression* ParsePostfixExpression(bool* ok);
+  Expression* ParseLeftHandSideExpression(bool* ok);
+  Expression* ParseNewExpression(bool* ok);
+  Expression* ParseMemberExpression(bool* ok);
+  Expression* ParseMemberWithNewPrefixesExpression(List<int>* new_prefixes,
+                                                   bool* ok);
+  Expression* ParsePrimaryExpression(bool* ok);
+  Expression* ParseArrayLiteral(bool* ok);
+  Expression* ParseObjectLiteral(bool* ok);
+  Expression* ParseRegExpLiteral(bool seen_equal, bool* ok);
+
+  // Decide if a property should be the object boilerplate.
+  bool IsBoilerplateProperty(ObjectLiteral::Property* property);
+  // If the expression is a literal, return the literal value;
+  // if the expression is a materialized literal and is simple return a
+  // compile time value as encoded by CompileTimeValue::GetValue().
+  // Otherwise, return undefined literal as the placeholder
+  // in the object literal boilerplate.
+  Handle<Object> GetBoilerplateValue(Expression* expression);
+
+  enum FunctionLiteralType {
+    EXPRESSION,
+    DECLARATION,
+    NESTED
+  };
+
+  ZoneList<Expression*>* ParseArguments(bool* ok);
+  FunctionLiteral* ParseFunctionLiteral(Handle<String> var_name,
+                                        int function_token_position,
+                                        FunctionLiteralType type,
+                                        bool* ok);
+
+
+  // Magical syntax support.
+  Expression* ParseV8Intrinsic(bool* ok);
+
+  INLINE(Token::Value peek()) { return scanner_.peek(); }
+  INLINE(Token::Value Next()) { return scanner_.Next(); }
+  INLINE(void Consume(Token::Value token));
+  void Expect(Token::Value token, bool* ok);
+  void ExpectSemicolon(bool* ok);
+
+  // Get odd-ball literals.
+  Literal* GetLiteralUndefined();
+  Literal* GetLiteralTheHole();
+  Literal* GetLiteralNumber(double value);
+
+  Handle<String> ParseIdentifier(bool* ok);
+  Handle<String> ParseIdentifierOrGetOrSet(bool* is_get,
+                                           bool* is_set,
+                                           bool* ok);
+
+  // Parser support
+  virtual VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
+                                 FunctionLiteral* fun,
+                                 bool resolve,
+                                 bool* ok) = 0;
+
+  bool TargetStackContainsLabel(Handle<String> label);
+  BreakableStatement* LookupBreakTarget(Handle<String> label, bool* ok);
+  IterationStatement* LookupContinueTarget(Handle<String> label, bool* ok);
+
+  void RegisterTargetUse(BreakTarget* target, int index);
+
+  // Create a number literal.
+  Literal* NewNumberLiteral(double value);
+
+  // Generate AST node that throw a ReferenceError with the given type.
+  Expression* NewThrowReferenceError(Handle<String> type);
+
+  // Generate AST node that throw a SyntaxError with the given
+  // type. The first argument may be null (in the handle sense) in
+  // which case no arguments are passed to the constructor.
+  Expression* NewThrowSyntaxError(Handle<String> type, Handle<Object> first);
+
+  // Generate AST node that throw a TypeError with the given
+  // type. Both arguments must be non-null (in the handle sense).
+  Expression* NewThrowTypeError(Handle<String> type,
+                                Handle<Object> first,
+                                Handle<Object> second);
+
+  // Generic AST generator for throwing errors from compiled code.
+  Expression* NewThrowError(Handle<String> constructor,
+                            Handle<String> type,
+                            Vector< Handle<Object> > arguments);
+
+  friend class Target;
+  friend class TargetScope;
+  friend class LexicalScope;
+  friend class TemporaryScope;
+};
+
+
+template <typename T, int initial_size>
+class BufferedZoneList {
+ public:
+
+  BufferedZoneList() :
+    list_(NULL), last_(NULL) {}
+
+  // Adds element at end of list. This element is buffered and can
+  // be read using last() or removed using RemoveLast until a new Add or until
+  // RemoveLast or GetList has been called.
+  void Add(T* value) {
+    if (last_ != NULL) {
+      if (list_ == NULL) {
+        list_ = new ZoneList<T*>(initial_size);
+      }
+      list_->Add(last_);
+    }
+    last_ = value;
+  }
+
+  T* last() {
+    ASSERT(last_ != NULL);
+    return last_;
+  }
+
+  T* RemoveLast() {
+    ASSERT(last_ != NULL);
+    T* result = last_;
+    if (list_ != NULL && list_->length() > 0)
+      last_ = list_->RemoveLast();
+    else
+      last_ = NULL;
+    return result;
+  }
+
+  T* Get(int i) {
+    ASSERT(0 <= i && i < length());
+    if (list_ == NULL) {
+      ASSERT_EQ(0, i);
+      return last_;
+    } else {
+      if (i == list_->length()) {
+        ASSERT(last_ != NULL);
+        return last_;
+      } else {
+        return list_->at(i);
+      }
+    }
+  }
+
+  void Clear() {
+    list_ = NULL;
+    last_ = NULL;
+  }
+
+  int length() {
+    int length = (list_ == NULL) ? 0 : list_->length();
+    return length + ((last_ == NULL) ? 0 : 1);
+  }
+
+  ZoneList<T*>* GetList() {
+    if (list_ == NULL) {
+      list_ = new ZoneList<T*>(initial_size);
+    }
+    if (last_ != NULL) {
+      list_->Add(last_);
+      last_ = NULL;
+    }
+    return list_;
+  }
+
+ private:
+  ZoneList<T*>* list_;
+  T* last_;
+};
+
+// Accumulates RegExp atoms and assertions into lists of terms and alternatives.
+class RegExpBuilder {
+ public:
+  RegExpBuilder();
+  void AddCharacter(uc16 character);
+  // "Adds" an empty expression. Does nothing except consume a
+  // following quantifier
+  void AddEmpty();
+  void AddAtom(RegExpTree* tree);
+  void AddAssertion(RegExpTree* tree);
+  void NewAlternative();  // '|'
+  void AddQuantifierToAtom(int min, int max, bool is_greedy);
+  RegExpTree* ToRegExp();
+ private:
+  void FlushCharacters();
+  void FlushText();
+  void FlushTerms();
+  bool pending_empty_;
+  ZoneList<uc16>* characters_;
+  BufferedZoneList<RegExpTree, 2> terms_;
+  BufferedZoneList<RegExpTree, 2> text_;
+  BufferedZoneList<RegExpTree, 2> alternatives_;
+#ifdef DEBUG
+  enum {ADD_NONE, ADD_CHAR, ADD_TERM, ADD_ASSERT, ADD_ATOM} last_added_;
+#define LAST(x) last_added_ = x;
+#else
+#define LAST(x)
+#endif
+};
+
+
+RegExpBuilder::RegExpBuilder()
+  : pending_empty_(false), characters_(NULL), terms_(), alternatives_()
+#ifdef DEBUG
+  , last_added_(ADD_NONE)
+#endif
+  {}
+
+
+void RegExpBuilder::FlushCharacters() {
+  pending_empty_ = false;
+  if (characters_ != NULL) {
+    RegExpTree* atom = new RegExpAtom(characters_->ToConstVector());
+    characters_ = NULL;
+    text_.Add(atom);
+    LAST(ADD_ATOM);
+  }
+}
+
+
+void RegExpBuilder::FlushText() {
+  FlushCharacters();
+  int num_text = text_.length();
+  if (num_text == 0) {
+    return;
+  } else if (num_text == 1) {
+    terms_.Add(text_.last());
+  } else {
+    RegExpText* text = new RegExpText();
+    for (int i = 0; i < num_text; i++)
+      text_.Get(i)->AppendToText(text);
+    terms_.Add(text);
+  }
+  text_.Clear();
+}
+
+
+void RegExpBuilder::AddCharacter(uc16 c) {
+  pending_empty_ = false;
+  if (characters_ == NULL) {
+    characters_ = new ZoneList<uc16>(4);
+  }
+  characters_->Add(c);
+  LAST(ADD_CHAR);
+}
+
+
+void RegExpBuilder::AddEmpty() {
+  pending_empty_ = true;
+}
+
+
+void RegExpBuilder::AddAtom(RegExpTree* term) {
+  if (term->IsEmpty()) {
+    AddEmpty();
+    return;
+  }
+  if (term->IsTextElement()) {
+    FlushCharacters();
+    text_.Add(term);
+  } else {
+    FlushText();
+    terms_.Add(term);
+  }
+  LAST(ADD_ATOM);
+}
+
+
+void RegExpBuilder::AddAssertion(RegExpTree* assert) {
+  FlushText();
+  terms_.Add(assert);
+  LAST(ADD_ASSERT);
+}
+
+
+void RegExpBuilder::NewAlternative() {
+  FlushTerms();
+}
+
+
+void RegExpBuilder::FlushTerms() {
+  FlushText();
+  int num_terms = terms_.length();
+  RegExpTree* alternative;
+  if (num_terms == 0) {
+    alternative = RegExpEmpty::GetInstance();
+  } else if (num_terms == 1) {
+    alternative = terms_.last();
+  } else {
+    alternative = new RegExpAlternative(terms_.GetList());
+  }
+  alternatives_.Add(alternative);
+  terms_.Clear();
+  LAST(ADD_NONE);
+}
+
+
+RegExpTree* RegExpBuilder::ToRegExp() {
+  FlushTerms();
+  int num_alternatives = alternatives_.length();
+  if (num_alternatives == 0) {
+    return RegExpEmpty::GetInstance();
+  }
+  if (num_alternatives == 1) {
+    return alternatives_.last();
+  }
+  return new RegExpDisjunction(alternatives_.GetList());
+}
+
+
+void RegExpBuilder::AddQuantifierToAtom(int min, int max, bool is_greedy) {
+  if (pending_empty_) {
+    pending_empty_ = false;
+    return;
+  }
+  RegExpTree* atom;
+  if (characters_ != NULL) {
+    ASSERT(last_added_ == ADD_CHAR);
+    // Last atom was character.
+    Vector<const uc16> char_vector = characters_->ToConstVector();
+    int num_chars = char_vector.length();
+    if (num_chars > 1) {
+      Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1);
+      text_.Add(new RegExpAtom(prefix));
+      char_vector = char_vector.SubVector(num_chars - 1, num_chars);
+    }
+    characters_ = NULL;
+    atom = new RegExpAtom(char_vector);
+    FlushText();
+  } else if (text_.length() > 0) {
+    ASSERT(last_added_ == ADD_ATOM);
+    atom = text_.RemoveLast();
+    FlushText();
+  } else if (terms_.length() > 0) {
+    ASSERT(last_added_ == ADD_ATOM);
+    atom = terms_.RemoveLast();
+    if (atom->max_match() == 0) {
+      // Guaranteed to only match an empty string.
+      LAST(ADD_TERM);
+      if (min == 0) {
+        return;
+      }
+      terms_.Add(atom);
+      return;
+    }
+  } else {
+    // Only call immediately after adding an atom or character!
+    UNREACHABLE();
+    return;
+  }
+  terms_.Add(new RegExpQuantifier(min, max, is_greedy, atom));
+  LAST(ADD_TERM);
+}
+
+
+class RegExpParser {
+ public:
+  RegExpParser(FlatStringReader* in,
+               Handle<String>* error,
+               bool multiline_mode);
+  RegExpTree* ParsePattern();
+  RegExpTree* ParseDisjunction();
+  RegExpTree* ParseGroup();
+  RegExpTree* ParseCharacterClass();
+
+  // Parses a {...,...} quantifier and stores the range in the given
+  // out parameters.
+  bool ParseIntervalQuantifier(int* min_out, int* max_out);
+
+  // Parses and returns a single escaped character.  The character
+  // must not be 'b' or 'B' since they are usually handle specially.
+  uc32 ParseClassCharacterEscape();
+
+  // Checks whether the following is a length-digit hexadecimal number,
+  // and sets the value if it is.
+  bool ParseHexEscape(int length, uc32* value);
+
+  uc32 ParseControlLetterEscape();
+  uc32 ParseOctalLiteral();
+
+  // Tries to parse the input as a back reference.  If successful it
+  // stores the result in the output parameter and returns true.  If
+  // it fails it will push back the characters read so the same characters
+  // can be reparsed.
+  bool ParseBackReferenceIndex(int* index_out);
+
+  CharacterRange ParseClassAtom(uc16* char_class);
+  RegExpTree* ReportError(Vector<const char> message);
+  void Advance();
+  void Advance(int dist);
+  void Reset(int pos);
+
+  // Reports whether the pattern might be used as a literal search string.
+  // Only use if the result of the parse is a single atom node.
+  bool simple();
+  bool contains_anchor() { return contains_anchor_; }
+  void set_contains_anchor() { contains_anchor_ = true; }
+  int captures_started() { return captures_ == NULL ? 0 : captures_->length(); }
+  int position() { return next_pos_ - 1; }
+  bool failed() { return failed_; }
+
+  static const int kMaxCaptures = 1 << 16;
+  static const uc32 kEndMarker = (1 << 21);
+ private:
+
+  uc32 current() { return current_; }
+  bool has_more() { return has_more_; }
+  bool has_next() { return next_pos_ < in()->length(); }
+  uc32 Next();
+  FlatStringReader* in() { return in_; }
+  void ScanForCaptures();
+  bool CaptureAvailable(int index);
+  uc32 current_;
+  bool has_more_;
+  bool multiline_;
+  int next_pos_;
+  FlatStringReader* in_;
+  Handle<String>* error_;
+  bool simple_;
+  bool contains_anchor_;
+  ZoneList<RegExpCapture*>* captures_;
+  bool is_scanned_for_captures_;
+  // The capture count is only valid after we have scanned for captures.
+  int capture_count_;
+  bool failed_;
+};
+
+
+// A temporary scope stores information during parsing, just like
+// a plain scope.  However, temporary scopes are not kept around
+// after parsing or referenced by syntax trees so they can be stack-
+// allocated and hence used by the pre-parser.
+class TemporaryScope BASE_EMBEDDED {
+ public:
+  explicit TemporaryScope(Parser* parser);
+  ~TemporaryScope();
+
+  int NextMaterializedLiteralIndex() {
+    int next_index =
+        materialized_literal_count_ + JSFunction::kLiteralsPrefixSize;
+    materialized_literal_count_++;
+    return next_index;
+  }
+  int materialized_literal_count() { return materialized_literal_count_; }
+
+  void set_contains_array_literal() { contains_array_literal_ = true; }
+  bool contains_array_literal() { return contains_array_literal_; }
+
+  void AddProperty() { expected_property_count_++; }
+  int expected_property_count() { return expected_property_count_; }
+ private:
+  // Captures the number of nodes that need materialization in the
+  // function.  regexp literals, and boilerplate for object literals.
+  int materialized_literal_count_;
+
+  // Captures whether or not the function contains array literals.  If
+  // the function contains array literals, we have to allocate space
+  // for the array constructor in the literals array of the function.
+  // This array constructor is used when creating the actual array
+  // literals.
+  bool contains_array_literal_;
+
+  // Properties count estimation.
+  int expected_property_count_;
+
+  // Bookkeeping
+  Parser* parser_;
+  TemporaryScope* parent_;
+
+  friend class Parser;
+};
+
+
+TemporaryScope::TemporaryScope(Parser* parser)
+  : materialized_literal_count_(0),
+    contains_array_literal_(false),
+    expected_property_count_(0),
+    parser_(parser),
+    parent_(parser->temp_scope_) {
+  parser->temp_scope_ = this;
+}
+
+
+TemporaryScope::~TemporaryScope() {
+  parser_->temp_scope_ = parent_;
+}
+
+
+// A zone list wrapper lets code either access a access a zone list
+// or appear to do so while actually ignoring all operations.
+template <typename T>
+class ZoneListWrapper {
+ public:
+  ZoneListWrapper() : list_(NULL) { }
+  explicit ZoneListWrapper(int size) : list_(new ZoneList<T*>(size)) { }
+  void Add(T* that) { if (list_) list_->Add(that); }
+  int length() { return list_->length(); }
+  ZoneList<T*>* elements() { return list_; }
+  T* at(int index) { return list_->at(index); }
+ private:
+  ZoneList<T*>* list_;
+};
+
+
+// Allocation macro that should be used to allocate objects that must
+// only be allocated in real parsing mode.  Note that in preparse mode
+// not only is the syntax tree not created but the constructor
+// arguments are not evaluated.
+#define NEW(expr) (is_pre_parsing_ ? NULL : new expr)
+
+
+class ParserFactory BASE_EMBEDDED {
+ public:
+  explicit ParserFactory(bool is_pre_parsing) :
+      is_pre_parsing_(is_pre_parsing) { }
+
+  virtual ~ParserFactory() { }
+
+  virtual Scope* NewScope(Scope* parent, Scope::Type type, bool inside_with);
+
+  virtual Handle<String> LookupSymbol(const char* string, int length) {
+    return Handle<String>();
+  }
+
+  virtual Handle<String> EmptySymbol() {
+    return Handle<String>();
+  }
+
+  virtual Expression* NewProperty(Expression* obj, Expression* key, int pos) {
+    if (obj == VariableProxySentinel::this_proxy()) {
+      return Property::this_property();
+    } else {
+      return ValidLeftHandSideSentinel::instance();
+    }
+  }
+
+  virtual Expression* NewCall(Expression* expression,
+                              ZoneList<Expression*>* arguments,
+                              int pos) {
+    return Call::sentinel();
+  }
+
+  virtual Expression* NewCallEval(Expression* expression,
+                                  ZoneList<Expression*>* arguments,
+                                  int pos) {
+    return CallEval::sentinel();
+  }
+
+  virtual Statement* EmptyStatement() {
+    return NULL;
+  }
+
+  template <typename T> ZoneListWrapper<T> NewList(int size) {
+    return is_pre_parsing_ ? ZoneListWrapper<T>() : ZoneListWrapper<T>(size);
+  }
+
+ private:
+  bool is_pre_parsing_;
+};
+
+
+class ParserLog BASE_EMBEDDED {
+ public:
+  virtual ~ParserLog() { }
+
+  // Records the occurrence of a function.  The returned object is
+  // only guaranteed to be valid until the next function has been
+  // logged.
+  virtual FunctionEntry LogFunction(int start) { return FunctionEntry(); }
+
+  virtual void LogError() { }
+};
+
+
+class AstBuildingParserFactory : public ParserFactory {
+ public:
+  AstBuildingParserFactory() : ParserFactory(false) { }
+
+  virtual Scope* NewScope(Scope* parent, Scope::Type type, bool inside_with);
+
+  virtual Handle<String> LookupSymbol(const char* string, int length) {
+    return Factory::LookupSymbol(Vector<const char>(string, length));
+  }
+
+  virtual Handle<String> EmptySymbol() {
+    return Factory::empty_symbol();
+  }
+
+  virtual Expression* NewProperty(Expression* obj, Expression* key, int pos) {
+    return new Property(obj, key, pos);
+  }
+
+  virtual Expression* NewCall(Expression* expression,
+                              ZoneList<Expression*>* arguments,
+                              int pos) {
+    return new Call(expression, arguments, pos);
+  }
+
+  virtual Expression* NewCallEval(Expression* expression,
+                                  ZoneList<Expression*>* arguments,
+                                  int pos) {
+    return new CallEval(expression, arguments, pos);
+  }
+
+  virtual Statement* EmptyStatement() {
+    // Use a statically allocated empty statement singleton to avoid
+    // allocating lots and lots of empty statements.
+    static v8::internal::EmptyStatement empty;
+    return &empty;
+  }
+};
+
+
+class ParserRecorder: public ParserLog {
+ public:
+  ParserRecorder();
+  virtual FunctionEntry LogFunction(int start);
+  virtual void LogError() { }
+  virtual void LogMessage(Scanner::Location loc,
+                          const char* message,
+                          Vector<const char*> args);
+  void WriteString(Vector<const char> str);
+  static const char* ReadString(unsigned* start, int* chars);
+  List<unsigned>* store() { return &store_; }
+ private:
+  bool has_error_;
+  List<unsigned> store_;
+};
+
+
+FunctionEntry ScriptDataImpl::GetFunctionEnd(int start) {
+  if (nth(last_entry_).start_pos() > start) {
+    // If the last entry we looked up is higher than what we're
+    // looking for then it's useless and we reset it.
+    last_entry_ = 0;
+  }
+  for (int i = last_entry_; i < EntryCount(); i++) {
+    FunctionEntry entry = nth(i);
+    if (entry.start_pos() == start) {
+      last_entry_ = i;
+      return entry;
+    }
+  }
+  return FunctionEntry();
+}
+
+
+bool ScriptDataImpl::SanityCheck() {
+  if (store_.length() < static_cast<int>(ScriptDataImpl::kHeaderSize))
+    return false;
+  if (magic() != ScriptDataImpl::kMagicNumber)
+    return false;
+  if (version() != ScriptDataImpl::kCurrentVersion)
+    return false;
+  return true;
+}
+
+
+int ScriptDataImpl::EntryCount() {
+  return (store_.length() - kHeaderSize) / FunctionEntry::kSize;
+}
+
+
+FunctionEntry ScriptDataImpl::nth(int n) {
+  int offset = kHeaderSize + n * FunctionEntry::kSize;
+  return FunctionEntry(Vector<unsigned>(store_.start() + offset,
+                                        FunctionEntry::kSize));
+}
+
+
+ParserRecorder::ParserRecorder()
+  : has_error_(false), store_(4) {
+  Vector<unsigned> preamble = store()->AddBlock(0, ScriptDataImpl::kHeaderSize);
+  preamble[ScriptDataImpl::kMagicOffset] = ScriptDataImpl::kMagicNumber;
+  preamble[ScriptDataImpl::kVersionOffset] = ScriptDataImpl::kCurrentVersion;
+  preamble[ScriptDataImpl::kHasErrorOffset] = false;
+}
+
+
+void ParserRecorder::WriteString(Vector<const char> str) {
+  store()->Add(str.length());
+  for (int i = 0; i < str.length(); i++)
+    store()->Add(str[i]);
+}
+
+
+const char* ParserRecorder::ReadString(unsigned* start, int* chars) {
+  int length = start[0];
+  char* result = NewArray<char>(length + 1);
+  for (int i = 0; i < length; i++)
+    result[i] = start[i + 1];
+  result[length] = '\0';
+  if (chars != NULL) *chars = length;
+  return result;
+}
+
+
+void ParserRecorder::LogMessage(Scanner::Location loc, const char* message,
+                                Vector<const char*> args) {
+  if (has_error_) return;
+  store()->Rewind(ScriptDataImpl::kHeaderSize);
+  store()->at(ScriptDataImpl::kHasErrorOffset) = true;
+  store()->Add(loc.beg_pos);
+  store()->Add(loc.end_pos);
+  store()->Add(args.length());
+  WriteString(CStrVector(message));
+  for (int i = 0; i < args.length(); i++)
+    WriteString(CStrVector(args[i]));
+}
+
+
+Scanner::Location ScriptDataImpl::MessageLocation() {
+  int beg_pos = Read(0);
+  int end_pos = Read(1);
+  return Scanner::Location(beg_pos, end_pos);
+}
+
+
+const char* ScriptDataImpl::BuildMessage() {
+  unsigned* start = ReadAddress(3);
+  return ParserRecorder::ReadString(start, NULL);
+}
+
+
+Vector<const char*> ScriptDataImpl::BuildArgs() {
+  int arg_count = Read(2);
+  const char** array = NewArray<const char*>(arg_count);
+  int pos = ScriptDataImpl::kHeaderSize + Read(3);
+  for (int i = 0; i < arg_count; i++) {
+    int count = 0;
+    array[i] = ParserRecorder::ReadString(ReadAddress(pos), &count);
+    pos += count + 1;
+  }
+  return Vector<const char*>(array, arg_count);
+}
+
+
+unsigned ScriptDataImpl::Read(int position) {
+  return store_[ScriptDataImpl::kHeaderSize + position];
+}
+
+
+unsigned* ScriptDataImpl::ReadAddress(int position) {
+  return &store_[ScriptDataImpl::kHeaderSize + position];
+}
+
+
+FunctionEntry ParserRecorder::LogFunction(int start) {
+  if (has_error_) return FunctionEntry();
+  FunctionEntry result(store()->AddBlock(0, FunctionEntry::kSize));
+  result.set_start_pos(start);
+  return result;
+}
+
+
+class AstBuildingParser : public Parser {
+ public:
+  AstBuildingParser(Handle<Script> script, bool allow_natives_syntax,
+                    v8::Extension* extension, ScriptDataImpl* pre_data)
+      : Parser(script, allow_natives_syntax, extension, false,
+               factory(), log(), pre_data) { }
+  virtual void ReportMessageAt(Scanner::Location loc, const char* message,
+                               Vector<const char*> args);
+  virtual VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
+                                 FunctionLiteral* fun, bool resolve, bool* ok);
+  AstBuildingParserFactory* factory() { return &factory_; }
+  ParserLog* log() { return &log_; }
+
+ private:
+  ParserLog log_;
+  AstBuildingParserFactory factory_;
+};
+
+
+class PreParser : public Parser {
+ public:
+  PreParser(Handle<Script> script, bool allow_natives_syntax,
+            v8::Extension* extension)
+      : Parser(script, allow_natives_syntax, extension, true,
+               factory(), recorder(), NULL)
+      , factory_(true) { }
+  virtual void ReportMessageAt(Scanner::Location loc, const char* message,
+                               Vector<const char*> args);
+  virtual VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
+                                 FunctionLiteral* fun, bool resolve, bool* ok);
+  ParserFactory* factory() { return &factory_; }
+  ParserRecorder* recorder() { return &recorder_; }
+
+ private:
+  ParserRecorder recorder_;
+  ParserFactory factory_;
+};
+
+
+Scope* AstBuildingParserFactory::NewScope(Scope* parent, Scope::Type type,
+                                          bool inside_with) {
+  Scope* result = new Scope(parent, type);
+  result->Initialize(inside_with);
+  return result;
+}
+
+
+Scope* ParserFactory::NewScope(Scope* parent, Scope::Type type,
+                               bool inside_with) {
+  ASSERT(parent != NULL);
+  parent->type_ = type;
+  return parent;
+}
+
+
+VariableProxy* PreParser::Declare(Handle<String> name, Variable::Mode mode,
+                                  FunctionLiteral* fun, bool resolve,
+                                  bool* ok) {
+  return NULL;
+}
+
+
+
+// ----------------------------------------------------------------------------
+// Target is a support class to facilitate manipulation of the
+// Parser's target_stack_ (the stack of potential 'break' and
+// 'continue' statement targets). Upon construction, a new target is
+// added; it is removed upon destruction.
+
+class Target BASE_EMBEDDED {
+ public:
+  Target(Parser* parser, Node* node) : parser_(parser) {
+    parser_->target_stack_->Add(node);
+  }
+
+  ~Target() {
+    parser_->target_stack_->RemoveLast();
+  }
+
+ private:
+  Parser* parser_;
+};
+
+
+class TargetScope BASE_EMBEDDED {
+ public:
+  explicit TargetScope(Parser* parser)
+      : parser_(parser), previous_(parser->target_stack_), stack_(0) {
+    parser_->target_stack_ = &stack_;
+  }
+
+  ~TargetScope() {
+    ASSERT(stack_.is_empty());
+    parser_->target_stack_ = previous_;
+  }
+
+ private:
+  Parser* parser_;
+  List<Node*>* previous_;
+  List<Node*> stack_;
+};
+
+
+// ----------------------------------------------------------------------------
+// LexicalScope is a support class to facilitate manipulation of the
+// Parser's scope stack. The constructor sets the parser's top scope
+// to the incoming scope, and the destructor resets it.
+
+class LexicalScope BASE_EMBEDDED {
+ public:
+  LexicalScope(Parser* parser, Scope* scope)
+    : parser_(parser),
+      prev_scope_(parser->top_scope_),
+      prev_level_(parser->with_nesting_level_) {
+    parser_->top_scope_ = scope;
+    parser_->with_nesting_level_ = 0;
+  }
+
+  ~LexicalScope() {
+    parser_->top_scope_ = prev_scope_;
+    parser_->with_nesting_level_ = prev_level_;
+  }
+
+ private:
+  Parser* parser_;
+  Scope* prev_scope_;
+  int prev_level_;
+};
+
+
+// ----------------------------------------------------------------------------
+// The CHECK_OK macro is a convenient macro to enforce error
+// handling for functions that may fail (by returning !*ok).
+//
+// CAUTION: This macro appends extra statements after a call,
+// thus it must never be used where only a single statement
+// is correct (e.g. an if statement branch w/o braces)!
+
+#define CHECK_OK  ok);   \
+  if (!*ok) return NULL; \
+  ((void)0
+#define DUMMY )  // to make indentation work
+#undef DUMMY
+
+#define CHECK_FAILED  /**/);   \
+  if (failed_) return NULL; \
+  ((void)0
+#define DUMMY )  // to make indentation work
+#undef DUMMY
+
+// ----------------------------------------------------------------------------
+// Implementation of Parser
+
+Parser::Parser(Handle<Script> script,
+               bool allow_natives_syntax,
+               v8::Extension* extension,
+               bool is_pre_parsing,
+               ParserFactory* factory,
+               ParserLog* log,
+               ScriptDataImpl* pre_data)
+    : script_(script),
+      scanner_(is_pre_parsing),
+      top_scope_(NULL),
+      with_nesting_level_(0),
+      temp_scope_(NULL),
+      target_stack_(NULL),
+      allow_natives_syntax_(allow_natives_syntax),
+      extension_(extension),
+      factory_(factory),
+      log_(log),
+      is_pre_parsing_(is_pre_parsing),
+      pre_data_(pre_data) {
+}
+
+
+bool Parser::PreParseProgram(unibrow::CharacterStream* stream) {
+  HistogramTimerScope timer(&Counters::pre_parse);
+  StackGuard guard;
+  AssertNoZoneAllocation assert_no_zone_allocation;
+  AssertNoAllocation assert_no_allocation;
+  NoHandleAllocation no_handle_allocation;
+  scanner_.Init(Handle<String>(), stream, 0);
+  ASSERT(target_stack_ == NULL);
+  mode_ = PARSE_EAGERLY;
+  DummyScope top_scope;
+  LexicalScope scope(this, &top_scope);
+  TemporaryScope temp_scope(this);
+  ZoneListWrapper<Statement> processor;
+  bool ok = true;
+  ParseSourceElements(&processor, Token::EOS, &ok);
+  return !scanner().stack_overflow();
+}
+
+
+FunctionLiteral* Parser::ParseProgram(Handle<String> source,
+                                      unibrow::CharacterStream* stream,
+                                      bool in_global_context) {
+  ZoneScope zone_scope(DONT_DELETE_ON_EXIT);
+
+  HistogramTimerScope timer(&Counters::parse);
+  Counters::total_parse_size.Increment(source->length());
+
+  // Initialize parser state.
+  source->TryFlattenIfNotFlat();
+  scanner_.Init(source, stream, 0);
+  ASSERT(target_stack_ == NULL);
+
+  // Compute the parsing mode.
+  mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY;
+  if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY;
+
+  Scope::Type type =
+    in_global_context
+      ? Scope::GLOBAL_SCOPE
+      : Scope::EVAL_SCOPE;
+  Handle<String> no_name = factory()->EmptySymbol();
+
+  FunctionLiteral* result = NULL;
+  { Scope* scope = factory()->NewScope(top_scope_, type, inside_with());
+    LexicalScope lexical_scope(this, scope);
+    TemporaryScope temp_scope(this);
+    ZoneListWrapper<Statement> body(16);
+    bool ok = true;
+    ParseSourceElements(&body, Token::EOS, &ok);
+    if (ok) {
+      result = NEW(FunctionLiteral(no_name, top_scope_,
+                                   body.elements(),
+                                   temp_scope.materialized_literal_count(),
+                                   temp_scope.contains_array_literal(),
+                                   temp_scope.expected_property_count(),
+                                   0, 0, source->length(), false));
+    } else if (scanner().stack_overflow()) {
+      Top::StackOverflow();
+    }
+  }
+
+  // Make sure the target stack is empty.
+  ASSERT(target_stack_ == NULL);
+
+  // If there was a syntax error we have to get rid of the AST
+  // and it is not safe to do so before the scope has been deleted.
+  if (result == NULL) zone_scope.DeleteOnExit();
+  return result;
+}
+
+
+FunctionLiteral* Parser::ParseLazy(Handle<String> source,
+                                   Handle<String> name,
+                                   int start_position,
+                                   bool is_expression) {
+  ZoneScope zone_scope(DONT_DELETE_ON_EXIT);
+  HistogramTimerScope timer(&Counters::parse_lazy);
+  source->TryFlattenIfNotFlat();
+  Counters::total_parse_size.Increment(source->length());
+  SafeStringInputBuffer buffer(source.location());
+
+  // Initialize parser state.
+  scanner_.Init(source, &buffer, start_position);
+  ASSERT(target_stack_ == NULL);
+  mode_ = PARSE_EAGERLY;
+
+  // Place holder for the result.
+  FunctionLiteral* result = NULL;
+
+  {
+    // Parse the function literal.
+    Handle<String> no_name = factory()->EmptySymbol();
+    Scope* scope =
+        factory()->NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
+    LexicalScope lexical_scope(this, scope);
+    TemporaryScope temp_scope(this);
+
+    FunctionLiteralType type = is_expression ? EXPRESSION : DECLARATION;
+    bool ok = true;
+    result = ParseFunctionLiteral(name, RelocInfo::kNoPosition, type, &ok);
+    // Make sure the results agree.
+    ASSERT(ok == (result != NULL));
+    // The only errors should be stack overflows.
+    ASSERT(ok || scanner_.stack_overflow());
+  }
+
+  // Make sure the target stack is empty.
+  ASSERT(target_stack_ == NULL);
+
+  // If there was a stack overflow we have to get rid of AST and it is
+  // not safe to do before scope has been deleted.
+  if (result == NULL) {
+    Top::StackOverflow();
+    zone_scope.DeleteOnExit();
+  }
+  return result;
+}
+
+
+void Parser::ReportMessage(const char* type, Vector<const char*> args) {
+  Scanner::Location source_location = scanner_.location();
+  ReportMessageAt(source_location, type, args);
+}
+
+
+void AstBuildingParser::ReportMessageAt(Scanner::Location source_location,
+                                        const char* type,
+                                        Vector<const char*> args) {
+  MessageLocation location(script_,
+                           source_location.beg_pos, source_location.end_pos);
+  Handle<JSArray> array = Factory::NewJSArray(args.length());
+  for (int i = 0; i < args.length(); i++) {
+    SetElement(array, i, Factory::NewStringFromUtf8(CStrVector(args[i])));
+  }
+  Handle<Object> result = Factory::NewSyntaxError(type, array);
+  Top::Throw(*result, &location);
+}
+
+
+void PreParser::ReportMessageAt(Scanner::Location source_location,
+                                const char* type,
+                                Vector<const char*> args) {
+  recorder()->LogMessage(source_location, type, args);
+}
+
+
+// An InitializationBlockFinder finds and marks sequences of statements of the
+// form x.y.z.a = ...; x.y.z.b = ...; etc.
+class InitializationBlockFinder {
+ public:
+  InitializationBlockFinder()
+    : first_in_block_(NULL), last_in_block_(NULL), block_size_(0) {}
+
+  ~InitializationBlockFinder() {
+    if (InBlock()) EndBlock();
+  }
+
+  void Update(Statement* stat) {
+    Assignment* assignment = AsAssignment(stat);
+    if (InBlock()) {
+      if (BlockContinues(assignment)) {
+        UpdateBlock(assignment);
+      } else {
+        EndBlock();
+      }
+    }
+    if (!InBlock() && (assignment != NULL) &&
+        (assignment->op() == Token::ASSIGN)) {
+      StartBlock(assignment);
+    }
+  }
+
+ private:
+  static Assignment* AsAssignment(Statement* stat) {
+    if (stat == NULL) return NULL;
+    ExpressionStatement* exp_stat = stat->AsExpressionStatement();
+    if (exp_stat == NULL) return NULL;
+    return exp_stat->expression()->AsAssignment();
+  }
+
+  // Returns true if the expressions appear to denote the same object.
+  // In the context of initialization blocks, we only consider expressions
+  // of the form 'x.y.z'.
+  static bool SameObject(Expression* e1, Expression* e2) {
+    VariableProxy* v1 = e1->AsVariableProxy();
+    VariableProxy* v2 = e2->AsVariableProxy();
+    if (v1 != NULL && v2 != NULL) {
+      return v1->name()->Equals(*v2->name());
+    }
+    Property* p1 = e1->AsProperty();
+    Property* p2 = e2->AsProperty();
+    if ((p1 == NULL) || (p2 == NULL)) return false;
+    Literal* key1 = p1->key()->AsLiteral();
+    Literal* key2 = p2->key()->AsLiteral();
+    if ((key1 == NULL) || (key2 == NULL)) return false;
+    if (!key1->handle()->IsString() || !key2->handle()->IsString()) {
+      return false;
+    }
+    String* name1 = String::cast(*key1->handle());
+    String* name2 = String::cast(*key2->handle());
+    if (!name1->Equals(name2)) return false;
+    return SameObject(p1->obj(), p2->obj());
+  }
+
+  // Returns true if the expressions appear to denote different properties
+  // of the same object.
+  static bool PropertyOfSameObject(Expression* e1, Expression* e2) {
+    Property* p1 = e1->AsProperty();
+    Property* p2 = e2->AsProperty();
+    if ((p1 == NULL) || (p2 == NULL)) return false;
+    return SameObject(p1->obj(), p2->obj());
+  }
+
+  bool BlockContinues(Assignment* assignment) {
+    if ((assignment == NULL) || (first_in_block_ == NULL)) return false;
+    if (assignment->op() != Token::ASSIGN) return false;
+    return PropertyOfSameObject(first_in_block_->target(),
+                                assignment->target());
+  }
+
+  void StartBlock(Assignment* assignment) {
+    first_in_block_ = assignment;
+    last_in_block_ = assignment;
+    block_size_ = 1;
+  }
+
+  void UpdateBlock(Assignment* assignment) {
+    last_in_block_ = assignment;
+    ++block_size_;
+  }
+
+  void EndBlock() {
+    if (block_size_ >= Parser::kMinInitializationBlock) {
+      first_in_block_->mark_block_start();
+      last_in_block_->mark_block_end();
+    }
+    last_in_block_ = first_in_block_ = NULL;
+    block_size_ = 0;
+  }
+
+  bool InBlock() { return first_in_block_ != NULL; }
+
+  Assignment* first_in_block_;
+  Assignment* last_in_block_;
+  int block_size_;
+
+  DISALLOW_COPY_AND_ASSIGN(InitializationBlockFinder);
+};
+
+
+void* Parser::ParseSourceElements(ZoneListWrapper<Statement>* processor,
+                                  int end_token,
+                                  bool* ok) {
+  // SourceElements ::
+  //   (Statement)* <end_token>
+
+  // Allocate a target stack to use for this set of source
+  // elements. This way, all scripts and functions get their own
+  // target stack thus avoiding illegal breaks and continues across
+  // functions.
+  TargetScope scope(this);
+
+  ASSERT(processor != NULL);
+  InitializationBlockFinder block_finder;
+  while (peek() != end_token) {
+    Statement* stat = ParseStatement(NULL, CHECK_OK);
+    if (stat == NULL || stat->IsEmpty()) continue;
+    // We find and mark the initialization blocks on top level code only.
+    // This is because the optimization prevents reuse of the map transitions,
+    // so it should be used only for code that will only be run once.
+    if (top_scope_->is_global_scope()) block_finder.Update(stat);
+    processor->Add(stat);
+  }
+  return 0;
+}
+
+
+Statement* Parser::ParseStatement(ZoneStringList* labels, 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
+  int statement_pos = scanner().peek_location().beg_pos;
+  Statement* stmt = NULL;
+  switch (peek()) {
+    case Token::LBRACE:
+      return ParseBlock(labels, ok);
+
+    case Token::CONST:  // fall through
+    case Token::VAR:
+      stmt = ParseVariableStatement(ok);
+      break;
+
+    case Token::SEMICOLON:
+      Next();
+      return factory()->EmptyStatement();
+
+    case Token::IF:
+      stmt = ParseIfStatement(labels, ok);
+      break;
+
+    case Token::DO:
+      stmt = ParseDoStatement(labels, ok);
+      break;
+
+    case Token::WHILE:
+      stmt = ParseWhileStatement(labels, ok);
+      break;
+
+    case Token::FOR:
+      stmt = ParseForStatement(labels, ok);
+      break;
+
+    case Token::CONTINUE:
+      stmt = ParseContinueStatement(ok);
+      break;
+
+    case Token::BREAK:
+      stmt = ParseBreakStatement(labels, ok);
+      break;
+
+    case Token::RETURN:
+      stmt = ParseReturnStatement(ok);
+      break;
+
+    case Token::WITH:
+      stmt = ParseWithStatement(labels, ok);
+      break;
+
+    case Token::SWITCH:
+      stmt = ParseSwitchStatement(labels, ok);
+      break;
+
+    case Token::THROW:
+      stmt = ParseThrowStatement(ok);
+      break;
+
+    case Token::TRY: {
+      // NOTE: It is somewhat complicated to have labels on
+      // try-statements. When breaking out of a try-finally statement,
+      // one must take great care not to treat it as a
+      // fall-through. It is much easier just to wrap the entire
+      // try-statement in a statement block and put the labels there
+      Block* result = NEW(Block(labels, 1, false));
+      Target target(this, result);
+      TryStatement* statement = ParseTryStatement(CHECK_OK);
+      if (statement) {
+        statement->set_statement_pos(statement_pos);
+      }
+      if (result) result->AddStatement(statement);
+      return result;
+    }
+
+    case Token::FUNCTION:
+      return ParseFunctionDeclaration(ok);
+
+    case Token::NATIVE:
+      return ParseNativeDeclaration(ok);
+
+    case Token::DEBUGGER:
+      stmt = ParseDebuggerStatement(ok);
+      break;
+
+    default:
+      stmt = ParseExpressionOrLabelledStatement(labels, ok);
+  }
+
+  // Store the source position of the statement
+  if (stmt != NULL) stmt->set_statement_pos(statement_pos);
+  return stmt;
+}
+
+
+VariableProxy* AstBuildingParser::Declare(Handle<String> name,
+                                          Variable::Mode mode,
+                                          FunctionLiteral* fun,
+                                          bool resolve,
+                                          bool* ok) {
+  Variable* var = NULL;
+  // If we are inside a function, a declaration of a variable
+  // is a truly local variable, and the scope of the variable
+  // is always the function scope.
+
+  // If a function scope exists, then we can statically declare this
+  // variable and also set its mode. In any case, a Declaration node
+  // will be added to the scope so that the declaration can be added
+  // to the corresponding activation frame at runtime if necessary.
+  // For instance declarations inside an eval scope need to be added
+  // to the calling function context.
+  if (top_scope_->is_function_scope()) {
+    // Declare the variable in the function scope.
+    var = top_scope_->LookupLocal(name);
+    if (var == NULL) {
+      // Declare the name.
+      var = top_scope_->Declare(name, mode);
+    } else {
+      // The name was declared before; check for conflicting
+      // re-declarations. If the previous declaration was a const or the
+      // current declaration is a const then we have a conflict. There is
+      // similar code in runtime.cc in the Declare functions.
+      if ((mode == Variable::CONST) || (var->mode() == Variable::CONST)) {
+        // We only have vars and consts in declarations.
+        ASSERT(var->mode() == Variable::VAR ||
+               var->mode() == Variable::CONST);
+        const char* type = (var->mode() == Variable::VAR) ? "var" : "const";
+        Handle<String> type_string =
+            Factory::NewStringFromUtf8(CStrVector(type), TENURED);
+        Expression* expression =
+            NewThrowTypeError(Factory::redeclaration_symbol(),
+                              type_string, name);
+        top_scope_->SetIllegalRedeclaration(expression);
+      }
+    }
+  }
+
+  // We add a declaration node for every declaration. The compiler
+  // will only generate code if necessary. In particular, declarations
+  // for inner local variables that do not represent functions won't
+  // result in any generated code.
+  //
+  // Note that we always add an unresolved proxy even if it's not
+  // used, simply because we don't know in this method (w/o extra
+  // parameters) if the proxy is needed or not. The proxy will be
+  // bound during variable resolution time unless it was pre-bound
+  // below.
+  //
+  // WARNING: This will lead to multiple declaration nodes for the
+  // same variable if it is declared several times. This is not a
+  // semantic issue as long as we keep the source order, but it may be
+  // a performance issue since it may lead to repeated
+  // Runtime::DeclareContextSlot() calls.
+  VariableProxy* proxy = top_scope_->NewUnresolved(name, inside_with());
+  top_scope_->AddDeclaration(NEW(Declaration(proxy, mode, fun)));
+
+  // For global const variables we bind the proxy to a variable.
+  if (mode == Variable::CONST && top_scope_->is_global_scope()) {
+    ASSERT(resolve);  // should be set by all callers
+    var = NEW(Variable(top_scope_, name, Variable::CONST, true, false));
+  }
+
+  // If requested and we have a local variable, bind the proxy to the variable
+  // at parse-time. This is used for functions (and consts) declared inside
+  // statements: the corresponding function (or const) variable must be in the
+  // function scope and not a statement-local scope, e.g. as provided with a
+  // 'with' statement:
+  //
+  //   with (obj) {
+  //     function f() {}
+  //   }
+  //
+  // which is translated into:
+  //
+  //   with (obj) {
+  //     // in this case this is not: 'var f; f = function () {};'
+  //     var f = function () {};
+  //   }
+  //
+  // Note that if 'f' is accessed from inside the 'with' statement, it
+  // will be allocated in the context (because we must be able to look
+  // it up dynamically) but it will also be accessed statically, i.e.,
+  // with a context slot index and a context chain length for this
+  // initialization code. Thus, inside the 'with' statement, we need
+  // both access to the static and the dynamic context chain; the
+  // runtime needs to provide both.
+  if (resolve && var != NULL) proxy->BindTo(var);
+
+  return proxy;
+}
+
+
+// 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* Parser::ParseNativeDeclaration(bool* ok) {
+  if (extension_ == NULL) {
+    ReportUnexpectedToken(Token::NATIVE);
+    *ok = false;
+    return NULL;
+  }
+
+  Expect(Token::NATIVE, CHECK_OK);
+  Expect(Token::FUNCTION, CHECK_OK);
+  Handle<String> name = ParseIdentifier(CHECK_OK);
+  Expect(Token::LPAREN, CHECK_OK);
+  bool done = (peek() == Token::RPAREN);
+  while (!done) {
+    ParseIdentifier(CHECK_OK);
+    done = (peek() == Token::RPAREN);
+    if (!done) Expect(Token::COMMA, CHECK_OK);
+  }
+  Expect(Token::RPAREN, CHECK_OK);
+  Expect(Token::SEMICOLON, CHECK_OK);
+
+  if (is_pre_parsing_) return NULL;
+
+  // Make sure that the function containing the native declaration
+  // isn't lazily compiled. The extension structures are only
+  // accessible while parsing the first time not when reparsing
+  // because of lazy compilation.
+  top_scope_->ForceEagerCompilation();
+
+  // Compute the function template for the native function.
+  v8::Handle<v8::FunctionTemplate> fun_template =
+      extension_->GetNativeFunction(v8::Utils::ToLocal(name));
+  ASSERT(!fun_template.IsEmpty());
+
+  // Instantiate the function and create a boilerplate function from it.
+  Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction());
+  const int literals = fun->NumberOfLiterals();
+  Handle<Code> code = Handle<Code>(fun->shared()->code());
+  Handle<JSFunction> boilerplate =
+      Factory::NewFunctionBoilerplate(name, literals, false, code);
+
+  // Copy the function data to the boilerplate. Used by
+  // builtins.cc:HandleApiCall to perform argument type checks and to
+  // find the right native code to call.
+  boilerplate->shared()->set_function_data(fun->shared()->function_data());
+  int parameters = fun->shared()->formal_parameter_count();
+  boilerplate->shared()->set_formal_parameter_count(parameters);
+
+  // TODO(1240846): It's weird that native function declarations are
+  // introduced dynamically when we meet their declarations, whereas
+  // other functions are setup when entering the surrounding scope.
+  FunctionBoilerplateLiteral* lit =
+      NEW(FunctionBoilerplateLiteral(boilerplate));
+  VariableProxy* var = Declare(name, Variable::VAR, NULL, true, CHECK_OK);
+  return NEW(ExpressionStatement(
+      new Assignment(Token::INIT_VAR, var, lit, RelocInfo::kNoPosition)));
+}
+
+
+Statement* Parser::ParseFunctionDeclaration(bool* ok) {
+  // Parse a function literal. We may or may not have a function name.
+  // If we have a name we use it as the variable name for the function
+  // (a function declaration) and not as the function name of a function
+  // expression.
+
+  Expect(Token::FUNCTION, CHECK_OK);
+  int function_token_position = scanner().location().beg_pos;
+
+  Handle<String> name;
+  if (peek() == Token::IDENTIFIER) name = ParseIdentifier(CHECK_OK);
+  FunctionLiteral* fun = ParseFunctionLiteral(name, function_token_position,
+                                              DECLARATION, CHECK_OK);
+
+  if (name.is_null()) {
+    // We don't have a name - it is always an anonymous function
+    // expression.
+    return NEW(ExpressionStatement(fun));
+  } else {
+    // We have a name so even if we're not at the top-level of the
+    // global or a function scope, we treat is as such and introduce
+    // the function with it's initial value upon entering the
+    // corresponding scope.
+    Declare(name, Variable::VAR, fun, true, CHECK_OK);
+    return factory()->EmptyStatement();
+  }
+}
+
+
+Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
+  // Block ::
+  //   '{' Statement* '}'
+
+  // Note that a Block does not introduce a new execution scope!
+  // (ECMA-262, 3rd, 12.2)
+  //
+  // Construct block expecting 16 statements.
+  Block* result = NEW(Block(labels, 16, false));
+  Target target(this, result);
+  Expect(Token::LBRACE, CHECK_OK);
+  while (peek() != Token::RBRACE) {
+    Statement* stat = ParseStatement(NULL, CHECK_OK);
+    if (stat && !stat->IsEmpty()) result->AddStatement(stat);
+  }
+  Expect(Token::RBRACE, CHECK_OK);
+  return result;
+}
+
+
+Block* Parser::ParseVariableStatement(bool* ok) {
+  // VariableStatement ::
+  //   VariableDeclarations ';'
+
+  Expression* dummy;  // to satisfy the ParseVariableDeclarations() signature
+  Block* result = ParseVariableDeclarations(true, &dummy, 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 used for the parsing
+// of 'for-in' loops.
+Block* Parser::ParseVariableDeclarations(bool accept_IN,
+                                         Expression** var,
+                                         bool* ok) {
+  // VariableDeclarations ::
+  //   ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
+
+  Variable::Mode mode = Variable::VAR;
+  bool is_const = false;
+  if (peek() == Token::VAR) {
+    Consume(Token::VAR);
+  } else if (peek() == Token::CONST) {
+    Consume(Token::CONST);
+    mode = Variable::CONST;
+    is_const = true;
+  } else {
+    UNREACHABLE();  // by current callers
+  }
+
+  // The scope of a variable/const declared anywhere inside a function
+  // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
+  // transform a source-level variable/const declaration into a (Function)
+  // Scope declaration, and rewrite the source-level initialization into an
+  // assignment statement. We use a block to collect multiple assignments.
+  //
+  // We mark the block as initializer block because we don't want the
+  // rewriter to add a '.result' assignment to such a block (to get compliant
+  // behavior for code such as print(eval('var x = 7')), and for cosmetic
+  // reasons when pretty-printing. Also, unless an assignment (initialization)
+  // is inside an initializer block, it is ignored.
+  //
+  // Create new block with one expected declaration.
+  Block* block = NEW(Block(NULL, 1, true));
+  VariableProxy* last_var = NULL;  // the last variable declared
+  int nvars = 0;  // the number of variables declared
+  do {
+    // Parse variable name.
+    if (nvars > 0) Consume(Token::COMMA);
+    Handle<String> name = ParseIdentifier(CHECK_OK);
+
+    // Declare variable.
+    // Note that we *always* must treat the initial value via a separate init
+    // assignment for variables and constants because the value must be assigned
+    // when the variable is encountered in the source. But the variable/constant
+    // is declared (and set to 'undefined') upon entering the function within
+    // which the variable or constant is declared. Only function variables have
+    // an initial value in the declaration (because they are initialized upon
+    // entering the function).
+    //
+    // If we have a const declaration, in an inner scope, the proxy is always
+    // bound to the declared variable (independent of possibly surrounding with
+    // statements).
+    last_var = Declare(name, mode, NULL,
+                       is_const /* always bound for CONST! */,
+                       CHECK_OK);
+    nvars++;
+
+    // Parse initialization expression if present and/or needed. A
+    // declaration of the form:
+    //
+    //    var v = x;
+    //
+    // is syntactic sugar for:
+    //
+    //    var v; v = x;
+    //
+    // In particular, we need to re-lookup 'v' as it may be a
+    // different 'v' than the 'v' in the declaration (if we are inside
+    // a 'with' statement that makes a object property with name 'v'
+    // visible).
+    //
+    // However, note that const declarations are different! A const
+    // declaration of the form:
+    //
+    //   const c = x;
+    //
+    // is *not* syntactic sugar for:
+    //
+    //   const c; c = x;
+    //
+    // The "variable" c initialized to x is the same as the declared
+    // one - there is no re-lookup (see the last parameter of the
+    // Declare() call above).
+
+    Expression* value = NULL;
+    int position = -1;
+    if (peek() == Token::ASSIGN) {
+      Expect(Token::ASSIGN, CHECK_OK);
+      position = scanner().location().beg_pos;
+      value = ParseAssignmentExpression(accept_IN, CHECK_OK);
+    }
+
+    // Make sure that 'const c' actually initializes 'c' to undefined
+    // even though it seems like a stupid thing to do.
+    if (value == NULL && is_const) {
+      value = GetLiteralUndefined();
+    }
+
+    // Global variable declarations must be compiled in a specific
+    // way. When the script containing the global variable declaration
+    // is entered, the global variable must be declared, so that if it
+    // doesn't exist (not even in a prototype of the global object) it
+    // gets created with an initial undefined value. This is handled
+    // by the declarations part of the function representing the
+    // top-level global code; see Runtime::DeclareGlobalVariable. If
+    // it already exists (in the object or in a prototype), it is
+    // *not* touched until the variable declaration statement is
+    // executed.
+    //
+    // Executing the variable declaration statement will always
+    // guarantee to give the global object a "local" variable; a
+    // variable defined in the global object and not in any
+    // prototype. This way, global variable declarations can shadow
+    // properties in the prototype chain, but only after the variable
+    // declaration statement has been executed. This is important in
+    // browsers where the global object (window) has lots of
+    // properties defined in prototype objects.
+
+    if (!is_pre_parsing_ && top_scope_->is_global_scope()) {
+      // Compute the arguments for the runtime call.
+      ZoneList<Expression*>* arguments = new ZoneList<Expression*>(2);
+      // Be careful not to assign a value to the global variable if
+      // we're in a with. The initialization value should not
+      // necessarily be stored in the global object in that case,
+      // which is why we need to generate a separate assignment node.
+      arguments->Add(NEW(Literal(name)));  // we have at least 1 parameter
+      if (is_const || (value != NULL && !inside_with())) {
+        arguments->Add(value);
+        value = NULL;  // zap the value to avoid the unnecessary assignment
+      }
+      // Construct the call to Runtime::DeclareGlobal{Variable,Const}Locally
+      // and add it to the initialization statement block. Note that
+      // this function does different things depending on if we have
+      // 1 or 2 parameters.
+      CallRuntime* initialize;
+      if (is_const) {
+        initialize =
+          NEW(CallRuntime(
+            Factory::InitializeConstGlobal_symbol(),
+            Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
+            arguments));
+      } else {
+        initialize =
+          NEW(CallRuntime(
+            Factory::InitializeVarGlobal_symbol(),
+            Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
+            arguments));
+      }
+      block->AddStatement(NEW(ExpressionStatement(initialize)));
+    }
+
+    // Add an assignment node to the initialization statement block if
+    // we still have a pending initialization value. We must distinguish
+    // between variables and constants: Variable initializations are simply
+    // assignments (with all the consequences if they are inside a 'with'
+    // statement - they may change a 'with' object property). Constant
+    // initializations always assign to the declared constant which is
+    // always at the function scope level. This is only relevant for
+    // dynamically looked-up variables and constants (the start context
+    // for constant lookups is always the function context, while it is
+    // the top context for variables). Sigh...
+    if (value != NULL) {
+      Token::Value op = (is_const ? Token::INIT_CONST : Token::INIT_VAR);
+      Assignment* assignment = NEW(Assignment(op, last_var, value, position));
+      if (block) block->AddStatement(NEW(ExpressionStatement(assignment)));
+    }
+  } while (peek() == Token::COMMA);
+
+  if (!is_const && nvars == 1) {
+    // We have a single, non-const variable.
+    if (is_pre_parsing_) {
+      // If we're preparsing then we need to set the var to something
+      // in order for for-in loops to parse correctly.
+      *var = ValidLeftHandSideSentinel::instance();
+    } else {
+      ASSERT(last_var != NULL);
+      *var = last_var;
+    }
+  }
+
+  return block;
+}
+
+
+static bool ContainsLabel(ZoneStringList* labels, Handle<String> label) {
+  ASSERT(!label.is_null());
+  if (labels != NULL)
+    for (int i = labels->length(); i-- > 0; )
+      if (labels->at(i).is_identical_to(label))
+        return true;
+
+  return false;
+}
+
+
+Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
+                                                      bool* ok) {
+  // ExpressionStatement | LabelledStatement ::
+  //   Expression ';'
+  //   Identifier ':' Statement
+
+  Expression* expr = ParseExpression(true, CHECK_OK);
+  if (peek() == Token::COLON && expr &&
+      expr->AsVariableProxy() != NULL &&
+      !expr->AsVariableProxy()->is_this()) {
+    VariableProxy* var = expr->AsVariableProxy();
+    Handle<String> label = var->name();
+    // TODO(1240780): We don't check for redeclaration of labels
+    // during preparsing since keeping track of the set of active
+    // labels requires nontrivial changes to the way scopes are
+    // structured.  However, these are probably changes we want to
+    // make later anyway so we should go back and fix this then.
+    if (!is_pre_parsing_) {
+      if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
+        SmartPointer<char> c_string = label->ToCString(DISALLOW_NULLS);
+        const char* elms[2] = { "Label", *c_string };
+        Vector<const char*> args(elms, 2);
+        ReportMessage("redeclaration", args);
+        *ok = false;
+        return NULL;
+      }
+      if (labels == NULL) labels = new ZoneStringList(4);
+      labels->Add(label);
+      // Remove the "ghost" variable that turned out to be a label
+      // from the top scope. This way, we don't try to resolve it
+      // during the scope processing.
+      top_scope_->RemoveUnresolved(var);
+    }
+    Expect(Token::COLON, CHECK_OK);
+    return ParseStatement(labels, ok);
+  }
+
+  // Parsed expression statement.
+  ExpectSemicolon(CHECK_OK);
+  return NEW(ExpressionStatement(expr));
+}
+
+
+IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
+  // IfStatement ::
+  //   'if' '(' Expression ')' Statement ('else' Statement)?
+
+  Expect(Token::IF, CHECK_OK);
+  Expect(Token::LPAREN, CHECK_OK);
+  Expression* condition = ParseExpression(true, CHECK_OK);
+  Expect(Token::RPAREN, CHECK_OK);
+  Statement* then_statement = ParseStatement(labels, CHECK_OK);
+  Statement* else_statement = NULL;
+  if (peek() == Token::ELSE) {
+    Next();
+    else_statement = ParseStatement(labels, CHECK_OK);
+  } else if (!is_pre_parsing_) {
+    else_statement = factory()->EmptyStatement();
+  }
+  return NEW(IfStatement(condition, then_statement, else_statement));
+}
+
+
+Statement* Parser::ParseContinueStatement(bool* ok) {
+  // ContinueStatement ::
+  //   'continue' Identifier? ';'
+
+  Expect(Token::CONTINUE, CHECK_OK);
+  Handle<String> label(static_cast<String**>(NULL));
+  Token::Value tok = peek();
+  if (!scanner_.has_line_terminator_before_next() &&
+      tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
+    label = ParseIdentifier(CHECK_OK);
+  }
+  IterationStatement* target = NULL;
+  if (!is_pre_parsing_) {
+    target = LookupContinueTarget(label, CHECK_OK);
+    if (target == NULL) {
+      // Illegal continue statement.  To be consistent with KJS we delay
+      // reporting of the syntax error until runtime.
+      Handle<String> error_type = Factory::illegal_continue_symbol();
+      if (!label.is_null()) error_type = Factory::unknown_label_symbol();
+      Expression* throw_error = NewThrowSyntaxError(error_type, label);
+      return NEW(ExpressionStatement(throw_error));
+    }
+  }
+  ExpectSemicolon(CHECK_OK);
+  return NEW(ContinueStatement(target));
+}
+
+
+Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
+  // BreakStatement ::
+  //   'break' Identifier? ';'
+
+  Expect(Token::BREAK, CHECK_OK);
+  Handle<String> label;
+  Token::Value tok = peek();
+  if (!scanner_.has_line_terminator_before_next() &&
+      tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
+    label = ParseIdentifier(CHECK_OK);
+  }
+  // Parse labeled break statements that target themselves into
+  // empty statements, e.g. 'l1: l2: l3: break l2;'
+  if (!label.is_null() && ContainsLabel(labels, label)) {
+    return factory()->EmptyStatement();
+  }
+  BreakableStatement* target = NULL;
+  if (!is_pre_parsing_) {
+    target = LookupBreakTarget(label, CHECK_OK);
+    if (target == NULL) {
+      // Illegal break statement.  To be consistent with KJS we delay
+      // reporting of the syntax error until runtime.
+      Handle<String> error_type = Factory::illegal_break_symbol();
+      if (!label.is_null()) error_type = Factory::unknown_label_symbol();
+      Expression* throw_error = NewThrowSyntaxError(error_type, label);
+      return NEW(ExpressionStatement(throw_error));
+    }
+  }
+  ExpectSemicolon(CHECK_OK);
+  return NEW(BreakStatement(target));
+}
+
+
+Statement* Parser::ParseReturnStatement(bool* ok) {
+  // ReturnStatement ::
+  //   'return' 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(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.
+  //
+  // To be consistent with KJS we report the syntax error at runtime.
+  if (!is_pre_parsing_ && !top_scope_->is_function_scope()) {
+    Handle<String> type = Factory::illegal_return_symbol();
+    Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
+    return NEW(ExpressionStatement(throw_error));
+  }
+
+  Token::Value tok = peek();
+  if (scanner_.has_line_terminator_before_next() ||
+      tok == Token::SEMICOLON ||
+      tok == Token::RBRACE ||
+      tok == Token::EOS) {
+    ExpectSemicolon(CHECK_OK);
+    return NEW(ReturnStatement(GetLiteralUndefined()));
+  }
+
+  Expression* expr = ParseExpression(true, CHECK_OK);
+  ExpectSemicolon(CHECK_OK);
+  return NEW(ReturnStatement(expr));
+}
+
+
+Block* Parser::WithHelper(Expression* obj,
+                          ZoneStringList* labels,
+                          bool is_catch_block,
+                          bool* ok) {
+  // Parse the statement and collect escaping labels.
+  ZoneList<BreakTarget*>* target_list = NEW(ZoneList<BreakTarget*>(0));
+  TargetCollector collector(target_list);
+  Statement* stat;
+  { Target target(this, &collector);
+    with_nesting_level_++;
+    top_scope_->RecordWithStatement();
+    stat = ParseStatement(labels, CHECK_OK);
+    with_nesting_level_--;
+  }
+  // Create resulting block with two statements.
+  // 1: Evaluate the with expression.
+  // 2: The try-finally block evaluating the body.
+  Block* result = NEW(Block(NULL, 2, false));
+
+  if (result != NULL) {
+    result->AddStatement(NEW(WithEnterStatement(obj, is_catch_block)));
+
+    // Create body block.
+    Block* body = NEW(Block(NULL, 1, false));
+    body->AddStatement(stat);
+
+    // Create exit block.
+    Block* exit = NEW(Block(NULL, 1, false));
+    exit->AddStatement(NEW(WithExitStatement()));
+
+    // Return a try-finally statement.
+    TryFinally* wrapper = NEW(TryFinally(body, exit));
+    wrapper->set_escaping_targets(collector.targets());
+    result->AddStatement(wrapper);
+  }
+  return result;
+}
+
+
+Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
+  // WithStatement ::
+  //   'with' '(' Expression ')' Statement
+
+  // We do not allow the use of 'with' statements in the internal JS
+  // code. If 'with' statements were allowed, the simplified setup of
+  // the runtime context chain would allow access to properties in the
+  // global object from within a 'with' statement.
+  ASSERT(extension_ != NULL || !Bootstrapper::IsActive());
+
+  Expect(Token::WITH, CHECK_OK);
+  Expect(Token::LPAREN, CHECK_OK);
+  Expression* expr = ParseExpression(true, CHECK_OK);
+  Expect(Token::RPAREN, CHECK_OK);
+
+  return WithHelper(expr, labels, false, CHECK_OK);
+}
+
+
+CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
+  // CaseClause ::
+  //   'case' Expression ':' Statement*
+  //   'default' ':' Statement*
+
+  Expression* label = NULL;  // NULL expression indicates default case
+  if (peek() == Token::CASE) {
+    Expect(Token::CASE, CHECK_OK);
+    label = ParseExpression(true, CHECK_OK);
+  } else {
+    Expect(Token::DEFAULT, CHECK_OK);
+    if (*default_seen_ptr) {
+      ReportMessage("multiple_defaults_in_switch",
+                    Vector<const char*>::empty());
+      *ok = false;
+      return NULL;
+    }
+    *default_seen_ptr = true;
+  }
+  Expect(Token::COLON, CHECK_OK);
+
+  ZoneListWrapper<Statement> statements = factory()->NewList<Statement>(5);
+  while (peek() != Token::CASE &&
+         peek() != Token::DEFAULT &&
+         peek() != Token::RBRACE) {
+    Statement* stat = ParseStatement(NULL, CHECK_OK);
+    statements.Add(stat);
+  }
+
+  return NEW(CaseClause(label, statements.elements()));
+}
+
+
+SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
+                                              bool* ok) {
+  // SwitchStatement ::
+  //   'switch' '(' Expression ')' '{' CaseClause* '}'
+
+  SwitchStatement* statement = NEW(SwitchStatement(labels));
+  Target target(this, statement);
+
+  Expect(Token::SWITCH, CHECK_OK);
+  Expect(Token::LPAREN, CHECK_OK);
+  Expression* tag = ParseExpression(true, CHECK_OK);
+  Expect(Token::RPAREN, CHECK_OK);
+
+  bool default_seen = false;
+  ZoneListWrapper<CaseClause> cases = factory()->NewList<CaseClause>(4);
+  Expect(Token::LBRACE, CHECK_OK);
+  while (peek() != Token::RBRACE) {
+    CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
+    cases.Add(clause);
+  }
+  Expect(Token::RBRACE, CHECK_OK);
+
+  if (statement) statement->Initialize(tag, cases.elements());
+  return statement;
+}
+
+
+Statement* Parser::ParseThrowStatement(bool* ok) {
+  // ThrowStatement ::
+  //   'throw' Expression ';'
+
+  Expect(Token::THROW, CHECK_OK);
+  int pos = scanner().location().beg_pos;
+  if (scanner_.has_line_terminator_before_next()) {
+    ReportMessage("newline_after_throw", Vector<const char*>::empty());
+    *ok = false;
+    return NULL;
+  }
+  Expression* exception = ParseExpression(true, CHECK_OK);
+  ExpectSemicolon(CHECK_OK);
+
+  return NEW(ExpressionStatement(new Throw(exception, pos)));
+}
+
+
+TryStatement* Parser::ParseTryStatement(bool* ok) {
+  // TryStatement ::
+  //   'try' Block Catch
+  //   'try' Block Finally
+  //   'try' Block Catch Finally
+  //
+  // Catch ::
+  //   'catch' '(' Identifier ')' Block
+  //
+  // Finally ::
+  //   'finally' Block
+
+  Expect(Token::TRY, CHECK_OK);
+
+  ZoneList<BreakTarget*>* target_list = NEW(ZoneList<BreakTarget*>(0));
+  TargetCollector collector(target_list);
+  Block* try_block;
+
+  { Target target(this, &collector);
+    try_block = ParseBlock(NULL, CHECK_OK);
+  }
+
+  Block* catch_block = NULL;
+  VariableProxy* catch_var = NULL;
+  Block* finally_block = NULL;
+
+  Token::Value tok = peek();
+  if (tok != Token::CATCH && tok != Token::FINALLY) {
+    ReportMessage("no_catch_or_finally", Vector<const char*>::empty());
+    *ok = false;
+    return NULL;
+  }
+
+  // If we can break out from the catch block and there is a finally block,
+  // then we will need to collect jump targets from the catch block. Since
+  // we don't know yet if there will be a finally block, we always collect
+  // the jump targets.
+  ZoneList<BreakTarget*>* catch_target_list = NEW(ZoneList<BreakTarget*>(0));
+  TargetCollector catch_collector(catch_target_list);
+  bool has_catch = false;
+  if (tok == Token::CATCH) {
+    has_catch = true;
+    Consume(Token::CATCH);
+
+    Expect(Token::LPAREN, CHECK_OK);
+    Handle<String> name = ParseIdentifier(CHECK_OK);
+    Expect(Token::RPAREN, CHECK_OK);
+
+    if (peek() == Token::LBRACE) {
+      // Allocate a temporary for holding the finally state while
+      // executing the finally block.
+      catch_var = top_scope_->NewTemporary(Factory::catch_var_symbol());
+      Literal* name_literal = NEW(Literal(name));
+      Expression* obj = NEW(CatchExtensionObject(name_literal, catch_var));
+      { Target target(this, &catch_collector);
+        catch_block = WithHelper(obj, NULL, true, CHECK_OK);
+      }
+    } else {
+      Expect(Token::LBRACE, CHECK_OK);
+    }
+
+    tok = peek();
+  }
+
+  if (tok == Token::FINALLY || !has_catch) {
+    Consume(Token::FINALLY);
+    // Declare a variable for holding the finally state while
+    // executing the finally block.
+    finally_block = ParseBlock(NULL, CHECK_OK);
+  }
+
+  // Simplify the AST nodes by converting:
+  //   'try { } catch { } finally { }'
+  // to:
+  //   'try { try { } catch { } } finally { }'
+
+  if (!is_pre_parsing_ && catch_block != NULL && finally_block != NULL) {
+    TryCatch* statement = NEW(TryCatch(try_block, catch_var, catch_block));
+    statement->set_escaping_targets(collector.targets());
+    try_block = NEW(Block(NULL, 1, false));
+    try_block->AddStatement(statement);
+    catch_block = NULL;
+  }
+
+  TryStatement* result = NULL;
+  if (!is_pre_parsing_) {
+    if (catch_block != NULL) {
+      ASSERT(finally_block == NULL);
+      result = NEW(TryCatch(try_block, catch_var, catch_block));
+      result->set_escaping_targets(collector.targets());
+    } else {
+      ASSERT(finally_block != NULL);
+      result = NEW(TryFinally(try_block, finally_block));
+      // Add the jump targets of the try block and the catch block.
+      for (int i = 0; i < collector.targets()->length(); i++) {
+        catch_collector.targets()->Add(collector.targets()->at(i));
+      }
+      result->set_escaping_targets(catch_collector.targets());
+    }
+  }
+
+  return result;
+}
+
+
+LoopStatement* Parser::ParseDoStatement(ZoneStringList* labels, bool* ok) {
+  // DoStatement ::
+  //   'do' Statement 'while' '(' Expression ')' ';'
+
+  LoopStatement* loop = NEW(LoopStatement(labels, LoopStatement::DO_LOOP));
+  Target target(this, loop);
+
+  Expect(Token::DO, CHECK_OK);
+  Statement* body = ParseStatement(NULL, CHECK_OK);
+  Expect(Token::WHILE, CHECK_OK);
+  Expect(Token::LPAREN, CHECK_OK);
+  Expression* cond = ParseExpression(true, CHECK_OK);
+  Expect(Token::RPAREN, CHECK_OK);
+
+  // Allow do-statements to be terminated with and without
+  // semi-colons. This allows code such as 'do;while(0)return' to
+  // parse, which would not be the case if we had used the
+  // ExpectSemicolon() functionality here.
+  if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
+
+  if (loop) loop->Initialize(NULL, cond, NULL, body);
+  return loop;
+}
+
+
+LoopStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
+  // WhileStatement ::
+  //   'while' '(' Expression ')' Statement
+
+  LoopStatement* loop = NEW(LoopStatement(labels, LoopStatement::WHILE_LOOP));
+  Target target(this, loop);
+
+  Expect(Token::WHILE, CHECK_OK);
+  Expect(Token::LPAREN, CHECK_OK);
+  Expression* cond = ParseExpression(true, CHECK_OK);
+  Expect(Token::RPAREN, CHECK_OK);
+  Statement* body = ParseStatement(NULL, CHECK_OK);
+
+  if (loop) loop->Initialize(NULL, cond, NULL, body);
+  return loop;
+}
+
+
+Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
+  // ForStatement ::
+  //   'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
+
+  Statement* init = NULL;
+
+  Expect(Token::FOR, CHECK_OK);
+  Expect(Token::LPAREN, CHECK_OK);
+  if (peek() != Token::SEMICOLON) {
+    if (peek() == Token::VAR || peek() == Token::CONST) {
+      Expression* each = NULL;
+      Block* variable_statement =
+          ParseVariableDeclarations(false, &each, CHECK_OK);
+      if (peek() == Token::IN && each != NULL) {
+        ForInStatement* loop = NEW(ForInStatement(labels));
+        Target target(this, loop);
+
+        Expect(Token::IN, CHECK_OK);
+        Expression* enumerable = ParseExpression(true, CHECK_OK);
+        Expect(Token::RPAREN, CHECK_OK);
+
+        Statement* body = ParseStatement(NULL, CHECK_OK);
+        if (is_pre_parsing_) {
+          return NULL;
+        } else {
+          loop->Initialize(each, enumerable, body);
+          Block* result = NEW(Block(NULL, 2, false));
+          result->AddStatement(variable_statement);
+          result->AddStatement(loop);
+          // Parsed for-in loop w/ variable/const declaration.
+          return result;
+        }
+
+      } else {
+        init = variable_statement;
+      }
+
+    } else {
+      Expression* expression = ParseExpression(false, CHECK_OK);
+      if (peek() == Token::IN) {
+        // Report syntax error if the expression is an invalid
+        // left-hand side expression.
+        if (expression == NULL || !expression->IsValidLeftHandSide()) {
+          if (expression != NULL && expression->AsCall() != NULL) {
+            // According to ECMA-262 host function calls are permitted to
+            // return references.  This cannot happen in our system so we
+            // will always get an error.  We could report this as a syntax
+            // error here but for compatibility with KJS and SpiderMonkey we
+            // choose to report the error at runtime.
+            Handle<String> type = Factory::invalid_lhs_in_for_in_symbol();
+            expression = NewThrowReferenceError(type);
+          } else {
+            // Invalid left hand side expressions that are not function
+            // calls are reported as syntax errors at compile time.
+            ReportMessage("invalid_lhs_in_for_in",
+                          Vector<const char*>::empty());
+            *ok = false;
+            return NULL;
+          }
+        }
+        ForInStatement* loop = NEW(ForInStatement(labels));
+        Target target(this, loop);
+
+        Expect(Token::IN, CHECK_OK);
+        Expression* enumerable = ParseExpression(true, CHECK_OK);
+        Expect(Token::RPAREN, CHECK_OK);
+
+        Statement* body = ParseStatement(NULL, CHECK_OK);
+        if (loop) loop->Initialize(expression, enumerable, body);
+
+        // Parsed for-in loop.
+        return loop;
+
+      } else {
+        init = NEW(ExpressionStatement(expression));
+      }
+    }
+  }
+
+  // Standard 'for' loop
+  LoopStatement* loop = NEW(LoopStatement(labels, LoopStatement::FOR_LOOP));
+  Target target(this, loop);
+
+  // Parsed initializer at this point.
+  Expect(Token::SEMICOLON, CHECK_OK);
+
+  Expression* cond = NULL;
+  if (peek() != Token::SEMICOLON) {
+    cond = ParseExpression(true, CHECK_OK);
+  }
+  Expect(Token::SEMICOLON, CHECK_OK);
+
+  Statement* next = NULL;
+  if (peek() != Token::RPAREN) {
+    Expression* exp = ParseExpression(true, CHECK_OK);
+    next = NEW(ExpressionStatement(exp));
+  }
+  Expect(Token::RPAREN, CHECK_OK);
+
+  Statement* body = ParseStatement(NULL, CHECK_OK);
+
+  if (loop) loop->Initialize(init, cond, next, body);
+  return loop;
+}
+
+
+// Precedence = 1
+Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
+  // Expression ::
+  //   AssignmentExpression
+  //   Expression ',' AssignmentExpression
+
+  Expression* result = ParseAssignmentExpression(accept_IN, CHECK_OK);
+  while (peek() == Token::COMMA) {
+    Expect(Token::COMMA, CHECK_OK);
+    Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
+    result = NEW(BinaryOperation(Token::COMMA, result, right));
+  }
+  return result;
+}
+
+
+// Precedence = 2
+Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
+  // AssignmentExpression ::
+  //   ConditionalExpression
+  //   LeftHandSideExpression AssignmentOperator AssignmentExpression
+
+  Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK);
+
+  if (!Token::IsAssignmentOp(peek())) {
+    // Parsed conditional expression only (no assignment).
+    return expression;
+  }
+
+  if (expression == NULL || !expression->IsValidLeftHandSide()) {
+    if (expression != NULL && expression->AsCall() != NULL) {
+      // According to ECMA-262 host function calls are permitted to
+      // return references.  This cannot happen in our system so we
+      // will always get an error.  We could report this as a syntax
+      // error here but for compatibility with KJS and SpiderMonkey we
+      // choose to report the error at runtime.
+      Handle<String> type = Factory::invalid_lhs_in_assignment_symbol();
+      expression = NewThrowReferenceError(type);
+    } else {
+      // Invalid left hand side expressions that are not function
+      // calls are reported as syntax errors at compile time.
+      //
+      // NOTE: KJS sometimes delay the error reporting to runtime. If
+      // we want to be completely compatible we should do the same.
+      // For example: "(x++) = 42" gives a reference error at runtime
+      // with KJS whereas we report a syntax error at compile time.
+      ReportMessage("invalid_lhs_in_assignment", Vector<const char*>::empty());
+      *ok = false;
+      return NULL;
+    }
+  }
+
+
+  Token::Value op = Next();  // Get assignment operator.
+  int pos = scanner().location().beg_pos;
+  Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
+
+  // TODO(1231235): We try to estimate the set of properties set by
+  // constructors. We define a new property whenever there is an
+  // assignment to a property of 'this'. We should probably only add
+  // properties if we haven't seen them before. Otherwise we'll
+  // probably overestimate the number of properties.
+  Property* property = expression ? expression->AsProperty() : NULL;
+  if (op == Token::ASSIGN &&
+      property != NULL &&
+      property->obj()->AsVariableProxy() != NULL &&
+      property->obj()->AsVariableProxy()->is_this()) {
+    temp_scope_->AddProperty();
+  }
+
+  return NEW(Assignment(op, expression, right, pos));
+}
+
+
+// Precedence = 3
+Expression* Parser::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() != Token::CONDITIONAL) return expression;
+  Consume(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.
+  Expression* left = ParseAssignmentExpression(true, CHECK_OK);
+  Expect(Token::COLON, CHECK_OK);
+  Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
+  return NEW(Conditional(expression, left, right));
+}
+
+
+static int Precedence(Token::Value tok, bool accept_IN) {
+  if (tok == Token::IN && !accept_IN)
+    return 0;  // 0 precedence will terminate binary expression parsing
+
+  return Token::Precedence(tok);
+}
+
+
+// Precedence >= 4
+Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
+  ASSERT(prec >= 4);
+  Expression* x = ParseUnaryExpression(CHECK_OK);
+  for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
+    // prec1 >= 4
+    while (Precedence(peek(), accept_IN) == prec1) {
+      Token::Value op = Next();
+      Expression* y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
+
+      // Compute some expressions involving only number literals.
+      if (x && x->AsLiteral() && x->AsLiteral()->handle()->IsNumber() &&
+          y && y->AsLiteral() && y->AsLiteral()->handle()->IsNumber()) {
+        double x_val = x->AsLiteral()->handle()->Number();
+        double y_val = y->AsLiteral()->handle()->Number();
+
+        switch (op) {
+          case Token::ADD:
+            x = NewNumberLiteral(x_val + y_val);
+            continue;
+          case Token::SUB:
+            x = NewNumberLiteral(x_val - y_val);
+            continue;
+          case Token::MUL:
+            x = NewNumberLiteral(x_val * y_val);
+            continue;
+          case Token::DIV:
+            x = NewNumberLiteral(x_val / y_val);
+            continue;
+          case Token::BIT_OR:
+            x = NewNumberLiteral(DoubleToInt32(x_val) | DoubleToInt32(y_val));
+            continue;
+          case Token::BIT_AND:
+            x = NewNumberLiteral(DoubleToInt32(x_val) & DoubleToInt32(y_val));
+            continue;
+          case Token::BIT_XOR:
+            x = NewNumberLiteral(DoubleToInt32(x_val) ^ DoubleToInt32(y_val));
+            continue;
+          case Token::SHL: {
+            int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
+            x = NewNumberLiteral(value);
+            continue;
+          }
+          case Token::SHR: {
+            uint32_t shift = DoubleToInt32(y_val) & 0x1f;
+            uint32_t value = DoubleToUint32(x_val) >> shift;
+            x = NewNumberLiteral(value);
+            continue;
+          }
+          case Token::SAR: {
+            uint32_t shift = DoubleToInt32(y_val) & 0x1f;
+            int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
+            x = NewNumberLiteral(value);
+            continue;
+          }
+          default:
+            break;
+        }
+      }
+
+      // For now we distinguish between comparisons and other binary
+      // operations.  (We could combine the two and get rid of this
+      // code an AST node eventually.)
+      if (Token::IsCompareOp(op)) {
+        // We have a comparison.
+        Token::Value cmp = op;
+        switch (op) {
+          case Token::NE: cmp = Token::EQ; break;
+          case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
+          default: break;
+        }
+        x = NEW(CompareOperation(cmp, x, y));
+        if (cmp != op) {
+          // The comparison was negated - add a NOT.
+          x = NEW(UnaryOperation(Token::NOT, x));
+        }
+
+      } else {
+        // We have a "normal" binary operation.
+        x = NEW(BinaryOperation(op, x, y));
+      }
+    }
+  }
+  return x;
+}
+
+
+Expression* Parser::ParseUnaryExpression(bool* ok) {
+  // UnaryExpression ::
+  //   PostfixExpression
+  //   'delete' UnaryExpression
+  //   'void' UnaryExpression
+  //   'typeof' UnaryExpression
+  //   '++' UnaryExpression
+  //   '--' UnaryExpression
+  //   '+' UnaryExpression
+  //   '-' UnaryExpression
+  //   '~' UnaryExpression
+  //   '!' UnaryExpression
+
+  Token::Value op = peek();
+  if (Token::IsUnaryOp(op)) {
+    op = Next();
+    Expression* x = ParseUnaryExpression(CHECK_OK);
+
+    // Compute some expressions involving only number literals.
+    if (x && x->AsLiteral() && x->AsLiteral()->handle()->IsNumber()) {
+      double x_val = x->AsLiteral()->handle()->Number();
+      switch (op) {
+        case Token::ADD:
+          return x;
+        case Token::SUB:
+          return NewNumberLiteral(-x_val);
+        case Token::BIT_NOT:
+          return NewNumberLiteral(~DoubleToInt32(x_val));
+        default: break;
+      }
+    }
+
+    return NEW(UnaryOperation(op, x));
+
+  } else if (Token::IsCountOp(op)) {
+    op = Next();
+    Expression* x = ParseUnaryExpression(CHECK_OK);
+    if (x == NULL || !x->IsValidLeftHandSide()) {
+      if (x != NULL && x->AsCall() != NULL) {
+        // According to ECMA-262 host function calls are permitted to
+        // return references.  This cannot happen in our system so we
+        // will always get an error.  We could report this as a syntax
+        // error here but for compatibility with KJS and SpiderMonkey we
+        // choose to report the error at runtime.
+        Handle<String> type = Factory::invalid_lhs_in_prefix_op_symbol();
+        x = NewThrowReferenceError(type);
+      } else {
+        // Invalid left hand side expressions that are not function
+        // calls are reported as syntax errors at compile time.
+        ReportMessage("invalid_lhs_in_prefix_op", Vector<const char*>::empty());
+        *ok = false;
+        return NULL;
+      }
+    }
+    return NEW(CountOperation(true /* prefix */, op, x));
+
+  } else {
+    return ParsePostfixExpression(ok);
+  }
+}
+
+
+Expression* Parser::ParsePostfixExpression(bool* ok) {
+  // PostfixExpression ::
+  //   LeftHandSideExpression ('++' | '--')?
+
+  Expression* result = ParseLeftHandSideExpression(CHECK_OK);
+  if (!scanner_.has_line_terminator_before_next() && Token::IsCountOp(peek())) {
+    if (result == NULL || !result->IsValidLeftHandSide()) {
+      if (result != NULL && result->AsCall() != NULL) {
+        // According to ECMA-262 host function calls are permitted to
+        // return references.  This cannot happen in our system so we
+        // will always get an error.  We could report this as a syntax
+        // error here but for compatibility with KJS and SpiderMonkey we
+        // choose to report the error at runtime.
+        Handle<String> type = Factory::invalid_lhs_in_postfix_op_symbol();
+        result = NewThrowReferenceError(type);
+      } else {
+        // Invalid left hand side expressions that are not function
+        // calls are reported as syntax errors at compile time.
+        ReportMessage("invalid_lhs_in_postfix_op",
+                      Vector<const char*>::empty());
+        *ok = false;
+        return NULL;
+      }
+    }
+    Token::Value next = Next();
+    result = NEW(CountOperation(false /* postfix */, next, result));
+  }
+  return result;
+}
+
+
+Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
+  // LeftHandSideExpression ::
+  //   (NewExpression | MemberExpression) ...
+
+  Expression* result;
+  if (peek() == Token::NEW) {
+    result = ParseNewExpression(CHECK_OK);
+  } else {
+    result = ParseMemberExpression(CHECK_OK);
+  }
+
+  while (true) {
+    switch (peek()) {
+      case Token::LBRACK: {
+        Consume(Token::LBRACK);
+        int pos = scanner().location().beg_pos;
+        Expression* index = ParseExpression(true, CHECK_OK);
+        result = factory()->NewProperty(result, index, pos);
+        Expect(Token::RBRACK, CHECK_OK);
+        break;
+      }
+
+      case Token::LPAREN: {
+        int pos = scanner().location().beg_pos;
+        ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
+
+        // Keep track of eval() calls since they disable all local variable
+        // optimizations.
+        // The calls that need special treatment are the
+        // direct (i.e. not aliased) eval calls. These calls are all of the
+        // form eval(...) with no explicit receiver object where eval is not
+        // declared in the current scope chain. These calls are marked as
+        // potentially direct eval calls. Whether they are actually direct calls
+        // to eval is determined at run time.
+
+        bool is_potentially_direct_eval = false;
+        if (!is_pre_parsing_) {
+          VariableProxy* callee = result->AsVariableProxy();
+          if (callee != NULL && callee->IsVariable(Factory::eval_symbol())) {
+            Handle<String> name = callee->name();
+            Variable* var = top_scope_->Lookup(name);
+            if (var == NULL) {
+              // We do not allow direct calls to 'eval' in our internal
+              // JS files. Use builtin functions instead.
+              ASSERT(extension_ != NULL || !Bootstrapper::IsActive());
+              top_scope_->RecordEvalCall();
+              is_potentially_direct_eval = true;
+            }
+          }
+        }
+
+        if (is_potentially_direct_eval) {
+          result = factory()->NewCallEval(result, args, pos);
+        } else {
+          result = factory()->NewCall(result, args, pos);
+        }
+        break;
+      }
+
+      case Token::PERIOD: {
+        Consume(Token::PERIOD);
+        int pos = scanner().location().beg_pos;
+        Handle<String> name = ParseIdentifier(CHECK_OK);
+        result = factory()->NewProperty(result, NEW(Literal(name)), pos);
+        break;
+      }
+
+      default:
+        return result;
+    }
+  }
+}
+
+
+Expression* Parser::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
+  List<int> new_positions(4);
+  while (peek() == Token::NEW) {
+    Consume(Token::NEW);
+    new_positions.Add(scanner().location().beg_pos);
+  }
+  ASSERT(new_positions.length() > 0);
+
+  Expression* result =
+      ParseMemberWithNewPrefixesExpression(&new_positions, CHECK_OK);
+  while (!new_positions.is_empty()) {
+    int last = new_positions.RemoveLast();
+    result = NEW(CallNew(result, new ZoneList<Expression*>(0), last));
+  }
+  return result;
+}
+
+
+Expression* Parser::ParseMemberExpression(bool* ok) {
+  static List<int> new_positions(0);
+  return ParseMemberWithNewPrefixesExpression(&new_positions, ok);
+}
+
+
+Expression* Parser::ParseMemberWithNewPrefixesExpression(
+    List<int>* new_positions,
+    bool* ok) {
+  // MemberExpression ::
+  //   (PrimaryExpression | FunctionLiteral)
+  //     ('[' Expression ']' | '.' Identifier | Arguments)*
+
+  // Parse the initial primary or function expression.
+  Expression* result = NULL;
+  if (peek() == Token::FUNCTION) {
+    Expect(Token::FUNCTION, CHECK_OK);
+    int function_token_position = scanner().location().beg_pos;
+    Handle<String> name;
+    if (peek() == Token::IDENTIFIER) name = ParseIdentifier(CHECK_OK);
+    result = ParseFunctionLiteral(name, function_token_position,
+                                  NESTED, CHECK_OK);
+  } else {
+    result = ParsePrimaryExpression(CHECK_OK);
+  }
+
+  while (true) {
+    switch (peek()) {
+      case Token::LBRACK: {
+        Consume(Token::LBRACK);
+        int pos = scanner().location().beg_pos;
+        Expression* index = ParseExpression(true, CHECK_OK);
+        result = factory()->NewProperty(result, index, pos);
+        Expect(Token::RBRACK, CHECK_OK);
+        break;
+      }
+      case Token::PERIOD: {
+        Consume(Token::PERIOD);
+        int pos = scanner().location().beg_pos;
+        Handle<String> name = ParseIdentifier(CHECK_OK);
+        result = factory()->NewProperty(result, NEW(Literal(name)), pos);
+        break;
+      }
+      case Token::LPAREN: {
+        if (new_positions->is_empty()) return result;
+        // Consume one of the new prefixes (already parsed).
+        ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
+        int last = new_positions->RemoveLast();
+        result = NEW(CallNew(result, args, last));
+        break;
+      }
+      default:
+        return result;
+    }
+  }
+}
+
+
+DebuggerStatement* Parser::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 i a
+  // break point is present.
+  // DebuggerStatement ::
+  //   'debugger' ';'
+
+  Expect(Token::DEBUGGER, CHECK_OK);
+  ExpectSemicolon(CHECK_OK);
+  return NEW(DebuggerStatement());
+}
+
+
+void Parser::ReportUnexpectedToken(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 == Token::ILLEGAL && scanner().stack_overflow())
+    return;
+  // Four of the tokens are treated specially
+  switch (token) {
+  case Token::EOS:
+    return ReportMessage("unexpected_eos", Vector<const char*>::empty());
+  case Token::NUMBER:
+    return ReportMessage("unexpected_token_number",
+                         Vector<const char*>::empty());
+  case Token::STRING:
+    return ReportMessage("unexpected_token_string",
+                         Vector<const char*>::empty());
+  case Token::IDENTIFIER:
+    return ReportMessage("unexpected_token_identifier",
+                         Vector<const char*>::empty());
+  default:
+    const char* name = Token::String(token);
+    ASSERT(name != NULL);
+    ReportMessage("unexpected_token", Vector<const char*>(&name, 1));
+  }
+}
+
+
+Expression* Parser::ParsePrimaryExpression(bool* ok) {
+  // PrimaryExpression ::
+  //   'this'
+  //   'null'
+  //   'true'
+  //   'false'
+  //   Identifier
+  //   Number
+  //   String
+  //   ArrayLiteral
+  //   ObjectLiteral
+  //   RegExpLiteral
+  //   '(' Expression ')'
+
+  Expression* result = NULL;
+  switch (peek()) {
+    case Token::THIS: {
+      Consume(Token::THIS);
+      if (is_pre_parsing_) {
+        result = VariableProxySentinel::this_proxy();
+      } else {
+        VariableProxy* recv = top_scope_->receiver();
+        recv->var_uses()->RecordRead(1);
+        result = recv;
+      }
+      break;
+    }
+
+    case Token::NULL_LITERAL:
+      Consume(Token::NULL_LITERAL);
+      result = NEW(Literal(Factory::null_value()));
+      break;
+
+    case Token::TRUE_LITERAL:
+      Consume(Token::TRUE_LITERAL);
+      result = NEW(Literal(Factory::true_value()));
+      break;
+
+    case Token::FALSE_LITERAL:
+      Consume(Token::FALSE_LITERAL);
+      result = NEW(Literal(Factory::false_value()));
+      break;
+
+    case Token::IDENTIFIER: {
+      Handle<String> name = ParseIdentifier(CHECK_OK);
+      if (is_pre_parsing_) {
+        result = VariableProxySentinel::identifier_proxy();
+      } else {
+        result = top_scope_->NewUnresolved(name, inside_with());
+      }
+      break;
+    }
+
+    case Token::NUMBER: {
+      Consume(Token::NUMBER);
+      double value =
+        StringToDouble(scanner_.literal_string(), ALLOW_HEX | ALLOW_OCTALS);
+      result = NewNumberLiteral(value);
+      break;
+    }
+
+    case Token::STRING: {
+      Consume(Token::STRING);
+      Handle<String> symbol =
+          factory()->LookupSymbol(scanner_.literal_string(),
+                                  scanner_.literal_length());
+      result = NEW(Literal(symbol));
+      break;
+    }
+
+    case Token::ASSIGN_DIV:
+      result = ParseRegExpLiteral(true, CHECK_OK);
+      break;
+
+    case Token::DIV:
+      result = ParseRegExpLiteral(false, CHECK_OK);
+      break;
+
+    case Token::LBRACK:
+      result = ParseArrayLiteral(CHECK_OK);
+      break;
+
+    case Token::LBRACE:
+      result = ParseObjectLiteral(CHECK_OK);
+      break;
+
+    case Token::LPAREN:
+      Consume(Token::LPAREN);
+      result = ParseExpression(true, CHECK_OK);
+      Expect(Token::RPAREN, CHECK_OK);
+      break;
+
+    case Token::MOD:
+      if (allow_natives_syntax_ || extension_ != NULL) {
+        result = ParseV8Intrinsic(CHECK_OK);
+        break;
+      }
+      // If we're not allowing special syntax we fall-through to the
+      // default case.
+
+    default: {
+      Token::Value tok = peek();
+      // Token::Peek returns the value of the next token but
+      // location() gives info about the current token.
+      // Therefore, we need to read ahead to the next token
+      Next();
+      ReportUnexpectedToken(tok);
+      *ok = false;
+      return NULL;
+    }
+  }
+
+  return result;
+}
+
+
+Expression* Parser::ParseArrayLiteral(bool* ok) {
+  // ArrayLiteral ::
+  //   '[' Expression? (',' Expression?)* ']'
+
+  ZoneListWrapper<Expression> values = factory()->NewList<Expression>(4);
+  Expect(Token::LBRACK, CHECK_OK);
+  while (peek() != Token::RBRACK) {
+    Expression* elem;
+    if (peek() == Token::COMMA) {
+      elem = GetLiteralTheHole();
+    } else {
+      elem = ParseAssignmentExpression(true, CHECK_OK);
+    }
+    values.Add(elem);
+    if (peek() != Token::RBRACK) {
+      Expect(Token::COMMA, CHECK_OK);
+    }
+  }
+  Expect(Token::RBRACK, CHECK_OK);
+
+  // Update the scope information before the pre-parsing bailout.
+  temp_scope_->set_contains_array_literal();
+  int literal_index = temp_scope_->NextMaterializedLiteralIndex();
+
+  if (is_pre_parsing_) return NULL;
+
+  // Allocate a fixed array with all the literals.
+  Handle<FixedArray> literals =
+      Factory::NewFixedArray(values.length(), TENURED);
+
+  // Fill in the literals.
+  bool is_simple = true;
+  int depth = 1;
+  for (int i = 0; i < values.length(); i++) {
+    MaterializedLiteral* m_literal = values.at(i)->AsMaterializedLiteral();
+    if (m_literal != NULL && m_literal->depth() + 1 > depth) {
+      depth = m_literal->depth() + 1;
+    }
+    Handle<Object> boilerplate_value = GetBoilerplateValue(values.at(i));
+    if (boilerplate_value->IsUndefined()) {
+      literals->set_the_hole(i);
+      is_simple = false;
+    } else {
+      literals->set(i, *boilerplate_value);
+    }
+  }
+
+  return NEW(ArrayLiteral(literals, values.elements(),
+                          literal_index, is_simple, depth));
+}
+
+
+bool Parser::IsBoilerplateProperty(ObjectLiteral::Property* property) {
+  return property != NULL &&
+         property->kind() != ObjectLiteral::Property::PROTOTYPE;
+}
+
+
+bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
+  MaterializedLiteral* lit = expression->AsMaterializedLiteral();
+  return lit != NULL && lit->is_simple();
+}
+
+Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) {
+  ASSERT(IsCompileTimeValue(expression));
+  Handle<FixedArray> result = Factory::NewFixedArray(2, TENURED);
+  ObjectLiteral* object_literal = expression->AsObjectLiteral();
+  if (object_literal != NULL) {
+    ASSERT(object_literal->is_simple());
+    result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL));
+    result->set(kElementsSlot, *object_literal->constant_properties());
+  } else {
+    ArrayLiteral* array_literal = expression->AsArrayLiteral();
+    ASSERT(array_literal != NULL && array_literal->is_simple());
+    result->set(kTypeSlot, Smi::FromInt(ARRAY_LITERAL));
+    result->set(kElementsSlot, *array_literal->literals());
+  }
+  return result;
+}
+
+
+CompileTimeValue::Type CompileTimeValue::GetType(Handle<FixedArray> value) {
+  Smi* type_value = Smi::cast(value->get(kTypeSlot));
+  return static_cast<Type>(type_value->value());
+}
+
+
+Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
+  return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
+}
+
+
+Handle<Object> Parser::GetBoilerplateValue(Expression* expression) {
+  if (expression->AsLiteral() != NULL) {
+    return expression->AsLiteral()->handle();
+  }
+  if (CompileTimeValue::IsCompileTimeValue(expression)) {
+    return CompileTimeValue::GetValue(expression);
+  }
+  return Factory::undefined_value();
+}
+
+
+Expression* Parser::ParseObjectLiteral(bool* ok) {
+  // ObjectLiteral ::
+  //   '{' (
+  //       ((Identifier | String | Number) ':' AssignmentExpression)
+  //     | (('get' | 'set') FunctionLiteral)
+  //    )*[','] '}'
+
+  ZoneListWrapper<ObjectLiteral::Property> properties =
+      factory()->NewList<ObjectLiteral::Property>(4);
+  int number_of_boilerplate_properties = 0;
+
+  Expect(Token::LBRACE, CHECK_OK);
+  while (peek() != Token::RBRACE) {
+    Literal* key = NULL;
+    switch (peek()) {
+      case Token::IDENTIFIER: {
+        // Store identifier keys as literal symbols to avoid
+        // resolving them when compiling code for the object
+        // literal.
+        bool is_getter = false;
+        bool is_setter = false;
+        Handle<String> id =
+            ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
+        if (is_getter || is_setter) {
+          // Special handling of getter and setter syntax.
+          if (peek() == Token::IDENTIFIER) {
+            Handle<String> name = ParseIdentifier(CHECK_OK);
+            FunctionLiteral* value =
+                ParseFunctionLiteral(name, RelocInfo::kNoPosition,
+                                     DECLARATION, CHECK_OK);
+            ObjectLiteral::Property* property =
+                NEW(ObjectLiteral::Property(is_getter, value));
+            if (IsBoilerplateProperty(property))
+              number_of_boilerplate_properties++;
+            properties.Add(property);
+            if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
+            continue;  // restart the while
+          }
+        }
+        key = NEW(Literal(id));
+        break;
+      }
+
+      case Token::STRING: {
+        Consume(Token::STRING);
+        Handle<String> string =
+            factory()->LookupSymbol(scanner_.literal_string(),
+                                    scanner_.literal_length());
+        uint32_t index;
+        if (!string.is_null() && string->AsArrayIndex(&index)) {
+          key = NewNumberLiteral(index);
+        } else {
+          key = NEW(Literal(string));
+        }
+        break;
+      }
+
+      case Token::NUMBER: {
+        Consume(Token::NUMBER);
+        double value =
+          StringToDouble(scanner_.literal_string(), ALLOW_HEX | ALLOW_OCTALS);
+        key = NewNumberLiteral(value);
+        break;
+      }
+
+      default:
+        Expect(Token::RBRACE, CHECK_OK);
+        break;
+    }
+
+    Expect(Token::COLON, CHECK_OK);
+    Expression* value = ParseAssignmentExpression(true, CHECK_OK);
+
+    ObjectLiteral::Property* property =
+        NEW(ObjectLiteral::Property(key, value));
+
+    // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
+    if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
+    properties.Add(property);
+
+    // TODO(1240767): Consider allowing trailing comma.
+    if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
+  }
+  Expect(Token::RBRACE, CHECK_OK);
+  // Computation of literal_index must happen before pre parse bailout.
+  int literal_index = temp_scope_->NextMaterializedLiteralIndex();
+  if (is_pre_parsing_) return NULL;
+
+  Handle<FixedArray> constant_properties =
+      Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED);
+  int position = 0;
+  bool is_simple = true;
+  int depth = 1;
+  for (int i = 0; i < properties.length(); i++) {
+    ObjectLiteral::Property* property = properties.at(i);
+    if (!IsBoilerplateProperty(property)) {
+      is_simple = false;
+      continue;
+    }
+    MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
+    if (m_literal != NULL && m_literal->depth() + 1 > depth) {
+      depth = m_literal->depth() + 1;
+    }
+
+    // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
+    // value for COMPUTED properties, the real value is filled in at
+    // runtime. The enumeration order is maintained.
+    Handle<Object> key = property->key()->handle();
+    Handle<Object> value = GetBoilerplateValue(property->value());
+    is_simple = is_simple && !value->IsUndefined();
+
+    // Add name, value pair to the fixed array.
+    constant_properties->set(position++, *key);
+    constant_properties->set(position++, *value);
+  }
+
+  return new ObjectLiteral(constant_properties,
+                           properties.elements(),
+                           literal_index,
+                           is_simple,
+                           depth);
+}
+
+
+Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
+  if (!scanner_.ScanRegExpPattern(seen_equal)) {
+    Next();
+    ReportMessage("unterminated_regexp", Vector<const char*>::empty());
+    *ok = false;
+    return NULL;
+  }
+
+  int literal_index = temp_scope_->NextMaterializedLiteralIndex();
+
+  if (is_pre_parsing_) {
+    // If we're preparsing we just do all the parsing stuff without
+    // building anything.
+    if (!scanner_.ScanRegExpFlags()) {
+      Next();
+      ReportMessage("invalid_regexp_flags", Vector<const char*>::empty());
+      *ok = false;
+      return NULL;
+    }
+    Next();
+    return NULL;
+  }
+
+  Handle<String> js_pattern =
+      Factory::NewStringFromUtf8(scanner_.next_literal(), TENURED);
+  scanner_.ScanRegExpFlags();
+  Handle<String> js_flags =
+      Factory::NewStringFromUtf8(scanner_.next_literal(), TENURED);
+  Next();
+
+  return new RegExpLiteral(js_pattern, js_flags, literal_index);
+}
+
+
+ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
+  // Arguments ::
+  //   '(' (AssignmentExpression)*[','] ')'
+
+  ZoneListWrapper<Expression> result = factory()->NewList<Expression>(4);
+  Expect(Token::LPAREN, CHECK_OK);
+  bool done = (peek() == Token::RPAREN);
+  while (!done) {
+    Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
+    result.Add(argument);
+    done = (peek() == Token::RPAREN);
+    if (!done) Expect(Token::COMMA, CHECK_OK);
+  }
+  Expect(Token::RPAREN, CHECK_OK);
+  return result.elements();
+}
+
+
+FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
+                                              int function_token_position,
+                                              FunctionLiteralType type,
+                                              bool* ok) {
+  // Function ::
+  //   '(' FormalParameterList? ')' '{' FunctionBody '}'
+
+  bool is_named = !var_name.is_null();
+
+  // The name associated with this function. If it's a function expression,
+  // this is the actual function name, otherwise this is the name of the
+  // variable declared and initialized with the function (expression). In
+  // that case, we don't have a function name (it's empty).
+  Handle<String> name = is_named ? var_name : factory()->EmptySymbol();
+  // The function name, if any.
+  Handle<String> function_name = factory()->EmptySymbol();
+  if (is_named && (type == EXPRESSION || type == NESTED)) {
+    function_name = name;
+  }
+
+  int num_parameters = 0;
+  // Parse function body.
+  { Scope::Type type = Scope::FUNCTION_SCOPE;
+    Scope* scope = factory()->NewScope(top_scope_, type, inside_with());
+    LexicalScope lexical_scope(this, scope);
+    TemporaryScope temp_scope(this);
+    top_scope_->SetScopeName(name);
+
+    //  FormalParameterList ::
+    //    '(' (Identifier)*[','] ')'
+    Expect(Token::LPAREN, CHECK_OK);
+    int start_pos = scanner_.location().beg_pos;
+    bool done = (peek() == Token::RPAREN);
+    while (!done) {
+      Handle<String> param_name = ParseIdentifier(CHECK_OK);
+      if (!is_pre_parsing_) {
+        top_scope_->AddParameter(top_scope_->Declare(param_name,
+                                                     Variable::VAR));
+        num_parameters++;
+      }
+      done = (peek() == Token::RPAREN);
+      if (!done) Expect(Token::COMMA, CHECK_OK);
+    }
+    Expect(Token::RPAREN, CHECK_OK);
+
+    Expect(Token::LBRACE, CHECK_OK);
+    ZoneListWrapper<Statement> body = factory()->NewList<Statement>(8);
+
+    // If we have a named function expression, we add a local variable
+    // declaration to the body of the function with the name of the
+    // function and let it refer to the function itself (closure).
+    // NOTE: We create a proxy and resolve it here so that in the
+    // future we can change the AST to only refer to VariableProxies
+    // instead of Variables and Proxis as is the case now.
+    if (!function_name.is_null() && function_name->length() > 0) {
+      Variable* fvar = top_scope_->DeclareFunctionVar(function_name);
+      VariableProxy* fproxy =
+          top_scope_->NewUnresolved(function_name, inside_with());
+      fproxy->BindTo(fvar);
+      body.Add(new ExpressionStatement(
+                   new Assignment(Token::INIT_VAR, fproxy,
+                                  NEW(ThisFunction()),
+                                  RelocInfo::kNoPosition)));
+    }
+
+    // Determine if the function will be lazily compiled. The mode can
+    // only be PARSE_LAZILY if the --lazy flag is true.
+    bool is_lazily_compiled =
+        mode() == PARSE_LAZILY && top_scope_->HasTrivialOuterContext();
+
+    int materialized_literal_count;
+    int expected_property_count;
+    bool contains_array_literal;
+    if (is_lazily_compiled && pre_data() != NULL) {
+      FunctionEntry entry = pre_data()->GetFunctionEnd(start_pos);
+      int end_pos = entry.end_pos();
+      Counters::total_preparse_skipped.Increment(end_pos - start_pos);
+      scanner_.SeekForward(end_pos);
+      materialized_literal_count = entry.literal_count();
+      expected_property_count = entry.property_count();
+      contains_array_literal = entry.contains_array_literal();
+    } else {
+      ParseSourceElements(&body, Token::RBRACE, CHECK_OK);
+      materialized_literal_count = temp_scope.materialized_literal_count();
+      expected_property_count = temp_scope.expected_property_count();
+      contains_array_literal = temp_scope.contains_array_literal();
+    }
+
+    Expect(Token::RBRACE, CHECK_OK);
+    int end_pos = scanner_.location().end_pos;
+
+    FunctionEntry entry = log()->LogFunction(start_pos);
+    if (entry.is_valid()) {
+      entry.set_end_pos(end_pos);
+      entry.set_literal_count(materialized_literal_count);
+      entry.set_property_count(expected_property_count);
+      entry.set_contains_array_literal(contains_array_literal);
+    }
+
+    FunctionLiteral* function_literal =
+        NEW(FunctionLiteral(name, top_scope_,
+                            body.elements(), materialized_literal_count,
+                            contains_array_literal, expected_property_count,
+                            num_parameters, start_pos, end_pos,
+                            function_name->length() > 0));
+    if (!is_pre_parsing_) {
+      function_literal->set_function_token_position(function_token_position);
+    }
+    return function_literal;
+  }
+}
+
+
+Expression* Parser::ParseV8Intrinsic(bool* ok) {
+  // CallRuntime ::
+  //   '%' Identifier Arguments
+
+  Expect(Token::MOD, CHECK_OK);
+  Handle<String> name = ParseIdentifier(CHECK_OK);
+  Runtime::Function* function =
+      Runtime::FunctionForName(scanner_.literal_string());
+  ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
+  if (function == NULL && extension_ != NULL) {
+    // The extension structures are only accessible while parsing the
+    // very first time not when reparsing because of lazy compilation.
+    top_scope_->ForceEagerCompilation();
+  }
+
+  // Check for built-in macros.
+  if (!is_pre_parsing_) {
+    if (function == Runtime::FunctionForId(Runtime::kIS_VAR)) {
+      // %IS_VAR(x)
+      //   evaluates to x if x is a variable,
+      //   leads to a parse error otherwise
+      if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
+        return args->at(0);
+      }
+      *ok = false;
+    // Check here for other macros.
+    // } else if (function == Runtime::FunctionForId(Runtime::kIS_VAR)) {
+    //   ...
+    }
+
+    if (!*ok) {
+      // We found a macro but it failed.
+      ReportMessage("unable_to_parse", Vector<const char*>::empty());
+      return NULL;
+    }
+  }
+
+  // Otherwise we have a runtime call.
+  return NEW(CallRuntime(name, function, args));
+}
+
+
+void Parser::Consume(Token::Value token) {
+  Token::Value next = Next();
+  USE(next);
+  USE(token);
+  ASSERT(next == token);
+}
+
+
+void Parser::Expect(Token::Value token, bool* ok) {
+  Token::Value next = Next();
+  if (next == token) return;
+  ReportUnexpectedToken(next);
+  *ok = false;
+}
+
+
+void Parser::ExpectSemicolon(bool* ok) {
+  // Check for automatic semicolon insertion according to
+  // the rules given in ECMA-262, section 7.9, page 21.
+  Token::Value tok = peek();
+  if (tok == Token::SEMICOLON) {
+    Next();
+    return;
+  }
+  if (scanner_.has_line_terminator_before_next() ||
+      tok == Token::RBRACE ||
+      tok == Token::EOS) {
+    return;
+  }
+  Expect(Token::SEMICOLON, ok);
+}
+
+
+Literal* Parser::GetLiteralUndefined() {
+  return NEW(Literal(Factory::undefined_value()));
+}
+
+
+Literal* Parser::GetLiteralTheHole() {
+  return NEW(Literal(Factory::the_hole_value()));
+}
+
+
+Literal* Parser::GetLiteralNumber(double value) {
+  return NewNumberLiteral(value);
+}
+
+
+Handle<String> Parser::ParseIdentifier(bool* ok) {
+  Expect(Token::IDENTIFIER, ok);
+  if (!*ok) return Handle<String>();
+  return factory()->LookupSymbol(scanner_.literal_string(),
+                                 scanner_.literal_length());
+}
+
+// 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.
+Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get,
+                                                 bool* is_set,
+                                                 bool* ok) {
+  Expect(Token::IDENTIFIER, ok);
+  if (!*ok) return Handle<String>();
+  if (scanner_.literal_length() == 3) {
+    const char* token = scanner_.literal_string();
+    *is_get = strcmp(token, "get") == 0;
+    *is_set = !*is_get && strcmp(token, "set") == 0;
+  }
+  return factory()->LookupSymbol(scanner_.literal_string(),
+                                 scanner_.literal_length());
+}
+
+
+// ----------------------------------------------------------------------------
+// Parser support
+
+
+bool Parser::TargetStackContainsLabel(Handle<String> label) {
+  for (int i = target_stack_->length(); i-- > 0;) {
+    BreakableStatement* stat = target_stack_->at(i)->AsBreakableStatement();
+    if (stat != NULL && ContainsLabel(stat->labels(), label))
+      return true;
+  }
+  return false;
+}
+
+
+BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) {
+  bool anonymous = label.is_null();
+  for (int i = target_stack_->length(); i-- > 0;) {
+    BreakableStatement* stat = target_stack_->at(i)->AsBreakableStatement();
+    if (stat == NULL) continue;
+
+    if ((anonymous && stat->is_target_for_anonymous()) ||
+        (!anonymous && ContainsLabel(stat->labels(), label))) {
+      RegisterTargetUse(stat->break_target(), i);
+      return stat;
+    }
+  }
+  return NULL;
+}
+
+
+IterationStatement* Parser::LookupContinueTarget(Handle<String> label,
+                                                 bool* ok) {
+  bool anonymous = label.is_null();
+  for (int i = target_stack_->length(); i-- > 0;) {
+    IterationStatement* stat = target_stack_->at(i)->AsIterationStatement();
+    if (stat == NULL) continue;
+
+    ASSERT(stat->is_target_for_anonymous());
+    if (anonymous || ContainsLabel(stat->labels(), label)) {
+      RegisterTargetUse(stat->continue_target(), i);
+      return stat;
+    }
+  }
+  return NULL;
+}
+
+
+void Parser::RegisterTargetUse(BreakTarget* target, int index) {
+  // Register that a break target found at the given index in the
+  // target stack has been used from the top of the target stack. Add
+  // the break target to any TargetCollectors passed on the stack.
+  for (int i = target_stack_->length(); i-- > index;) {
+    TargetCollector* collector = target_stack_->at(i)->AsTargetCollector();
+    if (collector != NULL) collector->AddTarget(target);
+  }
+}
+
+
+Literal* Parser::NewNumberLiteral(double number) {
+  return NEW(Literal(Factory::NewNumber(number, TENURED)));
+}
+
+
+Expression* Parser::NewThrowReferenceError(Handle<String> type) {
+  return NewThrowError(Factory::MakeReferenceError_symbol(),
+                       type, HandleVector<Object>(NULL, 0));
+}
+
+
+Expression* Parser::NewThrowSyntaxError(Handle<String> type,
+                                        Handle<Object> first) {
+  int argc = first.is_null() ? 0 : 1;
+  Vector< Handle<Object> > arguments = HandleVector<Object>(&first, argc);
+  return NewThrowError(Factory::MakeSyntaxError_symbol(), type, arguments);
+}
+
+
+Expression* Parser::NewThrowTypeError(Handle<String> type,
+                                      Handle<Object> first,
+                                      Handle<Object> second) {
+  ASSERT(!first.is_null() && !second.is_null());
+  Handle<Object> elements[] = { first, second };
+  Vector< Handle<Object> > arguments =
+      HandleVector<Object>(elements, ARRAY_SIZE(elements));
+  return NewThrowError(Factory::MakeTypeError_symbol(), type, arguments);
+}
+
+
+Expression* Parser::NewThrowError(Handle<String> constructor,
+                                  Handle<String> type,
+                                  Vector< Handle<Object> > arguments) {
+  if (is_pre_parsing_) return NULL;
+
+  int argc = arguments.length();
+  Handle<JSArray> array = Factory::NewJSArray(argc, TENURED);
+  ASSERT(array->IsJSArray() && array->HasFastElements());
+  for (int i = 0; i < argc; i++) {
+    Handle<Object> element = arguments[i];
+    if (!element.is_null()) {
+      array->SetFastElement(i, *element);
+    }
+  }
+  ZoneList<Expression*>* args = new ZoneList<Expression*>(2);
+  args->Add(new Literal(type));
+  args->Add(new Literal(array));
+  return new Throw(new CallRuntime(constructor, NULL, args),
+                   scanner().location().beg_pos);
+}
+
+
+// ----------------------------------------------------------------------------
+// Regular expressions
+
+
+RegExpParser::RegExpParser(FlatStringReader* in,
+                           Handle<String>* error,
+                           bool multiline)
+  : current_(kEndMarker),
+    has_more_(true),
+    multiline_(multiline),
+    next_pos_(0),
+    in_(in),
+    error_(error),
+    simple_(false),
+    contains_anchor_(false),
+    captures_(NULL),
+    is_scanned_for_captures_(false),
+    capture_count_(0),
+    failed_(false) {
+  Advance(1);
+}
+
+
+uc32 RegExpParser::Next() {
+  if (has_next()) {
+    return in()->Get(next_pos_);
+  } else {
+    return kEndMarker;
+  }
+}
+
+
+void RegExpParser::Advance() {
+  if (next_pos_ < in()->length()) {
+    StackLimitCheck check;
+    if (check.HasOverflowed()) {
+      ReportError(CStrVector(Top::kStackOverflowMessage));
+    } else if (Zone::excess_allocation()) {
+      ReportError(CStrVector("Regular expression too large"));
+    } else {
+      current_ = in()->Get(next_pos_);
+      next_pos_++;
+    }
+  } else {
+    current_ = kEndMarker;
+    has_more_ = false;
+  }
+}
+
+
+void RegExpParser::Reset(int pos) {
+  next_pos_ = pos;
+  Advance();
+}
+
+
+void RegExpParser::Advance(int dist) {
+  for (int i = 0; i < dist; i++)
+    Advance();
+}
+
+
+bool RegExpParser::simple() {
+  return simple_;
+}
+
+RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
+  failed_ = true;
+  *error_ = Factory::NewStringFromAscii(message, NOT_TENURED);
+  // Zip to the end to make sure the no more input is read.
+  current_ = kEndMarker;
+  next_pos_ = in()->length();
+  return NULL;
+}
+
+
+// Pattern ::
+//   Disjunction
+RegExpTree* RegExpParser::ParsePattern() {
+  RegExpTree* result = ParseDisjunction(CHECK_FAILED);
+  if (has_more()) {
+    ReportError(CStrVector("Unmatched ')'") CHECK_FAILED);
+  }
+  // If the result of parsing is a literal string atom, and it has the
+  // same length as the input, then the atom is identical to the input.
+  if (result->IsAtom() && result->AsAtom()->length() == in()->length()) {
+    simple_ = true;
+  }
+  return result;
+}
+
+
+bool RegExpParser::CaptureAvailable(int index) {
+  if (captures_ == NULL) return false;
+  if (index >= captures_->length()) return false;
+  RegExpCapture* capture = captures_->at(index);
+  return capture != NULL && capture->available() == CAPTURE_AVAILABLE;
+}
+
+
+// Disjunction ::
+//   Alternative
+//   Alternative | Disjunction
+// Alternative ::
+//   [empty]
+//   Term Alternative
+// Term ::
+//   Assertion
+//   Atom
+//   Atom Quantifier
+RegExpTree* RegExpParser::ParseDisjunction() {
+  RegExpBuilder builder;
+  int capture_start_index = captures_started();
+  while (true) {
+    switch (current()) {
+    case kEndMarker:
+    case ')':
+      return builder.ToRegExp();
+    case '|': {
+      Advance();
+      builder.NewAlternative();
+      int capture_new_alt_start_index = captures_started();
+      for (int i = capture_start_index; i < capture_new_alt_start_index; i++) {
+        RegExpCapture* capture = captures_->at(i);
+        if (capture->available() == CAPTURE_AVAILABLE) {
+          capture->set_available(CAPTURE_UNREACHABLE);
+        }
+      }
+      capture_start_index = capture_new_alt_start_index;
+      continue;
+    }
+    case '*':
+    case '+':
+    case '?':
+      ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
+    case '^': {
+      Advance();
+      if (multiline_) {
+        builder.AddAssertion(
+            new RegExpAssertion(RegExpAssertion::START_OF_LINE));
+      } else {
+        builder.AddAssertion(
+            new RegExpAssertion(RegExpAssertion::START_OF_INPUT));
+        set_contains_anchor();
+      }
+      continue;
+    }
+    case '$': {
+      Advance();
+      RegExpAssertion::Type type =
+          multiline_ ? RegExpAssertion::END_OF_LINE :
+                       RegExpAssertion::END_OF_INPUT;
+      builder.AddAssertion(new RegExpAssertion(type));
+      continue;
+    }
+    case '.': {
+      Advance();
+      // everything except \x0a, \x0d, \u2028 and \u2029
+      ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
+      CharacterRange::AddClassEscape('.', ranges);
+      RegExpTree* atom = new RegExpCharacterClass(ranges, false);
+      builder.AddAtom(atom);
+      break;
+    }
+    case '(': {
+      RegExpTree* atom = ParseGroup(CHECK_FAILED);
+      builder.AddAtom(atom);
+      break;
+    }
+    case '[': {
+      RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
+      builder.AddAtom(atom);
+      break;
+    }
+    // Atom ::
+    //   \ AtomEscape
+    case '\\':
+      switch (Next()) {
+      case kEndMarker:
+        ReportError(CStrVector("\\ at end of pattern") CHECK_FAILED);
+      case 'b':
+        Advance(2);
+        builder.AddAssertion(
+            new RegExpAssertion(RegExpAssertion::BOUNDARY));
+        continue;
+      case 'B':
+        Advance(2);
+        builder.AddAssertion(
+            new RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
+        continue;
+        // AtomEscape ::
+        //   CharacterClassEscape
+        //
+        // CharacterClassEscape :: one of
+        //   d D s S w W
+      case 'd': case 'D': case 's': case 'S': case 'w': case 'W': {
+        uc32 c = Next();
+        Advance(2);
+        ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
+        CharacterRange::AddClassEscape(c, ranges);
+        RegExpTree* atom = new RegExpCharacterClass(ranges, false);
+        builder.AddAtom(atom);
+        goto has_read_atom;  // Avoid setting has_character_escapes_.
+      }
+      case '1': case '2': case '3': case '4': case '5': case '6':
+      case '7': case '8': case '9': {
+        int index = 0;
+        if (ParseBackReferenceIndex(&index)) {
+          if (!CaptureAvailable(index - 1)) {
+            // Prepare to ignore a following quantifier
+            builder.AddEmpty();
+            goto has_read_atom;
+          }
+          RegExpCapture* capture = captures_->at(index - 1);
+          RegExpTree* atom = new RegExpBackReference(capture);
+          builder.AddAtom(atom);
+          goto has_read_atom;  // Avoid setting has_character_escapes_.
+        }
+        uc32 first_digit = Next();
+        if (first_digit == '8' || first_digit == '9') {
+          // Treat as identity escape
+          builder.AddCharacter(first_digit);
+          Advance(2);
+          break;
+        }
+      }
+      // FALLTHROUGH
+      case '0': {
+        Advance();
+        uc32 octal = ParseOctalLiteral();
+        builder.AddCharacter(octal);
+        break;
+      }
+      // ControlEscape :: one of
+      //   f n r t v
+      case 'f':
+        Advance(2);
+        builder.AddCharacter('\f');
+        break;
+      case 'n':
+        Advance(2);
+        builder.AddCharacter('\n');
+        break;
+      case 'r':
+        Advance(2);
+        builder.AddCharacter('\r');
+        break;
+      case 't':
+        Advance(2);
+        builder.AddCharacter('\t');
+        break;
+      case 'v':
+        Advance(2);
+        builder.AddCharacter('\v');
+        break;
+      case 'c': {
+        Advance(2);
+        uc32 control = ParseControlLetterEscape();
+        builder.AddCharacter(control);
+        break;
+      }
+      case 'x': {
+        Advance(2);
+        uc32 value;
+        if (ParseHexEscape(2, &value)) {
+          builder.AddCharacter(value);
+        } else {
+          builder.AddCharacter('x');
+        }
+        break;
+      }
+      case 'u': {
+        Advance(2);
+        uc32 value;
+        if (ParseHexEscape(4, &value)) {
+          builder.AddCharacter(value);
+        } else {
+          builder.AddCharacter('u');
+        }
+        break;
+      }
+      default:
+        // Identity escape.
+        builder.AddCharacter(Next());
+        Advance(2);
+        break;
+      }
+      break;
+    case '{': {
+      int dummy;
+      if (ParseIntervalQuantifier(&dummy, &dummy)) {
+        ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
+      }
+      // fallthrough
+    }
+    default:
+      builder.AddCharacter(current());
+      Advance();
+      break;
+    }  // end switch(current())
+
+   has_read_atom:
+    int min;
+    int max;
+    switch (current()) {
+    // QuantifierPrefix ::
+    //   *
+    //   +
+    //   ?
+    //   {
+    case '*':
+      min = 0;
+      max = RegExpTree::kInfinity;
+      Advance();
+      break;
+    case '+':
+      min = 1;
+      max = RegExpTree::kInfinity;
+      Advance();
+      break;
+    case '?':
+      min = 0;
+      max = 1;
+      Advance();
+      break;
+    case '{':
+      if (ParseIntervalQuantifier(&min, &max)) {
+        if (max < min) {
+          ReportError(CStrVector("numbers out of order in {} quantifier.")
+                      CHECK_FAILED);
+        }
+        break;
+      } else {
+        continue;
+      }
+    default:
+      continue;
+    }
+    bool is_greedy = true;
+    if (current() == '?') {
+      is_greedy = false;
+      Advance();
+    }
+    builder.AddQuantifierToAtom(min, max, is_greedy);
+  }
+}
+
+class SourceCharacter {
+ public:
+  static bool Is(uc32 c) {
+    switch (c) {
+      // case ']': case '}':
+      // In spidermonkey and jsc these are treated as source characters
+      // so we do too.
+      case '^': case '$': case '\\': case '.': case '*': case '+':
+      case '?': case '(': case ')': case '[': case '{': case '|':
+      case RegExpParser::kEndMarker:
+        return false;
+      default:
+        return true;
+    }
+  }
+};
+
+
+static unibrow::Predicate<SourceCharacter> source_character;
+
+
+static inline bool IsSourceCharacter(uc32 c) {
+  return source_character.get(c);
+}
+
+#ifdef DEBUG
+// Currently only used in an ASSERT.
+static bool IsSpecialClassEscape(uc32 c) {
+  switch (c) {
+    case 'd': case 'D':
+    case 's': case 'S':
+    case 'w': case 'W':
+      return true;
+    default:
+      return false;
+  }
+}
+#endif
+
+
+// In order to know whether an escape is a backreference or not we have to scan
+// the entire regexp and find the number of capturing parentheses.  However we
+// don't want to scan the regexp twice unless it is necessary.  This mini-parser
+// is called when needed.  It can see the difference between capturing and
+// noncapturing parentheses and can skip character classes and backslash-escaped
+// characters.
+void RegExpParser::ScanForCaptures() {
+  // Start with captures started previous to current position
+  int capture_count = captures_started();
+  // Add count of captures after this position.
+  int n;
+  while ((n = current()) != kEndMarker) {
+    Advance();
+    switch (n) {
+      case '\\':
+        Advance();
+        break;
+      case '[': {
+        int c;
+        while ((c = current()) != kEndMarker) {
+          Advance();
+          if (c == '\\') {
+            Advance();
+          } else {
+            if (c == ']') break;
+          }
+        }
+        break;
+      }
+      case '(':
+        if (current() != '?') capture_count++;
+        break;
+    }
+  }
+  capture_count_ = capture_count;
+  is_scanned_for_captures_ = true;
+}
+
+
+bool RegExpParser::ParseBackReferenceIndex(int* index_out) {
+  ASSERT_EQ('\\', current());
+  ASSERT('1' <= Next() && Next() <= '9');
+  // Try to parse a decimal literal that is no greater than the total number
+  // of left capturing parentheses in the input.
+  int start = position();
+  int value = Next() - '0';
+  Advance(2);
+  while (true) {
+    uc32 c = current();
+    if (IsDecimalDigit(c)) {
+      value = 10 * value + (c - '0');
+      if (value > kMaxCaptures) {
+        Reset(start);
+        return false;
+      }
+      Advance();
+    } else {
+      break;
+    }
+  }
+  if (value > captures_started()) {
+    if (!is_scanned_for_captures_) {
+      int saved_position = position();
+      ScanForCaptures();
+      Reset(saved_position);
+    }
+    if (value > capture_count_) {
+      Reset(start);
+      return false;
+    }
+  }
+  *index_out = value;
+  return true;
+}
+
+
+// QuantifierPrefix ::
+//   { DecimalDigits }
+//   { DecimalDigits , }
+//   { DecimalDigits , DecimalDigits }
+//
+// Returns true if parsing succeeds, and set the min_out and max_out
+// values. Values are truncated to RegExpTree::kInfinity if they overflow.
+bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
+  ASSERT_EQ(current(), '{');
+  int start = position();
+  Advance();
+  int min = 0;
+  if (!IsDecimalDigit(current())) {
+    Reset(start);
+    return false;
+  }
+  while (IsDecimalDigit(current())) {
+    int next = current() - '0';
+    if (min > (RegExpTree::kInfinity - next) / 10) {
+      // Overflow. Skip past remaining decimal digits and return -1.
+      do {
+        Advance();
+      } while (IsDecimalDigit(current()));
+      min = RegExpTree::kInfinity;
+      break;
+    }
+    min = 10 * min + next;
+    Advance();
+  }
+  int max = 0;
+  if (current() == '}') {
+    max = min;
+    Advance();
+  } else if (current() == ',') {
+    Advance();
+    if (current() == '}') {
+      max = RegExpTree::kInfinity;
+      Advance();
+    } else {
+      while (IsDecimalDigit(current())) {
+        int next = current() - '0';
+        if (max > (RegExpTree::kInfinity - next) / 10) {
+          do {
+            Advance();
+          } while (IsDecimalDigit(current()));
+          max = RegExpTree::kInfinity;
+          break;
+        }
+        max = 10 * max + next;
+        Advance();
+      }
+      if (current() != '}') {
+        Reset(start);
+        return false;
+      }
+      Advance();
+    }
+  } else {
+    Reset(start);
+    return false;
+  }
+  *min_out = min;
+  *max_out = max;
+  return true;
+}
+
+
+// Upper and lower case letters differ by one bit.
+STATIC_CHECK(('a' ^ 'A') == 0x20);
+
+uc32 RegExpParser::ParseControlLetterEscape() {
+  if (!has_more())
+    return 'c';
+  uc32 letter = current() & ~(0x20);  // Collapse upper and lower case letters.
+  if (letter < 'A' || 'Z' < letter) {
+    // Non-spec error-correction: "\c" followed by non-control letter is
+    // interpreted as an IdentityEscape of 'c'.
+    return 'c';
+  }
+  Advance();
+  return letter & 0x1f;  // Remainder modulo 32, per specification.
+}
+
+
+uc32 RegExpParser::ParseOctalLiteral() {
+  ASSERT('0' <= current() && current() <= '7');
+  // For compatibility with some other browsers (not all), we parse
+  // up to three octal digits with a value below 256.
+  uc32 value = current() - '0';
+  Advance();
+  if ('0' <= current() && current() <= '7') {
+    value = value * 8 + current() - '0';
+    Advance();
+    if (value < 32 && '0' <= current() && current() <= '7') {
+      value = value * 8 + current() - '0';
+      Advance();
+    }
+  }
+  return value;
+}
+
+
+bool RegExpParser::ParseHexEscape(int length, uc32 *value) {
+  int start = position();
+  uc32 val = 0;
+  bool done = false;
+  for (int i = 0; !done; i++) {
+    uc32 c = current();
+    int d = HexValue(c);
+    if (d < 0) {
+      Reset(start);
+      return false;
+    }
+    val = val * 16 + d;
+    Advance();
+    if (i == length - 1) {
+      done = true;
+    }
+  }
+  *value = val;
+  return true;
+}
+
+
+uc32 RegExpParser::ParseClassCharacterEscape() {
+  ASSERT(current() == '\\');
+  ASSERT(has_next() && !IsSpecialClassEscape(Next()));
+  Advance();
+  switch (current()) {
+    case 'b':
+      Advance();
+      return '\b';
+    // ControlEscape :: one of
+    //   f n r t v
+    case 'f':
+      Advance();
+      return '\f';
+    case 'n':
+      Advance();
+      return '\n';
+    case 'r':
+      Advance();
+      return '\r';
+    case 't':
+      Advance();
+      return '\t';
+    case 'v':
+      Advance();
+      return '\v';
+    case 'c':
+      Advance();
+      return ParseControlLetterEscape();
+    case '0': case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7':
+      // For compatibility, we interpret a decimal escape that isn't
+      // a back reference (and therefore either \0 or not valid according
+      // to the specification) as a 1..3 digit octal character code.
+      return ParseOctalLiteral();
+    case 'x': {
+      Advance();
+      uc32 value;
+      if (ParseHexEscape(2, &value)) {
+        return value;
+      }
+      // If \x is not followed by a two-digit hexadecimal, treat it
+      // as an identity escape.
+      return 'x';
+    }
+    case 'u': {
+      Advance();
+      uc32 value;
+      if (ParseHexEscape(4, &value)) {
+        return value;
+      }
+      // If \u is not followed by a four-digit hexadecimal, treat it
+      // as an identity escape.
+      return 'u';
+    }
+    default: {
+      // Extended identity escape. We accept any character that hasn't
+      // been matched by a more specific case, not just the subset required
+      // by the ECMAScript specification.
+      uc32 result = current();
+      Advance();
+      return result;
+    }
+  }
+  return 0;
+}
+
+
+RegExpTree* RegExpParser::ParseGroup() {
+  ASSERT_EQ(current(), '(');
+  char type = '(';
+  Advance();
+  if (current() == '?') {
+    switch (Next()) {
+      case ':': case '=': case '!':
+        type = Next();
+        Advance(2);
+        break;
+      default:
+        ReportError(CStrVector("Invalid group") CHECK_FAILED);
+        break;
+    }
+  } else {
+    if (captures_ == NULL) {
+      captures_ = new ZoneList<RegExpCapture*>(2);
+    }
+    if (captures_started() >= kMaxCaptures) {
+      ReportError(CStrVector("Too many captures") CHECK_FAILED);
+    }
+    captures_->Add(NULL);
+  }
+  int capture_index = captures_started();
+  RegExpTree* body = ParseDisjunction(CHECK_FAILED);
+  if (current() != ')') {
+    ReportError(CStrVector("Unterminated group") CHECK_FAILED);
+  }
+  Advance();
+
+  int end_capture_index = captures_started();
+  if (type == '!') {
+    // Captures inside a negative lookahead are never available outside it.
+    for (int i = capture_index; i < end_capture_index; i++) {
+      RegExpCapture* capture = captures_->at(i);
+      ASSERT(capture != NULL);
+      capture->set_available(CAPTURE_PERMANENTLY_UNREACHABLE);
+    }
+  } else {
+    // Captures temporarily unavailable because they are in different
+    // alternatives are all available after the disjunction.
+    for (int i = capture_index; i < end_capture_index; i++) {
+      RegExpCapture* capture = captures_->at(i);
+      ASSERT(capture != NULL);
+      if (capture->available() == CAPTURE_UNREACHABLE) {
+        capture->set_available(CAPTURE_AVAILABLE);
+      }
+    }
+  }
+
+  if (type == '(') {
+    RegExpCapture* capture = new RegExpCapture(body, capture_index);
+    captures_->at(capture_index - 1) = capture;
+    return capture;
+  } else if (type == ':') {
+    return body;
+  } else {
+    ASSERT(type == '=' || type == '!');
+    bool is_positive = (type == '=');
+    return new RegExpLookahead(body,
+                               is_positive,
+                               end_capture_index - capture_index,
+                               capture_index);
+  }
+}
+
+
+CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) {
+  ASSERT_EQ(0, *char_class);
+  uc32 first = current();
+  if (first == '\\') {
+    switch (Next()) {
+      case 'w': case 'W': case 'd': case 'D': case 's': case 'S': {
+        *char_class = Next();
+        Advance(2);
+        return CharacterRange::Singleton(0);  // Return dummy value.
+      }
+      case kEndMarker:
+        ReportError(CStrVector("\\ at end of pattern") CHECK_FAILED);
+      default:
+        uc32 c = ParseClassCharacterEscape(CHECK_FAILED);
+        return CharacterRange::Singleton(c);
+    }
+  } else {
+    Advance();
+    return CharacterRange::Singleton(first);
+  }
+}
+
+
+RegExpTree* RegExpParser::ParseCharacterClass() {
+  static const char* kUnterminated = "Unterminated character class";
+  static const char* kRangeOutOfOrder = "Range out of order in character class";
+
+  ASSERT_EQ(current(), '[');
+  Advance();
+  bool is_negated = false;
+  if (current() == '^') {
+    is_negated = true;
+    Advance();
+  }
+  ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
+  while (has_more() && current() != ']') {
+    uc16 char_class = 0;
+    CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED);
+    if (char_class) {
+      CharacterRange::AddClassEscape(char_class, ranges);
+      continue;
+    }
+    if (current() == '-') {
+      Advance();
+      if (current() == kEndMarker) {
+        // If we reach the end we break out of the loop and let the
+        // following code report an error.
+        break;
+      } else if (current() == ']') {
+        ranges->Add(first);
+        ranges->Add(CharacterRange::Singleton('-'));
+        break;
+      }
+      CharacterRange next = ParseClassAtom(&char_class CHECK_FAILED);
+      if (char_class) {
+        ranges->Add(first);
+        ranges->Add(CharacterRange::Singleton('-'));
+        CharacterRange::AddClassEscape(char_class, ranges);
+        continue;
+      }
+      if (first.from() > next.to()) {
+        return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED);
+      }
+      ranges->Add(CharacterRange::Range(first.from(), next.to()));
+    } else {
+      ranges->Add(first);
+    }
+  }
+  if (!has_more()) {
+    return ReportError(CStrVector(kUnterminated) CHECK_FAILED);
+  }
+  Advance();
+  if (ranges->length() == 0) {
+    ranges->Add(CharacterRange::Everything());
+    is_negated = !is_negated;
+  }
+  return new RegExpCharacterClass(ranges, is_negated);
+}
+
+
+// ----------------------------------------------------------------------------
+// The Parser interface.
+
+// MakeAST() is just a wrapper for the corresponding Parser calls
+// so we don't have to expose the entire Parser class in the .h file.
+
+static bool always_allow_natives_syntax = false;
+
+
+ParserMessage::~ParserMessage() {
+  for (int i = 0; i < args().length(); i++)
+    DeleteArray(args()[i]);
+  DeleteArray(args().start());
+}
+
+
+ScriptDataImpl::~ScriptDataImpl() {
+  store_.Dispose();
+}
+
+
+int ScriptDataImpl::Length() {
+  return store_.length();
+}
+
+
+unsigned* ScriptDataImpl::Data() {
+  return store_.start();
+}
+
+
+ScriptDataImpl* PreParse(unibrow::CharacterStream* stream,
+                         v8::Extension* extension) {
+  Handle<Script> no_script;
+  bool allow_natives_syntax =
+      always_allow_natives_syntax ||
+      FLAG_allow_natives_syntax ||
+      Bootstrapper::IsActive();
+  PreParser parser(no_script, allow_natives_syntax, extension);
+  if (!parser.PreParseProgram(stream)) return NULL;
+  // The list owns the backing store so we need to clone the vector.
+  // That way, the result will be exactly the right size rather than
+  // the expected 50% too large.
+  Vector<unsigned> store = parser.recorder()->store()->ToVector().Clone();
+  return new ScriptDataImpl(store);
+}
+
+
+bool ParseRegExp(FlatStringReader* input,
+                 bool multiline,
+                 RegExpCompileData* result) {
+  ASSERT(result != NULL);
+  // Make sure we have a stack guard.
+  StackGuard guard;
+  RegExpParser parser(input, &result->error, multiline);
+  RegExpTree* tree = parser.ParsePattern();
+  if (parser.failed()) {
+    ASSERT(tree == NULL);
+    ASSERT(!result->error.is_null());
+  } else {
+    ASSERT(tree != NULL);
+    ASSERT(result->error.is_null());
+    result->tree = tree;
+    int capture_count = parser.captures_started();
+    result->simple = tree->IsAtom() && parser.simple() && capture_count == 0;
+    result->contains_anchor = parser.contains_anchor();
+    result->capture_count = capture_count;
+  }
+  return !parser.failed();
+}
+
+
+FunctionLiteral* MakeAST(bool compile_in_global_context,
+                         Handle<Script> script,
+                         v8::Extension* extension,
+                         ScriptDataImpl* pre_data) {
+  bool allow_natives_syntax =
+      always_allow_natives_syntax ||
+      FLAG_allow_natives_syntax ||
+      Bootstrapper::IsActive();
+  AstBuildingParser parser(script, allow_natives_syntax, extension, pre_data);
+  if (pre_data != NULL && pre_data->has_error()) {
+    Scanner::Location loc = pre_data->MessageLocation();
+    const char* message = pre_data->BuildMessage();
+    Vector<const char*> args = pre_data->BuildArgs();
+    parser.ReportMessageAt(loc, message, args);
+    DeleteArray(message);
+    for (int i = 0; i < args.length(); i++)
+      DeleteArray(args[i]);
+    DeleteArray(args.start());
+    return NULL;
+  }
+  Handle<String> source = Handle<String>(String::cast(script->source()));
+  SafeStringInputBuffer input(source.location());
+  FunctionLiteral* result = parser.ParseProgram(source,
+      &input, compile_in_global_context);
+  return result;
+}
+
+
+FunctionLiteral* MakeLazyAST(Handle<Script> script,
+                             Handle<String> name,
+                             int start_position,
+                             int end_position,
+                             bool is_expression) {
+  bool allow_natives_syntax_before = always_allow_natives_syntax;
+  always_allow_natives_syntax = true;
+  AstBuildingParser parser(script, true, NULL, NULL);  // always allow
+  always_allow_natives_syntax = allow_natives_syntax_before;
+  // Parse the function by pulling the function source from the script source.
+  Handle<String> script_source(String::cast(script->source()));
+  FunctionLiteral* result =
+      parser.ParseLazy(SubString(script_source, start_position, end_position),
+                       name,
+                       start_position,
+                       is_expression);
+  return result;
+}
+
+
+#undef NEW
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/parser.h b/deps/v8/src/parser.h
new file mode 100644
index 0000000..4c1401c
--- /dev/null
+++ b/deps/v8/src/parser.h
@@ -0,0 +1,200 @@
+// 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_PARSER_H_
+#define V8_PARSER_H_
+
+#include "scanner.h"
+#include "allocation.h"
+
+namespace v8 { namespace internal {
+
+
+class ParserMessage : public Malloced {
+ public:
+  ParserMessage(Scanner::Location loc, const char* message,
+                Vector<const char*> args)
+      : loc_(loc),
+        message_(message),
+        args_(args) { }
+  ~ParserMessage();
+  Scanner::Location location() { return loc_; }
+  const char* message() { return message_; }
+  Vector<const char*> args() { return args_; }
+ private:
+  Scanner::Location loc_;
+  const char* message_;
+  Vector<const char*> args_;
+};
+
+
+class FunctionEntry BASE_EMBEDDED {
+ public:
+  explicit FunctionEntry(Vector<unsigned> backing) : backing_(backing) { }
+  FunctionEntry() : backing_(Vector<unsigned>::empty()) { }
+
+  int start_pos() { return backing_[kStartPosOffset]; }
+  void set_start_pos(int value) { backing_[kStartPosOffset] = value; }
+
+  int end_pos() { return backing_[kEndPosOffset]; }
+  void set_end_pos(int value) { backing_[kEndPosOffset] = value; }
+
+  int literal_count() { return backing_[kLiteralCountOffset]; }
+  void set_literal_count(int value) { backing_[kLiteralCountOffset] = value; }
+
+  int property_count() { return backing_[kPropertyCountOffset]; }
+  void set_property_count(int value) { backing_[kPropertyCountOffset] = value; }
+
+  bool contains_array_literal() {
+    return backing_[kContainsArrayLiteralOffset] != 0;
+  }
+  void set_contains_array_literal(bool value) {
+    backing_[kContainsArrayLiteralOffset] = value ? 1 : 0;
+  }
+
+  bool is_valid() { return backing_.length() > 0; }
+
+  static const int kSize = 5;
+
+ private:
+  Vector<unsigned> backing_;
+  static const int kStartPosOffset = 0;
+  static const int kEndPosOffset = 1;
+  static const int kLiteralCountOffset = 2;
+  static const int kPropertyCountOffset = 3;
+  static const int kContainsArrayLiteralOffset = 4;
+};
+
+
+class ScriptDataImpl : public ScriptData {
+ public:
+  explicit ScriptDataImpl(Vector<unsigned> store)
+      : store_(store),
+        last_entry_(0) { }
+  virtual ~ScriptDataImpl();
+  virtual int Length();
+  virtual unsigned* Data();
+  FunctionEntry GetFunctionEnd(int start);
+  bool SanityCheck();
+
+  Scanner::Location MessageLocation();
+  const char* BuildMessage();
+  Vector<const char*> BuildArgs();
+
+  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 = 1;
+
+  static const unsigned kMagicOffset = 0;
+  static const unsigned kVersionOffset = 1;
+  static const unsigned kHasErrorOffset = 2;
+  static const unsigned kSizeOffset = 3;
+  static const unsigned kHeaderSize = 4;
+
+ private:
+  unsigned Read(int position);
+  unsigned* ReadAddress(int position);
+  int EntryCount();
+  FunctionEntry nth(int n);
+
+  Vector<unsigned> store_;
+
+  // The last entry returned.  This is used to make lookup faster:
+  // the next entry to return is typically the next entry so lookup
+  // will usually be much faster if we start from the last entry.
+  int last_entry_;
+};
+
+
+// The parser: Takes a script and and context information, and builds a
+// FunctionLiteral AST node. Returns NULL and deallocates any allocated
+// AST nodes if parsing failed.
+FunctionLiteral* MakeAST(bool compile_in_global_context,
+                         Handle<Script> script,
+                         v8::Extension* extension,
+                         ScriptDataImpl* pre_data);
+
+
+ScriptDataImpl* PreParse(unibrow::CharacterStream* stream,
+                         v8::Extension* extension);
+
+
+bool ParseRegExp(FlatStringReader* input,
+                 bool multiline,
+                 RegExpCompileData* result);
+
+
+// Support for doing lazy compilation. The script is the script containing full
+// source of the script where the function is declared. The start_position and
+// end_position specifies the part of the script source which has the source
+// for the function declaration in the form:
+//
+//    (<formal parameters>) { <function body> }
+//
+// without any function keyword or name.
+//
+FunctionLiteral* MakeLazyAST(Handle<Script> script,
+                             Handle<String> name,
+                             int start_position,
+                             int end_position,
+                             bool is_expression);
+
+
+// Support for handling complex values (array and object literals) that
+// can be fully handled at compile time.
+class CompileTimeValue: public AllStatic {
+ public:
+  enum Type {
+    OBJECT_LITERAL,
+    ARRAY_LITERAL
+  };
+
+  static bool IsCompileTimeValue(Expression* expression);
+
+  // Get the value as a compile time value.
+  static Handle<FixedArray> GetValue(Expression* expression);
+
+  // Get the type of a compile time value returned by GetValue().
+  static Type GetType(Handle<FixedArray> value);
+
+  // Get the elements array of a compile time value returned by GetValue().
+  static Handle<FixedArray> GetElements(Handle<FixedArray> value);
+
+ private:
+  static const int kTypeSlot = 0;
+  static const int kElementsSlot = 1;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(CompileTimeValue);
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_PARSER_H_
diff --git a/deps/v8/src/platform-freebsd.cc b/deps/v8/src/platform-freebsd.cc
new file mode 100644
index 0000000..9209990
--- /dev/null
+++ b/deps/v8/src/platform-freebsd.cc
@@ -0,0 +1,639 @@
+// 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.
+
+// Platform specific code for FreeBSD goes here. For the POSIX comaptible parts
+// the implementation is in platform-posix.cc.
+
+#include <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <stdlib.h>
+
+#include <sys/types.h>  // mmap & munmap
+#include <sys/mman.h>   // mmap & munmap
+#include <sys/stat.h>   // open
+#include <sys/fcntl.h>  // open
+#include <unistd.h>     // getpagesize
+#include <execinfo.h>   // backtrace, backtrace_symbols
+#include <strings.h>    // index
+#include <errno.h>
+#include <stdarg.h>
+#include <limits.h>
+
+#undef MAP_TYPE
+
+#include "v8.h"
+
+#include "platform.h"
+
+
+namespace v8 { namespace internal {
+
+// 0 is never a valid thread id on FreeBSD since tids and pids share a
+// name space and pid 0 is used to kill the group (see man 2 kill).
+static const pthread_t kNoThread = (pthread_t) 0;
+
+
+double ceiling(double x) {
+    // Correct as on OS X
+    if (-1.0 < x && x < 0.0) {
+        return -0.0;
+    } else {
+        return ceil(x);
+    }
+}
+
+
+void OS::Setup() {
+  // Seed the random number generator.
+  // Convert the current time to a 64-bit integer first, before converting it
+  // to an unsigned. Going directly can cause an overflow and the seed to be
+  // set to all ones. The seed will be identical for different instances that
+  // call this setup code within the same millisecond.
+  uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
+  srandom(static_cast<unsigned int>(seed));
+}
+
+
+double OS::nan_value() {
+  return NAN;
+}
+
+
+int OS::ActivationFrameAlignment() {
+  // 16 byte alignment on FreeBSD
+  return 16;
+}
+
+
+// We keep the lowest and highest addresses mapped as a quick way of
+// determining that pointers are outside the heap (used mostly in assertions
+// and verification).  The estimate is conservative, ie, not all addresses in
+// 'allocated' space are actually allocated to our heap.  The range is
+// [lowest, highest), inclusive on the low and and exclusive on the high end.
+static void* lowest_ever_allocated = reinterpret_cast<void*>(-1);
+static void* highest_ever_allocated = reinterpret_cast<void*>(0);
+
+
+static void UpdateAllocatedSpaceLimits(void* address, int size) {
+  lowest_ever_allocated = Min(lowest_ever_allocated, address);
+  highest_ever_allocated =
+      Max(highest_ever_allocated,
+          reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));
+}
+
+
+bool OS::IsOutsideAllocatedSpace(void* address) {
+  return address < lowest_ever_allocated || address >= highest_ever_allocated;
+}
+
+
+size_t OS::AllocateAlignment() {
+  return getpagesize();
+}
+
+
+void* OS::Allocate(const size_t requested,
+                   size_t* allocated,
+                   bool executable) {
+  const size_t msize = RoundUp(requested, getpagesize());
+  int prot = PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0);
+  void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
+
+  if (mbase == MAP_FAILED) {
+    LOG(StringEvent("OS::Allocate", "mmap failed"));
+    return NULL;
+  }
+  *allocated = msize;
+  UpdateAllocatedSpaceLimits(mbase, msize);
+  return mbase;
+}
+
+
+void OS::Free(void* buf, const size_t length) {
+  // TODO(1240712): munmap has a return value which is ignored here.
+  munmap(buf, length);
+}
+
+
+#ifdef ENABLE_HEAP_PROTECTION
+
+void OS::Protect(void* address, size_t size) {
+  UNIMPLEMENTED();
+}
+
+
+void OS::Unprotect(void* address, size_t size, bool is_executable) {
+  UNIMPLEMENTED();
+}
+
+#endif
+
+
+void OS::Sleep(int milliseconds) {
+  unsigned int ms = static_cast<unsigned int>(milliseconds);
+  usleep(1000 * ms);
+}
+
+
+void OS::Abort() {
+  // Redirect to std abort to signal abnormal program termination.
+  abort();
+}
+
+
+void OS::DebugBreak() {
+#if defined (__arm__) || defined(__thumb__)
+  asm("bkpt 0");
+#else
+  asm("int $3");
+#endif
+}
+
+
+class PosixMemoryMappedFile : public OS::MemoryMappedFile {
+ public:
+  PosixMemoryMappedFile(FILE* file, void* memory, int size)
+    : file_(file), memory_(memory), size_(size) { }
+  virtual ~PosixMemoryMappedFile();
+  virtual void* memory() { return memory_; }
+ private:
+  FILE* file_;
+  void* memory_;
+  int size_;
+};
+
+
+OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
+    void* initial) {
+  FILE* file = fopen(name, "w+");
+  if (file == NULL) return NULL;
+  int result = fwrite(initial, size, 1, file);
+  if (result < 1) {
+    fclose(file);
+    return NULL;
+  }
+  void* memory =
+      mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
+  return new PosixMemoryMappedFile(file, memory, size);
+}
+
+
+PosixMemoryMappedFile::~PosixMemoryMappedFile() {
+  if (memory_) munmap(memory_, size_);
+  fclose(file_);
+}
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+static unsigned StringToLong(char* buffer) {
+  return static_cast<unsigned>(strtol(buffer, NULL, 16));  // NOLINT
+}
+#endif
+
+
+void OS::LogSharedLibraryAddresses() {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  static const int MAP_LENGTH = 1024;
+  int fd = open("/proc/self/maps", O_RDONLY);
+  if (fd < 0) return;
+  while (true) {
+    char addr_buffer[11];
+    addr_buffer[0] = '0';
+    addr_buffer[1] = 'x';
+    addr_buffer[10] = 0;
+    int result = read(fd, addr_buffer + 2, 8);
+    if (result < 8) break;
+    unsigned start = StringToLong(addr_buffer);
+    result = read(fd, addr_buffer + 2, 1);
+    if (result < 1) break;
+    if (addr_buffer[2] != '-') break;
+    result = read(fd, addr_buffer + 2, 8);
+    if (result < 8) break;
+    unsigned end = StringToLong(addr_buffer);
+    char buffer[MAP_LENGTH];
+    int bytes_read = -1;
+    do {
+      bytes_read++;
+      if (bytes_read >= MAP_LENGTH - 1)
+        break;
+      result = read(fd, buffer + bytes_read, 1);
+      if (result < 1) break;
+    } while (buffer[bytes_read] != '\n');
+    buffer[bytes_read] = 0;
+    // Ignore mappings that are not executable.
+    if (buffer[3] != 'x') continue;
+    char* start_of_path = index(buffer, '/');
+    // There may be no filename in this line.  Skip to next.
+    if (start_of_path == NULL) continue;
+    buffer[bytes_read] = 0;
+    LOG(SharedLibraryEvent(start_of_path, start, end));
+  }
+  close(fd);
+#endif
+}
+
+
+int OS::StackWalk(OS::StackFrame* frames, int frames_size) {
+  void** addresses = NewArray<void*>(frames_size);
+
+  int frames_count = backtrace(addresses, frames_size);
+
+  char** symbols;
+  symbols = backtrace_symbols(addresses, frames_count);
+  if (symbols == NULL) {
+    DeleteArray(addresses);
+    return kStackWalkError;
+  }
+
+  for (int i = 0; i < frames_count; i++) {
+    frames[i].address = addresses[i];
+    // Format a text representation of the frame based on the information
+    // available.
+    SNPrintF(MutableCStrVector(frames[i].text, kStackWalkMaxTextLen),
+             "%s",
+             symbols[i]);
+    // Make sure line termination is in place.
+    frames[i].text[kStackWalkMaxTextLen - 1] = '\0';
+  }
+
+  DeleteArray(addresses);
+  free(symbols);
+
+  return frames_count;
+}
+
+
+// Constants used for mmap.
+static const int kMmapFd = -1;
+static const int kMmapFdOffset = 0;
+
+
+VirtualMemory::VirtualMemory(size_t size) {
+  address_ = mmap(NULL, size, PROT_NONE,
+                  MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
+                  kMmapFd, kMmapFdOffset);
+  size_ = size;
+}
+
+
+VirtualMemory::~VirtualMemory() {
+  if (IsReserved()) {
+    if (0 == munmap(address(), size())) address_ = MAP_FAILED;
+  }
+}
+
+
+bool VirtualMemory::IsReserved() {
+  return address_ != MAP_FAILED;
+}
+
+
+bool VirtualMemory::Commit(void* address, size_t size, bool executable) {
+  int prot = PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0);
+  if (MAP_FAILED == mmap(address, size, prot,
+                         MAP_PRIVATE | MAP_ANON | MAP_FIXED,
+                         kMmapFd, kMmapFdOffset)) {
+    return false;
+  }
+
+  UpdateAllocatedSpaceLimits(address, size);
+  return true;
+}
+
+
+bool VirtualMemory::Uncommit(void* address, size_t size) {
+  return mmap(address, size, PROT_NONE,
+              MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
+              kMmapFd, kMmapFdOffset) != MAP_FAILED;
+}
+
+
+class ThreadHandle::PlatformData : public Malloced {
+ public:
+  explicit PlatformData(ThreadHandle::Kind kind) {
+    Initialize(kind);
+  }
+
+  void Initialize(ThreadHandle::Kind kind) {
+    switch (kind) {
+      case ThreadHandle::SELF: thread_ = pthread_self(); break;
+      case ThreadHandle::INVALID: thread_ = kNoThread; break;
+    }
+  }
+  pthread_t thread_;  // Thread handle for pthread.
+};
+
+
+ThreadHandle::ThreadHandle(Kind kind) {
+  data_ = new PlatformData(kind);
+}
+
+
+void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
+  data_->Initialize(kind);
+}
+
+
+ThreadHandle::~ThreadHandle() {
+  delete data_;
+}
+
+
+bool ThreadHandle::IsSelf() const {
+  return pthread_equal(data_->thread_, pthread_self());
+}
+
+
+bool ThreadHandle::IsValid() const {
+  return data_->thread_ != kNoThread;
+}
+
+
+Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
+}
+
+
+Thread::~Thread() {
+}
+
+
+static void* ThreadEntry(void* arg) {
+  Thread* thread = reinterpret_cast<Thread*>(arg);
+  // This is also initialized by the first argument to pthread_create() but we
+  // don't know which thread will run first (the original thread or the new
+  // one) so we initialize it here too.
+  thread->thread_handle_data()->thread_ = pthread_self();
+  ASSERT(thread->IsValid());
+  thread->Run();
+  return NULL;
+}
+
+
+void Thread::Start() {
+  pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this);
+  ASSERT(IsValid());
+}
+
+
+void Thread::Join() {
+  pthread_join(thread_handle_data()->thread_, NULL);
+}
+
+
+Thread::LocalStorageKey Thread::CreateThreadLocalKey() {
+  pthread_key_t key;
+  int result = pthread_key_create(&key, NULL);
+  USE(result);
+  ASSERT(result == 0);
+  return static_cast<LocalStorageKey>(key);
+}
+
+
+void Thread::DeleteThreadLocalKey(LocalStorageKey key) {
+  pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
+  int result = pthread_key_delete(pthread_key);
+  USE(result);
+  ASSERT(result == 0);
+}
+
+
+void* Thread::GetThreadLocal(LocalStorageKey key) {
+  pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
+  return pthread_getspecific(pthread_key);
+}
+
+
+void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
+  pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
+  pthread_setspecific(pthread_key, value);
+}
+
+
+void Thread::YieldCPU() {
+  sched_yield();
+}
+
+
+class FreeBSDMutex : public Mutex {
+ public:
+
+  FreeBSDMutex() {
+    pthread_mutexattr_t attrs;
+    int result = pthread_mutexattr_init(&attrs);
+    ASSERT(result == 0);
+    result = pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE);
+    ASSERT(result == 0);
+    result = pthread_mutex_init(&mutex_, &attrs);
+    ASSERT(result == 0);
+  }
+
+  virtual ~FreeBSDMutex() { pthread_mutex_destroy(&mutex_); }
+
+  virtual int Lock() {
+    int result = pthread_mutex_lock(&mutex_);
+    return result;
+  }
+
+  virtual int Unlock() {
+    int result = pthread_mutex_unlock(&mutex_);
+    return result;
+  }
+
+ private:
+  pthread_mutex_t mutex_;   // Pthread mutex for POSIX platforms.
+};
+
+
+Mutex* OS::CreateMutex() {
+  return new FreeBSDMutex();
+}
+
+
+class FreeBSDSemaphore : public Semaphore {
+ public:
+  explicit FreeBSDSemaphore(int count) {  sem_init(&sem_, 0, count); }
+  virtual ~FreeBSDSemaphore() { sem_destroy(&sem_); }
+
+  virtual void Wait();
+  virtual bool Wait(int timeout);
+  virtual void Signal() { sem_post(&sem_); }
+ private:
+  sem_t sem_;
+};
+
+
+void FreeBSDSemaphore::Wait() {
+  while (true) {
+    int result = sem_wait(&sem_);
+    if (result == 0) return;  // Successfully got semaphore.
+    CHECK(result == -1 && errno == EINTR);  // Signal caused spurious wakeup.
+  }
+}
+
+
+bool FreeBSDSemaphore::Wait(int timeout) {
+  const long kOneSecondMicros = 1000000;  // NOLINT
+  const long kOneSecondNanos = 1000000000;  // NOLINT
+
+  // Split timeout into second and nanosecond parts.
+  long nanos = (timeout % kOneSecondMicros) * 1000;  // NOLINT
+  time_t secs = timeout / kOneSecondMicros;
+
+  // Get the current real time clock.
+  struct timespec ts;
+  if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
+    return false;
+  }
+
+  // Calculate realtime for end of timeout.
+  ts.tv_nsec += nanos;
+  if (ts.tv_nsec >= kOneSecondNanos) {
+    ts.tv_nsec -= kOneSecondNanos;
+    ts.tv_nsec++;
+  }
+  ts.tv_sec += secs;
+
+  // Wait for semaphore signalled or timeout.
+  while (true) {
+    int result = sem_timedwait(&sem_, &ts);
+    if (result == 0) return true;  // Successfully got semaphore.
+    if (result == -1 && errno == ETIMEDOUT) return false;  // Timeout.
+    CHECK(result == -1 && errno == EINTR);  // Signal caused spurious wakeup.
+  }
+}
+
+
+Semaphore* OS::CreateSemaphore(int count) {
+  return new FreeBSDSemaphore(count);
+}
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+
+static Sampler* active_sampler_ = NULL;
+
+static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
+  USE(info);
+  if (signal != SIGPROF) return;
+  if (active_sampler_ == NULL) return;
+
+  TickSample sample;
+
+  // If profiling, we extract the current pc and sp.
+  if (active_sampler_->IsProfiling()) {
+    // Extracting the sample from the context is extremely machine dependent.
+    ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
+    mcontext_t& mcontext = ucontext->uc_mcontext;
+#if defined (__arm__) || defined(__thumb__)
+    sample.pc = mcontext.mc_r15;
+    sample.sp = mcontext.mc_r13;
+    sample.fp = mcontext.mc_r11;
+#else
+    sample.pc = mcontext.mc_eip;
+    sample.sp = mcontext.mc_esp;
+    sample.fp = mcontext.mc_ebp;
+#endif
+  }
+
+  // We always sample the VM state.
+  sample.state = Logger::state();
+
+  active_sampler_->Tick(&sample);
+}
+
+
+class Sampler::PlatformData : public Malloced {
+ public:
+  PlatformData() {
+    signal_handler_installed_ = false;
+  }
+
+  bool signal_handler_installed_;
+  struct sigaction old_signal_handler_;
+  struct itimerval old_timer_value_;
+};
+
+
+Sampler::Sampler(int interval, bool profiling)
+    : interval_(interval), profiling_(profiling), active_(false) {
+  data_ = new PlatformData();
+}
+
+
+Sampler::~Sampler() {
+  delete data_;
+}
+
+
+void Sampler::Start() {
+  // There can only be one active sampler at the time on POSIX
+  // platforms.
+  if (active_sampler_ != NULL) return;
+
+  // Request profiling signals.
+  struct sigaction sa;
+  sa.sa_sigaction = ProfilerSignalHandler;
+  sigemptyset(&sa.sa_mask);
+  sa.sa_flags = SA_SIGINFO;
+  if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return;
+  data_->signal_handler_installed_ = true;
+
+  // Set the itimer to generate a tick for each interval.
+  itimerval itimer;
+  itimer.it_interval.tv_sec = interval_ / 1000;
+  itimer.it_interval.tv_usec = (interval_ % 1000) * 1000;
+  itimer.it_value.tv_sec = itimer.it_interval.tv_sec;
+  itimer.it_value.tv_usec = itimer.it_interval.tv_usec;
+  setitimer(ITIMER_PROF, &itimer, &data_->old_timer_value_);
+
+  // Set this sampler as the active sampler.
+  active_sampler_ = this;
+  active_ = true;
+}
+
+
+void Sampler::Stop() {
+  // Restore old signal handler
+  if (data_->signal_handler_installed_) {
+    setitimer(ITIMER_PROF, &data_->old_timer_value_, NULL);
+    sigaction(SIGPROF, &data_->old_signal_handler_, 0);
+    data_->signal_handler_installed_ = false;
+  }
+
+  // This sampler is no longer the active sampler.
+  active_sampler_ = NULL;
+  active_ = false;
+}
+
+#endif  // ENABLE_LOGGING_AND_PROFILING
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/platform-linux.cc b/deps/v8/src/platform-linux.cc
new file mode 100644
index 0000000..f9a5dea
--- /dev/null
+++ b/deps/v8/src/platform-linux.cc
@@ -0,0 +1,677 @@
+// 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.
+
+// Platform specific code for Linux goes here. For the POSIX comaptible parts
+// the implementation is in platform-posix.cc.
+
+#include <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
+// Ubuntu Dapper requires memory pages to be marked as
+// executable. Otherwise, OS raises an exception when executing code
+// in that page.
+#include <sys/types.h>  // mmap & munmap
+#include <sys/mman.h>   // mmap & munmap
+#include <sys/stat.h>   // open
+#include <fcntl.h>      // open
+#include <unistd.h>     // sysconf
+#ifdef __GLIBC__
+#include <execinfo.h>   // backtrace, backtrace_symbols
+#endif  // def __GLIBC__
+#include <strings.h>    // index
+#include <errno.h>
+#include <stdarg.h>
+
+#undef MAP_TYPE
+
+#include "v8.h"
+
+#include "platform.h"
+
+
+namespace v8 { namespace internal {
+
+// 0 is never a valid thread id on Linux since tids and pids share a
+// name space and pid 0 is reserved (see man 2 kill).
+static const pthread_t kNoThread = (pthread_t) 0;
+
+
+double ceiling(double x) {
+  return ceil(x);
+}
+
+
+void OS::Setup() {
+  // Seed the random number generator.
+  // Convert the current time to a 64-bit integer first, before converting it
+  // to an unsigned. Going directly can cause an overflow and the seed to be
+  // set to all ones. The seed will be identical for different instances that
+  // call this setup code within the same millisecond.
+  uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
+  srandom(static_cast<unsigned int>(seed));
+}
+
+
+double OS::nan_value() {
+  return NAN;
+}
+
+
+int OS::ActivationFrameAlignment() {
+  // Floating point code runs faster if the stack is 8-byte aligned.
+  return 8;
+}
+
+
+// We keep the lowest and highest addresses mapped as a quick way of
+// determining that pointers are outside the heap (used mostly in assertions
+// and verification).  The estimate is conservative, ie, not all addresses in
+// 'allocated' space are actually allocated to our heap.  The range is
+// [lowest, highest), inclusive on the low and and exclusive on the high end.
+static void* lowest_ever_allocated = reinterpret_cast<void*>(-1);
+static void* highest_ever_allocated = reinterpret_cast<void*>(0);
+
+
+static void UpdateAllocatedSpaceLimits(void* address, int size) {
+  lowest_ever_allocated = Min(lowest_ever_allocated, address);
+  highest_ever_allocated =
+      Max(highest_ever_allocated,
+          reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));
+}
+
+
+bool OS::IsOutsideAllocatedSpace(void* address) {
+  return address < lowest_ever_allocated || address >= highest_ever_allocated;
+}
+
+
+size_t OS::AllocateAlignment() {
+  return sysconf(_SC_PAGESIZE);
+}
+
+
+void* OS::Allocate(const size_t requested,
+                   size_t* allocated,
+                   bool is_executable) {
+  const size_t msize = RoundUp(requested, sysconf(_SC_PAGESIZE));
+  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
+  void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  if (mbase == MAP_FAILED) {
+    LOG(StringEvent("OS::Allocate", "mmap failed"));
+    return NULL;
+  }
+  *allocated = msize;
+  UpdateAllocatedSpaceLimits(mbase, msize);
+  return mbase;
+}
+
+
+void OS::Free(void* address, const size_t size) {
+  // TODO(1240712): munmap has a return value which is ignored here.
+  munmap(address, size);
+}
+
+
+#ifdef ENABLE_HEAP_PROTECTION
+
+void OS::Protect(void* address, size_t size) {
+  // TODO(1240712): mprotect has a return value which is ignored here.
+  mprotect(address, size, PROT_READ);
+}
+
+
+void OS::Unprotect(void* address, size_t size, bool is_executable) {
+  // TODO(1240712): mprotect has a return value which is ignored here.
+  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
+  mprotect(address, size, prot);
+}
+
+#endif
+
+
+void OS::Sleep(int milliseconds) {
+  unsigned int ms = static_cast<unsigned int>(milliseconds);
+  usleep(1000 * ms);
+}
+
+
+void OS::Abort() {
+  // Redirect to std abort to signal abnormal program termination.
+  abort();
+}
+
+
+void OS::DebugBreak() {
+#if defined(__arm__) || defined(__thumb__)
+  asm("bkpt 0");
+#else
+  asm("int $3");
+#endif
+}
+
+
+class PosixMemoryMappedFile : public OS::MemoryMappedFile {
+ public:
+  PosixMemoryMappedFile(FILE* file, void* memory, int size)
+    : file_(file), memory_(memory), size_(size) { }
+  virtual ~PosixMemoryMappedFile();
+  virtual void* memory() { return memory_; }
+ private:
+  FILE* file_;
+  void* memory_;
+  int size_;
+};
+
+
+OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
+    void* initial) {
+  FILE* file = fopen(name, "w+");
+  if (file == NULL) return NULL;
+  int result = fwrite(initial, size, 1, file);
+  if (result < 1) {
+    fclose(file);
+    return NULL;
+  }
+  void* memory =
+      mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
+  return new PosixMemoryMappedFile(file, memory, size);
+}
+
+
+PosixMemoryMappedFile::~PosixMemoryMappedFile() {
+  if (memory_) munmap(memory_, size_);
+  fclose(file_);
+}
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+static unsigned StringToLong(char* buffer) {
+  return static_cast<unsigned>(strtol(buffer, NULL, 16));  // NOLINT
+}
+#endif
+
+
+void OS::LogSharedLibraryAddresses() {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  static const int MAP_LENGTH = 1024;
+  int fd = open("/proc/self/maps", O_RDONLY);
+  if (fd < 0) return;
+  while (true) {
+    char addr_buffer[11];
+    addr_buffer[0] = '0';
+    addr_buffer[1] = 'x';
+    addr_buffer[10] = 0;
+    int result = read(fd, addr_buffer + 2, 8);
+    if (result < 8) break;
+    unsigned start = StringToLong(addr_buffer);
+    result = read(fd, addr_buffer + 2, 1);
+    if (result < 1) break;
+    if (addr_buffer[2] != '-') break;
+    result = read(fd, addr_buffer + 2, 8);
+    if (result < 8) break;
+    unsigned end = StringToLong(addr_buffer);
+    char buffer[MAP_LENGTH];
+    int bytes_read = -1;
+    do {
+      bytes_read++;
+      if (bytes_read >= MAP_LENGTH - 1)
+        break;
+      result = read(fd, buffer + bytes_read, 1);
+      if (result < 1) break;
+    } while (buffer[bytes_read] != '\n');
+    buffer[bytes_read] = 0;
+    // Ignore mappings that are not executable.
+    if (buffer[3] != 'x') continue;
+    char* start_of_path = index(buffer, '/');
+    // There may be no filename in this line.  Skip to next.
+    if (start_of_path == NULL) continue;
+    buffer[bytes_read] = 0;
+    LOG(SharedLibraryEvent(start_of_path, start, end));
+  }
+  close(fd);
+#endif
+}
+
+
+int OS::StackWalk(OS::StackFrame* frames, int frames_size) {
+  // backtrace is a glibc extension.
+#ifdef __GLIBC__
+  void** addresses = NewArray<void*>(frames_size);
+
+  int frames_count = backtrace(addresses, frames_size);
+
+  char** symbols;
+  symbols = backtrace_symbols(addresses, frames_count);
+  if (symbols == NULL) {
+    DeleteArray(addresses);
+    return kStackWalkError;
+  }
+
+  for (int i = 0; i < frames_count; i++) {
+    frames[i].address = addresses[i];
+    // Format a text representation of the frame based on the information
+    // available.
+    SNPrintF(MutableCStrVector(frames[i].text, kStackWalkMaxTextLen),
+             "%s",
+             symbols[i]);
+    // Make sure line termination is in place.
+    frames[i].text[kStackWalkMaxTextLen - 1] = '\0';
+  }
+
+  DeleteArray(addresses);
+  free(symbols);
+
+  return frames_count;
+#else  // ndef __GLIBC__
+  return 0;
+#endif  // ndef __GLIBC__
+}
+
+
+// Constants used for mmap.
+static const int kMmapFd = -1;
+static const int kMmapFdOffset = 0;
+
+
+VirtualMemory::VirtualMemory(size_t size) {
+  address_ = mmap(NULL, size, PROT_NONE,
+                  MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
+                  kMmapFd, kMmapFdOffset);
+  size_ = size;
+}
+
+
+VirtualMemory::~VirtualMemory() {
+  if (IsReserved()) {
+    if (0 == munmap(address(), size())) address_ = MAP_FAILED;
+  }
+}
+
+
+bool VirtualMemory::IsReserved() {
+  return address_ != MAP_FAILED;
+}
+
+
+bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
+  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
+  if (MAP_FAILED == mmap(address, size, prot,
+                         MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
+                         kMmapFd, kMmapFdOffset)) {
+    return false;
+  }
+
+  UpdateAllocatedSpaceLimits(address, size);
+  return true;
+}
+
+
+bool VirtualMemory::Uncommit(void* address, size_t size) {
+  return mmap(address, size, PROT_NONE,
+              MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
+              kMmapFd, kMmapFdOffset) != MAP_FAILED;
+}
+
+
+class ThreadHandle::PlatformData : public Malloced {
+ public:
+  explicit PlatformData(ThreadHandle::Kind kind) {
+    Initialize(kind);
+  }
+
+  void Initialize(ThreadHandle::Kind kind) {
+    switch (kind) {
+      case ThreadHandle::SELF: thread_ = pthread_self(); break;
+      case ThreadHandle::INVALID: thread_ = kNoThread; break;
+    }
+  }
+
+  pthread_t thread_;  // Thread handle for pthread.
+};
+
+
+ThreadHandle::ThreadHandle(Kind kind) {
+  data_ = new PlatformData(kind);
+}
+
+
+void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
+  data_->Initialize(kind);
+}
+
+
+ThreadHandle::~ThreadHandle() {
+  delete data_;
+}
+
+
+bool ThreadHandle::IsSelf() const {
+  return pthread_equal(data_->thread_, pthread_self());
+}
+
+
+bool ThreadHandle::IsValid() const {
+  return data_->thread_ != kNoThread;
+}
+
+
+Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
+}
+
+
+Thread::~Thread() {
+}
+
+
+static void* ThreadEntry(void* arg) {
+  Thread* thread = reinterpret_cast<Thread*>(arg);
+  // This is also initialized by the first argument to pthread_create() but we
+  // don't know which thread will run first (the original thread or the new
+  // one) so we initialize it here too.
+  thread->thread_handle_data()->thread_ = pthread_self();
+  ASSERT(thread->IsValid());
+  thread->Run();
+  return NULL;
+}
+
+
+void Thread::Start() {
+  pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this);
+  ASSERT(IsValid());
+}
+
+
+void Thread::Join() {
+  pthread_join(thread_handle_data()->thread_, NULL);
+}
+
+
+Thread::LocalStorageKey Thread::CreateThreadLocalKey() {
+  pthread_key_t key;
+  int result = pthread_key_create(&key, NULL);
+  USE(result);
+  ASSERT(result == 0);
+  return static_cast<LocalStorageKey>(key);
+}
+
+
+void Thread::DeleteThreadLocalKey(LocalStorageKey key) {
+  pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
+  int result = pthread_key_delete(pthread_key);
+  USE(result);
+  ASSERT(result == 0);
+}
+
+
+void* Thread::GetThreadLocal(LocalStorageKey key) {
+  pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
+  return pthread_getspecific(pthread_key);
+}
+
+
+void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
+  pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
+  pthread_setspecific(pthread_key, value);
+}
+
+
+void Thread::YieldCPU() {
+  sched_yield();
+}
+
+
+class LinuxMutex : public Mutex {
+ public:
+
+  LinuxMutex() {
+    pthread_mutexattr_t attrs;
+    int result = pthread_mutexattr_init(&attrs);
+    ASSERT(result == 0);
+    result = pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE);
+    ASSERT(result == 0);
+    result = pthread_mutex_init(&mutex_, &attrs);
+    ASSERT(result == 0);
+  }
+
+  virtual ~LinuxMutex() { pthread_mutex_destroy(&mutex_); }
+
+  virtual int Lock() {
+    int result = pthread_mutex_lock(&mutex_);
+    return result;
+  }
+
+  virtual int Unlock() {
+    int result = pthread_mutex_unlock(&mutex_);
+    return result;
+  }
+
+ private:
+  pthread_mutex_t mutex_;   // Pthread mutex for POSIX platforms.
+};
+
+
+Mutex* OS::CreateMutex() {
+  return new LinuxMutex();
+}
+
+
+class LinuxSemaphore : public Semaphore {
+ public:
+  explicit LinuxSemaphore(int count) {  sem_init(&sem_, 0, count); }
+  virtual ~LinuxSemaphore() { sem_destroy(&sem_); }
+
+  virtual void Wait();
+  virtual bool Wait(int timeout);
+  virtual void Signal() { sem_post(&sem_); }
+ private:
+  sem_t sem_;
+};
+
+
+void LinuxSemaphore::Wait() {
+  while (true) {
+    int result = sem_wait(&sem_);
+    if (result == 0) return;  // Successfully got semaphore.
+    CHECK(result == -1 && errno == EINTR);  // Signal caused spurious wakeup.
+  }
+}
+
+
+bool LinuxSemaphore::Wait(int timeout) {
+  const long kOneSecondMicros = 1000000;  // NOLINT
+  const long kOneSecondNanos = 1000000000;  // NOLINT
+
+  // Split timeout into second and nanosecond parts.
+  long nanos = (timeout % kOneSecondMicros) * 1000;  // NOLINT
+  time_t secs = timeout / kOneSecondMicros;
+
+  // Get the current realtime clock.
+  struct timespec ts;
+  if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
+    return false;
+  }
+
+  // Calculate real time for end of timeout.
+  ts.tv_nsec += nanos;
+  if (ts.tv_nsec >= kOneSecondNanos) {
+    ts.tv_nsec -= kOneSecondNanos;
+    ts.tv_nsec++;
+  }
+  ts.tv_sec += secs;
+
+  // Wait for semaphore signalled or timeout.
+  while (true) {
+    int result = sem_timedwait(&sem_, &ts);
+    if (result == 0) return true;  // Successfully got semaphore.
+    if (result > 0) {
+      // For glibc prior to 2.3.4 sem_timedwait returns the error instead of -1.
+      errno = result;
+      result = -1;
+    }
+    if (result == -1 && errno == ETIMEDOUT) return false;  // Timeout.
+    CHECK(result == -1 && errno == EINTR);  // Signal caused spurious wakeup.
+  }
+}
+
+
+Semaphore* OS::CreateSemaphore(int count) {
+  return new LinuxSemaphore(count);
+}
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+
+static Sampler* active_sampler_ = NULL;
+
+
+#if !defined(__GLIBC__) && (defined(__arm__) || defined(__thumb__))
+// Android runs a fairly new Linux kernel, so signal info is there,
+// but the C library doesn't have the structs defined.
+
+struct sigcontext {
+  uint32_t trap_no;
+  uint32_t error_code;
+  uint32_t oldmask;
+  uint32_t gregs[16];
+  uint32_t arm_cpsr;
+  uint32_t fault_address;
+};
+typedef uint32_t __sigset_t;
+typedef struct sigcontext mcontext_t;
+typedef struct ucontext {
+  uint32_t uc_flags;
+  struct ucontext *uc_link;
+  stack_t uc_stack;
+  mcontext_t uc_mcontext;
+  __sigset_t uc_sigmask;
+} ucontext_t;
+enum ArmRegisters {R15 = 15, R13 = 13, R11 = 11};
+
+#endif
+
+
+static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
+  USE(info);
+  if (signal != SIGPROF) return;
+  if (active_sampler_ == NULL) return;
+
+  TickSample sample;
+
+  // If profiling, we extract the current pc and sp.
+  if (active_sampler_->IsProfiling()) {
+    // Extracting the sample from the context is extremely machine dependent.
+    ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
+    mcontext_t& mcontext = ucontext->uc_mcontext;
+#if defined (__arm__) || defined(__thumb__)
+    sample.pc = mcontext.gregs[R15];
+    sample.sp = mcontext.gregs[R13];
+    sample.fp = mcontext.gregs[R11];
+#else
+    sample.pc = mcontext.gregs[REG_EIP];
+    sample.sp = mcontext.gregs[REG_ESP];
+    sample.fp = mcontext.gregs[REG_EBP];
+#endif
+  }
+
+  // We always sample the VM state.
+  sample.state = Logger::state();
+
+  active_sampler_->Tick(&sample);
+}
+
+
+class Sampler::PlatformData : public Malloced {
+ public:
+  PlatformData() {
+    signal_handler_installed_ = false;
+  }
+
+  bool signal_handler_installed_;
+  struct sigaction old_signal_handler_;
+  struct itimerval old_timer_value_;
+};
+
+
+Sampler::Sampler(int interval, bool profiling)
+    : interval_(interval), profiling_(profiling), active_(false) {
+  data_ = new PlatformData();
+}
+
+
+Sampler::~Sampler() {
+  delete data_;
+}
+
+
+void Sampler::Start() {
+  // There can only be one active sampler at the time on POSIX
+  // platforms.
+  if (active_sampler_ != NULL) return;
+
+  // Request profiling signals.
+  struct sigaction sa;
+  sa.sa_sigaction = ProfilerSignalHandler;
+  sigemptyset(&sa.sa_mask);
+  sa.sa_flags = SA_SIGINFO;
+  if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return;
+  data_->signal_handler_installed_ = true;
+
+  // Set the itimer to generate a tick for each interval.
+  itimerval itimer;
+  itimer.it_interval.tv_sec = interval_ / 1000;
+  itimer.it_interval.tv_usec = (interval_ % 1000) * 1000;
+  itimer.it_value.tv_sec = itimer.it_interval.tv_sec;
+  itimer.it_value.tv_usec = itimer.it_interval.tv_usec;
+  setitimer(ITIMER_PROF, &itimer, &data_->old_timer_value_);
+
+  // Set this sampler as the active sampler.
+  active_sampler_ = this;
+  active_ = true;
+}
+
+
+void Sampler::Stop() {
+  // Restore old signal handler
+  if (data_->signal_handler_installed_) {
+    setitimer(ITIMER_PROF, &data_->old_timer_value_, NULL);
+    sigaction(SIGPROF, &data_->old_signal_handler_, 0);
+    data_->signal_handler_installed_ = false;
+  }
+
+  // This sampler is no longer the active sampler.
+  active_sampler_ = NULL;
+  active_ = false;
+}
+
+#endif  // ENABLE_LOGGING_AND_PROFILING
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/platform-macos.cc b/deps/v8/src/platform-macos.cc
new file mode 100644
index 0000000..b13122f
--- /dev/null
+++ b/deps/v8/src/platform-macos.cc
@@ -0,0 +1,566 @@
+// 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.
+
+// Platform specific code for MacOS goes here. For the POSIX comaptible parts
+// the implementation is in platform-posix.cc.
+
+#include <ucontext.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <mach/mach_init.h>
+
+#include <AvailabilityMacros.h>
+
+#ifdef MAC_OS_X_VERSION_10_5
+# include <execinfo.h>  // backtrace, backtrace_symbols
+#endif
+
+#include <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <mach/semaphore.h>
+#include <mach/task.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include <errno.h>
+
+#undef MAP_TYPE
+
+#include "v8.h"
+
+#include "platform.h"
+
+namespace v8 { namespace internal {
+
+// 0 is never a valid thread id on MacOSX since a ptread_t is
+// a pointer.
+static const pthread_t kNoThread = (pthread_t) 0;
+
+
+double ceiling(double x) {
+  // Correct Mac OS X Leopard 'ceil' behavior.
+  if (-1.0 < x && x < 0.0) {
+    return -0.0;
+  } else {
+    return ceil(x);
+  }
+}
+
+
+void OS::Setup() {
+  // Seed the random number generator.
+  // Convert the current time to a 64-bit integer first, before converting it
+  // to an unsigned. Going directly will cause an overflow and the seed to be
+  // set to all ones. The seed will be identical for different instances that
+  // call this setup code within the same millisecond.
+  uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
+  srandom(static_cast<unsigned int>(seed));
+}
+
+
+// We keep the lowest and highest addresses mapped as a quick way of
+// determining that pointers are outside the heap (used mostly in assertions
+// and verification).  The estimate is conservative, ie, not all addresses in
+// 'allocated' space are actually allocated to our heap.  The range is
+// [lowest, highest), inclusive on the low and and exclusive on the high end.
+static void* lowest_ever_allocated = reinterpret_cast<void*>(-1);
+static void* highest_ever_allocated = reinterpret_cast<void*>(0);
+
+
+static void UpdateAllocatedSpaceLimits(void* address, int size) {
+  lowest_ever_allocated = Min(lowest_ever_allocated, address);
+  highest_ever_allocated =
+      Max(highest_ever_allocated,
+          reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));
+}
+
+
+bool OS::IsOutsideAllocatedSpace(void* address) {
+  return address < lowest_ever_allocated || address >= highest_ever_allocated;
+}
+
+
+size_t OS::AllocateAlignment() {
+  return getpagesize();
+}
+
+
+void* OS::Allocate(const size_t requested,
+                   size_t* allocated,
+                   bool is_executable) {
+  const size_t msize = RoundUp(requested, getpagesize());
+  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
+  void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
+  if (mbase == MAP_FAILED) {
+    LOG(StringEvent("OS::Allocate", "mmap failed"));
+    return NULL;
+  }
+  *allocated = msize;
+  UpdateAllocatedSpaceLimits(mbase, msize);
+  return mbase;
+}
+
+
+void OS::Free(void* address, const size_t size) {
+  // TODO(1240712): munmap has a return value which is ignored here.
+  munmap(address, size);
+}
+
+
+#ifdef ENABLE_HEAP_PROTECTION
+
+void OS::Protect(void* address, size_t size) {
+  UNIMPLEMENTED();
+}
+
+
+void OS::Unprotect(void* address, size_t size, bool is_executable) {
+  UNIMPLEMENTED();
+}
+
+#endif
+
+
+void OS::Sleep(int milliseconds) {
+  usleep(1000 * milliseconds);
+}
+
+
+void OS::Abort() {
+  // Redirect to std abort to signal abnormal program termination
+  abort();
+}
+
+
+void OS::DebugBreak() {
+  asm("int $3");
+}
+
+
+class PosixMemoryMappedFile : public OS::MemoryMappedFile {
+ public:
+  PosixMemoryMappedFile(FILE* file, void* memory, int size)
+    : file_(file), memory_(memory), size_(size) { }
+  virtual ~PosixMemoryMappedFile();
+  virtual void* memory() { return memory_; }
+ private:
+  FILE* file_;
+  void* memory_;
+  int size_;
+};
+
+
+OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
+    void* initial) {
+  FILE* file = fopen(name, "w+");
+  if (file == NULL) return NULL;
+  fwrite(initial, size, 1, file);
+  void* memory =
+      mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
+  return new PosixMemoryMappedFile(file, memory, size);
+}
+
+
+PosixMemoryMappedFile::~PosixMemoryMappedFile() {
+  if (memory_) munmap(memory_, size_);
+  fclose(file_);
+}
+
+
+void OS::LogSharedLibraryAddresses() {
+  // TODO(1233579): Implement.
+}
+
+
+double OS::nan_value() {
+  return NAN;
+}
+
+
+int OS::ActivationFrameAlignment() {
+  // OS X activation frames must be 16 byte-aligned; see "Mac OS X ABI
+  // Function Call Guide".
+  return 16;
+}
+
+
+int OS::StackWalk(StackFrame* frames, int frames_size) {
+#ifndef MAC_OS_X_VERSION_10_5
+  return 0;
+#else
+  void** addresses = NewArray<void*>(frames_size);
+  int frames_count = backtrace(addresses, frames_size);
+
+  char** symbols;
+  symbols = backtrace_symbols(addresses, frames_count);
+  if (symbols == NULL) {
+    DeleteArray(addresses);
+    return kStackWalkError;
+  }
+
+  for (int i = 0; i < frames_count; i++) {
+    frames[i].address = addresses[i];
+    // Format a text representation of the frame based on the information
+    // available.
+    SNPrintF(MutableCStrVector(frames[i].text,
+                               kStackWalkMaxTextLen),
+             "%s",
+             symbols[i]);
+    // Make sure line termination is in place.
+    frames[i].text[kStackWalkMaxTextLen - 1] = '\0';
+  }
+
+  DeleteArray(addresses);
+  free(symbols);
+
+  return frames_count;
+#endif
+}
+
+
+// Constants used for mmap.
+static const int kMmapFd = -1;
+static const int kMmapFdOffset = 0;
+
+
+VirtualMemory::VirtualMemory(size_t size) {
+  address_ = mmap(NULL, size, PROT_NONE,
+                  MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
+                  kMmapFd, kMmapFdOffset);
+  size_ = size;
+}
+
+
+VirtualMemory::~VirtualMemory() {
+  if (IsReserved()) {
+    if (0 == munmap(address(), size())) address_ = MAP_FAILED;
+  }
+}
+
+
+bool VirtualMemory::IsReserved() {
+  return address_ != MAP_FAILED;
+}
+
+
+bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
+  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
+  if (MAP_FAILED == mmap(address, size, prot,
+                         MAP_PRIVATE | MAP_ANON | MAP_FIXED,
+                         kMmapFd, kMmapFdOffset)) {
+    return false;
+  }
+
+  UpdateAllocatedSpaceLimits(address, size);
+  return true;
+}
+
+
+bool VirtualMemory::Uncommit(void* address, size_t size) {
+  return mmap(address, size, PROT_NONE,
+              MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
+              kMmapFd, kMmapFdOffset) != MAP_FAILED;
+}
+
+
+class ThreadHandle::PlatformData : public Malloced {
+ public:
+  explicit PlatformData(ThreadHandle::Kind kind) {
+    Initialize(kind);
+  }
+
+  void Initialize(ThreadHandle::Kind kind) {
+    switch (kind) {
+      case ThreadHandle::SELF: thread_ = pthread_self(); break;
+      case ThreadHandle::INVALID: thread_ = kNoThread; break;
+    }
+  }
+  pthread_t thread_;  // Thread handle for pthread.
+};
+
+
+
+ThreadHandle::ThreadHandle(Kind kind) {
+  data_ = new PlatformData(kind);
+}
+
+
+void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
+  data_->Initialize(kind);
+}
+
+
+ThreadHandle::~ThreadHandle() {
+  delete data_;
+}
+
+
+bool ThreadHandle::IsSelf() const {
+  return pthread_equal(data_->thread_, pthread_self());
+}
+
+
+bool ThreadHandle::IsValid() const {
+  return data_->thread_ != kNoThread;
+}
+
+
+Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
+}
+
+
+Thread::~Thread() {
+}
+
+
+static void* ThreadEntry(void* arg) {
+  Thread* thread = reinterpret_cast<Thread*>(arg);
+  // This is also initialized by the first argument to pthread_create() but we
+  // don't know which thread will run first (the original thread or the new
+  // one) so we initialize it here too.
+  thread->thread_handle_data()->thread_ = pthread_self();
+  ASSERT(thread->IsValid());
+  thread->Run();
+  return NULL;
+}
+
+
+void Thread::Start() {
+  pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this);
+}
+
+
+void Thread::Join() {
+  pthread_join(thread_handle_data()->thread_, NULL);
+}
+
+
+Thread::LocalStorageKey Thread::CreateThreadLocalKey() {
+  pthread_key_t key;
+  int result = pthread_key_create(&key, NULL);
+  USE(result);
+  ASSERT(result == 0);
+  return static_cast<LocalStorageKey>(key);
+}
+
+
+void Thread::DeleteThreadLocalKey(LocalStorageKey key) {
+  pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
+  int result = pthread_key_delete(pthread_key);
+  USE(result);
+  ASSERT(result == 0);
+}
+
+
+void* Thread::GetThreadLocal(LocalStorageKey key) {
+  pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
+  return pthread_getspecific(pthread_key);
+}
+
+
+void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
+  pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
+  pthread_setspecific(pthread_key, value);
+}
+
+
+void Thread::YieldCPU() {
+  sched_yield();
+}
+
+
+class MacOSMutex : public Mutex {
+ public:
+
+  MacOSMutex() {
+    // For some reason the compiler doesn't allow you to write
+    // "this->mutex_ = PTHREAD_..." directly on mac.
+    pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+    pthread_mutexattr_t attr;
+    pthread_mutexattr_init(&attr);
+    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+    pthread_mutex_init(&m, &attr);
+    mutex_ = m;
+  }
+
+  ~MacOSMutex() { pthread_mutex_destroy(&mutex_); }
+
+  int Lock() { return pthread_mutex_lock(&mutex_); }
+
+  int Unlock() { return pthread_mutex_unlock(&mutex_); }
+
+ private:
+  pthread_mutex_t mutex_;
+};
+
+
+Mutex* OS::CreateMutex() {
+  return new MacOSMutex();
+}
+
+
+class MacOSSemaphore : public Semaphore {
+ public:
+  explicit MacOSSemaphore(int count) {
+    semaphore_create(mach_task_self(), &semaphore_, SYNC_POLICY_FIFO, count);
+  }
+
+  ~MacOSSemaphore() {
+    semaphore_destroy(mach_task_self(), semaphore_);
+  }
+
+  // The MacOS mach semaphore documentation claims it does not have spurious
+  // wakeups, the way pthreads semaphores do.  So the code from the linux
+  // platform is not needed here.
+  void Wait() { semaphore_wait(semaphore_); }
+
+  bool Wait(int timeout);
+
+  void Signal() { semaphore_signal(semaphore_); }
+
+ private:
+  semaphore_t semaphore_;
+};
+
+
+bool MacOSSemaphore::Wait(int timeout) {
+  mach_timespec_t ts;
+  ts.tv_sec = timeout / 1000000;
+  ts.tv_nsec = (timeout % 1000000) * 1000;
+  return semaphore_timedwait(semaphore_, ts) != KERN_OPERATION_TIMED_OUT;
+}
+
+
+Semaphore* OS::CreateSemaphore(int count) {
+  return new MacOSSemaphore(count);
+}
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+
+static Sampler* active_sampler_ = NULL;
+
+static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
+  USE(info);
+  if (signal != SIGPROF) return;
+  if (active_sampler_ == NULL) return;
+
+  TickSample sample;
+
+  // If profiling, we extract the current pc and sp.
+  if (active_sampler_->IsProfiling()) {
+    // Extracting the sample from the context is extremely machine dependent.
+    ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
+    mcontext_t& mcontext = ucontext->uc_mcontext;
+#if __DARWIN_UNIX03
+    sample.pc = mcontext->__ss.__eip;
+    sample.sp = mcontext->__ss.__esp;
+    sample.fp = mcontext->__ss.__ebp;
+#else  // !__DARWIN_UNIX03
+    sample.pc = mcontext->ss.eip;
+    sample.sp = mcontext->ss.esp;
+    sample.fp = mcontext->ss.ebp;
+#endif  // __DARWIN_UNIX03
+  }
+
+  // We always sample the VM state.
+  sample.state = Logger::state();
+
+  active_sampler_->Tick(&sample);
+}
+
+
+class Sampler::PlatformData : public Malloced {
+ public:
+  PlatformData() {
+    signal_handler_installed_ = false;
+  }
+
+  bool signal_handler_installed_;
+  struct sigaction old_signal_handler_;
+  struct itimerval old_timer_value_;
+};
+
+
+Sampler::Sampler(int interval, bool profiling)
+    : interval_(interval), profiling_(profiling), active_(false) {
+  data_ = new PlatformData();
+}
+
+
+Sampler::~Sampler() {
+  delete data_;
+}
+
+
+void Sampler::Start() {
+  // There can only be one active sampler at the time on POSIX
+  // platforms.
+  if (active_sampler_ != NULL) return;
+
+  // Request profiling signals.
+  struct sigaction sa;
+  sa.sa_sigaction = ProfilerSignalHandler;
+  sigemptyset(&sa.sa_mask);
+  sa.sa_flags = SA_SIGINFO;
+  if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return;
+  data_->signal_handler_installed_ = true;
+
+  // Set the itimer to generate a tick for each interval.
+  itimerval itimer;
+  itimer.it_interval.tv_sec = interval_ / 1000;
+  itimer.it_interval.tv_usec = (interval_ % 1000) * 1000;
+  itimer.it_value.tv_sec = itimer.it_interval.tv_sec;
+  itimer.it_value.tv_usec = itimer.it_interval.tv_usec;
+  setitimer(ITIMER_PROF, &itimer, &data_->old_timer_value_);
+
+  // Set this sampler as the active sampler.
+  active_sampler_ = this;
+  active_ = true;
+}
+
+
+void Sampler::Stop() {
+  // Restore old signal handler
+  if (data_->signal_handler_installed_) {
+    setitimer(ITIMER_PROF, &data_->old_timer_value_, NULL);
+    sigaction(SIGPROF, &data_->old_signal_handler_, 0);
+    data_->signal_handler_installed_ = false;
+  }
+
+  // This sampler is no longer the active sampler.
+  active_sampler_ = NULL;
+  active_ = false;
+}
+
+#endif  // ENABLE_LOGGING_AND_PROFILING
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/platform-nullos.cc b/deps/v8/src/platform-nullos.cc
new file mode 100644
index 0000000..3a50b9d
--- /dev/null
+++ b/deps/v8/src/platform-nullos.cc
@@ -0,0 +1,435 @@
+// 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.
+
+// Platform specific code for NULLOS goes here
+
+// Minimal include to get access to abort, fprintf and friends for bootstrapping
+// messages.
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "platform.h"
+
+
+namespace v8 { namespace internal {
+
+// Give V8 the opportunity to override the default ceil behaviour.
+double ceiling(double x) {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+// Initialize OS class early in the V8 startup.
+void OS::Setup() {
+  // Seed the random number generator.
+  UNIMPLEMENTED();
+}
+
+
+// Returns the accumulated user time for thread.
+int OS::GetUserTime(uint32_t* secs,  uint32_t* usecs) {
+  UNIMPLEMENTED();
+  *secs = 0;
+  *usecs = 0;
+  return 0;
+}
+
+
+// Returns current time as the number of milliseconds since
+// 00:00:00 UTC, January 1, 1970.
+double OS::TimeCurrentMillis() {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+// Returns ticks in microsecond resolution.
+int64_t OS::Ticks() {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+// Returns a string identifying the current timezone taking into
+// account daylight saving.
+char* OS::LocalTimezone(double time) {
+  UNIMPLEMENTED();
+  return "<none>";
+}
+
+
+// Returns the daylight savings offset in milliseconds for the given time.
+double OS::DaylightSavingsOffset(double time) {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+// Returns the local time offset in milliseconds east of UTC without
+// taking daylight savings time into account.
+double OS::LocalTimeOffset() {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+// Print (debug) message to console.
+void OS::Print(const char* format, ...) {
+  UNIMPLEMENTED();
+}
+
+
+// Print (debug) message to console.
+void OS::VPrint(const char* format, va_list args) {
+  // Minimalistic implementation for bootstrapping.
+  vfprintf(stdout, format, args);
+}
+
+
+// Print error message to console.
+void OS::PrintError(const char* format, ...) {
+  // Minimalistic implementation for bootstrapping.
+  va_list args;
+  va_start(args, format);
+  VPrintError(format, args);
+  va_end(args);
+}
+
+
+// Print error message to console.
+void OS::VPrintError(const char* format, va_list args) {
+  // Minimalistic implementation for bootstrapping.
+  vfprintf(stderr, format, args);
+}
+
+
+int OS::SNPrintF(char* str, size_t size, const char* format, ...) {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+int OS::VSNPrintF(char* str, size_t size, const char* format, va_list args) {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+double OS::nan_value() {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+bool OS::IsOutsideAllocatedSpace(void* address) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+size_t OS::AllocateAlignment() {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+void* OS::Allocate(const size_t requested,
+                   size_t* allocated,
+                   bool executable) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void OS::Free(void* buf, const size_t length) {
+  // TODO(1240712): potential system call return value which is ignored here.
+  UNIMPLEMENTED();
+}
+
+
+#ifdef ENABLE_HEAP_PROTECTION
+
+void OS::Protect(void* address, size_t size) {
+  UNIMPLEMENTED();
+}
+
+
+void OS::Unprotect(void* address, size_t size, bool is_executable) {
+  UNIMPLEMENTED();
+}
+
+#endif
+
+
+void OS::Sleep(int milliseconds) {
+  UNIMPLEMENTED();
+}
+
+
+void OS::Abort() {
+  // Minimalistic implementation for bootstrapping.
+  abort();
+}
+
+
+void OS::DebugBreak() {
+  UNIMPLEMENTED();
+}
+
+
+OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
+    void* initial) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void OS::LogSharedLibraryAddresses() {
+  UNIMPLEMENTED();
+}
+
+
+int OS::StackWalk(OS::StackFrame* frames, int frames_size) {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+VirtualMemory::VirtualMemory(size_t size, void* address_hint) {
+  UNIMPLEMENTED();
+}
+
+
+VirtualMemory::~VirtualMemory() {
+  UNIMPLEMENTED();
+}
+
+
+bool VirtualMemory::IsReserved() {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+bool VirtualMemory::Commit(void* address, size_t size, bool executable) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+bool VirtualMemory::Uncommit(void* address, size_t size) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+class ThreadHandle::PlatformData : public Malloced {
+ public:
+  explicit PlatformData(ThreadHandle::Kind kind) {
+    UNIMPLEMENTED();
+  }
+
+  void* pd_data_;
+};
+
+
+ThreadHandle::ThreadHandle(Kind kind) {
+  UNIMPLEMENTED();
+  // Shared setup follows.
+  data_ = new PlatformData(kind);
+}
+
+
+void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
+  UNIMPLEMENTED();
+}
+
+
+ThreadHandle::~ThreadHandle() {
+  UNIMPLEMENTED();
+  // Shared tear down follows.
+  delete data_;
+}
+
+
+bool ThreadHandle::IsSelf() const {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+bool ThreadHandle::IsValid() const {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
+  UNIMPLEMENTED();
+}
+
+
+Thread::~Thread() {
+  UNIMPLEMENTED();
+}
+
+
+void Thread::Start() {
+  UNIMPLEMENTED();
+}
+
+
+void Thread::Join() {
+  UNIMPLEMENTED();
+}
+
+
+Thread::LocalStorageKey Thread::CreateThreadLocalKey() {
+  UNIMPLEMENTED();
+  return static_cast<LocalStorageKey>(0);
+}
+
+
+void Thread::DeleteThreadLocalKey(LocalStorageKey key) {
+  UNIMPLEMENTED();
+}
+
+
+void* Thread::GetThreadLocal(LocalStorageKey key) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
+  UNIMPLEMENTED();
+}
+
+
+void Thread::YieldCPU() {
+  UNIMPLEMENTED();
+}
+
+
+class NullMutex : public Mutex {
+ public:
+  NullMutex() : data_(NULL) {
+    UNIMPLEMENTED();
+  }
+
+  virtual ~NullMutex() {
+    UNIMPLEMENTED();
+  }
+
+  virtual int Lock() {
+    UNIMPLEMENTED();
+    return 0;
+  }
+
+  virtual int Unlock() {
+    UNIMPLEMENTED();
+    return 0;
+  }
+
+ private:
+  void* data_;
+};
+
+
+Mutex* OS::CreateMutex() {
+  UNIMPLEMENTED();
+  return new NullMutex();
+}
+
+
+class NullSemaphore : public Semaphore {
+ public:
+  explicit NullSemaphore(int count) : data_(NULL) {
+    UNIMPLEMENTED();
+  }
+
+  virtual ~NullSemaphore() {
+    UNIMPLEMENTED();
+  }
+
+  virtual void Wait() {
+    UNIMPLEMENTED();
+  }
+
+  virtual void Signal() {
+    UNIMPLEMENTED();
+  }
+ private:
+  void* data_;
+};
+
+
+Semaphore* OS::CreateSemaphore(int count) {
+  UNIMPLEMENTED();
+  return new NullSemaphore(count);
+}
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+
+class ProfileSampler::PlatformData  : public Malloced {
+ public:
+  PlatformData() {
+    UNIMPLEMENTED();
+  }
+};
+
+
+ProfileSampler::ProfileSampler(int interval) {
+  UNIMPLEMENTED();
+  // Shared setup follows.
+  data_ = new PlatformData();
+  interval_ = interval;
+  active_ = false;
+}
+
+
+ProfileSampler::~ProfileSampler() {
+  UNIMPLEMENTED();
+  // Shared tear down follows.
+  delete data_;
+}
+
+
+void ProfileSampler::Start() {
+  UNIMPLEMENTED();
+}
+
+
+void ProfileSampler::Stop() {
+  UNIMPLEMENTED();
+}
+
+#endif  // ENABLE_LOGGING_AND_PROFILING
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/platform-posix.cc b/deps/v8/src/platform-posix.cc
new file mode 100644
index 0000000..de16ef5
--- /dev/null
+++ b/deps/v8/src/platform-posix.cc
@@ -0,0 +1,350 @@
+// 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.
+
+// Platform specific code for POSIX goes here. This is not a platform on its
+// own but contains the parts which are the same across POSIX platforms Linux,
+// Mac OS and FreeBSD.
+
+#include <unistd.h>
+#include <errno.h>
+#include <time.h>
+
+#include <sys/socket.h>
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include "v8.h"
+
+#include "platform.h"
+
+
+namespace v8 { namespace internal {
+
+
+// ----------------------------------------------------------------------------
+// POSIX date/time support.
+//
+
+int OS::GetUserTime(uint32_t* secs,  uint32_t* usecs) {
+  struct rusage usage;
+
+  if (getrusage(RUSAGE_SELF, &usage) < 0) return -1;
+  *secs = usage.ru_utime.tv_sec;
+  *usecs = usage.ru_utime.tv_usec;
+  return 0;
+}
+
+
+double OS::TimeCurrentMillis() {
+  struct timeval tv;
+  if (gettimeofday(&tv, NULL) < 0) return 0.0;
+  return (static_cast<double>(tv.tv_sec) * 1000) +
+         (static_cast<double>(tv.tv_usec) / 1000);
+}
+
+
+int64_t OS::Ticks() {
+  // gettimeofday has microsecond resolution.
+  struct timeval tv;
+  if (gettimeofday(&tv, NULL) < 0)
+    return 0;
+  return (static_cast<int64_t>(tv.tv_sec) * 1000000) + tv.tv_usec;
+}
+
+
+char* OS::LocalTimezone(double time) {
+  time_t tv = static_cast<time_t>(floor(time/msPerSecond));
+  struct tm* t = localtime(&tv);
+  return const_cast<char*>(t->tm_zone);
+}
+
+
+double OS::DaylightSavingsOffset(double time) {
+  time_t tv = static_cast<time_t>(floor(time/msPerSecond));
+  struct tm* t = localtime(&tv);
+  return t->tm_isdst > 0 ? 3600 * msPerSecond : 0;
+}
+
+
+double OS::LocalTimeOffset() {
+  time_t tv = time(NULL);
+  struct tm* t = localtime(&tv);
+  // tm_gmtoff includes any daylight savings offset, so subtract it.
+  return static_cast<double>(t->tm_gmtoff * msPerSecond -
+                             (t->tm_isdst > 0 ? 3600 * msPerSecond : 0));
+}
+
+
+// ----------------------------------------------------------------------------
+// POSIX stdio support.
+//
+
+FILE* OS::FOpen(const char* path, const char* mode) {
+  return fopen(path, mode);
+}
+
+
+const char* OS::LogFileOpenMode = "w";
+
+
+void OS::Print(const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  VPrint(format, args);
+  va_end(args);
+}
+
+
+void OS::VPrint(const char* format, va_list args) {
+  vprintf(format, args);
+}
+
+
+void OS::PrintError(const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  VPrintError(format, args);
+  va_end(args);
+}
+
+
+void OS::VPrintError(const char* format, va_list args) {
+  vfprintf(stderr, format, args);
+}
+
+
+int OS::SNPrintF(Vector<char> str, const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  int result = VSNPrintF(str, format, args);
+  va_end(args);
+  return result;
+}
+
+
+int OS::VSNPrintF(Vector<char> str,
+                  const char* format,
+                  va_list args) {
+  int n = vsnprintf(str.start(), str.length(), format, args);
+  if (n < 0 || n >= str.length()) {
+    str[str.length() - 1] = '\0';
+    return -1;
+  } else {
+    return n;
+  }
+}
+
+
+// ----------------------------------------------------------------------------
+// POSIX string support.
+//
+
+char* OS::StrChr(char* str, int c) {
+  return strchr(str, c);
+}
+
+
+void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) {
+  strncpy(dest.start(), src, n);
+}
+
+
+// ----------------------------------------------------------------------------
+// POSIX socket support.
+//
+
+class POSIXSocket : public Socket {
+ public:
+  explicit POSIXSocket() {
+    // Create the socket.
+    socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+  }
+  explicit POSIXSocket(int socket): socket_(socket) { }
+  virtual ~POSIXSocket() { Shutdown(); }
+
+  // Server initialization.
+  bool Bind(const int port);
+  bool Listen(int backlog) const;
+  Socket* Accept() const;
+
+  // Client initialization.
+  bool Connect(const char* host, const char* port);
+
+  // Shutdown socket for both read and write.
+  bool Shutdown();
+
+  // Data Transimission
+  int Send(const char* data, int len) const;
+  int Receive(char* data, int len) const;
+
+  bool SetReuseAddress(bool reuse_address);
+
+  bool IsValid() const { return socket_ != -1; }
+
+ private:
+  int socket_;
+};
+
+
+bool POSIXSocket::Bind(const int port) {
+  if (!IsValid())  {
+    return false;
+  }
+
+  sockaddr_in addr;
+  memset(&addr, 0, sizeof(addr));
+  addr.sin_family = AF_INET;
+  addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+  addr.sin_port = htons(port);
+  int status = bind(socket_,
+                    reinterpret_cast<struct sockaddr *>(&addr),
+                    sizeof(addr));
+  return status == 0;
+}
+
+
+bool POSIXSocket::Listen(int backlog) const {
+  if (!IsValid()) {
+    return false;
+  }
+
+  int status = listen(socket_, backlog);
+  return status == 0;
+}
+
+
+Socket* POSIXSocket::Accept() const {
+  if (!IsValid()) {
+    return NULL;
+  }
+
+  int socket = accept(socket_, NULL, NULL);
+  if (socket == -1) {
+    return NULL;
+  } else {
+    return new POSIXSocket(socket);
+  }
+}
+
+
+bool POSIXSocket::Connect(const char* host, const char* port) {
+  if (!IsValid()) {
+    return false;
+  }
+
+  // Lookup host and port.
+  struct addrinfo *result = NULL;
+  struct addrinfo hints;
+  memset(&hints, 0, sizeof(addrinfo));
+  hints.ai_family = AF_INET;
+  hints.ai_socktype = SOCK_STREAM;
+  hints.ai_protocol = IPPROTO_TCP;
+  int status = getaddrinfo(host, port, &hints, &result);
+  if (status != 0) {
+    return false;
+  }
+
+  // Connect.
+  status = connect(socket_, result->ai_addr, result->ai_addrlen);
+  freeaddrinfo(result);
+  return status == 0;
+}
+
+
+bool POSIXSocket::Shutdown() {
+  if (IsValid()) {
+    // Shutdown socket for both read and write.
+    int status = shutdown(socket_, SHUT_RDWR);
+    close(socket_);
+    socket_ = -1;
+    return status == 0;
+  }
+  return true;
+}
+
+
+int POSIXSocket::Send(const char* data, int len) const {
+  int status = send(socket_, data, len, 0);
+  return status;
+}
+
+
+int POSIXSocket::Receive(char* data, int len) const {
+  int status = recv(socket_, data, len, 0);
+  return status;
+}
+
+
+bool POSIXSocket::SetReuseAddress(bool reuse_address) {
+  int on = reuse_address ? 1 : 0;
+  int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+  return status == 0;
+}
+
+
+bool Socket::Setup() {
+  // Nothing to do on POSIX.
+  return true;
+}
+
+
+int Socket::LastError() {
+  return errno;
+}
+
+
+uint16_t Socket::HToN(uint16_t value) {
+  return htons(value);
+}
+
+
+uint16_t Socket::NToH(uint16_t value) {
+  return ntohs(value);
+}
+
+
+uint32_t Socket::HToN(uint32_t value) {
+  return htonl(value);
+}
+
+
+uint32_t Socket::NToH(uint32_t value) {
+  return ntohl(value);
+}
+
+
+Socket* OS::CreateSocket() {
+  return new POSIXSocket();
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/platform-win32.cc b/deps/v8/src/platform-win32.cc
new file mode 100644
index 0000000..7177870
--- /dev/null
+++ b/deps/v8/src/platform-win32.cc
@@ -0,0 +1,1864 @@
+// 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.
+
+// Platform specific code for Win32.
+#ifndef WIN32_LEAN_AND_MEAN
+// WIN32_LEAN_AND_MEAN implies NOCRYPT and NOGDI.
+#define WIN32_LEAN_AND_MEAN
+#endif
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#ifndef NOKERNEL
+#define NOKERNEL
+#endif
+#ifndef NOUSER
+#define NOUSER
+#endif
+#ifndef NOSERVICE
+#define NOSERVICE
+#endif
+#ifndef NOSOUND
+#define NOSOUND
+#endif
+#ifndef NOMCX
+#define NOMCX
+#endif
+// Require Windows 2000 or higher (this is required for the IsDebuggerPresent
+// function to be present).
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x500
+#endif
+
+#include <windows.h>
+
+#include <time.h>  // For LocalOffset() implementation.
+#include <mmsystem.h>  // For timeGetTime().
+#ifndef __MINGW32__
+#include <dbghelp.h>  // For SymLoadModule64 and al.
+#endif  // __MINGW32__
+#include <limits.h>  // For INT_MAX and al.
+#include <tlhelp32.h>  // For Module32First and al.
+
+// These additional WIN32 includes have to be right here as the #undef's below
+// makes it impossible to have them elsewhere.
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <process.h>  // for _beginthreadex()
+#include <stdlib.h>
+
+#undef VOID
+#undef DELETE
+#undef IN
+#undef THIS
+#undef CONST
+#undef NAN
+#undef GetObject
+#undef CreateMutex
+#undef CreateSemaphore
+
+#include "v8.h"
+
+#include "platform.h"
+
+// Extra POSIX/ANSI routines for Win32 when when using Visual Studio C++. Please
+// refer to The Open Group Base Specification for specification of the correct
+// semantics for these functions.
+// (http://www.opengroup.org/onlinepubs/000095399/)
+#ifdef _MSC_VER
+
+namespace v8 {
+namespace internal {
+
+// Test for finite value - usually defined in math.h
+int isfinite(double x) {
+  return _finite(x);
+}
+
+}  // namespace v8
+}  // namespace internal
+
+// Test for a NaN (not a number) value - usually defined in math.h
+int isnan(double x) {
+  return _isnan(x);
+}
+
+
+// Test for infinity - usually defined in math.h
+int isinf(double x) {
+  return (_fpclass(x) & (_FPCLASS_PINF | _FPCLASS_NINF)) != 0;
+}
+
+
+// Test if x is less than y and both nominal - usually defined in math.h
+int isless(double x, double y) {
+  return isnan(x) || isnan(y) ? 0 : x < y;
+}
+
+
+// Test if x is greater than y and both nominal - usually defined in math.h
+int isgreater(double x, double y) {
+  return isnan(x) || isnan(y) ? 0 : x > y;
+}
+
+
+// Classify floating point number - usually defined in math.h
+int fpclassify(double x) {
+  // Use the MS-specific _fpclass() for classification.
+  int flags = _fpclass(x);
+
+  // Determine class. We cannot use a switch statement because
+  // the _FPCLASS_ constants are defined as flags.
+  if (flags & (_FPCLASS_PN | _FPCLASS_NN)) return FP_NORMAL;
+  if (flags & (_FPCLASS_PZ | _FPCLASS_NZ)) return FP_ZERO;
+  if (flags & (_FPCLASS_PD | _FPCLASS_ND)) return FP_SUBNORMAL;
+  if (flags & (_FPCLASS_PINF | _FPCLASS_NINF)) return FP_INFINITE;
+
+  // All cases should be covered by the code above.
+  ASSERT(flags & (_FPCLASS_SNAN | _FPCLASS_QNAN));
+  return FP_NAN;
+}
+
+
+// Test sign - usually defined in math.h
+int signbit(double x) {
+  // We need to take care of the special case of both positive
+  // and negative versions of zero.
+  if (x == 0)
+    return _fpclass(x) & _FPCLASS_NZ;
+  else
+    return x < 0;
+}
+
+
+// Case-insensitive bounded string comparisons. Use stricmp() on Win32. Usually
+// defined in strings.h.
+int strncasecmp(const char* s1, const char* s2, int n) {
+  return _strnicmp(s1, s2, n);
+}
+
+#endif  // _MSC_VER
+
+
+// Extra functions for MinGW. Most of these are the _s functions which are in
+// the Microsoft Visual Studio C++ CRT.
+#ifdef __MINGW32__
+
+int localtime_s(tm* out_tm, const time_t* time) {
+  tm* posix_local_time_struct = localtime(time);
+  if (posix_local_time_struct == NULL) return 1;
+  *out_tm = *posix_local_time_struct;
+  return 0;
+}
+
+
+// Not sure this the correct interpretation of _mkgmtime
+time_t _mkgmtime(tm* timeptr) {
+  return mktime(timeptr);
+}
+
+
+int fopen_s(FILE** pFile, const char* filename, const char* mode) {
+  *pFile = fopen(filename, mode);
+  return *pFile != NULL ? 0 : 1;
+}
+
+
+int _vsnprintf_s(char* buffer, size_t sizeOfBuffer, size_t count,
+                 const char* format, va_list argptr) {
+  return _vsnprintf(buffer, sizeOfBuffer, format, argptr);
+}
+#define _TRUNCATE 0
+
+
+int strncpy_s(char* strDest, size_t numberOfElements,
+              const char* strSource, size_t count) {
+  strncpy(strDest, strSource, count);
+  return 0;
+}
+
+#endif  // __MINGW32__
+
+// Generate a pseudo-random number in the range 0-2^31-1. Usually
+// defined in stdlib.h. Missing in both Microsoft Visual Studio C++ and MinGW.
+int random() {
+  return rand();
+}
+
+
+namespace v8 { namespace internal {
+
+double ceiling(double x) {
+  return ceil(x);
+}
+
+// ----------------------------------------------------------------------------
+// The Time class represents time on win32. A timestamp is represented as
+// a 64-bit integer in 100 nano-seconds since January 1, 1601 (UTC). JavaScript
+// timestamps are represented as a doubles in milliseconds since 00:00:00 UTC,
+// January 1, 1970.
+
+class Time {
+ public:
+  // Constructors.
+  Time();
+  explicit Time(double jstime);
+  Time(int year, int mon, int day, int hour, int min, int sec);
+
+  // Convert timestamp to JavaScript representation.
+  double ToJSTime();
+
+  // Set timestamp to current time.
+  void SetToCurrentTime();
+
+  // Returns the local timezone offset in milliseconds east of UTC. This is
+  // the number of milliseconds you must add to UTC to get local time, i.e.
+  // LocalOffset(CET) = 3600000 and LocalOffset(PST) = -28800000. This
+  // routine also takes into account whether daylight saving is effect
+  // at the time.
+  int64_t LocalOffset();
+
+  // Returns the daylight savings time offset for the time in milliseconds.
+  int64_t DaylightSavingsOffset();
+
+  // Returns a string identifying the current timezone for the
+  // timestamp taking into account daylight saving.
+  char* LocalTimezone();
+
+ private:
+  // Constants for time conversion.
+  static const int64_t kTimeEpoc = 116444736000000000LL;
+  static const int64_t kTimeScaler = 10000;
+  static const int64_t kMsPerMinute = 60000;
+
+  // Constants for timezone information.
+  static const int kTzNameSize = 128;
+  static const bool kShortTzNames = false;
+
+  // Timezone information. We need to have static buffers for the
+  // timezone names because we return pointers to these in
+  // LocalTimezone().
+  static bool tz_initialized_;
+  static TIME_ZONE_INFORMATION tzinfo_;
+  static char std_tz_name_[kTzNameSize];
+  static char dst_tz_name_[kTzNameSize];
+
+  // Initialize the timezone information (if not already done).
+  static void TzSet();
+
+  // Guess the name of the timezone from the bias.
+  static const char* GuessTimezoneNameFromBias(int bias);
+
+  // Return whether or not daylight savings time is in effect at this time.
+  bool InDST();
+
+  // Return the difference (in milliseconds) between this timestamp and
+  // another timestamp.
+  int64_t Diff(Time* other);
+
+  // Accessor for FILETIME representation.
+  FILETIME& ft() { return time_.ft_; }
+
+  // Accessor for integer representation.
+  int64_t& t() { return time_.t_; }
+
+  // Although win32 uses 64-bit integers for representing timestamps,
+  // these are packed into a FILETIME structure. The FILETIME structure
+  // is just a struct representing a 64-bit integer. The TimeStamp union
+  // allows access to both a FILETIME and an integer representation of
+  // the timestamp.
+  union TimeStamp {
+    FILETIME ft_;
+    int64_t t_;
+  };
+
+  TimeStamp time_;
+};
+
+// Static variables.
+bool Time::tz_initialized_ = false;
+TIME_ZONE_INFORMATION Time::tzinfo_;
+char Time::std_tz_name_[kTzNameSize];
+char Time::dst_tz_name_[kTzNameSize];
+
+
+// Initialize timestamp to start of epoc.
+Time::Time() {
+  t() = 0;
+}
+
+
+// Initialize timestamp from a JavaScript timestamp.
+Time::Time(double jstime) {
+  t() = static_cast<int64_t>(jstime) * kTimeScaler + kTimeEpoc;
+}
+
+
+// Initialize timestamp from date/time components.
+Time::Time(int year, int mon, int day, int hour, int min, int sec) {
+  SYSTEMTIME st;
+  st.wYear = year;
+  st.wMonth = mon;
+  st.wDay = day;
+  st.wHour = hour;
+  st.wMinute = min;
+  st.wSecond = sec;
+  st.wMilliseconds = 0;
+  SystemTimeToFileTime(&st, &ft());
+}
+
+
+// Convert timestamp to JavaScript timestamp.
+double Time::ToJSTime() {
+  return static_cast<double>((t() - kTimeEpoc) / kTimeScaler);
+}
+
+
+// Guess the name of the timezone from the bias.
+// The guess is very biased towards the northern hemisphere.
+const char* Time::GuessTimezoneNameFromBias(int bias) {
+  static const int kHour = 60;
+  switch (-bias) {
+    case -9*kHour: return "Alaska";
+    case -8*kHour: return "Pacific";
+    case -7*kHour: return "Mountain";
+    case -6*kHour: return "Central";
+    case -5*kHour: return "Eastern";
+    case -4*kHour: return "Atlantic";
+    case  0*kHour: return "GMT";
+    case +1*kHour: return "Central Europe";
+    case +2*kHour: return "Eastern Europe";
+    case +3*kHour: return "Russia";
+    case +5*kHour + 30: return "India";
+    case +8*kHour: return "China";
+    case +9*kHour: return "Japan";
+    case +12*kHour: return "New Zealand";
+    default: return "Local";
+  }
+}
+
+
+// Initialize timezone information. The timezone information is obtained from
+// windows. If we cannot get the timezone information we fall back to CET.
+// Please notice that this code is not thread-safe.
+void Time::TzSet() {
+  // Just return if timezone information has already been initialized.
+  if (tz_initialized_) return;
+
+  // Initialize POSIX time zone data.
+  _tzset();
+  // Obtain timezone information from operating system.
+  memset(&tzinfo_, 0, sizeof(tzinfo_));
+  if (GetTimeZoneInformation(&tzinfo_) == TIME_ZONE_ID_INVALID) {
+    // If we cannot get timezone information we fall back to CET.
+    tzinfo_.Bias = -60;
+    tzinfo_.StandardDate.wMonth = 10;
+    tzinfo_.StandardDate.wDay = 5;
+    tzinfo_.StandardDate.wHour = 3;
+    tzinfo_.StandardBias = 0;
+    tzinfo_.DaylightDate.wMonth = 3;
+    tzinfo_.DaylightDate.wDay = 5;
+    tzinfo_.DaylightDate.wHour = 2;
+    tzinfo_.DaylightBias = -60;
+  }
+
+  // Make standard and DST timezone names.
+  OS::SNPrintF(Vector<char>(std_tz_name_, kTzNameSize),
+               "%S",
+               tzinfo_.StandardName);
+  std_tz_name_[kTzNameSize - 1] = '\0';
+  OS::SNPrintF(Vector<char>(dst_tz_name_, kTzNameSize),
+               "%S",
+               tzinfo_.DaylightName);
+  dst_tz_name_[kTzNameSize - 1] = '\0';
+
+  // If OS returned empty string or resource id (like "@tzres.dll,-211")
+  // simply guess the name from the UTC bias of the timezone.
+  // To properly resolve the resource identifier requires a library load,
+  // which is not possible in a sandbox.
+  if (std_tz_name_[0] == '\0' || std_tz_name_[0] == '@') {
+    OS::SNPrintF(Vector<char>(std_tz_name_, kTzNameSize - 1),
+                 "%s Standard Time",
+                 GuessTimezoneNameFromBias(tzinfo_.Bias));
+  }
+  if (dst_tz_name_[0] == '\0' || dst_tz_name_[0] == '@') {
+    OS::SNPrintF(Vector<char>(dst_tz_name_, kTzNameSize - 1),
+                 "%s Daylight Time",
+                 GuessTimezoneNameFromBias(tzinfo_.Bias));
+  }
+
+  // Timezone information initialized.
+  tz_initialized_ = true;
+}
+
+
+// Return the difference in milliseconds between this and another timestamp.
+int64_t Time::Diff(Time* other) {
+  return (t() - other->t()) / kTimeScaler;
+}
+
+
+// Set timestamp to current time.
+void Time::SetToCurrentTime() {
+  // The default GetSystemTimeAsFileTime has a ~15.5ms resolution.
+  // Because we're fast, we like fast timers which have at least a
+  // 1ms resolution.
+  //
+  // timeGetTime() provides 1ms granularity when combined with
+  // timeBeginPeriod().  If the host application for v8 wants fast
+  // timers, it can use timeBeginPeriod to increase the resolution.
+  //
+  // Using timeGetTime() has a drawback because it is a 32bit value
+  // and hence rolls-over every ~49days.
+  //
+  // To use the clock, we use GetSystemTimeAsFileTime as our base;
+  // and then use timeGetTime to extrapolate current time from the
+  // start time.  To deal with rollovers, we resync the clock
+  // any time when more than kMaxClockElapsedTime has passed or
+  // whenever timeGetTime creates a rollover.
+
+  static bool initialized = false;
+  static TimeStamp init_time;
+  static DWORD init_ticks;
+  static const int64_t kHundredNanosecondsPerSecond = 10000000;
+  static const int64_t kMaxClockElapsedTime =
+      60*kHundredNanosecondsPerSecond;  // 1 minute
+
+  // If we are uninitialized, we need to resync the clock.
+  bool needs_resync = !initialized;
+
+  // Get the current time.
+  TimeStamp time_now;
+  GetSystemTimeAsFileTime(&time_now.ft_);
+  DWORD ticks_now = timeGetTime();
+
+  // Check if we need to resync due to clock rollover.
+  needs_resync |= ticks_now < init_ticks;
+
+  // Check if we need to resync due to elapsed time.
+  needs_resync |= (time_now.t_ - init_time.t_) > kMaxClockElapsedTime;
+
+  // Resync the clock if necessary.
+  if (needs_resync) {
+    GetSystemTimeAsFileTime(&init_time.ft_);
+    init_ticks = ticks_now = timeGetTime();
+    initialized = true;
+  }
+
+  // Finally, compute the actual time.  Why is this so hard.
+  DWORD elapsed = ticks_now - init_ticks;
+  this->time_.t_ = init_time.t_ + (static_cast<int64_t>(elapsed) * 10000);
+}
+
+
+// Return the local timezone offset in milliseconds east of UTC. This
+// takes into account whether daylight saving is in effect at the time.
+// Only times in the 32-bit Unix range may be passed to this function.
+// Also, adding the time-zone offset to the input must not overflow.
+// The function EquivalentTime() in date-delay.js guarantees this.
+int64_t Time::LocalOffset() {
+  // Initialize timezone information, if needed.
+  TzSet();
+
+  Time rounded_to_second(*this);
+  rounded_to_second.t() = rounded_to_second.t() / 1000 / kTimeScaler *
+      1000 * kTimeScaler;
+  // Convert to local time using POSIX localtime function.
+  // Windows XP Service Pack 3 made SystemTimeToTzSpecificLocalTime()
+  // very slow.  Other browsers use localtime().
+
+  // Convert from JavaScript milliseconds past 1/1/1970 0:00:00 to
+  // POSIX seconds past 1/1/1970 0:00:00.
+  double unchecked_posix_time = rounded_to_second.ToJSTime() / 1000;
+  if (unchecked_posix_time > INT_MAX || unchecked_posix_time < 0) {
+    return 0;
+  }
+  // Because _USE_32BIT_TIME_T is defined, time_t is a 32-bit int.
+  time_t posix_time = static_cast<time_t>(unchecked_posix_time);
+
+  // Convert to local time, as struct with fields for day, hour, year, etc.
+  tm posix_local_time_struct;
+  if (localtime_s(&posix_local_time_struct, &posix_time)) return 0;
+  // Convert local time in struct to POSIX time as if it were a UTC time.
+  time_t local_posix_time = _mkgmtime(&posix_local_time_struct);
+  Time localtime(1000.0 * local_posix_time);
+
+  return localtime.Diff(&rounded_to_second);
+}
+
+
+// Return whether or not daylight savings time is in effect at this time.
+bool Time::InDST() {
+  // Initialize timezone information, if needed.
+  TzSet();
+
+  // Determine if DST is in effect at the specified time.
+  bool in_dst = false;
+  if (tzinfo_.StandardDate.wMonth != 0 || tzinfo_.DaylightDate.wMonth != 0) {
+    // Get the local timezone offset for the timestamp in milliseconds.
+    int64_t offset = LocalOffset();
+
+    // Compute the offset for DST. The bias parameters in the timezone info
+    // are specified in minutes. These must be converted to milliseconds.
+    int64_t dstofs = -(tzinfo_.Bias + tzinfo_.DaylightBias) * kMsPerMinute;
+
+    // If the local time offset equals the timezone bias plus the daylight
+    // bias then DST is in effect.
+    in_dst = offset == dstofs;
+  }
+
+  return in_dst;
+}
+
+
+// Return the daylight savings time offset for this time.
+int64_t Time::DaylightSavingsOffset() {
+  return InDST() ? 60 * kMsPerMinute : 0;
+}
+
+
+// Returns a string identifying the current timezone for the
+// timestamp taking into account daylight saving.
+char* Time::LocalTimezone() {
+  // Return the standard or DST time zone name based on whether daylight
+  // saving is in effect at the given time.
+  return InDST() ? dst_tz_name_ : std_tz_name_;
+}
+
+
+void OS::Setup() {
+  // Seed the random number generator.
+  // Convert the current time to a 64-bit integer first, before converting it
+  // to an unsigned. Going directly can cause an overflow and the seed to be
+  // set to all ones. The seed will be identical for different instances that
+  // call this setup code within the same millisecond.
+  uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
+  srand(static_cast<unsigned int>(seed));
+}
+
+
+// Returns the accumulated user time for thread.
+int OS::GetUserTime(uint32_t* secs,  uint32_t* usecs) {
+  FILETIME dummy;
+  uint64_t usertime;
+
+  // Get the amount of time that the thread has executed in user mode.
+  if (!GetThreadTimes(GetCurrentThread(), &dummy, &dummy, &dummy,
+                      reinterpret_cast<FILETIME*>(&usertime))) return -1;
+
+  // Adjust the resolution to micro-seconds.
+  usertime /= 10;
+
+  // Convert to seconds and microseconds
+  *secs = static_cast<uint32_t>(usertime / 1000000);
+  *usecs = static_cast<uint32_t>(usertime % 1000000);
+  return 0;
+}
+
+
+// Returns current time as the number of milliseconds since
+// 00:00:00 UTC, January 1, 1970.
+double OS::TimeCurrentMillis() {
+  Time t;
+  t.SetToCurrentTime();
+  return t.ToJSTime();
+}
+
+// Returns the tickcounter based on timeGetTime.
+int64_t OS::Ticks() {
+  return timeGetTime() * 1000;  // Convert to microseconds.
+}
+
+
+// Returns a string identifying the current timezone taking into
+// account daylight saving.
+char* OS::LocalTimezone(double time) {
+  return Time(time).LocalTimezone();
+}
+
+
+// Returns the local time offset in milliseconds east of UTC without
+// taking daylight savings time into account.
+double OS::LocalTimeOffset() {
+  // Use current time, rounded to the millisecond.
+  Time t(TimeCurrentMillis());
+  // Time::LocalOffset inlcudes any daylight savings offset, so subtract it.
+  return static_cast<double>(t.LocalOffset() - t.DaylightSavingsOffset());
+}
+
+
+// Returns the daylight savings offset in milliseconds for the given
+// time.
+double OS::DaylightSavingsOffset(double time) {
+  int64_t offset = Time(time).DaylightSavingsOffset();
+  return static_cast<double>(offset);
+}
+
+
+// ----------------------------------------------------------------------------
+// Win32 console output.
+//
+// If a Win32 application is linked as a console application it has a normal
+// standard output and standard error. In this case normal printf works fine
+// for output. However, if the application is linked as a GUI application,
+// the process doesn't have a console, and therefore (debugging) output is lost.
+// This is the case if we are embedded in a windows program (like a browser).
+// In order to be able to get debug output in this case the the debugging
+// facility using OutputDebugString. This output goes to the active debugger
+// for the process (if any). Else the output can be monitored using DBMON.EXE.
+
+enum OutputMode {
+  UNKNOWN,  // Output method has not yet been determined.
+  CONSOLE,  // Output is written to stdout.
+  ODS       // Output is written to debug facility.
+};
+
+static OutputMode output_mode = UNKNOWN;  // Current output mode.
+
+
+// Determine if the process has a console for output.
+static bool HasConsole() {
+  // Only check the first time. Eventual race conditions are not a problem,
+  // because all threads will eventually determine the same mode.
+  if (output_mode == UNKNOWN) {
+    // We cannot just check that the standard output is attached to a console
+    // because this would fail if output is redirected to a file. Therefore we
+    // say that a process does not have an output console if either the
+    // standard output handle is invalid or its file type is unknown.
+    if (GetStdHandle(STD_OUTPUT_HANDLE) != INVALID_HANDLE_VALUE &&
+        GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) != FILE_TYPE_UNKNOWN)
+      output_mode = CONSOLE;
+    else
+      output_mode = ODS;
+  }
+  return output_mode == CONSOLE;
+}
+
+
+static void VPrintHelper(FILE* stream, const char* format, va_list args) {
+  if (HasConsole()) {
+    vfprintf(stream, format, args);
+  } else {
+    // It is important to use safe print here in order to avoid
+    // overflowing the buffer. We might truncate the output, but this
+    // does not crash.
+    EmbeddedVector<char, 4096> buffer;
+    OS::VSNPrintF(buffer, format, args);
+    OutputDebugStringA(buffer.start());
+  }
+}
+
+
+FILE* OS::FOpen(const char* path, const char* mode) {
+  FILE* result;
+  if (fopen_s(&result, path, mode) == 0) {
+    return result;
+  } else {
+    return NULL;
+  }
+}
+
+
+// Open log file in binary mode to avoid /n -> /r/n conversion.
+const char* OS::LogFileOpenMode = "wb";
+
+
+// Print (debug) message to console.
+void OS::Print(const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  VPrint(format, args);
+  va_end(args);
+}
+
+
+void OS::VPrint(const char* format, va_list args) {
+  VPrintHelper(stdout, format, args);
+}
+
+
+// Print error message to console.
+void OS::PrintError(const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  VPrintError(format, args);
+  va_end(args);
+}
+
+
+void OS::VPrintError(const char* format, va_list args) {
+  VPrintHelper(stderr, format, args);
+}
+
+
+int OS::SNPrintF(Vector<char> str, const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  int result = VSNPrintF(str, format, args);
+  va_end(args);
+  return result;
+}
+
+
+int OS::VSNPrintF(Vector<char> str, const char* format, va_list args) {
+  int n = _vsnprintf_s(str.start(), str.length(), _TRUNCATE, format, args);
+  // Make sure to zero-terminate the string if the output was
+  // truncated or if there was an error.
+  if (n < 0 || n >= str.length()) {
+    str[str.length() - 1] = '\0';
+    return -1;
+  } else {
+    return n;
+  }
+}
+
+
+char* OS::StrChr(char* str, int c) {
+  return const_cast<char*>(strchr(str, c));
+}
+
+
+void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) {
+  int result = strncpy_s(dest.start(), dest.length(), src, n);
+  USE(result);
+  ASSERT(result == 0);
+}
+
+
+// We keep the lowest and highest addresses mapped as a quick way of
+// determining that pointers are outside the heap (used mostly in assertions
+// and verification).  The estimate is conservative, ie, not all addresses in
+// 'allocated' space are actually allocated to our heap.  The range is
+// [lowest, highest), inclusive on the low and and exclusive on the high end.
+static void* lowest_ever_allocated = reinterpret_cast<void*>(-1);
+static void* highest_ever_allocated = reinterpret_cast<void*>(0);
+
+
+static void UpdateAllocatedSpaceLimits(void* address, int size) {
+  lowest_ever_allocated = Min(lowest_ever_allocated, address);
+  highest_ever_allocated =
+      Max(highest_ever_allocated,
+          reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));
+}
+
+
+bool OS::IsOutsideAllocatedSpace(void* pointer) {
+  if (pointer < lowest_ever_allocated || pointer >= highest_ever_allocated)
+    return true;
+  // Ask the Windows API
+  if (IsBadWritePtr(pointer, 1))
+    return true;
+  return false;
+}
+
+
+// Get the system's page size used by VirtualAlloc() or the next power
+// of two. The reason for always returning a power of two is that the
+// rounding up in OS::Allocate expects that.
+static size_t GetPageSize() {
+  static size_t page_size = 0;
+  if (page_size == 0) {
+    SYSTEM_INFO info;
+    GetSystemInfo(&info);
+    page_size = RoundUpToPowerOf2(info.dwPageSize);
+  }
+  return page_size;
+}
+
+
+// The allocation alignment is the guaranteed alignment for
+// VirtualAlloc'ed blocks of memory.
+size_t OS::AllocateAlignment() {
+  static size_t allocate_alignment = 0;
+  if (allocate_alignment == 0) {
+    SYSTEM_INFO info;
+    GetSystemInfo(&info);
+    allocate_alignment = info.dwAllocationGranularity;
+  }
+  return allocate_alignment;
+}
+
+
+void* OS::Allocate(const size_t requested,
+                   size_t* allocated,
+                   bool is_executable) {
+  // VirtualAlloc rounds allocated size to page size automatically.
+  size_t msize = RoundUp(requested, GetPageSize());
+
+  // Windows XP SP2 allows Data Excution Prevention (DEP).
+  int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
+  LPVOID mbase = VirtualAlloc(NULL, msize, MEM_COMMIT | MEM_RESERVE, prot);
+  if (mbase == NULL) {
+    LOG(StringEvent("OS::Allocate", "VirtualAlloc failed"));
+    return NULL;
+  }
+
+  ASSERT(IsAligned(reinterpret_cast<size_t>(mbase), OS::AllocateAlignment()));
+
+  *allocated = msize;
+  UpdateAllocatedSpaceLimits(mbase, msize);
+  return mbase;
+}
+
+
+void OS::Free(void* address, const size_t size) {
+  // TODO(1240712): VirtualFree has a return value which is ignored here.
+  VirtualFree(address, 0, MEM_RELEASE);
+  USE(size);
+}
+
+
+#ifdef ENABLE_HEAP_PROTECTION
+
+void OS::Protect(void* address, size_t size) {
+  // TODO(1240712): VirtualProtect has a return value which is ignored here.
+  DWORD old_protect;
+  VirtualProtect(address, size, PAGE_READONLY, &old_protect);
+}
+
+
+void OS::Unprotect(void* address, size_t size, bool is_executable) {
+  // TODO(1240712): VirtualProtect has a return value which is ignored here.
+  DWORD new_protect = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
+  DWORD old_protect;
+  VirtualProtect(address, size, new_protect, &old_protect);
+}
+
+#endif
+
+
+void OS::Sleep(int milliseconds) {
+  ::Sleep(milliseconds);
+}
+
+
+void OS::Abort() {
+  if (!IsDebuggerPresent()) {
+#ifdef _MSC_VER
+    // Make the MSVCRT do a silent abort.
+    _set_abort_behavior(0, _WRITE_ABORT_MSG);
+    _set_abort_behavior(0, _CALL_REPORTFAULT);
+#endif  // _MSC_VER
+    abort();
+  } else {
+    DebugBreak();
+  }
+}
+
+
+void OS::DebugBreak() {
+#ifdef _MSC_VER
+  __debugbreak();
+#else
+  ::DebugBreak();
+#endif
+}
+
+
+class Win32MemoryMappedFile : public OS::MemoryMappedFile {
+ public:
+  Win32MemoryMappedFile(HANDLE file, HANDLE file_mapping, void* memory)
+    : file_(file), file_mapping_(file_mapping), memory_(memory) { }
+  virtual ~Win32MemoryMappedFile();
+  virtual void* memory() { return memory_; }
+ private:
+  HANDLE file_;
+  HANDLE file_mapping_;
+  void* memory_;
+};
+
+
+OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
+    void* initial) {
+  // Open a physical file
+  HANDLE file = CreateFileA(name, GENERIC_READ | GENERIC_WRITE,
+      FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL);
+  if (file == NULL) return NULL;
+  // Create a file mapping for the physical file
+  HANDLE file_mapping = CreateFileMapping(file, NULL,
+      PAGE_READWRITE, 0, static_cast<DWORD>(size), NULL);
+  if (file_mapping == NULL) return NULL;
+  // Map a view of the file into memory
+  void* memory = MapViewOfFile(file_mapping, FILE_MAP_ALL_ACCESS, 0, 0, size);
+  if (memory) memmove(memory, initial, size);
+  return new Win32MemoryMappedFile(file, file_mapping, memory);
+}
+
+
+Win32MemoryMappedFile::~Win32MemoryMappedFile() {
+  if (memory_ != NULL)
+    UnmapViewOfFile(memory_);
+  CloseHandle(file_mapping_);
+  CloseHandle(file_);
+}
+
+
+// The following code loads functions defined in DbhHelp.h and TlHelp32.h
+// dynamically. This is to avoid being depending on dbghelp.dll and
+// tlhelp32.dll when running (the functions in tlhelp32.dll have been moved to
+// kernel32.dll at some point so loading functions defines in TlHelp32.h
+// dynamically might not be necessary any more - for some versions of Windows?).
+
+// Function pointers to functions dynamically loaded from dbghelp.dll.
+#define DBGHELP_FUNCTION_LIST(V)  \
+  V(SymInitialize)                \
+  V(SymGetOptions)                \
+  V(SymSetOptions)                \
+  V(SymGetSearchPath)             \
+  V(SymLoadModule64)              \
+  V(StackWalk64)                  \
+  V(SymGetSymFromAddr64)          \
+  V(SymGetLineFromAddr64)         \
+  V(SymFunctionTableAccess64)     \
+  V(SymGetModuleBase64)
+
+// Function pointers to functions dynamically loaded from dbghelp.dll.
+#define TLHELP32_FUNCTION_LIST(V)  \
+  V(CreateToolhelp32Snapshot)      \
+  V(Module32FirstW)                \
+  V(Module32NextW)
+
+// Define the decoration to use for the type and variable name used for
+// dynamically loaded DLL function..
+#define DLL_FUNC_TYPE(name) _##name##_
+#define DLL_FUNC_VAR(name) _##name
+
+// Define the type for each dynamically loaded DLL function. The function
+// definitions are copied from DbgHelp.h and TlHelp32.h. The IN and VOID macros
+// from the Windows include files are redefined here to have the function
+// definitions to be as close to the ones in the original .h files as possible.
+#ifndef IN
+#define IN
+#endif
+#ifndef VOID
+#define VOID void
+#endif
+
+// DbgHelp isn't supported on MinGW yet
+#ifndef __MINGW32__
+// DbgHelp.h functions.
+typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymInitialize))(IN HANDLE hProcess,
+                                                       IN PSTR UserSearchPath,
+                                                       IN BOOL fInvadeProcess);
+typedef DWORD (__stdcall *DLL_FUNC_TYPE(SymGetOptions))(VOID);
+typedef DWORD (__stdcall *DLL_FUNC_TYPE(SymSetOptions))(IN DWORD SymOptions);
+typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetSearchPath))(
+    IN HANDLE hProcess,
+    OUT PSTR SearchPath,
+    IN DWORD SearchPathLength);
+typedef DWORD64 (__stdcall *DLL_FUNC_TYPE(SymLoadModule64))(
+    IN HANDLE hProcess,
+    IN HANDLE hFile,
+    IN PSTR ImageName,
+    IN PSTR ModuleName,
+    IN DWORD64 BaseOfDll,
+    IN DWORD SizeOfDll);
+typedef BOOL (__stdcall *DLL_FUNC_TYPE(StackWalk64))(
+    DWORD MachineType,
+    HANDLE hProcess,
+    HANDLE hThread,
+    LPSTACKFRAME64 StackFrame,
+    PVOID ContextRecord,
+    PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
+    PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
+    PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
+    PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
+typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetSymFromAddr64))(
+    IN HANDLE hProcess,
+    IN DWORD64 qwAddr,
+    OUT PDWORD64 pdwDisplacement,
+    OUT PIMAGEHLP_SYMBOL64 Symbol);
+typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetLineFromAddr64))(
+    IN HANDLE hProcess,
+    IN DWORD64 qwAddr,
+    OUT PDWORD pdwDisplacement,
+    OUT PIMAGEHLP_LINE64 Line64);
+// DbgHelp.h typedefs. Implementation found in dbghelp.dll.
+typedef PVOID (__stdcall *DLL_FUNC_TYPE(SymFunctionTableAccess64))(
+    HANDLE hProcess,
+    DWORD64 AddrBase);  // DbgHelp.h typedef PFUNCTION_TABLE_ACCESS_ROUTINE64
+typedef DWORD64 (__stdcall *DLL_FUNC_TYPE(SymGetModuleBase64))(
+    HANDLE hProcess,
+    DWORD64 AddrBase);  // DbgHelp.h typedef PGET_MODULE_BASE_ROUTINE64
+
+// TlHelp32.h functions.
+typedef HANDLE (__stdcall *DLL_FUNC_TYPE(CreateToolhelp32Snapshot))(
+    DWORD dwFlags,
+    DWORD th32ProcessID);
+typedef BOOL (__stdcall *DLL_FUNC_TYPE(Module32FirstW))(HANDLE hSnapshot,
+                                                        LPMODULEENTRY32W lpme);
+typedef BOOL (__stdcall *DLL_FUNC_TYPE(Module32NextW))(HANDLE hSnapshot,
+                                                       LPMODULEENTRY32W lpme);
+
+#undef IN
+#undef VOID
+
+// Declare a variable for each dynamically loaded DLL function.
+#define DEF_DLL_FUNCTION(name) DLL_FUNC_TYPE(name) DLL_FUNC_VAR(name) = NULL;
+DBGHELP_FUNCTION_LIST(DEF_DLL_FUNCTION)
+TLHELP32_FUNCTION_LIST(DEF_DLL_FUNCTION)
+#undef DEF_DLL_FUNCTION
+
+// Load the functions. This function has a lot of "ugly" macros in order to
+// keep down code duplication.
+
+static bool LoadDbgHelpAndTlHelp32() {
+  static bool dbghelp_loaded = false;
+
+  if (dbghelp_loaded) return true;
+
+  HMODULE module;
+
+  // Load functions from the dbghelp.dll module.
+  module = LoadLibrary(TEXT("dbghelp.dll"));
+  if (module == NULL) {
+    return false;
+  }
+
+#define LOAD_DLL_FUNC(name)                                                 \
+  DLL_FUNC_VAR(name) =                                                      \
+      reinterpret_cast<DLL_FUNC_TYPE(name)>(GetProcAddress(module, #name));
+
+DBGHELP_FUNCTION_LIST(LOAD_DLL_FUNC)
+
+#undef LOAD_DLL_FUNC
+
+  // Load functions from the kernel32.dll module (the TlHelp32.h function used
+  // to be in tlhelp32.dll but are now moved to kernel32.dll).
+  module = LoadLibrary(TEXT("kernel32.dll"));
+  if (module == NULL) {
+    return false;
+  }
+
+#define LOAD_DLL_FUNC(name)                                                 \
+  DLL_FUNC_VAR(name) =                                                      \
+      reinterpret_cast<DLL_FUNC_TYPE(name)>(GetProcAddress(module, #name));
+
+TLHELP32_FUNCTION_LIST(LOAD_DLL_FUNC)
+
+#undef LOAD_DLL_FUNC
+
+  // Check that all functions where loaded.
+  bool result =
+#define DLL_FUNC_LOADED(name) (DLL_FUNC_VAR(name) != NULL) &&
+
+DBGHELP_FUNCTION_LIST(DLL_FUNC_LOADED)
+TLHELP32_FUNCTION_LIST(DLL_FUNC_LOADED)
+
+#undef DLL_FUNC_LOADED
+  true;
+
+  dbghelp_loaded = result;
+  return result;
+  // NOTE: The modules are never unloaded and will stay around until the
+  // application is closed.
+}
+
+
+// Load the symbols for generating stack traces.
+static bool LoadSymbols(HANDLE process_handle) {
+  static bool symbols_loaded = false;
+
+  if (symbols_loaded) return true;
+
+  BOOL ok;
+
+  // Initialize the symbol engine.
+  ok = _SymInitialize(process_handle,  // hProcess
+                      NULL,            // UserSearchPath
+                      FALSE);          // fInvadeProcess
+  if (!ok) return false;
+
+  DWORD options = _SymGetOptions();
+  options |= SYMOPT_LOAD_LINES;
+  options |= SYMOPT_FAIL_CRITICAL_ERRORS;
+  options = _SymSetOptions(options);
+
+  char buf[OS::kStackWalkMaxNameLen] = {0};
+  ok = _SymGetSearchPath(process_handle, buf, OS::kStackWalkMaxNameLen);
+  if (!ok) {
+    int err = GetLastError();
+    PrintF("%d\n", err);
+    return false;
+  }
+
+  HANDLE snapshot = _CreateToolhelp32Snapshot(
+      TH32CS_SNAPMODULE,       // dwFlags
+      GetCurrentProcessId());  // th32ProcessId
+  if (snapshot == INVALID_HANDLE_VALUE) return false;
+  MODULEENTRY32W module_entry;
+  module_entry.dwSize = sizeof(module_entry);  // Set the size of the structure.
+  BOOL cont = _Module32FirstW(snapshot, &module_entry);
+  while (cont) {
+    DWORD64 base;
+    // NOTE the SymLoadModule64 function has the peculiarity of accepting a
+    // both unicode and ASCII strings even though the parameter is PSTR.
+    base = _SymLoadModule64(
+        process_handle,                                       // hProcess
+        0,                                                    // hFile
+        reinterpret_cast<PSTR>(module_entry.szExePath),       // ImageName
+        reinterpret_cast<PSTR>(module_entry.szModule),        // ModuleName
+        reinterpret_cast<DWORD64>(module_entry.modBaseAddr),  // BaseOfDll
+        module_entry.modBaseSize);                            // SizeOfDll
+    if (base == 0) {
+      int err = GetLastError();
+      if (err != ERROR_MOD_NOT_FOUND &&
+          err != ERROR_INVALID_HANDLE) return false;
+    }
+    LOG(SharedLibraryEvent(
+            module_entry.szExePath,
+            reinterpret_cast<unsigned int>(module_entry.modBaseAddr),
+            reinterpret_cast<unsigned int>(module_entry.modBaseAddr +
+                                           module_entry.modBaseSize)));
+    cont = _Module32NextW(snapshot, &module_entry);
+  }
+  CloseHandle(snapshot);
+
+  symbols_loaded = true;
+  return true;
+}
+
+
+void OS::LogSharedLibraryAddresses() {
+  // SharedLibraryEvents are logged when loading symbol information.
+  // Only the shared libraries loaded at the time of the call to
+  // LogSharedLibraryAddresses are logged.  DLLs loaded after
+  // initialization are not accounted for.
+  if (!LoadDbgHelpAndTlHelp32()) return;
+  HANDLE process_handle = GetCurrentProcess();
+  LoadSymbols(process_handle);
+}
+
+
+// Walk the stack using the facilities in dbghelp.dll and tlhelp32.dll
+
+// Switch off warning 4748 (/GS can not protect parameters and local variables
+// from local buffer overrun because optimizations are disabled in function) as
+// it is triggered by the use of inline assembler.
+#pragma warning(push)
+#pragma warning(disable : 4748)
+int OS::StackWalk(OS::StackFrame* frames, int frames_size) {
+  BOOL ok;
+
+  // Load the required functions from DLL's.
+  if (!LoadDbgHelpAndTlHelp32()) return kStackWalkError;
+
+  // Get the process and thread handles.
+  HANDLE process_handle = GetCurrentProcess();
+  HANDLE thread_handle = GetCurrentThread();
+
+  // Read the symbols.
+  if (!LoadSymbols(process_handle)) return kStackWalkError;
+
+  // Capture current context.
+  CONTEXT context;
+  memset(&context, 0, sizeof(context));
+  context.ContextFlags = CONTEXT_CONTROL;
+  context.ContextFlags = CONTEXT_CONTROL;
+  __asm    call x
+  __asm x: pop eax
+  __asm    mov context.Eip, eax
+  __asm    mov context.Ebp, ebp
+  __asm    mov context.Esp, esp
+  // NOTE: At some point, we could use RtlCaptureContext(&context) to
+  // capture the context instead of inline assembler. However it is
+  // only available on XP, Vista, Server 2003 and Server 2008 which
+  // might not be sufficient.
+
+  // Initialize the stack walking
+  STACKFRAME64 stack_frame;
+  memset(&stack_frame, 0, sizeof(stack_frame));
+  stack_frame.AddrPC.Offset = context.Eip;
+  stack_frame.AddrPC.Mode = AddrModeFlat;
+  stack_frame.AddrFrame.Offset = context.Ebp;
+  stack_frame.AddrFrame.Mode = AddrModeFlat;
+  stack_frame.AddrStack.Offset = context.Esp;
+  stack_frame.AddrStack.Mode = AddrModeFlat;
+  int frames_count = 0;
+
+  // Collect stack frames.
+  while (frames_count < frames_size) {
+    ok = _StackWalk64(
+        IMAGE_FILE_MACHINE_I386,    // MachineType
+        process_handle,             // hProcess
+        thread_handle,              // hThread
+        &stack_frame,               // StackFrame
+        &context,                   // ContextRecord
+        NULL,                       // ReadMemoryRoutine
+        _SymFunctionTableAccess64,  // FunctionTableAccessRoutine
+        _SymGetModuleBase64,        // GetModuleBaseRoutine
+        NULL);                      // TranslateAddress
+    if (!ok) break;
+
+    // Store the address.
+    ASSERT((stack_frame.AddrPC.Offset >> 32) == 0);  // 32-bit address.
+    frames[frames_count].address =
+        reinterpret_cast<void*>(stack_frame.AddrPC.Offset);
+
+    // Try to locate a symbol for this frame.
+    DWORD64 symbol_displacement;
+    IMAGEHLP_SYMBOL64* symbol = NULL;
+    symbol = NewArray<IMAGEHLP_SYMBOL64>(kStackWalkMaxNameLen);
+    if (!symbol) return kStackWalkError;  // Out of memory.
+    memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64) + kStackWalkMaxNameLen);
+    symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
+    symbol->MaxNameLength = kStackWalkMaxNameLen;
+    ok = _SymGetSymFromAddr64(process_handle,             // hProcess
+                              stack_frame.AddrPC.Offset,  // Address
+                              &symbol_displacement,       // Displacement
+                              symbol);                    // Symbol
+    if (ok) {
+      // Try to locate more source information for the symbol.
+      IMAGEHLP_LINE64 Line;
+      memset(&Line, 0, sizeof(Line));
+      Line.SizeOfStruct = sizeof(Line);
+      DWORD line_displacement;
+      ok = _SymGetLineFromAddr64(
+          process_handle,             // hProcess
+          stack_frame.AddrPC.Offset,  // dwAddr
+          &line_displacement,         // pdwDisplacement
+          &Line);                     // Line
+      // Format a text representation of the frame based on the information
+      // available.
+      if (ok) {
+        SNPrintF(MutableCStrVector(frames[frames_count].text,
+                                   kStackWalkMaxTextLen),
+                 "%s %s:%d:%d",
+                 symbol->Name, Line.FileName, Line.LineNumber,
+                 line_displacement);
+      } else {
+        SNPrintF(MutableCStrVector(frames[frames_count].text,
+                                   kStackWalkMaxTextLen),
+                 "%s",
+                 symbol->Name);
+      }
+      // Make sure line termination is in place.
+      frames[frames_count].text[kStackWalkMaxTextLen - 1] = '\0';
+    } else {
+      // No text representation of this frame
+      frames[frames_count].text[0] = '\0';
+
+      // Continue if we are just missing a module (for non C/C++ frames a
+      // module will never be found).
+      int err = GetLastError();
+      if (err != ERROR_MOD_NOT_FOUND) {
+        DeleteArray(symbol);
+        break;
+      }
+    }
+    DeleteArray(symbol);
+
+    frames_count++;
+  }
+
+  // Return the number of frames filled in.
+  return frames_count;
+}
+
+// Restore warnings to previous settings.
+#pragma warning(pop)
+
+#else  // __MINGW32__
+void OS::LogSharedLibraryAddresses() { }
+int OS::StackWalk(OS::StackFrame* frames, int frames_size) { return 0; }
+#endif  // __MINGW32__
+
+
+double OS::nan_value() {
+#ifdef _MSC_VER
+  static const __int64 nanval = 0xfff8000000000000;
+  return *reinterpret_cast<const double*>(&nanval);
+#else  // _MSC_VER
+  return NAN;
+#endif  // _MSC_VER
+}
+
+
+int OS::ActivationFrameAlignment() {
+  // Floating point code runs faster if the stack is 8-byte aligned.
+  return 8;
+}
+
+
+bool VirtualMemory::IsReserved() {
+  return address_ != NULL;
+}
+
+
+VirtualMemory::VirtualMemory(size_t size) {
+  address_ = VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS);
+  size_ = size;
+}
+
+
+VirtualMemory::~VirtualMemory() {
+  if (IsReserved()) {
+    if (0 == VirtualFree(address(), 0, MEM_RELEASE)) address_ = NULL;
+  }
+}
+
+
+bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
+  int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
+  if (NULL == VirtualAlloc(address, size, MEM_COMMIT, prot)) {
+    return false;
+  }
+
+  UpdateAllocatedSpaceLimits(address, size);
+  return true;
+}
+
+
+bool VirtualMemory::Uncommit(void* address, size_t size) {
+  ASSERT(IsReserved());
+  return VirtualFree(address, size, MEM_DECOMMIT) != FALSE;
+}
+
+
+// ----------------------------------------------------------------------------
+// Win32 thread support.
+
+// Definition of invalid thread handle and id.
+static const HANDLE kNoThread = INVALID_HANDLE_VALUE;
+static const DWORD kNoThreadId = 0;
+
+
+class ThreadHandle::PlatformData : public Malloced {
+ public:
+  explicit PlatformData(ThreadHandle::Kind kind) {
+    Initialize(kind);
+  }
+
+  void Initialize(ThreadHandle::Kind kind) {
+    switch (kind) {
+      case ThreadHandle::SELF: tid_ = GetCurrentThreadId(); break;
+      case ThreadHandle::INVALID: tid_ = kNoThreadId; break;
+    }
+  }
+  DWORD tid_;  // Win32 thread identifier.
+};
+
+
+// Entry point for threads. The supplied argument is a pointer to the thread
+// object. The entry function dispatches to the run method in the thread
+// object. It is important that this function has __stdcall calling
+// convention.
+static unsigned int __stdcall ThreadEntry(void* arg) {
+  Thread* thread = reinterpret_cast<Thread*>(arg);
+  // This is also initialized by the last parameter to _beginthreadex() but we
+  // don't know which thread will run first (the original thread or the new
+  // one) so we initialize it here too.
+  thread->thread_handle_data()->tid_ = GetCurrentThreadId();
+  thread->Run();
+  return 0;
+}
+
+
+// Initialize thread handle to invalid handle.
+ThreadHandle::ThreadHandle(ThreadHandle::Kind kind) {
+  data_ = new PlatformData(kind);
+}
+
+
+ThreadHandle::~ThreadHandle() {
+  delete data_;
+}
+
+
+// The thread is running if it has the same id as the current thread.
+bool ThreadHandle::IsSelf() const {
+  return GetCurrentThreadId() == data_->tid_;
+}
+
+
+// Test for invalid thread handle.
+bool ThreadHandle::IsValid() const {
+  return data_->tid_ != kNoThreadId;
+}
+
+
+void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
+  data_->Initialize(kind);
+}
+
+
+class Thread::PlatformData : public Malloced {
+ public:
+  explicit PlatformData(HANDLE thread) : thread_(thread) {}
+  HANDLE thread_;
+};
+
+
+// Initialize a Win32 thread object. The thread has an invalid thread
+// handle until it is started.
+
+Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
+  data_ = new PlatformData(kNoThread);
+}
+
+
+// Close our own handle for the thread.
+Thread::~Thread() {
+  if (data_->thread_ != kNoThread) CloseHandle(data_->thread_);
+  delete data_;
+}
+
+
+// Create a new thread. It is important to use _beginthreadex() instead of
+// the Win32 function CreateThread(), because the CreateThread() does not
+// initialize thread specific structures in the C runtime library.
+void Thread::Start() {
+  data_->thread_ = reinterpret_cast<HANDLE>(
+      _beginthreadex(NULL,
+                     0,
+                     ThreadEntry,
+                     this,
+                     0,
+                     reinterpret_cast<unsigned int*>(
+                         &thread_handle_data()->tid_)));
+  ASSERT(IsValid());
+}
+
+
+// Wait for thread to terminate.
+void Thread::Join() {
+  WaitForSingleObject(data_->thread_, INFINITE);
+}
+
+
+Thread::LocalStorageKey Thread::CreateThreadLocalKey() {
+  DWORD result = TlsAlloc();
+  ASSERT(result != TLS_OUT_OF_INDEXES);
+  return static_cast<LocalStorageKey>(result);
+}
+
+
+void Thread::DeleteThreadLocalKey(LocalStorageKey key) {
+  BOOL result = TlsFree(static_cast<DWORD>(key));
+  USE(result);
+  ASSERT(result);
+}
+
+
+void* Thread::GetThreadLocal(LocalStorageKey key) {
+  return TlsGetValue(static_cast<DWORD>(key));
+}
+
+
+void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
+  BOOL result = TlsSetValue(static_cast<DWORD>(key), value);
+  USE(result);
+  ASSERT(result);
+}
+
+
+
+void Thread::YieldCPU() {
+  Sleep(0);
+}
+
+
+// ----------------------------------------------------------------------------
+// Win32 mutex support.
+//
+// On Win32 mutexes are implemented using CRITICAL_SECTION objects. These are
+// faster than Win32 Mutex objects because they are implemented using user mode
+// atomic instructions. Therefore we only do ring transitions if there is lock
+// contention.
+
+class Win32Mutex : public Mutex {
+ public:
+
+  Win32Mutex() { InitializeCriticalSection(&cs_); }
+
+  ~Win32Mutex() { DeleteCriticalSection(&cs_); }
+
+  int Lock() {
+    EnterCriticalSection(&cs_);
+    return 0;
+  }
+
+  int Unlock() {
+    LeaveCriticalSection(&cs_);
+    return 0;
+  }
+
+ private:
+  CRITICAL_SECTION cs_;  // Critical section used for mutex
+};
+
+
+Mutex* OS::CreateMutex() {
+  return new Win32Mutex();
+}
+
+
+// ----------------------------------------------------------------------------
+// Win32 semaphore support.
+//
+// On Win32 semaphores are implemented using Win32 Semaphore objects. The
+// semaphores are anonymous. Also, the semaphores are initialized to have
+// no upper limit on count.
+
+
+class Win32Semaphore : public Semaphore {
+ public:
+  explicit Win32Semaphore(int count) {
+    sem = ::CreateSemaphoreA(NULL, count, 0x7fffffff, NULL);
+  }
+
+  ~Win32Semaphore() {
+    CloseHandle(sem);
+  }
+
+  void Wait() {
+    WaitForSingleObject(sem, INFINITE);
+  }
+
+  bool Wait(int timeout) {
+    // Timeout in Windows API is in milliseconds.
+    DWORD millis_timeout = timeout / 1000;
+    return WaitForSingleObject(sem, millis_timeout) != WAIT_TIMEOUT;
+  }
+
+  void Signal() {
+    LONG dummy;
+    ReleaseSemaphore(sem, 1, &dummy);
+  }
+
+ private:
+  HANDLE sem;
+};
+
+
+Semaphore* OS::CreateSemaphore(int count) {
+  return new Win32Semaphore(count);
+}
+
+
+// ----------------------------------------------------------------------------
+// Win32 socket support.
+//
+
+class Win32Socket : public Socket {
+ public:
+  explicit Win32Socket() {
+    // Create the socket.
+    socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+  }
+  explicit Win32Socket(SOCKET socket): socket_(socket) { }
+  virtual ~Win32Socket() { Shutdown(); }
+
+  // Server initialization.
+  bool Bind(const int port);
+  bool Listen(int backlog) const;
+  Socket* Accept() const;
+
+  // Client initialization.
+  bool Connect(const char* host, const char* port);
+
+  // Shutdown socket for both read and write.
+  bool Shutdown();
+
+  // Data Transimission
+  int Send(const char* data, int len) const;
+  int Receive(char* data, int len) const;
+
+  bool SetReuseAddress(bool reuse_address);
+
+  bool IsValid() const { return socket_ != INVALID_SOCKET; }
+
+ private:
+  SOCKET socket_;
+};
+
+
+bool Win32Socket::Bind(const int port) {
+  if (!IsValid())  {
+    return false;
+  }
+
+  sockaddr_in addr;
+  memset(&addr, 0, sizeof(addr));
+  addr.sin_family = AF_INET;
+  addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+  addr.sin_port = htons(port);
+  int status = bind(socket_,
+                    reinterpret_cast<struct sockaddr *>(&addr),
+                    sizeof(addr));
+  return status == 0;
+}
+
+
+bool Win32Socket::Listen(int backlog) const {
+  if (!IsValid()) {
+    return false;
+  }
+
+  int status = listen(socket_, backlog);
+  return status == 0;
+}
+
+
+Socket* Win32Socket::Accept() const {
+  if (!IsValid()) {
+    return NULL;
+  }
+
+  SOCKET socket = accept(socket_, NULL, NULL);
+  if (socket == INVALID_SOCKET) {
+    return NULL;
+  } else {
+    return new Win32Socket(socket);
+  }
+}
+
+
+bool Win32Socket::Connect(const char* host, const char* port) {
+  if (!IsValid()) {
+    return false;
+  }
+
+  // Lookup host and port.
+  struct addrinfo *result = NULL;
+  struct addrinfo hints;
+  memset(&hints, 0, sizeof(addrinfo));
+  hints.ai_family = AF_INET;
+  hints.ai_socktype = SOCK_STREAM;
+  hints.ai_protocol = IPPROTO_TCP;
+  int status = getaddrinfo(host, port, &hints, &result);
+  if (status != 0) {
+    return false;
+  }
+
+  // Connect.
+  status = connect(socket_, result->ai_addr, result->ai_addrlen);
+  freeaddrinfo(result);
+  return status == 0;
+}
+
+
+bool Win32Socket::Shutdown() {
+  if (IsValid()) {
+    // Shutdown socket for both read and write.
+    int status = shutdown(socket_, SD_BOTH);
+    closesocket(socket_);
+    socket_ = INVALID_SOCKET;
+    return status == SOCKET_ERROR;
+  }
+  return true;
+}
+
+
+int Win32Socket::Send(const char* data, int len) const {
+  int status = send(socket_, data, len, 0);
+  return status;
+}
+
+
+int Win32Socket::Receive(char* data, int len) const {
+  int status = recv(socket_, data, len, 0);
+  return status;
+}
+
+
+bool Win32Socket::SetReuseAddress(bool reuse_address) {
+  BOOL on = reuse_address ? TRUE : FALSE;
+  int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
+                          reinterpret_cast<char*>(&on), sizeof(on));
+  return status == SOCKET_ERROR;
+}
+
+
+bool Socket::Setup() {
+  // Initialize Winsock32
+  int err;
+  WSADATA winsock_data;
+  WORD version_requested = MAKEWORD(1, 0);
+  err = WSAStartup(version_requested, &winsock_data);
+  if (err != 0) {
+    PrintF("Unable to initialize Winsock, err = %d\n", Socket::LastError());
+  }
+
+  return err == 0;
+}
+
+
+int Socket::LastError() {
+  return WSAGetLastError();
+}
+
+
+uint16_t Socket::HToN(uint16_t value) {
+  return htons(value);
+}
+
+
+uint16_t Socket::NToH(uint16_t value) {
+  return ntohs(value);
+}
+
+
+uint32_t Socket::HToN(uint32_t value) {
+  return htonl(value);
+}
+
+
+uint32_t Socket::NToH(uint32_t value) {
+  return ntohl(value);
+}
+
+
+Socket* OS::CreateSocket() {
+  return new Win32Socket();
+}
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+
+// ----------------------------------------------------------------------------
+// Win32 profiler support.
+//
+// On win32 we use a sampler thread with high priority to sample the program
+// counter for the profiled thread.
+
+class Sampler::PlatformData : public Malloced {
+ public:
+  explicit PlatformData(Sampler* sampler) {
+    sampler_ = sampler;
+    sampler_thread_ = INVALID_HANDLE_VALUE;
+    profiled_thread_ = INVALID_HANDLE_VALUE;
+  }
+
+  Sampler* sampler_;
+  HANDLE sampler_thread_;
+  HANDLE profiled_thread_;
+
+  // Sampler thread handler.
+  void Runner() {
+    // Context used for sampling the register state of the profiled thread.
+    CONTEXT context;
+    memset(&context, 0, sizeof(context));
+    // Loop until the sampler is disengaged.
+    while (sampler_->IsActive()) {
+      TickSample sample;
+
+      // If profiling, we record the pc and sp of the profiled thread.
+      if (sampler_->IsProfiling()) {
+        // Pause the profiled thread and get its context.
+        SuspendThread(profiled_thread_);
+        context.ContextFlags = CONTEXT_FULL;
+        GetThreadContext(profiled_thread_, &context);
+        // Invoke tick handler with program counter and stack pointer.
+        sample.pc = context.Eip;
+        sample.sp = context.Esp;
+        sample.fp = context.Ebp;
+      }
+
+      // We always sample the VM state.
+      sample.state = Logger::state();
+      sampler_->Tick(&sample);
+
+      if (sampler_->IsProfiling()) {
+        ResumeThread(profiled_thread_);
+      }
+
+      // Wait until next sampling.
+      Sleep(sampler_->interval_);
+    }
+  }
+};
+
+
+// Entry point for sampler thread.
+static unsigned int __stdcall SamplerEntry(void* arg) {
+  Sampler::PlatformData* data =
+      reinterpret_cast<Sampler::PlatformData*>(arg);
+  data->Runner();
+  return 0;
+}
+
+
+// Initialize a profile sampler.
+Sampler::Sampler(int interval, bool profiling)
+    : interval_(interval), profiling_(profiling), active_(false) {
+  data_ = new PlatformData(this);
+}
+
+
+Sampler::~Sampler() {
+  delete data_;
+}
+
+
+// Start profiling.
+void Sampler::Start() {
+  // If we are profiling, we need to be able to access the calling
+  // thread.
+  if (IsProfiling()) {
+    // Get a handle to the calling thread. This is the thread that we are
+    // going to profile. We need to make a copy of the handle because we are
+    // going to use it in the sampler thread. Using GetThreadHandle() will
+    // not work in this case. We're using OpenThread because DuplicateHandle
+    // for some reason doesn't work in Chrome's sandbox.
+    data_->profiled_thread_ = OpenThread(THREAD_GET_CONTEXT |
+                                         THREAD_SUSPEND_RESUME |
+                                         THREAD_QUERY_INFORMATION,
+                                         FALSE,
+                                         GetCurrentThreadId());
+    BOOL ok = data_->profiled_thread_ != NULL;
+    if (!ok) return;
+  }
+
+  // Start sampler thread.
+  unsigned int tid;
+  active_ = true;
+  data_->sampler_thread_ = reinterpret_cast<HANDLE>(
+      _beginthreadex(NULL, 0, SamplerEntry, data_, 0, &tid));
+  // Set thread to high priority to increase sampling accuracy.
+  SetThreadPriority(data_->sampler_thread_, THREAD_PRIORITY_TIME_CRITICAL);
+}
+
+
+// Stop profiling.
+void Sampler::Stop() {
+  // Seting active to false triggers termination of the sampler
+  // thread.
+  active_ = false;
+
+  // Wait for sampler thread to terminate.
+  WaitForSingleObject(data_->sampler_thread_, INFINITE);
+
+  // Release the thread handles
+  CloseHandle(data_->sampler_thread_);
+  CloseHandle(data_->profiled_thread_);
+}
+
+
+#endif  // ENABLE_LOGGING_AND_PROFILING
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/platform.h b/deps/v8/src/platform.h
new file mode 100644
index 0000000..db4f2fd
--- /dev/null
+++ b/deps/v8/src/platform.h
@@ -0,0 +1,528 @@
+// 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.
+
+// This module contains the platform-specific code. This make the rest of the
+// code less dependent on operating system, compilers and runtime libraries.
+// This module does specifically not deal with differences between different
+// processor architecture.
+// The platform classes have the same definition for all platforms. The
+// implementation for a particular platform is put in platform_<os>.cc.
+// The build system then uses the implementation for the target platform.
+//
+// This design has been chosen because it is simple and fast. Alternatively,
+// the platform dependent classes could have been implemented using abstract
+// superclasses with virtual methods and having specializations for each
+// platform. This design was rejected because it was more complicated and
+// slower. It would require factory methods for selecting the right
+// implementation and the overhead of virtual methods for performance
+// sensitive like mutex locking/unlocking.
+
+#ifndef V8_PLATFORM_H_
+#define V8_PLATFORM_H_
+
+// Windows specific stuff.
+#ifdef WIN32
+
+// Microsoft Visual C++ specific stuff.
+#ifdef _MSC_VER
+
+enum {
+  FP_NAN,
+  FP_INFINITE,
+  FP_ZERO,
+  FP_SUBNORMAL,
+  FP_NORMAL
+};
+
+#define INFINITY HUGE_VAL
+
+namespace v8 { namespace internal {
+int isfinite(double x);
+} }
+int isnan(double x);
+int isinf(double x);
+int isless(double x, double y);
+int isgreater(double x, double y);
+int fpclassify(double x);
+int signbit(double x);
+
+int strncasecmp(const char* s1, const char* s2, int n);
+
+#endif  // _MSC_VER
+
+// MinGW specific stuff.
+#ifdef __MINGW32__
+
+// Needed for va_list.
+#include <stdarg.h>
+
+#endif  // __MINGW32__
+
+// Random is missing on both Visual Studio and MinGW.
+int random();
+
+#endif  // WIN32
+
+// GCC specific stuff
+#ifdef __GNUC__
+#define __GNUC_VERSION__ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100)
+
+// Unfortunately, the INFINITY macro cannot be used with the '-pedantic'
+// warning flag and certain versions of GCC due to a bug:
+// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11931
+// For now, we use the more involved template-based version from <limits>, but
+// only when compiling with GCC versions affected by the bug (2.96.x - 4.0.x)
+// __GNUC_PREREQ is not defined in GCC for Mac OS X, so we define our own macro
+#if __GNUC_VERSION__ >= 29600 && __GNUC_VERSION__ < 40100
+#include <limits>
+#undef INFINITY
+#define INFINITY std::numeric_limits<double>::infinity()
+#endif
+
+#endif  // __GNUC__
+
+namespace v8 { namespace internal {
+
+double ceiling(double x);
+
+// Forward declarations.
+class Socket;
+
+// ----------------------------------------------------------------------------
+// OS
+//
+// This class has static methods for the different platform specific
+// functions. Add methods here to cope with differences between the
+// supported platforms.
+
+class OS {
+ public:
+  // Initializes the platform OS support. Called once at VM startup.
+  static void Setup();
+
+  // Returns the accumulated user time for thread. This routine
+  // can be used for profiling. The implementation should
+  // strive for high-precision timer resolution, preferable
+  // micro-second resolution.
+  static int GetUserTime(uint32_t* secs,  uint32_t* usecs);
+
+  // Get a tick counter normalized to one tick per microsecond.
+  // Used for calculating time intervals.
+  static int64_t Ticks();
+
+  // Returns current time as the number of milliseconds since
+  // 00:00:00 UTC, January 1, 1970.
+  static double TimeCurrentMillis();
+
+  // Returns a string identifying the current time zone. The
+  // timestamp is used for determining if DST is in effect.
+  static char* LocalTimezone(double time);
+
+  // Returns the local time offset in milliseconds east of UTC without
+  // taking daylight savings time into account.
+  static double LocalTimeOffset();
+
+  // Returns the daylight savings offset for the given time.
+  static double DaylightSavingsOffset(double time);
+
+  static FILE* FOpen(const char* path, const char* mode);
+
+  // Log file open mode is platform-dependent due to line ends issues.
+  static const char* LogFileOpenMode;
+
+  // Print output to console. This is mostly used for debugging output.
+  // On platforms that has standard terminal output, the output
+  // should go to stdout.
+  static void Print(const char* format, ...);
+  static void VPrint(const char* format, va_list args);
+
+  // Print error output to console. This is mostly used for error message
+  // output. On platforms that has standard terminal output, the output
+  // should go to stderr.
+  static void PrintError(const char* format, ...);
+  static void VPrintError(const char* format, va_list args);
+
+  // Allocate/Free memory used by JS heap. Pages are readable/writable, but
+  // they are not guaranteed to be executable unless 'executable' is true.
+  // Returns the address of allocated memory, or NULL if failed.
+  static void* Allocate(const size_t requested,
+                        size_t* allocated,
+                        bool is_executable);
+  static void Free(void* address, const size_t size);
+  // Get the Alignment guaranteed by Allocate().
+  static size_t AllocateAlignment();
+
+#ifdef ENABLE_HEAP_PROTECTION
+  // Protect/unprotect a block of memory by marking it read-only/writable.
+  static void Protect(void* address, size_t size);
+  static void Unprotect(void* address, size_t size, bool is_executable);
+#endif
+
+  // Returns an indication of whether a pointer is in a space that
+  // has been allocated by Allocate().  This method may conservatively
+  // always return false, but giving more accurate information may
+  // improve the robustness of the stack dump code in the presence of
+  // heap corruption.
+  static bool IsOutsideAllocatedSpace(void* pointer);
+
+  // Sleep for a number of milliseconds.
+  static void Sleep(const int milliseconds);
+
+  // Abort the current process.
+  static void Abort();
+
+  // Debug break.
+  static void DebugBreak();
+
+  // Walk the stack.
+  static const int kStackWalkError = -1;
+  static const int kStackWalkMaxNameLen = 256;
+  static const int kStackWalkMaxTextLen = 256;
+  struct StackFrame {
+    void* address;
+    char text[kStackWalkMaxTextLen];
+  };
+
+  static int StackWalk(StackFrame* frames, int frames_size);
+
+  // Factory method for creating platform dependent Mutex.
+  // Please use delete to reclaim the storage for the returned Mutex.
+  static Mutex* CreateMutex();
+
+  // Factory method for creating platform dependent Semaphore.
+  // Please use delete to reclaim the storage for the returned Semaphore.
+  static Semaphore* CreateSemaphore(int count);
+
+  // Factory method for creating platform dependent Socket.
+  // Please use delete to reclaim the storage for the returned Socket.
+  static Socket* CreateSocket();
+
+  class MemoryMappedFile {
+   public:
+    static MemoryMappedFile* create(const char* name, int size, void* initial);
+    virtual ~MemoryMappedFile() { }
+    virtual void* memory() = 0;
+  };
+
+  // Safe formatting print. Ensures that str is always null-terminated.
+  // Returns the number of chars written, or -1 if output was truncated.
+  static int SNPrintF(Vector<char> str, const char* format, ...);
+  static int VSNPrintF(Vector<char> str,
+                       const char* format,
+                       va_list args);
+
+  static char* StrChr(char* str, int c);
+  static void StrNCpy(Vector<char> dest, const char* src, size_t n);
+
+  // Support for profiler.  Can do nothing, in which case ticks
+  // occuring in shared libraries will not be properly accounted
+  // for.
+  static void LogSharedLibraryAddresses();
+
+  // Returns the double constant NAN
+  static double nan_value();
+
+  // Returns the activation frame alignment constraint or zero if
+  // the platform doesn't care. Guaranteed to be a power of two.
+  static int ActivationFrameAlignment();
+
+ private:
+  static const int msPerSecond = 1000;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
+};
+
+
+class VirtualMemory {
+ public:
+  // Reserves virtual memory with size.
+  explicit VirtualMemory(size_t size);
+  ~VirtualMemory();
+
+  // Returns whether the memory has been reserved.
+  bool IsReserved();
+
+  // Returns the start address of the reserved memory.
+  void* address() {
+    ASSERT(IsReserved());
+    return address_;
+  };
+
+  // Returns the size of the reserved memory.
+  size_t size() { return size_; }
+
+  // Commits real memory. Returns whether the operation succeeded.
+  bool Commit(void* address, size_t size, bool is_executable);
+
+  // Uncommit real memory.  Returns whether the operation succeeded.
+  bool Uncommit(void* address, size_t size);
+
+ private:
+  void* address_;  // Start address of the virtual memory.
+  size_t size_;  // Size of the virtual memory.
+};
+
+
+// ----------------------------------------------------------------------------
+// ThreadHandle
+//
+// A ThreadHandle represents a thread identifier for a thread. The ThreadHandle
+// does not own the underlying os handle. Thread handles can be used for
+// refering to threads and testing equality.
+
+class ThreadHandle {
+ public:
+  enum Kind { SELF, INVALID };
+  explicit ThreadHandle(Kind kind);
+
+  // Destructor.
+  ~ThreadHandle();
+
+  // Test for thread running.
+  bool IsSelf() const;
+
+  // Test for valid thread handle.
+  bool IsValid() const;
+
+  // Get platform-specific data.
+  class PlatformData;
+  PlatformData* thread_handle_data() { return data_; }
+
+  // Initialize the handle to kind
+  void Initialize(Kind kind);
+
+ private:
+  PlatformData* data_;  // Captures platform dependent data.
+};
+
+
+// ----------------------------------------------------------------------------
+// Thread
+//
+// Thread objects are used for creating and running threads. When the start()
+// method is called the new thread starts running the run() method in the new
+// thread. The Thread object should not be deallocated before the thread has
+// terminated.
+
+class Thread: public ThreadHandle {
+ public:
+  // Opaque data type for thread-local storage keys.
+  enum LocalStorageKey {};
+
+  // Create new thread.
+  Thread();
+  virtual ~Thread();
+
+  // Start new thread by calling the Run() method in the new thread.
+  void Start();
+
+  // Wait until thread terminates.
+  void Join();
+
+  // Abstract method for run handler.
+  virtual void Run() = 0;
+
+  // Thread-local storage.
+  static LocalStorageKey CreateThreadLocalKey();
+  static void DeleteThreadLocalKey(LocalStorageKey key);
+  static void* GetThreadLocal(LocalStorageKey key);
+  static void SetThreadLocal(LocalStorageKey key, void* value);
+
+  // A hint to the scheduler to let another thread run.
+  static void YieldCPU();
+
+ private:
+  class PlatformData;
+  PlatformData* data_;
+  DISALLOW_COPY_AND_ASSIGN(Thread);
+};
+
+
+// ----------------------------------------------------------------------------
+// Mutex
+//
+// Mutexes are used for serializing access to non-reentrant sections of code.
+// The implementations of mutex should allow for nested/recursive locking.
+
+class Mutex {
+ public:
+  virtual ~Mutex() {}
+
+  // Locks the given mutex. If the mutex is currently unlocked, it becomes
+  // locked and owned by the calling thread, and immediately. If the mutex
+  // is already locked by another thread, suspends the calling thread until
+  // the mutex is unlocked.
+  virtual int Lock() = 0;
+
+  // Unlocks the given mutex. The mutex is assumed to be locked and owned by
+  // the calling thread on entrance.
+  virtual int Unlock() = 0;
+};
+
+
+// ----------------------------------------------------------------------------
+// ScopedLock
+//
+// Stack-allocated ScopedLocks provide block-scoped locking and unlocking
+// of a mutex.
+class ScopedLock {
+ public:
+  explicit ScopedLock(Mutex* mutex): mutex_(mutex) {
+    mutex_->Lock();
+  }
+  ~ScopedLock() {
+    mutex_->Unlock();
+  }
+
+ private:
+  Mutex* mutex_;
+  DISALLOW_COPY_AND_ASSIGN(ScopedLock);
+};
+
+
+// ----------------------------------------------------------------------------
+// Semaphore
+//
+// A semaphore object is a synchronization object that maintains a count. The
+// count is decremented each time a thread completes a wait for the semaphore
+// object and incremented each time a thread signals the semaphore. When the
+// count reaches zero,  threads waiting for the semaphore blocks until the
+// count becomes non-zero.
+
+class Semaphore {
+ public:
+  virtual ~Semaphore() {}
+
+  // Suspends the calling thread until the semaphore counter is non zero
+  // and then decrements the semaphore counter.
+  virtual void Wait() = 0;
+
+  // Suspends the calling thread until the counter is non zero or the timeout
+  // time has passsed. If timeout happens the return value is false and the
+  // counter is unchanged. Otherwise the semaphore counter is decremented and
+  // true is returned. The timeout value is specified in microseconds.
+  virtual bool Wait(int timeout) = 0;
+
+  // Increments the semaphore counter.
+  virtual void Signal() = 0;
+};
+
+
+// ----------------------------------------------------------------------------
+// Socket
+//
+
+class Socket {
+ public:
+  virtual ~Socket() {}
+
+  // Server initialization.
+  virtual bool Bind(const int port) = 0;
+  virtual bool Listen(int backlog) const = 0;
+  virtual Socket* Accept() const = 0;
+
+  // Client initialization.
+  virtual bool Connect(const char* host, const char* port) = 0;
+
+  // Shutdown socket for both read and write. This causes blocking Send and
+  // Receive calls to exit. After Shutdown the Socket object cannot be used for
+  // any communication.
+  virtual bool Shutdown() = 0;
+
+  // Data Transimission
+  virtual int Send(const char* data, int len) const = 0;
+  virtual int Receive(char* data, int len) const = 0;
+
+  // Set the value of the SO_REUSEADDR socket option.
+  virtual bool SetReuseAddress(bool reuse_address) = 0;
+
+  virtual bool IsValid() const = 0;
+
+  static bool Setup();
+  static int LastError();
+  static uint16_t HToN(uint16_t value);
+  static uint16_t NToH(uint16_t value);
+  static uint32_t HToN(uint32_t value);
+  static uint32_t NToH(uint32_t value);
+};
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+// ----------------------------------------------------------------------------
+// Sampler
+//
+// A sampler periodically samples the state of the VM and optionally
+// (if used for profiling) the program counter and stack pointer for
+// the thread that created it.
+
+// TickSample captures the information collected for each sample.
+class TickSample {
+ public:
+  TickSample() : pc(0), sp(0), fp(0), state(OTHER) {}
+  unsigned int pc;  // Instruction pointer.
+  unsigned int sp;  // Stack pointer.
+  unsigned int fp;  // Frame pointer.
+  StateTag state;   // The state of the VM.
+  static const int kMaxFramesCount = 100;
+  EmbeddedVector<Address, kMaxFramesCount> stack;  // Call stack.
+  int frames_count;  // Number of captured frames.
+};
+
+class Sampler {
+ public:
+  // Initialize sampler.
+  explicit Sampler(int interval, bool profiling);
+  virtual ~Sampler();
+
+  // This method is called for each sampling period with the current
+  // program counter.
+  virtual void Tick(TickSample* sample) = 0;
+
+  // Start and stop sampler.
+  void Start();
+  void Stop();
+
+  // Is the sampler used for profiling.
+  inline bool IsProfiling() { return profiling_; }
+
+  class PlatformData;
+ protected:
+  inline bool IsActive() { return active_; }
+
+ private:
+  int interval_;
+  bool profiling_;
+  bool active_;
+  PlatformData* data_;  // Platform specific data.
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
+};
+
+#endif  // ENABLE_LOGGING_AND_PROFILING
+
+} }  // namespace v8::internal
+
+#endif  // V8_PLATFORM_H_
diff --git a/deps/v8/src/prettyprinter.cc b/deps/v8/src/prettyprinter.cc
new file mode 100644
index 0000000..b58000a
--- /dev/null
+++ b/deps/v8/src/prettyprinter.cc
@@ -0,0 +1,1102 @@
+// 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.
+
+#include <stdarg.h>
+
+#include "v8.h"
+
+#include "prettyprinter.h"
+#include "scopes.h"
+#include "platform.h"
+
+namespace v8 { namespace internal {
+
+#ifdef DEBUG
+
+PrettyPrinter::PrettyPrinter() {
+  output_ = NULL;
+  size_ = 0;
+  pos_ = 0;
+}
+
+
+PrettyPrinter::~PrettyPrinter() {
+  DeleteArray(output_);
+}
+
+
+void PrettyPrinter::VisitBlock(Block* node) {
+  if (!node->is_initializer_block()) Print("{ ");
+  PrintStatements(node->statements());
+  if (node->statements()->length() > 0) Print(" ");
+  if (!node->is_initializer_block()) Print("}");
+}
+
+
+void PrettyPrinter::VisitDeclaration(Declaration* node) {
+  Print("var ");
+  PrintLiteral(node->proxy()->name(), false);
+  if (node->fun() != NULL) {
+    Print(" = ");
+    PrintFunctionLiteral(node->fun());
+  }
+  Print(";");
+}
+
+
+void PrettyPrinter::VisitExpressionStatement(ExpressionStatement* node) {
+  Visit(node->expression());
+  Print(";");
+}
+
+
+void PrettyPrinter::VisitEmptyStatement(EmptyStatement* node) {
+  Print(";");
+}
+
+
+void PrettyPrinter::VisitIfStatement(IfStatement* node) {
+  Print("if (");
+  Visit(node->condition());
+  Print(") ");
+  Visit(node->then_statement());
+  if (node->HasElseStatement()) {
+    Print(" else ");
+    Visit(node->else_statement());
+  }
+}
+
+
+void PrettyPrinter::VisitContinueStatement(ContinueStatement* node) {
+  Print("continue");
+  ZoneStringList* labels = node->target()->labels();
+  if (labels != NULL) {
+    Print(" ");
+    ASSERT(labels->length() > 0);  // guaranteed to have at least one entry
+    PrintLiteral(labels->at(0), false);  // any label from the list is fine
+  }
+  Print(";");
+}
+
+
+void PrettyPrinter::VisitBreakStatement(BreakStatement* node) {
+  Print("break");
+  ZoneStringList* labels = node->target()->labels();
+  if (labels != NULL) {
+    Print(" ");
+    ASSERT(labels->length() > 0);  // guaranteed to have at least one entry
+    PrintLiteral(labels->at(0), false);  // any label from the list is fine
+  }
+  Print(";");
+}
+
+
+void PrettyPrinter::VisitReturnStatement(ReturnStatement* node) {
+  Print("return ");
+  Visit(node->expression());
+  Print(";");
+}
+
+
+void PrettyPrinter::VisitWithEnterStatement(WithEnterStatement* node) {
+  Print("<enter with> (");
+  Visit(node->expression());
+  Print(") ");
+}
+
+
+void PrettyPrinter::VisitWithExitStatement(WithExitStatement* node) {
+  Print("<exit with>");
+}
+
+
+void PrettyPrinter::VisitSwitchStatement(SwitchStatement* node) {
+  PrintLabels(node->labels());
+  Print("switch (");
+  Visit(node->tag());
+  Print(") { ");
+  ZoneList<CaseClause*>* cases = node->cases();
+  for (int i = 0; i < cases->length(); i++)
+    PrintCaseClause(cases->at(i));
+  Print("}");
+}
+
+
+void PrettyPrinter::VisitLoopStatement(LoopStatement* node) {
+  PrintLabels(node->labels());
+  switch (node->type()) {
+    case LoopStatement::DO_LOOP:
+      ASSERT(node->init() == NULL);
+      ASSERT(node->next() == NULL);
+      Print("do ");
+      Visit(node->body());
+      Print(" while (");
+      Visit(node->cond());
+      Print(");");
+      break;
+
+    case LoopStatement::FOR_LOOP:
+      Print("for (");
+      if (node->init() != NULL) {
+        Visit(node->init());
+        Print(" ");
+      } else {
+        Print("; ");
+      }
+      if (node->cond() != NULL)
+        Visit(node->cond());
+      Print("; ");
+      if (node->next() != NULL)
+        Visit(node->next());  // prints extra ';', unfortunately
+      // to fix: should use Expression for next
+      Print(") ");
+      Visit(node->body());
+      break;
+
+    case LoopStatement::WHILE_LOOP:
+      ASSERT(node->init() == NULL);
+      ASSERT(node->next() == NULL);
+      Print("while (");
+      Visit(node->cond());
+      Print(") ");
+      Visit(node->body());
+      break;
+  }
+}
+
+
+void PrettyPrinter::VisitForInStatement(ForInStatement* node) {
+  PrintLabels(node->labels());
+  Print("for (");
+  Visit(node->each());
+  Print(" in ");
+  Visit(node->enumerable());
+  Print(") ");
+  Visit(node->body());
+}
+
+
+void PrettyPrinter::VisitTryCatch(TryCatch* node) {
+  Print("try ");
+  Visit(node->try_block());
+  Print(" catch (");
+  Visit(node->catch_var());
+  Print(") ");
+  Visit(node->catch_block());
+}
+
+
+void PrettyPrinter::VisitTryFinally(TryFinally* node) {
+  Print("try ");
+  Visit(node->try_block());
+  Print(" finally ");
+  Visit(node->finally_block());
+}
+
+
+void PrettyPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
+  Print("debugger ");
+}
+
+
+void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
+  Print("(");
+  PrintFunctionLiteral(node);
+  Print(")");
+}
+
+
+void PrettyPrinter::VisitFunctionBoilerplateLiteral(
+    FunctionBoilerplateLiteral* node) {
+  Print("(");
+  PrintLiteral(node->boilerplate(), true);
+  Print(")");
+}
+
+
+void PrettyPrinter::VisitConditional(Conditional* node) {
+  Visit(node->condition());
+  Print(" ? ");
+  Visit(node->then_expression());
+  Print(" : ");
+  Visit(node->else_expression());
+}
+
+
+void PrettyPrinter::VisitLiteral(Literal* node) {
+  PrintLiteral(node->handle(), true);
+}
+
+
+void PrettyPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
+  Print(" RegExp(");
+  PrintLiteral(node->pattern(), false);
+  Print(",");
+  PrintLiteral(node->flags(), false);
+  Print(") ");
+}
+
+
+void PrettyPrinter::VisitObjectLiteral(ObjectLiteral* node) {
+  Print("{ ");
+  for (int i = 0; i < node->properties()->length(); i++) {
+    if (i != 0) Print(",");
+    ObjectLiteral::Property* property = node->properties()->at(i);
+    Print(" ");
+    Visit(property->key());
+    Print(": ");
+    Visit(property->value());
+  }
+  Print(" }");
+}
+
+
+void PrettyPrinter::VisitArrayLiteral(ArrayLiteral* node) {
+  Print("[ ");
+  for (int i = 0; i < node->values()->length(); i++) {
+    if (i != 0) Print(",");
+    Visit(node->values()->at(i));
+  }
+  Print(" ]");
+}
+
+
+void PrettyPrinter::VisitCatchExtensionObject(CatchExtensionObject* node) {
+  Print("{ ");
+  Visit(node->key());
+  Print(": ");
+  Visit(node->value());
+  Print(" }");
+}
+
+
+void PrettyPrinter::VisitSlot(Slot* node) {
+  switch (node->type()) {
+    case Slot::PARAMETER:
+      Print("parameter[%d]", node->index());
+      break;
+    case Slot::LOCAL:
+      Print("frame[%d]", node->index());
+      break;
+    case Slot::CONTEXT:
+      Print(".context[%d]", node->index());
+      break;
+    case Slot::LOOKUP:
+      Print(".context[");
+      PrintLiteral(node->var()->name(), false);
+      Print("]");
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void PrettyPrinter::VisitVariableProxy(VariableProxy* node) {
+  PrintLiteral(node->name(), false);
+}
+
+
+void PrettyPrinter::VisitAssignment(Assignment* node) {
+  Visit(node->target());
+  Print(" %s ", Token::String(node->op()));
+  Visit(node->value());
+}
+
+
+void PrettyPrinter::VisitThrow(Throw* node) {
+  Print("throw ");
+  Visit(node->exception());
+}
+
+
+void PrettyPrinter::VisitProperty(Property* node) {
+  Expression* key = node->key();
+  Literal* literal = key->AsLiteral();
+  if (literal != NULL && literal->handle()->IsSymbol()) {
+    Print("(");
+    Visit(node->obj());
+    Print(").");
+    PrintLiteral(literal->handle(), false);
+  } else {
+    Visit(node->obj());
+    Print("[");
+    Visit(key);
+    Print("]");
+  }
+}
+
+
+void PrettyPrinter::VisitCall(Call* node) {
+  Visit(node->expression());
+  PrintArguments(node->arguments());
+}
+
+
+void PrettyPrinter::VisitCallEval(CallEval* node) {
+  VisitCall(node);
+}
+
+
+void PrettyPrinter::VisitCallNew(CallNew* node) {
+  Print("new (");
+  Visit(node->expression());
+  Print(")");
+  PrintArguments(node->arguments());
+}
+
+
+void PrettyPrinter::VisitCallRuntime(CallRuntime* node) {
+  Print("%%");
+  PrintLiteral(node->name(), false);
+  PrintArguments(node->arguments());
+}
+
+
+void PrettyPrinter::VisitUnaryOperation(UnaryOperation* node) {
+  Print("(%s", Token::String(node->op()));
+  Visit(node->expression());
+  Print(")");
+}
+
+
+void PrettyPrinter::VisitCountOperation(CountOperation* node) {
+  Print("(");
+  if (node->is_prefix()) Print("%s", Token::String(node->op()));
+  Visit(node->expression());
+  if (node->is_postfix()) Print("%s", Token::String(node->op()));
+  Print(")");
+}
+
+
+void PrettyPrinter::VisitBinaryOperation(BinaryOperation* node) {
+  Print("(");
+  Visit(node->left());
+  Print("%s", Token::String(node->op()));
+  Visit(node->right());
+  Print(")");
+}
+
+
+void PrettyPrinter::VisitCompareOperation(CompareOperation* node) {
+  Print("(");
+  Visit(node->left());
+  Print("%s", Token::String(node->op()));
+  Visit(node->right());
+  Print(")");
+}
+
+
+void PrettyPrinter::VisitThisFunction(ThisFunction* node) {
+  Print("<this-function>");
+}
+
+
+const char* PrettyPrinter::Print(Node* node) {
+  Init();
+  Visit(node);
+  return output_;
+}
+
+
+const char* PrettyPrinter::PrintExpression(FunctionLiteral* program) {
+  Init();
+  ExpressionStatement* statement =
+    program->body()->at(0)->AsExpressionStatement();
+  Visit(statement->expression());
+  return output_;
+}
+
+
+const char* PrettyPrinter::PrintProgram(FunctionLiteral* program) {
+  Init();
+  PrintStatements(program->body());
+  Print("\n");
+  return output_;
+}
+
+
+void PrettyPrinter::PrintOut(Node* node) {
+  PrettyPrinter printer;
+  PrintF("%s", printer.Print(node));
+}
+
+
+void PrettyPrinter::Init() {
+  if (size_ == 0) {
+    ASSERT(output_ == NULL);
+    const int initial_size = 256;
+    output_ = NewArray<char>(initial_size);
+    size_ = initial_size;
+  }
+  output_[0] = '\0';
+  pos_ = 0;
+}
+
+
+void PrettyPrinter::Print(const char* format, ...) {
+  for (;;) {
+    va_list arguments;
+    va_start(arguments, format);
+    int n = OS::VSNPrintF(Vector<char>(output_, size_) + pos_,
+                          format,
+                          arguments);
+    va_end(arguments);
+
+    if (n >= 0) {
+      // there was enough space - we are done
+      pos_ += n;
+      return;
+    } else {
+      // there was not enough space - allocate more and try again
+      const int slack = 32;
+      int new_size = size_ + (size_ >> 1) + slack;
+      char* new_output = NewArray<char>(new_size);
+      memcpy(new_output, output_, pos_);
+      DeleteArray(output_);
+      output_ = new_output;
+      size_ = new_size;
+    }
+  }
+}
+
+
+void PrettyPrinter::PrintStatements(ZoneList<Statement*>* statements) {
+  for (int i = 0; i < statements->length(); i++) {
+    if (i != 0) Print(" ");
+    Visit(statements->at(i));
+  }
+}
+
+
+void PrettyPrinter::PrintLabels(ZoneStringList* labels) {
+  if (labels != NULL) {
+    for (int i = 0; i < labels->length(); i++) {
+      PrintLiteral(labels->at(i), false);
+      Print(": ");
+    }
+  }
+}
+
+
+void PrettyPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
+  Print("(");
+  for (int i = 0; i < arguments->length(); i++) {
+    if (i != 0) Print(", ");
+    Visit(arguments->at(i));
+  }
+  Print(")");
+}
+
+
+void PrettyPrinter::PrintLiteral(Handle<Object> value, bool quote) {
+  Object* object = *value;
+  if (object->IsString()) {
+    String* string = String::cast(object);
+    if (quote) Print("\"");
+    for (int i = 0; i < string->length(); i++) {
+      Print("%c", string->Get(i));
+    }
+    if (quote) Print("\"");
+  } else if (object == Heap::null_value()) {
+    Print("null");
+  } else if (object == Heap::true_value()) {
+    Print("true");
+  } else if (object == Heap::false_value()) {
+    Print("false");
+  } else if (object == Heap::undefined_value()) {
+    Print("undefined");
+  } else if (object->IsNumber()) {
+    Print("%g", object->Number());
+  } else if (object->IsJSObject()) {
+    // regular expression
+    if (object->IsJSFunction()) {
+      Print("JS-Function");
+    } else if (object->IsJSArray()) {
+      Print("JS-array[%u]", JSArray::cast(object)->length());
+    } else if (object->IsJSObject()) {
+      Print("JS-Object");
+    } else {
+      Print("?UNKNOWN?");
+    }
+  } else if (object->IsFixedArray()) {
+    Print("FixedArray");
+  } else {
+    Print("<unknown literal %p>", object);
+  }
+}
+
+
+void PrettyPrinter::PrintParameters(Scope* scope) {
+  Print("(");
+  for (int i = 0; i < scope->num_parameters(); i++) {
+    if (i  > 0) Print(", ");
+    PrintLiteral(scope->parameter(i)->name(), false);
+  }
+  Print(")");
+}
+
+
+void PrettyPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) {
+  for (int i = 0; i < declarations->length(); i++) {
+    if (i > 0) Print(" ");
+    Visit(declarations->at(i));
+  }
+}
+
+
+void PrettyPrinter::PrintFunctionLiteral(FunctionLiteral* function) {
+  Print("function ");
+  PrintLiteral(function->name(), false);
+  PrintParameters(function->scope());
+  Print(" { ");
+  PrintDeclarations(function->scope()->declarations());
+  PrintStatements(function->body());
+  Print(" }");
+}
+
+
+void PrettyPrinter::PrintCaseClause(CaseClause* clause) {
+  if (clause->is_default()) {
+    Print("default");
+  } else {
+    Print("case ");
+    Visit(clause->label());
+  }
+  Print(": ");
+  PrintStatements(clause->statements());
+  if (clause->statements()->length() > 0)
+    Print(" ");
+}
+
+
+//-----------------------------------------------------------------------------
+
+class IndentedScope BASE_EMBEDDED {
+ public:
+  IndentedScope() {
+    ast_printer_->inc_indent();
+  }
+
+  explicit IndentedScope(const char* txt, SmiAnalysis* type = NULL) {
+    ast_printer_->PrintIndented(txt);
+    if ((type != NULL) && (type->IsKnown())) {
+      ast_printer_->Print(" (type = ");
+      ast_printer_->Print(SmiAnalysis::Type2String(type));
+      ast_printer_->Print(")");
+    }
+    ast_printer_->Print("\n");
+    ast_printer_->inc_indent();
+  }
+
+  virtual ~IndentedScope() {
+    ast_printer_->dec_indent();
+  }
+
+  static void SetAstPrinter(AstPrinter* a) { ast_printer_ = a; }
+
+ private:
+  static AstPrinter* ast_printer_;
+};
+
+
+AstPrinter* IndentedScope::ast_printer_ = NULL;
+
+
+//-----------------------------------------------------------------------------
+
+int AstPrinter::indent_ = 0;
+
+
+AstPrinter::AstPrinter() {
+  ASSERT(indent_ == 0);
+  IndentedScope::SetAstPrinter(this);
+}
+
+
+AstPrinter::~AstPrinter() {
+  ASSERT(indent_ == 0);
+  IndentedScope::SetAstPrinter(NULL);
+}
+
+
+void AstPrinter::PrintIndented(const char* txt) {
+  for (int i = 0; i < indent_; i++) {
+    Print(". ");
+  }
+  Print(txt);
+}
+
+
+void AstPrinter::PrintLiteralIndented(const char* info,
+                                      Handle<Object> value,
+                                      bool quote) {
+  PrintIndented(info);
+  Print(" ");
+  PrintLiteral(value, quote);
+  Print("\n");
+}
+
+
+void AstPrinter::PrintLiteralWithModeIndented(const char* info,
+                                              Variable* var,
+                                              Handle<Object> value,
+                                              SmiAnalysis* type) {
+  if (var == NULL) {
+    PrintLiteralIndented(info, value, true);
+  } else {
+    EmbeddedVector<char, 256> buf;
+    if (type->IsKnown()) {
+      OS::SNPrintF(buf, "%s (mode = %s, type = %s)", info,
+                   Variable::Mode2String(var->mode()),
+                   SmiAnalysis::Type2String(type));
+    } else {
+      OS::SNPrintF(buf, "%s (mode = %s)", info,
+                   Variable::Mode2String(var->mode()));
+    }
+    PrintLiteralIndented(buf.start(), value, true);
+  }
+}
+
+
+void AstPrinter::PrintLabelsIndented(const char* info, ZoneStringList* labels) {
+  if (labels != NULL && labels->length() > 0) {
+    if (info == NULL) {
+      PrintIndented("LABELS ");
+    } else {
+      PrintIndented(info);
+      Print(" ");
+    }
+    PrintLabels(labels);
+    Print("\n");
+  } else if (info != NULL) {
+    PrintIndented(info);
+  }
+}
+
+
+void AstPrinter::PrintIndentedVisit(const char* s, Node* node) {
+  IndentedScope indent(s);
+  Visit(node);
+}
+
+
+const char* AstPrinter::PrintProgram(FunctionLiteral* program) {
+  Init();
+  { IndentedScope indent("FUNC");
+    PrintLiteralIndented("NAME", program->name(), true);
+    PrintLiteralIndented("INFERRED NAME", program->inferred_name(), true);
+    PrintParameters(program->scope());
+    PrintDeclarations(program->scope()->declarations());
+    PrintStatements(program->body());
+  }
+  return Output();
+}
+
+
+void AstPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) {
+  if (declarations->length() > 0) {
+    IndentedScope indent("DECLS");
+    for (int i = 0; i < declarations->length(); i++) {
+      Visit(declarations->at(i));
+    }
+  }
+}
+
+
+void AstPrinter::PrintParameters(Scope* scope) {
+  if (scope->num_parameters() > 0) {
+    IndentedScope indent("PARAMS");
+    for (int i = 0; i < scope->num_parameters(); i++) {
+      PrintLiteralWithModeIndented("VAR", scope->parameter(i),
+                                   scope->parameter(i)->name(),
+                                   scope->parameter(i)->type());
+    }
+  }
+}
+
+
+void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) {
+  for (int i = 0; i < statements->length(); i++) {
+    Visit(statements->at(i));
+  }
+}
+
+
+void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
+  for (int i = 0; i < arguments->length(); i++) {
+    Visit(arguments->at(i));
+  }
+}
+
+
+void AstPrinter::PrintCaseClause(CaseClause* clause) {
+  if (clause->is_default()) {
+    IndentedScope indent("DEFAULT");
+    PrintStatements(clause->statements());
+  } else {
+    IndentedScope indent("CASE");
+    Visit(clause->label());
+    PrintStatements(clause->statements());
+  }
+}
+
+
+void AstPrinter::VisitBlock(Block* node) {
+  const char* block_txt = node->is_initializer_block() ? "BLOCK INIT" : "BLOCK";
+  IndentedScope indent(block_txt);
+  PrintStatements(node->statements());
+}
+
+
+void AstPrinter::VisitDeclaration(Declaration* node) {
+  if (node->fun() == NULL) {
+    // var or const declarations
+    PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()),
+                                 node->proxy()->AsVariable(),
+                                 node->proxy()->name(),
+                                 node->proxy()->AsVariable()->type());
+  } else {
+    // function declarations
+    PrintIndented("FUNCTION ");
+    PrintLiteral(node->proxy()->name(), true);
+    Print(" = function ");
+    PrintLiteral(node->fun()->name(), false);
+    Print("\n");
+  }
+}
+
+
+void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) {
+  Visit(node->expression());
+}
+
+
+void AstPrinter::VisitEmptyStatement(EmptyStatement* node) {
+  PrintIndented("EMPTY\n");
+}
+
+
+void AstPrinter::VisitIfStatement(IfStatement* node) {
+  PrintIndentedVisit("IF", node->condition());
+  PrintIndentedVisit("THEN", node->then_statement());
+  if (node->HasElseStatement()) {
+    PrintIndentedVisit("ELSE", node->else_statement());
+  }
+}
+
+
+void AstPrinter::VisitContinueStatement(ContinueStatement* node) {
+  PrintLabelsIndented("CONTINUE", node->target()->labels());
+}
+
+
+void AstPrinter::VisitBreakStatement(BreakStatement* node) {
+  PrintLabelsIndented("BREAK", node->target()->labels());
+}
+
+
+void AstPrinter::VisitReturnStatement(ReturnStatement* node) {
+  PrintIndentedVisit("RETURN", node->expression());
+}
+
+
+void AstPrinter::VisitWithEnterStatement(WithEnterStatement* node) {
+  PrintIndentedVisit("WITH ENTER", node->expression());
+}
+
+
+void AstPrinter::VisitWithExitStatement(WithExitStatement* node) {
+  PrintIndented("WITH EXIT\n");
+}
+
+
+void AstPrinter::VisitSwitchStatement(SwitchStatement* node) {
+  IndentedScope indent("SWITCH");
+  PrintLabelsIndented(NULL, node->labels());
+  PrintIndentedVisit("TAG", node->tag());
+  for (int i = 0; i < node->cases()->length(); i++) {
+    PrintCaseClause(node->cases()->at(i));
+  }
+}
+
+
+void AstPrinter::VisitLoopStatement(LoopStatement* node) {
+  IndentedScope indent(node->OperatorString());
+  PrintLabelsIndented(NULL, node->labels());
+  if (node->init()) PrintIndentedVisit("INIT", node->init());
+  if (node->cond()) PrintIndentedVisit("COND", node->cond());
+  if (node->body()) PrintIndentedVisit("BODY", node->body());
+  if (node->next()) PrintIndentedVisit("NEXT", node->next());
+}
+
+
+void AstPrinter::VisitForInStatement(ForInStatement* node) {
+  IndentedScope indent("FOR IN");
+  PrintIndentedVisit("FOR", node->each());
+  PrintIndentedVisit("IN", node->enumerable());
+  PrintIndentedVisit("BODY", node->body());
+}
+
+
+void AstPrinter::VisitTryCatch(TryCatch* node) {
+  IndentedScope indent("TRY CATCH");
+  PrintIndentedVisit("TRY", node->try_block());
+  PrintIndentedVisit("CATCHVAR", node->catch_var());
+  PrintIndentedVisit("CATCH", node->catch_block());
+}
+
+
+void AstPrinter::VisitTryFinally(TryFinally* node) {
+  IndentedScope indent("TRY FINALLY");
+  PrintIndentedVisit("TRY", node->try_block());
+  PrintIndentedVisit("FINALLY", node->finally_block());
+}
+
+
+void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
+  IndentedScope indent("DEBUGGER");
+}
+
+
+void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
+  IndentedScope indent("FUNC LITERAL");
+  PrintLiteralIndented("NAME", node->name(), false);
+  PrintLiteralIndented("INFERRED NAME", node->inferred_name(), false);
+  PrintParameters(node->scope());
+  // We don't want to see the function literal in this case: it
+  // will be printed via PrintProgram when the code for it is
+  // generated.
+  // PrintStatements(node->body());
+}
+
+
+void AstPrinter::VisitFunctionBoilerplateLiteral(
+    FunctionBoilerplateLiteral* node) {
+  IndentedScope indent("FUNC LITERAL");
+  PrintLiteralIndented("BOILERPLATE", node->boilerplate(), true);
+}
+
+
+void AstPrinter::VisitConditional(Conditional* node) {
+  IndentedScope indent("CONDITIONAL");
+  PrintIndentedVisit("?", node->condition());
+  PrintIndentedVisit("THEN", node->then_expression());
+  PrintIndentedVisit("ELSE", node->else_expression());
+}
+
+
+void AstPrinter::VisitLiteral(Literal* node) {
+  PrintLiteralIndented("LITERAL", node->handle(), true);
+}
+
+
+void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
+  IndentedScope indent("REGEXP LITERAL");
+  PrintLiteral(node->pattern(), false);
+  Print(",");
+  PrintLiteral(node->flags(), false);
+}
+
+
+void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) {
+  IndentedScope indent("OBJ LITERAL");
+  for (int i = 0; i < node->properties()->length(); i++) {
+    const char* prop_kind = NULL;
+    switch (node->properties()->at(i)->kind()) {
+      case ObjectLiteral::Property::CONSTANT:
+        prop_kind = "PROPERTY - CONSTANT";
+        break;
+      case ObjectLiteral::Property::COMPUTED:
+        prop_kind = "PROPERTY - COMPUTED";
+        break;
+      case ObjectLiteral::Property::PROTOTYPE:
+        prop_kind = "PROPERTY - PROTOTYPE";
+        break;
+      case ObjectLiteral::Property::GETTER:
+        prop_kind = "PROPERTY - GETTER";
+        break;
+      case ObjectLiteral::Property::SETTER:
+        prop_kind = "PROPERTY - SETTER";
+        break;
+      default:
+        UNREACHABLE();
+        break;
+    }
+    IndentedScope prop(prop_kind);
+    PrintIndentedVisit("KEY", node->properties()->at(i)->key());
+    PrintIndentedVisit("VALUE", node->properties()->at(i)->value());
+  }
+}
+
+
+void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) {
+  IndentedScope indent("ARRAY LITERAL");
+  if (node->values()->length() > 0) {
+    IndentedScope indent("VALUES");
+    for (int i = 0; i < node->values()->length(); i++) {
+      Visit(node->values()->at(i));
+    }
+  }
+}
+
+
+void AstPrinter::VisitCatchExtensionObject(CatchExtensionObject* node) {
+  IndentedScope indent("CatchExtensionObject");
+  PrintIndentedVisit("KEY", node->key());
+  PrintIndentedVisit("VALUE", node->value());
+}
+
+
+void AstPrinter::VisitSlot(Slot* node) {
+  PrintIndented("SLOT ");
+  switch (node->type()) {
+    case Slot::PARAMETER:
+      Print("parameter[%d]", node->index());
+      break;
+    case Slot::LOCAL:
+      Print("frame[%d]", node->index());
+      break;
+    case Slot::CONTEXT:
+      Print(".context[%d]", node->index());
+      break;
+    case Slot::LOOKUP:
+      Print(".context[");
+      PrintLiteral(node->var()->name(), false);
+      Print("]");
+      break;
+    default:
+      UNREACHABLE();
+  }
+  Print("\n");
+}
+
+
+void AstPrinter::VisitVariableProxy(VariableProxy* node) {
+  PrintLiteralWithModeIndented("VAR PROXY", node->AsVariable(), node->name(),
+                               node->type());
+  Variable* var = node->var();
+  if (var != NULL && var->rewrite() != NULL) {
+    IndentedScope indent;
+    Visit(var->rewrite());
+  }
+}
+
+
+void AstPrinter::VisitAssignment(Assignment* node) {
+  IndentedScope indent(Token::Name(node->op()), node->type());
+  Visit(node->target());
+  Visit(node->value());
+}
+
+
+void AstPrinter::VisitThrow(Throw* node) {
+  PrintIndentedVisit("THROW", node->exception());
+}
+
+
+void AstPrinter::VisitProperty(Property* node) {
+  IndentedScope indent("PROPERTY");
+  Visit(node->obj());
+  Literal* literal = node->key()->AsLiteral();
+  if (literal != NULL && literal->handle()->IsSymbol()) {
+    PrintLiteralIndented("NAME", literal->handle(), false);
+  } else {
+    PrintIndentedVisit("KEY", node->key());
+  }
+}
+
+
+void AstPrinter::VisitCall(Call* node) {
+  IndentedScope indent("CALL");
+  Visit(node->expression());
+  PrintArguments(node->arguments());
+}
+
+
+void AstPrinter::VisitCallEval(CallEval* node) {
+  VisitCall(node);
+}
+
+
+void AstPrinter::VisitCallNew(CallNew* node) {
+  IndentedScope indent("CALL NEW");
+  Visit(node->expression());
+  PrintArguments(node->arguments());
+}
+
+
+void AstPrinter::VisitCallRuntime(CallRuntime* node) {
+  PrintLiteralIndented("CALL RUNTIME ", node->name(), false);
+  IndentedScope indent;
+  PrintArguments(node->arguments());
+}
+
+
+void AstPrinter::VisitUnaryOperation(UnaryOperation* node) {
+  PrintIndentedVisit(Token::Name(node->op()), node->expression());
+}
+
+
+void AstPrinter::VisitCountOperation(CountOperation* node) {
+  EmbeddedVector<char, 128> buf;
+  if (node->type()->IsKnown()) {
+    OS::SNPrintF(buf, "%s %s (type = %s)",
+                 (node->is_prefix() ? "PRE" : "POST"),
+                 Token::Name(node->op()),
+                 SmiAnalysis::Type2String(node->type()));
+  } else {
+    OS::SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"),
+                 Token::Name(node->op()));
+  }
+  PrintIndentedVisit(buf.start(), node->expression());
+}
+
+
+void AstPrinter::VisitBinaryOperation(BinaryOperation* node) {
+  IndentedScope indent(Token::Name(node->op()), node->type());
+  Visit(node->left());
+  Visit(node->right());
+}
+
+
+void AstPrinter::VisitCompareOperation(CompareOperation* node) {
+  IndentedScope indent(Token::Name(node->op()), node->type());
+  Visit(node->left());
+  Visit(node->right());
+}
+
+
+void AstPrinter::VisitThisFunction(ThisFunction* node) {
+  IndentedScope indent("THIS-FUNCTION");
+}
+
+
+
+#endif  // DEBUG
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/prettyprinter.h b/deps/v8/src/prettyprinter.h
new file mode 100644
index 0000000..720fe7b
--- /dev/null
+++ b/deps/v8/src/prettyprinter.h
@@ -0,0 +1,118 @@
+// 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_PRETTYPRINTER_H_
+#define V8_PRETTYPRINTER_H_
+
+#include "ast.h"
+
+namespace v8 { namespace internal {
+
+#ifdef DEBUG
+
+class PrettyPrinter: public AstVisitor {
+ public:
+  PrettyPrinter();
+  virtual ~PrettyPrinter();
+
+  // The following routines print a node into a string.
+  // The result string is alive as long as the PrettyPrinter is alive.
+  const char* Print(Node* node);
+  const char* PrintExpression(FunctionLiteral* program);
+  const char* PrintProgram(FunctionLiteral* program);
+
+  // Print a node to stdout.
+  static void PrintOut(Node* node);
+
+  // Individual nodes
+#define DEF_VISIT(type)                         \
+  virtual void Visit##type(type* node);
+  NODE_LIST(DEF_VISIT)
+#undef DEF_VISIT
+
+ private:
+  char* output_;  // output string buffer
+  int size_;  // output_ size
+  int pos_;  // current printing position
+
+ protected:
+  void Init();
+  void Print(const char* format, ...);
+  const char* Output() const { return output_; }
+
+  virtual void PrintStatements(ZoneList<Statement*>* statements);
+  void PrintLabels(ZoneStringList* labels);
+  virtual void PrintArguments(ZoneList<Expression*>* arguments);
+  void PrintLiteral(Handle<Object> value, bool quote);
+  void PrintParameters(Scope* scope);
+  void PrintDeclarations(ZoneList<Declaration*>* declarations);
+  void PrintFunctionLiteral(FunctionLiteral* function);
+  void PrintCaseClause(CaseClause* clause);
+};
+
+
+// Prints the AST structure
+class AstPrinter: public PrettyPrinter {
+ public:
+  AstPrinter();
+  virtual ~AstPrinter();
+
+  const char* PrintProgram(FunctionLiteral* program);
+
+  // Individual nodes
+#define DEF_VISIT(type)                         \
+  virtual void Visit##type(type* node);
+  NODE_LIST(DEF_VISIT)
+#undef DEF_VISIT
+ private:
+  friend class IndentedScope;
+  void PrintIndented(const char* txt);
+  void PrintIndentedVisit(const char* s, Node* node);
+
+  void PrintStatements(ZoneList<Statement*>* statements);
+  void PrintDeclarations(ZoneList<Declaration*>* declarations);
+  void PrintParameters(Scope* scope);
+  void PrintArguments(ZoneList<Expression*>* arguments);
+  void PrintCaseClause(CaseClause* clause);
+  void PrintLiteralIndented(const char* info, Handle<Object> value, bool quote);
+  void PrintLiteralWithModeIndented(const char* info,
+                                    Variable* var,
+                                    Handle<Object> value,
+                                    SmiAnalysis* type);
+  void PrintLabelsIndented(const char* info, ZoneStringList* labels);
+
+  void inc_indent() { indent_++; }
+  void dec_indent() { indent_--; }
+
+  static int indent_;
+};
+
+#endif  // DEBUG
+
+} }  // namespace v8::internal
+
+#endif  // V8_PRETTYPRINTER_H_
diff --git a/deps/v8/src/property.cc b/deps/v8/src/property.cc
new file mode 100644
index 0000000..6c21530
--- /dev/null
+++ b/deps/v8/src/property.cc
@@ -0,0 +1,109 @@
+// 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.
+
+#include "v8.h"
+
+namespace v8 { namespace internal {
+
+
+void DescriptorWriter::Write(Descriptor* desc) {
+  ASSERT(desc->key_->IsSymbol());
+  descriptors_->Set(pos_, desc);
+  advance();
+}
+
+
+void DescriptorWriter::WriteFrom(DescriptorReader* reader) {
+  Descriptor desc;
+  reader->Get(&desc);
+  Write(&desc);
+}
+
+
+#ifdef DEBUG
+void LookupResult::Print() {
+  if (!IsValid()) {
+    PrintF("Not Found\n");
+    return;
+  }
+
+  PrintF("LookupResult:\n");
+  PrintF(" -cacheable = %s\n", IsCacheable() ? "true" : "false");
+  PrintF(" -attributes = %x\n", GetAttributes());
+  switch (type()) {
+    case NORMAL:
+      PrintF(" -type = normal\n");
+      PrintF(" -entry = %d", GetDictionaryEntry());
+      break;
+    case MAP_TRANSITION:
+      PrintF(" -type = map transition\n");
+      PrintF(" -map:\n");
+      GetTransitionMap()->Print();
+      PrintF("\n");
+      break;
+    case CONSTANT_FUNCTION:
+      PrintF(" -type = constant function\n");
+      PrintF(" -function:\n");
+      GetConstantFunction()->Print();
+      PrintF("\n");
+      break;
+    case FIELD:
+      PrintF(" -type = field\n");
+      PrintF(" -index = %d", GetFieldIndex());
+      PrintF("\n");
+      break;
+    case CALLBACKS:
+      PrintF(" -type = call backs\n");
+      PrintF(" -callback object:\n");
+      GetCallbackObject()->Print();
+      break;
+    case INTERCEPTOR:
+      PrintF(" -type = lookup interceptor\n");
+      break;
+    case CONSTANT_TRANSITION:
+      PrintF(" -type = constant property transition\n");
+      break;
+    case NULL_DESCRIPTOR:
+      PrintF(" =type = null descriptor\n");
+      break;
+  }
+}
+
+
+void Descriptor::Print() {
+  PrintF("Descriptor ");
+  GetKey()->ShortPrint();
+  PrintF(" @ ");
+  GetValue()->ShortPrint();
+  PrintF(" %d\n", GetDetails().index());
+}
+
+
+#endif
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/property.h b/deps/v8/src/property.h
new file mode 100644
index 0000000..65d4a0d
--- /dev/null
+++ b/deps/v8/src/property.h
@@ -0,0 +1,396 @@
+// 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_PROPERTY_H_
+#define V8_PROPERTY_H_
+
+namespace v8 { namespace internal {
+
+
+// Abstraction for elements in instance-descriptor arrays.
+//
+// Each descriptor has a key, property attributes, property type,
+// property index (in the actual instance-descriptor array) and
+// optionally a piece of data.
+//
+
+class Descriptor BASE_EMBEDDED {
+ public:
+  static int IndexFromValue(Object* value) {
+    return Smi::cast(value)->value();
+  }
+
+  Object* KeyToSymbol() {
+    if (!StringShape(key_).IsSymbol()) {
+      Object* result = Heap::LookupSymbol(key_);
+      if (result->IsFailure()) return result;
+      key_ = String::cast(result);
+    }
+    return key_;
+  }
+
+  String* GetKey() { return key_; }
+  Object* GetValue() { return value_; }
+  PropertyDetails GetDetails() { return details_; }
+
+#ifdef DEBUG
+  void Print();
+#endif
+
+  void SetEnumerationIndex(int index) {
+    ASSERT(PropertyDetails::IsValidIndex(index));
+    details_ = PropertyDetails(details_.attributes(), details_.type(), index);
+  }
+
+ private:
+  String* key_;
+  Object* value_;
+  PropertyDetails details_;
+
+ protected:
+  Descriptor() : details_(Smi::FromInt(0)) {}
+
+  void Init(String* key, Object* value, PropertyDetails details) {
+    key_ = key;
+    value_ = value;
+    details_ = details;
+  }
+
+  Descriptor(String* key, Object* value, PropertyDetails details)
+      : key_(key),
+        value_(value),
+        details_(details) { }
+
+  Descriptor(String* key,
+             Object* value,
+             PropertyAttributes attributes,
+             PropertyType type,
+             int index = 0)
+      : key_(key),
+        value_(value),
+        details_(attributes, type, index) { }
+
+  friend class DescriptorWriter;
+  friend class DescriptorReader;
+  friend class DescriptorArray;
+};
+
+// A pointer from a map to the new map that is created by adding
+// a named property.  These are key to the speed and functioning of V8.
+// The two maps should always have the same prototype, since
+// MapSpace::CreateBackPointers depends on this.
+class MapTransitionDescriptor: public Descriptor {
+ public:
+  MapTransitionDescriptor(String* key, Map* map, PropertyAttributes attributes)
+      : Descriptor(key, map, attributes, MAP_TRANSITION) { }
+};
+
+// Marks a field name in a map so that adding the field is guaranteed
+// to create a FIELD descriptor in the new map.  Used after adding
+// a constant function the first time, creating a CONSTANT_FUNCTION
+// descriptor in the new map.  This avoids creating multiple maps with
+// the same CONSTANT_FUNCTION field.
+class ConstTransitionDescriptor: public Descriptor {
+ public:
+  explicit ConstTransitionDescriptor(String* key)
+      : Descriptor(key, Smi::FromInt(0), NONE, CONSTANT_TRANSITION) { }
+};
+
+
+class FieldDescriptor: public Descriptor {
+ public:
+  FieldDescriptor(String* key,
+                  int field_index,
+                  PropertyAttributes attributes,
+                  int index = 0)
+      : Descriptor(key, Smi::FromInt(field_index), attributes, FIELD, index) {}
+};
+
+
+class ConstantFunctionDescriptor: public Descriptor {
+ public:
+  ConstantFunctionDescriptor(String* key,
+                             JSFunction* function,
+                             PropertyAttributes attributes,
+                             int index = 0)
+      : Descriptor(key, function, attributes, CONSTANT_FUNCTION, index) {}
+};
+
+
+class CallbacksDescriptor:  public Descriptor {
+ public:
+  CallbacksDescriptor(String* key,
+                      Object* proxy,
+                      PropertyAttributes attributes,
+                      int index = 0)
+      : Descriptor(key, proxy, attributes, CALLBACKS, index) {}
+};
+
+
+class LookupResult BASE_EMBEDDED {
+ public:
+  // Where did we find the result;
+  enum {
+    NOT_FOUND,
+    DESCRIPTOR_TYPE,
+    DICTIONARY_TYPE,
+    INTERCEPTOR_TYPE,
+    CONSTANT_TYPE
+  } lookup_type_;
+
+  LookupResult()
+      : lookup_type_(NOT_FOUND),
+        cacheable_(true),
+        details_(NONE, NORMAL) {}
+
+  void DescriptorResult(JSObject* holder, PropertyDetails details, int number) {
+    lookup_type_ = DESCRIPTOR_TYPE;
+    holder_ = holder;
+    details_ = details;
+    number_ = number;
+  }
+
+  void ConstantResult(JSObject* holder) {
+    lookup_type_ = CONSTANT_TYPE;
+    holder_ = holder;
+    details_ =
+        PropertyDetails(static_cast<PropertyAttributes>(DONT_ENUM |
+                                                        DONT_DELETE),
+                        CALLBACKS);
+    number_ = -1;
+  }
+
+  void DictionaryResult(JSObject* holder, int entry) {
+    lookup_type_ = DICTIONARY_TYPE;
+    holder_ = holder;
+    details_ = holder->property_dictionary()->DetailsAt(entry);
+    number_ = entry;
+  }
+
+  void InterceptorResult(JSObject* holder) {
+    lookup_type_ = INTERCEPTOR_TYPE;
+    holder_ = holder;
+    details_ = PropertyDetails(NONE, INTERCEPTOR);
+  }
+
+  void NotFound() {
+    lookup_type_ = NOT_FOUND;
+  }
+
+  JSObject* holder() {
+    ASSERT(IsValid());
+    return holder_;
+  }
+
+  PropertyType type() {
+    ASSERT(IsValid());
+    return details_.type();
+  }
+
+  bool IsTransitionType() {
+    PropertyType t = type();
+    if (t == MAP_TRANSITION || t == CONSTANT_TRANSITION) return true;
+    return false;
+  }
+
+  PropertyAttributes GetAttributes() {
+    ASSERT(IsValid());
+    return details_.attributes();
+  }
+
+  PropertyDetails GetPropertyDetails() {
+    return details_;
+  }
+
+  bool IsReadOnly() { return details_.IsReadOnly(); }
+  bool IsDontDelete() { return details_.IsDontDelete(); }
+  bool IsDontEnum() { return details_.IsDontEnum(); }
+
+  bool IsValid() { return  lookup_type_ != NOT_FOUND; }
+  bool IsNotFound() { return lookup_type_ == NOT_FOUND; }
+
+  // Tells whether the result is a property.
+  // Excluding transitions and the null descriptor.
+  bool IsProperty() {
+    return IsValid() && type() < FIRST_PHANTOM_PROPERTY_TYPE;
+  }
+
+  bool IsCacheable() { return cacheable_; }
+  void DisallowCaching() { cacheable_ = false; }
+
+  // Tells whether the value needs to be loaded.
+  bool IsLoaded() {
+    if (lookup_type_ == DESCRIPTOR_TYPE || lookup_type_ == DICTIONARY_TYPE) {
+      Object* value = GetValue();
+      if (value->IsJSFunction()) {
+        return JSFunction::cast(value)->IsLoaded();
+      }
+    }
+    return true;
+  }
+
+  Map* GetTransitionMap() {
+    ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
+    ASSERT(type() == MAP_TRANSITION);
+    return Map::cast(GetValue());
+  }
+
+  int GetFieldIndex() {
+    ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
+    ASSERT(type() == FIELD);
+    return Descriptor::IndexFromValue(GetValue());
+  }
+
+  int GetDictionaryEntry() {
+    ASSERT(lookup_type_ == DICTIONARY_TYPE);
+    return number_;
+  }
+
+  JSFunction* GetConstantFunction() {
+    ASSERT(type() == CONSTANT_FUNCTION);
+    return JSFunction::cast(GetValue());
+  }
+
+  Object* GetCallbackObject() {
+    if (lookup_type_ == CONSTANT_TYPE) {
+      // For now we only have the __proto__ as constant type.
+      return Heap::prototype_accessors();
+    }
+    return GetValue();
+  }
+
+#ifdef DEBUG
+  void Print();
+#endif
+
+  Object* GetValue() {
+    if (lookup_type_ == DESCRIPTOR_TYPE) {
+      DescriptorArray* descriptors = holder()->map()->instance_descriptors();
+      return descriptors->GetValue(number_);
+    }
+    // In the dictionary case, the data is held in the value field.
+    ASSERT(lookup_type_ == DICTIONARY_TYPE);
+    return holder()->property_dictionary()->ValueAt(GetDictionaryEntry());
+  }
+
+ private:
+  JSObject* holder_;
+  int number_;
+  bool cacheable_;
+  PropertyDetails details_;
+};
+
+
+// The DescriptorStream is an abstraction for iterating over a map's
+// instance descriptors.
+class DescriptorStream BASE_EMBEDDED {
+ public:
+  explicit DescriptorStream(DescriptorArray* descriptors, int pos) {
+    descriptors_ = descriptors;
+    pos_ = pos;
+    limit_ = descriptors_->number_of_descriptors();
+  }
+
+  // Tells whether we have reached the end of the steam.
+  bool eos() { return pos_ >= limit_; }
+
+  int next_position() { return pos_ + 1; }
+  void advance() { pos_ = next_position(); }
+
+ protected:
+  DescriptorArray* descriptors_;
+  int pos_;   // Current position.
+  int limit_;  // Limit for position.
+};
+
+
+class DescriptorReader: public DescriptorStream {
+ public:
+  explicit DescriptorReader(DescriptorArray* descriptors, int pos = 0)
+      : DescriptorStream(descriptors, pos) {}
+
+  String* GetKey() { return descriptors_->GetKey(pos_); }
+  Object* GetValue() { return descriptors_->GetValue(pos_); }
+  PropertyDetails GetDetails() {
+    return PropertyDetails(descriptors_->GetDetails(pos_));
+  }
+
+  int GetFieldIndex() { return Descriptor::IndexFromValue(GetValue()); }
+
+  bool IsDontEnum() { return GetDetails().IsDontEnum(); }
+
+  PropertyType type() { return GetDetails().type(); }
+
+  // Tells whether the type is a transition.
+  bool IsTransition() {
+    PropertyType t = type();
+    ASSERT(t != INTERCEPTOR);
+    return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
+  }
+
+  bool IsNullDescriptor() {
+    return type() == NULL_DESCRIPTOR;
+  }
+
+  bool IsProperty() {
+    return type() < FIRST_PHANTOM_PROPERTY_TYPE;
+  }
+
+  JSFunction* GetConstantFunction() { return JSFunction::cast(GetValue()); }
+
+  AccessorDescriptor* GetCallbacks() {
+    ASSERT(type() == CALLBACKS);
+    Proxy* p = Proxy::cast(GetCallbacksObject());
+    return reinterpret_cast<AccessorDescriptor*>(p->proxy());
+  }
+
+  Object* GetCallbacksObject() {
+    ASSERT(type() == CALLBACKS);
+    return GetValue();
+  }
+
+  bool Equals(String* name) { return name->Equals(GetKey()); }
+
+  void Get(Descriptor* desc) {
+    descriptors_->Get(pos_, desc);
+  }
+};
+
+class DescriptorWriter: public DescriptorStream {
+ public:
+  explicit DescriptorWriter(DescriptorArray* descriptors)
+      : DescriptorStream(descriptors, 0) {}
+
+  // Append a descriptor to this stream.
+  void Write(Descriptor* desc);
+  // Read a descriptor from the reader and append it to this stream.
+  void WriteFrom(DescriptorReader* reader);
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_PROPERTY_H_
diff --git a/deps/v8/src/regexp-delay.js b/deps/v8/src/regexp-delay.js
new file mode 100644
index 0000000..8491863
--- /dev/null
+++ b/deps/v8/src/regexp-delay.js
@@ -0,0 +1,412 @@
+// Copyright 2006-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.
+
+// Expect $Object = global.Object;
+// Expect $Array = global.Array;
+
+const $RegExp = global.RegExp;
+
+// A recursive descent parser for Patterns according to the grammar of
+// ECMA-262 15.10.1, with deviations noted below.
+function DoConstructRegExp(object, pattern, flags, isConstructorCall) {
+  // RegExp : Called as constructor; see ECMA-262, section 15.10.4.
+  if (IS_REGEXP(pattern)) {
+    if (!IS_UNDEFINED(flags)) {
+      throw MakeTypeError('regexp_flags', []);
+    }
+    flags = (pattern.global ? 'g' : '')
+        + (pattern.ignoreCase ? 'i' : '')
+        + (pattern.multiline ? 'm' : '');
+    pattern = pattern.source;
+  }
+
+  pattern = IS_UNDEFINED(pattern) ? '' : ToString(pattern);
+  flags = IS_UNDEFINED(flags) ? '' : ToString(flags);
+
+  var global = false;
+  var ignoreCase = false;
+  var multiline = false;
+
+  for (var i = 0; i < flags.length; i++) {
+    var c = StringCharAt.call(flags, i);
+    switch (c) {
+      case 'g':
+        // Allow duplicate flags to be consistent with JSC and others.
+        global = true;
+        break;
+      case 'i':
+        ignoreCase = true;
+        break;
+      case 'm':
+        multiline = true;
+        break;
+      default:
+        // Ignore flags that have no meaning to be consistent with
+        // JSC.
+        break;
+    }
+  }
+
+  if (isConstructorCall) {
+    // ECMA-262, section 15.10.7.1.
+    %SetProperty(object, 'source', pattern,
+                 DONT_DELETE |  READ_ONLY | DONT_ENUM);
+
+    // ECMA-262, section 15.10.7.2.
+    %SetProperty(object, 'global', global, DONT_DELETE | READ_ONLY | DONT_ENUM);
+
+    // ECMA-262, section 15.10.7.3.
+    %SetProperty(object, 'ignoreCase', ignoreCase,
+                 DONT_DELETE | READ_ONLY | DONT_ENUM);
+
+    // ECMA-262, section 15.10.7.4.
+    %SetProperty(object, 'multiline', multiline,
+                 DONT_DELETE | READ_ONLY | DONT_ENUM);
+
+    // ECMA-262, section 15.10.7.5.
+    %SetProperty(object, 'lastIndex', 0, DONT_DELETE | DONT_ENUM);
+  } else { // RegExp is being recompiled via RegExp.prototype.compile.
+    %IgnoreAttributesAndSetProperty(object, 'source', pattern);
+    %IgnoreAttributesAndSetProperty(object, 'global', global);
+    %IgnoreAttributesAndSetProperty(object, 'ignoreCase', ignoreCase);
+    %IgnoreAttributesAndSetProperty(object, 'multiline', multiline);
+    %IgnoreAttributesAndSetProperty(object, 'lastIndex', 0);
+  }
+
+  // Call internal function to compile the pattern.
+  %RegExpCompile(object, pattern, flags);
+}
+
+
+function RegExpConstructor(pattern, flags) {
+  if (%IsConstructCall()) {
+    DoConstructRegExp(this, pattern, flags, true);
+  } else {
+    // RegExp : Called as function; see ECMA-262, section 15.10.3.1.
+    if (IS_REGEXP(pattern) && IS_UNDEFINED(flags)) {
+      return pattern;
+    }
+    return new $RegExp(pattern, flags);
+  }
+}
+
+
+// Deprecated RegExp.prototype.compile method.  We behave like the constructor
+// were called again.  In SpiderMonkey, this method returns the regexp object.
+// In JSC, it returns undefined.  For compatibility with JSC, we match their
+// behavior.
+function CompileRegExp(pattern, flags) {
+  // Both JSC and SpiderMonkey treat a missing pattern argument as the
+  // empty subject string, and an actual undefined value passed as the
+  // pattern as the string 'undefined'.  Note that JSC is inconsistent
+  // here, treating undefined values differently in
+  // RegExp.prototype.compile and in the constructor, where they are
+  // the empty string.  For compatibility with JSC, we match their
+  // behavior.
+  if (IS_UNDEFINED(pattern) && %_ArgumentsLength() != 0) {
+    DoConstructRegExp(this, 'undefined', flags, false);
+  } else {
+    DoConstructRegExp(this, pattern, flags, false);
+  }
+}
+
+
+function DoRegExpExec(regexp, string, index) {
+  return %RegExpExec(regexp, string, index, lastMatchInfo);
+}
+
+
+function DoRegExpExecGlobal(regexp, string) {
+  // Returns an array of arrays of substring indices.
+  return %RegExpExecGlobal(regexp, string, lastMatchInfo);
+}
+
+
+function RegExpExec(string) {
+  if (!IS_REGEXP(this)) {
+    throw MakeTypeError('method_called_on_incompatible',
+                        ['RegExp.prototype.exec', this]);
+  }
+  if (%_ArgumentsLength() == 0) {
+    var regExpInput = LAST_INPUT(lastMatchInfo);
+    if (IS_UNDEFINED(regExpInput)) {
+      throw MakeError('no_input_to_regexp', [this]);
+    }
+    string = regExpInput;
+  }
+  var s = ToString(string);
+  var length = s.length;
+  var lastIndex = this.lastIndex;
+  var i = this.global ? TO_INTEGER(lastIndex) : 0;
+
+  if (i < 0 || i > s.length) {
+    this.lastIndex = 0;
+    return null;
+  }
+
+  %_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 (this.global) this.lastIndex = 0;
+    return matchIndices; // no match
+  }
+
+  var numResults = NUMBER_OF_CAPTURES(lastMatchInfo) >> 1;
+  var result = new $Array(numResults);
+  for (var i = 0; i < numResults; i++) {
+    var matchStart = lastMatchInfo[CAPTURE(i << 1)];
+    var matchEnd = lastMatchInfo[CAPTURE((i << 1) + 1)];
+    if (matchStart != -1 && matchEnd != -1) {
+      result[i] = SubString(s, matchStart, matchEnd);
+    } else {
+      // Make sure the element is present. Avoid reading the undefined
+      // property from the global object since this may change.
+      result[i] = void 0;
+    }
+  }
+
+  if (this.global)
+    this.lastIndex = lastMatchInfo[CAPTURE1];
+  result.index = lastMatchInfo[CAPTURE0];
+  result.input = s;
+  return result;
+}
+
+
+// Section 15.10.6.3 doesn't actually make sense, but the intention seems to be
+// that test is defined in terms of String.prototype.exec. However, it probably
+// means the original value of String.prototype.exec, which is what everybody
+// else implements.
+function RegExpTest(string) {
+  if (!IS_REGEXP(this)) {
+    throw MakeTypeError('method_called_on_incompatible',
+                        ['RegExp.prototype.test', this]);
+  }
+  if (%_ArgumentsLength() == 0) {
+    var regExpInput = LAST_INPUT(lastMatchInfo);
+    if (IS_UNDEFINED(regExpInput)) {
+      throw MakeError('no_input_to_regexp', [this]);
+    }
+    string = regExpInput;
+  }
+  var s = ToString(string);
+  var length = s.length;
+  var lastIndex = this.lastIndex;
+  var i = this.global ? TO_INTEGER(lastIndex) : 0;
+
+  if (i < 0 || i > s.length) {
+    this.lastIndex = 0;
+    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, i, lastMatchInfo);
+
+  if (matchIndices == null) {
+    if (this.global) this.lastIndex = 0;
+    return false;
+  }
+
+  if (this.global) this.lastIndex = lastMatchInfo[CAPTURE1];
+  return true;
+}
+
+
+function RegExpToString() {
+  // If this.source is an empty string, output /(?:)/.
+  // http://bugzilla.mozilla.org/show_bug.cgi?id=225550
+  // ecma_2/RegExp/properties-001.js.
+  var src = this.source ? this.source : '(?:)';
+  var result = '/' + src + '/';
+  if (this.global)
+    result += 'g';
+  if (this.ignoreCase)
+    result += 'i';
+  if (this.multiline)
+    result += 'm';
+  return result;
+}
+
+
+// Getters for the static properties lastMatch, lastParen, leftContext, and
+// rightContext of the RegExp constructor.  The properties are computed based
+// on the captures array of the last successful match and the subject string
+// of the last successful match.
+function RegExpGetLastMatch() {
+  var regExpSubject = LAST_SUBJECT(lastMatchInfo);
+  return SubString(regExpSubject,
+                   lastMatchInfo[CAPTURE0],
+                   lastMatchInfo[CAPTURE1]);
+}
+
+
+function RegExpGetLastParen() {
+  var length = NUMBER_OF_CAPTURES(lastMatchInfo);
+  if (length <= 2) return '';  // There were no captures.
+  // We match the SpiderMonkey behavior: return the substring defined by the
+  // last pair (after the first pair) of elements of the capture array even if
+  // it is empty.
+  var regExpSubject = LAST_SUBJECT(lastMatchInfo);
+  var start = lastMatchInfo[CAPTURE(length - 2)];
+  var end = lastMatchInfo[CAPTURE(length - 1)];
+  if (start != -1 && end != -1) {
+    return SubString(regExpSubject, start, end);
+  }
+  return "";
+}
+
+
+function RegExpGetLeftContext() {
+  return SubString(LAST_SUBJECT(lastMatchInfo),
+                   0,
+                   lastMatchInfo[CAPTURE0]);
+}
+
+
+function RegExpGetRightContext() {
+  var subject = LAST_SUBJECT(lastMatchInfo);
+  return SubString(subject,
+                   lastMatchInfo[CAPTURE1],
+                   subject.length);
+}
+
+
+// The properties $1..$9 are the first nine capturing substrings of the last
+// successful match, or ''.  The function RegExpMakeCaptureGetter will be
+// called with indices from 1 to 9.
+function RegExpMakeCaptureGetter(n) {
+  return function() {
+    var index = n * 2;
+    if (index >= NUMBER_OF_CAPTURES(lastMatchInfo)) return '';
+    var matchStart = lastMatchInfo[CAPTURE(index)];
+    var matchEnd = lastMatchInfo[CAPTURE(index + 1)];
+    if (matchStart == -1 || matchEnd == -1) return '';
+    return SubString(LAST_SUBJECT(lastMatchInfo), matchStart, matchEnd);
+  };
+}
+
+
+// Property of the builtins object for recording the result of the last
+// regexp match.  The property lastMatchInfo includes the matchIndices
+// array of the last successful regexp match (an array of start/end index
+// pairs for the match and all the captured substrings), the invariant is
+// that there are at least two capture indeces.  The array also contains
+// the subject string for the last successful match.
+var lastMatchInfo = [
+    2,                 // REGEXP_NUMBER_OF_CAPTURES
+    "",                // Last subject.
+    void 0,            // Last input - settable with RegExpSetInput.
+    0,                 // REGEXP_FIRST_CAPTURE + 0
+    0,                 // REGEXP_FIRST_CAPTURE + 1
+];
+
+// -------------------------------------------------------------------
+
+function SetupRegExp() {
+  %FunctionSetInstanceClassName($RegExp, 'RegExp');
+  %FunctionSetPrototype($RegExp, new $Object());
+  %SetProperty($RegExp.prototype, 'constructor', $RegExp, DONT_ENUM);
+  %SetCode($RegExp, RegExpConstructor);
+
+  InstallFunctions($RegExp.prototype, DONT_ENUM, $Array(
+    "exec", RegExpExec,
+    "test", RegExpTest,
+    "toString", RegExpToString,
+    "compile", CompileRegExp
+  ));
+
+  // The length of compile is 1 in SpiderMonkey.
+  %FunctionSetLength($RegExp.prototype.compile, 1);
+
+  // The properties input, $input, and $_ are aliases for each other.  When this
+  // value is set the value it is set to is coerced to a string. 
+  // Getter and setter for the input.
+  function RegExpGetInput() {
+    var regExpInput = LAST_INPUT(lastMatchInfo);
+    return IS_UNDEFINED(regExpInput) ? "" : regExpInput;
+  }
+  function RegExpSetInput(string) {
+    LAST_INPUT(lastMatchInfo) = ToString(string);
+  };
+
+  %DefineAccessor($RegExp, 'input', GETTER, RegExpGetInput, DONT_DELETE);
+  %DefineAccessor($RegExp, 'input', SETTER, RegExpSetInput, DONT_DELETE);
+  %DefineAccessor($RegExp, '$_', GETTER, RegExpGetInput, DONT_ENUM | DONT_DELETE);
+  %DefineAccessor($RegExp, '$_', SETTER, RegExpSetInput, DONT_ENUM | DONT_DELETE);
+  %DefineAccessor($RegExp, '$input', GETTER, RegExpGetInput, DONT_ENUM | DONT_DELETE);
+  %DefineAccessor($RegExp, '$input', SETTER, RegExpSetInput, DONT_ENUM | DONT_DELETE);
+
+  // The properties multiline and $* are aliases for each other.  When this
+  // value is set in SpiderMonkey, the value it is set to is coerced to a
+  // boolean.  We mimic that behavior with a slight difference: in SpiderMonkey
+  // the value of the expression 'RegExp.multiline = null' (for instance) is the
+  // boolean false (ie, the value after coercion), while in V8 it is the value
+  // null (ie, the value before coercion).
+
+  // Getter and setter for multiline.
+  var multiline = false;
+  function RegExpGetMultiline() { return multiline; };
+  function RegExpSetMultiline(flag) { multiline = flag ? true : false; };
+
+  %DefineAccessor($RegExp, 'multiline', GETTER, RegExpGetMultiline, DONT_DELETE);
+  %DefineAccessor($RegExp, 'multiline', SETTER, RegExpSetMultiline, DONT_DELETE);
+  %DefineAccessor($RegExp, '$*', GETTER, RegExpGetMultiline, DONT_ENUM | DONT_DELETE);
+  %DefineAccessor($RegExp, '$*', SETTER, RegExpSetMultiline, DONT_ENUM | DONT_DELETE);
+
+
+  function NoOpSetter(ignored) {}
+
+
+  // Static properties set by a successful match.
+  %DefineAccessor($RegExp, 'lastMatch', GETTER, RegExpGetLastMatch, DONT_DELETE);
+  %DefineAccessor($RegExp, 'lastMatch', SETTER, NoOpSetter, DONT_DELETE);
+  %DefineAccessor($RegExp, '$&', GETTER, RegExpGetLastMatch, DONT_ENUM | DONT_DELETE);
+  %DefineAccessor($RegExp, '$&', SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE);
+  %DefineAccessor($RegExp, 'lastParen', GETTER, RegExpGetLastParen, DONT_DELETE);
+  %DefineAccessor($RegExp, 'lastParen', SETTER, NoOpSetter, DONT_DELETE);
+  %DefineAccessor($RegExp, '$+', GETTER, RegExpGetLastParen, DONT_ENUM | DONT_DELETE);
+  %DefineAccessor($RegExp, '$+', SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE);
+  %DefineAccessor($RegExp, 'leftContext', GETTER, RegExpGetLeftContext, DONT_DELETE);
+  %DefineAccessor($RegExp, 'leftContext', SETTER, NoOpSetter, DONT_DELETE);
+  %DefineAccessor($RegExp, '$`', GETTER, RegExpGetLeftContext, DONT_ENUM | DONT_DELETE);
+  %DefineAccessor($RegExp, '$`', SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE);
+  %DefineAccessor($RegExp, 'rightContext', GETTER, RegExpGetRightContext, DONT_DELETE);
+  %DefineAccessor($RegExp, 'rightContext', SETTER, NoOpSetter, DONT_DELETE);
+  %DefineAccessor($RegExp, "$'", GETTER, RegExpGetRightContext, DONT_ENUM | DONT_DELETE);
+  %DefineAccessor($RegExp, "$'", SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE);
+
+  for (var i = 1; i < 10; ++i) {
+    %DefineAccessor($RegExp, '$' + i, GETTER, RegExpMakeCaptureGetter(i), DONT_DELETE);
+    %DefineAccessor($RegExp, '$' + i, SETTER, NoOpSetter, DONT_DELETE);
+  }
+}
+
+
+SetupRegExp();
diff --git a/deps/v8/src/regexp-macro-assembler-arm.cc b/deps/v8/src/regexp-macro-assembler-arm.cc
new file mode 100644
index 0000000..bcfddf6
--- /dev/null
+++ b/deps/v8/src/regexp-macro-assembler-arm.cc
@@ -0,0 +1,43 @@
+// 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.
+
+#include "v8.h"
+#include "ast.h"
+#include "regexp-macro-assembler.h"
+#include "regexp-macro-assembler-arm.h"
+
+namespace v8 { namespace internal {
+
+RegExpMacroAssemblerARM::RegExpMacroAssemblerARM() {
+  UNIMPLEMENTED();
+}
+
+
+RegExpMacroAssemblerARM::~RegExpMacroAssemblerARM() {}
+
+}}  // namespace v8::internal
+
diff --git a/deps/v8/src/regexp-macro-assembler-arm.h b/deps/v8/src/regexp-macro-assembler-arm.h
new file mode 100644
index 0000000..51352bc
--- /dev/null
+++ b/deps/v8/src/regexp-macro-assembler-arm.h
@@ -0,0 +1,41 @@
+// 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 REGEXP_MACRO_ASSEMBLER_ARM_H_
+#define REGEXP_MACRO_ASSEMBLER_ARM_H_
+
+namespace v8 { namespace internal {
+
+class RegExpMacroAssemblerARM: public RegExpMacroAssembler {
+ public:
+  RegExpMacroAssemblerARM();
+  virtual ~RegExpMacroAssemblerARM();
+};
+
+}}  // namespace v8::internal
+
+#endif /* REGEXP_MACRO_ASSEMBLER_ARM_H_ */
diff --git a/deps/v8/src/regexp-macro-assembler-ia32.cc b/deps/v8/src/regexp-macro-assembler-ia32.cc
new file mode 100644
index 0000000..c2f76b4
--- /dev/null
+++ b/deps/v8/src/regexp-macro-assembler-ia32.cc
@@ -0,0 +1,1390 @@
+// Copyright 2008-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.
+
+#include "v8.h"
+#include "unicode.h"
+#include "log.h"
+#include "ast.h"
+#include "regexp-stack.h"
+#include "macro-assembler.h"
+#include "regexp-macro-assembler.h"
+#include "macro-assembler-ia32.h"
+#include "regexp-macro-assembler-ia32.h"
+
+namespace v8 { namespace internal {
+
+/*
+ * This assembler uses the following register assignment convention
+ * - edx : current character. Must be loaded using LoadCurrentCharacter
+ *         before using any of the dispatch methods.
+ * - edi : current position in input, as negative offset from end of string.
+ *         Please notice that this is the byte offset, not the character offset!
+ * - esi : end of input (points to byte after last character in input).
+ * - ebp : frame pointer. Used to access arguments, local variables and
+ *         RegExp registers.
+ * - esp : points to tip of C stack.
+ * - ecx : points to tip of backtrack stack
+ *
+ * The registers eax, ebx and ecx are free to use for computations.
+ *
+ * Each call to a public method should retain this convention.
+ * The stack will have the following structure:
+ *       - stack_area_top     (High end of the memory area to use as
+ *                             backtracking stack)
+ *       - at_start           (if 1, start at start of string, if 0, don't)
+ *       - int* capture_array (int[num_saved_registers_], for output).
+ *       - end of input       (Address of end of string)
+ *       - start of input     (Address of first character in string)
+ *       - void* input_string (location of a handle containing the string)
+ *       --- frame alignment (if applicable) ---
+ *       - return address
+ * ebp-> - old ebp
+ *       - backup of caller esi
+ *       - backup of caller edi
+ *       - backup of caller ebx
+ *       - Offset of location before start of input (effectively character
+ *         position -1). Used to initialize capture registers to a non-position.
+ *       - register 0  ebp[-4]  (Only positions must be stored in the first
+ *       - register 1  ebp[-8]   num_saved_registers_ registers)
+ *       - ...
+ *
+ * The first num_saved_registers_ registers are initialized to point to
+ * "character -1" in the string (i.e., char_size() bytes before the first
+ * character of the string). The remaining registers starts out as garbage.
+ *
+ * The data up to the return address must be placed there by the calling
+ * code, e.g., by calling the code entry as cast to:
+ * int (*match)(String* input_string,
+ *              Address start,
+ *              Address end,
+ *              int* capture_output_array,
+ *              bool at_start,
+ *              byte* stack_area_top)
+ */
+
+#define __ masm_->
+
+RegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32(
+    Mode mode,
+    int registers_to_save)
+    : masm_(new MacroAssembler(NULL, kRegExpCodeSize)),
+      constants_(kRegExpConstantsSize),
+      mode_(mode),
+      num_registers_(registers_to_save),
+      num_saved_registers_(registers_to_save),
+      entry_label_(),
+      start_label_(),
+      success_label_(),
+      backtrack_label_(),
+      exit_label_() {
+  __ jmp(&entry_label_);   // We'll write the entry code later.
+  __ bind(&start_label_);  // And then continue from here.
+}
+
+
+RegExpMacroAssemblerIA32::~RegExpMacroAssemblerIA32() {
+  delete masm_;
+  // Unuse labels in case we throw away the assembler without calling GetCode.
+  entry_label_.Unuse();
+  start_label_.Unuse();
+  success_label_.Unuse();
+  backtrack_label_.Unuse();
+  exit_label_.Unuse();
+  check_preempt_label_.Unuse();
+  stack_overflow_label_.Unuse();
+}
+
+
+int RegExpMacroAssemblerIA32::stack_limit_slack()  {
+  return RegExpStack::kStackLimitSlack;
+}
+
+
+void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) {
+  if (by != 0) {
+    Label inside_string;
+    __ add(Operand(edi), Immediate(by * char_size()));
+  }
+}
+
+
+void RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) {
+  ASSERT(reg >= 0);
+  ASSERT(reg < num_registers_);
+  if (by != 0) {
+    __ add(register_location(reg), Immediate(by));
+  }
+}
+
+
+void RegExpMacroAssemblerIA32::Backtrack() {
+  CheckPreemption();
+  // Pop Code* offset from backtrack stack, add Code* and jump to location.
+  Pop(ebx);
+  __ add(Operand(ebx), Immediate(masm_->CodeObject()));
+  __ jmp(Operand(ebx));
+}
+
+
+void RegExpMacroAssemblerIA32::Bind(Label* label) {
+  __ bind(label);
+}
+
+
+void RegExpMacroAssemblerIA32::CheckBitmap(uc16 start,
+                                           Label* bitmap,
+                                           Label* on_zero) {
+  UNIMPLEMENTED();
+}
+
+
+void RegExpMacroAssemblerIA32::CheckCharacter(uint32_t c, Label* on_equal) {
+  __ cmp(current_character(), c);
+  BranchOrBacktrack(equal, on_equal);
+}
+
+
+void RegExpMacroAssemblerIA32::CheckCharacterGT(uc16 limit, Label* on_greater) {
+  __ cmp(current_character(), limit);
+  BranchOrBacktrack(greater, on_greater);
+}
+
+
+void RegExpMacroAssemblerIA32::CheckAtStart(Label* on_at_start) {
+  Label not_at_start;
+  // Did we start the match at the start of the string at all?
+  __ cmp(Operand(ebp, kAtStart), Immediate(0));
+  BranchOrBacktrack(equal, &not_at_start);
+  // If we did, are we still at the start of the input?
+  __ lea(eax, Operand(esi, edi, times_1, 0));
+  __ cmp(eax, Operand(ebp, kInputStart));
+  BranchOrBacktrack(equal, on_at_start);
+  __ bind(&not_at_start);
+}
+
+
+void RegExpMacroAssemblerIA32::CheckNotAtStart(Label* on_not_at_start) {
+  // Did we start the match at the start of the string at all?
+  __ cmp(Operand(ebp, kAtStart), Immediate(0));
+  BranchOrBacktrack(equal, on_not_at_start);
+  // If we did, are we still at the start of the input?
+  __ lea(eax, Operand(esi, edi, times_1, 0));
+  __ cmp(eax, Operand(ebp, kInputStart));
+  BranchOrBacktrack(not_equal, on_not_at_start);
+}
+
+
+void RegExpMacroAssemblerIA32::CheckCharacterLT(uc16 limit, Label* on_less) {
+  __ cmp(current_character(), limit);
+  BranchOrBacktrack(less, on_less);
+}
+
+
+void RegExpMacroAssemblerIA32::CheckCharacters(Vector<const uc16> str,
+                                               int cp_offset,
+                                               Label* on_failure,
+                                               bool check_end_of_string) {
+  int byte_length = str.length() * char_size();
+  int byte_offset = cp_offset * char_size();
+  if (check_end_of_string) {
+    // Check that there are at least str.length() characters left in the input.
+    __ cmp(Operand(edi), Immediate(-(byte_offset + byte_length)));
+    BranchOrBacktrack(greater, on_failure);
+  }
+
+  Label backtrack;
+  if (on_failure == NULL) {
+    // Avoid inlining the Backtrack macro for each test.
+    Label skip_backtrack;
+    __ jmp(&skip_backtrack);
+    __ bind(&backtrack);
+    Backtrack();
+    __ bind(&skip_backtrack);
+    on_failure = &backtrack;
+  }
+
+  for (int i = 0; i < str.length(); i++) {
+    if (mode_ == ASCII) {
+      __ cmpb(Operand(esi, edi, times_1, byte_offset + i),
+              static_cast<int8_t>(str[i]));
+    } else {
+      ASSERT(mode_ == UC16);
+      __ cmpw(Operand(esi, edi, times_1, byte_offset + i * sizeof(uc16)),
+              Immediate(str[i]));
+    }
+    BranchOrBacktrack(not_equal, on_failure);
+  }
+}
+
+
+void RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) {
+  Label fallthrough;
+  __ cmp(edi, Operand(backtrack_stackpointer(), 0));
+  __ j(not_equal, &fallthrough);
+  __ add(Operand(backtrack_stackpointer()), Immediate(kPointerSize));  // Pop.
+  BranchOrBacktrack(no_condition, on_equal);
+  __ bind(&fallthrough);
+}
+
+
+void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase(
+    int start_reg,
+    Label* on_no_match) {
+  Label fallthrough;
+  __ mov(edx, register_location(start_reg));  // Index of start of capture
+  __ mov(ebx, register_location(start_reg + 1));  // Index of end of capture
+  __ sub(ebx, Operand(edx));  // Length of capture.
+
+  // The length of a capture should not be negative. This can only happen
+  // if the end of the capture is unrecorded, or at a point earlier than
+  // the start of the capture.
+  BranchOrBacktrack(less, on_no_match, not_taken);
+
+  // If length is zero, either the capture is empty or it is completely
+  // uncaptured. In either case succeed immediately.
+  __ j(equal, &fallthrough);
+
+  if (mode_ == ASCII) {
+    Label success;
+    Label fail;
+    Label loop_increment;
+    // Save register contents to make the registers available below.
+    __ push(edi);
+    __ push(backtrack_stackpointer());
+    // After this, the eax, ecx, and edi registers are available.
+
+    __ add(edx, Operand(esi));  // Start of capture
+    __ add(edi, Operand(esi));  // Start of text to match against capture.
+    __ add(ebx, Operand(edi));  // End of text to match against capture.
+
+    Label loop;
+    __ bind(&loop);
+    __ movzx_b(eax, Operand(edi, 0));
+    __ cmpb_al(Operand(edx, 0));
+    __ j(equal, &loop_increment);
+
+    // Mismatch, try case-insensitive match (converting letters to lower-case).
+    __ or_(eax, 0x20);  // Convert match character to lower-case.
+    __ lea(ecx, Operand(eax, -'a'));
+    __ cmp(ecx, static_cast<int32_t>('z' - 'a'));  // Is eax a lowercase letter?
+    __ j(above, &fail);
+    // Also convert capture character.
+    __ movzx_b(ecx, Operand(edx, 0));
+    __ or_(ecx, 0x20);
+
+    __ cmp(eax, Operand(ecx));
+    __ j(not_equal, &fail);
+
+    __ bind(&loop_increment);
+    // Increment pointers into match and capture strings.
+    __ add(Operand(edx), Immediate(1));
+    __ add(Operand(edi), Immediate(1));
+    // Compare to end of match, and loop if not done.
+    __ cmp(edi, Operand(ebx));
+    __ j(below, &loop, taken);
+    __ jmp(&success);
+
+    __ bind(&fail);
+    // Restore original values before failing.
+    __ pop(backtrack_stackpointer());
+    __ pop(edi);
+    BranchOrBacktrack(no_condition, on_no_match);
+
+    __ bind(&success);
+    // Restore original value before continuing.
+    __ pop(backtrack_stackpointer());
+    // Drop original value of character position.
+    __ add(Operand(esp), Immediate(kPointerSize));
+    // Compute new value of character position after the matched part.
+    __ sub(edi, Operand(esi));
+  } else {
+    ASSERT(mode_ == UC16);
+    // Save registers before calling C function.
+    __ push(esi);
+    __ push(edi);
+    __ push(backtrack_stackpointer());
+    __ push(ebx);
+
+    const int argument_count = 3;
+    FrameAlign(argument_count, ecx);
+    // Put arguments into allocated stack area, last argument highest on stack.
+    // Parameters are
+    //   Address byte_offset1 - Address captured substring's start.
+    //   Address byte_offset2 - Address of current character position.
+    //   size_t byte_length - length of capture in bytes(!)
+
+    // Set byte_length.
+    __ mov(Operand(esp, 2 * kPointerSize), ebx);
+    // Set byte_offset2.
+    // Found by adding negative string-end offset of current position (edi)
+    // to end of string.
+    __ add(edi, Operand(esi));
+    __ mov(Operand(esp, 1 * kPointerSize), edi);
+    // Set byte_offset1.
+    // Start of capture, where edx already holds string-end negative offset.
+    __ add(edx, Operand(esi));
+    __ mov(Operand(esp, 0 * kPointerSize), edx);
+
+    Address function_address = FUNCTION_ADDR(&CaseInsensitiveCompareUC16);
+    CallCFunction(function_address, argument_count);
+    // Pop original values before reacting on result value.
+    __ pop(ebx);
+    __ pop(backtrack_stackpointer());
+    __ pop(edi);
+    __ pop(esi);
+
+    // Check if function returned non-zero for success or zero for failure.
+    __ or_(eax, Operand(eax));
+    BranchOrBacktrack(zero, on_no_match);
+    // On success, increment position by length of capture.
+    __ add(edi, Operand(ebx));
+  }
+  __ bind(&fallthrough);
+}
+
+
+void RegExpMacroAssemblerIA32::CheckNotBackReference(
+    int start_reg,
+    Label* on_no_match) {
+  Label fallthrough;
+  Label success;
+  Label fail;
+
+  // Find length of back-referenced capture.
+  __ mov(edx, register_location(start_reg));
+  __ mov(eax, register_location(start_reg + 1));
+  __ sub(eax, Operand(edx));  // Length to check.
+  // Fail on partial or illegal capture (start of capture after end of capture).
+  BranchOrBacktrack(less, on_no_match);
+  // Succeed on empty capture (including no capture)
+  __ j(equal, &fallthrough);
+
+  // Check that there are sufficient characters left in the input.
+  __ mov(ebx, edi);
+  __ add(ebx, Operand(eax));
+  BranchOrBacktrack(greater, on_no_match);
+
+  // Save register to make it available below.
+  __ push(backtrack_stackpointer());
+
+  // Compute pointers to match string and capture string
+  __ lea(ebx, Operand(esi, edi, times_1, 0));  // Start of match.
+  __ add(edx, Operand(esi));  // Start of capture.
+  __ lea(ecx, Operand(eax, ebx, times_1, 0));  // End of match
+
+  Label loop;
+  __ bind(&loop);
+  if (mode_ == ASCII) {
+    __ movzx_b(eax, Operand(edx, 0));
+    __ cmpb_al(Operand(ebx, 0));
+  } else {
+    ASSERT(mode_ == UC16);
+    __ movzx_w(eax, Operand(edx, 0));
+    __ cmpw_ax(Operand(ebx, 0));
+  }
+  __ j(not_equal, &fail);
+  // Increment pointers into capture and match string.
+  __ add(Operand(edx), Immediate(char_size()));
+  __ add(Operand(ebx), Immediate(char_size()));
+  // Check if we have reached end of match area.
+  __ cmp(ebx, Operand(ecx));
+  __ j(below, &loop);
+  __ jmp(&success);
+
+  __ bind(&fail);
+  // Restore backtrack stackpointer.
+  __ pop(backtrack_stackpointer());
+  BranchOrBacktrack(no_condition, on_no_match);
+
+  __ bind(&success);
+  // Move current character position to position after match.
+  __ mov(edi, ecx);
+  __ sub(Operand(edi), esi);
+  // Restore backtrack stackpointer.
+  __ pop(backtrack_stackpointer());
+
+  __ bind(&fallthrough);
+}
+
+
+void RegExpMacroAssemblerIA32::CheckNotRegistersEqual(int reg1,
+                                                      int reg2,
+                                                      Label* on_not_equal) {
+  __ mov(eax, register_location(reg1));
+  __ cmp(eax, register_location(reg2));
+  BranchOrBacktrack(not_equal, on_not_equal);
+}
+
+
+void RegExpMacroAssemblerIA32::CheckNotCharacter(uint32_t c,
+                                                 Label* on_not_equal) {
+  __ cmp(current_character(), c);
+  BranchOrBacktrack(not_equal, on_not_equal);
+}
+
+
+void RegExpMacroAssemblerIA32::CheckCharacterAfterAnd(uint32_t c,
+                                                      uint32_t mask,
+                                                      Label* on_equal) {
+  __ mov(eax, current_character());
+  __ and_(eax, mask);
+  __ cmp(eax, c);
+  BranchOrBacktrack(equal, on_equal);
+}
+
+
+void RegExpMacroAssemblerIA32::CheckNotCharacterAfterAnd(uint32_t c,
+                                                         uint32_t mask,
+                                                         Label* on_not_equal) {
+  __ mov(eax, current_character());
+  __ and_(eax, mask);
+  __ cmp(eax, c);
+  BranchOrBacktrack(not_equal, on_not_equal);
+}
+
+
+void RegExpMacroAssemblerIA32::CheckNotCharacterAfterMinusAnd(
+    uc16 c,
+    uc16 minus,
+    uc16 mask,
+    Label* on_not_equal) {
+  ASSERT(minus < String::kMaxUC16CharCode);
+  __ lea(eax, Operand(current_character(), -minus));
+  __ and_(eax, mask);
+  __ cmp(eax, c);
+  BranchOrBacktrack(not_equal, on_not_equal);
+}
+
+
+bool RegExpMacroAssemblerIA32::CheckSpecialCharacterClass(uc16 type,
+                                                          int cp_offset,
+                                                          bool check_offset,
+                                                          Label* on_no_match) {
+  // Range checks (c in min..max) are generally implemented by an unsigned
+  // (c - min) <= (max - min) check
+  switch (type) {
+  case 's':
+    // Match space-characters
+    if (mode_ == ASCII) {
+      // ASCII space characters are '\t'..'\r' and ' '.
+      if (check_offset) {
+        LoadCurrentCharacter(cp_offset, on_no_match);
+      } else {
+        LoadCurrentCharacterUnchecked(cp_offset, 1);
+      }
+      Label success;
+      __ cmp(current_character(), ' ');
+      __ j(equal, &success);
+      // Check range 0x09..0x0d
+      __ sub(Operand(current_character()), Immediate('\t'));
+      __ cmp(current_character(), '\r' - '\t');
+      BranchOrBacktrack(above, on_no_match);
+      __ bind(&success);
+      return true;
+    }
+    return false;
+  case 'S':
+    // Match non-space characters.
+    if (check_offset) {
+      LoadCurrentCharacter(cp_offset, on_no_match, 1);
+    } else {
+      LoadCurrentCharacterUnchecked(cp_offset, 1);
+    }
+    if (mode_ == ASCII) {
+      // ASCII space characters are '\t'..'\r' and ' '.
+      __ cmp(current_character(), ' ');
+      BranchOrBacktrack(equal, on_no_match);
+      __ sub(Operand(current_character()), Immediate('\t'));
+      __ cmp(current_character(), '\r' - '\t');
+      BranchOrBacktrack(below_equal, on_no_match);
+      return true;
+    }
+    return false;
+  case 'd':
+    // Match ASCII digits ('0'..'9')
+    if (check_offset) {
+      LoadCurrentCharacter(cp_offset, on_no_match, 1);
+    } else {
+      LoadCurrentCharacterUnchecked(cp_offset, 1);
+    }
+    __ sub(Operand(current_character()), Immediate('0'));
+    __ cmp(current_character(), '9' - '0');
+    BranchOrBacktrack(above, on_no_match);
+    return true;
+  case 'D':
+    // Match non ASCII-digits
+    if (check_offset) {
+      LoadCurrentCharacter(cp_offset, on_no_match, 1);
+    } else {
+      LoadCurrentCharacterUnchecked(cp_offset, 1);
+    }
+    __ sub(Operand(current_character()), Immediate('0'));
+    __ cmp(current_character(), '9' - '0');
+    BranchOrBacktrack(below_equal, on_no_match);
+    return true;
+  case '.': {
+    // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029)
+    if (check_offset) {
+      LoadCurrentCharacter(cp_offset, on_no_match, 1);
+    } else {
+      LoadCurrentCharacterUnchecked(cp_offset, 1);
+    }
+    __ xor_(Operand(current_character()), Immediate(0x01));
+    // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
+    __ sub(Operand(current_character()), Immediate(0x0b));
+    __ cmp(current_character(), 0x0c - 0x0b);
+    BranchOrBacktrack(below_equal, on_no_match);
+    if (mode_ == UC16) {
+      // Compare original value to 0x2028 and 0x2029, using the already
+      // computed (current_char ^ 0x01 - 0x0b). I.e., check for
+      // 0x201d (0x2028 - 0x0b) or 0x201e.
+      __ sub(Operand(current_character()), Immediate(0x2028 - 0x0b));
+      __ cmp(current_character(), 1);
+      BranchOrBacktrack(below_equal, on_no_match);
+    }
+    return true;
+  }
+  case '*':
+    // Match any character.
+    if (check_offset) {
+      CheckPosition(cp_offset, on_no_match);
+    }
+    return true;
+  // No custom implementation (yet): w, W, s(UC16), S(UC16).
+  default:
+    return false;
+  }
+}
+
+void RegExpMacroAssemblerIA32::DispatchHalfNibbleMap(
+    uc16 start,
+    Label* half_nibble_map,
+    const Vector<Label*>& destinations) {
+  UNIMPLEMENTED();
+}
+
+
+void RegExpMacroAssemblerIA32::DispatchByteMap(
+    uc16 start,
+    Label* byte_map,
+    const Vector<Label*>& destinations) {
+  UNIMPLEMENTED();
+}
+
+
+void RegExpMacroAssemblerIA32::DispatchHighByteMap(
+    byte start,
+    Label* byte_map,
+    const Vector<Label*>& destinations) {
+  UNIMPLEMENTED();
+}
+
+
+void RegExpMacroAssemblerIA32::EmitOrLink(Label* label) {
+  UNIMPLEMENTED();  // Has no use.
+}
+
+
+void RegExpMacroAssemblerIA32::Fail() {
+  ASSERT(FAILURE == 0);  // Return value for failure is zero.
+  __ xor_(eax, Operand(eax));  // zero eax.
+  __ jmp(&exit_label_);
+}
+
+
+Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
+  // Finalize code - write the entry point code now we know how many
+  // registers we need.
+
+  // Entry code:
+  __ bind(&entry_label_);
+  // Start new stack frame.
+  __ push(ebp);
+  __ mov(ebp, esp);
+  // Save callee-save registers. Order here should correspond to order of
+  // kBackup_ebx etc.
+  __ push(esi);
+  __ push(edi);
+  __ push(ebx);  // Callee-save on MacOS.
+  __ push(Immediate(0));  // Make room for "input start - 1" constant.
+
+  // Check if we have space on the stack for registers.
+  Label retry_stack_check;
+  Label stack_limit_hit;
+  Label stack_ok;
+
+  __ bind(&retry_stack_check);
+  ExternalReference stack_guard_limit =
+      ExternalReference::address_of_stack_guard_limit();
+  __ mov(ecx, esp);
+  __ sub(ecx, Operand::StaticVariable(stack_guard_limit));
+  // Handle it if the stack pointer is already below the stack limit.
+  __ j(below_equal, &stack_limit_hit, not_taken);
+  // Check if there is room for the variable number of registers above
+  // the stack limit.
+  __ cmp(ecx, num_registers_ * kPointerSize);
+  __ j(above_equal, &stack_ok, taken);
+  // Exit with OutOfMemory exception. There is not enough space on the stack
+  // for our working registers.
+  __ mov(eax, EXCEPTION);
+  __ jmp(&exit_label_);
+
+  __ bind(&stack_limit_hit);
+  CallCheckStackGuardState(ebx);
+  __ or_(eax, Operand(eax));
+  // If returned value is non-zero, we exit with the returned value as result.
+  // Otherwise it was a preemption and we just check the limit again.
+  __ j(equal, &retry_stack_check);
+  // Return value was non-zero. Exit with exception or retry.
+  __ jmp(&exit_label_);
+
+  __ bind(&stack_ok);
+
+  // Allocate space on stack for registers.
+  __ sub(Operand(esp), Immediate(num_registers_ * kPointerSize));
+  // Load string length.
+  __ mov(esi, Operand(ebp, kInputEnd));
+  // Load input position.
+  __ mov(edi, Operand(ebp, kInputStart));
+  // Set up edi to be negative offset from string end.
+  __ sub(edi, Operand(esi));
+  if (num_saved_registers_ > 0) {
+    // Fill saved registers with initial value = start offset - 1
+    // Fill in stack push order, to avoid accessing across an unwritten
+    // page (a problem on Windows).
+    __ mov(ecx, kRegisterZero);
+    // Set eax to address of char before start of input
+    // (effectively string position -1).
+    __ lea(eax, Operand(edi, -char_size()));
+    // Store this value in a local variable, for use when clearing
+    // position registers.
+    __ mov(Operand(ebp, kInputStartMinusOne), eax);
+    Label init_loop;
+    __ bind(&init_loop);
+    __ mov(Operand(ebp, ecx, times_1, +0), eax);
+    __ sub(Operand(ecx), Immediate(kPointerSize));
+    __ cmp(ecx, kRegisterZero - num_saved_registers_ * kPointerSize);
+    __ j(greater, &init_loop);
+  }
+  // Ensure that we have written to each stack page, in order. Skipping a page
+  // on Windows can cause segmentation faults. Assuming page size is 4k.
+  const int kPageSize = 4096;
+  const int kRegistersPerPage = kPageSize / kPointerSize;
+  for (int i = num_saved_registers_ + kRegistersPerPage - 1;
+      i < num_registers_;
+      i += kRegistersPerPage) {
+    __ mov(register_location(i), eax);  // One write every page.
+  }
+
+
+  // Initialize backtrack stack pointer.
+  __ mov(backtrack_stackpointer(), Operand(ebp, kStackHighEnd));
+  // Load previous char as initial value of current-character.
+  Label at_start;
+  __ cmp(Operand(ebp, kAtStart), Immediate(0));
+  __ j(not_equal, &at_start);
+  LoadCurrentCharacterUnchecked(-1, 1);  // Load previous char.
+  __ jmp(&start_label_);
+  __ bind(&at_start);
+  __ mov(current_character(), '\n');
+  __ jmp(&start_label_);
+
+
+  // Exit code:
+  if (success_label_.is_linked()) {
+    // Save captures when successful.
+    __ bind(&success_label_);
+    if (num_saved_registers_ > 0) {
+      // copy captures to output
+      __ mov(ebx, Operand(ebp, kRegisterOutput));
+      __ mov(ecx, Operand(ebp, kInputEnd));
+      __ sub(ecx, Operand(ebp, kInputStart));
+      for (int i = 0; i < num_saved_registers_; i++) {
+        __ mov(eax, register_location(i));
+        __ add(eax, Operand(ecx));  // Convert to index from start, not end.
+        if (mode_ == UC16) {
+          __ sar(eax, 1);  // Convert byte index to character index.
+        }
+        __ mov(Operand(ebx, i * kPointerSize), eax);
+      }
+    }
+    __ mov(eax, Immediate(SUCCESS));
+  }
+  // Exit and return eax
+  __ bind(&exit_label_);
+  // Skip esp past regexp registers.
+  __ lea(esp, Operand(ebp, kBackup_ebx));
+  // Restore callee-save registers.
+  __ pop(ebx);
+  __ pop(edi);
+  __ pop(esi);
+  // Exit function frame, restore previous one.
+  __ pop(ebp);
+  __ ret(0);
+
+  // Backtrack code (branch target for conditional backtracks).
+  if (backtrack_label_.is_linked()) {
+    __ bind(&backtrack_label_);
+    Backtrack();
+  }
+
+  Label exit_with_exception;
+
+  // Preempt-code
+  if (check_preempt_label_.is_linked()) {
+    __ bind(&check_preempt_label_);
+
+    __ push(backtrack_stackpointer());
+    __ push(edi);
+
+    Label retry;
+
+    __ bind(&retry);
+    CallCheckStackGuardState(ebx);
+    __ or_(eax, Operand(eax));
+    // If returning non-zero, we should end execution with the given
+    // result as return value.
+    __ j(not_zero, &exit_label_);
+    // Check if we are still preempted.
+    ExternalReference stack_guard_limit =
+        ExternalReference::address_of_stack_guard_limit();
+    __ cmp(esp, Operand::StaticVariable(stack_guard_limit));
+    __ j(below_equal, &retry);
+
+    __ pop(edi);
+    __ pop(backtrack_stackpointer());
+    // String might have moved: Reload esi from frame.
+    __ mov(esi, Operand(ebp, kInputEnd));
+    SafeReturn();
+  }
+
+  // Backtrack stack overflow code.
+  if (stack_overflow_label_.is_linked()) {
+    __ bind(&stack_overflow_label_);
+    // Reached if the backtrack-stack limit has been hit.
+
+    Label grow_failed;
+    // Save registers before calling C function
+    __ push(esi);
+    __ push(edi);
+
+    // Call GrowStack(backtrack_stackpointer())
+    int num_arguments = 2;
+    FrameAlign(num_arguments, ebx);
+    __ lea(eax, Operand(ebp, kStackHighEnd));
+    __ mov(Operand(esp, 1 * kPointerSize), eax);
+    __ mov(Operand(esp, 0 * kPointerSize), backtrack_stackpointer());
+    CallCFunction(FUNCTION_ADDR(&GrowStack), num_arguments);
+    // If return NULL, we have failed to grow the stack, and
+    // must exit with a stack-overflow exception.
+    __ or_(eax, Operand(eax));
+    __ j(equal, &exit_with_exception);
+    // Otherwise use return value as new stack pointer.
+    __ mov(backtrack_stackpointer(), eax);
+    // Restore saved registers and continue.
+    __ pop(edi);
+    __ pop(esi);
+    SafeReturn();
+  }
+
+  if (exit_with_exception.is_linked()) {
+    // If any of the code above needed to exit with an exception.
+    __ bind(&exit_with_exception);
+    // Exit with Result EXCEPTION(-1) to signal thrown exception.
+    __ mov(eax, EXCEPTION);
+    __ jmp(&exit_label_);
+  }
+
+  CodeDesc code_desc;
+  masm_->GetCode(&code_desc);
+  Handle<Code> code = Factory::NewCode(code_desc,
+                                       NULL,
+                                       Code::ComputeFlags(Code::REGEXP),
+                                       masm_->CodeObject());
+  LOG(RegExpCodeCreateEvent(*code, *source));
+  return Handle<Object>::cast(code);
+}
+
+
+void RegExpMacroAssemblerIA32::GoTo(Label* to) {
+  BranchOrBacktrack(no_condition, to);
+}
+
+
+void RegExpMacroAssemblerIA32::IfRegisterGE(int reg,
+                                            int comparand,
+                                            Label* if_ge) {
+  __ cmp(register_location(reg), Immediate(comparand));
+  BranchOrBacktrack(greater_equal, if_ge);
+}
+
+
+void RegExpMacroAssemblerIA32::IfRegisterLT(int reg,
+                                            int comparand,
+                                            Label* if_lt) {
+  __ cmp(register_location(reg), Immediate(comparand));
+  BranchOrBacktrack(less, if_lt);
+}
+
+
+void RegExpMacroAssemblerIA32::IfRegisterEqPos(int reg,
+                                               Label* if_eq) {
+  __ cmp(edi, register_location(reg));
+  BranchOrBacktrack(equal, if_eq);
+}
+
+
+RegExpMacroAssembler::IrregexpImplementation
+    RegExpMacroAssemblerIA32::Implementation() {
+  return kIA32Implementation;
+}
+
+
+void RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset,
+                                                    Label* on_end_of_input,
+                                                    bool check_bounds,
+                                                    int characters) {
+  ASSERT(cp_offset >= -1);      // ^ and \b can look behind one character.
+  ASSERT(cp_offset < (1<<30));  // Be sane! (And ensure negation works)
+  CheckPosition(cp_offset + characters - 1, on_end_of_input);
+  LoadCurrentCharacterUnchecked(cp_offset, characters);
+}
+
+
+void RegExpMacroAssemblerIA32::PopCurrentPosition() {
+  Pop(edi);
+}
+
+
+void RegExpMacroAssemblerIA32::PopRegister(int register_index) {
+  Pop(eax);
+  __ mov(register_location(register_index), eax);
+}
+
+
+void RegExpMacroAssemblerIA32::PushBacktrack(Label* label) {
+  Push(Immediate::CodeRelativeOffset(label));
+  CheckStackLimit();
+}
+
+
+void RegExpMacroAssemblerIA32::PushCurrentPosition() {
+  Push(edi);
+}
+
+
+void RegExpMacroAssemblerIA32::PushRegister(int register_index,
+                                            StackCheckFlag check_stack_limit) {
+  __ mov(eax, register_location(register_index));
+  Push(eax);
+  if (check_stack_limit) CheckStackLimit();
+}
+
+
+void RegExpMacroAssemblerIA32::ReadCurrentPositionFromRegister(int reg) {
+  __ mov(edi, register_location(reg));
+}
+
+
+void RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) {
+  __ mov(backtrack_stackpointer(), register_location(reg));
+  __ add(backtrack_stackpointer(), Operand(ebp, kStackHighEnd));
+}
+
+
+void RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) {
+  ASSERT(register_index >= num_saved_registers_);  // Reserved for positions!
+  __ mov(register_location(register_index), Immediate(to));
+}
+
+
+void RegExpMacroAssemblerIA32::Succeed() {
+  __ jmp(&success_label_);
+}
+
+
+void RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister(int reg,
+                                                              int cp_offset) {
+  if (cp_offset == 0) {
+    __ mov(register_location(reg), edi);
+  } else {
+    __ lea(eax, Operand(edi, cp_offset * char_size()));
+    __ mov(register_location(reg), eax);
+  }
+}
+
+
+void RegExpMacroAssemblerIA32::ClearRegisters(int reg_from, int reg_to) {
+  ASSERT(reg_from <= reg_to);
+  __ mov(eax, Operand(ebp, kInputStartMinusOne));
+  for (int reg = reg_from; reg <= reg_to; reg++) {
+    __ mov(register_location(reg), eax);
+  }
+}
+
+
+void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) {
+  __ mov(eax, backtrack_stackpointer());
+  __ sub(eax, Operand(ebp, kStackHighEnd));
+  __ mov(register_location(reg), eax);
+}
+
+
+RegExpMacroAssemblerIA32::Result RegExpMacroAssemblerIA32::Match(
+    Handle<Code> regexp_code,
+    Handle<String> subject,
+    int* offsets_vector,
+    int offsets_vector_length,
+    int previous_index) {
+
+  ASSERT(subject->IsFlat());
+  ASSERT(previous_index >= 0);
+  ASSERT(previous_index <= subject->length());
+
+  // No allocations before calling the regexp, but we can't use
+  // AssertNoAllocation, since regexps might be preempted, and another thread
+  // might do allocation anyway.
+
+  String* subject_ptr = *subject;
+  // Character offsets into string.
+  int start_offset = previous_index;
+  int end_offset = subject_ptr->length();
+
+  bool is_ascii = StringShape(*subject).IsAsciiRepresentation();
+
+  if (StringShape(subject_ptr).IsCons()) {
+    subject_ptr = ConsString::cast(subject_ptr)->first();
+  } else if (StringShape(subject_ptr).IsSliced()) {
+    SlicedString* slice = SlicedString::cast(subject_ptr);
+    start_offset += slice->start();
+    end_offset += slice->start();
+    subject_ptr = slice->buffer();
+  }
+  // Ensure that an underlying string has the same ascii-ness.
+  ASSERT(StringShape(subject_ptr).IsAsciiRepresentation() == is_ascii);
+  ASSERT(subject_ptr->IsExternalString() || subject_ptr->IsSeqString());
+  // String is now either Sequential or External
+  int char_size_shift = is_ascii ? 0 : 1;
+  int char_length = end_offset - start_offset;
+
+  const byte* input_start =
+      StringCharacterPosition(subject_ptr, start_offset);
+  int byte_length = char_length << char_size_shift;
+  const byte* input_end = input_start + byte_length;
+  RegExpMacroAssemblerIA32::Result res = Execute(*regexp_code,
+                                                 subject_ptr,
+                                                 start_offset,
+                                                 input_start,
+                                                 input_end,
+                                                 offsets_vector,
+                                                 previous_index == 0);
+
+  if (res == SUCCESS) {
+    // Capture values are relative to start_offset only.
+    // Convert them to be relative to start of string.
+    for (int i = 0; i < offsets_vector_length; i++) {
+      if (offsets_vector[i] >= 0) {
+        offsets_vector[i] += previous_index;
+      }
+    }
+  }
+
+  return res;
+}
+
+// Private methods:
+
+static unibrow::Mapping<unibrow::Ecma262Canonicalize> canonicalize;
+
+RegExpMacroAssemblerIA32::Result RegExpMacroAssemblerIA32::Execute(
+    Code* code,
+    String* input,
+    int start_offset,
+    const byte* input_start,
+    const byte* input_end,
+    int* output,
+    bool at_start) {
+  typedef int (*matcher)(String*, int, const byte*,
+                         const byte*, int*, int, Address);
+  matcher matcher_func = FUNCTION_CAST<matcher>(code->entry());
+
+  int at_start_val = at_start ? 1 : 0;
+
+  // Ensure that the minimum stack has been allocated.
+  RegExpStack stack;
+  Address stack_top = RegExpStack::stack_top();
+
+  int result = matcher_func(input,
+                            start_offset,
+                            input_start,
+                            input_end,
+                            output,
+                            at_start_val,
+                            stack_top);
+  ASSERT(result <= SUCCESS);
+  ASSERT(result >= RETRY);
+
+  if (result == EXCEPTION && !Top::has_pending_exception()) {
+    // We detected a stack overflow (on the backtrack stack) in RegExp code,
+    // but haven't created the exception yet.
+    Top::StackOverflow();
+  }
+  return static_cast<Result>(result);
+}
+
+
+int RegExpMacroAssemblerIA32::CaseInsensitiveCompareUC16(Address byte_offset1,
+                                                         Address byte_offset2,
+                                                         size_t byte_length) {
+  // This function is not allowed to cause a garbage collection.
+  // A GC might move the calling generated code and invalidate the
+  // return address on the stack.
+  ASSERT(byte_length % 2 == 0);
+  uc16* substring1 = reinterpret_cast<uc16*>(byte_offset1);
+  uc16* substring2 = reinterpret_cast<uc16*>(byte_offset2);
+  size_t length = byte_length >> 1;
+
+  for (size_t i = 0; i < length; i++) {
+    unibrow::uchar c1 = substring1[i];
+    unibrow::uchar c2 = substring2[i];
+    if (c1 != c2) {
+      canonicalize.get(c1, '\0', &c1);
+      if (c1 != c2) {
+        canonicalize.get(c2, '\0', &c2);
+        if (c1 != c2) {
+          return 0;
+        }
+      }
+    }
+  }
+  return 1;
+}
+
+
+void RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch) {
+  int num_arguments = 3;
+  FrameAlign(num_arguments, scratch);
+  // RegExp code frame pointer.
+  __ mov(Operand(esp, 2 * kPointerSize), ebp);
+  // Code* of self.
+  __ mov(Operand(esp, 1 * kPointerSize), Immediate(masm_->CodeObject()));
+  // Next address on the stack (will be address of return address).
+  __ lea(eax, Operand(esp, -kPointerSize));
+  __ mov(Operand(esp, 0 * kPointerSize), eax);
+  CallCFunction(FUNCTION_ADDR(&CheckStackGuardState), num_arguments);
+}
+
+
+// Helper function for reading a value out of a stack frame.
+template <typename T>
+static T& frame_entry(Address re_frame, int frame_offset) {
+  return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset));
+}
+
+
+const byte* RegExpMacroAssemblerIA32::StringCharacterPosition(String* subject,
+                                                              int start_index) {
+  // Not just flat, but ultra flat.
+  ASSERT(subject->IsExternalString() || subject->IsSeqString());
+  ASSERT(start_index >= 0);
+  ASSERT(start_index <= subject->length());
+  if (StringShape(subject).IsAsciiRepresentation()) {
+    const byte* address;
+    if (StringShape(subject).IsExternal()) {
+      const char* data = ExternalAsciiString::cast(subject)->resource()->data();
+      address = reinterpret_cast<const byte*>(data);
+    } else {
+      ASSERT(subject->IsSeqAsciiString());
+      char* data = SeqAsciiString::cast(subject)->GetChars();
+      address = reinterpret_cast<const byte*>(data);
+    }
+    return address + start_index;
+  }
+  const uc16* data;
+  if (StringShape(subject).IsExternal()) {
+    data = ExternalTwoByteString::cast(subject)->resource()->data();
+  } else {
+    ASSERT(subject->IsSeqTwoByteString());
+    data = SeqTwoByteString::cast(subject)->GetChars();
+  }
+  return reinterpret_cast<const byte*>(data + start_index);
+}
+
+
+int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address,
+                                                   Code* re_code,
+                                                   Address re_frame) {
+  if (StackGuard::IsStackOverflow()) {
+    Top::StackOverflow();
+    return EXCEPTION;
+  }
+
+  // If not real stack overflow the stack guard was used to interrupt
+  // execution for another purpose.
+
+  // Prepare for possible GC.
+  HandleScope handles;
+  Handle<Code> code_handle(re_code);
+
+  Handle<String> subject(frame_entry<String*>(re_frame, kInputString));
+  // Current string.
+  bool is_ascii = StringShape(*subject).IsAsciiRepresentation();
+
+  ASSERT(re_code->instruction_start() <= *return_address);
+  ASSERT(*return_address <=
+      re_code->instruction_start() + re_code->instruction_size());
+
+  Object* result = Execution::HandleStackGuardInterrupt();
+
+  if (*code_handle != re_code) {  // Return address no longer valid
+    int delta = *code_handle - re_code;
+    // Overwrite the return address on the stack.
+    *return_address += delta;
+  }
+
+  if (result->IsException()) {
+    return EXCEPTION;
+  }
+
+  // String might have changed.
+  if (StringShape(*subject).IsAsciiRepresentation() != is_ascii) {
+    // If we changed between an ASCII and an UC16 string, the specialized
+    // code cannot be used, and we need to restart regexp matching from
+    // scratch (including, potentially, compiling a new version of the code).
+    return RETRY;
+  }
+
+  // Otherwise, the content of the string might have moved. It must still
+  // be a sequential or external string with the same content.
+  // Update the start and end pointers in the stack frame to the current
+  // location (whether it has actually moved or not).
+  ASSERT(StringShape(*subject).IsSequential() ||
+      StringShape(*subject).IsExternal());
+
+  // The original start address of the characters to match.
+  const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart);
+
+  // Find the current start address of the same character at the current string
+  // position.
+  int start_index = frame_entry<int>(re_frame, kStartIndex);
+  const byte* new_address = StringCharacterPosition(*subject, start_index);
+
+  if (start_address != new_address) {
+    // If there is a difference, update start and end addresses in the
+    // RegExp stack frame to match the new value.
+    const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd);
+    int byte_length = end_address - start_address;
+    frame_entry<const byte*>(re_frame, kInputStart) = new_address;
+    frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length;
+  }
+
+  return 0;
+}
+
+
+Address RegExpMacroAssemblerIA32::GrowStack(Address stack_pointer,
+                                            Address* stack_top) {
+  size_t size = RegExpStack::stack_capacity();
+  Address old_stack_top = RegExpStack::stack_top();
+  ASSERT(old_stack_top == *stack_top);
+  ASSERT(stack_pointer <= old_stack_top);
+  ASSERT(static_cast<size_t>(old_stack_top - stack_pointer) <= size);
+  Address new_stack_top = RegExpStack::EnsureCapacity(size * 2);
+  if (new_stack_top == NULL) {
+    return NULL;
+  }
+  *stack_top = new_stack_top;
+  return new_stack_top - (old_stack_top - stack_pointer);
+}
+
+
+Operand RegExpMacroAssemblerIA32::register_location(int register_index) {
+  ASSERT(register_index < (1<<30));
+  if (num_registers_ <= register_index) {
+    num_registers_ = register_index + 1;
+  }
+  return Operand(ebp, kRegisterZero - register_index * kPointerSize);
+}
+
+
+void RegExpMacroAssemblerIA32::CheckPosition(int cp_offset,
+                                             Label* on_outside_input) {
+  __ cmp(edi, -cp_offset * char_size());
+  BranchOrBacktrack(greater_equal, on_outside_input);
+}
+
+
+void RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition,
+                                                 Label* to,
+                                                 Hint hint) {
+  if (condition < 0) {  // No condition
+    if (to == NULL) {
+      Backtrack();
+      return;
+    }
+    __ jmp(to);
+    return;
+  }
+  if (to == NULL) {
+    __ j(condition, &backtrack_label_, hint);
+    return;
+  }
+  __ j(condition, to, hint);
+}
+
+
+void RegExpMacroAssemblerIA32::SafeCall(Label* to) {
+  Label return_to;
+  __ push(Immediate::CodeRelativeOffset(&return_to));
+  __ jmp(to);
+  __ bind(&return_to);
+}
+
+
+void RegExpMacroAssemblerIA32::SafeReturn() {
+  __ pop(ebx);
+  __ add(Operand(ebx), Immediate(masm_->CodeObject()));
+  __ jmp(Operand(ebx));
+}
+
+
+void RegExpMacroAssemblerIA32::Push(Register source) {
+  ASSERT(!source.is(backtrack_stackpointer()));
+  // Notice: This updates flags, unlike normal Push.
+  __ sub(Operand(backtrack_stackpointer()), Immediate(kPointerSize));
+  __ mov(Operand(backtrack_stackpointer(), 0), source);
+}
+
+
+void RegExpMacroAssemblerIA32::Push(Immediate value) {
+  // Notice: This updates flags, unlike normal Push.
+  __ sub(Operand(backtrack_stackpointer()), Immediate(kPointerSize));
+  __ mov(Operand(backtrack_stackpointer(), 0), value);
+}
+
+
+void RegExpMacroAssemblerIA32::Pop(Register target) {
+  ASSERT(!target.is(backtrack_stackpointer()));
+  __ mov(target, Operand(backtrack_stackpointer(), 0));
+  // Notice: This updates flags, unlike normal Pop.
+  __ add(Operand(backtrack_stackpointer()), Immediate(kPointerSize));
+}
+
+
+void RegExpMacroAssemblerIA32::CheckPreemption() {
+  // Check for preemption.
+  Label no_preempt;
+  ExternalReference stack_guard_limit =
+      ExternalReference::address_of_stack_guard_limit();
+  __ cmp(esp, Operand::StaticVariable(stack_guard_limit));
+  __ j(above, &no_preempt, taken);
+
+  SafeCall(&check_preempt_label_);
+
+  __ bind(&no_preempt);
+}
+
+
+void RegExpMacroAssemblerIA32::CheckStackLimit() {
+  if (FLAG_check_stack) {
+    Label no_stack_overflow;
+    ExternalReference stack_limit =
+        ExternalReference::address_of_regexp_stack_limit();
+    __ cmp(backtrack_stackpointer(), Operand::StaticVariable(stack_limit));
+    __ j(above, &no_stack_overflow);
+
+    SafeCall(&stack_overflow_label_);
+
+    __ bind(&no_stack_overflow);
+  }
+}
+
+
+void RegExpMacroAssemblerIA32::FrameAlign(int num_arguments, Register scratch) {
+  // TODO(lrn): Since we no longer use the system stack arbitrarily (but we do
+  // use it, e.g., for SafeCall), we know the number of elements on the stack
+  // since the last frame alignment. We might be able to do this simpler then.
+  int frameAlignment = OS::ActivationFrameAlignment();
+  if (frameAlignment != 0) {
+    // Make stack end at alignment and make room for num_arguments words
+    // and the original value of esp.
+    __ mov(scratch, esp);
+    __ sub(Operand(esp), Immediate((num_arguments + 1) * kPointerSize));
+    ASSERT(IsPowerOf2(frameAlignment));
+    __ and_(esp, -frameAlignment);
+    __ mov(Operand(esp, num_arguments * kPointerSize), scratch);
+  } else {
+    __ sub(Operand(esp), Immediate(num_arguments * kPointerSize));
+  }
+}
+
+
+void RegExpMacroAssemblerIA32::CallCFunction(Address function_address,
+                                             int num_arguments) {
+  __ mov(Operand(eax), Immediate(reinterpret_cast<int32_t>(function_address)));
+  __ call(Operand(eax));
+  if (OS::ActivationFrameAlignment() != 0) {
+    __ mov(esp, Operand(esp, num_arguments * kPointerSize));
+  } else {
+    __ add(Operand(esp), Immediate(num_arguments * sizeof(int32_t)));
+  }
+}
+
+
+void RegExpMacroAssemblerIA32::LoadCurrentCharacterUnchecked(int cp_offset,
+                                                             int characters) {
+  if (mode_ == ASCII) {
+    if (characters == 4) {
+      __ mov(current_character(), Operand(esi, edi, times_1, cp_offset));
+    } else if (characters == 2) {
+      __ movzx_w(current_character(), Operand(esi, edi, times_1, cp_offset));
+    } else {
+      ASSERT(characters == 1);
+      __ movzx_b(current_character(), Operand(esi, edi, times_1, cp_offset));
+    }
+  } else {
+    ASSERT(mode_ == UC16);
+    if (characters == 2) {
+      __ mov(current_character(),
+             Operand(esi, edi, times_1, cp_offset * sizeof(uc16)));
+    } else {
+      ASSERT(characters == 1);
+      __ movzx_w(current_character(),
+                 Operand(esi, edi, times_1, cp_offset * sizeof(uc16)));
+    }
+  }
+}
+
+
+void RegExpMacroAssemblerIA32::LoadConstantBufferAddress(Register reg,
+                                                         ArraySlice* buffer) {
+  __ mov(reg, buffer->array());
+  __ add(Operand(reg), Immediate(buffer->base_offset()));
+}
+
+#undef __
+}}  // namespace v8::internal
diff --git a/deps/v8/src/regexp-macro-assembler-ia32.h b/deps/v8/src/regexp-macro-assembler-ia32.h
new file mode 100644
index 0000000..0309f20
--- /dev/null
+++ b/deps/v8/src/regexp-macro-assembler-ia32.h
@@ -0,0 +1,285 @@
+// Copyright 2008-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.
+
+#ifndef REGEXP_MACRO_ASSEMBLER_IA32_H_
+#define REGEXP_MACRO_ASSEMBLER_IA32_H_
+
+namespace v8 { namespace internal {
+
+class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
+ public:
+  // Type of input string to generate code for.
+  enum Mode { ASCII = 1, UC16 = 2 };
+  // Result of calling the generated RegExp code:
+  // RETRY: Something significant changed during execution, and the matching
+  //        should be retried from scratch.
+  // EXCEPTION: Something failed during execution. If no exception has been
+  //        thrown, it's an internal out-of-memory, and the caller should
+  //        throw the exception.
+  // FAILURE: Matching failed.
+  // SUCCESS: Matching succeeded, and the output array has been filled with
+  //        capture positions.
+  enum Result { RETRY = -2, EXCEPTION = -1, FAILURE = 0, SUCCESS = 1 };
+
+  RegExpMacroAssemblerIA32(Mode mode, int registers_to_save);
+  virtual ~RegExpMacroAssemblerIA32();
+  virtual int stack_limit_slack();
+  virtual void AdvanceCurrentPosition(int by);
+  virtual void AdvanceRegister(int reg, int by);
+  virtual void Backtrack();
+  virtual void Bind(Label* label);
+  virtual void CheckAtStart(Label* on_at_start);
+  virtual void CheckBitmap(uc16 start, Label* bitmap, Label* on_zero);
+  virtual void CheckCharacter(uint32_t c, Label* on_equal);
+  virtual void CheckCharacterAfterAnd(uint32_t c,
+                                      uint32_t mask,
+                                      Label* on_equal);
+  virtual void CheckCharacterGT(uc16 limit, Label* on_greater);
+  virtual void CheckCharacterLT(uc16 limit, Label* on_less);
+  virtual void CheckCharacters(Vector<const uc16> str,
+                               int cp_offset,
+                               Label* on_failure,
+                               bool check_end_of_string);
+  // A "greedy loop" is a loop that is both greedy and with a simple
+  // body. It has a particularly simple implementation.
+  virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
+  virtual void CheckNotAtStart(Label* on_not_at_start);
+  virtual void CheckNotBackReference(int start_reg, Label* on_no_match);
+  virtual void CheckNotBackReferenceIgnoreCase(int start_reg,
+                                               Label* on_no_match);
+  virtual void CheckNotRegistersEqual(int reg1, int reg2, Label* on_not_equal);
+  virtual void CheckNotCharacter(uint32_t c, Label* on_not_equal);
+  virtual void CheckNotCharacterAfterAnd(uint32_t c,
+                                         uint32_t mask,
+                                         Label* on_not_equal);
+  virtual void CheckNotCharacterAfterMinusAnd(uc16 c,
+                                              uc16 minus,
+                                              uc16 mask,
+                                              Label* on_not_equal);
+  // Checks whether the given offset from the current position is before
+  // the end of the string.
+  virtual void CheckPosition(int cp_offset, Label* on_outside_input);
+  virtual bool CheckSpecialCharacterClass(uc16 type,
+                                          int cp_offset,
+                                          bool check_offset,
+                                          Label* on_no_match);
+  virtual void DispatchByteMap(uc16 start,
+                               Label* byte_map,
+                               const Vector<Label*>& destinations);
+  virtual void DispatchHalfNibbleMap(uc16 start,
+                                     Label* half_nibble_map,
+                                     const Vector<Label*>& destinations);
+  virtual void DispatchHighByteMap(byte start,
+                                   Label* byte_map,
+                                   const Vector<Label*>& destinations);
+  virtual void EmitOrLink(Label* label);
+  virtual void Fail();
+  virtual Handle<Object> GetCode(Handle<String> source);
+  virtual void GoTo(Label* label);
+  virtual void IfRegisterGE(int reg, int comparand, Label* if_ge);
+  virtual void IfRegisterLT(int reg, int comparand, Label* if_lt);
+  virtual void IfRegisterEqPos(int reg, Label* if_eq);
+  virtual IrregexpImplementation Implementation();
+  virtual void LoadCurrentCharacter(int cp_offset,
+                                    Label* on_end_of_input,
+                                    bool check_bounds = true,
+                                    int characters = 1);
+  virtual void PopCurrentPosition();
+  virtual void PopRegister(int register_index);
+  virtual void PushBacktrack(Label* label);
+  virtual void PushCurrentPosition();
+  virtual void PushRegister(int register_index,
+                            StackCheckFlag check_stack_limit);
+  virtual void ReadCurrentPositionFromRegister(int reg);
+  virtual void ReadStackPointerFromRegister(int reg);
+  virtual void SetRegister(int register_index, int to);
+  virtual void Succeed();
+  virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
+  virtual void ClearRegisters(int reg_from, int reg_to);
+  virtual void WriteStackPointerToRegister(int reg);
+
+  static Result Match(Handle<Code> regexp,
+                      Handle<String> subject,
+                      int* offsets_vector,
+                      int offsets_vector_length,
+                      int previous_index);
+
+  static Result Execute(Code* code,
+                        String* input,
+                        int start_offset,
+                        const byte* input_start,
+                        const byte* input_end,
+                        int* output,
+                        bool at_start);
+
+ private:
+  // Offsets from ebp of function parameters and stored registers.
+  static const int kFramePointer = 0;
+  // Above the frame pointer - function parameters and return address.
+  static const int kReturn_eip = kFramePointer + kPointerSize;
+  static const int kFrameAlign = kReturn_eip + kPointerSize;
+  // Parameters.
+  static const int kInputString = kFrameAlign;
+  static const int kStartIndex = kInputString + kPointerSize;
+  static const int kInputStart = kStartIndex + kPointerSize;
+  static const int kInputEnd = kInputStart + kPointerSize;
+  static const int kRegisterOutput = kInputEnd + kPointerSize;
+  static const int kAtStart = kRegisterOutput + kPointerSize;
+  static const int kStackHighEnd = kAtStart + kPointerSize;
+  // Below the frame pointer - local stack variables.
+  // When adding local variables remember to push space for them in
+  // the frame in GetCode.
+  static const int kBackup_esi = kFramePointer - kPointerSize;
+  static const int kBackup_edi = kBackup_esi - kPointerSize;
+  static const int kBackup_ebx = kBackup_edi - kPointerSize;
+  static const int kInputStartMinusOne = kBackup_ebx - kPointerSize;
+  // First register address. Following registers are below it on the stack.
+  static const int kRegisterZero = kInputStartMinusOne - kPointerSize;
+
+  // Initial size of code buffer.
+  static const size_t kRegExpCodeSize = 1024;
+  // Initial size of constant buffers allocated during compilation.
+  static const int kRegExpConstantsSize = 256;
+
+  static const byte* StringCharacterPosition(String* subject, int start_index);
+
+  // Compares two-byte strings case insensitively.
+  // Called from generated RegExp code.
+  static int CaseInsensitiveCompareUC16(Address byte_offset1,
+                                        Address byte_offset2,
+                                        size_t byte_length);
+
+  // Load a number of characters at the given offset from the
+  // current position, into the current-character register.
+  void LoadCurrentCharacterUnchecked(int cp_offset, int character_count);
+
+  // Check whether preemption has been requested.
+  void CheckPreemption();
+
+  // Check whether we are exceeding the stack limit on the backtrack stack.
+  void CheckStackLimit();
+
+  // Called from RegExp if the stack-guard is triggered.
+  // If the code object is relocated, the return address is fixed before
+  // returning.
+  static int CheckStackGuardState(Address* return_address,
+                                  Code* re_code,
+                                  Address re_frame);
+
+  // Generate a call to CheckStackGuardState.
+  void CallCheckStackGuardState(Register scratch);
+
+  // Called from RegExp if the backtrack stack limit is hit.
+  // Tries to expand the stack. Returns the new stack-pointer if
+  // successful, and updates the stack_top address, or returns 0 if unable
+  // to grow the stack.
+  // This function must not trigger a garbage collection.
+  static Address GrowStack(Address stack_pointer, Address* stack_top);
+
+  // The ebp-relative location of a regexp register.
+  Operand register_location(int register_index);
+
+  // The register containing the current character after LoadCurrentCharacter.
+  inline Register current_character() { return edx; }
+
+  // The register containing the backtrack stack top. Provides a meaningful
+  // name to the register.
+  inline Register backtrack_stackpointer() { return ecx; }
+
+  // Byte size of chars in the string to match (decided by the Mode argument)
+  inline int char_size() { return static_cast<int>(mode_); }
+
+  // Equivalent to a conditional branch to the label, unless the label
+  // is NULL, in which case it is a conditional Backtrack.
+  void BranchOrBacktrack(Condition condition, Label* to, Hint hint = no_hint);
+
+  // Load the address of a "constant buffer" (a slice of a byte array)
+  // into a register. The address is computed from the ByteArray* address
+  // and an offset. Uses no extra registers.
+  void LoadConstantBufferAddress(Register reg, ArraySlice* buffer);
+
+  // Call and return internally in the generated code in a way that
+  // is GC-safe (i.e., doesn't leave absolute code addresses on the stack)
+  inline void SafeCall(Label* to);
+  inline void SafeReturn();
+
+  // Pushes the value of a register on the backtrack stack. Decrements the
+  // stack pointer (ecx) by a word size and stores the register's value there.
+  inline void Push(Register source);
+
+  // Pushes a value on the backtrack stack. Decrements the stack pointer (ecx)
+  // by a word size and stores the value there.
+  inline void Push(Immediate value);
+
+  // Pops a value from the backtrack stack. Reads the word at the stack pointer
+  // (ecx) and increments it by a word size.
+  inline void Pop(Register target);
+
+  // 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.
+  // Some compilers/platforms require the stack to be aligned when calling
+  // C++ code.
+  // Needs a scratch register to do some arithmetic. This register will be
+  // trashed.
+  inline void FrameAlign(int num_arguments, Register scratch);
+
+  // Calls a C function and cleans up the space for arguments allocated
+  // by FrameAlign. The called function is not allowed to trigger a garbage
+  // collection, since that might move the code and invalidate the return
+  // address (unless this is somehow accounted for).
+  inline void CallCFunction(Address function_address, int num_arguments);
+
+  MacroAssembler* masm_;
+
+  // Constant buffer provider. Allocates external storage for storing
+  // constants.
+  ByteArrayProvider constants_;
+
+  // Which mode to generate code for (ASCII or UC16).
+  Mode mode_;
+
+  // One greater than maximal register index actually used.
+  int num_registers_;
+
+  // Number of registers to output at the end (the saved registers
+  // are always 0..num_saved_registers_-1)
+  int num_saved_registers_;
+
+  // Labels used internally.
+  Label entry_label_;
+  Label start_label_;
+  Label success_label_;
+  Label backtrack_label_;
+  Label exit_label_;
+  Label check_preempt_label_;
+  Label stack_overflow_label_;
+};
+
+}}  // namespace v8::internal
+
+#endif /* REGEXP_MACRO_ASSEMBLER_IA32_H_ */
diff --git a/deps/v8/src/regexp-macro-assembler-irregexp-inl.h b/deps/v8/src/regexp-macro-assembler-irregexp-inl.h
new file mode 100644
index 0000000..3785291
--- /dev/null
+++ b/deps/v8/src/regexp-macro-assembler-irregexp-inl.h
@@ -0,0 +1,71 @@
+// Copyright 2008-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.
+
+// A light-weight assembler for the Irregexp byte code.
+
+
+#include "v8.h"
+#include "ast.h"
+#include "bytecodes-irregexp.h"
+
+
+namespace v8 { namespace internal {
+
+
+void RegExpMacroAssemblerIrregexp::Emit(uint32_t byte,
+                                        uint32_t twenty_four_bits) {
+  uint32_t word = ((twenty_four_bits << BYTECODE_SHIFT) | byte);
+  ASSERT(pc_ <= buffer_.length());
+  if (pc_  + 3 >= buffer_.length()) {
+    Expand();
+  }
+  *reinterpret_cast<uint32_t*>(buffer_.start() + pc_) = word;
+  pc_ += 4;
+}
+
+
+void RegExpMacroAssemblerIrregexp::Emit16(uint32_t word) {
+  ASSERT(pc_ <= buffer_.length());
+  if (pc_ + 1 >= buffer_.length()) {
+    Expand();
+  }
+  *reinterpret_cast<uint16_t*>(buffer_.start() + pc_) = word;
+  pc_ += 2;
+}
+
+
+void RegExpMacroAssemblerIrregexp::Emit32(uint32_t word) {
+  ASSERT(pc_ <= buffer_.length());
+  if (pc_ + 3 >= buffer_.length()) {
+    Expand();
+  }
+  *reinterpret_cast<uint32_t*>(buffer_.start() + pc_) = word;
+  pc_ += 4;
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/regexp-macro-assembler-irregexp.cc b/deps/v8/src/regexp-macro-assembler-irregexp.cc
new file mode 100644
index 0000000..436db35
--- /dev/null
+++ b/deps/v8/src/regexp-macro-assembler-irregexp.cc
@@ -0,0 +1,491 @@
+// Copyright 2008-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.
+
+#include "v8.h"
+#include "ast.h"
+#include "bytecodes-irregexp.h"
+#include "regexp-macro-assembler.h"
+#include "regexp-macro-assembler-irregexp.h"
+#include "regexp-macro-assembler-irregexp-inl.h"
+
+
+namespace v8 { namespace internal {
+
+
+RegExpMacroAssemblerIrregexp::RegExpMacroAssemblerIrregexp(Vector<byte> buffer)
+    : buffer_(buffer),
+      pc_(0),
+      own_buffer_(false),
+      advance_current_end_(kInvalidPC) {
+}
+
+
+RegExpMacroAssemblerIrregexp::~RegExpMacroAssemblerIrregexp() {
+  if (backtrack_.is_linked()) backtrack_.Unuse();
+}
+
+
+RegExpMacroAssemblerIrregexp::IrregexpImplementation
+RegExpMacroAssemblerIrregexp::Implementation() {
+  return kBytecodeImplementation;
+}
+
+
+void RegExpMacroAssemblerIrregexp::Bind(Label* l) {
+  advance_current_end_ = kInvalidPC;
+  ASSERT(!l->is_bound());
+  if (l->is_linked()) {
+    int pos = l->pos();
+    while (pos != 0) {
+      int fixup = pos;
+      pos = *reinterpret_cast<int32_t*>(buffer_.start() + fixup);
+      *reinterpret_cast<uint32_t*>(buffer_.start() + fixup) = pc_;
+    }
+  }
+  l->bind_to(pc_);
+}
+
+
+void RegExpMacroAssemblerIrregexp::EmitOrLink(Label* l) {
+  if (l == NULL) l = &backtrack_;
+  if (l->is_bound()) {
+    Emit32(l->pos());
+  } else {
+    int pos = 0;
+    if (l->is_linked()) {
+      pos = l->pos();
+    }
+    l->link_to(pc_);
+    Emit32(pos);
+  }
+}
+
+
+void RegExpMacroAssemblerIrregexp::PopRegister(int register_index) {
+  ASSERT(register_index >= 0);
+  ASSERT(register_index <= kMaxRegister);
+  Emit(BC_POP_REGISTER, register_index);
+}
+
+
+void RegExpMacroAssemblerIrregexp::PushRegister(
+    int register_index,
+    StackCheckFlag check_stack_limit) {
+  ASSERT(register_index >= 0);
+  ASSERT(register_index <= kMaxRegister);
+  Emit(BC_PUSH_REGISTER, register_index);
+}
+
+
+void RegExpMacroAssemblerIrregexp::WriteCurrentPositionToRegister(
+    int register_index, int cp_offset) {
+  ASSERT(register_index >= 0);
+  ASSERT(register_index <= kMaxRegister);
+  Emit(BC_SET_REGISTER_TO_CP, register_index);
+  Emit32(cp_offset);  // Current position offset.
+}
+
+
+void RegExpMacroAssemblerIrregexp::ClearRegisters(int reg_from, int reg_to) {
+  ASSERT(reg_from <= reg_to);
+  for (int reg = reg_from; reg <= reg_to; reg++) {
+    SetRegister(reg, -1);
+  }
+}
+
+
+void RegExpMacroAssemblerIrregexp::ReadCurrentPositionFromRegister(
+    int register_index) {
+  ASSERT(register_index >= 0);
+  ASSERT(register_index <= kMaxRegister);
+  Emit(BC_SET_CP_TO_REGISTER, register_index);
+}
+
+
+void RegExpMacroAssemblerIrregexp::WriteStackPointerToRegister(
+    int register_index) {
+  ASSERT(register_index >= 0);
+  ASSERT(register_index <= kMaxRegister);
+  Emit(BC_SET_REGISTER_TO_SP, register_index);
+}
+
+
+void RegExpMacroAssemblerIrregexp::ReadStackPointerFromRegister(
+    int register_index) {
+  ASSERT(register_index >= 0);
+  ASSERT(register_index <= kMaxRegister);
+  Emit(BC_SET_SP_TO_REGISTER, register_index);
+}
+
+
+void RegExpMacroAssemblerIrregexp::SetRegister(int register_index, int to) {
+  ASSERT(register_index >= 0);
+  ASSERT(register_index <= kMaxRegister);
+  Emit(BC_SET_REGISTER, register_index);
+  Emit32(to);
+}
+
+
+void RegExpMacroAssemblerIrregexp::AdvanceRegister(int register_index, int by) {
+  ASSERT(register_index >= 0);
+  ASSERT(register_index <= kMaxRegister);
+  Emit(BC_ADVANCE_REGISTER, register_index);
+  Emit32(by);
+}
+
+
+void RegExpMacroAssemblerIrregexp::PopCurrentPosition() {
+  Emit(BC_POP_CP, 0);
+}
+
+
+void RegExpMacroAssemblerIrregexp::PushCurrentPosition() {
+  Emit(BC_PUSH_CP, 0);
+}
+
+
+void RegExpMacroAssemblerIrregexp::Backtrack() {
+  Emit(BC_POP_BT, 0);
+}
+
+
+void RegExpMacroAssemblerIrregexp::GoTo(Label* l) {
+  if (advance_current_end_ == pc_) {
+    // Combine advance current and goto.
+    pc_ = advance_current_start_;
+    Emit(BC_ADVANCE_CP_AND_GOTO, advance_current_offset_);
+    EmitOrLink(l);
+    advance_current_end_ = kInvalidPC;
+  } else {
+    // Regular goto.
+    Emit(BC_GOTO, 0);
+    EmitOrLink(l);
+  }
+}
+
+
+void RegExpMacroAssemblerIrregexp::PushBacktrack(Label* l) {
+  Emit(BC_PUSH_BT, 0);
+  EmitOrLink(l);
+}
+
+
+void RegExpMacroAssemblerIrregexp::Succeed() {
+  Emit(BC_SUCCEED, 0);
+}
+
+
+void RegExpMacroAssemblerIrregexp::Fail() {
+  Emit(BC_FAIL, 0);
+}
+
+
+void RegExpMacroAssemblerIrregexp::AdvanceCurrentPosition(int by) {
+  ASSERT(by >= kMinCPOffset);
+  ASSERT(by <= kMaxCPOffset);
+  advance_current_start_ = pc_;
+  advance_current_offset_ = by;
+  Emit(BC_ADVANCE_CP, by);
+  advance_current_end_ = pc_;
+}
+
+
+void RegExpMacroAssemblerIrregexp::CheckGreedyLoop(
+      Label* on_tos_equals_current_position) {
+  Emit(BC_CHECK_GREEDY, 0);
+  EmitOrLink(on_tos_equals_current_position);
+}
+
+
+void RegExpMacroAssemblerIrregexp::LoadCurrentCharacter(int cp_offset,
+                                                        Label* on_failure,
+                                                        bool check_bounds,
+                                                        int characters) {
+  ASSERT(cp_offset >= kMinCPOffset);
+  ASSERT(cp_offset <= kMaxCPOffset);
+  int bytecode;
+  if (check_bounds) {
+    if (characters == 4) {
+      bytecode = BC_LOAD_4_CURRENT_CHARS;
+    } else if (characters == 2) {
+      bytecode = BC_LOAD_2_CURRENT_CHARS;
+    } else {
+      ASSERT(characters == 1);
+      bytecode = BC_LOAD_CURRENT_CHAR;
+    }
+  } else {
+    if (characters == 4) {
+      bytecode = BC_LOAD_4_CURRENT_CHARS_UNCHECKED;
+    } else if (characters == 2) {
+      bytecode = BC_LOAD_2_CURRENT_CHARS_UNCHECKED;
+    } else {
+      ASSERT(characters == 1);
+      bytecode = BC_LOAD_CURRENT_CHAR_UNCHECKED;
+    }
+  }
+  Emit(bytecode, cp_offset);
+  if (check_bounds) EmitOrLink(on_failure);
+}
+
+
+void RegExpMacroAssemblerIrregexp::CheckCharacterLT(uc16 limit,
+                                                    Label* on_less) {
+  Emit(BC_CHECK_LT, limit);
+  EmitOrLink(on_less);
+}
+
+
+void RegExpMacroAssemblerIrregexp::CheckCharacterGT(uc16 limit,
+                                                    Label* on_greater) {
+  Emit(BC_CHECK_GT, limit);
+  EmitOrLink(on_greater);
+}
+
+
+void RegExpMacroAssemblerIrregexp::CheckCharacter(uint32_t c, Label* on_equal) {
+  if (c > MAX_FIRST_ARG) {
+    Emit(BC_CHECK_4_CHARS, 0);
+    Emit32(c);
+  } else {
+    Emit(BC_CHECK_CHAR, c);
+  }
+  EmitOrLink(on_equal);
+}
+
+
+void RegExpMacroAssemblerIrregexp::CheckAtStart(Label* on_at_start) {
+  Emit(BC_CHECK_AT_START, 0);
+  EmitOrLink(on_at_start);
+}
+
+
+void RegExpMacroAssemblerIrregexp::CheckNotAtStart(Label* on_not_at_start) {
+  Emit(BC_CHECK_NOT_AT_START, 0);
+  EmitOrLink(on_not_at_start);
+}
+
+
+void RegExpMacroAssemblerIrregexp::CheckNotCharacter(uint32_t c,
+                                                     Label* on_not_equal) {
+  if (c > MAX_FIRST_ARG) {
+    Emit(BC_CHECK_NOT_4_CHARS, 0);
+    Emit32(c);
+  } else {
+    Emit(BC_CHECK_NOT_CHAR, c);
+  }
+  EmitOrLink(on_not_equal);
+}
+
+
+void RegExpMacroAssemblerIrregexp::CheckCharacterAfterAnd(
+    uint32_t c,
+    uint32_t mask,
+    Label* on_equal) {
+  if (c > MAX_FIRST_ARG) {
+    Emit(BC_AND_CHECK_4_CHARS, 0);
+    Emit32(c);
+  } else {
+    Emit(BC_AND_CHECK_CHAR, c);
+  }
+  Emit32(mask);
+  EmitOrLink(on_equal);
+}
+
+
+void RegExpMacroAssemblerIrregexp::CheckNotCharacterAfterAnd(
+    uint32_t c,
+    uint32_t mask,
+    Label* on_not_equal) {
+  if (c > MAX_FIRST_ARG) {
+    Emit(BC_AND_CHECK_NOT_4_CHARS, 0);
+    Emit32(c);
+  } else {
+    Emit(BC_AND_CHECK_NOT_CHAR, c);
+  }
+  Emit32(mask);
+  EmitOrLink(on_not_equal);
+}
+
+
+void RegExpMacroAssemblerIrregexp::CheckNotCharacterAfterMinusAnd(
+    uc16 c,
+    uc16 minus,
+    uc16 mask,
+    Label* on_not_equal) {
+  Emit(BC_MINUS_AND_CHECK_NOT_CHAR, c);
+  Emit16(minus);
+  Emit16(mask);
+  EmitOrLink(on_not_equal);
+}
+
+
+void RegExpMacroAssemblerIrregexp::CheckNotBackReference(int start_reg,
+                                                         Label* on_not_equal) {
+  ASSERT(start_reg >= 0);
+  ASSERT(start_reg <= kMaxRegister);
+  Emit(BC_CHECK_NOT_BACK_REF, start_reg);
+  EmitOrLink(on_not_equal);
+}
+
+
+void RegExpMacroAssemblerIrregexp::CheckNotBackReferenceIgnoreCase(
+    int start_reg,
+    Label* on_not_equal) {
+  ASSERT(start_reg >= 0);
+  ASSERT(start_reg <= kMaxRegister);
+  Emit(BC_CHECK_NOT_BACK_REF_NO_CASE, start_reg);
+  EmitOrLink(on_not_equal);
+}
+
+
+void RegExpMacroAssemblerIrregexp::CheckNotRegistersEqual(int reg1,
+                                                          int reg2,
+                                                          Label* on_not_equal) {
+  ASSERT(reg1 >= 0);
+  ASSERT(reg1 <= kMaxRegister);
+  Emit(BC_CHECK_NOT_REGS_EQUAL, reg1);
+  Emit32(reg2);
+  EmitOrLink(on_not_equal);
+}
+
+
+void RegExpMacroAssemblerIrregexp::CheckBitmap(uc16 start,
+                                           Label* bitmap,
+                                           Label* on_zero) {
+  UNIMPLEMENTED();
+}
+
+
+void RegExpMacroAssemblerIrregexp::DispatchHalfNibbleMap(
+    uc16 start,
+    Label* half_nibble_map,
+    const Vector<Label*>& table) {
+  UNIMPLEMENTED();
+}
+
+
+void RegExpMacroAssemblerIrregexp::DispatchByteMap(
+    uc16 start,
+    Label* byte_map,
+    const Vector<Label*>& table) {
+  UNIMPLEMENTED();
+}
+
+
+void RegExpMacroAssemblerIrregexp::DispatchHighByteMap(
+    byte start,
+    Label* byte_map,
+    const Vector<Label*>& table) {
+  UNIMPLEMENTED();
+}
+
+
+void RegExpMacroAssemblerIrregexp::CheckCharacters(
+  Vector<const uc16> str,
+  int cp_offset,
+  Label* on_failure,
+  bool check_end_of_string) {
+  ASSERT(cp_offset >= kMinCPOffset);
+  ASSERT(cp_offset + str.length() - 1 <= kMaxCPOffset);
+  // It is vital that this loop is backwards due to the unchecked character
+  // load below.
+  for (int i = str.length() - 1; i >= 0; i--) {
+    if (check_end_of_string && i == str.length() - 1) {
+      Emit(BC_LOAD_CURRENT_CHAR, cp_offset + i);
+      EmitOrLink(on_failure);
+    } else {
+      Emit(BC_LOAD_CURRENT_CHAR_UNCHECKED, cp_offset + i);
+    }
+    Emit(BC_CHECK_NOT_CHAR, str[i]);
+    EmitOrLink(on_failure);
+  }
+}
+
+
+void RegExpMacroAssemblerIrregexp::IfRegisterLT(int register_index,
+                                                int comparand,
+                                                Label* on_less_than) {
+  ASSERT(register_index >= 0);
+  ASSERT(register_index <= kMaxRegister);
+  Emit(BC_CHECK_REGISTER_LT, register_index);
+  Emit32(comparand);
+  EmitOrLink(on_less_than);
+}
+
+
+void RegExpMacroAssemblerIrregexp::IfRegisterGE(int register_index,
+                                                int comparand,
+                                                Label* on_greater_or_equal) {
+  ASSERT(register_index >= 0);
+  ASSERT(register_index <= kMaxRegister);
+  Emit(BC_CHECK_REGISTER_GE, register_index);
+  Emit32(comparand);
+  EmitOrLink(on_greater_or_equal);
+}
+
+
+void RegExpMacroAssemblerIrregexp::IfRegisterEqPos(int register_index,
+                                                   Label* on_eq) {
+  ASSERT(register_index >= 0);
+  ASSERT(register_index <= kMaxRegister);
+  Emit(BC_CHECK_REGISTER_EQ_POS, register_index);
+  EmitOrLink(on_eq);
+}
+
+
+Handle<Object> RegExpMacroAssemblerIrregexp::GetCode(Handle<String> source) {
+  Bind(&backtrack_);
+  Emit(BC_POP_BT, 0);
+  Handle<ByteArray> array = Factory::NewByteArray(length());
+  Copy(array->GetDataStartAddress());
+  return array;
+}
+
+
+int RegExpMacroAssemblerIrregexp::length() {
+  return pc_;
+}
+
+
+void RegExpMacroAssemblerIrregexp::Copy(Address a) {
+  memcpy(a, buffer_.start(), length());
+}
+
+
+void RegExpMacroAssemblerIrregexp::Expand() {
+  bool old_buffer_was_our_own = own_buffer_;
+  Vector<byte> old_buffer = buffer_;
+  buffer_ = Vector<byte>::New(old_buffer.length() * 2);
+  own_buffer_ = true;
+  memcpy(buffer_.start(), old_buffer.start(), old_buffer.length());
+  if (old_buffer_was_our_own) {
+    old_buffer.Dispose();
+  }
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/regexp-macro-assembler-irregexp.h b/deps/v8/src/regexp-macro-assembler-irregexp.h
new file mode 100644
index 0000000..9ed82e3
--- /dev/null
+++ b/deps/v8/src/regexp-macro-assembler-irregexp.h
@@ -0,0 +1,147 @@
+// Copyright 2008-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.
+
+#ifndef V8_REGEXP_MACRO_ASSEMBLER_IRREGEXP_H_
+#define V8_REGEXP_MACRO_ASSEMBLER_IRREGEXP_H_
+
+namespace v8 { namespace internal {
+
+
+class RegExpMacroAssemblerIrregexp: public RegExpMacroAssembler {
+ public:
+  // Create an assembler. Instructions and relocation information are emitted
+  // into a buffer, with the instructions starting from the beginning and the
+  // relocation information starting from the end of the buffer. See CodeDesc
+  // for a detailed comment on the layout (globals.h).
+  //
+  // If the provided buffer is NULL, the assembler allocates and grows its own
+  // buffer, and buffer_size determines the initial buffer size. The buffer is
+  // owned by the assembler and deallocated upon destruction of the assembler.
+  //
+  // If the provided buffer is not NULL, the assembler uses the provided buffer
+  // for code generation and assumes its size to be buffer_size. If the buffer
+  // is too small, a fatal error occurs. No deallocation of the buffer is done
+  // upon destruction of the assembler.
+  explicit RegExpMacroAssemblerIrregexp(Vector<byte>);
+  virtual ~RegExpMacroAssemblerIrregexp();
+  // The byte-code interpreter checks on each push anyway.
+  virtual int stack_limit_slack() { return 1; }
+  virtual void Bind(Label* label);
+  virtual void EmitOrLink(Label* label);
+  virtual void AdvanceCurrentPosition(int by);  // Signed cp change.
+  virtual void PopCurrentPosition();
+  virtual void PushCurrentPosition();
+  virtual void Backtrack();
+  virtual void GoTo(Label* label);
+  virtual void PushBacktrack(Label* label);
+  virtual void Succeed();
+  virtual void Fail();
+  virtual void PopRegister(int register_index);
+  virtual void PushRegister(int register_index,
+                            StackCheckFlag check_stack_limit);
+  virtual void AdvanceRegister(int reg, int by);  // r[reg] += by.
+  virtual void SetRegister(int register_index, int to);
+  virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
+  virtual void ClearRegisters(int reg_from, int reg_to);
+  virtual void ReadCurrentPositionFromRegister(int reg);
+  virtual void WriteStackPointerToRegister(int reg);
+  virtual void ReadStackPointerFromRegister(int reg);
+  virtual void LoadCurrentCharacter(int cp_offset,
+                                    Label* on_end_of_input,
+                                    bool check_bounds = true,
+                                    int characters = 1);
+  virtual void CheckCharacter(uint32_t c, Label* on_equal);
+  virtual void CheckCharacterAfterAnd(uint32_t c,
+                                      uint32_t mask,
+                                      Label* on_equal);
+  virtual void CheckCharacterGT(uc16 limit, Label* on_greater);
+  virtual void CheckCharacterLT(uc16 limit, Label* on_less);
+  virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
+  virtual void CheckAtStart(Label* on_at_start);
+  virtual void CheckNotAtStart(Label* on_not_at_start);
+  virtual void CheckNotCharacter(uint32_t c, Label* on_not_equal);
+  virtual void CheckNotCharacterAfterAnd(uint32_t c,
+                                         uint32_t mask,
+                                         Label* on_not_equal);
+  virtual void CheckNotCharacterAfterMinusAnd(uc16 c,
+                                              uc16 minus,
+                                              uc16 mask,
+                                              Label* on_not_equal);
+  virtual void CheckNotBackReference(int start_reg, Label* on_no_match);
+  virtual void CheckNotBackReferenceIgnoreCase(int start_reg,
+                                               Label* on_no_match);
+  virtual void CheckNotRegistersEqual(int reg1, int reg2, Label* on_not_equal);
+  virtual void CheckCharacters(Vector<const uc16> str,
+                               int cp_offset,
+                               Label* on_failure,
+                               bool check_end_of_string);
+  virtual void CheckBitmap(uc16 start, Label* bitmap, Label* on_zero);
+  virtual void DispatchHalfNibbleMap(uc16 start,
+                                     Label* half_nibble_map,
+                                     const Vector<Label*>& destinations);
+  virtual void DispatchByteMap(uc16 start,
+                               Label* byte_map,
+                               const Vector<Label*>& destinations);
+  virtual void DispatchHighByteMap(byte start,
+                                   Label* byte_map,
+                                   const Vector<Label*>& destinations);
+  virtual void IfRegisterLT(int register_index, int comparand, Label* if_lt);
+  virtual void IfRegisterGE(int register_index, int comparand, Label* if_ge);
+  virtual void IfRegisterEqPos(int register_index, Label* if_eq);
+
+  virtual IrregexpImplementation Implementation();
+  virtual Handle<Object> GetCode(Handle<String> source);
+ private:
+  void Expand();
+  // Code and bitmap emission.
+  inline void Emit32(uint32_t x);
+  inline void Emit16(uint32_t x);
+  inline void Emit(uint32_t bc, uint32_t arg);
+  // Bytecode buffer.
+  int length();
+  void Copy(Address a);
+
+  // The buffer into which code and relocation info are generated.
+  Vector<byte> buffer_;
+  // The program counter.
+  int pc_;
+  // True if the assembler owns the buffer, false if buffer is external.
+  bool own_buffer_;
+  Label backtrack_;
+
+  int advance_current_start_;
+  int advance_current_offset_;
+  int advance_current_end_;
+
+  static const int kInvalidPC = -1;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(RegExpMacroAssemblerIrregexp);
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_REGEXP_MACRO_ASSEMBLER_IRREGEXP_H_
diff --git a/deps/v8/src/regexp-macro-assembler-tracer.cc b/deps/v8/src/regexp-macro-assembler-tracer.cc
new file mode 100644
index 0000000..74345d8
--- /dev/null
+++ b/deps/v8/src/regexp-macro-assembler-tracer.cc
@@ -0,0 +1,420 @@
+// Copyright 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.
+
+#include "v8.h"
+#include "ast.h"
+#include "regexp-macro-assembler.h"
+#include "regexp-macro-assembler-tracer.h"
+
+namespace v8 { namespace internal {
+
+RegExpMacroAssemblerTracer::RegExpMacroAssemblerTracer(
+    RegExpMacroAssembler* assembler) :
+  assembler_(assembler) {
+  unsigned int type = assembler->Implementation();
+  ASSERT(type < 3);
+  const char* impl_names[3] = {"IA32", "ARM", "Bytecode"};
+  PrintF("RegExpMacroAssembler%s();\n", impl_names[type]);
+}
+
+
+RegExpMacroAssemblerTracer::~RegExpMacroAssemblerTracer() {
+}
+
+
+void RegExpMacroAssemblerTracer::Bind(Label* label) {
+  PrintF("label[%08x]: (Bind)\n", label, label);
+  assembler_->Bind(label);
+}
+
+
+void RegExpMacroAssemblerTracer::EmitOrLink(Label* label) {
+  PrintF(" EmitOrLink(label[%08x]);\n", label);
+  assembler_->EmitOrLink(label);
+}
+
+
+void RegExpMacroAssemblerTracer::AdvanceCurrentPosition(int by) {
+  PrintF(" AdvanceCurrentPosition(by=%d);\n", by);
+  assembler_->AdvanceCurrentPosition(by);
+}
+
+
+void RegExpMacroAssemblerTracer::CheckGreedyLoop(Label* label) {
+  PrintF(" CheckGreedyLoop(label[%08x]);\n\n", label);
+  assembler_->CheckGreedyLoop(label);
+}
+
+
+void RegExpMacroAssemblerTracer::PopCurrentPosition() {
+  PrintF(" PopCurrentPosition();\n");
+  assembler_->PopCurrentPosition();
+}
+
+
+void RegExpMacroAssemblerTracer::PushCurrentPosition() {
+  PrintF(" PushCurrentPosition();\n");
+  assembler_->PushCurrentPosition();
+}
+
+
+void RegExpMacroAssemblerTracer::Backtrack() {
+  PrintF(" Backtrack();\n");
+  assembler_->Backtrack();
+}
+
+
+void RegExpMacroAssemblerTracer::GoTo(Label* label) {
+  PrintF(" GoTo(label[%08x]);\n\n", label);
+  assembler_->GoTo(label);
+}
+
+
+void RegExpMacroAssemblerTracer::PushBacktrack(Label* label) {
+  PrintF(" PushBacktrack(label[%08x]);\n",
+         label);
+  assembler_->PushBacktrack(label);
+}
+
+
+void RegExpMacroAssemblerTracer::Succeed() {
+  PrintF(" Succeed();\n");
+  assembler_->Succeed();
+}
+
+
+void RegExpMacroAssemblerTracer::Fail() {
+  PrintF(" Fail();\n");
+  assembler_->Fail();
+}
+
+
+void RegExpMacroAssemblerTracer::PopRegister(int register_index) {
+  PrintF(" PopRegister(register=%d);\n", register_index);
+  assembler_->PopRegister(register_index);
+}
+
+
+void RegExpMacroAssemblerTracer::PushRegister(
+    int register_index,
+    StackCheckFlag check_stack_limit) {
+  PrintF(" PushRegister(register=%d, %s);\n",
+         register_index,
+         check_stack_limit ? "check stack limit" : "");
+  assembler_->PushRegister(register_index, check_stack_limit);
+}
+
+
+void RegExpMacroAssemblerTracer::AdvanceRegister(int reg, int by) {
+  PrintF(" AdvanceRegister(register=%d, by=%d);\n", reg, by);
+  assembler_->AdvanceRegister(reg, by);
+}
+
+
+void RegExpMacroAssemblerTracer::SetRegister(int register_index, int to) {
+  PrintF(" SetRegister(register=%d, to=%d);\n", register_index, to);
+  assembler_->SetRegister(register_index, to);
+}
+
+
+void RegExpMacroAssemblerTracer::WriteCurrentPositionToRegister(int reg,
+                                                                int cp_offset) {
+  PrintF(" WriteCurrentPositionToRegister(register=%d,cp_offset=%d);\n",
+         reg,
+         cp_offset);
+  assembler_->WriteCurrentPositionToRegister(reg, cp_offset);
+}
+
+
+void RegExpMacroAssemblerTracer::ClearRegisters(int reg_from, int reg_to) {
+  PrintF(" ClearRegister(from=%d, to=%d);\n", reg_from, reg_to);
+  assembler_->ClearRegisters(reg_from, reg_to);
+}
+
+
+void RegExpMacroAssemblerTracer::ReadCurrentPositionFromRegister(int reg) {
+  PrintF(" ReadCurrentPositionFromRegister(register=%d);\n", reg);
+  assembler_->ReadCurrentPositionFromRegister(reg);
+}
+
+
+void RegExpMacroAssemblerTracer::WriteStackPointerToRegister(int reg) {
+  PrintF(" WriteStackPointerToRegister(register=%d);\n", reg);
+  assembler_->WriteStackPointerToRegister(reg);
+}
+
+
+void RegExpMacroAssemblerTracer::ReadStackPointerFromRegister(int reg) {
+  PrintF(" ReadStackPointerFromRegister(register=%d);\n", reg);
+  assembler_->ReadStackPointerFromRegister(reg);
+}
+
+
+void RegExpMacroAssemblerTracer::LoadCurrentCharacter(int cp_offset,
+                                                      Label* on_end_of_input,
+                                                      bool check_bounds,
+                                                      int characters) {
+  const char* check_msg = check_bounds ? "" : " (unchecked)";
+  PrintF(" LoadCurrentCharacter(cp_offset=%d, label[%08x]%s (%d chars));\n",
+         cp_offset,
+         on_end_of_input,
+         check_msg,
+         characters);
+  assembler_->LoadCurrentCharacter(cp_offset,
+                                   on_end_of_input,
+                                   check_bounds,
+                                   characters);
+}
+
+
+void RegExpMacroAssemblerTracer::CheckCharacterLT(uc16 limit, Label* on_less) {
+  PrintF(" CheckCharacterLT(c='u%04x', label[%08x]);\n", limit, on_less);
+  assembler_->CheckCharacterLT(limit, on_less);
+}
+
+
+void RegExpMacroAssemblerTracer::CheckCharacterGT(uc16 limit,
+                                                  Label* on_greater) {
+  PrintF(" CheckCharacterGT(c='u%04x', label[%08x]);\n", limit, on_greater);
+  assembler_->CheckCharacterGT(limit, on_greater);
+}
+
+
+void RegExpMacroAssemblerTracer::CheckCharacter(uint32_t c, Label* on_equal) {
+  PrintF(" CheckCharacter(c='u%04x', label[%08x]);\n", c, on_equal);
+  assembler_->CheckCharacter(c, on_equal);
+}
+
+
+void RegExpMacroAssemblerTracer::CheckAtStart(Label* on_at_start) {
+  PrintF(" CheckAtStart(label[%08x]);\n", on_at_start);
+  assembler_->CheckAtStart(on_at_start);
+}
+
+
+void RegExpMacroAssemblerTracer::CheckNotAtStart(Label* on_not_at_start) {
+  PrintF(" CheckNotAtStart(label[%08x]);\n", on_not_at_start);
+  assembler_->CheckNotAtStart(on_not_at_start);
+}
+
+
+void RegExpMacroAssemblerTracer::CheckNotCharacter(uint32_t c,
+                                                   Label* on_not_equal) {
+  PrintF(" CheckNotCharacter(c='u%04x', label[%08x]);\n", c, on_not_equal);
+  assembler_->CheckNotCharacter(c, on_not_equal);
+}
+
+
+void RegExpMacroAssemblerTracer::CheckCharacterAfterAnd(
+    uint32_t c,
+    uint32_t mask,
+    Label* on_equal) {
+  PrintF(" CheckCharacterAfterAnd(c='u%04x', mask=0x%04x, label[%08x]);\n",
+         c,
+         mask,
+         on_equal);
+  assembler_->CheckCharacterAfterAnd(c, mask, on_equal);
+}
+
+
+void RegExpMacroAssemblerTracer::CheckNotCharacterAfterAnd(
+    uint32_t c,
+    uint32_t mask,
+    Label* on_not_equal) {
+  PrintF(" CheckNotCharacterAfterAnd(c='u%04x', mask=0x%04x, label[%08x]);\n",
+         c,
+         mask,
+         on_not_equal);
+  assembler_->CheckNotCharacterAfterAnd(c, mask, on_not_equal);
+}
+
+
+void RegExpMacroAssemblerTracer::CheckNotCharacterAfterMinusAnd(
+    uc16 c,
+    uc16 minus,
+    uc16 mask,
+    Label* on_not_equal) {
+  PrintF(" CheckNotCharacterAfterMinusAnd(c='u%04x', minus=%04x, mask=0x%04x, "
+             "label[%08x]);\n",
+         c,
+         minus,
+         mask,
+         on_not_equal);
+  assembler_->CheckNotCharacterAfterMinusAnd(c, minus, mask, on_not_equal);
+}
+
+
+void RegExpMacroAssemblerTracer::CheckNotBackReference(int start_reg,
+                                                       Label* on_no_match) {
+  PrintF(" CheckNotBackReference(register=%d, label[%08x]);\n", start_reg,
+         on_no_match);
+  assembler_->CheckNotBackReference(start_reg, on_no_match);
+}
+
+
+void RegExpMacroAssemblerTracer::CheckNotBackReferenceIgnoreCase(
+    int start_reg,
+    Label* on_no_match) {
+  PrintF(" CheckNotBackReferenceIgnoreCase(register=%d, label[%08x]);\n",
+         start_reg, on_no_match);
+  assembler_->CheckNotBackReferenceIgnoreCase(start_reg, on_no_match);
+}
+
+
+void RegExpMacroAssemblerTracer::CheckNotRegistersEqual(int reg1,
+                                                        int reg2,
+                                                        Label* on_not_equal) {
+  PrintF(" CheckNotRegistersEqual(reg1=%d, reg2=%d, label[%08x]);\n",
+         reg1,
+         reg2,
+         on_not_equal);
+  assembler_->CheckNotRegistersEqual(reg1, reg2, on_not_equal);
+}
+
+
+void RegExpMacroAssemblerTracer::CheckCharacters(Vector<const uc16> str,
+                                                 int cp_offset,
+                                                 Label* on_failure,
+                                                 bool check_end_of_string) {
+  PrintF(" %s(str=\"",
+         check_end_of_string ? "CheckCharacters" : "CheckCharactersUnchecked");
+  for (int i = 0; i < str.length(); i++) {
+    PrintF("u%04x", str[i]);
+  }
+  PrintF("\", cp_offset=%d, label[%08x])\n", cp_offset, on_failure);
+  assembler_->CheckCharacters(str, cp_offset, on_failure, check_end_of_string);
+}
+
+
+void RegExpMacroAssemblerTracer::CheckBitmap(uc16 start, Label* bitmap,
+                                             Label* on_zero) {
+  PrintF(" CheckBitmap(start=u%04x, <bitmap>, label[%08x]);\n", start, on_zero);
+  assembler_->CheckBitmap(start, bitmap, on_zero);
+}
+
+
+bool RegExpMacroAssemblerTracer::CheckSpecialCharacterClass(
+    uc16 type,
+    int cp_offset,
+    bool check_offset,
+    Label* on_no_match) {
+  bool supported = assembler_->CheckSpecialCharacterClass(type,
+                                                          cp_offset,
+                                                          check_offset,
+                                                          on_no_match);
+  PrintF(" CheckSpecialCharacterClass(type='%c', offset=%d, "
+             "check_offset=%s, label[%08x]): %s;\n",
+         type,
+         cp_offset,
+         check_offset ? "true" : "false",
+         on_no_match,
+         supported ? "true" : "false");
+  return supported;
+}
+
+
+void RegExpMacroAssemblerTracer::DispatchHalfNibbleMap(
+    uc16 start,
+    Label* half_nibble_map,
+    const Vector<Label*>& destinations) {
+  PrintF(" DispatchHalfNibbleMap(start=u%04x, <half_nibble_map>, [", start);
+  for (int i = 0; i < destinations.length(); i++) {
+    if (i > 0)
+      PrintF(", ");
+    PrintF("label[%08x]", destinations[i]);
+  }
+  PrintF(");\n");
+  assembler_->DispatchHalfNibbleMap(start, half_nibble_map, destinations);
+}
+
+
+void RegExpMacroAssemblerTracer::DispatchByteMap(
+    uc16 start,
+    Label* byte_map,
+    const Vector<Label*>& destinations) {
+  PrintF(" DispatchByteMap(start=u%04x, <byte_map>, [", start);
+  for (int i = 0; i < destinations.length(); i++) {
+    if (i > 0)
+      PrintF(", ");
+    PrintF("label[%08x]", destinations[i]);
+  }
+  PrintF(");\n");
+  assembler_->DispatchByteMap(start, byte_map, destinations);
+}
+
+
+void RegExpMacroAssemblerTracer::DispatchHighByteMap(
+    byte start,
+    Label* byte_map,
+    const Vector<Label*>& destinations) {
+  PrintF(" DispatchHighByteMap(start=u%04x, <byte_map>, [", start);
+  for (int i = 0; i < destinations.length(); i++) {
+    if (i > 0)
+      PrintF(", ");
+    PrintF("label[%08x]", destinations[i]);
+  }
+  PrintF(");\n");
+  assembler_->DispatchHighByteMap(start, byte_map, destinations);
+}
+
+
+void RegExpMacroAssemblerTracer::IfRegisterLT(int register_index,
+                                              int comparand, Label* if_lt) {
+  PrintF(" IfRegisterLT(register=%d, number=%d, label[%08x]);\n",
+         register_index, comparand, if_lt);
+  assembler_->IfRegisterLT(register_index, comparand, if_lt);
+}
+
+
+void RegExpMacroAssemblerTracer::IfRegisterEqPos(int register_index,
+                                                 Label* if_eq) {
+  PrintF(" IfRegisterEqPos(register=%d, label[%08x]);\n",
+         register_index, if_eq);
+  assembler_->IfRegisterEqPos(register_index, if_eq);
+}
+
+
+void RegExpMacroAssemblerTracer::IfRegisterGE(int register_index,
+                                              int comparand, Label* if_ge) {
+  PrintF(" IfRegisterGE(register=%d, number=%d, label[%08x]);\n",
+         register_index, comparand, if_ge);
+  assembler_->IfRegisterGE(register_index, comparand, if_ge);
+}
+
+
+RegExpMacroAssembler::IrregexpImplementation
+    RegExpMacroAssemblerTracer::Implementation() {
+  return assembler_->Implementation();
+}
+
+
+Handle<Object> RegExpMacroAssemblerTracer::GetCode(Handle<String> source) {
+  PrintF(" GetCode(%s);\n", *(source->ToCString()));
+  return assembler_->GetCode(source);
+}
+
+}}  // namespace v8::internal
diff --git a/deps/v8/src/regexp-macro-assembler-tracer.h b/deps/v8/src/regexp-macro-assembler-tracer.h
new file mode 100644
index 0000000..d3aeff7
--- /dev/null
+++ b/deps/v8/src/regexp-macro-assembler-tracer.h
@@ -0,0 +1,118 @@
+// Copyright 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 REGEXP_MACRO_ASSEMBLER_TRACER_H_
+#define REGEXP_MACRO_ASSEMBLER_TRACER_H_
+
+namespace v8 { namespace internal {
+
+// Decorator on a RegExpMacroAssembler that write all calls.
+class RegExpMacroAssemblerTracer: public RegExpMacroAssembler {
+ public:
+  explicit RegExpMacroAssemblerTracer(RegExpMacroAssembler* assembler);
+  virtual ~RegExpMacroAssemblerTracer();
+  virtual int stack_limit_slack() { return assembler_->stack_limit_slack(); }
+
+  virtual void AdvanceCurrentPosition(int by);  // Signed cp change.
+  virtual void AdvanceRegister(int reg, int by);  // r[reg] += by.
+  virtual void Backtrack();
+  virtual void Bind(Label* label);
+  virtual void CheckAtStart(Label* on_at_start);
+  virtual void CheckBitmap(uc16 start, Label* bitmap, Label* on_zero);
+  virtual void CheckCharacter(uint32_t c, Label* on_equal);
+  virtual void CheckCharacterAfterAnd(uint32_t c,
+                                      uint32_t and_with,
+                                      Label* on_equal);
+  virtual void CheckCharacterGT(uc16 limit, Label* on_greater);
+  virtual void CheckCharacterLT(uc16 limit, Label* on_less);
+  virtual void CheckCharacters(
+      Vector<const uc16> str,
+      int cp_offset,
+      Label* on_failure,
+      bool check_end_of_string);
+  virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
+  virtual void CheckNotAtStart(Label* on_not_at_start);
+  virtual void CheckNotBackReference(int start_reg, Label* on_no_match);
+  virtual void CheckNotBackReferenceIgnoreCase(int start_reg,
+                                               Label* on_no_match);
+  virtual void CheckNotRegistersEqual(int reg1, int reg2, Label* on_not_equal);
+  virtual void CheckNotCharacter(uint32_t c, Label* on_not_equal);
+  virtual void CheckNotCharacterAfterAnd(uint32_t c,
+                                         uint32_t and_with,
+                                         Label* on_not_equal);
+  virtual void CheckNotCharacterAfterMinusAnd(uc16 c,
+                                              uc16 minus,
+                                              uc16 and_with,
+                                              Label* on_not_equal);
+  virtual bool CheckSpecialCharacterClass(uc16 type,
+                                          int cp_offset,
+                                          bool check_offset,
+                                          Label* on_no_match);
+  virtual void DispatchByteMap(
+      uc16 start,
+      Label* byte_map,
+      const Vector<Label*>& destinations);
+  virtual void DispatchHalfNibbleMap(
+      uc16 start,
+      Label* half_nibble_map,
+      const Vector<Label*>& destinations);
+  virtual void DispatchHighByteMap(
+      byte start,
+      Label* byte_map,
+      const Vector<Label*>& destinations);
+  virtual void EmitOrLink(Label* label);
+  virtual void Fail();
+  virtual Handle<Object> GetCode(Handle<String> source);
+  virtual void GoTo(Label* label);
+  virtual void IfRegisterGE(int reg, int comparand, Label* if_ge);
+  virtual void IfRegisterLT(int reg, int comparand, Label* if_lt);
+  virtual void IfRegisterEqPos(int reg, Label* if_eq);
+  virtual IrregexpImplementation Implementation();
+  virtual void LoadCurrentCharacter(int cp_offset,
+                                    Label* on_end_of_input,
+                                    bool check_bounds = true,
+                                    int characters = 1);
+  virtual void PopCurrentPosition();
+  virtual void PopRegister(int register_index);
+  virtual void PushBacktrack(Label* label);
+  virtual void PushCurrentPosition();
+  virtual void PushRegister(int register_index,
+                            StackCheckFlag check_stack_limit);
+  virtual void ReadCurrentPositionFromRegister(int reg);
+  virtual void ReadStackPointerFromRegister(int reg);
+  virtual void SetRegister(int register_index, int to);
+  virtual void Succeed();
+  virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
+  virtual void ClearRegisters(int reg_from, int reg_to);
+  virtual void WriteStackPointerToRegister(int reg);
+ private:
+  RegExpMacroAssembler* assembler_;
+};
+
+}}  // namespace v8::internal
+
+#endif  // REGEXP_MACRO_ASSEMBLER_TRACER_H_
diff --git a/deps/v8/src/regexp-macro-assembler.cc b/deps/v8/src/regexp-macro-assembler.cc
new file mode 100644
index 0000000..913ac64
--- /dev/null
+++ b/deps/v8/src/regexp-macro-assembler.cc
@@ -0,0 +1,78 @@
+// Copyright 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.
+
+#include <string.h>
+#include "v8.h"
+#include "ast.h"
+#include "assembler.h"
+#include "regexp-macro-assembler.h"
+
+namespace v8 { namespace internal {
+
+RegExpMacroAssembler::RegExpMacroAssembler() {
+}
+
+
+RegExpMacroAssembler::~RegExpMacroAssembler() {
+}
+
+
+ByteArrayProvider::ByteArrayProvider(unsigned int initial_size)
+  : byte_array_size_(initial_size),
+    current_byte_array_(),
+    current_byte_array_free_offset_(initial_size) {}
+
+
+ArraySlice ByteArrayProvider::GetBuffer(unsigned int size,
+                                        unsigned int elem_size) {
+  ASSERT(size > 0);
+  size_t byte_size = size * elem_size;
+  int free_offset = current_byte_array_free_offset_;
+  // align elements
+  free_offset += elem_size - 1;
+  free_offset = free_offset - (free_offset % elem_size);
+
+  if (free_offset + byte_size > byte_array_size_) {
+    if (byte_size > (byte_array_size_ / 2)) {
+      Handle<ByteArray> solo_buffer(Factory::NewByteArray(byte_size, TENURED));
+      return ArraySlice(solo_buffer, 0);
+    }
+    current_byte_array_ = Factory::NewByteArray(byte_array_size_, TENURED);
+    free_offset = 0;
+  }
+  current_byte_array_free_offset_ = free_offset + byte_size;
+  return ArraySlice(current_byte_array_, free_offset);
+}
+
+
+template <typename T>
+ArraySlice ByteArrayProvider::GetBuffer(Vector<T> values) {
+  ArraySlice slice = GetBuffer(values.length(), sizeof(T));
+  memcpy(slice.location(), values.start(), values.length() * sizeof(T));
+  return slice;
+}
+} }  // namespace v8::internal
diff --git a/deps/v8/src/regexp-macro-assembler.h b/deps/v8/src/regexp-macro-assembler.h
new file mode 100644
index 0000000..a3f398d
--- /dev/null
+++ b/deps/v8/src/regexp-macro-assembler.h
@@ -0,0 +1,230 @@
+// Copyright 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_REGEXP_MACRO_ASSEMBLER_H_
+#define V8_REGEXP_MACRO_ASSEMBLER_H_
+
+namespace v8 { namespace internal {
+
+struct DisjunctDecisionRow {
+  RegExpCharacterClass cc;
+  Label* on_match;
+};
+
+
+class RegExpMacroAssembler {
+ public:
+  // The implementation must be able to handle at least:
+  static const int kMaxRegister = (1 << 16) - 1;
+  static const int kMaxCPOffset = (1 << 15) - 1;
+  static const int kMinCPOffset = -(1 << 15);
+  enum IrregexpImplementation {
+    kIA32Implementation,
+    kARMImplementation,
+    kBytecodeImplementation
+  };
+
+  enum StackCheckFlag {
+    kNoStackLimitCheck = false,
+    kCheckStackLimit = true
+  };
+
+  RegExpMacroAssembler();
+  virtual ~RegExpMacroAssembler();
+  // The maximal number of pushes between stack checks. Users must supply
+  // kCheckStackLimit flag to push operations (instead of kNoStackLimitCheck)
+  // at least once for every stack_limit() pushes that are executed.
+  virtual int stack_limit_slack() = 0;
+  virtual void AdvanceCurrentPosition(int by) = 0;  // Signed cp change.
+  virtual void AdvanceRegister(int reg, int by) = 0;  // r[reg] += by.
+  // Continues execution from the position pushed on the top of the backtrack
+  // stack by an earlier PushBacktrack(Label*).
+  virtual void Backtrack() = 0;
+  virtual void Bind(Label* label) = 0;
+  virtual void CheckAtStart(Label* on_at_start) = 0;
+  // Check the current character against a bitmap.  The range of the current
+  // character must be from start to start + length_of_bitmap_in_bits.
+  virtual void CheckBitmap(
+      uc16 start,           // The bitmap is indexed from this character.
+      Label* bitmap,        // Where the bitmap is emitted.
+      Label* on_zero) = 0;  // Where to go if the bit is 0.  Fall through on 1.
+  // Dispatch after looking the current character up in a 2-bits-per-entry
+  // map.  The destinations vector has up to 4 labels.
+  virtual void CheckCharacter(uint32_t c, Label* on_equal) = 0;
+  // Bitwise and the current character with the given constant and then
+  // check for a match with c.
+  virtual void CheckCharacterAfterAnd(uint32_t c,
+                                      uint32_t and_with,
+                                      Label* on_equal) = 0;
+  virtual void CheckCharacterGT(uc16 limit, Label* on_greater) = 0;
+  virtual void CheckCharacterLT(uc16 limit, Label* on_less) = 0;
+  // Check the current character for a match with a literal string.  If we
+  // fail to match then goto the on_failure label.  If check_eos is set then
+  // the end of input always fails.  If check_eos is clear then it is the
+  // caller's responsibility to ensure that the end of string is not hit.
+  // If the label is NULL then we should pop a backtrack address off
+  // the stack and go to that.
+  virtual void CheckCharacters(
+      Vector<const uc16> str,
+      int cp_offset,
+      Label* on_failure,
+      bool check_eos) = 0;
+  virtual void CheckGreedyLoop(Label* on_tos_equals_current_position) = 0;
+  virtual void CheckNotAtStart(Label* on_not_at_start) = 0;
+  virtual void CheckNotBackReference(int start_reg, Label* on_no_match) = 0;
+  virtual void CheckNotBackReferenceIgnoreCase(int start_reg,
+                                               Label* on_no_match) = 0;
+  // Check the current character for a match with a literal character.  If we
+  // fail to match then goto the on_failure label.  End of input always
+  // matches.  If the label is NULL then we should pop a backtrack address off
+  // the stack and go to that.
+  virtual void CheckNotCharacter(uint32_t c, Label* on_not_equal) = 0;
+  virtual void CheckNotCharacterAfterAnd(uint32_t c,
+                                         uint32_t and_with,
+                                         Label* on_not_equal) = 0;
+  // Subtract a constant from the current character, then or with the given
+  // constant and then check for a match with c.
+  virtual void CheckNotCharacterAfterMinusAnd(uc16 c,
+                                              uc16 minus,
+                                              uc16 and_with,
+                                              Label* on_not_equal) = 0;
+  virtual void CheckNotRegistersEqual(int reg1,
+                                      int reg2,
+                                      Label* on_not_equal) = 0;
+
+  // Checks whether the given offset from the current position is before
+  // the end of the string.  May overwrite the current character.
+  virtual void CheckPosition(int cp_offset, Label* on_outside_input) {
+    LoadCurrentCharacter(cp_offset, on_outside_input, true);
+  }
+  // Check whether a standard/default character class matches the current
+  // character. Returns false if the type of special character class does
+  // not have custom support.
+  // May clobber the current loaded character.
+  virtual bool CheckSpecialCharacterClass(uc16 type,
+                                          int cp_offset,
+                                          bool check_offset,
+                                          Label* on_no_match) {
+    return false;
+  }
+  // Dispatch after looking the current character up in a byte map.  The
+  // destinations vector has up to 256 labels.
+  virtual void DispatchByteMap(
+      uc16 start,
+      Label* byte_map,
+      const Vector<Label*>& destinations) = 0;
+  virtual void DispatchHalfNibbleMap(
+      uc16 start,
+      Label* half_nibble_map,
+      const Vector<Label*>& destinations) = 0;
+  // Dispatch after looking the high byte of the current character up in a byte
+  // map.  The destinations vector has up to 256 labels.
+  virtual void DispatchHighByteMap(
+      byte start,
+      Label* byte_map,
+      const Vector<Label*>& destinations) = 0;
+  virtual void EmitOrLink(Label* label) = 0;
+  virtual void Fail() = 0;
+  virtual Handle<Object> GetCode(Handle<String> source) = 0;
+  virtual void GoTo(Label* label) = 0;
+  // Check whether a register is >= a given constant and go to a label if it
+  // is.  Backtracks instead if the label is NULL.
+  virtual void IfRegisterGE(int reg, int comparand, Label* if_ge) = 0;
+  // Check whether a register is < a given constant and go to a label if it is.
+  // Backtracks instead if the label is NULL.
+  virtual void IfRegisterLT(int reg, int comparand, Label* if_lt) = 0;
+  // Check whether a register is == to the current position and go to a
+  // label if it is.
+  virtual void IfRegisterEqPos(int reg, Label* if_eq) = 0;
+  virtual IrregexpImplementation Implementation() = 0;
+  virtual void LoadCurrentCharacter(int cp_offset,
+                                    Label* on_end_of_input,
+                                    bool check_bounds = true,
+                                    int characters = 1) = 0;
+  virtual void PopCurrentPosition() = 0;
+  virtual void PopRegister(int register_index) = 0;
+  // Pushes the label on the backtrack stack, so that a following Backtrack
+  // will go to this label. Always checks the backtrack stack limit.
+  virtual void PushBacktrack(Label* label) = 0;
+  virtual void PushCurrentPosition() = 0;
+  virtual void PushRegister(int register_index,
+                            StackCheckFlag check_stack_limit) = 0;
+  virtual void ReadCurrentPositionFromRegister(int reg) = 0;
+  virtual void ReadStackPointerFromRegister(int reg) = 0;
+  virtual void SetRegister(int register_index, int to) = 0;
+  virtual void Succeed() = 0;
+  virtual void WriteCurrentPositionToRegister(int reg, int cp_offset) = 0;
+  virtual void ClearRegisters(int reg_from, int reg_to) = 0;
+  virtual void WriteStackPointerToRegister(int reg) = 0;
+
+ private:
+};
+
+
+struct ArraySlice {
+ public:
+  ArraySlice(Handle<ByteArray> array, size_t offset)
+    : array_(array), offset_(offset) {}
+  Handle<ByteArray> array() { return array_; }
+  // Offset in the byte array data.
+  size_t offset() { return offset_; }
+  // Offset from the ByteArray pointer.
+  size_t base_offset() {
+    return ByteArray::kHeaderSize - kHeapObjectTag + offset_;
+  }
+  void* location() {
+    return reinterpret_cast<void*>(array_->GetDataStartAddress() + offset_);
+  }
+  template <typename T>
+  T& at(int idx) {
+    return reinterpret_cast<T*>(array_->GetDataStartAddress() + offset_)[idx];
+  }
+ private:
+  Handle<ByteArray> array_;
+  size_t offset_;
+};
+
+
+class ByteArrayProvider {
+ public:
+  explicit ByteArrayProvider(unsigned int initial_size);
+  // Provides a place to put "size" elements of size "element_size".
+  // The information can be stored in the provided ByteArray at the "offset".
+  // The offset is aligned to the element size.
+  ArraySlice GetBuffer(unsigned int size,
+                       unsigned int element_size);
+  template <typename T>
+  ArraySlice GetBuffer(Vector<T> values);
+ private:
+  size_t byte_array_size_;
+  Handle<ByteArray> current_byte_array_;
+  int current_byte_array_free_offset_;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_REGEXP_MACRO_ASSEMBLER_H_
diff --git a/deps/v8/src/regexp-stack.cc b/deps/v8/src/regexp-stack.cc
new file mode 100644
index 0000000..05daa58
--- /dev/null
+++ b/deps/v8/src/regexp-stack.cc
@@ -0,0 +1,94 @@
+// 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.
+
+#include "v8.h"
+#include "top.h"
+#include "regexp-stack.h"
+
+namespace v8 { namespace internal {
+
+RegExpStack::RegExpStack() {
+  // Initialize, if not already initialized.
+  RegExpStack::EnsureCapacity(0);
+}
+
+
+RegExpStack::~RegExpStack() {
+  // Reset the buffer if it has grown.
+  RegExpStack::Reset();
+}
+
+
+char* RegExpStack::ArchiveStack(char* to) {
+  size_t size = sizeof(thread_local_);
+  memcpy(reinterpret_cast<void*>(to),
+         &thread_local_,
+         size);
+  thread_local_ = ThreadLocal();
+  return to + size;
+}
+
+
+char* RegExpStack::RestoreStack(char* from) {
+  size_t size = sizeof(thread_local_);
+  memcpy(&thread_local_, reinterpret_cast<void*>(from), size);
+  return from + size;
+}
+
+
+void RegExpStack::Reset() {
+  if (thread_local_.memory_size_ > kMinimumStackSize) {
+    DeleteArray(thread_local_.memory_);
+    thread_local_ = ThreadLocal();
+  }
+}
+
+
+Address RegExpStack::EnsureCapacity(size_t size) {
+  if (size > kMaximumStackSize) return NULL;
+  if (size < kMinimumStackSize) size = kMinimumStackSize;
+  if (thread_local_.memory_size_ < size) {
+    Address new_memory = NewArray<byte>(size);
+    if (thread_local_.memory_size_ > 0) {
+      // Copy original memory into top of new memory.
+      memcpy(reinterpret_cast<void*>(
+          new_memory + size - thread_local_.memory_size_),
+             reinterpret_cast<void*>(thread_local_.memory_),
+             thread_local_.memory_size_);
+      DeleteArray(thread_local_.memory_);
+    }
+    thread_local_.memory_ = new_memory;
+    thread_local_.memory_size_ = size;
+    thread_local_.limit_ = new_memory + kStackLimitSlack * kPointerSize;
+  }
+  return thread_local_.memory_ + thread_local_.memory_size_;
+}
+
+
+RegExpStack::ThreadLocal RegExpStack::thread_local_;
+
+}}  // namespace v8::internal
diff --git a/deps/v8/src/regexp-stack.h b/deps/v8/src/regexp-stack.h
new file mode 100644
index 0000000..e47462f
--- /dev/null
+++ b/deps/v8/src/regexp-stack.h
@@ -0,0 +1,106 @@
+// 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.
+
+#ifndef REGEXP_STACK_H_
+#define REGEXP_STACK_H_
+
+namespace v8 { namespace internal {
+
+// Maintains a per-v8thread stack area that can be used by irregexp
+// implementation for its backtracking stack.
+// Since there is only one stack area, the Irregexp implementation is not
+// re-entrant. I.e., no regular expressions may be executed in the same thread
+// during a preempted Irregexp execution.
+class RegExpStack {
+ public:
+  // Number of allocated locations on the stack below the limit.
+  // No sequence of pushes must be longer that this without doing a stack-limit
+  // check.
+  static const int kStackLimitSlack = 32;
+
+  // Create and delete an instance to control the life-time of a growing stack.
+  RegExpStack();  // Initializes the stack memory area if necessary.
+  ~RegExpStack();  // Releases the stack if it has grown.
+
+  // Gives the top of the memory used as stack.
+  static Address stack_top() {
+    ASSERT(thread_local_.memory_size_ != 0);
+    return thread_local_.memory_ + thread_local_.memory_size_;
+  }
+
+  // The total size of the memory allocated for the stack.
+  static size_t stack_capacity() { return thread_local_.memory_size_; }
+
+  // If the stack pointer gets below the limit, we should react and
+  // either grow the stack or report an out-of-stack exception.
+  // There is only a limited number of locations below the stack limit,
+  // so users of the stack should check the stack limit during any
+  // sequence of pushes longer that this.
+  static Address* limit_address() { return &(thread_local_.limit_); }
+
+  // Ensures that there is a memory area with at least the specified size.
+  // If passing zero, the default/minimum size buffer is allocated.
+  static Address EnsureCapacity(size_t size);
+
+  // Thread local archiving.
+  static size_t ArchiveSpacePerThread() { return sizeof(thread_local_); }
+  static char* ArchiveStack(char* to);
+  static char* RestoreStack(char* from);
+
+ private:
+  // Artificial limit used when no memory has been allocated.
+  static const uint32_t kMemoryTop = 0xffffffff;
+
+  // Minimal size of allocated stack area.
+  static const size_t kMinimumStackSize = 1 * KB;
+
+  // Maximal size of allocated stack area.
+  static const size_t kMaximumStackSize = 64 * MB;
+
+  // Structure holding the allocated memory, size and limit.
+  struct ThreadLocal {
+    ThreadLocal()
+        : memory_(NULL),
+          memory_size_(0),
+          limit_(reinterpret_cast<Address>(kMemoryTop)) {}
+    // If memory_size_ > 0 then memory_ must be non-NULL.
+    Address memory_;
+    size_t memory_size_;
+    Address limit_;
+  };
+
+  // Resets the buffer if it has grown beyond the default/minimum size.
+  // After this, the buffer is either the default size, or it is empty, so
+  // you have to call EnsureCapacity before using it again.
+  static void Reset();
+
+  static ThreadLocal thread_local_;
+};
+
+}}  // namespace v8::internal
+
+#endif /* REGEXP_STACK_H_ */
diff --git a/deps/v8/src/register-allocator-arm.cc b/deps/v8/src/register-allocator-arm.cc
new file mode 100644
index 0000000..36a4d20
--- /dev/null
+++ b/deps/v8/src/register-allocator-arm.cc
@@ -0,0 +1,96 @@
+// 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.
+
+#include "v8.h"
+
+#include "codegen-inl.h"
+#include "register-allocator-inl.h"
+
+namespace v8 { namespace internal {
+
+// -------------------------------------------------------------------------
+// Result implementation.
+
+void Result::ToRegister() {
+  UNIMPLEMENTED();
+}
+
+
+void Result::ToRegister(Register target) {
+  UNIMPLEMENTED();
+}
+
+
+// -------------------------------------------------------------------------
+// RegisterAllocator implementation.
+
+RegisterFile RegisterAllocator::Reserved() {
+  RegisterFile reserved;
+  reserved.Use(sp);
+  reserved.Use(fp);
+  reserved.Use(cp);
+  reserved.Use(pc);
+  return reserved;
+}
+
+
+void RegisterAllocator::UnuseReserved(RegisterFile* register_file) {
+  register_file->ref_counts_[sp.code()] = 0;
+  register_file->ref_counts_[fp.code()] = 0;
+  register_file->ref_counts_[cp.code()] = 0;
+  register_file->ref_counts_[pc.code()] = 0;
+}
+
+
+void RegisterAllocator::Initialize() {
+  Reset();
+  // The following registers are live on function entry, saved in the
+  // frame, and available for allocation during execution.
+  Use(r1);  // JS function.
+  Use(lr);  // Return address.
+}
+
+
+void RegisterAllocator::Reset() {
+  registers_.Reset();
+  // The following registers are live on function entry and reserved
+  // during execution.
+  Use(sp);  // Stack pointer.
+  Use(fp);  // Frame pointer (caller's frame pointer on entry).
+  Use(cp);  // Context context (callee's context on entry).
+  Use(pc);  // Program counter.
+}
+
+
+Result RegisterAllocator::AllocateByteRegisterWithoutSpilling() {
+  UNIMPLEMENTED();
+  Result invalid(cgen_);
+  return invalid;
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/register-allocator-ia32.cc b/deps/v8/src/register-allocator-ia32.cc
new file mode 100644
index 0000000..a898827
--- /dev/null
+++ b/deps/v8/src/register-allocator-ia32.cc
@@ -0,0 +1,130 @@
+// Copyright 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.
+
+#include "v8.h"
+
+#include "codegen-inl.h"
+#include "register-allocator-inl.h"
+
+namespace v8 { namespace internal {
+
+// -------------------------------------------------------------------------
+// Result implementation.
+
+void Result::ToRegister() {
+  ASSERT(is_valid());
+  if (is_constant()) {
+    Result fresh = cgen_->allocator()->Allocate();
+    ASSERT(fresh.is_valid());
+    if (cgen_->IsUnsafeSmi(handle())) {
+      cgen_->LoadUnsafeSmi(fresh.reg(), handle());
+    } else {
+      cgen_->masm()->Set(fresh.reg(), Immediate(handle()));
+    }
+    // This result becomes a copy of the fresh one.
+    *this = fresh;
+  }
+  ASSERT(is_register());
+}
+
+
+void Result::ToRegister(Register target) {
+  ASSERT(is_valid());
+  if (!is_register() || !reg().is(target)) {
+    Result fresh = cgen_->allocator()->Allocate(target);
+    ASSERT(fresh.is_valid());
+    if (is_register()) {
+      cgen_->masm()->mov(fresh.reg(), reg());
+    } else {
+      ASSERT(is_constant());
+      if (cgen_->IsUnsafeSmi(handle())) {
+        cgen_->LoadUnsafeSmi(fresh.reg(), handle());
+      } else {
+        cgen_->masm()->Set(fresh.reg(), Immediate(handle()));
+      }
+    }
+    *this = fresh;
+  } else if (is_register() && reg().is(target)) {
+    ASSERT(cgen_->has_valid_frame());
+    cgen_->frame()->Spill(target);
+    ASSERT(cgen_->allocator()->count(target) == 1);
+  }
+  ASSERT(is_register());
+  ASSERT(reg().is(target));
+}
+
+
+// -------------------------------------------------------------------------
+// RegisterAllocator implementation.
+
+RegisterFile RegisterAllocator::Reserved() {
+  RegisterFile reserved;
+  reserved.Use(esp);
+  reserved.Use(ebp);
+  reserved.Use(esi);
+  return reserved;
+}
+
+
+void RegisterAllocator::UnuseReserved(RegisterFile* register_file) {
+  register_file->ref_counts_[esp.code()] = 0;
+  register_file->ref_counts_[ebp.code()] = 0;
+  register_file->ref_counts_[esi.code()] = 0;
+}
+
+
+void RegisterAllocator::Initialize() {
+  Reset();
+  // The following register is live on function entry, saved in the
+  // frame, and available for allocation during execution.
+  Use(edi);  // JS function.
+}
+
+
+void RegisterAllocator::Reset() {
+  registers_.Reset();
+  // The following registers are live on function entry and reserved
+  // during execution.
+  Use(esp);  // Stack pointer.
+  Use(ebp);  // Frame pointer (caller's frame pointer on entry).
+  Use(esi);  // Context (callee's context on entry).
+}
+
+
+Result RegisterAllocator::AllocateByteRegisterWithoutSpilling() {
+  Result result = AllocateWithoutSpilling();
+  // Check that the register is a byte register.  If not, unuse the
+  // register if valid and return an invalid result.
+  if (result.is_valid() && !result.reg().is_byte_register()) {
+    result.Unuse();
+    return Result(cgen_);
+  }
+  return result;
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/register-allocator-inl.h b/deps/v8/src/register-allocator-inl.h
new file mode 100644
index 0000000..9e745b5
--- /dev/null
+++ b/deps/v8/src/register-allocator-inl.h
@@ -0,0 +1,49 @@
+// 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.
+
+#ifndef V8_REGISTER_ALLOCATOR_INL_H_
+#define V8_REGISTER_ALLOCATOR_INL_H_
+
+#include "register-allocator.h"
+#include "virtual-frame.h"
+
+namespace v8 { namespace internal {
+
+Result::~Result() {
+  if (is_register()) cgen_->allocator()->Unuse(reg());
+}
+
+
+void Result::Unuse() {
+  if (is_register()) cgen_->allocator()->Unuse(reg());
+  type_ = INVALID;
+}
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_REGISTER_ALLOCATOR_INL_H_
diff --git a/deps/v8/src/register-allocator.cc b/deps/v8/src/register-allocator.cc
new file mode 100644
index 0000000..94e031f
--- /dev/null
+++ b/deps/v8/src/register-allocator.cc
@@ -0,0 +1,132 @@
+// 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.
+
+#include "v8.h"
+
+#include "codegen-inl.h"
+#include "register-allocator-inl.h"
+
+namespace v8 { namespace internal {
+
+// -------------------------------------------------------------------------
+// Result implementation.
+
+Result::Result(Register reg, CodeGenerator* cgen)
+    : static_type_(),
+      type_(REGISTER),
+      cgen_(cgen) {
+  data_.reg_ = reg;
+  ASSERT(reg.is_valid());
+  cgen_->allocator()->Use(reg);
+}
+
+
+Result::Result(Register reg, CodeGenerator* cgen, StaticType static_type)
+    : static_type_(static_type),
+      type_(REGISTER),
+      cgen_(cgen) {
+  data_.reg_ = reg;
+  ASSERT(reg.is_valid());
+  cgen_->allocator()->Use(reg);
+}
+
+
+void Result::CopyTo(Result* destination) const {
+  destination->static_type_ = static_type_;
+  destination->type_ = type();
+  destination->cgen_ = cgen_;
+
+  if (is_register()) {
+    destination->data_.reg_ = reg();
+    cgen_->allocator()->Use(reg());
+  } else if (is_constant()) {
+    destination->data_.handle_ = data_.handle_;
+  } else {
+    ASSERT(!is_valid());
+  }
+}
+
+
+// -------------------------------------------------------------------------
+// RegisterFile implementation.
+
+void RegisterFile::CopyTo(RegisterFile* other) {
+  for (int i = 0; i < kNumRegisters; i++) {
+    other->ref_counts_[i] = ref_counts_[i];
+  }
+}
+
+
+// -------------------------------------------------------------------------
+// RegisterAllocator implementation.
+
+
+Result RegisterAllocator::AllocateWithoutSpilling() {
+  // Return the first free register, if any.
+  int free_reg = registers_.ScanForFreeRegister();
+  if (free_reg < kNumRegisters) {
+    Register free_result = { free_reg };
+    return Result(free_result, cgen_);
+  }
+  return Result(cgen_);
+}
+
+
+Result RegisterAllocator::Allocate() {
+  Result result = AllocateWithoutSpilling();
+  if (!result.is_valid()) {
+    // Ask the current frame to spill a register.
+    ASSERT(cgen_->has_valid_frame());
+    Register free_reg = cgen_->frame()->SpillAnyRegister();
+    if (free_reg.is_valid()) {
+      ASSERT(!is_used(free_reg));
+      return Result(free_reg, cgen_);
+    }
+  }
+  return result;
+}
+
+
+Result RegisterAllocator::Allocate(Register target) {
+  // If the target is not referenced, it can simply be allocated.
+  if (!is_used(target)) {
+    return Result(target, cgen_);
+  }
+  // If the target is only referenced in the frame, it can be spilled and
+  // then allocated.
+  ASSERT(cgen_->has_valid_frame());
+  if (cgen_->frame()->is_used(target) && count(target) == 1)  {
+    cgen_->frame()->Spill(target);
+    ASSERT(!is_used(target));
+    return Result(target, cgen_);
+  }
+  // Otherwise (if it's referenced outside the frame) we cannot allocate it.
+  return Result(cgen_);
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/register-allocator.h b/deps/v8/src/register-allocator.h
new file mode 100644
index 0000000..dcc2eb7
--- /dev/null
+++ b/deps/v8/src/register-allocator.h
@@ -0,0 +1,333 @@
+// Copyright 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_REGISTER_ALLOCATOR_H_
+#define V8_REGISTER_ALLOCATOR_H_
+
+#include "macro-assembler.h"
+
+namespace v8 { namespace internal {
+
+
+// -------------------------------------------------------------------------
+// StaticType
+//
+// StaticType represent the type of an expression or a word at runtime.
+// The types are ordered by knowledge, so that if a value can come about
+// in more than one way, and there are different static types inferred
+// for the different ways, the types can be combined to a type that we
+// are still certain of (possibly just "unknown").
+
+class StaticType BASE_EMBEDDED {
+ public:
+  StaticType() : static_type_(UNKNOWN_TYPE) {}
+
+  static StaticType unknown() { return StaticType(); }
+  static StaticType smi() { return StaticType(SMI_TYPE); }
+  static StaticType jsstring() { return StaticType(STRING_TYPE); }
+  static StaticType heap_object() { return StaticType(HEAP_OBJECT_TYPE); }
+
+  // Accessors
+  bool is_unknown() { return static_type_ == UNKNOWN_TYPE; }
+  bool is_smi() { return static_type_ == SMI_TYPE; }
+  bool is_heap_object() { return (static_type_ & HEAP_OBJECT_TYPE) != 0; }
+  bool is_jsstring() { return static_type_ == STRING_TYPE; }
+
+  bool operator==(StaticType other) const {
+    return static_type_ == other.static_type_;
+  }
+
+  // Find the best approximating type for a value.
+  // The argument must not be NULL.
+  static StaticType TypeOf(Object* object) {
+    // Remember to make the most specific tests first. A string is also a heap
+    // object, so test for string-ness first.
+    if (object->IsSmi()) return smi();
+    if (object->IsString()) return jsstring();
+    if (object->IsHeapObject()) return heap_object();
+    return unknown();
+  }
+
+  // Merges two static types to a type that combines the knowledge
+  // of both. If there is no way to combine (e.g., being a string *and*
+  // being a smi), the resulting type is unknown.
+  StaticType merge(StaticType other) {
+    StaticType x(
+        static_cast<StaticTypeEnum>(static_type_ & other.static_type_));
+    return x;
+  }
+
+ private:
+  enum StaticTypeEnum {
+    // Numbers are chosen so that least upper bound of the following
+    // partial order is implemented by bitwise "and":
+    //
+    //    string
+    //       |
+    //    heap-object    smi
+    //           \       /
+    //            unknown
+    //
+    UNKNOWN_TYPE     = 0x00,
+    SMI_TYPE         = 0x01,
+    HEAP_OBJECT_TYPE = 0x02,
+    STRING_TYPE      = 0x04 | HEAP_OBJECT_TYPE
+  };
+  explicit StaticType(StaticTypeEnum static_type) : static_type_(static_type) {}
+
+  // StaticTypeEnum static_type_;
+  byte static_type_;
+};
+
+
+// -------------------------------------------------------------------------
+// Results
+//
+// Results encapsulate the compile-time values manipulated by the code
+// generator.  They can represent registers or constants.
+
+class Result BASE_EMBEDDED {
+ public:
+  enum Type {
+    INVALID,
+    REGISTER,
+    CONSTANT
+  };
+
+  // Construct an invalid result.
+  explicit Result(CodeGenerator* cgen)
+      : static_type_(),
+        type_(INVALID),
+        cgen_(cgen) {}
+
+  // Construct a register Result.
+  Result(Register reg,
+         CodeGenerator* cgen);
+
+  // Construct a register Result with a known static type.
+  Result(Register reg,
+         CodeGenerator* cgen,
+         StaticType static_type);
+
+  // Construct a Result whose value is a compile-time constant.
+  Result(Handle<Object> value, CodeGenerator * cgen)
+      : static_type_(StaticType::TypeOf(*value)),
+        type_(CONSTANT),
+        cgen_(cgen) {
+    data_.handle_ = value.location();
+  }
+
+  // The copy constructor and assignment operators could each create a new
+  // register reference.
+  Result(const Result& other) {
+    other.CopyTo(this);
+  }
+
+  Result& operator=(const Result& other) {
+    if (this != &other) {
+      Unuse();
+      other.CopyTo(this);
+    }
+    return *this;
+  }
+
+  inline ~Result();
+
+  inline void Unuse();
+
+  StaticType static_type() const { return static_type_; }
+  void set_static_type(StaticType static_type) { static_type_ = static_type; }
+
+  Type type() const { return static_cast<Type>(type_); }
+
+  bool is_valid() const { return type() != INVALID; }
+  bool is_register() const { return type() == REGISTER; }
+  bool is_constant() const { return type() == CONSTANT; }
+
+  Register reg() const {
+    ASSERT(type() == REGISTER);
+    return data_.reg_;
+  }
+
+  Handle<Object> handle() const {
+    ASSERT(type() == CONSTANT);
+    return Handle<Object>(data_.handle_);
+  }
+
+  // Move this result to an arbitrary register.  The register is not
+  // necessarily spilled from the frame or even singly-referenced outside
+  // it.
+  void ToRegister();
+
+  // Move this result to a specified register.  The register is spilled from
+  // the frame, and the register is singly-referenced (by this result)
+  // outside the frame.
+  void ToRegister(Register reg);
+
+ private:
+  StaticType static_type_;
+  byte type_;
+
+  union {
+    Register reg_;
+    Object** handle_;
+  } data_;
+
+  CodeGenerator* cgen_;
+
+  void CopyTo(Result* destination) const;
+};
+
+
+// -------------------------------------------------------------------------
+// Register file
+//
+// The register file tracks reference counts for the processor registers.
+// It is used by both the register allocator and the virtual frame.
+
+class RegisterFile BASE_EMBEDDED {
+ public:
+  RegisterFile() { Reset(); }
+
+  void Reset() {
+    for (int i = 0; i < kNumRegisters; i++) {
+      ref_counts_[i] = 0;
+    }
+  }
+
+  // Predicates and accessors for the reference counts.  The versions
+  // that take a register code rather than a register are for
+  // convenience in loops over the register codes.
+  bool is_used(int reg_code) const { return ref_counts_[reg_code] > 0; }
+  bool is_used(Register reg) const { return is_used(reg.code()); }
+  int count(int reg_code) const { return ref_counts_[reg_code]; }
+  int count(Register reg) const { return count(reg.code()); }
+
+  // Record a use of a register by incrementing its reference count.
+  void Use(Register reg) {
+    ref_counts_[reg.code()]++;
+  }
+
+  // Record that a register will no longer be used by decrementing its
+  // reference count.
+  void Unuse(Register reg) {
+    ASSERT(!reg.is(no_reg));
+    ASSERT(is_used(reg.code()));
+    ref_counts_[reg.code()]--;
+  }
+
+  // Copy the reference counts from this register file to the other.
+  void CopyTo(RegisterFile* other);
+
+ private:
+  int ref_counts_[kNumRegisters];
+
+  // Very fast inlined loop to find a free register.
+  // Used in RegisterAllocator::AllocateWithoutSpilling.
+  // Returns kNumRegisters if no free register found.
+  inline int ScanForFreeRegister() {
+    int i = 0;
+    for (; i < kNumRegisters ; ++i) {
+      if (ref_counts_[i] == 0) break;
+    }
+    return i;
+  }
+
+  friend class RegisterAllocator;
+};
+
+
+// -------------------------------------------------------------------------
+// Register allocator
+//
+
+class RegisterAllocator BASE_EMBEDDED {
+ public:
+  explicit RegisterAllocator(CodeGenerator* cgen) : cgen_(cgen) {}
+
+  // A register file with each of the reserved registers counted once.
+  static RegisterFile Reserved();
+
+  // Unuse all the reserved registers in a register file.
+  static void UnuseReserved(RegisterFile* register_file);
+
+  // Predicates and accessors for the registers' reference counts.
+  bool is_used(int reg_code) const { return registers_.is_used(reg_code); }
+  bool is_used(Register reg) const { return registers_.is_used(reg.code()); }
+  int count(int reg_code) const { return registers_.count(reg_code); }
+  int count(Register reg) const { return registers_.count(reg.code()); }
+
+  // Explicitly record a reference to a register.
+  void Use(Register reg) { registers_.Use(reg); }
+
+  // Explicitly record that a register will no longer be used.
+  void Unuse(Register reg) { registers_.Unuse(reg); }
+
+  // Initialize the register allocator for entry to a JS function.  On
+  // entry, the registers used by the JS calling convention are
+  // externally referenced (ie, outside the virtual frame); and the
+  // other registers are free.
+  void Initialize();
+
+  // Reset the register reference counts to free all non-reserved registers.
+  // A frame-external reference is kept to each of the reserved registers.
+  void Reset();
+
+  // Allocate a free register and return a register result if possible or
+  // fail and return an invalid result.
+  Result Allocate();
+
+  // Allocate a specific register if possible, spilling it from the frame if
+  // necessary, or else fail and return an invalid result.
+  Result Allocate(Register target);
+
+  // Allocate a free register without spilling any from the current frame or
+  // fail and return an invalid result.
+  Result AllocateWithoutSpilling();
+
+  // Allocate a free byte register without spilling any from the
+  // current frame or fail and return an invalid result.
+  Result AllocateByteRegisterWithoutSpilling();
+
+  // Copy the internal state to a register file, to be restored later by
+  // RestoreFrom.
+  void SaveTo(RegisterFile* register_file) {
+    registers_.CopyTo(register_file);
+  }
+
+  void RestoreFrom(RegisterFile* register_file) {
+    register_file->CopyTo(&registers_);
+  }
+
+ private:
+  CodeGenerator* cgen_;
+  RegisterFile registers_;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_REGISTER_ALLOCATOR_H_
diff --git a/deps/v8/src/rewriter.cc b/deps/v8/src/rewriter.cc
new file mode 100644
index 0000000..6641f26
--- /dev/null
+++ b/deps/v8/src/rewriter.cc
@@ -0,0 +1,839 @@
+// 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.
+
+#include "v8.h"
+
+#include "ast.h"
+#include "func-name-inferrer.h"
+#include "scopes.h"
+#include "rewriter.h"
+
+namespace v8 { namespace internal {
+
+
+class AstOptimizer: public AstVisitor {
+ public:
+  explicit AstOptimizer() {}
+  explicit AstOptimizer(Handle<String> enclosing_name) {
+    func_name_inferrer_.PushEnclosingName(enclosing_name);
+  }
+
+  void Optimize(ZoneList<Statement*>* statements);
+
+ private:
+  // Used for loop condition analysis.  Cleared before visiting a loop
+  // condition, set when a function literal is visited.
+  bool has_function_literal_;
+  // Helper object for function name inferring.
+  FuncNameInferrer func_name_inferrer_;
+
+  // Helpers
+  void OptimizeArguments(ZoneList<Expression*>* arguments);
+
+  // Node visitors.
+#define DEF_VISIT(type) \
+  virtual void Visit##type(type* node);
+  NODE_LIST(DEF_VISIT)
+#undef DEF_VISIT
+
+  DISALLOW_COPY_AND_ASSIGN(AstOptimizer);
+};
+
+
+void AstOptimizer::Optimize(ZoneList<Statement*>* statements) {
+  int len = statements->length();
+  for (int i = 0; i < len; i++) {
+    Visit(statements->at(i));
+  }
+}
+
+
+void AstOptimizer::OptimizeArguments(ZoneList<Expression*>* arguments) {
+  for (int i = 0; i < arguments->length(); i++) {
+    Visit(arguments->at(i));
+  }
+}
+
+
+void AstOptimizer::VisitBlock(Block* node) {
+  Optimize(node->statements());
+}
+
+
+void AstOptimizer::VisitExpressionStatement(ExpressionStatement* node) {
+  Visit(node->expression());
+}
+
+
+void AstOptimizer::VisitIfStatement(IfStatement* node) {
+  Visit(node->condition());
+  Visit(node->then_statement());
+  if (node->HasElseStatement()) {
+    Visit(node->else_statement());
+  }
+}
+
+
+void AstOptimizer::VisitLoopStatement(LoopStatement* node) {
+  if (node->init() != NULL) {
+    Visit(node->init());
+  }
+  if (node->cond() != NULL) {
+    has_function_literal_ = false;
+    Visit(node->cond());
+    node->may_have_function_literal_ = has_function_literal_;
+  }
+  if (node->body() != NULL) {
+    Visit(node->body());
+  }
+  if (node->next() != NULL) {
+    Visit(node->next());
+  }
+}
+
+
+void AstOptimizer::VisitForInStatement(ForInStatement* node) {
+  Visit(node->each());
+  Visit(node->enumerable());
+  Visit(node->body());
+}
+
+
+void AstOptimizer::VisitTryCatch(TryCatch* node) {
+  Visit(node->try_block());
+  Visit(node->catch_var());
+  Visit(node->catch_block());
+}
+
+
+void AstOptimizer::VisitTryFinally(TryFinally* node) {
+  Visit(node->try_block());
+  Visit(node->finally_block());
+}
+
+
+void AstOptimizer::VisitSwitchStatement(SwitchStatement* node) {
+  Visit(node->tag());
+  for (int i = 0; i < node->cases()->length(); i++) {
+    CaseClause* clause = node->cases()->at(i);
+    if (!clause->is_default()) {
+      Visit(clause->label());
+    }
+    Optimize(clause->statements());
+  }
+}
+
+
+void AstOptimizer::VisitContinueStatement(ContinueStatement* node) {
+  USE(node);
+}
+
+
+void AstOptimizer::VisitBreakStatement(BreakStatement* node) {
+  USE(node);
+}
+
+
+void AstOptimizer::VisitDeclaration(Declaration* node) {
+  // Will not be reached by the current optimizations.
+  USE(node);
+}
+
+
+void AstOptimizer::VisitEmptyStatement(EmptyStatement* node) {
+  USE(node);
+}
+
+
+void AstOptimizer::VisitReturnStatement(ReturnStatement* node) {
+  Visit(node->expression());
+}
+
+
+void AstOptimizer::VisitWithEnterStatement(WithEnterStatement* node) {
+  Visit(node->expression());
+}
+
+
+void AstOptimizer::VisitWithExitStatement(WithExitStatement* node) {
+  USE(node);
+}
+
+
+void AstOptimizer::VisitDebuggerStatement(DebuggerStatement* node) {
+  USE(node);
+}
+
+
+void AstOptimizer::VisitFunctionLiteral(FunctionLiteral* node) {
+  has_function_literal_ = true;
+
+  if (node->name()->length() == 0) {
+    // Anonymous function.
+    func_name_inferrer_.SetFuncToInfer(node);
+  }
+}
+
+
+void AstOptimizer::VisitFunctionBoilerplateLiteral(
+    FunctionBoilerplateLiteral* node) {
+  USE(node);
+}
+
+
+void AstOptimizer::VisitConditional(Conditional* node) {
+  Visit(node->condition());
+  Visit(node->then_expression());
+  Visit(node->else_expression());
+}
+
+
+void AstOptimizer::VisitSlot(Slot* node) {
+  USE(node);
+}
+
+
+void AstOptimizer::VisitVariableProxy(VariableProxy* node) {
+  Variable* var = node->AsVariable();
+  if (var != NULL) {
+    if (var->type()->IsKnown()) {
+      node->type()->CopyFrom(var->type());
+    } else if (node->type()->IsLikelySmi()) {
+      var->type()->SetAsLikelySmi();
+    }
+
+    if (!var->is_this() &&
+        !Heap::result_symbol()->Equals(*var->name())) {
+      func_name_inferrer_.PushName(var->name());
+    }
+  }
+}
+
+
+void AstOptimizer::VisitLiteral(Literal* node) {
+  Handle<Object> literal = node->handle();
+  if (literal->IsSmi()) {
+    node->type()->SetAsLikelySmi();
+  } else if (literal->IsString()) {
+    Handle<String> lit_str(Handle<String>::cast(literal));
+    if (!Heap::prototype_symbol()->Equals(*lit_str)) {
+      func_name_inferrer_.PushName(lit_str);
+    }
+  }
+}
+
+
+void AstOptimizer::VisitRegExpLiteral(RegExpLiteral* node) {
+  USE(node);
+}
+
+
+void AstOptimizer::VisitArrayLiteral(ArrayLiteral* node) {
+  for (int i = 0; i < node->values()->length(); i++) {
+    Visit(node->values()->at(i));
+  }
+}
+
+void AstOptimizer::VisitObjectLiteral(ObjectLiteral* node) {
+  for (int i = 0; i < node->properties()->length(); i++) {
+    ScopedFuncNameInferrer scoped_fni(&func_name_inferrer_);
+    scoped_fni.Enter();
+    Visit(node->properties()->at(i)->key());
+    Visit(node->properties()->at(i)->value());
+  }
+}
+
+
+void AstOptimizer::VisitCatchExtensionObject(CatchExtensionObject* node) {
+  Visit(node->key());
+  Visit(node->value());
+}
+
+
+void AstOptimizer::VisitAssignment(Assignment* node) {
+  ScopedFuncNameInferrer scoped_fni(&func_name_inferrer_);
+  switch (node->op()) {
+    case Token::INIT_VAR:
+    case Token::INIT_CONST:
+    case Token::ASSIGN:
+      // No type can be infered from the general assignment.
+
+      if (node->value()->AsFunctionLiteral() != NULL ||
+          node->value()->AsObjectLiteral() != NULL) {
+        scoped_fni.Enter();
+      }
+      break;
+    case Token::ASSIGN_BIT_OR:
+    case Token::ASSIGN_BIT_XOR:
+    case Token::ASSIGN_BIT_AND:
+    case Token::ASSIGN_SHL:
+    case Token::ASSIGN_SAR:
+    case Token::ASSIGN_SHR:
+      node->type()->SetAsLikelySmiIfUnknown();
+      node->target()->type()->SetAsLikelySmiIfUnknown();
+      node->value()->type()->SetAsLikelySmiIfUnknown();
+      break;
+    case Token::ASSIGN_ADD:
+    case Token::ASSIGN_SUB:
+    case Token::ASSIGN_MUL:
+    case Token::ASSIGN_DIV:
+    case Token::ASSIGN_MOD:
+      if (node->type()->IsLikelySmi()) {
+        node->target()->type()->SetAsLikelySmiIfUnknown();
+        node->value()->type()->SetAsLikelySmiIfUnknown();
+      }
+      break;
+    default:
+      UNREACHABLE();
+      break;
+  }
+
+  Visit(node->target());
+  Visit(node->value());
+
+  switch (node->op()) {
+    case Token::INIT_VAR:
+    case Token::INIT_CONST:
+    case Token::ASSIGN:
+      // Pure assignment copies the type from the value.
+      node->type()->CopyFrom(node->value()->type());
+      break;
+    case Token::ASSIGN_BIT_OR:
+    case Token::ASSIGN_BIT_XOR:
+    case Token::ASSIGN_BIT_AND:
+    case Token::ASSIGN_SHL:
+    case Token::ASSIGN_SAR:
+    case Token::ASSIGN_SHR:
+      // Should have been setup above already.
+      break;
+    case Token::ASSIGN_ADD:
+    case Token::ASSIGN_SUB:
+    case Token::ASSIGN_MUL:
+    case Token::ASSIGN_DIV:
+    case Token::ASSIGN_MOD:
+      if (node->type()->IsUnknown()) {
+        if (node->target()->type()->IsLikelySmi() ||
+            node->value()->type()->IsLikelySmi()) {
+          node->type()->SetAsLikelySmi();
+        }
+      }
+      break;
+    default:
+      UNREACHABLE();
+      break;
+  }
+
+  // Since this is an assignment. We have to propagate this node's type to the
+  // variable.
+  VariableProxy* proxy = node->target()->AsVariableProxy();
+  if (proxy != NULL) {
+    Variable* var = proxy->AsVariable();
+    if (var != NULL) {
+      SmiAnalysis* var_type = var->type();
+      if (var_type->IsUnknown()) {
+        var_type->CopyFrom(node->type());
+      } else if (var_type->IsLikelySmi()) {
+        // We do not reset likely types to Unknown.
+      }
+    }
+  }
+}
+
+
+void AstOptimizer::VisitThrow(Throw* node) {
+  Visit(node->exception());
+}
+
+
+void AstOptimizer::VisitProperty(Property* node) {
+  Visit(node->obj());
+  Visit(node->key());
+}
+
+
+void AstOptimizer::VisitCall(Call* node) {
+  Visit(node->expression());
+  OptimizeArguments(node->arguments());
+}
+
+
+void AstOptimizer::VisitCallEval(CallEval* node) {
+  Visit(node->expression());
+  OptimizeArguments(node->arguments());
+}
+
+
+void AstOptimizer::VisitCallNew(CallNew* node) {
+  Visit(node->expression());
+  OptimizeArguments(node->arguments());
+}
+
+
+void AstOptimizer::VisitCallRuntime(CallRuntime* node) {
+  ScopedFuncNameInferrer scoped_fni(&func_name_inferrer_);
+  if (Factory::InitializeVarGlobal_symbol()->Equals(*node->name()) &&
+      node->arguments()->length() >= 2 &&
+      node->arguments()->at(1)->AsFunctionLiteral() != NULL) {
+      scoped_fni.Enter();
+  }
+  OptimizeArguments(node->arguments());
+}
+
+
+void AstOptimizer::VisitUnaryOperation(UnaryOperation* node) {
+  Visit(node->expression());
+}
+
+
+void AstOptimizer::VisitCountOperation(CountOperation* node) {
+  // Count operations assume that they work on Smis.
+  node->type()->SetAsLikelySmiIfUnknown();
+  node->expression()->type()->SetAsLikelySmiIfUnknown();
+  Visit(node->expression());
+}
+
+
+void AstOptimizer::VisitBinaryOperation(BinaryOperation* node) {
+  // Depending on the operation we can propagate this node's type down the
+  // AST nodes.
+  switch (node->op()) {
+    case Token::COMMA:
+    case Token::OR:
+    case Token::AND:
+      break;
+    case Token::BIT_OR:
+    case Token::BIT_XOR:
+    case Token::BIT_AND:
+    case Token::SHL:
+    case Token::SAR:
+    case Token::SHR:
+      node->type()->SetAsLikelySmiIfUnknown();
+      node->left()->type()->SetAsLikelySmiIfUnknown();
+      node->right()->type()->SetAsLikelySmiIfUnknown();
+      break;
+    case Token::ADD:
+    case Token::SUB:
+    case Token::MUL:
+    case Token::DIV:
+    case Token::MOD:
+      if (node->type()->IsLikelySmi()) {
+        node->left()->type()->SetAsLikelySmiIfUnknown();
+        node->right()->type()->SetAsLikelySmiIfUnknown();
+      }
+      break;
+    default:
+      UNREACHABLE();
+      break;
+  }
+
+  Visit(node->left());
+  Visit(node->right());
+
+  // After visiting the operand nodes we have to check if this node's type
+  // can be updated. If it does, then we can push that information down
+  // towards the leafs again if the new information is an upgrade over the
+  // previous type of the operand nodes.
+  if (node->type()->IsUnknown()) {
+    if (node->left()->type()->IsLikelySmi() ||
+        node->right()->type()->IsLikelySmi()) {
+      node->type()->SetAsLikelySmi();
+    }
+    if (node->type()->IsLikelySmi()) {
+      // The type of this node changed to LIKELY_SMI. Propagate this knowledge
+      // down through the nodes.
+      if (node->left()->type()->IsUnknown()) {
+        node->left()->type()->SetAsLikelySmi();
+        Visit(node->left());
+      }
+      if (node->right()->type()->IsUnknown()) {
+        node->right()->type()->SetAsLikelySmi();
+        Visit(node->right());
+      }
+    }
+  }
+}
+
+
+void AstOptimizer::VisitCompareOperation(CompareOperation* node) {
+  if (node->type()->IsKnown()) {
+    // Propagate useful information down towards the leafs.
+    node->left()->type()->SetAsLikelySmiIfUnknown();
+    node->right()->type()->SetAsLikelySmiIfUnknown();
+  }
+
+  Visit(node->left());
+  Visit(node->right());
+
+  // After visiting the operand nodes we have to check if this node's type
+  // can be updated. If it does, then we can push that information down
+  // towards the leafs again if the new information is an upgrade over the
+  // previous type of the operand nodes.
+  if (node->type()->IsUnknown()) {
+    if (node->left()->type()->IsLikelySmi() ||
+        node->right()->type()->IsLikelySmi()) {
+      node->type()->SetAsLikelySmi();
+    }
+    if (node->type()->IsLikelySmi()) {
+      // The type of this node changed to LIKELY_SMI. Propagate this knowledge
+      // down through the nodes.
+      if (node->left()->type()->IsUnknown()) {
+        node->left()->type()->SetAsLikelySmi();
+        Visit(node->left());
+      }
+      if (node->right()->type()->IsUnknown()) {
+        node->right()->type()->SetAsLikelySmi();
+        Visit(node->right());
+      }
+    }
+  }
+}
+
+
+void AstOptimizer::VisitThisFunction(ThisFunction* node) {
+  USE(node);
+}
+
+
+class Processor: public AstVisitor {
+ public:
+  explicit Processor(VariableProxy* result)
+      : result_(result),
+        result_assigned_(false),
+        is_set_(false),
+        in_try_(false) {
+  }
+
+  void Process(ZoneList<Statement*>* statements);
+  bool result_assigned() const  { return result_assigned_; }
+
+ private:
+  VariableProxy* result_;
+
+  // We are not tracking result usage via the result_'s use
+  // counts (we leave the accurate computation to the
+  // usage analyzer). Instead we simple remember if
+  // there was ever an assignment to result_.
+  bool result_assigned_;
+
+  // To avoid storing to .result all the time, we eliminate some of
+  // the stores by keeping track of whether or not we're sure .result
+  // will be overwritten anyway. This is a bit more tricky than what I
+  // was hoping for
+  bool is_set_;
+  bool in_try_;
+
+  Expression* SetResult(Expression* value) {
+    result_assigned_ = true;
+    return new Assignment(Token::ASSIGN, result_, value,
+                          RelocInfo::kNoPosition);
+  }
+
+  // Node visitors.
+#define DEF_VISIT(type) \
+  virtual void Visit##type(type* node);
+  NODE_LIST(DEF_VISIT)
+#undef DEF_VISIT
+};
+
+
+void Processor::Process(ZoneList<Statement*>* statements) {
+  for (int i = statements->length() - 1; i >= 0; --i) {
+    Visit(statements->at(i));
+  }
+}
+
+
+void Processor::VisitBlock(Block* node) {
+  // An initializer block is the rewritten form of a variable declaration
+  // with initialization expressions. The initializer block contains the
+  // list of assignments corresponding to the initialization expressions.
+  // While unclear from the spec (ECMA-262, 3rd., 12.2), the value of
+  // a variable declaration with initialization expression is 'undefined'
+  // with some JS VMs: For instance, using smjs, print(eval('var x = 7'))
+  // returns 'undefined'. To obtain the same behavior with v8, we need
+  // to prevent rewriting in that case.
+  if (!node->is_initializer_block()) Process(node->statements());
+}
+
+
+void Processor::VisitExpressionStatement(ExpressionStatement* node) {
+  // Rewrite : <x>; -> .result = <x>;
+  if (!is_set_) {
+    node->set_expression(SetResult(node->expression()));
+    if (!in_try_) is_set_ = true;
+  }
+}
+
+
+void Processor::VisitIfStatement(IfStatement* node) {
+  // Rewrite both then and else parts (reversed).
+  bool save = is_set_;
+  Visit(node->else_statement());
+  bool set_after_then = is_set_;
+  is_set_ = save;
+  Visit(node->then_statement());
+  is_set_ = is_set_ && set_after_then;
+}
+
+
+
+
+void Processor::VisitLoopStatement(LoopStatement* node) {
+  // Rewrite loop body statement.
+  bool set_after_loop = is_set_;
+  Visit(node->body());
+  is_set_ = is_set_ && set_after_loop;
+}
+
+
+void Processor::VisitForInStatement(ForInStatement* node) {
+  // Rewrite for-in body statement.
+  bool set_after_for = is_set_;
+  Visit(node->body());
+  is_set_ = is_set_ && set_after_for;
+}
+
+
+void Processor::VisitTryCatch(TryCatch* node) {
+  // Rewrite both try and catch blocks (reversed order).
+  bool set_after_catch = is_set_;
+  Visit(node->catch_block());
+  is_set_ = is_set_ && set_after_catch;
+  bool save = in_try_;
+  in_try_ = true;
+  Visit(node->try_block());
+  in_try_ = save;
+}
+
+
+void Processor::VisitTryFinally(TryFinally* node) {
+  // Rewrite both try and finally block (reversed order).
+  Visit(node->finally_block());
+  bool save = in_try_;
+  in_try_ = true;
+  Visit(node->try_block());
+  in_try_ = save;
+}
+
+
+void Processor::VisitSwitchStatement(SwitchStatement* node) {
+  // Rewrite statements in all case clauses in reversed order.
+  ZoneList<CaseClause*>* clauses = node->cases();
+  bool set_after_switch = is_set_;
+  for (int i = clauses->length() - 1; i >= 0; --i) {
+    CaseClause* clause = clauses->at(i);
+    Process(clause->statements());
+  }
+  is_set_ = is_set_ && set_after_switch;
+}
+
+
+void Processor::VisitContinueStatement(ContinueStatement* node) {
+  is_set_ = false;
+}
+
+
+void Processor::VisitBreakStatement(BreakStatement* node) {
+  is_set_ = false;
+}
+
+
+// Do nothing:
+void Processor::VisitDeclaration(Declaration* node) {}
+void Processor::VisitEmptyStatement(EmptyStatement* node) {}
+void Processor::VisitReturnStatement(ReturnStatement* node) {}
+void Processor::VisitWithEnterStatement(WithEnterStatement* node) {}
+void Processor::VisitWithExitStatement(WithExitStatement* node) {}
+void Processor::VisitDebuggerStatement(DebuggerStatement* node) {}
+
+
+// Expressions are never visited yet.
+void Processor::VisitFunctionLiteral(FunctionLiteral* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+void Processor::VisitFunctionBoilerplateLiteral(
+    FunctionBoilerplateLiteral* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+void Processor::VisitConditional(Conditional* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+void Processor::VisitSlot(Slot* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+void Processor::VisitVariableProxy(VariableProxy* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+void Processor::VisitLiteral(Literal* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+void Processor::VisitRegExpLiteral(RegExpLiteral* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+void Processor::VisitArrayLiteral(ArrayLiteral* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+void Processor::VisitObjectLiteral(ObjectLiteral* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+void Processor::VisitCatchExtensionObject(CatchExtensionObject* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+void Processor::VisitAssignment(Assignment* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+void Processor::VisitThrow(Throw* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+void Processor::VisitProperty(Property* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+void Processor::VisitCall(Call* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+void Processor::VisitCallEval(CallEval* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+void Processor::VisitCallNew(CallNew* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+void Processor::VisitCallRuntime(CallRuntime* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+void Processor::VisitUnaryOperation(UnaryOperation* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+void Processor::VisitCountOperation(CountOperation* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+void Processor::VisitBinaryOperation(BinaryOperation* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+void Processor::VisitCompareOperation(CompareOperation* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+void Processor::VisitThisFunction(ThisFunction* node) {
+  USE(node);
+  UNREACHABLE();
+}
+
+
+bool Rewriter::Process(FunctionLiteral* function) {
+  Scope* scope = function->scope();
+  if (scope->is_function_scope()) return true;
+
+  ZoneList<Statement*>* body = function->body();
+  if (body->is_empty()) return true;
+
+  VariableProxy* result = scope->NewTemporary(Factory::result_symbol());
+  Processor processor(result);
+  processor.Process(body);
+  if (processor.HasStackOverflow()) return false;
+
+  if (processor.result_assigned()) body->Add(new ReturnStatement(result));
+  return true;
+}
+
+
+bool Rewriter::Optimize(FunctionLiteral* function) {
+  ZoneList<Statement*>* body = function->body();
+
+  if (FLAG_optimize_ast && !body->is_empty()) {
+    AstOptimizer optimizer(function->name());
+    optimizer.Optimize(body);
+    if (optimizer.HasStackOverflow()) {
+      return false;
+    }
+  }
+  return true;
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/rewriter.h b/deps/v8/src/rewriter.h
new file mode 100644
index 0000000..aa2f981
--- /dev/null
+++ b/deps/v8/src/rewriter.h
@@ -0,0 +1,53 @@
+// 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_REWRITER_H_
+#define V8_REWRITER_H_
+
+namespace v8 { namespace internal {
+
+
+// Currently, the rewriter takes function literals (only top-level)
+// and rewrites them to return the value of the last expression in
+// them.
+//
+// The rewriter adds a (hidden) variable, called .result, to the
+// activation, and tries to figure out where it needs to store into
+// this variable. If the variable is ever used, we conclude by adding
+// a return statement that returns the variable to the body of the
+// given function.
+
+class Rewriter {
+ public:
+  static bool Process(FunctionLiteral* function);
+  static bool Optimize(FunctionLiteral* function);
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_REWRITER_H_
diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc
new file mode 100644
index 0000000..ab25c9e
--- /dev/null
+++ b/deps/v8/src/runtime.cc
@@ -0,0 +1,6961 @@
+// Copyright 2006-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.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "accessors.h"
+#include "api.h"
+#include "arguments.h"
+#include "compiler.h"
+#include "cpu.h"
+#include "dateparser.h"
+#include "dateparser-inl.h"
+#include "debug.h"
+#include "execution.h"
+#include "jsregexp.h"
+#include "platform.h"
+#include "runtime.h"
+#include "scopeinfo.h"
+#include "v8threads.h"
+#include "smart-pointer.h"
+#include "parser.h"
+
+namespace v8 { namespace internal {
+
+
+#define RUNTIME_ASSERT(value) do {                                   \
+  if (!(value)) return IllegalOperation();                           \
+} while (false)
+
+// Cast the given object to a value of the specified type and store
+// it in a variable with the given name.  If the object is not of the
+// expected type call IllegalOperation and return.
+#define CONVERT_CHECKED(Type, name, obj)                             \
+  RUNTIME_ASSERT(obj->Is##Type());                                   \
+  Type* name = Type::cast(obj);
+
+#define CONVERT_ARG_CHECKED(Type, name, index)                       \
+  RUNTIME_ASSERT(args[index]->Is##Type());                           \
+  Handle<Type> name = args.at<Type>(index);
+
+// Cast the given object to a boolean and store it in a variable with
+// the given name.  If the object is not a boolean call IllegalOperation
+// and return.
+#define CONVERT_BOOLEAN_CHECKED(name, obj)                            \
+  RUNTIME_ASSERT(obj->IsBoolean());                                   \
+  bool name = (obj)->IsTrue();
+
+// Cast the given object to a Smi and store its value in an int variable
+// with the given name.  If the object is not a Smi call IllegalOperation
+// and return.
+#define CONVERT_SMI_CHECKED(name, obj)                            \
+  RUNTIME_ASSERT(obj->IsSmi());                                   \
+  int name = Smi::cast(obj)->value();
+
+// Cast the given object to a double and store it in a variable with
+// the given name.  If the object is not a number (as opposed to
+// the number not-a-number) call IllegalOperation and return.
+#define CONVERT_DOUBLE_CHECKED(name, obj)                            \
+  RUNTIME_ASSERT(obj->IsNumber());                                   \
+  double name = (obj)->Number();
+
+// Call the specified converter on the object *comand store the result in
+// a variable of the specified type with the given name.  If the
+// object is not a Number call IllegalOperation and return.
+#define CONVERT_NUMBER_CHECKED(type, name, Type, obj)                \
+  RUNTIME_ASSERT(obj->IsNumber());                                   \
+  type name = NumberTo##Type(obj);
+
+// Non-reentrant string buffer for efficient general use in this file.
+static StaticResource<StringInputBuffer> runtime_string_input_buffer;
+
+
+static Object* IllegalOperation() {
+  return Top::Throw(Heap::illegal_access_symbol());
+}
+
+
+static Object* DeepCopyBoilerplate(JSObject* boilerplate) {
+  StackLimitCheck check;
+  if (check.HasOverflowed()) return Top::StackOverflow();
+
+  Object* result = Heap::CopyJSObject(boilerplate);
+  if (result->IsFailure()) return result;
+  JSObject* copy = JSObject::cast(result);
+
+  // Deep copy local properties.
+  if (copy->HasFastProperties()) {
+    FixedArray* properties = copy->properties();
+    WriteBarrierMode mode = properties->GetWriteBarrierMode();
+    for (int i = 0; i < properties->length(); i++) {
+      Object* value = properties->get(i);
+      if (value->IsJSObject()) {
+        JSObject* jsObject = JSObject::cast(value);
+        result = DeepCopyBoilerplate(jsObject);
+        if (result->IsFailure()) return result;
+        properties->set(i, result, mode);
+      }
+    }
+    mode = copy->GetWriteBarrierMode();
+    for (int i = 0; i < copy->map()->inobject_properties(); i++) {
+      Object* value = copy->InObjectPropertyAt(i);
+      if (value->IsJSObject()) {
+        JSObject* jsObject = JSObject::cast(value);
+        result = DeepCopyBoilerplate(jsObject);
+        if (result->IsFailure()) return result;
+        copy->InObjectPropertyAtPut(i, result, mode);
+      }
+    }
+  } else {
+    result = Heap::AllocateFixedArray(copy->NumberOfLocalProperties(NONE));
+    if (result->IsFailure()) return result;
+    FixedArray* names = FixedArray::cast(result);
+    copy->GetLocalPropertyNames(names, 0);
+    for (int i = 0; i < names->length(); i++) {
+      ASSERT(names->get(i)->IsString());
+      String* keyString = String::cast(names->get(i));
+      PropertyAttributes attributes =
+        copy->GetLocalPropertyAttribute(keyString);
+      // Only deep copy fields from the object literal expression.
+      // In particular, don't try to copy the length attribute of
+      // an array.
+      if (attributes != NONE) continue;
+      Object* value = copy->GetProperty(keyString, &attributes);
+      ASSERT(!value->IsFailure());
+      if (value->IsJSObject()) {
+        JSObject* jsObject = JSObject::cast(value);
+        result = DeepCopyBoilerplate(jsObject);
+        if (result->IsFailure()) return result;
+        result = copy->SetProperty(keyString, result, NONE);
+        if (result->IsFailure()) return result;
+      }
+    }
+  }
+
+  // Deep copy local elements.
+  if (copy->HasFastElements()) {
+    FixedArray* elements = copy->elements();
+    WriteBarrierMode mode = elements->GetWriteBarrierMode();
+    for (int i = 0; i < elements->length(); i++) {
+      Object* value = elements->get(i);
+      if (value->IsJSObject()) {
+        JSObject* jsObject = JSObject::cast(value);
+        result = DeepCopyBoilerplate(jsObject);
+        if (result->IsFailure()) return result;
+        elements->set(i, result, mode);
+      }
+    }
+  } else {
+    Dictionary* element_dictionary = copy->element_dictionary();
+    int capacity = element_dictionary->Capacity();
+    for (int i = 0; i < capacity; i++) {
+      Object* k = element_dictionary->KeyAt(i);
+      if (element_dictionary->IsKey(k)) {
+        Object* value = element_dictionary->ValueAt(i);
+        if (value->IsJSObject()) {
+          JSObject* jsObject = JSObject::cast(value);
+          result = DeepCopyBoilerplate(jsObject);
+          if (result->IsFailure()) return result;
+          element_dictionary->ValueAtPut(i, result);
+        }
+      }
+    }
+  }
+  return copy;
+}
+
+
+static Object* Runtime_CloneLiteralBoilerplate(Arguments args) {
+  CONVERT_CHECKED(JSObject, boilerplate, args[0]);
+  return DeepCopyBoilerplate(boilerplate);
+}
+
+
+static Object* Runtime_CloneShallowLiteralBoilerplate(Arguments args) {
+  CONVERT_CHECKED(JSObject, boilerplate, args[0]);
+  return Heap::CopyJSObject(boilerplate);
+}
+
+
+static Handle<Map> ComputeObjectLiteralMap(
+    Handle<Context> context,
+    Handle<FixedArray> constant_properties,
+    bool* is_result_from_cache) {
+  int number_of_properties = constant_properties->length() / 2;
+  if (FLAG_canonicalize_object_literal_maps) {
+    // First find prefix of consecutive symbol keys.
+    int number_of_symbol_keys = 0;
+    while ((number_of_symbol_keys < number_of_properties) &&
+           (constant_properties->get(number_of_symbol_keys*2)->IsSymbol())) {
+      number_of_symbol_keys++;
+    }
+    // Based on the number of prefix symbols key we decide whether
+    // to use the map cache in the global context.
+    const int kMaxKeys = 10;
+    if ((number_of_symbol_keys == number_of_properties) &&
+        (number_of_symbol_keys < kMaxKeys)) {
+      // Create the fixed array with the key.
+      Handle<FixedArray> keys = Factory::NewFixedArray(number_of_symbol_keys);
+      for (int i = 0; i < number_of_symbol_keys; i++) {
+        keys->set(i, constant_properties->get(i*2));
+      }
+      *is_result_from_cache = true;
+      return Factory::ObjectLiteralMapFromCache(context, keys);
+    }
+  }
+  *is_result_from_cache = false;
+  return Factory::CopyMap(
+      Handle<Map>(context->object_function()->initial_map()),
+      number_of_properties);
+}
+
+
+static Handle<Object> CreateLiteralBoilerplate(
+    Handle<FixedArray> literals,
+    Handle<FixedArray> constant_properties);
+
+
+static Handle<Object> CreateObjectLiteralBoilerplate(
+    Handle<FixedArray> literals,
+    Handle<FixedArray> constant_properties) {
+  // Get the global context from the literals array.  This is the
+  // context in which the function was created and we use the object
+  // function from this context to create the object literal.  We do
+  // not use the object function from the current global context
+  // because this might be the object function from another context
+  // which we should not have access to.
+  Handle<Context> context =
+      Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals));
+
+  bool is_result_from_cache;
+  Handle<Map> map = ComputeObjectLiteralMap(context,
+                                            constant_properties,
+                                            &is_result_from_cache);
+
+  Handle<JSObject> boilerplate = Factory::NewJSObjectFromMap(map);
+  {  // Add the constant properties to the boilerplate.
+    int length = constant_properties->length();
+    OptimizedObjectForAddingMultipleProperties opt(boilerplate,
+                                                   !is_result_from_cache);
+    for (int index = 0; index < length; index +=2) {
+      Handle<Object> key(constant_properties->get(index+0));
+      Handle<Object> value(constant_properties->get(index+1));
+      if (value->IsFixedArray()) {
+        // The value contains the constant_properties of a
+        // simple object literal.
+        Handle<FixedArray> array = Handle<FixedArray>::cast(value);
+        value = CreateLiteralBoilerplate(literals, array);
+        if (value.is_null()) return value;
+      }
+      Handle<Object> result;
+      uint32_t element_index = 0;
+      if (key->IsSymbol()) {
+        // If key is a symbol it is not an array element.
+        Handle<String> name(String::cast(*key));
+        ASSERT(!name->AsArrayIndex(&element_index));
+        result = SetProperty(boilerplate, name, value, NONE);
+      } else if (Array::IndexFromObject(*key, &element_index)) {
+        // Array index (uint32).
+        result = SetElement(boilerplate, element_index, value);
+      } else {
+        // Non-uint32 number.
+        ASSERT(key->IsNumber());
+        double num = key->Number();
+        char arr[100];
+        Vector<char> buffer(arr, ARRAY_SIZE(arr));
+        const char* str = DoubleToCString(num, buffer);
+        Handle<String> name = Factory::NewStringFromAscii(CStrVector(str));
+        result = SetProperty(boilerplate, name, value, NONE);
+      }
+      // If setting the property on the boilerplate throws an
+      // exception, the exception is converted to an empty handle in
+      // the handle based operations.  In that case, we need to
+      // convert back to an exception.
+      if (result.is_null()) return result;
+    }
+  }
+
+  return boilerplate;
+}
+
+
+static Handle<Object> CreateArrayLiteralBoilerplate(
+    Handle<FixedArray> literals,
+    Handle<FixedArray> elements) {
+  // Create the JSArray.
+  Handle<JSFunction> constructor(
+      JSFunction::GlobalContextFromLiterals(*literals)->array_function());
+  Handle<Object> object = Factory::NewJSObject(constructor);
+
+  Handle<Object> copied_elements = Factory::CopyFixedArray(elements);
+
+  Handle<FixedArray> content = Handle<FixedArray>::cast(copied_elements);
+  for (int i = 0; i < content->length(); i++) {
+    if (content->get(i)->IsFixedArray()) {
+      // The value contains the constant_properties of a
+      // simple object literal.
+      Handle<FixedArray> fa(FixedArray::cast(content->get(i)));
+      Handle<Object> result =
+        CreateLiteralBoilerplate(literals, fa);
+      if (result.is_null()) return result;
+      content->set(i, *result);
+    }
+  }
+
+  // Set the elements.
+  Handle<JSArray>::cast(object)->SetContent(*content);
+  return object;
+}
+
+
+static Handle<Object> CreateLiteralBoilerplate(
+    Handle<FixedArray> literals,
+    Handle<FixedArray> array) {
+  Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
+  switch (CompileTimeValue::GetType(array)) {
+    case CompileTimeValue::OBJECT_LITERAL:
+      return CreateObjectLiteralBoilerplate(literals, elements);
+    case CompileTimeValue::ARRAY_LITERAL:
+      return CreateArrayLiteralBoilerplate(literals, elements);
+    default:
+      UNREACHABLE();
+      return Handle<Object>::null();
+  }
+}
+
+
+static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 3);
+  // Copy the arguments.
+  CONVERT_ARG_CHECKED(FixedArray, literals, 0);
+  CONVERT_SMI_CHECKED(literals_index, args[1]);
+  CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2);
+
+  Handle<Object> result =
+    CreateObjectLiteralBoilerplate(literals, constant_properties);
+
+  if (result.is_null()) return Failure::Exception();
+
+  // Update the functions literal and return the boilerplate.
+  literals->set(literals_index, *result);
+
+  return *result;
+}
+
+
+static Object* Runtime_CreateArrayLiteralBoilerplate(Arguments args) {
+  // Takes a FixedArray of elements containing the literal elements of
+  // the array literal and produces JSArray with those elements.
+  // Additionally takes the literals array of the surrounding function
+  // which contains the context from which to get the Array function
+  // to use for creating the array literal.
+  HandleScope scope;
+  ASSERT(args.length() == 3);
+  CONVERT_ARG_CHECKED(FixedArray, literals, 0);
+  CONVERT_SMI_CHECKED(literals_index, args[1]);
+  CONVERT_ARG_CHECKED(FixedArray, elements, 2);
+
+  Handle<Object> object = CreateArrayLiteralBoilerplate(literals, elements);
+  if (object.is_null()) return Failure::Exception();
+
+  // Update the functions literal and return the boilerplate.
+  literals->set(literals_index, *object);
+  return *object;
+}
+
+
+static Object* Runtime_CreateCatchExtensionObject(Arguments args) {
+  ASSERT(args.length() == 2);
+  CONVERT_CHECKED(String, key, args[0]);
+  Object* value = args[1];
+  // Create a catch context extension object.
+  JSFunction* constructor =
+      Top::context()->global_context()->context_extension_function();
+  Object* object = Heap::AllocateJSObject(constructor);
+  if (object->IsFailure()) return object;
+  // Assign the exception value to the catch variable and make sure
+  // that the catch variable is DontDelete.
+  value = JSObject::cast(object)->SetProperty(key, value, DONT_DELETE);
+  if (value->IsFailure()) return value;
+  return object;
+}
+
+
+static Object* Runtime_ClassOf(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+  Object* obj = args[0];
+  if (!obj->IsJSObject()) return Heap::null_value();
+  return JSObject::cast(obj)->class_name();
+}
+
+
+static Object* Runtime_HasStringClass(Arguments args) {
+  return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::String_symbol()));
+}
+
+
+static Object* Runtime_HasDateClass(Arguments args) {
+  return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::Date_symbol()));
+}
+
+
+static Object* Runtime_HasArrayClass(Arguments args) {
+  return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::Array_symbol()));
+}
+
+
+static Object* Runtime_HasFunctionClass(Arguments args) {
+  return Heap::ToBoolean(
+             args[0]->HasSpecificClassOf(Heap::function_class_symbol()));
+}
+
+
+static Object* Runtime_HasNumberClass(Arguments args) {
+  return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::Number_symbol()));
+}
+
+
+static Object* Runtime_HasBooleanClass(Arguments args) {
+  return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::Boolean_symbol()));
+}
+
+
+static Object* Runtime_HasArgumentsClass(Arguments args) {
+  return Heap::ToBoolean(
+             args[0]->HasSpecificClassOf(Heap::Arguments_symbol()));
+}
+
+
+static Object* Runtime_HasRegExpClass(Arguments args) {
+  return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::RegExp_symbol()));
+}
+
+
+static Object* Runtime_IsInPrototypeChain(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+  // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
+  Object* O = args[0];
+  Object* V = args[1];
+  while (true) {
+    Object* prototype = V->GetPrototype();
+    if (prototype->IsNull()) return Heap::false_value();
+    if (O == prototype) return Heap::true_value();
+    V = prototype;
+  }
+}
+
+
+static Object* Runtime_IsConstructCall(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 0);
+  JavaScriptFrameIterator it;
+  return Heap::ToBoolean(it.frame()->IsConstructor());
+}
+
+
+static Object* Runtime_RegExpCompile(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 3);
+  CONVERT_CHECKED(JSRegExp, raw_re, args[0]);
+  Handle<JSRegExp> re(raw_re);
+  CONVERT_CHECKED(String, raw_pattern, args[1]);
+  Handle<String> pattern(raw_pattern);
+  CONVERT_CHECKED(String, raw_flags, args[2]);
+  Handle<String> flags(raw_flags);
+  Handle<Object> result = RegExpImpl::Compile(re, pattern, flags);
+  if (result.is_null()) return Failure::Exception();
+  return *result;
+}
+
+
+static Object* Runtime_CreateApiFunction(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+  CONVERT_CHECKED(FunctionTemplateInfo, raw_data, args[0]);
+  Handle<FunctionTemplateInfo> data(raw_data);
+  return *Factory::CreateApiFunction(data);
+}
+
+
+static Object* Runtime_IsTemplate(Arguments args) {
+  ASSERT(args.length() == 1);
+  Object* arg = args[0];
+  bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
+  return Heap::ToBoolean(result);
+}
+
+
+static Object* Runtime_GetTemplateField(Arguments args) {
+  ASSERT(args.length() == 2);
+  CONVERT_CHECKED(HeapObject, templ, args[0]);
+  CONVERT_CHECKED(Smi, field, args[1]);
+  int index = field->value();
+  int offset = index * kPointerSize + HeapObject::kHeaderSize;
+  InstanceType type = templ->map()->instance_type();
+  RUNTIME_ASSERT(type ==  FUNCTION_TEMPLATE_INFO_TYPE ||
+                 type ==  OBJECT_TEMPLATE_INFO_TYPE);
+  RUNTIME_ASSERT(offset > 0);
+  if (type ==  FUNCTION_TEMPLATE_INFO_TYPE) {
+    RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize);
+  } else {
+    RUNTIME_ASSERT(offset < ObjectTemplateInfo::kSize);
+  }
+  return *HeapObject::RawField(templ, offset);
+}
+
+
+static Object* Runtime_DisableAccessChecks(Arguments args) {
+  ASSERT(args.length() == 1);
+  CONVERT_CHECKED(HeapObject, object, args[0]);
+  Map* old_map = object->map();
+  bool needs_access_checks = old_map->is_access_check_needed();
+  if (needs_access_checks) {
+    // Copy map so it won't interfere constructor's initial map.
+    Object* new_map = old_map->CopyDropTransitions();
+    if (new_map->IsFailure()) return new_map;
+
+    Map::cast(new_map)->set_is_access_check_needed(false);
+    object->set_map(Map::cast(new_map));
+  }
+  return needs_access_checks ? Heap::true_value() : Heap::false_value();
+}
+
+
+static Object* Runtime_EnableAccessChecks(Arguments args) {
+  ASSERT(args.length() == 1);
+  CONVERT_CHECKED(HeapObject, object, args[0]);
+  Map* old_map = object->map();
+  if (!old_map->is_access_check_needed()) {
+    // Copy map so it won't interfere constructor's initial map.
+    Object* new_map = old_map->CopyDropTransitions();
+    if (new_map->IsFailure()) return new_map;
+
+    Map::cast(new_map)->set_is_access_check_needed(true);
+    object->set_map(Map::cast(new_map));
+  }
+  return Heap::undefined_value();
+}
+
+
+static Object* ThrowRedeclarationError(const char* type, Handle<String> name) {
+  HandleScope scope;
+  Handle<Object> type_handle = Factory::NewStringFromAscii(CStrVector(type));
+  Handle<Object> args[2] = { type_handle, name };
+  Handle<Object> error =
+      Factory::NewTypeError("redeclaration", HandleVector(args, 2));
+  return Top::Throw(*error);
+}
+
+
+static Object* Runtime_DeclareGlobals(Arguments args) {
+  HandleScope scope;
+  Handle<GlobalObject> global = Handle<GlobalObject>(Top::context()->global());
+
+  CONVERT_ARG_CHECKED(FixedArray, pairs, 0);
+  Handle<Context> context = args.at<Context>(1);
+  bool is_eval = Smi::cast(args[2])->value() == 1;
+
+  // Compute the property attributes. According to ECMA-262, section
+  // 13, page 71, the property must be read-only and
+  // non-deletable. However, neither SpiderMonkey nor KJS creates the
+  // property as read-only, so we don't either.
+  PropertyAttributes base = is_eval ? NONE : DONT_DELETE;
+
+  // Only optimize the object if we intend to add more than 5 properties.
+  OptimizedObjectForAddingMultipleProperties ba(global, pairs->length()/2 > 5);
+
+  // Traverse the name/value pairs and set the properties.
+  int length = pairs->length();
+  for (int i = 0; i < length; i += 2) {
+    HandleScope scope;
+    Handle<String> name(String::cast(pairs->get(i)));
+    Handle<Object> value(pairs->get(i + 1));
+
+    // We have to declare a global const property. To capture we only
+    // assign to it when evaluating the assignment for "const x =
+    // <expr>" the initial value is the hole.
+    bool is_const_property = value->IsTheHole();
+
+    if (value->IsUndefined() || is_const_property) {
+      // Lookup the property in the global object, and don't set the
+      // value of the variable if the property is already there.
+      LookupResult lookup;
+      global->Lookup(*name, &lookup);
+      if (lookup.IsProperty()) {
+        // Determine if the property is local by comparing the holder
+        // against the global object. The information will be used to
+        // avoid throwing re-declaration errors when declaring
+        // variables or constants that exist in the prototype chain.
+        bool is_local = (*global == lookup.holder());
+        // Get the property attributes and determine if the property is
+        // read-only.
+        PropertyAttributes attributes = global->GetPropertyAttribute(*name);
+        bool is_read_only = (attributes & READ_ONLY) != 0;
+        if (lookup.type() == INTERCEPTOR) {
+          // If the interceptor says the property is there, we
+          // just return undefined without overwriting the property.
+          // Otherwise, we continue to setting the property.
+          if (attributes != ABSENT) {
+            // Check if the existing property conflicts with regards to const.
+            if (is_local && (is_read_only || is_const_property)) {
+              const char* type = (is_read_only) ? "const" : "var";
+              return ThrowRedeclarationError(type, name);
+            };
+            // The property already exists without conflicting: Go to
+            // the next declaration.
+            continue;
+          }
+          // Fall-through and introduce the absent property by using
+          // SetProperty.
+        } else {
+          if (is_local && (is_read_only || is_const_property)) {
+            const char* type = (is_read_only) ? "const" : "var";
+            return ThrowRedeclarationError(type, name);
+          }
+          // The property already exists without conflicting: Go to
+          // the next declaration.
+          continue;
+        }
+      }
+    } else {
+      // Copy the function and update its context. Use it as value.
+      Handle<JSFunction> boilerplate = Handle<JSFunction>::cast(value);
+      Handle<JSFunction> function =
+          Factory::NewFunctionFromBoilerplate(boilerplate, context);
+      value = function;
+    }
+
+    LookupResult lookup;
+    global->LocalLookup(*name, &lookup);
+
+    PropertyAttributes attributes = is_const_property
+        ? static_cast<PropertyAttributes>(base | READ_ONLY)
+        : base;
+
+    if (lookup.IsProperty()) {
+      // There's a local property that we need to overwrite because
+      // we're either declaring a function or there's an interceptor
+      // that claims the property is absent.
+
+      // Check for conflicting re-declarations. We cannot have
+      // conflicting types in case of intercepted properties because
+      // they are absent.
+      if (lookup.type() != INTERCEPTOR &&
+          (lookup.IsReadOnly() || is_const_property)) {
+        const char* type = (lookup.IsReadOnly()) ? "const" : "var";
+        return ThrowRedeclarationError(type, name);
+      }
+      SetProperty(global, name, value, attributes);
+    } else {
+      // If a property with this name does not already exist on the
+      // global object add the property locally.  We take special
+      // precautions to always add it as a local property even in case
+      // of callbacks in the prototype chain (this rules out using
+      // SetProperty).  Also, we must use the handle-based version to
+      // avoid GC issues.
+      IgnoreAttributesAndSetLocalProperty(global, name, value, attributes);
+    }
+  }
+
+  return Heap::undefined_value();
+}
+
+
+static Object* Runtime_DeclareContextSlot(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 4);
+
+  CONVERT_ARG_CHECKED(Context, context, 0);
+  Handle<String> name(String::cast(args[1]));
+  PropertyAttributes mode =
+      static_cast<PropertyAttributes>(Smi::cast(args[2])->value());
+  ASSERT(mode == READ_ONLY || mode == NONE);
+  Handle<Object> initial_value(args[3]);
+
+  // Declarations are always done in the function context.
+  context = Handle<Context>(context->fcontext());
+
+  int index;
+  PropertyAttributes attributes;
+  ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
+  Handle<Object> holder =
+      context->Lookup(name, flags, &index, &attributes);
+
+  if (attributes != ABSENT) {
+    // The name was declared before; check for conflicting
+    // re-declarations: This is similar to the code in parser.cc in
+    // the AstBuildingParser::Declare function.
+    if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
+      // Functions are not read-only.
+      ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
+      const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
+      return ThrowRedeclarationError(type, name);
+    }
+
+    // Initialize it if necessary.
+    if (*initial_value != NULL) {
+      if (index >= 0) {
+        // The variable or constant context slot should always be in
+        // the function context; not in any outer context nor in the
+        // arguments object.
+        ASSERT(holder.is_identical_to(context));
+        if (((attributes & READ_ONLY) == 0) ||
+            context->get(index)->IsTheHole()) {
+          context->set(index, *initial_value);
+        }
+      } else {
+        // Slow case: The property is not in the FixedArray part of the context.
+        Handle<JSObject> context_ext = Handle<JSObject>::cast(holder);
+        SetProperty(context_ext, name, initial_value, mode);
+      }
+    }
+
+  } else {
+    // The property is not in the function context. It needs to be
+    // "declared" in the function context's extension context, or in the
+    // global context.
+    Handle<JSObject> context_ext;
+    if (context->has_extension()) {
+      // The function context's extension context exists - use it.
+      context_ext = Handle<JSObject>(context->extension());
+    } else {
+      // The function context's extension context does not exists - allocate
+      // it.
+      context_ext = Factory::NewJSObject(Top::context_extension_function());
+      // And store it in the extension slot.
+      context->set_extension(*context_ext);
+    }
+    ASSERT(*context_ext != NULL);
+
+    // Declare the property by setting it to the initial value if provided,
+    // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
+    // constant declarations).
+    ASSERT(!context_ext->HasLocalProperty(*name));
+    Handle<Object> value(Heap::undefined_value());
+    if (*initial_value != NULL) value = initial_value;
+    SetProperty(context_ext, name, value, mode);
+    ASSERT(context_ext->GetLocalPropertyAttribute(*name) == mode);
+  }
+
+  return Heap::undefined_value();
+}
+
+
+static Object* Runtime_InitializeVarGlobal(Arguments args) {
+  NoHandleAllocation nha;
+
+  // Determine if we need to assign to the variable if it already
+  // exists (based on the number of arguments).
+  RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
+  bool assign = args.length() == 2;
+
+  CONVERT_ARG_CHECKED(String, name, 0);
+  GlobalObject* global = Top::context()->global();
+
+  // According to ECMA-262, section 12.2, page 62, the property must
+  // not be deletable.
+  PropertyAttributes attributes = DONT_DELETE;
+
+  // Lookup the property locally in the global object. If it isn't
+  // there, we add the property and take special precautions to always
+  // add it as a local property even in case of callbacks in the
+  // prototype chain (this rules out using SetProperty).
+  // We have IgnoreAttributesAndSetLocalProperty for this.
+  LookupResult lookup;
+  global->LocalLookup(*name, &lookup);
+  if (!lookup.IsProperty()) {
+    Object* value = (assign) ? args[1] : Heap::undefined_value();
+    return global->IgnoreAttributesAndSetLocalProperty(*name,
+                                                       value,
+                                                       attributes);
+  }
+
+  // Determine if this is a redeclaration of something read-only.
+  if (lookup.IsReadOnly()) {
+    return ThrowRedeclarationError("const", name);
+  }
+
+  // Determine if this is a redeclaration of an intercepted read-only
+  // property and figure out if the property exists at all.
+  bool found = true;
+  PropertyType type = lookup.type();
+  if (type == INTERCEPTOR) {
+    PropertyAttributes intercepted = global->GetPropertyAttribute(*name);
+    if (intercepted == ABSENT) {
+      // The interceptor claims the property isn't there. We need to
+      // make sure to introduce it.
+      found = false;
+    } else if ((intercepted & READ_ONLY) != 0) {
+      // The property is present, but read-only. Since we're trying to
+      // overwrite it with a variable declaration we must throw a
+      // re-declaration error.
+      return ThrowRedeclarationError("const", name);
+    }
+    // Restore global object from context (in case of GC).
+    global = Top::context()->global();
+  }
+
+  if (found && !assign) {
+    // The global property is there and we're not assigning any value
+    // to it. Just return.
+    return Heap::undefined_value();
+  }
+
+  // Assign the value (or undefined) to the property.
+  Object* value = (assign) ? args[1] : Heap::undefined_value();
+  return global->SetProperty(&lookup, *name, value, attributes);
+}
+
+
+static Object* Runtime_InitializeConstGlobal(Arguments args) {
+  // All constants are declared with an initial value. The name
+  // of the constant is the first argument and the initial value
+  // is the second.
+  RUNTIME_ASSERT(args.length() == 2);
+  CONVERT_ARG_CHECKED(String, name, 0);
+  Handle<Object> value = args.at<Object>(1);
+
+  // Get the current global object from top.
+  GlobalObject* global = Top::context()->global();
+
+  // According to ECMA-262, section 12.2, page 62, the property must
+  // not be deletable. Since it's a const, it must be READ_ONLY too.
+  PropertyAttributes attributes =
+      static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
+
+  // Lookup the property locally in the global object. If it isn't
+  // there, we add the property and take special precautions to always
+  // add it as a local property even in case of callbacks in the
+  // prototype chain (this rules out using SetProperty).
+  // We use IgnoreAttributesAndSetLocalProperty instead
+  LookupResult lookup;
+  global->LocalLookup(*name, &lookup);
+  if (!lookup.IsProperty()) {
+    return global->IgnoreAttributesAndSetLocalProperty(*name,
+                                                       *value,
+                                                       attributes);
+  }
+
+  // Determine if this is a redeclaration of something not
+  // read-only. In case the result is hidden behind an interceptor we
+  // need to ask it for the property attributes.
+  if (!lookup.IsReadOnly()) {
+    if (lookup.type() != INTERCEPTOR) {
+      return ThrowRedeclarationError("var", name);
+    }
+
+    PropertyAttributes intercepted = global->GetPropertyAttribute(*name);
+
+    // Throw re-declaration error if the intercepted property is present
+    // but not read-only.
+    if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
+      return ThrowRedeclarationError("var", name);
+    }
+
+    // Restore global object from context (in case of GC) and continue
+    // with setting the value because the property is either absent or
+    // read-only. We also have to do redo the lookup.
+    global = Top::context()->global();
+
+    // BUG 1213579: Handle the case where we have to set a read-only
+    // property through an interceptor and only do it if it's
+    // uninitialized, e.g. the hole. Nirk...
+    global->SetProperty(*name, *value, attributes);
+    return *value;
+  }
+
+  // Set the value, but only we're assigning the initial value to a
+  // constant. For now, we determine this by checking if the
+  // current value is the hole.
+  PropertyType type = lookup.type();
+  if (type == FIELD) {
+    FixedArray* properties = global->properties();
+    int index = lookup.GetFieldIndex();
+    if (properties->get(index)->IsTheHole()) {
+      properties->set(index, *value);
+    }
+  } else if (type == NORMAL) {
+    Dictionary* dictionary = global->property_dictionary();
+    int entry = lookup.GetDictionaryEntry();
+    if (dictionary->ValueAt(entry)->IsTheHole()) {
+      dictionary->ValueAtPut(entry, *value);
+    }
+  } else {
+    // Ignore re-initialization of constants that have already been
+    // assigned a function value.
+    ASSERT(lookup.IsReadOnly() && type == CONSTANT_FUNCTION);
+  }
+
+  // Use the set value as the result of the operation.
+  return *value;
+}
+
+
+static Object* Runtime_InitializeConstContextSlot(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 3);
+
+  Handle<Object> value(args[0]);
+  ASSERT(!value->IsTheHole());
+  CONVERT_ARG_CHECKED(Context, context, 1);
+  Handle<String> name(String::cast(args[2]));
+
+  // Initializations are always done in the function context.
+  context = Handle<Context>(context->fcontext());
+
+  int index;
+  PropertyAttributes attributes;
+  ContextLookupFlags flags = FOLLOW_CHAINS;
+  Handle<Object> holder =
+      context->Lookup(name, flags, &index, &attributes);
+
+  // In most situations, the property introduced by the const
+  // declaration should be present in the context extension object.
+  // However, because declaration and initialization are separate, the
+  // property might have been deleted (if it was introduced by eval)
+  // before we reach the initialization point.
+  //
+  // Example:
+  //
+  //    function f() { eval("delete x; const x;"); }
+  //
+  // In that case, the initialization behaves like a normal assignment
+  // to property 'x'.
+  if (index >= 0) {
+    // Property was found in a context.
+    if (holder->IsContext()) {
+      // The holder cannot be the function context.  If it is, there
+      // should have been a const redeclaration error when declaring
+      // the const property.
+      ASSERT(!holder.is_identical_to(context));
+      if ((attributes & READ_ONLY) == 0) {
+        Handle<Context>::cast(holder)->set(index, *value);
+      }
+    } else {
+      // The holder is an arguments object.
+      ASSERT((attributes & READ_ONLY) == 0);
+      Handle<JSObject>::cast(holder)->SetElement(index, *value);
+    }
+    return *value;
+  }
+
+  // The property could not be found, we introduce it in the global
+  // context.
+  if (attributes == ABSENT) {
+    Handle<JSObject> global = Handle<JSObject>(Top::context()->global());
+    SetProperty(global, name, value, NONE);
+    return *value;
+  }
+
+  // The property was present in a context extension object.
+  Handle<JSObject> context_ext = Handle<JSObject>::cast(holder);
+
+  if (*context_ext == context->extension()) {
+    // This is the property that was introduced by the const
+    // declaration.  Set it if it hasn't been set before.  NOTE: We
+    // cannot use GetProperty() to get the current value as it
+    // 'unholes' the value.
+    LookupResult lookup;
+    context_ext->LocalLookupRealNamedProperty(*name, &lookup);
+    ASSERT(lookup.IsProperty());  // the property was declared
+    ASSERT(lookup.IsReadOnly());  // and it was declared as read-only
+
+    PropertyType type = lookup.type();
+    if (type == FIELD) {
+      FixedArray* properties = context_ext->properties();
+      int index = lookup.GetFieldIndex();
+      if (properties->get(index)->IsTheHole()) {
+        properties->set(index, *value);
+      }
+    } else if (type == NORMAL) {
+      Dictionary* dictionary = context_ext->property_dictionary();
+      int entry = lookup.GetDictionaryEntry();
+      if (dictionary->ValueAt(entry)->IsTheHole()) {
+        dictionary->ValueAtPut(entry, *value);
+      }
+    } else {
+      // We should not reach here. Any real, named property should be
+      // either a field or a dictionary slot.
+      UNREACHABLE();
+    }
+  } else {
+    // The property was found in a different context extension object.
+    // Set it if it is not a read-only property.
+    if ((attributes & READ_ONLY) == 0) {
+      Handle<Object> set = SetProperty(context_ext, name, value, attributes);
+      // Setting a property might throw an exception.  Exceptions
+      // are converted to empty handles in handle operations.  We
+      // need to convert back to exceptions here.
+      if (set.is_null()) {
+        ASSERT(Top::has_pending_exception());
+        return Failure::Exception();
+      }
+    }
+  }
+
+  return *value;
+}
+
+
+static Object* Runtime_RegExpExec(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 4);
+  CONVERT_CHECKED(JSRegExp, raw_regexp, args[0]);
+  Handle<JSRegExp> regexp(raw_regexp);
+  CONVERT_CHECKED(String, raw_subject, args[1]);
+  Handle<String> subject(raw_subject);
+  // Due to the way the JS files are constructed this must be less than the
+  // length of a string, i.e. it is always a Smi.  We check anyway for security.
+  CONVERT_CHECKED(Smi, index, args[2]);
+  CONVERT_CHECKED(JSArray, raw_last_match_info, args[3]);
+  Handle<JSArray> last_match_info(raw_last_match_info);
+  RUNTIME_ASSERT(last_match_info->HasFastElements());
+  RUNTIME_ASSERT(index->value() >= 0);
+  RUNTIME_ASSERT(index->value() <= subject->length());
+  Handle<Object> result = RegExpImpl::Exec(regexp,
+                                           subject,
+                                           index->value(),
+                                           last_match_info);
+  if (result.is_null()) return Failure::Exception();
+  return *result;
+}
+
+
+static Object* Runtime_MaterializeRegExpLiteral(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 4);
+  CONVERT_ARG_CHECKED(FixedArray, literals, 0);
+  int index = Smi::cast(args[1])->value();
+  Handle<String> pattern = args.at<String>(2);
+  Handle<String> flags = args.at<String>(3);
+
+  // Get the RegExp function from the context in the literals array.
+  // This is the RegExp function from the context in which the
+  // function was created.  We do not use the RegExp function from the
+  // current global context because this might be the RegExp function
+  // from another context which we should not have access to.
+  Handle<JSFunction> constructor =
+      Handle<JSFunction>(
+          JSFunction::GlobalContextFromLiterals(*literals)->regexp_function());
+  // Compute the regular expression literal.
+  bool has_pending_exception;
+  Handle<Object> regexp =
+      RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
+                                      &has_pending_exception);
+  if (has_pending_exception) {
+    ASSERT(Top::has_pending_exception());
+    return Failure::Exception();
+  }
+  literals->set(index, *regexp);
+  return *regexp;
+}
+
+
+static Object* Runtime_FunctionGetName(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_CHECKED(JSFunction, f, args[0]);
+  return f->shared()->name();
+}
+
+
+static Object* Runtime_FunctionSetName(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_CHECKED(JSFunction, f, args[0]);
+  CONVERT_CHECKED(String, name, args[1]);
+  f->shared()->set_name(name);
+  return Heap::undefined_value();
+}
+
+
+static Object* Runtime_FunctionGetScript(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+
+  CONVERT_CHECKED(JSFunction, fun, args[0]);
+  Handle<Object> script = Handle<Object>(fun->shared()->script());
+  if (!script->IsScript()) return Heap::undefined_value();
+
+  return *GetScriptWrapper(Handle<Script>::cast(script));
+}
+
+
+static Object* Runtime_FunctionGetSourceCode(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_CHECKED(JSFunction, f, args[0]);
+  return f->shared()->GetSourceCode();
+}
+
+
+static Object* Runtime_FunctionGetScriptSourcePosition(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_CHECKED(JSFunction, fun, args[0]);
+  int pos = fun->shared()->start_position();
+  return Smi::FromInt(pos);
+}
+
+
+static Object* Runtime_FunctionSetInstanceClassName(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_CHECKED(JSFunction, fun, args[0]);
+  CONVERT_CHECKED(String, name, args[1]);
+  fun->SetInstanceClassName(name);
+  return Heap::undefined_value();
+}
+
+
+static Object* Runtime_FunctionSetLength(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_CHECKED(JSFunction, fun, args[0]);
+  CONVERT_CHECKED(Smi, length, args[1]);
+  fun->shared()->set_length(length->value());
+  return length;
+}
+
+
+static Object* Runtime_FunctionSetPrototype(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_CHECKED(JSFunction, fun, args[0]);
+  Object* obj = Accessors::FunctionSetPrototype(fun, args[1], NULL);
+  if (obj->IsFailure()) return obj;
+  return args[0];  // return TOS
+}
+
+
+static Object* Runtime_FunctionIsAPIFunction(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_CHECKED(JSFunction, f, args[0]);
+  // The function_data field of the shared function info is used exclusively by
+  // the API.
+  return !f->shared()->function_data()->IsUndefined() ? Heap::true_value()
+                                                      : Heap::false_value();
+}
+
+
+static Object* Runtime_SetCode(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 2);
+
+  CONVERT_CHECKED(JSFunction, raw_target, args[0]);
+  Handle<JSFunction> target(raw_target);
+  Handle<Object> code = args.at<Object>(1);
+
+  Handle<Context> context(target->context());
+
+  if (!code->IsNull()) {
+    RUNTIME_ASSERT(code->IsJSFunction());
+    Handle<JSFunction> fun = Handle<JSFunction>::cast(code);
+    SetExpectedNofProperties(target, fun->shared()->expected_nof_properties());
+    if (!fun->is_compiled() && !CompileLazy(fun, KEEP_EXCEPTION)) {
+      return Failure::Exception();
+    }
+    // Set the code, formal parameter count, and the length of the target
+    // function.
+    target->set_code(fun->code());
+    target->shared()->set_length(fun->shared()->length());
+    target->shared()->set_formal_parameter_count(
+        fun->shared()->formal_parameter_count());
+    // Set the source code of the target function to undefined.
+    // SetCode is only used for built-in constructors like String,
+    // Array, and Object, and some web code
+    // doesn't like seeing source code for constructors.
+    target->shared()->set_script(Heap::undefined_value());
+    context = Handle<Context>(fun->context());
+
+    // Make sure we get a fresh copy of the literal vector to avoid
+    // cross context contamination.
+    int number_of_literals = fun->NumberOfLiterals();
+    Handle<FixedArray> literals =
+        Factory::NewFixedArray(number_of_literals, TENURED);
+    if (number_of_literals > 0) {
+      // Insert the object, regexp and array functions in the literals
+      // array prefix.  These are the functions that will be used when
+      // creating object, regexp and array literals.
+      literals->set(JSFunction::kLiteralGlobalContextIndex,
+                    context->global_context());
+    }
+    target->set_literals(*literals, SKIP_WRITE_BARRIER);
+  }
+
+  target->set_context(*context);
+  return *target;
+}
+
+
+static Object* CharCodeAt(String* subject, Object* index) {
+  uint32_t i = 0;
+  if (!Array::IndexFromObject(index, &i)) return Heap::nan_value();
+  // Flatten the string.  If someone wants to get a char at an index
+  // in a cons string, it is likely that more indices will be
+  // accessed.
+  subject->TryFlattenIfNotFlat();
+  if (i >= static_cast<uint32_t>(subject->length())) {
+    return Heap::nan_value();
+  }
+  return Smi::FromInt(subject->Get(i));
+}
+
+
+static Object* Runtime_StringCharCodeAt(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_CHECKED(String, subject, args[0]);
+  Object* index = args[1];
+  return CharCodeAt(subject, index);
+}
+
+
+static Object* Runtime_CharFromCode(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+  uint32_t code;
+  if (Array::IndexFromObject(args[0], &code)) {
+    if (code <= 0xffff) {
+      return Heap::LookupSingleCharacterStringFromCode(code);
+    }
+  }
+  return Heap::empty_string();
+}
+
+// Forward declarations.
+static const int kStringBuilderConcatHelperLengthBits = 11;
+static const int kStringBuilderConcatHelperPositionBits = 19;
+
+template <typename schar>
+static inline void StringBuilderConcatHelper(String*,
+                                             schar*,
+                                             FixedArray*,
+                                             int);
+
+typedef BitField<int, 0, 11> StringBuilderSubstringLength;
+typedef BitField<int, 11, 19> StringBuilderSubstringPosition;
+
+class ReplacementStringBuilder {
+ public:
+  ReplacementStringBuilder(Handle<String> subject, int estimated_part_count)
+      : subject_(subject),
+        parts_(Factory::NewFixedArray(estimated_part_count)),
+        part_count_(0),
+        character_count_(0),
+        is_ascii_(StringShape(*subject).IsAsciiRepresentation()) {
+    // Require a non-zero initial size. Ensures that doubling the size to
+    // extend the array will work.
+    ASSERT(estimated_part_count > 0);
+  }
+
+  void EnsureCapacity(int elements) {
+    int length = parts_->length();
+    int required_length = part_count_ + elements;
+    if (length < required_length) {
+      int new_length = length;
+      do {
+        new_length *= 2;
+      } while (new_length < required_length);
+      Handle<FixedArray> extended_array =
+          Factory::NewFixedArray(new_length);
+      parts_->CopyTo(0, *extended_array, 0, part_count_);
+      parts_ = extended_array;
+    }
+  }
+
+  void AddSubjectSlice(int from, int to) {
+    ASSERT(from >= 0);
+    int length = to - from;
+    ASSERT(length > 0);
+    // Can we encode the slice in 11 bits for length and 19 bits for
+    // start position - as used by StringBuilderConcatHelper?
+    if (StringBuilderSubstringLength::is_valid(length) &&
+        StringBuilderSubstringPosition::is_valid(from)) {
+      int encoded_slice = StringBuilderSubstringLength::encode(length) |
+          StringBuilderSubstringPosition::encode(from);
+      AddElement(Smi::FromInt(encoded_slice));
+    } else {
+      Handle<String> slice = Factory::NewStringSlice(subject_, from, to);
+      AddElement(*slice);
+    }
+    IncrementCharacterCount(length);
+  }
+
+
+  void AddString(Handle<String> string) {
+    int length = string->length();
+    ASSERT(length > 0);
+    AddElement(*string);
+    if (!StringShape(*string).IsAsciiRepresentation()) {
+      is_ascii_ = false;
+    }
+    IncrementCharacterCount(length);
+  }
+
+
+  Handle<String> ToString() {
+    if (part_count_ == 0) {
+      return Factory::empty_string();
+    }
+
+    Handle<String> joined_string;
+    if (is_ascii_) {
+      joined_string = NewRawAsciiString(character_count_);
+      AssertNoAllocation no_alloc;
+      SeqAsciiString* seq = SeqAsciiString::cast(*joined_string);
+      char* char_buffer = seq->GetChars();
+      StringBuilderConcatHelper(*subject_,
+                                char_buffer,
+                                *parts_,
+                                part_count_);
+    } else {
+      // Non-ASCII.
+      joined_string = NewRawTwoByteString(character_count_);
+      AssertNoAllocation no_alloc;
+      SeqTwoByteString* seq = SeqTwoByteString::cast(*joined_string);
+      uc16* char_buffer = seq->GetChars();
+      StringBuilderConcatHelper(*subject_,
+                                char_buffer,
+                                *parts_,
+                                part_count_);
+    }
+    return joined_string;
+  }
+
+
+  void IncrementCharacterCount(int by) {
+    if (character_count_ > Smi::kMaxValue - by) {
+      V8::FatalProcessOutOfMemory("String.replace result too large.");
+    }
+    character_count_ += by;
+  }
+
+ private:
+
+  Handle<String> NewRawAsciiString(int size) {
+    CALL_HEAP_FUNCTION(Heap::AllocateRawAsciiString(size), String);
+  }
+
+
+  Handle<String> NewRawTwoByteString(int size) {
+    CALL_HEAP_FUNCTION(Heap::AllocateRawTwoByteString(size), String);
+  }
+
+
+  void AddElement(Object* element) {
+    ASSERT(element->IsSmi() || element->IsString());
+    parts_->set(part_count_, element);
+    part_count_++;
+  }
+
+  Handle<String> subject_;
+  Handle<FixedArray> parts_;
+  int part_count_;
+  int character_count_;
+  bool is_ascii_;
+};
+
+
+class CompiledReplacement {
+ public:
+  CompiledReplacement()
+      : parts_(1), replacement_substrings_(0) {}
+
+  void Compile(Handle<String> replacement,
+               int capture_count,
+               int subject_length);
+
+  void Apply(ReplacementStringBuilder* builder,
+             int match_from,
+             int match_to,
+             Handle<JSArray> last_match_info);
+
+  // Number of distinct parts of the replacement pattern.
+  int parts() {
+    return parts_.length();
+  }
+ private:
+  enum PartType {
+    SUBJECT_PREFIX = 1,
+    SUBJECT_SUFFIX,
+    SUBJECT_CAPTURE,
+    REPLACEMENT_SUBSTRING,
+    REPLACEMENT_STRING,
+
+    NUMBER_OF_PART_TYPES
+  };
+
+  struct ReplacementPart {
+    static inline ReplacementPart SubjectMatch() {
+      return ReplacementPart(SUBJECT_CAPTURE, 0);
+    }
+    static inline ReplacementPart SubjectCapture(int capture_index) {
+      return ReplacementPart(SUBJECT_CAPTURE, capture_index);
+    }
+    static inline ReplacementPart SubjectPrefix() {
+      return ReplacementPart(SUBJECT_PREFIX, 0);
+    }
+    static inline ReplacementPart SubjectSuffix(int subject_length) {
+      return ReplacementPart(SUBJECT_SUFFIX, subject_length);
+    }
+    static inline ReplacementPart ReplacementString() {
+      return ReplacementPart(REPLACEMENT_STRING, 0);
+    }
+    static inline ReplacementPart ReplacementSubString(int from, int to) {
+      ASSERT(from >= 0);
+      ASSERT(to > from);
+      return ReplacementPart(-from, to);
+    }
+
+    // If tag <= 0 then it is the negation of a start index of a substring of
+    // the replacement pattern, otherwise it's a value from PartType.
+    ReplacementPart(int tag, int data)
+        : tag(tag), data(data) {
+      // Must be non-positive or a PartType value.
+      ASSERT(tag < NUMBER_OF_PART_TYPES);
+    }
+    // Either a value of PartType or a non-positive number that is
+    // the negation of an index into the replacement string.
+    int tag;
+    // The data value's interpretation depends on the value of tag:
+    // tag == SUBJECT_PREFIX ||
+    // tag == SUBJECT_SUFFIX:  data is unused.
+    // tag == SUBJECT_CAPTURE: data is the number of the capture.
+    // tag == REPLACEMENT_SUBSTRING ||
+    // tag == REPLACEMENT_STRING:    data is index into array of substrings
+    //                               of the replacement string.
+    // tag <= 0: Temporary representation of the substring of the replacement
+    //           string ranging over -tag .. data.
+    //           Is replaced by REPLACEMENT_{SUB,}STRING when we create the
+    //           substring objects.
+    int data;
+  };
+
+  template<typename Char>
+  static void ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
+                                      Vector<Char> characters,
+                                      int capture_count,
+                                      int subject_length) {
+    int length = characters.length();
+    int last = 0;
+    for (int i = 0; i < length; i++) {
+      Char c = characters[i];
+      if (c == '$') {
+        int next_index = i + 1;
+        if (next_index == length) {  // No next character!
+          break;
+        }
+        Char c2 = characters[next_index];
+        switch (c2) {
+        case '$':
+          if (i > last) {
+            // There is a substring before. Include the first "$".
+            parts->Add(ReplacementPart::ReplacementSubString(last, next_index));
+            last = next_index + 1;  // Continue after the second "$".
+          } else {
+            // Let the next substring start with the second "$".
+            last = next_index;
+          }
+          i = next_index;
+          break;
+        case '`':
+          if (i > last) {
+            parts->Add(ReplacementPart::ReplacementSubString(last, i));
+          }
+          parts->Add(ReplacementPart::SubjectPrefix());
+          i = next_index;
+          last = i + 1;
+          break;
+        case '\'':
+          if (i > last) {
+            parts->Add(ReplacementPart::ReplacementSubString(last, i));
+          }
+          parts->Add(ReplacementPart::SubjectSuffix(subject_length));
+          i = next_index;
+          last = i + 1;
+          break;
+        case '&':
+          if (i > last) {
+            parts->Add(ReplacementPart::ReplacementSubString(last, i));
+          }
+          parts->Add(ReplacementPart::SubjectMatch());
+          i = next_index;
+          last = i + 1;
+          break;
+        case '0':
+        case '1':
+        case '2':
+        case '3':
+        case '4':
+        case '5':
+        case '6':
+        case '7':
+        case '8':
+        case '9': {
+          int capture_ref = c2 - '0';
+          if (capture_ref > capture_count) {
+            i = next_index;
+            continue;
+          }
+          int second_digit_index = next_index + 1;
+          if (second_digit_index < length) {
+            // Peek ahead to see if we have two digits.
+            Char c3 = characters[second_digit_index];
+            if ('0' <= c3 && c3 <= '9') {  // Double digits.
+              int double_digit_ref = capture_ref * 10 + c3 - '0';
+              if (double_digit_ref <= capture_count) {
+                next_index = second_digit_index;
+                capture_ref = double_digit_ref;
+              }
+            }
+          }
+          if (capture_ref > 0) {
+            if (i > last) {
+              parts->Add(ReplacementPart::ReplacementSubString(last, i));
+            }
+            parts->Add(ReplacementPart::SubjectCapture(capture_ref));
+            last = next_index + 1;
+          }
+          i = next_index;
+          break;
+        }
+        default:
+          i = next_index;
+          break;
+        }
+      }
+    }
+    if (length > last) {
+      if (last == 0) {
+        parts->Add(ReplacementPart::ReplacementString());
+      } else {
+        parts->Add(ReplacementPart::ReplacementSubString(last, length));
+      }
+    }
+  }
+
+  ZoneList<ReplacementPart> parts_;
+  ZoneList<Handle<String> > replacement_substrings_;
+};
+
+
+void CompiledReplacement::Compile(Handle<String> replacement,
+                                  int capture_count,
+                                  int subject_length) {
+  ASSERT(replacement->IsFlat());
+  if (StringShape(*replacement).IsAsciiRepresentation()) {
+    AssertNoAllocation no_alloc;
+    ParseReplacementPattern(&parts_,
+                            replacement->ToAsciiVector(),
+                            capture_count,
+                            subject_length);
+  } else {
+    ASSERT(StringShape(*replacement).IsTwoByteRepresentation());
+    AssertNoAllocation no_alloc;
+
+    ParseReplacementPattern(&parts_,
+                            replacement->ToUC16Vector(),
+                            capture_count,
+                            subject_length);
+  }
+  // Find substrings of replacement string and create them as String objects..
+  int substring_index = 0;
+  for (int i = 0, n = parts_.length(); i < n; i++) {
+    int tag = parts_[i].tag;
+    if (tag <= 0) {  // A replacement string slice.
+      int from = -tag;
+      int to = parts_[i].data;
+      replacement_substrings_.Add(Factory::NewStringSlice(replacement,
+                                                          from,
+                                                          to));
+      parts_[i].tag = REPLACEMENT_SUBSTRING;
+      parts_[i].data = substring_index;
+      substring_index++;
+    } else if (tag == REPLACEMENT_STRING) {
+      replacement_substrings_.Add(replacement);
+      parts_[i].data = substring_index;
+      substring_index++;
+    }
+  }
+}
+
+
+void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
+                                int match_from,
+                                int match_to,
+                                Handle<JSArray> last_match_info) {
+  for (int i = 0, n = parts_.length(); i < n; i++) {
+    ReplacementPart part = parts_[i];
+    switch (part.tag) {
+      case SUBJECT_PREFIX:
+        if (match_from > 0) builder->AddSubjectSlice(0, match_from);
+        break;
+      case SUBJECT_SUFFIX: {
+        int subject_length = part.data;
+        if (match_to < subject_length) {
+          builder->AddSubjectSlice(match_to, subject_length);
+        }
+        break;
+      }
+      case SUBJECT_CAPTURE: {
+        int capture = part.data;
+        FixedArray* match_info = last_match_info->elements();
+        int from = RegExpImpl::GetCapture(match_info, capture * 2);
+        int to = RegExpImpl::GetCapture(match_info, capture * 2 + 1);
+        if (from >= 0 && to > from) {
+          builder->AddSubjectSlice(from, to);
+        }
+        break;
+      }
+      case REPLACEMENT_SUBSTRING:
+      case REPLACEMENT_STRING:
+        builder->AddString(replacement_substrings_[part.data]);
+        break;
+      default:
+        UNREACHABLE();
+    }
+  }
+}
+
+
+
+static Object* StringReplaceRegExpWithString(String* subject,
+                                             JSRegExp* regexp,
+                                             String* replacement,
+                                             JSArray* last_match_info) {
+  ASSERT(subject->IsFlat());
+  ASSERT(replacement->IsFlat());
+
+  HandleScope handles;
+
+  int length = subject->length();
+  Handle<String> subject_handle(subject);
+  Handle<JSRegExp> regexp_handle(regexp);
+  Handle<String> replacement_handle(replacement);
+  Handle<JSArray> last_match_info_handle(last_match_info);
+  Handle<Object> match = RegExpImpl::Exec(regexp_handle,
+                                          subject_handle,
+                                          0,
+                                          last_match_info_handle);
+  if (match.is_null()) {
+    return Failure::Exception();
+  }
+  if (match->IsNull()) {
+    return *subject_handle;
+  }
+
+  int capture_count = regexp_handle->CaptureCount();
+
+  // CompiledReplacement uses zone allocation.
+  ZoneScope zone(DELETE_ON_EXIT);
+  CompiledReplacement compiled_replacement;
+  compiled_replacement.Compile(replacement_handle,
+                               capture_count,
+                               length);
+
+  bool is_global = regexp_handle->GetFlags().is_global();
+
+  // Guessing the number of parts that the final result string is built
+  // from. Global regexps can match any number of times, so we guess
+  // conservatively.
+  int expected_parts =
+      (compiled_replacement.parts() + 1) * (is_global ? 4 : 1) + 1;
+  ReplacementStringBuilder builder(subject_handle, expected_parts);
+
+  // Index of end of last match.
+  int prev = 0;
+
+  // Number of parts added by compiled replacement plus preceeding string
+  // and possibly suffix after last match.
+  const int parts_added_per_loop = compiled_replacement.parts() + 2;
+  bool matched = true;
+  do {
+    ASSERT(last_match_info_handle->HasFastElements());
+    // Increase the capacity of the builder before entering local handle-scope,
+    // so its internal buffer can safely allocate a new handle if it grows.
+    builder.EnsureCapacity(parts_added_per_loop);
+
+    HandleScope loop_scope;
+    int start, end;
+    {
+      AssertNoAllocation match_info_array_is_not_in_a_handle;
+      FixedArray* match_info_array = last_match_info_handle->elements();
+
+      ASSERT_EQ(capture_count * 2 + 2,
+                RegExpImpl::GetLastCaptureCount(match_info_array));
+      start = RegExpImpl::GetCapture(match_info_array, 0);
+      end = RegExpImpl::GetCapture(match_info_array, 1);
+    }
+
+    if (prev < start) {
+      builder.AddSubjectSlice(prev, start);
+    }
+    compiled_replacement.Apply(&builder,
+                               start,
+                               end,
+                               last_match_info_handle);
+    prev = end;
+
+    // Only continue checking for global regexps.
+    if (!is_global) break;
+
+    // Continue from where the match ended, unless it was an empty match.
+    int next = end;
+    if (start == end) {
+      next = end + 1;
+      if (next > length) break;
+    }
+
+    match = RegExpImpl::Exec(regexp_handle,
+                             subject_handle,
+                             next,
+                             last_match_info_handle);
+    if (match.is_null()) {
+      return Failure::Exception();
+    }
+    matched = !match->IsNull();
+  } while (matched);
+
+  if (prev < length) {
+    builder.AddSubjectSlice(prev, length);
+  }
+
+  return *(builder.ToString());
+}
+
+
+static Object* Runtime_StringReplaceRegExpWithString(Arguments args) {
+  ASSERT(args.length() == 4);
+
+  CONVERT_CHECKED(String, subject, args[0]);
+  if (!subject->IsFlat()) {
+    Object* flat_subject = subject->TryFlatten();
+    if (flat_subject->IsFailure()) {
+      return flat_subject;
+    }
+    subject = String::cast(flat_subject);
+  }
+
+  CONVERT_CHECKED(String, replacement, args[2]);
+  if (!replacement->IsFlat()) {
+    Object* flat_replacement = replacement->TryFlatten();
+    if (flat_replacement->IsFailure()) {
+      return flat_replacement;
+    }
+    replacement = String::cast(flat_replacement);
+  }
+
+  CONVERT_CHECKED(JSRegExp, regexp, args[1]);
+  CONVERT_CHECKED(JSArray, last_match_info, args[3]);
+
+  ASSERT(last_match_info->HasFastElements());
+
+  return StringReplaceRegExpWithString(subject,
+                                       regexp,
+                                       replacement,
+                                       last_match_info);
+}
+
+
+
+// Cap on the maximal shift in the Boyer-Moore implementation. By setting a
+// limit, we can fix the size of tables.
+static const int kBMMaxShift = 0xff;
+// Reduce alphabet to this size.
+static const int kBMAlphabetSize = 0x100;
+// For patterns below this length, the skip length of Boyer-Moore is too short
+// to compensate for the algorithmic overhead compared to simple brute force.
+static const int kBMMinPatternLength = 5;
+
+// Holds the two buffers used by Boyer-Moore string search's Good Suffix
+// shift. Only allows the last kBMMaxShift characters of the needle
+// to be indexed.
+class BMGoodSuffixBuffers {
+ public:
+  BMGoodSuffixBuffers() {}
+  inline void init(int needle_length) {
+    ASSERT(needle_length > 1);
+    int start = needle_length < kBMMaxShift ? 0 : needle_length - kBMMaxShift;
+    int len = needle_length - start;
+    biased_suffixes_ = suffixes_ - start;
+    biased_good_suffix_shift_ = good_suffix_shift_ - start;
+    for (int i = 0; i <= len; i++) {
+      good_suffix_shift_[i] = len;
+    }
+  }
+  inline int& suffix(int index) {
+    ASSERT(biased_suffixes_ + index >= suffixes_);
+    return biased_suffixes_[index];
+  }
+  inline int& shift(int index) {
+    ASSERT(biased_good_suffix_shift_ + index >= good_suffix_shift_);
+    return biased_good_suffix_shift_[index];
+  }
+ private:
+  int suffixes_[kBMMaxShift + 1];
+  int good_suffix_shift_[kBMMaxShift + 1];
+  int* biased_suffixes_;
+  int* biased_good_suffix_shift_;
+  DISALLOW_COPY_AND_ASSIGN(BMGoodSuffixBuffers);
+};
+
+// buffers reused by BoyerMoore
+static int bad_char_occurrence[kBMAlphabetSize];
+static BMGoodSuffixBuffers bmgs_buffers;
+
+// Compute the bad-char table for Boyer-Moore in the static buffer.
+template <typename pchar>
+static void BoyerMoorePopulateBadCharTable(Vector<const pchar> pattern,
+                                          int start) {
+  // Run forwards to populate bad_char_table, so that *last* instance
+  // of character equivalence class is the one registered.
+  // Notice: Doesn't include the last character.
+  int table_size = (sizeof(pchar) == 1) ? String::kMaxAsciiCharCode + 1
+                                        : kBMAlphabetSize;
+  if (start == 0) {  // All patterns less than kBMMaxShift in length.
+    memset(bad_char_occurrence, -1, table_size * sizeof(*bad_char_occurrence));
+  } else {
+    for (int i = 0; i < table_size; i++) {
+      bad_char_occurrence[i] = start - 1;
+    }
+  }
+  for (int i = start; i < pattern.length() - 1; i++) {
+    pchar c = pattern[i];
+    int bucket = (sizeof(pchar) ==1) ? c : c % kBMAlphabetSize;
+    bad_char_occurrence[bucket] = i;
+  }
+}
+
+template <typename pchar>
+static void BoyerMoorePopulateGoodSuffixTable(Vector<const pchar> pattern,
+                                              int start) {
+  int m = pattern.length();
+  int len = m - start;
+  // Compute Good Suffix tables.
+  bmgs_buffers.init(m);
+
+  bmgs_buffers.shift(m-1) = 1;
+  bmgs_buffers.suffix(m) = m + 1;
+  pchar last_char = pattern[m - 1];
+  int suffix = m + 1;
+  for (int i = m; i > start;) {
+    for (pchar c = pattern[i - 1]; suffix <= m && c != pattern[suffix - 1];) {
+      if (bmgs_buffers.shift(suffix) == len) {
+        bmgs_buffers.shift(suffix) = suffix - i;
+      }
+      suffix = bmgs_buffers.suffix(suffix);
+    }
+    i--;
+    suffix--;
+    bmgs_buffers.suffix(i) = suffix;
+    if (suffix == m) {
+      // No suffix to extend, so we check against last_char only.
+      while (i > start && pattern[i - 1] != last_char) {
+        if (bmgs_buffers.shift(m) == len) {
+          bmgs_buffers.shift(m) = m - i;
+        }
+        i--;
+        bmgs_buffers.suffix(i) = m;
+      }
+      if (i > start) {
+        i--;
+        suffix--;
+        bmgs_buffers.suffix(i) = suffix;
+      }
+    }
+  }
+  if (suffix < m) {
+    for (int i = start; i <= m; i++) {
+      if (bmgs_buffers.shift(i) == len) {
+        bmgs_buffers.shift(i) = suffix - start;
+      }
+      if (i == suffix) {
+        suffix = bmgs_buffers.suffix(suffix);
+      }
+    }
+  }
+}
+
+template <typename schar, typename pchar>
+static inline int CharOccurrence(int char_code) {
+  if (sizeof(schar) == 1) {
+    return bad_char_occurrence[char_code];
+  }
+  if (sizeof(pchar) == 1) {
+    if (char_code > String::kMaxAsciiCharCode) {
+      return -1;
+    }
+    return bad_char_occurrence[char_code];
+  }
+  return bad_char_occurrence[char_code % kBMAlphabetSize];
+}
+
+// Restricted simplified Boyer-Moore string matching.
+// Uses only the bad-shift table of Boyer-Moore and only uses it
+// for the character compared to the last character of the needle.
+template <typename schar, typename pchar>
+static int BoyerMooreHorspool(Vector<const schar> subject,
+                              Vector<const pchar> pattern,
+                              int start_index,
+                              bool* complete) {
+  int n = subject.length();
+  int m = pattern.length();
+  // Only preprocess at most kBMMaxShift last characters of pattern.
+  int start = m < kBMMaxShift ? 0 : m - kBMMaxShift;
+
+  BoyerMoorePopulateBadCharTable(pattern, start);
+
+  int badness = -m;  // How bad we are doing without a good-suffix table.
+  int idx;  // No matches found prior to this index.
+  pchar last_char = pattern[m - 1];
+  int last_char_shift = m - 1 - CharOccurrence<schar, pchar>(last_char);
+  // Perform search
+  for (idx = start_index; idx <= n - m;) {
+    int j = m - 1;
+    int c;
+    while (last_char != (c = subject[idx + j])) {
+      int bc_occ = CharOccurrence<schar, pchar>(c);
+      int shift = j - bc_occ;
+      idx += shift;
+      badness += 1 - shift;  // at most zero, so badness cannot increase.
+      if (idx > n - m) {
+        *complete = true;
+        return -1;
+      }
+    }
+    j--;
+    while (j >= 0 && pattern[j] == (subject[idx + j])) j--;
+    if (j < 0) {
+      *complete = true;
+      return idx;
+    } else {
+      idx += last_char_shift;
+      // Badness increases by the number of characters we have
+      // checked, and decreases by the number of characters we
+      // can skip by shifting. It's a measure of how we are doing
+      // compared to reading each character exactly once.
+      badness += (m - j) - last_char_shift;
+      if (badness > 0) {
+        *complete = false;
+        return idx;
+      }
+    }
+  }
+  *complete = true;
+  return -1;
+}
+
+
+template <typename schar, typename pchar>
+static int BoyerMooreIndexOf(Vector<const schar> subject,
+                             Vector<const pchar> pattern,
+                             int idx) {
+  int n = subject.length();
+  int m = pattern.length();
+  // Only preprocess at most kBMMaxShift last characters of pattern.
+  int start = m < kBMMaxShift ? 0 : m - kBMMaxShift;
+
+  // Build the Good Suffix table and continue searching.
+  BoyerMoorePopulateGoodSuffixTable(pattern, start);
+  pchar last_char = pattern[m - 1];
+  // Continue search from i.
+  do {
+    int j = m - 1;
+    schar c;
+    while (last_char != (c = subject[idx + j])) {
+      int shift = j - CharOccurrence<schar, pchar>(c);
+      idx += shift;
+      if (idx > n - m) {
+        return -1;
+      }
+    }
+    while (j >= 0 && pattern[j] == (c = subject[idx + j])) j--;
+    if (j < 0) {
+      return idx;
+    } else if (j < start) {
+      // we have matched more than our tables allow us to be smart about.
+      // Fall back on BMH shift.
+      idx += m - 1 - CharOccurrence<schar, pchar>(last_char);
+    } else {
+      int gs_shift = bmgs_buffers.shift(j + 1);       // Good suffix shift.
+      int bc_occ = CharOccurrence<schar, pchar>(c);
+      int shift = j - bc_occ;                         // Bad-char shift.
+      if (gs_shift > shift) {
+        shift = gs_shift;
+      }
+      idx += shift;
+    }
+  } while (idx <= n - m);
+
+  return -1;
+}
+
+
+template <typename schar>
+static int SingleCharIndexOf(Vector<const schar> string,
+                             schar pattern_char,
+                             int start_index) {
+  for (int i = start_index, n = string.length(); i < n; i++) {
+    if (pattern_char == string[i]) {
+      return i;
+    }
+  }
+  return -1;
+}
+
+// Trivial string search for shorter strings.
+// On return, if "complete" is set to true, the return value is the
+// final result of searching for the patter in the subject.
+// If "complete" is set to false, the return value is the index where
+// further checking should start, i.e., it's guaranteed that the pattern
+// does not occur at a position prior to the returned index.
+template <typename pchar, typename schar>
+static int SimpleIndexOf(Vector<const schar> subject,
+                         Vector<const pchar> pattern,
+                         int idx,
+                         bool* complete) {
+  // Badness is a count of how much work we have done.  When we have
+  // done enough work we decide it's probably worth switching to a better
+  // algorithm.
+  int badness = -10 - (pattern.length() << 2);
+  // We know our pattern is at least 2 characters, we cache the first so
+  // the common case of the first character not matching is faster.
+  pchar pattern_first_char = pattern[0];
+
+  for (int i = idx, n = subject.length() - pattern.length(); i <= n; i++) {
+    badness++;
+    if (badness > 0) {
+      *complete = false;
+      return i;
+    }
+    if (subject[i] != pattern_first_char) continue;
+    int j = 1;
+    do {
+      if (pattern[j] != subject[i+j]) {
+        break;
+      }
+      j++;
+    } while (j < pattern.length());
+    if (j == pattern.length()) {
+      *complete = true;
+      return i;
+    }
+    badness += j;
+  }
+  *complete = true;
+  return -1;
+}
+
+// Simple indexOf that never bails out. For short patterns only.
+template <typename pchar, typename schar>
+static int SimpleIndexOf(Vector<const schar> subject,
+                         Vector<const pchar> pattern,
+                         int idx) {
+  pchar pattern_first_char = pattern[0];
+  for (int i = idx, n = subject.length() - pattern.length(); i <= n; i++) {
+    if (subject[i] != pattern_first_char) continue;
+    int j = 1;
+    do {
+      if (pattern[j] != subject[i+j]) {
+        break;
+      }
+      j++;
+    } while (j < pattern.length());
+    if (j == pattern.length()) {
+      return i;
+    }
+  }
+  return -1;
+}
+
+
+// Dispatch to different algorithms.
+template <typename schar, typename pchar>
+static int StringMatchStrategy(Vector<const schar> sub,
+                               Vector<const pchar> pat,
+                               int start_index) {
+  ASSERT(pat.length() > 1);
+
+  // We have an ASCII haystack and a non-ASCII needle. Check if there
+  // really is a non-ASCII character in the needle and bail out if there
+  // is.
+  if (sizeof(pchar) > 1 && sizeof(schar) == 1) {
+    for (int i = 0; i < pat.length(); i++) {
+      uc16 c = pat[i];
+      if (c > String::kMaxAsciiCharCode) {
+        return -1;
+      }
+    }
+  }
+  if (pat.length() < kBMMinPatternLength) {
+    // We don't believe fancy searching can ever be more efficient.
+    // The max shift of Boyer-Moore on a pattern of this length does
+    // not compensate for the overhead.
+    return SimpleIndexOf(sub, pat, start_index);
+  }
+  // Try algorithms in order of increasing setup cost and expected performance.
+  bool complete;
+  int idx = SimpleIndexOf(sub, pat, start_index, &complete);
+  if (complete) return idx;
+  idx = BoyerMooreHorspool(sub, pat, idx, &complete);
+  if (complete) return idx;
+  return BoyerMooreIndexOf(sub, pat, idx);
+}
+
+// Perform string match of pattern on subject, starting at start index.
+// Caller must ensure that 0 <= start_index <= sub->length(),
+// and should check that pat->length() + start_index <= sub->length()
+int Runtime::StringMatch(Handle<String> sub,
+                         Handle<String> pat,
+                         int start_index) {
+  ASSERT(0 <= start_index);
+  ASSERT(start_index <= sub->length());
+
+  int pattern_length = pat->length();
+  if (pattern_length == 0) return start_index;
+
+  int subject_length = sub->length();
+  if (start_index + pattern_length > subject_length) return -1;
+
+  if (!sub->IsFlat()) {
+    FlattenString(sub);
+  }
+  // Searching for one specific character is common.  For one
+  // character patterns linear search is necessary, so any smart
+  // algorithm is unnecessary overhead.
+  if (pattern_length == 1) {
+    AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
+    if (StringShape(*sub).IsAsciiRepresentation()) {
+      uc16 pchar = pat->Get(0);
+      if (pchar > String::kMaxAsciiCharCode) {
+        return -1;
+      }
+      Vector<const char> ascii_vector =
+        sub->ToAsciiVector().SubVector(start_index, subject_length);
+      const void* pos = memchr(ascii_vector.start(),
+                               static_cast<const char>(pchar),
+                               static_cast<size_t>(ascii_vector.length()));
+      if (pos == NULL) {
+        return -1;
+      }
+      return reinterpret_cast<const char*>(pos) - ascii_vector.start()
+          + start_index;
+    }
+    return SingleCharIndexOf(sub->ToUC16Vector(), pat->Get(0), start_index);
+  }
+
+  if (!pat->IsFlat()) {
+    FlattenString(pat);
+  }
+
+  AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
+  // dispatch on type of strings
+  if (StringShape(*pat).IsAsciiRepresentation()) {
+    Vector<const char> pat_vector = pat->ToAsciiVector();
+    if (StringShape(*sub).IsAsciiRepresentation()) {
+      return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
+    }
+    return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
+  }
+  Vector<const uc16> pat_vector = pat->ToUC16Vector();
+  if (StringShape(*sub).IsAsciiRepresentation()) {
+    return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
+  }
+  return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
+}
+
+
+static Object* Runtime_StringIndexOf(Arguments args) {
+  HandleScope scope;  // create a new handle scope
+  ASSERT(args.length() == 3);
+
+  CONVERT_ARG_CHECKED(String, sub, 0);
+  CONVERT_ARG_CHECKED(String, pat, 1);
+
+  Object* index = args[2];
+  uint32_t start_index;
+  if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1);
+
+  RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
+  int position = Runtime::StringMatch(sub, pat, start_index);
+  return Smi::FromInt(position);
+}
+
+
+static Object* Runtime_StringLastIndexOf(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 3);
+
+  CONVERT_CHECKED(String, sub, args[0]);
+  CONVERT_CHECKED(String, pat, args[1]);
+  Object* index = args[2];
+
+  sub->TryFlattenIfNotFlat();
+  pat->TryFlattenIfNotFlat();
+
+  uint32_t start_index;
+  if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1);
+
+  uint32_t pattern_length = pat->length();
+  uint32_t sub_length = sub->length();
+
+  if (start_index + pattern_length > sub_length) {
+    start_index = sub_length - pattern_length;
+  }
+
+  for (int i = start_index; i >= 0; i--) {
+    bool found = true;
+    for (uint32_t j = 0; j < pattern_length; j++) {
+      if (sub->Get(i + j) != pat->Get(j)) {
+        found = false;
+        break;
+      }
+    }
+    if (found) return Smi::FromInt(i);
+  }
+
+  return Smi::FromInt(-1);
+}
+
+
+static Object* Runtime_StringLocaleCompare(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_CHECKED(String, str1, args[0]);
+  CONVERT_CHECKED(String, str2, args[1]);
+
+  if (str1 == str2) return Smi::FromInt(0);  // Equal.
+  int str1_length = str1->length();
+  int str2_length = str2->length();
+
+  // Decide trivial cases without flattening.
+  if (str1_length == 0) {
+    if (str2_length == 0) return Smi::FromInt(0);  // Equal.
+    return Smi::FromInt(-str2_length);
+  } else {
+    if (str2_length == 0) return Smi::FromInt(str1_length);
+  }
+
+  int end = str1_length < str2_length ? str1_length : str2_length;
+
+  // No need to flatten if we are going to find the answer on the first
+  // character.  At this point we know there is at least one character
+  // in each string, due to the trivial case handling above.
+  int d = str1->Get(0) - str2->Get(0);
+  if (d != 0) return Smi::FromInt(d);
+
+  str1->TryFlattenIfNotFlat();
+  str2->TryFlattenIfNotFlat();
+
+  static StringInputBuffer buf1;
+  static StringInputBuffer buf2;
+
+  buf1.Reset(str1);
+  buf2.Reset(str2);
+
+  for (int i = 0; i < end; i++) {
+    uint16_t char1 = buf1.GetNext();
+    uint16_t char2 = buf2.GetNext();
+    if (char1 != char2) return Smi::FromInt(char1 - char2);
+  }
+
+  return Smi::FromInt(str1_length - str2_length);
+}
+
+
+static Object* Runtime_StringSlice(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 3);
+
+  CONVERT_CHECKED(String, value, args[0]);
+  CONVERT_DOUBLE_CHECKED(from_number, args[1]);
+  CONVERT_DOUBLE_CHECKED(to_number, args[2]);
+
+  int start = FastD2I(from_number);
+  int end = FastD2I(to_number);
+
+  RUNTIME_ASSERT(end >= start);
+  RUNTIME_ASSERT(start >= 0);
+  RUNTIME_ASSERT(end <= value->length());
+  return value->Slice(start, end);
+}
+
+
+static Object* Runtime_StringMatch(Arguments args) {
+  ASSERT_EQ(3, args.length());
+
+  CONVERT_ARG_CHECKED(String, subject, 0);
+  CONVERT_ARG_CHECKED(JSRegExp, regexp, 1);
+  CONVERT_ARG_CHECKED(JSArray, regexp_info, 2);
+  HandleScope handles;
+
+  Handle<Object> match = RegExpImpl::Exec(regexp, subject, 0, regexp_info);
+
+  if (match.is_null()) {
+    return Failure::Exception();
+  }
+  if (match->IsNull()) {
+    return Heap::null_value();
+  }
+  int length = subject->length();
+
+  ZoneScope zone_space(DELETE_ON_EXIT);
+  ZoneList<int> offsets(8);
+  do {
+    int start;
+    int end;
+    {
+      AssertNoAllocation no_alloc;
+      FixedArray* elements = regexp_info->elements();
+      start = Smi::cast(elements->get(RegExpImpl::kFirstCapture))->value();
+      end = Smi::cast(elements->get(RegExpImpl::kFirstCapture + 1))->value();
+    }
+    offsets.Add(start);
+    offsets.Add(end);
+    int index = start < end ? end : end + 1;
+    if (index > length) break;
+    match = RegExpImpl::Exec(regexp, subject, index, regexp_info);
+    if (match.is_null()) {
+      return Failure::Exception();
+    }
+  } while (!match->IsNull());
+  int matches = offsets.length() / 2;
+  Handle<FixedArray> elements = Factory::NewFixedArray(matches);
+  for (int i = 0; i < matches ; i++) {
+    int from = offsets.at(i * 2);
+    int to = offsets.at(i * 2 + 1);
+    elements->set(i, *Factory::NewStringSlice(subject, from, to));
+  }
+  Handle<JSArray> result = Factory::NewJSArrayWithElements(elements);
+  result->set_length(Smi::FromInt(matches));
+  return *result;
+}
+
+
+static Object* Runtime_NumberToRadixString(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_DOUBLE_CHECKED(value, args[0]);
+  if (isnan(value)) {
+    return Heap::AllocateStringFromAscii(CStrVector("NaN"));
+  }
+  if (isinf(value)) {
+    if (value < 0) {
+      return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
+    }
+    return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
+  }
+  CONVERT_DOUBLE_CHECKED(radix_number, args[1]);
+  int radix = FastD2I(radix_number);
+  RUNTIME_ASSERT(2 <= radix && radix <= 36);
+  char* str = DoubleToRadixCString(value, radix);
+  Object* result = Heap::AllocateStringFromAscii(CStrVector(str));
+  DeleteArray(str);
+  return result;
+}
+
+
+static Object* Runtime_NumberToFixed(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_DOUBLE_CHECKED(value, args[0]);
+  if (isnan(value)) {
+    return Heap::AllocateStringFromAscii(CStrVector("NaN"));
+  }
+  if (isinf(value)) {
+    if (value < 0) {
+      return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
+    }
+    return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
+  }
+  CONVERT_DOUBLE_CHECKED(f_number, args[1]);
+  int f = FastD2I(f_number);
+  RUNTIME_ASSERT(f >= 0);
+  char* str = DoubleToFixedCString(value, f);
+  Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
+  DeleteArray(str);
+  return res;
+}
+
+
+static Object* Runtime_NumberToExponential(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_DOUBLE_CHECKED(value, args[0]);
+  if (isnan(value)) {
+    return Heap::AllocateStringFromAscii(CStrVector("NaN"));
+  }
+  if (isinf(value)) {
+    if (value < 0) {
+      return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
+    }
+    return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
+  }
+  CONVERT_DOUBLE_CHECKED(f_number, args[1]);
+  int f = FastD2I(f_number);
+  RUNTIME_ASSERT(f >= -1 && f <= 20);
+  char* str = DoubleToExponentialCString(value, f);
+  Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
+  DeleteArray(str);
+  return res;
+}
+
+
+static Object* Runtime_NumberToPrecision(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_DOUBLE_CHECKED(value, args[0]);
+  if (isnan(value)) {
+    return Heap::AllocateStringFromAscii(CStrVector("NaN"));
+  }
+  if (isinf(value)) {
+    if (value < 0) {
+      return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
+    }
+    return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
+  }
+  CONVERT_DOUBLE_CHECKED(f_number, args[1]);
+  int f = FastD2I(f_number);
+  RUNTIME_ASSERT(f >= 1 && f <= 21);
+  char* str = DoubleToPrecisionCString(value, f);
+  Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
+  DeleteArray(str);
+  return res;
+}
+
+
+// Returns a single character string where first character equals
+// string->Get(index).
+static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
+  if (index < static_cast<uint32_t>(string->length())) {
+    string->TryFlattenIfNotFlat();
+    return LookupSingleCharacterStringFromCode(
+        string->Get(index));
+  }
+  return Execution::CharAt(string, index);
+}
+
+
+Object* Runtime::GetElementOrCharAt(Handle<Object> object, uint32_t index) {
+  // Handle [] indexing on Strings
+  if (object->IsString()) {
+    Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
+    if (!result->IsUndefined()) return *result;
+  }
+
+  // Handle [] indexing on String objects
+  if (object->IsStringObjectWithCharacterAt(index)) {
+    Handle<JSValue> js_value = Handle<JSValue>::cast(object);
+    Handle<Object> result =
+        GetCharAt(Handle<String>(String::cast(js_value->value())), index);
+    if (!result->IsUndefined()) return *result;
+  }
+
+  if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
+    Handle<Object> prototype = GetPrototype(object);
+    return prototype->GetElement(index);
+  }
+
+  return object->GetElement(index);
+}
+
+
+Object* Runtime::GetObjectProperty(Handle<Object> object, Handle<Object> key) {
+  HandleScope scope;
+
+  if (object->IsUndefined() || object->IsNull()) {
+    Handle<Object> args[2] = { key, object };
+    Handle<Object> error =
+        Factory::NewTypeError("non_object_property_load",
+                              HandleVector(args, 2));
+    return Top::Throw(*error);
+  }
+
+  // Check if the given key is an array index.
+  uint32_t index;
+  if (Array::IndexFromObject(*key, &index)) {
+    return GetElementOrCharAt(object, index);
+  }
+
+  // Convert the key to a string - possibly by calling back into JavaScript.
+  Handle<String> name;
+  if (key->IsString()) {
+    name = Handle<String>::cast(key);
+  } else {
+    bool has_pending_exception = false;
+    Handle<Object> converted =
+        Execution::ToString(key, &has_pending_exception);
+    if (has_pending_exception) return Failure::Exception();
+    name = Handle<String>::cast(converted);
+  }
+
+  // Check if the name is trivially convertible to an index and get
+  // the element if so.
+  if (name->AsArrayIndex(&index)) {
+    return GetElementOrCharAt(object, index);
+  } else {
+    PropertyAttributes attr;
+    return object->GetProperty(*name, &attr);
+  }
+}
+
+
+static Object* Runtime_GetProperty(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  Handle<Object> object = args.at<Object>(0);
+  Handle<Object> key = args.at<Object>(1);
+
+  return Runtime::GetObjectProperty(object, key);
+}
+
+
+
+// KeyedStringGetProperty is called from KeyedLoadIC::GenerateGeneric.
+static Object* Runtime_KeyedGetProperty(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  // Fast cases for getting named properties of the receiver JSObject
+  // itself.
+  //
+  // The global proxy objects has to be excluded since LocalLookup on
+  // the global proxy object can return a valid result even though the
+  // global proxy object never has properties.  This is the case
+  // because the global proxy object forwards everything to its hidden
+  // prototype including local lookups.
+  //
+  // Additionally, we need to make sure that we do not cache results
+  // for objects that require access checks.
+  if (args[0]->IsJSObject() &&
+      !args[0]->IsJSGlobalProxy() &&
+      !args[0]->IsAccessCheckNeeded() &&
+      args[1]->IsString()) {
+    JSObject* receiver = JSObject::cast(args[0]);
+    String* key = String::cast(args[1]);
+    if (receiver->HasFastProperties()) {
+      // Attempt to use lookup cache.
+      Object* obj = Heap::GetKeyedLookupCache();
+      if (obj->IsFailure()) return obj;
+      LookupCache* cache = LookupCache::cast(obj);
+      Map* receiver_map = receiver->map();
+      int offset = cache->Lookup(receiver_map, key);
+      if (offset != LookupCache::kNotFound) {
+        Object* value = receiver->FastPropertyAt(offset);
+        return value->IsTheHole() ? Heap::undefined_value() : value;
+      }
+      // Lookup cache miss.  Perform lookup and update the cache if
+      // appropriate.
+      LookupResult result;
+      receiver->LocalLookup(key, &result);
+      if (result.IsProperty() && result.IsLoaded() && result.type() == FIELD) {
+        int offset = result.GetFieldIndex();
+        Object* obj = cache->Put(receiver_map, key, offset);
+        if (obj->IsFailure()) return obj;
+        Heap::SetKeyedLookupCache(LookupCache::cast(obj));
+        Object* value = receiver->FastPropertyAt(offset);
+        return value->IsTheHole() ? Heap::undefined_value() : value;
+      }
+    } else {
+      // Attempt dictionary lookup.
+      Dictionary* dictionary = receiver->property_dictionary();
+      int entry = dictionary->FindStringEntry(key);
+      if ((entry != DescriptorArray::kNotFound) &&
+          (dictionary->DetailsAt(entry).type() == NORMAL)) {
+        return dictionary->ValueAt(entry);
+      }
+    }
+  }
+
+  // Fall back to GetObjectProperty.
+  return Runtime::GetObjectProperty(args.at<Object>(0),
+                                    args.at<Object>(1));
+}
+
+
+Object* Runtime::SetObjectProperty(Handle<Object> object,
+                                   Handle<Object> key,
+                                   Handle<Object> value,
+                                   PropertyAttributes attr) {
+  HandleScope scope;
+
+  if (object->IsUndefined() || object->IsNull()) {
+    Handle<Object> args[2] = { key, object };
+    Handle<Object> error =
+        Factory::NewTypeError("non_object_property_store",
+                              HandleVector(args, 2));
+    return Top::Throw(*error);
+  }
+
+  // If the object isn't a JavaScript object, we ignore the store.
+  if (!object->IsJSObject()) return *value;
+
+  Handle<JSObject> js_object = Handle<JSObject>::cast(object);
+
+  // Check if the given key is an array index.
+  uint32_t index;
+  if (Array::IndexFromObject(*key, &index)) {
+    ASSERT(attr == NONE);
+
+    // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
+    // of a string using [] notation.  We need to support this too in
+    // JavaScript.
+    // In the case of a String object we just need to redirect the assignment to
+    // the underlying string if the index is in range.  Since the underlying
+    // string does nothing with the assignment then we can ignore such
+    // assignments.
+    if (js_object->IsStringObjectWithCharacterAt(index)) {
+      return *value;
+    }
+
+    Handle<Object> result = SetElement(js_object, index, value);
+    if (result.is_null()) return Failure::Exception();
+    return *value;
+  }
+
+  if (key->IsString()) {
+    Handle<Object> result;
+    if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
+      ASSERT(attr == NONE);
+      result = SetElement(js_object, index, value);
+    } else {
+      Handle<String> key_string = Handle<String>::cast(key);
+      key_string->TryFlattenIfNotFlat();
+      result = SetProperty(js_object, key_string, value, attr);
+    }
+    if (result.is_null()) return Failure::Exception();
+    return *value;
+  }
+
+  // Call-back into JavaScript to convert the key to a string.
+  bool has_pending_exception = false;
+  Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
+  if (has_pending_exception) return Failure::Exception();
+  Handle<String> name = Handle<String>::cast(converted);
+
+  if (name->AsArrayIndex(&index)) {
+    ASSERT(attr == NONE);
+    return js_object->SetElement(index, *value);
+  } else {
+    return js_object->SetProperty(*name, *value, attr);
+  }
+}
+
+
+static Object* Runtime_SetProperty(Arguments args) {
+  NoHandleAllocation ha;
+  RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
+
+  Handle<Object> object = args.at<Object>(0);
+  Handle<Object> key = args.at<Object>(1);
+  Handle<Object> value = args.at<Object>(2);
+
+  // Compute attributes.
+  PropertyAttributes attributes = NONE;
+  if (args.length() == 4) {
+    CONVERT_CHECKED(Smi, value_obj, args[3]);
+    int unchecked_value = value_obj->value();
+    // Only attribute bits should be set.
+    RUNTIME_ASSERT(
+        (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
+    attributes = static_cast<PropertyAttributes>(unchecked_value);
+  }
+  return Runtime::SetObjectProperty(object, key, value, attributes);
+}
+
+
+// Set a local property, even if it is READ_ONLY.  If the property does not
+// exist, it will be added with attributes NONE.
+static Object* Runtime_IgnoreAttributesAndSetProperty(Arguments args) {
+  NoHandleAllocation ha;
+  RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
+  CONVERT_CHECKED(JSObject, object, args[0]);
+  CONVERT_CHECKED(String, name, args[1]);
+  // Compute attributes.
+  PropertyAttributes attributes = NONE;
+  if (args.length() == 4) {
+    CONVERT_CHECKED(Smi, value_obj, args[3]);
+    int unchecked_value = value_obj->value();
+    // Only attribute bits should be set.
+    RUNTIME_ASSERT(
+        (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
+    attributes = static_cast<PropertyAttributes>(unchecked_value);
+  }
+
+  return object->
+      IgnoreAttributesAndSetLocalProperty(name, args[2], attributes);
+}
+
+
+static Object* Runtime_DeleteProperty(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_CHECKED(JSObject, object, args[0]);
+  CONVERT_CHECKED(String, key, args[1]);
+  return object->DeleteProperty(key);
+}
+
+
+static Object* Runtime_HasLocalProperty(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+  CONVERT_CHECKED(String, key, args[1]);
+
+  // Only JS objects can have properties.
+  if (args[0]->IsJSObject()) {
+    JSObject* object = JSObject::cast(args[0]);
+    if (object->HasLocalProperty(key)) return Heap::true_value();
+  } else if (args[0]->IsString()) {
+    // Well, there is one exception:  Handle [] on strings.
+    uint32_t index;
+    if (key->AsArrayIndex(&index)) {
+      String* string = String::cast(args[0]);
+      if (index < static_cast<uint32_t>(string->length()))
+        return Heap::true_value();
+    }
+  }
+  return Heap::false_value();
+}
+
+
+static Object* Runtime_HasProperty(Arguments args) {
+  NoHandleAllocation na;
+  ASSERT(args.length() == 2);
+
+  // Only JS objects can have properties.
+  if (args[0]->IsJSObject()) {
+    JSObject* object = JSObject::cast(args[0]);
+    CONVERT_CHECKED(String, key, args[1]);
+    if (object->HasProperty(key)) return Heap::true_value();
+  }
+  return Heap::false_value();
+}
+
+
+static Object* Runtime_HasElement(Arguments args) {
+  NoHandleAllocation na;
+  ASSERT(args.length() == 2);
+
+  // Only JS objects can have elements.
+  if (args[0]->IsJSObject()) {
+    JSObject* object = JSObject::cast(args[0]);
+    CONVERT_CHECKED(Smi, index_obj, args[1]);
+    uint32_t index = index_obj->value();
+    if (object->HasElement(index)) return Heap::true_value();
+  }
+  return Heap::false_value();
+}
+
+
+static Object* Runtime_IsPropertyEnumerable(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_CHECKED(JSObject, object, args[0]);
+  CONVERT_CHECKED(String, key, args[1]);
+
+  uint32_t index;
+  if (key->AsArrayIndex(&index)) {
+    return Heap::ToBoolean(object->HasElement(index));
+  }
+
+  PropertyAttributes att = object->GetLocalPropertyAttribute(key);
+  return Heap::ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0);
+}
+
+
+static Object* Runtime_GetPropertyNames(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+
+  CONVERT_CHECKED(JSObject, raw_object, args[0]);
+  Handle<JSObject> object(raw_object);
+  return *GetKeysFor(object);
+}
+
+
+// Returns either a FixedArray as Runtime_GetPropertyNames,
+// or, if the given object has an enum cache that contains
+// all enumerable properties of the object and its prototypes
+// have none, the map of the object. This is used to speed up
+// the check for deletions during a for-in.
+static Object* Runtime_GetPropertyNamesFast(Arguments args) {
+  ASSERT(args.length() == 1);
+
+  CONVERT_CHECKED(JSObject, raw_object, args[0]);
+
+  if (raw_object->IsSimpleEnum()) return raw_object->map();
+
+  HandleScope scope;
+  Handle<JSObject> object(raw_object);
+  Handle<FixedArray> content = GetKeysInFixedArrayFor(object);
+
+  // Test again, since cache may have been built by preceding call.
+  if (object->IsSimpleEnum()) return object->map();
+
+  return *content;
+}
+
+
+static Object* Runtime_GetArgumentsProperty(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  // Compute the frame holding the arguments.
+  JavaScriptFrameIterator it;
+  it.AdvanceToArgumentsFrame();
+  JavaScriptFrame* frame = it.frame();
+
+  // Get the actual number of provided arguments.
+  const uint32_t n = frame->GetProvidedParametersCount();
+
+  // Try to convert the key to an index. If successful and within
+  // index return the the argument from the frame.
+  uint32_t index;
+  if (Array::IndexFromObject(args[0], &index) && index < n) {
+    return frame->GetParameter(index);
+  }
+
+  // Convert the key to a string.
+  HandleScope scope;
+  bool exception = false;
+  Handle<Object> converted =
+      Execution::ToString(args.at<Object>(0), &exception);
+  if (exception) return Failure::Exception();
+  Handle<String> key = Handle<String>::cast(converted);
+
+  // Try to convert the string key into an array index.
+  if (key->AsArrayIndex(&index)) {
+    if (index < n) {
+      return frame->GetParameter(index);
+    } else {
+      return Top::initial_object_prototype()->GetElement(index);
+    }
+  }
+
+  // Handle special arguments properties.
+  if (key->Equals(Heap::length_symbol())) return Smi::FromInt(n);
+  if (key->Equals(Heap::callee_symbol())) return frame->function();
+
+  // Lookup in the initial Object.prototype object.
+  return Top::initial_object_prototype()->GetProperty(*key);
+}
+
+
+static Object* Runtime_ToFastProperties(Arguments args) {
+  ASSERT(args.length() == 1);
+  Handle<Object> object = args.at<Object>(0);
+  if (object->IsJSObject()) {
+    Handle<JSObject> js_object = Handle<JSObject>::cast(object);
+    js_object->TransformToFastProperties(0);
+  }
+  return *object;
+}
+
+
+static Object* Runtime_ToSlowProperties(Arguments args) {
+  ASSERT(args.length() == 1);
+  Handle<Object> object = args.at<Object>(0);
+  if (object->IsJSObject()) {
+    Handle<JSObject> js_object = Handle<JSObject>::cast(object);
+    js_object->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
+  }
+  return *object;
+}
+
+
+static Object* Runtime_ToBool(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  return args[0]->ToBoolean();
+}
+
+
+// Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
+// Possible optimizations: put the type string into the oddballs.
+static Object* Runtime_Typeof(Arguments args) {
+  NoHandleAllocation ha;
+
+  Object* obj = args[0];
+  if (obj->IsNumber()) return Heap::number_symbol();
+  HeapObject* heap_obj = HeapObject::cast(obj);
+
+  // typeof an undetectable object is 'undefined'
+  if (heap_obj->map()->is_undetectable()) return Heap::undefined_symbol();
+
+  InstanceType instance_type = heap_obj->map()->instance_type();
+  if (instance_type < FIRST_NONSTRING_TYPE) {
+    return Heap::string_symbol();
+  }
+
+  switch (instance_type) {
+    case ODDBALL_TYPE:
+      if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
+        return Heap::boolean_symbol();
+      }
+      if (heap_obj->IsNull()) {
+        return Heap::object_symbol();
+      }
+      ASSERT(heap_obj->IsUndefined());
+      return Heap::undefined_symbol();
+    case JS_FUNCTION_TYPE:
+      return Heap::function_symbol();
+    default:
+      // For any kind of object not handled above, the spec rule for
+      // host objects gives that it is okay to return "object"
+      return Heap::object_symbol();
+  }
+}
+
+
+static Object* Runtime_StringToNumber(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+  CONVERT_CHECKED(String, subject, args[0]);
+  subject->TryFlattenIfNotFlat();
+  return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX));
+}
+
+
+static Object* Runtime_StringFromCharCodeArray(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_CHECKED(JSArray, codes, args[0]);
+  int length = Smi::cast(codes->length())->value();
+
+  // Check if the string can be ASCII.
+  int i;
+  for (i = 0; i < length; i++) {
+    Object* element = codes->GetElement(i);
+    CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
+    if ((chr & 0xffff) > String::kMaxAsciiCharCode)
+      break;
+  }
+
+  Object* object = NULL;
+  if (i == length) {  // The string is ASCII.
+    object = Heap::AllocateRawAsciiString(length);
+  } else {  // The string is not ASCII.
+    object = Heap::AllocateRawTwoByteString(length);
+  }
+
+  if (object->IsFailure()) return object;
+  String* result = String::cast(object);
+  for (int i = 0; i < length; i++) {
+    Object* element = codes->GetElement(i);
+    CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
+    result->Set(i, chr & 0xffff);
+  }
+  return result;
+}
+
+
+// kNotEscaped is generated by the following:
+//
+// #!/bin/perl
+// for (my $i = 0; $i < 256; $i++) {
+//   print "\n" if $i % 16 == 0;
+//   my $c = chr($i);
+//   my $escaped = 1;
+//   $escaped = 0 if $c =~ m#[A-Za-z0-9@*_+./-]#;
+//   print $escaped ? "0, " : "1, ";
+// }
+
+
+static bool IsNotEscaped(uint16_t character) {
+  // Only for 8 bit characters, the rest are always escaped (in a different way)
+  ASSERT(character < 256);
+  static const char kNotEscaped[256] = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
+    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  };
+  return kNotEscaped[character] != 0;
+}
+
+
+static Object* Runtime_URIEscape(Arguments args) {
+  const char hex_chars[] = "0123456789ABCDEF";
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+  CONVERT_CHECKED(String, source, args[0]);
+
+  source->TryFlattenIfNotFlat();
+
+  int escaped_length = 0;
+  int length = source->length();
+  {
+    Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
+    buffer->Reset(source);
+    while (buffer->has_more()) {
+      uint16_t character = buffer->GetNext();
+      if (character >= 256) {
+        escaped_length += 6;
+      } else if (IsNotEscaped(character)) {
+        escaped_length++;
+      } else {
+        escaped_length += 3;
+      }
+      // We don't allow strings that are longer than Smi range.
+      if (!Smi::IsValid(escaped_length)) {
+        Top::context()->mark_out_of_memory();
+        return Failure::OutOfMemoryException();
+      }
+    }
+  }
+  // No length change implies no change.  Return original string if no change.
+  if (escaped_length == length) {
+    return source;
+  }
+  Object* o = Heap::AllocateRawAsciiString(escaped_length);
+  if (o->IsFailure()) return o;
+  String* destination = String::cast(o);
+  int dest_position = 0;
+
+  Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
+  buffer->Rewind();
+  while (buffer->has_more()) {
+    uint16_t chr = buffer->GetNext();
+    if (chr >= 256) {
+      destination->Set(dest_position, '%');
+      destination->Set(dest_position+1, 'u');
+      destination->Set(dest_position+2, hex_chars[chr >> 12]);
+      destination->Set(dest_position+3, hex_chars[(chr >> 8) & 0xf]);
+      destination->Set(dest_position+4, hex_chars[(chr >> 4) & 0xf]);
+      destination->Set(dest_position+5, hex_chars[chr & 0xf]);
+      dest_position += 6;
+    } else if (IsNotEscaped(chr)) {
+      destination->Set(dest_position, chr);
+      dest_position++;
+    } else {
+      destination->Set(dest_position, '%');
+      destination->Set(dest_position+1, hex_chars[chr >> 4]);
+      destination->Set(dest_position+2, hex_chars[chr & 0xf]);
+      dest_position += 3;
+    }
+  }
+  return destination;
+}
+
+
+static inline int TwoDigitHex(uint16_t character1, uint16_t character2) {
+  static const signed char kHexValue['g'] = {
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    0,  1,  2,   3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
+    -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, 10, 11, 12, 13, 14, 15 };
+
+  if (character1 > 'f') return -1;
+  int hi = kHexValue[character1];
+  if (hi == -1) return -1;
+  if (character2 > 'f') return -1;
+  int lo = kHexValue[character2];
+  if (lo == -1) return -1;
+  return (hi << 4) + lo;
+}
+
+
+static inline int Unescape(String* source,
+                           int i,
+                           int length,
+                           int* step) {
+  uint16_t character = source->Get(i);
+  int32_t hi = 0;
+  int32_t lo = 0;
+  if (character == '%' &&
+      i <= length - 6 &&
+      source->Get(i + 1) == 'u' &&
+      (hi = TwoDigitHex(source->Get(i + 2),
+                        source->Get(i + 3))) != -1 &&
+      (lo = TwoDigitHex(source->Get(i + 4),
+                        source->Get(i + 5))) != -1) {
+    *step = 6;
+    return (hi << 8) + lo;
+  } else if (character == '%' &&
+      i <= length - 3 &&
+      (lo = TwoDigitHex(source->Get(i + 1),
+                        source->Get(i + 2))) != -1) {
+    *step = 3;
+    return lo;
+  } else {
+    *step = 1;
+    return character;
+  }
+}
+
+
+static Object* Runtime_URIUnescape(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+  CONVERT_CHECKED(String, source, args[0]);
+
+  source->TryFlattenIfNotFlat();
+
+  bool ascii = true;
+  int length = source->length();
+
+  int unescaped_length = 0;
+  for (int i = 0; i < length; unescaped_length++) {
+    int step;
+    if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode) {
+      ascii = false;
+    }
+    i += step;
+  }
+
+  // No length change implies no change.  Return original string if no change.
+  if (unescaped_length == length)
+    return source;
+
+  Object* o = ascii ?
+              Heap::AllocateRawAsciiString(unescaped_length) :
+              Heap::AllocateRawTwoByteString(unescaped_length);
+  if (o->IsFailure()) return o;
+  String* destination = String::cast(o);
+
+  int dest_position = 0;
+  for (int i = 0; i < length; dest_position++) {
+    int step;
+    destination->Set(dest_position, Unescape(source, i, length, &step));
+    i += step;
+  }
+  return destination;
+}
+
+
+static Object* Runtime_StringParseInt(Arguments args) {
+  NoHandleAllocation ha;
+
+  CONVERT_CHECKED(String, s, args[0]);
+  CONVERT_DOUBLE_CHECKED(n, args[1]);
+  int radix = FastD2I(n);
+
+  s->TryFlattenIfNotFlat();
+
+  int len = s->length();
+  int i;
+
+  // Skip leading white space.
+  for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(i)); i++) ;
+  if (i == len) return Heap::nan_value();
+
+  // Compute the sign (default to +).
+  int sign = 1;
+  if (s->Get(i) == '-') {
+    sign = -1;
+    i++;
+  } else if (s->Get(i) == '+') {
+    i++;
+  }
+
+  // Compute the radix if 0.
+  if (radix == 0) {
+    radix = 10;
+    if (i < len && s->Get(i) == '0') {
+      radix = 8;
+      if (i + 1 < len) {
+        int c = s->Get(i + 1);
+        if (c == 'x' || c == 'X') {
+          radix = 16;
+          i += 2;
+        }
+      }
+    }
+  } else if (radix == 16) {
+    // Allow 0x or 0X prefix if radix is 16.
+    if (i + 1 < len && s->Get(i) == '0') {
+      int c = s->Get(i + 1);
+      if (c == 'x' || c == 'X') i += 2;
+    }
+  }
+
+  RUNTIME_ASSERT(2 <= radix && radix <= 36);
+  double value;
+  int end_index = StringToInt(s, i, radix, &value);
+  if (end_index != i) {
+    return Heap::NumberFromDouble(sign * value);
+  }
+  return Heap::nan_value();
+}
+
+
+static Object* Runtime_StringParseFloat(Arguments args) {
+  NoHandleAllocation ha;
+  CONVERT_CHECKED(String, str, args[0]);
+
+  // ECMA-262 section 15.1.2.3, empty string is NaN
+  double value = StringToDouble(str, ALLOW_TRAILING_JUNK, OS::nan_value());
+
+  // Create a number object from the value.
+  return Heap::NumberFromDouble(value);
+}
+
+
+static unibrow::Mapping<unibrow::ToUppercase, 128> to_upper_mapping;
+static unibrow::Mapping<unibrow::ToLowercase, 128> to_lower_mapping;
+
+
+template <class Converter>
+static Object* ConvertCaseHelper(String* s,
+                                 int length,
+                                 int input_string_length,
+                                 unibrow::Mapping<Converter, 128>* mapping) {
+  // We try this twice, once with the assumption that the result is no longer
+  // than the input and, if that assumption breaks, again with the exact
+  // length.  This may not be pretty, but it is nicer than what was here before
+  // and I hereby claim my vaffel-is.
+  //
+  // Allocate the resulting string.
+  //
+  // NOTE: This assumes that the upper/lower case of an ascii
+  // character is also ascii.  This is currently the case, but it
+  // might break in the future if we implement more context and locale
+  // dependent upper/lower conversions.
+  Object* o = StringShape(s).IsAsciiRepresentation()
+      ? Heap::AllocateRawAsciiString(length)
+      : Heap::AllocateRawTwoByteString(length);
+  if (o->IsFailure()) return o;
+  String* result = String::cast(o);
+  bool has_changed_character = false;
+
+  // Convert all characters to upper case, assuming that they will fit
+  // in the buffer
+  Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
+  buffer->Reset(s);
+  unibrow::uchar chars[Converter::kMaxWidth];
+  // We can assume that the string is not empty
+  uc32 current = buffer->GetNext();
+  for (int i = 0; i < length;) {
+    bool has_next = buffer->has_more();
+    uc32 next = has_next ? buffer->GetNext() : 0;
+    int char_length = mapping->get(current, next, chars);
+    if (char_length == 0) {
+      // The case conversion of this character is the character itself.
+      result->Set(i, current);
+      i++;
+    } else if (char_length == 1) {
+      // Common case: converting the letter resulted in one character.
+      ASSERT(static_cast<uc32>(chars[0]) != current);
+      result->Set(i, chars[0]);
+      has_changed_character = true;
+      i++;
+    } else if (length == input_string_length) {
+      // We've assumed that the result would be as long as the
+      // input but here is a character that converts to several
+      // characters.  No matter, we calculate the exact length
+      // of the result and try the whole thing again.
+      //
+      // Note that this leaves room for optimization.  We could just
+      // memcpy what we already have to the result string.  Also,
+      // the result string is the last object allocated we could
+      // "realloc" it and probably, in the vast majority of cases,
+      // extend the existing string to be able to hold the full
+      // result.
+      int next_length = 0;
+      if (has_next) {
+        next_length = mapping->get(next, 0, chars);
+        if (next_length == 0) next_length = 1;
+      }
+      int current_length = i + char_length + next_length;
+      while (buffer->has_more()) {
+        current = buffer->GetNext();
+        // NOTE: we use 0 as the next character here because, while
+        // the next character may affect what a character converts to,
+        // it does not in any case affect the length of what it convert
+        // to.
+        int char_length = mapping->get(current, 0, chars);
+        if (char_length == 0) char_length = 1;
+        current_length += char_length;
+        if (current_length > Smi::kMaxValue) {
+          Top::context()->mark_out_of_memory();
+          return Failure::OutOfMemoryException();
+        }
+      }
+      // Try again with the real length.
+      return Smi::FromInt(current_length);
+    } else {
+      for (int j = 0; j < char_length; j++) {
+        result->Set(i, chars[j]);
+        i++;
+      }
+      has_changed_character = true;
+    }
+    current = next;
+  }
+  if (has_changed_character) {
+    return result;
+  } else {
+    // If we didn't actually change anything in doing the conversion
+    // we simple return the result and let the converted string
+    // become garbage; there is no reason to keep two identical strings
+    // alive.
+    return s;
+  }
+}
+
+
+template <class Converter>
+static Object* ConvertCase(Arguments args,
+                           unibrow::Mapping<Converter, 128>* mapping) {
+  NoHandleAllocation ha;
+
+  CONVERT_CHECKED(String, s, args[0]);
+  s->TryFlattenIfNotFlat();
+
+  int input_string_length = s->length();
+  // Assume that the string is not empty; we need this assumption later
+  if (input_string_length == 0) return s;
+  int length = input_string_length;
+
+  Object* answer = ConvertCaseHelper(s, length, length, mapping);
+  if (answer->IsSmi()) {
+    // Retry with correct length.
+    answer = ConvertCaseHelper(s, Smi::cast(answer)->value(), length, mapping);
+  }
+  return answer;  // This may be a failure.
+}
+
+
+static Object* Runtime_StringToLowerCase(Arguments args) {
+  return ConvertCase<unibrow::ToLowercase>(args, &to_lower_mapping);
+}
+
+
+static Object* Runtime_StringToUpperCase(Arguments args) {
+  return ConvertCase<unibrow::ToUppercase>(args, &to_upper_mapping);
+}
+
+
+bool Runtime::IsUpperCaseChar(uint16_t ch) {
+  unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth];
+  int char_length = to_upper_mapping.get(ch, 0, chars);
+  return char_length == 0;
+}
+
+
+static Object* Runtime_NumberToString(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  Object* number = args[0];
+  RUNTIME_ASSERT(number->IsNumber());
+
+  Object* cached = Heap::GetNumberStringCache(number);
+  if (cached != Heap::undefined_value()) {
+    return cached;
+  }
+
+  char arr[100];
+  Vector<char> buffer(arr, ARRAY_SIZE(arr));
+  const char* str;
+  if (number->IsSmi()) {
+    int num = Smi::cast(number)->value();
+    str = IntToCString(num, buffer);
+  } else {
+    double num = HeapNumber::cast(number)->value();
+    str = DoubleToCString(num, buffer);
+  }
+  Object* result = Heap::AllocateStringFromAscii(CStrVector(str));
+
+  if (!result->IsFailure()) {
+    Heap::SetNumberStringCache(number, String::cast(result));
+  }
+  return result;
+}
+
+
+static Object* Runtime_NumberToInteger(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  Object* obj = args[0];
+  if (obj->IsSmi()) return obj;
+  CONVERT_DOUBLE_CHECKED(number, obj);
+  return Heap::NumberFromDouble(DoubleToInteger(number));
+}
+
+
+static Object* Runtime_NumberToJSUint32(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  Object* obj = args[0];
+  if (obj->IsSmi() && Smi::cast(obj)->value() >= 0) return obj;
+  CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, obj);
+  return Heap::NumberFromUint32(number);
+}
+
+
+static Object* Runtime_NumberToJSInt32(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  Object* obj = args[0];
+  if (obj->IsSmi()) return obj;
+  CONVERT_DOUBLE_CHECKED(number, obj);
+  return Heap::NumberFromInt32(DoubleToInt32(number));
+}
+
+
+// Converts a Number to a Smi, if possible. Returns NaN if the number is not
+// a small integer.
+static Object* Runtime_NumberToSmi(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  Object* obj = args[0];
+  if (obj->IsSmi()) {
+    return obj;
+  }
+  if (obj->IsHeapNumber()) {
+    double value = HeapNumber::cast(obj)->value();
+    int int_value = FastD2I(value);
+    if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
+      return Smi::FromInt(int_value);
+    }
+  }
+  return Heap::nan_value();
+}
+
+static Object* Runtime_NumberAdd(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  CONVERT_DOUBLE_CHECKED(y, args[1]);
+  return Heap::AllocateHeapNumber(x + y);
+}
+
+
+static Object* Runtime_NumberSub(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  CONVERT_DOUBLE_CHECKED(y, args[1]);
+  return Heap::AllocateHeapNumber(x - y);
+}
+
+
+static Object* Runtime_NumberMul(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  CONVERT_DOUBLE_CHECKED(y, args[1]);
+  return Heap::AllocateHeapNumber(x * y);
+}
+
+
+static Object* Runtime_NumberUnaryMinus(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  return Heap::AllocateHeapNumber(-x);
+}
+
+
+static Object* Runtime_NumberDiv(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  CONVERT_DOUBLE_CHECKED(y, args[1]);
+  return Heap::NewNumberFromDouble(x / y);
+}
+
+
+static Object* Runtime_NumberMod(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  CONVERT_DOUBLE_CHECKED(y, args[1]);
+
+#ifdef WIN32
+  // Workaround MS fmod bugs. ECMA-262 says:
+  // dividend is finite and divisor is an infinity => result equals dividend
+  // dividend is a zero and divisor is nonzero finite => result equals dividend
+  if (!(isfinite(x) && (!isfinite(y) && !isnan(y))) &&
+      !(x == 0 && (y != 0 && isfinite(y))))
+#endif
+  x = fmod(x, y);
+  // NewNumberFromDouble may return a Smi instead of a Number object
+  return Heap::NewNumberFromDouble(x);
+}
+
+
+static Object* Runtime_StringAdd(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_CHECKED(String, str1, args[0]);
+  CONVERT_CHECKED(String, str2, args[1]);
+  int len1 = str1->length();
+  int len2 = str2->length();
+  if (len1 == 0) return str2;
+  if (len2 == 0) return str1;
+  int length_sum = len1 + len2;
+  // Make sure that an out of memory exception is thrown if the length
+  // of the new cons string is too large to fit in a Smi.
+  if (length_sum > Smi::kMaxValue || length_sum < 0) {
+    Top::context()->mark_out_of_memory();
+    return Failure::OutOfMemoryException();
+  }
+  return Heap::AllocateConsString(str1, str2);
+}
+
+
+template<typename sinkchar>
+static inline void StringBuilderConcatHelper(String* special,
+                                             sinkchar* sink,
+                                             FixedArray* fixed_array,
+                                             int array_length) {
+  int position = 0;
+  for (int i = 0; i < array_length; i++) {
+    Object* element = fixed_array->get(i);
+    if (element->IsSmi()) {
+      int encoded_slice = Smi::cast(element)->value();
+      int pos = StringBuilderSubstringPosition::decode(encoded_slice);
+      int len = StringBuilderSubstringLength::decode(encoded_slice);
+      String::WriteToFlat(special,
+                          sink + position,
+                          pos,
+                          pos + len);
+      position += len;
+    } else {
+      String* string = String::cast(element);
+      int element_length = string->length();
+      String::WriteToFlat(string, sink + position, 0, element_length);
+      position += element_length;
+    }
+  }
+}
+
+
+static Object* Runtime_StringBuilderConcat(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+  CONVERT_CHECKED(JSArray, array, args[0]);
+  CONVERT_CHECKED(String, special, args[1]);
+  int special_length = special->length();
+  Object* smi_array_length = array->length();
+  if (!smi_array_length->IsSmi()) {
+    Top::context()->mark_out_of_memory();
+    return Failure::OutOfMemoryException();
+  }
+  int array_length = Smi::cast(smi_array_length)->value();
+  if (!array->HasFastElements()) {
+    return Top::Throw(Heap::illegal_argument_symbol());
+  }
+  FixedArray* fixed_array = FixedArray::cast(array->elements());
+  if (fixed_array->length() < array_length) {
+    array_length = fixed_array->length();
+  }
+
+  if (array_length == 0) {
+    return Heap::empty_string();
+  } else if (array_length == 1) {
+    Object* first = fixed_array->get(0);
+    if (first->IsString()) return first;
+  }
+
+  bool ascii = StringShape(special).IsAsciiRepresentation();
+  int position = 0;
+  for (int i = 0; i < array_length; i++) {
+    Object* elt = fixed_array->get(i);
+    if (elt->IsSmi()) {
+      int len = Smi::cast(elt)->value();
+      int pos = len >> 11;
+      len &= 0x7ff;
+      if (pos + len > special_length) {
+        return Top::Throw(Heap::illegal_argument_symbol());
+      }
+      position += len;
+    } else if (elt->IsString()) {
+      String* element = String::cast(elt);
+      int element_length = element->length();
+      if (!Smi::IsValid(element_length + position)) {
+        Top::context()->mark_out_of_memory();
+        return Failure::OutOfMemoryException();
+      }
+      position += element_length;
+      if (ascii && !StringShape(element).IsAsciiRepresentation()) {
+        ascii = false;
+      }
+    } else {
+      return Top::Throw(Heap::illegal_argument_symbol());
+    }
+  }
+
+  int length = position;
+  Object* object;
+
+  if (ascii) {
+    object = Heap::AllocateRawAsciiString(length);
+    if (object->IsFailure()) return object;
+    SeqAsciiString* answer = SeqAsciiString::cast(object);
+    StringBuilderConcatHelper(special,
+                              answer->GetChars(),
+                              fixed_array,
+                              array_length);
+    return answer;
+  } else {
+    object = Heap::AllocateRawTwoByteString(length);
+    if (object->IsFailure()) return object;
+    SeqTwoByteString* answer = SeqTwoByteString::cast(object);
+    StringBuilderConcatHelper(special,
+                              answer->GetChars(),
+                              fixed_array,
+                              array_length);
+    return answer;
+  }
+}
+
+
+static Object* Runtime_NumberOr(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
+  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
+  return Heap::NumberFromInt32(x | y);
+}
+
+
+static Object* Runtime_NumberAnd(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
+  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
+  return Heap::NumberFromInt32(x & y);
+}
+
+
+static Object* Runtime_NumberXor(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
+  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
+  return Heap::NumberFromInt32(x ^ y);
+}
+
+
+static Object* Runtime_NumberNot(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
+  return Heap::NumberFromInt32(~x);
+}
+
+
+static Object* Runtime_NumberShl(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
+  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
+  return Heap::NumberFromInt32(x << (y & 0x1f));
+}
+
+
+static Object* Runtime_NumberShr(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
+  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
+  return Heap::NumberFromUint32(x >> (y & 0x1f));
+}
+
+
+static Object* Runtime_NumberSar(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
+  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
+  return Heap::NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
+}
+
+
+static Object* Runtime_NumberEquals(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  CONVERT_DOUBLE_CHECKED(y, args[1]);
+  if (isnan(x)) return Smi::FromInt(NOT_EQUAL);
+  if (isnan(y)) return Smi::FromInt(NOT_EQUAL);
+  if (x == y) return Smi::FromInt(EQUAL);
+  Object* result;
+  if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
+    result = Smi::FromInt(EQUAL);
+  } else {
+    result = Smi::FromInt(NOT_EQUAL);
+  }
+  return result;
+}
+
+
+static Object* Runtime_StringEquals(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_CHECKED(String, x, args[0]);
+  CONVERT_CHECKED(String, y, args[1]);
+
+  bool not_equal = !x->Equals(y);
+  // This is slightly convoluted because the value that signifies
+  // equality is 0 and inequality is 1 so we have to negate the result
+  // from String::Equals.
+  ASSERT(not_equal == 0 || not_equal == 1);
+  STATIC_CHECK(EQUAL == 0);
+  STATIC_CHECK(NOT_EQUAL == 1);
+  return Smi::FromInt(not_equal);
+}
+
+
+static Object* Runtime_NumberCompare(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 3);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  CONVERT_DOUBLE_CHECKED(y, args[1]);
+  if (isnan(x) || isnan(y)) return args[2];
+  if (x == y) return Smi::FromInt(EQUAL);
+  if (isless(x, y)) return Smi::FromInt(LESS);
+  return Smi::FromInt(GREATER);
+}
+
+
+// Compare two Smis as if they were converted to strings and then
+// compared lexicographically.
+static Object* Runtime_SmiLexicographicCompare(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  // Arrays for the individual characters of the two Smis.  Smis are
+  // 31 bit integers and 10 decimal digits are therefore enough.
+  static int x_elms[10];
+  static int y_elms[10];
+
+  // Extract the integer values from the Smis.
+  CONVERT_CHECKED(Smi, x, args[0]);
+  CONVERT_CHECKED(Smi, y, args[1]);
+  int x_value = x->value();
+  int y_value = y->value();
+
+  // If the integers are equal so are the string representations.
+  if (x_value == y_value) return Smi::FromInt(EQUAL);
+
+  // If one of the integers are zero the normal integer order is the
+  // same as the lexicographic order of the string representations.
+  if (x_value == 0 || y_value == 0) return Smi::FromInt(x_value - y_value);
+
+  // If only one of the integers is negative the negative number is
+  // smallest because the char code of '-' is less than the char code
+  // of any digit.  Otherwise, we make both values positive.
+  if (x_value < 0 || y_value < 0) {
+    if (y_value >= 0) return Smi::FromInt(LESS);
+    if (x_value >= 0) return Smi::FromInt(GREATER);
+    x_value = -x_value;
+    y_value = -y_value;
+  }
+
+  // Convert the integers to arrays of their decimal digits.
+  int x_index = 0;
+  int y_index = 0;
+  while (x_value > 0) {
+    x_elms[x_index++] = x_value % 10;
+    x_value /= 10;
+  }
+  while (y_value > 0) {
+    y_elms[y_index++] = y_value % 10;
+    y_value /= 10;
+  }
+
+  // Loop through the arrays of decimal digits finding the first place
+  // where they differ.
+  while (--x_index >= 0 && --y_index >= 0) {
+    int diff = x_elms[x_index] - y_elms[y_index];
+    if (diff != 0) return Smi::FromInt(diff);
+  }
+
+  // If one array is a suffix of the other array, the longest array is
+  // the representation of the largest of the Smis in the
+  // lexicographic ordering.
+  return Smi::FromInt(x_index - y_index);
+}
+
+
+static Object* Runtime_StringCompare(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_CHECKED(String, x, args[0]);
+  CONVERT_CHECKED(String, y, args[1]);
+
+  // A few fast case tests before we flatten.
+  if (x == y) return Smi::FromInt(EQUAL);
+  if (y->length() == 0) {
+    if (x->length() == 0) return Smi::FromInt(EQUAL);
+    return Smi::FromInt(GREATER);
+  } else if (x->length() == 0) {
+    return Smi::FromInt(LESS);
+  }
+
+  int d = x->Get(0) - y->Get(0);
+  if (d < 0) return Smi::FromInt(LESS);
+  else if (d > 0) return Smi::FromInt(GREATER);
+
+  x->TryFlattenIfNotFlat();
+  y->TryFlattenIfNotFlat();
+
+  static StringInputBuffer bufx;
+  static StringInputBuffer bufy;
+  bufx.Reset(x);
+  bufy.Reset(y);
+  while (bufx.has_more() && bufy.has_more()) {
+    int d = bufx.GetNext() - bufy.GetNext();
+    if (d < 0) return Smi::FromInt(LESS);
+    else if (d > 0) return Smi::FromInt(GREATER);
+  }
+
+  // x is (non-trivial) prefix of y:
+  if (bufy.has_more()) return Smi::FromInt(LESS);
+  // y is prefix of x:
+  return Smi::FromInt(bufx.has_more() ? GREATER : EQUAL);
+}
+
+
+static Object* Runtime_Math_abs(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  return Heap::AllocateHeapNumber(fabs(x));
+}
+
+
+static Object* Runtime_Math_acos(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  return Heap::AllocateHeapNumber(acos(x));
+}
+
+
+static Object* Runtime_Math_asin(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  return Heap::AllocateHeapNumber(asin(x));
+}
+
+
+static Object* Runtime_Math_atan(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  return Heap::AllocateHeapNumber(atan(x));
+}
+
+
+static Object* Runtime_Math_atan2(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  CONVERT_DOUBLE_CHECKED(y, args[1]);
+  double result;
+  if (isinf(x) && isinf(y)) {
+    // Make sure that the result in case of two infinite arguments
+    // is a multiple of Pi / 4. The sign of the result is determined
+    // by the first argument (x) and the sign of the second argument
+    // determines the multiplier: one or three.
+    static double kPiDividedBy4 = 0.78539816339744830962;
+    int multiplier = (x < 0) ? -1 : 1;
+    if (y < 0) multiplier *= 3;
+    result = multiplier * kPiDividedBy4;
+  } else {
+    result = atan2(x, y);
+  }
+  return Heap::AllocateHeapNumber(result);
+}
+
+
+static Object* Runtime_Math_ceil(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  return Heap::NumberFromDouble(ceiling(x));
+}
+
+
+static Object* Runtime_Math_cos(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  return Heap::AllocateHeapNumber(cos(x));
+}
+
+
+static Object* Runtime_Math_exp(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  return Heap::AllocateHeapNumber(exp(x));
+}
+
+
+static Object* Runtime_Math_floor(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  return Heap::NumberFromDouble(floor(x));
+}
+
+
+static Object* Runtime_Math_log(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  return Heap::AllocateHeapNumber(log(x));
+}
+
+
+static Object* Runtime_Math_pow(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  CONVERT_DOUBLE_CHECKED(y, args[1]);
+  if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
+    return Heap::nan_value();
+  } else if (y == 0) {
+    return Smi::FromInt(1);
+  } else {
+    return Heap::AllocateHeapNumber(pow(x, y));
+  }
+}
+
+// Returns a number value with positive sign, greater than or equal to
+// 0 but less than 1, chosen randomly.
+static Object* Runtime_Math_random(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 0);
+
+  // To get much better precision, we combine the results of two
+  // invocations of random(). The result is computed by normalizing a
+  // double in the range [0, RAND_MAX + 1) obtained by adding the
+  // high-order bits in the range [0, RAND_MAX] with the low-order
+  // bits in the range [0, 1).
+  double lo = static_cast<double>(random()) * (1.0 / (RAND_MAX + 1.0));
+  double hi = static_cast<double>(random());
+  double result = (hi + lo) * (1.0 / (RAND_MAX + 1.0));
+  ASSERT(result >= 0 && result < 1);
+  return Heap::AllocateHeapNumber(result);
+}
+
+
+static Object* Runtime_Math_round(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  if (signbit(x) && x >= -0.5) return Heap::minus_zero_value();
+  return Heap::NumberFromDouble(floor(x + 0.5));
+}
+
+
+static Object* Runtime_Math_sin(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  return Heap::AllocateHeapNumber(sin(x));
+}
+
+
+static Object* Runtime_Math_sqrt(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  return Heap::AllocateHeapNumber(sqrt(x));
+}
+
+
+static Object* Runtime_Math_tan(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  return Heap::AllocateHeapNumber(tan(x));
+}
+
+
+// The NewArguments function is only used when constructing the
+// arguments array when calling non-functions from JavaScript in
+// runtime.js:CALL_NON_FUNCTION.
+static Object* Runtime_NewArguments(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  // ECMA-262, 3rd., 10.1.8, p.39
+  CONVERT_CHECKED(JSFunction, callee, args[0]);
+
+  // Compute the frame holding the arguments.
+  JavaScriptFrameIterator it;
+  it.AdvanceToArgumentsFrame();
+  JavaScriptFrame* frame = it.frame();
+
+  const int length = frame->GetProvidedParametersCount();
+  Object* result = Heap::AllocateArgumentsObject(callee, length);
+  if (result->IsFailure()) return result;
+  if (length > 0) {
+    Object* obj =  Heap::AllocateFixedArray(length);
+    if (obj->IsFailure()) return obj;
+    FixedArray* array = FixedArray::cast(obj);
+    ASSERT(array->length() == length);
+    WriteBarrierMode mode = array->GetWriteBarrierMode();
+    for (int i = 0; i < length; i++) {
+      array->set(i, frame->GetParameter(i), mode);
+    }
+    JSObject::cast(result)->set_elements(array);
+  }
+  return result;
+}
+
+
+static Object* Runtime_NewArgumentsFast(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 3);
+
+  JSFunction* callee = JSFunction::cast(args[0]);
+  Object** parameters = reinterpret_cast<Object**>(args[1]);
+  const int length = Smi::cast(args[2])->value();
+
+  Object* result = Heap::AllocateArgumentsObject(callee, length);
+  if (result->IsFailure()) return result;
+  ASSERT(Heap::InNewSpace(result));
+
+  // Allocate the elements if needed.
+  if (length > 0) {
+    // Allocate the fixed array.
+    Object* obj = Heap::AllocateRawFixedArray(length);
+    if (obj->IsFailure()) return obj;
+    reinterpret_cast<Array*>(obj)->set_map(Heap::fixed_array_map());
+    FixedArray* array = FixedArray::cast(obj);
+    array->set_length(length);
+    WriteBarrierMode mode = array->GetWriteBarrierMode();
+    for (int i = 0; i < length; i++) {
+      array->set(i, *--parameters, mode);
+    }
+    JSObject::cast(result)->set_elements(FixedArray::cast(obj),
+                                         SKIP_WRITE_BARRIER);
+  }
+  return result;
+}
+
+
+static Object* Runtime_NewClosure(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 2);
+  CONVERT_ARG_CHECKED(JSFunction, boilerplate, 0);
+  CONVERT_ARG_CHECKED(Context, context, 1);
+
+  Handle<JSFunction> result =
+      Factory::NewFunctionFromBoilerplate(boilerplate, context);
+  return *result;
+}
+
+
+static Object* Runtime_NewObject(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  Object* constructor = args[0];
+  if (constructor->IsJSFunction()) {
+    JSFunction* function = JSFunction::cast(constructor);
+
+    // Handle stepping into constructors if step into is active.
+    if (Debug::StepInActive()) {
+      HandleScope scope;
+      Debug::HandleStepIn(Handle<JSFunction>(function), 0, true);
+    }
+
+    if (function->has_initial_map() &&
+        function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
+      // The 'Function' function ignores the receiver object when
+      // called using 'new' and creates a new JSFunction object that
+      // is returned.  The receiver object is only used for error
+      // reporting if an error occurs when constructing the new
+      // JSFunction.  AllocateJSObject should not be used to allocate
+      // JSFunctions since it does not properly initialize the shared
+      // part of the function.  Since the receiver is ignored anyway,
+      // we use the global object as the receiver instead of a new
+      // JSFunction object.  This way, errors are reported the same
+      // way whether or not 'Function' is called using 'new'.
+      return Top::context()->global();
+    }
+    return Heap::AllocateJSObject(function);
+  }
+
+  HandleScope scope;
+  Handle<Object> cons(constructor);
+  // The constructor is not a function; throw a type error.
+  Handle<Object> type_error =
+    Factory::NewTypeError("not_constructor", HandleVector(&cons, 1));
+  return Top::Throw(*type_error);
+}
+
+
+static Object* Runtime_LazyCompile(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+
+  Handle<JSFunction> function = args.at<JSFunction>(0);
+#ifdef DEBUG
+  if (FLAG_trace_lazy) {
+    PrintF("[lazy: ");
+    function->shared()->name()->Print();
+    PrintF("]\n");
+  }
+#endif
+
+  // Compile the target function.
+  ASSERT(!function->is_compiled());
+  if (!CompileLazy(function, KEEP_EXCEPTION)) {
+    return Failure::Exception();
+  }
+
+  return function->code();
+}
+
+
+static Object* Runtime_GetCalledFunction(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 0);
+  StackFrameIterator it;
+  // Get past the JS-to-C exit frame.
+  ASSERT(it.frame()->is_exit());
+  it.Advance();
+  // Get past the CALL_NON_FUNCTION activation frame.
+  ASSERT(it.frame()->is_java_script());
+  it.Advance();
+  // Argument adaptor frames do not copy the function; we have to skip
+  // past them to get to the real calling frame.
+  if (it.frame()->is_arguments_adaptor()) it.Advance();
+  // Get the function from the top of the expression stack of the
+  // calling frame.
+  StandardFrame* frame = StandardFrame::cast(it.frame());
+  int index = frame->ComputeExpressionsCount() - 1;
+  Object* result = frame->GetExpression(index);
+  return result;
+}
+
+
+static Object* Runtime_GetFunctionDelegate(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+  RUNTIME_ASSERT(!args[0]->IsJSFunction());
+  return *Execution::GetFunctionDelegate(args.at<Object>(0));
+}
+
+
+static Object* Runtime_NewContext(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_CHECKED(JSFunction, function, args[0]);
+  int length = ScopeInfo<>::NumberOfContextSlots(function->code());
+  Object* result = Heap::AllocateFunctionContext(length, function);
+  if (result->IsFailure()) return result;
+
+  Top::set_context(Context::cast(result));
+
+  return result;  // non-failure
+}
+
+static Object* PushContextHelper(Object* object, bool is_catch_context) {
+  // Convert the object to a proper JavaScript object.
+  Object* js_object = object;
+  if (!js_object->IsJSObject()) {
+    js_object = js_object->ToObject();
+    if (js_object->IsFailure()) {
+      if (!Failure::cast(js_object)->IsInternalError()) return js_object;
+      HandleScope scope;
+      Handle<Object> handle(object);
+      Handle<Object> result =
+          Factory::NewTypeError("with_expression", HandleVector(&handle, 1));
+      return Top::Throw(*result);
+    }
+  }
+
+  Object* result =
+      Heap::AllocateWithContext(Top::context(),
+                                JSObject::cast(js_object),
+                                is_catch_context);
+  if (result->IsFailure()) return result;
+
+  Context* context = Context::cast(result);
+  Top::set_context(context);
+
+  return result;
+}
+
+
+static Object* Runtime_PushContext(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+  return PushContextHelper(args[0], false);
+}
+
+
+static Object* Runtime_PushCatchContext(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+  return PushContextHelper(args[0], true);
+}
+
+
+static Object* Runtime_LookupContext(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 2);
+
+  CONVERT_ARG_CHECKED(Context, context, 0);
+  CONVERT_ARG_CHECKED(String, name, 1);
+
+  int index;
+  PropertyAttributes attributes;
+  ContextLookupFlags flags = FOLLOW_CHAINS;
+  Handle<Object> holder =
+      context->Lookup(name, flags, &index, &attributes);
+
+  if (index < 0 && !holder.is_null()) {
+    ASSERT(holder->IsJSObject());
+    return *holder;
+  }
+
+  // No intermediate context found. Use global object by default.
+  return Top::context()->global();
+}
+
+
+// A mechanism to return pairs of Object*'s. This is somewhat
+// compiler-dependent as it assumes that a 64-bit value (a long long)
+// is returned via two registers (edx:eax on ia32). Both the ia32 and
+// arm platform support this; it is mostly an issue of "coaxing" the
+// compiler to do the right thing.
+//
+// TODO(1236026): This is a non-portable hack that should be removed.
+typedef uint64_t ObjectPair;
+static inline ObjectPair MakePair(Object* x, Object* y) {
+  return reinterpret_cast<uint32_t>(x) |
+      (reinterpret_cast<ObjectPair>(y) << 32);
+}
+
+
+static inline Object* Unhole(Object* x, PropertyAttributes attributes) {
+  ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
+  USE(attributes);
+  return x->IsTheHole() ? Heap::undefined_value() : x;
+}
+
+
+static JSObject* ComputeReceiverForNonGlobal(JSObject* holder) {
+  ASSERT(!holder->IsGlobalObject());
+  Context* top = Top::context();
+  // Get the context extension function.
+  JSFunction* context_extension_function =
+      top->global_context()->context_extension_function();
+  // If the holder isn't a context extension object, we just return it
+  // as the receiver. This allows arguments objects to be used as
+  // receivers, but only if they are put in the context scope chain
+  // explicitly via a with-statement.
+  Object* constructor = holder->map()->constructor();
+  if (constructor != context_extension_function) return holder;
+  // Fall back to using the global object as the receiver if the
+  // property turns out to be a local variable allocated in a context
+  // extension object - introduced via eval.
+  return top->global()->global_receiver();
+}
+
+
+static ObjectPair LoadContextSlotHelper(Arguments args, bool throw_error) {
+  HandleScope scope;
+  ASSERT(args.length() == 2);
+
+  if (!args[0]->IsContext() || !args[1]->IsString()) {
+    return MakePair(IllegalOperation(), NULL);
+  }
+  Handle<Context> context = args.at<Context>(0);
+  Handle<String> name = args.at<String>(1);
+
+  int index;
+  PropertyAttributes attributes;
+  ContextLookupFlags flags = FOLLOW_CHAINS;
+  Handle<Object> holder =
+      context->Lookup(name, flags, &index, &attributes);
+
+  // If the index is non-negative, the slot has been found in a local
+  // variable or a parameter. Read it from the context object or the
+  // arguments object.
+  if (index >= 0) {
+    // If the "property" we were looking for is a local variable or an
+    // argument in a context, the receiver is the global object; see
+    // ECMA-262, 3rd., 10.1.6 and 10.2.3.
+    JSObject* receiver = Top::context()->global()->global_receiver();
+    Object* value = (holder->IsContext())
+        ? Context::cast(*holder)->get(index)
+        : JSObject::cast(*holder)->GetElement(index);
+    return MakePair(Unhole(value, attributes), receiver);
+  }
+
+  // If the holder is found, we read the property from it.
+  if (!holder.is_null() && holder->IsJSObject()) {
+    ASSERT(Handle<JSObject>::cast(holder)->HasProperty(*name));
+    JSObject* object = JSObject::cast(*holder);
+    JSObject* receiver;
+    if (object->IsGlobalObject()) {
+      receiver = GlobalObject::cast(object)->global_receiver();
+    } else if (context->is_exception_holder(*holder)) {
+      receiver = Top::context()->global()->global_receiver();
+    } else {
+      receiver = ComputeReceiverForNonGlobal(object);
+    }
+    // No need to unhole the value here. This is taken care of by the
+    // GetProperty function.
+    Object* value = object->GetProperty(*name);
+    return MakePair(value, receiver);
+  }
+
+  if (throw_error) {
+    // The property doesn't exist - throw exception.
+    Handle<Object> reference_error =
+        Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
+    return MakePair(Top::Throw(*reference_error), NULL);
+  } else {
+    // The property doesn't exist - return undefined
+    return MakePair(Heap::undefined_value(), Heap::undefined_value());
+  }
+}
+
+
+static ObjectPair Runtime_LoadContextSlot(Arguments args) {
+  return LoadContextSlotHelper(args, true);
+}
+
+
+static ObjectPair Runtime_LoadContextSlotNoReferenceError(Arguments args) {
+  return LoadContextSlotHelper(args, false);
+}
+
+
+static Object* Runtime_StoreContextSlot(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 3);
+
+  Handle<Object> value(args[0]);
+  CONVERT_ARG_CHECKED(Context, context, 1);
+  CONVERT_ARG_CHECKED(String, name, 2);
+
+  int index;
+  PropertyAttributes attributes;
+  ContextLookupFlags flags = FOLLOW_CHAINS;
+  Handle<Object> holder =
+      context->Lookup(name, flags, &index, &attributes);
+
+  if (index >= 0) {
+    if (holder->IsContext()) {
+      // Ignore if read_only variable.
+      if ((attributes & READ_ONLY) == 0) {
+        Handle<Context>::cast(holder)->set(index, *value);
+      }
+    } else {
+      ASSERT((attributes & READ_ONLY) == 0);
+      Object* result =
+          Handle<JSObject>::cast(holder)->SetElement(index, *value);
+      USE(result);
+      ASSERT(!result->IsFailure());
+    }
+    return *value;
+  }
+
+  // Slow case: The property is not in a FixedArray context.
+  // It is either in an JSObject extension context or it was not found.
+  Handle<JSObject> context_ext;
+
+  if (!holder.is_null()) {
+    // The property exists in the extension context.
+    context_ext = Handle<JSObject>::cast(holder);
+  } else {
+    // The property was not found. It needs to be stored in the global context.
+    ASSERT(attributes == ABSENT);
+    attributes = NONE;
+    context_ext = Handle<JSObject>(Top::context()->global());
+  }
+
+  // Set the property, but ignore if read_only variable on the context
+  // extension object itself.
+  if ((attributes & READ_ONLY) == 0 ||
+      (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) {
+    Handle<Object> set = SetProperty(context_ext, name, value, attributes);
+    if (set.is_null()) {
+      // Failure::Exception is converted to a null handle in the
+      // handle-based methods such as SetProperty.  We therefore need
+      // to convert null handles back to exceptions.
+      ASSERT(Top::has_pending_exception());
+      return Failure::Exception();
+    }
+  }
+  return *value;
+}
+
+
+static Object* Runtime_Throw(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+
+  return Top::Throw(args[0]);
+}
+
+
+static Object* Runtime_ReThrow(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+
+  return Top::ReThrow(args[0]);
+}
+
+
+static Object* Runtime_ThrowReferenceError(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+
+  Handle<Object> name(args[0]);
+  Handle<Object> reference_error =
+    Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
+  return Top::Throw(*reference_error);
+}
+
+
+static Object* Runtime_StackOverflow(Arguments args) {
+  NoHandleAllocation na;
+  return Top::StackOverflow();
+}
+
+
+static Object* Runtime_DebugBreak(Arguments args) {
+  ASSERT(args.length() == 0);
+  return Execution::DebugBreakHelper();
+}
+
+
+static Object* Runtime_StackGuard(Arguments args) {
+  ASSERT(args.length() == 1);
+
+  // First check if this is a real stack overflow.
+  if (StackGuard::IsStackOverflow()) {
+    return Runtime_StackOverflow(args);
+  }
+
+  return Execution::HandleStackGuardInterrupt();
+}
+
+
+// NOTE: These PrintXXX functions are defined for all builds (not just
+// DEBUG builds) because we may want to be able to trace function
+// calls in all modes.
+static void PrintString(String* str) {
+  // not uncommon to have empty strings
+  if (str->length() > 0) {
+    SmartPointer<char> s =
+        str->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+    PrintF("%s", *s);
+  }
+}
+
+
+static void PrintObject(Object* obj) {
+  if (obj->IsSmi()) {
+    PrintF("%d", Smi::cast(obj)->value());
+  } else if (obj->IsString() || obj->IsSymbol()) {
+    PrintString(String::cast(obj));
+  } else if (obj->IsNumber()) {
+    PrintF("%g", obj->Number());
+  } else if (obj->IsFailure()) {
+    PrintF("<failure>");
+  } else if (obj->IsUndefined()) {
+    PrintF("<undefined>");
+  } else if (obj->IsNull()) {
+    PrintF("<null>");
+  } else if (obj->IsTrue()) {
+    PrintF("<true>");
+  } else if (obj->IsFalse()) {
+    PrintF("<false>");
+  } else {
+    PrintF("%p", obj);
+  }
+}
+
+
+static int StackSize() {
+  int n = 0;
+  for (JavaScriptFrameIterator it; !it.done(); it.Advance()) n++;
+  return n;
+}
+
+
+static void PrintTransition(Object* result) {
+  // indentation
+  { const int nmax = 80;
+    int n = StackSize();
+    if (n <= nmax)
+      PrintF("%4d:%*s", n, n, "");
+    else
+      PrintF("%4d:%*s", n, nmax, "...");
+  }
+
+  if (result == NULL) {
+    // constructor calls
+    JavaScriptFrameIterator it;
+    JavaScriptFrame* frame = it.frame();
+    if (frame->IsConstructor()) PrintF("new ");
+    // function name
+    Object* fun = frame->function();
+    if (fun->IsJSFunction()) {
+      PrintObject(JSFunction::cast(fun)->shared()->name());
+    } else {
+      PrintObject(fun);
+    }
+    // function arguments
+    // (we are intentionally only printing the actually
+    // supplied parameters, not all parameters required)
+    PrintF("(this=");
+    PrintObject(frame->receiver());
+    const int length = frame->GetProvidedParametersCount();
+    for (int i = 0; i < length; i++) {
+      PrintF(", ");
+      PrintObject(frame->GetParameter(i));
+    }
+    PrintF(") {\n");
+
+  } else {
+    // function result
+    PrintF("} -> ");
+    PrintObject(result);
+    PrintF("\n");
+  }
+}
+
+
+static Object* Runtime_TraceEnter(Arguments args) {
+  ASSERT(args.length() == 0);
+  NoHandleAllocation ha;
+  PrintTransition(NULL);
+  return Heap::undefined_value();
+}
+
+
+static Object* Runtime_TraceExit(Arguments args) {
+  NoHandleAllocation ha;
+  PrintTransition(args[0]);
+  return args[0];  // return TOS
+}
+
+
+static Object* Runtime_DebugPrint(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+#ifdef DEBUG
+  if (args[0]->IsString()) {
+    // If we have a string, assume it's a code "marker"
+    // and print some interesting cpu debugging info.
+    JavaScriptFrameIterator it;
+    JavaScriptFrame* frame = it.frame();
+    PrintF("fp = %p, sp = %p, pp = %p: ",
+           frame->fp(), frame->sp(), frame->pp());
+  } else {
+    PrintF("DebugPrint: ");
+  }
+  args[0]->Print();
+#else
+  // ShortPrint is available in release mode. Print is not.
+  args[0]->ShortPrint();
+#endif
+  PrintF("\n");
+  Flush();
+
+  return args[0];  // return TOS
+}
+
+
+static Object* Runtime_DebugTrace(Arguments args) {
+  ASSERT(args.length() == 0);
+  NoHandleAllocation ha;
+  Top::PrintStack();
+  return Heap::undefined_value();
+}
+
+
+static Object* Runtime_DateCurrentTime(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 0);
+
+  // According to ECMA-262, section 15.9.1, page 117, the precision of
+  // the number in a Date object representing a particular instant in
+  // time is milliseconds. Therefore, we floor the result of getting
+  // the OS time.
+  double millis = floor(OS::TimeCurrentMillis());
+  return Heap::NumberFromDouble(millis);
+}
+
+
+static Object* Runtime_DateParseString(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 2);
+
+  CONVERT_ARG_CHECKED(String, str, 0);
+  FlattenString(str);
+
+  CONVERT_ARG_CHECKED(JSArray, output, 1);
+  RUNTIME_ASSERT(output->HasFastElements());
+
+  AssertNoAllocation no_allocation;
+
+  FixedArray* output_array = output->elements();
+  RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
+  bool result;
+  if (StringShape(*str).IsAsciiRepresentation()) {
+    result = DateParser::Parse(str->ToAsciiVector(), output_array);
+  } else {
+    ASSERT(StringShape(*str).IsTwoByteRepresentation());
+    result = DateParser::Parse(str->ToUC16Vector(), output_array);
+  }
+
+  if (result) {
+    return *output;
+  } else {
+    return Heap::null_value();
+  }
+}
+
+
+static Object* Runtime_DateLocalTimezone(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  char* zone = OS::LocalTimezone(x);
+  return Heap::AllocateStringFromUtf8(CStrVector(zone));
+}
+
+
+static Object* Runtime_DateLocalTimeOffset(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 0);
+
+  return Heap::NumberFromDouble(OS::LocalTimeOffset());
+}
+
+
+static Object* Runtime_DateDaylightSavingsOffset(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_DOUBLE_CHECKED(x, args[0]);
+  return Heap::NumberFromDouble(OS::DaylightSavingsOffset(x));
+}
+
+
+static Object* Runtime_NumberIsFinite(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_DOUBLE_CHECKED(value, args[0]);
+  Object* result;
+  if (isnan(value) || (fpclassify(value) == FP_INFINITE)) {
+    result = Heap::false_value();
+  } else {
+    result = Heap::true_value();
+  }
+  return result;
+}
+
+
+static Object* Runtime_GlobalReceiver(Arguments args) {
+  ASSERT(args.length() == 1);
+  Object* global = args[0];
+  if (!global->IsJSGlobalObject()) return Heap::null_value();
+  return JSGlobalObject::cast(global)->global_receiver();
+}
+
+
+static Object* Runtime_CompileString(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 2);
+  CONVERT_ARG_CHECKED(String, source, 0);
+  CONVERT_ARG_CHECKED(Smi, line_offset, 1);
+
+  // Compile source string in the global context.
+  Handle<Context> context(Top::context()->global_context());
+  Handle<JSFunction> boilerplate =
+      Compiler::CompileEval(source, context, line_offset->value(), true);
+  if (boilerplate.is_null()) return Failure::Exception();
+  Handle<JSFunction> fun =
+      Factory::NewFunctionFromBoilerplate(boilerplate, context);
+  return *fun;
+}
+
+
+static Handle<JSFunction> GetBuiltinFunction(String* name) {
+  LookupResult result;
+  Top::global_context()->builtins()->LocalLookup(name, &result);
+  return Handle<JSFunction>(JSFunction::cast(result.GetValue()));
+}
+
+
+static Object* CompileDirectEval(Handle<String> source) {
+  // Compute the eval context.
+  HandleScope scope;
+  StackFrameLocator locator;
+  JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
+  Handle<Context> context(Context::cast(frame->context()));
+  bool is_global = context->IsGlobalContext();
+
+  // Compile source string in the current context.
+  Handle<JSFunction> boilerplate =
+      Compiler::CompileEval(source, context, 0, is_global);
+  if (boilerplate.is_null()) return Failure::Exception();
+  Handle<JSFunction> fun =
+    Factory::NewFunctionFromBoilerplate(boilerplate, context);
+  return *fun;
+}
+
+
+static Object* Runtime_ResolvePossiblyDirectEval(Arguments args) {
+  ASSERT(args.length() == 2);
+
+  HandleScope scope;
+
+  CONVERT_ARG_CHECKED(JSFunction, callee, 0);
+
+  Handle<Object> receiver;
+
+  // Find where the 'eval' symbol is bound. It is unaliased only if
+  // it is bound in the global context.
+  StackFrameLocator locator;
+  JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
+  Handle<Context> context(Context::cast(frame->context()));
+  int index;
+  PropertyAttributes attributes;
+  while (!context.is_null()) {
+    receiver = context->Lookup(Factory::eval_symbol(), FOLLOW_PROTOTYPE_CHAIN,
+                               &index, &attributes);
+    // Stop search when eval is found or when the global context is
+    // reached.
+    if (attributes != ABSENT || context->IsGlobalContext()) break;
+    if (context->is_function_context()) {
+      context = Handle<Context>(Context::cast(context->closure()->context()));
+    } else {
+      context = Handle<Context>(context->previous());
+    }
+  }
+
+  // If eval could not be resolved, it has been deleted and we need to
+  // throw a reference error.
+  if (attributes == ABSENT) {
+    Handle<Object> name = Factory::eval_symbol();
+    Handle<Object> reference_error =
+        Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
+    return Top::Throw(*reference_error);
+  }
+
+  if (context->IsGlobalContext()) {
+    // 'eval' is bound in the global context, but it may have been overwritten.
+    // Compare it to the builtin 'GlobalEval' function to make sure.
+    Handle<JSFunction> global_eval =
+      GetBuiltinFunction(Heap::global_eval_symbol());
+    if (global_eval.is_identical_to(callee)) {
+      // A direct eval call.
+      if (args[1]->IsString()) {
+        CONVERT_ARG_CHECKED(String, source, 1);
+        // A normal eval call on a string. Compile it and return the
+        // compiled function bound in the local context.
+        Object* compiled_source = CompileDirectEval(source);
+        if (compiled_source->IsFailure()) return compiled_source;
+        receiver = Handle<Object>(frame->receiver());
+        callee = Handle<JSFunction>(JSFunction::cast(compiled_source));
+      } else {
+        // An eval call that is not called on a string. Global eval
+        // deals better with this.
+        receiver = Handle<Object>(Top::global_context()->global());
+      }
+    } else {
+      // 'eval' is overwritten. Just call the function with the given arguments.
+      receiver = Handle<Object>(Top::global_context()->global());
+    }
+  } else {
+    // 'eval' is not bound in the global context. Just call the function
+    // with the given arguments. This is not necessarily the global eval.
+    if (receiver->IsContext()) {
+      context = Handle<Context>::cast(receiver);
+      receiver = Handle<Object>(context->get(index));
+    }
+  }
+
+  Handle<FixedArray> call = Factory::NewFixedArray(2);
+  call->set(0, *callee);
+  call->set(1, *receiver);
+  return *call;
+}
+
+
+static Object* Runtime_CompileScript(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 4);
+
+  CONVERT_ARG_CHECKED(String, source, 0);
+  CONVERT_ARG_CHECKED(String, script, 1);
+  CONVERT_CHECKED(Smi, line_attrs, args[2]);
+  int line = line_attrs->value();
+  CONVERT_CHECKED(Smi, col_attrs, args[3]);
+  int col = col_attrs->value();
+  Handle<JSFunction> boilerplate =
+      Compiler::Compile(source, script, line, col, NULL, NULL);
+  if (boilerplate.is_null()) return Failure::Exception();
+  Handle<JSFunction> fun =
+      Factory::NewFunctionFromBoilerplate(boilerplate,
+                                          Handle<Context>(Top::context()));
+  return *fun;
+}
+
+
+static Object* Runtime_SetNewFunctionAttributes(Arguments args) {
+  // This utility adjusts the property attributes for newly created Function
+  // object ("new Function(...)") by changing the map.
+  // All it does is changing the prototype property to enumerable
+  // as specified in ECMA262, 15.3.5.2.
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+  CONVERT_ARG_CHECKED(JSFunction, func, 0);
+  ASSERT(func->map()->instance_type() ==
+         Top::function_instance_map()->instance_type());
+  ASSERT(func->map()->instance_size() ==
+         Top::function_instance_map()->instance_size());
+  func->set_map(*Top::function_instance_map());
+  return *func;
+}
+
+
+// Push an array unto an array of arrays if it is not already in the
+// array.  Returns true if the element was pushed on the stack and
+// false otherwise.
+static Object* Runtime_PushIfAbsent(Arguments args) {
+  ASSERT(args.length() == 2);
+  CONVERT_CHECKED(JSArray, array, args[0]);
+  CONVERT_CHECKED(JSArray, element, args[1]);
+  RUNTIME_ASSERT(array->HasFastElements());
+  int length = Smi::cast(array->length())->value();
+  FixedArray* elements = FixedArray::cast(array->elements());
+  for (int i = 0; i < length; i++) {
+    if (elements->get(i) == element) return Heap::false_value();
+  }
+  Object* obj = array->SetFastElement(length, element);
+  if (obj->IsFailure()) return obj;
+  return Heap::true_value();
+}
+
+
+/**
+ * A simple visitor visits every element of Array's.
+ * The backend storage can be a fixed array for fast elements case,
+ * or a dictionary for sparse array. Since Dictionary is a subtype
+ * of FixedArray, the class can be used by both fast and slow cases.
+ * The second parameter of the constructor, fast_elements, specifies
+ * whether the storage is a FixedArray or Dictionary.
+ *
+ * An index limit is used to deal with the situation that a result array
+ * length overflows 32-bit non-negative integer.
+ */
+class ArrayConcatVisitor {
+ public:
+  ArrayConcatVisitor(Handle<FixedArray> storage,
+                     uint32_t index_limit,
+                     bool fast_elements) :
+      storage_(storage), index_limit_(index_limit),
+      fast_elements_(fast_elements), index_offset_(0) { }
+
+  void visit(uint32_t i, Handle<Object> elm) {
+    uint32_t index = i + index_offset_;
+    if (index >= index_limit_) return;
+
+    if (fast_elements_) {
+      ASSERT(index < static_cast<uint32_t>(storage_->length()));
+      storage_->set(index, *elm);
+
+    } else {
+      Handle<Dictionary> dict = Handle<Dictionary>::cast(storage_);
+      Handle<Dictionary> result =
+          Factory::DictionaryAtNumberPut(dict, index, elm);
+      if (!result.is_identical_to(dict))
+        storage_ = result;
+    }
+  }
+
+  void increase_index_offset(uint32_t delta) {
+    index_offset_ += delta;
+  }
+
+ private:
+  Handle<FixedArray> storage_;
+  uint32_t index_limit_;
+  bool fast_elements_;
+  uint32_t index_offset_;
+};
+
+
+/**
+ * A helper function that visits elements of a JSObject. Only elements
+ * whose index between 0 and range (exclusive) are visited.
+ *
+ * If the third parameter, visitor, is not NULL, the visitor is called
+ * with parameters, 'visitor_index_offset + element index' and the element.
+ *
+ * It returns the number of visisted elements.
+ */
+static uint32_t IterateElements(Handle<JSObject> receiver,
+                                uint32_t range,
+                                ArrayConcatVisitor* visitor) {
+  uint32_t num_of_elements = 0;
+
+  if (receiver->HasFastElements()) {
+    Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
+    uint32_t len = elements->length();
+    if (range < len) len = range;
+
+    for (uint32_t j = 0; j < len; j++) {
+      Handle<Object> e(elements->get(j));
+      if (!e->IsTheHole()) {
+        num_of_elements++;
+        if (visitor)
+          visitor->visit(j, e);
+      }
+    }
+
+  } else {
+    Handle<Dictionary> dict(receiver->element_dictionary());
+    uint32_t capacity = dict->Capacity();
+    for (uint32_t j = 0; j < capacity; j++) {
+      Handle<Object> k(dict->KeyAt(j));
+      if (dict->IsKey(*k)) {
+        ASSERT(k->IsNumber());
+        uint32_t index = static_cast<uint32_t>(k->Number());
+        if (index < range) {
+          num_of_elements++;
+          if (visitor) {
+            visitor->visit(index,
+                           Handle<Object>(dict->ValueAt(j)));
+          }
+        }
+      }
+    }
+  }
+
+  return num_of_elements;
+}
+
+
+/**
+ * A helper function that visits elements of an Array object, and elements
+ * on its prototypes.
+ *
+ * Elements on prototypes are visited first, and only elements whose indices
+ * less than Array length are visited.
+ *
+ * If a ArrayConcatVisitor object is given, the visitor is called with
+ * parameters, element's index + visitor_index_offset and the element.
+ */
+static uint32_t IterateArrayAndPrototypeElements(Handle<JSArray> array,
+                                                 ArrayConcatVisitor* visitor) {
+  uint32_t range = static_cast<uint32_t>(array->length()->Number());
+  Handle<Object> obj = array;
+
+  static const int kEstimatedPrototypes = 3;
+  List< Handle<JSObject> > objects(kEstimatedPrototypes);
+
+  // Visit prototype first. If an element on the prototype is shadowed by
+  // the inheritor using the same index, the ArrayConcatVisitor visits
+  // the prototype element before the shadowing element.
+  // The visitor can simply overwrite the old value by new value using
+  // the same index.  This follows Array::concat semantics.
+  while (!obj->IsNull()) {
+    objects.Add(Handle<JSObject>::cast(obj));
+    obj = Handle<Object>(obj->GetPrototype());
+  }
+
+  uint32_t nof_elements = 0;
+  for (int i = objects.length() - 1; i >= 0; i--) {
+    Handle<JSObject> obj = objects[i];
+    nof_elements +=
+        IterateElements(Handle<JSObject>::cast(obj), range, visitor);
+  }
+
+  return nof_elements;
+}
+
+
+/**
+ * A helper function of Runtime_ArrayConcat.
+ *
+ * The first argument is an Array of arrays and objects. It is the
+ * same as the arguments array of Array::concat JS function.
+ *
+ * If an argument is an Array object, the function visits array
+ * elements.  If an argument is not an Array object, the function
+ * visits the object as if it is an one-element array.
+ *
+ * If the result array index overflows 32-bit integer, the rounded
+ * non-negative number is used as new length. For example, if one
+ * array length is 2^32 - 1, second array length is 1, the
+ * concatenated array length is 0.
+ */
+static uint32_t IterateArguments(Handle<JSArray> arguments,
+                                 ArrayConcatVisitor* visitor) {
+  uint32_t visited_elements = 0;
+  uint32_t num_of_args = static_cast<uint32_t>(arguments->length()->Number());
+
+  for (uint32_t i = 0; i < num_of_args; i++) {
+    Handle<Object> obj(arguments->GetElement(i));
+    if (obj->IsJSArray()) {
+      Handle<JSArray> array = Handle<JSArray>::cast(obj);
+      uint32_t len = static_cast<uint32_t>(array->length()->Number());
+      uint32_t nof_elements =
+          IterateArrayAndPrototypeElements(array, visitor);
+      // Total elements of array and its prototype chain can be more than
+      // the array length, but ArrayConcat can only concatenate at most
+      // the array length number of elements.
+      visited_elements += (nof_elements > len) ? len : nof_elements;
+      if (visitor) visitor->increase_index_offset(len);
+
+    } else {
+      if (visitor) {
+        visitor->visit(0, obj);
+        visitor->increase_index_offset(1);
+      }
+      visited_elements++;
+    }
+  }
+  return visited_elements;
+}
+
+
+/**
+ * Array::concat implementation.
+ * See ECMAScript 262, 15.4.4.4.
+ */
+static Object* Runtime_ArrayConcat(Arguments args) {
+  ASSERT(args.length() == 1);
+  HandleScope handle_scope;
+
+  CONVERT_CHECKED(JSArray, arg_arrays, args[0]);
+  Handle<JSArray> arguments(arg_arrays);
+
+  // Pass 1: estimate the number of elements of the result
+  // (it could be more than real numbers if prototype has elements).
+  uint32_t result_length = 0;
+  uint32_t num_of_args = static_cast<uint32_t>(arguments->length()->Number());
+
+  { AssertNoAllocation nogc;
+    for (uint32_t i = 0; i < num_of_args; i++) {
+      Object* obj = arguments->GetElement(i);
+      if (obj->IsJSArray()) {
+        result_length +=
+            static_cast<uint32_t>(JSArray::cast(obj)->length()->Number());
+      } else {
+        result_length++;
+      }
+    }
+  }
+
+  // Allocate an empty array, will set length and content later.
+  Handle<JSArray> result = Factory::NewJSArray(0);
+
+  uint32_t estimate_nof_elements = IterateArguments(arguments, NULL);
+  // If estimated number of elements is more than half of length, a
+  // fixed array (fast case) is more time and space-efficient than a
+  // dictionary.
+  bool fast_case = (estimate_nof_elements * 2) >= result_length;
+
+  Handle<FixedArray> storage;
+  if (fast_case) {
+    // The backing storage array must have non-existing elements to
+    // preserve holes across concat operations.
+    storage = Factory::NewFixedArrayWithHoles(result_length);
+
+  } else {
+    // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
+    uint32_t at_least_space_for = estimate_nof_elements +
+                                  (estimate_nof_elements >> 2);
+    storage = Handle<FixedArray>::cast(
+                  Factory::NewDictionary(at_least_space_for));
+  }
+
+  Handle<Object> len = Factory::NewNumber(static_cast<double>(result_length));
+
+  ArrayConcatVisitor visitor(storage, result_length, fast_case);
+
+  IterateArguments(arguments, &visitor);
+
+  result->set_length(*len);
+  result->set_elements(*storage);
+
+  return *result;
+}
+
+
+// This will not allocate (flatten the string), but it may run
+// very slowly for very deeply nested ConsStrings.  For debugging use only.
+static Object* Runtime_GlobalPrint(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_CHECKED(String, string, args[0]);
+  StringInputBuffer buffer(string);
+  while (buffer.has_more()) {
+    uint16_t character = buffer.GetNext();
+    PrintF("%c", character);
+  }
+  return string;
+}
+
+
+static Object* Runtime_RemoveArrayHoles(Arguments args) {
+  ASSERT(args.length() == 1);
+  // Ignore the case if this is not a JSArray.
+  if (!args[0]->IsJSArray()) return args[0];
+  return JSArray::cast(args[0])->RemoveHoles();
+}
+
+
+// Move contents of argument 0 (an array) to argument 1 (an array)
+static Object* Runtime_MoveArrayContents(Arguments args) {
+  ASSERT(args.length() == 2);
+  CONVERT_CHECKED(JSArray, from, args[0]);
+  CONVERT_CHECKED(JSArray, to, args[1]);
+  to->SetContent(FixedArray::cast(from->elements()));
+  to->set_length(from->length());
+  from->SetContent(Heap::empty_fixed_array());
+  from->set_length(0);
+  return to;
+}
+
+
+// How many elements does this array have?
+static Object* Runtime_EstimateNumberOfElements(Arguments args) {
+  ASSERT(args.length() == 1);
+  CONVERT_CHECKED(JSArray, array, args[0]);
+  HeapObject* elements = array->elements();
+  if (elements->IsDictionary()) {
+    return Smi::FromInt(Dictionary::cast(elements)->NumberOfElements());
+  } else {
+    return array->length();
+  }
+}
+
+
+// Returns an array that tells you where in the [0, length) interval an array
+// might have elements.  Can either return keys or intervals.  Keys can have
+// gaps in (undefined).  Intervals can also span over some undefined keys.
+static Object* Runtime_GetArrayKeys(Arguments args) {
+  ASSERT(args.length() == 2);
+  HandleScope scope;
+  CONVERT_CHECKED(JSArray, raw_array, args[0]);
+  Handle<JSArray> array(raw_array);
+  CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
+  if (array->elements()->IsDictionary()) {
+    // Create an array and get all the keys into it, then remove all the
+    // keys that are not integers in the range 0 to length-1.
+    Handle<FixedArray> keys = GetKeysInFixedArrayFor(array);
+    int keys_length = keys->length();
+    for (int i = 0; i < keys_length; i++) {
+      Object* key = keys->get(i);
+      uint32_t index;
+      if (!Array::IndexFromObject(key, &index) || index >= length) {
+        // Zap invalid keys.
+        keys->set_undefined(i);
+      }
+    }
+    return *Factory::NewJSArrayWithElements(keys);
+  } else {
+    Handle<FixedArray> single_interval = Factory::NewFixedArray(2);
+    // -1 means start of array.
+    single_interval->set(0,
+                         Smi::FromInt(-1),
+                         SKIP_WRITE_BARRIER);
+    Handle<Object> length_object =
+        Factory::NewNumber(static_cast<double>(length));
+    single_interval->set(1, *length_object);
+    return *Factory::NewJSArrayWithElements(single_interval);
+  }
+}
+
+
+// DefineAccessor takes an optional final argument which is the
+// property attributes (eg, DONT_ENUM, DONT_DELETE).  IMPORTANT: due
+// to the way accessors are implemented, it is set for both the getter
+// and setter on the first call to DefineAccessor and ignored on
+// subsequent calls.
+static Object* Runtime_DefineAccessor(Arguments args) {
+  RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
+  // Compute attributes.
+  PropertyAttributes attributes = NONE;
+  if (args.length() == 5) {
+    CONVERT_CHECKED(Smi, attrs, args[4]);
+    int value = attrs->value();
+    // Only attribute bits should be set.
+    ASSERT((value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
+    attributes = static_cast<PropertyAttributes>(value);
+  }
+
+  CONVERT_CHECKED(JSObject, obj, args[0]);
+  CONVERT_CHECKED(String, name, args[1]);
+  CONVERT_CHECKED(Smi, flag, args[2]);
+  CONVERT_CHECKED(JSFunction, fun, args[3]);
+  return obj->DefineAccessor(name, flag->value() == 0, fun, attributes);
+}
+
+
+static Object* Runtime_LookupAccessor(Arguments args) {
+  ASSERT(args.length() == 3);
+  CONVERT_CHECKED(JSObject, obj, args[0]);
+  CONVERT_CHECKED(String, name, args[1]);
+  CONVERT_CHECKED(Smi, flag, args[2]);
+  return obj->LookupAccessor(name, flag->value() == 0);
+}
+
+
+// Helper functions for wrapping and unwrapping stack frame ids.
+static Smi* WrapFrameId(StackFrame::Id id) {
+  ASSERT(IsAligned(OffsetFrom(id), 4));
+  return Smi::FromInt(id >> 2);
+}
+
+
+static StackFrame::Id UnwrapFrameId(Smi* wrapped) {
+  return static_cast<StackFrame::Id>(wrapped->value() << 2);
+}
+
+
+// Adds a JavaScript function as a debug event listener.
+// args[0]: debug event listener function to set or null or undefined for
+//          clearing the event listener function
+// args[1]: object supplied during callback
+static Object* Runtime_SetDebugEventListener(Arguments args) {
+  ASSERT(args.length() == 2);
+  RUNTIME_ASSERT(args[0]->IsJSFunction() ||
+                 args[0]->IsUndefined() ||
+                 args[0]->IsNull());
+  Handle<Object> callback = args.at<Object>(0);
+  Handle<Object> data = args.at<Object>(1);
+  Debugger::SetEventListener(callback, data);
+
+  return Heap::undefined_value();
+}
+
+
+static Object* Runtime_Break(Arguments args) {
+  ASSERT(args.length() == 0);
+  StackGuard::DebugBreak();
+  return Heap::undefined_value();
+}
+
+
+// Find the length of the prototype chain that is to to handled as one. If a
+// prototype object is hidden it is to be viewed as part of the the object it
+// is prototype for.
+static int LocalPrototypeChainLength(JSObject* obj) {
+  int count = 1;
+  Object* proto = obj->GetPrototype();
+  while (proto->IsJSObject() &&
+         JSObject::cast(proto)->map()->is_hidden_prototype()) {
+    count++;
+    proto = JSObject::cast(proto)->GetPrototype();
+  }
+  return count;
+}
+
+
+static Object* DebugLookupResultValue(Object* receiver, LookupResult* result,
+                                      bool* caught_exception) {
+  Object* value;
+  switch (result->type()) {
+    case NORMAL: {
+      Dictionary* dict =
+          JSObject::cast(result->holder())->property_dictionary();
+      value = dict->ValueAt(result->GetDictionaryEntry());
+      if (value->IsTheHole()) {
+        return Heap::undefined_value();
+      }
+      return value;
+    }
+    case FIELD:
+      value =
+          JSObject::cast(
+              result->holder())->FastPropertyAt(result->GetFieldIndex());
+      if (value->IsTheHole()) {
+        return Heap::undefined_value();
+      }
+      return value;
+    case CONSTANT_FUNCTION:
+      return result->GetConstantFunction();
+    case CALLBACKS: {
+      Object* structure = result->GetCallbackObject();
+      if (structure->IsProxy()) {
+        AccessorDescriptor* callback =
+            reinterpret_cast<AccessorDescriptor*>(
+                Proxy::cast(structure)->proxy());
+        value = (callback->getter)(receiver, callback->data);
+        if (value->IsException()) {
+          value = Top::pending_exception();
+          Top::clear_pending_exception();
+          if (caught_exception != NULL) {
+            *caught_exception = true;
+          }
+        }
+        return value;
+      } else {
+        return Heap::undefined_value();
+      }
+    }
+    case INTERCEPTOR:
+    case MAP_TRANSITION:
+    case CONSTANT_TRANSITION:
+    case NULL_DESCRIPTOR:
+      return Heap::undefined_value();
+    default:
+      UNREACHABLE();
+  }
+  UNREACHABLE();
+  return Heap::undefined_value();
+}
+
+
+// Get debugger related details for an object property.
+// args[0]: object holding property
+// args[1]: name of the property
+//
+// The array returned contains the following information:
+// 0: Property value
+// 1: Property details
+// 2: Property value is exception
+// 3: Getter function if defined
+// 4: Setter function if defined
+// Items 2-4 are only filled if the property has either a getter or a setter
+// defined through __defineGetter__ and/or __defineSetter__.
+static Object* Runtime_DebugGetPropertyDetails(Arguments args) {
+  HandleScope scope;
+
+  ASSERT(args.length() == 2);
+
+  CONVERT_ARG_CHECKED(JSObject, obj, 0);
+  CONVERT_ARG_CHECKED(String, name, 1);
+
+  // Skip the global proxy as it has no properties and always delegates to the
+  // real global object.
+  if (obj->IsJSGlobalProxy()) {
+    obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
+  }
+
+
+  // Check if the name is trivially convertible to an index and get the element
+  // if so.
+  uint32_t index;
+  if (name->AsArrayIndex(&index)) {
+    Handle<FixedArray> details = Factory::NewFixedArray(2);
+    details->set(0, Runtime::GetElementOrCharAt(obj, index));
+    details->set(1, PropertyDetails(NONE, NORMAL).AsSmi());
+    return *Factory::NewJSArrayWithElements(details);
+  }
+
+  // Find the number of objects making up this.
+  int length = LocalPrototypeChainLength(*obj);
+
+  // Try local lookup on each of the objects.
+  LookupResult result;
+  Handle<JSObject> jsproto = obj;
+  for (int i = 0; i < length; i++) {
+    jsproto->LocalLookup(*name, &result);
+    if (result.IsProperty()) {
+      break;
+    }
+    if (i < length - 1) {
+      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
+    }
+  }
+
+  if (result.IsProperty()) {
+    bool caught_exception = false;
+    Object* value = DebugLookupResultValue(*obj, &result,
+                                           &caught_exception);
+    if (value->IsFailure()) return value;
+    Handle<Object> value_handle(value);
+    // If the callback object is a fixed array then it contains JavaScript
+    // getter and/or setter.
+    bool hasJavaScriptAccessors = result.type() == CALLBACKS &&
+                                  result.GetCallbackObject()->IsFixedArray();
+    Handle<FixedArray> details =
+        Factory::NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
+    details->set(0, *value_handle);
+    details->set(1, result.GetPropertyDetails().AsSmi());
+    if (hasJavaScriptAccessors) {
+      details->set(2,
+                   caught_exception ? Heap::true_value() : Heap::false_value());
+      details->set(3, FixedArray::cast(result.GetCallbackObject())->get(0));
+      details->set(4, FixedArray::cast(result.GetCallbackObject())->get(1));
+    }
+
+    return *Factory::NewJSArrayWithElements(details);
+  }
+  return Heap::undefined_value();
+}
+
+
+static Object* Runtime_DebugGetProperty(Arguments args) {
+  HandleScope scope;
+
+  ASSERT(args.length() == 2);
+
+  CONVERT_ARG_CHECKED(JSObject, obj, 0);
+  CONVERT_ARG_CHECKED(String, name, 1);
+
+  LookupResult result;
+  obj->Lookup(*name, &result);
+  if (result.IsProperty()) {
+    return DebugLookupResultValue(*obj, &result, NULL);
+  }
+  return Heap::undefined_value();
+}
+
+
+// Return the names of the local named properties.
+// args[0]: object
+static Object* Runtime_DebugLocalPropertyNames(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+  if (!args[0]->IsJSObject()) {
+    return Heap::undefined_value();
+  }
+  CONVERT_ARG_CHECKED(JSObject, obj, 0);
+
+  // Skip the global proxy as it has no properties and always delegates to the
+  // real global object.
+  if (obj->IsJSGlobalProxy()) {
+    obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
+  }
+
+  // Find the number of objects making up this.
+  int length = LocalPrototypeChainLength(*obj);
+
+  // Find the number of local properties for each of the objects.
+  int* local_property_count = NewArray<int>(length);
+  int total_property_count = 0;
+  Handle<JSObject> jsproto = obj;
+  for (int i = 0; i < length; i++) {
+    int n;
+    n = jsproto->NumberOfLocalProperties(static_cast<PropertyAttributes>(NONE));
+    local_property_count[i] = n;
+    total_property_count += n;
+    if (i < length - 1) {
+      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
+    }
+  }
+
+  // Allocate an array with storage for all the property names.
+  Handle<FixedArray> names = Factory::NewFixedArray(total_property_count);
+
+  // Get the property names.
+  jsproto = obj;
+  for (int i = 0; i < length; i++) {
+    jsproto->GetLocalPropertyNames(*names,
+                                   i == 0 ? 0 : local_property_count[i - 1]);
+    if (i < length - 1) {
+      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
+    }
+  }
+
+  DeleteArray(local_property_count);
+  return *Factory::NewJSArrayWithElements(names);
+}
+
+
+// Return the names of the local indexed properties.
+// args[0]: object
+static Object* Runtime_DebugLocalElementNames(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+  if (!args[0]->IsJSObject()) {
+    return Heap::undefined_value();
+  }
+  CONVERT_ARG_CHECKED(JSObject, obj, 0);
+
+  int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
+  Handle<FixedArray> names = Factory::NewFixedArray(n);
+  obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
+  return *Factory::NewJSArrayWithElements(names);
+}
+
+
+// Return the property type calculated from the property details.
+// args[0]: smi with property details.
+static Object* Runtime_DebugPropertyTypeFromDetails(Arguments args) {
+  ASSERT(args.length() == 1);
+  CONVERT_CHECKED(Smi, details, args[0]);
+  PropertyType type = PropertyDetails(details).type();
+  return Smi::FromInt(static_cast<int>(type));
+}
+
+
+// Return the property attribute calculated from the property details.
+// args[0]: smi with property details.
+static Object* Runtime_DebugPropertyAttributesFromDetails(Arguments args) {
+  ASSERT(args.length() == 1);
+  CONVERT_CHECKED(Smi, details, args[0]);
+  PropertyAttributes attributes = PropertyDetails(details).attributes();
+  return Smi::FromInt(static_cast<int>(attributes));
+}
+
+
+// Return the property insertion index calculated from the property details.
+// args[0]: smi with property details.
+static Object* Runtime_DebugPropertyIndexFromDetails(Arguments args) {
+  ASSERT(args.length() == 1);
+  CONVERT_CHECKED(Smi, details, args[0]);
+  int index = PropertyDetails(details).index();
+  return Smi::FromInt(index);
+}
+
+
+// Return information on whether an object has a named or indexed interceptor.
+// args[0]: object
+static Object* Runtime_DebugInterceptorInfo(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+  if (!args[0]->IsJSObject()) {
+    return Smi::FromInt(0);
+  }
+  CONVERT_ARG_CHECKED(JSObject, obj, 0);
+
+  int result = 0;
+  if (obj->HasNamedInterceptor()) result |= 2;
+  if (obj->HasIndexedInterceptor()) result |= 1;
+
+  return Smi::FromInt(result);
+}
+
+
+// Return property names from named interceptor.
+// args[0]: object
+static Object* Runtime_DebugNamedInterceptorPropertyNames(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+  CONVERT_ARG_CHECKED(JSObject, obj, 0);
+
+  if (obj->HasNamedInterceptor()) {
+    v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
+    if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
+  }
+  return Heap::undefined_value();
+}
+
+
+// Return element names from indexed interceptor.
+// args[0]: object
+static Object* Runtime_DebugIndexedInterceptorElementNames(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+  CONVERT_ARG_CHECKED(JSObject, obj, 0);
+
+  if (obj->HasIndexedInterceptor()) {
+    v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
+    if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
+  }
+  return Heap::undefined_value();
+}
+
+
+// Return property value from named interceptor.
+// args[0]: object
+// args[1]: property name
+static Object* Runtime_DebugNamedInterceptorPropertyValue(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 2);
+  CONVERT_ARG_CHECKED(JSObject, obj, 0);
+  RUNTIME_ASSERT(obj->HasNamedInterceptor());
+  CONVERT_ARG_CHECKED(String, name, 1);
+
+  PropertyAttributes attributes;
+  return obj->GetPropertyWithInterceptor(*obj, *name, &attributes);
+}
+
+
+// Return element value from indexed interceptor.
+// args[0]: object
+// args[1]: index
+static Object* Runtime_DebugIndexedInterceptorElementValue(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 2);
+  CONVERT_ARG_CHECKED(JSObject, obj, 0);
+  RUNTIME_ASSERT(obj->HasIndexedInterceptor());
+  CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
+
+  return obj->GetElementWithInterceptor(*obj, index);
+}
+
+
+static Object* Runtime_CheckExecutionState(Arguments args) {
+  ASSERT(args.length() >= 1);
+  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+  // Check that the break id is valid.
+  if (Debug::break_id() == 0 || break_id != Debug::break_id()) {
+    return Top::Throw(Heap::illegal_execution_state_symbol());
+  }
+
+  return Heap::true_value();
+}
+
+
+static Object* Runtime_GetFrameCount(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+
+  // Check arguments.
+  Object* result = Runtime_CheckExecutionState(args);
+  if (result->IsFailure()) return result;
+
+  // Count all frames which are relevant to debugging stack trace.
+  int n = 0;
+  StackFrame::Id id = Debug::break_frame_id();
+  if (id == StackFrame::NO_ID) {
+    // If there is no JavaScript stack frame count is 0.
+    return Smi::FromInt(0);
+  }
+  for (JavaScriptFrameIterator it(id); !it.done(); it.Advance()) n++;
+  return Smi::FromInt(n);
+}
+
+
+static const int kFrameDetailsFrameIdIndex = 0;
+static const int kFrameDetailsReceiverIndex = 1;
+static const int kFrameDetailsFunctionIndex = 2;
+static const int kFrameDetailsArgumentCountIndex = 3;
+static const int kFrameDetailsLocalCountIndex = 4;
+static const int kFrameDetailsSourcePositionIndex = 5;
+static const int kFrameDetailsConstructCallIndex = 6;
+static const int kFrameDetailsDebuggerFrameIndex = 7;
+static const int kFrameDetailsFirstDynamicIndex = 8;
+
+// Return an array with frame details
+// args[0]: number: break id
+// args[1]: number: frame index
+//
+// The array returned contains the following information:
+// 0: Frame id
+// 1: Receiver
+// 2: Function
+// 3: Argument count
+// 4: Local count
+// 5: Source position
+// 6: Constructor call
+// 7: Debugger frame
+// Arguments name, value
+// Locals name, value
+static Object* Runtime_GetFrameDetails(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 2);
+
+  // Check arguments.
+  Object* check = Runtime_CheckExecutionState(args);
+  if (check->IsFailure()) return check;
+  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
+
+  // Find the relevant frame with the requested index.
+  StackFrame::Id id = Debug::break_frame_id();
+  if (id == StackFrame::NO_ID) {
+    // If there are no JavaScript stack frames return undefined.
+    return Heap::undefined_value();
+  }
+  int count = 0;
+  JavaScriptFrameIterator it(id);
+  for (; !it.done(); it.Advance()) {
+    if (count == index) break;
+    count++;
+  }
+  if (it.done()) return Heap::undefined_value();
+
+  // Traverse the saved contexts chain to find the active context for the
+  // selected frame.
+  SaveContext* save = Top::save_context();
+  while (save != NULL && !save->below(it.frame())) {
+    save = save->prev();
+  }
+  ASSERT(save != NULL);
+
+  // Get the frame id.
+  Handle<Object> frame_id(WrapFrameId(it.frame()->id()));
+
+  // Find source position.
+  int position = it.frame()->code()->SourcePosition(it.frame()->pc());
+
+  // Check for constructor frame.
+  bool constructor = it.frame()->IsConstructor();
+
+  // Get code and read scope info from it for local variable information.
+  Handle<Code> code(it.frame()->code());
+  ScopeInfo<> info(*code);
+
+  // Get the context.
+  Handle<Context> context(Context::cast(it.frame()->context()));
+
+  // Get the locals names and values into a temporary array.
+  //
+  // TODO(1240907): Hide compiler-introduced stack variables
+  // (e.g. .result)?  For users of the debugger, they will probably be
+  // confusing.
+  Handle<FixedArray> locals = Factory::NewFixedArray(info.NumberOfLocals() * 2);
+  for (int i = 0; i < info.NumberOfLocals(); i++) {
+    // Name of the local.
+    locals->set(i * 2, *info.LocalName(i));
+
+    // Fetch the value of the local - either from the stack or from a
+    // heap-allocated context.
+    if (i < info.number_of_stack_slots()) {
+      locals->set(i * 2 + 1, it.frame()->GetExpression(i));
+    } else {
+      Handle<String> name = info.LocalName(i);
+      // Traverse the context chain to the function context as all local
+      // variables stored in the context will be on the function context.
+      while (!context->is_function_context()) {
+        context = Handle<Context>(context->previous());
+      }
+      ASSERT(context->is_function_context());
+      locals->set(i * 2 + 1,
+                  context->get(ScopeInfo<>::ContextSlotIndex(*code, *name,
+                                                             NULL)));
+    }
+  }
+
+  // Now advance to the arguments adapter frame (if any). If contains all
+  // the provided parameters and
+
+  // Now advance to the arguments adapter frame (if any). It contains all
+  // the provided parameters whereas the function frame always have the number
+  // of arguments matching the functions parameters. The rest of the
+  // information (except for what is collected above) is the same.
+  it.AdvanceToArgumentsFrame();
+
+  // Find the number of arguments to fill. At least fill the number of
+  // parameters for the function and fill more if more parameters are provided.
+  int argument_count = info.number_of_parameters();
+  if (argument_count < it.frame()->GetProvidedParametersCount()) {
+    argument_count = it.frame()->GetProvidedParametersCount();
+  }
+
+  // Calculate the size of the result.
+  int details_size = kFrameDetailsFirstDynamicIndex +
+                     2 * (argument_count + info.NumberOfLocals());
+  Handle<FixedArray> details = Factory::NewFixedArray(details_size);
+
+  // Add the frame id.
+  details->set(kFrameDetailsFrameIdIndex, *frame_id);
+
+  // Add the function (same as in function frame).
+  details->set(kFrameDetailsFunctionIndex, it.frame()->function());
+
+  // Add the arguments count.
+  details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
+
+  // Add the locals count
+  details->set(kFrameDetailsLocalCountIndex,
+               Smi::FromInt(info.NumberOfLocals()));
+
+  // Add the source position.
+  if (position != RelocInfo::kNoPosition) {
+    details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
+  } else {
+    details->set(kFrameDetailsSourcePositionIndex, Heap::undefined_value());
+  }
+
+  // Add the constructor information.
+  details->set(kFrameDetailsConstructCallIndex, Heap::ToBoolean(constructor));
+
+  // Add information on whether this frame is invoked in the debugger context.
+  details->set(kFrameDetailsDebuggerFrameIndex,
+               Heap::ToBoolean(*save->context() == *Debug::debug_context()));
+
+  // Fill the dynamic part.
+  int details_index = kFrameDetailsFirstDynamicIndex;
+
+  // Add arguments name and value.
+  for (int i = 0; i < argument_count; i++) {
+    // Name of the argument.
+    if (i < info.number_of_parameters()) {
+      details->set(details_index++, *info.parameter_name(i));
+    } else {
+      details->set(details_index++, Heap::undefined_value());
+    }
+
+    // Parameter value.
+    if (i < it.frame()->GetProvidedParametersCount()) {
+      details->set(details_index++, it.frame()->GetParameter(i));
+    } else {
+      details->set(details_index++, Heap::undefined_value());
+    }
+  }
+
+  // Add locals name and value from the temporary copy from the function frame.
+  for (int i = 0; i < info.NumberOfLocals() * 2; i++) {
+    details->set(details_index++, locals->get(i));
+  }
+
+  // Add the receiver (same as in function frame).
+  // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
+  // THE FRAME ITERATOR TO WRAP THE RECEIVER.
+  Handle<Object> receiver(it.frame()->receiver());
+  if (!receiver->IsJSObject()) {
+    // If the receiver is NOT a JSObject we have hit an optimization
+    // where a value object is not converted into a wrapped JS objects.
+    // To hide this optimization from the debugger, we wrap the receiver
+    // by creating correct wrapper object based on the calling frame's
+    // global context.
+    it.Advance();
+    Handle<Context> calling_frames_global_context(
+        Context::cast(Context::cast(it.frame()->context())->global_context()));
+    receiver = Factory::ToObject(receiver, calling_frames_global_context);
+  }
+  details->set(kFrameDetailsReceiverIndex, *receiver);
+
+  ASSERT_EQ(details_size, details_index);
+  return *Factory::NewJSArrayWithElements(details);
+}
+
+
+static Object* Runtime_GetCFrames(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+  Object* result = Runtime_CheckExecutionState(args);
+  if (result->IsFailure()) return result;
+
+  static const int kMaxCFramesSize = 200;
+  OS::StackFrame frames[kMaxCFramesSize];
+  int frames_count = OS::StackWalk(frames, kMaxCFramesSize);
+  if (frames_count == OS::kStackWalkError) {
+    return Heap::undefined_value();
+  }
+
+  Handle<String> address_str = Factory::LookupAsciiSymbol("address");
+  Handle<String> text_str = Factory::LookupAsciiSymbol("text");
+  Handle<FixedArray> frames_array = Factory::NewFixedArray(frames_count);
+  for (int i = 0; i < frames_count; i++) {
+    Handle<JSObject> frame_value = Factory::NewJSObject(Top::object_function());
+    frame_value->SetProperty(
+        *address_str,
+        *Factory::NewNumberFromInt(reinterpret_cast<int>(frames[i].address)),
+        NONE);
+
+    // Get the stack walk text for this frame.
+    Handle<String> frame_text;
+    if (strlen(frames[i].text) > 0) {
+      Vector<const char> str(frames[i].text, strlen(frames[i].text));
+      frame_text = Factory::NewStringFromAscii(str);
+    }
+
+    if (!frame_text.is_null()) {
+      frame_value->SetProperty(*text_str, *frame_text, NONE);
+    }
+
+    frames_array->set(i, *frame_value);
+  }
+  return *Factory::NewJSArrayWithElements(frames_array);
+}
+
+
+static Object* Runtime_GetThreadCount(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+
+  // Check arguments.
+  Object* result = Runtime_CheckExecutionState(args);
+  if (result->IsFailure()) return result;
+
+  // Count all archived V8 threads.
+  int n = 0;
+  for (ThreadState* thread = ThreadState::FirstInUse();
+       thread != NULL;
+       thread = thread->Next()) {
+    n++;
+  }
+
+  // Total number of threads is current thread and archived threads.
+  return Smi::FromInt(n + 1);
+}
+
+
+static const int kThreadDetailsCurrentThreadIndex = 0;
+static const int kThreadDetailsThreadIdIndex = 1;
+static const int kThreadDetailsSize = 2;
+
+// Return an array with thread details
+// args[0]: number: break id
+// args[1]: number: thread index
+//
+// The array returned contains the following information:
+// 0: Is current thread?
+// 1: Thread id
+static Object* Runtime_GetThreadDetails(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 2);
+
+  // Check arguments.
+  Object* check = Runtime_CheckExecutionState(args);
+  if (check->IsFailure()) return check;
+  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
+
+  // Allocate array for result.
+  Handle<FixedArray> details = Factory::NewFixedArray(kThreadDetailsSize);
+
+  // Thread index 0 is current thread.
+  if (index == 0) {
+    // Fill the details.
+    details->set(kThreadDetailsCurrentThreadIndex, Heap::true_value());
+    details->set(kThreadDetailsThreadIdIndex,
+                 Smi::FromInt(ThreadManager::CurrentId()));
+  } else {
+    // Find the thread with the requested index.
+    int n = 1;
+    ThreadState* thread = ThreadState::FirstInUse();
+    while (index != n && thread != NULL) {
+      thread = thread->Next();
+      n++;
+    }
+    if (thread == NULL) {
+      return Heap::undefined_value();
+    }
+
+    // Fill the details.
+    details->set(kThreadDetailsCurrentThreadIndex, Heap::false_value());
+    details->set(kThreadDetailsThreadIdIndex, Smi::FromInt(thread->id()));
+  }
+
+  // Convert to JS array and return.
+  return *Factory::NewJSArrayWithElements(details);
+}
+
+
+static Object* Runtime_GetBreakLocations(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+
+  CONVERT_ARG_CHECKED(JSFunction, raw_fun, 0);
+  Handle<SharedFunctionInfo> shared(raw_fun->shared());
+  // Find the number of break points
+  Handle<Object> break_locations = Debug::GetSourceBreakLocations(shared);
+  if (break_locations->IsUndefined()) return Heap::undefined_value();
+  // Return array as JS array
+  return *Factory::NewJSArrayWithElements(
+      Handle<FixedArray>::cast(break_locations));
+}
+
+
+// Set a break point in a function
+// args[0]: function
+// args[1]: number: break source position (within the function source)
+// args[2]: number: break point object
+static Object* Runtime_SetFunctionBreakPoint(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 3);
+  CONVERT_ARG_CHECKED(JSFunction, raw_fun, 0);
+  Handle<SharedFunctionInfo> shared(raw_fun->shared());
+  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
+  RUNTIME_ASSERT(source_position >= 0);
+  Handle<Object> break_point_object_arg = args.at<Object>(2);
+
+  // Set break point.
+  Debug::SetBreakPoint(shared, source_position, break_point_object_arg);
+
+  return Heap::undefined_value();
+}
+
+
+Object* Runtime::FindSharedFunctionInfoInScript(Handle<Script> script,
+                                                int position) {
+  // Iterate the heap looking for SharedFunctionInfo generated from the
+  // script. The inner most SharedFunctionInfo containing the source position
+  // for the requested break point is found.
+  // NOTE: This might reqire several heap iterations. If the SharedFunctionInfo
+  // which is found is not compiled it is compiled and the heap is iterated
+  // again as the compilation might create inner functions from the newly
+  // compiled function and the actual requested break point might be in one of
+  // these functions.
+  bool done = false;
+  // The current candidate for the source position:
+  int target_start_position = RelocInfo::kNoPosition;
+  Handle<SharedFunctionInfo> target;
+  // The current candidate for the last function in script:
+  Handle<SharedFunctionInfo> last;
+  while (!done) {
+    HeapIterator iterator;
+    while (iterator.has_next()) {
+      HeapObject* obj = iterator.next();
+      ASSERT(obj != NULL);
+      if (obj->IsSharedFunctionInfo()) {
+        Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(obj));
+        if (shared->script() == *script) {
+          // If the SharedFunctionInfo found has the requested script data and
+          // contains the source position it is a candidate.
+          int start_position = shared->function_token_position();
+          if (start_position == RelocInfo::kNoPosition) {
+            start_position = shared->start_position();
+          }
+          if (start_position <= position &&
+              position <= shared->end_position()) {
+            // If there is no candidate or this function is within the current
+            // candidate this is the new candidate.
+            if (target.is_null()) {
+              target_start_position = start_position;
+              target = shared;
+            } else {
+              if (target_start_position < start_position &&
+                  shared->end_position() < target->end_position()) {
+                target_start_position = start_position;
+                target = shared;
+              }
+            }
+          }
+
+          // Keep track of the last function in the script.
+          if (last.is_null() ||
+              shared->end_position() > last->start_position()) {
+            last = shared;
+          }
+        }
+      }
+    }
+
+    // Make sure some candidate is selected.
+    if (target.is_null()) {
+      if (!last.is_null()) {
+        // Position after the last function - use last.
+        target = last;
+      } else {
+        // Unable to find function - possibly script without any function.
+        return Heap::undefined_value();
+      }
+    }
+
+    // If the candidate found is compiled we are done. NOTE: when lazy
+    // compilation of inner functions is introduced some additional checking
+    // needs to be done here to compile inner functions.
+    done = target->is_compiled();
+    if (!done) {
+      // If the candidate is not compiled compile it to reveal any inner
+      // functions which might contain the requested source position.
+      CompileLazyShared(target, KEEP_EXCEPTION, 0);
+    }
+  }
+
+  return *target;
+}
+
+
+// Change the state of a break point in a script. NOTE: Regarding performance
+// see the NOTE for GetScriptFromScriptData.
+// args[0]: script to set break point in
+// args[1]: number: break source position (within the script source)
+// args[2]: number: break point object
+static Object* Runtime_SetScriptBreakPoint(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 3);
+  CONVERT_ARG_CHECKED(JSValue, wrapper, 0);
+  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
+  RUNTIME_ASSERT(source_position >= 0);
+  Handle<Object> break_point_object_arg = args.at<Object>(2);
+
+  // Get the script from the script wrapper.
+  RUNTIME_ASSERT(wrapper->value()->IsScript());
+  Handle<Script> script(Script::cast(wrapper->value()));
+
+  Object* result = Runtime::FindSharedFunctionInfoInScript(
+      script, source_position);
+  if (!result->IsUndefined()) {
+    Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
+    // Find position within function. The script position might be before the
+    // source position of the first function.
+    int position;
+    if (shared->start_position() > source_position) {
+      position = 0;
+    } else {
+      position = source_position - shared->start_position();
+    }
+    Debug::SetBreakPoint(shared, position, break_point_object_arg);
+  }
+  return  Heap::undefined_value();
+}
+
+
+// Clear a break point
+// args[0]: number: break point object
+static Object* Runtime_ClearBreakPoint(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+  Handle<Object> break_point_object_arg = args.at<Object>(0);
+
+  // Clear break point.
+  Debug::ClearBreakPoint(break_point_object_arg);
+
+  return Heap::undefined_value();
+}
+
+
+// Change the state of break on exceptions
+// args[0]: boolean indicating uncaught exceptions
+// args[1]: boolean indicating on/off
+static Object* Runtime_ChangeBreakOnException(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 2);
+  ASSERT(args[0]->IsNumber());
+  ASSERT(args[1]->IsBoolean());
+
+  // Update break point state
+  ExceptionBreakType type =
+      static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
+  bool enable = args[1]->ToBoolean()->IsTrue();
+  Debug::ChangeBreakOnException(type, enable);
+  return Heap::undefined_value();
+}
+
+
+// Prepare for stepping
+// args[0]: break id for checking execution state
+// args[1]: step action from the enumeration StepAction
+// args[2]: number of times to perform the step
+static Object* Runtime_PrepareStep(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 3);
+  // Check arguments.
+  Object* check = Runtime_CheckExecutionState(args);
+  if (check->IsFailure()) return check;
+  if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
+    return Top::Throw(Heap::illegal_argument_symbol());
+  }
+
+  // Get the step action and check validity.
+  StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
+  if (step_action != StepIn &&
+      step_action != StepNext &&
+      step_action != StepOut &&
+      step_action != StepInMin &&
+      step_action != StepMin) {
+    return Top::Throw(Heap::illegal_argument_symbol());
+  }
+
+  // Get the number of steps.
+  int step_count = NumberToInt32(args[2]);
+  if (step_count < 1) {
+    return Top::Throw(Heap::illegal_argument_symbol());
+  }
+
+  // Prepare step.
+  Debug::PrepareStep(static_cast<StepAction>(step_action), step_count);
+  return Heap::undefined_value();
+}
+
+
+// Clear all stepping set by PrepareStep.
+static Object* Runtime_ClearStepping(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 0);
+  Debug::ClearStepping();
+  return Heap::undefined_value();
+}
+
+
+// Creates a copy of the with context chain. The copy of the context chain is
+// is linked to the function context supplied.
+static Handle<Context> CopyWithContextChain(Handle<Context> context_chain,
+                                            Handle<Context> function_context) {
+  // At the bottom of the chain. Return the function context to link to.
+  if (context_chain->is_function_context()) {
+    return function_context;
+  }
+
+  // Recursively copy the with contexts.
+  Handle<Context> previous(context_chain->previous());
+  Handle<JSObject> extension(JSObject::cast(context_chain->extension()));
+  return Factory::NewWithContext(
+      CopyWithContextChain(function_context, previous),
+      extension,
+      context_chain->IsCatchContext());
+}
+
+
+// Helper function to find or create the arguments object for
+// Runtime_DebugEvaluate.
+static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame,
+                                         Handle<JSFunction> function,
+                                         Handle<Code> code,
+                                         const ScopeInfo<>* sinfo,
+                                         Handle<Context> function_context) {
+  // Try to find the value of 'arguments' to pass as parameter. If it is not
+  // found (that is the debugged function does not reference 'arguments' and
+  // does not support eval) then create an 'arguments' object.
+  int index;
+  if (sinfo->number_of_stack_slots() > 0) {
+    index = ScopeInfo<>::StackSlotIndex(*code, Heap::arguments_symbol());
+    if (index != -1) {
+      return Handle<Object>(frame->GetExpression(index));
+    }
+  }
+
+  if (sinfo->number_of_context_slots() > Context::MIN_CONTEXT_SLOTS) {
+    index = ScopeInfo<>::ContextSlotIndex(*code, Heap::arguments_symbol(),
+                                          NULL);
+    if (index != -1) {
+      return Handle<Object>(function_context->get(index));
+    }
+  }
+
+  const int length = frame->GetProvidedParametersCount();
+  Handle<JSObject> arguments = Factory::NewArgumentsObject(function, length);
+  Handle<FixedArray> array = Factory::NewFixedArray(length);
+  WriteBarrierMode mode = array->GetWriteBarrierMode();
+  for (int i = 0; i < length; i++) {
+    array->set(i, frame->GetParameter(i), mode);
+  }
+  arguments->set_elements(*array);
+  return arguments;
+}
+
+
+// Evaluate a piece of JavaScript in the context of a stack frame for
+// debugging. This is accomplished by creating a new context which in its
+// extension part has all the parameters and locals of the function on the
+// stack frame. A function which calls eval with the code to evaluate is then
+// compiled in this context and called in this context. As this context
+// replaces the context of the function on the stack frame a new (empty)
+// function is created as well to be used as the closure for the context.
+// This function and the context acts as replacements for the function on the
+// stack frame presenting the same view of the values of parameters and
+// local variables as if the piece of JavaScript was evaluated at the point
+// where the function on the stack frame is currently stopped.
+static Object* Runtime_DebugEvaluate(Arguments args) {
+  HandleScope scope;
+
+  // Check the execution state and decode arguments frame and source to be
+  // evaluated.
+  ASSERT(args.length() == 4);
+  Object* check_result = Runtime_CheckExecutionState(args);
+  if (check_result->IsFailure()) return check_result;
+  CONVERT_CHECKED(Smi, wrapped_id, args[1]);
+  CONVERT_ARG_CHECKED(String, source, 2);
+  CONVERT_BOOLEAN_CHECKED(disable_break, args[3]);
+
+  // Handle the processing of break.
+  DisableBreak disable_break_save(disable_break);
+
+  // Get the frame where the debugging is performed.
+  StackFrame::Id id = UnwrapFrameId(wrapped_id);
+  JavaScriptFrameIterator it(id);
+  JavaScriptFrame* frame = it.frame();
+  Handle<JSFunction> function(JSFunction::cast(frame->function()));
+  Handle<Code> code(function->code());
+  ScopeInfo<> sinfo(*code);
+
+  // Traverse the saved contexts chain to find the active context for the
+  // selected frame.
+  SaveContext* save = Top::save_context();
+  while (save != NULL && !save->below(frame)) {
+    save = save->prev();
+  }
+  ASSERT(save != NULL);
+  SaveContext savex;
+  Top::set_context(*(save->context()));
+
+  // Create the (empty) function replacing the function on the stack frame for
+  // the purpose of evaluating in the context created below. It is important
+  // that this function does not describe any parameters and local variables
+  // in the context. If it does then this will cause problems with the lookup
+  // in Context::Lookup, where context slots for parameters and local variables
+  // are looked at before the extension object.
+  Handle<JSFunction> go_between =
+      Factory::NewFunction(Factory::empty_string(), Factory::undefined_value());
+  go_between->set_context(function->context());
+#ifdef DEBUG
+  ScopeInfo<> go_between_sinfo(go_between->shared()->code());
+  ASSERT(go_between_sinfo.number_of_parameters() == 0);
+  ASSERT(go_between_sinfo.number_of_context_slots() == 0);
+#endif
+
+  // Allocate and initialize a context extension object with all the
+  // arguments, stack locals heap locals and extension properties of the
+  // debugged function.
+  Handle<JSObject> context_ext = Factory::NewJSObject(Top::object_function());
+  // First fill all parameters to the context extension.
+  for (int i = 0; i < sinfo.number_of_parameters(); ++i) {
+    SetProperty(context_ext,
+                sinfo.parameter_name(i),
+                Handle<Object>(frame->GetParameter(i)), NONE);
+  }
+  // Second fill all stack locals to the context extension.
+  for (int i = 0; i < sinfo.number_of_stack_slots(); i++) {
+    SetProperty(context_ext,
+                sinfo.stack_slot_name(i),
+                Handle<Object>(frame->GetExpression(i)), NONE);
+  }
+  // Third fill all context locals to the context extension.
+  Handle<Context> frame_context(Context::cast(frame->context()));
+  Handle<Context> function_context(frame_context->fcontext());
+  for (int i = Context::MIN_CONTEXT_SLOTS;
+       i < sinfo.number_of_context_slots();
+       ++i) {
+    int context_index =
+        ScopeInfo<>::ContextSlotIndex(*code, *sinfo.context_slot_name(i), NULL);
+    SetProperty(context_ext,
+                sinfo.context_slot_name(i),
+                Handle<Object>(function_context->get(context_index)), NONE);
+  }
+  // Finally copy any properties from the function context extension. This will
+  // be variables introduced by eval.
+  if (function_context->has_extension() &&
+      !function_context->IsGlobalContext()) {
+    Handle<JSObject> ext(JSObject::cast(function_context->extension()));
+    Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext);
+    for (int i = 0; i < keys->length(); i++) {
+      // Names of variables introduced by eval are strings.
+      ASSERT(keys->get(i)->IsString());
+      Handle<String> key(String::cast(keys->get(i)));
+      SetProperty(context_ext, key, GetProperty(ext, key), NONE);
+    }
+  }
+
+  // Allocate a new context for the debug evaluation and set the extension
+  // object build.
+  Handle<Context> context =
+      Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, go_between);
+  context->set_extension(*context_ext);
+  // Copy any with contexts present and chain them in front of this context.
+  context = CopyWithContextChain(frame_context, context);
+
+  // Wrap the evaluation statement in a new function compiled in the newly
+  // created context. The function has one parameter which has to be called
+  // 'arguments'. This it to have access to what would have been 'arguments' in
+  // the function being debugged.
+  // function(arguments,__source__) {return eval(__source__);}
+  static const char* source_str =
+      "function(arguments,__source__){return eval(__source__);}";
+  static const int source_str_length = strlen(source_str);
+  Handle<String> function_source =
+      Factory::NewStringFromAscii(Vector<const char>(source_str,
+                                                     source_str_length));
+  Handle<JSFunction> boilerplate =
+      Compiler::CompileEval(function_source,
+                            context,
+                            0,
+                            context->IsGlobalContext());
+  if (boilerplate.is_null()) return Failure::Exception();
+  Handle<JSFunction> compiled_function =
+      Factory::NewFunctionFromBoilerplate(boilerplate, context);
+
+  // Invoke the result of the compilation to get the evaluation function.
+  bool has_pending_exception;
+  Handle<Object> receiver(frame->receiver());
+  Handle<Object> evaluation_function =
+      Execution::Call(compiled_function, receiver, 0, NULL,
+                      &has_pending_exception);
+  if (has_pending_exception) return Failure::Exception();
+
+  Handle<Object> arguments = GetArgumentsObject(frame, function, code, &sinfo,
+                                                function_context);
+
+  // Invoke the evaluation function and return the result.
+  const int argc = 2;
+  Object** argv[argc] = { arguments.location(),
+                          Handle<Object>::cast(source).location() };
+  Handle<Object> result =
+      Execution::Call(Handle<JSFunction>::cast(evaluation_function), receiver,
+                      argc, argv, &has_pending_exception);
+  if (has_pending_exception) return Failure::Exception();
+  return *result;
+}
+
+
+static Object* Runtime_DebugEvaluateGlobal(Arguments args) {
+  HandleScope scope;
+
+  // Check the execution state and decode arguments frame and source to be
+  // evaluated.
+  ASSERT(args.length() == 3);
+  Object* check_result = Runtime_CheckExecutionState(args);
+  if (check_result->IsFailure()) return check_result;
+  CONVERT_ARG_CHECKED(String, source, 1);
+  CONVERT_BOOLEAN_CHECKED(disable_break, args[2]);
+
+  // Handle the processing of break.
+  DisableBreak disable_break_save(disable_break);
+
+  // Enter the top context from before the debugger was invoked.
+  SaveContext save;
+  SaveContext* top = &save;
+  while (top != NULL && *top->context() == *Debug::debug_context()) {
+    top = top->prev();
+  }
+  if (top != NULL) {
+    Top::set_context(*top->context());
+  }
+
+  // Get the global context now set to the top context from before the
+  // debugger was invoked.
+  Handle<Context> context = Top::global_context();
+
+  // Compile the source to be evaluated.
+  Handle<JSFunction> boilerplate =
+      Handle<JSFunction>(Compiler::CompileEval(source, context, 0, true));
+  if (boilerplate.is_null()) return Failure::Exception();
+  Handle<JSFunction> compiled_function =
+      Handle<JSFunction>(Factory::NewFunctionFromBoilerplate(boilerplate,
+                                                             context));
+
+  // Invoke the result of the compilation to get the evaluation function.
+  bool has_pending_exception;
+  Handle<Object> receiver = Top::global();
+  Handle<Object> result =
+    Execution::Call(compiled_function, receiver, 0, NULL,
+                    &has_pending_exception);
+  if (has_pending_exception) return Failure::Exception();
+  return *result;
+}
+
+
+// If an object given is an external string, check that the underlying
+// resource is accessible. For other kinds of objects, always return true.
+static bool IsExternalStringValid(Object* str) {
+  if (!str->IsString() || !StringShape(String::cast(str)).IsExternal()) {
+    return true;
+  }
+  if (StringShape(String::cast(str)).IsAsciiRepresentation()) {
+    return ExternalAsciiString::cast(str)->resource() != NULL;
+  } else if (StringShape(String::cast(str)).IsTwoByteRepresentation()) {
+    return ExternalTwoByteString::cast(str)->resource() != NULL;
+  } else {
+    return true;
+  }
+}
+
+
+// Helper function used by Runtime_DebugGetLoadedScripts below.
+static int DebugGetLoadedScripts(FixedArray* instances, int instances_size) {
+  NoHandleAllocation ha;
+  AssertNoAllocation no_alloc;
+
+  // Scan heap for Script objects.
+  int count = 0;
+  HeapIterator iterator;
+  while (iterator.has_next()) {
+    HeapObject* obj = iterator.next();
+    ASSERT(obj != NULL);
+    if (obj->IsScript() && IsExternalStringValid(Script::cast(obj)->source())) {
+      if (instances != NULL && count < instances_size) {
+        instances->set(count, obj);
+      }
+      count++;
+    }
+  }
+
+  return count;
+}
+
+
+static Object* Runtime_DebugGetLoadedScripts(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 0);
+
+  // Perform two GCs to get rid of all unreferenced scripts. The first GC gets
+  // rid of all the cached script wrappers and the second gets rid of the
+  // scripts which is no longer referenced.
+  Heap::CollectAllGarbage();
+  Heap::CollectAllGarbage();
+
+  // Get the number of scripts.
+  int count;
+  count = DebugGetLoadedScripts(NULL, 0);
+
+  // Allocate an array to hold the result.
+  Handle<FixedArray> instances = Factory::NewFixedArray(count);
+
+  // Fill the script objects.
+  count = DebugGetLoadedScripts(*instances, count);
+
+  // Convert the script objects to proper JS objects.
+  for (int i = 0; i < count; i++) {
+    Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
+    // Get the script wrapper in a local handle before calling GetScriptWrapper,
+    // because using
+    //   instances->set(i, *GetScriptWrapper(script))
+    // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
+    // already have deferenced the instances handle.
+    Handle<JSValue> wrapper = GetScriptWrapper(script);
+    instances->set(i, *wrapper);
+  }
+
+  // Return result as a JS array.
+  Handle<JSObject> result = Factory::NewJSObject(Top::array_function());
+  Handle<JSArray>::cast(result)->SetContent(*instances);
+  return *result;
+}
+
+
+// Helper function used by Runtime_DebugReferencedBy below.
+static int DebugReferencedBy(JSObject* target,
+                             Object* instance_filter, int max_references,
+                             FixedArray* instances, int instances_size,
+                             JSFunction* arguments_function) {
+  NoHandleAllocation ha;
+  AssertNoAllocation no_alloc;
+
+  // Iterate the heap.
+  int count = 0;
+  JSObject* last = NULL;
+  HeapIterator iterator;
+  while (iterator.has_next() &&
+         (max_references == 0 || count < max_references)) {
+    // Only look at all JSObjects.
+    HeapObject* heap_obj = iterator.next();
+    if (heap_obj->IsJSObject()) {
+      // Skip context extension objects and argument arrays as these are
+      // checked in the context of functions using them.
+      JSObject* obj = JSObject::cast(heap_obj);
+      if (obj->IsJSContextExtensionObject() ||
+          obj->map()->constructor() == arguments_function) {
+        continue;
+      }
+
+      // Check if the JS object has a reference to the object looked for.
+      if (obj->ReferencesObject(target)) {
+        // Check instance filter if supplied. This is normally used to avoid
+        // references from mirror objects (see Runtime_IsInPrototypeChain).
+        if (!instance_filter->IsUndefined()) {
+          Object* V = obj;
+          while (true) {
+            Object* prototype = V->GetPrototype();
+            if (prototype->IsNull()) {
+              break;
+            }
+            if (instance_filter == prototype) {
+              obj = NULL;  // Don't add this object.
+              break;
+            }
+            V = prototype;
+          }
+        }
+
+        if (obj != NULL) {
+          // Valid reference found add to instance array if supplied an update
+          // count.
+          if (instances != NULL && count < instances_size) {
+            instances->set(count, obj);
+          }
+          last = obj;
+          count++;
+        }
+      }
+    }
+  }
+
+  // Check for circular reference only. This can happen when the object is only
+  // referenced from mirrors and has a circular reference in which case the
+  // object is not really alive and would have been garbage collected if not
+  // referenced from the mirror.
+  if (count == 1 && last == target) {
+    count = 0;
+  }
+
+  // Return the number of referencing objects found.
+  return count;
+}
+
+
+// Scan the heap for objects with direct references to an object
+// args[0]: the object to find references to
+// args[1]: constructor function for instances to exclude (Mirror)
+// args[2]: the the maximum number of objects to return
+static Object* Runtime_DebugReferencedBy(Arguments args) {
+  ASSERT(args.length() == 3);
+
+  // First perform a full GC in order to avoid references from dead objects.
+  Heap::CollectAllGarbage();
+
+  // Check parameters.
+  CONVERT_CHECKED(JSObject, target, args[0]);
+  Object* instance_filter = args[1];
+  RUNTIME_ASSERT(instance_filter->IsUndefined() ||
+                 instance_filter->IsJSObject());
+  CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
+  RUNTIME_ASSERT(max_references >= 0);
+
+  // Get the constructor function for context extension and arguments array.
+  JSObject* arguments_boilerplate =
+      Top::context()->global_context()->arguments_boilerplate();
+  JSFunction* arguments_function =
+      JSFunction::cast(arguments_boilerplate->map()->constructor());
+
+  // Get the number of referencing objects.
+  int count;
+  count = DebugReferencedBy(target, instance_filter, max_references,
+                            NULL, 0, arguments_function);
+
+  // Allocate an array to hold the result.
+  Object* object = Heap::AllocateFixedArray(count);
+  if (object->IsFailure()) return object;
+  FixedArray* instances = FixedArray::cast(object);
+
+  // Fill the referencing objects.
+  count = DebugReferencedBy(target, instance_filter, max_references,
+                            instances, count, arguments_function);
+
+  // Return result as JS array.
+  Object* result =
+      Heap::AllocateJSObject(
+          Top::context()->global_context()->array_function());
+  if (!result->IsFailure()) JSArray::cast(result)->SetContent(instances);
+  return result;
+}
+
+
+// Helper function used by Runtime_DebugConstructedBy below.
+static int DebugConstructedBy(JSFunction* constructor, int max_references,
+                              FixedArray* instances, int instances_size) {
+  AssertNoAllocation no_alloc;
+
+  // Iterate the heap.
+  int count = 0;
+  HeapIterator iterator;
+  while (iterator.has_next() &&
+         (max_references == 0 || count < max_references)) {
+    // Only look at all JSObjects.
+    HeapObject* heap_obj = iterator.next();
+    if (heap_obj->IsJSObject()) {
+      JSObject* obj = JSObject::cast(heap_obj);
+      if (obj->map()->constructor() == constructor) {
+        // Valid reference found add to instance array if supplied an update
+        // count.
+        if (instances != NULL && count < instances_size) {
+          instances->set(count, obj);
+        }
+        count++;
+      }
+    }
+  }
+
+  // Return the number of referencing objects found.
+  return count;
+}
+
+
+// Scan the heap for objects constructed by a specific function.
+// args[0]: the constructor to find instances of
+// args[1]: the the maximum number of objects to return
+static Object* Runtime_DebugConstructedBy(Arguments args) {
+  ASSERT(args.length() == 2);
+
+  // First perform a full GC in order to avoid dead objects.
+  Heap::CollectAllGarbage();
+
+  // Check parameters.
+  CONVERT_CHECKED(JSFunction, constructor, args[0]);
+  CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
+  RUNTIME_ASSERT(max_references >= 0);
+
+  // Get the number of referencing objects.
+  int count;
+  count = DebugConstructedBy(constructor, max_references, NULL, 0);
+
+  // Allocate an array to hold the result.
+  Object* object = Heap::AllocateFixedArray(count);
+  if (object->IsFailure()) return object;
+  FixedArray* instances = FixedArray::cast(object);
+
+  // Fill the referencing objects.
+  count = DebugConstructedBy(constructor, max_references, instances, count);
+
+  // Return result as JS array.
+  Object* result =
+      Heap::AllocateJSObject(
+          Top::context()->global_context()->array_function());
+  if (!result->IsFailure()) JSArray::cast(result)->SetContent(instances);
+  return result;
+}
+
+
+// Find the effective prototype object as returned by __proto__.
+// args[0]: the object to find the prototype for.
+static Object* Runtime_DebugGetPrototype(Arguments args) {
+  ASSERT(args.length() == 1);
+
+  CONVERT_CHECKED(JSObject, obj, args[0]);
+
+  // Use the __proto__ accessor.
+  return Accessors::ObjectPrototype.getter(obj, NULL);
+}
+
+
+static Object* Runtime_SystemBreak(Arguments args) {
+  ASSERT(args.length() == 0);
+  CPU::DebugBreak();
+  return Heap::undefined_value();
+}
+
+
+// Finds the script object from the script data. NOTE: This operation uses
+// heap traversal to find the function generated for the source position
+// for the requested break point. For lazily compiled functions several heap
+// traversals might be required rendering this operation as a rather slow
+// operation. However for setting break points which is normally done through
+// some kind of user interaction the performance is not crucial.
+static Handle<Object> Runtime_GetScriptFromScriptName(
+    Handle<String> script_name) {
+  // Scan the heap for Script objects to find the script with the requested
+  // script data.
+  Handle<Script> script;
+  HeapIterator iterator;
+  while (script.is_null() && iterator.has_next()) {
+    HeapObject* obj = iterator.next();
+    // If a script is found check if it has the script data requested.
+    if (obj->IsScript()) {
+      if (Script::cast(obj)->name()->IsString()) {
+        if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) {
+          script = Handle<Script>(Script::cast(obj));
+        }
+      }
+    }
+  }
+
+  // If no script with the requested script data is found return undefined.
+  if (script.is_null()) return Factory::undefined_value();
+
+  // Return the script found.
+  return GetScriptWrapper(script);
+}
+
+
+// Get the script object from script data. NOTE: Regarding performance
+// see the NOTE for GetScriptFromScriptData.
+// args[0]: script data for the script to find the source for
+static Object* Runtime_GetScript(Arguments args) {
+  HandleScope scope;
+
+  ASSERT(args.length() == 1);
+
+  CONVERT_CHECKED(String, script_name, args[0]);
+
+  // Find the requested script.
+  Handle<Object> result =
+      Runtime_GetScriptFromScriptName(Handle<String>(script_name));
+  return *result;
+}
+
+
+static Object* Runtime_FunctionGetAssemblerCode(Arguments args) {
+#ifdef DEBUG
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+  // Get the function and make sure it is compiled.
+  CONVERT_ARG_CHECKED(JSFunction, func, 0);
+  if (!func->is_compiled() && !CompileLazy(func, KEEP_EXCEPTION)) {
+    return Failure::Exception();
+  }
+  func->code()->PrintLn();
+#endif  // DEBUG
+  return Heap::undefined_value();
+}
+
+
+static Object* Runtime_Abort(Arguments args) {
+  ASSERT(args.length() == 2);
+  OS::PrintError("abort: %s\n", reinterpret_cast<char*>(args[0]) +
+                                    Smi::cast(args[1])->value());
+  Top::PrintStack();
+  OS::Abort();
+  UNREACHABLE();
+  return NULL;
+}
+
+
+#ifdef DEBUG
+// ListNatives is ONLY used by the fuzz-natives.js in debug mode
+// Exclude the code in release mode.
+static Object* Runtime_ListNatives(Arguments args) {
+  ASSERT(args.length() == 0);
+  HandleScope scope;
+  Handle<JSArray> result = Factory::NewJSArray(0);
+  int index = 0;
+#define ADD_ENTRY(Name, argc)                                                \
+  {                                                                          \
+    HandleScope inner;                                                       \
+    Handle<String> name =                                                    \
+      Factory::NewStringFromAscii(Vector<const char>(#Name, strlen(#Name))); \
+    Handle<JSArray> pair = Factory::NewJSArray(0);                           \
+    SetElement(pair, 0, name);                                               \
+    SetElement(pair, 1, Handle<Smi>(Smi::FromInt(argc)));                    \
+    SetElement(result, index++, pair);                                       \
+  }
+  RUNTIME_FUNCTION_LIST(ADD_ENTRY)
+#undef ADD_ENTRY
+  return *result;
+}
+#endif
+
+
+static Object* Runtime_Log(Arguments args) {
+  ASSERT(args.length() == 2);
+  CONVERT_CHECKED(String, format, args[0]);
+  CONVERT_CHECKED(JSArray, elms, args[1]);
+  Vector<const char> chars = format->ToAsciiVector();
+  Logger::LogRuntime(chars, elms);
+  return Heap::undefined_value();
+}
+
+
+static Object* Runtime_IS_VAR(Arguments args) {
+  UNREACHABLE();  // implemented as macro in the parser
+  return NULL;
+}
+
+
+// ----------------------------------------------------------------------------
+// Implementation of Runtime
+
+#define F(name, nargs)                                                 \
+  { #name, "RuntimeStub_" #name, FUNCTION_ADDR(Runtime_##name), nargs, \
+    static_cast<int>(Runtime::k##name) },
+
+static Runtime::Function Runtime_functions[] = {
+  RUNTIME_FUNCTION_LIST(F)
+  { NULL, NULL, NULL, 0, -1 }
+};
+
+#undef F
+
+
+Runtime::Function* Runtime::FunctionForId(FunctionId fid) {
+  ASSERT(0 <= fid && fid < kNofFunctions);
+  return &Runtime_functions[fid];
+}
+
+
+Runtime::Function* Runtime::FunctionForName(const char* name) {
+  for (Function* f = Runtime_functions; f->name != NULL; f++) {
+    if (strcmp(f->name, name) == 0) {
+      return f;
+    }
+  }
+  return NULL;
+}
+
+
+void Runtime::PerformGC(Object* result) {
+  Failure* failure = Failure::cast(result);
+  if (failure->IsRetryAfterGC()) {
+    // Try to do a garbage collection; ignore it if it fails. The C
+    // entry stub will throw an out-of-memory exception in that case.
+    Heap::CollectGarbage(failure->requested(), failure->allocation_space());
+  } else {
+    // Handle last resort GC and make sure to allow future allocations
+    // to grow the heap without causing GCs (if possible).
+    Counters::gc_last_resort_from_js.Increment();
+    Heap::CollectAllGarbage();
+  }
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/runtime.h b/deps/v8/src/runtime.h
new file mode 100644
index 0000000..657e5c5
--- /dev/null
+++ b/deps/v8/src/runtime.h
@@ -0,0 +1,385 @@
+// 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_RUNTIME_H_
+#define V8_RUNTIME_H_
+
+namespace v8 { namespace internal {
+
+// The interface to C++ runtime functions.
+
+// ----------------------------------------------------------------------------
+// RUNTIME_FUNCTION_LIST_ALWAYS defines runtime calls available in both
+// release and debug mode.
+// This macro should only be used by the macro RUNTIME_FUNCTION_LIST.
+
+#define RUNTIME_FUNCTION_LIST_ALWAYS(F) \
+  /* Property access */ \
+  F(GetProperty, 2) \
+  F(KeyedGetProperty, 2) \
+  F(DeleteProperty, 2) \
+  F(HasLocalProperty, 2) \
+  F(HasProperty, 2) \
+  F(HasElement, 2) \
+  F(IsPropertyEnumerable, 2) \
+  F(GetPropertyNames, 1) \
+  F(GetPropertyNamesFast, 1) \
+  F(GetArgumentsProperty, 1) \
+  F(ToFastProperties, 1) \
+  F(ToSlowProperties, 1) \
+  \
+  F(IsInPrototypeChain, 2) \
+  \
+  F(IsConstructCall, 0) \
+  \
+  /* Utilities */ \
+  F(GetCalledFunction, 0) \
+  F(GetFunctionDelegate, 1) \
+  F(NewArguments, 1) \
+  F(NewArgumentsFast, 3) \
+  F(LazyCompile, 1) \
+  F(SetNewFunctionAttributes, 1) \
+  \
+  /* Array join support */ \
+  F(PushIfAbsent, 2) \
+  F(ArrayConcat, 1) \
+  \
+  /* Conversions */ \
+  F(ToBool, 1) \
+  F(Typeof, 1) \
+  \
+  F(StringToNumber, 1) \
+  F(StringFromCharCodeArray, 1) \
+  F(StringParseInt, 2) \
+  F(StringParseFloat, 1) \
+  F(StringToLowerCase, 1) \
+  F(StringToUpperCase, 1) \
+  F(CharFromCode, 1) \
+  F(URIEscape, 1) \
+  F(URIUnescape, 1) \
+  \
+  F(NumberToString, 1) \
+  F(NumberToInteger, 1) \
+  F(NumberToJSUint32, 1) \
+  F(NumberToJSInt32, 1) \
+  F(NumberToSmi, 1) \
+  \
+  /* Arithmetic operations */ \
+  F(NumberAdd, 2) \
+  F(NumberSub, 2) \
+  F(NumberMul, 2) \
+  F(NumberDiv, 2) \
+  F(NumberMod, 2) \
+  F(NumberUnaryMinus, 1) \
+  \
+  F(StringAdd, 2) \
+  F(StringBuilderConcat, 2) \
+  \
+  /* Bit operations */ \
+  F(NumberOr, 2) \
+  F(NumberAnd, 2) \
+  F(NumberXor, 2) \
+  F(NumberNot, 1) \
+  \
+  F(NumberShl, 2) \
+  F(NumberShr, 2) \
+  F(NumberSar, 2) \
+  \
+  /* Comparisons */ \
+  F(NumberEquals, 2) \
+  F(StringEquals, 2) \
+  \
+  F(NumberCompare, 3) \
+  F(SmiLexicographicCompare, 2) \
+  F(StringCompare, 2) \
+  \
+  /* Math */ \
+  F(Math_abs, 1) \
+  F(Math_acos, 1) \
+  F(Math_asin, 1) \
+  F(Math_atan, 1) \
+  F(Math_atan2, 2) \
+  F(Math_ceil, 1) \
+  F(Math_cos, 1) \
+  F(Math_exp, 1) \
+  F(Math_floor, 1) \
+  F(Math_log, 1) \
+  F(Math_pow, 2) \
+  F(Math_random, 0) \
+  F(Math_round, 1) \
+  F(Math_sin, 1) \
+  F(Math_sqrt, 1) \
+  F(Math_tan, 1) \
+  \
+  /* Regular expressions */ \
+  F(RegExpCompile, 3) \
+  F(RegExpExec, 4) \
+  \
+  /* Strings */ \
+  F(StringCharCodeAt, 2) \
+  F(StringIndexOf, 3) \
+  F(StringLastIndexOf, 3) \
+  F(StringLocaleCompare, 2) \
+  F(StringSlice, 3) \
+  F(StringReplaceRegExpWithString, 4) \
+  F(StringMatch, 3) \
+  \
+  /* Numbers */ \
+  F(NumberToRadixString, 2) \
+  F(NumberToFixed, 2) \
+  F(NumberToExponential, 2) \
+  F(NumberToPrecision, 2) \
+  \
+  /* Reflection */ \
+  F(FunctionSetInstanceClassName, 2) \
+  F(FunctionSetLength, 2) \
+  F(FunctionSetPrototype, 2) \
+  F(FunctionGetName, 1) \
+  F(FunctionSetName, 2) \
+  F(FunctionGetSourceCode, 1) \
+  F(FunctionGetScript, 1) \
+  F(FunctionGetScriptSourcePosition, 1) \
+  F(FunctionIsAPIFunction, 1) \
+  F(GetScript, 1) \
+  \
+  F(ClassOf, 1) \
+  F(HasDateClass, 1) \
+  F(HasStringClass, 1) \
+  F(HasArrayClass, 1) \
+  F(HasFunctionClass, 1) \
+  F(HasNumberClass, 1) \
+  F(HasBooleanClass, 1) \
+  F(HasArgumentsClass, 1) \
+  F(HasRegExpClass, 1) \
+  F(SetCode, 2) \
+  \
+  F(CreateApiFunction, 1) \
+  F(IsTemplate, 1) \
+  F(GetTemplateField, 2) \
+  F(DisableAccessChecks, 1) \
+  F(EnableAccessChecks, 1) \
+  \
+  /* Dates */ \
+  F(DateCurrentTime, 0) \
+  F(DateParseString, 2) \
+  F(DateLocalTimezone, 1) \
+  F(DateLocalTimeOffset, 0) \
+  F(DateDaylightSavingsOffset, 1) \
+  \
+  /* Numbers */ \
+  F(NumberIsFinite, 1) \
+  \
+  /* Globals */ \
+  F(CompileString, 2) \
+  F(CompileScript, 4) \
+  F(GlobalPrint, 1) \
+  \
+  /* Eval */ \
+  F(GlobalReceiver, 1) \
+  F(ResolvePossiblyDirectEval, 2) \
+  \
+  F(SetProperty, -1 /* 3 or 4 */) \
+  F(IgnoreAttributesAndSetProperty, -1 /* 3 or 4 */) \
+  \
+  /* Arrays */ \
+  F(RemoveArrayHoles, 1) \
+  F(GetArrayKeys, 2) \
+  F(MoveArrayContents, 2) \
+  F(EstimateNumberOfElements, 1) \
+  \
+  /* Getters and Setters */ \
+  F(DefineAccessor, -1 /* 4 or 5 */) \
+  F(LookupAccessor, 3) \
+  \
+  /* Debugging */ \
+  F(SetDebugEventListener, 2) \
+  F(Break, 0) \
+  F(DebugGetPropertyDetails, 2) \
+  F(DebugGetProperty, 2) \
+  F(DebugLocalPropertyNames, 1) \
+  F(DebugLocalElementNames, 1) \
+  F(DebugPropertyTypeFromDetails, 1) \
+  F(DebugPropertyAttributesFromDetails, 1) \
+  F(DebugPropertyIndexFromDetails, 1) \
+  F(DebugInterceptorInfo, 1) \
+  F(DebugNamedInterceptorPropertyNames, 1) \
+  F(DebugIndexedInterceptorElementNames, 1) \
+  F(DebugNamedInterceptorPropertyValue, 2) \
+  F(DebugIndexedInterceptorElementValue, 2) \
+  F(CheckExecutionState, 1) \
+  F(GetFrameCount, 1) \
+  F(GetFrameDetails, 2) \
+  F(GetCFrames, 1) \
+  F(GetThreadCount, 1) \
+  F(GetThreadDetails, 2) \
+  F(GetBreakLocations, 1) \
+  F(SetFunctionBreakPoint, 3) \
+  F(SetScriptBreakPoint, 3) \
+  F(ClearBreakPoint, 1) \
+  F(ChangeBreakOnException, 2) \
+  F(PrepareStep, 3) \
+  F(ClearStepping, 0) \
+  F(DebugEvaluate, 4) \
+  F(DebugEvaluateGlobal, 3) \
+  F(DebugGetLoadedScripts, 0) \
+  F(DebugReferencedBy, 3) \
+  F(DebugConstructedBy, 2) \
+  F(DebugGetPrototype, 1) \
+  F(SystemBreak, 0) \
+  \
+  /* Literals */ \
+  F(MaterializeRegExpLiteral, 4)\
+  F(CreateArrayLiteralBoilerplate, 3) \
+  F(CreateObjectLiteralBoilerplate, 3) \
+  F(CloneLiteralBoilerplate, 1) \
+  F(CloneShallowLiteralBoilerplate, 1) \
+  \
+  /* Catch context extension objects */ \
+  F(CreateCatchExtensionObject, 2) \
+  \
+  /* Statements */ \
+  F(NewClosure, 2) \
+  F(NewObject, 1) \
+  F(Throw, 1) \
+  F(ReThrow, 1) \
+  F(ThrowReferenceError, 1) \
+  F(StackGuard, 1) \
+  \
+  /* Contexts */ \
+  F(NewContext, 1) \
+  F(PushContext, 1) \
+  F(PushCatchContext, 1) \
+  F(LookupContext, 2) \
+  F(LoadContextSlot, 2) \
+  F(LoadContextSlotNoReferenceError, 2) \
+  F(StoreContextSlot, 3) \
+  \
+  /* Declarations and initialization */ \
+  F(DeclareGlobals, 3) \
+  F(DeclareContextSlot, 4) \
+  F(InitializeVarGlobal, -1 /* 1 or 2 */) \
+  F(InitializeConstGlobal, 2) \
+  F(InitializeConstContextSlot, 3) \
+  \
+  /* Debugging */ \
+  F(DebugPrint, 1) \
+  F(DebugTrace, 0) \
+  F(TraceEnter, 0) \
+  F(TraceExit, 1) \
+  F(DebugBreak, 0) \
+  F(FunctionGetAssemblerCode, 1) \
+  F(Abort, 2) \
+  /* Logging */ \
+  F(Log, 2) \
+  \
+  /* Pseudo functions - handled as macros by parser */ \
+  F(IS_VAR, 1)
+
+
+#ifdef DEBUG
+#define RUNTIME_FUNCTION_LIST_DEBUG(F) \
+  /* Testing */ \
+  F(ListNatives, 0)
+#else
+#define RUNTIME_FUNCTION_LIST_DEBUG(F)
+#endif
+
+
+// ----------------------------------------------------------------------------
+// RUNTIME_FUNCTION_LIST defines all runtime functions accessed
+// either directly by id (via the code generator), or indirectly
+// via a native call by name (from within JS code).
+
+#define RUNTIME_FUNCTION_LIST(F) \
+  RUNTIME_FUNCTION_LIST_ALWAYS(F) \
+  RUNTIME_FUNCTION_LIST_DEBUG(F)
+
+// ----------------------------------------------------------------------------
+// Runtime provides access to all C++ runtime functions.
+
+class Runtime : public AllStatic {
+ public:
+  enum FunctionId {
+#define F(name, nargs) k##name,
+    RUNTIME_FUNCTION_LIST(F)
+    kNofFunctions
+#undef F
+  };
+
+  // Runtime function descriptor.
+  struct Function {
+    // The JS name of the function.
+    const char* name;
+
+    // The name of the stub that calls the runtime function.
+    const char* stub_name;
+
+    // The C++ (native) entry point.
+    byte* entry;
+
+    // The number of arguments expected; nargs < 0 if variable no. of
+    // arguments.
+    int nargs;
+    int stub_id;
+  };
+
+  // Get the runtime function with the given function id.
+  static Function* FunctionForId(FunctionId fid);
+
+  // Get the runtime function with the given name.
+  static Function* FunctionForName(const char* name);
+
+  static int StringMatch(Handle<String> sub, Handle<String> pat, int index);
+
+  static bool IsUpperCaseChar(uint16_t ch);
+
+  // TODO(1240886): The following three methods are *not* handle safe,
+  // but accept handle arguments. This seems fragile.
+
+  // Support getting the characters in a string using [] notation as
+  // in Firefox/SpiderMonkey, Safari and Opera.
+  static Object* GetElementOrCharAt(Handle<Object> object, uint32_t index);
+
+  static Object* SetObjectProperty(Handle<Object> object,
+                                   Handle<Object> key,
+                                   Handle<Object> value,
+                                   PropertyAttributes attr);
+
+  static Object* GetObjectProperty(Handle<Object> object, Handle<Object> key);
+
+  // This function is used in FunctionNameUsing* tests.
+  static Object* FindSharedFunctionInfoInScript(Handle<Script> script,
+                                                int position);
+
+  // Helper functions used stubs.
+  static void PerformGC(Object* result);
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_RUNTIME_H_
diff --git a/deps/v8/src/runtime.js b/deps/v8/src/runtime.js
new file mode 100644
index 0000000..63e9292
--- /dev/null
+++ b/deps/v8/src/runtime.js
@@ -0,0 +1,525 @@
+// 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.
+
+// This files contains runtime support implemented in JavaScript.
+
+// CAUTION: Some of the functions specified in this file are called
+// directly from compiled code. These are the functions with names in
+// ALL CAPS. The compiled code passes the first argument in 'this' and
+// it does not push the function onto the stack. This means that you
+// cannot use contexts in all these functions.
+
+
+/* -----------------------------------
+   - - -   C o m p a r i s o n   - - -
+   -----------------------------------
+*/
+
+// The following const declarations are shared with other native JS files.
+// They are all declared at this one spot to avoid const redeclaration errors.
+const $Object = global.Object;
+const $Array = global.Array;
+const $String = global.String;
+const $Number = global.Number;
+const $Function = global.Function;
+const $Boolean = global.Boolean;
+const $NaN = 0/0;
+
+
+// ECMA-262, section 11.9.1, page 55.
+function EQUALS(y) {
+  if (IS_STRING(this) && IS_STRING(y)) return %StringEquals(this, y);
+  var x = this;
+
+  // NOTE: We use iteration instead of recursion, because it is
+  // difficult to call EQUALS with the correct setting of 'this' in
+  // an efficient way.
+  while (true) {
+    if (IS_NUMBER(x)) {
+      if (y == null) return 1;  // not equal
+      return %NumberEquals(x, %ToNumber(y));
+    } else if (IS_STRING(x)) {
+      if (IS_STRING(y)) return %StringEquals(x, y);
+      if (IS_NUMBER(y)) return %NumberEquals(%ToNumber(x), y);
+      if (IS_BOOLEAN(y)) return %NumberEquals(%ToNumber(x), %ToNumber(y));
+      if (y == null) return 1;  // not equal
+      y = %ToPrimitive(y, NO_HINT);
+    } else if (IS_BOOLEAN(x)) {
+      if (IS_BOOLEAN(y)) {
+        return %_ObjectEquals(x, y) ? 0 : 1;
+      }
+      if (y == null) return 1;  // not equal
+      return %NumberEquals(%ToNumber(x), %ToNumber(y));
+    } else if (x == null) {
+      // NOTE: This checks for both null and undefined.
+      return (y == null) ? 0 : 1;
+    } else {
+      // x is not a number, boolean, null or undefined.
+      if (y == null) return 1;  // not equal
+      if (IS_OBJECT(y)) {
+        return %_ObjectEquals(x, y) ? 0 : 1;
+      }
+      if (IS_FUNCTION(y)) {
+        return %_ObjectEquals(x, y) ? 0 : 1;
+      }
+
+      x = %ToPrimitive(x, NO_HINT);
+    }
+  }
+}
+
+// ECMA-262, section 11.9.4, page 56.
+function STRICT_EQUALS(x) {
+  if (IS_STRING(this)) {
+    if (!IS_STRING(x)) return 1;  // not equal
+    return %StringEquals(this, x);
+  } 
+
+  if (IS_NUMBER(this)) {
+    if (!IS_NUMBER(x)) return 1;  // not equal
+    return %NumberEquals(this, x);
+  } 
+
+  // If anything else gets here, we just do simple identity check.
+  // Objects (including functions), null, undefined and booleans were
+  // checked in the CompareStub, so there should be nothing left.
+  return %_ObjectEquals(this, x) ? 0 : 1;
+}
+
+
+// ECMA-262, section 11.8.5, page 53. The 'ncr' parameter is used as
+// the result when either (or both) the operands are NaN.
+function COMPARE(x, ncr) {
+  // Fast case for numbers and strings.
+  if (IS_NUMBER(this) && IS_NUMBER(x)) {
+    return %NumberCompare(this, x, ncr);
+  }
+  if (IS_STRING(this) && IS_STRING(x)) {
+    return %StringCompare(this, x);
+  }
+
+  // Default implementation.
+  var a = %ToPrimitive(this, NUMBER_HINT);
+  var b = %ToPrimitive(x, NUMBER_HINT);
+  if (IS_STRING(a) && IS_STRING(b)) {
+    return %StringCompare(a, b);
+  } else {
+    return %NumberCompare(%ToNumber(a), %ToNumber(b), ncr);
+  }
+}
+
+
+
+/* -----------------------------------
+   - - -   A r i t h m e t i c   - - -
+   -----------------------------------
+*/
+
+// ECMA-262, section 11.6.1, page 50.
+function ADD(x) {
+  // Fast case: Check for number operands and do the addition.
+  if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x);
+  if (IS_STRING(this) && IS_STRING(x)) return %StringAdd(this, x);
+
+  // Default implementation.
+  var a = %ToPrimitive(this, NO_HINT);
+  var b = %ToPrimitive(x, NO_HINT);
+  
+  if (IS_STRING(a)) {
+    return %StringAdd(a, %ToString(b));
+  } else if (IS_STRING(b)) {
+    return %StringAdd(%ToString(a), b);
+  } else {
+    return %NumberAdd(%ToNumber(a), %ToNumber(b));
+  }
+}
+
+
+// Left operand (this) is already a string.
+function STRING_ADD_LEFT(x) {
+  x = %ToString(%ToPrimitive(x, NO_HINT));
+  return %StringAdd(this, x);
+}
+
+
+// Right operand (x) is already a string.
+function STRING_ADD_RIGHT(x) {
+  var a = %ToString(%ToPrimitive(this, NO_HINT));
+  return %StringAdd(a, x);
+}
+
+
+// ECMA-262, section 11.6.2, page 50.
+function SUB(x) {
+  return %NumberSub(%ToNumber(this), %ToNumber(x));
+}
+
+
+// ECMA-262, section 11.5.1, page 48.
+function MUL(x) {
+  return %NumberMul(%ToNumber(this), %ToNumber(x));
+}
+
+
+// ECMA-262, section 11.5.2, page 49.
+function DIV(x) {
+  return %NumberDiv(%ToNumber(this), %ToNumber(x));
+}
+
+
+// ECMA-262, section 11.5.3, page 49.
+function MOD(x) {
+  return %NumberMod(%ToNumber(this), %ToNumber(x));
+}
+
+
+
+/* -------------------------------------------
+   - - -   B i t   o p e r a t i o n s   - - -
+   -------------------------------------------
+*/
+
+// ECMA-262, section 11.10, page 57.
+function BIT_OR(x) {
+  return %NumberOr(%ToNumber(this), %ToNumber(x));
+}
+
+
+// ECMA-262, section 11.10, page 57.
+function BIT_AND(x) {
+  return %NumberAnd(%ToNumber(this), %ToNumber(x));
+}
+
+
+// ECMA-262, section 11.10, page 57.
+function BIT_XOR(x) {
+  return %NumberXor(%ToNumber(this), %ToNumber(x));
+}
+
+
+// ECMA-262, section 11.4.7, page 47.
+function UNARY_MINUS() {
+  return %NumberUnaryMinus(%ToNumber(this));
+}
+
+
+// ECMA-262, section 11.4.8, page 48.
+function BIT_NOT() {
+  return %NumberNot(%ToNumber(this));
+}
+
+
+// ECMA-262, section 11.7.1, page 51.
+function SHL(x) {
+  return %NumberShl(%ToNumber(this), %ToNumber(x));
+}
+
+
+// ECMA-262, section 11.7.2, page 51.
+function SAR(x) {
+  return %NumberSar(%ToNumber(this), %ToNumber(x));
+}
+
+
+// ECMA-262, section 11.7.3, page 52.
+function SHR(x) {
+  return %NumberShr(%ToNumber(this), %ToNumber(x));
+}
+
+
+
+/* -----------------------------
+   - - -   H e l p e r s   - - -
+   -----------------------------
+*/
+
+// ECMA-262, section 11.4.1, page 46.
+function DELETE(key) {
+  return %DeleteProperty(%ToObject(this), %ToString(key));
+}
+
+
+// ECMA-262, section 11.8.7, page 54.
+function IN(x) {
+  if (x == null || (!IS_OBJECT(x) && !IS_FUNCTION(x))) {
+    throw %MakeTypeError('invalid_in_operator_use', [this, x]);
+  }
+  return %_IsNonNegativeSmi(this) ? %HasElement(x, this) : %HasProperty(x, %ToString(this));
+}
+
+
+// ECMA-262, section 11.8.6, page 54. To make the implementation more
+// efficient, the return value should be zero if the 'this' is an
+// instance of F, and non-zero if not. This makes it possible to avoid
+// an expensive ToBoolean conversion in the generated code.
+function INSTANCE_OF(F) {
+  var V = this;
+  if (!IS_FUNCTION(F)) {
+    throw %MakeTypeError('instanceof_function_expected', [V]);
+  }
+
+  // If V is not an object, return false.
+  if (IS_NULL(V) || (!IS_OBJECT(V) && !IS_FUNCTION(V))) {
+    return 1;
+  }
+
+  // Get the prototype of F; if it is not an object, throw an error.
+  var O = F.prototype;
+  if (IS_NULL(O) || (!IS_OBJECT(O) && !IS_FUNCTION(O))) {
+    throw %MakeTypeError('instanceof_nonobject_proto', [O]);
+  }
+
+  // Return whether or not O is in the prototype chain of V.
+  return %IsInPrototypeChain(O, V) ? 0 : 1;
+}
+
+
+// Get an array of property keys for the given object. Used in
+// for-in statements.
+function GET_KEYS() {
+  return %GetPropertyNames(this);
+}
+
+
+// Filter a given key against an object by checking if the object
+// has a property with the given key; return the key as a string if
+// it has. Otherwise returns null. Used in for-in statements.
+function FILTER_KEY(key) {
+  var string = %ToString(key);
+  if (%HasProperty(this, string)) return string;
+  return null;
+}
+
+
+function CALL_NON_FUNCTION() {
+  var callee = %GetCalledFunction();
+  var delegate = %GetFunctionDelegate(callee);
+  if (!IS_FUNCTION(delegate)) {
+    throw %MakeTypeError('called_non_callable', [typeof callee]);
+  }
+
+  var parameters = %NewArguments(delegate);
+  return delegate.apply(callee, parameters);
+}
+
+
+function APPLY_PREPARE(args) {
+  var length;
+  // First check whether length is a positive Smi and args is an array.  This is the
+  // fast case.  If this fails, we do the slow case that takes care of more eventualities
+  if (%_IsArray(args)) {
+    length = args.length;
+    if (%_IsSmi(length) && length >= 0 && length < 0x800000 && IS_FUNCTION(this)) {
+      return length;
+    }
+  }
+
+  length = (args == null) ? 0 : %ToUint32(args.length);
+
+  // We can handle any number of apply arguments if the stack is
+  // big enough, but sanity check the value to avoid overflow when
+  // multiplying with pointer size.
+  if (length > 0x800000) {
+    throw %MakeRangeError('apply_overflow', [length]);
+  }
+
+  if (!IS_FUNCTION(this)) {
+    throw %MakeTypeError('apply_non_function', [ %ToString(this), typeof this ]);
+  }
+
+  // Make sure the arguments list has the right type.
+  if (args != null &&
+      !%HasArrayClass(args) &&
+      !%HasArgumentsClass(args)) {
+    throw %MakeTypeError('apply_wrong_args', []);
+  }
+
+  // Return the length which is the number of arguments to copy to the
+  // stack. It is guaranteed to be a small integer at this point.
+  return length;
+}
+
+
+function APPLY_OVERFLOW(length) {
+  throw %MakeRangeError('apply_overflow', [length]);
+}
+
+
+// Convert the receiver to an object - forward to ToObject.
+function TO_OBJECT() {
+  return %ToObject(this);
+}
+
+
+// Convert the receiver to a number - forward to ToNumber.
+function TO_NUMBER() {
+  return %ToNumber(this);
+}
+
+
+// Convert the receiver to a string - forward to ToString.
+function TO_STRING() {
+  return %ToString(this);
+}
+
+
+/* -------------------------------------
+   - - -   C o n v e r s i o n s   - - -
+   -------------------------------------
+*/
+
+// ECMA-262, section 9.1, page 30. Use null/undefined for no hint,
+// (1) for number hint, and (2) for string hint.
+function ToPrimitive(x, hint) {
+  // Fast case check.
+  if (IS_STRING(x)) return x;
+  // Normal behavior.
+  if (!IS_OBJECT(x) && !IS_FUNCTION(x)) return x;
+  if (x == null) return x;  // check for null, undefined
+  if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT;
+  return (hint == NUMBER_HINT) ? %DefaultNumber(x) : %DefaultString(x);
+}
+
+
+// ECMA-262, section 9.3, page 31.
+function ToNumber(x) {
+  if (IS_NUMBER(x)) return x;
+  if (IS_STRING(x)) return %StringToNumber(x);
+  if (IS_BOOLEAN(x)) return x ? 1 : 0;
+  if (IS_UNDEFINED(x)) return $NaN;
+  return (IS_NULL(x)) ? 0 : ToNumber(%DefaultNumber(x));
+}
+
+
+// ECMA-262, section 9.8, page 35.
+function ToString(x) {
+  if (IS_STRING(x)) return x;
+  if (IS_NUMBER(x)) return %NumberToString(x);
+  if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
+  if (IS_UNDEFINED(x)) return 'undefined';
+  return (IS_NULL(x)) ? 'null' : %ToString(%DefaultString(x));
+}
+
+
+// ... where did this come from?
+function ToBoolean(x) {
+  if (IS_BOOLEAN(x)) return x;
+  if (IS_STRING(x)) return x.length != 0;
+  if (x == null) return false;
+  if (IS_NUMBER(x)) return !((x == 0) || NUMBER_IS_NAN(x));
+  return true;
+}
+
+
+// ECMA-262, section 9.9, page 36.
+function ToObject(x) {
+  if (IS_STRING(x)) return new $String(x);
+  if (IS_NUMBER(x)) return new $Number(x);
+  if (IS_BOOLEAN(x)) return new $Boolean(x);
+  if (x == null) throw %MakeTypeError('null_to_object', []);
+  return x;
+}
+
+
+// ECMA-262, section 9.4, page 34.
+function ToInteger(x) {
+  if (%_IsSmi(x)) return x;
+  return %NumberToInteger(ToNumber(x));
+}
+
+
+// ECMA-262, section 9.6, page 34.
+function ToUint32(x) {
+  if (%_IsSmi(x) && x >= 0) return x;
+  return %NumberToJSUint32(ToNumber(x));
+}
+
+
+// ECMA-262, section 9.5, page 34
+function ToInt32(x) {
+  if (%_IsSmi(x)) return x;
+  return %NumberToJSInt32(ToNumber(x));
+}
+
+
+
+/* ---------------------------------
+   - - -   U t i l i t i e s   - - -
+   ---------------------------------
+*/
+
+// Returns if the given x is a primitive value - not an object or a
+// function.
+function IsPrimitive(x) {
+  if (!IS_OBJECT(x) && !IS_FUNCTION(x)) {
+    return true;
+  } else {
+    // Even though the type of null is "object", null is still
+    // considered a primitive value.
+    return IS_NULL(x);
+  }
+}
+
+
+// ECMA-262, section 8.6.2.6, page 28.
+function DefaultNumber(x) {
+  if (IS_FUNCTION(x.valueOf)) {
+    var v = x.valueOf();
+    if (%IsPrimitive(v)) return v;
+  }
+
+  if (IS_FUNCTION(x.toString)) {
+    var s = x.toString();
+    if (%IsPrimitive(s)) return s;
+  }
+
+  throw %MakeTypeError('cannot_convert_to_primitive', []);
+}
+
+
+// ECMA-262, section 8.6.2.6, page 28.
+function DefaultString(x) {
+  if (IS_FUNCTION(x.toString)) {
+    var s = x.toString();
+    if (%IsPrimitive(s)) return s;
+  }
+
+  if (IS_FUNCTION(x.valueOf)) {
+    var v = x.valueOf();
+    if (%IsPrimitive(v)) return v;
+  }
+
+  throw %MakeTypeError('cannot_convert_to_primitive', []);
+}
+
+
+// NOTE: Setting the prototype for Array must take place as early as
+// possible due to code generation for array literals.  When
+// generating code for a array literal a boilerplate array is created
+// that is cloned when running the code.  It is essiential that the
+// boilerplate gets the right prototype.
+%FunctionSetPrototype($Array, new $Array(0));
diff --git a/deps/v8/src/scanner.cc b/deps/v8/src/scanner.cc
new file mode 100644
index 0000000..65ec0f8
--- /dev/null
+++ b/deps/v8/src/scanner.cc
@@ -0,0 +1,850 @@
+// 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.
+
+#include "v8.h"
+
+#include "ast.h"
+#include "scanner.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() : data_(NULL) {
+  Initialize(NULL, 0);
+}
+
+
+UTF8Buffer::~UTF8Buffer() {
+  DeleteArray(data_);
+}
+
+
+void UTF8Buffer::Initialize(char* src, int length) {
+  DeleteArray(data_);
+  data_ = src;
+  size_ = length;
+  Reset();
+}
+
+
+void UTF8Buffer::AddChar(uc32 c) {
+  const int min_size = 1024;
+  if (pos_ + static_cast<int>(unibrow::Utf8::kMaxEncodedSize) > size_) {
+    int new_size = size_ * 2;
+    if (new_size < min_size) {
+      new_size = min_size;
+    }
+    char* new_data = NewArray<char>(new_size);
+    memcpy(new_data, data_, pos_);
+    DeleteArray(data_);
+    data_ = new_data;
+    size_ = new_size;
+  }
+  if (static_cast<unsigned>(c) < unibrow::Utf8::kMaxOneByteChar) {
+    data_[pos_++] = c;  // common case: 7bit ASCII
+  } else {
+    pos_ += unibrow::Utf8::Encode(&data_[pos_], c);
+  }
+  ASSERT(pos_ <= size_);
+}
+
+
+// ----------------------------------------------------------------------------
+// UTF16Buffer
+
+
+UTF16Buffer::UTF16Buffer()
+  : pos_(0),
+    pushback_buffer_(0),
+    last_(0),
+    stream_(NULL) { }
+
+
+void UTF16Buffer::Initialize(Handle<String> data,
+                             unibrow::CharacterStream* input) {
+  data_ = data;
+  pos_ = 0;
+  stream_ = input;
+}
+
+
+Handle<String> UTF16Buffer::SubString(int start, int end) {
+  return internal::SubString(data_, start, end);
+}
+
+
+void UTF16Buffer::PushBack(uc32 ch) {
+  pushback_buffer()->Add(last_);
+  last_ = ch;
+  pos_--;
+}
+
+
+uc32 UTF16Buffer::Advance() {
+  // NOTE: It is of importance to Persian / Farsi resources that we do
+  // *not* strip format control characters in the scanner; see
+  //
+  //    https://bugzilla.mozilla.org/show_bug.cgi?id=274152
+  //
+  // So, even though ECMA-262, section 7.1, page 11, dictates that we
+  // must remove Unicode format-control characters, we do not. This is
+  // in line with how IE and SpiderMonkey handles it.
+  if (!pushback_buffer()->is_empty()) {
+    pos_++;
+    return last_ = pushback_buffer()->RemoveLast();
+  } else if (stream_->has_more()) {
+    pos_++;
+    uc32 next = stream_->GetNext();
+    return last_ = next;
+  } else {
+    // note: currently the following increment is necessary to avoid a
+    // test-parser problem!
+    pos_++;
+    return last_ = static_cast<uc32>(-1);
+  }
+}
+
+
+void UTF16Buffer::SeekForward(int pos) {
+  pos_ = pos;
+  ASSERT(pushback_buffer()->is_empty());
+  stream_->Seek(pos);
+}
+
+
+// ----------------------------------------------------------------------------
+// Scanner
+
+Scanner::Scanner(bool pre) : stack_overflow_(false), is_pre_parsing_(pre) {
+  Token::Initialize();
+}
+
+
+void Scanner::Init(Handle<String> source, unibrow::CharacterStream* stream,
+    int position) {
+  // Initialize the source buffer.
+  source_.Initialize(source, stream);
+  position_ = position;
+
+  // Reset literals buffer
+  literals_.Reset();
+
+  // Set c0_ (one character ahead)
+  ASSERT(kCharacterLookaheadBufferSize == 1);
+  Advance();
+
+  // Skip initial whitespace (allowing HTML comment ends) and scan
+  // first token.
+  SkipWhiteSpace(true);
+  Scan();
+}
+
+
+Handle<String> Scanner::SubString(int start, int end) {
+  return source_.SubString(start - position_, end - position_);
+}
+
+
+Token::Value Scanner::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.
+  current_ = next_;
+  // Check for stack-overflow before returning any tokens.
+  StackLimitCheck check;
+  if (check.HasOverflowed()) {
+    stack_overflow_ = true;
+    next_.token = Token::ILLEGAL;
+  } else {
+    Scan();
+  }
+  return current_.token;
+}
+
+
+void Scanner::StartLiteral() {
+  next_.literal_pos = literals_.pos();
+}
+
+
+void Scanner::AddChar(uc32 c) {
+  literals_.AddChar(c);
+}
+
+
+void Scanner::TerminateLiteral() {
+  next_.literal_end = literals_.pos();
+  AddChar(0);
+}
+
+
+void Scanner::AddCharAdvance() {
+  AddChar(c0_);
+  Advance();
+}
+
+
+void Scanner::Advance() {
+  c0_ = source_.Advance();
+}
+
+
+void Scanner::PushBack(uc32 ch) {
+  source_.PushBack(ch);
+  c0_ = ch;
+}
+
+
+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;
+}
+
+
+void Scanner::SkipWhiteSpace(bool initial) {
+  has_line_terminator_before_next_ = initial;
+
+  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;
+  }
+}
+
+
+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::COMMENT;
+}
+
+
+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::COMMENT;
+    }
+  }
+
+  // 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::Scan() {
+  Token::Value token;
+  bool has_line_terminator = false;
+  do {
+    SkipWhiteSpace(has_line_terminator);
+
+    // Remember the line terminator in previous loop
+    has_line_terminator = has_line_terminator_before_next();
+
+    // Remember the position of the next token
+    next_.location.beg_pos = source_pos();
+
+    token = ScanToken();
+  } while (token == Token::COMMENT);
+
+  next_.location.end_pos = source_pos();
+  next_.token = token;
+}
+
+
+void Scanner::SeekForward(int pos) {
+  source_.SeekForward(pos - 1);
+  Advance();
+  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
+
+  StartLiteral();
+  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;
+  }
+  TerminateLiteral();
+
+  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_;
+  }
+}
+
+
+Token::Value Scanner::ScanToken() {
+  switch (c0_) {
+    // strings
+    case '"': case '\'':
+      return ScanString();
+
+    case '<':
+      // < <= << <<= <!--
+      Advance();
+      if (c0_ == '=') return Select(Token::LTE);
+      if (c0_ == '<') return Select('=', Token::ASSIGN_SHL, Token::SHL);
+      if (c0_ == '!') return ScanHtmlComment();
+      return Token::LT;
+
+    case '>':
+      // > >= >> >>= >>> >>>=
+      Advance();
+      if (c0_ == '=') return Select(Token::GTE);
+      if (c0_ == '>') {
+        // >> >>= >>> >>>=
+        Advance();
+        if (c0_ == '=') return Select(Token::ASSIGN_SAR);
+        if (c0_ == '>') return Select('=', Token::ASSIGN_SHR, Token::SHR);
+        return Token::SAR;
+      }
+      return Token::GT;
+
+    case '=':
+      // = == ===
+      Advance();
+      if (c0_ == '=') return Select('=', Token::EQ_STRICT, Token::EQ);
+      return Token::ASSIGN;
+
+    case '!':
+      // ! != !==
+      Advance();
+      if (c0_ == '=') return Select('=', Token::NE_STRICT, Token::NE);
+      return Token::NOT;
+
+    case '+':
+      // + ++ +=
+      Advance();
+      if (c0_ == '+') return Select(Token::INC);
+      if (c0_ == '=') return Select(Token::ASSIGN_ADD);
+      return Token::ADD;
+
+    case '-':
+      // - -- -=
+      Advance();
+      if (c0_ == '-') return Select(Token::DEC);
+      if (c0_ == '=') return Select(Token::ASSIGN_SUB);
+      return Token::SUB;
+
+    case '*':
+      // * *=
+      return Select('=', Token::ASSIGN_MUL, Token::MUL);
+
+    case '%':
+      // % %=
+      return Select('=', Token::ASSIGN_MOD, Token::MOD);
+
+    case '/':
+      // /  // /* /=
+      Advance();
+      if (c0_ == '/') return SkipSingleLineComment();
+      if (c0_ == '*') return SkipMultiLineComment();
+      if (c0_ == '=') return Select(Token::ASSIGN_DIV);
+      return Token::DIV;
+
+    case '&':
+      // & && &=
+      Advance();
+      if (c0_ == '&') return Select(Token::AND);
+      if (c0_ == '=') return Select(Token::ASSIGN_BIT_AND);
+      return Token::BIT_AND;
+
+    case '|':
+      // | || |=
+      Advance();
+      if (c0_ == '|') return Select(Token::OR);
+      if (c0_ == '=') return Select(Token::ASSIGN_BIT_OR);
+      return Token::BIT_OR;
+
+    case '^':
+      // ^ ^=
+      return Select('=', Token::ASSIGN_BIT_XOR, Token::BIT_XOR);
+
+    case '.':
+      // . Number
+      Advance();
+      if (IsDecimalDigit(c0_)) return ScanNumber(true);
+      return Token::PERIOD;
+
+    case ':':
+      return Select(Token::COLON);
+
+    case ';':
+      return Select(Token::SEMICOLON);
+
+    case ',':
+      return Select(Token::COMMA);
+
+    case '(':
+      return Select(Token::LPAREN);
+
+    case ')':
+      return Select(Token::RPAREN);
+
+    case '[':
+      return Select(Token::LBRACK);
+
+    case ']':
+      return Select(Token::RBRACK);
+
+    case '{':
+      return Select(Token::LBRACE);
+
+    case '}':
+      return Select(Token::RBRACE);
+
+    case '?':
+      return Select(Token::CONDITIONAL);
+
+    case '~':
+      return Select(Token::BIT_NOT);
+
+    default:
+      if (kIsIdentifierStart.get(c0_))
+        return ScanIdentifier();
+      if (IsDecimalDigit(c0_))
+        return ScanNumber(false);
+      if (c0_ < 0)
+        return Token::EOS;
+      return Select(Token::ILLEGAL);
+  }
+
+  UNREACHABLE();
+  return Token::ILLEGAL;
+}
+
+
+// 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;
+
+  StartLiteral();
+  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();
+  }
+  TerminateLiteral();
+
+  // 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;
+
+  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_));
+
+  bool has_escapes = false;
+
+  StartLiteral();
+  // Scan identifier start character.
+  if (c0_ == '\\') {
+    has_escapes = true;
+    uc32 c = ScanIdentifierUnicodeEscape();
+    // Only allow legal identifier start characters.
+    if (!kIsIdentifierStart.get(c)) return Token::ILLEGAL;
+    AddChar(c);
+  } else {
+    AddCharAdvance();
+  }
+  // Scan the rest of the identifier characters.
+  while (kIsIdentifierPart.get(c0_)) {
+    if (c0_ == '\\') {
+      has_escapes = true;
+      uc32 c = ScanIdentifierUnicodeEscape();
+      // Only allow legal identifier part characters.
+      if (!kIsIdentifierPart.get(c)) return Token::ILLEGAL;
+      AddChar(c);
+    } else {
+      AddCharAdvance();
+    }
+  }
+  TerminateLiteral();
+
+  // We don't have any 1-letter keywords (this is probably a common case).
+  if ((next_.literal_end - next_.literal_pos) == 1)
+    return Token::IDENTIFIER;
+
+  // If the identifier contains unicode escapes, it must not be
+  // resolved to a keyword.
+  if (has_escapes)
+    return Token::IDENTIFIER;
+
+  return Token::Lookup(&literals_.data()[next_.literal_pos]);
+}
+
+
+
+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.
+  StartLiteral();
+  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 '/'
+
+  TerminateLiteral();
+
+  return true;
+}
+
+bool Scanner::ScanRegExpFlags() {
+  // Scan regular expression flags.
+  StartLiteral();
+  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();
+  }
+  TerminateLiteral();
+
+  next_.location.end_pos = source_pos() - 1;
+  return true;
+}
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/scanner.h b/deps/v8/src/scanner.h
new file mode 100644
index 0000000..79a4a4c
--- /dev/null
+++ b/deps/v8/src/scanner.h
@@ -0,0 +1,239 @@
+// 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_SCANNER_H_
+#define V8_SCANNER_H_
+
+#include "token.h"
+#include "char-predicates-inl.h"
+
+namespace v8 { namespace internal {
+
+
+class UTF8Buffer {
+ public:
+  UTF8Buffer();
+  ~UTF8Buffer();
+
+  void Initialize(char* src, int length);
+  void AddChar(uc32 c);
+  void Reset() { pos_ = 0; }
+  int pos() const { return pos_; }
+  char* data() const { return data_; }
+
+ private:
+  char* data_;
+  int size_;
+  int pos_;
+};
+
+
+class UTF16Buffer {
+ public:
+  UTF16Buffer();
+
+  void Initialize(Handle<String> data, unibrow::CharacterStream* stream);
+  void PushBack(uc32 ch);
+  uc32 Advance();  // returns a value < 0 when the buffer end is reached
+  uint16_t CharAt(int index);
+  int pos() const { return pos_; }
+  int size() const { return size_; }
+  Handle<String> SubString(int start, int end);
+  List<uc32>* pushback_buffer() { return &pushback_buffer_; }
+  void SeekForward(int pos);
+
+ private:
+  Handle<String> data_;
+  int pos_;
+  int size_;
+  List<uc32> pushback_buffer_;
+  uc32 last_;
+  unibrow::CharacterStream* stream_;
+};
+
+
+class Scanner {
+ public:
+
+  typedef unibrow::Utf8InputBuffer<1024> Utf8Decoder;
+
+  // Construction
+  explicit Scanner(bool is_pre_parsing);
+
+  // Initialize the Scanner to scan source:
+  void Init(Handle<String> source,
+            unibrow::CharacterStream* stream,
+            int position);
+
+  // Returns the next token.
+  Token::Value Next();
+
+  // 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.
+  const char* literal_string() const {
+    return &literals_.data()[current_.literal_pos];
+  }
+  int literal_length() const {
+    return current_.literal_end - current_.literal_pos;
+  }
+
+  Vector<const char> next_literal() const {
+    return Vector<const char>(next_literal_string(), next_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 &literals_.data()[next_.literal_pos];
+  }
+  // Returns the length of the next token (that would be returned if
+  // Next() were called).
+  int next_literal_length() const {
+    return next_.literal_end - next_.literal_pos;
+  }
+
+  // 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);
+
+  Handle<String> SubString(int start_pos, int end_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;
+
+ private:
+  // Source.
+  UTF16Buffer source_;
+  int position_;
+
+  // Buffer to hold literal values (identifiers, strings, numbers)
+  // using 0-terminated UTF-8 encoding.
+  UTF8Buffer literals_;
+
+  bool stack_overflow_;
+  static StaticResource<Utf8Decoder> utf8_decoder_;
+
+  // One Unicode character look-ahead; c0_ < 0 at the end of the input.
+  uc32 c0_;
+
+  // The current and look-ahead token.
+  struct TokenDesc {
+    Token::Value token;
+    Location location;
+    int literal_pos, literal_end;
+  };
+
+  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_pre_parsing_;
+
+  static const int kCharacterLookaheadBufferSize = 1;
+
+  // Literal buffer support
+  void StartLiteral();
+  void AddChar(uc32 ch);
+  void AddCharAdvance();
+  void TerminateLiteral();
+
+  // Low-level scanning support.
+  void Advance();
+  void PushBack(uc32 ch);
+
+  void SkipWhiteSpace(bool initial);
+  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_);
+
+  void Scan();
+  Token::Value ScanToken();
+  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 + position_;
+  }
+
+  // Decodes a unicode escape-sequence which is part of an identifier.
+  // If the escape sequence cannot be decoded the result is kBadRune.
+  uc32 ScanIdentifierUnicodeEscape();
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_SCANNER_H_
diff --git a/deps/v8/src/scopeinfo.cc b/deps/v8/src/scopeinfo.cc
new file mode 100644
index 0000000..6d2ade8
--- /dev/null
+++ b/deps/v8/src/scopeinfo.cc
@@ -0,0 +1,570 @@
+// 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.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "scopeinfo.h"
+#include "scopes.h"
+
+namespace v8 { namespace internal {
+
+
+static int CompareLocal(Variable* const* v, Variable* const* w) {
+  Slot* s = (*v)->slot();
+  Slot* t = (*w)->slot();
+  // We may have rewritten parameters (that are in the arguments object)
+  // and which may have a NULL slot... - find a better solution...
+  int x = (s != NULL ? s->index() : 0);
+  int y = (t != NULL ? t->index() : 0);
+  // Consider sorting them according to type as well?
+  return x - y;
+}
+
+
+template<class Allocator>
+ScopeInfo<Allocator>::ScopeInfo(Scope* scope)
+    : function_name_(Factory::empty_symbol()),
+      calls_eval_(scope->calls_eval()),
+      parameters_(scope->num_parameters()),
+      stack_slots_(scope->num_stack_slots()),
+      context_slots_(scope->num_heap_slots()),
+      context_modes_(scope->num_heap_slots()) {
+  // Add parameters.
+  for (int i = 0; i < scope->num_parameters(); i++) {
+    ASSERT(parameters_.length() == i);
+    parameters_.Add(scope->parameter(i)->name());
+  }
+
+  // Add stack locals and collect heap locals.
+  // We are assuming that the locals' slots are allocated in
+  // increasing order, so we can simply add them to the
+  // ScopeInfo lists. However, due to usage analysis, this is
+  // not true for context-allocated locals: Some of them
+  // may be parameters which are allocated before the
+  // non-parameter locals. When the non-parameter locals are
+  // sorted according to usage, the allocated slot indices may
+  // not be in increasing order with the variable list anymore.
+  // Thus, we first collect the context-allocated locals, and then
+  // sort them by context slot index before adding them to the
+  // ScopeInfo list.
+  List<Variable*, Allocator> locals(32);  // 32 is a wild guess
+  ASSERT(locals.is_empty());
+  scope->CollectUsedVariables(&locals);
+  locals.Sort(&CompareLocal);
+
+  List<Variable*, Allocator> heap_locals(locals.length());
+  for (int i = 0; i < locals.length(); i++) {
+    Variable* var = locals[i];
+    if (var->var_uses()->is_used()) {
+      Slot* slot = var->slot();
+      if (slot != NULL) {
+        switch (slot->type()) {
+          case Slot::PARAMETER:
+            // explicitly added to parameters_ above - ignore
+            break;
+
+          case Slot::LOCAL:
+            ASSERT(stack_slots_.length() == slot->index());
+            stack_slots_.Add(var->name());
+            break;
+
+          case Slot::CONTEXT:
+            heap_locals.Add(var);
+            break;
+
+          case Slot::LOOKUP:
+          case Slot::GLOBAL:
+            // these are currently not used
+            UNREACHABLE();
+            break;
+        }
+      }
+    }
+  }
+
+  // Add heap locals.
+  if (scope->num_heap_slots() > 0) {
+    // Add user-defined slots.
+    for (int i = 0; i < heap_locals.length(); i++) {
+      ASSERT(heap_locals[i]->slot()->index() - Context::MIN_CONTEXT_SLOTS ==
+             context_slots_.length());
+      ASSERT(heap_locals[i]->slot()->index() - Context::MIN_CONTEXT_SLOTS ==
+             context_modes_.length());
+      context_slots_.Add(heap_locals[i]->name());
+      context_modes_.Add(heap_locals[i]->mode());
+    }
+
+  } else {
+    ASSERT(heap_locals.length() == 0);
+  }
+
+  // Add the function context slot, if present.
+  // For now, this must happen at the very end because of the
+  // ordering of the scope info slots and the respective slot indices.
+  if (scope->is_function_scope()) {
+    Variable* var = scope->function();
+    if (var != NULL &&
+        var->var_uses()->is_used() &&
+        var->slot()->type() == Slot::CONTEXT) {
+      function_name_ = var->name();
+      // Note that we must not find the function name in the context slot
+      // list - instead it must be handled separately in the
+      // Contexts::Lookup() function. Thus record an empty symbol here so we
+      // get the correct number of context slots.
+      ASSERT(var->slot()->index() - Context::MIN_CONTEXT_SLOTS ==
+             context_slots_.length());
+      ASSERT(var->slot()->index() - Context::MIN_CONTEXT_SLOTS ==
+             context_modes_.length());
+      context_slots_.Add(Factory::empty_symbol());
+      context_modes_.Add(Variable::INTERNAL);
+    }
+  }
+}
+
+
+// Encoding format in the Code object:
+//
+// - function name
+//
+// - number of variables in the context object (smi) (= function context
+//   slot index + 1)
+// - list of pairs (name, Var mode) of context-allocated variables (starting
+//   with context slot 0)
+// - NULL (sentinel)
+//
+// - number of parameters (smi)
+// - list of parameter names (starting with parameter 0 first)
+// - NULL (sentinel)
+//
+// - number of variables on the stack (smi)
+// - list of names of stack-allocated variables (starting with stack slot 0)
+// - NULL (sentinel)
+
+// The ScopeInfo representation could be simplified and the ScopeInfo
+// re-implemented (with almost the same interface). Here is a
+// suggestion for the new format:
+//
+// - have a single list with all variable names (parameters, stack locals,
+//   context locals), followed by a list of non-Object* values containing
+//   the variables information (what kind, index, attributes)
+// - searching the linear list of names is fast and yields an index into the
+//   list if the variable name is found
+// - that list index is then used to find the variable information in the
+//   subsequent list
+// - the list entries don't have to be in any particular order, so all the
+//   current sorting business can go away
+// - the ScopeInfo lookup routines can be reduced to perhaps a single lookup
+//   which returns all information at once
+// - when gathering the information from a Scope, we only need to iterate
+//   through the local variables (parameters and context info is already
+//   present)
+
+
+static inline Object** ReadInt(Object** p, int* x) {
+  *x = (reinterpret_cast<Smi*>(*p++))->value();
+  return p;
+}
+
+
+static inline Object** ReadBool(Object** p, bool* x) {
+  *x = (reinterpret_cast<Smi*>(*p++))->value() != 0;
+  return p;
+}
+
+
+static inline Object** ReadSymbol(Object** p, Handle<String>* s) {
+  *s = Handle<String>(reinterpret_cast<String*>(*p++));
+  return p;
+}
+
+
+static inline Object** ReadSentinel(Object** p) {
+  ASSERT(*p == NULL);
+  return p + 1;
+}
+
+
+template <class Allocator>
+static Object** ReadList(Object** p, List<Handle<String>, Allocator >* list) {
+  ASSERT(list->is_empty());
+  int n;
+  p = ReadInt(p, &n);
+  while (n-- > 0) {
+    Handle<String> s;
+    p = ReadSymbol(p, &s);
+    list->Add(s);
+  }
+  return ReadSentinel(p);
+}
+
+
+template <class Allocator>
+static Object** ReadList(Object** p,
+                         List<Handle<String>, Allocator>* list,
+                         List<Variable::Mode, Allocator>* modes) {
+  ASSERT(list->is_empty());
+  int n;
+  p = ReadInt(p, &n);
+  while (n-- > 0) {
+    Handle<String> s;
+    int m;
+    p = ReadSymbol(p, &s);
+    p = ReadInt(p, &m);
+    list->Add(s);
+    modes->Add(static_cast<Variable::Mode>(m));
+  }
+  return ReadSentinel(p);
+}
+
+
+template<class Allocator>
+ScopeInfo<Allocator>::ScopeInfo(Code* code)
+  : function_name_(Factory::empty_symbol()),
+    parameters_(4),
+    stack_slots_(8),
+    context_slots_(8),
+    context_modes_(8) {
+  if (code == NULL || code->sinfo_size() == 0) return;
+
+  Object** p0 = &Memory::Object_at(code->sinfo_start());
+  Object** p = p0;
+  p = ReadSymbol(p, &function_name_);
+  p = ReadBool(p, &calls_eval_);
+  p = ReadList<Allocator>(p, &context_slots_, &context_modes_);
+  p = ReadList<Allocator>(p, &parameters_);
+  p = ReadList<Allocator>(p, &stack_slots_);
+  ASSERT((p - p0) * kPointerSize == code->sinfo_size());
+}
+
+
+static inline Object** WriteInt(Object** p, int x) {
+  *p++ = Smi::FromInt(x);
+  return p;
+}
+
+
+static inline Object** WriteBool(Object** p, bool b) {
+  *p++ = Smi::FromInt(b ? 1 : 0);
+  return p;
+}
+
+
+static inline Object** WriteSymbol(Object** p, Handle<String> s) {
+  *p++ = *s;
+  return p;
+}
+
+
+static inline Object** WriteSentinel(Object** p) {
+  *p++ = NULL;
+  return p;
+}
+
+
+template <class Allocator>
+static Object** WriteList(Object** p, List<Handle<String>, Allocator >* list) {
+  const int n = list->length();
+  p = WriteInt(p, n);
+  for (int i = 0; i < n; i++) {
+    p = WriteSymbol(p, list->at(i));
+  }
+  return WriteSentinel(p);
+}
+
+
+template <class Allocator>
+static Object** WriteList(Object** p,
+                          List<Handle<String>, Allocator>* list,
+                          List<Variable::Mode, Allocator>* modes) {
+  const int n = list->length();
+  p = WriteInt(p, n);
+  for (int i = 0; i < n; i++) {
+    p = WriteSymbol(p, list->at(i));
+    p = WriteInt(p, modes->at(i));
+  }
+  return WriteSentinel(p);
+}
+
+
+template<class Allocator>
+int ScopeInfo<Allocator>::Serialize(Code* code) {
+  // function name, calls eval, length & sentinel for 3 tables:
+  const int extra_slots = 1 + 1 + 2 * 3;
+  int size = (extra_slots +
+              context_slots_.length() * 2 +
+              parameters_.length() +
+              stack_slots_.length()) * kPointerSize;
+
+  if (code != NULL) {
+    CHECK(code->sinfo_size() == size);
+    Object** p0 = &Memory::Object_at(code->sinfo_start());
+    Object** p = p0;
+    p = WriteSymbol(p, function_name_);
+    p = WriteBool(p, calls_eval_);
+    p = WriteList(p, &context_slots_, &context_modes_);
+    p = WriteList(p, &parameters_);
+    p = WriteList(p, &stack_slots_);
+    ASSERT((p - p0) * kPointerSize == size);
+  }
+
+  return size;
+}
+
+
+template<class Allocator>
+void ScopeInfo<Allocator>::IterateScopeInfo(Code* code, ObjectVisitor* v) {
+  Object** start = &Memory::Object_at(code->sinfo_start());
+  Object** end = &Memory::Object_at(code->sinfo_start() + code->sinfo_size());
+  v->VisitPointers(start, end);
+}
+
+
+static Object** ContextEntriesAddr(Code* code) {
+  ASSERT(code->sinfo_size() > 0);
+  // +2 for function name and calls eval:
+  return &Memory::Object_at(code->sinfo_start()) + 2;
+}
+
+
+static Object** ParameterEntriesAddr(Code* code) {
+  ASSERT(code->sinfo_size() > 0);
+  Object** p = ContextEntriesAddr(code);
+  int n;  // number of context slots;
+  p = ReadInt(p, &n);
+  return p + n*2 + 1;  // *2 for pairs, +1 for sentinel
+}
+
+
+static Object** StackSlotEntriesAddr(Code* code) {
+  ASSERT(code->sinfo_size() > 0);
+  Object** p = ParameterEntriesAddr(code);
+  int n;  // number of parameter slots;
+  p = ReadInt(p, &n);
+  return p + n + 1;  // +1 for sentinel
+}
+
+
+template<class Allocator>
+bool ScopeInfo<Allocator>::CallsEval(Code* code) {
+  if (code->sinfo_size() > 0) {
+    // +1 for function name:
+    Object** p = &Memory::Object_at(code->sinfo_start()) + 1;
+    bool calls_eval;
+    p = ReadBool(p, &calls_eval);
+    return calls_eval;
+  }
+  return true;
+}
+
+
+template<class Allocator>
+int ScopeInfo<Allocator>::NumberOfStackSlots(Code* code) {
+  if (code->sinfo_size() > 0) {
+    Object** p = StackSlotEntriesAddr(code);
+    int n;  // number of stack slots;
+    ReadInt(p, &n);
+    return n;
+  }
+  return 0;
+}
+
+
+template<class Allocator>
+int ScopeInfo<Allocator>::NumberOfContextSlots(Code* code) {
+  if (code->sinfo_size() > 0) {
+    Object** p = ContextEntriesAddr(code);
+    int n;  // number of context slots;
+    ReadInt(p, &n);
+    return n + Context::MIN_CONTEXT_SLOTS;
+  }
+  return 0;
+}
+
+
+template<class Allocator>
+int ScopeInfo<Allocator>::StackSlotIndex(Code* code, String* name) {
+  ASSERT(name->IsSymbol());
+  if (code->sinfo_size() > 0) {
+    // Loop below depends on the NULL sentinel after the stack slot names.
+    ASSERT(NumberOfStackSlots(code) > 0 ||
+           *(StackSlotEntriesAddr(code) + 1) == NULL);
+    // slots start after length entry
+    Object** p0 = StackSlotEntriesAddr(code) + 1;
+    Object** p = p0;
+    while (*p != NULL) {
+      if (*p == name) return p - p0;
+      p++;
+    }
+  }
+  return -1;
+}
+
+
+template<class Allocator>
+int ScopeInfo<Allocator>::ContextSlotIndex(Code* code,
+                                           String* name,
+                                           Variable::Mode* mode) {
+  ASSERT(name->IsSymbol());
+  if (code->sinfo_size() > 0) {
+    // Loop below depends on the NULL sentinel after the context slot names.
+    ASSERT(NumberOfContextSlots(code) >= Context::MIN_CONTEXT_SLOTS ||
+           *(ContextEntriesAddr(code) + 1) == NULL);
+    // slots start after length entry
+    Object** p0 = ContextEntriesAddr(code) + 1;
+    Object** p = p0;
+    // contexts may have no variable slots (in the presence of eval()).
+    while (*p != NULL) {
+      if (*p == name) {
+        ASSERT(((p - p0) & 1) == 0);
+        if (mode != NULL) {
+          ReadInt(p + 1, reinterpret_cast<int*>(mode));
+        }
+        return ((p - p0) >> 1) + Context::MIN_CONTEXT_SLOTS;
+      }
+      p += 2;
+    }
+  }
+  return -1;
+}
+
+
+template<class Allocator>
+int ScopeInfo<Allocator>::ParameterIndex(Code* code, String* name) {
+  ASSERT(name->IsSymbol());
+  if (code->sinfo_size() > 0) {
+    // We must read parameters from the end since for
+    // multiply declared parameters the value of the
+    // last declaration of that parameter is used
+    // inside a function (and thus we need to look
+    // at the last index). Was bug# 1110337.
+    //
+    // Eventually, we should only register such parameters
+    // once, with corresponding index. This requires a new
+    // implementation of the ScopeInfo code. See also other
+    // comments in this file regarding this.
+    Object** p = ParameterEntriesAddr(code);
+    int n;  // number of parameters
+    Object** p0 = ReadInt(p, &n);
+    p = p0 + n;
+    while (p > p0) {
+      p--;
+      if (*p == name) return p - p0;
+    }
+  }
+  return -1;
+}
+
+
+template<class Allocator>
+int ScopeInfo<Allocator>::FunctionContextSlotIndex(Code* code, String* name) {
+  ASSERT(name->IsSymbol());
+  if (code->sinfo_size() > 0) {
+    Object** p = &Memory::Object_at(code->sinfo_start());
+    if (*p == name) {
+      p = ContextEntriesAddr(code);
+      int n;  // number of context slots
+      ReadInt(p, &n);
+      ASSERT(n != 0);
+      // The function context slot is the last entry.
+      return n + Context::MIN_CONTEXT_SLOTS - 1;
+    }
+  }
+  return -1;
+}
+
+
+template<class Allocator>
+Handle<String> ScopeInfo<Allocator>::LocalName(int i) const {
+  // A local variable can be allocated either on the stack or in the context.
+  // For variables allocated in the context they are always preceded by the
+  // number Context::MIN_CONTEXT_SLOTS number of fixed allocated slots in the
+  // context.
+  if (i < number_of_stack_slots()) {
+    return stack_slot_name(i);
+  } else {
+    return context_slot_name(i - number_of_stack_slots() +
+                             Context::MIN_CONTEXT_SLOTS);
+  }
+}
+
+
+template<class Allocator>
+int ScopeInfo<Allocator>::NumberOfLocals() const {
+  int number_of_locals = number_of_stack_slots();
+  if (number_of_context_slots() > 0) {
+    ASSERT(number_of_context_slots() >= Context::MIN_CONTEXT_SLOTS);
+    number_of_locals += number_of_context_slots() - Context::MIN_CONTEXT_SLOTS;
+  }
+  return number_of_locals;
+}
+
+
+#ifdef DEBUG
+template <class Allocator>
+static void PrintList(const char* list_name,
+                      int nof_internal_slots,
+                      List<Handle<String>, Allocator>& list) {
+  if (list.length() > 0) {
+    PrintF("\n  // %s\n", list_name);
+    if (nof_internal_slots > 0) {
+      PrintF("  %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1);
+    }
+    for (int i = 0; i < list.length(); i++) {
+      PrintF("  %2d ", i + nof_internal_slots);
+      list[i]->ShortPrint();
+      PrintF("\n");
+    }
+  }
+}
+
+
+template<class Allocator>
+void ScopeInfo<Allocator>::Print() {
+  PrintF("ScopeInfo ");
+  if (function_name_->length() > 0)
+    function_name_->ShortPrint();
+  else
+    PrintF("/* no function name */");
+  PrintF("{");
+
+  PrintList<Allocator>("parameters", 0, parameters_);
+  PrintList<Allocator>("stack slots", 0, stack_slots_);
+  PrintList<Allocator>("context slots", Context::MIN_CONTEXT_SLOTS,
+                       context_slots_);
+
+  PrintF("}\n");
+}
+#endif  // DEBUG
+
+
+// Make sure the classes get instantiated by the template system.
+template class ScopeInfo<FreeStoreAllocationPolicy>;
+template class ScopeInfo<PreallocatedStorage>;
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/scopeinfo.h b/deps/v8/src/scopeinfo.h
new file mode 100644
index 0000000..dbe235a
--- /dev/null
+++ b/deps/v8/src/scopeinfo.h
@@ -0,0 +1,155 @@
+// 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_SCOPEINFO_H_
+#define V8_SCOPEINFO_H_
+
+#include "variables.h"
+
+namespace v8 { namespace internal {
+
+// Scope information represents information about a functions's
+// scopes (currently only one, because we don't do any inlining)
+// and the allocation of the scope's variables. Scope information
+// is stored in a compressed form with Code objects and is used
+// at runtime (stack dumps, deoptimization, etc.).
+//
+// Historical note: In other VMs built by this team, ScopeInfo was
+// usually called DebugInfo since the information was used (among
+// other things) for on-demand debugging (Self, Smalltalk). However,
+// DebugInfo seems misleading, since this information is primarily used
+// in debugging-unrelated contexts.
+
+// Forward defined as
+// template <class Allocator = FreeStoreAllocationPolicy> class ScopeInfo;
+template<class Allocator>
+class ScopeInfo BASE_EMBEDDED {
+ public:
+  // Create a ScopeInfo instance from a scope.
+  explicit ScopeInfo(Scope* scope);
+
+  // Create a ScopeInfo instance from a Code object.
+  explicit ScopeInfo(Code* code);
+
+  // Write the ScopeInfo data into a Code object, and returns the
+  // amount of space that was needed. If no Code object is provided
+  // (NULL handle), Serialize() only returns the amount of space needed.
+  //
+  // This operations requires that the Code object has the correct amount
+  // of space for the ScopeInfo data; otherwise the operation fails (fatal
+  // error). Any existing scope info in the Code object is simply overwritten.
+  int Serialize(Code* code);
+
+  // Garbage collection support for scope info embedded in Code objects.
+  // This code is in ScopeInfo because only here we should have to know
+  // about the encoding.
+  static void IterateScopeInfo(Code* code, ObjectVisitor* v);
+
+
+  // --------------------------------------------------------------------------
+  // Lookup
+
+  Handle<String> function_name() const  { return function_name_; }
+
+  Handle<String> parameter_name(int i) const  { return parameters_[i]; }
+  int number_of_parameters() const  { return parameters_.length(); }
+
+  Handle<String> stack_slot_name(int i) const  { return stack_slots_[i]; }
+  int number_of_stack_slots() const  { return stack_slots_.length(); }
+
+  Handle<String> context_slot_name(int i) const {
+    return context_slots_[i - Context::MIN_CONTEXT_SLOTS];
+  }
+  int number_of_context_slots() const {
+    int l = context_slots_.length();
+    return l == 0 ? 0 : l + Context::MIN_CONTEXT_SLOTS;
+  }
+
+  Handle<String> LocalName(int i) const;
+  int NumberOfLocals() const;
+
+  // --------------------------------------------------------------------------
+  // The following functions provide quick access to scope info details
+  // for runtime routines w/o the need to explicitly create a ScopeInfo
+  // object.
+  //
+  // ScopeInfo is the only class which should have to know about the
+  // encoding of it's information in a Code object, which is why these
+  // functions are in this class.
+
+  // Does this scope call eval.
+  static bool CallsEval(Code* code);
+
+  // Return the number of stack slots for code.
+  static int NumberOfStackSlots(Code* code);
+
+  // Return the number of context slots for code.
+  static int NumberOfContextSlots(Code* code);
+
+  // Lookup support for scope info embedded in Code objects. Returns
+  // the stack slot index for a given slot name if the slot is
+  // present; otherwise returns a value < 0. The name must be a symbol
+  // (canonicalized).
+  static int StackSlotIndex(Code* code, String* name);
+
+  // Lookup support for scope info embedded in Code objects. Returns the
+  // context slot index for a given slot name if the slot is present; otherwise
+  // returns a value < 0. The name must be a symbol (canonicalized).
+  // If the slot is present and mode != NULL, sets *mode to the corresponding
+  // mode for that variable.
+  static int ContextSlotIndex(Code* code, String* name, Variable::Mode* mode);
+
+  // Lookup support for scope info embedded in Code objects. Returns the
+  // parameter index for a given parameter name if the parameter is present;
+  // otherwise returns a value < 0. The name must be a symbol (canonicalized).
+  static int ParameterIndex(Code* code, String* name);
+
+  // Lookup support for scope info embedded in Code objects. Returns the
+  // function context slot index if the function name is present (named
+  // function expressions, only), otherwise returns a value < 0. The name
+  // must be a symbol (canonicalized).
+  static int FunctionContextSlotIndex(Code* code, String* name);
+
+  // --------------------------------------------------------------------------
+  // Debugging support
+
+#ifdef DEBUG
+  void Print();
+#endif
+
+ private:
+  Handle<String> function_name_;
+  bool calls_eval_;
+  List<Handle<String>, Allocator > parameters_;
+  List<Handle<String>, Allocator > stack_slots_;
+  List<Handle<String>, Allocator > context_slots_;
+  List<Variable::Mode, Allocator > context_modes_;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_SCOPEINFO_H_
diff --git a/deps/v8/src/scopes.cc b/deps/v8/src/scopes.cc
new file mode 100644
index 0000000..e959f02
--- /dev/null
+++ b/deps/v8/src/scopes.cc
@@ -0,0 +1,946 @@
+// 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.
+
+#include "v8.h"
+
+#include "prettyprinter.h"
+#include "scopeinfo.h"
+#include "scopes.h"
+
+namespace v8 { namespace internal {
+
+// ----------------------------------------------------------------------------
+// A Zone allocator for use with LocalsMap.
+
+class ZoneAllocator: public Allocator {
+ public:
+  /* nothing to do */
+  virtual ~ZoneAllocator()  {}
+
+  virtual void* New(size_t size)  { return Zone::New(size); }
+
+  /* ignored - Zone is freed in one fell swoop */
+  virtual void Delete(void* p)  {}
+};
+
+
+static ZoneAllocator LocalsMapAllocator;
+
+
+// ----------------------------------------------------------------------------
+// Implementation of LocalsMap
+//
+// Note: We are storing the handle locations as key values in the hash map.
+//       When inserting a new variable via Declare(), we rely on the fact that
+//       the handle location remains alive for the duration of that variable
+//       use. Because a Variable holding a handle with the same location exists
+//       this is ensured.
+
+static bool Match(void* key1, void* key2) {
+  String* name1 = *reinterpret_cast<String**>(key1);
+  String* name2 = *reinterpret_cast<String**>(key2);
+  ASSERT(name1->IsSymbol());
+  ASSERT(name2->IsSymbol());
+  return name1 == name2;
+}
+
+
+// Dummy constructor
+LocalsMap::LocalsMap(bool gotta_love_static_overloading) : HashMap()  {}
+
+LocalsMap::LocalsMap() : HashMap(Match, &LocalsMapAllocator, 8)  {}
+LocalsMap::~LocalsMap()  {}
+
+
+Variable* LocalsMap::Declare(Scope* scope,
+                             Handle<String> name,
+                             Variable::Mode mode,
+                             bool is_valid_LHS,
+                             bool is_this) {
+  HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), true);
+  if (p->value == NULL) {
+    // The variable has not been declared yet -> insert it.
+    ASSERT(p->key == name.location());
+    p->value = new Variable(scope, name, mode, is_valid_LHS, is_this);
+  }
+  return reinterpret_cast<Variable*>(p->value);
+}
+
+
+Variable* LocalsMap::Lookup(Handle<String> name) {
+  HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), false);
+  if (p != NULL) {
+    ASSERT(*reinterpret_cast<String**>(p->key) == *name);
+    ASSERT(p->value != NULL);
+    return reinterpret_cast<Variable*>(p->value);
+  }
+  return NULL;
+}
+
+
+// ----------------------------------------------------------------------------
+// Implementation of Scope
+
+
+// Dummy constructor
+Scope::Scope()
+  : inner_scopes_(0),
+    locals_(false),
+    temps_(0),
+    params_(0),
+    nonlocals_(0),
+    unresolved_(0),
+    decls_(0) {
+}
+
+
+Scope::Scope(Scope* outer_scope, Type type)
+  : outer_scope_(outer_scope),
+    inner_scopes_(4),
+    type_(type),
+    scope_name_(Factory::empty_symbol()),
+    locals_(),
+    temps_(4),
+    params_(4),
+    nonlocals_(4),
+    unresolved_(16),
+    decls_(4),
+    receiver_(NULL),
+    function_(NULL),
+    arguments_(NULL),
+    arguments_shadow_(NULL),
+    illegal_redecl_(NULL),
+    scope_inside_with_(false),
+    scope_contains_with_(false),
+    scope_calls_eval_(false),
+    outer_scope_calls_eval_(false),
+    inner_scope_calls_eval_(false),
+    outer_scope_is_eval_scope_(false),
+    force_eager_compilation_(false),
+    num_stack_slots_(0),
+    num_heap_slots_(0) {
+  // At some point we might want to provide outer scopes to
+  // eval scopes (by walking the stack and reading the scope info).
+  // In that case, the ASSERT below needs to be adjusted.
+  ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL));
+  ASSERT(!HasIllegalRedeclaration());
+}
+
+
+void Scope::Initialize(bool inside_with) {
+  // Add this scope as a new inner scope of the outer scope.
+  if (outer_scope_ != NULL) {
+    outer_scope_->inner_scopes_.Add(this);
+    scope_inside_with_ = outer_scope_->scope_inside_with_ || inside_with;
+  } else {
+    scope_inside_with_ = inside_with;
+  }
+
+  // Declare convenience variables.
+  // Declare and allocate receiver (even for the global scope, and even
+  // if naccesses_ == 0).
+  // NOTE: When loading parameters in the global scope, we must take
+  // care not to access them as properties of the global object, but
+  // instead load them directly from the stack. Currently, the only
+  // such parameter is 'this' which is passed on the stack when
+  // invoking scripts
+  { Variable* var =
+      locals_.Declare(this, Factory::this_symbol(), Variable::VAR, false, true);
+    var->rewrite_ = new Slot(var, Slot::PARAMETER, -1);
+    receiver_ = new VariableProxy(Factory::this_symbol(), true, false);
+    receiver_->BindTo(var);
+  }
+
+  if (is_function_scope()) {
+    // Declare 'arguments' variable which exists in all functions.
+    // Note that it may never be accessed, in which case it won't
+    // be allocated during variable allocation.
+    Declare(Factory::arguments_symbol(), Variable::VAR);
+  }
+}
+
+
+
+Variable* Scope::LookupLocal(Handle<String> name) {
+  return locals_.Lookup(name);
+}
+
+
+Variable* Scope::Lookup(Handle<String> name) {
+  for (Scope* scope = this;
+       scope != NULL;
+       scope = scope->outer_scope()) {
+    Variable* var = scope->LookupLocal(name);
+    if (var != NULL) return var;
+  }
+  return NULL;
+}
+
+
+Variable* Scope::DeclareFunctionVar(Handle<String> name) {
+  ASSERT(is_function_scope() && function_ == NULL);
+  function_ = new Variable(this, name, Variable::CONST, true, false);
+  return function_;
+}
+
+
+Variable* Scope::Declare(Handle<String> name, Variable::Mode mode) {
+  // DYNAMIC variables are introduces during variable allocation,
+  // INTERNAL variables are allocated explicitly, and TEMPORARY
+  // variables are allocated via NewTemporary().
+  ASSERT(mode == Variable::VAR || mode == Variable::CONST);
+  return locals_.Declare(this, name, mode, true, false);
+}
+
+
+void Scope::AddParameter(Variable* var) {
+  ASSERT(is_function_scope());
+  ASSERT(LookupLocal(var->name()) == var);
+  params_.Add(var);
+}
+
+
+VariableProxy* Scope::NewUnresolved(Handle<String> name, bool inside_with) {
+  // Note that we must not share the unresolved variables with
+  // the same name because they may be removed selectively via
+  // RemoveUnresolved().
+  VariableProxy* proxy = new VariableProxy(name, false, inside_with);
+  unresolved_.Add(proxy);
+  return proxy;
+}
+
+
+void Scope::RemoveUnresolved(VariableProxy* var) {
+  // Most likely (always?) any variable we want to remove
+  // was just added before, so we search backwards.
+  for (int i = unresolved_.length(); i-- > 0;) {
+    if (unresolved_[i] == var) {
+      unresolved_.Remove(i);
+      return;
+    }
+  }
+}
+
+
+VariableProxy* Scope::NewTemporary(Handle<String> name) {
+  Variable* var = new Variable(this, name, Variable::TEMPORARY, true, false);
+  VariableProxy* tmp = new VariableProxy(name, false, false);
+  tmp->BindTo(var);
+  temps_.Add(var);
+  return tmp;
+}
+
+
+void Scope::AddDeclaration(Declaration* declaration) {
+  decls_.Add(declaration);
+}
+
+
+void Scope::SetIllegalRedeclaration(Expression* expression) {
+  // Only set the illegal redeclaration expression the
+  // first time the function is called.
+  if (!HasIllegalRedeclaration()) {
+    illegal_redecl_ = expression;
+  }
+  ASSERT(HasIllegalRedeclaration());
+}
+
+
+void Scope::VisitIllegalRedeclaration(AstVisitor* visitor) {
+  ASSERT(HasIllegalRedeclaration());
+  illegal_redecl_->Accept(visitor);
+}
+
+
+template<class Allocator>
+void Scope::CollectUsedVariables(List<Variable*, Allocator>* locals) {
+  // Collect variables in this scope.
+  // Note that the function_ variable - if present - is not
+  // collected here but handled separately in ScopeInfo
+  // which is the current user of this function).
+  for (int i = 0; i < temps_.length(); i++) {
+    Variable* var = temps_[i];
+    if (var->var_uses()->is_used()) {
+      locals->Add(var);
+    }
+  }
+  for (LocalsMap::Entry* p = locals_.Start(); p != NULL; p = locals_.Next(p)) {
+    Variable* var = reinterpret_cast<Variable*>(p->value);
+    if (var->var_uses()->is_used()) {
+      locals->Add(var);
+    }
+  }
+}
+
+
+// Make sure the method gets instantiated by the template system.
+template void Scope::CollectUsedVariables(
+    List<Variable*, FreeStoreAllocationPolicy>* locals);
+template void Scope::CollectUsedVariables(
+    List<Variable*, PreallocatedStorage>* locals);
+
+
+void Scope::AllocateVariables(Handle<Context> context) {
+  ASSERT(outer_scope_ == NULL);  // eval or global scopes only
+
+  // 1) Propagate scope information.
+  // If we are in an eval scope, we may have other outer scopes about
+  // which we don't know anything at this point. Thus we must be conservative
+  // and assume they may invoke eval themselves. Eventually we could capture
+  // this information in the ScopeInfo and then use it here (by traversing
+  // the call chain stack, at compile time).
+  bool eval_scope = is_eval_scope();
+  PropagateScopeInfo(eval_scope, eval_scope);
+
+  // 2) Resolve variables.
+  Scope* global_scope = NULL;
+  if (is_global_scope()) global_scope = this;
+  ResolveVariablesRecursively(global_scope, context);
+
+  // 3) Allocate variables.
+  AllocateVariablesRecursively();
+}
+
+
+bool Scope::AllowsLazyCompilation() const {
+  return !force_eager_compilation_ && HasTrivialOuterContext();
+}
+
+
+bool Scope::HasTrivialContext() const {
+  // A function scope has a trivial context if it always is the global
+  // context. We iteratively scan out the context chain to see if
+  // there is anything that makes this scope non-trivial; otherwise we
+  // return true.
+  for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) {
+    if (scope->is_eval_scope()) return false;
+    if (scope->scope_inside_with_) return false;
+    if (scope->num_heap_slots_ > 0) return false;
+  }
+  return true;
+}
+
+
+bool Scope::HasTrivialOuterContext() const {
+  Scope* outer = outer_scope_;
+  if (outer == NULL) return true;
+  // Note that the outer context may be trivial in general, but the current
+  // scope may be inside a 'with' statement in which case the outer context
+  // for this scope is not trivial.
+  return !scope_inside_with_ && outer->HasTrivialContext();
+}
+
+
+int Scope::ContextChainLength(Scope* scope) {
+  int n = 0;
+  for (Scope* s = this; s != scope; s = s->outer_scope_) {
+    ASSERT(s != NULL);  // scope must be in the scope chain
+    if (s->num_heap_slots() > 0) n++;
+  }
+  return n;
+}
+
+
+#ifdef DEBUG
+static const char* Header(Scope::Type type) {
+  switch (type) {
+    case Scope::EVAL_SCOPE: return "eval";
+    case Scope::FUNCTION_SCOPE: return "function";
+    case Scope::GLOBAL_SCOPE: return "global";
+  }
+  UNREACHABLE();
+  return NULL;
+}
+
+
+static void Indent(int n, const char* str) {
+  PrintF("%*s%s", n, "", str);
+}
+
+
+static void PrintName(Handle<String> name) {
+  SmartPointer<char> s = name->ToCString(DISALLOW_NULLS);
+  PrintF("%s", *s);
+}
+
+
+static void PrintVar(PrettyPrinter* printer, int indent, Variable* var) {
+  if (var->var_uses()->is_used() || var->rewrite() != NULL) {
+    Indent(indent, Variable::Mode2String(var->mode()));
+    PrintF(" ");
+    PrintName(var->name());
+    PrintF(";  // ");
+    if (var->rewrite() != NULL) PrintF("%s, ", printer->Print(var->rewrite()));
+    if (var->is_accessed_from_inner_scope()) PrintF("inner scope access, ");
+    PrintF("var ");
+    var->var_uses()->Print();
+    PrintF(", obj ");
+    var->obj_uses()->Print();
+    PrintF("\n");
+  }
+}
+
+
+void Scope::Print(int n) {
+  int n0 = (n > 0 ? n : 0);
+  int n1 = n0 + 2;  // indentation
+
+  // Print header.
+  Indent(n0, Header(type_));
+  if (scope_name_->length() > 0) {
+    PrintF(" ");
+    PrintName(scope_name_);
+  }
+
+  // Print parameters, if any.
+  if (is_function_scope()) {
+    PrintF(" (");
+    for (int i = 0; i < params_.length(); i++) {
+      if (i > 0) PrintF(", ");
+      PrintName(params_[i]->name());
+    }
+    PrintF(")");
+  }
+
+  PrintF(" {\n");
+
+  // Function name, if any (named function literals, only).
+  if (function_ != NULL) {
+    Indent(n1, "// (local) function name: ");
+    PrintName(function_->name());
+    PrintF("\n");
+  }
+
+  // Scope info.
+  if (HasTrivialOuterContext()) {
+    Indent(n1, "// scope has trivial outer context\n");
+  }
+  if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n");
+  if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n");
+  if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
+  if (outer_scope_calls_eval_) Indent(n1, "// outer scope calls 'eval'\n");
+  if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
+  if (outer_scope_is_eval_scope_) {
+    Indent(n1, "// outer scope is 'eval' scope\n");
+  }
+  if (num_stack_slots_ > 0) { Indent(n1, "// ");
+  PrintF("%d stack slots\n", num_stack_slots_); }
+  if (num_heap_slots_ > 0) { Indent(n1, "// ");
+  PrintF("%d heap slots\n", num_heap_slots_); }
+
+  // Print locals.
+  PrettyPrinter printer;
+  Indent(n1, "// function var\n");
+  if (function_ != NULL) {
+    PrintVar(&printer, n1, function_);
+  }
+
+  Indent(n1, "// temporary vars\n");
+  for (int i = 0; i < temps_.length(); i++) {
+    PrintVar(&printer, n1, temps_[i]);
+  }
+
+  Indent(n1, "// local vars\n");
+  for (LocalsMap::Entry* p = locals_.Start(); p != NULL; p = locals_.Next(p)) {
+    Variable* var = reinterpret_cast<Variable*>(p->value);
+    PrintVar(&printer, n1, var);
+  }
+
+  Indent(n1, "// nonlocal vars\n");
+  for (int i = 0; i < nonlocals_.length(); i++)
+    PrintVar(&printer, n1, nonlocals_[i]);
+
+  // Print inner scopes (disable by providing negative n).
+  if (n >= 0) {
+    for (int i = 0; i < inner_scopes_.length(); i++) {
+      PrintF("\n");
+      inner_scopes_[i]->Print(n1);
+    }
+  }
+
+  Indent(n0, "}\n");
+}
+#endif  // DEBUG
+
+
+Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) {
+  // Space optimization: reuse existing non-local with the same name
+  // and mode.
+  for (int i = 0; i < nonlocals_.length(); i++) {
+    Variable* var = nonlocals_[i];
+    if (var->name().is_identical_to(name) && var->mode() == mode) {
+      return var;
+    }
+  }
+
+  // Otherwise create a new non-local and add it to the list.
+  Variable* var = new Variable(NULL, name, mode, true, false);
+  nonlocals_.Add(var);
+
+  // Allocate it by giving it a dynamic lookup.
+  var->rewrite_ = new Slot(var, Slot::LOOKUP, -1);
+
+  return var;
+}
+
+
+// Lookup a variable starting with this scope. The result is either
+// the statically resolved (local!) variable belonging to an outer scope,
+// or NULL. It may be NULL because a) we couldn't find a variable, or b)
+// because the variable is just a guess (and may be shadowed by another
+// variable that is introduced dynamically via an 'eval' call or a 'with'
+// statement).
+Variable* Scope::LookupRecursive(Handle<String> name,
+                                 bool inner_lookup,
+                                 Variable** invalidated_local) {
+  // If we find a variable, but the current scope calls 'eval', the found
+  // variable may not be the correct one (the 'eval' may introduce a
+  // property with the same name). In that case, remember that the variable
+  // found is just a guess.
+  bool guess = scope_calls_eval_;
+
+  // Try to find the variable in this scope.
+  Variable* var = LookupLocal(name);
+
+  if (var != NULL) {
+    // We found a variable. If this is not an inner lookup, we are done.
+    // (Even if there is an 'eval' in this scope which introduces the
+    // same variable again, the resulting variable remains the same.
+    // Note that enclosing 'with' statements are handled at the call site.)
+    if (!inner_lookup)
+      return var;
+
+  } else {
+    // We did not find a variable locally. Check against the function variable,
+    // if any. We can do this for all scopes, since the function variable is
+    // only present - if at all - for function scopes.
+    //
+    // This lookup corresponds to a lookup in the "intermediate" scope sitting
+    // between this scope and the outer scope. (ECMA-262, 3rd., requires that
+    // the name of named function literal is kept in an intermediate scope
+    // in between this scope and the next outer scope.)
+    if (function_ != NULL && function_->name().is_identical_to(name)) {
+      var = function_;
+
+    } else if (outer_scope_ != NULL) {
+      var = outer_scope_->LookupRecursive(name, true, invalidated_local);
+      // We may have found a variable in an outer scope. However, if
+      // the current scope is inside a 'with', the actual variable may
+      // be a property introduced via the 'with' statement. Then, the
+      // variable we may have found is just a guess.
+      if (scope_inside_with_)
+        guess = true;
+    }
+
+    // If we did not find a variable, we are done.
+    if (var == NULL)
+      return NULL;
+  }
+
+  ASSERT(var != NULL);
+
+  // If this is a lookup from an inner scope, mark the variable.
+  if (inner_lookup)
+    var->is_accessed_from_inner_scope_ = true;
+
+  // If the variable we have found is just a guess, invalidate the result.
+  if (guess) {
+    *invalidated_local = var;
+    var = NULL;
+  }
+
+  return var;
+}
+
+
+void Scope::ResolveVariable(Scope* global_scope,
+                            Handle<Context> context,
+                            VariableProxy* proxy) {
+  ASSERT(global_scope == NULL || global_scope->is_global_scope());
+
+  // If the proxy is already resolved there's nothing to do
+  // (functions and consts may be resolved by the parser).
+  if (proxy->var() != NULL) return;
+
+  // Otherwise, try to resolve the variable.
+  Variable* invalidated_local = NULL;
+  Variable* var = LookupRecursive(proxy->name(), false, &invalidated_local);
+
+  if (proxy->inside_with()) {
+    // If we are inside a local 'with' statement, all bets are off
+    // and we cannot resolve the proxy to a local variable even if
+    // we found an outer matching variable.
+    // Note that we must do a lookup anyway, because if we find one,
+    // we must mark that variable as potentially accessed from this
+    // inner scope (the property may not be in the 'with' object).
+    var = NonLocal(proxy->name(), Variable::DYNAMIC);
+
+  } else {
+    // We are not inside a local 'with' statement.
+
+    if (var == NULL) {
+      // We did not find the variable. We have a global variable
+      // if we are in the global scope (we know already that we
+      // are outside a 'with' statement) or if there is no way
+      // that the variable might be introduced dynamically (through
+      // a local or outer eval() call, or an outer 'with' statement),
+      // or we don't know about the outer scope (because we are
+      // in an eval scope).
+      if (is_global_scope() ||
+          !(scope_inside_with_ || outer_scope_is_eval_scope_ ||
+            scope_calls_eval_ || outer_scope_calls_eval_)) {
+        // We must have a global variable.
+        ASSERT(global_scope != NULL);
+        var = new Variable(global_scope, proxy->name(),
+                           Variable::DYNAMIC, true, false);
+        // Ideally we simply rewrite these variables into property
+        // accesses. Unfortunately, we cannot do this here at the
+        // moment because then we can't differentiate between
+        // global variable ('x') and global property ('this.x') access.
+        // If 'x' doesn't exist, the former leads to an error, while the
+        // latter returns undefined. Sigh...
+        // var->rewrite_ = new Property(new Literal(env_->global()),
+        //                              new Literal(proxy->name()));
+
+      } else if (scope_inside_with_) {
+        // If we are inside a with statement we give up and look up
+        // the variable at runtime.
+        var = NonLocal(proxy->name(), Variable::DYNAMIC);
+
+      } else if (invalidated_local != NULL) {
+        // No with statements are involved and we found a local
+        // variable that might be shadowed by eval introduced
+        // variables.
+        var = NonLocal(proxy->name(), Variable::DYNAMIC_LOCAL);
+        var->set_local_if_not_shadowed(invalidated_local);
+
+      } else if (outer_scope_is_eval_scope_) {
+        // No with statements and we did not find a local and the code
+        // is executed with a call to eval.  The context contains
+        // scope information that we can use to determine if the
+        // variable is global if it is not shadowed by eval-introduced
+        // variables.
+        if (context->GlobalIfNotShadowedByEval(proxy->name())) {
+          var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL);
+
+        } else {
+          var = NonLocal(proxy->name(), Variable::DYNAMIC);
+        }
+
+      } else {
+        // No with statements and we did not find a local and the code
+        // is not executed with a call to eval.  We know that this
+        // variable is global unless it is shadowed by eval-introduced
+        // variables.
+        var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL);
+      }
+    }
+  }
+
+  proxy->BindTo(var);
+}
+
+
+void Scope::ResolveVariablesRecursively(Scope* global_scope,
+                                        Handle<Context> context) {
+  ASSERT(global_scope == NULL || global_scope->is_global_scope());
+
+  // Resolve unresolved variables for this scope.
+  for (int i = 0; i < unresolved_.length(); i++) {
+    ResolveVariable(global_scope, context, unresolved_[i]);
+  }
+
+  // Resolve unresolved variables for inner scopes.
+  for (int i = 0; i < inner_scopes_.length(); i++) {
+    inner_scopes_[i]->ResolveVariablesRecursively(global_scope, context);
+  }
+}
+
+
+bool Scope::PropagateScopeInfo(bool outer_scope_calls_eval,
+                               bool outer_scope_is_eval_scope) {
+  if (outer_scope_calls_eval) {
+    outer_scope_calls_eval_ = true;
+  }
+
+  if (outer_scope_is_eval_scope) {
+    outer_scope_is_eval_scope_ = true;
+  }
+
+  bool calls_eval = scope_calls_eval_ || outer_scope_calls_eval_;
+  bool is_eval = is_eval_scope() || outer_scope_is_eval_scope_;
+  for (int i = 0; i < inner_scopes_.length(); i++) {
+    Scope* inner_scope = inner_scopes_[i];
+    if (inner_scope->PropagateScopeInfo(calls_eval, is_eval)) {
+      inner_scope_calls_eval_ = true;
+    }
+    if (inner_scope->force_eager_compilation_) {
+      force_eager_compilation_ = true;
+    }
+  }
+
+  return scope_calls_eval_ || inner_scope_calls_eval_;
+}
+
+
+bool Scope::MustAllocate(Variable* var) {
+  // Give var a read/write use if there is a chance it might be
+  // accessed via an eval() call, or if it is a global variable.
+  // This is only possible if the variable has a visible name.
+  if ((var->is_this() || var->name()->length() > 0) &&
+      (var->is_accessed_from_inner_scope_ ||
+       scope_calls_eval_ || inner_scope_calls_eval_ ||
+       scope_contains_with_ || var->is_global())) {
+    var->var_uses()->RecordAccess(1);
+  }
+  return var->var_uses()->is_used();
+}
+
+
+bool Scope::MustAllocateInContext(Variable* var) {
+  // If var is accessed from an inner scope, or if there is a
+  // possibility that it might be accessed from the current or
+  // an inner scope (through an eval() call), it must be allocated
+  // in the context.
+  // Exceptions: Global variables and temporary variables must
+  // never be allocated in the (FixedArray part of the) context.
+  return
+    var->mode() != Variable::TEMPORARY &&
+    (var->is_accessed_from_inner_scope_ ||
+     scope_calls_eval_ || inner_scope_calls_eval_ ||
+     scope_contains_with_ || var->is_global());
+}
+
+
+bool Scope::HasArgumentsParameter() {
+  for (int i = 0; i < params_.length(); i++) {
+    if (params_[i]->name().is_identical_to(Factory::arguments_symbol()))
+      return true;
+  }
+  return false;
+}
+
+
+void Scope::AllocateStackSlot(Variable* var) {
+  var->rewrite_ = new Slot(var, Slot::LOCAL, num_stack_slots_++);
+}
+
+
+void Scope::AllocateHeapSlot(Variable* var) {
+  var->rewrite_ = new Slot(var, Slot::CONTEXT, num_heap_slots_++);
+}
+
+
+void Scope::AllocateParameterLocals() {
+  ASSERT(is_function_scope());
+  Variable* arguments = LookupLocal(Factory::arguments_symbol());
+  ASSERT(arguments != NULL);  // functions have 'arguments' declared implicitly
+  if (MustAllocate(arguments) && !HasArgumentsParameter()) {
+    // 'arguments' is used. Unless there is also a parameter called
+    // 'arguments', we must be conservative and access all parameters via
+    // the arguments object: The i'th parameter is rewritten into
+    // '.arguments[i]' (*). If we have a parameter named 'arguments', a
+    // (new) value is always assigned to it via the function
+    // invocation. Then 'arguments' denotes that specific parameter value
+    // and cannot be used to access the parameters, which is why we don't
+    // need to rewrite in that case.
+    //
+    // (*) Instead of having a parameter called 'arguments', we may have an
+    // assignment to 'arguments' in the function body, at some arbitrary
+    // point in time (possibly through an 'eval()' call!). After that
+    // assignment any re-write of parameters would be invalid (was bug
+    // 881452). Thus, we introduce a shadow '.arguments'
+    // variable which also points to the arguments object. For rewrites we
+    // use '.arguments' which remains valid even if we assign to
+    // 'arguments'. To summarize: If we need to rewrite, we allocate an
+    // 'arguments' object dynamically upon function invocation. The compiler
+    // introduces 2 local variables 'arguments' and '.arguments', both of
+    // which originally point to the arguments object that was
+    // allocated. All parameters are rewritten into property accesses via
+    // the '.arguments' variable. Thus, any changes to properties of
+    // 'arguments' are reflected in the variables and vice versa. If the
+    // 'arguments' variable is changed, '.arguments' still points to the
+    // correct arguments object and the rewrites still work.
+
+    // We are using 'arguments'. Tell the code generator that is needs to
+    // allocate the arguments object by setting 'arguments_'.
+    arguments_ = new VariableProxy(Factory::arguments_symbol(), false, false);
+    arguments_->BindTo(arguments);
+
+    // We also need the '.arguments' shadow variable. Declare it and create
+    // and bind the corresponding proxy. It's ok to declare it only now
+    // because it's a local variable that is allocated after the parameters
+    // have been allocated.
+    //
+    // Note: This is "almost" at temporary variable but we cannot use
+    // NewTemporary() because the mode needs to be INTERNAL since this
+    // variable may be allocated in the heap-allocated context (temporaries
+    // are never allocated in the context).
+    Variable* arguments_shadow =
+        new Variable(this, Factory::arguments_shadow_symbol(),
+                     Variable::INTERNAL, true, false);
+    arguments_shadow_ =
+        new VariableProxy(Factory::arguments_shadow_symbol(), false, false);
+    arguments_shadow_->BindTo(arguments_shadow);
+    temps_.Add(arguments_shadow);
+
+    // Allocate the parameters by rewriting them into '.arguments[i]' accesses.
+    for (int i = 0; i < params_.length(); i++) {
+      Variable* var = params_[i];
+      ASSERT(var->scope() == this);
+      if (MustAllocate(var)) {
+        if (MustAllocateInContext(var)) {
+          // It is ok to set this only now, because arguments is a local
+          // variable that is allocated after the parameters have been
+          // allocated.
+          arguments_shadow->is_accessed_from_inner_scope_ = true;
+        }
+        var->rewrite_ =
+          new Property(arguments_shadow_,
+                       new Literal(Handle<Object>(Smi::FromInt(i))),
+                       RelocInfo::kNoPosition,
+                       Property::SYNTHETIC);
+        arguments_shadow->var_uses()->RecordUses(var->var_uses());
+      }
+    }
+
+  } else {
+    // The arguments object is not used, so we can access parameters directly.
+    // The same parameter may occur multiple times in the parameters_ list.
+    // If it does, and if it is not copied into the context object, it must
+    // receive the highest parameter index for that parameter; thus iteration
+    // order is relevant!
+    for (int i = 0; i < params_.length(); i++) {
+      Variable* var = params_[i];
+      ASSERT(var->scope() == this);
+      if (MustAllocate(var)) {
+        if (MustAllocateInContext(var)) {
+          ASSERT(var->rewrite_ == NULL ||
+                 (var->slot() != NULL && var->slot()->type() == Slot::CONTEXT));
+          if (var->rewrite_ == NULL) {
+            // Only set the heap allocation if the parameter has not
+            // been allocated yet.
+            AllocateHeapSlot(var);
+          }
+        } else {
+          ASSERT(var->rewrite_ == NULL ||
+                 (var->slot() != NULL &&
+                  var->slot()->type() == Slot::PARAMETER));
+          // Set the parameter index always, even if the parameter
+          // was seen before! (We need to access the actual parameter
+          // supplied for the last occurrence of a multiply declared
+          // parameter.)
+          var->rewrite_ = new Slot(var, Slot::PARAMETER, i);
+        }
+      }
+    }
+  }
+}
+
+
+void Scope::AllocateNonParameterLocal(Variable* var) {
+  ASSERT(var->scope() == this);
+  ASSERT(var->rewrite_ == NULL ||
+         (!var->IsVariable(Factory::result_symbol())) ||
+         (var->slot() == NULL || var->slot()->type() != Slot::LOCAL));
+  if (MustAllocate(var) && var->rewrite_ == NULL) {
+    if (MustAllocateInContext(var)) {
+      AllocateHeapSlot(var);
+    } else {
+      AllocateStackSlot(var);
+    }
+  }
+}
+
+
+void Scope::AllocateNonParameterLocals() {
+  // Each variable occurs exactly once in the locals_ list; all
+  // variables that have no rewrite yet are non-parameter locals.
+
+  // Sort them according to use such that the locals with more uses
+  // get allocated first.
+  if (FLAG_usage_computation) {
+    // This is currently not implemented.
+  }
+
+  for (int i = 0; i < temps_.length(); i++) {
+    AllocateNonParameterLocal(temps_[i]);
+  }
+
+  for (LocalsMap::Entry* p = locals_.Start(); p != NULL; p = locals_.Next(p)) {
+    Variable* var = reinterpret_cast<Variable*>(p->value);
+    AllocateNonParameterLocal(var);
+  }
+
+  // Note: For now, function_ must be allocated at the very end.  If
+  // it gets allocated in the context, it must be the last slot in the
+  // context, because of the current ScopeInfo implementation (see
+  // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
+  if (function_ != NULL) {
+    AllocateNonParameterLocal(function_);
+  }
+}
+
+
+void Scope::AllocateVariablesRecursively() {
+  // The number of slots required for variables.
+  num_stack_slots_ = 0;
+  num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
+
+  // Allocate variables for inner scopes.
+  for (int i = 0; i < inner_scopes_.length(); i++) {
+    inner_scopes_[i]->AllocateVariablesRecursively();
+  }
+
+  // Allocate variables for this scope.
+  // Parameters must be allocated first, if any.
+  if (is_function_scope()) AllocateParameterLocals();
+  AllocateNonParameterLocals();
+
+  // Allocate context if necessary.
+  bool must_have_local_context = false;
+  if (scope_calls_eval_ || scope_contains_with_) {
+    // The context for the eval() call or 'with' statement in this scope.
+    // Unless we are in the global or an eval scope, we need a local
+    // context even if we didn't statically allocate any locals in it,
+    // and the compiler will access the context variable. If we are
+    // not in an inner scope, the scope is provided from the outside.
+    must_have_local_context = is_function_scope();
+  }
+
+  // If we didn't allocate any locals in the local context, then we only
+  // need the minimal number of slots if we must have a local context.
+  if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS &&
+      !must_have_local_context) {
+    num_heap_slots_ = 0;
+  }
+
+  // Allocation done.
+  ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
+}
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/scopes.h b/deps/v8/src/scopes.h
new file mode 100644
index 0000000..e78bd2a
--- /dev/null
+++ b/deps/v8/src/scopes.h
@@ -0,0 +1,366 @@
+// 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_SCOPES_H_
+#define V8_SCOPES_H_
+
+#include "ast.h"
+#include "hashmap.h"
+
+namespace v8 { namespace internal {
+
+
+// A hash map to support fast local variable declaration and lookup.
+
+class LocalsMap: public HashMap {
+ public:
+  LocalsMap();
+
+  // Dummy constructor.  This constructor doesn't set up the map
+  // properly so don't use it unless you have a good reason.
+  explicit LocalsMap(bool gotta_love_static_overloading);
+
+  virtual ~LocalsMap();
+
+  Variable* Declare(Scope* scope, Handle<String> name, Variable::Mode mode,
+                    bool is_valid_LHS, bool is_this);
+
+  Variable* Lookup(Handle<String> name);
+};
+
+
+// Global invariants after AST construction: Each reference (i.e. identifier)
+// to a JavaScript variable (including global properties) is represented by a
+// VariableProxy node. Immediately after AST construction and before variable
+// allocation, most VariableProxy nodes are "unresolved", i.e. not bound to a
+// corresponding variable (though some are bound during parse time). Variable
+// allocation binds each unresolved VariableProxy to one Variable and assigns
+// a location. Note that many VariableProxy nodes may refer to the same Java-
+// Script variable.
+
+class Scope: public ZoneObject {
+ public:
+  // ---------------------------------------------------------------------------
+  // Construction
+
+  enum Type {
+    EVAL_SCOPE,     // the top-level scope for an 'eval' source
+    FUNCTION_SCOPE,  // the top-level scope for a function
+    GLOBAL_SCOPE    // the top-level scope for a program or a top-level eval
+  };
+
+  Scope();
+  Scope(Scope* outer_scope, Type type);
+
+  virtual ~Scope() { }
+
+  // The scope name is only used for printing/debugging.
+  void SetScopeName(Handle<String> scope_name)  { scope_name_ = scope_name; }
+
+  void Initialize(bool inside_with);
+
+
+  // ---------------------------------------------------------------------------
+  // Declarations
+
+  // Lookup a variable in this scope. Returns the variable or NULL if not found.
+  virtual Variable* LookupLocal(Handle<String> name);
+
+  // Lookup a variable in this scope or outer scopes.
+  // Returns the variable or NULL if not found.
+  virtual Variable* Lookup(Handle<String> name);
+
+  // Declare the function variable for a function literal. This variable
+  // is in an intermediate scope between this function scope and the the
+  // outer scope. Only possible for function scopes; at most one variable.
+  Variable* DeclareFunctionVar(Handle<String> name);
+
+  // Declare a variable in this scope. If the variable has been
+  // declared before, the previously declared variable is returned.
+  virtual Variable* Declare(Handle<String> name, Variable::Mode mode);
+
+  // Add a parameter to the parameter list. The parameter must have been
+  // declared via Declare. The same parameter may occur more then once in
+  // the parameter list; they must be added in source order, from left to
+  // right.
+  void AddParameter(Variable* var);
+
+  // Create a new unresolved variable.
+  virtual VariableProxy* NewUnresolved(Handle<String> name, bool inside_with);
+
+  // Remove a unresolved variable. During parsing, an unresolved variable
+  // may have been added optimistically, but then only the variable name
+  // was used (typically for labels). If the variable was not declared, the
+  // addition introduced a new unresolved variable which may end up being
+  // allocated globally as a "ghost" variable. RemoveUnresolved removes
+  // such a variable again if it was added; otherwise this is a no-op.
+  void RemoveUnresolved(VariableProxy* var);
+
+  // Creates a new temporary variable in this scope and binds a proxy to it.
+  // The name is only used for printing and cannot be used to find the variable.
+  // In particular, the only way to get hold of the temporary is by keeping the
+  // VariableProxy* around.
+  virtual VariableProxy* NewTemporary(Handle<String> name);
+
+  // Adds the specific declaration node to the list of declarations in
+  // this scope. The declarations are processed as part of entering
+  // the scope; see codegen.cc:ProcessDeclarations.
+  void AddDeclaration(Declaration* declaration);
+
+  // ---------------------------------------------------------------------------
+  // Illegal redeclaration support.
+
+  // Set an expression node that will be executed when the scope is
+  // entered. We only keep track of one illegal redeclaration node per
+  // scope - the first one - so if you try to set it multiple times
+  // the additional requests will be silently ignored.
+  void SetIllegalRedeclaration(Expression* expression);
+
+  // Visit the illegal redeclaration expression. Do not call if the
+  // scope doesn't have an illegal redeclaration node.
+  void VisitIllegalRedeclaration(AstVisitor* visitor);
+
+  // Check if the scope has (at least) one illegal redeclaration.
+  bool HasIllegalRedeclaration() const { return illegal_redecl_ != NULL; }
+
+
+  // ---------------------------------------------------------------------------
+  // Scope-specific info.
+
+  // Inform the scope that the corresponding code contains a with statement.
+  void RecordWithStatement()  { scope_contains_with_ = true; }
+
+  // Inform the scope that the corresponding code contains an eval call.
+  void RecordEvalCall()  { scope_calls_eval_ = true; }
+
+
+  // ---------------------------------------------------------------------------
+  // Predicates.
+
+  // Specific scope types.
+  bool is_eval_scope() const  { return type_ == EVAL_SCOPE; }
+  bool is_function_scope() const  { return type_ == FUNCTION_SCOPE; }
+  bool is_global_scope() const  { return type_ == GLOBAL_SCOPE; }
+
+  // Information about which scopes calls eval.
+  bool calls_eval() const  { return scope_calls_eval_; }
+  bool outer_scope_calls_eval() const  { return outer_scope_calls_eval_; }
+
+  // Is this scope inside a with statement.
+  bool inside_with() const  { return scope_inside_with_; }
+  // Does this scope contain a with statement.
+  bool contains_with() const  { return scope_contains_with_; }
+
+  // The scope immediately surrounding this scope, or NULL.
+  Scope* outer_scope() const  { return outer_scope_; }
+
+  // ---------------------------------------------------------------------------
+  // Accessors.
+
+  // The variable corresponding to the (function) receiver.
+  VariableProxy* receiver() const  { return receiver_; }
+
+  // The variable holding the function literal for named function
+  // literals, or NULL.
+  // Only valid for function scopes.
+  Variable* function() const  {
+    ASSERT(is_function_scope());
+    return function_;
+  }
+
+  // Parameters. The left-most parameter has index 0.
+  // Only valid for function scopes.
+  Variable* parameter(int index) const  {
+    ASSERT(is_function_scope());
+    return params_[index];
+  }
+
+  int num_parameters() const  { return params_.length(); }
+
+  // The local variable 'arguments' if we need to allocate it; NULL otherwise.
+  // If arguments() exist, arguments_shadow() exists, too.
+  VariableProxy* arguments()  const  { return arguments_; }
+
+  // The '.arguments' shadow variable if we need to allocate it; NULL otherwise.
+  // If arguments_shadow() exist, arguments() exists, too.
+  VariableProxy* arguments_shadow()  const  { return arguments_shadow_; }
+
+  // Declarations list.
+  ZoneList<Declaration*>* declarations() { return &decls_; }
+
+
+
+  // ---------------------------------------------------------------------------
+  // Variable allocation.
+
+  // Collect all used locals in this scope.
+  template<class Allocator>
+  void CollectUsedVariables(List<Variable*, Allocator>* locals);
+
+  // Resolve and fill in the allocation information for all variables
+  // in this scopes. Must be called *after* all scopes have been
+  // processed (parsed) to ensure that unresolved variables can be
+  // resolved properly.
+  //
+  // In the case of code compiled and run using 'eval', the context
+  // parameter is the context in which eval was called.  In all other
+  // cases the context parameter is an empty handle.
+  void AllocateVariables(Handle<Context> context);
+
+  // Result of variable allocation.
+  int num_stack_slots() const  { return num_stack_slots_; }
+  int num_heap_slots() const  { return num_heap_slots_; }
+
+  // Make sure this scope and all outer scopes are eagerly compiled.
+  void ForceEagerCompilation()  { force_eager_compilation_ = true; }
+
+  // Determine if we can use lazy compilation for this scope.
+  bool AllowsLazyCompilation() const;
+
+  // True if the outer context of this scope is always the global context.
+  bool HasTrivialOuterContext() const;
+
+  // The number of contexts between this and scope; zero if this == scope.
+  int ContextChainLength(Scope* scope);
+
+
+  // ---------------------------------------------------------------------------
+  // Debugging.
+
+#ifdef DEBUG
+  void Print(int n = 0);  // n = indentation; n < 0 => don't print recursively
+#endif
+
+  // ---------------------------------------------------------------------------
+  // Implementation.
+ protected:
+  friend class ParserFactory;
+
+  // Scope tree.
+  Scope* outer_scope_;  // the immediately enclosing outer scope, or NULL
+  ZoneList<Scope*> inner_scopes_;  // the immediately enclosed inner scopes
+
+  // The scope type.
+  Type type_;
+
+  // Debugging support.
+  Handle<String> scope_name_;
+
+  // The variables declared in this scope:
+  // all user-declared variables (incl. parameters)
+  LocalsMap locals_;
+  // compiler-allocated (user-invisible) temporaries
+  ZoneList<Variable*> temps_;
+  // parameter list in source order
+  ZoneList<Variable*> params_;
+  // variables that must be looked up dynamically
+  ZoneList<Variable*> nonlocals_;
+  // unresolved variables referred to from this scope
+  ZoneList<VariableProxy*> unresolved_;
+  // declarations
+  ZoneList<Declaration*> decls_;
+  // convenience variable
+  VariableProxy* receiver_;
+  // function variable, if any; function scopes only
+  Variable* function_;
+  // convenience variable; function scopes only
+  VariableProxy* arguments_;
+  // convenience variable; function scopes only
+  VariableProxy* arguments_shadow_;
+
+  // Illegal redeclaration.
+  Expression* illegal_redecl_;
+
+  // Scope-specific information.
+  bool scope_inside_with_;  // this scope is inside a 'with' of some outer scope
+  bool scope_contains_with_;  // this scope contains a 'with' statement
+  bool scope_calls_eval_;  // this scope contains an 'eval' call
+
+  // Computed via PropagateScopeInfo.
+  bool outer_scope_calls_eval_;
+  bool inner_scope_calls_eval_;
+  bool outer_scope_is_eval_scope_;
+  bool force_eager_compilation_;
+
+  // Computed via AllocateVariables; function scopes only.
+  int num_stack_slots_;
+  int num_heap_slots_;
+
+  // Create a non-local variable with a given name.
+  // These variables are looked up dynamically at runtime.
+  Variable* NonLocal(Handle<String> name, Variable::Mode mode);
+
+  // Variable resolution.
+  Variable* LookupRecursive(Handle<String> name,
+                            bool inner_lookup,
+                            Variable** invalidated_local);
+  void ResolveVariable(Scope* global_scope,
+                       Handle<Context> context,
+                       VariableProxy* proxy);
+  void ResolveVariablesRecursively(Scope* global_scope,
+                                   Handle<Context> context);
+
+  // Scope analysis.
+  bool PropagateScopeInfo(bool outer_scope_calls_eval,
+                          bool outer_scope_is_eval_scope);
+  bool HasTrivialContext() const;
+
+  // Predicates.
+  bool MustAllocate(Variable* var);
+  bool MustAllocateInContext(Variable* var);
+  bool HasArgumentsParameter();
+
+  // Variable allocation.
+  void AllocateStackSlot(Variable* var);
+  void AllocateHeapSlot(Variable* var);
+  void AllocateParameterLocals();
+  void AllocateNonParameterLocal(Variable* var);
+  void AllocateNonParameterLocals();
+  void AllocateVariablesRecursively();
+};
+
+
+class DummyScope : public Scope {
+ public:
+  DummyScope() {
+    outer_scope_ = this;
+  }
+
+  virtual Variable* Lookup(Handle<String> name)  { return NULL; }
+  virtual Variable* Declare(Handle<String> name, Variable::Mode mode) {
+    return NULL;
+  }
+  virtual VariableProxy* NewUnresolved(Handle<String> name, bool inside_with) {
+    return NULL;
+  }
+  virtual VariableProxy* NewTemporary(Handle<String> name)  { return NULL; }
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_SCOPES_H_
diff --git a/deps/v8/src/serialize.cc b/deps/v8/src/serialize.cc
new file mode 100644
index 0000000..9a2be23
--- /dev/null
+++ b/deps/v8/src/serialize.cc
@@ -0,0 +1,1596 @@
+// 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.
+
+#include "v8.h"
+
+#include "accessors.h"
+#include "api.h"
+#include "execution.h"
+#include "global-handles.h"
+#include "ic-inl.h"
+#include "natives.h"
+#include "platform.h"
+#include "runtime.h"
+#include "serialize.h"
+#include "stub-cache.h"
+#include "v8threads.h"
+
+namespace v8 { namespace internal {
+
+// Encoding: a RelativeAddress must be able to fit in a pointer:
+// it is encoded as an Address with (from MS to LS bits):
+// 27 bits identifying a word in the space, in one of three formats:
+// - MAP and OLD spaces: 16 bits of page number, 11 bits of word offset in page
+// - NEW space:          27 bits of word offset
+// - LO space:           27 bits of page number
+// 3 bits to encode the AllocationSpace (special values for code in LO space)
+// 2 bits identifying this as a HeapObject
+
+const int kSpaceShift = kHeapObjectTagSize;
+const int kSpaceBits = kSpaceTagSize;
+const int kSpaceMask = kSpaceTagMask;
+
+// These value are used instead of space numbers when serializing/
+// deserializing.  They indicate an object that is in large object space, but
+// should be treated specially.
+// Make the pages executable on platforms that support it:
+const int kLOSpaceExecutable = LAST_SPACE + 1;
+// Reserve space for write barrier bits (for objects that can contain
+// references to new space):
+const int kLOSpacePointer = LAST_SPACE + 2;
+
+
+const int kOffsetShift = kSpaceShift + kSpaceBits;
+const int kOffsetBits = 11;
+const int kOffsetMask = (1 << kOffsetBits) - 1;
+
+const int kPageBits = 32 - (kOffsetBits + kSpaceBits + kHeapObjectTagSize);
+const int kPageShift = kOffsetShift + kOffsetBits;
+const int kPageMask = (1 << kPageBits) - 1;
+
+const int kPageAndOffsetShift = kOffsetShift;
+const int kPageAndOffsetBits = kPageBits + kOffsetBits;
+const int kPageAndOffsetMask = (1 << kPageAndOffsetBits) - 1;
+
+
+static inline AllocationSpace GetSpace(Address addr) {
+  const int encoded = reinterpret_cast<int>(addr);
+  int space_number = ((encoded >> kSpaceShift) & kSpaceMask);
+  if (space_number == kLOSpaceExecutable) space_number = LO_SPACE;
+  else if (space_number == kLOSpacePointer) space_number = LO_SPACE;
+  return static_cast<AllocationSpace>(space_number);
+}
+
+
+static inline bool IsLargeExecutableObject(Address addr) {
+  const int encoded = reinterpret_cast<int>(addr);
+  const int space_number = ((encoded >> kSpaceShift) & kSpaceMask);
+  if (space_number == kLOSpaceExecutable) return true;
+  return false;
+}
+
+
+static inline bool IsLargeFixedArray(Address addr) {
+  const int encoded = reinterpret_cast<int>(addr);
+  const int space_number = ((encoded >> kSpaceShift) & kSpaceMask);
+  if (space_number == kLOSpacePointer) return true;
+  return false;
+}
+
+
+static inline int PageIndex(Address addr) {
+  const int encoded = reinterpret_cast<int>(addr);
+  return (encoded >> kPageShift) & kPageMask;
+}
+
+
+static inline int PageOffset(Address addr) {
+  const int encoded = reinterpret_cast<int>(addr);
+  return ((encoded >> kOffsetShift) & kOffsetMask) << kObjectAlignmentBits;
+}
+
+
+static inline int NewSpaceOffset(Address addr) {
+  const int encoded = reinterpret_cast<int>(addr);
+  return ((encoded >> kPageAndOffsetShift) & kPageAndOffsetMask) <<
+      kObjectAlignmentBits;
+}
+
+
+static inline int LargeObjectIndex(Address addr) {
+  const int encoded = reinterpret_cast<int>(addr);
+  return (encoded >> kPageAndOffsetShift) & kPageAndOffsetMask;
+}
+
+
+// A RelativeAddress encodes a heap address that is independent of
+// the actual memory addresses in real heap. The general case (for the
+// OLD, CODE and MAP spaces) is as a (space id, page number, page offset)
+// triple. The NEW space has page number == 0, because there are no
+// pages. The LARGE_OBJECT space has page offset = 0, since there is
+// exactly one object per page.  RelativeAddresses are encodable as
+// Addresses, so that they can replace the map() pointers of
+// HeapObjects. The encoded Addresses are also encoded as HeapObjects
+// and allow for marking (is_marked() see mark(), clear_mark()...) as
+// used by the Mark-Compact collector.
+
+class RelativeAddress {
+ public:
+  RelativeAddress(AllocationSpace space,
+                  int page_index,
+                  int page_offset)
+  : space_(space), page_index_(page_index), page_offset_(page_offset)  {
+    ASSERT(space <= LAST_SPACE && space >= 0);
+  }
+
+  // Return the encoding of 'this' as an Address. Decode with constructor.
+  Address Encode() const;
+
+  AllocationSpace space() const {
+    if (space_ == kLOSpaceExecutable) return LO_SPACE;
+    if (space_ == kLOSpacePointer) return LO_SPACE;
+    return static_cast<AllocationSpace>(space_);
+  }
+  int page_index() const { return page_index_; }
+  int page_offset() const { return page_offset_; }
+
+  bool in_paged_space() const {
+    return space_ == CODE_SPACE ||
+           space_ == OLD_POINTER_SPACE ||
+           space_ == OLD_DATA_SPACE ||
+           space_ == MAP_SPACE;
+  }
+
+  void next_address(int offset) { page_offset_ += offset; }
+  void next_page(int init_offset = 0) {
+    page_index_++;
+    page_offset_ = init_offset;
+  }
+
+#ifdef DEBUG
+  void Verify();
+#endif
+
+  void set_to_large_code_object() {
+    ASSERT(space_ == LO_SPACE);
+    space_ = kLOSpaceExecutable;
+  }
+  void set_to_large_fixed_array() {
+    ASSERT(space_ == LO_SPACE);
+    space_ = kLOSpacePointer;
+  }
+
+
+ private:
+  int space_;
+  int page_index_;
+  int page_offset_;
+};
+
+
+Address RelativeAddress::Encode() const {
+  ASSERT(page_index_ >= 0);
+  int word_offset = 0;
+  int result = 0;
+  switch (space_) {
+    case MAP_SPACE:
+    case OLD_POINTER_SPACE:
+    case OLD_DATA_SPACE:
+    case CODE_SPACE:
+      ASSERT_EQ(0, page_index_ & ~kPageMask);
+      word_offset = page_offset_ >> kObjectAlignmentBits;
+      ASSERT_EQ(0, word_offset & ~kOffsetMask);
+      result = (page_index_ << kPageShift) | (word_offset << kOffsetShift);
+      break;
+    case NEW_SPACE:
+      ASSERT_EQ(0, page_index_);
+      word_offset = page_offset_ >> kObjectAlignmentBits;
+      ASSERT_EQ(0, word_offset & ~kPageAndOffsetMask);
+      result = word_offset << kPageAndOffsetShift;
+      break;
+    case LO_SPACE:
+    case kLOSpaceExecutable:
+    case kLOSpacePointer:
+      ASSERT_EQ(0, page_offset_);
+      ASSERT_EQ(0, page_index_ & ~kPageAndOffsetMask);
+      result = page_index_ << kPageAndOffsetShift;
+      break;
+  }
+  // OR in AllocationSpace and kHeapObjectTag
+  ASSERT_EQ(0, space_ & ~kSpaceMask);
+  result |= (space_ << kSpaceShift) | kHeapObjectTag;
+  return reinterpret_cast<Address>(result);
+}
+
+
+#ifdef DEBUG
+void RelativeAddress::Verify() {
+  ASSERT(page_offset_ >= 0 && page_index_ >= 0);
+  switch (space_) {
+    case MAP_SPACE:
+    case OLD_POINTER_SPACE:
+    case OLD_DATA_SPACE:
+    case CODE_SPACE:
+      ASSERT(Page::kObjectStartOffset <= page_offset_ &&
+             page_offset_ <= Page::kPageSize);
+      break;
+    case NEW_SPACE:
+      ASSERT(page_index_ == 0);
+      break;
+    case LO_SPACE:
+    case kLOSpaceExecutable:
+    case kLOSpacePointer:
+      ASSERT(page_offset_ == 0);
+      break;
+  }
+}
+#endif
+
+enum GCTreatment {
+  DataObject,     // Object that cannot contain a reference to new space.
+  PointerObject,  // Object that can contain a reference to new space.
+  CodeObject      // Object that contains executable code.
+};
+
+// A SimulatedHeapSpace simulates the allocation of objects in a page in
+// the heap. It uses linear allocation - that is, it doesn't simulate the
+// use of a free list. This simulated
+// allocation must exactly match that done by Heap.
+
+class SimulatedHeapSpace {
+ public:
+  // The default constructor initializes to an invalid state.
+  SimulatedHeapSpace(): current_(LAST_SPACE, -1, -1) {}
+
+  // Sets 'this' to the first address in 'space' that would be
+  // returned by allocation in an empty heap.
+  void InitEmptyHeap(AllocationSpace space);
+
+  // Sets 'this' to the next address in 'space' that would be returned
+  // by allocation in the current heap. Intended only for testing
+  // serialization and deserialization in the current address space.
+  void InitCurrentHeap(AllocationSpace space);
+
+  // Returns the RelativeAddress where the next
+  // object of 'size' bytes will be allocated, and updates 'this' to
+  // point to the next free address beyond that object.
+  RelativeAddress Allocate(int size, GCTreatment special_gc_treatment);
+
+ private:
+  RelativeAddress current_;
+};
+
+
+void SimulatedHeapSpace::InitEmptyHeap(AllocationSpace space) {
+  switch (space) {
+    case MAP_SPACE:
+    case OLD_POINTER_SPACE:
+    case OLD_DATA_SPACE:
+    case CODE_SPACE:
+      current_ = RelativeAddress(space, 0, Page::kObjectStartOffset);
+      break;
+    case NEW_SPACE:
+    case LO_SPACE:
+      current_ = RelativeAddress(space, 0, 0);
+      break;
+  }
+}
+
+
+void SimulatedHeapSpace::InitCurrentHeap(AllocationSpace space) {
+  switch (space) {
+    case MAP_SPACE:
+    case OLD_POINTER_SPACE:
+    case OLD_DATA_SPACE:
+    case CODE_SPACE: {
+      PagedSpace* ps;
+      if (space == MAP_SPACE) {
+        ps = Heap::map_space();
+      } else if (space == OLD_POINTER_SPACE) {
+        ps = Heap::old_pointer_space();
+      } else if (space == OLD_DATA_SPACE) {
+        ps = Heap::old_data_space();
+      } else {
+        ASSERT(space == CODE_SPACE);
+        ps = Heap::code_space();
+      }
+      Address top = ps->top();
+      Page* top_page = Page::FromAllocationTop(top);
+      int page_index = 0;
+      PageIterator it(ps, PageIterator::PAGES_IN_USE);
+      while (it.has_next()) {
+        if (it.next() == top_page) break;
+        page_index++;
+      }
+      current_ = RelativeAddress(space,
+                                 page_index,
+                                 top_page->Offset(top));
+      break;
+    }
+    case NEW_SPACE:
+      current_ = RelativeAddress(space,
+                                 0,
+                                 Heap::NewSpaceTop() - Heap::NewSpaceStart());
+      break;
+    case LO_SPACE:
+      int page_index = 0;
+      for (LargeObjectIterator it(Heap::lo_space()); it.has_next(); it.next()) {
+        page_index++;
+      }
+      current_ = RelativeAddress(space, page_index, 0);
+      break;
+  }
+}
+
+
+RelativeAddress SimulatedHeapSpace::Allocate(int size,
+                                             GCTreatment special_gc_treatment) {
+#ifdef DEBUG
+  current_.Verify();
+#endif
+  int alloc_size = OBJECT_SIZE_ALIGN(size);
+  if (current_.in_paged_space() &&
+      current_.page_offset() + alloc_size > Page::kPageSize) {
+    ASSERT(alloc_size <= Page::kMaxHeapObjectSize);
+    current_.next_page(Page::kObjectStartOffset);
+  }
+  RelativeAddress result = current_;
+  if (current_.space() == LO_SPACE) {
+    current_.next_page();
+    if (special_gc_treatment == CodeObject) {
+      result.set_to_large_code_object();
+    } else if (special_gc_treatment == PointerObject) {
+      result.set_to_large_fixed_array();
+    }
+  } else {
+    current_.next_address(alloc_size);
+  }
+#ifdef DEBUG
+  current_.Verify();
+  result.Verify();
+#endif
+  return result;
+}
+
+// -----------------------------------------------------------------------------
+// Coding of external references.
+
+// The encoding of an external reference. The type is in the high word.
+// The id is in the low word.
+static uint32_t EncodeExternal(TypeCode type, uint16_t id) {
+  return static_cast<uint32_t>(type) << 16 | id;
+}
+
+
+static int* GetInternalPointer(StatsCounter* counter) {
+  // All counters refer to dummy_counter, if deserializing happens without
+  // setting up counters.
+  static int dummy_counter = 0;
+  return counter->Enabled() ? counter->GetInternalPointer() : &dummy_counter;
+}
+
+
+// ExternalReferenceTable is a helper class that defines the relationship
+// between external references and their encodings. It is used to build
+// hashmaps in ExternalReferenceEncoder and ExternalReferenceDecoder.
+class ExternalReferenceTable {
+ public:
+  static ExternalReferenceTable* instance() {
+    if (!instance_) instance_ = new ExternalReferenceTable();
+    return instance_;
+  }
+
+  int size() const { return refs_.length(); }
+
+  Address address(int i) { return refs_[i].address; }
+
+  uint32_t code(int i) { return refs_[i].code; }
+
+  const char* name(int i) { return refs_[i].name; }
+
+  int max_id(int code) { return max_id_[code]; }
+
+ private:
+  static ExternalReferenceTable* instance_;
+
+  ExternalReferenceTable() : refs_(64) { PopulateTable(); }
+  ~ExternalReferenceTable() { }
+
+  struct ExternalReferenceEntry {
+    Address address;
+    uint32_t code;
+    const char* name;
+  };
+
+  void PopulateTable();
+
+  // For a few types of references, we can get their address from their id.
+  void AddFromId(TypeCode type, uint16_t id, const char* name);
+
+  // For other types of references, the caller will figure out the address.
+  void Add(Address address, TypeCode type, uint16_t id, const char* name);
+
+  List<ExternalReferenceEntry> refs_;
+  int max_id_[kTypeCodeCount];
+};
+
+
+ExternalReferenceTable* ExternalReferenceTable::instance_ = NULL;
+
+
+void ExternalReferenceTable::AddFromId(TypeCode type,
+                                       uint16_t id,
+                                       const char* name) {
+  Address address;
+  switch (type) {
+    case C_BUILTIN:
+      address = Builtins::c_function_address(
+          static_cast<Builtins::CFunctionId>(id));
+      break;
+    case BUILTIN:
+      address = Builtins::builtin_address(static_cast<Builtins::Name>(id));
+      break;
+    case RUNTIME_FUNCTION:
+      address = Runtime::FunctionForId(
+          static_cast<Runtime::FunctionId>(id))->entry;
+      break;
+    case IC_UTILITY:
+      address = IC::AddressFromUtilityId(static_cast<IC::UtilityId>(id));
+      break;
+    default:
+      UNREACHABLE();
+      return;
+  }
+  Add(address, type, id, name);
+}
+
+
+void ExternalReferenceTable::Add(Address address,
+                                 TypeCode type,
+                                 uint16_t id,
+                                 const char* name) {
+  CHECK_NE(NULL, address);
+  ExternalReferenceEntry entry;
+  entry.address = address;
+  entry.code = EncodeExternal(type, id);
+  entry.name = name;
+  CHECK_NE(0, entry.code);
+  refs_.Add(entry);
+  if (id > max_id_[type]) max_id_[type] = id;
+}
+
+
+void ExternalReferenceTable::PopulateTable() {
+  for (int type_code = 0; type_code < kTypeCodeCount; type_code++) {
+    max_id_[type_code] = 0;
+  }
+
+  // The following populates all of the different type of external references
+  // into the ExternalReferenceTable.
+  //
+  // NOTE: This function was originally 100k of code.  It has since been
+  // rewritten to be mostly table driven, as the callback macro style tends to
+  // very easily cause code bloat.  Please be careful in the future when adding
+  // new references.
+
+  struct RefTableEntry {
+    TypeCode type;
+    uint16_t id;
+    const char* name;
+  };
+
+  static const RefTableEntry ref_table[] = {
+  // Builtins
+#define DEF_ENTRY_C(name) \
+  { C_BUILTIN, \
+    Builtins::c_##name, \
+    "Builtins::" #name },
+
+  BUILTIN_LIST_C(DEF_ENTRY_C)
+#undef DEF_ENTRY_C
+
+#define DEF_ENTRY_C(name) \
+  { BUILTIN, \
+    Builtins::name, \
+    "Builtins::" #name },
+#define DEF_ENTRY_A(name, kind, state) DEF_ENTRY_C(name)
+
+  BUILTIN_LIST_C(DEF_ENTRY_C)
+  BUILTIN_LIST_A(DEF_ENTRY_A)
+  BUILTIN_LIST_DEBUG_A(DEF_ENTRY_A)
+#undef DEF_ENTRY_C
+#undef DEF_ENTRY_A
+
+  // Runtime functions
+#define RUNTIME_ENTRY(name, nargs) \
+  { RUNTIME_FUNCTION, \
+    Runtime::k##name, \
+    "Runtime::" #name },
+
+  RUNTIME_FUNCTION_LIST(RUNTIME_ENTRY)
+#undef RUNTIME_ENTRY
+
+  // IC utilities
+#define IC_ENTRY(name) \
+  { IC_UTILITY, \
+    IC::k##name, \
+    "IC::" #name },
+
+  IC_UTIL_LIST(IC_ENTRY)
+#undef IC_ENTRY
+  };  // end of ref_table[].
+
+  for (size_t i = 0; i < ARRAY_SIZE(ref_table); ++i) {
+    AddFromId(ref_table[i].type, ref_table[i].id, ref_table[i].name);
+  }
+
+  // Debug addresses
+  Add(Debug_Address(Debug::k_after_break_target_address).address(),
+      DEBUG_ADDRESS,
+      Debug::k_after_break_target_address << kDebugIdShift,
+      "Debug::after_break_target_address()");
+  Add(Debug_Address(Debug::k_debug_break_return_address).address(),
+      DEBUG_ADDRESS,
+      Debug::k_debug_break_return_address << kDebugIdShift,
+      "Debug::debug_break_return_address()");
+  const char* debug_register_format = "Debug::register_address(%i)";
+  size_t dr_format_length = strlen(debug_register_format);
+  for (int i = 0; i < kNumJSCallerSaved; ++i) {
+    Vector<char> name = Vector<char>::New(dr_format_length + 1);
+    OS::SNPrintF(name, debug_register_format, i);
+    Add(Debug_Address(Debug::k_register_address, i).address(),
+        DEBUG_ADDRESS,
+        Debug::k_register_address << kDebugIdShift | i,
+        name.start());
+  }
+
+  // Stat counters
+  struct StatsRefTableEntry {
+    StatsCounter* counter;
+    uint16_t id;
+    const char* name;
+  };
+
+  static const StatsRefTableEntry stats_ref_table[] = {
+#define COUNTER_ENTRY(name, caption) \
+  { &Counters::name, \
+    Counters::k_##name, \
+    "Counters::" #name },
+
+  STATS_COUNTER_LIST_1(COUNTER_ENTRY)
+  STATS_COUNTER_LIST_2(COUNTER_ENTRY)
+#undef COUNTER_ENTRY
+  };  // end of stats_ref_table[].
+
+  for (size_t i = 0; i < ARRAY_SIZE(stats_ref_table); ++i) {
+    Add(reinterpret_cast<Address>(
+            GetInternalPointer(stats_ref_table[i].counter)),
+        STATS_COUNTER,
+        stats_ref_table[i].id,
+        stats_ref_table[i].name);
+  }
+
+  // Top addresses
+  const char* top_address_format = "Top::get_address_from_id(%i)";
+  size_t top_format_length = strlen(top_address_format);
+  for (uint16_t i = 0; i < Top::k_top_address_count; ++i) {
+    Vector<char> name = Vector<char>::New(top_format_length + 1);
+    const char* chars = name.start();
+    OS::SNPrintF(name, top_address_format, i);
+    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, \
+      ACCESSOR, \
+      Accessors::k##name, \
+      "Accessors::" #name);
+
+  ACCESSOR_DESCRIPTOR_LIST(ACCESSOR_DESCRIPTOR_DECLARATION)
+#undef ACCESSOR_DESCRIPTOR_DECLARATION
+
+  // Stub cache tables
+  Add(SCTableReference::keyReference(StubCache::kPrimary).address(),
+      STUB_CACHE_TABLE,
+      1,
+      "StubCache::primary_->key");
+  Add(SCTableReference::valueReference(StubCache::kPrimary).address(),
+      STUB_CACHE_TABLE,
+      2,
+      "StubCache::primary_->value");
+  Add(SCTableReference::keyReference(StubCache::kSecondary).address(),
+      STUB_CACHE_TABLE,
+      3,
+      "StubCache::secondary_->key");
+  Add(SCTableReference::valueReference(StubCache::kSecondary).address(),
+      STUB_CACHE_TABLE,
+      4,
+      "StubCache::secondary_->value");
+
+  // Runtime entries
+  Add(FUNCTION_ADDR(Runtime::PerformGC),
+      RUNTIME_ENTRY,
+      1,
+      "Runtime::PerformGC");
+
+  // Miscellaneous
+  Add(ExternalReference::builtin_passed_function().address(),
+      UNCLASSIFIED,
+      1,
+      "Builtins::builtin_passed_function");
+  Add(ExternalReference::the_hole_value_location().address(),
+      UNCLASSIFIED,
+      2,
+      "Factory::the_hole_value().location()");
+  Add(ExternalReference::address_of_stack_guard_limit().address(),
+      UNCLASSIFIED,
+      3,
+      "StackGuard::address_of_jslimit()");
+  Add(ExternalReference::address_of_regexp_stack_limit().address(),
+      UNCLASSIFIED,
+      4,
+      "RegExpStack::limit_address()");
+  Add(ExternalReference::debug_break().address(),
+      UNCLASSIFIED,
+      5,
+      "Debug::Break()");
+  Add(ExternalReference::new_space_start().address(),
+      UNCLASSIFIED,
+      6,
+      "Heap::NewSpaceStart()");
+  Add(ExternalReference::heap_always_allocate_scope_depth().address(),
+      UNCLASSIFIED,
+      7,
+      "Heap::always_allocate_scope_depth()");
+  Add(ExternalReference::new_space_allocation_limit_address().address(),
+      UNCLASSIFIED,
+      8,
+      "Heap::NewSpaceAllocationLimitAddress()");
+  Add(ExternalReference::new_space_allocation_top_address().address(),
+      UNCLASSIFIED,
+      9,
+      "Heap::NewSpaceAllocationTopAddress()");
+  Add(ExternalReference::debug_step_in_fp_address().address(),
+      UNCLASSIFIED,
+      10,
+      "Debug::step_in_fp_addr()");
+}
+
+
+ExternalReferenceEncoder::ExternalReferenceEncoder()
+    : encodings_(Match) {
+  ExternalReferenceTable* external_references =
+      ExternalReferenceTable::instance();
+  for (int i = 0; i < external_references->size(); ++i) {
+    Put(external_references->address(i), i);
+  }
+}
+
+
+uint32_t ExternalReferenceEncoder::Encode(Address key) const {
+  int index = IndexOf(key);
+  return index >=0 ? ExternalReferenceTable::instance()->code(index) : 0;
+}
+
+
+const char* ExternalReferenceEncoder::NameOfAddress(Address key) const {
+  int index = IndexOf(key);
+  return index >=0 ? ExternalReferenceTable::instance()->name(index) : NULL;
+}
+
+
+int ExternalReferenceEncoder::IndexOf(Address key) const {
+  if (key == NULL) return -1;
+  HashMap::Entry* entry =
+      const_cast<HashMap &>(encodings_).Lookup(key, Hash(key), false);
+  return entry == NULL ? -1 : reinterpret_cast<int>(entry->value);
+}
+
+
+void ExternalReferenceEncoder::Put(Address key, int index) {
+  HashMap::Entry* entry = encodings_.Lookup(key, Hash(key), true);
+  entry->value = reinterpret_cast<void *>(index);
+}
+
+
+ExternalReferenceDecoder::ExternalReferenceDecoder()
+  : encodings_(NewArray<Address*>(kTypeCodeCount)) {
+  ExternalReferenceTable* external_references =
+      ExternalReferenceTable::instance();
+  for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) {
+    int max = external_references->max_id(type) + 1;
+    encodings_[type] = NewArray<Address>(max + 1);
+  }
+  for (int i = 0; i < external_references->size(); ++i) {
+    Put(external_references->code(i), external_references->address(i));
+  }
+}
+
+
+ExternalReferenceDecoder::~ExternalReferenceDecoder() {
+  for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) {
+    DeleteArray(encodings_[type]);
+  }
+  DeleteArray(encodings_);
+}
+
+
+//------------------------------------------------------------------------------
+// Implementation of Serializer
+
+
+// Helper class to write the bytes of the serialized heap.
+
+class SnapshotWriter {
+ public:
+  SnapshotWriter() {
+    len_ = 0;
+    max_ = 8 << 10;  // 8K initial size
+    str_ = NewArray<byte>(max_);
+  }
+
+  ~SnapshotWriter() {
+    DeleteArray(str_);
+  }
+
+  void GetBytes(byte** str, int* len) {
+    *str = NewArray<byte>(len_);
+    memcpy(*str, str_, len_);
+    *len = len_;
+  }
+
+  void Reserve(int bytes, int pos);
+
+  void PutC(char c) {
+    InsertC(c, len_);
+  }
+
+  void PutInt(int i) {
+    InsertInt(i, len_);
+  }
+
+  void PutBytes(const byte* a, int size) {
+    InsertBytes(a, len_, size);
+  }
+
+  void PutString(const char* s) {
+    InsertString(s, len_);
+  }
+
+  int InsertC(char c, int pos) {
+    Reserve(1, pos);
+    str_[pos] = c;
+    len_++;
+    return pos + 1;
+  }
+
+  int InsertInt(int i, int pos) {
+    return InsertBytes(reinterpret_cast<byte*>(&i), pos, sizeof(i));
+  }
+
+  int InsertBytes(const byte* a, int pos, int size) {
+    Reserve(size, pos);
+    memcpy(&str_[pos], a, size);
+    len_ += size;
+    return pos + size;
+  }
+
+  int InsertString(const char* s, int pos);
+
+  int length() { return len_; }
+
+  Address position() { return reinterpret_cast<Address>(&str_[len_]); }
+
+ private:
+  byte* str_;  // the snapshot
+  int len_;   // the current length of str_
+  int max_;   // the allocated size of str_
+};
+
+
+void SnapshotWriter::Reserve(int bytes, int pos) {
+  CHECK(0 <= pos && pos <= len_);
+  while (len_ + bytes >= max_) {
+    max_ *= 2;
+    byte* old = str_;
+    str_ = NewArray<byte>(max_);
+    memcpy(str_, old, len_);
+    DeleteArray(old);
+  }
+  if (pos < len_) {
+    byte* old = str_;
+    str_ = NewArray<byte>(max_);
+    memcpy(str_, old, pos);
+    memcpy(str_ + pos + bytes, old + pos, len_ - pos);
+    DeleteArray(old);
+  }
+}
+
+int SnapshotWriter::InsertString(const char* s, int pos) {
+  int size = strlen(s);
+  pos = InsertC('[', pos);
+  pos = InsertInt(size, pos);
+  pos = InsertC(']', pos);
+  return InsertBytes(reinterpret_cast<const byte*>(s), pos, size);
+}
+
+
+class ReferenceUpdater: public ObjectVisitor {
+ public:
+  ReferenceUpdater(HeapObject* obj, Serializer* serializer)
+    : obj_address_(obj->address()),
+      serializer_(serializer),
+      reference_encoder_(serializer->reference_encoder_),
+      offsets_(8),
+      addresses_(8) {
+  }
+
+  virtual void VisitPointers(Object** start, Object** end) {
+    for (Object** p = start; p < end; ++p) {
+      if ((*p)->IsHeapObject()) {
+        offsets_.Add(reinterpret_cast<Address>(p) - obj_address_);
+        Address a = serializer_->GetSavedAddress(HeapObject::cast(*p));
+        addresses_.Add(a);
+      }
+    }
+  }
+
+  virtual void VisitExternalReferences(Address* start, Address* end) {
+    for (Address* p = start; p < end; ++p) {
+      uint32_t code = reference_encoder_->Encode(*p);
+      CHECK(*p == NULL ? code == 0 : code != 0);
+      offsets_.Add(reinterpret_cast<Address>(p) - obj_address_);
+      addresses_.Add(reinterpret_cast<Address>(code));
+    }
+  }
+
+  virtual void VisitRuntimeEntry(RelocInfo* rinfo) {
+    Address target = rinfo->target_address();
+    uint32_t encoding = reference_encoder_->Encode(target);
+    CHECK(target == NULL ? encoding == 0 : encoding != 0);
+    offsets_.Add(rinfo->target_address_address() - obj_address_);
+    addresses_.Add(reinterpret_cast<Address>(encoding));
+  }
+
+  void Update(Address start_address) {
+    for (int i = 0; i < offsets_.length(); i++) {
+      memcpy(start_address + offsets_[i], &addresses_[i], sizeof(Address));
+    }
+  }
+
+ private:
+  Address obj_address_;
+  Serializer* serializer_;
+  ExternalReferenceEncoder* reference_encoder_;
+  List<int> offsets_;
+  List<Address> addresses_;
+};
+
+
+// Helper functions for a map of encoded heap object addresses.
+static uint32_t HeapObjectHash(HeapObject* key) {
+  return reinterpret_cast<uint32_t>(key) >> 2;
+}
+
+
+static bool MatchHeapObject(void* key1, void* key2) {
+  return key1 == key2;
+}
+
+
+Serializer::Serializer()
+  : global_handles_(4),
+    saved_addresses_(MatchHeapObject) {
+  root_ = true;
+  roots_ = 0;
+  objects_ = 0;
+  reference_encoder_ = NULL;
+  writer_ = new SnapshotWriter();
+  for (int i = 0; i <= LAST_SPACE; i++) {
+    allocator_[i] = new SimulatedHeapSpace();
+  }
+}
+
+
+Serializer::~Serializer() {
+  for (int i = 0; i <= LAST_SPACE; i++) {
+    delete allocator_[i];
+  }
+  if (reference_encoder_) delete reference_encoder_;
+  delete writer_;
+}
+
+
+bool Serializer::serialization_enabled_ = false;
+
+
+#ifdef DEBUG
+static const int kMaxTagLength = 32;
+
+void Serializer::Synchronize(const char* tag) {
+  if (FLAG_debug_serialization) {
+    int length = strlen(tag);
+    ASSERT(length <= kMaxTagLength);
+    writer_->PutC('S');
+    writer_->PutInt(length);
+    writer_->PutBytes(reinterpret_cast<const byte*>(tag), length);
+  }
+}
+#endif
+
+
+void Serializer::InitializeAllocators() {
+  for (int i = 0; i <= LAST_SPACE; i++) {
+    allocator_[i]->InitEmptyHeap(static_cast<AllocationSpace>(i));
+  }
+}
+
+
+bool Serializer::IsVisited(HeapObject* obj) {
+  HashMap::Entry* entry =
+    saved_addresses_.Lookup(obj, HeapObjectHash(obj), false);
+  return entry != NULL;
+}
+
+
+Address Serializer::GetSavedAddress(HeapObject* obj) {
+  HashMap::Entry* entry =
+    saved_addresses_.Lookup(obj, HeapObjectHash(obj), false);
+  ASSERT(entry != NULL);
+  return reinterpret_cast<Address>(entry->value);
+}
+
+
+void Serializer::SaveAddress(HeapObject* obj, Address addr) {
+  HashMap::Entry* entry =
+    saved_addresses_.Lookup(obj, HeapObjectHash(obj), true);
+  entry->value = addr;
+}
+
+
+void Serializer::Serialize() {
+  // No active threads.
+  CHECK_EQ(NULL, ThreadState::FirstInUse());
+  // No active or weak handles.
+  CHECK(HandleScopeImplementer::instance()->Blocks()->is_empty());
+  CHECK_EQ(0, GlobalHandles::NumberOfWeakHandles());
+  // We need a counter function during serialization to resolve the
+  // references to counters in the code on the heap.
+  CHECK(StatsTable::HasCounterFunction());
+  CHECK(enabled());
+  InitializeAllocators();
+  reference_encoder_ = new ExternalReferenceEncoder();
+  PutHeader();
+  Heap::IterateRoots(this);
+  PutLog();
+  PutContextStack();
+  Disable();
+}
+
+
+void Serializer::Finalize(byte** str, int* len) {
+  writer_->GetBytes(str, len);
+}
+
+
+// Serialize objects by writing them into the stream.
+
+void Serializer::VisitPointers(Object** start, Object** end) {
+  bool root = root_;
+  root_ = false;
+  for (Object** p = start; p < end; ++p) {
+    bool serialized;
+    Address a = Encode(*p, &serialized);
+    if (root) {
+      roots_++;
+      // If the object was not just serialized,
+      // write its encoded address instead.
+      if (!serialized) PutEncodedAddress(a);
+    }
+  }
+  root_ = root;
+}
+
+
+class GlobalHandlesRetriever: public ObjectVisitor {
+ public:
+  explicit GlobalHandlesRetriever(List<Object**>* handles)
+  : global_handles_(handles) {}
+
+  virtual void VisitPointers(Object** start, Object** end) {
+    for (; start != end; ++start) {
+      global_handles_->Add(start);
+    }
+  }
+
+ private:
+  List<Object**>* global_handles_;
+};
+
+
+void Serializer::PutFlags() {
+  writer_->PutC('F');
+  List<const char*>* argv = FlagList::argv();
+  writer_->PutInt(argv->length());
+  writer_->PutC('[');
+  for (int i = 0; i < argv->length(); i++) {
+    if (i > 0) writer_->PutC('|');
+    writer_->PutString((*argv)[i]);
+    DeleteArray((*argv)[i]);
+  }
+  writer_->PutC(']');
+  flags_end_ = writer_->length();
+  delete argv;
+}
+
+
+void Serializer::PutHeader() {
+  PutFlags();
+  writer_->PutC('D');
+#ifdef DEBUG
+  writer_->PutC(FLAG_debug_serialization ? '1' : '0');
+#else
+  writer_->PutC('0');
+#endif
+  // Write sizes of paged memory spaces. Allocate extra space for the old
+  // and code spaces, because objects in new space will be promoted to them.
+  writer_->PutC('S');
+  writer_->PutC('[');
+  writer_->PutInt(Heap::old_pointer_space()->Size() +
+                  Heap::new_space()->Size());
+  writer_->PutC('|');
+  writer_->PutInt(Heap::old_data_space()->Size() + Heap::new_space()->Size());
+  writer_->PutC('|');
+  writer_->PutInt(Heap::code_space()->Size() + Heap::new_space()->Size());
+  writer_->PutC('|');
+  writer_->PutInt(Heap::map_space()->Size());
+  writer_->PutC(']');
+  // Write global handles.
+  writer_->PutC('G');
+  writer_->PutC('[');
+  GlobalHandlesRetriever ghr(&global_handles_);
+  GlobalHandles::IterateRoots(&ghr);
+  for (int i = 0; i < global_handles_.length(); i++) {
+    writer_->PutC('N');
+  }
+  writer_->PutC(']');
+}
+
+
+void Serializer::PutLog() {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (FLAG_log_code) {
+    Logger::TearDown();
+    int pos = writer_->InsertC('L', flags_end_);
+    bool exists;
+    Vector<const char> log = ReadFile(FLAG_logfile, &exists);
+    writer_->InsertString(log.start(), pos);
+    log.Dispose();
+  }
+#endif
+}
+
+
+static int IndexOf(const List<Object**>& list, Object** element) {
+  for (int i = 0; i < list.length(); i++) {
+    if (list[i] == element) return i;
+  }
+  return -1;
+}
+
+
+void Serializer::PutGlobalHandleStack(const List<Handle<Object> >& stack) {
+  writer_->PutC('[');
+  writer_->PutInt(stack.length());
+  for (int i = stack.length() - 1; i >= 0; i--) {
+    writer_->PutC('|');
+    int gh_index = IndexOf(global_handles_, stack[i].location());
+    CHECK_GE(gh_index, 0);
+    writer_->PutInt(gh_index);
+  }
+  writer_->PutC(']');
+}
+
+
+void Serializer::PutContextStack() {
+  List<Handle<Object> > contexts(2);
+  while (HandleScopeImplementer::instance()->HasSavedContexts()) {
+    Handle<Object> context =
+      HandleScopeImplementer::instance()->RestoreContext();
+    contexts.Add(context);
+  }
+  for (int i = contexts.length() - 1; i >= 0; i--) {
+    HandleScopeImplementer::instance()->SaveContext(contexts[i]);
+  }
+  PutGlobalHandleStack(contexts);
+}
+
+
+void Serializer::PutEncodedAddress(Address addr) {
+  writer_->PutC('P');
+  writer_->PutInt(reinterpret_cast<int>(addr));
+}
+
+
+Address Serializer::Encode(Object* o, bool* serialized) {
+  *serialized = false;
+  if (o->IsSmi()) {
+    return reinterpret_cast<Address>(o);
+  } else {
+    HeapObject* obj = HeapObject::cast(o);
+    if (IsVisited(obj)) {
+      return GetSavedAddress(obj);
+    } else {
+      // First visit: serialize the object.
+      *serialized = true;
+      return PutObject(obj);
+    }
+  }
+}
+
+
+Address Serializer::PutObject(HeapObject* obj) {
+  Map* map = obj->map();
+  InstanceType type = map->instance_type();
+  int size = obj->SizeFromMap(map);
+
+  // Simulate the allocation of obj to predict where it will be
+  // allocated during deserialization.
+  Address addr = Allocate(obj).Encode();
+
+  SaveAddress(obj, addr);
+
+  if (type == CODE_TYPE) {
+    Code* code = Code::cast(obj);
+    // Ensure Code objects contain Object pointers, not Addresses.
+    code->ConvertICTargetsFromAddressToObject();
+    LOG(CodeMoveEvent(code->address(), addr));
+  }
+
+  // Write out the object prologue: type, size, and simulated address of obj.
+  writer_->PutC('[');
+  CHECK_EQ(0, size & kObjectAlignmentMask);
+  writer_->PutInt(type);
+  writer_->PutInt(size >> kObjectAlignmentBits);
+  PutEncodedAddress(addr);  // encodes AllocationSpace
+
+  // Visit all the pointers in the object other than the map. This
+  // will recursively serialize any as-yet-unvisited objects.
+  obj->Iterate(this);
+
+  // Mark end of recursively embedded objects, start of object body.
+  writer_->PutC('|');
+  // Write out the raw contents of the object. No compression, but
+  // fast to deserialize.
+  writer_->PutBytes(obj->address(), size);
+  // Update pointers and external references in the written object.
+  ReferenceUpdater updater(obj, this);
+  obj->Iterate(&updater);
+  updater.Update(writer_->position() - size);
+
+#ifdef DEBUG
+  if (FLAG_debug_serialization) {
+    // Write out the object epilogue to catch synchronization errors.
+    PutEncodedAddress(addr);
+    writer_->PutC(']');
+  }
+#endif
+
+  if (type == CODE_TYPE) {
+    Code* code = Code::cast(obj);
+    // Convert relocations from Object* to Address in Code objects
+    code->ConvertICTargetsFromObjectToAddress();
+  }
+
+  objects_++;
+  return addr;
+}
+
+
+RelativeAddress Serializer::Allocate(HeapObject* obj) {
+  // Find out which AllocationSpace 'obj' is in.
+  AllocationSpace s;
+  bool found = false;
+  for (int i = FIRST_SPACE; !found && i <= LAST_SPACE; i++) {
+    s = static_cast<AllocationSpace>(i);
+    found = Heap::InSpace(obj, s);
+  }
+  CHECK(found);
+  if (s == NEW_SPACE) {
+    Space* space = Heap::TargetSpace(obj);
+    ASSERT(space == Heap::old_pointer_space() ||
+           space == Heap::old_data_space());
+    s = (space == Heap::old_pointer_space()) ?
+        OLD_POINTER_SPACE :
+        OLD_DATA_SPACE;
+  }
+  int size = obj->Size();
+  GCTreatment gc_treatment = DataObject;
+  if (obj->IsFixedArray()) gc_treatment = PointerObject;
+  else if (obj->IsCode()) gc_treatment = CodeObject;
+  return allocator_[s]->Allocate(size, gc_treatment);
+}
+
+
+//------------------------------------------------------------------------------
+// Implementation of Deserializer
+
+
+static const int kInitArraySize = 32;
+
+
+Deserializer::Deserializer(const byte* str, int len)
+  : reader_(str, len),
+    map_pages_(kInitArraySize),
+    old_pointer_pages_(kInitArraySize),
+    old_data_pages_(kInitArraySize),
+    code_pages_(kInitArraySize),
+    large_objects_(kInitArraySize),
+    global_handles_(4) {
+  root_ = true;
+  roots_ = 0;
+  objects_ = 0;
+  reference_decoder_ = NULL;
+#ifdef DEBUG
+  expect_debug_information_ = false;
+#endif
+}
+
+
+Deserializer::~Deserializer() {
+  if (reference_decoder_) delete reference_decoder_;
+}
+
+
+void Deserializer::ExpectEncodedAddress(Address expected) {
+  Address a = GetEncodedAddress();
+  USE(a);
+  ASSERT(a == expected);
+}
+
+
+#ifdef DEBUG
+void Deserializer::Synchronize(const char* tag) {
+  if (expect_debug_information_) {
+    char buf[kMaxTagLength];
+    reader_.ExpectC('S');
+    int length = reader_.GetInt();
+    ASSERT(length <= kMaxTagLength);
+    reader_.GetBytes(reinterpret_cast<Address>(buf), length);
+    ASSERT_EQ(strlen(tag), length);
+    ASSERT(strncmp(tag, buf, length) == 0);
+  }
+}
+#endif
+
+
+void Deserializer::Deserialize() {
+  // No active threads.
+  ASSERT_EQ(NULL, ThreadState::FirstInUse());
+  // No active handles.
+  ASSERT(HandleScopeImplementer::instance()->Blocks()->is_empty());
+  reference_decoder_ = new ExternalReferenceDecoder();
+  // By setting linear allocation only, we forbid the use of free list
+  // allocation which is not predicted by SimulatedAddress.
+  GetHeader();
+  Heap::IterateRoots(this);
+  GetContextStack();
+}
+
+
+void Deserializer::VisitPointers(Object** start, Object** end) {
+  bool root = root_;
+  root_ = false;
+  for (Object** p = start; p < end; ++p) {
+    if (root) {
+      roots_++;
+      // Read the next object or pointer from the stream
+      // pointer in the stream.
+      int c = reader_.GetC();
+      if (c == '[') {
+        *p = GetObject();  // embedded object
+      } else {
+        ASSERT(c == 'P');  // pointer to previously serialized object
+        *p = Resolve(reinterpret_cast<Address>(reader_.GetInt()));
+      }
+    } else {
+      // A pointer internal to a HeapObject that we've already
+      // read: resolve it to a true address (or Smi)
+      *p = Resolve(reinterpret_cast<Address>(*p));
+    }
+  }
+  root_ = root;
+}
+
+
+void Deserializer::VisitExternalReferences(Address* start, Address* end) {
+  for (Address* p = start; p < end; ++p) {
+    uint32_t code = reinterpret_cast<uint32_t>(*p);
+    *p = reference_decoder_->Decode(code);
+  }
+}
+
+
+void Deserializer::VisitRuntimeEntry(RelocInfo* rinfo) {
+  uint32_t* pc = reinterpret_cast<uint32_t*>(rinfo->target_address_address());
+  uint32_t encoding = *pc;
+  Address target = reference_decoder_->Decode(encoding);
+  rinfo->set_target_address(target);
+}
+
+
+void Deserializer::GetFlags() {
+  reader_.ExpectC('F');
+  int argc = reader_.GetInt() + 1;
+  char** argv = NewArray<char*>(argc);
+  reader_.ExpectC('[');
+  for (int i = 1; i < argc; i++) {
+    if (i > 1) reader_.ExpectC('|');
+    argv[i] = reader_.GetString();
+  }
+  reader_.ExpectC(']');
+  has_log_ = false;
+  for (int i = 1; i < argc; i++) {
+    if (strcmp("--log_code", argv[i]) == 0) {
+      has_log_ = true;
+    } else if (strcmp("--nouse_ic", argv[i]) == 0) {
+      FLAG_use_ic = false;
+    } else if (strcmp("--debug_code", argv[i]) == 0) {
+      FLAG_debug_code = true;
+    } else if (strcmp("--nolazy", argv[i]) == 0) {
+      FLAG_lazy = false;
+    }
+    DeleteArray(argv[i]);
+  }
+
+  DeleteArray(argv);
+}
+
+
+void Deserializer::GetLog() {
+  if (has_log_) {
+    reader_.ExpectC('L');
+    char* snapshot_log = reader_.GetString();
+#ifdef ENABLE_LOGGING_AND_PROFILING
+    if (FLAG_log_code) {
+      LOG(Preamble(snapshot_log));
+    }
+#endif
+    DeleteArray(snapshot_log);
+  }
+}
+
+
+static void InitPagedSpace(PagedSpace* space,
+                           int capacity,
+                           List<Page*>* page_list) {
+  space->EnsureCapacity(capacity);
+  // TODO(1240712): PagedSpace::EnsureCapacity can return false due to
+  // a failure to allocate from the OS to expand the space.
+  PageIterator it(space, PageIterator::ALL_PAGES);
+  while (it.has_next()) page_list->Add(it.next());
+}
+
+
+void Deserializer::GetHeader() {
+  reader_.ExpectC('D');
+#ifdef DEBUG
+  expect_debug_information_ = reader_.GetC() == '1';
+#else
+  // In release mode, don't attempt to read a snapshot containing
+  // synchronization tags.
+  if (reader_.GetC() != '0') FATAL("Snapshot contains synchronization tags.");
+#endif
+  // Ensure sufficient capacity in paged memory spaces to avoid growth
+  // during deserialization.
+  reader_.ExpectC('S');
+  reader_.ExpectC('[');
+  InitPagedSpace(Heap::old_pointer_space(),
+                 reader_.GetInt(),
+                 &old_pointer_pages_);
+  reader_.ExpectC('|');
+  InitPagedSpace(Heap::old_data_space(), reader_.GetInt(), &old_data_pages_);
+  reader_.ExpectC('|');
+  InitPagedSpace(Heap::code_space(), reader_.GetInt(), &code_pages_);
+  reader_.ExpectC('|');
+  InitPagedSpace(Heap::map_space(), reader_.GetInt(), &map_pages_);
+  reader_.ExpectC(']');
+  // Create placeholders for global handles later to be fill during
+  // IterateRoots.
+  reader_.ExpectC('G');
+  reader_.ExpectC('[');
+  int c = reader_.GetC();
+  while (c != ']') {
+    ASSERT(c == 'N');
+    global_handles_.Add(GlobalHandles::Create(NULL).location());
+    c = reader_.GetC();
+  }
+}
+
+
+void Deserializer::GetGlobalHandleStack(List<Handle<Object> >* stack) {
+  reader_.ExpectC('[');
+  int length = reader_.GetInt();
+  for (int i = 0; i < length; i++) {
+    reader_.ExpectC('|');
+    int gh_index = reader_.GetInt();
+    stack->Add(global_handles_[gh_index]);
+  }
+  reader_.ExpectC(']');
+}
+
+
+void Deserializer::GetContextStack() {
+  List<Handle<Object> > entered_contexts(2);
+  GetGlobalHandleStack(&entered_contexts);
+  for (int i = 0; i < entered_contexts.length(); i++) {
+    HandleScopeImplementer::instance()->SaveContext(entered_contexts[i]);
+  }
+}
+
+
+Address Deserializer::GetEncodedAddress() {
+  reader_.ExpectC('P');
+  return reinterpret_cast<Address>(reader_.GetInt());
+}
+
+
+Object* Deserializer::GetObject() {
+  // Read the prologue: type, size and encoded address.
+  InstanceType type = static_cast<InstanceType>(reader_.GetInt());
+  int size = reader_.GetInt() << kObjectAlignmentBits;
+  Address a = GetEncodedAddress();
+
+  // Get a raw object of the right size in the right space.
+  AllocationSpace space = GetSpace(a);
+  Object* o;
+  if (IsLargeExecutableObject(a)) {
+    o = Heap::lo_space()->AllocateRawCode(size);
+  } else if (IsLargeFixedArray(a)) {
+    o = Heap::lo_space()->AllocateRawFixedArray(size);
+  } else {
+    AllocationSpace retry_space = (space == NEW_SPACE)
+        ? Heap::TargetSpaceId(type)
+        : space;
+    o = Heap::AllocateRaw(size, space, retry_space);
+  }
+  ASSERT(!o->IsFailure());
+  // Check that the simulation of heap allocation was correct.
+  ASSERT(o == Resolve(a));
+
+  // Read any recursively embedded objects.
+  int c = reader_.GetC();
+  while (c == '[') {
+    GetObject();
+    c = reader_.GetC();
+  }
+  ASSERT(c == '|');
+
+  HeapObject* obj = reinterpret_cast<HeapObject*>(o);
+  // Read the uninterpreted contents of the object after the map
+  reader_.GetBytes(obj->address(), size);
+#ifdef DEBUG
+  if (expect_debug_information_) {
+    // Read in the epilogue to check that we're still synchronized
+    ExpectEncodedAddress(a);
+    reader_.ExpectC(']');
+  }
+#endif
+
+  // Resolve the encoded pointers we just read in.
+  // Same as obj->Iterate(this), but doesn't rely on the map pointer being set.
+  VisitPointer(reinterpret_cast<Object**>(obj->address()));
+  obj->IterateBody(type, size, this);
+
+  if (type == CODE_TYPE) {
+    Code* code = Code::cast(obj);
+    // Convert relocations from Object* to Address in Code objects
+    code->ConvertICTargetsFromObjectToAddress();
+    LOG(CodeMoveEvent(a, code->address()));
+  }
+  objects_++;
+  return o;
+}
+
+
+static inline Object* ResolvePaged(int page_index,
+                                   int page_offset,
+                                   PagedSpace* space,
+                                   List<Page*>* page_list) {
+  ASSERT(page_index < page_list->length());
+  Address address = (*page_list)[page_index]->OffsetToAddress(page_offset);
+  return HeapObject::FromAddress(address);
+}
+
+
+template<typename T>
+void ConcatReversed(List<T>* target, const List<T>& source) {
+  for (int i = source.length() - 1; i >= 0; i--) {
+    target->Add(source[i]);
+  }
+}
+
+
+Object* Deserializer::Resolve(Address encoded) {
+  Object* o = reinterpret_cast<Object*>(encoded);
+  if (o->IsSmi()) return o;
+
+  // Encoded addresses of HeapObjects always have 'HeapObject' tags.
+  ASSERT(o->IsHeapObject());
+
+  switch (GetSpace(encoded)) {
+    // For Map space and Old space, we cache the known Pages in map_pages,
+    // old_pointer_pages and old_data_pages. Even though MapSpace keeps a list
+    // of page addresses, we don't rely on it since GetObject uses AllocateRaw,
+    // and that appears not to update the page list.
+    case MAP_SPACE:
+      return ResolvePaged(PageIndex(encoded), PageOffset(encoded),
+                          Heap::map_space(), &map_pages_);
+    case OLD_POINTER_SPACE:
+      return ResolvePaged(PageIndex(encoded), PageOffset(encoded),
+                          Heap::old_pointer_space(), &old_pointer_pages_);
+    case OLD_DATA_SPACE:
+      return ResolvePaged(PageIndex(encoded), PageOffset(encoded),
+                          Heap::old_data_space(), &old_data_pages_);
+    case CODE_SPACE:
+      return ResolvePaged(PageIndex(encoded), PageOffset(encoded),
+                          Heap::code_space(), &code_pages_);
+    case NEW_SPACE:
+      return HeapObject::FromAddress(Heap::NewSpaceStart() +
+                                     NewSpaceOffset(encoded));
+    case LO_SPACE:
+      // Cache the known large_objects, allocated one per 'page'
+      int index = LargeObjectIndex(encoded);
+      if (index >= large_objects_.length()) {
+        int new_object_count =
+          Heap::lo_space()->PageCount() - large_objects_.length();
+        List<Object*> new_objects(new_object_count);
+        LargeObjectIterator it(Heap::lo_space());
+        for (int i = 0; i < new_object_count; i++) {
+          new_objects.Add(it.next());
+        }
+#ifdef DEBUG
+        for (int i = large_objects_.length() - 1; i >= 0; i--) {
+          ASSERT(it.next() == large_objects_[i]);
+        }
+#endif
+        ConcatReversed(&large_objects_, new_objects);
+        ASSERT(index < large_objects_.length());
+      }
+      return large_objects_[index];  // s.page_offset() is ignored.
+  }
+  UNREACHABLE();
+  return NULL;
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/serialize.h b/deps/v8/src/serialize.h
new file mode 100644
index 0000000..ce7d947
--- /dev/null
+++ b/deps/v8/src/serialize.h
@@ -0,0 +1,335 @@
+// 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_SERIALIZE_H_
+#define V8_SERIALIZE_H_
+
+#include "hashmap.h"
+
+namespace v8 { namespace internal {
+
+// A TypeCode is used to distinguish different kinds of external reference.
+// It is a single bit to make testing for types easy.
+enum TypeCode {
+  UNCLASSIFIED,        // One-of-a-kind references.
+  BUILTIN,
+  RUNTIME_FUNCTION,
+  IC_UTILITY,
+  DEBUG_ADDRESS,
+  STATS_COUNTER,
+  TOP_ADDRESS,
+  C_BUILTIN,
+  EXTENSION,
+  ACCESSOR,
+  RUNTIME_ENTRY,
+  STUB_CACHE_TABLE
+};
+
+const int kTypeCodeCount = STUB_CACHE_TABLE + 1;
+const int kFirstTypeCode = UNCLASSIFIED;
+
+const int kReferenceIdBits = 16;
+const int kReferenceIdMask = (1 << kReferenceIdBits) - 1;
+const int kReferenceTypeShift = kReferenceIdBits;
+const int kDebugRegisterBits = 4;
+const int kDebugIdShift = kDebugRegisterBits;
+
+
+class ExternalReferenceEncoder {
+ public:
+  ExternalReferenceEncoder();
+
+  uint32_t Encode(Address key) const;
+
+  const char* NameOfAddress(Address key) const;
+
+ private:
+  HashMap encodings_;
+  static uint32_t Hash(Address key) {
+    return reinterpret_cast<uint32_t>(key) >> 2;
+  }
+
+  int IndexOf(Address key) const;
+
+  static bool Match(void* key1, void* key2) { return key1 == key2; }
+
+  void Put(Address key, int index);
+};
+
+
+class ExternalReferenceDecoder {
+ public:
+  ExternalReferenceDecoder();
+  ~ExternalReferenceDecoder();
+
+  Address Decode(uint32_t key) const {
+    if (key == 0) return NULL;
+    return *Lookup(key);
+  }
+
+ private:
+  Address** encodings_;
+
+  Address* Lookup(uint32_t key) const {
+    int type = key >> kReferenceTypeShift;
+    ASSERT(kFirstTypeCode <= type && type < kTypeCodeCount);
+    int id = key & kReferenceIdMask;
+    return &encodings_[type][id];
+  }
+
+  void Put(uint32_t key, Address value) {
+    *Lookup(key) = value;
+  }
+};
+
+
+// A Serializer recursively visits objects to construct a serialized
+// representation of the Heap stored in a string. Serialization is
+// destructive. We use a similar mechanism to the GC to ensure that
+// each object is visited once, namely, we modify the map pointer of
+// each visited object to contain the relative address in the
+// appropriate space where that object will be allocated when the heap
+// is deserialized.
+
+
+// Helper classes defined in serialize.cc.
+class RelativeAddress;
+class SimulatedHeapSpace;
+class SnapshotWriter;
+class ReferenceUpdater;
+
+
+class Serializer: public ObjectVisitor {
+ public:
+  Serializer();
+
+  virtual ~Serializer();
+
+  // Serialize the current state of the heap. This operation destroys the
+  // heap contents and the contents of the roots into the heap.
+  void Serialize();
+
+  // Returns the serialized buffer. Ownership is transferred to the
+  // caller. Only the destructor and getters may be called after this call.
+  void Finalize(byte** str, int* len);
+
+  int roots() { return roots_; }
+  int objects() { return objects_; }
+
+#ifdef DEBUG
+  // insert "tag" into the serialized stream
+  virtual void Synchronize(const char* tag);
+#endif
+
+  static bool enabled() { return serialization_enabled_; }
+
+  static void Enable() { serialization_enabled_ = true; }
+  static void Disable() { serialization_enabled_ = false; }
+
+ private:
+  friend class ReferenceUpdater;
+
+  virtual void VisitPointers(Object** start, Object** end);
+
+  bool IsVisited(HeapObject* obj);
+
+  Address GetSavedAddress(HeapObject* obj);
+
+  void SaveAddress(HeapObject* obj, Address addr);
+
+  void PutEncodedAddress(Address addr);
+  // Write the global flags into the file.
+  void PutFlags();
+  // Write global information into the header of the file.
+  void PutHeader();
+  // Write the contents of the log into the file.
+  void PutLog();
+  // Serialize 'obj', and return its encoded RelativeAddress.
+  Address PutObject(HeapObject* obj);
+  // Write a stack of handles to the file bottom first.
+  void PutGlobalHandleStack(const List<Handle<Object> >& stack);
+  // Write the context stack into the file.
+  void PutContextStack();
+
+  // Return the encoded RelativeAddress where this object will be
+  // allocated on deserialization. On the first visit of 'o',
+  // serialize its contents. On return, *serialized will be true iff
+  // 'o' has just been serialized.
+  Address Encode(Object* o, bool* serialized);
+
+  // Simulate the allocation of 'obj', returning the address where it will
+  // be allocated on deserialization
+  RelativeAddress Allocate(HeapObject* obj);
+
+  void InitializeAllocators();
+
+  SnapshotWriter* writer_;
+  bool root_;  // serializing a root?
+  int roots_;  // number of roots visited
+  int objects_;  // number of objects serialized
+
+  static bool serialization_enabled_;
+
+  int flags_end_;  // The position right after the flags.
+
+  // An array of per-space SimulatedHeapSpacees used as memory allocators.
+  SimulatedHeapSpace* allocator_[LAST_SPACE+1];
+  // A list of global handles at serialization time.
+  List<Object**> global_handles_;
+
+  ExternalReferenceEncoder* reference_encoder_;
+
+  HashMap saved_addresses_;
+
+  DISALLOW_COPY_AND_ASSIGN(Serializer);
+};
+
+// Helper class to read the bytes of the serialized heap.
+
+class SnapshotReader {
+ public:
+  SnapshotReader(const byte* str, int len): str_(str), end_(str + len) {}
+
+  void ExpectC(char expected) {
+    int c = GetC();
+    USE(c);
+    ASSERT(c == expected);
+  }
+
+  int GetC() {
+    if (str_ >= end_) return EOF;
+    return *str_++;
+  }
+
+  int GetInt() {
+    int result;
+    GetBytes(reinterpret_cast<Address>(&result), sizeof(result));
+    return result;
+  }
+
+  void GetBytes(Address a, int size) {
+    ASSERT(str_ + size <= end_);
+    memcpy(a, str_, size);
+    str_ += size;
+  }
+
+  char* GetString() {
+    ExpectC('[');
+    int size = GetInt();
+    ExpectC(']');
+    char* s = NewArray<char>(size + 1);
+    GetBytes(reinterpret_cast<Address>(s), size);
+    s[size] = 0;
+    return s;
+  }
+
+ private:
+  const byte* str_;
+  const byte* end_;
+};
+
+
+// A Deserializer reads a snapshot and reconstructs the Object graph it defines.
+
+class Deserializer: public ObjectVisitor {
+ public:
+  // Create a deserializer. The snapshot is held in str and has size len.
+  Deserializer(const byte* str, int len);
+
+  virtual ~Deserializer();
+
+  // Read the flags from the header of the file, and set those that
+  // should be inherited from the snapshot.
+  void GetFlags();
+
+  // Read saved profiling information from the file and log it if required.
+  void GetLog();
+
+  // Deserialize the snapshot into an empty heap.
+  void Deserialize();
+
+  int roots() { return roots_; }
+  int objects() { return objects_; }
+
+#ifdef DEBUG
+  // Check for the presence of "tag" in the serialized stream
+  virtual void Synchronize(const char* tag);
+#endif
+
+ private:
+  virtual void VisitPointers(Object** start, Object** end);
+  virtual void VisitExternalReferences(Address* start, Address* end);
+  virtual void VisitRuntimeEntry(RelocInfo* rinfo);
+
+  Address GetEncodedAddress();
+
+  // Read other global information (except flags) from the header of the file.
+  void GetHeader();
+  // Read a stack of handles from the file bottom first.
+  void GetGlobalHandleStack(List<Handle<Object> >* stack);
+  // Read the context stack from the file.
+  void GetContextStack();
+
+  Object* GetObject();
+
+  // Get the encoded address. In debug mode we make sure
+  // it matches the given expectations.
+  void ExpectEncodedAddress(Address expected);
+
+  // Given an encoded address (the result of
+  // RelativeAddress::Encode), return the object to which it points,
+  // which will be either an Smi or a HeapObject in the current heap.
+  Object* Resolve(Address encoded_address);
+
+  SnapshotReader reader_;
+  bool root_;  // Deserializing a root?
+  int roots_;  // number of roots visited
+  int objects_;  // number of objects serialized
+
+  bool has_log_;  // The file has log information.
+
+  // Resolve caches the following:
+  List<Page*> map_pages_;          // All pages in the map space.
+  List<Page*> old_pointer_pages_;  // All pages in the old pointer space.
+  List<Page*> old_data_pages_;     // All pages in the old data space.
+  List<Page*> code_pages_;
+  List<Object*> large_objects_;    // All known large objects.
+  // A list of global handles at deserialization time.
+  List<Object**> global_handles_;
+
+  ExternalReferenceDecoder* reference_decoder_;
+
+#ifdef DEBUG
+  bool expect_debug_information_;
+#endif
+
+  DISALLOW_COPY_AND_ASSIGN(Deserializer);
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_SERIALIZE_H_
diff --git a/deps/v8/src/shell.h b/deps/v8/src/shell.h
new file mode 100644
index 0000000..4042c07
--- /dev/null
+++ b/deps/v8/src/shell.h
@@ -0,0 +1,49 @@
+// 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.
+//
+// A simple interactive shell.  Enable with --shell.
+
+#include "../public/debug.h"
+
+namespace v8 { namespace internal {
+
+// Debug event handler for interactive debugging.
+void handle_debug_event(v8::DebugEvent event,
+                        v8::Handle<v8::Object> exec_state,
+                        v8::Handle<v8::Object> event_data,
+                        v8::Handle<Value> data);
+
+
+class Shell {
+ public:
+  static void PrintObject(v8::Handle<v8::Value> obj);
+  // Run the read-eval loop, executing code in the specified
+  // environment.
+  static void Run(v8::Handle<v8::Context> context);
+};
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/simulator-arm.cc b/deps/v8/src/simulator-arm.cc
new file mode 100644
index 0000000..5a61107
--- /dev/null
+++ b/deps/v8/src/simulator-arm.cc
@@ -0,0 +1,1598 @@
+// Copyright 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.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "disasm.h"
+#include "constants-arm.h"
+#include "simulator-arm.h"
+
+#if !defined(__arm__)
+
+// Only build the simulator if not compiling for real ARM hardware.
+namespace assembler { namespace arm {
+
+using ::v8::internal::Object;
+using ::v8::internal::PrintF;
+using ::v8::internal::OS;
+using ::v8::internal::ReadLine;
+using ::v8::internal::DeleteArray;
+
+// This macro provides a platform independent use of sscanf. The reason for
+// SScanF not being implemented in a platform independent was through
+// ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time
+// Library does not provide vsscanf.
+#define SScanF sscanf  // NOLINT
+
+// The Debugger class is used by the simulator while debugging simulated ARM
+// code.
+class Debugger {
+ public:
+  explicit Debugger(Simulator* sim);
+  ~Debugger();
+
+  void Stop(Instr* instr);
+  void Debug();
+
+ private:
+  static const instr_t kBreakpointInstr =
+      ((AL << 28) | (7 << 25) | (1 << 24) | break_point);
+  static const instr_t kNopInstr =
+      ((AL << 28) | (13 << 21));
+
+  Simulator* sim_;
+
+  bool GetValue(char* desc, int32_t* value);
+
+  // Set or delete a breakpoint. Returns true if successful.
+  bool SetBreakpoint(Instr* breakpc);
+  bool DeleteBreakpoint(Instr* breakpc);
+
+  // Undo and redo all breakpoints. This is needed to bracket disassembly and
+  // execution to skip past breakpoints when run from the debugger.
+  void UndoBreakpoints();
+  void RedoBreakpoints();
+};
+
+
+Debugger::Debugger(Simulator* sim) {
+  sim_ = sim;
+}
+
+
+Debugger::~Debugger() {
+}
+
+
+void Debugger::Stop(Instr* instr) {
+  const char* str = (const char*)(instr->InstructionBits() & 0x0fffffff);
+  PrintF("Simulator hit %s\n", str);
+  sim_->set_pc(sim_->get_pc() + Instr::kInstrSize);
+  Debug();
+}
+
+
+static const char* reg_names[] = {  "r0",  "r1",  "r2",  "r3",
+                                    "r4",  "r5",  "r6",  "r7",
+                                    "r8",  "r9", "r10", "r11",
+                                   "r12", "r13", "r14", "r15",
+                                    "pc",  "lr",  "sp",  "ip",
+                                    "fp",  "sl", ""};
+
+static int   reg_nums[]  = {           0,     1,     2,     3,
+                                       4,     5,     6,     7,
+                                       8,     9,    10,    11,
+                                      12,    13,    14,    15,
+                                      15,    14,    13,    12,
+                                      11,    10};
+
+
+static int RegNameToRegNum(char* name) {
+  int reg = 0;
+  while (*reg_names[reg] != 0) {
+    if (strcmp(reg_names[reg], name) == 0) {
+      return reg_nums[reg];
+    }
+    reg++;
+  }
+  return -1;
+}
+
+
+bool Debugger::GetValue(char* desc, int32_t* value) {
+  int regnum = RegNameToRegNum(desc);
+  if (regnum >= 0) {
+    if (regnum == 15) {
+      *value = sim_->get_pc();
+    } else {
+      *value = sim_->get_register(regnum);
+    }
+    return true;
+  } else {
+    return SScanF(desc, "%i", value) == 1;
+  }
+  return false;
+}
+
+
+bool Debugger::SetBreakpoint(Instr* breakpc) {
+  // Check if a breakpoint can be set. If not return without any side-effects.
+  if (sim_->break_pc_ != NULL) {
+    return false;
+  }
+
+  // Set the breakpoint.
+  sim_->break_pc_ = breakpc;
+  sim_->break_instr_ = breakpc->InstructionBits();
+  // Not setting the breakpoint instruction in the code itself. It will be set
+  // when the debugger shell continues.
+  return true;
+}
+
+
+bool Debugger::DeleteBreakpoint(Instr* breakpc) {
+  if (sim_->break_pc_ != NULL) {
+    sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
+  }
+
+  sim_->break_pc_ = NULL;
+  sim_->break_instr_ = 0;
+  return true;
+}
+
+
+void Debugger::UndoBreakpoints() {
+  if (sim_->break_pc_ != NULL) {
+    sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
+  }
+}
+
+
+void Debugger::RedoBreakpoints() {
+  if (sim_->break_pc_ != NULL) {
+    sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
+  }
+}
+
+
+void Debugger::Debug() {
+  intptr_t last_pc = -1;
+  bool done = false;
+
+#define COMMAND_SIZE 63
+#define ARG_SIZE 255
+
+#define STR(a) #a
+#define XSTR(a) STR(a)
+
+  char cmd[COMMAND_SIZE + 1];
+  char arg1[ARG_SIZE + 1];
+  char arg2[ARG_SIZE + 1];
+
+  // make sure to have a proper terminating character if reaching the limit
+  cmd[COMMAND_SIZE] = 0;
+  arg1[ARG_SIZE] = 0;
+  arg2[ARG_SIZE] = 0;
+
+  // Undo all set breakpoints while running in the debugger shell. This will
+  // make them invisible to all commands.
+  UndoBreakpoints();
+
+  while (!done) {
+    if (last_pc != sim_->get_pc()) {
+      disasm::NameConverter converter;
+      disasm::Disassembler dasm(converter);
+      // use a reasonably large buffer
+      v8::internal::EmbeddedVector<char, 256> buffer;
+      dasm.InstructionDecode(buffer,
+                             reinterpret_cast<byte*>(sim_->get_pc()));
+      PrintF("  0x%x  %s\n", sim_->get_pc(), buffer.start());
+      last_pc = sim_->get_pc();
+    }
+    char* line = ReadLine("sim> ");
+    if (line == NULL) {
+      break;
+    } else {
+      // Use sscanf to parse the individual parts of the command line. At the
+      // moment no command expects more than two parameters.
+      int args = SScanF(line,
+                        "%" XSTR(COMMAND_SIZE) "s "
+                        "%" XSTR(ARG_SIZE) "s "
+                        "%" XSTR(ARG_SIZE) "s",
+                        cmd, arg1, arg2);
+      if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
+        sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
+      } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
+        // Execute the one instruction we broke at with breakpoints disabled.
+        sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
+        // Leave the debugger shell.
+        done = true;
+      } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
+        if (args == 2) {
+          int32_t value;
+          if (GetValue(arg1, &value)) {
+            PrintF("%s: %d 0x%x\n", arg1, value, value);
+          } else {
+            PrintF("%s unrecognized\n", arg1);
+          }
+        } else {
+          PrintF("print value\n");
+        }
+      } else if ((strcmp(cmd, "po") == 0)
+                 || (strcmp(cmd, "printobject") == 0)) {
+        if (args == 2) {
+          int32_t value;
+          if (GetValue(arg1, &value)) {
+            Object* obj = reinterpret_cast<Object*>(value);
+            USE(obj);
+            PrintF("%s: \n", arg1);
+#if defined(DEBUG)
+            obj->PrintLn();
+#endif  // defined(DEBUG)
+          } else {
+            PrintF("%s unrecognized\n", arg1);
+          }
+        } else {
+          PrintF("printobject value\n");
+        }
+      } else if (strcmp(cmd, "disasm") == 0) {
+        disasm::NameConverter converter;
+        disasm::Disassembler dasm(converter);
+        // use a reasonably large buffer
+        v8::internal::EmbeddedVector<char, 256> buffer;
+
+        byte* cur = NULL;
+        byte* end = NULL;
+
+        if (args == 1) {
+          cur = reinterpret_cast<byte*>(sim_->get_pc());
+          end = cur + (10 * Instr::kInstrSize);
+        } else if (args == 2) {
+          int32_t value;
+          if (GetValue(arg1, &value)) {
+            cur = reinterpret_cast<byte*>(value);
+            // no length parameter passed, assume 10 instructions
+            end = cur + (10 * Instr::kInstrSize);
+          }
+        } else {
+          int32_t value1;
+          int32_t value2;
+          if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
+            cur = reinterpret_cast<byte*>(value1);
+            end = cur + (value2 * Instr::kInstrSize);
+          }
+        }
+
+        while (cur < end) {
+          dasm.InstructionDecode(buffer, cur);
+          PrintF("  0x%x  %s\n", cur, buffer.start());
+          cur += Instr::kInstrSize;
+        }
+      } else if (strcmp(cmd, "gdb") == 0) {
+        PrintF("relinquishing control to gdb\n");
+        v8::internal::OS::DebugBreak();
+        PrintF("regaining control from gdb\n");
+      } else if (strcmp(cmd, "break") == 0) {
+        if (args == 2) {
+          int32_t value;
+          if (GetValue(arg1, &value)) {
+            if (!SetBreakpoint(reinterpret_cast<Instr*>(value))) {
+              PrintF("setting breakpoint failed\n");
+            }
+          } else {
+            PrintF("%s unrecognized\n", arg1);
+          }
+        } else {
+          PrintF("break addr\n");
+        }
+      } else if (strcmp(cmd, "del") == 0) {
+        if (!DeleteBreakpoint(NULL)) {
+          PrintF("deleting breakpoint failed\n");
+        }
+      } else if (strcmp(cmd, "flags") == 0) {
+        PrintF("N flag: %d; ", sim_->n_flag_);
+        PrintF("Z flag: %d; ", sim_->z_flag_);
+        PrintF("C flag: %d; ", sim_->c_flag_);
+        PrintF("V flag: %d\n", sim_->v_flag_);
+      } else if (strcmp(cmd, "unstop") == 0) {
+        intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize;
+        Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc);
+        if (stop_instr->ConditionField() == special_condition) {
+          stop_instr->SetInstructionBits(kNopInstr);
+        } else {
+          PrintF("Not at debugger stop.");
+        }
+      } else {
+        PrintF("Unknown command: %s\n", cmd);
+      }
+    }
+    DeleteArray(line);
+  }
+
+  // Add all the breakpoints back to stop execution and enter the debugger
+  // shell when hit.
+  RedoBreakpoints();
+
+#undef COMMAND_SIZE
+#undef ARG_SIZE
+
+#undef STR
+#undef XSTR
+}
+
+
+Simulator::Simulator() {
+  // Setup simulator support first. Some of this information is needed to
+  // setup the architecture state.
+  size_t stack_size = 1 * 1024*1024;  // allocate 1MB for stack
+  stack_ = reinterpret_cast<char*>(malloc(stack_size));
+  pc_modified_ = false;
+  icount_ = 0;
+  break_pc_ = NULL;
+  break_instr_ = 0;
+
+  // Setup architecture state.
+  // All registers are initialized to zero to start with.
+  for (int i = 0; i < num_registers; i++) {
+    registers_[i] = 0;
+  }
+  n_flag_ = false;
+  z_flag_ = false;
+  c_flag_ = false;
+  v_flag_ = false;
+
+  // The sp is initialized to point to the bottom (high address) of the
+  // allocated stack area. To be safe in potential stack underflows we leave
+  // some buffer below.
+  registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64;
+  // The lr and pc are initialized to a known bad value that will cause an
+  // access violation if the simulator ever tries to execute it.
+  registers_[pc] = bad_lr;
+  registers_[lr] = bad_lr;
+}
+
+
+// Create one simulator per thread and keep it in thread local storage.
+static v8::internal::Thread::LocalStorageKey simulator_key =
+    v8::internal::Thread::CreateThreadLocalKey();
+
+// Get the active Simulator for the current thread.
+Simulator* Simulator::current() {
+  Simulator* sim = reinterpret_cast<Simulator*>(
+      v8::internal::Thread::GetThreadLocal(simulator_key));
+  if (sim == NULL) {
+    // TODO(146): delete the simulator object when a thread goes away.
+    sim = new Simulator();
+    v8::internal::Thread::SetThreadLocal(simulator_key, sim);
+  }
+  return sim;
+}
+
+
+// Sets the register in the architecture state. It will also deal with updating
+// Simulator internal state for special registers such as PC.
+void Simulator::set_register(int reg, int32_t value) {
+  ASSERT((reg >= 0) && (reg < num_registers));
+  if (reg == pc) {
+    pc_modified_ = true;
+  }
+  registers_[reg] = value;
+}
+
+
+// Get the register from the architecture state. This function does handle
+// the special case of accessing the PC register.
+int32_t Simulator::get_register(int reg) const {
+  ASSERT((reg >= 0) && (reg < num_registers));
+  return registers_[reg] + ((reg == pc) ? Instr::kPCReadOffset : 0);
+}
+
+
+// Raw access to the PC register.
+void Simulator::set_pc(int32_t value) {
+  pc_modified_ = true;
+  registers_[pc] = value;
+}
+
+
+// Raw access to the PC register without the special adjustment when reading.
+int32_t Simulator::get_pc() const {
+  return registers_[pc];
+}
+
+
+// The ARM cannot do unaligned reads and writes.  On some ARM platforms an
+// interrupt is caused.  On others it does a funky rotation thing.  For now we
+// simply disallow unaligned reads, but at some point we may want to move to
+// emulating the rotate behaviour.  Note that simulator runs have the runtime
+// system running directly on the host system and only generated code is
+// executed in the simulator.  Since the host is typically IA32 we will not
+// get the correct ARM-like behaviour on unaligned accesses.
+
+int Simulator::ReadW(int32_t addr, Instr* instr) {
+  if ((addr & 3) == 0) {
+    intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
+    return *ptr;
+  }
+  PrintF("Unaligned read at %x\n", addr);
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+void Simulator::WriteW(int32_t addr, int value, Instr* instr) {
+  if ((addr & 3) == 0) {
+    intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
+    *ptr = value;
+    return;
+  }
+  PrintF("Unaligned write at %x, pc=%p\n", addr, instr);
+  UNIMPLEMENTED();
+}
+
+
+uint16_t Simulator::ReadHU(int32_t addr, Instr* instr) {
+  if ((addr & 1) == 0) {
+    uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
+    return *ptr;
+  }
+  PrintF("Unaligned read at %x, pc=%p\n", addr, instr);
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+int16_t Simulator::ReadH(int32_t addr, Instr* instr) {
+  if ((addr & 1) == 0) {
+    int16_t* ptr = reinterpret_cast<int16_t*>(addr);
+    return *ptr;
+  }
+  PrintF("Unaligned read at %x\n", addr);
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+void Simulator::WriteH(int32_t addr, uint16_t value, Instr* instr) {
+  if ((addr & 1) == 0) {
+    uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
+    *ptr = value;
+    return;
+  }
+  PrintF("Unaligned write at %x, pc=%p\n", addr, instr);
+  UNIMPLEMENTED();
+}
+
+
+void Simulator::WriteH(int32_t addr, int16_t value, Instr* instr) {
+  if ((addr & 1) == 0) {
+    int16_t* ptr = reinterpret_cast<int16_t*>(addr);
+    *ptr = value;
+    return;
+  }
+  PrintF("Unaligned write at %x, pc=%p\n", addr, instr);
+  UNIMPLEMENTED();
+}
+
+
+uint8_t Simulator::ReadBU(int32_t addr) {
+  uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
+  return *ptr;
+}
+
+
+int8_t Simulator::ReadB(int32_t addr) {
+  int8_t* ptr = reinterpret_cast<int8_t*>(addr);
+  return *ptr;
+}
+
+
+void Simulator::WriteB(int32_t addr, uint8_t value) {
+  uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
+  *ptr = value;
+}
+
+
+void Simulator::WriteB(int32_t addr, int8_t value) {
+  int8_t* ptr = reinterpret_cast<int8_t*>(addr);
+  *ptr = value;
+}
+
+
+// Returns the limit of the stack area to enable checking for stack overflows.
+uintptr_t Simulator::StackLimit() const {
+  // Leave a safety margin of 256 bytes to prevent overrunning the stack when
+  // pushing values.
+  return reinterpret_cast<uintptr_t>(stack_) + 256;
+}
+
+
+// Unsupported instructions use Format to print an error and stop execution.
+void Simulator::Format(Instr* instr, const char* format) {
+  PrintF("Simulator found unsupported instruction:\n 0x%x: %s\n",
+         instr, format);
+  UNIMPLEMENTED();
+}
+
+
+// Checks if the current instruction should be executed based on its
+// condition bits.
+bool Simulator::ConditionallyExecute(Instr* instr) {
+  switch (instr->ConditionField()) {
+    case EQ: return z_flag_;
+    case NE: return !z_flag_;
+    case CS: return c_flag_;
+    case CC: return !c_flag_;
+    case MI: return n_flag_;
+    case PL: return !n_flag_;
+    case VS: return v_flag_;
+    case VC: return !v_flag_;
+    case HI: return c_flag_ && !z_flag_;
+    case LS: return !c_flag_ || z_flag_;
+    case GE: return n_flag_ == v_flag_;
+    case LT: return n_flag_ != v_flag_;
+    case GT: return !z_flag_ && (n_flag_ == v_flag_);
+    case LE: return z_flag_ || (n_flag_ != v_flag_);
+    case AL: return true;
+    default: UNREACHABLE();
+  }
+  return false;
+}
+
+
+// Calculate and set the Negative and Zero flags.
+void Simulator::SetNZFlags(int32_t val) {
+  n_flag_ = (val < 0);
+  z_flag_ = (val == 0);
+}
+
+
+// Set the Carry flag.
+void Simulator::SetCFlag(bool val) {
+  c_flag_ = val;
+}
+
+
+// Set the oVerflow flag.
+void Simulator::SetVFlag(bool val) {
+  v_flag_ = val;
+}
+
+
+// Calculate C flag value for additions.
+bool Simulator::CarryFrom(int32_t left, int32_t right) {
+  uint32_t uleft = static_cast<uint32_t>(left);
+  uint32_t uright = static_cast<uint32_t>(right);
+  uint32_t urest  = 0xffffffffU - uleft;
+
+  return (uright > urest);
+}
+
+
+// Calculate C flag value for subtractions.
+bool Simulator::BorrowFrom(int32_t left, int32_t right) {
+  uint32_t uleft = static_cast<uint32_t>(left);
+  uint32_t uright = static_cast<uint32_t>(right);
+
+  return (uright > uleft);
+}
+
+
+// Calculate V flag value for additions and subtractions.
+bool Simulator::OverflowFrom(int32_t alu_out,
+                             int32_t left, int32_t right, bool addition) {
+  bool overflow;
+  if (addition) {
+               // operands have the same sign
+    overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
+               // and operands and result have different sign
+               && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
+  } else {
+               // operands have different signs
+    overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
+               // and first operand and result have different signs
+               && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
+  }
+  return overflow;
+}
+
+
+// Addressing Mode 1 - Data-processing operands:
+// Get the value based on the shifter_operand with register.
+int32_t Simulator::GetShiftRm(Instr* instr, bool* carry_out) {
+  Shift shift = instr->ShiftField();
+  int shift_amount = instr->ShiftAmountField();
+  int32_t result = get_register(instr->RmField());
+  if (instr->Bit(4) == 0) {
+    // by immediate
+    if ((shift == ROR) && (shift_amount == 0)) {
+      UNIMPLEMENTED();
+      return result;
+    } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
+      shift_amount = 32;
+    }
+    switch (shift) {
+      case ASR: {
+        if (shift_amount == 0) {
+          if (result < 0) {
+            result = 0xffffffff;
+            *carry_out = true;
+          } else {
+            result = 0;
+            *carry_out = false;
+          }
+        } else {
+          result >>= (shift_amount - 1);
+          *carry_out = (result & 1) == 1;
+          result >>= 1;
+        }
+        break;
+      }
+
+      case LSL: {
+        if (shift_amount == 0) {
+          *carry_out = c_flag_;
+        } else {
+          result <<= (shift_amount - 1);
+          *carry_out = (result < 0);
+          result <<= 1;
+        }
+        break;
+      }
+
+      case LSR: {
+        if (shift_amount == 0) {
+          result = 0;
+          *carry_out = c_flag_;
+        } else {
+          uint32_t uresult = static_cast<uint32_t>(result);
+          uresult >>= (shift_amount - 1);
+          *carry_out = (uresult & 1) == 1;
+          uresult >>= 1;
+          result = static_cast<int32_t>(uresult);
+        }
+        break;
+      }
+
+      case ROR: {
+        UNIMPLEMENTED();
+        break;
+      }
+
+      default: {
+        UNREACHABLE();
+        break;
+      }
+    }
+  } else {
+    // by register
+    int rs = instr->RsField();
+    shift_amount = get_register(rs) &0xff;
+    switch (shift) {
+      case ASR: {
+        if (shift_amount == 0) {
+          *carry_out = c_flag_;
+        } else if (shift_amount < 32) {
+          result >>= (shift_amount - 1);
+          *carry_out = (result & 1) == 1;
+          result >>= 1;
+        } else {
+          ASSERT(shift_amount >= 32);
+          if (result < 0) {
+            *carry_out = true;
+            result = 0xffffffff;
+          } else {
+            *carry_out = false;
+            result = 0;
+          }
+        }
+        break;
+      }
+
+      case LSL: {
+        if (shift_amount == 0) {
+          *carry_out = c_flag_;
+        } else if (shift_amount < 32) {
+          result <<= (shift_amount - 1);
+          *carry_out = (result < 0);
+          result <<= 1;
+        } else if (shift_amount == 32) {
+          *carry_out = (result & 1) == 1;
+          result = 0;
+        } else {
+          ASSERT(shift_amount > 32);
+          *carry_out = false;
+          result = 0;
+        }
+        break;
+      }
+
+      case LSR: {
+        if (shift_amount == 0) {
+          *carry_out = c_flag_;
+        } else if (shift_amount < 32) {
+          uint32_t uresult = static_cast<uint32_t>(result);
+          uresult >>= (shift_amount - 1);
+          *carry_out = (uresult & 1) == 1;
+          uresult >>= 1;
+          result = static_cast<int32_t>(uresult);
+        } else if (shift_amount == 32) {
+          *carry_out = (result < 0);
+          result = 0;
+        } else {
+          *carry_out = false;
+          result = 0;
+        }
+        break;
+      }
+
+      case ROR: {
+        UNIMPLEMENTED();
+        break;
+      }
+
+      default: {
+        UNREACHABLE();
+        break;
+      }
+    }
+  }
+  return result;
+}
+
+
+// Addressing Mode 1 - Data-processing operands:
+// Get the value based on the shifter_operand with immediate.
+int32_t Simulator::GetImm(Instr* instr, bool* carry_out) {
+  int rotate = instr->RotateField() * 2;
+  int immed8 = instr->Immed8Field();
+  int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
+  *carry_out = (rotate == 0) ? c_flag_ : (imm < 0);
+  return imm;
+}
+
+
+static int count_bits(int bit_vector) {
+  int count = 0;
+  while (bit_vector != 0) {
+    if ((bit_vector & 1) != 0) {
+      count++;
+    }
+    bit_vector >>= 1;
+  }
+  return count;
+}
+
+
+// Addressing Mode 4 - Load and Store Multiple
+void Simulator::HandleRList(Instr* instr, bool load) {
+  int rn = instr->RnField();
+  int32_t rn_val = get_register(rn);
+  int rlist = instr->RlistField();
+  int num_regs = count_bits(rlist);
+
+  intptr_t start_address = 0;
+  intptr_t end_address = 0;
+  switch (instr->PUField()) {
+    case 0: {
+      // Print("da");
+      UNIMPLEMENTED();
+      break;
+    }
+    case 1: {
+      // Print("ia");
+      start_address = rn_val;
+      end_address = rn_val + (num_regs * 4) - 4;
+      rn_val = rn_val + (num_regs * 4);
+      break;
+    }
+    case 2: {
+      // Print("db");
+      start_address = rn_val - (num_regs * 4);
+      end_address = rn_val - 4;
+      rn_val = start_address;
+      break;
+    }
+    case 3: {
+      // Print("ib");
+      UNIMPLEMENTED();
+      break;
+    }
+    default: {
+      UNREACHABLE();
+      break;
+    }
+  }
+  if (instr->HasW()) {
+    set_register(rn, rn_val);
+  }
+  intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
+  int reg = 0;
+  while (rlist != 0) {
+    if ((rlist & 1) != 0) {
+      if (load) {
+        set_register(reg, *address);
+      } else {
+        *address = get_register(reg);
+      }
+      address += 1;
+    }
+    reg++;
+    rlist >>= 1;
+  }
+  ASSERT(end_address == ((intptr_t)address) - 4);
+}
+
+
+// Calls into the V8 runtime are based on this very simple interface.
+// Note: To be able to return two values from some calls the code in runtime.cc
+// uses the ObjectPair which is essentially two 32-bit values stuffed into a
+// 64-bit value. With the code below we assume that all runtime calls return
+// 64 bits of result. If they don't, the r1 result register contains a bogus
+// value, which is fine because it is caller-saved.
+typedef int64_t (*SimulatorRuntimeCall)(intptr_t arg0, intptr_t arg1);
+
+
+// Software interrupt instructions are used by the simulator to call into the
+// C-based V8 runtime.
+void Simulator::SoftwareInterrupt(Instr* instr) {
+  switch (instr->SwiField()) {
+    case call_rt_r5: {
+      SimulatorRuntimeCall target =
+          reinterpret_cast<SimulatorRuntimeCall>(get_register(r5));
+      intptr_t arg0 = get_register(r0);
+      intptr_t arg1 = get_register(r1);
+      int64_t result = target(arg0, arg1);
+      int32_t lo_res = static_cast<int32_t>(result);
+      int32_t hi_res = static_cast<int32_t>(result >> 32);
+      set_register(r0, lo_res);
+      set_register(r1, hi_res);
+      set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
+      break;
+    }
+    case call_rt_r2: {
+      SimulatorRuntimeCall target =
+          reinterpret_cast<SimulatorRuntimeCall>(get_register(r2));
+      intptr_t arg0 = get_register(r0);
+      intptr_t arg1 = get_register(r1);
+      int64_t result = target(arg0, arg1);
+      int32_t lo_res = static_cast<int32_t>(result);
+      int32_t hi_res = static_cast<int32_t>(result >> 32);
+      set_register(r0, lo_res);
+      set_register(r1, hi_res);
+      set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
+      break;
+    }
+    case break_point: {
+      Debugger dbg(this);
+      dbg.Debug();
+      break;
+    }
+    default: {
+      UNREACHABLE();
+      break;
+    }
+  }
+}
+
+
+// Handle execution based on instruction types.
+
+// Instruction types 0 and 1 are both rolled into one function because they
+// only differ in the handling of the shifter_operand.
+void Simulator::DecodeType01(Instr* instr) {
+  int type = instr->TypeField();
+  if ((type == 0) && instr->IsSpecialType0()) {
+    // multiply instruction or extra loads and stores
+    if (instr->Bits(7, 4) == 9) {
+      if (instr->Bit(24) == 0) {
+        // multiply instructions
+        int rd = instr->RdField();
+        int rm = instr->RmField();
+        int rs = instr->RsField();
+        int32_t rs_val = get_register(rs);
+        int32_t rm_val = get_register(rm);
+        if (instr->Bit(23) == 0) {
+          if (instr->Bit(21) == 0) {
+            // Format(instr, "mul'cond's 'rd, 'rm, 'rs");
+            int32_t alu_out = rm_val * rs_val;
+            set_register(rd, alu_out);
+            if (instr->HasS()) {
+              SetNZFlags(alu_out);
+            }
+          } else {
+            Format(instr, "mla'cond's 'rd, 'rm, 'rs, 'rn");
+          }
+        } else {
+          // Format(instr, "'um'al'cond's 'rn, 'rd, 'rs, 'rm");
+          int rn = instr->RnField();
+          int32_t hi_res = 0;
+          int32_t lo_res = 0;
+          if (instr->Bit(22) == 0) {
+            // signed multiply
+            UNIMPLEMENTED();
+          } else {
+            // unsigned multiply
+            uint64_t left_op  = rm_val;
+            uint64_t right_op = rs_val;
+            uint64_t result = left_op * right_op;
+            hi_res = static_cast<int32_t>(result >> 32);
+            lo_res = static_cast<int32_t>(result & 0xffffffff);
+          }
+          set_register(rn, hi_res);
+          set_register(rd, lo_res);
+          if (instr->HasS()) {
+            UNIMPLEMENTED();
+          }
+        }
+      } else {
+        UNIMPLEMENTED();  // not used by V8
+      }
+    } else {
+      // extra load/store instructions
+      int rd = instr->RdField();
+      int rn = instr->RnField();
+      int32_t rn_val = get_register(rn);
+      int32_t addr = 0;
+      if (instr->Bit(22) == 0) {
+        int rm = instr->RmField();
+        int32_t rm_val = get_register(rm);
+        switch (instr->PUField()) {
+          case 0: {
+            // Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
+            ASSERT(!instr->HasW());
+            addr = rn_val;
+            rn_val -= rm_val;
+            set_register(rn, rn_val);
+            break;
+          }
+          case 1: {
+            // Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
+            ASSERT(!instr->HasW());
+            addr = rn_val;
+            rn_val += rm_val;
+            set_register(rn, rn_val);
+            break;
+          }
+          case 2: {
+            // Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
+            rn_val -= rm_val;
+            addr = rn_val;
+            if (instr->HasW()) {
+              set_register(rn, rn_val);
+            }
+            break;
+          }
+          case 3: {
+            // Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
+            rn_val += rm_val;
+            addr = rn_val;
+            if (instr->HasW()) {
+              set_register(rn, rn_val);
+            }
+            break;
+          }
+          default: {
+            // The PU field is a 2-bit field.
+            UNREACHABLE();
+            break;
+          }
+        }
+      } else {
+        int32_t imm_val = (instr->ImmedHField() << 4) | instr->ImmedLField();
+        switch (instr->PUField()) {
+          case 0: {
+            // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
+            ASSERT(!instr->HasW());
+            addr = rn_val;
+            rn_val -= imm_val;
+            set_register(rn, rn_val);
+            break;
+          }
+          case 1: {
+            // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
+            ASSERT(!instr->HasW());
+            addr = rn_val;
+            rn_val += imm_val;
+            set_register(rn, rn_val);
+            break;
+          }
+          case 2: {
+            // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
+            rn_val -= imm_val;
+            addr = rn_val;
+            if (instr->HasW()) {
+              set_register(rn, rn_val);
+            }
+            break;
+          }
+          case 3: {
+            // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
+            rn_val += imm_val;
+            addr = rn_val;
+            if (instr->HasW()) {
+              set_register(rn, rn_val);
+            }
+            break;
+          }
+          default: {
+            // The PU field is a 2-bit field.
+            UNREACHABLE();
+            break;
+          }
+        }
+      }
+      if (instr->HasH()) {
+        if (instr->HasSign()) {
+          if (instr->HasL()) {
+            int16_t val = ReadH(addr, instr);
+            set_register(rd, val);
+          } else {
+            int16_t val = get_register(rd);
+            WriteH(addr, val, instr);
+          }
+        } else {
+          if (instr->HasL()) {
+            uint16_t val = ReadHU(addr, instr);
+            set_register(rd, val);
+          } else {
+            uint16_t val = get_register(rd);
+            WriteH(addr, val, instr);
+          }
+        }
+      } else {
+        // signed byte loads
+        ASSERT(instr->HasSign());
+        ASSERT(instr->HasL());
+        int8_t val = ReadB(addr);
+        set_register(rd, val);
+      }
+      return;
+    }
+  } else {
+    int rd = instr->RdField();
+    int rn = instr->RnField();
+    int32_t rn_val = get_register(rn);
+    int32_t shifter_operand = 0;
+    bool shifter_carry_out = 0;
+    if (type == 0) {
+      shifter_operand = GetShiftRm(instr, &shifter_carry_out);
+    } else {
+      ASSERT(instr->TypeField() == 1);
+      shifter_operand = GetImm(instr, &shifter_carry_out);
+    }
+    int32_t alu_out;
+
+    switch (instr->OpcodeField()) {
+      case AND: {
+        // Format(instr, "and'cond's 'rd, 'rn, 'shift_rm");
+        // Format(instr, "and'cond's 'rd, 'rn, 'imm");
+        alu_out = rn_val & shifter_operand;
+        set_register(rd, alu_out);
+        if (instr->HasS()) {
+          SetNZFlags(alu_out);
+          SetCFlag(shifter_carry_out);
+        }
+        break;
+      }
+
+      case EOR: {
+        // Format(instr, "eor'cond's 'rd, 'rn, 'shift_rm");
+        // Format(instr, "eor'cond's 'rd, 'rn, 'imm");
+        alu_out = rn_val ^ shifter_operand;
+        set_register(rd, alu_out);
+        if (instr->HasS()) {
+          SetNZFlags(alu_out);
+          SetCFlag(shifter_carry_out);
+        }
+        break;
+      }
+
+      case SUB: {
+        // Format(instr, "sub'cond's 'rd, 'rn, 'shift_rm");
+        // Format(instr, "sub'cond's 'rd, 'rn, 'imm");
+        alu_out = rn_val - shifter_operand;
+        set_register(rd, alu_out);
+        if (instr->HasS()) {
+          SetNZFlags(alu_out);
+          SetCFlag(!BorrowFrom(rn_val, shifter_operand));
+          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
+        }
+        break;
+      }
+
+      case RSB: {
+        // Format(instr, "rsb'cond's 'rd, 'rn, 'shift_rm");
+        // Format(instr, "rsb'cond's 'rd, 'rn, 'imm");
+        alu_out = shifter_operand - rn_val;
+        set_register(rd, alu_out);
+        if (instr->HasS()) {
+          SetNZFlags(alu_out);
+          SetCFlag(!BorrowFrom(shifter_operand, rn_val));
+          SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val, false));
+        }
+        break;
+      }
+
+      case ADD: {
+        // Format(instr, "add'cond's 'rd, 'rn, 'shift_rm");
+        // Format(instr, "add'cond's 'rd, 'rn, 'imm");
+        alu_out = rn_val + shifter_operand;
+        set_register(rd, alu_out);
+        if (instr->HasS()) {
+          SetNZFlags(alu_out);
+          SetCFlag(CarryFrom(rn_val, shifter_operand));
+          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
+        }
+        break;
+      }
+
+      case ADC: {
+        Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm");
+        Format(instr, "adc'cond's 'rd, 'rn, 'imm");
+        break;
+      }
+
+      case SBC: {
+        Format(instr, "sbc'cond's 'rd, 'rn, 'shift_rm");
+        Format(instr, "sbc'cond's 'rd, 'rn, 'imm");
+        break;
+      }
+
+      case RSC: {
+        Format(instr, "rsc'cond's 'rd, 'rn, 'shift_rm");
+        Format(instr, "rsc'cond's 'rd, 'rn, 'imm");
+        break;
+      }
+
+      case TST: {
+        if (instr->HasS()) {
+          // Format(instr, "tst'cond 'rn, 'shift_rm");
+          // Format(instr, "tst'cond 'rn, 'imm");
+          alu_out = rn_val & shifter_operand;
+          SetNZFlags(alu_out);
+          SetCFlag(shifter_carry_out);
+        } else {
+          UNIMPLEMENTED();
+        }
+        break;
+      }
+
+      case TEQ: {
+        if (instr->HasS()) {
+          // Format(instr, "teq'cond 'rn, 'shift_rm");
+          // Format(instr, "teq'cond 'rn, 'imm");
+          alu_out = rn_val ^ shifter_operand;
+          SetNZFlags(alu_out);
+          SetCFlag(shifter_carry_out);
+        } else {
+          UNIMPLEMENTED();
+        }
+        break;
+      }
+
+      case CMP: {
+        if (instr->HasS()) {
+          // Format(instr, "cmp'cond 'rn, 'shift_rm");
+          // Format(instr, "cmp'cond 'rn, 'imm");
+          alu_out = rn_val - shifter_operand;
+          SetNZFlags(alu_out);
+          SetCFlag(!BorrowFrom(rn_val, shifter_operand));
+          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
+        } else {
+          UNIMPLEMENTED();
+        }
+        break;
+      }
+
+      case CMN: {
+        if (instr->HasS()) {
+          Format(instr, "cmn'cond 'rn, 'shift_rm");
+          Format(instr, "cmn'cond 'rn, 'imm");
+        } else {
+          UNIMPLEMENTED();
+        }
+        break;
+      }
+
+      case ORR: {
+        // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm");
+        // Format(instr, "orr'cond's 'rd, 'rn, 'imm");
+        alu_out = rn_val | shifter_operand;
+        set_register(rd, alu_out);
+        if (instr->HasS()) {
+          SetNZFlags(alu_out);
+          SetCFlag(shifter_carry_out);
+        }
+        break;
+      }
+
+      case MOV: {
+        // Format(instr, "mov'cond's 'rd, 'shift_rm");
+        // Format(instr, "mov'cond's 'rd, 'imm");
+        alu_out = shifter_operand;
+        set_register(rd, alu_out);
+        if (instr->HasS()) {
+          SetNZFlags(alu_out);
+          SetCFlag(shifter_carry_out);
+        }
+        break;
+      }
+
+      case BIC: {
+        // Format(instr, "bic'cond's 'rd, 'rn, 'shift_rm");
+        // Format(instr, "bic'cond's 'rd, 'rn, 'imm");
+        alu_out = rn_val & ~shifter_operand;
+        set_register(rd, alu_out);
+        if (instr->HasS()) {
+          SetNZFlags(alu_out);
+          SetCFlag(shifter_carry_out);
+        }
+        break;
+      }
+
+      case MVN: {
+        // Format(instr, "mvn'cond's 'rd, 'shift_rm");
+        // Format(instr, "mvn'cond's 'rd, 'imm");
+        alu_out = ~shifter_operand;
+        set_register(rd, alu_out);
+        if (instr->HasS()) {
+          SetNZFlags(alu_out);
+          SetCFlag(shifter_carry_out);
+        }
+        break;
+      }
+
+      default: {
+        UNREACHABLE();
+        break;
+      }
+    }
+  }
+}
+
+
+void Simulator::DecodeType2(Instr* instr) {
+  int rd = instr->RdField();
+  int rn = instr->RnField();
+  int32_t rn_val = get_register(rn);
+  int32_t im_val = instr->Offset12Field();
+  int32_t addr = 0;
+  switch (instr->PUField()) {
+    case 0: {
+      // Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
+      ASSERT(!instr->HasW());
+      addr = rn_val;
+      rn_val -= im_val;
+      set_register(rn, rn_val);
+      break;
+    }
+    case 1: {
+      // Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
+      ASSERT(!instr->HasW());
+      addr = rn_val;
+      rn_val += im_val;
+      set_register(rn, rn_val);
+      break;
+    }
+    case 2: {
+      // Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
+      rn_val -= im_val;
+      addr = rn_val;
+      if (instr->HasW()) {
+        set_register(rn, rn_val);
+      }
+      break;
+    }
+    case 3: {
+      // Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
+      rn_val += im_val;
+      addr = rn_val;
+      if (instr->HasW()) {
+        set_register(rn, rn_val);
+      }
+      break;
+    }
+    default: {
+      UNREACHABLE();
+      break;
+    }
+  }
+  if (instr->HasB()) {
+    if (instr->HasL()) {
+      byte val = ReadBU(addr);
+      set_register(rd, val);
+    } else {
+      byte val = get_register(rd);
+      WriteB(addr, val);
+    }
+  } else {
+    if (instr->HasL()) {
+      set_register(rd, ReadW(addr, instr));
+    } else {
+      WriteW(addr, get_register(rd), instr);
+    }
+  }
+}
+
+
+void Simulator::DecodeType3(Instr* instr) {
+  int rd = instr->RdField();
+  int rn = instr->RnField();
+  int32_t rn_val = get_register(rn);
+  bool shifter_carry_out = 0;
+  int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out);
+  int32_t addr = 0;
+  switch (instr->PUField()) {
+    case 0: {
+      ASSERT(!instr->HasW());
+      Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
+      break;
+    }
+    case 1: {
+      ASSERT(!instr->HasW());
+      Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
+      break;
+    }
+    case 2: {
+      // Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
+      addr = rn_val - shifter_operand;
+      if (instr->HasW()) {
+        set_register(rn, addr);
+      }
+      break;
+    }
+    case 3: {
+      // Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
+      addr = rn_val + shifter_operand;
+      if (instr->HasW()) {
+        set_register(rn, addr);
+      }
+      break;
+    }
+    default: {
+      UNREACHABLE();
+      break;
+    }
+  }
+  if (instr->HasB()) {
+    UNIMPLEMENTED();
+  } else {
+    if (instr->HasL()) {
+      set_register(rd, ReadW(addr, instr));
+    } else {
+      WriteW(addr, get_register(rd), instr);
+    }
+  }
+}
+
+
+void Simulator::DecodeType4(Instr* instr) {
+  ASSERT(instr->Bit(22) == 0);  // only allowed to be set in privileged mode
+  if (instr->HasL()) {
+    // Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
+    HandleRList(instr, true);
+  } else {
+    // Format(instr, "stm'cond'pu 'rn'w, 'rlist");
+    HandleRList(instr, false);
+  }
+}
+
+
+void Simulator::DecodeType5(Instr* instr) {
+  // Format(instr, "b'l'cond 'target");
+  int off = (instr->SImmed24Field() << 2) + 8;
+  intptr_t pc = get_pc();
+  if (instr->HasLink()) {
+    set_register(lr, pc + Instr::kInstrSize);
+  }
+  set_pc(pc+off);
+}
+
+
+void Simulator::DecodeType6(Instr* instr) {
+  UNIMPLEMENTED();
+}
+
+
+void Simulator::DecodeType7(Instr* instr) {
+  if (instr->Bit(24) == 1) {
+    // Format(instr, "swi 'swi");
+    SoftwareInterrupt(instr);
+  } else {
+    UNIMPLEMENTED();
+  }
+}
+
+
+// Executes the current instruction.
+void Simulator::InstructionDecode(Instr* instr) {
+  pc_modified_ = false;
+  if (instr->ConditionField() == special_condition) {
+    Debugger dbg(this);
+    dbg.Stop(instr);
+    return;
+  }
+  if (::v8::internal::FLAG_trace_sim) {
+    disasm::NameConverter converter;
+    disasm::Disassembler dasm(converter);
+    // use a reasonably large buffer
+    v8::internal::EmbeddedVector<char, 256> buffer;
+    dasm.InstructionDecode(buffer,
+                           reinterpret_cast<byte*>(instr));
+    PrintF("  0x%x  %s\n", instr, buffer.start());
+  }
+  if (ConditionallyExecute(instr)) {
+    switch (instr->TypeField()) {
+      case 0:
+      case 1: {
+        DecodeType01(instr);
+        break;
+      }
+      case 2: {
+        DecodeType2(instr);
+        break;
+      }
+      case 3: {
+        DecodeType3(instr);
+        break;
+      }
+      case 4: {
+        DecodeType4(instr);
+        break;
+      }
+      case 5: {
+        DecodeType5(instr);
+        break;
+      }
+      case 6: {
+        DecodeType6(instr);
+        break;
+      }
+      case 7: {
+        DecodeType7(instr);
+        break;
+      }
+      default: {
+        UNIMPLEMENTED();
+        break;
+      }
+    }
+  }
+  if (!pc_modified_) {
+    set_register(pc, reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
+  }
+}
+
+
+//
+void Simulator::Execute() {
+  // Get the PC to simulate. Cannot use the accessor here as we need the
+  // raw PC value and not the one used as input to arithmetic instructions.
+  int program_counter = get_pc();
+
+  if (::v8::internal::FLAG_stop_sim_at == 0) {
+    // Fast version of the dispatch loop without checking whether the simulator
+    // should be stopping at a particular executed instruction.
+    while (program_counter != end_sim_pc) {
+      Instr* instr = reinterpret_cast<Instr*>(program_counter);
+      icount_++;
+      InstructionDecode(instr);
+      program_counter = get_pc();
+    }
+  } else {
+    // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
+    // we reach the particular instuction count.
+    while (program_counter != end_sim_pc) {
+      Instr* instr = reinterpret_cast<Instr*>(program_counter);
+      icount_++;
+      if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
+        Debugger dbg(this);
+        dbg.Debug();
+      } else {
+        InstructionDecode(instr);
+      }
+      program_counter = get_pc();
+    }
+  }
+}
+
+
+Object* Simulator::Call(int32_t entry, int32_t p0, int32_t p1, int32_t p2,
+                        int32_t p3, int32_t p4) {
+  // Setup parameters
+  set_register(r0, p0);
+  set_register(r1, p1);
+  set_register(r2, p2);
+  set_register(r3, p3);
+  intptr_t* stack_pointer = reinterpret_cast<intptr_t*>(get_register(sp));
+  *(--stack_pointer) = p4;
+  set_register(sp, reinterpret_cast<int32_t>(stack_pointer));
+
+  // Prepare to execute the code at entry
+  set_register(pc, entry);
+  // Put down marker for end of simulation. The simulator will stop simulation
+  // when the PC reaches this value. By saving the "end simulation" value into
+  // the LR the simulation stops when returning to this call point.
+  set_register(lr, end_sim_pc);
+
+  // Remember the values of callee-saved registers.
+  // The code below assumes that r9 is not used as sb (static base) in
+  // simulator code and therefore is regarded as a callee-saved register.
+  int32_t r4_val = get_register(r4);
+  int32_t r5_val = get_register(r5);
+  int32_t r6_val = get_register(r6);
+  int32_t r7_val = get_register(r7);
+  int32_t r8_val = get_register(r8);
+  int32_t r9_val = get_register(r9);
+  int32_t r10_val = get_register(r10);
+  int32_t r11_val = get_register(r11);
+
+  // Setup the callee-saved registers with a known value. To be able to check
+  // that they are preserved properly across JS execution.
+  int32_t callee_saved_value = icount_;
+  set_register(r4, callee_saved_value);
+  set_register(r5, callee_saved_value);
+  set_register(r6, callee_saved_value);
+  set_register(r7, callee_saved_value);
+  set_register(r8, callee_saved_value);
+  set_register(r9, callee_saved_value);
+  set_register(r10, callee_saved_value);
+  set_register(r11, callee_saved_value);
+
+  // Start the simulation
+  Execute();
+
+  // Check that the callee-saved registers have been preserved.
+  CHECK_EQ(get_register(r4), callee_saved_value);
+  CHECK_EQ(get_register(r5), callee_saved_value);
+  CHECK_EQ(get_register(r6), callee_saved_value);
+  CHECK_EQ(get_register(r7), callee_saved_value);
+  CHECK_EQ(get_register(r8), callee_saved_value);
+  CHECK_EQ(get_register(r9), callee_saved_value);
+  CHECK_EQ(get_register(r10), callee_saved_value);
+  CHECK_EQ(get_register(r11), callee_saved_value);
+
+  // Restore callee-saved registers with the original value.
+  set_register(r4, r4_val);
+  set_register(r5, r5_val);
+  set_register(r6, r6_val);
+  set_register(r7, r7_val);
+  set_register(r8, r8_val);
+  set_register(r9, r9_val);
+  set_register(r10, r10_val);
+  set_register(r11, r11_val);
+
+  int result = get_register(r0);
+  return reinterpret_cast<Object*>(result);
+}
+
+} }  // namespace assembler::arm
+
+#endif  // !defined(__arm__)
diff --git a/deps/v8/src/simulator-arm.h b/deps/v8/src/simulator-arm.h
new file mode 100644
index 0000000..4f3c53d
--- /dev/null
+++ b/deps/v8/src/simulator-arm.h
@@ -0,0 +1,198 @@
+// Copyright 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.
+
+
+// Declares a Simulator for ARM instructions if we are not generating a native
+// ARM binary. This Simulator allows us to run and debug ARM code generation on
+// regular desktop machines.
+// V8 calls into generated code by "calling" the CALL_GENERATED_CODE macro,
+// which will start execution in the Simulator or forwards to the real entry
+// on a ARM HW platform.
+
+#ifndef V8_SIMULATOR_ARM_H_
+#define V8_SIMULATOR_ARM_H_
+
+#if defined(__arm__)
+
+// When running without a simulator we call the entry directly.
+#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
+  entry(p0, p1, p2, p3, p4)
+
+// Calculated the stack limit beyond which we will throw stack overflow errors.
+// This macro must be called from a C++ method. It relies on being able to take
+// the address of "this" to get a value on the current execution stack and then
+// calculates the stack limit based on that value.
+#define GENERATED_CODE_STACK_LIMIT(limit) \
+  (reinterpret_cast<uintptr_t>(this) - limit)
+
+#else  // defined(__arm__)
+
+// When running with the simulator transition into simulated execution at this
+// point.
+#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
+  assembler::arm::Simulator::current()->Call((int32_t)entry, (int32_t)p0, \
+    (int32_t)p1, (int32_t)p2, (int32_t)p3, (int32_t)p4)
+
+// The simulator has its own stack. Thus it has a different stack limit from
+// the C-based native code.
+#define GENERATED_CODE_STACK_LIMIT(limit) \
+  (assembler::arm::Simulator::current()->StackLimit())
+
+
+#include "constants-arm.h"
+
+
+namespace assembler { namespace arm {
+
+class Simulator {
+ public:
+  friend class Debugger;
+
+  enum Register {
+    no_reg = -1,
+    r0 = 0, r1, r2, r3, r4, r5, r6, r7,
+    r8, r9, r10, r11, r12, r13, r14, r15,
+    num_registers,
+    sp = 13,
+    lr = 14,
+    pc = 15
+  };
+
+  Simulator();
+  ~Simulator();
+
+  // The currently executing Simulator instance. Potentially there can be one
+  // for each native thread.
+  static Simulator* current();
+
+  // Accessors for register state. Reading the pc value adheres to the ARM
+  // architecture specification and is off by a 8 from the currently executing
+  // instruction.
+  void set_register(int reg, int32_t value);
+  int32_t get_register(int reg) const;
+
+  // Special case of set_register and get_register to access the raw PC value.
+  void set_pc(int32_t value);
+  int32_t get_pc() const;
+
+  // Accessor to the internal simulator stack area.
+  uintptr_t StackLimit() const;
+
+  // Executes ARM instructions until the PC reaches end_sim_pc.
+  void Execute();
+
+  // V8 generally calls into generated code with 5 parameters. This is a
+  // convenience function, which sets up the simulator state and grabs the
+  // result on return.
+  v8::internal::Object* Call(int32_t entry, int32_t p0, int32_t p1,
+                             int32_t p2, int32_t p3, int32_t p4);
+
+ private:
+  enum special_values {
+    // Known bad pc value to ensure that the simulator does not execute
+    // without being properly setup.
+    bad_lr = -1,
+    // A pc value used to signal the simulator to stop execution.  Generally
+    // the lr is set to this value on transition from native C code to
+    // simulated execution, so that the simulator can "return" to the native
+    // C code.
+    end_sim_pc = -2
+  };
+
+  // Unsupported instructions use Format to print an error and stop execution.
+  void Format(Instr* instr, const char* format);
+
+  // Checks if the current instruction should be executed based on its
+  // condition bits.
+  bool ConditionallyExecute(Instr* instr);
+
+  // Helper functions to set the conditional flags in the architecture state.
+  void SetNZFlags(int32_t val);
+  void SetCFlag(bool val);
+  void SetVFlag(bool val);
+  bool CarryFrom(int32_t left, int32_t right);
+  bool BorrowFrom(int32_t left, int32_t right);
+  bool OverflowFrom(int32_t alu_out,
+                    int32_t left,
+                    int32_t right,
+                    bool addition);
+
+  // Helper functions to decode common "addressing" modes
+  int32_t GetShiftRm(Instr* instr, bool* carry_out);
+  int32_t GetImm(Instr* instr, bool* carry_out);
+  void HandleRList(Instr* instr, bool load);
+  void SoftwareInterrupt(Instr* instr);
+
+  // Read and write memory.
+  inline uint8_t ReadBU(int32_t addr);
+  inline int8_t ReadB(int32_t addr);
+  inline void WriteB(int32_t addr, uint8_t value);
+  inline void WriteB(int32_t addr, int8_t value);
+
+  inline uint16_t ReadHU(int32_t addr, Instr* instr);
+  inline int16_t ReadH(int32_t addr, Instr* instr);
+  // Note: Overloaded on the sign of the value.
+  inline void WriteH(int32_t addr, uint16_t value, Instr* instr);
+  inline void WriteH(int32_t addr, int16_t value, Instr* instr);
+
+  inline int ReadW(int32_t addr, Instr* instr);
+  inline void WriteW(int32_t addr, int value, Instr* instr);
+
+  // Executing is handled based on the instruction type.
+  void DecodeType01(Instr* instr);  // both type 0 and type 1 rolled into one
+  void DecodeType2(Instr* instr);
+  void DecodeType3(Instr* instr);
+  void DecodeType4(Instr* instr);
+  void DecodeType5(Instr* instr);
+  void DecodeType6(Instr* instr);
+  void DecodeType7(Instr* instr);
+
+  // Executes one instruction.
+  void InstructionDecode(Instr* instr);
+
+  // architecture state
+  int32_t registers_[16];
+  bool n_flag_;
+  bool z_flag_;
+  bool c_flag_;
+  bool v_flag_;
+
+  // simulator support
+  char* stack_;
+  bool pc_modified_;
+  int icount_;
+
+  // registered breakpoints
+  Instr* break_pc_;
+  instr_t break_instr_;
+};
+
+} }  // namespace assembler::arm
+
+#endif  // defined(__arm__)
+
+#endif  // V8_SIMULATOR_ARM_H_
diff --git a/deps/v8/src/simulator-ia32.cc b/deps/v8/src/simulator-ia32.cc
new file mode 100644
index 0000000..ab81693
--- /dev/null
+++ b/deps/v8/src/simulator-ia32.cc
@@ -0,0 +1,30 @@
+// Copyright 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.
+
+
+// Since there is no simulator for the ia32 architecture this file is empty.
+
diff --git a/deps/v8/src/simulator-ia32.h b/deps/v8/src/simulator-ia32.h
new file mode 100644
index 0000000..2267721
--- /dev/null
+++ b/deps/v8/src/simulator-ia32.h
@@ -0,0 +1,47 @@
+// Copyright 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_SIMULATOR_IA32_H_
+#define V8_SIMULATOR_IA32_H_
+
+
+// Since there is no simulator for the ia32 architecture the only thing we can
+// do is to call the entry directly.
+#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
+  entry(p0, p1, p2, p3, p4);
+
+// Calculated the stack limit beyond which we will throw stack overflow errors.
+// This macro must be called from a C++ method. It relies on being able to take
+// the address of "this" to get a value on the current execution stack and then
+// calculates the stack limit based on that value.
+// NOTE: The check for overflow is not safe as there is no guarantee that the
+// running thread has its stack in all memory up to address 0x00000000.
+#define GENERATED_CODE_STACK_LIMIT(limit) \
+  (reinterpret_cast<uintptr_t>(this) >= limit ? \
+      reinterpret_cast<uintptr_t>(this) - limit : 0)
+
+#endif  // V8_SIMULATOR_IA32_H_
diff --git a/deps/v8/src/smart-pointer.h b/deps/v8/src/smart-pointer.h
new file mode 100644
index 0000000..c39df16
--- /dev/null
+++ b/deps/v8/src/smart-pointer.h
@@ -0,0 +1,108 @@
+// Copyright 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_SMART_POINTER_H_
+#define V8_SMART_POINTER_H_
+
+namespace v8 { namespace internal {
+
+
+// A 'scoped array pointer' that calls DeleteArray on its pointer when the
+// destructor is called.
+template<typename T>
+class SmartPointer {
+ public:
+
+  // Default constructor. Construct an empty scoped pointer.
+  inline SmartPointer() : p(NULL) {}
+
+
+  // Construct a scoped pointer from a plain one.
+  explicit inline SmartPointer(T* pointer) : p(pointer) {}
+
+
+  // Copy constructor removes the pointer from the original to avoid double
+  // freeing.
+  inline SmartPointer(const SmartPointer<T>& rhs) : p(rhs.p) {
+    const_cast<SmartPointer<T>&>(rhs).p = NULL;
+  }
+
+
+  // When the destructor of the scoped pointer is executed the plain pointer
+  // is deleted using DeleteArray.  This implies that you must allocate with
+  // NewArray.
+  inline ~SmartPointer() { if (p) DeleteArray(p); }
+
+
+  // You can get the underlying pointer out with the * operator.
+  inline T* operator*() { return p; }
+
+
+  // You can use [n] to index as if it was a plain pointer
+  inline T& operator[](size_t i) {
+    return p[i];
+  }
+
+  // We don't have implicit conversion to a T* since that hinders migration:
+  // You would not be able to change a method from returning a T* to
+  // returning an SmartPointer<T> and then get errors wherever it is used.
+
+
+  // If you want to take out the plain pointer and don't want it automatically
+  // deleted then call Detach().  Afterwards, the smart pointer is empty
+  // (NULL).
+  inline T* Detach() {
+    T* temp = p;
+    p = NULL;
+    return temp;
+  }
+
+
+  // Assignment requires an empty (NULL) SmartPointer as the receiver.  Like
+  // the copy constructor it removes the pointer in the original to avoid
+  // double freeing.
+  inline SmartPointer& operator=(const SmartPointer<T>& rhs) {
+    ASSERT(is_empty());
+    T* tmp = rhs.p;  // swap to handle self-assignment
+    const_cast<SmartPointer<T>&>(rhs).p = NULL;
+    p = tmp;
+    return *this;
+  }
+
+
+  inline bool is_empty() {
+    return p == NULL;
+  }
+
+
+ private:
+  T* p;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_SMART_POINTER_H_
diff --git a/deps/v8/src/snapshot-common.cc b/deps/v8/src/snapshot-common.cc
new file mode 100644
index 0000000..3aa1cae
--- /dev/null
+++ b/deps/v8/src/snapshot-common.cc
@@ -0,0 +1,74 @@
+// 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.
+
+// The common functionality when building with or without snapshots.
+
+#include "v8.h"
+
+#include "api.h"
+#include "serialize.h"
+#include "snapshot.h"
+
+namespace v8 { namespace internal {
+
+bool Snapshot::Deserialize(const byte* content, int len) {
+  Deserializer des(content, len);
+  des.GetFlags();
+  return V8::Initialize(&des);
+}
+
+
+bool Snapshot::Initialize(const char* snapshot_file) {
+  if (snapshot_file) {
+    int len;
+    byte* str = ReadBytes(snapshot_file, &len);
+    if (!str) return false;
+    bool result = Deserialize(str, len);
+    DeleteArray(str);
+    return result;
+  } else if (size_ > 0) {
+    return Deserialize(data_, size_);
+  }
+  return false;
+}
+
+
+bool Snapshot::WriteToFile(const char* snapshot_file) {
+  Serializer ser;
+  ser.Serialize();
+  byte* str;
+  int len;
+  ser.Finalize(&str, &len);
+
+  int written = WriteBytes(snapshot_file, str, len);
+
+  DeleteArray(str);
+  return written == len;
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/snapshot-empty.cc b/deps/v8/src/snapshot-empty.cc
new file mode 100644
index 0000000..d4cda19
--- /dev/null
+++ b/deps/v8/src/snapshot-empty.cc
@@ -0,0 +1,39 @@
+// 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.
+
+// Used for building without snapshots.
+
+#include "v8.h"
+
+#include "snapshot.h"
+
+namespace v8 { namespace internal {
+
+const byte Snapshot::data_[] = { 0 };
+int Snapshot::size_ = 0;
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/snapshot.h b/deps/v8/src/snapshot.h
new file mode 100644
index 0000000..b3f23d3
--- /dev/null
+++ b/deps/v8/src/snapshot.h
@@ -0,0 +1,58 @@
+// 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_SNAPSHOT_H_
+#define V8_SNAPSHOT_H_
+
+namespace v8 { namespace internal {
+
+class Snapshot {
+ public:
+  // Initialize the VM from the given snapshot file. If snapshot_file is
+  // NULL, use the internal snapshot instead. Returns false if no snapshot
+  // could be found.
+  static bool Initialize(const char* snapshot_file = NULL);
+
+  // Returns whether or not the snapshot is enabled.
+  static bool IsEnabled() { return size_ != 0; }
+
+  // Write snapshot to the given file. Returns true if snapshot was written
+  // successfully.
+  static bool WriteToFile(const char* snapshot_file);
+
+ private:
+  static const byte data_[];
+  static int size_;
+
+  static bool Deserialize(const byte* content, int len);
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Snapshot);
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_SNAPSHOT_H_
diff --git a/deps/v8/src/spaces-inl.h b/deps/v8/src/spaces-inl.h
new file mode 100644
index 0000000..d7cddb4
--- /dev/null
+++ b/deps/v8/src/spaces-inl.h
@@ -0,0 +1,356 @@
+// 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_SPACES_INL_H_
+#define V8_SPACES_INL_H_
+
+#include "memory.h"
+#include "spaces.h"
+
+namespace v8 { namespace internal {
+
+
+// -----------------------------------------------------------------------------
+// HeapObjectIterator
+
+bool HeapObjectIterator::has_next() {
+  if (cur_addr_ < cur_limit_) {
+    return true;  // common case
+  }
+  ASSERT(cur_addr_ == cur_limit_);
+  return HasNextInNextPage();  // slow path
+}
+
+
+HeapObject* HeapObjectIterator::next() {
+  ASSERT(has_next());
+
+  HeapObject* obj = HeapObject::FromAddress(cur_addr_);
+  int obj_size = (size_func_ == NULL) ? obj->Size() : size_func_(obj);
+  ASSERT_OBJECT_SIZE(obj_size);
+
+  cur_addr_ += obj_size;
+  ASSERT(cur_addr_ <= cur_limit_);
+
+  return obj;
+}
+
+
+// -----------------------------------------------------------------------------
+// PageIterator
+
+bool PageIterator::has_next() {
+  return cur_page_ != stop_page_;
+}
+
+
+Page* PageIterator::next() {
+  ASSERT(has_next());
+  Page* result = cur_page_;
+  cur_page_ = cur_page_->next_page();
+  return result;
+}
+
+
+// -----------------------------------------------------------------------------
+// Page
+
+Page* Page::next_page() {
+  return MemoryAllocator::GetNextPage(this);
+}
+
+
+Address Page::AllocationTop() {
+  PagedSpace* owner = MemoryAllocator::PageOwner(this);
+  return owner->PageAllocationTop(this);
+}
+
+
+void Page::ClearRSet() {
+  // This method can be called in all rset states.
+  memset(RSetStart(), 0, kRSetEndOffset - kRSetStartOffset);
+}
+
+
+// Give an address a (32-bits):
+// | page address | words (6) | bit offset (5) | pointer alignment (2) |
+// The rset address is computed as:
+//    page_address + words * 4
+
+Address Page::ComputeRSetBitPosition(Address address, int offset,
+                                     uint32_t* bitmask) {
+  ASSERT(Page::is_rset_in_use());
+
+  Page* page = Page::FromAddress(address);
+  uint32_t bit_offset = ArithmeticShiftRight(page->Offset(address) + offset,
+                                             kObjectAlignmentBits);
+  *bitmask = 1 << (bit_offset % kBitsPerInt);
+
+  Address rset_address =
+      page->address() + (bit_offset / kBitsPerInt) * kIntSize;
+  // The remembered set address is either in the normal remembered set range
+  // of a page or else we have a large object page.
+  ASSERT((page->RSetStart() <= rset_address && rset_address < page->RSetEnd())
+         || page->IsLargeObjectPage());
+
+  if (rset_address >= page->RSetEnd()) {
+    // We have a large object page, and the remembered set address is actually
+    // past the end of the object.  The address of the remembered set in this
+    // case is the extra remembered set start address at the address of the
+    // end of the object:
+    //   (page->ObjectAreaStart() + object size)
+    // plus the offset of the computed remembered set address from the start
+    // of the object:
+    //   (rset_address - page->ObjectAreaStart()).
+    // Ie, we can just add the object size.
+    ASSERT(HeapObject::FromAddress(address)->IsFixedArray());
+    rset_address +=
+        FixedArray::SizeFor(Memory::int_at(page->ObjectAreaStart()
+                                           + Array::kLengthOffset));
+  }
+  return rset_address;
+}
+
+
+void Page::SetRSet(Address address, int offset) {
+  uint32_t bitmask = 0;
+  Address rset_address = ComputeRSetBitPosition(address, offset, &bitmask);
+  Memory::uint32_at(rset_address) |= bitmask;
+
+  ASSERT(IsRSetSet(address, offset));
+}
+
+
+// Clears the corresponding remembered set bit for a given address.
+void Page::UnsetRSet(Address address, int offset) {
+  uint32_t bitmask = 0;
+  Address rset_address = ComputeRSetBitPosition(address, offset, &bitmask);
+  Memory::uint32_at(rset_address) &= ~bitmask;
+
+  ASSERT(!IsRSetSet(address, offset));
+}
+
+
+bool Page::IsRSetSet(Address address, int offset) {
+  uint32_t bitmask = 0;
+  Address rset_address = ComputeRSetBitPosition(address, offset, &bitmask);
+  return (Memory::uint32_at(rset_address) & bitmask) != 0;
+}
+
+
+// -----------------------------------------------------------------------------
+// MemoryAllocator
+
+bool MemoryAllocator::IsValidChunk(int chunk_id) {
+  if (!IsValidChunkId(chunk_id)) return false;
+
+  ChunkInfo& c = chunks_[chunk_id];
+  return (c.address() != NULL) && (c.size() != 0) && (c.owner() != NULL);
+}
+
+
+bool MemoryAllocator::IsValidChunkId(int chunk_id) {
+  return (0 <= chunk_id) && (chunk_id < max_nof_chunks_);
+}
+
+
+bool MemoryAllocator::IsPageInSpace(Page* p, PagedSpace* space) {
+  ASSERT(p->is_valid());
+
+  int chunk_id = GetChunkId(p);
+  if (!IsValidChunkId(chunk_id)) return false;
+
+  ChunkInfo& c = chunks_[chunk_id];
+  return (c.address() <= p->address()) &&
+         (p->address() < c.address() + c.size()) &&
+         (space == c.owner());
+}
+
+
+Page* MemoryAllocator::GetNextPage(Page* p) {
+  ASSERT(p->is_valid());
+  int raw_addr = p->opaque_header & ~Page::kPageAlignmentMask;
+  return Page::FromAddress(AddressFrom<Address>(raw_addr));
+}
+
+
+int MemoryAllocator::GetChunkId(Page* p) {
+  ASSERT(p->is_valid());
+  return p->opaque_header & Page::kPageAlignmentMask;
+}
+
+
+void MemoryAllocator::SetNextPage(Page* prev, Page* next) {
+  ASSERT(prev->is_valid());
+  int chunk_id = prev->opaque_header & Page::kPageAlignmentMask;
+  ASSERT_PAGE_ALIGNED(next->address());
+  prev->opaque_header = OffsetFrom(next->address()) | chunk_id;
+}
+
+
+PagedSpace* MemoryAllocator::PageOwner(Page* page) {
+  int chunk_id = GetChunkId(page);
+  ASSERT(IsValidChunk(chunk_id));
+  return chunks_[chunk_id].owner();
+}
+
+
+bool MemoryAllocator::InInitialChunk(Address address) {
+  if (initial_chunk_ == NULL) return false;
+
+  Address start = static_cast<Address>(initial_chunk_->address());
+  return (start <= address) && (address < start + initial_chunk_->size());
+}
+
+
+#ifdef ENABLE_HEAP_PROTECTION
+
+void MemoryAllocator::Protect(Address start, size_t size) {
+  OS::Protect(start, size);
+}
+
+
+void MemoryAllocator::Unprotect(Address start,
+                                size_t size,
+                                Executability executable) {
+  OS::Unprotect(start, size, executable);
+}
+
+
+void MemoryAllocator::ProtectChunkFromPage(Page* page) {
+  int id = GetChunkId(page);
+  OS::Protect(chunks_[id].address(), chunks_[id].size());
+}
+
+
+void MemoryAllocator::UnprotectChunkFromPage(Page* page) {
+  int id = GetChunkId(page);
+  OS::Unprotect(chunks_[id].address(), chunks_[id].size(),
+                chunks_[id].owner()->executable() == EXECUTABLE);
+}
+
+#endif
+
+
+// --------------------------------------------------------------------------
+// PagedSpace
+
+bool PagedSpace::Contains(Address addr) {
+  Page* p = Page::FromAddress(addr);
+  ASSERT(p->is_valid());
+
+  return MemoryAllocator::IsPageInSpace(p, this);
+}
+
+
+// Try linear allocation in the page of alloc_info's allocation top.  Does
+// not contain slow case logic (eg, move to the next page or try free list
+// allocation) so it can be used by all the allocation functions and for all
+// the paged spaces.
+HeapObject* PagedSpace::AllocateLinearly(AllocationInfo* alloc_info,
+                                         int size_in_bytes) {
+  Address current_top = alloc_info->top;
+  Address new_top = current_top + size_in_bytes;
+  if (new_top > alloc_info->limit) return NULL;
+
+  alloc_info->top = new_top;
+  ASSERT(alloc_info->VerifyPagedAllocation());
+  accounting_stats_.AllocateBytes(size_in_bytes);
+  return HeapObject::FromAddress(current_top);
+}
+
+
+// Raw allocation.
+Object* PagedSpace::AllocateRaw(int size_in_bytes) {
+  ASSERT(HasBeenSetup());
+  ASSERT_OBJECT_SIZE(size_in_bytes);
+  HeapObject* object = AllocateLinearly(&allocation_info_, size_in_bytes);
+  if (object != NULL) return object;
+
+  object = SlowAllocateRaw(size_in_bytes);
+  if (object != NULL) return object;
+
+  return Failure::RetryAfterGC(size_in_bytes, identity());
+}
+
+
+// Reallocating (and promoting) objects during a compacting collection.
+Object* PagedSpace::MCAllocateRaw(int size_in_bytes) {
+  ASSERT(HasBeenSetup());
+  ASSERT_OBJECT_SIZE(size_in_bytes);
+  HeapObject* object = AllocateLinearly(&mc_forwarding_info_, size_in_bytes);
+  if (object != NULL) return object;
+
+  object = SlowMCAllocateRaw(size_in_bytes);
+  if (object != NULL) return object;
+
+  return Failure::RetryAfterGC(size_in_bytes, identity());
+}
+
+
+// -----------------------------------------------------------------------------
+// LargeObjectChunk
+
+HeapObject* LargeObjectChunk::GetObject() {
+  // Round the chunk address up to the nearest page-aligned address
+  // and return the heap object in that page.
+  Page* page = Page::FromAddress(RoundUp(address(), Page::kPageSize));
+  return HeapObject::FromAddress(page->ObjectAreaStart());
+}
+
+
+// -----------------------------------------------------------------------------
+// LargeObjectSpace
+
+int LargeObjectSpace::ExtraRSetBytesFor(int object_size) {
+  int extra_rset_bits =
+      RoundUp((object_size - Page::kObjectAreaSize) / kPointerSize,
+              kBitsPerInt);
+  return extra_rset_bits / kBitsPerByte;
+}
+
+
+Object* NewSpace::AllocateRawInternal(int size_in_bytes,
+                                      AllocationInfo* alloc_info) {
+  Address new_top = alloc_info->top + size_in_bytes;
+  if (new_top > alloc_info->limit) return Failure::RetryAfterGC(size_in_bytes);
+
+  Object* obj = HeapObject::FromAddress(alloc_info->top);
+  alloc_info->top = new_top;
+#ifdef DEBUG
+  SemiSpace* space =
+      (alloc_info == &allocation_info_) ? &to_space_ : &from_space_;
+  ASSERT(space->low() <= alloc_info->top
+         && alloc_info->top <= space->high()
+         && alloc_info->limit == space->high());
+#endif
+  return obj;
+}
+
+} }  // namespace v8::internal
+
+#endif  // V8_SPACES_INL_H_
diff --git a/deps/v8/src/spaces.cc b/deps/v8/src/spaces.cc
new file mode 100644
index 0000000..ea40d52
--- /dev/null
+++ b/deps/v8/src/spaces.cc
@@ -0,0 +1,2599 @@
+// 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.
+
+#include "v8.h"
+
+#include "macro-assembler.h"
+#include "mark-compact.h"
+#include "platform.h"
+
+namespace v8 { namespace internal {
+
+// For contiguous spaces, top should be in the space (or at the end) and limit
+// should be the end of the space.
+#define ASSERT_SEMISPACE_ALLOCATION_INFO(info, space) \
+  ASSERT((space).low() <= (info).top                 \
+         && (info).top <= (space).high()             \
+         && (info).limit == (space).high())
+
+
+// ----------------------------------------------------------------------------
+// HeapObjectIterator
+
+HeapObjectIterator::HeapObjectIterator(PagedSpace* space) {
+  Initialize(space->bottom(), space->top(), NULL);
+}
+
+
+HeapObjectIterator::HeapObjectIterator(PagedSpace* space,
+                                       HeapObjectCallback size_func) {
+  Initialize(space->bottom(), space->top(), size_func);
+}
+
+
+HeapObjectIterator::HeapObjectIterator(PagedSpace* space, Address start) {
+  Initialize(start, space->top(), NULL);
+}
+
+
+HeapObjectIterator::HeapObjectIterator(PagedSpace* space, Address start,
+                                       HeapObjectCallback size_func) {
+  Initialize(start, space->top(), size_func);
+}
+
+
+void HeapObjectIterator::Initialize(Address cur, Address end,
+                                    HeapObjectCallback size_f) {
+  cur_addr_ = cur;
+  end_addr_ = end;
+  end_page_ = Page::FromAllocationTop(end);
+  size_func_ = size_f;
+  Page* p = Page::FromAllocationTop(cur_addr_);
+  cur_limit_ = (p == end_page_) ? end_addr_ : p->AllocationTop();
+
+#ifdef DEBUG
+  Verify();
+#endif
+}
+
+
+bool HeapObjectIterator::HasNextInNextPage() {
+  if (cur_addr_ == end_addr_) return false;
+
+  Page* cur_page = Page::FromAllocationTop(cur_addr_);
+  cur_page = cur_page->next_page();
+  ASSERT(cur_page->is_valid());
+
+  cur_addr_ = cur_page->ObjectAreaStart();
+  cur_limit_ = (cur_page == end_page_) ? end_addr_ : cur_page->AllocationTop();
+
+  ASSERT(cur_addr_ < cur_limit_);
+#ifdef DEBUG
+  Verify();
+#endif
+  return true;
+}
+
+
+#ifdef DEBUG
+void HeapObjectIterator::Verify() {
+  Page* p = Page::FromAllocationTop(cur_addr_);
+  ASSERT(p == Page::FromAllocationTop(cur_limit_));
+  ASSERT(p->Offset(cur_addr_) <= p->Offset(cur_limit_));
+}
+#endif
+
+
+// -----------------------------------------------------------------------------
+// PageIterator
+
+PageIterator::PageIterator(PagedSpace* space, Mode mode) {
+  cur_page_ = space->first_page_;
+  switch (mode) {
+    case PAGES_IN_USE:
+      stop_page_ = space->AllocationTopPage()->next_page();
+      break;
+    case PAGES_USED_BY_MC:
+      stop_page_ = space->MCRelocationTopPage()->next_page();
+      break;
+    case ALL_PAGES:
+      stop_page_ = Page::FromAddress(NULL);
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+// -----------------------------------------------------------------------------
+// Page
+
+#ifdef DEBUG
+Page::RSetState Page::rset_state_ = Page::IN_USE;
+#endif
+
+// -----------------------------------------------------------------------------
+// MemoryAllocator
+//
+int MemoryAllocator::capacity_   = 0;
+int MemoryAllocator::size_       = 0;
+
+VirtualMemory* MemoryAllocator::initial_chunk_ = NULL;
+
+// 270 is an estimate based on the static default heap size of a pair of 256K
+// semispaces and a 64M old generation.
+const int kEstimatedNumberOfChunks = 270;
+List<MemoryAllocator::ChunkInfo> MemoryAllocator::chunks_(
+    kEstimatedNumberOfChunks);
+List<int> MemoryAllocator::free_chunk_ids_(kEstimatedNumberOfChunks);
+int MemoryAllocator::max_nof_chunks_ = 0;
+int MemoryAllocator::top_ = 0;
+
+
+void MemoryAllocator::Push(int free_chunk_id) {
+  ASSERT(max_nof_chunks_ > 0);
+  ASSERT(top_ < max_nof_chunks_);
+  free_chunk_ids_[top_++] = free_chunk_id;
+}
+
+
+int MemoryAllocator::Pop() {
+  ASSERT(top_ > 0);
+  return free_chunk_ids_[--top_];
+}
+
+
+bool MemoryAllocator::Setup(int capacity) {
+  capacity_ = RoundUp(capacity, Page::kPageSize);
+
+  // Over-estimate the size of chunks_ array.  It assumes the expansion of old
+  // space is always in the unit of a chunk (kChunkSize) except the last
+  // expansion.
+  //
+  // Due to alignment, allocated space might be one page less than required
+  // number (kPagesPerChunk) of pages for old spaces.
+  //
+  // Reserve two chunk ids for semispaces, one for map space, one for old
+  // space, and one for code space.
+  max_nof_chunks_ = (capacity_ / (kChunkSize - Page::kPageSize)) + 5;
+  if (max_nof_chunks_ > kMaxNofChunks) return false;
+
+  size_ = 0;
+  ChunkInfo info;  // uninitialized element.
+  for (int i = max_nof_chunks_ - 1; i >= 0; i--) {
+    chunks_.Add(info);
+    free_chunk_ids_.Add(i);
+  }
+  top_ = max_nof_chunks_;
+  return true;
+}
+
+
+void MemoryAllocator::TearDown() {
+  for (int i = 0; i < max_nof_chunks_; i++) {
+    if (chunks_[i].address() != NULL) DeleteChunk(i);
+  }
+  chunks_.Clear();
+  free_chunk_ids_.Clear();
+
+  if (initial_chunk_ != NULL) {
+    LOG(DeleteEvent("InitialChunk", initial_chunk_->address()));
+    delete initial_chunk_;
+    initial_chunk_ = NULL;
+  }
+
+  ASSERT(top_ == max_nof_chunks_);  // all chunks are free
+  top_ = 0;
+  capacity_ = 0;
+  size_ = 0;
+  max_nof_chunks_ = 0;
+}
+
+
+void* MemoryAllocator::AllocateRawMemory(const size_t requested,
+                                         size_t* allocated,
+                                         Executability executable) {
+  if (size_ + static_cast<int>(requested) > capacity_) return NULL;
+
+  void* mem = OS::Allocate(requested, allocated, executable == EXECUTABLE);
+  int alloced = *allocated;
+  size_ += alloced;
+  Counters::memory_allocated.Increment(alloced);
+  return mem;
+}
+
+
+void MemoryAllocator::FreeRawMemory(void* mem, size_t length) {
+  OS::Free(mem, length);
+  Counters::memory_allocated.Decrement(length);
+  size_ -= length;
+  ASSERT(size_ >= 0);
+}
+
+
+void* MemoryAllocator::ReserveInitialChunk(const size_t requested) {
+  ASSERT(initial_chunk_ == NULL);
+
+  initial_chunk_ = new VirtualMemory(requested);
+  CHECK(initial_chunk_ != NULL);
+  if (!initial_chunk_->IsReserved()) {
+    delete initial_chunk_;
+    initial_chunk_ = NULL;
+    return NULL;
+  }
+
+  // We are sure that we have mapped a block of requested addresses.
+  ASSERT(initial_chunk_->size() == requested);
+  LOG(NewEvent("InitialChunk", initial_chunk_->address(), requested));
+  size_ += requested;
+  return initial_chunk_->address();
+}
+
+
+static int PagesInChunk(Address start, size_t size) {
+  // The first page starts on the first page-aligned address from start onward
+  // and the last page ends on the last page-aligned address before
+  // start+size.  Page::kPageSize is a power of two so we can divide by
+  // shifting.
+  return (RoundDown(start + size, Page::kPageSize)
+          - RoundUp(start, Page::kPageSize)) >> Page::kPageSizeBits;
+}
+
+
+Page* MemoryAllocator::AllocatePages(int requested_pages, int* allocated_pages,
+                                     PagedSpace* owner) {
+  if (requested_pages <= 0) return Page::FromAddress(NULL);
+  size_t chunk_size = requested_pages * Page::kPageSize;
+
+  // There is not enough space to guarantee the desired number pages can be
+  // allocated.
+  if (size_ + static_cast<int>(chunk_size) > capacity_) {
+    // Request as many pages as we can.
+    chunk_size = capacity_ - size_;
+    requested_pages = chunk_size >> Page::kPageSizeBits;
+
+    if (requested_pages <= 0) return Page::FromAddress(NULL);
+  }
+  void* chunk = AllocateRawMemory(chunk_size, &chunk_size, owner->executable());
+  if (chunk == NULL) return Page::FromAddress(NULL);
+  LOG(NewEvent("PagedChunk", chunk, chunk_size));
+
+  *allocated_pages = PagesInChunk(static_cast<Address>(chunk), chunk_size);
+  if (*allocated_pages == 0) {
+    FreeRawMemory(chunk, chunk_size);
+    LOG(DeleteEvent("PagedChunk", chunk));
+    return Page::FromAddress(NULL);
+  }
+
+  int chunk_id = Pop();
+  chunks_[chunk_id].init(static_cast<Address>(chunk), chunk_size, owner);
+
+  return InitializePagesInChunk(chunk_id, *allocated_pages, owner);
+}
+
+
+Page* MemoryAllocator::CommitPages(Address start, size_t size,
+                                   PagedSpace* owner, int* num_pages) {
+  ASSERT(start != NULL);
+  *num_pages = PagesInChunk(start, size);
+  ASSERT(*num_pages > 0);
+  ASSERT(initial_chunk_ != NULL);
+  ASSERT(InInitialChunk(start));
+  ASSERT(InInitialChunk(start + size - 1));
+  if (!initial_chunk_->Commit(start, size, owner->executable() == EXECUTABLE)) {
+    return Page::FromAddress(NULL);
+  }
+  Counters::memory_allocated.Increment(size);
+
+  // So long as we correctly overestimated the number of chunks we should not
+  // run out of chunk ids.
+  CHECK(!OutOfChunkIds());
+  int chunk_id = Pop();
+  chunks_[chunk_id].init(start, size, owner);
+  return InitializePagesInChunk(chunk_id, *num_pages, owner);
+}
+
+
+bool MemoryAllocator::CommitBlock(Address start,
+                                  size_t size,
+                                  Executability executable) {
+  ASSERT(start != NULL);
+  ASSERT(size > 0);
+  ASSERT(initial_chunk_ != NULL);
+  ASSERT(InInitialChunk(start));
+  ASSERT(InInitialChunk(start + size - 1));
+
+  if (!initial_chunk_->Commit(start, size, executable)) return false;
+  Counters::memory_allocated.Increment(size);
+  return true;
+}
+
+
+Page* MemoryAllocator::InitializePagesInChunk(int chunk_id, int pages_in_chunk,
+                                              PagedSpace* owner) {
+  ASSERT(IsValidChunk(chunk_id));
+  ASSERT(pages_in_chunk > 0);
+
+  Address chunk_start = chunks_[chunk_id].address();
+
+  Address low = RoundUp(chunk_start, Page::kPageSize);
+
+#ifdef DEBUG
+  size_t chunk_size = chunks_[chunk_id].size();
+  Address high = RoundDown(chunk_start + chunk_size, Page::kPageSize);
+  ASSERT(pages_in_chunk <=
+        ((OffsetFrom(high) - OffsetFrom(low)) / Page::kPageSize));
+#endif
+
+  Address page_addr = low;
+  for (int i = 0; i < pages_in_chunk; i++) {
+    Page* p = Page::FromAddress(page_addr);
+    p->opaque_header = OffsetFrom(page_addr + Page::kPageSize) | chunk_id;
+    p->is_normal_page = 1;
+    page_addr += Page::kPageSize;
+  }
+
+  // Set the next page of the last page to 0.
+  Page* last_page = Page::FromAddress(page_addr - Page::kPageSize);
+  last_page->opaque_header = OffsetFrom(0) | chunk_id;
+
+  return Page::FromAddress(low);
+}
+
+
+Page* MemoryAllocator::FreePages(Page* p) {
+  if (!p->is_valid()) return p;
+
+  // Find the first page in the same chunk as 'p'
+  Page* first_page = FindFirstPageInSameChunk(p);
+  Page* page_to_return = Page::FromAddress(NULL);
+
+  if (p != first_page) {
+    // Find the last page in the same chunk as 'prev'.
+    Page* last_page = FindLastPageInSameChunk(p);
+    first_page = GetNextPage(last_page);  // first page in next chunk
+
+    // set the next_page of last_page to NULL
+    SetNextPage(last_page, Page::FromAddress(NULL));
+    page_to_return = p;  // return 'p' when exiting
+  }
+
+  while (first_page->is_valid()) {
+    int chunk_id = GetChunkId(first_page);
+    ASSERT(IsValidChunk(chunk_id));
+
+    // Find the first page of the next chunk before deleting this chunk.
+    first_page = GetNextPage(FindLastPageInSameChunk(first_page));
+
+    // Free the current chunk.
+    DeleteChunk(chunk_id);
+  }
+
+  return page_to_return;
+}
+
+
+void MemoryAllocator::DeleteChunk(int chunk_id) {
+  ASSERT(IsValidChunk(chunk_id));
+
+  ChunkInfo& c = chunks_[chunk_id];
+
+  // We cannot free a chunk contained in the initial chunk because it was not
+  // allocated with AllocateRawMemory.  Instead we uncommit the virtual
+  // memory.
+  if (InInitialChunk(c.address())) {
+    // TODO(1240712): VirtualMemory::Uncommit has a return value which
+    // is ignored here.
+    initial_chunk_->Uncommit(c.address(), c.size());
+    Counters::memory_allocated.Decrement(c.size());
+  } else {
+    LOG(DeleteEvent("PagedChunk", c.address()));
+    FreeRawMemory(c.address(), c.size());
+  }
+  c.init(NULL, 0, NULL);
+  Push(chunk_id);
+}
+
+
+Page* MemoryAllocator::FindFirstPageInSameChunk(Page* p) {
+  int chunk_id = GetChunkId(p);
+  ASSERT(IsValidChunk(chunk_id));
+
+  Address low = RoundUp(chunks_[chunk_id].address(), Page::kPageSize);
+  return Page::FromAddress(low);
+}
+
+
+Page* MemoryAllocator::FindLastPageInSameChunk(Page* p) {
+  int chunk_id = GetChunkId(p);
+  ASSERT(IsValidChunk(chunk_id));
+
+  Address chunk_start = chunks_[chunk_id].address();
+  size_t chunk_size = chunks_[chunk_id].size();
+
+  Address high = RoundDown(chunk_start + chunk_size, Page::kPageSize);
+  ASSERT(chunk_start <= p->address() && p->address() < high);
+
+  return Page::FromAddress(high - Page::kPageSize);
+}
+
+
+#ifdef DEBUG
+void MemoryAllocator::ReportStatistics() {
+  float pct = static_cast<float>(capacity_ - size_) / capacity_;
+  PrintF("  capacity: %d, used: %d, available: %%%d\n\n",
+         capacity_, size_, static_cast<int>(pct*100));
+}
+#endif
+
+
+// -----------------------------------------------------------------------------
+// PagedSpace implementation
+
+PagedSpace::PagedSpace(int max_capacity,
+                       AllocationSpace id,
+                       Executability executable)
+    : Space(id, executable) {
+  max_capacity_ = (RoundDown(max_capacity, Page::kPageSize) / Page::kPageSize)
+                  * Page::kObjectAreaSize;
+  accounting_stats_.Clear();
+
+  allocation_info_.top = NULL;
+  allocation_info_.limit = NULL;
+
+  mc_forwarding_info_.top = NULL;
+  mc_forwarding_info_.limit = NULL;
+}
+
+
+bool PagedSpace::Setup(Address start, size_t size) {
+  if (HasBeenSetup()) return false;
+
+  int num_pages = 0;
+  // Try to use the virtual memory range passed to us.  If it is too small to
+  // contain at least one page, ignore it and allocate instead.
+  int pages_in_chunk = PagesInChunk(start, size);
+  if (pages_in_chunk > 0) {
+    first_page_ = MemoryAllocator::CommitPages(RoundUp(start, Page::kPageSize),
+                                               Page::kPageSize * pages_in_chunk,
+                                               this, &num_pages);
+  } else {
+    int requested_pages = Min(MemoryAllocator::kPagesPerChunk,
+                              max_capacity_ / Page::kObjectAreaSize);
+    first_page_ =
+        MemoryAllocator::AllocatePages(requested_pages, &num_pages, this);
+    if (!first_page_->is_valid()) return false;
+  }
+
+  // We are sure that the first page is valid and that we have at least one
+  // page.
+  ASSERT(first_page_->is_valid());
+  ASSERT(num_pages > 0);
+  accounting_stats_.ExpandSpace(num_pages * Page::kObjectAreaSize);
+  ASSERT(Capacity() <= max_capacity_);
+
+  for (Page* p = first_page_; p->is_valid(); p = p->next_page()) {
+    p->ClearRSet();
+  }
+
+  // Use first_page_ for allocation.
+  SetAllocationInfo(&allocation_info_, first_page_);
+
+  return true;
+}
+
+
+bool PagedSpace::HasBeenSetup() {
+  return (Capacity() > 0);
+}
+
+
+void PagedSpace::TearDown() {
+  first_page_ = MemoryAllocator::FreePages(first_page_);
+  ASSERT(!first_page_->is_valid());
+
+  accounting_stats_.Clear();
+}
+
+
+#ifdef ENABLE_HEAP_PROTECTION
+
+void PagedSpace::Protect() {
+  Page* page = first_page_;
+  while (page->is_valid()) {
+    MemoryAllocator::ProtectChunkFromPage(page);
+    page = MemoryAllocator::FindLastPageInSameChunk(page)->next_page();
+  }
+}
+
+
+void PagedSpace::Unprotect() {
+  Page* page = first_page_;
+  while (page->is_valid()) {
+    MemoryAllocator::UnprotectChunkFromPage(page);
+    page = MemoryAllocator::FindLastPageInSameChunk(page)->next_page();
+  }
+}
+
+#endif
+
+
+void PagedSpace::ClearRSet() {
+  PageIterator it(this, PageIterator::ALL_PAGES);
+  while (it.has_next()) {
+    it.next()->ClearRSet();
+  }
+}
+
+
+Object* PagedSpace::FindObject(Address addr) {
+  // Note: this function can only be called before or after mark-compact GC
+  // because it accesses map pointers.
+  ASSERT(!MarkCompactCollector::in_use());
+
+  if (!Contains(addr)) return Failure::Exception();
+
+  Page* p = Page::FromAddress(addr);
+  ASSERT(IsUsed(p));
+  Address cur = p->ObjectAreaStart();
+  Address end = p->AllocationTop();
+  while (cur < end) {
+    HeapObject* obj = HeapObject::FromAddress(cur);
+    Address next = cur + obj->Size();
+    if ((cur <= addr) && (addr < next)) return obj;
+    cur = next;
+  }
+
+  UNREACHABLE();
+  return Failure::Exception();
+}
+
+
+bool PagedSpace::IsUsed(Page* page) {
+  PageIterator it(this, PageIterator::PAGES_IN_USE);
+  while (it.has_next()) {
+    if (page == it.next()) return true;
+  }
+  return false;
+}
+
+
+void PagedSpace::SetAllocationInfo(AllocationInfo* alloc_info, Page* p) {
+  alloc_info->top = p->ObjectAreaStart();
+  alloc_info->limit = p->ObjectAreaEnd();
+  ASSERT(alloc_info->VerifyPagedAllocation());
+}
+
+
+void PagedSpace::MCResetRelocationInfo() {
+  // Set page indexes.
+  int i = 0;
+  PageIterator it(this, PageIterator::ALL_PAGES);
+  while (it.has_next()) {
+    Page* p = it.next();
+    p->mc_page_index = i++;
+  }
+
+  // Set mc_forwarding_info_ to the first page in the space.
+  SetAllocationInfo(&mc_forwarding_info_, first_page_);
+  // All the bytes in the space are 'available'.  We will rediscover
+  // allocated and wasted bytes during GC.
+  accounting_stats_.Reset();
+}
+
+
+int PagedSpace::MCSpaceOffsetForAddress(Address addr) {
+#ifdef DEBUG
+  // The Contains function considers the address at the beginning of a
+  // page in the page, MCSpaceOffsetForAddress considers it is in the
+  // previous page.
+  if (Page::IsAlignedToPageSize(addr)) {
+    ASSERT(Contains(addr - kPointerSize));
+  } else {
+    ASSERT(Contains(addr));
+  }
+#endif
+
+  // If addr is at the end of a page, it belongs to previous page
+  Page* p = Page::IsAlignedToPageSize(addr)
+            ? Page::FromAllocationTop(addr)
+            : Page::FromAddress(addr);
+  int index = p->mc_page_index;
+  return (index * Page::kPageSize) + p->Offset(addr);
+}
+
+
+// Slow case for reallocating and promoting objects during a compacting
+// collection.  This function is not space-specific.
+HeapObject* PagedSpace::SlowMCAllocateRaw(int size_in_bytes) {
+  Page* current_page = TopPageOf(mc_forwarding_info_);
+  if (!current_page->next_page()->is_valid()) {
+    if (!Expand(current_page)) {
+      return NULL;
+    }
+  }
+
+  // There are surely more pages in the space now.
+  ASSERT(current_page->next_page()->is_valid());
+  // We do not add the top of page block for current page to the space's
+  // free list---the block may contain live objects so we cannot write
+  // bookkeeping information to it.  Instead, we will recover top of page
+  // blocks when we move objects to their new locations.
+  //
+  // We do however write the allocation pointer to the page.  The encoding
+  // of forwarding addresses is as an offset in terms of live bytes, so we
+  // need quick access to the allocation top of each page to decode
+  // forwarding addresses.
+  current_page->mc_relocation_top = mc_forwarding_info_.top;
+  SetAllocationInfo(&mc_forwarding_info_, current_page->next_page());
+  return AllocateLinearly(&mc_forwarding_info_, size_in_bytes);
+}
+
+
+bool PagedSpace::Expand(Page* last_page) {
+  ASSERT(max_capacity_ % Page::kObjectAreaSize == 0);
+  ASSERT(Capacity() % Page::kObjectAreaSize == 0);
+
+  if (Capacity() == max_capacity_) return false;
+
+  ASSERT(Capacity() < max_capacity_);
+  // Last page must be valid and its next page is invalid.
+  ASSERT(last_page->is_valid() && !last_page->next_page()->is_valid());
+
+  int available_pages = (max_capacity_ - Capacity()) / Page::kObjectAreaSize;
+  if (available_pages <= 0) return false;
+
+  int desired_pages = Min(available_pages, MemoryAllocator::kPagesPerChunk);
+  Page* p = MemoryAllocator::AllocatePages(desired_pages, &desired_pages, this);
+  if (!p->is_valid()) return false;
+
+  accounting_stats_.ExpandSpace(desired_pages * Page::kObjectAreaSize);
+  ASSERT(Capacity() <= max_capacity_);
+
+  MemoryAllocator::SetNextPage(last_page, p);
+
+  // Clear remembered set of new pages.
+  while (p->is_valid()) {
+    p->ClearRSet();
+    p = p->next_page();
+  }
+
+  return true;
+}
+
+
+#ifdef DEBUG
+int PagedSpace::CountTotalPages() {
+  int count = 0;
+  for (Page* p = first_page_; p->is_valid(); p = p->next_page()) {
+    count++;
+  }
+  return count;
+}
+#endif
+
+
+void PagedSpace::Shrink() {
+  // Release half of free pages.
+  Page* top_page = AllocationTopPage();
+  ASSERT(top_page->is_valid());
+
+  // Loop over the pages from the top page to the end of the space to count
+  // the number of pages to keep and find the last page to keep.
+  int free_pages = 0;
+  int pages_to_keep = 0;  // Of the free pages.
+  Page* last_page_to_keep = top_page;
+  Page* current_page = top_page->next_page();
+  // Loop over the pages to the end of the space.
+  while (current_page->is_valid()) {
+    // Advance last_page_to_keep every other step to end up at the midpoint.
+    if ((free_pages & 0x1) == 1) {
+      pages_to_keep++;
+      last_page_to_keep = last_page_to_keep->next_page();
+    }
+    free_pages++;
+    current_page = current_page->next_page();
+  }
+
+  // Free pages after last_page_to_keep, and adjust the next_page link.
+  Page* p = MemoryAllocator::FreePages(last_page_to_keep->next_page());
+  MemoryAllocator::SetNextPage(last_page_to_keep, p);
+
+  // Since pages are only freed in whole chunks, we may have kept more than
+  // pages_to_keep.
+  while (p->is_valid()) {
+    pages_to_keep++;
+    p = p->next_page();
+  }
+
+  // The difference between free_pages and pages_to_keep is the number of
+  // pages actually freed.
+  ASSERT(pages_to_keep <= free_pages);
+  int bytes_freed = (free_pages - pages_to_keep) * Page::kObjectAreaSize;
+  accounting_stats_.ShrinkSpace(bytes_freed);
+
+  ASSERT(Capacity() == CountTotalPages() * Page::kObjectAreaSize);
+}
+
+
+bool PagedSpace::EnsureCapacity(int capacity) {
+  if (Capacity() >= capacity) return true;
+
+  // Start from the allocation top and loop to the last page in the space.
+  Page* last_page = AllocationTopPage();
+  Page* next_page = last_page->next_page();
+  while (next_page->is_valid()) {
+    last_page = MemoryAllocator::FindLastPageInSameChunk(next_page);
+    next_page = last_page->next_page();
+  }
+
+  // Expand the space until it has the required capacity or expansion fails.
+  do {
+    if (!Expand(last_page)) return false;
+    ASSERT(last_page->next_page()->is_valid());
+    last_page =
+        MemoryAllocator::FindLastPageInSameChunk(last_page->next_page());
+  } while (Capacity() < capacity);
+
+  return true;
+}
+
+
+#ifdef DEBUG
+void PagedSpace::Print() { }
+#endif
+
+
+// -----------------------------------------------------------------------------
+// NewSpace implementation
+
+
+bool NewSpace::Setup(Address start, int size) {
+  // Setup new space based on the preallocated memory block defined by
+  // start and size. The provided space is divided into two semi-spaces.
+  // To support fast containment testing in the new space, the size of
+  // this chunk must be a power of two and it must be aligned to its size.
+  int initial_semispace_capacity = Heap::InitialSemiSpaceSize();
+  int maximum_semispace_capacity = Heap::SemiSpaceSize();
+
+  ASSERT(initial_semispace_capacity <= maximum_semispace_capacity);
+  ASSERT(IsPowerOf2(maximum_semispace_capacity));
+  maximum_capacity_ = maximum_semispace_capacity;
+  capacity_ = initial_semispace_capacity;
+
+  // Allocate and setup the histogram arrays if necessary.
+#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
+  allocated_histogram_ = NewArray<HistogramInfo>(LAST_TYPE + 1);
+  promoted_histogram_ = NewArray<HistogramInfo>(LAST_TYPE + 1);
+
+#define SET_NAME(name) allocated_histogram_[name].set_name(#name); \
+                       promoted_histogram_[name].set_name(#name);
+  INSTANCE_TYPE_LIST(SET_NAME)
+#undef SET_NAME
+#endif
+
+  ASSERT(size == 2 * maximum_capacity_);
+  ASSERT(IsAddressAligned(start, size, 0));
+
+  if (!to_space_.Setup(start, capacity_, maximum_capacity_)) {
+    return false;
+  }
+  if (!from_space_.Setup(start + maximum_capacity_,
+                         capacity_,
+                         maximum_capacity_)) {
+    return false;
+  }
+
+  start_ = start;
+  address_mask_ = ~(size - 1);
+  object_mask_ = address_mask_ | kHeapObjectTag;
+  object_expected_ = reinterpret_cast<uint32_t>(start) | kHeapObjectTag;
+
+  allocation_info_.top = to_space_.low();
+  allocation_info_.limit = to_space_.high();
+  mc_forwarding_info_.top = NULL;
+  mc_forwarding_info_.limit = NULL;
+
+  ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_);
+  return true;
+}
+
+
+void NewSpace::TearDown() {
+#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
+  if (allocated_histogram_) {
+    DeleteArray(allocated_histogram_);
+    allocated_histogram_ = NULL;
+  }
+  if (promoted_histogram_) {
+    DeleteArray(promoted_histogram_);
+    promoted_histogram_ = NULL;
+  }
+#endif
+
+  start_ = NULL;
+  capacity_ = 0;
+  allocation_info_.top = NULL;
+  allocation_info_.limit = NULL;
+  mc_forwarding_info_.top = NULL;
+  mc_forwarding_info_.limit = NULL;
+
+  to_space_.TearDown();
+  from_space_.TearDown();
+}
+
+
+#ifdef ENABLE_HEAP_PROTECTION
+
+void NewSpace::Protect() {
+  MemoryAllocator::Protect(ToSpaceLow(), Capacity());
+  MemoryAllocator::Protect(FromSpaceLow(), Capacity());
+}
+
+
+void NewSpace::Unprotect() {
+  MemoryAllocator::Unprotect(ToSpaceLow(), Capacity(),
+                             to_space_.executable());
+  MemoryAllocator::Unprotect(FromSpaceLow(), Capacity(),
+                             from_space_.executable());
+}
+
+#endif
+
+
+void NewSpace::Flip() {
+  SemiSpace tmp = from_space_;
+  from_space_ = to_space_;
+  to_space_ = tmp;
+}
+
+
+bool NewSpace::Double() {
+  ASSERT(capacity_ <= maximum_capacity_ / 2);
+  // TODO(1240712): Failure to double the from space can result in
+  // semispaces of different sizes.  In the event of that failure, the
+  // to space doubling should be rolled back before returning false.
+  if (!to_space_.Double() || !from_space_.Double()) return false;
+  capacity_ *= 2;
+  allocation_info_.limit = to_space_.high();
+  ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_);
+  return true;
+}
+
+
+void NewSpace::ResetAllocationInfo() {
+  allocation_info_.top = to_space_.low();
+  allocation_info_.limit = to_space_.high();
+  ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_);
+}
+
+
+void NewSpace::MCResetRelocationInfo() {
+  mc_forwarding_info_.top = from_space_.low();
+  mc_forwarding_info_.limit = from_space_.high();
+  ASSERT_SEMISPACE_ALLOCATION_INFO(mc_forwarding_info_, from_space_);
+}
+
+
+void NewSpace::MCCommitRelocationInfo() {
+  // Assumes that the spaces have been flipped so that mc_forwarding_info_ is
+  // valid allocation info for the to space.
+  allocation_info_.top = mc_forwarding_info_.top;
+  allocation_info_.limit = to_space_.high();
+  ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_);
+}
+
+
+#ifdef DEBUG
+// We do not use the SemispaceIterator because verification doesn't assume
+// that it works (it depends on the invariants we are checking).
+void NewSpace::Verify() {
+  // The allocation pointer should be in the space or at the very end.
+  ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_);
+
+  // There should be objects packed in from the low address up to the
+  // allocation pointer.
+  Address current = to_space_.low();
+  while (current < top()) {
+    HeapObject* object = HeapObject::FromAddress(current);
+
+    // The first word should be a map, and we expect all map pointers to
+    // be in map space.
+    Map* map = object->map();
+    ASSERT(map->IsMap());
+    ASSERT(Heap::map_space()->Contains(map));
+
+    // The object should not be code or a map.
+    ASSERT(!object->IsMap());
+    ASSERT(!object->IsCode());
+
+    // The object itself should look OK.
+    object->Verify();
+
+    // All the interior pointers should be contained in the heap.
+    VerifyPointersVisitor visitor;
+    int size = object->Size();
+    object->IterateBody(map->instance_type(), size, &visitor);
+
+    current += size;
+  }
+
+  // The allocation pointer should not be in the middle of an object.
+  ASSERT(current == top());
+}
+#endif
+
+
+// -----------------------------------------------------------------------------
+// SemiSpace implementation
+
+bool SemiSpace::Setup(Address start,
+                      int initial_capacity,
+                      int maximum_capacity) {
+  // Creates a space in the young generation. The constructor does not
+  // allocate memory from the OS.  A SemiSpace is given a contiguous chunk of
+  // memory of size 'capacity' when set up, and does not grow or shrink
+  // otherwise.  In the mark-compact collector, the memory region of the from
+  // space is used as the marking stack. It requires contiguous memory
+  // addresses.
+  capacity_ = initial_capacity;
+  maximum_capacity_ = maximum_capacity;
+
+  if (!MemoryAllocator::CommitBlock(start, capacity_, executable())) {
+    return false;
+  }
+
+  start_ = start;
+  address_mask_ = ~(maximum_capacity - 1);
+  object_mask_ = address_mask_ | kHeapObjectTag;
+  object_expected_ = reinterpret_cast<uint32_t>(start) | kHeapObjectTag;
+
+  age_mark_ = start_;
+  return true;
+}
+
+
+void SemiSpace::TearDown() {
+  start_ = NULL;
+  capacity_ = 0;
+}
+
+
+bool SemiSpace::Double() {
+  if (!MemoryAllocator::CommitBlock(high(), capacity_, executable())) {
+    return false;
+  }
+  capacity_ *= 2;
+  return true;
+}
+
+
+#ifdef DEBUG
+void SemiSpace::Print() { }
+
+
+void SemiSpace::Verify() { }
+#endif
+
+
+// -----------------------------------------------------------------------------
+// SemiSpaceIterator implementation.
+SemiSpaceIterator::SemiSpaceIterator(NewSpace* space) {
+  Initialize(space, space->bottom(), space->top(), NULL);
+}
+
+
+SemiSpaceIterator::SemiSpaceIterator(NewSpace* space,
+                                     HeapObjectCallback size_func) {
+  Initialize(space, space->bottom(), space->top(), size_func);
+}
+
+
+SemiSpaceIterator::SemiSpaceIterator(NewSpace* space, Address start) {
+  Initialize(space, start, space->top(), NULL);
+}
+
+
+void SemiSpaceIterator::Initialize(NewSpace* space, Address start,
+                                   Address end,
+                                   HeapObjectCallback size_func) {
+  ASSERT(space->ToSpaceContains(start));
+  ASSERT(space->ToSpaceLow() <= end
+         && end <= space->ToSpaceHigh());
+  space_ = &space->to_space_;
+  current_ = start;
+  limit_ = end;
+  size_func_ = size_func;
+}
+
+
+#ifdef DEBUG
+// A static array of histogram info for each type.
+static HistogramInfo heap_histograms[LAST_TYPE+1];
+static JSObject::SpillInformation js_spill_information;
+
+// heap_histograms is shared, always clear it before using it.
+static void ClearHistograms() {
+  // We reset the name each time, though it hasn't changed.
+#define DEF_TYPE_NAME(name) heap_histograms[name].set_name(#name);
+  INSTANCE_TYPE_LIST(DEF_TYPE_NAME)
+#undef DEF_TYPE_NAME
+
+#define CLEAR_HISTOGRAM(name) heap_histograms[name].clear();
+  INSTANCE_TYPE_LIST(CLEAR_HISTOGRAM)
+#undef CLEAR_HISTOGRAM
+
+  js_spill_information.Clear();
+}
+
+
+static int code_kind_statistics[Code::NUMBER_OF_KINDS];
+
+
+static void ClearCodeKindStatistics() {
+  for (int i = 0; i < Code::NUMBER_OF_KINDS; i++) {
+    code_kind_statistics[i] = 0;
+  }
+}
+
+
+static void ReportCodeKindStatistics() {
+  const char* table[Code::NUMBER_OF_KINDS];
+
+#define CASE(name)                            \
+  case Code::name: table[Code::name] = #name; \
+  break
+
+  for (int i = 0; i < Code::NUMBER_OF_KINDS; i++) {
+    switch (static_cast<Code::Kind>(i)) {
+      CASE(FUNCTION);
+      CASE(STUB);
+      CASE(BUILTIN);
+      CASE(LOAD_IC);
+      CASE(KEYED_LOAD_IC);
+      CASE(STORE_IC);
+      CASE(KEYED_STORE_IC);
+      CASE(CALL_IC);
+    }
+  }
+
+#undef CASE
+
+  PrintF("\n   Code kind histograms: \n");
+  for (int i = 0; i < Code::NUMBER_OF_KINDS; i++) {
+    if (code_kind_statistics[i] > 0) {
+      PrintF("     %-20s: %10d bytes\n", table[i], code_kind_statistics[i]);
+    }
+  }
+  PrintF("\n");
+}
+
+
+static int CollectHistogramInfo(HeapObject* obj) {
+  InstanceType type = obj->map()->instance_type();
+  ASSERT(0 <= type && type <= LAST_TYPE);
+  ASSERT(heap_histograms[type].name() != NULL);
+  heap_histograms[type].increment_number(1);
+  heap_histograms[type].increment_bytes(obj->Size());
+
+  if (FLAG_collect_heap_spill_statistics && obj->IsJSObject()) {
+    JSObject::cast(obj)->IncrementSpillStatistics(&js_spill_information);
+  }
+
+  return obj->Size();
+}
+
+
+static void ReportHistogram(bool print_spill) {
+  PrintF("\n  Object Histogram:\n");
+  for (int i = 0; i <= LAST_TYPE; i++) {
+    if (heap_histograms[i].number() > 0) {
+      PrintF("    %-33s%10d (%10d bytes)\n",
+             heap_histograms[i].name(),
+             heap_histograms[i].number(),
+             heap_histograms[i].bytes());
+    }
+  }
+  PrintF("\n");
+
+  // Summarize string types.
+  int string_number = 0;
+  int string_bytes = 0;
+#define INCREMENT(type, size, name)                  \
+    string_number += heap_histograms[type].number(); \
+    string_bytes += heap_histograms[type].bytes();
+  STRING_TYPE_LIST(INCREMENT)
+#undef INCREMENT
+  if (string_number > 0) {
+    PrintF("    %-33s%10d (%10d bytes)\n\n", "STRING_TYPE", string_number,
+           string_bytes);
+  }
+
+  if (FLAG_collect_heap_spill_statistics && print_spill) {
+    js_spill_information.Print();
+  }
+}
+#endif  // DEBUG
+
+
+// Support for statistics gathering for --heap-stats and --log-gc.
+#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
+void NewSpace::ClearHistograms() {
+  for (int i = 0; i <= LAST_TYPE; i++) {
+    allocated_histogram_[i].clear();
+    promoted_histogram_[i].clear();
+  }
+}
+
+// Because the copying collector does not touch garbage objects, we iterate
+// the new space before a collection to get a histogram of allocated objects.
+// This only happens (1) when compiled with DEBUG and the --heap-stats flag is
+// set, or when compiled with ENABLE_LOGGING_AND_PROFILING and the --log-gc
+// flag is set.
+void NewSpace::CollectStatistics() {
+  ClearHistograms();
+  SemiSpaceIterator it(this);
+  while (it.has_next()) RecordAllocation(it.next());
+}
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+static void DoReportStatistics(HistogramInfo* info, const char* description) {
+  LOG(HeapSampleBeginEvent("NewSpace", description));
+  // Lump all the string types together.
+  int string_number = 0;
+  int string_bytes = 0;
+#define INCREMENT(type, size, name)       \
+    string_number += info[type].number(); \
+    string_bytes += info[type].bytes();
+  STRING_TYPE_LIST(INCREMENT)
+#undef INCREMENT
+  if (string_number > 0) {
+    LOG(HeapSampleItemEvent("STRING_TYPE", string_number, string_bytes));
+  }
+
+  // Then do the other types.
+  for (int i = FIRST_NONSTRING_TYPE; i <= LAST_TYPE; ++i) {
+    if (info[i].number() > 0) {
+      LOG(HeapSampleItemEvent(info[i].name(), info[i].number(),
+                              info[i].bytes()));
+    }
+  }
+  LOG(HeapSampleEndEvent("NewSpace", description));
+}
+#endif  // ENABLE_LOGGING_AND_PROFILING
+
+
+void NewSpace::ReportStatistics() {
+#ifdef DEBUG
+  if (FLAG_heap_stats) {
+    float pct = static_cast<float>(Available()) / Capacity();
+    PrintF("  capacity: %d, available: %d, %%%d\n",
+           Capacity(), Available(), static_cast<int>(pct*100));
+    PrintF("\n  Object Histogram:\n");
+    for (int i = 0; i <= LAST_TYPE; i++) {
+      if (allocated_histogram_[i].number() > 0) {
+        PrintF("    %-33s%10d (%10d bytes)\n",
+               allocated_histogram_[i].name(),
+               allocated_histogram_[i].number(),
+               allocated_histogram_[i].bytes());
+      }
+    }
+    PrintF("\n");
+  }
+#endif  // DEBUG
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (FLAG_log_gc) {
+    DoReportStatistics(allocated_histogram_, "allocated");
+    DoReportStatistics(promoted_histogram_, "promoted");
+  }
+#endif  // ENABLE_LOGGING_AND_PROFILING
+}
+
+
+void NewSpace::RecordAllocation(HeapObject* obj) {
+  InstanceType type = obj->map()->instance_type();
+  ASSERT(0 <= type && type <= LAST_TYPE);
+  allocated_histogram_[type].increment_number(1);
+  allocated_histogram_[type].increment_bytes(obj->Size());
+}
+
+
+void NewSpace::RecordPromotion(HeapObject* obj) {
+  InstanceType type = obj->map()->instance_type();
+  ASSERT(0 <= type && type <= LAST_TYPE);
+  promoted_histogram_[type].increment_number(1);
+  promoted_histogram_[type].increment_bytes(obj->Size());
+}
+#endif  // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
+
+
+// -----------------------------------------------------------------------------
+// Free lists for old object spaces implementation
+
+void FreeListNode::set_size(int size_in_bytes) {
+  ASSERT(size_in_bytes > 0);
+  ASSERT(IsAligned(size_in_bytes, kPointerSize));
+
+  // We write a map and possibly size information to the block.  If the block
+  // is big enough to be a ByteArray with at least one extra word (the next
+  // pointer), we set its map to be the byte array map and its size to an
+  // appropriate array length for the desired size from HeapObject::Size().
+  // If the block is too small (eg, one or two words), to hold both a size
+  // field and a next pointer, we give it a filler map that gives it the
+  // correct size.
+  if (size_in_bytes > Array::kHeaderSize) {
+    set_map(Heap::byte_array_map());
+    ByteArray::cast(this)->set_length(ByteArray::LengthFor(size_in_bytes));
+  } else if (size_in_bytes == kPointerSize) {
+    set_map(Heap::one_word_filler_map());
+  } else if (size_in_bytes == 2 * kPointerSize) {
+    set_map(Heap::two_word_filler_map());
+  } else {
+    UNREACHABLE();
+  }
+  ASSERT(Size() == size_in_bytes);
+}
+
+
+Address FreeListNode::next() {
+  ASSERT(map() == Heap::byte_array_map());
+  ASSERT(Size() >= kNextOffset + kPointerSize);
+  return Memory::Address_at(address() + kNextOffset);
+}
+
+
+void FreeListNode::set_next(Address next) {
+  ASSERT(map() == Heap::byte_array_map());
+  ASSERT(Size() >= kNextOffset + kPointerSize);
+  Memory::Address_at(address() + kNextOffset) = next;
+}
+
+
+OldSpaceFreeList::OldSpaceFreeList(AllocationSpace owner) : owner_(owner) {
+  Reset();
+}
+
+
+void OldSpaceFreeList::Reset() {
+  available_ = 0;
+  for (int i = 0; i < kFreeListsLength; i++) {
+    free_[i].head_node_ = NULL;
+  }
+  needs_rebuild_ = false;
+  finger_ = kHead;
+  free_[kHead].next_size_ = kEnd;
+}
+
+
+void OldSpaceFreeList::RebuildSizeList() {
+  ASSERT(needs_rebuild_);
+  int cur = kHead;
+  for (int i = cur + 1; i < kFreeListsLength; i++) {
+    if (free_[i].head_node_ != NULL) {
+      free_[cur].next_size_ = i;
+      cur = i;
+    }
+  }
+  free_[cur].next_size_ = kEnd;
+  needs_rebuild_ = false;
+}
+
+
+int OldSpaceFreeList::Free(Address start, int size_in_bytes) {
+#ifdef DEBUG
+  for (int i = 0; i < size_in_bytes; i += kPointerSize) {
+    Memory::Address_at(start + i) = kZapValue;
+  }
+#endif
+  FreeListNode* node = FreeListNode::FromAddress(start);
+  node->set_size(size_in_bytes);
+
+  // Early return to drop too-small blocks on the floor (one or two word
+  // blocks cannot hold a map pointer, a size field, and a pointer to the
+  // next block in the free list).
+  if (size_in_bytes < kMinBlockSize) {
+    return size_in_bytes;
+  }
+
+  // Insert other blocks at the head of an exact free list.
+  int index = size_in_bytes >> kPointerSizeLog2;
+  node->set_next(free_[index].head_node_);
+  free_[index].head_node_ = node->address();
+  available_ += size_in_bytes;
+  needs_rebuild_ = true;
+  return 0;
+}
+
+
+Object* OldSpaceFreeList::Allocate(int size_in_bytes, int* wasted_bytes) {
+  ASSERT(0 < size_in_bytes);
+  ASSERT(size_in_bytes <= kMaxBlockSize);
+  ASSERT(IsAligned(size_in_bytes, kPointerSize));
+
+  if (needs_rebuild_) RebuildSizeList();
+  int index = size_in_bytes >> kPointerSizeLog2;
+  // Check for a perfect fit.
+  if (free_[index].head_node_ != NULL) {
+    FreeListNode* node = FreeListNode::FromAddress(free_[index].head_node_);
+    // If this was the last block of its size, remove the size.
+    if ((free_[index].head_node_ = node->next()) == NULL) RemoveSize(index);
+    available_ -= size_in_bytes;
+    *wasted_bytes = 0;
+    return node;
+  }
+  // Search the size list for the best fit.
+  int prev = finger_ < index ? finger_ : kHead;
+  int cur = FindSize(index, &prev);
+  ASSERT(index < cur);
+  if (cur == kEnd) {
+    // No large enough size in list.
+    *wasted_bytes = 0;
+    return Failure::RetryAfterGC(size_in_bytes, owner_);
+  }
+  int rem = cur - index;
+  int rem_bytes = rem << kPointerSizeLog2;
+  FreeListNode* cur_node = FreeListNode::FromAddress(free_[cur].head_node_);
+  ASSERT(cur_node->Size() == (cur << kPointerSizeLog2));
+  FreeListNode* rem_node = FreeListNode::FromAddress(free_[cur].head_node_ +
+                                                     size_in_bytes);
+  // Distinguish the cases prev < rem < cur and rem <= prev < cur
+  // to avoid many redundant tests and calls to Insert/RemoveSize.
+  if (prev < rem) {
+    // Simple case: insert rem between prev and cur.
+    finger_ = prev;
+    free_[prev].next_size_ = rem;
+    // If this was the last block of size cur, remove the size.
+    if ((free_[cur].head_node_ = cur_node->next()) == NULL) {
+      free_[rem].next_size_ = free_[cur].next_size_;
+    } else {
+      free_[rem].next_size_ = cur;
+    }
+    // Add the remainder block.
+    rem_node->set_size(rem_bytes);
+    rem_node->set_next(free_[rem].head_node_);
+    free_[rem].head_node_ = rem_node->address();
+  } else {
+    // If this was the last block of size cur, remove the size.
+    if ((free_[cur].head_node_ = cur_node->next()) == NULL) {
+      finger_ = prev;
+      free_[prev].next_size_ = free_[cur].next_size_;
+    }
+    if (rem_bytes < kMinBlockSize) {
+      // Too-small remainder is wasted.
+      rem_node->set_size(rem_bytes);
+      available_ -= size_in_bytes + rem_bytes;
+      *wasted_bytes = rem_bytes;
+      return cur_node;
+    }
+    // Add the remainder block and, if needed, insert its size.
+    rem_node->set_size(rem_bytes);
+    rem_node->set_next(free_[rem].head_node_);
+    free_[rem].head_node_ = rem_node->address();
+    if (rem_node->next() == NULL) InsertSize(rem);
+  }
+  available_ -= size_in_bytes;
+  *wasted_bytes = 0;
+  return cur_node;
+}
+
+
+#ifdef DEBUG
+bool OldSpaceFreeList::Contains(FreeListNode* node) {
+  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);
+      if (cur_node == node) return true;
+      cur_addr = cur_node->next();
+    }
+  }
+  return false;
+}
+#endif
+
+
+MapSpaceFreeList::MapSpaceFreeList(AllocationSpace owner) {
+  owner_ = owner;
+  Reset();
+}
+
+
+void MapSpaceFreeList::Reset() {
+  available_ = 0;
+  head_ = NULL;
+}
+
+
+void MapSpaceFreeList::Free(Address start) {
+#ifdef DEBUG
+  for (int i = 0; i < Map::kSize; i += kPointerSize) {
+    Memory::Address_at(start + i) = kZapValue;
+  }
+#endif
+  FreeListNode* node = FreeListNode::FromAddress(start);
+  node->set_size(Map::kSize);
+  node->set_next(head_);
+  head_ = node->address();
+  available_ += Map::kSize;
+}
+
+
+Object* MapSpaceFreeList::Allocate() {
+  if (head_ == NULL) {
+    return Failure::RetryAfterGC(Map::kSize, owner_);
+  }
+
+  FreeListNode* node = FreeListNode::FromAddress(head_);
+  head_ = node->next();
+  available_ -= Map::kSize;
+  return node;
+}
+
+
+// -----------------------------------------------------------------------------
+// OldSpace implementation
+
+void OldSpace::PrepareForMarkCompact(bool will_compact) {
+  if (will_compact) {
+    // Reset relocation info.  During a compacting collection, everything in
+    // the space is considered 'available' and we will rediscover live data
+    // and waste during the collection.
+    MCResetRelocationInfo();
+    mc_end_of_relocation_ = bottom();
+    ASSERT(Available() == Capacity());
+  } else {
+    // During a non-compacting collection, everything below the linear
+    // allocation pointer is considered allocated (everything above is
+    // available) and we will rediscover available and wasted bytes during
+    // the collection.
+    accounting_stats_.AllocateBytes(free_list_.available());
+    accounting_stats_.FillWastedBytes(Waste());
+  }
+
+  // Clear the free list before a full GC---it will be rebuilt afterward.
+  free_list_.Reset();
+}
+
+
+void OldSpace::MCAdjustRelocationEnd(Address address, int size_in_bytes) {
+  ASSERT(Contains(address));
+  Address current_top = mc_end_of_relocation_;
+  Page* current_page = Page::FromAllocationTop(current_top);
+
+  // No more objects relocated to this page?  Move to the next.
+  ASSERT(current_top <= current_page->mc_relocation_top);
+  if (current_top == current_page->mc_relocation_top) {
+    // The space should already be properly expanded.
+    Page* next_page = current_page->next_page();
+    CHECK(next_page->is_valid());
+    mc_end_of_relocation_ = next_page->ObjectAreaStart();
+  }
+  ASSERT(mc_end_of_relocation_ == address);
+  mc_end_of_relocation_ += size_in_bytes;
+}
+
+
+void OldSpace::MCCommitRelocationInfo() {
+  // Update fast allocation info.
+  allocation_info_.top = mc_forwarding_info_.top;
+  allocation_info_.limit = mc_forwarding_info_.limit;
+  ASSERT(allocation_info_.VerifyPagedAllocation());
+
+  // The space is compacted and we haven't yet built free lists or
+  // wasted any space.
+  ASSERT(Waste() == 0);
+  ASSERT(AvailableFree() == 0);
+
+  // Build the free list for the space.
+  int computed_size = 0;
+  PageIterator it(this, PageIterator::PAGES_USED_BY_MC);
+  while (it.has_next()) {
+    Page* p = it.next();
+    // Space below the relocation pointer is allocated.
+    computed_size += p->mc_relocation_top - p->ObjectAreaStart();
+    if (it.has_next()) {
+      // Free the space at the top of the page.  We cannot use
+      // p->mc_relocation_top after the call to Free (because Free will clear
+      // remembered set bits).
+      int extra_size = p->ObjectAreaEnd() - p->mc_relocation_top;
+      if (extra_size > 0) {
+        int wasted_bytes = free_list_.Free(p->mc_relocation_top, extra_size);
+        // The bytes we have just "freed" to add to the free list were
+        // already accounted as available.
+        accounting_stats_.WasteBytes(wasted_bytes);
+      }
+    }
+  }
+
+  // Make sure the computed size - based on the used portion of the pages in
+  // use - matches the size obtained while computing forwarding addresses.
+  ASSERT(computed_size == Size());
+}
+
+
+// Slow case for normal allocation.  Try in order: (1) allocate in the next
+// page in the space, (2) allocate off the space's free list, (3) expand the
+// space, (4) fail.
+HeapObject* OldSpace::SlowAllocateRaw(int size_in_bytes) {
+  // Linear allocation in this space has failed.  If there is another page
+  // in the space, move to that page and allocate there.  This allocation
+  // should succeed (size_in_bytes should not be greater than a page's
+  // object area size).
+  Page* current_page = TopPageOf(allocation_info_);
+  if (current_page->next_page()->is_valid()) {
+    return AllocateInNextPage(current_page, size_in_bytes);
+  }
+
+  // There is no next page in this space.  Try free list allocation.
+  int wasted_bytes;
+  Object* result = free_list_.Allocate(size_in_bytes, &wasted_bytes);
+  accounting_stats_.WasteBytes(wasted_bytes);
+  if (!result->IsFailure()) {
+    accounting_stats_.AllocateBytes(size_in_bytes);
+    return HeapObject::cast(result);
+  }
+
+  // Free list allocation failed and there is no next page.  Fail if we have
+  // hit the old generation size limit that should cause a garbage
+  // collection.
+  if (!Heap::always_allocate() && Heap::OldGenerationAllocationLimitReached()) {
+    return NULL;
+  }
+
+  // Try to expand the space and allocate in the new next page.
+  ASSERT(!current_page->next_page()->is_valid());
+  if (Expand(current_page)) {
+    return AllocateInNextPage(current_page, size_in_bytes);
+  }
+
+  // Finally, fail.
+  return NULL;
+}
+
+
+// Add the block at the top of the page to the space's free list, set the
+// allocation info to the next page (assumed to be one), and allocate
+// linearly there.
+HeapObject* OldSpace::AllocateInNextPage(Page* current_page,
+                                         int size_in_bytes) {
+  ASSERT(current_page->next_page()->is_valid());
+  // Add the block at the top of this page to the free list.
+  int free_size = current_page->ObjectAreaEnd() - allocation_info_.top;
+  if (free_size > 0) {
+    int wasted_bytes = free_list_.Free(allocation_info_.top, free_size);
+    accounting_stats_.WasteBytes(wasted_bytes);
+  }
+  SetAllocationInfo(&allocation_info_, current_page->next_page());
+  return AllocateLinearly(&allocation_info_, size_in_bytes);
+}
+
+
+#ifdef DEBUG
+// We do not assume that the PageIterator works, because it depends on the
+// invariants we are checking during verification.
+void OldSpace::Verify() {
+  // The allocation pointer should be valid, and it should be in a page in the
+  // space.
+  ASSERT(allocation_info_.VerifyPagedAllocation());
+  Page* top_page = Page::FromAllocationTop(allocation_info_.top);
+  ASSERT(MemoryAllocator::IsPageInSpace(top_page, this));
+
+  // Loop over all the pages.
+  bool above_allocation_top = false;
+  Page* current_page = first_page_;
+  while (current_page->is_valid()) {
+    if (above_allocation_top) {
+      // We don't care what's above the allocation top.
+    } else {
+      // Unless this is the last page in the space containing allocated
+      // objects, the allocation top should be at the object area end.
+      Address top = current_page->AllocationTop();
+      if (current_page == top_page) {
+        ASSERT(top == allocation_info_.top);
+        // The next page will be above the allocation top.
+        above_allocation_top = true;
+      } else {
+        ASSERT(top == current_page->ObjectAreaEnd());
+      }
+
+      // It should be packed with objects from the bottom to the top.
+      Address current = current_page->ObjectAreaStart();
+      while (current < top) {
+        HeapObject* object = HeapObject::FromAddress(current);
+
+        // The first word should be a map, and we expect all map pointers to
+        // be in map space.
+        Map* map = object->map();
+        ASSERT(map->IsMap());
+        ASSERT(Heap::map_space()->Contains(map));
+
+        // The object should not be a map.
+        ASSERT(!object->IsMap());
+
+        // The object itself should look OK.
+        object->Verify();
+
+        // All the interior pointers should be contained in the heap and have
+        // their remembered set bits set if they point to new space.  Code
+        // objects do not have remembered set bits that we care about.
+        VerifyPointersAndRSetVisitor rset_visitor;
+        VerifyPointersVisitor no_rset_visitor;
+        int size = object->Size();
+        if (object->IsCode()) {
+          Code::cast(object)->ConvertICTargetsFromAddressToObject();
+          object->IterateBody(map->instance_type(), size, &no_rset_visitor);
+          Code::cast(object)->ConvertICTargetsFromObjectToAddress();
+        } else {
+          object->IterateBody(map->instance_type(), size, &rset_visitor);
+        }
+
+        current += size;
+      }
+
+      // The allocation pointer should not be in the middle of an object.
+      ASSERT(current == top);
+    }
+
+    current_page = current_page->next_page();
+  }
+}
+
+
+struct CommentStatistic {
+  const char* comment;
+  int size;
+  int count;
+  void Clear() {
+    comment = NULL;
+    size = 0;
+    count = 0;
+  }
+};
+
+
+// must be small, since an iteration is used for lookup
+const int kMaxComments = 64;
+static CommentStatistic comments_statistics[kMaxComments+1];
+
+
+void PagedSpace::ReportCodeStatistics() {
+  ReportCodeKindStatistics();
+  PrintF("Code comment statistics (\"   [ comment-txt   :    size/   "
+         "count  (average)\"):\n");
+  for (int i = 0; i <= kMaxComments; i++) {
+    const CommentStatistic& cs = comments_statistics[i];
+    if (cs.size > 0) {
+      PrintF("   %-30s: %10d/%6d     (%d)\n", cs.comment, cs.size, cs.count,
+             cs.size/cs.count);
+    }
+  }
+  PrintF("\n");
+}
+
+
+void PagedSpace::ResetCodeStatistics() {
+  ClearCodeKindStatistics();
+  for (int i = 0; i < kMaxComments; i++) comments_statistics[i].Clear();
+  comments_statistics[kMaxComments].comment = "Unknown";
+  comments_statistics[kMaxComments].size = 0;
+  comments_statistics[kMaxComments].count = 0;
+}
+
+
+// Adds comment to 'comment_statistics' table. Performance OK sa long as
+// 'kMaxComments' is small
+static void EnterComment(const char* comment, int delta) {
+  // Do not count empty comments
+  if (delta <= 0) return;
+  CommentStatistic* cs = &comments_statistics[kMaxComments];
+  // Search for a free or matching entry in 'comments_statistics': 'cs'
+  // points to result.
+  for (int i = 0; i < kMaxComments; i++) {
+    if (comments_statistics[i].comment == NULL) {
+      cs = &comments_statistics[i];
+      cs->comment = comment;
+      break;
+    } else if (strcmp(comments_statistics[i].comment, comment) == 0) {
+      cs = &comments_statistics[i];
+      break;
+    }
+  }
+  // Update entry for 'comment'
+  cs->size += delta;
+  cs->count += 1;
+}
+
+
+// Call for each nested comment start (start marked with '[ xxx', end marked
+// with ']'.  RelocIterator 'it' must point to a comment reloc info.
+static void CollectCommentStatistics(RelocIterator* it) {
+  ASSERT(!it->done());
+  ASSERT(it->rinfo()->rmode() == RelocInfo::COMMENT);
+  const char* tmp = reinterpret_cast<const char*>(it->rinfo()->data());
+  if (tmp[0] != '[') {
+    // Not a nested comment; skip
+    return;
+  }
+
+  // Search for end of nested comment or a new nested comment
+  const char* const comment_txt =
+      reinterpret_cast<const char*>(it->rinfo()->data());
+  const byte* prev_pc = it->rinfo()->pc();
+  int flat_delta = 0;
+  it->next();
+  while (true) {
+    // All nested comments must be terminated properly, and therefore exit
+    // from loop.
+    ASSERT(!it->done());
+    if (it->rinfo()->rmode() == RelocInfo::COMMENT) {
+      const char* const txt =
+          reinterpret_cast<const char*>(it->rinfo()->data());
+      flat_delta += it->rinfo()->pc() - prev_pc;
+      if (txt[0] == ']') break;  // End of nested  comment
+      // A new comment
+      CollectCommentStatistics(it);
+      // Skip code that was covered with previous comment
+      prev_pc = it->rinfo()->pc();
+    }
+    it->next();
+  }
+  EnterComment(comment_txt, flat_delta);
+}
+
+
+// Collects code size statistics:
+// - by code kind
+// - by code comment
+void PagedSpace::CollectCodeStatistics() {
+  HeapObjectIterator obj_it(this);
+  while (obj_it.has_next()) {
+    HeapObject* obj = obj_it.next();
+    if (obj->IsCode()) {
+      Code* code = Code::cast(obj);
+      code_kind_statistics[code->kind()] += code->Size();
+      RelocIterator it(code);
+      int delta = 0;
+      const byte* prev_pc = code->instruction_start();
+      while (!it.done()) {
+        if (it.rinfo()->rmode() == RelocInfo::COMMENT) {
+          delta += it.rinfo()->pc() - prev_pc;
+          CollectCommentStatistics(&it);
+          prev_pc = it.rinfo()->pc();
+        }
+        it.next();
+      }
+
+      ASSERT(code->instruction_start() <= prev_pc &&
+             prev_pc <= code->relocation_start());
+      delta += code->relocation_start() - prev_pc;
+      EnterComment("NoComment", delta);
+    }
+  }
+}
+
+
+void OldSpace::ReportStatistics() {
+  int pct = Available() * 100 / Capacity();
+  PrintF("  capacity: %d, waste: %d, available: %d, %%%d\n",
+         Capacity(), Waste(), Available(), pct);
+
+  // Report remembered set statistics.
+  int rset_marked_pointers = 0;
+  int rset_marked_arrays = 0;
+  int rset_marked_array_elements = 0;
+  int cross_gen_pointers = 0;
+  int cross_gen_array_elements = 0;
+
+  PageIterator page_it(this, PageIterator::PAGES_IN_USE);
+  while (page_it.has_next()) {
+    Page* p = page_it.next();
+
+    for (Address rset_addr = p->RSetStart();
+         rset_addr < p->RSetEnd();
+         rset_addr += kIntSize) {
+      int rset = Memory::int_at(rset_addr);
+      if (rset != 0) {
+        // Bits were set
+        int intoff = rset_addr - p->address();
+        int bitoff = 0;
+        for (; bitoff < kBitsPerInt; ++bitoff) {
+          if ((rset & (1 << bitoff)) != 0) {
+            int bitpos = intoff*kBitsPerByte + bitoff;
+            Address slot = p->OffsetToAddress(bitpos << kObjectAlignmentBits);
+            Object** obj = reinterpret_cast<Object**>(slot);
+            if (*obj == Heap::fixed_array_map()) {
+              rset_marked_arrays++;
+              FixedArray* fa = FixedArray::cast(HeapObject::FromAddress(slot));
+
+              rset_marked_array_elements += fa->length();
+              // Manually inline FixedArray::IterateBody
+              Address elm_start = slot + FixedArray::kHeaderSize;
+              Address elm_stop = elm_start + fa->length() * kPointerSize;
+              for (Address elm_addr = elm_start;
+                   elm_addr < elm_stop; elm_addr += kPointerSize) {
+                // Filter non-heap-object pointers
+                Object** elm_p = reinterpret_cast<Object**>(elm_addr);
+                if (Heap::InNewSpace(*elm_p))
+                  cross_gen_array_elements++;
+              }
+            } else {
+              rset_marked_pointers++;
+              if (Heap::InNewSpace(*obj))
+                cross_gen_pointers++;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  pct = rset_marked_pointers == 0 ?
+        0 : cross_gen_pointers * 100 / rset_marked_pointers;
+  PrintF("  rset-marked pointers %d, to-new-space %d (%%%d)\n",
+            rset_marked_pointers, cross_gen_pointers, pct);
+  PrintF("  rset_marked arrays %d, ", rset_marked_arrays);
+  PrintF("  elements %d, ", rset_marked_array_elements);
+  pct = rset_marked_array_elements == 0 ? 0
+           : cross_gen_array_elements * 100 / rset_marked_array_elements;
+  PrintF("  pointers to new space %d (%%%d)\n", cross_gen_array_elements, pct);
+  PrintF("  total rset-marked bits %d\n",
+            (rset_marked_pointers + rset_marked_arrays));
+  pct = (rset_marked_pointers + rset_marked_array_elements) == 0 ? 0
+        : (cross_gen_pointers + cross_gen_array_elements) * 100 /
+          (rset_marked_pointers + rset_marked_array_elements);
+  PrintF("  total rset pointers %d, true cross generation ones %d (%%%d)\n",
+         (rset_marked_pointers + rset_marked_array_elements),
+         (cross_gen_pointers + cross_gen_array_elements),
+         pct);
+
+  ClearHistograms();
+  HeapObjectIterator obj_it(this);
+  while (obj_it.has_next()) { CollectHistogramInfo(obj_it.next()); }
+  ReportHistogram(true);
+}
+
+
+// Dump the range of remembered set words between [start, end) corresponding
+// to the pointers starting at object_p.  The allocation_top is an object
+// pointer which should not be read past.  This is important for large object
+// pages, where some bits in the remembered set range do not correspond to
+// allocated addresses.
+static void PrintRSetRange(Address start, Address end, Object** object_p,
+                           Address allocation_top) {
+  Address rset_address = start;
+
+  // If the range starts on on odd numbered word (eg, for large object extra
+  // remembered set ranges), print some spaces.
+  if ((reinterpret_cast<uint32_t>(start) / kIntSize) % 2 == 1) {
+    PrintF("                                    ");
+  }
+
+  // Loop over all the words in the range.
+  while (rset_address < end) {
+    uint32_t rset_word = Memory::uint32_at(rset_address);
+    int bit_position = 0;
+
+    // Loop over all the bits in the word.
+    while (bit_position < kBitsPerInt) {
+      if (object_p == reinterpret_cast<Object**>(allocation_top)) {
+        // Print a bar at the allocation pointer.
+        PrintF("|");
+      } else if (object_p > reinterpret_cast<Object**>(allocation_top)) {
+        // Do not dereference object_p past the allocation pointer.
+        PrintF("#");
+      } else if ((rset_word & (1 << bit_position)) == 0) {
+        // Print a dot for zero bits.
+        PrintF(".");
+      } else if (Heap::InNewSpace(*object_p)) {
+        // Print an X for one bits for pointers to new space.
+        PrintF("X");
+      } else {
+        // Print a circle for one bits for pointers to old space.
+        PrintF("o");
+      }
+
+      // Print a space after every 8th bit except the last.
+      if (bit_position % 8 == 7 && bit_position != (kBitsPerInt - 1)) {
+        PrintF(" ");
+      }
+
+      // Advance to next bit.
+      bit_position++;
+      object_p++;
+    }
+
+    // Print a newline after every odd numbered word, otherwise a space.
+    if ((reinterpret_cast<uint32_t>(rset_address) / kIntSize) % 2 == 1) {
+      PrintF("\n");
+    } else {
+      PrintF(" ");
+    }
+
+    // Advance to next remembered set word.
+    rset_address += kIntSize;
+  }
+}
+
+
+void PagedSpace::DoPrintRSet(const char* space_name) {
+  PageIterator it(this, PageIterator::PAGES_IN_USE);
+  while (it.has_next()) {
+    Page* p = it.next();
+    PrintF("%s page 0x%x:\n", space_name, p);
+    PrintRSetRange(p->RSetStart(), p->RSetEnd(),
+                   reinterpret_cast<Object**>(p->ObjectAreaStart()),
+                   p->AllocationTop());
+    PrintF("\n");
+  }
+}
+
+
+void OldSpace::PrintRSet() { DoPrintRSet("old"); }
+#endif
+
+// -----------------------------------------------------------------------------
+// MapSpace implementation
+
+void MapSpace::PrepareForMarkCompact(bool will_compact) {
+  if (will_compact) {
+    // Reset relocation info.
+    MCResetRelocationInfo();
+
+    // Initialize map index entry.
+    int page_count = 0;
+    PageIterator it(this, PageIterator::ALL_PAGES);
+    while (it.has_next()) {
+      ASSERT_MAP_PAGE_INDEX(page_count);
+
+      Page* p = it.next();
+      ASSERT(p->mc_page_index == page_count);
+
+      page_addresses_[page_count++] = p->address();
+    }
+
+    // During a compacting collection, everything in the space is considered
+    // 'available' (set by the call to MCResetRelocationInfo) and we will
+    // rediscover live and wasted bytes during the collection.
+    ASSERT(Available() == Capacity());
+  } else {
+    // During a non-compacting collection, everything below the linear
+    // allocation pointer except wasted top-of-page blocks is considered
+    // allocated and we will rediscover available bytes during the
+    // collection.
+    accounting_stats_.AllocateBytes(free_list_.available());
+  }
+
+  // Clear the free list before a full GC---it will be rebuilt afterward.
+  free_list_.Reset();
+}
+
+
+void MapSpace::MCCommitRelocationInfo() {
+  // Update fast allocation info.
+  allocation_info_.top = mc_forwarding_info_.top;
+  allocation_info_.limit = mc_forwarding_info_.limit;
+  ASSERT(allocation_info_.VerifyPagedAllocation());
+
+  // The space is compacted and we haven't yet wasted any space.
+  ASSERT(Waste() == 0);
+
+  // Update allocation_top of each page in use and compute waste.
+  int computed_size = 0;
+  PageIterator it(this, PageIterator::PAGES_USED_BY_MC);
+  while (it.has_next()) {
+    Page* page = it.next();
+    Address page_top = page->AllocationTop();
+    computed_size += page_top - page->ObjectAreaStart();
+    if (it.has_next()) {
+      accounting_stats_.WasteBytes(page->ObjectAreaEnd() - page_top);
+    }
+  }
+
+  // Make sure the computed size - based on the used portion of the
+  // pages in use - matches the size we adjust during allocation.
+  ASSERT(computed_size == Size());
+}
+
+
+// Slow case for normal allocation. Try in order: (1) allocate in the next
+// page in the space, (2) allocate off the space's free list, (3) expand the
+// space, (4) fail.
+HeapObject* MapSpace::SlowAllocateRaw(int size_in_bytes) {
+  // Linear allocation in this space has failed.  If there is another page
+  // in the space, move to that page and allocate there.  This allocation
+  // should succeed.
+  Page* current_page = TopPageOf(allocation_info_);
+  if (current_page->next_page()->is_valid()) {
+    return AllocateInNextPage(current_page, size_in_bytes);
+  }
+
+  // There is no next page in this space.  Try free list allocation.  The
+  // map space free list implicitly assumes that all free blocks are map
+  // sized.
+  if (size_in_bytes == Map::kSize) {
+    Object* result = free_list_.Allocate();
+    if (!result->IsFailure()) {
+      accounting_stats_.AllocateBytes(size_in_bytes);
+      return HeapObject::cast(result);
+    }
+  }
+
+  // Free list allocation failed and there is no next page.  Fail if we have
+  // hit the old generation size limit that should cause a garbage
+  // collection.
+  if (!Heap::always_allocate() && Heap::OldGenerationAllocationLimitReached()) {
+    return NULL;
+  }
+
+  // Try to expand the space and allocate in the new next page.
+  ASSERT(!current_page->next_page()->is_valid());
+  if (Expand(current_page)) {
+    return AllocateInNextPage(current_page, size_in_bytes);
+  }
+
+  // Finally, fail.
+  return NULL;
+}
+
+
+// Move to the next page (there is assumed to be one) and allocate there.
+// The top of page block is always wasted, because it is too small to hold a
+// map.
+HeapObject* MapSpace::AllocateInNextPage(Page* current_page,
+                                         int size_in_bytes) {
+  ASSERT(current_page->next_page()->is_valid());
+  ASSERT(current_page->ObjectAreaEnd() - allocation_info_.top == kPageExtra);
+  accounting_stats_.WasteBytes(kPageExtra);
+  SetAllocationInfo(&allocation_info_, current_page->next_page());
+  return AllocateLinearly(&allocation_info_, size_in_bytes);
+}
+
+
+#ifdef DEBUG
+// We do not assume that the PageIterator works, because it depends on the
+// invariants we are checking during verification.
+void MapSpace::Verify() {
+  // The allocation pointer should be valid, and it should be in a page in the
+  // space.
+  ASSERT(allocation_info_.VerifyPagedAllocation());
+  Page* top_page = Page::FromAllocationTop(allocation_info_.top);
+  ASSERT(MemoryAllocator::IsPageInSpace(top_page, this));
+
+  // Loop over all the pages.
+  bool above_allocation_top = false;
+  Page* current_page = first_page_;
+  while (current_page->is_valid()) {
+    if (above_allocation_top) {
+      // We don't care what's above the allocation top.
+    } else {
+      // Unless this is the last page in the space containing allocated
+      // objects, the allocation top should be at a constant offset from the
+      // object area end.
+      Address top = current_page->AllocationTop();
+      if (current_page == top_page) {
+        ASSERT(top == allocation_info_.top);
+        // The next page will be above the allocation top.
+        above_allocation_top = true;
+      } else {
+        ASSERT(top == current_page->ObjectAreaEnd() - kPageExtra);
+      }
+
+      // It should be packed with objects from the bottom to the top.
+      Address current = current_page->ObjectAreaStart();
+      while (current < top) {
+        HeapObject* object = HeapObject::FromAddress(current);
+
+        // The first word should be a map, and we expect all map pointers to
+        // be in map space.
+        Map* map = object->map();
+        ASSERT(map->IsMap());
+        ASSERT(Heap::map_space()->Contains(map));
+
+        // The object should be a map or a byte array.
+        ASSERT(object->IsMap() || object->IsByteArray());
+
+        // The object itself should look OK.
+        object->Verify();
+
+        // All the interior pointers should be contained in the heap and
+        // have their remembered set bits set if they point to new space.
+        VerifyPointersAndRSetVisitor visitor;
+        int size = object->Size();
+        object->IterateBody(map->instance_type(), size, &visitor);
+
+        current += size;
+      }
+
+      // The allocation pointer should not be in the middle of an object.
+      ASSERT(current == top);
+    }
+
+    current_page = current_page->next_page();
+  }
+}
+
+
+void MapSpace::ReportStatistics() {
+  int pct = Available() * 100 / Capacity();
+  PrintF("  capacity: %d, waste: %d, available: %d, %%%d\n",
+         Capacity(), Waste(), Available(), pct);
+
+  // Report remembered set statistics.
+  int rset_marked_pointers = 0;
+  int cross_gen_pointers = 0;
+
+  PageIterator page_it(this, PageIterator::PAGES_IN_USE);
+  while (page_it.has_next()) {
+    Page* p = page_it.next();
+
+    for (Address rset_addr = p->RSetStart();
+         rset_addr < p->RSetEnd();
+         rset_addr += kIntSize) {
+      int rset = Memory::int_at(rset_addr);
+      if (rset != 0) {
+        // Bits were set
+        int intoff = rset_addr - p->address();
+        int bitoff = 0;
+        for (; bitoff < kBitsPerInt; ++bitoff) {
+          if ((rset & (1 << bitoff)) != 0) {
+            int bitpos = intoff*kBitsPerByte + bitoff;
+            Address slot = p->OffsetToAddress(bitpos << kObjectAlignmentBits);
+            Object** obj = reinterpret_cast<Object**>(slot);
+            rset_marked_pointers++;
+            if (Heap::InNewSpace(*obj))
+              cross_gen_pointers++;
+          }
+        }
+      }
+    }
+  }
+
+  pct = rset_marked_pointers == 0 ?
+          0 : cross_gen_pointers * 100 / rset_marked_pointers;
+  PrintF("  rset-marked pointers %d, to-new-space %d (%%%d)\n",
+            rset_marked_pointers, cross_gen_pointers, pct);
+
+  ClearHistograms();
+  HeapObjectIterator obj_it(this);
+  while (obj_it.has_next()) { CollectHistogramInfo(obj_it.next()); }
+  ReportHistogram(false);
+}
+
+
+void MapSpace::PrintRSet() { DoPrintRSet("map"); }
+#endif
+
+
+// -----------------------------------------------------------------------------
+// LargeObjectIterator
+
+LargeObjectIterator::LargeObjectIterator(LargeObjectSpace* space) {
+  current_ = space->first_chunk_;
+  size_func_ = NULL;
+}
+
+
+LargeObjectIterator::LargeObjectIterator(LargeObjectSpace* space,
+                                         HeapObjectCallback size_func) {
+  current_ = space->first_chunk_;
+  size_func_ = size_func;
+}
+
+
+HeapObject* LargeObjectIterator::next() {
+  ASSERT(has_next());
+  HeapObject* object = current_->GetObject();
+  current_ = current_->next();
+  return object;
+}
+
+
+// -----------------------------------------------------------------------------
+// LargeObjectChunk
+
+LargeObjectChunk* LargeObjectChunk::New(int size_in_bytes,
+                                        size_t* chunk_size,
+                                        Executability executable) {
+  size_t requested = ChunkSizeFor(size_in_bytes);
+  void* mem = MemoryAllocator::AllocateRawMemory(requested,
+                                                 chunk_size,
+                                                 executable);
+  if (mem == NULL) return NULL;
+  LOG(NewEvent("LargeObjectChunk", mem, *chunk_size));
+  if (*chunk_size < requested) {
+    MemoryAllocator::FreeRawMemory(mem, *chunk_size);
+    LOG(DeleteEvent("LargeObjectChunk", mem));
+    return NULL;
+  }
+  return reinterpret_cast<LargeObjectChunk*>(mem);
+}
+
+
+int LargeObjectChunk::ChunkSizeFor(int size_in_bytes) {
+  int os_alignment = OS::AllocateAlignment();
+  if (os_alignment < Page::kPageSize)
+    size_in_bytes += (Page::kPageSize - os_alignment);
+  return size_in_bytes + Page::kObjectStartOffset;
+}
+
+// -----------------------------------------------------------------------------
+// LargeObjectSpace
+
+LargeObjectSpace::LargeObjectSpace(AllocationSpace id)
+    : Space(id, NOT_EXECUTABLE),  // Managed on a per-allocation basis
+      first_chunk_(NULL),
+      size_(0),
+      page_count_(0) {}
+
+
+bool LargeObjectSpace::Setup() {
+  first_chunk_ = NULL;
+  size_ = 0;
+  page_count_ = 0;
+  return true;
+}
+
+
+void LargeObjectSpace::TearDown() {
+  while (first_chunk_ != NULL) {
+    LargeObjectChunk* chunk = first_chunk_;
+    first_chunk_ = first_chunk_->next();
+    LOG(DeleteEvent("LargeObjectChunk", chunk->address()));
+    MemoryAllocator::FreeRawMemory(chunk->address(), chunk->size());
+  }
+
+  size_ = 0;
+  page_count_ = 0;
+}
+
+
+#ifdef ENABLE_HEAP_PROTECTION
+
+void LargeObjectSpace::Protect() {
+  LargeObjectChunk* chunk = first_chunk_;
+  while (chunk != NULL) {
+    MemoryAllocator::Protect(chunk->address(), chunk->size());
+    chunk = chunk->next();
+  }
+}
+
+
+void LargeObjectSpace::Unprotect() {
+  LargeObjectChunk* chunk = first_chunk_;
+  while (chunk != NULL) {
+    bool is_code = chunk->GetObject()->IsCode();
+    MemoryAllocator::Unprotect(chunk->address(), chunk->size(),
+                               is_code ? EXECUTABLE : NOT_EXECUTABLE);
+    chunk = chunk->next();
+  }
+}
+
+#endif
+
+
+Object* LargeObjectSpace::AllocateRawInternal(int requested_size,
+                                              int object_size,
+                                              Executability executable) {
+  ASSERT(0 < object_size && object_size <= requested_size);
+
+  // Check if we want to force a GC before growing the old space further.
+  // If so, fail the allocation.
+  if (!Heap::always_allocate() && Heap::OldGenerationAllocationLimitReached()) {
+    return Failure::RetryAfterGC(requested_size, identity());
+  }
+
+  size_t chunk_size;
+  LargeObjectChunk* chunk =
+      LargeObjectChunk::New(requested_size, &chunk_size, executable);
+  if (chunk == NULL) {
+    return Failure::RetryAfterGC(requested_size, identity());
+  }
+
+  size_ += chunk_size;
+  page_count_++;
+  chunk->set_next(first_chunk_);
+  chunk->set_size(chunk_size);
+  first_chunk_ = chunk;
+
+  // Set the object address and size in the page header and clear its
+  // remembered set.
+  Page* page = Page::FromAddress(RoundUp(chunk->address(), Page::kPageSize));
+  Address object_address = page->ObjectAreaStart();
+  // Clear the low order bit of the second word in the page to flag it as a
+  // large object page.  If the chunk_size happened to be written there, its
+  // low order bit should already be clear.
+  ASSERT((chunk_size & 0x1) == 0);
+  page->is_normal_page &= ~0x1;
+  page->ClearRSet();
+  int extra_bytes = requested_size - object_size;
+  if (extra_bytes > 0) {
+    // The extra memory for the remembered set should be cleared.
+    memset(object_address + object_size, 0, extra_bytes);
+  }
+
+  return HeapObject::FromAddress(object_address);
+}
+
+
+Object* LargeObjectSpace::AllocateRawCode(int size_in_bytes) {
+  ASSERT(0 < size_in_bytes);
+  return AllocateRawInternal(size_in_bytes,
+                             size_in_bytes,
+                             EXECUTABLE);
+}
+
+
+Object* LargeObjectSpace::AllocateRawFixedArray(int size_in_bytes) {
+  ASSERT(0 < size_in_bytes);
+  int extra_rset_bytes = ExtraRSetBytesFor(size_in_bytes);
+  return AllocateRawInternal(size_in_bytes + extra_rset_bytes,
+                             size_in_bytes,
+                             NOT_EXECUTABLE);
+}
+
+
+Object* LargeObjectSpace::AllocateRaw(int size_in_bytes) {
+  ASSERT(0 < size_in_bytes);
+  return AllocateRawInternal(size_in_bytes,
+                             size_in_bytes,
+                             NOT_EXECUTABLE);
+}
+
+
+// GC support
+Object* LargeObjectSpace::FindObject(Address a) {
+  for (LargeObjectChunk* chunk = first_chunk_;
+       chunk != NULL;
+       chunk = chunk->next()) {
+    Address chunk_address = chunk->address();
+    if (chunk_address <= a && a < chunk_address + chunk->size()) {
+      return chunk->GetObject();
+    }
+  }
+  return Failure::Exception();
+}
+
+
+void LargeObjectSpace::ClearRSet() {
+  ASSERT(Page::is_rset_in_use());
+
+  LargeObjectIterator it(this);
+  while (it.has_next()) {
+    HeapObject* object = it.next();
+    // We only have code, sequential strings, or fixed arrays in large
+    // object space, and only fixed arrays need remembered set support.
+    if (object->IsFixedArray()) {
+      // Clear the normal remembered set region of the page;
+      Page* page = Page::FromAddress(object->address());
+      page->ClearRSet();
+
+      // Clear the extra remembered set.
+      int size = object->Size();
+      int extra_rset_bytes = ExtraRSetBytesFor(size);
+      memset(object->address() + size, 0, extra_rset_bytes);
+    }
+  }
+}
+
+
+void LargeObjectSpace::IterateRSet(ObjectSlotCallback copy_object_func) {
+  ASSERT(Page::is_rset_in_use());
+
+  LargeObjectIterator it(this);
+  while (it.has_next()) {
+    // We only have code, sequential strings, or fixed arrays in large
+    // object space, and only fixed arrays can possibly contain pointers to
+    // the young generation.
+    HeapObject* object = it.next();
+    if (object->IsFixedArray()) {
+      // Iterate the normal page remembered set range.
+      Page* page = Page::FromAddress(object->address());
+      Address object_end = object->address() + object->Size();
+      Heap::IterateRSetRange(page->ObjectAreaStart(),
+                             Min(page->ObjectAreaEnd(), object_end),
+                             page->RSetStart(),
+                             copy_object_func);
+
+      // Iterate the extra array elements.
+      if (object_end > page->ObjectAreaEnd()) {
+        Heap::IterateRSetRange(page->ObjectAreaEnd(), object_end,
+                               object_end, copy_object_func);
+      }
+    }
+  }
+}
+
+
+void LargeObjectSpace::FreeUnmarkedObjects() {
+  LargeObjectChunk* previous = NULL;
+  LargeObjectChunk* current = first_chunk_;
+  while (current != NULL) {
+    HeapObject* object = current->GetObject();
+    if (object->IsMarked()) {
+      object->ClearMark();
+      MarkCompactCollector::tracer()->decrement_marked_count();
+      previous = current;
+      current = current->next();
+    } else {
+      Address chunk_address = current->address();
+      size_t chunk_size = current->size();
+
+      // Cut the chunk out from the chunk list.
+      current = current->next();
+      if (previous == NULL) {
+        first_chunk_ = current;
+      } else {
+        previous->set_next(current);
+      }
+
+      // Free the chunk.
+      if (object->IsCode()) {
+        LOG(CodeDeleteEvent(object->address()));
+      }
+      size_ -= chunk_size;
+      page_count_--;
+      MemoryAllocator::FreeRawMemory(chunk_address, chunk_size);
+      LOG(DeleteEvent("LargeObjectChunk", chunk_address));
+    }
+  }
+}
+
+
+bool LargeObjectSpace::Contains(HeapObject* object) {
+  Address address = object->address();
+  Page* page = Page::FromAddress(address);
+
+  SLOW_ASSERT(!page->IsLargeObjectPage()
+              || !FindObject(address)->IsFailure());
+
+  return page->IsLargeObjectPage();
+}
+
+
+#ifdef DEBUG
+// We do not assume that the large object iterator works, because it depends
+// on the invariants we are checking during verification.
+void LargeObjectSpace::Verify() {
+  for (LargeObjectChunk* chunk = first_chunk_;
+       chunk != NULL;
+       chunk = chunk->next()) {
+    // Each chunk contains an object that starts at the large object page's
+    // object area start.
+    HeapObject* object = chunk->GetObject();
+    Page* page = Page::FromAddress(object->address());
+    ASSERT(object->address() == page->ObjectAreaStart());
+
+    // The first word should be a map, and we expect all map pointers to be
+    // in map space.
+    Map* map = object->map();
+    ASSERT(map->IsMap());
+    ASSERT(Heap::map_space()->Contains(map));
+
+    // We have only code, sequential strings, fixed arrays, and byte arrays
+    // in large object space.
+    ASSERT(object->IsCode() || object->IsSeqString()
+           || object->IsFixedArray() || object->IsByteArray());
+
+    // The object itself should look OK.
+    object->Verify();
+
+    // Byte arrays and strings don't have interior pointers.
+    if (object->IsCode()) {
+      VerifyPointersVisitor code_visitor;
+      Code::cast(object)->ConvertICTargetsFromAddressToObject();
+      object->IterateBody(map->instance_type(),
+                          object->Size(),
+                          &code_visitor);
+      Code::cast(object)->ConvertICTargetsFromObjectToAddress();
+    } else if (object->IsFixedArray()) {
+      // We loop over fixed arrays ourselves, rather then using the visitor,
+      // because the visitor doesn't support the start/offset iteration
+      // needed for IsRSetSet.
+      FixedArray* array = FixedArray::cast(object);
+      for (int j = 0; j < array->length(); j++) {
+        Object* element = array->get(j);
+        if (element->IsHeapObject()) {
+          HeapObject* element_object = HeapObject::cast(element);
+          ASSERT(Heap::Contains(element_object));
+          ASSERT(element_object->map()->IsMap());
+          if (Heap::InNewSpace(element_object)) {
+            ASSERT(Page::IsRSetSet(object->address(),
+                                   FixedArray::kHeaderSize + j * kPointerSize));
+          }
+        }
+      }
+    }
+  }
+}
+
+
+void LargeObjectSpace::Print() {
+  LargeObjectIterator it(this);
+  while (it.has_next()) {
+    it.next()->Print();
+  }
+}
+
+
+void LargeObjectSpace::ReportStatistics() {
+  PrintF("  size: %d\n", size_);
+  int num_objects = 0;
+  ClearHistograms();
+  LargeObjectIterator it(this);
+  while (it.has_next()) {
+    num_objects++;
+    CollectHistogramInfo(it.next());
+  }
+
+  PrintF("  number of objects %d\n", num_objects);
+  if (num_objects > 0) ReportHistogram(false);
+}
+
+
+void LargeObjectSpace::CollectCodeStatistics() {
+  LargeObjectIterator obj_it(this);
+  while (obj_it.has_next()) {
+    HeapObject* obj = obj_it.next();
+    if (obj->IsCode()) {
+      Code* code = Code::cast(obj);
+      code_kind_statistics[code->kind()] += code->Size();
+    }
+  }
+}
+
+
+void LargeObjectSpace::PrintRSet() {
+  LargeObjectIterator it(this);
+  while (it.has_next()) {
+    HeapObject* object = it.next();
+    if (object->IsFixedArray()) {
+      Page* page = Page::FromAddress(object->address());
+
+      Address allocation_top = object->address() + object->Size();
+      PrintF("large page 0x%x:\n", page);
+      PrintRSetRange(page->RSetStart(), page->RSetEnd(),
+                     reinterpret_cast<Object**>(object->address()),
+                     allocation_top);
+      int extra_array_bytes = object->Size() - Page::kObjectAreaSize;
+      int extra_rset_bits = RoundUp(extra_array_bytes / kPointerSize,
+                                    kBitsPerInt);
+      PrintF("------------------------------------------------------------"
+             "-----------\n");
+      PrintRSetRange(allocation_top,
+                     allocation_top + extra_rset_bits / kBitsPerByte,
+                     reinterpret_cast<Object**>(object->address()
+                                                + Page::kObjectAreaSize),
+                     allocation_top);
+      PrintF("\n");
+    }
+  }
+}
+#endif  // DEBUG
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/spaces.h b/deps/v8/src/spaces.h
new file mode 100644
index 0000000..3138cc3
--- /dev/null
+++ b/deps/v8/src/spaces.h
@@ -0,0 +1,1703 @@
+// 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_SPACES_H_
+#define V8_SPACES_H_
+
+#include "list-inl.h"
+#include "log.h"
+
+namespace v8 { namespace internal {
+
+// -----------------------------------------------------------------------------
+// Heap structures:
+//
+// A JS heap consists of a young generation, an old generation, and a large
+// object space. The young generation is divided into two semispaces. A
+// scavenger implements Cheney's copying algorithm. The old generation is
+// separated into a map space and an old object space. The map space contains
+// all (and only) map objects, the rest of old objects go into the old space.
+// The old generation is collected by a mark-sweep-compact collector.
+//
+// The semispaces of the young generation are contiguous.  The old and map
+// spaces consists of a list of pages. A page has a page header, a remembered
+// set area, and an object area. A page size is deliberately chosen as 8K
+// bytes. The first word of a page is an opaque page header that has the
+// address of the next page and its ownership information. The second word may
+// have the allocation top address of this page. The next 248 bytes are
+// remembered sets. Heap objects are aligned to the pointer size (4 bytes). A
+// remembered set bit corresponds to a pointer in the object area.
+//
+// There is a separate large object space for objects larger than
+// Page::kMaxHeapObjectSize, so that they do not have to move during
+// collection.  The large object space is paged and uses the same remembered
+// set implementation.  Pages in large object space may be larger than 8K.
+//
+// NOTE: The mark-compact collector rebuilds the remembered set after a
+// collection. It reuses first a few words of the remembered set for
+// bookkeeping relocation information.
+
+
+// Some assertion macros used in the debugging mode.
+
+#define ASSERT_PAGE_ALIGNED(address)                  \
+  ASSERT((OffsetFrom(address) & Page::kPageAlignmentMask) == 0)
+
+#define ASSERT_OBJECT_ALIGNED(address)                \
+  ASSERT((OffsetFrom(address) & kObjectAlignmentMask) == 0)
+
+#define ASSERT_OBJECT_SIZE(size)                      \
+  ASSERT((0 < size) && (size <= Page::kMaxHeapObjectSize))
+
+#define ASSERT_PAGE_OFFSET(offset)                    \
+  ASSERT((Page::kObjectStartOffset <= offset)         \
+      && (offset <= Page::kPageSize))
+
+#define ASSERT_MAP_PAGE_INDEX(index)                            \
+  ASSERT((0 <= index) && (index <= MapSpace::kMaxMapPageIndex))
+
+
+class PagedSpace;
+class MemoryAllocator;
+class AllocationInfo;
+
+// -----------------------------------------------------------------------------
+// A page normally has 8K bytes. Large object pages may be larger.  A page
+// address is always aligned to the 8K page size.  A page is divided into
+// three areas: the first two words are used for bookkeeping, the next 248
+// bytes are used as remembered set, and the rest of the page is the object
+// area.
+//
+// Pointers are aligned to the pointer size (4 bytes), only 1 bit is needed
+// for a pointer in the remembered set. Given an address, its remembered set
+// bit position (offset from the start of the page) is calculated by dividing
+// its page offset by 32. Therefore, the object area in a page starts at the
+// 256th byte (8K/32). Bytes 0 to 255 do not need the remembered set, so that
+// the first two words (64 bits) in a page can be used for other purposes.
+//
+// The mark-compact collector transforms a map pointer into a page index and a
+// page offset. The map space can have up to 1024 pages, and 8M bytes (1024 *
+// 8K) in total.  Because a map pointer is aligned to the pointer size (4
+// bytes), 11 bits are enough to encode the page offset. 21 bits (10 for the
+// page index + 11 for the offset in the page) are required to encode a map
+// pointer.
+//
+// The only way to get a page pointer is by calling factory methods:
+//   Page* p = Page::FromAddress(addr); or
+//   Page* p = Page::FromAllocationTop(top);
+class Page {
+ public:
+  // Returns the page containing a given address. The address ranges
+  // from [page_addr .. page_addr + kPageSize[
+  //
+  // Note that this function only works for addresses in normal paged
+  // spaces and addresses in the first 8K of large object pages (ie,
+  // the start of large objects but not necessarily derived pointers
+  // within them).
+  INLINE(static Page* FromAddress(Address a)) {
+    return reinterpret_cast<Page*>(OffsetFrom(a) & ~kPageAlignmentMask);
+  }
+
+  // Returns the page containing an allocation top. Because an allocation
+  // top address can be the upper bound of the page, we need to subtract
+  // it with kPointerSize first. The address ranges from
+  // [page_addr + kObjectStartOffset .. page_addr + kPageSize].
+  INLINE(static Page* FromAllocationTop(Address top)) {
+    Page* p = FromAddress(top - kPointerSize);
+    ASSERT_PAGE_OFFSET(p->Offset(top));
+    return p;
+  }
+
+  // Returns the start address of this page.
+  Address address() { return reinterpret_cast<Address>(this); }
+
+  // Checks whether this is a valid page address.
+  bool is_valid() { return address() != NULL; }
+
+  // Returns the next page of this page.
+  inline Page* next_page();
+
+  // Return the end of allocation in this page. Undefined for unused pages.
+  inline Address AllocationTop();
+
+  // Returns the start address of the object area in this page.
+  Address ObjectAreaStart() { return address() + kObjectStartOffset; }
+
+  // Returns the end address (exclusive) of the object area in this page.
+  Address ObjectAreaEnd() { return address() + Page::kPageSize; }
+
+  // Returns the start address of the remembered set area.
+  Address RSetStart() { return address() + kRSetStartOffset; }
+
+  // Returns the end address of the remembered set area (exclusive).
+  Address RSetEnd() { return address() + kRSetEndOffset; }
+
+  // Checks whether an address is page aligned.
+  static bool IsAlignedToPageSize(Address a) {
+    return 0 == (OffsetFrom(a) & kPageAlignmentMask);
+  }
+
+  // True if this page is a large object page.
+  bool IsLargeObjectPage() { return (is_normal_page & 0x1) == 0; }
+
+  // Returns the offset of a given address to this page.
+  INLINE(int Offset(Address a)) {
+    int offset = a - address();
+    ASSERT_PAGE_OFFSET(offset);
+    return offset;
+  }
+
+  // Returns the address for a given offset to the this page.
+  Address OffsetToAddress(int offset) {
+    ASSERT_PAGE_OFFSET(offset);
+    return address() + offset;
+  }
+
+  // ---------------------------------------------------------------------
+  // Remembered set support
+
+  // Clears remembered set in this page.
+  inline void ClearRSet();
+
+  // Return the address of the remembered set word corresponding to an
+  // object address/offset pair, and the bit encoded as a single-bit
+  // mask in the output parameter 'bitmask'.
+  INLINE(static Address ComputeRSetBitPosition(Address address, int offset,
+                                               uint32_t* bitmask));
+
+  // Sets the corresponding remembered set bit for a given address.
+  INLINE(static void SetRSet(Address address, int offset));
+
+  // Clears the corresponding remembered set bit for a given address.
+  static inline void UnsetRSet(Address address, int offset);
+
+  // Checks whether the remembered set bit for a given address is set.
+  static inline bool IsRSetSet(Address address, int offset);
+
+#ifdef DEBUG
+  // Use a state to mark whether remembered set space can be used for other
+  // purposes.
+  enum RSetState { IN_USE,  NOT_IN_USE };
+  static bool is_rset_in_use() { return rset_state_ == IN_USE; }
+  static void set_rset_state(RSetState state) { rset_state_ = state; }
+#endif
+
+  // 8K bytes per page.
+  static const int kPageSizeBits = 13;
+
+  // Page size in bytes.  This must be a multiple of the OS page size.
+  static const int kPageSize = 1 << kPageSizeBits;
+
+  // Page size mask.
+  static const int kPageAlignmentMask = (1 << kPageSizeBits) - 1;
+
+  // The end offset of the remembered set in a page
+  // (heaps are aligned to pointer size).
+  static const int kRSetEndOffset= kPageSize / kBitsPerPointer;
+
+  // The start offset of the remembered set in a page.
+  static const int kRSetStartOffset = kRSetEndOffset / kBitsPerPointer;
+
+  // The start offset of the object area in a page.
+  static const int kObjectStartOffset = kRSetEndOffset;
+
+  // Object area size in bytes.
+  static const int kObjectAreaSize = kPageSize - kObjectStartOffset;
+
+  // Maximum object size that fits in a page.
+  static const int kMaxHeapObjectSize = kObjectAreaSize;
+
+  //---------------------------------------------------------------------------
+  // Page header description.
+  //
+  // If a page is not in the large object space, the first word,
+  // opaque_header, encodes the next page address (aligned to kPageSize 8K)
+  // and the chunk number (0 ~ 8K-1).  Only MemoryAllocator should use
+  // opaque_header. The value range of the opaque_header is [0..kPageSize[,
+  // or [next_page_start, next_page_end[. It cannot point to a valid address
+  // in the current page.  If a page is in the large object space, the first
+  // word *may* (if the page start and large object chunk start are the
+  // same) contain the address of the next large object chunk.
+  int opaque_header;
+
+  // If the page is not in the large object space, the low-order bit of the
+  // second word is set. If the page is in the large object space, the
+  // second word *may* (if the page start and large object chunk start are
+  // the same) contain the large object chunk size.  In either case, the
+  // low-order bit for large object pages will be cleared.
+  int is_normal_page;
+
+  // The following fields overlap with remembered set, they can only
+  // be used in the mark-compact collector when remembered set is not
+  // used.
+
+  // The allocation pointer after relocating objects to this page.
+  Address mc_relocation_top;
+
+  // The index of the page in its owner space.
+  int mc_page_index;
+
+  // The forwarding address of the first live object in this page.
+  Address mc_first_forwarded;
+
+#ifdef DEBUG
+ private:
+  static RSetState rset_state_;  // state of the remembered set
+#endif
+};
+
+
+// ----------------------------------------------------------------------------
+// Space is the abstract superclass for all allocation spaces.
+class Space : public Malloced {
+ public:
+  Space(AllocationSpace id, Executability executable)
+      : id_(id), executable_(executable) {}
+
+  virtual ~Space() {}
+
+  // Does the space need executable memory?
+  Executability executable() { return executable_; }
+
+  // Identity used in error reporting.
+  AllocationSpace identity() { return id_; }
+
+  virtual int Size() = 0;
+
+#ifdef DEBUG
+  virtual void Verify() = 0;
+  virtual void Print() = 0;
+#endif
+
+ private:
+  AllocationSpace id_;
+  Executability executable_;
+};
+
+
+// ----------------------------------------------------------------------------
+// A space acquires chunks of memory from the operating system. The memory
+// allocator manages chunks for the paged heap spaces (old space and map
+// space).  A paged chunk consists of pages. Pages in a chunk have contiguous
+// addresses and are linked as a list.
+//
+// The allocator keeps an initial chunk which is used for the new space.  The
+// leftover regions of the initial chunk are used for the initial chunks of
+// old space and map space if they are big enough to hold at least one page.
+// The allocator assumes that there is one old space and one map space, each
+// expands the space by allocating kPagesPerChunk pages except the last
+// expansion (before running out of space).  The first chunk may contain fewer
+// than kPagesPerChunk pages as well.
+//
+// The memory allocator also allocates chunks for the large object space, but
+// they are managed by the space itself.  The new space does not expand.
+
+class MemoryAllocator : public AllStatic {
+ public:
+  // Initializes its internal bookkeeping structures.
+  // Max capacity of the total space.
+  static bool Setup(int max_capacity);
+
+  // Deletes valid chunks.
+  static void TearDown();
+
+  // Reserves an initial address range of virtual memory to be split between
+  // the two new space semispaces, the old space, and the map space.  The
+  // memory is not yet committed or assigned to spaces and split into pages.
+  // The initial chunk is unmapped when the memory allocator is torn down.
+  // This function should only be called when there is not already a reserved
+  // initial chunk (initial_chunk_ should be NULL).  It returns the start
+  // address of the initial chunk if successful, with the side effect of
+  // setting the initial chunk, or else NULL if unsuccessful and leaves the
+  // initial chunk NULL.
+  static void* ReserveInitialChunk(const size_t requested);
+
+  // Commits pages from an as-yet-unmanaged block of virtual memory into a
+  // paged space.  The block should be part of the initial chunk reserved via
+  // a call to ReserveInitialChunk.  The number of pages is always returned in
+  // the output parameter num_pages.  This function assumes that the start
+  // address is non-null and that it is big enough to hold at least one
+  // page-aligned page.  The call always succeeds, and num_pages is always
+  // greater than zero.
+  static Page* CommitPages(Address start, size_t size, PagedSpace* owner,
+                           int* num_pages);
+
+  // Commit a contiguous block of memory from the initial chunk.  Assumes that
+  // the address is not NULL, the size is greater than zero, and that the
+  // block is contained in the initial chunk.  Returns true if it succeeded
+  // and false otherwise.
+  static bool CommitBlock(Address start, size_t size, Executability executable);
+
+  // Attempts to allocate the requested (non-zero) number of pages from the
+  // OS.  Fewer pages might be allocated than requested. If it fails to
+  // allocate memory for the OS or cannot allocate a single page, this
+  // function returns an invalid page pointer (NULL). The caller must check
+  // whether the returned page is valid (by calling Page::is_valid()).  It is
+  // guaranteed that allocated pages have contiguous addresses.  The actual
+  // number of allocated page is returned in the output parameter
+  // allocated_pages.
+  static Page* AllocatePages(int requested_pages, int* allocated_pages,
+                             PagedSpace* owner);
+
+  // Frees pages from a given page and after. If 'p' is the first page
+  // of a chunk, pages from 'p' are freed and this function returns an
+  // invalid page pointer. Otherwise, the function searches a page
+  // after 'p' that is the first page of a chunk. Pages after the
+  // found page are freed and the function returns 'p'.
+  static Page* FreePages(Page* p);
+
+  // Allocates and frees raw memory of certain size.
+  // These are just thin wrappers around OS::Allocate and OS::Free,
+  // but keep track of allocated bytes as part of heap.
+  static void* AllocateRawMemory(const size_t requested,
+                                 size_t* allocated,
+                                 Executability executable);
+  static void FreeRawMemory(void* buf, size_t length);
+
+  // Returns the maximum available bytes of heaps.
+  static int Available() { return capacity_ < size_ ? 0 : capacity_ - size_; }
+
+  // Returns maximum available bytes that the old space can have.
+  static int MaxAvailable() {
+    return (Available() / Page::kPageSize) * Page::kObjectAreaSize;
+  }
+
+  // Links two pages.
+  static inline void SetNextPage(Page* prev, Page* next);
+
+  // Returns the next page of a given page.
+  static inline Page* GetNextPage(Page* p);
+
+  // Checks whether a page belongs to a space.
+  static inline bool IsPageInSpace(Page* p, PagedSpace* space);
+
+  // Returns the space that owns the given page.
+  static inline PagedSpace* PageOwner(Page* page);
+
+  // Finds the first/last page in the same chunk as a given page.
+  static Page* FindFirstPageInSameChunk(Page* p);
+  static Page* FindLastPageInSameChunk(Page* p);
+
+#ifdef ENABLE_HEAP_PROTECTION
+  // Protect/unprotect a block of memory by marking it read-only/writable.
+  static inline void Protect(Address start, size_t size);
+  static inline void Unprotect(Address start, size_t size,
+                               Executability executable);
+
+  // Protect/unprotect a chunk given a page in the chunk.
+  static inline void ProtectChunkFromPage(Page* page);
+  static inline void UnprotectChunkFromPage(Page* page);
+#endif
+
+#ifdef DEBUG
+  // Reports statistic info of the space.
+  static void ReportStatistics();
+#endif
+
+  // Due to encoding limitation, we can only have 8K chunks.
+  static const int kMaxNofChunks = 1 << Page::kPageSizeBits;
+  // If a chunk has at least 32 pages, the maximum heap size is about
+  // 8 * 1024 * 32 * 8K = 2G bytes.
+  static const int kPagesPerChunk = 64;
+  static const int kChunkSize = kPagesPerChunk * Page::kPageSize;
+
+ private:
+  // Maximum space size in bytes.
+  static int capacity_;
+
+  // Allocated space size in bytes.
+  static int size_;
+
+  // The initial chunk of virtual memory.
+  static VirtualMemory* initial_chunk_;
+
+  // Allocated chunk info: chunk start address, chunk size, and owning space.
+  class ChunkInfo BASE_EMBEDDED {
+   public:
+    ChunkInfo() : address_(NULL), size_(0), owner_(NULL) {}
+    void init(Address a, size_t s, PagedSpace* o) {
+      address_ = a;
+      size_ = s;
+      owner_ = o;
+    }
+    Address address() { return address_; }
+    size_t size() { return size_; }
+    PagedSpace* owner() { return owner_; }
+
+   private:
+    Address address_;
+    size_t size_;
+    PagedSpace* owner_;
+  };
+
+  // Chunks_, free_chunk_ids_ and top_ act as a stack of free chunk ids.
+  static List<ChunkInfo> chunks_;
+  static List<int> free_chunk_ids_;
+  static int max_nof_chunks_;
+  static int top_;
+
+  // Push/pop a free chunk id onto/from the stack.
+  static void Push(int free_chunk_id);
+  static int Pop();
+  static bool OutOfChunkIds() { return top_ == 0; }
+
+  // Frees a chunk.
+  static void DeleteChunk(int chunk_id);
+
+  // Basic check whether a chunk id is in the valid range.
+  static inline bool IsValidChunkId(int chunk_id);
+
+  // Checks whether a chunk id identifies an allocated chunk.
+  static inline bool IsValidChunk(int chunk_id);
+
+  // Returns the chunk id that a page belongs to.
+  static inline int GetChunkId(Page* p);
+
+  // True if the address lies in the initial chunk.
+  static inline bool InInitialChunk(Address address);
+
+  // Initializes pages in a chunk. Returns the first page address.
+  // This function and GetChunkId() are provided for the mark-compact
+  // collector to rebuild page headers in the from space, which is
+  // used as a marking stack and its page headers are destroyed.
+  static Page* InitializePagesInChunk(int chunk_id, int pages_in_chunk,
+                                      PagedSpace* owner);
+};
+
+
+// -----------------------------------------------------------------------------
+// Interface for heap object iterator to be implemented by all object space
+// object iterators.
+//
+// NOTE: The space specific object iterators also implements the own has_next()
+//       and next() methods which are used to avoid using virtual functions
+//       iterating a specific space.
+
+class ObjectIterator : public Malloced {
+ public:
+  virtual ~ObjectIterator() { }
+
+  virtual bool has_next_object() = 0;
+  virtual HeapObject* next_object() = 0;
+};
+
+
+// -----------------------------------------------------------------------------
+// Heap object iterator in new/old/map spaces.
+//
+// A HeapObjectIterator iterates objects from a given address to the
+// top of a space. The given address must be below the current
+// allocation pointer (space top). If the space top changes during
+// iteration (because of allocating new objects), the iterator does
+// not iterate new objects. The caller function must create a new
+// iterator starting from the old top in order to visit these new
+// objects. Heap::Scavenage() is such an example.
+
+class HeapObjectIterator: public ObjectIterator {
+ public:
+  // Creates a new object iterator in a given space. If a start
+  // address is not given, the iterator starts from the space bottom.
+  // If the size function is not given, the iterator calls the default
+  // Object::Size().
+  explicit HeapObjectIterator(PagedSpace* space);
+  HeapObjectIterator(PagedSpace* space, HeapObjectCallback size_func);
+  HeapObjectIterator(PagedSpace* space, Address start);
+  HeapObjectIterator(PagedSpace* space,
+                     Address start,
+                     HeapObjectCallback size_func);
+
+  inline bool has_next();
+  inline HeapObject* next();
+
+  // implementation of ObjectIterator.
+  virtual bool has_next_object() { return has_next(); }
+  virtual HeapObject* next_object() { return next(); }
+
+ private:
+  Address cur_addr_;  // current iteration point
+  Address end_addr_;  // end iteration point
+  Address cur_limit_;  // current page limit
+  HeapObjectCallback size_func_;  // size function
+  Page* end_page_;  // caches the page of the end address
+
+  // Slow path of has_next, checks whether there are more objects in
+  // the next page.
+  bool HasNextInNextPage();
+
+  // Initializes fields.
+  void Initialize(Address start, Address end, HeapObjectCallback size_func);
+
+#ifdef DEBUG
+  // Verifies whether fields have valid values.
+  void Verify();
+#endif
+};
+
+
+// -----------------------------------------------------------------------------
+// A PageIterator iterates pages in a space.
+//
+// The PageIterator class provides three modes for iterating pages in a space:
+//   PAGES_IN_USE iterates pages that are in use by the allocator;
+//   PAGES_USED_BY_GC iterates pages that hold relocated objects during a
+//                    mark-compact collection;
+//   ALL_PAGES iterates all pages in the space.
+
+class PageIterator BASE_EMBEDDED {
+ public:
+  enum Mode {PAGES_IN_USE, PAGES_USED_BY_MC, ALL_PAGES};
+
+  PageIterator(PagedSpace* space, Mode mode);
+
+  inline bool has_next();
+  inline Page* next();
+
+ private:
+  Page* cur_page_;  // next page to return
+  Page* stop_page_;  // page where to stop
+};
+
+
+// -----------------------------------------------------------------------------
+// A space has a list of pages. The next page can be accessed via
+// Page::next_page() call. The next page of the last page is an
+// invalid page pointer. A space can expand and shrink dynamically.
+
+// An abstraction of allocation and relocation pointers in a page-structured
+// space.
+class AllocationInfo {
+ public:
+  Address top;  // current allocation top
+  Address limit;  // current allocation limit
+
+#ifdef DEBUG
+  bool VerifyPagedAllocation() {
+    return (Page::FromAllocationTop(top) == Page::FromAllocationTop(limit))
+        && (top <= limit);
+  }
+#endif
+};
+
+
+// An abstraction of the accounting statistics of a page-structured space.
+// The 'capacity' of a space is the number of object-area bytes (ie, not
+// including page bookkeeping structures) currently in the space. The 'size'
+// of a space is the number of allocated bytes, the 'waste' in the space is
+// the number of bytes that are not allocated and not available to
+// allocation without reorganizing the space via a GC (eg, small blocks due
+// to internal fragmentation, top of page areas in map space), and the bytes
+// 'available' is the number of unallocated bytes that are not waste.  The
+// capacity is the sum of size, waste, and available.
+//
+// The stats are only set by functions that ensure they stay balanced. These
+// functions increase or decrease one of the non-capacity stats in
+// conjunction with capacity, or else they always balance increases and
+// decreases to the non-capacity stats.
+class AllocationStats BASE_EMBEDDED {
+ public:
+  AllocationStats() { Clear(); }
+
+  // Zero out all the allocation statistics (ie, no capacity).
+  void Clear() {
+    capacity_ = 0;
+    available_ = 0;
+    size_ = 0;
+    waste_ = 0;
+  }
+
+  // Reset the allocation statistics (ie, available = capacity with no
+  // wasted or allocated bytes).
+  void Reset() {
+    available_ = capacity_;
+    size_ = 0;
+    waste_ = 0;
+  }
+
+  // Accessors for the allocation statistics.
+  int Capacity() { return capacity_; }
+  int Available() { return available_; }
+  int Size() { return size_; }
+  int Waste() { return waste_; }
+
+  // Grow the space by adding available bytes.
+  void ExpandSpace(int size_in_bytes) {
+    capacity_ += size_in_bytes;
+    available_ += size_in_bytes;
+  }
+
+  // Shrink the space by removing available bytes.
+  void ShrinkSpace(int size_in_bytes) {
+    capacity_ -= size_in_bytes;
+    available_ -= size_in_bytes;
+  }
+
+  // Allocate from available bytes (available -> size).
+  void AllocateBytes(int size_in_bytes) {
+    available_ -= size_in_bytes;
+    size_ += size_in_bytes;
+  }
+
+  // Free allocated bytes, making them available (size -> available).
+  void DeallocateBytes(int size_in_bytes) {
+    size_ -= size_in_bytes;
+    available_ += size_in_bytes;
+  }
+
+  // Waste free bytes (available -> waste).
+  void WasteBytes(int size_in_bytes) {
+    available_ -= size_in_bytes;
+    waste_ += size_in_bytes;
+  }
+
+  // Consider the wasted bytes to be allocated, as they contain filler
+  // objects (waste -> size).
+  void FillWastedBytes(int size_in_bytes) {
+    waste_ -= size_in_bytes;
+    size_ += size_in_bytes;
+  }
+
+ private:
+  int capacity_;
+  int available_;
+  int size_;
+  int waste_;
+};
+
+
+class PagedSpace : public Space {
+ public:
+  // Creates a space with a maximum capacity, and an id.
+  PagedSpace(int max_capacity, AllocationSpace id, Executability executable);
+
+  virtual ~PagedSpace() {}
+
+  // Set up the space using the given address range of virtual memory (from
+  // the memory allocator's initial chunk) if possible.  If the block of
+  // addresses is not big enough to contain a single page-aligned page, a
+  // fresh chunk will be allocated.
+  bool Setup(Address start, size_t size);
+
+  // Returns true if the space has been successfully set up and not
+  // subsequently torn down.
+  bool HasBeenSetup();
+
+  // Cleans up the space, frees all pages in this space except those belonging
+  // to the initial chunk, uncommits addresses in the initial chunk.
+  void TearDown();
+
+  // Checks whether an object/address is in this space.
+  inline bool Contains(Address a);
+  bool Contains(HeapObject* o) { return Contains(o->address()); }
+
+  // Given an address occupied by a live object, return that object if it is
+  // in this space, or Failure::Exception() if it is not. The implementation
+  // iterates over objects in the page containing the address, the cost is
+  // linear in the number of objects in the page. It may be slow.
+  Object* FindObject(Address addr);
+
+  // Checks whether page is currently in use by this space.
+  bool IsUsed(Page* page);
+
+  // Clears remembered sets of pages in this space.
+  void ClearRSet();
+
+  // Prepares for a mark-compact GC.
+  virtual void PrepareForMarkCompact(bool will_compact) = 0;
+
+  virtual Address PageAllocationTop(Page* page) = 0;
+
+  // Current capacity without growing (Size() + Available() + Waste()).
+  int Capacity() { return accounting_stats_.Capacity(); }
+
+  // Available bytes without growing.
+  int Available() { return accounting_stats_.Available(); }
+
+  // Allocated bytes in this space.
+  virtual int Size() { return accounting_stats_.Size(); }
+
+  // Wasted bytes due to fragmentation and not recoverable until the
+  // next GC of this space.
+  int Waste() { return accounting_stats_.Waste(); }
+
+  // Returns the address of the first object in this space.
+  Address bottom() { return first_page_->ObjectAreaStart(); }
+
+  // Returns the allocation pointer in this space.
+  Address top() { return allocation_info_.top; }
+
+  // Allocate the requested number of bytes in the space if possible, return a
+  // failure object if not.
+  inline Object* AllocateRaw(int size_in_bytes);
+
+  // Allocate the requested number of bytes for relocation during mark-compact
+  // collection.
+  inline Object* MCAllocateRaw(int size_in_bytes);
+
+
+  // ---------------------------------------------------------------------------
+  // Mark-compact collection support functions
+
+  // Set the relocation point to the beginning of the space.
+  void MCResetRelocationInfo();
+
+  // Writes relocation info to the top page.
+  void MCWriteRelocationInfoToPage() {
+    TopPageOf(mc_forwarding_info_)->mc_relocation_top = mc_forwarding_info_.top;
+  }
+
+  // Computes the offset of a given address in this space to the beginning
+  // of the space.
+  int MCSpaceOffsetForAddress(Address addr);
+
+  // Updates the allocation pointer to the relocation top after a mark-compact
+  // collection.
+  virtual void MCCommitRelocationInfo() = 0;
+
+  // Releases half of unused pages.
+  void Shrink();
+
+  // Ensures that the capacity is at least 'capacity'. Returns false on failure.
+  bool EnsureCapacity(int capacity);
+
+#ifdef ENABLE_HEAP_PROTECTION
+  // Protect/unprotect the space by marking it read-only/writable.
+  void Protect();
+  void Unprotect();
+#endif
+
+#ifdef DEBUG
+  // Print meta info and objects in this space.
+  virtual void Print();
+
+  // Report code object related statistics
+  void CollectCodeStatistics();
+  static void ReportCodeStatistics();
+  static void ResetCodeStatistics();
+#endif
+
+ protected:
+  // Maximum capacity of this space.
+  int max_capacity_;
+
+  // Accounting information for this space.
+  AllocationStats accounting_stats_;
+
+  // The first page in this space.
+  Page* first_page_;
+
+  // Normal allocation information.
+  AllocationInfo allocation_info_;
+
+  // Relocation information during mark-compact collections.
+  AllocationInfo mc_forwarding_info_;
+
+  // Sets allocation pointer to a page bottom.
+  static void SetAllocationInfo(AllocationInfo* alloc_info, Page* p);
+
+  // Returns the top page specified by an allocation info structure.
+  static Page* TopPageOf(AllocationInfo alloc_info) {
+    return Page::FromAllocationTop(alloc_info.limit);
+  }
+
+  // Expands the space by allocating a fixed number of pages. Returns false if
+  // it cannot allocate requested number of pages from OS. Newly allocated
+  // pages are append to the last_page;
+  bool Expand(Page* last_page);
+
+  // Generic fast case allocation function that tries linear allocation in
+  // the top page of 'alloc_info'.  Returns NULL on failure.
+  inline HeapObject* AllocateLinearly(AllocationInfo* alloc_info,
+                                      int size_in_bytes);
+
+  // During normal allocation or deserialization, roll to the next page in
+  // the space (there is assumed to be one) and allocate there.  This
+  // function is space-dependent.
+  virtual HeapObject* AllocateInNextPage(Page* current_page,
+                                         int size_in_bytes) = 0;
+
+  // Slow path of AllocateRaw.  This function is space-dependent.
+  virtual HeapObject* SlowAllocateRaw(int size_in_bytes) = 0;
+
+  // Slow path of MCAllocateRaw.
+  HeapObject* SlowMCAllocateRaw(int size_in_bytes);
+
+#ifdef DEBUG
+  void DoPrintRSet(const char* space_name);
+#endif
+ private:
+  // Returns the page of the allocation pointer.
+  Page* AllocationTopPage() { return TopPageOf(allocation_info_); }
+
+  // Returns a pointer to the page of the relocation pointer.
+  Page* MCRelocationTopPage() { return TopPageOf(mc_forwarding_info_); }
+
+#ifdef DEBUG
+  // Returns the number of total pages in this space.
+  int CountTotalPages();
+#endif
+
+  friend class PageIterator;
+};
+
+
+#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
+// HistogramInfo class for recording a single "bar" of a histogram.  This
+// class is used for collecting statistics to print to stdout (when compiled
+// with DEBUG) or to the log file (when compiled with
+// ENABLE_LOGGING_AND_PROFILING).
+class HistogramInfo BASE_EMBEDDED {
+ public:
+  HistogramInfo() : number_(0), bytes_(0) {}
+
+  const char* name() { return name_; }
+  void set_name(const char* name) { name_ = name; }
+
+  int number() { return number_; }
+  void increment_number(int num) { number_ += num; }
+
+  int bytes() { return bytes_; }
+  void increment_bytes(int size) { bytes_ += size; }
+
+  // Clear the number of objects and size fields, but not the name.
+  void clear() {
+    number_ = 0;
+    bytes_ = 0;
+  }
+
+ private:
+  const char* name_;
+  int number_;
+  int bytes_;
+};
+#endif
+
+
+// -----------------------------------------------------------------------------
+// SemiSpace in young generation
+//
+// A semispace is a contiguous chunk of memory. The mark-compact collector
+// uses the memory in the from space as a marking stack when tracing live
+// objects.
+
+class SemiSpace : public Space {
+ public:
+  // Constructor.
+  SemiSpace() :Space(NEW_SPACE, NOT_EXECUTABLE) {
+    start_ = NULL;
+    age_mark_ = NULL;
+  }
+
+  // Sets up the semispace using the given chunk.
+  bool Setup(Address start, int initial_capacity, int maximum_capacity);
+
+  // Tear down the space.  Heap memory was not allocated by the space, so it
+  // is not deallocated here.
+  void TearDown();
+
+  // True if the space has been set up but not torn down.
+  bool HasBeenSetup() { return start_ != NULL; }
+
+  // Double the size of the semispace by committing extra virtual memory.
+  // Assumes that the caller has checked that the semispace has not reached
+  // its maximum capacity (and thus there is space available in the reserved
+  // address range to grow).
+  bool Double();
+
+  // Returns the start address of the space.
+  Address low() { return start_; }
+  // Returns one past the end address of the space.
+  Address high() { return low() + capacity_; }
+
+  // Age mark accessors.
+  Address age_mark() { return age_mark_; }
+  void set_age_mark(Address mark) { age_mark_ = mark; }
+
+  // True if the address is in the address range of this semispace (not
+  // necessarily below the allocation pointer).
+  bool Contains(Address a) {
+    return (reinterpret_cast<uint32_t>(a) & address_mask_)
+           == reinterpret_cast<uint32_t>(start_);
+  }
+
+  // True if the object is a heap object in the address range of this
+  // semispace (not necessarily below the allocation pointer).
+  bool Contains(Object* o) {
+    return (reinterpret_cast<uint32_t>(o) & object_mask_) == object_expected_;
+  }
+
+  // The offset of an address from the beginning of the space.
+  int SpaceOffsetForAddress(Address addr) { return addr - low(); }
+
+  // If we don't have this here then SemiSpace will be abstract.  However
+  // it should never be called.
+  virtual int Size() {
+    UNREACHABLE();
+    return 0;
+  }
+
+#ifdef DEBUG
+  virtual void Print();
+  virtual void Verify();
+#endif
+
+ private:
+  // The current and maximum capacity of the space.
+  int capacity_;
+  int maximum_capacity_;
+
+  // The start address of the space.
+  Address start_;
+  // Used to govern object promotion during mark-compact collection.
+  Address age_mark_;
+
+  // Masks and comparison values to test for containment in this semispace.
+  uint32_t address_mask_;
+  uint32_t object_mask_;
+  uint32_t object_expected_;
+
+ public:
+  TRACK_MEMORY("SemiSpace")
+};
+
+
+// A SemiSpaceIterator is an ObjectIterator that iterates over the active
+// semispace of the heap's new space.  It iterates over the objects in the
+// semispace from a given start address (defaulting to the bottom of the
+// semispace) to the top of the semispace.  New objects allocated after the
+// iterator is created are not iterated.
+class SemiSpaceIterator : public ObjectIterator {
+ public:
+  // Create an iterator over the objects in the given space.  If no start
+  // address is given, the iterator starts from the bottom of the space.  If
+  // no size function is given, the iterator calls Object::Size().
+  explicit SemiSpaceIterator(NewSpace* space);
+  SemiSpaceIterator(NewSpace* space, HeapObjectCallback size_func);
+  SemiSpaceIterator(NewSpace* space, Address start);
+
+  bool has_next() {return current_ < limit_; }
+
+  HeapObject* next() {
+    ASSERT(has_next());
+
+    HeapObject* object = HeapObject::FromAddress(current_);
+    int size = (size_func_ == NULL) ? object->Size() : size_func_(object);
+    ASSERT_OBJECT_SIZE(size);
+
+    current_ += size;
+    return object;
+  }
+
+  // Implementation of the ObjectIterator functions.
+  virtual bool has_next_object() { return has_next(); }
+  virtual HeapObject* next_object() { return next(); }
+
+ private:
+  void Initialize(NewSpace* space, Address start, Address end,
+                  HeapObjectCallback size_func);
+
+  // The semispace.
+  SemiSpace* space_;
+  // The current iteration point.
+  Address current_;
+  // The end of iteration.
+  Address limit_;
+  // The callback function.
+  HeapObjectCallback size_func_;
+};
+
+
+// -----------------------------------------------------------------------------
+// The young generation space.
+//
+// The new space consists of a contiguous pair of semispaces.  It simply
+// forwards most functions to the appropriate semispace.
+
+class NewSpace : public Space {
+ public:
+  // Constructor.
+  NewSpace() : Space(NEW_SPACE, NOT_EXECUTABLE) {}
+
+  // Sets up the new space using the given chunk.
+  bool Setup(Address start, int size);
+
+  // Tears down the space.  Heap memory was not allocated by the space, so it
+  // is not deallocated here.
+  void TearDown();
+
+  // True if the space has been set up but not torn down.
+  bool HasBeenSetup() {
+    return to_space_.HasBeenSetup() && from_space_.HasBeenSetup();
+  }
+
+  // Flip the pair of spaces.
+  void Flip();
+
+  // Doubles the capacity of the semispaces.  Assumes that they are not at
+  // their maximum capacity.  Returns a flag indicating success or failure.
+  bool Double();
+
+  // True if the address or object lies in the address range of either
+  // semispace (not necessarily below the allocation pointer).
+  bool Contains(Address a) {
+    return (reinterpret_cast<uint32_t>(a) & address_mask_)
+        == reinterpret_cast<uint32_t>(start_);
+  }
+  bool Contains(Object* o) {
+    return (reinterpret_cast<uint32_t>(o) & object_mask_) == object_expected_;
+  }
+
+  // Return the allocated bytes in the active semispace.
+  virtual int Size() { return top() - bottom(); }
+  // Return the current capacity of a semispace.
+  int Capacity() { return capacity_; }
+  // Return the available bytes without growing in the active semispace.
+  int Available() { return Capacity() - Size(); }
+
+  // Return the maximum capacity of a semispace.
+  int MaximumCapacity() { return maximum_capacity_; }
+
+  // Return the address of the allocation pointer in the active semispace.
+  Address top() { return allocation_info_.top; }
+  // Return the address of the first object in the active semispace.
+  Address bottom() { return to_space_.low(); }
+
+  // Get the age mark of the inactive semispace.
+  Address age_mark() { return from_space_.age_mark(); }
+  // Set the age mark in the active semispace.
+  void set_age_mark(Address mark) { to_space_.set_age_mark(mark); }
+
+  // The start address of the space and a bit mask. Anding an address in the
+  // new space with the mask will result in the start address.
+  Address start() { return start_; }
+  uint32_t mask() { return address_mask_; }
+
+  // The allocation top and limit addresses.
+  Address* allocation_top_address() { return &allocation_info_.top; }
+  Address* allocation_limit_address() { return &allocation_info_.limit; }
+
+  Object* AllocateRaw(int size_in_bytes) {
+    return AllocateRawInternal(size_in_bytes, &allocation_info_);
+  }
+
+  // Allocate the requested number of bytes for relocation during mark-compact
+  // collection.
+  Object* MCAllocateRaw(int size_in_bytes) {
+    return AllocateRawInternal(size_in_bytes, &mc_forwarding_info_);
+  }
+
+  // Reset the allocation pointer to the beginning of the active semispace.
+  void ResetAllocationInfo();
+  // Reset the reloction pointer to the bottom of the inactive semispace in
+  // preparation for mark-compact collection.
+  void MCResetRelocationInfo();
+  // Update the allocation pointer in the active semispace after a
+  // mark-compact collection.
+  void MCCommitRelocationInfo();
+
+  // Get the extent of the inactive semispace (for use as a marking stack).
+  Address FromSpaceLow() { return from_space_.low(); }
+  Address FromSpaceHigh() { return from_space_.high(); }
+
+  // Get the extent of the active semispace (to sweep newly copied objects
+  // during a scavenge collection).
+  Address ToSpaceLow() { return to_space_.low(); }
+  Address ToSpaceHigh() { return to_space_.high(); }
+
+  // Offsets from the beginning of the semispaces.
+  int ToSpaceOffsetForAddress(Address a) {
+    return to_space_.SpaceOffsetForAddress(a);
+  }
+  int FromSpaceOffsetForAddress(Address a) {
+    return from_space_.SpaceOffsetForAddress(a);
+  }
+
+  // True if the object is a heap object in the address range of the
+  // respective semispace (not necessarily below the allocation pointer of the
+  // semispace).
+  bool ToSpaceContains(Object* o) { return to_space_.Contains(o); }
+  bool FromSpaceContains(Object* o) { return from_space_.Contains(o); }
+
+  bool ToSpaceContains(Address a) { return to_space_.Contains(a); }
+  bool FromSpaceContains(Address a) { return from_space_.Contains(a); }
+
+#ifdef ENABLE_HEAP_PROTECTION
+  // Protect/unprotect the space by marking it read-only/writable.
+  virtual void Protect();
+  virtual void Unprotect();
+#endif
+
+#ifdef DEBUG
+  // Verify the active semispace.
+  virtual void Verify();
+  // Print the active semispace.
+  virtual void Print() { to_space_.Print(); }
+#endif
+
+#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
+  // Iterates the active semispace to collect statistics.
+  void CollectStatistics();
+  // Reports previously collected statistics of the active semispace.
+  void ReportStatistics();
+  // Clears previously collected statistics.
+  void ClearHistograms();
+
+  // Record the allocation or promotion of a heap object.  Note that we don't
+  // record every single allocation, but only those that happen in the
+  // to space during a scavenge GC.
+  void RecordAllocation(HeapObject* obj);
+  void RecordPromotion(HeapObject* obj);
+#endif
+
+ private:
+  // The current and maximum capacities of a semispace.
+  int capacity_;
+  int maximum_capacity_;
+
+  // The semispaces.
+  SemiSpace to_space_;
+  SemiSpace from_space_;
+
+  // Start address and bit mask for containment testing.
+  Address start_;
+  uint32_t address_mask_;
+  uint32_t object_mask_;
+  uint32_t object_expected_;
+
+  // Allocation pointer and limit for normal allocation and allocation during
+  // mark-compact collection.
+  AllocationInfo allocation_info_;
+  AllocationInfo mc_forwarding_info_;
+
+#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
+  HistogramInfo* allocated_histogram_;
+  HistogramInfo* promoted_histogram_;
+#endif
+
+  // Implementation of AllocateRaw and MCAllocateRaw.
+  inline Object* AllocateRawInternal(int size_in_bytes,
+                                     AllocationInfo* alloc_info);
+
+  friend class SemiSpaceIterator;
+
+ public:
+  TRACK_MEMORY("NewSpace")
+};
+
+
+// -----------------------------------------------------------------------------
+// Free lists for old object spaces
+//
+// Free-list nodes are free blocks in the heap.  They look like heap objects
+// (free-list node pointers have the heap object tag, and they have a map like
+// a heap object).  They have a size and a next pointer.  The next pointer is
+// the raw address of the next free list node (or NULL).
+class FreeListNode: public HeapObject {
+ public:
+  // Obtain a free-list node from a raw address.  This is not a cast because
+  // it does not check nor require that the first word at the address is a map
+  // pointer.
+  static FreeListNode* FromAddress(Address address) {
+    return reinterpret_cast<FreeListNode*>(HeapObject::FromAddress(address));
+  }
+
+  // Set the size in bytes, which can be read with HeapObject::Size().  This
+  // function also writes a map to the first word of the block so that it
+  // looks like a heap object to the garbage collector and heap iteration
+  // functions.
+  void set_size(int size_in_bytes);
+
+  // Accessors for the next field.
+  inline Address next();
+  inline void set_next(Address next);
+
+ private:
+  static const int kNextOffset = Array::kHeaderSize;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(FreeListNode);
+};
+
+
+// The free list for the old space.
+class OldSpaceFreeList BASE_EMBEDDED {
+ public:
+  explicit OldSpaceFreeList(AllocationSpace owner);
+
+  // Clear the free list.
+  void Reset();
+
+  // Return the number of bytes available on the free list.
+  int available() { return available_; }
+
+  // Place a node on the free list.  The block of size 'size_in_bytes'
+  // starting at 'start' is placed on the free list.  The return value is the
+  // number of bytes that have been lost due to internal fragmentation by
+  // freeing the block.  Bookkeeping information will be written to the block,
+  // ie, its contents will be destroyed.  The start address should be word
+  // aligned, and the size should be a non-zero multiple of the word size.
+  int Free(Address start, int size_in_bytes);
+
+  // Allocate a block of size 'size_in_bytes' from the free list.  The block
+  // is unitialized.  A failure is returned if no block is available.  The
+  // number of bytes lost to fragmentation is returned in the output parameter
+  // 'wasted_bytes'.  The size should be a non-zero multiple of the word size.
+  Object* Allocate(int size_in_bytes, int* wasted_bytes);
+
+ private:
+  // The size range of blocks, in bytes. (Smaller allocations are allowed, but
+  // will always result in waste.)
+  static const int kMinBlockSize = Array::kHeaderSize + kPointerSize;
+  static const int kMaxBlockSize = Page::kMaxHeapObjectSize;
+
+  // The identity of the owning space, for building allocation Failure
+  // objects.
+  AllocationSpace owner_;
+
+  // Total available bytes in all blocks on this free list.
+  int available_;
+
+  // Blocks are put on exact free lists in an array, indexed by size in words.
+  // The available sizes are kept in an increasingly ordered list. Entries
+  // corresponding to sizes < kMinBlockSize always have an empty free list
+  // (but index kHead is used for the head of the size list).
+  struct SizeNode {
+    // Address of the head FreeListNode of the implied block size or NULL.
+    Address head_node_;
+    // Size (words) of the next larger available size if head_node_ != NULL.
+    int next_size_;
+  };
+  static const int kFreeListsLength = kMaxBlockSize / kPointerSize + 1;
+  SizeNode free_[kFreeListsLength];
+
+  // Sentinel elements for the size list. Real elements are in ]kHead..kEnd[.
+  static const int kHead = kMinBlockSize / kPointerSize - 1;
+  static const int kEnd = kMaxInt;
+
+  // We keep a "finger" in the size list to speed up a common pattern:
+  // repeated requests for the same or increasing sizes.
+  int finger_;
+
+  // Starting from *prev, find and return the smallest size >= index (words),
+  // or kEnd. Update *prev to be the largest size < index, or kHead.
+  int FindSize(int index, int* prev) {
+    int cur = free_[*prev].next_size_;
+    while (cur < index) {
+      *prev = cur;
+      cur = free_[cur].next_size_;
+    }
+    return cur;
+  }
+
+  // Remove an existing element from the size list.
+  void RemoveSize(int index) {
+    int prev = kHead;
+    int cur = FindSize(index, &prev);
+    ASSERT(cur == index);
+    free_[prev].next_size_ = free_[cur].next_size_;
+    finger_ = prev;
+  }
+
+  // Insert a new element into the size list.
+  void InsertSize(int index) {
+    int prev = kHead;
+    int cur = FindSize(index, &prev);
+    ASSERT(cur != index);
+    free_[prev].next_size_ = index;
+    free_[index].next_size_ = cur;
+  }
+
+  // The size list is not updated during a sequence of calls to Free, but is
+  // rebuilt before the next allocation.
+  void RebuildSizeList();
+  bool needs_rebuild_;
+
+#ifdef DEBUG
+  // Does this free list contain a free block located at the address of 'node'?
+  bool Contains(FreeListNode* node);
+#endif
+
+  DISALLOW_COPY_AND_ASSIGN(OldSpaceFreeList);
+};
+
+
+// The free list for the map space.
+class MapSpaceFreeList BASE_EMBEDDED {
+ public:
+  explicit MapSpaceFreeList(AllocationSpace owner);
+
+  // Clear the free list.
+  void Reset();
+
+  // Return the number of bytes available on the free list.
+  int available() { return available_; }
+
+  // Place a node on the free list.  The block starting at 'start' (assumed to
+  // have size Map::kSize) is placed on the free list.  Bookkeeping
+  // information will be written to the block, ie, its contents will be
+  // destroyed.  The start address should be word aligned.
+  void Free(Address start);
+
+  // Allocate a map-sized block from the free list.  The block is unitialized.
+  // A failure is returned if no block is available.
+  Object* Allocate();
+
+ private:
+  // Available bytes on the free list.
+  int available_;
+
+  // The head of the free list.
+  Address head_;
+
+  // The identity of the owning space, for building allocation Failure
+  // objects.
+  AllocationSpace owner_;
+
+  DISALLOW_COPY_AND_ASSIGN(MapSpaceFreeList);
+};
+
+
+// -----------------------------------------------------------------------------
+// Old object space (excluding map objects)
+
+class OldSpace : public PagedSpace {
+ public:
+  // Creates an old space object with a given maximum capacity.
+  // The constructor does not allocate pages from OS.
+  explicit OldSpace(int max_capacity,
+                    AllocationSpace id,
+                    Executability executable)
+      : PagedSpace(max_capacity, id, executable), free_list_(id) {
+  }
+
+  // The bytes available on the free list (ie, not above the linear allocation
+  // pointer).
+  int AvailableFree() { return free_list_.available(); }
+
+  // The top of allocation in a page in this space. Undefined if page is unused.
+  virtual Address PageAllocationTop(Page* page) {
+    return page == TopPageOf(allocation_info_) ? top() : page->ObjectAreaEnd();
+  }
+
+  // Give a block of memory to the space's free list.  It might be added to
+  // the free list or accounted as waste.
+  void Free(Address start, int size_in_bytes) {
+    int wasted_bytes = free_list_.Free(start, size_in_bytes);
+    accounting_stats_.DeallocateBytes(size_in_bytes);
+    accounting_stats_.WasteBytes(wasted_bytes);
+  }
+
+  // Prepare for full garbage collection.  Resets the relocation pointer and
+  // clears the free list.
+  virtual void PrepareForMarkCompact(bool will_compact);
+
+  // Adjust the top of relocation pointer to point to the end of the object
+  // given by 'address' and 'size_in_bytes'.  Move it to the next page if
+  // necessary, ensure that it points to the address, then increment it by the
+  // size.
+  void MCAdjustRelocationEnd(Address address, int size_in_bytes);
+
+  // Updates the allocation pointer to the relocation top after a mark-compact
+  // collection.
+  virtual void MCCommitRelocationInfo();
+
+#ifdef DEBUG
+  // Verify integrity of this space.
+  virtual void Verify();
+
+  // Reports statistics for the space
+  void ReportStatistics();
+  // Dump the remembered sets in the space to stdout.
+  void PrintRSet();
+#endif
+
+ protected:
+  // Virtual function in the superclass.  Slow path of AllocateRaw.
+  HeapObject* SlowAllocateRaw(int size_in_bytes);
+
+  // Virtual function in the superclass.  Allocate linearly at the start of
+  // the page after current_page (there is assumed to be one).
+  HeapObject* AllocateInNextPage(Page* current_page, int size_in_bytes);
+
+ private:
+  // The space's free list.
+  OldSpaceFreeList free_list_;
+
+  // During relocation, we keep a pointer to the most recently relocated
+  // object in order to know when to move to the next page.
+  Address mc_end_of_relocation_;
+
+ public:
+  TRACK_MEMORY("OldSpace")
+};
+
+
+// -----------------------------------------------------------------------------
+// Old space for all map objects
+
+class MapSpace : public PagedSpace {
+ public:
+  // Creates a map space object with a maximum capacity.
+  explicit MapSpace(int max_capacity, AllocationSpace id)
+      : PagedSpace(max_capacity, id, NOT_EXECUTABLE), free_list_(id) { }
+
+  // The top of allocation in a page in this space. Undefined if page is unused.
+  virtual Address PageAllocationTop(Page* page) {
+    return page == TopPageOf(allocation_info_) ? top()
+        : page->ObjectAreaEnd() - kPageExtra;
+  }
+
+  // Give a map-sized block of memory to the space's free list.
+  void Free(Address start) {
+    free_list_.Free(start);
+    accounting_stats_.DeallocateBytes(Map::kSize);
+  }
+
+  // Given an index, returns the page address.
+  Address PageAddress(int page_index) { return page_addresses_[page_index]; }
+
+  // Prepares for a mark-compact GC.
+  virtual void PrepareForMarkCompact(bool will_compact);
+
+  // Updates the allocation pointer to the relocation top after a mark-compact
+  // collection.
+  virtual void MCCommitRelocationInfo();
+
+#ifdef DEBUG
+  // Verify integrity of this space.
+  virtual void Verify();
+
+  // Reports statistic info of the space
+  void ReportStatistics();
+  // Dump the remembered sets in the space to stdout.
+  void PrintRSet();
+#endif
+
+  // Constants.
+  static const int kMapPageIndexBits = 10;
+  static const int kMaxMapPageIndex = (1 << kMapPageIndexBits) - 1;
+
+  static const int kPageExtra = Page::kObjectAreaSize % Map::kSize;
+
+ protected:
+  // Virtual function in the superclass.  Slow path of AllocateRaw.
+  HeapObject* SlowAllocateRaw(int size_in_bytes);
+
+  // Virtual function in the superclass.  Allocate linearly at the start of
+  // the page after current_page (there is assumed to be one).
+  HeapObject* AllocateInNextPage(Page* current_page, int size_in_bytes);
+
+ private:
+  // The space's free list.
+  MapSpaceFreeList free_list_;
+
+  // An array of page start address in a map space.
+  Address page_addresses_[kMaxMapPageIndex + 1];
+
+ public:
+  TRACK_MEMORY("MapSpace")
+};
+
+
+// -----------------------------------------------------------------------------
+// Large objects ( > Page::kMaxHeapObjectSize ) are allocated and managed by
+// the large object space. A large object is allocated from OS heap with
+// extra padding bytes (Page::kPageSize + Page::kObjectStartOffset).
+// A large object always starts at Page::kObjectStartOffset to a page.
+// Large objects do not move during garbage collections.
+
+// A LargeObjectChunk holds exactly one large object page with exactly one
+// large object.
+class LargeObjectChunk {
+ public:
+  // Allocates a new LargeObjectChunk that contains a large object page
+  // (Page::kPageSize aligned) that has at least size_in_bytes (for a large
+  // object and possibly extra remembered set words) bytes after the object
+  // area start of that page. The allocated chunk size is set in the output
+  // parameter chunk_size.
+  static LargeObjectChunk* New(int size_in_bytes,
+                               size_t* chunk_size,
+                               Executability executable);
+
+  // Interpret a raw address as a large object chunk.
+  static LargeObjectChunk* FromAddress(Address address) {
+    return reinterpret_cast<LargeObjectChunk*>(address);
+  }
+
+  // Returns the address of this chunk.
+  Address address() { return reinterpret_cast<Address>(this); }
+
+  // Accessors for the fields of the chunk.
+  LargeObjectChunk* next() { return next_; }
+  void set_next(LargeObjectChunk* chunk) { next_ = chunk; }
+
+  size_t size() { return size_; }
+  void set_size(size_t size_in_bytes) { size_ = size_in_bytes; }
+
+  // Returns the object in this chunk.
+  inline HeapObject* GetObject();
+
+  // Given a requested size (including any extra remembered set words),
+  // returns the physical size of a chunk to be allocated.
+  static int ChunkSizeFor(int size_in_bytes);
+
+  // Given a chunk size, returns the object size it can accommodate (not
+  // including any extra remembered set words).  Used by
+  // LargeObjectSpace::Available.  Note that this can overestimate the size
+  // of object that will fit in a chunk---if the object requires extra
+  // remembered set words (eg, for large fixed arrays), the actual object
+  // size for the chunk will be smaller than reported by this function.
+  static int ObjectSizeFor(int chunk_size) {
+    if (chunk_size <= (Page::kPageSize + Page::kObjectStartOffset)) return 0;
+    return chunk_size - Page::kPageSize - Page::kObjectStartOffset;
+  }
+
+ private:
+  // A pointer to the next large object chunk in the space or NULL.
+  LargeObjectChunk* next_;
+
+  // The size of this chunk.
+  size_t size_;
+
+ public:
+  TRACK_MEMORY("LargeObjectChunk")
+};
+
+
+class LargeObjectSpace : public Space {
+ public:
+  explicit LargeObjectSpace(AllocationSpace id);
+  virtual ~LargeObjectSpace() {}
+
+  // Initializes internal data structures.
+  bool Setup();
+
+  // Releases internal resources, frees objects in this space.
+  void TearDown();
+
+  // Allocates a (non-FixedArray, non-Code) large object.
+  Object* AllocateRaw(int size_in_bytes);
+  // Allocates a large Code object.
+  Object* AllocateRawCode(int size_in_bytes);
+  // Allocates a large FixedArray.
+  Object* AllocateRawFixedArray(int size_in_bytes);
+
+  // Available bytes for objects in this space, not including any extra
+  // remembered set words.
+  int Available() {
+    return LargeObjectChunk::ObjectSizeFor(MemoryAllocator::Available());
+  }
+
+  virtual int Size() {
+    return size_;
+  }
+
+  int PageCount() {
+    return page_count_;
+  }
+
+  // Finds an object for a given address, returns Failure::Exception()
+  // if it is not found. The function iterates through all objects in this
+  // space, may be slow.
+  Object* FindObject(Address a);
+
+  // Clears remembered sets.
+  void ClearRSet();
+
+  // Iterates objects whose remembered set bits are set.
+  void IterateRSet(ObjectSlotCallback func);
+
+  // Frees unmarked objects.
+  void FreeUnmarkedObjects();
+
+  // Checks whether a heap object is in this space; O(1).
+  bool Contains(HeapObject* obj);
+
+  // Checks whether the space is empty.
+  bool IsEmpty() { return first_chunk_ == NULL; }
+
+#ifdef ENABLE_HEAP_PROTECTION
+  // Protect/unprotect the space by marking it read-only/writable.
+  void Protect();
+  void Unprotect();
+#endif
+
+#ifdef DEBUG
+  virtual void Verify();
+  virtual void Print();
+  void ReportStatistics();
+  void CollectCodeStatistics();
+  // Dump the remembered sets in the space to stdout.
+  void PrintRSet();
+#endif
+  // Checks whether an address is in the object area in this space.  It
+  // iterates all objects in the space. May be slow.
+  bool SlowContains(Address addr) { return !FindObject(addr)->IsFailure(); }
+
+ private:
+  // The head of the linked list of large object chunks.
+  LargeObjectChunk* first_chunk_;
+  int size_;  // allocated bytes
+  int page_count_;  // number of chunks
+
+
+  // Shared implementation of AllocateRaw, AllocateRawCode and
+  // AllocateRawFixedArray.
+  Object* AllocateRawInternal(int requested_size,
+                              int object_size,
+                              Executability executable);
+
+  // Returns the number of extra bytes (rounded up to the nearest full word)
+  // required for extra_object_bytes of extra pointers (in bytes).
+  static inline int ExtraRSetBytesFor(int extra_object_bytes);
+
+  friend class LargeObjectIterator;
+
+ public:
+  TRACK_MEMORY("LargeObjectSpace")
+};
+
+
+class LargeObjectIterator: public ObjectIterator {
+ public:
+  explicit LargeObjectIterator(LargeObjectSpace* space);
+  LargeObjectIterator(LargeObjectSpace* space, HeapObjectCallback size_func);
+
+  bool has_next() { return current_ != NULL; }
+  HeapObject* next();
+
+  // implementation of ObjectIterator.
+  virtual bool has_next_object() { return has_next(); }
+  virtual HeapObject* next_object() { return next(); }
+
+ private:
+  LargeObjectChunk* current_;
+  HeapObjectCallback size_func_;
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_SPACES_H_
diff --git a/deps/v8/src/string-stream.cc b/deps/v8/src/string-stream.cc
new file mode 100644
index 0000000..f311e20
--- /dev/null
+++ b/deps/v8/src/string-stream.cc
@@ -0,0 +1,577 @@
+// 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.
+
+#include "v8.h"
+
+#include "factory.h"
+#include "string-stream.h"
+
+namespace v8 { namespace internal {
+
+static const int kMentionedObjectCacheMaxSize = 256;
+static List<HeapObject*, PreallocatedStorage>* debug_object_cache = NULL;
+static Object* current_security_token = NULL;
+
+
+char* HeapStringAllocator::allocate(unsigned bytes) {
+  space_ = NewArray<char>(bytes);
+  return space_;
+}
+
+
+NoAllocationStringAllocator::NoAllocationStringAllocator(unsigned bytes) {
+  size_ = bytes;
+  space_ = NewArray<char>(bytes);
+}
+
+
+NoAllocationStringAllocator::NoAllocationStringAllocator(char* memory,
+                                                         unsigned size) {
+  size_ = size;
+  space_ = memory;
+}
+
+
+bool StringStream::Put(char c) {
+  if (space() == 0) return false;
+  if (length_ >= capacity_ - 1) {
+    unsigned new_capacity = capacity_;
+    char* new_buffer = allocator_->grow(&new_capacity);
+    if (new_capacity > capacity_) {
+      capacity_ = new_capacity;
+      buffer_ = new_buffer;
+    } else {
+      // Indicate truncation with dots.
+      memset(cursor(), '.', space());
+      length_ = capacity_;
+      buffer_[length_ - 2] = '\n';
+      buffer_[length_ - 1] = '\0';
+      return false;
+    }
+  }
+  buffer_[length_] = c;
+  buffer_[length_ + 1] = '\0';
+  length_++;
+  return true;
+}
+
+
+// A control character is one that configures a format element.  For
+// instance, in %.5s, .5 are control characters.
+static bool IsControlChar(char c) {
+  switch (c) {
+  case '0': case '1': case '2': case '3': case '4': case '5':
+  case '6': case '7': case '8': case '9': case '.': case '-':
+    return true;
+  default:
+    return false;
+  }
+}
+
+
+void StringStream::Add(Vector<const char> format, Vector<FmtElm> elms) {
+  // If we already ran out of space then return immediately.
+  if (space() == 0)
+    return;
+  int offset = 0;
+  int elm = 0;
+  while (offset < format.length()) {
+    if (format[offset] != '%' || elm == elms.length()) {
+      Put(format[offset]);
+      offset++;
+      continue;
+    }
+    // Read this formatting directive into a temporary buffer
+    EmbeddedVector<char, 24> temp;
+    int format_length = 0;
+    // Skip over the whole control character sequence until the
+    // format element type
+    temp[format_length++] = format[offset++];
+    while (offset < format.length() && IsControlChar(format[offset]))
+      temp[format_length++] = format[offset++];
+    if (offset >= format.length())
+      return;
+    char type = format[offset];
+    temp[format_length++] = type;
+    temp[format_length] = '\0';
+    offset++;
+    FmtElm current = elms[elm++];
+    switch (type) {
+    case 's': {
+      ASSERT_EQ(FmtElm::C_STR, current.type_);
+      const char* value = current.data_.u_c_str_;
+      Add(value);
+      break;
+    }
+    case 'w': {
+      ASSERT_EQ(FmtElm::LC_STR, current.type_);
+      Vector<const uc16> value = *current.data_.u_lc_str_;
+      for (int i = 0; i < value.length(); i++)
+        Put(static_cast<char>(value[i]));
+      break;
+    }
+    case 'o': {
+      ASSERT_EQ(FmtElm::OBJ, current.type_);
+      Object* obj = current.data_.u_obj_;
+      PrintObject(obj);
+      break;
+    }
+    case 'k': {
+      ASSERT_EQ(FmtElm::INT, current.type_);
+      int value = current.data_.u_int_;
+      if (0x20 <= value && value <= 0x7F) {
+        Put(value);
+      } else if (value <= 0xff) {
+        Add("\\x%02x", value);
+      } else {
+        Add("\\u%04x", value);
+      }
+      break;
+    }
+    case 'i': case 'd': case 'u': case 'x': case 'c': case 'p': case 'X': {
+      int value = current.data_.u_int_;
+      EmbeddedVector<char, 24> formatted;
+      int length = OS::SNPrintF(formatted, temp.start(), value);
+      Add(Vector<const char>(formatted.start(), length));
+      break;
+    }
+    case 'f': case 'g': case 'G': case 'e': case 'E': {
+      double value = current.data_.u_double_;
+      EmbeddedVector<char, 28> formatted;
+      OS::SNPrintF(formatted, temp.start(), value);
+      Add(formatted.start());
+      break;
+    }
+    default:
+      UNREACHABLE();
+      break;
+    }
+  }
+
+  // Verify that the buffer is 0-terminated
+  ASSERT(buffer_[length_] == '\0');
+}
+
+
+void StringStream::PrintObject(Object* o) {
+  o->ShortPrint(this);
+  if (o->IsString()) {
+    if (String::cast(o)->length() <= String::kMaxMediumStringSize) {
+      return;
+    }
+  } else if (o->IsNumber() || o->IsOddball()) {
+    return;
+  }
+  if (o->IsHeapObject()) {
+    for (int i = 0; i < debug_object_cache->length(); i++) {
+      if ((*debug_object_cache)[i] == o) {
+        Add("#%d#", i);
+        return;
+      }
+    }
+    if (debug_object_cache->length() < kMentionedObjectCacheMaxSize) {
+      Add("#%d#", debug_object_cache->length());
+      debug_object_cache->Add(HeapObject::cast(o));
+    } else {
+      Add("@%p", o);
+    }
+  }
+}
+
+
+void StringStream::Add(const char* format) {
+  Add(CStrVector(format));
+}
+
+
+void StringStream::Add(Vector<const char> format) {
+  Add(format, Vector<FmtElm>::empty());
+}
+
+
+void StringStream::Add(const char* format, FmtElm arg0) {
+  const char argc = 1;
+  FmtElm argv[argc] = { arg0 };
+  Add(CStrVector(format), Vector<FmtElm>(argv, argc));
+}
+
+
+void StringStream::Add(const char* format, FmtElm arg0, FmtElm arg1) {
+  const char argc = 2;
+  FmtElm argv[argc] = { arg0, arg1 };
+  Add(CStrVector(format), Vector<FmtElm>(argv, argc));
+}
+
+
+void StringStream::Add(const char* format, FmtElm arg0, FmtElm arg1,
+                       FmtElm arg2) {
+  const char argc = 3;
+  FmtElm argv[argc] = { arg0, arg1, arg2 };
+  Add(CStrVector(format), Vector<FmtElm>(argv, argc));
+}
+
+
+void StringStream::Add(const char* format, FmtElm arg0, FmtElm arg1,
+                       FmtElm arg2, FmtElm arg3) {
+  const char argc = 4;
+  FmtElm argv[argc] = { arg0, arg1, arg2, arg3 };
+  Add(CStrVector(format), Vector<FmtElm>(argv, argc));
+}
+
+
+SmartPointer<const char> StringStream::ToCString() {
+  char* str = NewArray<char>(length_ + 1);
+  memcpy(str, buffer_, length_);
+  str[length_] = '\0';
+  return SmartPointer<const char>(str);
+}
+
+
+void StringStream::Log() {
+  LOG(StringEvent("StackDump", buffer_));
+}
+
+
+void StringStream::OutputToStdOut() {
+  // Dump the output to stdout, but make sure to break it up into
+  // manageable chunks to avoid losing parts of the output in the OS
+  // printing code. This is a problem on Windows in particular; see
+  // the VPrint() function implementations in platform-win32.cc.
+  unsigned position = 0;
+  for (unsigned next; (next = position + 2048) < length_; position = next) {
+    char save = buffer_[next];
+    buffer_[next] = '\0';
+    internal::PrintF("%s", &buffer_[position]);
+    buffer_[next] = save;
+  }
+  internal::PrintF("%s", &buffer_[position]);
+}
+
+
+Handle<String> StringStream::ToString() {
+  return Factory::NewStringFromUtf8(Vector<const char>(buffer_, length_));
+}
+
+
+void StringStream::ClearMentionedObjectCache() {
+  current_security_token = NULL;
+  if (debug_object_cache == NULL) {
+    debug_object_cache = new List<HeapObject*, PreallocatedStorage>(0);
+  }
+  debug_object_cache->Clear();
+}
+
+
+#ifdef DEBUG
+bool StringStream::IsMentionedObjectCacheClear() {
+  return (debug_object_cache->length() == 0);
+}
+#endif
+
+
+bool StringStream::Put(String* str) {
+  return Put(str, 0, str->length());
+}
+
+
+bool StringStream::Put(String* str, int start, int end) {
+  StringInputBuffer name_buffer(str);
+  name_buffer.Seek(start);
+  for (int i = start; i < end && name_buffer.has_more(); i++) {
+    int c = name_buffer.GetNext();
+    if (c >= 127 || c < 32) {
+      c = '?';
+    }
+    if (!Put(c)) {
+      return false;  // Output was truncated.
+    }
+  }
+  return true;
+}
+
+
+void StringStream::PrintName(Object* name) {
+  if (name->IsString()) {
+    String* str = String::cast(name);
+    if (str->length() > 0) {
+      Put(str);
+    } else {
+      Add("/* anonymous */");
+    }
+  } else {
+    Add("%o", name);
+  }
+}
+
+
+void StringStream::PrintUsingMap(JSObject* js_object) {
+  Map* map = js_object->map();
+  if (!Heap::Contains(map) ||
+      !map->IsHeapObject() ||
+      !map->IsMap()) {
+    Add("<Invalid map>\n");
+    return;
+  }
+  for (DescriptorReader r(map->instance_descriptors()); !r.eos(); r.advance()) {
+    switch (r.type()) {
+      case FIELD: {
+        Object* key = r.GetKey();
+        if (key->IsString() || key->IsNumber()) {
+          int len = 3;
+          if (key->IsString()) {
+            len = String::cast(key)->length();
+          }
+          for (; len < 18; len++)
+            Put(' ');
+          if (key->IsString()) {
+            Put(String::cast(key));
+          } else {
+            key->ShortPrint();
+          }
+          Add(": ");
+          Object* value = js_object->FastPropertyAt(r.GetFieldIndex());
+          Add("%o\n", value);
+        }
+      }
+      break;
+      default:
+      break;
+    }
+  }
+}
+
+
+void StringStream::PrintFixedArray(FixedArray* array, unsigned int limit) {
+  for (unsigned int i = 0; i < 10 && i < limit; i++) {
+    Object* element = array->get(i);
+    if (element != Heap::the_hole_value()) {
+      for (int len = 1; len < 18; len++)
+        Put(' ');
+      Add("%d: %o\n", i, array->get(i));
+    }
+  }
+  if (limit >= 10) {
+    Add("                  ...\n");
+  }
+}
+
+
+void StringStream::PrintByteArray(ByteArray* byte_array) {
+  unsigned int limit = byte_array->length();
+  for (unsigned int i = 0; i < 10 && i < limit; i++) {
+    byte b = byte_array->get(i);
+    Add("             %d: %3d 0x%02x", i, b, b);
+    if (b >= ' ' && b <= '~') {
+      Add(" '%c'", b);
+    } else if (b == '\n') {
+      Add(" '\n'");
+    } else if (b == '\r') {
+      Add(" '\r'");
+    } else if (b >= 1 && b <= 26) {
+      Add(" ^%c", b + 'A' - 1);
+    }
+    Add("\n");
+  }
+  if (limit >= 10) {
+    Add("                  ...\n");
+  }
+}
+
+
+void StringStream::PrintMentionedObjectCache() {
+  Add("==== Key         ============================================\n\n");
+  for (int i = 0; i < debug_object_cache->length(); i++) {
+    HeapObject* printee = (*debug_object_cache)[i];
+    Add(" #%d# %p: ", i, printee);
+    printee->ShortPrint(this);
+    Add("\n");
+    if (printee->IsJSObject()) {
+      if (printee->IsJSValue()) {
+        Add("           value(): %o\n", JSValue::cast(printee)->value());
+      }
+      PrintUsingMap(JSObject::cast(printee));
+      if (printee->IsJSArray()) {
+        JSArray* array = JSArray::cast(printee);
+        if (array->HasFastElements()) {
+          unsigned int limit = FixedArray::cast(array->elements())->length();
+          unsigned int length =
+            static_cast<uint32_t>(JSArray::cast(array)->length()->Number());
+          if (length < limit) limit = length;
+          PrintFixedArray(FixedArray::cast(array->elements()), limit);
+        }
+      }
+    } else if (printee->IsByteArray()) {
+      PrintByteArray(ByteArray::cast(printee));
+    } else if (printee->IsFixedArray()) {
+      unsigned int limit = FixedArray::cast(printee)->length();
+      PrintFixedArray(FixedArray::cast(printee), limit);
+    }
+  }
+}
+
+
+void StringStream::PrintSecurityTokenIfChanged(Object* f) {
+  if (!f->IsHeapObject() || !Heap::Contains(HeapObject::cast(f))) {
+    return;
+  }
+  Map* map = HeapObject::cast(f)->map();
+  if (!map->IsHeapObject() ||
+      !Heap::Contains(map) ||
+      !map->IsMap() ||
+      !f->IsJSFunction()) {
+    return;
+  }
+
+  JSFunction* fun = JSFunction::cast(f);
+  Object* perhaps_context = fun->unchecked_context();
+  if (perhaps_context->IsHeapObject() &&
+      Heap::Contains(HeapObject::cast(perhaps_context)) &&
+      perhaps_context->IsContext()) {
+    Context* context = fun->context();
+    if (!Heap::Contains(context)) {
+      Add("(Function context is outside heap)\n");
+      return;
+    }
+    Object* token = context->global_context()->security_token();
+    if (token != current_security_token) {
+      Add("Security context: %o\n", token);
+      current_security_token = token;
+    }
+  } else {
+    Add("(Function context is corrupt)\n");
+  }
+}
+
+
+void StringStream::PrintFunction(Object* f, Object* receiver, Code** code) {
+  if (f->IsHeapObject() &&
+      Heap::Contains(HeapObject::cast(f)) &&
+      Heap::Contains(HeapObject::cast(f)->map()) &&
+      HeapObject::cast(f)->map()->IsMap()) {
+    if (f->IsJSFunction()) {
+      JSFunction* fun = JSFunction::cast(f);
+      // Common case: on-stack function present and resolved.
+      PrintPrototype(fun, receiver);
+      *code = fun->code();
+    } else if (f->IsSymbol()) {
+      // Unresolved and megamorphic calls: Instead of the function
+      // we have the function name on the stack.
+      PrintName(f);
+      Add("/* unresolved */ ");
+    } else {
+      // Unless this is the frame of a built-in function, we should always have
+      // the callee function or name on the stack. If we don't, we have a
+      // problem or a change of the stack frame layout.
+      Add("%o", f);
+      Add("/* warning: no JSFunction object or function name found */ ");
+    }
+    /* } else if (is_trampoline()) {
+       Print("trampoline ");
+    */
+  } else {
+    if (!f->IsHeapObject()) {
+      Add("/* warning: 'function' was not a heap object */ ");
+      return;
+    }
+    if (!Heap::Contains(HeapObject::cast(f))) {
+      Add("/* warning: 'function' was not on the heap */ ");
+      return;
+    }
+    if (!Heap::Contains(HeapObject::cast(f)->map())) {
+      Add("/* warning: function's map was not on the heap */ ");
+      return;
+    }
+    if (!HeapObject::cast(f)->map()->IsMap()) {
+      Add("/* warning: function's map was not a valid map */ ");
+      return;
+    }
+    Add("/* warning: Invalid JSFunction object found */ ");
+  }
+}
+
+
+void StringStream::PrintPrototype(JSFunction* fun, Object* receiver) {
+  Object* name = fun->shared()->name();
+  bool print_name = false;
+  for (Object* p = receiver; p != Heap::null_value(); p = p->GetPrototype()) {
+    if (p->IsJSObject()) {
+      Object* key = JSObject::cast(p)->SlowReverseLookup(fun);
+      if (key != Heap::undefined_value()) {
+        if (!name->IsString() ||
+            !key->IsString() ||
+            !String::cast(name)->Equals(String::cast(key))) {
+          print_name = true;
+        }
+        if (name->IsString() && String::cast(name)->length() == 0) {
+          print_name = false;
+        }
+        name = key;
+      }
+    } else {
+      print_name = true;
+    }
+  }
+  PrintName(name);
+  // Also known as - if the name in the function doesn't match the name under
+  // which it was looked up.
+  if (print_name) {
+    Add("(aka ");
+    PrintName(fun->shared()->name());
+    Put(')');
+  }
+}
+
+
+char* HeapStringAllocator::grow(unsigned* bytes) {
+  unsigned new_bytes = *bytes * 2;
+  // Check for overflow.
+  if (new_bytes <= *bytes) {
+    return space_;
+  }
+  char* new_space = NewArray<char>(new_bytes);
+  if (new_space == NULL) {
+    return space_;
+  }
+  memcpy(new_space, space_, *bytes);
+  *bytes = new_bytes;
+  DeleteArray(space_);
+  space_ = new_space;
+  return new_space;
+}
+
+
+char* NoAllocationStringAllocator::grow(unsigned* bytes) {
+  unsigned new_bytes = *bytes * 2;
+  if (new_bytes > size_) {
+    new_bytes = size_;
+  }
+  *bytes = new_bytes;
+  return space_;
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/string-stream.h b/deps/v8/src/string-stream.h
new file mode 100644
index 0000000..37ae93e
--- /dev/null
+++ b/deps/v8/src/string-stream.h
@@ -0,0 +1,174 @@
+// 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_STRING_STREAM_H_
+#define V8_STRING_STREAM_H_
+
+namespace v8 { namespace internal {
+
+
+class StringAllocator {
+ public:
+  virtual ~StringAllocator() {}
+  // Allocate a number of bytes.
+  virtual char* allocate(unsigned bytes) = 0;
+  // Allocate a larger number of bytes and copy the old buffer to the new one.
+  // bytes is an input and output parameter passing the old size of the buffer
+  // and returning the new size.  If allocation fails then we return the old
+  // buffer and do not increase the size.
+  virtual char* grow(unsigned* bytes) = 0;
+};
+
+
+// Normal allocator uses new[] and delete[].
+class HeapStringAllocator: public StringAllocator {
+ public:
+  ~HeapStringAllocator() { DeleteArray(space_); }
+  char* allocate(unsigned bytes);
+  char* grow(unsigned* bytes);
+ private:
+  char* space_;
+};
+
+
+// Allocator for use when no new c++ heap allocation is allowed.
+// Allocates all space up front and does no allocation while building
+// message.
+class NoAllocationStringAllocator: public StringAllocator {
+ public:
+  explicit NoAllocationStringAllocator(unsigned bytes);
+  NoAllocationStringAllocator(char* memory, unsigned size);
+  char* allocate(unsigned bytes) { return space_; }
+  char* grow(unsigned* bytes);
+ private:
+  unsigned size_;
+  char* space_;
+};
+
+
+class FmtElm {
+ public:
+  FmtElm(int value) : type_(INT) { data_.u_int_ = value; }  // NOLINT
+  explicit FmtElm(double value) : type_(DOUBLE) { data_.u_double_ = value; }  // NOLINT
+  FmtElm(const char* value) : type_(C_STR) { data_.u_c_str_ = value; }  // NOLINT
+  FmtElm(const Vector<const uc16>& value) : type_(LC_STR) { data_.u_lc_str_ = &value; } // NOLINT
+  FmtElm(Object* value) : type_(OBJ) { data_.u_obj_ = value; }  // NOLINT
+  FmtElm(Handle<Object> value) : type_(HANDLE) { data_.u_handle_ = value.location(); }  // NOLINT
+  FmtElm(void* value) : type_(INT) { data_.u_int_ = reinterpret_cast<int>(value); }  // NOLINT
+ private:
+  friend class StringStream;
+  enum Type { INT, DOUBLE, C_STR, LC_STR, OBJ, HANDLE };
+  Type type_;
+  union {
+    int u_int_;
+    double u_double_;
+    const char* u_c_str_;
+    const Vector<const uc16>* u_lc_str_;
+    Object* u_obj_;
+    Object** u_handle_;
+  } data_;
+};
+
+
+class StringStream {
+ public:
+  explicit StringStream(StringAllocator* allocator):
+    allocator_(allocator),
+    capacity_(kInitialCapacity),
+    length_(0),
+    buffer_(allocator_->allocate(kInitialCapacity)) {
+    buffer_[0] = 0;
+  }
+
+  ~StringStream() {
+  }
+
+  bool Put(char c);
+  bool Put(String* str);
+  bool Put(String* str, int start, int end);
+  void Add(Vector<const char> format, Vector<FmtElm> elms);
+  void Add(const char* format);
+  void Add(Vector<const char> format);
+  void Add(const char* format, FmtElm arg0);
+  void Add(const char* format, FmtElm arg0, FmtElm arg1);
+  void Add(const char* format, FmtElm arg0, FmtElm arg1, FmtElm arg2);
+  void Add(const char* format,
+           FmtElm arg0,
+           FmtElm arg1,
+           FmtElm arg2,
+           FmtElm arg3);
+
+  // Getting the message out.
+  void OutputToStdOut();
+  void Log();
+  Handle<String> ToString();
+  SmartPointer<const char> ToCString();
+
+  // Object printing support.
+  void PrintName(Object* o);
+  void PrintFixedArray(FixedArray* array, unsigned int limit);
+  void PrintByteArray(ByteArray* ba);
+  void PrintUsingMap(JSObject* js_object);
+  void PrintPrototype(JSFunction* fun, Object* receiver);
+  void PrintSecurityTokenIfChanged(Object* function);
+  // NOTE: Returns the code in the output parameter.
+  void PrintFunction(Object* function, Object* receiver, Code** code);
+
+  // Reset the stream.
+  void Reset() {
+    length_ = 0;
+    buffer_[0] = 0;
+  }
+
+  // Mentioned object cache support.
+  void PrintMentionedObjectCache();
+  static void ClearMentionedObjectCache();
+#ifdef DEBUG
+  static bool IsMentionedObjectCacheClear();
+#endif
+
+
+  static const int kInitialCapacity = 16;
+
+ private:
+  void PrintObject(Object* obj);
+
+  StringAllocator* allocator_;
+  unsigned capacity_;
+  unsigned length_;  // does not include terminating 0-character
+  char* buffer_;
+
+  int space() const { return capacity_ - length_; }
+  char* cursor() const { return buffer_ + length_; }
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(StringStream);
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_STRING_STREAM_H_
diff --git a/deps/v8/src/string.js b/deps/v8/src/string.js
new file mode 100644
index 0000000..3ccad9a
--- /dev/null
+++ b/deps/v8/src/string.js
@@ -0,0 +1,866 @@
+// 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.
+
+
+// This file relies on the fact that the following declaration has been made
+// in runtime.js:
+// const $String = global.String;
+// const $NaN = 0/0;
+
+
+// Set the String function and constructor.
+%SetCode($String, function(x) {
+  var value = %_ArgumentsLength() == 0 ? '' : ToString(x);
+  if (%IsConstructCall()) {
+    %_SetValueOf(this, value);
+  } else {
+    return value;
+  }
+});
+
+%FunctionSetPrototype($String, new $String());
+
+// ECMA-262 section 15.5.4.2
+function StringToString() {
+  if (!IS_STRING(this) && !%HasStringClass(this))
+    throw new $TypeError('String.prototype.toString is not generic');
+  return %_ValueOf(this);
+}
+
+
+// ECMA-262 section 15.5.4.3
+function StringValueOf() {
+  if (!IS_STRING(this) && !%HasStringClass(this))
+    throw new $TypeError('String.prototype.valueOf is not generic');
+  return %_ValueOf(this);
+}
+
+
+// ECMA-262, section 15.5.4.4
+function StringCharAt(pos) {
+  var char_code = %_FastCharCodeAt(this, index);
+  if (!%_IsSmi(char_code)) {
+    var subject = ToString(this);
+    var index = TO_INTEGER(pos);
+    if (index >= subject.length || index < 0) return "";
+    char_code = %StringCharCodeAt(subject, index);
+  }
+  return %CharFromCode(char_code);
+}
+
+
+// ECMA-262 section 15.5.4.5
+function StringCharCodeAt(pos) {
+  var fast_answer = %_FastCharCodeAt(this, pos);
+  if (%_IsSmi(fast_answer)) {
+    return fast_answer;
+  }
+  var subject = ToString(this);
+  var index = TO_INTEGER(pos);
+  return %StringCharCodeAt(subject, index);
+}
+
+
+// ECMA-262, section 15.5.4.6
+function StringConcat() {
+  var len = %_ArgumentsLength();
+  var parts = new $Array(len + 1);
+  parts[0] = ToString(this);
+  for (var i = 0; i < len; i++)
+    parts[i + 1] = ToString(%_Arguments(i));
+  return parts.join('');
+}
+
+// Match ES3 and Safari
+%FunctionSetLength(StringConcat, 1);
+
+
+// ECMA-262 section 15.5.4.7
+function StringIndexOf(searchString /* position */) {  // length == 1
+  var subject_str = ToString(this);
+  var pattern_str = ToString(searchString);
+  var subject_str_len = subject_str.length;
+  var pattern_str_len = pattern_str.length;
+  var index = 0;
+  if (%_ArgumentsLength() > 1) {
+    var arg1 = %_Arguments(1);  // position
+    index = TO_INTEGER(arg1);
+  }
+  if (index < 0) index = 0;
+  if (index > subject_str_len) index = subject_str_len;
+  if (pattern_str_len + index > subject_str_len) return -1;
+  return %StringIndexOf(subject_str, pattern_str, index);
+}
+
+
+// ECMA-262 section 15.5.4.8
+function StringLastIndexOf(searchString /* position */) {  // length == 1
+  var sub = ToString(this);
+  var pat = ToString(searchString);
+  var index = (%_ArgumentsLength() > 1)
+      ? ToNumber(%_Arguments(1) /* position */)
+      : $NaN;
+  var firstIndex;
+  if ($isNaN(index)) {
+    firstIndex = sub.length - pat.length;
+  } else {
+    firstIndex = TO_INTEGER(index);
+    if (firstIndex + pat.length > sub.length) {
+      firstIndex = sub.length - pat.length;
+    }
+  }
+  return %StringLastIndexOf(sub, pat, firstIndex);
+}
+
+
+// ECMA-262 section 15.5.4.9
+//
+// This function is implementation specific.  For now, we do not
+// do anything locale specific.
+function StringLocaleCompare(other) {
+  if (%_ArgumentsLength() === 0) return 0;
+
+  var this_str = ToString(this);
+  var other_str = ToString(other);
+  return %StringLocaleCompare(this_str, other_str);
+}
+
+
+// ECMA-262 section 15.5.4.10
+function StringMatch(regexp) {
+  if (!IS_REGEXP(regexp)) regexp = new ORIGINAL_REGEXP(regexp);
+  var subject = ToString(this);
+
+  if (!regexp.global) return regexp.exec(subject);
+  %_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]);
+  // lastMatchInfo is defined in regexp-delay.js.
+  return %StringMatch(subject, regexp, lastMatchInfo);
+}
+
+
+// SubString is an internal function that returns the sub string of 'string'.
+// If resulting string is of length 1, we use the one character cache
+// otherwise we call the runtime system.
+function SubString(string, start, end) {
+  // Use the one character string cache.
+  if (start + 1 == end) {
+    var char_code = %_FastCharCodeAt(string, start);
+    if (!%_IsSmi(char_code)) {
+      char_code = %StringCharCodeAt(string, start);
+    }
+    return %CharFromCode(char_code);
+  }
+  return %StringSlice(string, start, end);
+}
+
+
+// ECMA-262, section 15.5.4.11
+function StringReplace(search, replace) {
+  var subject = ToString(this);
+
+  // Delegate to one of the regular expression variants if necessary.
+  if (IS_REGEXP(search)) {
+    %_Log('regexp', 'regexp-replace,%0r,%1S', [search, subject]);
+    if (IS_FUNCTION(replace)) {
+      return StringReplaceRegExpWithFunction(subject, search, replace);
+    } else {
+      return StringReplaceRegExp(subject, search, replace);
+    }
+  }
+
+  // Convert the search argument to a string and search for it.
+  search = ToString(search);
+  var start = %StringIndexOf(subject, search, 0);
+  if (start < 0) return subject;
+  var end = start + search.length;
+
+  var builder = new ReplaceResultBuilder(subject);
+  // prefix
+  builder.addSpecialSlice(0, start);
+
+  // Compute the string to replace with.
+  if (IS_FUNCTION(replace)) {
+    builder.add(replace.call(null, search, start, subject));
+  } else {
+    reusableMatchInfo[CAPTURE0] = start;
+    reusableMatchInfo[CAPTURE1] = end;
+    ExpandReplacement(ToString(replace), subject, reusableMatchInfo, builder);
+  }
+
+  // suffix
+  builder.addSpecialSlice(end, subject.length);
+
+  return builder.generate();
+}
+
+
+// This has the same size as the lastMatchInfo array, and can be used for
+// functions that expect that structure to be returned.  It is used when the
+// needle is a string rather than a regexp.  In this case we can't update
+// lastMatchArray without erroneously affecting the properties on the global
+// RegExp object.
+var reusableMatchInfo = [2, "", "", -1, -1];
+
+
+// Helper function for regular expressions in String.prototype.replace.
+function StringReplaceRegExp(subject, regexp, replace) {
+  replace = ToString(replace);
+  return %StringReplaceRegExpWithString(subject,
+                                        regexp,
+                                        replace,
+                                        lastMatchInfo);
+};
+
+
+// Expand the $-expressions in the string and return a new string with
+// the result.
+function ExpandReplacement(string, subject, matchInfo, builder) {
+  var next = %StringIndexOf(string, '$', 0);
+  if (next < 0) {
+    builder.add(string);
+    return;
+  }
+
+  // Compute the number of captures; see ECMA-262, 15.5.4.11, p. 102.
+  var m = NUMBER_OF_CAPTURES(matchInfo) >> 1;  // Includes the match.
+
+  if (next > 0) builder.add(SubString(string, 0, next));
+  var length = string.length;
+
+  while (true) {
+    var expansion = '$';
+    var position = next + 1;
+    if (position < length) {
+      var peek = %_FastCharCodeAt(string, position);
+      if (!%_IsSmi(peek)) {
+        peek = %StringCharCodeAt(string, position);
+      }
+      if (peek == 36) {         // $$
+        ++position;
+        builder.add('$');
+      } else if (peek == 38) {  // $& - match
+        ++position;
+        builder.addSpecialSlice(matchInfo[CAPTURE0],
+                                matchInfo[CAPTURE1]);
+      } else if (peek == 96) {  // $` - prefix
+        ++position;
+        builder.addSpecialSlice(0, matchInfo[CAPTURE0]);
+      } else if (peek == 39) {  // $' - suffix
+        ++position;
+        builder.addSpecialSlice(matchInfo[CAPTURE1], subject.length);
+      } else if (peek >= 48 && peek <= 57) {  // $n, 0 <= n <= 9
+        ++position;
+        var n = peek - 48;
+        if (position < length) {
+          peek = %_FastCharCodeAt(string, position);
+          if (!%_IsSmi(peek)) {
+            peek = %StringCharCodeAt(string, position);
+          }
+          // $nn, 01 <= nn <= 99
+          if (n != 0 && peek == 48 || peek >= 49 && peek <= 57) {
+            var nn = n * 10 + (peek - 48);
+            if (nn < m) {
+              // If the two digit capture reference is within range of
+              // the captures, we use it instead of the single digit
+              // one. Otherwise, we fall back to using the single
+              // digit reference. This matches the behavior of
+              // SpiderMonkey.
+              ++position;
+              n = nn;
+            }
+          }
+        }
+        if (0 < n && n < m) {
+          addCaptureString(builder, matchInfo, n);
+        } else {
+          // Because of the captures range check in the parsing of two
+          // digit capture references, we can only enter here when a
+          // single digit capture reference is outside the range of
+          // captures.
+          builder.add('$');
+          --position;
+        }
+      } else {
+        builder.add('$');
+      }
+    } else {
+      builder.add('$');
+    }
+
+    // Go the the next $ in the string.
+    next = %StringIndexOf(string, '$', position);
+
+    // Return if there are no more $ characters in the string. If we
+    // haven't reached the end, we need to append the suffix.
+    if (next < 0) {
+      if (position < length) {
+        builder.add(SubString(string, position, length));
+      }
+      return;
+    }
+
+    // Append substring between the previous and the next $ character.
+    builder.add(SubString(string, position, next));
+  }
+};
+
+
+// Compute the string of a given regular expression capture.
+function CaptureString(string, lastCaptureInfo, index) {
+  // Scale the index.
+  var scaled = index << 1;
+  // Compute start and end.
+  var start = lastCaptureInfo[CAPTURE(scaled)];
+  var end = lastCaptureInfo[CAPTURE(scaled + 1)];
+  // If either start or end is missing return undefined.
+  if (start < 0 || end < 0) return;
+  return SubString(string, start, end);
+};
+
+
+// Add the string of a given regular expression capture to the
+// ReplaceResultBuilder
+function addCaptureString(builder, matchInfo, index) {
+  // Scale the index.
+  var scaled = index << 1;
+  // Compute start and end.
+  var start = matchInfo[CAPTURE(scaled)];
+  var end = matchInfo[CAPTURE(scaled + 1)];
+  // If either start or end is missing return.
+  if (start < 0 || end <= start) return;
+  builder.addSpecialSlice(start, end);
+};
+
+
+// Helper function for replacing regular expressions with the result of a
+// function application in String.prototype.replace.  The function application
+// must be interleaved with the regexp matching (contrary to ECMA-262
+// 15.5.4.11) to mimic SpiderMonkey and KJS behavior when the function uses
+// the static properties of the RegExp constructor.  Example:
+//     'abcd'.replace(/(.)/g, function() { return RegExp.$1; }
+// should be 'abcd' and not 'dddd' (or anything else).
+function StringReplaceRegExpWithFunction(subject, regexp, replace) {
+  var result = new ReplaceResultBuilder(subject);
+  var lastMatchInfo = DoRegExpExec(regexp, subject, 0);
+  if (IS_NULL(lastMatchInfo)) return subject;
+
+  // There's at least one match.  If the regexp is global, we have to loop
+  // over all matches.  The loop is not in C++ code here like the one in
+  // RegExp.prototype.exec, because of the interleaved function application.
+  // Unfortunately, that means this code is nearly duplicated, here and in
+  // jsregexp.cc.
+  if (regexp.global) {
+    var previous = 0;
+    do {
+      result.addSpecialSlice(previous, lastMatchInfo[CAPTURE0]);
+      var startOfMatch = lastMatchInfo[CAPTURE0];
+      previous = lastMatchInfo[CAPTURE1];
+      result.add(ApplyReplacementFunction(replace, lastMatchInfo, subject));
+      // Can't use lastMatchInfo any more from here, since the function could
+      // overwrite it.
+      // Continue with the next match.
+      // Increment previous if we matched an empty string, as per ECMA-262
+      // 15.5.4.10.
+      if (previous == startOfMatch) {
+        // Add the skipped character to the output, if any.
+        if (previous < subject.length) {
+          result.addSpecialSlice(previous, previous + 1);
+        }
+        previous++;
+      }
+
+      // Per ECMA-262 15.10.6.2, if the previous index is greater than the
+      // string length, there is no match
+      lastMatchInfo = (previous > subject.length)
+          ? null
+          : DoRegExpExec(regexp, subject, previous);
+    } while (!IS_NULL(lastMatchInfo));
+
+    // Tack on the final right substring after the last match, if necessary.
+    if (previous < subject.length) {
+      result.addSpecialSlice(previous, subject.length);
+    }
+  } else { // Not a global regexp, no need to loop.
+    result.addSpecialSlice(0, lastMatchInfo[CAPTURE0]);
+    var endOfMatch = lastMatchInfo[CAPTURE1];
+    result.add(ApplyReplacementFunction(replace, lastMatchInfo, subject));
+    // Can't use lastMatchInfo any more from here, since the function could
+    // overwrite it.
+    result.addSpecialSlice(endOfMatch, subject.length);
+  }
+
+  return result.generate();
+}
+
+
+// Helper function to apply a string replacement function once.
+function ApplyReplacementFunction(replace, lastMatchInfo, subject) {
+  // Compute the parameter list consisting of the match, captures, index,
+  // and subject for the replace function invocation.
+  var index = lastMatchInfo[CAPTURE0];
+  // The number of captures plus one for the match.
+  var m = NUMBER_OF_CAPTURES(lastMatchInfo) >> 1;
+  if (m == 1) {
+    var s = CaptureString(subject, lastMatchInfo, 0);
+    // Don't call directly to avoid exposing the built-in global object.
+    return ToString(replace.call(null, s, index, subject));
+  }
+  var parameters = $Array(m + 2);
+  for (var j = 0; j < m; j++) {
+    parameters[j] = CaptureString(subject, lastMatchInfo, j);
+  }
+  parameters[j] = index;
+  parameters[j + 1] = subject;
+  return ToString(replace.apply(null, parameters));
+}
+
+
+// ECMA-262 section 15.5.4.12
+function StringSearch(re) {
+  var regexp = new ORIGINAL_REGEXP(re);
+  var s = ToString(this);
+  var last_idx = regexp.lastIndex; // keep old lastIndex
+  regexp.lastIndex = 0;            // ignore re.global property
+  var result = regexp.exec(s);
+  regexp.lastIndex = last_idx;     // restore lastIndex
+  if (result == null)
+    return -1;
+  else
+    return result.index;
+}
+
+
+// ECMA-262 section 15.5.4.13
+function StringSlice(start, end) {
+  var s = ToString(this);
+  var s_len = s.length;
+  var start_i = TO_INTEGER(start);
+  var end_i = s_len;
+  if (end !== void 0)
+    end_i = TO_INTEGER(end);
+
+  if (start_i < 0) {
+    start_i += s_len;
+    if (start_i < 0)
+      start_i = 0;
+  } else {
+    if (start_i > s_len)
+      start_i = s_len;
+  }
+
+  if (end_i < 0) {
+    end_i += s_len;
+    if (end_i < 0)
+      end_i = 0;
+  } else {
+    if (end_i > s_len)
+      end_i = s_len;
+  }
+
+  var num_c = end_i - start_i;
+  if (num_c < 0)
+    num_c = 0;
+
+  return SubString(s, start_i, start_i + num_c);
+}
+
+
+// ECMA-262 section 15.5.4.14
+function StringSplit(separator, limit) {
+  var subject = ToString(this);
+  var result = [];
+  var lim = (limit === void 0) ? 0xffffffff : ToUint32(limit);
+
+  if (lim === 0) return result;
+
+  // ECMA-262 says that if separator is undefined, the result should
+  // be an array of size 1 containing the entire string.  SpiderMonkey
+  // and KJS have this behaviour only when no separator is given.  If
+  // undefined is explicitly given, they convert it to a string and
+  // use that.  We do as SpiderMonkey and KJS.
+  if (%_ArgumentsLength() === 0) {
+    result[result.length] = subject;
+    return result;
+  }
+
+  var length = subject.length;
+  var currentIndex = 0;
+  var startIndex = 0;
+
+  var sep;
+  if (IS_REGEXP(separator)) {
+    sep = separator;
+    %_Log('regexp', 'regexp-split,%0S,%1r', [subject, sep]);
+  } else {
+    sep = ToString(separator);
+  }
+
+  if (length === 0) {
+    if (splitMatch(sep, subject, 0, 0) != null) return result;
+    result[result.length] = subject;
+    return result;
+  }
+
+  while (true) {
+
+    if (startIndex === length) {
+      result[result.length] = subject.slice(currentIndex, length);
+      return result;
+    }
+
+    var lastMatchInfo = splitMatch(sep, subject, currentIndex, startIndex);
+
+    if (IS_NULL(lastMatchInfo)) {
+      result[result.length] = subject.slice(currentIndex, length);
+      return result;
+    }
+
+    var endIndex = lastMatchInfo[CAPTURE1];
+
+    // We ignore a zero-length match at the currentIndex.
+    if (startIndex === endIndex && endIndex === currentIndex) {
+      startIndex++;
+      continue;
+    }
+
+    result[result.length] =
+        SubString(subject, currentIndex, lastMatchInfo[CAPTURE0]);
+    if (result.length === lim) return result;
+
+    for (var i = 2; i < NUMBER_OF_CAPTURES(lastMatchInfo); i += 2) {
+      var start = lastMatchInfo[CAPTURE(i)];
+      var end = lastMatchInfo[CAPTURE(i + 1)];
+      if (start != -1 && end != -1) {
+        result[result.length] = SubString(subject,
+                                          lastMatchInfo[CAPTURE(i)],
+                                          lastMatchInfo[CAPTURE(i + 1)]);
+      } else {
+        result[result.length] = void 0;
+      }
+      if (result.length === lim) return result;
+    }
+
+    startIndex = currentIndex = endIndex;
+  }
+}
+
+
+// ECMA-262 section 15.5.4.14
+// Helper function used by split.  This version returns the lastMatchInfo
+// instead of allocating a new array with basically the same information.
+function splitMatch(separator, subject, current_index, start_index) {
+  if (IS_REGEXP(separator)) {
+    var lastMatchInfo = DoRegExpExec(separator, subject, start_index);
+    if (lastMatchInfo == null) return null;
+    // Section 15.5.4.14 paragraph two says that we do not allow zero length
+    // matches at the end of the string.
+    if (lastMatchInfo[CAPTURE0] === subject.length) return null;
+    return lastMatchInfo;
+  }
+
+  var separatorIndex = subject.indexOf(separator, start_index);
+  if (separatorIndex === -1) return null;
+
+  reusableMatchInfo[CAPTURE0] = separatorIndex;
+  reusableMatchInfo[CAPTURE1] = separatorIndex + separator.length;
+  return reusableMatchInfo;
+};
+
+
+// ECMA-262 section 15.5.4.15
+function StringSubstring(start, end) {
+  var s = ToString(this);
+  var s_len = s.length;
+  var start_i = TO_INTEGER(start);
+  var end_i = s_len;
+  if (!IS_UNDEFINED(end))
+    end_i = TO_INTEGER(end);
+
+  if (start_i < 0) start_i = 0;
+  if (start_i > s_len) start_i = s_len;
+  if (end_i < 0) end_i = 0;
+  if (end_i > s_len) end_i = s_len;
+
+  if (start_i > end_i) {
+    var tmp = end_i;
+    end_i = start_i;
+    start_i = tmp;
+  }
+
+  return SubString(s, start_i, end_i);
+}
+
+
+// This is not a part of ECMA-262.
+function StringSubstr(start, n) {
+  var s = ToString(this);
+  var len;
+
+  // Correct n: If not given, set to string length; if explicitly
+  // set to undefined, zero, or negative, returns empty string.
+  if (n === void 0) {
+    len = s.length;
+  } else {
+    len = TO_INTEGER(n);
+    if (len <= 0) return '';
+  }
+
+  // Correct start: If not given (or undefined), set to zero; otherwise
+  // convert to integer and handle negative case.
+  if (start === void 0) {
+    start = 0;
+  } else {
+    start = TO_INTEGER(start);
+    // If positive, and greater than or equal to the string length,
+    // return empty string.
+    if (start >= s.length) return '';
+    // If negative and absolute value is larger than the string length,
+    // use zero.
+    if (start < 0) {
+      start += s.length;
+      if (start < 0) start = 0;
+    }
+  }
+
+  var end = start + len;
+  if (end > s.length) end = s.length;
+
+  return SubString(s, start, end);
+}
+
+
+// ECMA-262, 15.5.4.16
+function StringToLowerCase() {
+  return %StringToLowerCase(ToString(this));
+}
+
+
+// ECMA-262, 15.5.4.17
+function StringToLocaleLowerCase() {
+  return %StringToLowerCase(ToString(this));
+}
+
+
+// ECMA-262, 15.5.4.18
+function StringToUpperCase() {
+  return %StringToUpperCase(ToString(this));
+}
+
+
+// ECMA-262, 15.5.4.19
+function StringToLocaleUpperCase() {
+  return %StringToUpperCase(ToString(this));
+}
+
+
+// ECMA-262, section 15.5.3.2
+function StringFromCharCode(code) {
+  var n = %_ArgumentsLength();
+  if (n == 1) return %CharFromCode(ToNumber(code) & 0xffff)
+
+  // NOTE: This is not super-efficient, but it is necessary because we
+  // want to avoid converting to numbers from within the virtual
+  // machine. Maybe we can find another way of doing this?
+  var codes = new $Array(n);
+  for (var i = 0; i < n; i++) codes[i] = ToNumber(%_Arguments(i));
+  return %StringFromCharCodeArray(codes);
+}
+
+
+// Helper function for very basic XSS protection.
+function HtmlEscape(str) {
+  return ToString(str).replace(/</g, "&lt;")
+                      .replace(/>/g, "&gt;")
+                      .replace(/"/g, "&quot;")
+                      .replace(/'/g, "&#039;");
+};
+
+
+// Compatibility support for KJS.
+// Tested by mozilla/js/tests/js1_5/Regress/regress-276103.js.
+function StringLink(s) {
+  return "<a href=\"" + HtmlEscape(s) + "\">" + this + "</a>";
+}
+
+
+function StringAnchor(name) {
+  return "<a name=\"" + HtmlEscape(name) + "\">" + this + "</a>";
+}
+
+
+function StringFontcolor(color) {
+  return "<font color=\"" + HtmlEscape(color) + "\">" + this + "</font>";
+}
+
+
+function StringFontsize(size) {
+  return "<font size=\"" + HtmlEscape(size) + "\">" + this + "</font>";
+}
+
+
+function StringBig() {
+  return "<big>" + this + "</big>";
+}
+
+
+function StringBlink() {
+  return "<blink>" + this + "</blink>";
+}
+
+
+function StringBold() {
+  return "<b>" + this + "</b>";
+}
+
+
+function StringFixed() {
+  return "<tt>" + this + "</tt>";
+}
+
+
+function StringItalics() {
+  return "<i>" + this + "</i>";
+}
+
+
+function StringSmall() {
+  return "<small>" + this + "</small>";
+}
+
+
+function StringStrike() {
+  return "<strike>" + this + "</strike>";
+}
+
+
+function StringSub() {
+  return "<sub>" + this + "</sub>";
+}
+
+
+function StringSup() {
+  return "<sup>" + this + "</sup>";
+}
+
+
+// StringBuilder support.
+
+function StringBuilder() {
+  this.elements = new $Array();
+}
+
+
+function ReplaceResultBuilder(str) {
+  this.elements = new $Array();
+  this.special_string = str;
+}
+
+
+ReplaceResultBuilder.prototype.add =
+StringBuilder.prototype.add = function(str) {
+  if (!IS_STRING(str)) str = ToString(str);
+  if (str.length > 0) {
+    var elements = this.elements;
+    elements[elements.length] = str;
+  }
+}
+
+
+ReplaceResultBuilder.prototype.addSpecialSlice = function(start, end) {
+  var len = end - start;
+  if (len == 0) return;
+  var elements = this.elements;
+  if (start >= 0 && len >= 0 && start < 0x80000 && len < 0x800) {
+    elements[elements.length] = (start << 11) + len;
+  } else {
+    elements[elements.length] = SubString(this.special_string, start, end);
+  }
+}
+
+
+StringBuilder.prototype.generate = function() {
+  return %StringBuilderConcat(this.elements, "");
+}
+
+
+ReplaceResultBuilder.prototype.generate = function() {
+  return %StringBuilderConcat(this.elements, this.special_string);
+}
+
+
+// -------------------------------------------------------------------
+
+function SetupString() {
+  // Setup the constructor property on the String prototype object.
+  %SetProperty($String.prototype, "constructor", $String, DONT_ENUM);
+
+
+  // Setup the non-enumerable functions on the String object.
+  InstallFunctions($String, DONT_ENUM, $Array(
+    "fromCharCode", StringFromCharCode
+  ));
+
+
+  // Setup the non-enumerable functions on the String prototype object.
+  InstallFunctions($String.prototype, DONT_ENUM, $Array(
+    "valueOf", StringValueOf,
+    "toString", StringToString,
+    "charAt", StringCharAt,
+    "charCodeAt", StringCharCodeAt,
+    "concat", StringConcat,
+    "indexOf", StringIndexOf,
+    "lastIndexOf", StringLastIndexOf,
+    "localeCompare", StringLocaleCompare,
+    "match", StringMatch,
+    "replace", StringReplace,
+    "search", StringSearch,
+    "slice", StringSlice,
+    "split", StringSplit,
+    "substring", StringSubstring,
+    "substr", StringSubstr,
+    "toLowerCase", StringToLowerCase,
+    "toLocaleLowerCase", StringToLocaleLowerCase,
+    "toUpperCase", StringToUpperCase,
+    "toLocaleUpperCase", StringToLocaleUpperCase,
+    "link", StringLink,
+    "anchor", StringAnchor,
+    "fontcolor", StringFontcolor,
+    "fontsize", StringFontsize,
+    "big", StringBig,
+    "blink", StringBlink,
+    "bold", StringBold,
+    "fixed", StringFixed,
+    "italics", StringItalics,
+    "small", StringSmall,
+    "strike", StringStrike,
+    "sub", StringSub,
+    "sup", StringSup
+  ));
+}
+
+
+SetupString();
diff --git a/deps/v8/src/stub-cache-arm.cc b/deps/v8/src/stub-cache-arm.cc
new file mode 100644
index 0000000..211b643
--- /dev/null
+++ b/deps/v8/src/stub-cache-arm.cc
@@ -0,0 +1,1125 @@
+// 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.
+
+#include "v8.h"
+
+#include "ic-inl.h"
+#include "codegen-inl.h"
+#include "stub-cache.h"
+
+namespace v8 { namespace internal {
+
+#define __ masm->
+
+
+static void ProbeTable(MacroAssembler* masm,
+                       Code::Flags flags,
+                       StubCache::Table table,
+                       Register name,
+                       Register offset) {
+  ExternalReference key_offset(SCTableReference::keyReference(table));
+  ExternalReference value_offset(SCTableReference::valueReference(table));
+
+  Label miss;
+
+  // Save the offset on the stack.
+  __ push(offset);
+
+  // Check that the key in the entry matches the name.
+  __ mov(ip, Operand(key_offset));
+  __ ldr(ip, MemOperand(ip, offset, LSL, 1));
+  __ cmp(name, Operand(ip));
+  __ b(ne, &miss);
+
+  // Get the code entry from the cache.
+  __ mov(ip, Operand(value_offset));
+  __ ldr(offset, MemOperand(ip, offset, LSL, 1));
+
+  // Check that the flags match what we're looking for.
+  __ ldr(offset, FieldMemOperand(offset, Code::kFlagsOffset));
+  __ and_(offset, offset, Operand(~Code::kFlagsTypeMask));
+  __ cmp(offset, Operand(flags));
+  __ b(ne, &miss);
+
+  // Restore offset and re-load code entry from cache.
+  __ pop(offset);
+  __ mov(ip, Operand(value_offset));
+  __ ldr(offset, MemOperand(ip, offset, LSL, 1));
+
+  // Jump to the first instruction in the code stub.
+  __ add(offset, offset, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ Jump(offset);
+
+  // Miss: Restore offset and fall through.
+  __ bind(&miss);
+  __ pop(offset);
+}
+
+
+void StubCache::GenerateProbe(MacroAssembler* masm,
+                              Code::Flags flags,
+                              Register receiver,
+                              Register name,
+                              Register scratch) {
+  Label miss;
+
+  // Make sure that code is valid. The shifting code relies on the
+  // entry size being 8.
+  ASSERT(sizeof(Entry) == 8);
+
+  // Make sure the flags does not name a specific type.
+  ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
+
+  // Make sure that there are no register conflicts.
+  ASSERT(!scratch.is(receiver));
+  ASSERT(!scratch.is(name));
+
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, &miss);
+
+  // Get the map of the receiver and compute the hash.
+  __ ldr(scratch, FieldMemOperand(name, String::kLengthOffset));
+  __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset));
+  __ add(scratch, scratch, Operand(ip));
+  __ eor(scratch, scratch, Operand(flags));
+  __ and_(scratch,
+          scratch,
+          Operand((kPrimaryTableSize - 1) << kHeapObjectTagSize));
+
+  // Probe the primary table.
+  ProbeTable(masm, flags, kPrimary, name, scratch);
+
+  // Primary miss: Compute hash for secondary probe.
+  __ sub(scratch, scratch, Operand(name));
+  __ add(scratch, scratch, Operand(flags));
+  __ and_(scratch,
+          scratch,
+          Operand((kSecondaryTableSize - 1) << kHeapObjectTagSize));
+
+  // Probe the secondary table.
+  ProbeTable(masm, flags, kSecondary, name, scratch);
+
+  // Cache miss: Fall-through and let caller handle the miss by
+  // entering the runtime system.
+  __ bind(&miss);
+}
+
+
+void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
+                                                       int index,
+                                                       Register prototype) {
+  // Load the global or builtins object from the current context.
+  __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
+  // Load the global context from the global or builtins object.
+  __ ldr(prototype,
+         FieldMemOperand(prototype, GlobalObject::kGlobalContextOffset));
+  // Load the function from the global context.
+  __ ldr(prototype, MemOperand(prototype, Context::SlotOffset(index)));
+  // Load the initial map.  The global functions all have initial maps.
+  __ ldr(prototype,
+         FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
+  // Load the prototype from the initial map.
+  __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
+}
+
+
+// Load a fast property out of a holder object (src). In-object properties
+// are loaded directly otherwise the property is loaded from the properties
+// fixed array.
+void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
+                                            Register dst, Register src,
+                                            JSObject* holder, int index) {
+  // Adjust for the number of properties stored in the holder.
+  index -= holder->map()->inobject_properties();
+  if (index < 0) {
+    // Get the property straight out of the holder.
+    int offset = holder->map()->instance_size() + (index * kPointerSize);
+    __ ldr(dst, FieldMemOperand(src, offset));
+  } else {
+    // Calculate the offset into the properties array.
+    int offset = index * kPointerSize + Array::kHeaderSize;
+    __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset));
+    __ ldr(dst, FieldMemOperand(dst, offset));
+  }
+}
+
+
+void StubCompiler::GenerateLoadField(MacroAssembler* masm,
+                                     JSObject* object,
+                                     JSObject* holder,
+                                     Register receiver,
+                                     Register scratch1,
+                                     Register scratch2,
+                                     int index,
+                                     Label* miss_label) {
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, miss_label);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+  GenerateFastPropertyLoad(masm, r0, reg, holder, index);
+  __ Ret();
+}
+
+
+void StubCompiler::GenerateLoadConstant(MacroAssembler* masm,
+                                        JSObject* object,
+                                        JSObject* holder,
+                                        Register receiver,
+                                        Register scratch1,
+                                        Register scratch2,
+                                        Object* value,
+                                        Label* miss_label) {
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, miss_label);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+
+  // Return the constant value.
+  __ mov(r0, Operand(Handle<Object>(value)));
+  __ Ret();
+}
+
+
+void StubCompiler::GenerateLoadCallback(MacroAssembler* masm,
+                                        JSObject* object,
+                                        JSObject* holder,
+                                        Register receiver,
+                                        Register name,
+                                        Register scratch1,
+                                        Register scratch2,
+                                        AccessorInfo* callback,
+                                        Label* miss_label) {
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, miss_label);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+
+  // Push the arguments on the JS stack of the caller.
+  __ push(receiver);  // receiver
+  __ mov(ip, Operand(Handle<AccessorInfo>(callback)));  // callback data
+  __ push(ip);
+  __ push(name);  // name
+  __ push(reg);  // holder
+
+  // Do tail-call to the runtime system.
+  ExternalReference load_callback_property =
+      ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
+  __ TailCallRuntime(load_callback_property, 4);
+}
+
+
+void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
+                                           JSObject* object,
+                                           JSObject* holder,
+                                           Register receiver,
+                                           Register name,
+                                           Register scratch1,
+                                           Register scratch2,
+                                           Label* miss_label) {
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, miss_label);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+
+  // Push the arguments on the JS stack of the caller.
+  __ push(receiver);  // receiver
+  __ push(reg);  // holder
+  __ push(name);  // name
+
+  // Do tail-call to the runtime system.
+  ExternalReference load_ic_property =
+      ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
+  __ TailCallRuntime(load_ic_property, 3);
+}
+
+
+void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
+                                           Register receiver,
+                                           Register scratch,
+                                           Label* miss_label) {
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, miss_label);
+
+  // Check that the object is a JS array.
+  __ ldr(scratch, FieldMemOperand(receiver, HeapObject::kMapOffset));
+  __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
+  __ cmp(scratch, Operand(JS_ARRAY_TYPE));
+  __ b(ne, miss_label);
+
+  // Load length directly from the JS array.
+  __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+  __ Ret();
+}
+
+
+// Generate code to check if an object is a string.  If the object is
+// a string, the map's instance type is left in the scratch1 register.
+static void GenerateStringCheck(MacroAssembler* masm,
+                                Register receiver,
+                                Register scratch1,
+                                Register scratch2,
+                                Label* smi,
+                                Label* non_string_object) {
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, smi);
+
+  // Check that the object is a string.
+  __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
+  __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
+  __ and_(scratch2, scratch1, Operand(kIsNotStringMask));
+  // The cast is to resolve the overload for the argument of 0x0.
+  __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag)));
+  __ b(ne, non_string_object);
+}
+
+
+// Generate code to load the length from a string object and return the length.
+// If the receiver object is not a string or a wrapped string object the
+// execution continues at the miss label. The register containing the
+// receiver is potentially clobbered.
+void StubCompiler::GenerateLoadStringLength2(MacroAssembler* masm,
+                                             Register receiver,
+                                             Register scratch1,
+                                             Register scratch2,
+                                             Label* miss) {
+  Label check_string, check_wrapper;
+
+  __ bind(&check_string);
+  // Check if the object is a string leaving the instance type in the
+  // scratch1 register.
+  GenerateStringCheck(masm, receiver, scratch1, scratch2,
+                      miss, &check_wrapper);
+
+  // Load length directly from the string.
+  __ and_(scratch1, scratch1, Operand(kStringSizeMask));
+  __ add(scratch1, scratch1, Operand(String::kHashShift));
+  __ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset));
+  __ mov(r0, Operand(r0, LSR, scratch1));
+  __ mov(r0, Operand(r0, LSL, kSmiTagSize));
+  __ Ret();
+
+  // Check if the object is a JSValue wrapper.
+  __ bind(&check_wrapper);
+  __ cmp(scratch1, Operand(JS_VALUE_TYPE));
+  __ b(ne, miss);
+
+  // Unwrap the value in place and check if the wrapped value is a string.
+  __ ldr(receiver, FieldMemOperand(receiver, JSValue::kValueOffset));
+  __ b(&check_string);
+}
+
+
+// Generate StoreField code, value is passed in r0 register.
+// After executing generated code, the receiver_reg and name_reg
+// may be clobbered.
+void StubCompiler::GenerateStoreField(MacroAssembler* masm,
+                                      Builtins::Name storage_extend,
+                                      JSObject* object,
+                                      int index,
+                                      Map* transition,
+                                      Register receiver_reg,
+                                      Register name_reg,
+                                      Register scratch,
+                                      Label* miss_label) {
+  // r0 : value
+  Label exit;
+
+  // Check that the receiver isn't a smi.
+  __ tst(receiver_reg, Operand(kSmiTagMask));
+  __ b(eq, miss_label);
+
+  // Check that the map of the receiver hasn't changed.
+  __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
+  __ cmp(scratch, Operand(Handle<Map>(object->map())));
+  __ b(ne, miss_label);
+
+  // Perform global security token check if needed.
+  if (object->IsJSGlobalProxy()) {
+    __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
+  }
+
+  // Stub never generated for non-global objects that require access
+  // checks.
+  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
+
+  // Perform map transition for the receiver if necessary.
+  if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
+    // The properties must be extended before we can store the value.
+    // We jump to a runtime call that extends the properties array.
+    __ mov(r2, Operand(Handle<Map>(transition)));
+    // Please note, if we implement keyed store for arm we need
+    // to call the Builtins::KeyedStoreIC_ExtendStorage.
+    Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_ExtendStorage));
+    __ Jump(ic, RelocInfo::CODE_TARGET);
+    return;
+  }
+
+  if (transition != NULL) {
+    // Update the map of the object; no write barrier updating is
+    // needed because the map is never in new space.
+    __ mov(ip, Operand(Handle<Map>(transition)));
+    __ str(ip, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
+  }
+
+  // Adjust for the number of properties stored in the object. Even in the
+  // face of a transition we can use the old map here because the size of the
+  // object and the number of in-object properties is not going to change.
+  index -= object->map()->inobject_properties();
+
+  if (index < 0) {
+    // Set the property straight into the object.
+    int offset = object->map()->instance_size() + (index * kPointerSize);
+    __ str(r0, FieldMemOperand(receiver_reg, offset));
+
+    // Skip updating write barrier if storing a smi.
+    __ tst(r0, Operand(kSmiTagMask));
+    __ b(eq, &exit);
+
+    // Update the write barrier for the array address.
+    // Pass the value being stored in the now unused name_reg.
+    __ mov(name_reg, Operand(offset));
+    __ RecordWrite(receiver_reg, name_reg, scratch);
+  } else {
+    // Write to the properties array.
+    int offset = index * kPointerSize + Array::kHeaderSize;
+    // Get the properties array
+    __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
+    __ str(r0, FieldMemOperand(scratch, offset));
+
+    // Skip updating write barrier if storing a smi.
+    __ tst(r0, Operand(kSmiTagMask));
+    __ b(eq, &exit);
+
+    // Update the write barrier for the array address.
+    // Ok to clobber receiver_reg and name_reg, since we return.
+    __ mov(name_reg, Operand(offset));
+    __ RecordWrite(scratch, name_reg, receiver_reg);
+  }
+
+  // Return the value (register r0).
+  __ bind(&exit);
+  __ Ret();
+}
+
+
+void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
+  ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
+  Code* code = NULL;
+  if (kind == Code::LOAD_IC) {
+    code = Builtins::builtin(Builtins::LoadIC_Miss);
+  } else {
+    code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
+  }
+
+  Handle<Code> ic(code);
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+}
+
+
+#undef __
+
+#define __ masm()->
+
+
+Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
+  // ----------- S t a t e -------------
+  //  -- r1: function
+  //  -- lr: return address
+  // -----------------------------------
+
+  // Enter an internal frame.
+  __ EnterInternalFrame();
+
+  // Preserve the function.
+  __ push(r1);
+
+  // Push the function on the stack as the argument to the runtime function.
+  __ push(r1);
+  __ CallRuntime(Runtime::kLazyCompile, 1);
+
+  // Calculate the entry point.
+  __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
+
+  // Restore saved function.
+  __ pop(r1);
+
+  // Tear down temporary frame.
+  __ LeaveInternalFrame();
+
+  // Do a tail-call of the compiled function.
+  __ Jump(r2);
+
+  return GetCodeWithFlags(flags, "LazyCompileStub");
+}
+
+
+Object* CallStubCompiler::CompileCallField(Object* object,
+                                           JSObject* holder,
+                                           int index,
+                                           String* name) {
+  // ----------- S t a t e -------------
+  //  -- lr: return address
+  // -----------------------------------
+  Label miss;
+
+  const int argc = arguments().immediate();
+
+  // Get the receiver of the function from the stack into r0.
+  __ ldr(r0, MemOperand(sp, argc * kPointerSize));
+  // Check that the receiver isn't a smi.
+  __ tst(r0, Operand(kSmiTagMask));
+  __ b(eq, &miss);
+
+  // Do the right check and compute the holder register.
+  Register reg =
+      __ CheckMaps(JSObject::cast(object), r0, holder, r3, r2, &miss);
+  GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
+
+  // Check that the function really is a function.
+  __ tst(r1, Operand(kSmiTagMask));
+  __ b(eq, &miss);
+  // Get the map.
+  __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+  __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
+  __ cmp(r2, Operand(JS_FUNCTION_TYPE));
+  __ b(ne, &miss);
+
+  // Patch the receiver on the stack with the global proxy if
+  // necessary.
+  if (object->IsGlobalObject()) {
+    __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
+    __ str(r3, MemOperand(sp, argc * kPointerSize));
+  }
+
+  // Invoke the function.
+  __ InvokeFunction(r1, arguments(), JUMP_FUNCTION);
+
+  // Handle call cache miss.
+  __ bind(&miss);
+  Handle<Code> ic = ComputeCallMiss(arguments().immediate());
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(FIELD, name);
+}
+
+
+Object* CallStubCompiler::CompileCallConstant(Object* object,
+                                              JSObject* holder,
+                                              JSFunction* function,
+                                              CheckType check) {
+  // ----------- S t a t e -------------
+  //  -- lr: return address
+  // -----------------------------------
+  Label miss;
+
+  // Get the receiver from the stack
+  const int argc = arguments().immediate();
+  __ ldr(r1, MemOperand(sp, argc * kPointerSize));
+
+  // Check that the receiver isn't a smi.
+  if (check != NUMBER_CHECK) {
+    __ tst(r1, Operand(kSmiTagMask));
+    __ b(eq, &miss);
+  }
+
+  // Make sure that it's okay not to patch the on stack receiver
+  // unless we're doing a receiver map check.
+  ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
+
+  switch (check) {
+    case RECEIVER_MAP_CHECK:
+      // Check that the maps haven't changed.
+      __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
+
+      // Patch the receiver on the stack with the global proxy if
+      // necessary.
+      if (object->IsGlobalObject()) {
+        __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
+        __ str(r3, MemOperand(sp, argc * kPointerSize));
+      }
+      break;
+
+    case STRING_CHECK:
+      // Check that the object is a two-byte string or a symbol.
+      __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+      __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
+      __ cmp(r2, Operand(FIRST_NONSTRING_TYPE));
+      __ b(hs, &miss);
+      // Check that the maps starting from the prototype haven't changed.
+      GenerateLoadGlobalFunctionPrototype(masm(),
+                                          Context::STRING_FUNCTION_INDEX,
+                                          r2);
+      __ CheckMaps(JSObject::cast(object->GetPrototype()),
+                   r2, holder, r3, r1, &miss);
+      break;
+
+    case NUMBER_CHECK: {
+      Label fast;
+      // Check that the object is a smi or a heap number.
+      __ tst(r1, Operand(kSmiTagMask));
+      __ b(eq, &fast);
+      __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+      __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
+      __ cmp(r2, Operand(HEAP_NUMBER_TYPE));
+      __ b(ne, &miss);
+      __ bind(&fast);
+      // Check that the maps starting from the prototype haven't changed.
+      GenerateLoadGlobalFunctionPrototype(masm(),
+                                          Context::NUMBER_FUNCTION_INDEX,
+                                          r2);
+      __ CheckMaps(JSObject::cast(object->GetPrototype()),
+                   r2, holder, r3, r1, &miss);
+      break;
+    }
+
+    case BOOLEAN_CHECK: {
+      Label fast;
+      // Check that the object is a boolean.
+      __ cmp(r1, Operand(Factory::true_value()));
+      __ b(eq, &fast);
+      __ cmp(r1, Operand(Factory::false_value()));
+      __ b(ne, &miss);
+      __ bind(&fast);
+      // Check that the maps starting from the prototype haven't changed.
+      GenerateLoadGlobalFunctionPrototype(masm(),
+                                          Context::BOOLEAN_FUNCTION_INDEX,
+                                          r2);
+      __ CheckMaps(JSObject::cast(object->GetPrototype()),
+                   r2, holder, r3, r1, &miss);
+      break;
+    }
+
+    case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
+      __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
+      // Make sure object->elements()->map() != Heap::hash_table_map()
+      // Get the elements array of the object.
+      __ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset));
+      // Check that the object is in fast mode (not dictionary).
+      __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
+      __ cmp(r2, Operand(Factory::hash_table_map()));
+      __ b(eq, &miss);
+      break;
+
+    default:
+      UNREACHABLE();
+  }
+
+  // Get the function and setup the context.
+  __ mov(r1, Operand(Handle<JSFunction>(function)));
+  __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
+
+  // Jump to the cached code (tail call).
+  Handle<Code> code(function->code());
+  ParameterCount expected(function->shared()->formal_parameter_count());
+  __ InvokeCode(code, expected, arguments(),
+                RelocInfo::CODE_TARGET, JUMP_FUNCTION);
+
+  // Handle call cache miss.
+  __ bind(&miss);
+  Handle<Code> ic = ComputeCallMiss(arguments().immediate());
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  String* function_name = NULL;
+  if (function->shared()->name()->IsString()) {
+    function_name = String::cast(function->shared()->name());
+  }
+  return GetCode(CONSTANT_FUNCTION, function_name);
+}
+
+
+Object* CallStubCompiler::CompileCallInterceptor(Object* object,
+                                                 JSObject* holder,
+                                                 String* name) {
+  // ----------- S t a t e -------------
+  //  -- lr: return address
+  // -----------------------------------
+  Label miss;
+
+  // TODO(1224669): Implement.
+
+  // Handle call cache miss.
+  __ bind(&miss);
+  Handle<Code> ic = ComputeCallMiss(arguments().immediate());
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(INTERCEPTOR, name);
+}
+
+
+Object* StoreStubCompiler::CompileStoreField(JSObject* object,
+                                             int index,
+                                             Map* transition,
+                                             String* name) {
+  // ----------- S t a t e -------------
+  //  -- r0    : value
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+  Label miss;
+
+  // Get the receiver from the stack.
+  __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
+
+  // name register might be clobbered.
+  GenerateStoreField(masm(),
+                     Builtins::StoreIC_ExtendStorage,
+                     object,
+                     index,
+                     transition,
+                     r3, r2, r1,
+                     &miss);
+  __ bind(&miss);
+  __ mov(r2, Operand(Handle<String>(name)));  // restore name
+  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
+}
+
+
+Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
+                                                AccessorInfo* callback,
+                                                String* name) {
+  // ----------- S t a t e -------------
+  //  -- r0    : value
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+  Label miss;
+
+  // Get the object from the stack.
+  __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
+
+  // Check that the object isn't a smi.
+  __ tst(r3, Operand(kSmiTagMask));
+  __ b(eq, &miss);
+
+  // Check that the map of the object hasn't changed.
+  __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
+  __ cmp(r1, Operand(Handle<Map>(object->map())));
+  __ b(ne, &miss);
+
+  // Perform global security token check if needed.
+  if (object->IsJSGlobalProxy()) {
+    __ CheckAccessGlobalProxy(r3, r1, &miss);
+  }
+
+  // Stub never generated for non-global objects that require access
+  // checks.
+  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
+
+  __ ldr(ip, MemOperand(sp));  // receiver
+  __ push(ip);
+  __ mov(ip, Operand(Handle<AccessorInfo>(callback)));  // callback info
+  __ push(ip);
+  __ push(r2);  // name
+  __ push(r0);  // value
+
+  // Do tail-call to the runtime system.
+  ExternalReference store_callback_property =
+      ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
+  __ TailCallRuntime(store_callback_property, 4);
+
+  // Handle store cache miss.
+  __ bind(&miss);
+  __ mov(r2, Operand(Handle<String>(name)));  // restore name
+  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(CALLBACKS, name);
+}
+
+
+Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
+                                                   String* name) {
+  // ----------- S t a t e -------------
+  //  -- r0    : value
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+  Label miss;
+
+  // Get the object from the stack.
+  __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
+
+  // Check that the object isn't a smi.
+  __ tst(r3, Operand(kSmiTagMask));
+  __ b(eq, &miss);
+
+  // Check that the map of the object hasn't changed.
+  __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
+  __ cmp(r1, Operand(Handle<Map>(receiver->map())));
+  __ b(ne, &miss);
+
+  // Perform global security token check if needed.
+  if (receiver->IsJSGlobalProxy()) {
+    __ CheckAccessGlobalProxy(r3, r1, &miss);
+  }
+
+  // Stub never generated for non-global objects that require access
+  // checks.
+  ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
+
+  __ ldr(ip, MemOperand(sp));  // receiver
+  __ push(ip);
+  __ push(r2);  // name
+  __ push(r0);  // value
+
+  // Do tail-call to the runtime system.
+  ExternalReference store_ic_property =
+      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
+  __ TailCallRuntime(store_ic_property, 3);
+
+  // Handle store cache miss.
+  __ bind(&miss);
+  __ mov(r2, Operand(Handle<String>(name)));  // restore name
+  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(INTERCEPTOR, name);
+}
+
+
+Object* LoadStubCompiler::CompileLoadField(JSObject* object,
+                                           JSObject* holder,
+                                           int index,
+                                           String* name) {
+  // ----------- S t a t e -------------
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+  Label miss;
+
+  __ ldr(r0, MemOperand(sp, 0));
+
+  GenerateLoadField(masm(), object, holder, r0, r3, r1, index, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(FIELD, name);
+}
+
+
+Object* LoadStubCompiler::CompileLoadCallback(JSObject* object,
+                                              JSObject* holder,
+                                              AccessorInfo* callback,
+                                              String* name) {
+  // ----------- S t a t e -------------
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+  Label miss;
+
+  __ ldr(r0, MemOperand(sp, 0));
+  GenerateLoadCallback(masm(), object, holder, r0, r2, r3, r1, callback, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(CALLBACKS, name);
+}
+
+
+Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
+                                              JSObject* holder,
+                                              Object* value,
+                                              String* name) {
+  // ----------- S t a t e -------------
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp] : receiver
+  // -----------------------------------
+  Label miss;
+
+  __ ldr(r0, MemOperand(sp, 0));
+
+  GenerateLoadConstant(masm(), object, holder, r0, r3, r1, value, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(CONSTANT_FUNCTION, name);
+}
+
+
+Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
+                                                 JSObject* holder,
+                                                 String* name) {
+  // ----------- S t a t e -------------
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+  Label miss;
+
+  __ ldr(r0, MemOperand(sp, 0));
+
+  GenerateLoadInterceptor(masm(), object, holder, r0, r2, r3, r1, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(INTERCEPTOR, name);
+}
+
+
+// TODO(1224671): IC stubs for keyed loads have not been implemented
+// for ARM.
+Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
+                                                JSObject* receiver,
+                                                JSObject* holder,
+                                                int index) {
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- sp[0] : key
+  //  -- sp[4] : receiver
+  // -----------------------------------
+  Label miss;
+
+  __ ldr(r2, MemOperand(sp, 0));
+  __ ldr(r0, MemOperand(sp, kPointerSize));
+
+  __ cmp(r2, Operand(Handle<String>(name)));
+  __ b(ne, &miss);
+
+  GenerateLoadField(masm(), receiver, holder, r0, r3, r1, index, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(FIELD, name);
+}
+
+
+Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
+                                                   JSObject* receiver,
+                                                   JSObject* holder,
+                                                   AccessorInfo* callback) {
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- sp[0] : key
+  //  -- sp[4] : receiver
+  // -----------------------------------
+  Label miss;
+
+  __ ldr(r2, MemOperand(sp, 0));
+  __ ldr(r0, MemOperand(sp, kPointerSize));
+
+  __ cmp(r2, Operand(Handle<String>(name)));
+  __ b(ne, &miss);
+
+  GenerateLoadCallback(masm(), receiver, holder, r0, r2, r3,
+                       r1, callback, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(CALLBACKS, name);
+}
+
+
+Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
+                                                   JSObject* receiver,
+                                                   JSObject* holder,
+                                                   Object* value) {
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- sp[0] : key
+  //  -- sp[4] : receiver
+  // -----------------------------------
+  Label miss;
+
+  // Check the key is the cached one
+  __ ldr(r2, MemOperand(sp, 0));
+  __ ldr(r0, MemOperand(sp, kPointerSize));
+
+  __ cmp(r2, Operand(Handle<String>(name)));
+  __ b(ne, &miss);
+
+  GenerateLoadConstant(masm(), receiver, holder, r0, r3, r1, value, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(CONSTANT_FUNCTION, name);
+}
+
+
+Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
+                                                      JSObject* holder,
+                                                      String* name) {
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- sp[0] : key
+  //  -- sp[4] : receiver
+  // -----------------------------------
+  Label miss;
+
+  // Check the key is the cached one
+  __ ldr(r2, MemOperand(sp, 0));
+  __ ldr(r0, MemOperand(sp, kPointerSize));
+
+  __ cmp(r2, Operand(Handle<String>(name)));
+  __ b(ne, &miss);
+
+  GenerateLoadInterceptor(masm(), receiver, holder, r0, r2, r3, r1, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(INTERCEPTOR, name);
+}
+
+
+Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- sp[0] : key
+  //  -- sp[4] : receiver
+  // -----------------------------------
+  Label miss;
+
+  // Check the key is the cached one
+  __ ldr(r2, MemOperand(sp, 0));
+  __ ldr(r0, MemOperand(sp, kPointerSize));
+
+  __ cmp(r2, Operand(Handle<String>(name)));
+  __ b(ne, &miss);
+
+  GenerateLoadArrayLength(masm(), r0, r3, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(CALLBACKS, name);
+}
+
+
+Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- sp[0] : key
+  //  -- sp[4] : receiver
+  // -----------------------------------
+  Label miss;
+  __ IncrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
+
+  __ ldr(r2, MemOperand(sp));
+  __ ldr(r0, MemOperand(sp, kPointerSize));  // receiver
+
+  __ cmp(r2, Operand(Handle<String>(name)));
+  __ b(ne, &miss);
+
+  GenerateLoadStringLength2(masm(), r0, r1, r3, &miss);
+  __ bind(&miss);
+  __ DecrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
+
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(CALLBACKS, name);
+}
+
+
+// TODO(1224671): implement the fast case.
+Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- sp[0] : key
+  //  -- sp[4] : receiver
+  // -----------------------------------
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(CALLBACKS, name);
+}
+
+
+Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
+                                                  int index,
+                                                  Map* transition,
+                                                  String* name) {
+  // ----------- S t a t e -------------
+  //  -- r0    : value
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+  Label miss;
+
+  __ IncrementCounter(&Counters::keyed_store_field, 1, r1, r3);
+
+  // Check that the name has not changed.
+  __ cmp(r2, Operand(Handle<String>(name)));
+  __ b(ne, &miss);
+
+  // Load receiver from the stack.
+  __ ldr(r3, MemOperand(sp));
+  // r1 is used as scratch register, r3 and r2 might be clobbered.
+  GenerateStoreField(masm(),
+                     Builtins::StoreIC_ExtendStorage,
+                     object,
+                     index,
+                     transition,
+                     r3, r2, r1,
+                     &miss);
+  __ bind(&miss);
+
+  __ DecrementCounter(&Counters::keyed_store_field, 1, r1, r3);
+  __ mov(r2, Operand(Handle<String>(name)));  // restore name register.
+  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
+}
+
+
+#undef __
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/stub-cache-ia32.cc b/deps/v8/src/stub-cache-ia32.cc
new file mode 100644
index 0000000..19777e6
--- /dev/null
+++ b/deps/v8/src/stub-cache-ia32.cc
@@ -0,0 +1,1179 @@
+// 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.
+
+#include "v8.h"
+
+#include "ic-inl.h"
+#include "codegen-inl.h"
+#include "stub-cache.h"
+
+namespace v8 { namespace internal {
+
+#define __ masm->
+
+
+static void ProbeTable(MacroAssembler* masm,
+                       Code::Flags flags,
+                       StubCache::Table table,
+                       Register name,
+                       Register offset) {
+  ExternalReference key_offset(SCTableReference::keyReference(table));
+  ExternalReference value_offset(SCTableReference::valueReference(table));
+
+  Label miss;
+
+  // Save the offset on the stack.
+  __ push(offset);
+
+  // Check that the key in the entry matches the name.
+  __ cmp(name, Operand::StaticArray(offset, times_2, key_offset));
+  __ j(not_equal, &miss, not_taken);
+
+  // Get the code entry from the cache.
+  __ mov(offset, Operand::StaticArray(offset, times_2, value_offset));
+
+  // Check that the flags match what we're looking for.
+  __ mov(offset, FieldOperand(offset, Code::kFlagsOffset));
+  __ and_(offset, ~Code::kFlagsTypeMask);
+  __ cmp(offset, flags);
+  __ j(not_equal, &miss);
+
+  // Restore offset and re-load code entry from cache.
+  __ pop(offset);
+  __ mov(offset, Operand::StaticArray(offset, times_2, value_offset));
+
+  // Jump to the first instruction in the code stub.
+  __ add(Operand(offset), Immediate(Code::kHeaderSize - kHeapObjectTag));
+  __ jmp(Operand(offset));
+
+  // Miss: Restore offset and fall through.
+  __ bind(&miss);
+  __ pop(offset);
+}
+
+
+void StubCache::GenerateProbe(MacroAssembler* masm,
+                              Code::Flags flags,
+                              Register receiver,
+                              Register name,
+                              Register scratch) {
+  Label miss;
+
+  // Make sure that code is valid. The shifting code relies on the
+  // entry size being 8.
+  ASSERT(sizeof(Entry) == 8);
+
+  // Make sure the flags does not name a specific type.
+  ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
+
+  // Make sure that there are no register conflicts.
+  ASSERT(!scratch.is(receiver));
+  ASSERT(!scratch.is(name));
+
+  // Check that the receiver isn't a smi.
+  __ test(receiver, Immediate(kSmiTagMask));
+  __ j(zero, &miss, not_taken);
+
+  // Get the map of the receiver and compute the hash.
+  __ mov(scratch, FieldOperand(name, String::kLengthOffset));
+  __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
+  __ xor_(scratch, flags);
+  __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
+
+  // Probe the primary table.
+  ProbeTable(masm, flags, kPrimary, name, scratch);
+
+  // Primary miss: Compute hash for secondary probe.
+  __ sub(scratch, Operand(name));
+  __ add(Operand(scratch), Immediate(flags));
+  __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize);
+
+  // Probe the secondary table.
+  ProbeTable(masm, flags, kSecondary, name, scratch);
+
+  // Cache miss: Fall-through and let caller handle the miss by
+  // entering the runtime system.
+  __ bind(&miss);
+}
+
+
+void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
+                                                       int index,
+                                                       Register prototype) {
+  // Load the global or builtins object from the current context.
+  __ mov(prototype, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
+  // Load the global context from the global or builtins object.
+  __ mov(prototype,
+         FieldOperand(prototype, GlobalObject::kGlobalContextOffset));
+  // Load the function from the global context.
+  __ mov(prototype, Operand(prototype, Context::SlotOffset(index)));
+  // Load the initial map.  The global functions all have initial maps.
+  __ mov(prototype,
+         FieldOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
+  // Load the prototype from the initial map.
+  __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
+}
+
+
+void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
+                                           Register receiver,
+                                           Register scratch,
+                                           Label* miss_label) {
+  // Check that the receiver isn't a smi.
+  __ test(receiver, Immediate(kSmiTagMask));
+  __ j(zero, miss_label, not_taken);
+
+  // Check that the object is a JS array.
+  __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
+  __ j(not_equal, miss_label, not_taken);
+
+  // Load length directly from the JS array.
+  __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset));
+  __ ret(0);
+}
+
+
+// Generate code to check if an object is a string.  If the object is
+// a string, the map's instance type is left in the scratch register.
+static void GenerateStringCheck(MacroAssembler* masm,
+                                Register receiver,
+                                Register scratch,
+                                Label* smi,
+                                Label* non_string_object) {
+  // Check that the object isn't a smi.
+  __ test(receiver, Immediate(kSmiTagMask));
+  __ j(zero, smi, not_taken);
+
+  // Check that the object is a string.
+  __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
+  __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
+  ASSERT(kNotStringTag != 0);
+  __ test(scratch, Immediate(kNotStringTag));
+  __ j(not_zero, non_string_object, not_taken);
+}
+
+
+void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
+                                            Register receiver,
+                                            Register scratch,
+                                            Label* miss) {
+  Label load_length, check_wrapper;
+
+  // Check if the object is a string leaving the instance type in the
+  // scratch register.
+  GenerateStringCheck(masm, receiver, scratch, miss, &check_wrapper);
+
+  // Load length directly from the string.
+  __ bind(&load_length);
+  __ and_(scratch, kStringSizeMask);
+  __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
+  // ecx is also the receiver.
+  __ lea(ecx, Operand(scratch, String::kLongLengthShift));
+  __ shr(eax);  // ecx is implicit shift register.
+  __ shl(eax, kSmiTagSize);
+  __ ret(0);
+
+  // Check if the object is a JSValue wrapper.
+  __ bind(&check_wrapper);
+  __ cmp(scratch, JS_VALUE_TYPE);
+  __ j(not_equal, miss, not_taken);
+
+  // Check if the wrapped value is a string and load the length
+  // directly if it is.
+  __ mov(receiver, FieldOperand(receiver, JSValue::kValueOffset));
+  GenerateStringCheck(masm, receiver, scratch, miss, miss);
+  __ jmp(&load_length);
+}
+
+
+void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
+                                                 Register receiver,
+                                                 Register scratch1,
+                                                 Register scratch2,
+                                                 Label* miss_label) {
+  __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
+  __ mov(eax, Operand(scratch1));
+  __ ret(0);
+}
+
+
+// Load a fast property out of a holder object (src). In-object properties
+// are loaded directly otherwise the property is loaded from the properties
+// fixed array.
+void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
+                                            Register dst, Register src,
+                                            JSObject* holder, int index) {
+  // Adjust for the number of properties stored in the holder.
+  index -= holder->map()->inobject_properties();
+  if (index < 0) {
+    // Get the property straight out of the holder.
+    int offset = holder->map()->instance_size() + (index * kPointerSize);
+    __ mov(dst, FieldOperand(src, offset));
+  } else {
+    // Calculate the offset into the properties array.
+    int offset = index * kPointerSize + Array::kHeaderSize;
+    __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset));
+    __ mov(dst, FieldOperand(dst, offset));
+  }
+}
+
+
+void StubCompiler::GenerateLoadField(MacroAssembler* masm,
+                                     JSObject* object,
+                                     JSObject* holder,
+                                     Register receiver,
+                                     Register scratch1,
+                                     Register scratch2,
+                                     int index,
+                                     Label* miss_label) {
+  // Check that the receiver isn't a smi.
+  __ test(receiver, Immediate(kSmiTagMask));
+  __ j(zero, miss_label, not_taken);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+
+  // Get the value from the properties.
+  GenerateFastPropertyLoad(masm, eax, reg, holder, index);
+  __ ret(0);
+}
+
+
+void StubCompiler::GenerateLoadCallback(MacroAssembler* masm,
+                                        JSObject* object,
+                                        JSObject* holder,
+                                        Register receiver,
+                                        Register name,
+                                        Register scratch1,
+                                        Register scratch2,
+                                        AccessorInfo* callback,
+                                        Label* miss_label) {
+  // Check that the receiver isn't a smi.
+  __ test(receiver, Immediate(kSmiTagMask));
+  __ j(zero, miss_label, not_taken);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+
+  // Push the arguments on the JS stack of the caller.
+  __ pop(scratch2);  // remove return address
+  __ push(receiver);  // receiver
+  __ push(Immediate(Handle<AccessorInfo>(callback)));  // callback data
+  __ push(name);  // name
+  __ push(reg);  // holder
+  __ push(scratch2);  // restore return address
+
+  // Do tail-call to the runtime system.
+  ExternalReference load_callback_property =
+      ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
+  __ TailCallRuntime(load_callback_property, 4);
+}
+
+
+void StubCompiler::GenerateLoadConstant(MacroAssembler* masm,
+                                        JSObject* object,
+                                        JSObject* holder,
+                                        Register receiver,
+                                        Register scratch1,
+                                        Register scratch2,
+                                        Object* value,
+                                        Label* miss_label) {
+  // Check that the receiver isn't a smi.
+  __ test(receiver, Immediate(kSmiTagMask));
+  __ j(zero, miss_label, not_taken);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+
+  // Return the constant value.
+  __ mov(eax, Handle<Object>(value));
+  __ ret(0);
+}
+
+
+void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
+                                           JSObject* object,
+                                           JSObject* holder,
+                                           Register receiver,
+                                           Register name,
+                                           Register scratch1,
+                                           Register scratch2,
+                                           Label* miss_label) {
+  // Check that the receiver isn't a smi.
+  __ test(receiver, Immediate(kSmiTagMask));
+  __ j(zero, miss_label, not_taken);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+
+  // Push the arguments on the JS stack of the caller.
+  __ pop(scratch2);  // remove return address
+  __ push(receiver);  // receiver
+  __ push(reg);  // holder
+  __ push(name);  // name
+  __ push(scratch2);  // restore return address
+
+  // Do tail-call to the runtime system.
+  ExternalReference load_ic_property =
+      ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
+  __ TailCallRuntime(load_ic_property, 3);
+}
+
+
+void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
+  ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
+  Code* code = NULL;
+  if (kind == Code::LOAD_IC) {
+    code = Builtins::builtin(Builtins::LoadIC_Miss);
+  } else {
+    code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
+  }
+
+  Handle<Code> ic(code);
+  __ jmp(ic, RelocInfo::CODE_TARGET);
+}
+
+
+void StubCompiler::GenerateStoreField(MacroAssembler* masm,
+                                      Builtins::Name storage_extend,
+                                      JSObject* object,
+                                      int index,
+                                      Map* transition,
+                                      Register receiver_reg,
+                                      Register name_reg,
+                                      Register scratch,
+                                      Label* miss_label) {
+  // Check that the object isn't a smi.
+  __ test(receiver_reg, Immediate(kSmiTagMask));
+  __ j(zero, miss_label, not_taken);
+
+  // Check that the map of the object hasn't changed.
+  __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset),
+         Immediate(Handle<Map>(object->map())));
+  __ j(not_equal, miss_label, not_taken);
+
+  // Perform global security token check if needed.
+  if (object->IsJSGlobalProxy()) {
+    __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
+  }
+
+  // Stub never generated for non-global objects that require access
+  // checks.
+  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
+
+  // Perform map transition for the receiver if necessary.
+  if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
+    // The properties must be extended before we can store the value.
+    // We jump to a runtime call that extends the properties array.
+    __ mov(ecx, Immediate(Handle<Map>(transition)));
+    Handle<Code> ic(Builtins::builtin(storage_extend));
+    __ jmp(ic, RelocInfo::CODE_TARGET);
+    return;
+  }
+
+  if (transition != NULL) {
+    // Update the map of the object; no write barrier updating is
+    // needed because the map is never in new space.
+    __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset),
+           Immediate(Handle<Map>(transition)));
+  }
+
+  // Adjust for the number of properties stored in the object. Even in the
+  // face of a transition we can use the old map here because the size of the
+  // object and the number of in-object properties is not going to change.
+  index -= object->map()->inobject_properties();
+
+  if (index < 0) {
+    // Set the property straight into the object.
+    int offset = object->map()->instance_size() + (index * kPointerSize);
+    __ mov(FieldOperand(receiver_reg, offset), eax);
+
+    // Update the write barrier for the array address.
+    // Pass the value being stored in the now unused name_reg.
+    __ mov(name_reg, Operand(eax));
+    __ RecordWrite(receiver_reg, offset, name_reg, scratch);
+  } else {
+    // Write to the properties array.
+    int offset = index * kPointerSize + Array::kHeaderSize;
+    // Get the properties array (optimistically).
+    __ mov(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
+    __ mov(FieldOperand(scratch, offset), eax);
+
+    // Update the write barrier for the array address.
+    // Pass the value being stored in the now unused name_reg.
+    __ mov(name_reg, Operand(eax));
+    __ RecordWrite(scratch, offset, name_reg, receiver_reg);
+  }
+
+  // Return the value (register eax).
+  __ ret(0);
+}
+
+
+#undef __
+
+#define __ masm()->
+
+
+// TODO(1241006): Avoid having lazy compile stubs specialized by the
+// number of arguments. It is not needed anymore.
+Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
+  // Enter an internal frame.
+  __ EnterInternalFrame();
+
+  // Push a copy of the function onto the stack.
+  __ push(edi);
+
+  __ push(edi);  // function is also the parameter to the runtime call
+  __ CallRuntime(Runtime::kLazyCompile, 1);
+  __ pop(edi);
+
+  // Tear down temporary frame.
+  __ LeaveInternalFrame();
+
+  // Do a tail-call of the compiled function.
+  __ lea(ecx, FieldOperand(eax, Code::kHeaderSize));
+  __ jmp(Operand(ecx));
+
+  return GetCodeWithFlags(flags, "LazyCompileStub");
+}
+
+
+Object* CallStubCompiler::CompileCallField(Object* object,
+                                           JSObject* holder,
+                                           int index,
+                                           String* name) {
+  // ----------- S t a t e -------------
+  // -----------------------------------
+  Label miss;
+
+  // Get the receiver from the stack.
+  const int argc = arguments().immediate();
+  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
+
+  // Check that the receiver isn't a smi.
+  __ test(edx, Immediate(kSmiTagMask));
+  __ j(zero, &miss, not_taken);
+
+  // Do the right check and compute the holder register.
+  Register reg =
+      __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
+
+  GenerateFastPropertyLoad(masm(), edi, reg, holder, index);
+
+  // Check that the function really is a function.
+  __ test(edi, Immediate(kSmiTagMask));
+  __ j(zero, &miss, not_taken);
+  __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
+  __ j(not_equal, &miss, not_taken);
+
+  // Patch the receiver on the stack with the global proxy if
+  // necessary.
+  if (object->IsGlobalObject()) {
+    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
+    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
+  }
+
+  // Invoke the function.
+  __ InvokeFunction(edi, arguments(), JUMP_FUNCTION);
+
+  // Handle call cache miss.
+  __ bind(&miss);
+  Handle<Code> ic = ComputeCallMiss(arguments().immediate());
+  __ jmp(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(FIELD, name);
+}
+
+
+Object* CallStubCompiler::CompileCallConstant(Object* object,
+                                              JSObject* holder,
+                                              JSFunction* function,
+                                              CheckType check) {
+  // ----------- S t a t e -------------
+  // -----------------------------------
+  Label miss;
+
+  // Get the receiver from the stack.
+  const int argc = arguments().immediate();
+  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
+
+  // Check that the receiver isn't a smi.
+  if (check != NUMBER_CHECK) {
+    __ test(edx, Immediate(kSmiTagMask));
+    __ j(zero, &miss, not_taken);
+  }
+
+  // Make sure that it's okay not to patch the on stack receiver
+  // unless we're doing a receiver map check.
+  ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
+
+  switch (check) {
+    case RECEIVER_MAP_CHECK:
+      // Check that the maps haven't changed.
+      __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
+
+      // Patch the receiver on the stack with the global proxy if
+      // necessary.
+      if (object->IsGlobalObject()) {
+        __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
+        __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
+      }
+      break;
+
+    case STRING_CHECK:
+      // Check that the object is a two-byte string or a symbol.
+      __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
+      __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
+      __ cmp(ecx, FIRST_NONSTRING_TYPE);
+      __ j(above_equal, &miss, not_taken);
+      // Check that the maps starting from the prototype haven't changed.
+      GenerateLoadGlobalFunctionPrototype(masm(),
+                                          Context::STRING_FUNCTION_INDEX,
+                                          ecx);
+      __ CheckMaps(JSObject::cast(object->GetPrototype()),
+                   ecx, holder, ebx, edx, &miss);
+      break;
+
+    case NUMBER_CHECK: {
+      Label fast;
+      // Check that the object is a smi or a heap number.
+      __ test(edx, Immediate(kSmiTagMask));
+      __ j(zero, &fast, taken);
+      __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx);
+      __ j(not_equal, &miss, not_taken);
+      __ bind(&fast);
+      // Check that the maps starting from the prototype haven't changed.
+      GenerateLoadGlobalFunctionPrototype(masm(),
+                                          Context::NUMBER_FUNCTION_INDEX,
+                                          ecx);
+      __ CheckMaps(JSObject::cast(object->GetPrototype()),
+                   ecx, holder, ebx, edx, &miss);
+      break;
+    }
+
+    case BOOLEAN_CHECK: {
+      Label fast;
+      // Check that the object is a boolean.
+      __ cmp(edx, Factory::true_value());
+      __ j(equal, &fast, taken);
+      __ cmp(edx, Factory::false_value());
+      __ j(not_equal, &miss, not_taken);
+      __ bind(&fast);
+      // Check that the maps starting from the prototype haven't changed.
+      GenerateLoadGlobalFunctionPrototype(masm(),
+                                          Context::BOOLEAN_FUNCTION_INDEX,
+                                          ecx);
+      __ CheckMaps(JSObject::cast(object->GetPrototype()),
+                   ecx, holder, ebx, edx, &miss);
+      break;
+    }
+
+    case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
+      __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
+      // Make sure object->elements()->map() != Heap::dictionary_array_map()
+      // Get the elements array of the object.
+      __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
+      // Check that the object is in fast mode (not dictionary).
+      __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
+             Immediate(Factory::hash_table_map()));
+      __ j(equal, &miss, not_taken);
+      break;
+
+    default:
+      UNREACHABLE();
+  }
+
+  // Get the function and setup the context.
+  __ mov(edi, Immediate(Handle<JSFunction>(function)));
+  __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
+
+  // Jump to the cached code (tail call).
+  Handle<Code> code(function->code());
+  ParameterCount expected(function->shared()->formal_parameter_count());
+  __ InvokeCode(code, expected, arguments(),
+                RelocInfo::CODE_TARGET, JUMP_FUNCTION);
+
+  // Handle call cache miss.
+  __ bind(&miss);
+  Handle<Code> ic = ComputeCallMiss(arguments().immediate());
+  __ jmp(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  String* function_name = NULL;
+  if (function->shared()->name()->IsString()) {
+    function_name = String::cast(function->shared()->name());
+  }
+  return GetCode(CONSTANT_FUNCTION, function_name);
+}
+
+
+Object* CallStubCompiler::CompileCallInterceptor(Object* object,
+                                                 JSObject* holder,
+                                                 String* name) {
+  // ----------- S t a t e -------------
+  // -----------------------------------
+  Label miss;
+
+  // Get the number of arguments.
+  const int argc = arguments().immediate();
+
+  // Get the receiver from the stack.
+  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
+
+  // Check that the receiver isn't a smi.
+  __ test(edx, Immediate(kSmiTagMask));
+  __ j(zero, &miss, not_taken);
+
+  // Check that maps have not changed and compute the holder register.
+  Register reg =
+      __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
+
+  // Enter an internal frame.
+  __ EnterInternalFrame();
+
+  // Push arguments on the expression stack.
+  __ push(edx);  // receiver
+  __ push(reg);  // holder
+  __ push(Operand(ebp, (argc + 3) * kPointerSize));  // name
+
+  // Perform call.
+  ExternalReference load_interceptor =
+      ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
+  __ mov(eax, Immediate(3));
+  __ mov(ebx, Immediate(load_interceptor));
+
+  CEntryStub stub;
+  __ CallStub(&stub);
+
+  // Move result to edi and restore receiver.
+  __ mov(edi, eax);
+  __ mov(edx, Operand(ebp, (argc + 2) * kPointerSize));  // receiver
+
+  // Exit frame.
+  __ LeaveInternalFrame();
+
+  // Check that the function really is a function.
+  __ test(edi, Immediate(kSmiTagMask));
+  __ j(zero, &miss, not_taken);
+  __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
+  __ j(not_equal, &miss, not_taken);
+
+  // Patch the receiver on the stack with the global proxy if
+  // necessary.
+  if (object->IsGlobalObject()) {
+    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
+    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
+  }
+
+  // Invoke the function.
+  __ InvokeFunction(edi, arguments(), JUMP_FUNCTION);
+
+  // Handle load cache miss.
+  __ bind(&miss);
+  Handle<Code> ic = ComputeCallMiss(argc);
+  __ jmp(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(INTERCEPTOR, name);
+}
+
+
+Object* StoreStubCompiler::CompileStoreField(JSObject* object,
+                                             int index,
+                                             Map* transition,
+                                             String* name) {
+  // ----------- S t a t e -------------
+  //  -- eax    : value
+  //  -- ecx    : name
+  //  -- esp[0] : return address
+  //  -- esp[4] : receiver
+  // -----------------------------------
+  Label miss;
+
+  // Get the object from the stack.
+  __ mov(ebx, Operand(esp, 1 * kPointerSize));
+
+  // Generate store field code.  Trashes the name register.
+  GenerateStoreField(masm(),
+                     Builtins::StoreIC_ExtendStorage,
+                     object,
+                     index,
+                     transition,
+                     ebx, ecx, edx,
+                     &miss);
+
+  // Handle store cache miss.
+  __ bind(&miss);
+  __ mov(ecx, Immediate(Handle<String>(name)));  // restore name
+  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+  __ jmp(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
+}
+
+
+Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
+                                                AccessorInfo* callback,
+                                                String* name) {
+  // ----------- S t a t e -------------
+  //  -- eax    : value
+  //  -- ecx    : name
+  //  -- esp[0] : return address
+  //  -- esp[4] : receiver
+  // -----------------------------------
+  Label miss;
+
+  // Get the object from the stack.
+  __ mov(ebx, Operand(esp, 1 * kPointerSize));
+
+  // Check that the object isn't a smi.
+  __ test(ebx, Immediate(kSmiTagMask));
+  __ j(zero, &miss, not_taken);
+
+  // Check that the map of the object hasn't changed.
+  __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
+         Immediate(Handle<Map>(object->map())));
+  __ j(not_equal, &miss, not_taken);
+
+  // Perform global security token check if needed.
+  if (object->IsJSGlobalProxy()) {
+    __ CheckAccessGlobalProxy(ebx, edx, &miss);
+  }
+
+  // Stub never generated for non-global objects that require access
+  // checks.
+  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
+
+  __ pop(ebx);  // remove the return address
+  __ push(Operand(esp, 0));  // receiver
+  __ push(Immediate(Handle<AccessorInfo>(callback)));  // callback info
+  __ push(ecx);  // name
+  __ push(eax);  // value
+  __ push(ebx);  // restore return address
+
+  // Do tail-call to the runtime system.
+  ExternalReference store_callback_property =
+      ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
+  __ TailCallRuntime(store_callback_property, 4);
+
+  // Handle store cache miss.
+  __ bind(&miss);
+  __ mov(ecx, Immediate(Handle<String>(name)));  // restore name
+  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+  __ jmp(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(CALLBACKS, name);
+}
+
+
+Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
+                                                   String* name) {
+  // ----------- S t a t e -------------
+  //  -- eax    : value
+  //  -- ecx    : name
+  //  -- esp[0] : return address
+  //  -- esp[4] : receiver
+  // -----------------------------------
+  Label miss;
+
+  // Get the object from the stack.
+  __ mov(ebx, Operand(esp, 1 * kPointerSize));
+
+  // Check that the object isn't a smi.
+  __ test(ebx, Immediate(kSmiTagMask));
+  __ j(zero, &miss, not_taken);
+
+  // Check that the map of the object hasn't changed.
+  __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
+         Immediate(Handle<Map>(receiver->map())));
+  __ j(not_equal, &miss, not_taken);
+
+  // Perform global security token check if needed.
+  if (receiver->IsJSGlobalProxy()) {
+    __ CheckAccessGlobalProxy(ebx, edx, &miss);
+  }
+
+  // Stub never generated for non-global objects that require access
+  // checks.
+  ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
+
+  __ pop(ebx);  // remove the return address
+  __ push(Operand(esp, 0));  // receiver
+  __ push(ecx);  // name
+  __ push(eax);  // value
+  __ push(ebx);  // restore return address
+
+  // Do tail-call to the runtime system.
+  ExternalReference store_ic_property =
+      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
+  __ TailCallRuntime(store_ic_property, 3);
+
+  // Handle store cache miss.
+  __ bind(&miss);
+  __ mov(ecx, Immediate(Handle<String>(name)));  // restore name
+  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+  __ jmp(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(INTERCEPTOR, name);
+}
+
+
+Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
+                                                  int index,
+                                                  Map* transition,
+                                                  String* name) {
+  // ----------- S t a t e -------------
+  //  -- eax    : value
+  //  -- esp[0] : return address
+  //  -- esp[4] : key
+  //  -- esp[8] : receiver
+  // -----------------------------------
+  Label miss;
+
+  __ IncrementCounter(&Counters::keyed_store_field, 1);
+
+  // Get the name from the stack.
+  __ mov(ecx, Operand(esp, 1 * kPointerSize));
+  // Check that the name has not changed.
+  __ cmp(Operand(ecx), Immediate(Handle<String>(name)));
+  __ j(not_equal, &miss, not_taken);
+
+  // Get the object from the stack.
+  __ mov(ebx, Operand(esp, 2 * kPointerSize));
+
+  // Generate store field code.  Trashes the name register.
+  GenerateStoreField(masm(),
+                     Builtins::KeyedStoreIC_ExtendStorage,
+                     object,
+                     index,
+                     transition,
+                     ebx, ecx, edx,
+                     &miss);
+
+  // Handle store cache miss.
+  __ bind(&miss);
+  __ DecrementCounter(&Counters::keyed_store_field, 1);
+  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
+  __ jmp(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
+}
+
+
+Object* LoadStubCompiler::CompileLoadField(JSObject* object,
+                                           JSObject* holder,
+                                           int index,
+                                           String* name) {
+  // ----------- S t a t e -------------
+  //  -- ecx    : name
+  //  -- esp[0] : return address
+  //  -- esp[4] : receiver
+  // -----------------------------------
+  Label miss;
+
+  __ mov(eax, (Operand(esp, kPointerSize)));
+  GenerateLoadField(masm(), object, holder, eax, ebx, edx, index, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(FIELD, name);
+}
+
+
+Object* LoadStubCompiler::CompileLoadCallback(JSObject* object,
+                                              JSObject* holder,
+                                              AccessorInfo* callback,
+                                              String* name) {
+  // ----------- S t a t e -------------
+  //  -- ecx    : name
+  //  -- esp[0] : return address
+  //  -- esp[4] : receiver
+  // -----------------------------------
+  Label miss;
+
+  __ mov(eax, (Operand(esp, kPointerSize)));
+  GenerateLoadCallback(masm(), object, holder, eax, ecx, ebx,
+                       edx, callback, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(CALLBACKS, name);
+}
+
+
+Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
+                                              JSObject* holder,
+                                              Object* value,
+                                              String* name) {
+  // ----------- S t a t e -------------
+  //  -- ecx    : name
+  //  -- esp[0] : return address
+  //  -- esp[4] : receiver
+  // -----------------------------------
+  Label miss;
+
+  __ mov(eax, (Operand(esp, kPointerSize)));
+  GenerateLoadConstant(masm(), object, holder, eax, ebx, edx, value, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(CONSTANT_FUNCTION, name);
+}
+
+
+Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
+                                                 JSObject* holder,
+                                                 String* name) {
+  // ----------- S t a t e -------------
+  //  -- ecx    : name
+  //  -- esp[0] : return address
+  //  -- esp[4] : receiver
+  // -----------------------------------
+  Label miss;
+
+  __ mov(eax, (Operand(esp, kPointerSize)));
+  GenerateLoadInterceptor(masm(), receiver, holder, eax, ecx, edx, ebx, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(INTERCEPTOR, name);
+}
+
+
+Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
+                                                JSObject* receiver,
+                                                JSObject* holder,
+                                                int index) {
+  // ----------- S t a t e -------------
+  //  -- esp[0] : return address
+  //  -- esp[4] : name
+  //  -- esp[8] : receiver
+  // -----------------------------------
+  Label miss;
+
+  __ mov(eax, (Operand(esp, kPointerSize)));
+  __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
+  __ IncrementCounter(&Counters::keyed_load_field, 1);
+
+  // Check that the name has not changed.
+  __ cmp(Operand(eax), Immediate(Handle<String>(name)));
+  __ j(not_equal, &miss, not_taken);
+
+  GenerateLoadField(masm(), receiver, holder, ecx, ebx, edx, index, &miss);
+  __ bind(&miss);
+  __ DecrementCounter(&Counters::keyed_load_field, 1);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(FIELD, name);
+}
+
+
+Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
+                                                   JSObject* receiver,
+                                                   JSObject* holder,
+                                                   AccessorInfo* callback) {
+  // ----------- S t a t e -------------
+  //  -- esp[0] : return address
+  //  -- esp[4] : name
+  //  -- esp[8] : receiver
+  // -----------------------------------
+  Label miss;
+
+  __ mov(eax, (Operand(esp, kPointerSize)));
+  __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
+  __ IncrementCounter(&Counters::keyed_load_callback, 1);
+
+  // Check that the name has not changed.
+  __ cmp(Operand(eax), Immediate(Handle<String>(name)));
+  __ j(not_equal, &miss, not_taken);
+
+  GenerateLoadCallback(masm(), receiver, holder, ecx, eax, ebx, edx,
+                       callback, &miss);
+  __ bind(&miss);
+  __ DecrementCounter(&Counters::keyed_load_callback, 1);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(CALLBACKS, name);
+}
+
+
+Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
+                                                   JSObject* receiver,
+                                                   JSObject* holder,
+                                                   Object* value) {
+  // ----------- S t a t e -------------
+  //  -- esp[0] : return address
+  //  -- esp[4] : name
+  //  -- esp[8] : receiver
+  // -----------------------------------
+  Label miss;
+
+  __ mov(eax, (Operand(esp, kPointerSize)));
+  __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
+  __ IncrementCounter(&Counters::keyed_load_constant_function, 1);
+
+  // Check that the name has not changed.
+  __ cmp(Operand(eax), Immediate(Handle<String>(name)));
+  __ j(not_equal, &miss, not_taken);
+
+  GenerateLoadConstant(masm(), receiver, holder, ecx, ebx, edx, value, &miss);
+  __ bind(&miss);
+  __ DecrementCounter(&Counters::keyed_load_constant_function, 1);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(CONSTANT_FUNCTION, name);
+}
+
+
+Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
+                                                      JSObject* holder,
+                                                      String* name) {
+  // ----------- S t a t e -------------
+  //  -- esp[0] : return address
+  //  -- esp[4] : name
+  //  -- esp[8] : receiver
+  // -----------------------------------
+  Label miss;
+
+  __ mov(eax, (Operand(esp, kPointerSize)));
+  __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
+  __ IncrementCounter(&Counters::keyed_load_interceptor, 1);
+
+  // Check that the name has not changed.
+  __ cmp(Operand(eax), Immediate(Handle<String>(name)));
+  __ j(not_equal, &miss, not_taken);
+
+  GenerateLoadInterceptor(masm(), receiver, holder, ecx, eax, edx, ebx, &miss);
+  __ bind(&miss);
+  __ DecrementCounter(&Counters::keyed_load_interceptor, 1);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(INTERCEPTOR, name);
+}
+
+
+
+
+Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
+  // ----------- S t a t e -------------
+  //  -- esp[0] : return address
+  //  -- esp[4] : name
+  //  -- esp[8] : receiver
+  // -----------------------------------
+  Label miss;
+
+  __ mov(eax, (Operand(esp, kPointerSize)));
+  __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
+  __ IncrementCounter(&Counters::keyed_load_array_length, 1);
+
+  // Check that the name has not changed.
+  __ cmp(Operand(eax), Immediate(Handle<String>(name)));
+  __ j(not_equal, &miss, not_taken);
+
+  GenerateLoadArrayLength(masm(), ecx, edx, &miss);
+  __ bind(&miss);
+  __ DecrementCounter(&Counters::keyed_load_array_length, 1);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(CALLBACKS, name);
+}
+
+
+Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
+  // ----------- S t a t e -------------
+  //  -- esp[0] : return address
+  //  -- esp[4] : name
+  //  -- esp[8] : receiver
+  // -----------------------------------
+  Label miss;
+
+  __ mov(eax, (Operand(esp, kPointerSize)));
+  __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
+  __ IncrementCounter(&Counters::keyed_load_string_length, 1);
+
+  // Check that the name has not changed.
+  __ cmp(Operand(eax), Immediate(Handle<String>(name)));
+  __ j(not_equal, &miss, not_taken);
+
+  GenerateLoadStringLength(masm(), ecx, edx, &miss);
+  __ bind(&miss);
+  __ DecrementCounter(&Counters::keyed_load_string_length, 1);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(CALLBACKS, name);
+}
+
+
+Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
+  // ----------- S t a t e -------------
+  //  -- esp[0] : return address
+  //  -- esp[4] : name
+  //  -- esp[8] : receiver
+  // -----------------------------------
+  Label miss;
+
+  __ mov(eax, (Operand(esp, kPointerSize)));
+  __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
+  __ IncrementCounter(&Counters::keyed_load_function_prototype, 1);
+
+  // Check that the name has not changed.
+  __ cmp(Operand(eax), Immediate(Handle<String>(name)));
+  __ j(not_equal, &miss, not_taken);
+
+  GenerateLoadFunctionPrototype(masm(), ecx, edx, ebx, &miss);
+  __ bind(&miss);
+  __ DecrementCounter(&Counters::keyed_load_function_prototype, 1);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(CALLBACKS, name);
+}
+
+
+#undef __
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/stub-cache.cc b/deps/v8/src/stub-cache.cc
new file mode 100644
index 0000000..35e3d42
--- /dev/null
+++ b/deps/v8/src/stub-cache.cc
@@ -0,0 +1,921 @@
+// 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.
+
+#include "v8.h"
+
+#include "api.h"
+#include "arguments.h"
+#include "ic-inl.h"
+#include "stub-cache.h"
+
+namespace v8 { namespace internal {
+
+// -----------------------------------------------------------------------
+// StubCache implementation.
+
+
+StubCache::Entry StubCache::primary_[StubCache::kPrimaryTableSize];
+StubCache::Entry StubCache::secondary_[StubCache::kSecondaryTableSize];
+
+void StubCache::Initialize(bool create_heap_objects) {
+  ASSERT(IsPowerOf2(kPrimaryTableSize));
+  ASSERT(IsPowerOf2(kSecondaryTableSize));
+  if (create_heap_objects) {
+    HandleScope scope;
+    Clear();
+  }
+}
+
+
+Code* StubCache::Set(String* name, Map* map, Code* code) {
+  // Get the flags from the code.
+  Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
+
+  // Validate that the name does not move on scavenge, and that we
+  // can use identity checks instead of string equality checks.
+  ASSERT(!Heap::InNewSpace(name));
+  ASSERT(name->IsSymbol());
+
+  // The state bits are not important to the hash function because
+  // the stub cache only contains monomorphic stubs. Make sure that
+  // the bits are the least significant so they will be the ones
+  // masked out.
+  ASSERT(Code::ExtractICStateFromFlags(flags) == MONOMORPHIC);
+  ASSERT(Code::kFlagsICStateShift == 0);
+
+  // Make sure that the code type is not included in the hash.
+  ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
+
+  // Compute the primary entry.
+  int primary_offset = PrimaryOffset(name, flags, map);
+  Entry* primary = entry(primary_, primary_offset);
+  Code* hit = primary->value;
+
+  // If the primary entry has useful data in it, we retire it to the
+  // secondary cache before overwriting it.
+  if (hit != Builtins::builtin(Builtins::Illegal)) {
+    Code::Flags primary_flags = Code::RemoveTypeFromFlags(hit->flags());
+    int secondary_offset =
+        SecondaryOffset(primary->key, primary_flags, primary_offset);
+    Entry* secondary = entry(secondary_, secondary_offset);
+    *secondary = *primary;
+  }
+
+  // Update primary cache.
+  primary->key = name;
+  primary->value = code;
+  return code;
+}
+
+
+Object* StubCache::ComputeLoadField(String* name,
+                                    JSObject* receiver,
+                                    JSObject* holder,
+                                    int field_index) {
+  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, FIELD);
+  Object* code = receiver->map()->FindInCodeCache(name, flags);
+  if (code->IsUndefined()) {
+    LoadStubCompiler compiler;
+    code = compiler.CompileLoadField(receiver, holder, field_index, name);
+    if (code->IsFailure()) return code;
+    LOG(CodeCreateEvent("LoadIC", Code::cast(code), name));
+    Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
+    if (result->IsFailure()) return code;
+  }
+  return Set(name, receiver->map(), Code::cast(code));
+}
+
+
+Object* StubCache::ComputeLoadCallback(String* name,
+                                       JSObject* receiver,
+                                       JSObject* holder,
+                                       AccessorInfo* callback) {
+  ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
+  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CALLBACKS);
+  Object* code = receiver->map()->FindInCodeCache(name, flags);
+  if (code->IsUndefined()) {
+    LoadStubCompiler compiler;
+    code = compiler.CompileLoadCallback(receiver, holder, callback, name);
+    if (code->IsFailure()) return code;
+    LOG(CodeCreateEvent("LoadIC", Code::cast(code), name));
+    Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
+    if (result->IsFailure()) return code;
+  }
+  return Set(name, receiver->map(), Code::cast(code));
+}
+
+
+Object* StubCache::ComputeLoadConstant(String* name,
+                                       JSObject* receiver,
+                                       JSObject* holder,
+                                       Object* value) {
+  Code::Flags flags =
+      Code::ComputeMonomorphicFlags(Code::LOAD_IC, CONSTANT_FUNCTION);
+  Object* code = receiver->map()->FindInCodeCache(name, flags);
+  if (code->IsUndefined()) {
+    LoadStubCompiler compiler;
+    code = compiler.CompileLoadConstant(receiver, holder, value, name);
+    if (code->IsFailure()) return code;
+    LOG(CodeCreateEvent("LoadIC", Code::cast(code), name));
+    Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
+    if (result->IsFailure()) return code;
+  }
+  return Set(name, receiver->map(), Code::cast(code));
+}
+
+
+Object* StubCache::ComputeLoadInterceptor(String* name,
+                                          JSObject* receiver,
+                                          JSObject* holder) {
+  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, INTERCEPTOR);
+  Object* code = receiver->map()->FindInCodeCache(name, flags);
+  if (code->IsUndefined()) {
+    LoadStubCompiler compiler;
+    code = compiler.CompileLoadInterceptor(receiver, holder, name);
+    if (code->IsFailure()) return code;
+    LOG(CodeCreateEvent("LoadIC", Code::cast(code), name));
+    Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
+    if (result->IsFailure()) return code;
+  }
+  return Set(name, receiver->map(), Code::cast(code));
+}
+
+
+Object* StubCache::ComputeLoadNormal(String* name, JSObject* receiver) {
+  Code* code = Builtins::builtin(Builtins::LoadIC_Normal);
+  return Set(name, receiver->map(), code);
+}
+
+
+Object* StubCache::ComputeKeyedLoadField(String* name,
+                                         JSObject* receiver,
+                                         JSObject* holder,
+                                         int field_index) {
+  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, FIELD);
+  Object* code = receiver->map()->FindInCodeCache(name, flags);
+  if (code->IsUndefined()) {
+    KeyedLoadStubCompiler compiler;
+    code = compiler.CompileLoadField(name, receiver, holder, field_index);
+    if (code->IsFailure()) return code;
+    LOG(CodeCreateEvent("KeyedLoadIC", Code::cast(code), name));
+    Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
+    if (result->IsFailure()) return result;
+  }
+  return code;
+}
+
+
+Object* StubCache::ComputeKeyedLoadConstant(String* name,
+                                            JSObject* receiver,
+                                            JSObject* holder,
+                                            Object* value) {
+  Code::Flags flags =
+      Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION);
+  Object* code = receiver->map()->FindInCodeCache(name, flags);
+  if (code->IsUndefined()) {
+    KeyedLoadStubCompiler compiler;
+    code = compiler.CompileLoadConstant(name, receiver, holder, value);
+    if (code->IsFailure()) return code;
+    LOG(CodeCreateEvent("KeyedLoadIC", Code::cast(code), name));
+    Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
+    if (result->IsFailure()) return result;
+  }
+  return code;
+}
+
+
+Object* StubCache::ComputeKeyedLoadInterceptor(String* name,
+                                               JSObject* receiver,
+                                               JSObject* holder) {
+  Code::Flags flags =
+      Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR);
+  Object* code = receiver->map()->FindInCodeCache(name, flags);
+  if (code->IsUndefined()) {
+    KeyedLoadStubCompiler compiler;
+    code = compiler.CompileLoadInterceptor(receiver, holder, name);
+    if (code->IsFailure()) return code;
+    LOG(CodeCreateEvent("KeyedLoadIC", Code::cast(code), name));
+    Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
+    if (result->IsFailure()) return result;
+  }
+  return code;
+}
+
+
+Object* StubCache::ComputeKeyedLoadCallback(String* name,
+                                            JSObject* receiver,
+                                            JSObject* holder,
+                                            AccessorInfo* callback) {
+  Code::Flags flags =
+      Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
+  Object* code = receiver->map()->FindInCodeCache(name, flags);
+  if (code->IsUndefined()) {
+    KeyedLoadStubCompiler compiler;
+    code = compiler.CompileLoadCallback(name, receiver, holder, callback);
+    if (code->IsFailure()) return code;
+    LOG(CodeCreateEvent("KeyedLoadIC", Code::cast(code), name));
+    Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
+    if (result->IsFailure()) return result;
+  }
+  return code;
+}
+
+
+
+Object* StubCache::ComputeKeyedLoadArrayLength(String* name,
+                                               JSArray* receiver) {
+  Code::Flags flags =
+      Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
+  Object* code = receiver->map()->FindInCodeCache(name, flags);
+  if (code->IsUndefined()) {
+    KeyedLoadStubCompiler compiler;
+    code = compiler.CompileLoadArrayLength(name);
+    if (code->IsFailure()) return code;
+    LOG(CodeCreateEvent("KeyedLoadIC", Code::cast(code), name));
+    Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
+    if (result->IsFailure()) return result;
+  }
+  return code;
+}
+
+
+Object* StubCache::ComputeKeyedLoadStringLength(String* name,
+                                                String* receiver) {
+  Code::Flags flags =
+      Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
+  Object* code = receiver->map()->FindInCodeCache(name, flags);
+  if (code->IsUndefined()) {
+    KeyedLoadStubCompiler compiler;
+    code = compiler.CompileLoadStringLength(name);
+    if (code->IsFailure()) return code;
+    LOG(CodeCreateEvent("KeyedLoadIC", Code::cast(code), name));
+    Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
+    if (result->IsFailure()) return result;
+  }
+  return code;
+}
+
+
+Object* StubCache::ComputeKeyedLoadFunctionPrototype(String* name,
+                                                     JSFunction* receiver) {
+  Code::Flags flags =
+      Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
+  Object* code = receiver->map()->FindInCodeCache(name, flags);
+  if (code->IsUndefined()) {
+    KeyedLoadStubCompiler compiler;
+    code = compiler.CompileLoadFunctionPrototype(name);
+    if (code->IsFailure()) return code;
+    LOG(CodeCreateEvent("KeyedLoadIC", Code::cast(code), name));
+    Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
+    if (result->IsFailure()) return result;
+  }
+  return code;
+}
+
+
+Object* StubCache::ComputeStoreField(String* name,
+                                     JSObject* receiver,
+                                     int field_index,
+                                     Map* transition) {
+  PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
+  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, type);
+  Object* code = receiver->map()->FindInCodeCache(name, flags);
+  if (code->IsUndefined()) {
+    StoreStubCompiler compiler;
+    code = compiler.CompileStoreField(receiver, field_index, transition, name);
+    if (code->IsFailure()) return code;
+    LOG(CodeCreateEvent("StoreIC", Code::cast(code), name));
+    Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
+    if (result->IsFailure()) return result;
+  }
+  return Set(name, receiver->map(), Code::cast(code));
+}
+
+
+Object* StubCache::ComputeStoreCallback(String* name,
+                                        JSObject* receiver,
+                                        AccessorInfo* callback) {
+  ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
+  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, CALLBACKS);
+  Object* code = receiver->map()->FindInCodeCache(name, flags);
+  if (code->IsUndefined()) {
+    StoreStubCompiler compiler;
+    code = compiler.CompileStoreCallback(receiver, callback, name);
+    if (code->IsFailure()) return code;
+    LOG(CodeCreateEvent("StoreIC", Code::cast(code), name));
+    Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
+    if (result->IsFailure()) return result;
+  }
+  return Set(name, receiver->map(), Code::cast(code));
+}
+
+
+Object* StubCache::ComputeStoreInterceptor(String* name,
+                                           JSObject* receiver) {
+  Code::Flags flags =
+      Code::ComputeMonomorphicFlags(Code::STORE_IC, INTERCEPTOR);
+  Object* code = receiver->map()->FindInCodeCache(name, flags);
+  if (code->IsUndefined()) {
+    StoreStubCompiler compiler;
+    code = compiler.CompileStoreInterceptor(receiver, name);
+    if (code->IsFailure()) return code;
+    LOG(CodeCreateEvent("StoreIC", Code::cast(code), name));
+    Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
+    if (result->IsFailure()) return result;
+  }
+  return Set(name, receiver->map(), Code::cast(code));
+}
+
+
+Object* StubCache::ComputeKeyedStoreField(String* name, JSObject* receiver,
+                                          int field_index, Map* transition) {
+  PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
+  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, type);
+  Object* code = receiver->map()->FindInCodeCache(name, flags);
+  if (code->IsUndefined()) {
+    KeyedStoreStubCompiler compiler;
+    code = compiler.CompileStoreField(receiver, field_index, transition, name);
+    if (code->IsFailure()) return code;
+    LOG(CodeCreateEvent("KeyedStoreIC", Code::cast(code), name));
+    Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
+    if (result->IsFailure()) return result;
+  }
+  return code;
+}
+
+
+Object* StubCache::ComputeCallConstant(int argc,
+                                       String* name,
+                                       Object* object,
+                                       JSObject* holder,
+                                       JSFunction* function) {
+  // Compute the check type and the map.
+  Map* map = IC::GetCodeCacheMapForObject(object);
+
+  // Compute check type based on receiver/holder.
+  StubCompiler::CheckType check = StubCompiler::RECEIVER_MAP_CHECK;
+  if (object->IsString()) {
+    check = StubCompiler::STRING_CHECK;
+  } else if (object->IsNumber()) {
+    check = StubCompiler::NUMBER_CHECK;
+  } else if (object->IsBoolean()) {
+    check = StubCompiler::BOOLEAN_CHECK;
+  }
+
+  Code::Flags flags =
+      Code::ComputeMonomorphicFlags(Code::CALL_IC, CONSTANT_FUNCTION, argc);
+  Object* code = map->FindInCodeCache(name, flags);
+  if (code->IsUndefined()) {
+    if (object->IsJSObject()) {
+      Object* opt =
+          Top::LookupSpecialFunction(JSObject::cast(object), holder, function);
+      if (opt->IsJSFunction()) {
+        check = StubCompiler::JSARRAY_HAS_FAST_ELEMENTS_CHECK;
+        function = JSFunction::cast(opt);
+      }
+    }
+    // If the function hasn't been compiled yet, we cannot do it now
+    // because it may cause GC. To avoid this issue, we return an
+    // internal error which will make sure we do not update any
+    // caches.
+    if (!function->is_compiled()) return Failure::InternalError();
+    // Compile the stub - only create stubs for fully compiled functions.
+    CallStubCompiler compiler(argc);
+    code = compiler.CompileCallConstant(object, holder, function, check);
+    if (code->IsFailure()) return code;
+    LOG(CodeCreateEvent("CallIC", Code::cast(code), name));
+    Object* result = map->UpdateCodeCache(name, Code::cast(code));
+    if (result->IsFailure()) return result;
+  }
+  return Set(name, map, Code::cast(code));
+}
+
+
+Object* StubCache::ComputeCallField(int argc,
+                                    String* name,
+                                    Object* object,
+                                    JSObject* holder,
+                                    int index) {
+  // Compute the check type and the map.
+  Map* map = IC::GetCodeCacheMapForObject(object);
+
+  // TODO(1233596): We cannot do receiver map check for non-JS objects
+  // because they may be represented as immediates without a
+  // map. Instead, we check against the map in the holder.
+  if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
+    object = holder;
+  }
+
+  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, FIELD, argc);
+  Object* code = map->FindInCodeCache(name, flags);
+  if (code->IsUndefined()) {
+    CallStubCompiler compiler(argc);
+    code = compiler.CompileCallField(object, holder, index, name);
+    if (code->IsFailure()) return code;
+    LOG(CodeCreateEvent("CallIC", Code::cast(code), name));
+    Object* result = map->UpdateCodeCache(name, Code::cast(code));
+    if (result->IsFailure()) return result;
+  }
+  return Set(name, map, Code::cast(code));
+}
+
+
+Object* StubCache::ComputeCallInterceptor(int argc,
+                                          String* name,
+                                          Object* object,
+                                          JSObject* holder) {
+  // Compute the check type and the map.
+  // If the object is a value, we use the prototype map for the cache.
+  Map* map = IC::GetCodeCacheMapForObject(object);
+
+  // TODO(1233596): We cannot do receiver map check for non-JS objects
+  // because they may be represented as immediates without a
+  // map. Instead, we check against the map in the holder.
+  if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
+    object = holder;
+  }
+
+  Code::Flags flags =
+      Code::ComputeMonomorphicFlags(Code::CALL_IC, INTERCEPTOR, argc);
+  Object* code = map->FindInCodeCache(name, flags);
+  if (code->IsUndefined()) {
+    CallStubCompiler compiler(argc);
+    code = compiler.CompileCallInterceptor(object, holder, name);
+    if (code->IsFailure()) return code;
+    LOG(CodeCreateEvent("CallIC", Code::cast(code), name));
+    Object* result = map->UpdateCodeCache(name, Code::cast(code));
+    if (result->IsFailure()) return result;
+  }
+  return Set(name, map, Code::cast(code));
+}
+
+
+Object* StubCache::ComputeCallNormal(int argc,
+                                     String* name,
+                                     JSObject* receiver) {
+  Object* code = ComputeCallNormal(argc);
+  if (code->IsFailure()) return code;
+  return Set(name, receiver->map(), Code::cast(code));
+}
+
+
+static Object* GetProbeValue(Code::Flags flags) {
+  Dictionary* dictionary = Heap::non_monomorphic_cache();
+  int entry = dictionary->FindNumberEntry(flags);
+  if (entry != -1) return dictionary->ValueAt(entry);
+  return Heap::undefined_value();
+}
+
+
+static Object* ProbeCache(Code::Flags flags) {
+  Object* probe = GetProbeValue(flags);
+  if (probe != Heap::undefined_value()) return probe;
+  // Seed the cache with an undefined value to make sure that any
+  // generated code object can always be inserted into the cache
+  // without causing  allocation failures.
+  Object* result =
+      Heap::non_monomorphic_cache()->AtNumberPut(flags,
+                                                 Heap::undefined_value());
+  if (result->IsFailure()) return result;
+  Heap::set_non_monomorphic_cache(Dictionary::cast(result));
+  return probe;
+}
+
+
+static Object* FillCache(Object* code) {
+  if (code->IsCode()) {
+    int entry =
+        Heap::non_monomorphic_cache()->FindNumberEntry(
+            Code::cast(code)->flags());
+    // The entry must be present see comment in ProbeCache.
+    ASSERT(entry != -1);
+    ASSERT(Heap::non_monomorphic_cache()->ValueAt(entry) ==
+           Heap::undefined_value());
+    Heap::non_monomorphic_cache()->ValueAtPut(entry, code);
+    CHECK(GetProbeValue(Code::cast(code)->flags()) == code);
+  }
+  return code;
+}
+
+
+Code* StubCache::FindCallInitialize(int argc) {
+  Code::Flags flags =
+      Code::ComputeFlags(Code::CALL_IC, UNINITIALIZED, NORMAL, argc);
+  Object* result = ProbeCache(flags);
+  ASSERT(!result->IsUndefined());
+  // This might be called during the marking phase of the collector
+  // hence the unchecked cast.
+  return reinterpret_cast<Code*>(result);
+}
+
+
+Object* StubCache::ComputeCallInitialize(int argc) {
+  Code::Flags flags =
+      Code::ComputeFlags(Code::CALL_IC, UNINITIALIZED, NORMAL, argc);
+  Object* probe = ProbeCache(flags);
+  if (!probe->IsUndefined()) return probe;
+  StubCompiler compiler;
+  return FillCache(compiler.CompileCallInitialize(flags));
+}
+
+
+Object* StubCache::ComputeCallInitializeInLoop(int argc) {
+  Code::Flags flags =
+      Code::ComputeFlags(Code::CALL_IC, UNINITIALIZED_IN_LOOP, NORMAL, argc);
+  Object* probe = ProbeCache(flags);
+  if (!probe->IsUndefined()) return probe;
+  StubCompiler compiler;
+  return FillCache(compiler.CompileCallInitialize(flags));
+}
+
+
+
+Object* StubCache::ComputeCallPreMonomorphic(int argc) {
+  Code::Flags flags =
+      Code::ComputeFlags(Code::CALL_IC, PREMONOMORPHIC, NORMAL, argc);
+  Object* probe = ProbeCache(flags);
+  if (!probe->IsUndefined()) return probe;
+  StubCompiler compiler;
+  return FillCache(compiler.CompileCallPreMonomorphic(flags));
+}
+
+
+Object* StubCache::ComputeCallNormal(int argc) {
+  Code::Flags flags =
+      Code::ComputeFlags(Code::CALL_IC, MONOMORPHIC, NORMAL, argc);
+  Object* probe = ProbeCache(flags);
+  if (!probe->IsUndefined()) return probe;
+  StubCompiler compiler;
+  return FillCache(compiler.CompileCallNormal(flags));
+}
+
+
+Object* StubCache::ComputeCallMegamorphic(int argc) {
+  Code::Flags flags =
+      Code::ComputeFlags(Code::CALL_IC, MEGAMORPHIC, NORMAL, argc);
+  Object* probe = ProbeCache(flags);
+  if (!probe->IsUndefined()) return probe;
+  StubCompiler compiler;
+  return FillCache(compiler.CompileCallMegamorphic(flags));
+}
+
+
+Object* StubCache::ComputeCallMiss(int argc) {
+  Code::Flags flags =
+      Code::ComputeFlags(Code::STUB, MEGAMORPHIC, NORMAL, argc);
+  Object* probe = ProbeCache(flags);
+  if (!probe->IsUndefined()) return probe;
+  StubCompiler compiler;
+  return FillCache(compiler.CompileCallMiss(flags));
+}
+
+
+Object* StubCache::ComputeCallDebugBreak(int argc) {
+  Code::Flags flags =
+      Code::ComputeFlags(Code::CALL_IC, DEBUG_BREAK, NORMAL, argc);
+  Object* probe = ProbeCache(flags);
+  if (!probe->IsUndefined()) return probe;
+  StubCompiler compiler;
+  return FillCache(compiler.CompileCallDebugBreak(flags));
+}
+
+
+Object* StubCache::ComputeCallDebugPrepareStepIn(int argc) {
+  Code::Flags flags =
+      Code::ComputeFlags(Code::CALL_IC, DEBUG_PREPARE_STEP_IN, NORMAL, argc);
+  Object* probe = ProbeCache(flags);
+  if (!probe->IsUndefined()) return probe;
+  StubCompiler compiler;
+  return FillCache(compiler.CompileCallDebugPrepareStepIn(flags));
+}
+
+
+Object* StubCache::ComputeLazyCompile(int argc) {
+  Code::Flags flags =
+      Code::ComputeFlags(Code::STUB, UNINITIALIZED, NORMAL, argc);
+  Object* probe = ProbeCache(flags);
+  if (!probe->IsUndefined()) return probe;
+  StubCompiler compiler;
+  Object* result = FillCache(compiler.CompileLazyCompile(flags));
+  if (result->IsCode()) {
+    Code* code = Code::cast(result);
+    USE(code);
+    LOG(CodeCreateEvent("LazyCompile", code, code->arguments_count()));
+  }
+  return result;
+}
+
+
+void StubCache::Clear() {
+  for (int i = 0; i < kPrimaryTableSize; i++) {
+    primary_[i].key = Heap::empty_string();
+    primary_[i].value = Builtins::builtin(Builtins::Illegal);
+  }
+  for (int j = 0; j < kSecondaryTableSize; j++) {
+    secondary_[j].key = Heap::empty_string();
+    secondary_[j].value = Builtins::builtin(Builtins::Illegal);
+  }
+}
+
+
+// ------------------------------------------------------------------------
+// StubCompiler implementation.
+
+
+// Support function for computing call IC miss stubs.
+Handle<Code> ComputeCallMiss(int argc) {
+  CALL_HEAP_FUNCTION(StubCache::ComputeCallMiss(argc), Code);
+}
+
+
+
+Object* LoadCallbackProperty(Arguments args) {
+  Handle<JSObject> recv = args.at<JSObject>(0);
+  AccessorInfo* callback = AccessorInfo::cast(args[1]);
+  Address getter_address = v8::ToCData<Address>(callback->getter());
+  v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
+  ASSERT(fun != NULL);
+  Handle<String> name = args.at<String>(2);
+  Handle<JSObject> holder = args.at<JSObject>(3);
+  HandleScope scope;
+  Handle<Object> data(callback->data());
+  LOG(ApiNamedPropertyAccess("load", *recv, *name));
+  // NOTE: If we can align the structure of an AccessorInfo with the
+  // locations of the arguments to this function maybe we don't have
+  // to explicitly create the structure but can just pass a pointer
+  // into the stack.
+  v8::AccessorInfo info(v8::Utils::ToLocal(recv),
+                        v8::Utils::ToLocal(data),
+                        v8::Utils::ToLocal(holder));
+  v8::Handle<v8::Value> result;
+  {
+    // Leaving JavaScript.
+    VMState state(EXTERNAL);
+    result = fun(v8::Utils::ToLocal(name), info);
+  }
+  RETURN_IF_SCHEDULED_EXCEPTION();
+  if (result.IsEmpty()) return Heap::undefined_value();
+  return *v8::Utils::OpenHandle(*result);
+}
+
+
+Object* StoreCallbackProperty(Arguments args) {
+  Handle<JSObject> recv = args.at<JSObject>(0);
+  AccessorInfo* callback = AccessorInfo::cast(args[1]);
+  Address setter_address = v8::ToCData<Address>(callback->setter());
+  v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
+  ASSERT(fun != NULL);
+  Handle<String> name = args.at<String>(2);
+  Handle<Object> value = args.at<Object>(3);
+  HandleScope scope;
+  Handle<Object> data(callback->data());
+  LOG(ApiNamedPropertyAccess("store", *recv, *name));
+  v8::AccessorInfo info(v8::Utils::ToLocal(recv),
+                        v8::Utils::ToLocal(data),
+                        v8::Utils::ToLocal(recv));
+  {
+    // Leaving JavaScript.
+    VMState state(EXTERNAL);
+    fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
+  }
+  RETURN_IF_SCHEDULED_EXCEPTION();
+  return *value;
+}
+
+
+Object* LoadInterceptorProperty(Arguments args) {
+  JSObject* recv = JSObject::cast(args[0]);
+  JSObject* holder = JSObject::cast(args[1]);
+  String* name = String::cast(args[2]);
+  ASSERT(holder->HasNamedInterceptor());
+  PropertyAttributes attr = NONE;
+  Object* result = holder->GetPropertyWithInterceptor(recv, name, &attr);
+
+  if (result->IsFailure()) return result;
+
+  // If the property is present, return it.
+  if (attr != ABSENT) return result;
+
+  // If the top frame is an internal frame, this is really a call
+  // IC. In this case, we simply return the undefined result which
+  // will lead to an exception when trying to invoke the result as a
+  // function.
+  StackFrameIterator it;
+  it.Advance();  // skip exit frame
+  if (it.frame()->is_internal()) return result;
+
+  // If the load is non-contextual, just return the undefined result.
+  // Note that both keyed and non-keyed loads may end up here, so we
+  // can't use either LoadIC or KeyedLoadIC constructors.
+  IC ic(IC::NO_EXTRA_FRAME);
+  ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
+  if (!ic.is_contextual()) return result;
+
+  // Throw a reference error.
+  {
+    HandleScope scope;
+    // We cannot use the raw name pointer here since getting the
+    // property might cause a GC.  However, we can get the name from
+    // the stack using the arguments object.
+    Handle<String> name_handle = args.at<String>(2);
+    Handle<Object> error =
+        Factory::NewReferenceError("not_defined",
+                                   HandleVector(&name_handle, 1));
+    return Top::Throw(*error);
+  }
+}
+
+
+Object* StoreInterceptorProperty(Arguments args) {
+  JSObject* recv = JSObject::cast(args[0]);
+  String* name = String::cast(args[1]);
+  Object* value = args[2];
+  ASSERT(recv->HasNamedInterceptor());
+  PropertyAttributes attr = NONE;
+  Object* result = recv->SetPropertyWithInterceptor(name, value, attr);
+  return result;
+}
+
+
+Object* StubCompiler::CompileCallInitialize(Code::Flags flags) {
+  HandleScope scope;
+  int argc = Code::ExtractArgumentsCountFromFlags(flags);
+  CallIC::GenerateInitialize(masm(), argc);
+  Object* result = GetCodeWithFlags(flags, "CompileCallInitialize");
+  if (!result->IsFailure()) {
+    Counters::call_initialize_stubs.Increment();
+    Code* code = Code::cast(result);
+    USE(code);
+    LOG(CodeCreateEvent("CallInitialize", code, code->arguments_count()));
+  }
+  return result;
+}
+
+
+Object* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
+  HandleScope scope;
+  int argc = Code::ExtractArgumentsCountFromFlags(flags);
+  CallIC::GenerateInitialize(masm(), argc);
+  Object* result = GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
+  if (!result->IsFailure()) {
+    Counters::call_premonomorphic_stubs.Increment();
+    Code* code = Code::cast(result);
+    USE(code);
+    LOG(CodeCreateEvent("CallPreMonomorphic", code, code->arguments_count()));
+  }
+  return result;
+}
+
+
+Object* StubCompiler::CompileCallNormal(Code::Flags flags) {
+  HandleScope scope;
+  int argc = Code::ExtractArgumentsCountFromFlags(flags);
+  CallIC::GenerateNormal(masm(), argc);
+  Object* result = GetCodeWithFlags(flags, "CompileCallNormal");
+  if (!result->IsFailure()) {
+    Counters::call_normal_stubs.Increment();
+    Code* code = Code::cast(result);
+    USE(code);
+    LOG(CodeCreateEvent("CallNormal", code, code->arguments_count()));
+  }
+  return result;
+}
+
+
+Object* StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
+  HandleScope scope;
+  int argc = Code::ExtractArgumentsCountFromFlags(flags);
+  CallIC::GenerateMegamorphic(masm(), argc);
+  Object* result = GetCodeWithFlags(flags, "CompileCallMegamorphic");
+  if (!result->IsFailure()) {
+    Counters::call_megamorphic_stubs.Increment();
+    Code* code = Code::cast(result);
+    USE(code);
+    LOG(CodeCreateEvent("CallMegamorphic", code, code->arguments_count()));
+  }
+  return result;
+}
+
+
+Object* StubCompiler::CompileCallMiss(Code::Flags flags) {
+  HandleScope scope;
+  int argc = Code::ExtractArgumentsCountFromFlags(flags);
+  CallIC::GenerateMiss(masm(), argc);
+  Object* result = GetCodeWithFlags(flags, "CompileCallMiss");
+  if (!result->IsFailure()) {
+    Counters::call_megamorphic_stubs.Increment();
+    Code* code = Code::cast(result);
+    USE(code);
+    LOG(CodeCreateEvent("CallMiss", code, code->arguments_count()));
+  }
+  return result;
+}
+
+
+Object* StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
+  HandleScope scope;
+  Debug::GenerateCallICDebugBreak(masm());
+  Object* result = GetCodeWithFlags(flags, "CompileCallDebugBreak");
+  if (!result->IsFailure()) {
+    Code* code = Code::cast(result);
+    USE(code);
+    LOG(CodeCreateEvent("CallDebugBreak", code, code->arguments_count()));
+  }
+  return result;
+}
+
+
+Object* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
+  HandleScope scope;
+  // Use the same code for the the step in preparations as we do for
+  // the miss case.
+  int argc = Code::ExtractArgumentsCountFromFlags(flags);
+  CallIC::GenerateMiss(masm(), argc);
+  Object* result = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
+  if (!result->IsFailure()) {
+    Code* code = Code::cast(result);
+    USE(code);
+    LOG(CodeCreateEvent("CallDebugPrepareStepIn", code,
+                        code->arguments_count()));
+  }
+  return result;
+}
+
+
+Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, const char* name) {
+  CodeDesc desc;
+  masm_.GetCode(&desc);
+  Object* result = Heap::CreateCode(desc, NULL, flags, masm_.CodeObject());
+#ifdef ENABLE_DISASSEMBLER
+  if (FLAG_print_code_stubs && !result->IsFailure()) {
+    Code::cast(result)->Disassemble(name);
+  }
+#endif
+  return result;
+}
+
+
+Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, String* name) {
+  if (FLAG_print_code_stubs && (name != NULL)) {
+    return GetCodeWithFlags(flags, *name->ToCString());
+  }
+  return GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
+}
+
+
+Object* LoadStubCompiler::GetCode(PropertyType type, String* name) {
+  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type);
+  return GetCodeWithFlags(flags, name);
+}
+
+
+Object* KeyedLoadStubCompiler::GetCode(PropertyType type, String* name) {
+  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, type);
+  return GetCodeWithFlags(flags, name);
+}
+
+
+Object* StoreStubCompiler::GetCode(PropertyType type, String* name) {
+  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, type);
+  return GetCodeWithFlags(flags, name);
+}
+
+
+Object* KeyedStoreStubCompiler::GetCode(PropertyType type, String* name) {
+  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, type);
+  return GetCodeWithFlags(flags, name);
+}
+
+
+Object* CallStubCompiler::GetCode(PropertyType type, String* name) {
+  int argc = arguments_.immediate();
+  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, type, argc);
+  return GetCodeWithFlags(flags, name);
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/stub-cache.h b/deps/v8/src/stub-cache.h
new file mode 100644
index 0000000..05845e5
--- /dev/null
+++ b/deps/v8/src/stub-cache.h
@@ -0,0 +1,480 @@
+// 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_STUB_CACHE_H_
+#define V8_STUB_CACHE_H_
+
+#include "macro-assembler.h"
+
+namespace v8 { namespace internal {
+
+
+// The stub cache is used for megamorphic calls and property accesses.
+// It maps (map, name, type)->Code*
+
+// The design of the table uses the inline cache stubs used for
+// mono-morphic calls. The beauty of this, we do not have to
+// invalidate the cache whenever a prototype map is changed.  The stub
+// validates the map chain as in the mono-morphic case.
+
+class SCTableReference;
+
+class StubCache : public AllStatic {
+ public:
+  struct Entry {
+    String* key;
+    Code* value;
+  };
+
+
+  static void Initialize(bool create_heap_objects);
+
+  // Computes the right stub matching. Inserts the result in the
+  // cache before returning.  This might compile a stub if needed.
+  static Object* ComputeLoadField(String* name,
+                                  JSObject* receiver,
+                                  JSObject* holder,
+                                  int field_index);
+
+  static Object* ComputeLoadCallback(String* name,
+                                     JSObject* receiver,
+                                     JSObject* holder,
+                                     AccessorInfo* callback);
+
+  static Object* ComputeLoadConstant(String* name,
+                                     JSObject* receiver,
+                                     JSObject* holder,
+                                     Object* value);
+
+  static Object* ComputeLoadInterceptor(String* name,
+                                        JSObject* receiver,
+                                        JSObject* holder);
+
+  static Object* ComputeLoadNormal(String* name, JSObject* receiver);
+
+
+  // ---
+
+  static Object* ComputeKeyedLoadField(String* name,
+                                       JSObject* receiver,
+                                       JSObject* holder,
+                                       int field_index);
+
+  static Object* ComputeKeyedLoadCallback(String* name,
+                                          JSObject* receiver,
+                                          JSObject* holder,
+                                          AccessorInfo* callback);
+
+  static Object* ComputeKeyedLoadConstant(String* name, JSObject* receiver,
+                                          JSObject* holder, Object* value);
+
+  static Object* ComputeKeyedLoadInterceptor(String* name,
+                                             JSObject* receiver,
+                                             JSObject* holder);
+
+  static Object* ComputeKeyedLoadArrayLength(String* name, JSArray* receiver);
+
+  static Object* ComputeKeyedLoadStringLength(String* name,
+                                              String* receiver);
+
+  static Object* ComputeKeyedLoadFunctionPrototype(String* name,
+                                                   JSFunction* receiver);
+
+  // ---
+
+  static Object* ComputeStoreField(String* name,
+                                   JSObject* receiver,
+                                   int field_index,
+                                   Map* transition = NULL);
+
+  static Object* ComputeStoreCallback(String* name,
+                                      JSObject* receiver,
+                                      AccessorInfo* callback);
+
+  static Object* ComputeStoreInterceptor(String* name, JSObject* receiver);
+
+  // ---
+
+  static Object* ComputeKeyedStoreField(String* name,
+                                        JSObject* receiver,
+                                        int field_index,
+                                        Map* transition = NULL);
+
+  // ---
+
+  static Object* ComputeCallField(int argc,
+                                  String* name,
+                                  Object* object,
+                                  JSObject* holder,
+                                  int index);
+
+  static Object* ComputeCallConstant(int argc,
+                                     String* name,
+                                     Object* object,
+                                     JSObject* holder,
+                                     JSFunction* function);
+
+  static Object* ComputeCallNormal(int argc, String* name, JSObject* receiver);
+
+  static Object* ComputeCallInterceptor(int argc,
+                                        String* name,
+                                        Object* object,
+                                        JSObject* holder);
+
+  // ---
+
+  static Object* ComputeCallInitialize(int argc);
+  static Object* ComputeCallInitializeInLoop(int argc);
+  static Object* ComputeCallPreMonomorphic(int argc);
+  static Object* ComputeCallNormal(int argc);
+  static Object* ComputeCallMegamorphic(int argc);
+  static Object* ComputeCallMiss(int argc);
+
+  // Finds the Code object stored in the Heap::non_monomorphic_cache().
+  static Code* FindCallInitialize(int argc);
+
+  static Object* ComputeCallDebugBreak(int argc);
+  static Object* ComputeCallDebugPrepareStepIn(int argc);
+
+  static Object* ComputeLazyCompile(int argc);
+
+
+  // Update cache for entry hash(name, map).
+  static Code* Set(String* name, Map* map, Code* code);
+
+  // Clear the lookup table (@ mark compact collection).
+  static void Clear();
+
+  // Functions for generating stubs at startup.
+  static void GenerateMiss(MacroAssembler* masm);
+
+  // Generate code for probing the stub cache table.
+  static void GenerateProbe(MacroAssembler* masm,
+                            Code::Flags flags,
+                            Register receiver,
+                            Register name,
+                            Register scratch);
+
+  enum Table {
+    kPrimary,
+    kSecondary
+  };
+
+ private:
+  friend class SCTableReference;
+  static const int kPrimaryTableSize = 2048;
+  static const int kSecondaryTableSize = 512;
+  static Entry primary_[];
+  static Entry secondary_[];
+
+  // Computes the hashed offsets for primary and secondary caches.
+  static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
+    // This works well because the heap object tag size and the hash
+    // shift are equal.  Shifting down the length field to get the
+    // hash code would effectively throw away two bits of the hash
+    // code.
+    ASSERT(kHeapObjectTagSize == String::kHashShift);
+    // Compute the hash of the name (use entire length field).
+    ASSERT(name->HasHashCode());
+    uint32_t field = name->length_field();
+    // Base the offset on a simple combination of name, flags, and map.
+    uint32_t key = (reinterpret_cast<uint32_t>(map) + field) ^ flags;
+    return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
+  }
+
+  static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
+    // Use the seed from the primary cache in the secondary cache.
+    uint32_t key = seed - reinterpret_cast<uint32_t>(name) + flags;
+    return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
+  }
+
+  // Compute the entry for a given offset in exactly the same way as
+  // we done in generated code. This makes it a lot easier to avoid
+  // making mistakes in the hashed offset computations.
+  static Entry* entry(Entry* table, int offset) {
+    return reinterpret_cast<Entry*>(
+        reinterpret_cast<Address>(table) + (offset << 1));
+  }
+};
+
+
+class SCTableReference {
+ public:
+  static SCTableReference keyReference(StubCache::Table table) {
+    return SCTableReference(
+        reinterpret_cast<Address>(&first_entry(table)->key));
+  }
+
+
+  static SCTableReference valueReference(StubCache::Table table) {
+    return SCTableReference(
+        reinterpret_cast<Address>(&first_entry(table)->value));
+  }
+
+  Address address() const { return address_; }
+
+ private:
+  explicit SCTableReference(Address address) : address_(address) {}
+
+  static StubCache::Entry* first_entry(StubCache::Table table) {
+    switch (table) {
+      case StubCache::kPrimary: return StubCache::primary_;
+      case StubCache::kSecondary: return StubCache::secondary_;
+    }
+    UNREACHABLE();
+    return NULL;
+  }
+
+  Address address_;
+};
+
+// ------------------------------------------------------------------------
+
+
+// Support functions for IC stubs for callbacks.
+Object* LoadCallbackProperty(Arguments args);
+Object* StoreCallbackProperty(Arguments args);
+
+
+// Support functions for IC stubs for interceptors.
+Object* LoadInterceptorProperty(Arguments args);
+Object* StoreInterceptorProperty(Arguments args);
+Object* CallInterceptorProperty(Arguments args);
+
+
+// Support function for computing call IC miss stubs.
+Handle<Code> ComputeCallMiss(int argc);
+
+
+// The stub compiler compiles stubs for the stub cache.
+class StubCompiler BASE_EMBEDDED {
+ public:
+  enum CheckType {
+    RECEIVER_MAP_CHECK,
+    STRING_CHECK,
+    NUMBER_CHECK,
+    BOOLEAN_CHECK,
+    JSARRAY_HAS_FAST_ELEMENTS_CHECK
+  };
+
+  StubCompiler() : scope_(), masm_(NULL, 256) { }
+
+  Object* CompileCallInitialize(Code::Flags flags);
+  Object* CompileCallPreMonomorphic(Code::Flags flags);
+  Object* CompileCallNormal(Code::Flags flags);
+  Object* CompileCallMegamorphic(Code::Flags flags);
+  Object* CompileCallMiss(Code::Flags flags);
+  Object* CompileCallDebugBreak(Code::Flags flags);
+  Object* CompileCallDebugPrepareStepIn(Code::Flags flags);
+  Object* CompileLazyCompile(Code::Flags flags);
+
+  // Static functions for generating parts of stubs.
+  static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
+                                                  int index,
+                                                  Register prototype);
+  static void GenerateFastPropertyLoad(MacroAssembler* masm,
+                                       Register dst, Register src,
+                                       JSObject* holder, int index);
+  static void GenerateLoadField(MacroAssembler* masm,
+                                JSObject* object,
+                                JSObject* holder,
+                                Register receiver,
+                                Register scratch1,
+                                Register scratch2,
+                                int index,
+                                Label* miss_label);
+  static void GenerateLoadCallback(MacroAssembler* masm,
+                                   JSObject* object,
+                                   JSObject* holder,
+                                   Register receiver,
+                                   Register name,
+                                   Register scratch1,
+                                   Register scratch2,
+                                   AccessorInfo* callback,
+                                   Label* miss_label);
+  static void GenerateLoadConstant(MacroAssembler* masm,
+                                   JSObject* object,
+                                   JSObject* holder,
+                                   Register receiver,
+                                   Register scratch1,
+                                   Register scratch2,
+                                   Object* value,
+                                   Label* miss_label);
+  static void GenerateLoadInterceptor(MacroAssembler* masm,
+                                      JSObject* object,
+                                      JSObject* holder,
+                                      Register receiver,
+                                      Register name,
+                                      Register scratch1,
+                                      Register scratch2,
+                                      Label* miss_label);
+  static void GenerateLoadArrayLength(MacroAssembler* masm,
+                                      Register receiver,
+                                      Register scratch,
+                                      Label* miss_label);
+  static void GenerateLoadStringLength(MacroAssembler* masm,
+                                       Register receiver,
+                                       Register scratch,
+                                       Label* miss_label);
+  static void GenerateLoadStringLength2(MacroAssembler* masm,
+                                        Register receiver,
+                                        Register scratch1,
+                                        Register scratch2,
+                                        Label* miss_label);
+  static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
+                                            Register receiver,
+                                            Register scratch1,
+                                            Register scratch2,
+                                            Label* miss_label);
+  static void GenerateStoreField(MacroAssembler* masm,
+                                 Builtins::Name storage_extend,
+                                 JSObject* object,
+                                 int index,
+                                 Map* transition,
+                                 Register receiver_reg,
+                                 Register name_reg,
+                                 Register scratch,
+                                 Label* miss_label);
+  static void GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind);
+
+ protected:
+  Object* GetCodeWithFlags(Code::Flags flags, const char* name);
+  Object* GetCodeWithFlags(Code::Flags flags, String* name);
+
+  MacroAssembler* masm() { return &masm_; }
+
+ private:
+  HandleScope scope_;
+  MacroAssembler masm_;
+};
+
+
+class LoadStubCompiler: public StubCompiler {
+ public:
+  Object* CompileLoadField(JSObject* object,
+                           JSObject* holder,
+                           int index,
+                           String* name);
+  Object* CompileLoadCallback(JSObject* object,
+                              JSObject* holder,
+                              AccessorInfo* callback,
+                              String* name);
+  Object* CompileLoadConstant(JSObject* object,
+                              JSObject* holder,
+                              Object* value,
+                              String* name);
+  Object* CompileLoadInterceptor(JSObject* object,
+                                 JSObject* holder,
+                                 String* name);
+
+ private:
+  Object* GetCode(PropertyType type, String* name);
+};
+
+
+class KeyedLoadStubCompiler: public StubCompiler {
+ public:
+  Object* CompileLoadField(String* name,
+                           JSObject* object,
+                           JSObject* holder,
+                           int index);
+  Object* CompileLoadCallback(String* name,
+                              JSObject* object,
+                              JSObject* holder,
+                              AccessorInfo* callback);
+  Object* CompileLoadConstant(String* name,
+                              JSObject* object,
+                              JSObject* holder,
+                              Object* value);
+  Object* CompileLoadInterceptor(JSObject* object,
+                                 JSObject* holder,
+                                 String* name);
+  Object* CompileLoadArrayLength(String* name);
+  Object* CompileLoadStringLength(String* name);
+  Object* CompileLoadFunctionPrototype(String* name);
+
+ private:
+  Object* GetCode(PropertyType type, String* name);
+};
+
+
+class StoreStubCompiler: public StubCompiler {
+ public:
+  Object* CompileStoreField(JSObject* object,
+                            int index,
+                            Map* transition,
+                            String* name);
+  Object* CompileStoreCallback(JSObject* object,
+                               AccessorInfo* callbacks,
+                               String* name);
+  Object* CompileStoreInterceptor(JSObject* object, String* name);
+
+ private:
+  Object* GetCode(PropertyType type, String* name);
+};
+
+
+class KeyedStoreStubCompiler: public StubCompiler {
+ public:
+  Object* CompileStoreField(JSObject* object,
+                            int index,
+                            Map* transition,
+                            String* name);
+
+ private:
+  Object* GetCode(PropertyType type, String* name);
+};
+
+
+class CallStubCompiler: public StubCompiler {
+ public:
+  explicit CallStubCompiler(int argc) : arguments_(argc) { }
+
+  Object* CompileCallField(Object* object,
+                           JSObject* holder,
+                           int index,
+                           String* name);
+  Object* CompileCallConstant(Object* object,
+                              JSObject* holder,
+                              JSFunction* function,
+                              CheckType check);
+  Object* CompileCallInterceptor(Object* object,
+                                 JSObject* holder,
+                                 String* name);
+
+ private:
+  const ParameterCount arguments_;
+
+  const ParameterCount& arguments() { return arguments_; }
+
+  Object* GetCode(PropertyType type, String* name);
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_STUB_CACHE_H_
diff --git a/deps/v8/src/third_party/dtoa/COPYING b/deps/v8/src/third_party/dtoa/COPYING
new file mode 100644
index 0000000..c991754
--- /dev/null
+++ b/deps/v8/src/third_party/dtoa/COPYING
@@ -0,0 +1,15 @@
+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/deps/v8/src/third_party/dtoa/dtoa.c b/deps/v8/src/third_party/dtoa/dtoa.c
new file mode 100644
index 0000000..5caa96d
--- /dev/null
+++ b/deps/v8/src/third_party/dtoa/dtoa.c
@@ -0,0 +1,3324 @@
+/****************************************************************
+ *
+ * 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
+#define Long long
+#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 YES_ALIAS
+#define dval(x) x
+#ifdef IEEE_8087
+#define word0(x) ((ULong *)&x)[1]
+#define word1(x) ((ULong *)&x)[0]
+#else
+#define word0(x) ((ULong *)&x)[0]
+#define word1(x) ((ULong *)&x)[1]
+#endif
+#else
+#ifdef IEEE_8087
+#define word0(x) ((U*)&x)->L[1]
+#define word1(x) ((U*)&x)->L[0]
+#else
+#define word0(x) ((U*)&x)->L[0]
+#define word1(x) ((U*)&x)->L[1]
+#endif
+#define dval(x) ((U*)&x)->d
+#endif
+
+/* 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);
+	if ((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 (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) {
+		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
+	(x) double x;
+#else
+	(double x)
+#endif
+{
+	register Long L;
+	double a;
+
+	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;
+	double 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
+	(d, e, bits) double d; int *e, *bits;
+#else
+	(double d, 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
+#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
+{
+	double 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, aadj1, adj, rv, rv0;
+	Long L;
+	ULong y, z;
+	Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
+#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) {
+						adj = 1.;
+						goto apply_adj;
+						}
+					}
+				else if (!dsign) {
+					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)
+							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) += adj*ulp(dval(rv));
+						word0(rv) -= P*Exp_msk1;
+						}
+					else
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+					dval(rv) += adj*ulp(dval(rv));
+					}
+				break;
+				}
+			adj = ratio(delta, bs);
+			if (adj < 1.)
+				adj = 1.;
+			if (adj <= 0x7ffffffe) {
+				/* adj = rounding ? ceil(adj) : floor(adj); */
+				y = adj;
+				if (y != adj) {
+					if (!((rounding>>1) ^ dsign))
+						y++;
+					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;
+				adj *= ulp(dval(rv));
+				if (dsign)
+					dval(rv) += adj;
+				else
+					dval(rv) -= adj;
+				word0(rv) -= P*Exp_msk1;
+				goto cont;
+				}
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+			adj *= ulp(dval(rv));
+			if (dsign)
+				dval(rv) += adj;
+			else
+				dval(rv) -= 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 = aadj1 = 1.;
+			else if (word1(rv) || word0(rv) & Bndry_mask) {
+#ifndef Sudden_Underflow
+				if (word1(rv) == Tiny1 && !word0(rv))
+					goto undfl;
+#endif
+				aadj = 1.;
+				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;
+				aadj1 = -aadj;
+				}
+			}
+		else {
+			aadj *= 0.5;
+			aadj1 = dsign ? aadj : -aadj;
+#ifdef Check_FLT_ROUNDS
+			switch(Rounding) {
+				case 2: /* towards +infinity */
+					aadj1 -= 0.5;
+					break;
+				case 0: /* towards 0 */
+				case 3: /* towards -infinity */
+					aadj1 += 0.5;
+				}
+#else
+			if (Flt_Rounds == 0)
+				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;
+			adj = aadj1 * ulp(dval(rv));
+			dval(rv) += 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;
+					aadj1 = dsign ? aadj : -aadj;
+					}
+				word0(aadj1) += (2*P+1)*Exp_msk1 - y;
+				}
+			adj = aadj1 * ulp(dval(rv));
+			dval(rv) += adj;
+#else
+#ifdef Sudden_Underflow
+			if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
+				dval(rv0) = dval(rv);
+				word0(rv) += P*Exp_msk1;
+				adj = aadj1 * ulp(dval(rv));
+				dval(rv) += 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 {
+				adj = aadj1 * ulp(dval(rv));
+				dval(rv) += 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.) {
+				aadj1 = (double)(int)(aadj + 0.5);
+				if (!dsign)
+					aadj1 = -aadj1;
+				}
+			adj = aadj1 * ulp(dval(rv));
+			dval(rv) += 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
+	(d, mode, ndigits, decpt, sign, rve)
+	double d; int mode, ndigits, *decpt, *sign; char **rve;
+#else
+	(double d, 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 d2, ds, eps;
+	char *s, *s0;
+#ifdef Honor_FLT_ROUNDS
+	int rounding;
+#endif
+#ifdef SET_INEXACT
+	int inexact, oldinexact;
+#endif
+
+        /* 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/deps/v8/src/token.cc b/deps/v8/src/token.cc
new file mode 100644
index 0000000..3f92707
--- /dev/null
+++ b/deps/v8/src/token.cc
@@ -0,0 +1,162 @@
+// 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.
+
+#include "v8.h"
+
+#include "token.h"
+
+namespace v8 { namespace internal {
+
+#ifdef DEBUG
+#define T(name, string, precedence) #name,
+const char* Token::name_[NUM_TOKENS] = {
+  TOKEN_LIST(T, T, IGNORE_TOKEN)
+};
+#undef T
+#endif
+
+
+#define T(name, string, precedence) string,
+const char* Token::string_[NUM_TOKENS] = {
+  TOKEN_LIST(T, T, IGNORE_TOKEN)
+};
+#undef T
+
+
+#define T(name, string, precedence) precedence,
+int8_t Token::precedence_[NUM_TOKENS] = {
+  TOKEN_LIST(T, T, IGNORE_TOKEN)
+};
+#undef T
+
+
+// A perfect (0 collision) hash table of keyword token values.
+
+// larger N will reduce the number of collisions (power of 2 for fast %)
+const unsigned int N = 128;
+// make this small since we have <= 256 tokens
+static uint8_t Hashtable[N];
+static bool IsInitialized = false;
+
+
+static unsigned int Hash(const char* s) {
+  // The following constants have been found using trial-and-error. If the
+  // keyword set changes, they may have to be recomputed (make them flags
+  // and play with the flag values). Increasing N is the simplest way to
+  // reduce the number of collisions.
+
+  // we must use at least 4 or more chars ('const' and 'continue' share
+  // 'con')
+  const unsigned int L = 5;
+  // smaller S tend to reduce the number of collisions
+  const unsigned int S = 4;
+  // make this a prime, or at least an odd number
+  const unsigned int M = 3;
+
+  unsigned int h = 0;
+  for (unsigned int i = 0; s[i] != '\0' && i < L; i++) {
+    h += (h << S) + s[i];
+  }
+  // unsigned int % by a power of 2 (otherwise this will not be a bit mask)
+  return h * M % N;
+}
+
+
+Token::Value Token::Lookup(const char* str) {
+  ASSERT(IsInitialized);
+  Value k = static_cast<Value>(Hashtable[Hash(str)]);
+  const char* s = string_[k];
+  ASSERT(s != NULL || k == IDENTIFIER);
+  if (s == NULL || strcmp(s, str) == 0) {
+    return k;
+  }
+  return IDENTIFIER;
+}
+
+
+#ifdef DEBUG
+// We need this function because C++ doesn't allow the expression
+// NULL == NULL, which is a result of macro expansion below. What
+// the hell?
+static bool IsNull(const char* s) {
+  return s == NULL;
+}
+#endif
+
+
+void Token::Initialize() {
+  if (IsInitialized) return;
+
+  // A list of all keywords, terminated by ILLEGAL.
+#define T(name, string, precedence) name,
+  static Value keyword[] = {
+    TOKEN_LIST(IGNORE_TOKEN, T, IGNORE_TOKEN)
+    ILLEGAL
+  };
+#undef T
+
+  // Assert that the keyword array contains the 25 keywords, 3 future
+  // reserved words (const, debugger, and native), and the 3 named literals
+  // defined by ECMA-262 standard.
+  ASSERT(ARRAY_SIZE(keyword) == 25 + 3 + 3 + 1);  // +1 for ILLEGAL sentinel
+
+  // Initialize Hashtable.
+  ASSERT(NUM_TOKENS <= 256);  // Hashtable contains uint8_t elements
+  for (unsigned int i = 0; i < N; i++) {
+    Hashtable[i] = IDENTIFIER;
+  }
+
+  // Insert all keywords into Hashtable.
+  int collisions = 0;
+  for (int i = 0; keyword[i] != ILLEGAL; i++) {
+    Value k = keyword[i];
+    unsigned int h = Hash(string_[k]);
+    if (Hashtable[h] != IDENTIFIER) collisions++;
+    Hashtable[h] = k;
+  }
+
+  if (collisions > 0) {
+    PrintF("%d collisions in keyword hashtable\n", collisions);
+    FATAL("Fix keyword lookup!");
+  }
+
+  IsInitialized = true;
+
+  // Verify hash table.
+#define T(name, string, precedence) \
+  ASSERT(IsNull(string) || Lookup(string) == IDENTIFIER);
+
+#define K(name, string, precedence) \
+  ASSERT(Lookup(string) == name);
+
+  TOKEN_LIST(T, K, IGNORE_TOKEN)
+
+#undef K
+#undef T
+}
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/token.h b/deps/v8/src/token.h
new file mode 100644
index 0000000..0f194a3
--- /dev/null
+++ b/deps/v8/src/token.h
@@ -0,0 +1,281 @@
+// 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_TOKEN_H_
+#define V8_TOKEN_H_
+
+namespace v8 { namespace internal {
+
+// TOKEN_LIST takes a list of 3 macros M, all of which satisfy the
+// same signature M(name, string, precedence), where name is the
+// symbolic token name, string is the corresponding syntactic symbol
+// (or NULL, for literals), and precedence is the precedence (or 0).
+// The parameters are invoked for token categories as follows:
+//
+//   T: Non-keyword tokens
+//   K: Keyword tokens
+//   F: Future (reserved) keyword tokens
+
+// IGNORE_TOKEN is a convenience macro that can be supplied as
+// an argument (at any position) for a TOKEN_LIST call. It does
+// nothing with tokens belonging to the respective category.
+
+#define IGNORE_TOKEN(name, string, precedence)
+
+#define TOKEN_LIST(T, K, F)                                             \
+  /* End of source indicator. */                                        \
+  T(EOS, "EOS", 0)                                                      \
+                                                                        \
+  /* Punctuators (ECMA-262, section 7.7, page 15). */                   \
+  T(LPAREN, "(", 0)                                                     \
+  T(RPAREN, ")", 0)                                                     \
+  T(LBRACK, "[", 0)                                                     \
+  T(RBRACK, "]", 0)                                                     \
+  T(LBRACE, "{", 0)                                                     \
+  T(RBRACE, "}", 0)                                                     \
+  T(COLON, ":", 0)                                                      \
+  T(SEMICOLON, ";", 0)                                                  \
+  T(PERIOD, ".", 0)                                                     \
+  T(CONDITIONAL, "?", 3)                                                \
+  T(INC, "++", 0)                                                       \
+  T(DEC, "--", 0)                                                       \
+                                                                        \
+  /* Assignment operators. */                                           \
+  /* IsAssignmentOp() relies on this block of enum values */            \
+  /* being contiguous and sorted in the same order! */                  \
+  T(INIT_VAR, "=init_var", 2)  /* AST-use only. */                      \
+  T(INIT_CONST, "=init_const", 2)  /* AST-use only. */                  \
+  T(ASSIGN, "=", 2)                                                     \
+  T(ASSIGN_BIT_OR, "|=", 2)                                             \
+  T(ASSIGN_BIT_XOR, "^=", 2)                                            \
+  T(ASSIGN_BIT_AND, "&=", 2)                                            \
+  T(ASSIGN_SHL, "<<=", 2)                                               \
+  T(ASSIGN_SAR, ">>=", 2)                                               \
+  T(ASSIGN_SHR, ">>>=", 2)                                              \
+  T(ASSIGN_ADD, "+=", 2)                                                \
+  T(ASSIGN_SUB, "-=", 2)                                                \
+  T(ASSIGN_MUL, "*=", 2)                                                \
+  T(ASSIGN_DIV, "/=", 2)                                                \
+  T(ASSIGN_MOD, "%=", 2)                                                \
+                                                                        \
+  /* Binary operators sorted by precedence. */                          \
+  /* IsBinaryOp() relies on this block of enum values */                \
+  /* being contiguous and sorted in the same order! */                  \
+  T(COMMA, ",", 1)                                                      \
+  T(OR, "||", 4)                                                        \
+  T(AND, "&&", 5)                                                       \
+  T(BIT_OR, "|", 6)                                                     \
+  T(BIT_XOR, "^", 7)                                                    \
+  T(BIT_AND, "&", 8)                                                    \
+  T(SHL, "<<", 11)                                                      \
+  T(SAR, ">>", 11)                                                      \
+  T(SHR, ">>>", 11)                                                     \
+  T(ADD, "+", 12)                                                       \
+  T(SUB, "-", 12)                                                       \
+  T(MUL, "*", 13)                                                       \
+  T(DIV, "/", 13)                                                       \
+  T(MOD, "%", 13)                                                       \
+                                                                        \
+  /* Compare operators sorted by precedence. */                         \
+  /* IsCompareOp() relies on this block of enum values */               \
+  /* being contiguous and sorted in the same order! */                  \
+  T(EQ, "==", 9)                                                        \
+  T(NE, "!=", 9)                                                        \
+  T(EQ_STRICT, "===", 9)                                                \
+  T(NE_STRICT, "!==", 9)                                                \
+  T(LT, "<", 10)                                                        \
+  T(GT, ">", 10)                                                        \
+  T(LTE, "<=", 10)                                                      \
+  T(GTE, ">=", 10)                                                      \
+  K(INSTANCEOF, "instanceof", 10)                                       \
+  K(IN, "in", 10)                                                       \
+                                                                        \
+  /* Unary operators. */                                                \
+  /* IsUnaryOp() relies on this block of enum values */                 \
+  /* being contiguous and sorted in the same order! */                  \
+  T(NOT, "!", 0)                                                        \
+  T(BIT_NOT, "~", 0)                                                    \
+  K(DELETE, "delete", 0)                                                \
+  K(TYPEOF, "typeof", 0)                                                \
+  K(VOID, "void", 0)                                                    \
+                                                                        \
+  /* Keywords (ECMA-262, section 7.5.2, page 13). */                    \
+  K(BREAK, "break", 0)                                                  \
+  K(CASE, "case", 0)                                                    \
+  K(CATCH, "catch", 0)                                                  \
+  K(CONTINUE, "continue", 0)                                            \
+  K(DEBUGGER, "debugger", 0)                                            \
+  K(DEFAULT, "default", 0)                                              \
+  /* DELETE */                                                          \
+  K(DO, "do", 0)                                                        \
+  K(ELSE, "else", 0)                                                    \
+  K(FINALLY, "finally", 0)                                              \
+  K(FOR, "for", 0)                                                      \
+  K(FUNCTION, "function", 0)                                            \
+  K(IF, "if", 0)                                                        \
+  /* IN */                                                              \
+  /* INSTANCEOF */                                                      \
+  K(NEW, "new", 0)                                                      \
+  K(RETURN, "return", 0)                                                \
+  K(SWITCH, "switch", 0)                                                \
+  K(THIS, "this", 0)                                                    \
+  K(THROW, "throw", 0)                                                  \
+  K(TRY, "try", 0)                                                      \
+  /* TYPEOF */                                                          \
+  K(VAR, "var", 0)                                                      \
+  /* VOID */                                                            \
+  K(WHILE, "while", 0)                                                  \
+  K(WITH, "with", 0)                                                    \
+                                                                        \
+  /* Future reserved words (ECMA-262, section 7.5.3, page 14). */       \
+  F(ABSTRACT, "abstract", 0)                                            \
+  F(BOOLEAN, "boolean", 0)                                              \
+  F(BYTE, "byte", 0)                                                    \
+  F(CHAR, "char", 0)                                                    \
+  F(CLASS, "class", 0)                                                  \
+  K(CONST, "const", 0)                                                  \
+  F(DOUBLE, "double", 0)                                                \
+  F(ENUM, "enum", 0)                                                    \
+  F(EXPORT, "export", 0)                                                \
+  F(EXTENDS, "extends", 0)                                              \
+  F(FINAL, "final", 0)                                                  \
+  F(FLOAT, "float", 0)                                                  \
+  F(GOTO, "goto", 0)                                                    \
+  F(IMPLEMENTS, "implements", 0)                                        \
+  F(IMPORT, "import", 0)                                                \
+  F(INT, "int", 0)                                                      \
+  F(INTERFACE, "interface", 0)                                          \
+  F(LONG, "long", 0)                                                    \
+  K(NATIVE, "native", 0)                                                \
+  F(PACKAGE, "package", 0)                                              \
+  F(PRIVATE, "private", 0)                                              \
+  F(PROTECTED, "protected", 0)                                          \
+  F(PUBLIC, "public", 0)                                                \
+  F(SHORT, "short", 0)                                                  \
+  F(STATIC, "static", 0)                                                \
+  F(SUPER, "super", 0)                                                  \
+  F(SYNCHRONIZED, "synchronized", 0)                                    \
+  F(THROWS, "throws", 0)                                                \
+  F(TRANSIENT, "transient", 0)                                          \
+  F(VOLATILE, "volatile", 0)                                            \
+                                                                        \
+  /* Literals (ECMA-262, section 7.8, page 16). */                      \
+  K(NULL_LITERAL, "null", 0)                                            \
+  K(TRUE_LITERAL, "true", 0)                                            \
+  K(FALSE_LITERAL, "false", 0)                                          \
+  T(NUMBER, NULL, 0)                                                    \
+  T(STRING, NULL, 0)                                                    \
+                                                                        \
+  /* Identifiers (not keywords or future reserved words). */            \
+  T(IDENTIFIER, NULL, 0)                                                \
+                                                                        \
+  /* Illegal token - not able to scan. */                               \
+  T(ILLEGAL, "ILLEGAL", 0)                                              \
+                                                                        \
+  /* Scanner-internal use only. */                                      \
+  T(COMMENT, NULL, 0)
+
+
+class Token {
+ public:
+  // All token values.
+#define T(name, string, precedence) name,
+  enum Value {
+    TOKEN_LIST(T, T, IGNORE_TOKEN)
+    NUM_TOKENS
+  };
+#undef T
+
+#ifdef DEBUG
+  // Returns a string corresponding to the C++ token name
+  // (e.g. "LT" for the token LT).
+  static const char* Name(Value tok) {
+    ASSERT(0 <= tok && tok < NUM_TOKENS);
+    return name_[tok];
+  }
+#endif
+
+  // Predicates
+  static bool IsAssignmentOp(Value tok) {
+    return INIT_VAR <= tok && tok <= ASSIGN_MOD;
+  }
+
+  static bool IsBinaryOp(Value op) {
+    return COMMA <= op && op <= MOD;
+  }
+
+  static bool IsCompareOp(Value op) {
+    return EQ <= op && op <= IN;
+  }
+
+  static bool IsBitOp(Value op) {
+    return (BIT_OR <= op && op <= SHR) || op == BIT_NOT;
+  }
+
+  static bool IsUnaryOp(Value op) {
+    return (NOT <= op && op <= VOID) || op == ADD || op == SUB;
+  }
+
+  static bool IsCountOp(Value op) {
+    return op == INC || op == DEC;
+  }
+
+  // Returns a string corresponding to the JS token string
+  // (.e., "<" for the token LT) or NULL if the token doesn't
+  // have a (unique) string (e.g. an IDENTIFIER).
+  static const char* String(Value tok) {
+    ASSERT(0 <= tok && tok < NUM_TOKENS);
+    return string_[tok];
+  }
+
+  // Returns the precedence > 0 for binary and compare
+  // operators; returns 0 otherwise.
+  static int Precedence(Value tok) {
+    ASSERT(0 <= tok && tok < NUM_TOKENS);
+    return precedence_[tok];
+  }
+
+  // Returns the keyword value if str is a keyword;
+  // returns IDENTIFIER otherwise. The class must
+  // have been initialized.
+  static Value Lookup(const char* str);
+
+  // Must be called once to initialize the class.
+  // Multiple calls are ignored.
+  static void Initialize();
+
+ private:
+#ifdef DEBUG
+  static const char* name_[NUM_TOKENS];
+#endif
+  static const char* string_[NUM_TOKENS];
+  static int8_t precedence_[NUM_TOKENS];
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_TOKEN_H_
diff --git a/deps/v8/src/top.cc b/deps/v8/src/top.cc
new file mode 100644
index 0000000..a99e9ff
--- /dev/null
+++ b/deps/v8/src/top.cc
@@ -0,0 +1,921 @@
+// 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.
+
+#include "v8.h"
+
+#include "api.h"
+#include "bootstrapper.h"
+#include "debug.h"
+#include "execution.h"
+#include "string-stream.h"
+#include "platform.h"
+
+namespace v8 { namespace internal {
+
+ThreadLocalTop Top::thread_local_;
+Mutex* Top::break_access_ = OS::CreateMutex();
+
+NoAllocationStringAllocator* preallocated_message_space = NULL;
+
+Address top_addresses[] = {
+#define C(name) reinterpret_cast<Address>(Top::name()),
+    TOP_ADDRESS_LIST(C)
+#undef C
+    NULL
+};
+
+Address Top::get_address_from_id(Top::AddressId id) {
+  return top_addresses[id];
+}
+
+char* Top::Iterate(ObjectVisitor* v, char* thread_storage) {
+  ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage);
+  Iterate(v, thread);
+  return thread_storage + sizeof(ThreadLocalTop);
+}
+
+
+void Top::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
+  v->VisitPointer(&(thread->pending_exception_));
+  v->VisitPointer(&(thread->pending_message_obj_));
+  v->VisitPointer(
+      bit_cast<Object**, Script**>(&(thread->pending_message_script_)));
+  v->VisitPointer(bit_cast<Object**, Context**>(&(thread->context_)));
+  v->VisitPointer(&(thread->scheduled_exception_));
+
+  for (v8::TryCatch* block = thread->try_catch_handler_;
+       block != NULL;
+       block = block->next_) {
+    v->VisitPointer(bit_cast<Object**, void**>(&(block->exception_)));
+    v->VisitPointer(bit_cast<Object**, void**>(&(block->message_)));
+  }
+
+  // Iterate over pointers on native execution stack.
+  for (StackFrameIterator it(thread); !it.done(); it.Advance()) {
+    it.frame()->Iterate(v);
+  }
+}
+
+
+void Top::Iterate(ObjectVisitor* v) {
+  ThreadLocalTop* current_t = &thread_local_;
+  Iterate(v, current_t);
+}
+
+
+void Top::InitializeThreadLocal() {
+  thread_local_.c_entry_fp_ = 0;
+  thread_local_.handler_ = 0;
+  thread_local_.stack_is_cooked_ = false;
+  thread_local_.try_catch_handler_ = NULL;
+  thread_local_.context_ = NULL;
+  thread_local_.external_caught_exception_ = false;
+  thread_local_.failed_access_check_callback_ = NULL;
+  clear_pending_exception();
+  clear_pending_message();
+  clear_scheduled_exception();
+  thread_local_.save_context_ = NULL;
+  thread_local_.catcher_ = NULL;
+}
+
+
+// Create a dummy thread that will wait forever on a semaphore. The only
+// purpose for this thread is to have some stack area to save essential data
+// into for use by a stacks only core dump (aka minidump).
+class PreallocatedMemoryThread: public Thread {
+ public:
+  PreallocatedMemoryThread() : keep_running_(true) {
+    wait_for_ever_semaphore_ = OS::CreateSemaphore(0);
+    data_ready_semaphore_ = OS::CreateSemaphore(0);
+  }
+
+  // When the thread starts running it will allocate a fixed number of bytes
+  // on the stack and publish the location of this memory for others to use.
+  void Run() {
+    EmbeddedVector<char, 32 * 1024> local_buffer;
+
+    // Initialize the buffer with a known good value.
+    OS::StrNCpy(local_buffer, "Trace data was not generated.\n",
+                local_buffer.length());
+
+    // Publish the local buffer and signal its availability.
+    data_ = &local_buffer[0];
+    length_ = sizeof(local_buffer);
+    data_ready_semaphore_->Signal();
+
+    while (keep_running_) {
+      // This thread will wait here until the end of time.
+      wait_for_ever_semaphore_->Wait();
+    }
+
+    // Make sure we access the buffer after the wait to remove all possibility
+    // of it being optimized away.
+    OS::StrNCpy(local_buffer, "PreallocatedMemoryThread shutting down.\n",
+                local_buffer.length());
+  }
+
+  static char* data() {
+    if (data_ready_semaphore_ != NULL) {
+      // Initial access is guarded until the data has been published.
+      data_ready_semaphore_->Wait();
+      delete data_ready_semaphore_;
+      data_ready_semaphore_ = NULL;
+    }
+    return data_;
+  }
+
+  static unsigned length() {
+    if (data_ready_semaphore_ != NULL) {
+      // Initial access is guarded until the data has been published.
+      data_ready_semaphore_->Wait();
+      delete data_ready_semaphore_;
+      data_ready_semaphore_ = NULL;
+    }
+    return length_;
+  }
+
+  static void StartThread() {
+    if (the_thread_ != NULL) return;
+
+    the_thread_ = new PreallocatedMemoryThread();
+    the_thread_->Start();
+  }
+
+  // Stop the PreallocatedMemoryThread and release its resources.
+  static void StopThread() {
+    if (the_thread_ == NULL) return;
+
+    the_thread_->keep_running_ = false;
+    wait_for_ever_semaphore_->Signal();
+
+    // Wait for the thread to terminate.
+    the_thread_->Join();
+
+    if (data_ready_semaphore_ != NULL) {
+      delete data_ready_semaphore_;
+      data_ready_semaphore_ = NULL;
+    }
+
+    delete wait_for_ever_semaphore_;
+    wait_for_ever_semaphore_ = NULL;
+
+    // Done with the thread entirely.
+    delete the_thread_;
+    the_thread_ = NULL;
+  }
+
+ private:
+  // Used to make sure that the thread keeps looping even for spurious wakeups.
+  bool keep_running_;
+
+  // The preallocated memory thread singleton.
+  static PreallocatedMemoryThread* the_thread_;
+  // This semaphore is used by the PreallocatedMemoryThread to wait for ever.
+  static Semaphore* wait_for_ever_semaphore_;
+  // Semaphore to signal that the data has been initialized.
+  static Semaphore* data_ready_semaphore_;
+
+  // Location and size of the preallocated memory block.
+  static char* data_;
+  static unsigned length_;
+
+  DISALLOW_COPY_AND_ASSIGN(PreallocatedMemoryThread);
+};
+
+PreallocatedMemoryThread* PreallocatedMemoryThread::the_thread_ = NULL;
+Semaphore* PreallocatedMemoryThread::wait_for_ever_semaphore_ = NULL;
+Semaphore* PreallocatedMemoryThread::data_ready_semaphore_ = NULL;
+char* PreallocatedMemoryThread::data_ = NULL;
+unsigned PreallocatedMemoryThread::length_ = 0;
+
+static bool initialized = false;
+
+void Top::Initialize() {
+  CHECK(!initialized);
+
+  InitializeThreadLocal();
+
+  // Only preallocate on the first initialization.
+  if (FLAG_preallocate_message_memory && (preallocated_message_space == NULL)) {
+    // Start the thread which will set aside some memory.
+    PreallocatedMemoryThread::StartThread();
+    preallocated_message_space =
+        new NoAllocationStringAllocator(PreallocatedMemoryThread::data(),
+                                        PreallocatedMemoryThread::length());
+    PreallocatedStorage::Init(PreallocatedMemoryThread::length() / 4);
+  }
+  initialized = true;
+}
+
+
+void Top::TearDown() {
+  if (initialized) {
+    // Remove the external reference to the preallocated stack memory.
+    if (preallocated_message_space != NULL) {
+      delete preallocated_message_space;
+      preallocated_message_space = NULL;
+    }
+
+    PreallocatedMemoryThread::StopThread();
+    initialized = false;
+  }
+}
+
+
+// There are cases where the C stack is separated from JS stack (ARM simulator).
+// To figure out the order of top-most JS try-catch handler and the top-most C
+// try-catch handler, the C try-catch handler keeps a reference to the top-most
+// JS try_catch handler when it was created.
+//
+// Here is a picture to explain the idea:
+//   Top::thread_local_.handler_       Top::thread_local_.try_catch_handler_
+//
+//             |                                         |
+//             v                                         v
+//
+//      | JS handler  |                        | C try_catch handler |
+//      |    next     |--+           +-------- |    js_handler_      |
+//                       |           |         |      next_          |--+
+//                       |           |                                  |
+//      | JS handler  |--+ <---------+                                  |
+//      |    next     |
+//
+// If the top-most JS try-catch handler is not equal to
+// Top::thread_local_.try_catch_handler_.js_handler_, it means the JS handler
+// is on the top. Otherwise, it means the C try-catch handler is on the top.
+//
+void Top::RegisterTryCatchHandler(v8::TryCatch* that) {
+  StackHandler* handler =
+    reinterpret_cast<StackHandler*>(thread_local_.handler_);
+
+  // Find the top-most try-catch handler.
+  while (handler != NULL && !handler->is_try_catch()) {
+    handler = handler->next();
+  }
+
+  that->js_handler_ = handler;  // casted to void*
+  thread_local_.try_catch_handler_ = that;
+}
+
+
+void Top::UnregisterTryCatchHandler(v8::TryCatch* that) {
+  ASSERT(thread_local_.try_catch_handler_ == that);
+  thread_local_.try_catch_handler_ = that->next_;
+  thread_local_.catcher_ = NULL;
+}
+
+
+void Top::MarkCompactPrologue(bool is_compacting) {
+  MarkCompactPrologue(is_compacting, &thread_local_);
+}
+
+
+void Top::MarkCompactPrologue(bool is_compacting, char* data) {
+  MarkCompactPrologue(is_compacting, reinterpret_cast<ThreadLocalTop*>(data));
+}
+
+
+void Top::MarkCompactPrologue(bool is_compacting, ThreadLocalTop* thread) {
+  if (is_compacting) {
+    StackFrame::CookFramesForThread(thread);
+  }
+}
+
+
+void Top::MarkCompactEpilogue(bool is_compacting, char* data) {
+  MarkCompactEpilogue(is_compacting, reinterpret_cast<ThreadLocalTop*>(data));
+}
+
+
+void Top::MarkCompactEpilogue(bool is_compacting) {
+  MarkCompactEpilogue(is_compacting, &thread_local_);
+}
+
+
+void Top::MarkCompactEpilogue(bool is_compacting, ThreadLocalTop* thread) {
+  if (is_compacting) {
+    StackFrame::UncookFramesForThread(thread);
+  }
+}
+
+
+static int stack_trace_nesting_level = 0;
+static StringStream* incomplete_message = NULL;
+
+
+Handle<String> Top::StackTrace() {
+  if (stack_trace_nesting_level == 0) {
+    stack_trace_nesting_level++;
+    HeapStringAllocator allocator;
+    StringStream::ClearMentionedObjectCache();
+    StringStream accumulator(&allocator);
+    incomplete_message = &accumulator;
+    PrintStack(&accumulator);
+    Handle<String> stack_trace = accumulator.ToString();
+    incomplete_message = NULL;
+    stack_trace_nesting_level = 0;
+    return stack_trace;
+  } else if (stack_trace_nesting_level == 1) {
+    stack_trace_nesting_level++;
+    OS::PrintError(
+      "\n\nAttempt to print stack while printing stack (double fault)\n");
+    OS::PrintError(
+      "If you are lucky you may find a partial stack dump on stdout.\n\n");
+    incomplete_message->OutputToStdOut();
+    return Factory::empty_symbol();
+  } else {
+    OS::Abort();
+    // Unreachable
+    return Factory::empty_symbol();
+  }
+}
+
+
+void Top::PrintStack() {
+  if (stack_trace_nesting_level == 0) {
+    stack_trace_nesting_level++;
+
+    StringAllocator* allocator;
+    if (preallocated_message_space == NULL) {
+      allocator = new HeapStringAllocator();
+    } else {
+      allocator = preallocated_message_space;
+    }
+
+    NativeAllocationChecker allocation_checker(
+      !FLAG_preallocate_message_memory ?
+      NativeAllocationChecker::ALLOW :
+      NativeAllocationChecker::DISALLOW);
+
+    StringStream::ClearMentionedObjectCache();
+    StringStream accumulator(allocator);
+    incomplete_message = &accumulator;
+    PrintStack(&accumulator);
+    accumulator.OutputToStdOut();
+    accumulator.Log();
+    incomplete_message = NULL;
+    stack_trace_nesting_level = 0;
+    if (preallocated_message_space == NULL) {
+      // Remove the HeapStringAllocator created above.
+      delete allocator;
+    }
+  } else if (stack_trace_nesting_level == 1) {
+    stack_trace_nesting_level++;
+    OS::PrintError(
+      "\n\nAttempt to print stack while printing stack (double fault)\n");
+    OS::PrintError(
+      "If you are lucky you may find a partial stack dump on stdout.\n\n");
+    incomplete_message->OutputToStdOut();
+  }
+}
+
+
+static void PrintFrames(StringStream* accumulator,
+                        StackFrame::PrintMode mode) {
+  StackFrameIterator it;
+  for (int i = 0; !it.done(); it.Advance()) {
+    it.frame()->Print(accumulator, mode, i++);
+  }
+}
+
+
+void Top::PrintStack(StringStream* accumulator) {
+  // The MentionedObjectCache is not GC-proof at the moment.
+  AssertNoAllocation nogc;
+  ASSERT(StringStream::IsMentionedObjectCacheClear());
+
+  // Avoid printing anything if there are no frames.
+  if (c_entry_fp(GetCurrentThread()) == 0) return;
+
+  accumulator->Add(
+      "\n==== Stack trace ============================================\n\n");
+  PrintFrames(accumulator, StackFrame::OVERVIEW);
+
+  accumulator->Add(
+      "\n==== Details ================================================\n\n");
+  PrintFrames(accumulator, StackFrame::DETAILS);
+
+  accumulator->PrintMentionedObjectCache();
+  accumulator->Add("=====================\n\n");
+}
+
+
+void Top::SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback) {
+  ASSERT(thread_local_.failed_access_check_callback_ == NULL);
+  thread_local_.failed_access_check_callback_ = callback;
+}
+
+
+void Top::ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type) {
+  if (!thread_local_.failed_access_check_callback_) return;
+
+  ASSERT(receiver->IsAccessCheckNeeded());
+  ASSERT(Top::context());
+  // The callers of this method are not expecting a GC.
+  AssertNoAllocation no_gc;
+
+  // Get the data object from access check info.
+  JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
+  Object* info = constructor->shared()->function_data();
+  if (info == Heap::undefined_value()) return;
+
+  Object* data_obj = FunctionTemplateInfo::cast(info)->access_check_info();
+  if (data_obj == Heap::undefined_value()) return;
+
+  HandleScope scope;
+  Handle<JSObject> receiver_handle(receiver);
+  Handle<Object> data(AccessCheckInfo::cast(data_obj)->data());
+  thread_local_.failed_access_check_callback_(
+    v8::Utils::ToLocal(receiver_handle),
+    type,
+    v8::Utils::ToLocal(data));
+}
+
+
+enum MayAccessDecision {
+  YES, NO, UNKNOWN
+};
+
+
+static MayAccessDecision MayAccessPreCheck(JSObject* receiver,
+                                           v8::AccessType type) {
+  // During bootstrapping, callback functions are not enabled yet.
+  if (Bootstrapper::IsActive()) return YES;
+
+  if (receiver->IsJSGlobalProxy()) {
+    Object* receiver_context = JSGlobalProxy::cast(receiver)->context();
+    if (!receiver_context->IsContext()) return NO;
+
+    // Get the global context of current top context.
+    // avoid using Top::global_context() because it uses Handle.
+    Context* global_context = Top::context()->global()->global_context();
+    if (receiver_context == global_context) return YES;
+
+    if (Context::cast(receiver_context)->security_token() ==
+        global_context->security_token())
+      return YES;
+  }
+
+  return UNKNOWN;
+}
+
+
+bool Top::MayNamedAccess(JSObject* receiver, Object* key, v8::AccessType type) {
+  ASSERT(receiver->IsAccessCheckNeeded());
+  // Check for compatibility between the security tokens in the
+  // current lexical context and the accessed object.
+  ASSERT(Top::context());
+  // The callers of this method are not expecting a GC.
+  AssertNoAllocation no_gc;
+
+  MayAccessDecision decision = MayAccessPreCheck(receiver, type);
+  if (decision != UNKNOWN) return decision == YES;
+
+  // Get named access check callback
+  JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
+  Object* info = constructor->shared()->function_data();
+  if (info == Heap::undefined_value()) return false;
+
+  Object* data_obj = FunctionTemplateInfo::cast(info)->access_check_info();
+  if (data_obj == Heap::undefined_value()) return false;
+
+  Object* fun_obj = AccessCheckInfo::cast(data_obj)->named_callback();
+  v8::NamedSecurityCallback callback =
+      v8::ToCData<v8::NamedSecurityCallback>(fun_obj);
+
+  if (!callback) return false;
+
+  HandleScope scope;
+  Handle<JSObject> receiver_handle(receiver);
+  Handle<Object> key_handle(key);
+  Handle<Object> data(AccessCheckInfo::cast(data_obj)->data());
+  LOG(ApiNamedSecurityCheck(key));
+  bool result = false;
+  {
+    // Leaving JavaScript.
+    VMState state(EXTERNAL);
+    result = callback(v8::Utils::ToLocal(receiver_handle),
+                      v8::Utils::ToLocal(key_handle),
+                      type,
+                      v8::Utils::ToLocal(data));
+  }
+  return result;
+}
+
+
+bool Top::MayIndexedAccess(JSObject* receiver,
+                           uint32_t index,
+                           v8::AccessType type) {
+  ASSERT(receiver->IsAccessCheckNeeded());
+  // Check for compatibility between the security tokens in the
+  // current lexical context and the accessed object.
+  ASSERT(Top::context());
+  // The callers of this method are not expecting a GC.
+  AssertNoAllocation no_gc;
+
+  MayAccessDecision decision = MayAccessPreCheck(receiver, type);
+  if (decision != UNKNOWN) return decision == YES;
+
+  // Get indexed access check callback
+  JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
+  Object* info = constructor->shared()->function_data();
+  if (info == Heap::undefined_value()) return false;
+
+  Object* data_obj = FunctionTemplateInfo::cast(info)->access_check_info();
+  if (data_obj == Heap::undefined_value()) return false;
+
+  Object* fun_obj = AccessCheckInfo::cast(data_obj)->indexed_callback();
+  v8::IndexedSecurityCallback callback =
+      v8::ToCData<v8::IndexedSecurityCallback>(fun_obj);
+
+  if (!callback) return false;
+
+  HandleScope scope;
+  Handle<JSObject> receiver_handle(receiver);
+  Handle<Object> data(AccessCheckInfo::cast(data_obj)->data());
+  LOG(ApiIndexedSecurityCheck(index));
+  bool result = false;
+  {
+    // Leaving JavaScript.
+    VMState state(EXTERNAL);
+    result = callback(v8::Utils::ToLocal(receiver_handle),
+                      index,
+                      type,
+                      v8::Utils::ToLocal(data));
+  }
+  return result;
+}
+
+
+const char* Top::kStackOverflowMessage =
+  "Uncaught RangeError: Maximum call stack size exceeded";
+
+
+Failure* Top::StackOverflow() {
+  HandleScope scope;
+  Handle<String> key = Factory::stack_overflow_symbol();
+  Handle<JSObject> boilerplate =
+      Handle<JSObject>::cast(GetProperty(Top::builtins(), key));
+  Handle<Object> exception = Copy(boilerplate);
+  // TODO(1240995): To avoid having to call JavaScript code to compute
+  // the message for stack overflow exceptions which is very likely to
+  // double fault with another stack overflow exception, we use a
+  // precomputed message. This is somewhat problematic in that it
+  // doesn't use ReportUncaughtException to determine the location
+  // from where the exception occurred. It should probably be
+  // reworked.
+  DoThrow(*exception, NULL, kStackOverflowMessage);
+  return Failure::Exception();
+}
+
+
+Failure* Top::Throw(Object* exception, MessageLocation* location) {
+  DoThrow(exception, location, NULL);
+  return Failure::Exception();
+}
+
+
+Failure* Top::ReThrow(Object* exception, MessageLocation* location) {
+  // Set the exception being re-thrown.
+  set_pending_exception(exception);
+  return Failure::Exception();
+}
+
+
+void Top::ScheduleThrow(Object* exception) {
+  // When scheduling a throw we first throw the exception to get the
+  // error reporting if it is uncaught before rescheduling it.
+  Throw(exception);
+  thread_local_.scheduled_exception_ = pending_exception();
+  thread_local_.external_caught_exception_ = false;
+  clear_pending_exception();
+}
+
+
+Object* Top::PromoteScheduledException() {
+  Object* thrown = scheduled_exception();
+  clear_scheduled_exception();
+  // Re-throw the exception to avoid getting repeated error reporting.
+  return ReThrow(thrown);
+}
+
+
+void Top::PrintCurrentStackTrace(FILE* out) {
+  StackTraceFrameIterator it;
+  while (!it.done()) {
+    HandleScope scope;
+    // Find code position if recorded in relocation info.
+    JavaScriptFrame* frame = it.frame();
+    int pos = frame->code()->SourcePosition(frame->pc());
+    Handle<Object> pos_obj(Smi::FromInt(pos));
+    // Fetch function and receiver.
+    Handle<JSFunction> fun(JSFunction::cast(frame->function()));
+    Handle<Object> recv(frame->receiver());
+    // Advance to the next JavaScript frame and determine if the
+    // current frame is the top-level frame.
+    it.Advance();
+    Handle<Object> is_top_level = it.done()
+        ? Factory::true_value()
+        : Factory::false_value();
+    // Generate and print stack trace line.
+    Handle<String> line =
+        Execution::GetStackTraceLine(recv, fun, pos_obj, is_top_level);
+    if (line->length() > 0) {
+      line->PrintOn(out);
+      fprintf(out, "\n");
+    }
+  }
+}
+
+
+void Top::ComputeLocation(MessageLocation* target) {
+  *target = MessageLocation(empty_script(), -1, -1);
+  StackTraceFrameIterator it;
+  if (!it.done()) {
+    JavaScriptFrame* frame = it.frame();
+    JSFunction* fun = JSFunction::cast(frame->function());
+    Object* script = fun->shared()->script();
+    if (script->IsScript() &&
+        !(Script::cast(script)->source()->IsUndefined())) {
+      int pos = frame->code()->SourcePosition(frame->pc());
+      // Compute the location from the function and the reloc info.
+      Handle<Script> casted_script(Script::cast(script));
+      *target = MessageLocation(casted_script, pos, pos + 1);
+    }
+  }
+}
+
+
+void Top::ReportUncaughtException(Handle<Object> exception,
+                                  MessageLocation* location,
+                                  Handle<String> stack_trace) {
+  Handle<Object> message =
+    MessageHandler::MakeMessageObject("uncaught_exception",
+                                      location,
+                                      HandleVector<Object>(&exception, 1),
+                                      stack_trace);
+
+  // Report the uncaught exception.
+  MessageHandler::ReportMessage(location, message);
+}
+
+
+bool Top::ShouldReportException(bool* is_caught_externally) {
+  // Find the top-most try-catch handler.
+  StackHandler* handler =
+      StackHandler::FromAddress(Top::handler(Top::GetCurrentThread()));
+  while (handler != NULL && !handler->is_try_catch()) {
+    handler = handler->next();
+  }
+
+  // Get the address of the external handler so we can compare the address to
+  // determine which one is closer to the top of the stack.
+  v8::TryCatch* try_catch = thread_local_.try_catch_handler_;
+
+  // The exception has been externally caught if and only if there is
+  // an external handler which is on top of the top-most try-catch
+  // handler.
+  //
+  // See comments in RegisterTryCatchHandler for details.
+  *is_caught_externally = try_catch != NULL &&
+      (handler == NULL || handler == try_catch->js_handler_);
+
+  if (*is_caught_externally) {
+    // Only report the exception if the external handler is verbose.
+    return thread_local_.try_catch_handler_->is_verbose_;
+  } else {
+    // Report the exception if it isn't caught by JavaScript code.
+    return handler == NULL;
+  }
+}
+
+
+void Top::DoThrow(Object* exception,
+                  MessageLocation* location,
+                  const char* message) {
+  ASSERT(!has_pending_exception());
+
+  HandleScope scope;
+  Handle<Object> exception_handle(exception);
+
+  // Determine reporting and whether the exception is caught externally.
+  bool is_caught_externally = false;
+  bool is_out_of_memory = exception == Failure::OutOfMemoryException();
+  bool should_return_exception = ShouldReportException(&is_caught_externally);
+  bool report_exception = !is_out_of_memory && should_return_exception;
+
+  // Notify debugger of exception.
+  Debugger::OnException(exception_handle, report_exception);
+
+  // Generate the message.
+  Handle<Object> message_obj;
+  MessageLocation potential_computed_location;
+  bool try_catch_needs_message =
+      is_caught_externally &&
+      thread_local_.try_catch_handler_->capture_message_;
+  if (report_exception || try_catch_needs_message) {
+    if (location == NULL) {
+      // If no location was specified we use a computed one instead
+      ComputeLocation(&potential_computed_location);
+      location = &potential_computed_location;
+    }
+    Handle<String> stack_trace;
+    if (FLAG_trace_exception) stack_trace = StackTrace();
+    message_obj = MessageHandler::MakeMessageObject("uncaught_exception",
+        location, HandleVector<Object>(&exception_handle, 1), stack_trace);
+  }
+
+  // Save the message for reporting if the the exception remains uncaught.
+  thread_local_.has_pending_message_ = report_exception;
+  thread_local_.pending_message_ = message;
+  if (!message_obj.is_null()) {
+    thread_local_.pending_message_obj_ = *message_obj;
+    if (location != NULL) {
+      thread_local_.pending_message_script_ = *location->script();
+      thread_local_.pending_message_start_pos_ = location->start_pos();
+      thread_local_.pending_message_end_pos_ = location->end_pos();
+    }
+  }
+
+  if (is_caught_externally) {
+    thread_local_.catcher_ = thread_local_.try_catch_handler_;
+  }
+
+  // NOTE: Notifying the debugger or generating the message
+  // may have caused new exceptions. For now, we just ignore
+  // that and set the pending exception to the original one.
+  set_pending_exception(*exception_handle);
+}
+
+
+void Top::ReportPendingMessages() {
+  ASSERT(has_pending_exception());
+  setup_external_caught();
+  // If the pending exception is OutOfMemoryException set out_of_memory in
+  // the global context.  Note: We have to mark the global context here
+  // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to
+  // set it.
+  HandleScope scope;
+  if (thread_local_.pending_exception_ == Failure::OutOfMemoryException()) {
+    context()->mark_out_of_memory();
+  } else {
+    Handle<Object> exception(pending_exception());
+    bool external_caught = thread_local_.external_caught_exception_;
+    thread_local_.external_caught_exception_ = false;
+    if (external_caught) {
+      thread_local_.try_catch_handler_->exception_ =
+        thread_local_.pending_exception_;
+      if (!thread_local_.pending_message_obj_->IsTheHole()) {
+        try_catch_handler()->message_ = thread_local_.pending_message_obj_;
+      }
+    }
+    if (thread_local_.has_pending_message_) {
+      thread_local_.has_pending_message_ = false;
+      if (thread_local_.pending_message_ != NULL) {
+        MessageHandler::ReportMessage(thread_local_.pending_message_);
+      } else if (!thread_local_.pending_message_obj_->IsTheHole()) {
+        Handle<Object> message_obj(thread_local_.pending_message_obj_);
+        if (thread_local_.pending_message_script_ != NULL) {
+          Handle<Script> script(thread_local_.pending_message_script_);
+          int start_pos = thread_local_.pending_message_start_pos_;
+          int end_pos = thread_local_.pending_message_end_pos_;
+          MessageLocation location(script, start_pos, end_pos);
+          MessageHandler::ReportMessage(&location, message_obj);
+        } else {
+          MessageHandler::ReportMessage(NULL, message_obj);
+        }
+      }
+    }
+    thread_local_.external_caught_exception_ = external_caught;
+    set_pending_exception(*exception);
+  }
+  clear_pending_message();
+}
+
+
+void Top::TraceException(bool flag) {
+  FLAG_trace_exception = flag;
+}
+
+
+bool Top::optional_reschedule_exception(bool is_bottom_call) {
+  // Allways reschedule out of memory exceptions.
+  if (!is_out_of_memory()) {
+    // Never reschedule the exception if this is the bottom call.
+    bool clear_exception = is_bottom_call;
+
+    // If the exception is externally caught, clear it if there are no
+    // JavaScript frames on the way to the C++ frame that has the
+    // external handler.
+    if (thread_local_.external_caught_exception_) {
+      ASSERT(thread_local_.try_catch_handler_ != NULL);
+      Address external_handler_address =
+          reinterpret_cast<Address>(thread_local_.try_catch_handler_);
+      JavaScriptFrameIterator it;
+      if (it.done() || (it.frame()->sp() > external_handler_address)) {
+        clear_exception = true;
+      }
+    }
+
+    // Clear the exception if needed.
+    if (clear_exception) {
+      thread_local_.external_caught_exception_ = false;
+      clear_pending_exception();
+      return false;
+    }
+  }
+
+  // Reschedule the exception.
+  thread_local_.scheduled_exception_ = pending_exception();
+  clear_pending_exception();
+  return true;
+}
+
+
+bool Top::is_out_of_memory() {
+  if (has_pending_exception()) {
+    Object* e = pending_exception();
+    if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) {
+      return true;
+    }
+  }
+  if (has_scheduled_exception()) {
+    Object* e = scheduled_exception();
+    if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) {
+      return true;
+    }
+  }
+  return false;
+}
+
+
+Handle<Context> Top::global_context() {
+  GlobalObject* global = thread_local_.context_->global();
+  return Handle<Context>(global->global_context());
+}
+
+
+Object* Top::LookupSpecialFunction(JSObject* receiver,
+                                   JSObject* prototype,
+                                   JSFunction* function) {
+  if (receiver->IsJSArray()) {
+    FixedArray* table = context()->global_context()->special_function_table();
+    for (int index = 0; index < table->length(); index +=3) {
+      if ((prototype == table->get(index)) &&
+          (function == table->get(index+1))) {
+        return table->get(index+2);
+      }
+    }
+  }
+  return Heap::undefined_value();
+}
+
+
+char* Top::ArchiveThread(char* to) {
+  memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(thread_local_));
+  InitializeThreadLocal();
+  return to + sizeof(thread_local_);
+}
+
+
+char* Top::RestoreThread(char* from) {
+  memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(thread_local_));
+  return from + sizeof(thread_local_);
+}
+
+
+ExecutionAccess::ExecutionAccess() {
+  Top::break_access_->Lock();
+}
+
+
+ExecutionAccess::~ExecutionAccess() {
+  Top::break_access_->Unlock();
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/top.h b/deps/v8/src/top.h
new file mode 100644
index 0000000..1e5ec5a
--- /dev/null
+++ b/deps/v8/src/top.h
@@ -0,0 +1,377 @@
+// 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_TOP_H_
+#define V8_TOP_H_
+
+#include "frames-inl.h"
+
+namespace v8 { namespace internal {
+
+
+#define RETURN_IF_SCHEDULED_EXCEPTION() \
+  if (Top::has_scheduled_exception()) return Top::PromoteScheduledException()
+
+// Top has static variables used for JavaScript execution.
+
+class SaveContext;  // Forward declaration.
+
+class ThreadLocalTop BASE_EMBEDDED {
+ public:
+  // The context where the current execution method is created and for variable
+  // lookups.
+  Context* context_;
+  Object* pending_exception_;
+  bool has_pending_message_;
+  const char* pending_message_;
+  Object* pending_message_obj_;
+  Script* pending_message_script_;
+  int pending_message_start_pos_;
+  int pending_message_end_pos_;
+  // Use a separate value for scheduled exceptions to preserve the
+  // invariants that hold about pending_exception.  We may want to
+  // unify them later.
+  Object* scheduled_exception_;
+  bool external_caught_exception_;
+  v8::TryCatch* try_catch_handler_;
+  SaveContext* save_context_;
+  v8::TryCatch* catcher_;
+
+  // Stack.
+  Address c_entry_fp_;  // the frame pointer of the top c entry frame
+  Address handler_;   // try-blocks are chained through the stack
+  bool stack_is_cooked_;
+  inline bool stack_is_cooked() { return stack_is_cooked_; }
+  inline void set_stack_is_cooked(bool value) { stack_is_cooked_ = value; }
+
+  // Generated code scratch locations.
+  int32_t formal_count_;
+
+  // Call back function to report unsafe JS accesses.
+  v8::FailedAccessCheckCallback failed_access_check_callback_;
+};
+
+#define TOP_ADDRESS_LIST(C) \
+  C(handler_address)                   \
+  C(c_entry_fp_address)                \
+  C(context_address)                   \
+  C(pending_exception_address)         \
+  C(external_caught_exception_address)
+
+class Top {
+ public:
+  enum AddressId {
+#define C(name) k_##name,
+    TOP_ADDRESS_LIST(C)
+#undef C
+    k_top_address_count
+  };
+
+  static Address get_address_from_id(AddressId id);
+
+  // Access to top context (where the current function object was created).
+  static Context* context() { return thread_local_.context_; }
+  static void set_context(Context* context) {
+    thread_local_.context_ = context;
+  }
+  static Context** context_address() { return &thread_local_.context_; }
+
+  static SaveContext* save_context() {return thread_local_.save_context_; }
+  static void set_save_context(SaveContext* save) {
+    thread_local_.save_context_ = save;
+  }
+
+  // Interface to pending exception.
+  static Object* pending_exception() {
+    ASSERT(has_pending_exception());
+    return thread_local_.pending_exception_;
+  }
+  static bool external_caught_exception() {
+    return thread_local_.external_caught_exception_;
+  }
+  static void set_pending_exception(Object* exception) {
+    thread_local_.pending_exception_ = exception;
+  }
+  static void clear_pending_exception() {
+    thread_local_.pending_exception_ = Heap::the_hole_value();
+  }
+
+  static Object** pending_exception_address() {
+    return &thread_local_.pending_exception_;
+  }
+  static bool has_pending_exception() {
+    return !thread_local_.pending_exception_->IsTheHole();
+  }
+  static void clear_pending_message() {
+    thread_local_.has_pending_message_ = false;
+    thread_local_.pending_message_ = NULL;
+    thread_local_.pending_message_obj_ = Heap::the_hole_value();
+    thread_local_.pending_message_script_ = NULL;
+  }
+  static v8::TryCatch* try_catch_handler() {
+    return thread_local_.try_catch_handler_;
+  }
+  // This method is called by the api after operations that may throw
+  // exceptions.  If an exception was thrown and not handled by an external
+  // handler the exception is scheduled to be rethrown when we return to running
+  // JavaScript code.  If an exception is scheduled true is returned.
+  static bool optional_reschedule_exception(bool is_bottom_call);
+
+  static bool* external_caught_exception_address() {
+    return &thread_local_.external_caught_exception_;
+  }
+
+  static Object* scheduled_exception() {
+    ASSERT(has_scheduled_exception());
+    return thread_local_.scheduled_exception_;
+  }
+  static bool has_scheduled_exception() {
+    return !thread_local_.scheduled_exception_->IsTheHole();
+  }
+  static void clear_scheduled_exception() {
+    thread_local_.scheduled_exception_ = Heap::the_hole_value();
+  }
+
+  static void setup_external_caught() {
+    thread_local_.external_caught_exception_ =
+        has_pending_exception() &&
+        (thread_local_.catcher_ != NULL) &&
+        (thread_local_.try_catch_handler_ == thread_local_.catcher_);
+  }
+
+  // Tells whether the current context has experienced an out of memory
+  // exception.
+  static bool is_out_of_memory();
+
+  // JS execution stack (see frames.h).
+  static Address c_entry_fp(ThreadLocalTop* thread) {
+    return thread->c_entry_fp_;
+  }
+  static Address handler(ThreadLocalTop* thread) { return thread->handler_; }
+
+  static inline Address* c_entry_fp_address() {
+    return &thread_local_.c_entry_fp_;
+  }
+  static inline Address* handler_address() { return &thread_local_.handler_; }
+
+  // Generated code scratch locations.
+  static void* formal_count_address() { return &thread_local_.formal_count_; }
+
+  static void MarkCompactPrologue(bool is_compacting);
+  static void MarkCompactEpilogue(bool is_compacting);
+  static void MarkCompactPrologue(bool is_compacting,
+                                  char* archived_thread_data);
+  static void MarkCompactEpilogue(bool is_compacting,
+                                  char* archived_thread_data);
+  static void PrintCurrentStackTrace(FILE* out);
+  static void PrintStackTrace(FILE* out, char* thread_data);
+  static void PrintStack(StringStream* accumulator);
+  static void PrintStack();
+  static Handle<String> StackTrace();
+
+  // Returns if the top context may access the given global object. If
+  // the result is false, the pending exception is guaranteed to be
+  // set.
+  static bool MayNamedAccess(JSObject* receiver,
+                             Object* key,
+                             v8::AccessType type);
+  static bool MayIndexedAccess(JSObject* receiver,
+                               uint32_t index,
+                               v8::AccessType type);
+
+  static void SetFailedAccessCheckCallback(
+      v8::FailedAccessCheckCallback callback);
+  static void ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type);
+
+  // Exception throwing support. The caller should use the result
+  // of Throw() as its return value.
+  static Failure* Throw(Object* exception, MessageLocation* location = NULL);
+  // Re-throw an exception.  This involves no error reporting since
+  // error reporting was handled when the exception was thrown
+  // originally.
+  static Failure* ReThrow(Object* exception, MessageLocation* location = NULL);
+  static void ScheduleThrow(Object* exception);
+  static void ReportPendingMessages();
+
+  // Promote a scheduled exception to pending. Asserts has_scheduled_exception.
+  static Object* PromoteScheduledException();
+  static void DoThrow(Object* exception,
+                      MessageLocation* location,
+                      const char* message);
+  static bool ShouldReportException(bool* is_caught_externally);
+  static void ReportUncaughtException(Handle<Object> exception,
+                                      MessageLocation* location,
+                                      Handle<String> stack_trace);
+
+  // Attempts to compute the current source location, storing the
+  // result in the target out parameter.
+  static void ComputeLocation(MessageLocation* target);
+
+  // Override command line flag.
+  static void TraceException(bool flag);
+
+  // Out of resource exception helpers.
+  static Failure* StackOverflow();
+
+  // Administration
+  static void Initialize();
+  static void TearDown();
+  static void Iterate(ObjectVisitor* v);
+  static void Iterate(ObjectVisitor* v, ThreadLocalTop* t);
+  static char* Iterate(ObjectVisitor* v, char* t);
+
+  // Returns the global object of the current context. It could be
+  // a builtin object, or a js global object.
+  static Handle<GlobalObject> global() {
+    return Handle<GlobalObject>(context()->global());
+  }
+
+  // Returns the global proxy object of the current context.
+  static Object* global_proxy() {
+    return context()->global_proxy();
+  }
+
+  static Handle<Context> global_context();
+
+  static Handle<JSBuiltinsObject> builtins() {
+    return Handle<JSBuiltinsObject>(thread_local_.context_->builtins());
+  }
+
+  static Object* LookupSpecialFunction(JSObject* receiver,
+                                       JSObject* prototype,
+                                       JSFunction* value);
+
+  static void RegisterTryCatchHandler(v8::TryCatch* that);
+  static void UnregisterTryCatchHandler(v8::TryCatch* that);
+
+#define TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR(index, type, name)  \
+  static Handle<type> name() {                                \
+    return Handle<type>(context()->global_context()->name()); \
+  }
+  GLOBAL_CONTEXT_FIELDS(TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR)
+#undef TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR
+
+  static inline ThreadLocalTop* GetCurrentThread() { return &thread_local_; }
+  static int ArchiveSpacePerThread() { return sizeof(ThreadLocalTop); }
+  static char* ArchiveThread(char* to);
+  static char* RestoreThread(char* from);
+
+  static const char* kStackOverflowMessage;
+
+ private:
+  // The context that initiated this JS execution.
+  static ThreadLocalTop thread_local_;
+  static void InitializeThreadLocal();
+  static void PrintStackTrace(FILE* out, ThreadLocalTop* thread);
+  static void MarkCompactPrologue(bool is_compacting,
+                                  ThreadLocalTop* archived_thread_data);
+  static void MarkCompactEpilogue(bool is_compacting,
+                                  ThreadLocalTop* archived_thread_data);
+
+  // Debug.
+  // Mutex for serializing access to break control structures.
+  static Mutex* break_access_;
+
+  friend class SaveContext;
+  friend class AssertNoContextChange;
+  friend class ExecutionAccess;
+
+  static void FillCache();
+};
+
+
+// If the GCC version is 4.1.x or 4.2.x an additional field is added to the
+// class as a work around for a bug in the generated code found with these
+// versions of GCC. See V8 issue 122 for details.
+class SaveContext BASE_EMBEDDED {
+ public:
+  SaveContext()
+      : context_(Top::context()),
+#if __GNUC_VERSION__ >= 40100 && __GNUC_VERSION__ < 40300
+        dummy_(Top::context()),
+#endif
+        prev_(Top::save_context()) {
+    Top::set_save_context(this);
+
+    // If there is no JS frame under the current C frame, use the value 0.
+    JavaScriptFrameIterator it;
+    js_sp_ = it.done() ? 0 : it.frame()->sp();
+  }
+
+  ~SaveContext() {
+    Top::set_context(*context_);
+    Top::set_save_context(prev_);
+  }
+
+  Handle<Context> context() { return context_; }
+  SaveContext* prev() { return prev_; }
+
+  // Returns true if this save context is below a given JavaScript frame.
+  bool below(JavaScriptFrame* frame) {
+    return (js_sp_ == 0) || (frame->sp() < js_sp_);
+  }
+
+ private:
+  Handle<Context> context_;
+#if __GNUC_VERSION__ >= 40100 && __GNUC_VERSION__ < 40300
+  Handle<Context> dummy_;
+#endif
+  SaveContext* prev_;
+  Address js_sp_;  // The top JS frame's sp when saving context.
+};
+
+
+class AssertNoContextChange BASE_EMBEDDED {
+#ifdef DEBUG
+ public:
+  AssertNoContextChange() :
+      context_(Top::context()) {
+  }
+
+  ~AssertNoContextChange() {
+    ASSERT(Top::context() == *context_);
+  }
+
+ private:
+  HandleScope scope_;
+  Handle<Context> context_;
+#else
+ public:
+  AssertNoContextChange() { }
+#endif
+};
+
+
+class ExecutionAccess BASE_EMBEDDED {
+ public:
+  ExecutionAccess();
+  ~ExecutionAccess();
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_TOP_H_
diff --git a/deps/v8/src/unicode-inl.h b/deps/v8/src/unicode-inl.h
new file mode 100644
index 0000000..9737c27
--- /dev/null
+++ b/deps/v8/src/unicode-inl.h
@@ -0,0 +1,238 @@
+// 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.
+
+#ifndef __UNIBROW_INL_H__
+#define __UNIBROW_INL_H__
+
+#include "unicode.h"
+
+namespace unibrow {
+
+template <class T, int s> bool Predicate<T, s>::get(uchar code_point) {
+  CacheEntry entry = entries_[code_point & kMask];
+  if (entry.code_point_ == code_point) return entry.value_;
+  return CalculateValue(code_point);
+}
+
+template <class T, int s> bool Predicate<T, s>::CalculateValue(
+    uchar code_point) {
+  bool result = T::Is(code_point);
+  entries_[code_point & kMask] = CacheEntry(code_point, result);
+  return result;
+}
+
+template <class T, int s> int Mapping<T, s>::get(uchar c, uchar n,
+    uchar* result) {
+  CacheEntry entry = entries_[c & kMask];
+  if (entry.code_point_ == c) {
+    if (entry.offset_ == 0) {
+      return 0;
+    } else {
+      result[0] = c + entry.offset_;
+      return 1;
+    }
+  } else {
+    return CalculateValue(c, n, result);
+  }
+}
+
+template <class T, int s> int Mapping<T, s>::CalculateValue(uchar c, uchar n,
+    uchar* result) {
+  bool allow_caching = true;
+  int length = T::Convert(c, n, result, &allow_caching);
+  if (allow_caching) {
+    if (length == 1) {
+      entries_[c & kMask] = CacheEntry(c, result[0] - c);
+      return 1;
+    } else {
+      entries_[c & kMask] = CacheEntry(c, 0);
+      return 0;
+    }
+  } else {
+    return length;
+  }
+}
+
+
+unsigned Utf8::Encode(char* str, uchar c) {
+  static const int kMask = ~(1 << 6);
+  if (c <= kMaxOneByteChar) {
+    str[0] = c;
+    return 1;
+  } else if (c <= kMaxTwoByteChar) {
+    str[0] = 0xC0 | (c >> 6);
+    str[1] = 0x80 | (c & kMask);
+    return 2;
+  } else if (c <= kMaxThreeByteChar) {
+    str[0] = 0xE0 | (c >> 12);
+    str[1] = 0x80 | ((c >> 6) & kMask);
+    str[2] = 0x80 | (c & kMask);
+    return 3;
+  } else {
+    str[0] = 0xF0 | (c >> 18);
+    str[1] = 0x80 | ((c >> 12) & kMask);
+    str[2] = 0x80 | ((c >> 6) & kMask);
+    str[3] = 0x80 | (c & kMask);
+    return 4;
+  }
+}
+
+
+uchar Utf8::ValueOf(const byte* bytes, unsigned length, unsigned* cursor) {
+  if (length <= 0) return kBadChar;
+  byte first = bytes[0];
+  // Characters between 0000 and 0007F are encoded as a single character
+  if (first <= kMaxOneByteChar) {
+    *cursor += 1;
+    return first;
+  }
+  return CalculateValue(bytes, length, cursor);
+}
+
+unsigned Utf8::Length(uchar c) {
+  if (c <= kMaxOneByteChar) {
+    return 1;
+  } else if (c <= kMaxTwoByteChar) {
+    return 2;
+  } else if (c <= kMaxThreeByteChar) {
+    return 3;
+  } else {
+    return 4;
+  }
+}
+
+uchar CharacterStream::GetNext() {
+  uchar result = DecodeCharacter(buffer_, &cursor_);
+  if (remaining_ == 1) {
+    cursor_ = 0;
+    FillBuffer();
+  } else {
+    remaining_--;
+  }
+  return result;
+}
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define IF_LITTLE(expr) expr
+#define IF_BIG(expr)    ((void) 0)
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define IF_LITTLE(expr) ((void) 0)
+#define IF_BIG(expr)    expr
+#else
+#warning Unknown byte ordering
+#endif
+
+bool CharacterStream::EncodeAsciiCharacter(uchar c, byte* buffer,
+    unsigned capacity, unsigned& offset) {
+  if (offset >= capacity) return false;
+  buffer[offset] = c;
+  offset += 1;
+  return true;
+}
+
+bool CharacterStream::EncodeNonAsciiCharacter(uchar c, byte* buffer,
+    unsigned capacity, unsigned& offset) {
+  unsigned aligned = (offset + 0x3) & ~0x3;
+  if ((aligned + sizeof(uchar)) > capacity)
+    return false;
+  if (offset == aligned) {
+    IF_LITTLE(*reinterpret_cast<uchar*>(buffer + aligned) = (c << 8) | 0x80);
+    IF_BIG(*reinterpret_cast<uchar*>(buffer + aligned) = c | (1 << 31));
+  } else {
+    buffer[offset] = 0x80;
+    IF_LITTLE(*reinterpret_cast<uchar*>(buffer + aligned) = c << 8);
+    IF_BIG(*reinterpret_cast<uchar*>(buffer + aligned) = c);
+  }
+  offset = aligned + sizeof(uchar);
+  return true;
+}
+
+bool CharacterStream::EncodeCharacter(uchar c, byte* buffer, unsigned capacity,
+    unsigned& offset) {
+  if (c <= Utf8::kMaxOneByteChar) {
+    return EncodeAsciiCharacter(c, buffer, capacity, offset);
+  } else {
+    return EncodeNonAsciiCharacter(c, buffer, capacity, offset);
+  }
+}
+
+uchar CharacterStream::DecodeCharacter(const byte* buffer, unsigned* offset) {
+  byte b = buffer[*offset];
+  if (b <= Utf8::kMaxOneByteChar) {
+    (*offset)++;
+    return b;
+  } else {
+    unsigned aligned = (*offset + 0x3) & ~0x3;
+    *offset = aligned + sizeof(uchar);
+    IF_LITTLE(return *reinterpret_cast<const uchar*>(buffer + aligned) >> 8);
+    IF_BIG(return *reinterpret_cast<const uchar*>(buffer + aligned) &
+                    ~(1 << 31));
+  }
+}
+
+#undef IF_LITTLE
+#undef IF_BIG
+
+template <class R, class I, unsigned s>
+void InputBuffer<R, I, s>::FillBuffer() {
+  buffer_ = R::ReadBlock(input_, util_buffer_, s, &remaining_, &offset_);
+}
+
+template <class R, class I, unsigned s>
+void InputBuffer<R, I, s>::Rewind() {
+  Reset(input_);
+}
+
+template <class R, class I, unsigned s>
+void InputBuffer<R, I, s>::Reset(unsigned position, I input) {
+  input_ = input;
+  remaining_ = 0;
+  cursor_ = 0;
+  offset_ = position;
+  buffer_ = R::ReadBlock(input_, util_buffer_, s, &remaining_, &offset_);
+}
+
+template <class R, class I, unsigned s>
+void InputBuffer<R, I, s>::Reset(I input) {
+  Reset(0, input);
+}
+
+template <class R, class I, unsigned s>
+void InputBuffer<R, I, s>::Seek(unsigned position) {
+  offset_ = position;
+  buffer_ = R::ReadBlock(input_, util_buffer_, s, &remaining_, &offset_);
+}
+
+template <unsigned s>
+Utf8InputBuffer<s>::Utf8InputBuffer(const char* data, unsigned length)
+    : InputBuffer<Utf8, Buffer<const char*>, s>(Buffer<const char*>(data,
+                                                                    length)) {
+}
+
+}  // namespace unibrow
+
+#endif  // __UNIBROW_INL_H__
diff --git a/deps/v8/src/unicode.cc b/deps/v8/src/unicode.cc
new file mode 100644
index 0000000..4a9e070
--- /dev/null
+++ b/deps/v8/src/unicode.cc
@@ -0,0 +1,754 @@
+// 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.
+//
+// This file was generated at 2008-11-25 16:02:40.592795
+
+#include "unicode-inl.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+namespace unibrow {
+
+static const int kStartBit = (1 << 30);
+static const int kChunkBits = (1 << 15);
+
+/**
+ * \file
+ * Implementations of functions for working with unicode.
+ */
+
+typedef signed short int16_t;  // NOLINT
+typedef unsigned short uint16_t;  // NOLINT
+typedef int int32_t;  // NOLINT
+
+// All access to the character table should go through this function.
+template <int D>
+static inline uchar TableGet(const int32_t* table, int index) {
+  return table[D * index];
+}
+
+static inline uchar GetEntry(int32_t entry) {
+  return entry & (kStartBit - 1);
+}
+
+static inline bool IsStart(int32_t entry) {
+  return (entry & kStartBit) != 0;
+}
+
+/**
+ * Look up a character in the unicode table using a mix of binary and
+ * interpolation search.  For a uniformly distributed array
+ * interpolation search beats binary search by a wide margin.  However,
+ * in this case interpolation search degenerates because of some very
+ * high values in the lower end of the table so this function uses a
+ * combination.  The average number of steps to look up the information
+ * about a character is around 10, slightly higher if there is no
+ * information available about the character.
+ */
+static bool LookupPredicate(const int32_t* table, uint16_t size, uchar chr) {
+  static const int kEntryDist = 1;
+  uint16_t value = chr & (kChunkBits - 1);
+  unsigned int low = 0;
+  unsigned int high = size - 1;
+  while (high != low) {
+    unsigned int mid = low + ((high - low) >> 1);
+    uchar current_value = GetEntry(TableGet<kEntryDist>(table, mid));
+    // If we've found an entry less than or equal to this one, and the
+    // next one is not also less than this one, we've arrived.
+    if ((current_value <= value) &&
+        (mid + 1 == size ||
+         GetEntry(TableGet<kEntryDist>(table, mid + 1)) > value)) {
+      low = mid;
+      break;
+    } else if (current_value < value) {
+      low = mid + 1;
+    } else if (current_value > value) {
+      // If we've just checked the bottom-most value and it's not
+      // the one we're looking for, we're done.
+      if (mid == 0) break;
+      high = mid - 1;
+    }
+  }
+  int32_t field = TableGet<kEntryDist>(table, low);
+  uchar entry = GetEntry(field);
+  bool is_start = IsStart(field);
+  return (entry == value) ||
+          (entry < value && is_start);
+}
+
+template <int kW>
+struct MultiCharacterSpecialCase {
+  uint16_t length;
+  uchar chars[kW];
+};
+
+// Look up the mapping for the given character in the specified table,
+// which is of the specified length and uses the specified special case
+// mapping for multi-char mappings.  The next parameter is the character
+// following the one to map.  The result will be written in to the result
+// buffer and the number of characters written will be returned.  Finally,
+// if the allow_caching_ptr is non-null then false will be stored in
+// it if the result contains multiple characters or depends on the
+// context.
+template <int kW>
+static int LookupMapping(const int32_t* table,
+                         uint16_t size,
+                         const MultiCharacterSpecialCase<kW>* multi_chars,
+                         uchar chr,
+                         uchar next,
+                         uchar* result,
+                         bool* allow_caching_ptr) {
+  static const int kEntryDist = 2;
+  uint16_t value = chr & (kChunkBits - 1);
+  unsigned int low = 0;
+  unsigned int high = size - 1;
+  while (high != low) {
+    unsigned int mid = low + ((high - low) >> 1);
+    uchar current_value = GetEntry(TableGet<kEntryDist>(table, mid));
+    // If we've found an entry less than or equal to this one, and the next one
+    // is not also less than this one, we've arrived.
+    if ((current_value <= value) &&
+        (mid + 1 == size ||
+         GetEntry(TableGet<kEntryDist>(table, mid + 1)) > value)) {
+      low = mid;
+      break;
+    } else if (current_value < value) {
+      low = mid + 1;
+    } else if (current_value > value) {
+      // If we've just checked the bottom-most value and it's not
+      // the one we're looking for, we're done.
+      if (mid == 0) break;
+      high = mid - 1;
+    }
+  }
+  int32_t field = TableGet<kEntryDist>(table, low);
+  uchar entry = GetEntry(field);
+  bool is_start = IsStart(field);
+  bool found = (entry == value) || (entry < value && is_start);
+  if (found) {
+    int32_t value = table[2 * low + 1];
+    if (value == 0) {
+      // 0 means not present
+      return 0;
+    } else if ((value & 3) == 0) {
+      // Low bits 0 means a constant offset from the given character.
+      result[0] = chr + (value >> 2);
+      return 1;
+    } else if ((value & 3) == 1) {
+      // Low bits 1 means a special case mapping
+      if (allow_caching_ptr) *allow_caching_ptr = false;
+      const MultiCharacterSpecialCase<kW>& mapping = multi_chars[value >> 2];
+      for (int i = 0; i < mapping.length; i++)
+        result[i] = mapping.chars[i];
+      return mapping.length;
+    } else {
+      // Low bits 2 means a really really special case
+      if (allow_caching_ptr) *allow_caching_ptr = false;
+      // The cases of this switch are defined in unicode.py in the
+      // really_special_cases mapping.
+      switch (value >> 2) {
+        case 1:
+          // Really special case 1: upper case sigma.  This letter
+          // converts to two different lower case sigmas depending on
+          // whether or not it occurs at the end of a word.
+          if (next != 0 && Letter::Is(next)) {
+            result[0] = 0x03C3;
+          } else {
+            result[0] = 0x03C2;
+          }
+          return 1;
+        default:
+          return 0;
+      }
+      return -1;
+    }
+  } else {
+    return 0;
+  }
+}
+
+uchar Utf8::CalculateValue(const byte* str,
+                           unsigned length,
+                           unsigned* cursor) {
+  static const uchar kMaxOneByteChar = 0x7F;
+  static const uchar kMaxTwoByteChar = 0x7FF;
+  static const uchar kMaxThreeByteChar = 0xFFFF;
+  static const uchar kMaxFourByteChar = 0x1FFFFF;
+
+  // We only get called for non-ascii characters.
+  if (length == 1) {
+    *cursor += 1;
+    return kBadChar;
+  }
+  int first = str[0];
+  int second = str[1] ^ 0x80;
+  if (second & 0xC0) {
+    *cursor += 1;
+    return kBadChar;
+  }
+  if (first < 0xE0) {
+    if (first < 0xC0) {
+      *cursor += 1;
+      return kBadChar;
+    }
+    uchar l = ((first << 6) | second) & kMaxTwoByteChar;
+    if (l <= kMaxOneByteChar) {
+      *cursor += 1;
+      return kBadChar;
+    }
+    *cursor += 2;
+    return l;
+  }
+  if (length == 2) {
+    *cursor += 1;
+    return kBadChar;
+  }
+  int third = str[2] ^ 0x80;
+  if (third & 0xC0) {
+    *cursor += 1;
+    return kBadChar;
+  }
+  if (first < 0xF0) {
+    uchar l = ((((first << 6) | second) << 6) | third) & kMaxThreeByteChar;
+    if (l <= kMaxTwoByteChar) {
+      *cursor += 1;
+      return kBadChar;
+    }
+    *cursor += 3;
+    return l;
+  }
+  if (length == 3) {
+    *cursor += 1;
+    return kBadChar;
+  }
+  int fourth = str[3] ^ 0x80;
+  if (fourth & 0xC0) {
+    *cursor += 1;
+    return kBadChar;
+  }
+  if (first < 0xF8) {
+    uchar l = (((((first << 6 | second) << 6) | third) << 6) | fourth) &
+              kMaxFourByteChar;
+    if (l <= kMaxThreeByteChar) {
+      *cursor += 1;
+      return kBadChar;
+    }
+    *cursor += 4;
+    return l;
+  }
+  *cursor += 1;
+  return kBadChar;
+}
+
+const byte* Utf8::ReadBlock(Buffer<const char*> str, byte* buffer,
+    unsigned capacity, unsigned* chars_read_ptr, unsigned* offset_ptr) {
+  unsigned offset = *offset_ptr;
+  // Bail out early if we've reached the end of the string.
+  if (offset == str.length()) {
+    *chars_read_ptr = 0;
+    return NULL;
+  }
+  const byte* data = reinterpret_cast<const byte*>(str.data());
+  if (data[offset] <= kMaxOneByteChar) {
+    // The next character is an ascii char so we scan forward over
+    // the following ascii characters and return the next pure ascii
+    // substring
+    const byte* result = data + offset;
+    offset++;
+    while ((offset < str.length()) && (data[offset] <= kMaxOneByteChar))
+      offset++;
+    *chars_read_ptr = offset - *offset_ptr;
+    *offset_ptr = offset;
+    return result;
+  } else {
+    // The next character is non-ascii so we just fill the buffer
+    unsigned cursor = 0;
+    unsigned chars_read = 0;
+    while (offset < str.length()) {
+      uchar c = data[offset];
+      if (c <= kMaxOneByteChar) {
+        // Fast case for ascii characters
+        if (!CharacterStream::EncodeAsciiCharacter(c,
+                                                   buffer,
+                                                   capacity,
+                                                   cursor))
+          break;
+        offset += 1;
+      } else {
+        unsigned chars = 0;
+        c = Utf8::ValueOf(data + offset, str.length() - offset, &chars);
+        if (!CharacterStream::EncodeNonAsciiCharacter(c,
+                                                      buffer,
+                                                      capacity,
+                                                      cursor))
+          break;
+        offset += chars;
+      }
+      chars_read++;
+    }
+    *offset_ptr = offset;
+    *chars_read_ptr = chars_read;
+    return buffer;
+  }
+}
+
+unsigned CharacterStream::Length() {
+  unsigned result = 0;
+  while (has_more()) {
+    result++;
+    GetNext();
+  }
+  Rewind();
+  return result;
+}
+
+void CharacterStream::Seek(unsigned position) {
+  Rewind();
+  for (unsigned i = 0; i < position; i++) {
+    GetNext();
+  }
+}
+
+// Uppercase:            point.category == 'Lu'
+
+static const uint16_t kUppercaseTable0Size = 509;
+static const int32_t kUppercaseTable0[509] = { 1073741889, 90, 1073742016, 214, 1073742040, 222, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 313, 315, 317, 319, 321, 323, 325, 327, 330, 332, 334, 336, 338, 340, 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, 1073742200, 377, 379, 381, 1073742209, 386, 388, 1073742214, 391, 1073742217, 395, 1073742222, 401, 1073742227, 404, 1073742230, 408, 1073742236, 413, 1073742239, 416, 418, 420, 1073742246, 423, 425, 428, 1073742254, 431, 1073742257, 435, 437, 1073742263, 440, 444, 452, 455, 458, 461, 463, 465, 467, 469, 471, 473, 475, 478, 480, 482, 484, 486, 488, 490, 492, 494, 497, 500, 1073742326, 504, 506, 508, 510, 512, 514, 516, 518, 520, 522, 524, 526, 528, 530, 532, 534, 536, 538, 540, 542, 544, 546, 548, 550, 552, 554, 556, 558, 560, 562, 1073742394, 571, 1073742397, 574, 577, 1073742403, 582, 584, 586, 588, 590, 902, 1073742728, 906, 908, 1073742734, 911, 1073742737, 929, 1073742755, 939, 1073742802, 980, 984, 986, 988, 990, 992, 994, 996, 998, 1000, 1002, 1004, 1006, 1012, 1015, 1073742841, 1018, 1073742845, 1071, 1120, 1122, 1124, 1126, 1128, 1130, 1132, 1134, 1136, 1138, 1140, 1142, 1144, 1146, 1148, 1150, 1152, 1162, 1164, 1166, 1168, 1170, 1172, 1174, 1176, 1178, 1180, 1182, 1184, 1186, 1188, 1190, 1192, 1194, 1196, 1198, 1200, 1202, 1204, 1206, 1208, 1210, 1212, 1214, 1073743040, 1217, 1219, 1221, 1223, 1225, 1227, 1229, 1232, 1234, 1236, 1238, 1240, 1242, 1244, 1246, 1248, 1250, 1252, 1254, 1256, 1258, 1260, 1262, 1264, 1266, 1268, 1270, 1272, 1274, 1276, 1278, 1280, 1282, 1284, 1286, 1288, 1290, 1292, 1294, 1296, 1298, 1073743153, 1366, 1073746080, 4293, 7680, 7682, 7684, 7686, 7688, 7690, 7692, 7694, 7696, 7698, 7700, 7702, 7704, 7706, 7708, 7710, 7712, 7714, 7716, 7718, 7720, 7722, 7724, 7726, 7728, 7730, 7732, 7734, 7736, 7738, 7740, 7742, 7744, 7746, 7748, 7750, 7752, 7754, 7756, 7758, 7760, 7762, 7764, 7766, 7768, 7770, 7772, 7774, 7776, 7778, 7780, 7782, 7784, 7786, 7788, 7790, 7792, 7794, 7796, 7798, 7800, 7802, 7804, 7806, 7808, 7810, 7812, 7814, 7816, 7818, 7820, 7822, 7824, 7826, 7828, 7840, 7842, 7844, 7846, 7848, 7850, 7852, 7854, 7856, 7858, 7860, 7862, 7864, 7866, 7868, 7870, 7872, 7874, 7876, 7878, 7880, 7882, 7884, 7886, 7888, 7890, 7892, 7894, 7896, 7898, 7900, 7902, 7904, 7906, 7908, 7910, 7912, 7914, 7916, 7918, 7920, 7922, 7924, 7926, 7928, 1073749768, 7951, 1073749784, 7965, 1073749800, 7983, 1073749816, 7999, 1073749832, 8013, 8025, 8027, 8029, 8031, 1073749864, 8047, 1073749944, 8123, 1073749960, 8139, 1073749976, 8155, 1073749992, 8172, 1073750008, 8187, 8450, 8455, 1073750283, 8461, 1073750288, 8466, 8469, 1073750297, 8477, 8484, 8486, 8488, 1073750314, 8493, 1073750320, 8499, 1073750334, 8511, 8517, 8579, 1073753088, 11310, 11360, 1073753186, 11364, 11367, 11369, 11371, 11381, 11392, 11394, 11396, 11398, 11400, 11402, 11404, 11406, 11408, 11410, 11412, 11414, 11416, 11418, 11420, 11422, 11424, 11426, 11428, 11430, 11432, 11434, 11436, 11438, 11440, 11442, 11444, 11446, 11448, 11450, 11452, 11454, 11456, 11458, 11460, 11462, 11464, 11466, 11468, 11470, 11472, 11474, 11476, 11478, 11480, 11482, 11484, 11486, 11488, 11490 }; // NOLINT
+static const uint16_t kUppercaseTable1Size = 2;
+static const int32_t kUppercaseTable1[2] = { 1073774369, 32570 }; // NOLINT
+static const uint16_t kUppercaseTable2Size = 2;
+static const int32_t kUppercaseTable2[2] = { 1073742848, 1063 }; // NOLINT
+static const uint16_t kUppercaseTable3Size = 58;
+static const int32_t kUppercaseTable3[58] = { 1073763328, 21529, 1073763380, 21581, 1073763432, 21633, 21660, 1073763486, 21663, 21666, 1073763493, 21670, 1073763497, 21676, 1073763502, 21685, 1073763536, 21737, 1073763588, 21765, 1073763591, 21770, 1073763597, 21780, 1073763606, 21788, 1073763640, 21817, 1073763643, 21822, 1073763648, 21828, 21830, 1073763658, 21840, 1073763692, 21893, 1073763744, 21945, 1073763796, 21997, 1073763848, 22049, 1073763900, 22101, 1073763952, 22153, 1073764008, 22208, 1073764066, 22266, 1073764124, 22324, 1073764182, 22382, 1073764240, 22440, 22474 }; // NOLINT
+bool Uppercase::Is(uchar c) {
+  int chunk_index = c >> 15;
+  switch (chunk_index) {
+    case 0: return LookupPredicate(kUppercaseTable0,
+                                       kUppercaseTable0Size,
+                                       c);
+    case 1: return LookupPredicate(kUppercaseTable1,
+                                       kUppercaseTable1Size,
+                                       c);
+    case 2: return LookupPredicate(kUppercaseTable2,
+                                       kUppercaseTable2Size,
+                                       c);
+    case 3: return LookupPredicate(kUppercaseTable3,
+                                       kUppercaseTable3Size,
+                                       c);
+    default: return false;
+  }
+}
+
+// Lowercase:            point.category == 'Ll'
+
+static const uint16_t kLowercaseTable0Size = 528;
+static const int32_t kLowercaseTable0[528] = { 1073741921, 122, 170, 181, 186, 1073742047, 246, 1073742072, 255, 257, 259, 261, 263, 265, 267, 269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293, 295, 297, 299, 301, 303, 305, 307, 309, 1073742135, 312, 314, 316, 318, 320, 322, 324, 326, 1073742152, 329, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, 359, 361, 363, 365, 367, 369, 371, 373, 375, 378, 380, 1073742206, 384, 387, 389, 392, 1073742220, 397, 402, 405, 1073742233, 411, 414, 417, 419, 421, 424, 1073742250, 427, 429, 432, 436, 438, 1073742265, 442, 1073742269, 447, 454, 457, 460, 462, 464, 466, 468, 470, 472, 474, 1073742300, 477, 479, 481, 483, 485, 487, 489, 491, 493, 1073742319, 496, 499, 501, 505, 507, 509, 511, 513, 515, 517, 519, 521, 523, 525, 527, 529, 531, 533, 535, 537, 539, 541, 543, 545, 547, 549, 551, 553, 555, 557, 559, 561, 1073742387, 569, 572, 1073742399, 576, 578, 583, 585, 587, 589, 1073742415, 659, 1073742485, 687, 1073742715, 893, 912, 1073742764, 974, 1073742800, 977, 1073742805, 983, 985, 987, 989, 991, 993, 995, 997, 999, 1001, 1003, 1005, 1073742831, 1011, 1013, 1016, 1073742843, 1020, 1073742896, 1119, 1121, 1123, 1125, 1127, 1129, 1131, 1133, 1135, 1137, 1139, 1141, 1143, 1145, 1147, 1149, 1151, 1153, 1163, 1165, 1167, 1169, 1171, 1173, 1175, 1177, 1179, 1181, 1183, 1185, 1187, 1189, 1191, 1193, 1195, 1197, 1199, 1201, 1203, 1205, 1207, 1209, 1211, 1213, 1215, 1218, 1220, 1222, 1224, 1226, 1228, 1073743054, 1231, 1233, 1235, 1237, 1239, 1241, 1243, 1245, 1247, 1249, 1251, 1253, 1255, 1257, 1259, 1261, 1263, 1265, 1267, 1269, 1271, 1273, 1275, 1277, 1279, 1281, 1283, 1285, 1287, 1289, 1291, 1293, 1295, 1297, 1299, 1073743201, 1415, 1073749248, 7467, 1073749346, 7543, 1073749369, 7578, 7681, 7683, 7685, 7687, 7689, 7691, 7693, 7695, 7697, 7699, 7701, 7703, 7705, 7707, 7709, 7711, 7713, 7715, 7717, 7719, 7721, 7723, 7725, 7727, 7729, 7731, 7733, 7735, 7737, 7739, 7741, 7743, 7745, 7747, 7749, 7751, 7753, 7755, 7757, 7759, 7761, 7763, 7765, 7767, 7769, 7771, 7773, 7775, 7777, 7779, 7781, 7783, 7785, 7787, 7789, 7791, 7793, 7795, 7797, 7799, 7801, 7803, 7805, 7807, 7809, 7811, 7813, 7815, 7817, 7819, 7821, 7823, 7825, 7827, 1073749653, 7835, 7841, 7843, 7845, 7847, 7849, 7851, 7853, 7855, 7857, 7859, 7861, 7863, 7865, 7867, 7869, 7871, 7873, 7875, 7877, 7879, 7881, 7883, 7885, 7887, 7889, 7891, 7893, 7895, 7897, 7899, 7901, 7903, 7905, 7907, 7909, 7911, 7913, 7915, 7917, 7919, 7921, 7923, 7925, 7927, 7929, 1073749760, 7943, 1073749776, 7957, 1073749792, 7975, 1073749808, 7991, 1073749824, 8005, 1073749840, 8023, 1073749856, 8039, 1073749872, 8061, 1073749888, 8071, 1073749904, 8087, 1073749920, 8103, 1073749936, 8116, 1073749942, 8119, 8126, 1073749954, 8132, 1073749958, 8135, 1073749968, 8147, 1073749974, 8151, 1073749984, 8167, 1073750002, 8180, 1073750006, 8183, 8305, 8319, 8458, 1073750286, 8463, 8467, 8495, 8500, 8505, 1073750332, 8509, 1073750342, 8521, 8526, 8580, 1073753136, 11358, 11361, 1073753189, 11366, 11368, 11370, 11372, 11380, 1073753206, 11383, 11393, 11395, 11397, 11399, 11401, 11403, 11405, 11407, 11409, 11411, 11413, 11415, 11417, 11419, 11421, 11423, 11425, 11427, 11429, 11431, 11433, 11435, 11437, 11439, 11441, 11443, 11445, 11447, 11449, 11451, 11453, 11455, 11457, 11459, 11461, 11463, 11465, 11467, 11469, 11471, 11473, 11475, 11477, 11479, 11481, 11483, 11485, 11487, 11489, 1073753315, 11492, 1073753344, 11557 }; // NOLINT
+static const uint16_t kLowercaseTable1Size = 6;
+static const int32_t kLowercaseTable1[6] = { 1073773312, 31494, 1073773331, 31511, 1073774401, 32602 }; // NOLINT
+static const uint16_t kLowercaseTable2Size = 2;
+static const int32_t kLowercaseTable2[2] = { 1073742888, 1103 }; // NOLINT
+static const uint16_t kLowercaseTable3Size = 54;
+static const int32_t kLowercaseTable3[54] = { 1073763354, 21555, 1073763406, 21588, 1073763414, 21607, 1073763458, 21659, 1073763510, 21689, 21691, 1073763517, 21699, 1073763525, 21711, 1073763562, 21763, 1073763614, 21815, 1073763666, 21867, 1073763718, 21919, 1073763770, 21971, 1073763822, 22023, 1073763874, 22075, 1073763926, 22127, 1073763978, 22181, 1073764034, 22234, 1073764060, 22241, 1073764092, 22292, 1073764118, 22299, 1073764150, 22350, 1073764176, 22357, 1073764208, 22408, 1073764234, 22415, 1073764266, 22466, 1073764292, 22473, 22475 }; // NOLINT
+bool Lowercase::Is(uchar c) {
+  int chunk_index = c >> 15;
+  switch (chunk_index) {
+    case 0: return LookupPredicate(kLowercaseTable0,
+                                       kLowercaseTable0Size,
+                                       c);
+    case 1: return LookupPredicate(kLowercaseTable1,
+                                       kLowercaseTable1Size,
+                                       c);
+    case 2: return LookupPredicate(kLowercaseTable2,
+                                       kLowercaseTable2Size,
+                                       c);
+    case 3: return LookupPredicate(kLowercaseTable3,
+                                       kLowercaseTable3Size,
+                                       c);
+    default: return false;
+  }
+}
+
+// Letter:               point.category in ['Lu', 'Ll', 'Lt', 'Lm', 'Lo' ]
+
+static const uint16_t kLetterTable0Size = 476;
+static const int32_t kLetterTable0[476] = { 1073741889, 90, 1073741921, 122, 170, 181, 186, 1073742016, 214, 1073742040, 246, 1073742072, 705, 1073742534, 721, 1073742560, 740, 750, 1073742714, 893, 902, 1073742728, 906, 908, 1073742734, 929, 1073742755, 974, 1073742800, 1013, 1073742839, 1153, 1073742986, 1299, 1073743153, 1366, 1369, 1073743201, 1415, 1073743312, 1514, 1073743344, 1522, 1073743393, 1594, 1073743424, 1610, 1073743470, 1647, 1073743473, 1747, 1749, 1073743589, 1766, 1073743598, 1775, 1073743610, 1788, 1791, 1808, 1073743634, 1839, 1073743693, 1901, 1073743744, 1957, 1969, 1073743818, 2026, 1073743860, 2037, 2042, 1073744132, 2361, 2365, 2384, 1073744216, 2401, 1073744251, 2431, 1073744261, 2444, 1073744271, 2448, 1073744275, 2472, 1073744298, 2480, 2482, 1073744310, 2489, 2493, 2510, 1073744348, 2525, 1073744351, 2529, 1073744368, 2545, 1073744389, 2570, 1073744399, 2576, 1073744403, 2600, 1073744426, 2608, 1073744434, 2611, 1073744437, 2614, 1073744440, 2617, 1073744473, 2652, 2654, 1073744498, 2676, 1073744517, 2701, 1073744527, 2705, 1073744531, 2728, 1073744554, 2736, 1073744562, 2739, 1073744565, 2745, 2749, 2768, 1073744608, 2785, 1073744645, 2828, 1073744655, 2832, 1073744659, 2856, 1073744682, 2864, 1073744690, 2867, 1073744693, 2873, 2877, 1073744732, 2909, 1073744735, 2913, 2929, 2947, 1073744773, 2954, 1073744782, 2960, 1073744786, 2965, 1073744793, 2970, 2972, 1073744798, 2975, 1073744803, 2980, 1073744808, 2986, 1073744814, 3001, 1073744901, 3084, 1073744910, 3088, 1073744914, 3112, 1073744938, 3123, 1073744949, 3129, 1073744992, 3169, 1073745029, 3212, 1073745038, 3216, 1073745042, 3240, 1073745066, 3251, 1073745077, 3257, 3261, 3294, 1073745120, 3297, 1073745157, 3340, 1073745166, 3344, 1073745170, 3368, 1073745194, 3385, 1073745248, 3425, 1073745285, 3478, 1073745306, 3505, 1073745331, 3515, 3517, 1073745344, 3526, 1073745409, 3632, 1073745458, 3635, 1073745472, 3654, 1073745537, 3714, 3716, 1073745543, 3720, 3722, 3725, 1073745556, 3735, 1073745561, 3743, 1073745569, 3747, 3749, 3751, 1073745578, 3755, 1073745581, 3760, 1073745586, 3763, 3773, 1073745600, 3780, 3782, 1073745628, 3805, 3840, 1073745728, 3911, 1073745737, 3946, 1073745800, 3979, 1073745920, 4129, 1073745955, 4135, 1073745961, 4138, 1073746000, 4181, 1073746080, 4293, 1073746128, 4346, 4348, 1073746176, 4441, 1073746271, 4514, 1073746344, 4601, 1073746432, 4680, 1073746506, 4685, 1073746512, 4694, 4696, 1073746522, 4701, 1073746528, 4744, 1073746570, 4749, 1073746576, 4784, 1073746610, 4789, 1073746616, 4798, 4800, 1073746626, 4805, 1073746632, 4822, 1073746648, 4880, 1073746706, 4885, 1073746712, 4954, 1073746816, 5007, 1073746848, 5108, 1073746945, 5740, 1073747567, 5750, 1073747585, 5786, 1073747616, 5866, 1073747712, 5900, 1073747726, 5905, 1073747744, 5937, 1073747776, 5969, 1073747808, 5996, 1073747822, 6000, 1073747840, 6067, 6103, 6108, 1073748000, 6263, 1073748096, 6312, 1073748224, 6428, 1073748304, 6509, 1073748336, 6516, 1073748352, 6569, 1073748417, 6599, 1073748480, 6678, 1073748741, 6963, 1073748805, 6987, 1073749248, 7615, 1073749504, 7835, 1073749664, 7929, 1073749760, 7957, 1073749784, 7965, 1073749792, 8005, 1073749832, 8013, 1073749840, 8023, 8025, 8027, 8029, 1073749855, 8061, 1073749888, 8116, 1073749942, 8124, 8126, 1073749954, 8132, 1073749958, 8140, 1073749968, 8147, 1073749974, 8155, 1073749984, 8172, 1073750002, 8180, 1073750006, 8188, 8305, 8319, 1073750160, 8340, 8450, 8455, 1073750282, 8467, 8469, 1073750297, 8477, 8484, 8486, 8488, 1073750314, 8493, 1073750319, 8505, 1073750332, 8511, 1073750341, 8521, 8526, 1073750403, 8580, 1073753088, 11310, 1073753136, 11358, 1073753184, 11372, 1073753204, 11383, 1073753216, 11492, 1073753344, 11557, 1073753392, 11621, 11631, 1073753472, 11670, 1073753504, 11686, 1073753512, 11694, 1073753520, 11702, 1073753528, 11710, 1073753536, 11718, 1073753544, 11726, 1073753552, 11734, 1073753560, 11742, 1073754117, 12294, 1073754161, 12341, 1073754171, 12348, 1073754177, 12438, 1073754269, 12447, 1073754273, 12538, 1073754364, 12543, 1073754373, 12588, 1073754417, 12686, 1073754528, 12727, 1073754608, 12799, 1073755136, 19893, 1073761792, 32767 }; // NOLINT
+static const uint16_t kLetterTable1Size = 68;
+static const int32_t kLetterTable1[68] = { 1073741824, 8123, 1073750016, 9356, 1073751831, 10010, 1073752064, 10241, 1073752067, 10245, 1073752071, 10250, 1073752076, 10274, 1073752128, 10355, 1073753088, 22435, 1073772800, 31277, 1073773104, 31338, 1073773168, 31449, 1073773312, 31494, 1073773331, 31511, 31517, 1073773343, 31528, 1073773354, 31542, 1073773368, 31548, 31550, 1073773376, 31553, 1073773379, 31556, 1073773382, 31665, 1073773523, 32061, 1073773904, 32143, 1073773970, 32199, 1073774064, 32251, 1073774192, 32372, 1073774198, 32508, 1073774369, 32570, 1073774401, 32602, 1073774438, 32702, 1073774530, 32711, 1073774538, 32719, 1073774546, 32727, 1073774554, 32732 }; // NOLINT
+static const uint16_t kLetterTable2Size = 48;
+static const int32_t kLetterTable2[48] = { 1073741824, 11, 1073741837, 38, 1073741864, 58, 1073741884, 61, 1073741887, 77, 1073741904, 93, 1073741952, 250, 1073742592, 798, 1073742640, 832, 1073742658, 841, 1073742720, 925, 1073742752, 963, 1073742792, 975, 1073742848, 1181, 1073743872, 2053, 2056, 1073743882, 2101, 1073743927, 2104, 2108, 2111, 1073744128, 2325, 2560, 1073744400, 2579, 1073744405, 2583, 1073744409, 2611, 1073750016, 9070 }; // NOLINT
+static const uint16_t kLetterTable3Size = 57;
+static const int32_t kLetterTable3[57] = { 1073763328, 21588, 1073763414, 21660, 1073763486, 21663, 21666, 1073763493, 21670, 1073763497, 21676, 1073763502, 21689, 21691, 1073763517, 21699, 1073763525, 21765, 1073763591, 21770, 1073763597, 21780, 1073763606, 21788, 1073763614, 21817, 1073763643, 21822, 1073763648, 21828, 21830, 1073763658, 21840, 1073763666, 22181, 1073764008, 22208, 1073764034, 22234, 1073764060, 22266, 1073764092, 22292, 1073764118, 22324, 1073764150, 22350, 1073764176, 22382, 1073764208, 22408, 1073764234, 22440, 1073764266, 22466, 1073764292, 22475 }; // NOLINT
+static const uint16_t kLetterTable4Size = 2;
+static const int32_t kLetterTable4[2] = { 1073741824, 32767 }; // NOLINT
+static const uint16_t kLetterTable5Size = 4;
+static const int32_t kLetterTable5[4] = { 1073741824, 9942, 1073772544, 31261 }; // NOLINT
+bool Letter::Is(uchar c) {
+  int chunk_index = c >> 15;
+  switch (chunk_index) {
+    case 0: return LookupPredicate(kLetterTable0,
+                                       kLetterTable0Size,
+                                       c);
+    case 1: return LookupPredicate(kLetterTable1,
+                                       kLetterTable1Size,
+                                       c);
+    case 2: return LookupPredicate(kLetterTable2,
+                                       kLetterTable2Size,
+                                       c);
+    case 3: return LookupPredicate(kLetterTable3,
+                                       kLetterTable3Size,
+                                       c);
+    case 4: return LookupPredicate(kLetterTable4,
+                                       kLetterTable4Size,
+                                       c);
+    case 5: return LookupPredicate(kLetterTable5,
+                                       kLetterTable5Size,
+                                       c);
+    default: return false;
+  }
+}
+
+// Space:                point.category == 'Zs'
+
+static const uint16_t kSpaceTable0Size = 9;
+static const int32_t kSpaceTable0[9] = { 32, 160, 5760, 6158, 1073750016, 8202, 8239, 8287, 12288 }; // NOLINT
+bool Space::Is(uchar c) {
+  int chunk_index = c >> 15;
+  switch (chunk_index) {
+    case 0: return LookupPredicate(kSpaceTable0,
+                                       kSpaceTable0Size,
+                                       c);
+    default: return false;
+  }
+}
+
+// Number:               point.category in ['Nd', 'Nl', 'No' ]
+
+static const uint16_t kNumberTable0Size = 86;
+static const int32_t kNumberTable0[86] = { 1073741872, 57, 1073742002, 179, 185, 1073742012, 190, 1073743456, 1641, 1073743600, 1785, 1073743808, 1993, 1073744230, 2415, 1073744358, 2543, 1073744372, 2553, 1073744486, 2671, 1073744614, 2799, 1073744742, 2927, 1073744870, 3058, 1073744998, 3183, 1073745126, 3311, 1073745254, 3439, 1073745488, 3673, 1073745616, 3801, 1073745696, 3891, 1073745984, 4169, 1073746793, 4988, 1073747694, 5872, 1073747936, 6121, 1073747952, 6137, 1073747984, 6169, 1073748294, 6479, 1073748432, 6617, 1073748816, 7001, 8304, 1073750132, 8313, 1073750144, 8329, 1073750355, 8578, 1073751136, 9371, 1073751274, 9471, 1073751926, 10131, 11517, 12295, 1073754145, 12329, 1073754168, 12346, 1073754514, 12693, 1073754656, 12841, 1073754705, 12895, 1073754752, 12937, 1073754801, 12991 }; // NOLINT
+static const uint16_t kNumberTable1Size = 2;
+static const int32_t kNumberTable1[2] = { 1073774352, 32537 }; // NOLINT
+static const uint16_t kNumberTable2Size = 19;
+static const int32_t kNumberTable2[19] = { 1073742087, 307, 1073742144, 376, 394, 1073742624, 803, 833, 842, 1073742801, 981, 1073743008, 1193, 1073744150, 2329, 1073744448, 2631, 1073751040, 9314 }; // NOLINT
+static const uint16_t kNumberTable3Size = 4;
+static const int32_t kNumberTable3[4] = { 1073763168, 21361, 1073764302, 22527 }; // NOLINT
+bool Number::Is(uchar c) {
+  int chunk_index = c >> 15;
+  switch (chunk_index) {
+    case 0: return LookupPredicate(kNumberTable0,
+                                       kNumberTable0Size,
+                                       c);
+    case 1: return LookupPredicate(kNumberTable1,
+                                       kNumberTable1Size,
+                                       c);
+    case 2: return LookupPredicate(kNumberTable2,
+                                       kNumberTable2Size,
+                                       c);
+    case 3: return LookupPredicate(kNumberTable3,
+                                       kNumberTable3Size,
+                                       c);
+    default: return false;
+  }
+}
+
+// WhiteSpace:           'Ws' in point.properties
+
+static const uint16_t kWhiteSpaceTable0Size = 14;
+static const int32_t kWhiteSpaceTable0[14] = { 1073741833, 13, 32, 133, 160, 5760, 6158, 1073750016, 8202, 1073750056, 8233, 8239, 8287, 12288 }; // NOLINT
+bool WhiteSpace::Is(uchar c) {
+  int chunk_index = c >> 15;
+  switch (chunk_index) {
+    case 0: return LookupPredicate(kWhiteSpaceTable0,
+                                       kWhiteSpaceTable0Size,
+                                       c);
+    default: return false;
+  }
+}
+
+// LineTerminator:       'Lt' in point.properties
+
+static const uint16_t kLineTerminatorTable0Size = 4;
+static const int32_t kLineTerminatorTable0[4] = { 10, 13, 1073750056, 8233 }; // NOLINT
+bool LineTerminator::Is(uchar c) {
+  int chunk_index = c >> 15;
+  switch (chunk_index) {
+    case 0: return LookupPredicate(kLineTerminatorTable0,
+                                       kLineTerminatorTable0Size,
+                                       c);
+    default: return false;
+  }
+}
+
+// CombiningMark:        point.category in ['Mn', 'Mc']
+
+static const uint16_t kCombiningMarkTable0Size = 214;
+static const int32_t kCombiningMarkTable0[214] = { 1073742592, 879, 1073742979, 1158, 1073743249, 1469, 1471, 1073743297, 1474, 1073743300, 1477, 1479, 1073743376, 1557, 1073743435, 1630, 1648, 1073743574, 1756, 1073743583, 1764, 1073743591, 1768, 1073743594, 1773, 1809, 1073743664, 1866, 1073743782, 1968, 1073743851, 2035, 1073744129, 2307, 2364, 1073744190, 2381, 1073744209, 2388, 1073744226, 2403, 1073744257, 2435, 2492, 1073744318, 2500, 1073744327, 2504, 1073744331, 2509, 2519, 1073744354, 2531, 1073744385, 2563, 2620, 1073744446, 2626, 1073744455, 2632, 1073744459, 2637, 1073744496, 2673, 1073744513, 2691, 2748, 1073744574, 2757, 1073744583, 2761, 1073744587, 2765, 1073744610, 2787, 1073744641, 2819, 2876, 1073744702, 2883, 1073744711, 2888, 1073744715, 2893, 1073744726, 2903, 2946, 1073744830, 3010, 1073744838, 3016, 1073744842, 3021, 3031, 1073744897, 3075, 1073744958, 3140, 1073744966, 3144, 1073744970, 3149, 1073744981, 3158, 1073745026, 3203, 3260, 1073745086, 3268, 1073745094, 3272, 1073745098, 3277, 1073745109, 3286, 1073745122, 3299, 1073745154, 3331, 1073745214, 3395, 1073745222, 3400, 1073745226, 3405, 3415, 1073745282, 3459, 3530, 1073745359, 3540, 3542, 1073745368, 3551, 1073745394, 3571, 3633, 1073745460, 3642, 1073745479, 3662, 3761, 1073745588, 3769, 1073745595, 3772, 1073745608, 3789, 1073745688, 3865, 3893, 3895, 3897, 1073745726, 3903, 1073745777, 3972, 1073745798, 3975, 1073745808, 3991, 1073745817, 4028, 4038, 1073745964, 4146, 1073745974, 4153, 1073746006, 4185, 4959, 1073747730, 5908, 1073747762, 5940, 1073747794, 5971, 1073747826, 6003, 1073747894, 6099, 6109, 1073747979, 6157, 6313, 1073748256, 6443, 1073748272, 6459, 1073748400, 6592, 1073748424, 6601, 1073748503, 6683, 1073748736, 6916, 1073748788, 6980, 1073748843, 7027, 1073749440, 7626, 1073749502, 7679, 1073750224, 8412, 8417, 1073750245, 8431, 1073754154, 12335, 1073754265, 12442 }; // NOLINT
+static const uint16_t kCombiningMarkTable1Size = 10;
+static const int32_t kCombiningMarkTable1[10] = { 10242, 10246, 10251, 1073752099, 10279, 31518, 1073774080, 32271, 1073774112, 32291 }; // NOLINT
+static const uint16_t kCombiningMarkTable2Size = 9;
+static const int32_t kCombiningMarkTable2[9] = { 1073744385, 2563, 1073744389, 2566, 1073744396, 2575, 1073744440, 2618, 2623 }; // NOLINT
+static const uint16_t kCombiningMarkTable3Size = 12;
+static const int32_t kCombiningMarkTable3[12] = { 1073762661, 20841, 1073762669, 20850, 1073762683, 20866, 1073762693, 20875, 1073762730, 20909, 1073762882, 21060 }; // NOLINT
+static const uint16_t kCombiningMarkTable28Size = 2;
+static const int32_t kCombiningMarkTable28[2] = { 1073742080, 495 }; // NOLINT
+bool CombiningMark::Is(uchar c) {
+  int chunk_index = c >> 15;
+  switch (chunk_index) {
+    case 0: return LookupPredicate(kCombiningMarkTable0,
+                                       kCombiningMarkTable0Size,
+                                       c);
+    case 1: return LookupPredicate(kCombiningMarkTable1,
+                                       kCombiningMarkTable1Size,
+                                       c);
+    case 2: return LookupPredicate(kCombiningMarkTable2,
+                                       kCombiningMarkTable2Size,
+                                       c);
+    case 3: return LookupPredicate(kCombiningMarkTable3,
+                                       kCombiningMarkTable3Size,
+                                       c);
+    case 28: return LookupPredicate(kCombiningMarkTable28,
+                                       kCombiningMarkTable28Size,
+                                       c);
+    default: return false;
+  }
+}
+
+// ConnectorPunctuation: point.category == 'Pc'
+
+static const uint16_t kConnectorPunctuationTable0Size = 4;
+static const int32_t kConnectorPunctuationTable0[4] = { 95, 1073750079, 8256, 8276 }; // NOLINT
+static const uint16_t kConnectorPunctuationTable1Size = 5;
+static const int32_t kConnectorPunctuationTable1[5] = { 1073774131, 32308, 1073774157, 32335, 32575 }; // NOLINT
+bool ConnectorPunctuation::Is(uchar c) {
+  int chunk_index = c >> 15;
+  switch (chunk_index) {
+    case 0: return LookupPredicate(kConnectorPunctuationTable0,
+                                       kConnectorPunctuationTable0Size,
+                                       c);
+    case 1: return LookupPredicate(kConnectorPunctuationTable1,
+                                       kConnectorPunctuationTable1Size,
+                                       c);
+    default: return false;
+  }
+}
+
+static const MultiCharacterSpecialCase<3> kToLowercaseMultiStrings0[] = { {2, {105, 775}}, {0, {0}} }; // NOLINT
+static const uint16_t kToLowercaseTable0Size = 531;
+static const int32_t kToLowercaseTable0[1062] = { 1073741889, 128, 90, 128, 1073742016, 128, 214, 128, 1073742040, 128, 222, 128, 256, 4, 258, 4, 260, 4, 262, 4, 264, 4, 266, 4, 268, 4, 270, 4, 272, 4, 274, 4, 276, 4, 278, 4, 280, 4, 282, 4, 284, 4, 286, 4, 288, 4, 290, 4, 292, 4, 294, 4, 296, 4, 298, 4, 300, 4, 302, 4, 304, 1, 306, 4, 308, 4, 310, 4, 313, 4, 315, 4, 317, 4, 319, 4, 321, 4, 323, 4, 325, 4, 327, 4, 330, 4, 332, 4, 334, 4, 336, 4, 338, 4, 340, 4, 342, 4, 344, 4, 346, 4, 348, 4, 350, 4, 352, 4, 354, 4, 356, 4, 358, 4, 360, 4, 362, 4, 364, 4, 366, 4, 368, 4, 370, 4, 372, 4, 374, 4, 376, -484, 377, 4, 379, 4, 381, 4, 385, 840, 386, 4, 388, 4, 390, 824, 391, 4, 1073742217, 820, 394, 820, 395, 4, 398, 316, 399, 808, 400, 812, 401, 4, 403, 820, 404, 828, 406, 844, 407, 836, 408, 4, 412, 844, 413, 852, 415, 856, 416, 4, 418, 4, 420, 4, 422, 872, 423, 4, 425, 872, 428, 4, 430, 872, 431, 4, 1073742257, 868, 434, 868, 435, 4, 437, 4, 439, 876, 440, 4, 444, 4, 452, 8, 453, 4, 455, 8, 456, 4, 458, 8, 459, 4, 461, 4, 463, 4, 465, 4, 467, 4, 469, 4, 471, 4, 473, 4, 475, 4, 478, 4, 480, 4, 482, 4, 484, 4, 486, 4, 488, 4, 490, 4, 492, 4, 494, 4, 497, 8, 498, 4, 500, 4, 502, -388, 503, -224, 504, 4, 506, 4, 508, 4, 510, 4, 512, 4, 514, 4, 516, 4, 518, 4, 520, 4, 522, 4, 524, 4, 526, 4, 528, 4, 530, 4, 532, 4, 534, 4, 536, 4, 538, 4, 540, 4, 542, 4, 544, -520, 546, 4, 548, 4, 550, 4, 552, 4, 554, 4, 556, 4, 558, 4, 560, 4, 562, 4, 570, 43180, 571, 4, 573, -652, 574, 43168, 577, 4, 579, -780, 580, 276, 581, 284, 582, 4, 584, 4, 586, 4, 588, 4, 590, 4, 902, 152, 1073742728, 148, 906, 148, 908, 256, 1073742734, 252, 911, 252, 1073742737, 128, 929, 128, 1073742755, 6, 939, 128, 984, 4, 986, 4, 988, 4, 990, 4, 992, 4, 994, 4, 996, 4, 998, 4, 1000, 4, 1002, 4, 1004, 4, 1006, 4, 1012, -240, 1015, 4, 1017, -28, 1018, 4, 1073742845, -520, 1023, -520, 1073742848, 320, 1039, 320, 1073742864, 128, 1071, 128, 1120, 4, 1122, 4, 1124, 4, 1126, 4, 1128, 4, 1130, 4, 1132, 4, 1134, 4, 1136, 4, 1138, 4, 1140, 4, 1142, 4, 1144, 4, 1146, 4, 1148, 4, 1150, 4, 1152, 4, 1162, 4, 1164, 4, 1166, 4, 1168, 4, 1170, 4, 1172, 4, 1174, 4, 1176, 4, 1178, 4, 1180, 4, 1182, 4, 1184, 4, 1186, 4, 1188, 4, 1190, 4, 1192, 4, 1194, 4, 1196, 4, 1198, 4, 1200, 4, 1202, 4, 1204, 4, 1206, 4, 1208, 4, 1210, 4, 1212, 4, 1214, 4, 1216, 60, 1217, 4, 1219, 4, 1221, 4, 1223, 4, 1225, 4, 1227, 4, 1229, 4, 1232, 4, 1234, 4, 1236, 4, 1238, 4, 1240, 4, 1242, 4, 1244, 4, 1246, 4, 1248, 4, 1250, 4, 1252, 4, 1254, 4, 1256, 4, 1258, 4, 1260, 4, 1262, 4, 1264, 4, 1266, 4, 1268, 4, 1270, 4, 1272, 4, 1274, 4, 1276, 4, 1278, 4, 1280, 4, 1282, 4, 1284, 4, 1286, 4, 1288, 4, 1290, 4, 1292, 4, 1294, 4, 1296, 4, 1298, 4, 1073743153, 192, 1366, 192, 1073746080, 29056, 4293, 29056, 7680, 4, 7682, 4, 7684, 4, 7686, 4, 7688, 4, 7690, 4, 7692, 4, 7694, 4, 7696, 4, 7698, 4, 7700, 4, 7702, 4, 7704, 4, 7706, 4, 7708, 4, 7710, 4, 7712, 4, 7714, 4, 7716, 4, 7718, 4, 7720, 4, 7722, 4, 7724, 4, 7726, 4, 7728, 4, 7730, 4, 7732, 4, 7734, 4, 7736, 4, 7738, 4, 7740, 4, 7742, 4, 7744, 4, 7746, 4, 7748, 4, 7750, 4, 7752, 4, 7754, 4, 7756, 4, 7758, 4, 7760, 4, 7762, 4, 7764, 4, 7766, 4, 7768, 4, 7770, 4, 7772, 4, 7774, 4, 7776, 4, 7778, 4, 7780, 4, 7782, 4, 7784, 4, 7786, 4, 7788, 4, 7790, 4, 7792, 4, 7794, 4, 7796, 4, 7798, 4, 7800, 4, 7802, 4, 7804, 4, 7806, 4, 7808, 4, 7810, 4, 7812, 4, 7814, 4, 7816, 4, 7818, 4, 7820, 4, 7822, 4, 7824, 4, 7826, 4, 7828, 4, 7840, 4, 7842, 4, 7844, 4, 7846, 4, 7848, 4, 7850, 4, 7852, 4, 7854, 4, 7856, 4, 7858, 4, 7860, 4, 7862, 4, 7864, 4, 7866, 4, 7868, 4, 7870, 4, 7872, 4, 7874, 4, 7876, 4, 7878, 4, 7880, 4, 7882, 4, 7884, 4, 7886, 4, 7888, 4, 7890, 4, 7892, 4, 7894, 4, 7896, 4, 7898, 4, 7900, 4, 7902, 4, 7904, 4, 7906, 4, 7908, 4, 7910, 4, 7912, 4, 7914, 4, 7916, 4, 7918, 4, 7920, 4, 7922, 4, 7924, 4, 7926, 4, 7928, 4, 1073749768, -32, 7951, -32, 1073749784, -32, 7965, -32, 1073749800, -32, 7983, -32, 1073749816, -32, 7999, -32, 1073749832, -32, 8013, -32, 8025, -32, 8027, -32, 8029, -32, 8031, -32, 1073749864, -32, 8047, -32, 1073749896, -32, 8079, -32, 1073749912, -32, 8095, -32, 1073749928, -32, 8111, -32, 1073749944, -32, 8121, -32, 1073749946, -296, 8123, -296, 8124, -36, 1073749960, -344, 8139, -344, 8140, -36, 1073749976, -32, 8153, -32, 1073749978, -400, 8155, -400, 1073749992, -32, 8169, -32, 1073749994, -448, 8171, -448, 8172, -28, 1073750008, -512, 8185, -512, 1073750010, -504, 8187, -504, 8188, -36, 8486, -30068, 8490, -33532, 8491, -33048, 8498, 112, 1073750368, 64, 8559, 64, 8579, 4, 1073751222, 104, 9423, 104, 1073753088, 192, 11310, 192, 11360, 4, 11362, -42972, 11363, -15256, 11364, -42908, 11367, 4, 11369, 4, 11371, 4, 11381, 4, 11392, 4, 11394, 4, 11396, 4, 11398, 4, 11400, 4, 11402, 4, 11404, 4, 11406, 4, 11408, 4, 11410, 4, 11412, 4, 11414, 4, 11416, 4, 11418, 4, 11420, 4, 11422, 4, 11424, 4, 11426, 4, 11428, 4, 11430, 4, 11432, 4, 11434, 4, 11436, 4, 11438, 4, 11440, 4, 11442, 4, 11444, 4, 11446, 4, 11448, 4, 11450, 4, 11452, 4, 11454, 4, 11456, 4, 11458, 4, 11460, 4, 11462, 4, 11464, 4, 11466, 4, 11468, 4, 11470, 4, 11472, 4, 11474, 4, 11476, 4, 11478, 4, 11480, 4, 11482, 4, 11484, 4, 11486, 4, 11488, 4, 11490, 4 }; // NOLINT
+static const MultiCharacterSpecialCase<3> kToLowercaseMultiStrings1[] = { {0, {0}} }; // NOLINT
+static const uint16_t kToLowercaseTable1Size = 2;
+static const int32_t kToLowercaseTable1[4] = { 1073774369, 128, 32570, 128 }; // NOLINT
+static const MultiCharacterSpecialCase<3> kToLowercaseMultiStrings2[] = { {0, {0}} }; // NOLINT
+static const uint16_t kToLowercaseTable2Size = 2;
+static const int32_t kToLowercaseTable2[4] = { 1073742848, 160, 1063, 160 }; // NOLINT
+int ToLowercase::Convert(uchar c,
+                      uchar n,
+                      uchar* result,
+                      bool* allow_caching_ptr) {
+  int chunk_index = c >> 15;
+  switch (chunk_index) {
+    case 0: return LookupMapping(kToLowercaseTable0,
+                                     kToLowercaseTable0Size,
+                                     kToLowercaseMultiStrings0,
+                                     c,
+                                     n,
+                                     result,
+                                     allow_caching_ptr);
+    case 1: return LookupMapping(kToLowercaseTable1,
+                                     kToLowercaseTable1Size,
+                                     kToLowercaseMultiStrings1,
+                                     c,
+                                     n,
+                                     result,
+                                     allow_caching_ptr);
+    case 2: return LookupMapping(kToLowercaseTable2,
+                                     kToLowercaseTable2Size,
+                                     kToLowercaseMultiStrings2,
+                                     c,
+                                     n,
+                                     result,
+                                     allow_caching_ptr);
+    default: return 0;
+  }
+}
+
+static const MultiCharacterSpecialCase<3> kToUppercaseMultiStrings0[] = { {2, {83, 83}}, {2, {700, 78}}, {2, {74, 780}}, {3, {921, 776, 769}}, {3, {933, 776, 769}}, {2, {1333, 1362}}, {2, {72, 817}}, {2, {84, 776}}, {2, {87, 778}}, {2, {89, 778}}, {2, {65, 702}}, {2, {933, 787}}, {3, {933, 787, 768}}, {3, {933, 787, 769}}, {3, {933, 787, 834}}, {2, {7944, 921}}, {2, {7945, 921}}, {2, {7946, 921}}, {2, {7947, 921}}, {2, {7948, 921}}, {2, {7949, 921}}, {2, {7950, 921}}, {2, {7951, 921}}, {2, {7944, 921}}, {2, {7945, 921}}, {2, {7946, 921}}, {2, {7947, 921}}, {2, {7948, 921}}, {2, {7949, 921}}, {2, {7950, 921}}, {2, {7951, 921}}, {2, {7976, 921}}, {2, {7977, 921}}, {2, {7978, 921}}, {2, {7979, 921}}, {2, {7980, 921}}, {2, {7981, 921}}, {2, {7982, 921}}, {2, {7983, 921}}, {2, {7976, 921}}, {2, {7977, 921}}, {2, {7978, 921}}, {2, {7979, 921}}, {2, {7980, 921}}, {2, {7981, 921}}, {2, {7982, 921}}, {2, {7983, 921}}, {2, {8040, 921}}, {2, {8041, 921}}, {2, {8042, 921}}, {2, {8043, 921}}, {2, {8044, 921}}, {2, {8045, 921}}, {2, {8046, 921}}, {2, {8047, 921}}, {2, {8040, 921}}, {2, {8041, 921}}, {2, {8042, 921}}, {2, {8043, 921}}, {2, {8044, 921}}, {2, {8045, 921}}, {2, {8046, 921}}, {2, {8047, 921}}, {2, {8122, 921}}, {2, {913, 921}}, {2, {902, 921}}, {2, {913, 834}}, {3, {913, 834, 921}}, {2, {913, 921}}, {2, {8138, 921}}, {2, {919, 921}}, {2, {905, 921}}, {2, {919, 834}}, {3, {919, 834, 921}}, {2, {919, 921}}, {3, {921, 776, 768}}, {3, {921, 776, 769}}, {2, {921, 834}}, {3, {921, 776, 834}}, {3, {933, 776, 768}}, {3, {933, 776, 769}}, {2, {929, 787}}, {2, {933, 834}}, {3, {933, 776, 834}}, {2, {8186, 921}}, {2, {937, 921}}, {2, {911, 921}}, {2, {937, 834}}, {3, {937, 834, 921}}, {2, {937, 921}}, {0, {0}} }; // NOLINT
+static const uint16_t kToUppercaseTable0Size = 621;
+static const int32_t kToUppercaseTable0[1242] = { 1073741921, -128, 122, -128, 181, 2972, 223, 1, 1073742048, -128, 246, -128, 1073742072, -128, 254, -128, 255, 484, 257, -4, 259, -4, 261, -4, 263, -4, 265, -4, 267, -4, 269, -4, 271, -4, 273, -4, 275, -4, 277, -4, 279, -4, 281, -4, 283, -4, 285, -4, 287, -4, 289, -4, 291, -4, 293, -4, 295, -4, 297, -4, 299, -4, 301, -4, 303, -4, 305, -928, 307, -4, 309, -4, 311, -4, 314, -4, 316, -4, 318, -4, 320, -4, 322, -4, 324, -4, 326, -4, 328, -4, 329, 5, 331, -4, 333, -4, 335, -4, 337, -4, 339, -4, 341, -4, 343, -4, 345, -4, 347, -4, 349, -4, 351, -4, 353, -4, 355, -4, 357, -4, 359, -4, 361, -4, 363, -4, 365, -4, 367, -4, 369, -4, 371, -4, 373, -4, 375, -4, 378, -4, 380, -4, 382, -4, 383, -1200, 384, 780, 387, -4, 389, -4, 392, -4, 396, -4, 402, -4, 405, 388, 409, -4, 410, 652, 414, 520, 417, -4, 419, -4, 421, -4, 424, -4, 429, -4, 432, -4, 436, -4, 438, -4, 441, -4, 445, -4, 447, 224, 453, -4, 454, -8, 456, -4, 457, -8, 459, -4, 460, -8, 462, -4, 464, -4, 466, -4, 468, -4, 470, -4, 472, -4, 474, -4, 476, -4, 477, -316, 479, -4, 481, -4, 483, -4, 485, -4, 487, -4, 489, -4, 491, -4, 493, -4, 495, -4, 496, 9, 498, -4, 499, -8, 501, -4, 505, -4, 507, -4, 509, -4, 511, -4, 513, -4, 515, -4, 517, -4, 519, -4, 521, -4, 523, -4, 525, -4, 527, -4, 529, -4, 531, -4, 533, -4, 535, -4, 537, -4, 539, -4, 541, -4, 543, -4, 547, -4, 549, -4, 551, -4, 553, -4, 555, -4, 557, -4, 559, -4, 561, -4, 563, -4, 572, -4, 578, -4, 583, -4, 585, -4, 587, -4, 589, -4, 591, -4, 595, -840, 596, -824, 1073742422, -820, 599, -820, 601, -808, 603, -812, 608, -820, 611, -828, 616, -836, 617, -844, 619, 42972, 623, -844, 626, -852, 629, -856, 637, 42908, 640, -872, 643, -872, 648, -872, 649, -276, 1073742474, -868, 651, -868, 652, -284, 658, -876, 837, 336, 1073742715, 520, 893, 520, 912, 13, 940, -152, 1073742765, -148, 943, -148, 944, 17, 1073742769, -128, 961, -128, 962, -124, 1073742787, -128, 971, -128, 972, -256, 1073742797, -252, 974, -252, 976, -248, 977, -228, 981, -188, 982, -216, 985, -4, 987, -4, 989, -4, 991, -4, 993, -4, 995, -4, 997, -4, 999, -4, 1001, -4, 1003, -4, 1005, -4, 1007, -4, 1008, -344, 1009, -320, 1010, 28, 1013, -384, 1016, -4, 1019, -4, 1073742896, -128, 1103, -128, 1073742928, -320, 1119, -320, 1121, -4, 1123, -4, 1125, -4, 1127, -4, 1129, -4, 1131, -4, 1133, -4, 1135, -4, 1137, -4, 1139, -4, 1141, -4, 1143, -4, 1145, -4, 1147, -4, 1149, -4, 1151, -4, 1153, -4, 1163, -4, 1165, -4, 1167, -4, 1169, -4, 1171, -4, 1173, -4, 1175, -4, 1177, -4, 1179, -4, 1181, -4, 1183, -4, 1185, -4, 1187, -4, 1189, -4, 1191, -4, 1193, -4, 1195, -4, 1197, -4, 1199, -4, 1201, -4, 1203, -4, 1205, -4, 1207, -4, 1209, -4, 1211, -4, 1213, -4, 1215, -4, 1218, -4, 1220, -4, 1222, -4, 1224, -4, 1226, -4, 1228, -4, 1230, -4, 1231, -60, 1233, -4, 1235, -4, 1237, -4, 1239, -4, 1241, -4, 1243, -4, 1245, -4, 1247, -4, 1249, -4, 1251, -4, 1253, -4, 1255, -4, 1257, -4, 1259, -4, 1261, -4, 1263, -4, 1265, -4, 1267, -4, 1269, -4, 1271, -4, 1273, -4, 1275, -4, 1277, -4, 1279, -4, 1281, -4, 1283, -4, 1285, -4, 1287, -4, 1289, -4, 1291, -4, 1293, -4, 1295, -4, 1297, -4, 1299, -4, 1073743201, -192, 1414, -192, 1415, 21, 7549, 15256, 7681, -4, 7683, -4, 7685, -4, 7687, -4, 7689, -4, 7691, -4, 7693, -4, 7695, -4, 7697, -4, 7699, -4, 7701, -4, 7703, -4, 7705, -4, 7707, -4, 7709, -4, 7711, -4, 7713, -4, 7715, -4, 7717, -4, 7719, -4, 7721, -4, 7723, -4, 7725, -4, 7727, -4, 7729, -4, 7731, -4, 7733, -4, 7735, -4, 7737, -4, 7739, -4, 7741, -4, 7743, -4, 7745, -4, 7747, -4, 7749, -4, 7751, -4, 7753, -4, 7755, -4, 7757, -4, 7759, -4, 7761, -4, 7763, -4, 7765, -4, 7767, -4, 7769, -4, 7771, -4, 7773, -4, 7775, -4, 7777, -4, 7779, -4, 7781, -4, 7783, -4, 7785, -4, 7787, -4, 7789, -4, 7791, -4, 7793, -4, 7795, -4, 7797, -4, 7799, -4, 7801, -4, 7803, -4, 7805, -4, 7807, -4, 7809, -4, 7811, -4, 7813, -4, 7815, -4, 7817, -4, 7819, -4, 7821, -4, 7823, -4, 7825, -4, 7827, -4, 7829, -4, 7830, 25, 7831, 29, 7832, 33, 7833, 37, 7834, 41, 7835, -236, 7841, -4, 7843, -4, 7845, -4, 7847, -4, 7849, -4, 7851, -4, 7853, -4, 7855, -4, 7857, -4, 7859, -4, 7861, -4, 7863, -4, 7865, -4, 7867, -4, 7869, -4, 7871, -4, 7873, -4, 7875, -4, 7877, -4, 7879, -4, 7881, -4, 7883, -4, 7885, -4, 7887, -4, 7889, -4, 7891, -4, 7893, -4, 7895, -4, 7897, -4, 7899, -4, 7901, -4, 7903, -4, 7905, -4, 7907, -4, 7909, -4, 7911, -4, 7913, -4, 7915, -4, 7917, -4, 7919, -4, 7921, -4, 7923, -4, 7925, -4, 7927, -4, 7929, -4, 1073749760, 32, 7943, 32, 1073749776, 32, 7957, 32, 1073749792, 32, 7975, 32, 1073749808, 32, 7991, 32, 1073749824, 32, 8005, 32, 8016, 45, 8017, 32, 8018, 49, 8019, 32, 8020, 53, 8021, 32, 8022, 57, 8023, 32, 1073749856, 32, 8039, 32, 1073749872, 296, 8049, 296, 1073749874, 344, 8053, 344, 1073749878, 400, 8055, 400, 1073749880, 512, 8057, 512, 1073749882, 448, 8059, 448, 1073749884, 504, 8061, 504, 8064, 61, 8065, 65, 8066, 69, 8067, 73, 8068, 77, 8069, 81, 8070, 85, 8071, 89, 8072, 93, 8073, 97, 8074, 101, 8075, 105, 8076, 109, 8077, 113, 8078, 117, 8079, 121, 8080, 125, 8081, 129, 8082, 133, 8083, 137, 8084, 141, 8085, 145, 8086, 149, 8087, 153, 8088, 157, 8089, 161, 8090, 165, 8091, 169, 8092, 173, 8093, 177, 8094, 181, 8095, 185, 8096, 189, 8097, 193, 8098, 197, 8099, 201, 8100, 205, 8101, 209, 8102, 213, 8103, 217, 8104, 221, 8105, 225, 8106, 229, 8107, 233, 8108, 237, 8109, 241, 8110, 245, 8111, 249, 1073749936, 32, 8113, 32, 8114, 253, 8115, 257, 8116, 261, 8118, 265, 8119, 269, 8124, 273, 8126, -28820, 8130, 277, 8131, 281, 8132, 285, 8134, 289, 8135, 293, 8140, 297, 1073749968, 32, 8145, 32, 8146, 301, 8147, 305, 8150, 309, 8151, 313, 1073749984, 32, 8161, 32, 8162, 317, 8163, 321, 8164, 325, 8165, 28, 8166, 329, 8167, 333, 8178, 337, 8179, 341, 8180, 345, 8182, 349, 8183, 353, 8188, 357, 8526, -112, 1073750384, -64, 8575, -64, 8580, -4, 1073751248, -104, 9449, -104, 1073753136, -192, 11358, -192, 11361, -4, 11365, -43180, 11366, -43168, 11368, -4, 11370, -4, 11372, -4, 11382, -4, 11393, -4, 11395, -4, 11397, -4, 11399, -4, 11401, -4, 11403, -4, 11405, -4, 11407, -4, 11409, -4, 11411, -4, 11413, -4, 11415, -4, 11417, -4, 11419, -4, 11421, -4, 11423, -4, 11425, -4, 11427, -4, 11429, -4, 11431, -4, 11433, -4, 11435, -4, 11437, -4, 11439, -4, 11441, -4, 11443, -4, 11445, -4, 11447, -4, 11449, -4, 11451, -4, 11453, -4, 11455, -4, 11457, -4, 11459, -4, 11461, -4, 11463, -4, 11465, -4, 11467, -4, 11469, -4, 11471, -4, 11473, -4, 11475, -4, 11477, -4, 11479, -4, 11481, -4, 11483, -4, 11485, -4, 11487, -4, 11489, -4, 11491, -4, 1073753344, -29056, 11557, -29056 }; // NOLINT
+static const MultiCharacterSpecialCase<3> kToUppercaseMultiStrings1[] = { {2, {70, 70}}, {2, {70, 73}}, {2, {70, 76}}, {3, {70, 70, 73}}, {3, {70, 70, 76}}, {2, {83, 84}}, {2, {83, 84}}, {2, {1348, 1350}}, {2, {1348, 1333}}, {2, {1348, 1339}}, {2, {1358, 1350}}, {2, {1348, 1341}}, {0, {0}} }; // NOLINT
+static const uint16_t kToUppercaseTable1Size = 14;
+static const int32_t kToUppercaseTable1[28] = { 31488, 1, 31489, 5, 31490, 9, 31491, 13, 31492, 17, 31493, 21, 31494, 25, 31507, 29, 31508, 33, 31509, 37, 31510, 41, 31511, 45, 1073774401, -128, 32602, -128 }; // NOLINT
+static const MultiCharacterSpecialCase<3> kToUppercaseMultiStrings2[] = { {0, {0}} }; // NOLINT
+static const uint16_t kToUppercaseTable2Size = 2;
+static const int32_t kToUppercaseTable2[4] = { 1073742888, -160, 1103, -160 }; // NOLINT
+int ToUppercase::Convert(uchar c,
+                      uchar n,
+                      uchar* result,
+                      bool* allow_caching_ptr) {
+  int chunk_index = c >> 15;
+  switch (chunk_index) {
+    case 0: return LookupMapping(kToUppercaseTable0,
+                                     kToUppercaseTable0Size,
+                                     kToUppercaseMultiStrings0,
+                                     c,
+                                     n,
+                                     result,
+                                     allow_caching_ptr);
+    case 1: return LookupMapping(kToUppercaseTable1,
+                                     kToUppercaseTable1Size,
+                                     kToUppercaseMultiStrings1,
+                                     c,
+                                     n,
+                                     result,
+                                     allow_caching_ptr);
+    case 2: return LookupMapping(kToUppercaseTable2,
+                                     kToUppercaseTable2Size,
+                                     kToUppercaseMultiStrings2,
+                                     c,
+                                     n,
+                                     result,
+                                     allow_caching_ptr);
+    default: return 0;
+  }
+}
+
+static const MultiCharacterSpecialCase<1> kEcma262CanonicalizeMultiStrings0[] = { {0, {0}} }; // NOLINT
+static const uint16_t kEcma262CanonicalizeTable0Size = 529;
+static const int32_t kEcma262CanonicalizeTable0[1058] = { 1073741921, -128, 122, -128, 181, 2972, 1073742048, -128, 246, -128, 1073742072, -128, 254, -128, 255, 484, 257, -4, 259, -4, 261, -4, 263, -4, 265, -4, 267, -4, 269, -4, 271, -4, 273, -4, 275, -4, 277, -4, 279, -4, 281, -4, 283, -4, 285, -4, 287, -4, 289, -4, 291, -4, 293, -4, 295, -4, 297, -4, 299, -4, 301, -4, 303, -4, 307, -4, 309, -4, 311, -4, 314, -4, 316, -4, 318, -4, 320, -4, 322, -4, 324, -4, 326, -4, 328, -4, 331, -4, 333, -4, 335, -4, 337, -4, 339, -4, 341, -4, 343, -4, 345, -4, 347, -4, 349, -4, 351, -4, 353, -4, 355, -4, 357, -4, 359, -4, 361, -4, 363, -4, 365, -4, 367, -4, 369, -4, 371, -4, 373, -4, 375, -4, 378, -4, 380, -4, 382, -4, 384, 780, 387, -4, 389, -4, 392, -4, 396, -4, 402, -4, 405, 388, 409, -4, 410, 652, 414, 520, 417, -4, 419, -4, 421, -4, 424, -4, 429, -4, 432, -4, 436, -4, 438, -4, 441, -4, 445, -4, 447, 224, 453, -4, 454, -8, 456, -4, 457, -8, 459, -4, 460, -8, 462, -4, 464, -4, 466, -4, 468, -4, 470, -4, 472, -4, 474, -4, 476, -4, 477, -316, 479, -4, 481, -4, 483, -4, 485, -4, 487, -4, 489, -4, 491, -4, 493, -4, 495, -4, 498, -4, 499, -8, 501, -4, 505, -4, 507, -4, 509, -4, 511, -4, 513, -4, 515, -4, 517, -4, 519, -4, 521, -4, 523, -4, 525, -4, 527, -4, 529, -4, 531, -4, 533, -4, 535, -4, 537, -4, 539, -4, 541, -4, 543, -4, 547, -4, 549, -4, 551, -4, 553, -4, 555, -4, 557, -4, 559, -4, 561, -4, 563, -4, 572, -4, 578, -4, 583, -4, 585, -4, 587, -4, 589, -4, 591, -4, 595, -840, 596, -824, 1073742422, -820, 599, -820, 601, -808, 603, -812, 608, -820, 611, -828, 616, -836, 617, -844, 619, 42972, 623, -844, 626, -852, 629, -856, 637, 42908, 640, -872, 643, -872, 648, -872, 649, -276, 1073742474, -868, 651, -868, 652, -284, 658, -876, 837, 336, 1073742715, 520, 893, 520, 940, -152, 1073742765, -148, 943, -148, 1073742769, -128, 961, -128, 962, -124, 1073742787, -128, 971, -128, 972, -256, 1073742797, -252, 974, -252, 976, -248, 977, -228, 981, -188, 982, -216, 985, -4, 987, -4, 989, -4, 991, -4, 993, -4, 995, -4, 997, -4, 999, -4, 1001, -4, 1003, -4, 1005, -4, 1007, -4, 1008, -344, 1009, -320, 1010, 28, 1013, -384, 1016, -4, 1019, -4, 1073742896, -128, 1103, -128, 1073742928, -320, 1119, -320, 1121, -4, 1123, -4, 1125, -4, 1127, -4, 1129, -4, 1131, -4, 1133, -4, 1135, -4, 1137, -4, 1139, -4, 1141, -4, 1143, -4, 1145, -4, 1147, -4, 1149, -4, 1151, -4, 1153, -4, 1163, -4, 1165, -4, 1167, -4, 1169, -4, 1171, -4, 1173, -4, 1175, -4, 1177, -4, 1179, -4, 1181, -4, 1183, -4, 1185, -4, 1187, -4, 1189, -4, 1191, -4, 1193, -4, 1195, -4, 1197, -4, 1199, -4, 1201, -4, 1203, -4, 1205, -4, 1207, -4, 1209, -4, 1211, -4, 1213, -4, 1215, -4, 1218, -4, 1220, -4, 1222, -4, 1224, -4, 1226, -4, 1228, -4, 1230, -4, 1231, -60, 1233, -4, 1235, -4, 1237, -4, 1239, -4, 1241, -4, 1243, -4, 1245, -4, 1247, -4, 1249, -4, 1251, -4, 1253, -4, 1255, -4, 1257, -4, 1259, -4, 1261, -4, 1263, -4, 1265, -4, 1267, -4, 1269, -4, 1271, -4, 1273, -4, 1275, -4, 1277, -4, 1279, -4, 1281, -4, 1283, -4, 1285, -4, 1287, -4, 1289, -4, 1291, -4, 1293, -4, 1295, -4, 1297, -4, 1299, -4, 1073743201, -192, 1414, -192, 7549, 15256, 7681, -4, 7683, -4, 7685, -4, 7687, -4, 7689, -4, 7691, -4, 7693, -4, 7695, -4, 7697, -4, 7699, -4, 7701, -4, 7703, -4, 7705, -4, 7707, -4, 7709, -4, 7711, -4, 7713, -4, 7715, -4, 7717, -4, 7719, -4, 7721, -4, 7723, -4, 7725, -4, 7727, -4, 7729, -4, 7731, -4, 7733, -4, 7735, -4, 7737, -4, 7739, -4, 7741, -4, 7743, -4, 7745, -4, 7747, -4, 7749, -4, 7751, -4, 7753, -4, 7755, -4, 7757, -4, 7759, -4, 7761, -4, 7763, -4, 7765, -4, 7767, -4, 7769, -4, 7771, -4, 7773, -4, 7775, -4, 7777, -4, 7779, -4, 7781, -4, 7783, -4, 7785, -4, 7787, -4, 7789, -4, 7791, -4, 7793, -4, 7795, -4, 7797, -4, 7799, -4, 7801, -4, 7803, -4, 7805, -4, 7807, -4, 7809, -4, 7811, -4, 7813, -4, 7815, -4, 7817, -4, 7819, -4, 7821, -4, 7823, -4, 7825, -4, 7827, -4, 7829, -4, 7835, -236, 7841, -4, 7843, -4, 7845, -4, 7847, -4, 7849, -4, 7851, -4, 7853, -4, 7855, -4, 7857, -4, 7859, -4, 7861, -4, 7863, -4, 7865, -4, 7867, -4, 7869, -4, 7871, -4, 7873, -4, 7875, -4, 7877, -4, 7879, -4, 7881, -4, 7883, -4, 7885, -4, 7887, -4, 7889, -4, 7891, -4, 7893, -4, 7895, -4, 7897, -4, 7899, -4, 7901, -4, 7903, -4, 7905, -4, 7907, -4, 7909, -4, 7911, -4, 7913, -4, 7915, -4, 7917, -4, 7919, -4, 7921, -4, 7923, -4, 7925, -4, 7927, -4, 7929, -4, 1073749760, 32, 7943, 32, 1073749776, 32, 7957, 32, 1073749792, 32, 7975, 32, 1073749808, 32, 7991, 32, 1073749824, 32, 8005, 32, 8017, 32, 8019, 32, 8021, 32, 8023, 32, 1073749856, 32, 8039, 32, 1073749872, 296, 8049, 296, 1073749874, 344, 8053, 344, 1073749878, 400, 8055, 400, 1073749880, 512, 8057, 512, 1073749882, 448, 8059, 448, 1073749884, 504, 8061, 504, 1073749936, 32, 8113, 32, 8126, -28820, 1073749968, 32, 8145, 32, 1073749984, 32, 8161, 32, 8165, 28, 8526, -112, 1073750384, -64, 8575, -64, 8580, -4, 1073751248, -104, 9449, -104, 1073753136, -192, 11358, -192, 11361, -4, 11365, -43180, 11366, -43168, 11368, -4, 11370, -4, 11372, -4, 11382, -4, 11393, -4, 11395, -4, 11397, -4, 11399, -4, 11401, -4, 11403, -4, 11405, -4, 11407, -4, 11409, -4, 11411, -4, 11413, -4, 11415, -4, 11417, -4, 11419, -4, 11421, -4, 11423, -4, 11425, -4, 11427, -4, 11429, -4, 11431, -4, 11433, -4, 11435, -4, 11437, -4, 11439, -4, 11441, -4, 11443, -4, 11445, -4, 11447, -4, 11449, -4, 11451, -4, 11453, -4, 11455, -4, 11457, -4, 11459, -4, 11461, -4, 11463, -4, 11465, -4, 11467, -4, 11469, -4, 11471, -4, 11473, -4, 11475, -4, 11477, -4, 11479, -4, 11481, -4, 11483, -4, 11485, -4, 11487, -4, 11489, -4, 11491, -4, 1073753344, -29056, 11557, -29056 }; // NOLINT
+static const MultiCharacterSpecialCase<1> kEcma262CanonicalizeMultiStrings1[] = { {0, {0}} }; // NOLINT
+static const uint16_t kEcma262CanonicalizeTable1Size = 2;
+static const int32_t kEcma262CanonicalizeTable1[4] = { 1073774401, -128, 32602, -128 }; // NOLINT
+static const MultiCharacterSpecialCase<1> kEcma262CanonicalizeMultiStrings2[] = { {0, {0}} }; // NOLINT
+static const uint16_t kEcma262CanonicalizeTable2Size = 2;
+static const int32_t kEcma262CanonicalizeTable2[4] = { 1073742888, -160, 1103, -160 }; // NOLINT
+int Ecma262Canonicalize::Convert(uchar c,
+                      uchar n,
+                      uchar* result,
+                      bool* allow_caching_ptr) {
+  int chunk_index = c >> 15;
+  switch (chunk_index) {
+    case 0: return LookupMapping(kEcma262CanonicalizeTable0,
+                                     kEcma262CanonicalizeTable0Size,
+                                     kEcma262CanonicalizeMultiStrings0,
+                                     c,
+                                     n,
+                                     result,
+                                     allow_caching_ptr);
+    case 1: return LookupMapping(kEcma262CanonicalizeTable1,
+                                     kEcma262CanonicalizeTable1Size,
+                                     kEcma262CanonicalizeMultiStrings1,
+                                     c,
+                                     n,
+                                     result,
+                                     allow_caching_ptr);
+    case 2: return LookupMapping(kEcma262CanonicalizeTable2,
+                                     kEcma262CanonicalizeTable2Size,
+                                     kEcma262CanonicalizeMultiStrings2,
+                                     c,
+                                     n,
+                                     result,
+                                     allow_caching_ptr);
+    default: return 0;
+  }
+}
+
+static const MultiCharacterSpecialCase<4> kEcma262UnCanonicalizeMultiStrings0[] = { {2, {65, 97}}, {2, {66, 98}}, {2, {67, 99}}, {2, {68, 100}}, {2, {69, 101}}, {2, {70, 102}}, {2, {71, 103}}, {2, {72, 104}}, {2, {73, 105}}, {2, {74, 106}}, {2, {75, 107}}, {2, {76, 108}}, {2, {77, 109}}, {2, {78, 110}}, {2, {79, 111}}, {2, {80, 112}}, {2, {81, 113}}, {2, {82, 114}}, {2, {83, 115}}, {2, {84, 116}}, {2, {85, 117}}, {2, {86, 118}}, {2, {87, 119}}, {2, {88, 120}}, {2, {89, 121}}, {2, {90, 122}}, {2, {65, 97}}, {2, {66, 98}}, {2, {67, 99}}, {2, {68, 100}}, {2, {69, 101}}, {2, {70, 102}}, {2, {71, 103}}, {2, {72, 104}}, {2, {73, 105}}, {2, {74, 106}}, {2, {75, 107}}, {2, {76, 108}}, {2, {77, 109}}, {2, {78, 110}}, {2, {79, 111}}, {2, {80, 112}}, {2, {81, 113}}, {2, {82, 114}}, {2, {83, 115}}, {2, {84, 116}}, {2, {85, 117}}, {2, {86, 118}}, {2, {87, 119}}, {2, {88, 120}}, {2, {89, 121}}, {2, {90, 122}}, {3, {181, 924, 956}}, {2, {192, 224}}, {2, {193, 225}}, {2, {194, 226}}, {2, {195, 227}}, {2, {196, 228}}, {2, {197, 229}}, {2, {198, 230}}, {2, {199, 231}}, {2, {200, 232}}, {2, {201, 233}}, {2, {202, 234}}, {2, {203, 235}}, {2, {204, 236}}, {2, {205, 237}}, {2, {206, 238}}, {2, {207, 239}}, {2, {208, 240}}, {2, {209, 241}}, {2, {210, 242}}, {2, {211, 243}}, {2, {212, 244}}, {2, {213, 245}}, {2, {214, 246}}, {2, {216, 248}}, {2, {217, 249}}, {2, {218, 250}}, {2, {219, 251}}, {2, {220, 252}}, {2, {221, 253}}, {2, {222, 254}}, {2, {192, 224}}, {2, {193, 225}}, {2, {194, 226}}, {2, {195, 227}}, {2, {196, 228}}, {2, {197, 229}}, {2, {198, 230}}, {2, {199, 231}}, {2, {200, 232}}, {2, {201, 233}}, {2, {202, 234}}, {2, {203, 235}}, {2, {204, 236}}, {2, {205, 237}}, {2, {206, 238}}, {2, {207, 239}}, {2, {208, 240}}, {2, {209, 241}}, {2, {210, 242}}, {2, {211, 243}}, {2, {212, 244}}, {2, {213, 245}}, {2, {214, 246}}, {2, {216, 248}}, {2, {217, 249}}, {2, {218, 250}}, {2, {219, 251}}, {2, {220, 252}}, {2, {221, 253}}, {2, {222, 254}}, {2, {255, 376}}, {2, {256, 257}}, {2, {256, 257}}, {2, {258, 259}}, {2, {258, 259}}, {2, {260, 261}}, {2, {260, 261}}, {2, {262, 263}}, {2, {262, 263}}, {2, {264, 265}}, {2, {264, 265}}, {2, {266, 267}}, {2, {266, 267}}, {2, {268, 269}}, {2, {268, 269}}, {2, {270, 271}}, {2, {270, 271}}, {2, {272, 273}}, {2, {272, 273}}, {2, {274, 275}}, {2, {274, 275}}, {2, {276, 277}}, {2, {276, 277}}, {2, {278, 279}}, {2, {278, 279}}, {2, {280, 281}}, {2, {280, 281}}, {2, {282, 283}}, {2, {282, 283}}, {2, {284, 285}}, {2, {284, 285}}, {2, {286, 287}}, {2, {286, 287}}, {2, {288, 289}}, {2, {288, 289}}, {2, {290, 291}}, {2, {290, 291}}, {2, {292, 293}}, {2, {292, 293}}, {2, {294, 295}}, {2, {294, 295}}, {2, {296, 297}}, {2, {296, 297}}, {2, {298, 299}}, {2, {298, 299}}, {2, {300, 301}}, {2, {300, 301}}, {2, {302, 303}}, {2, {302, 303}}, {2, {306, 307}}, {2, {306, 307}}, {2, {308, 309}}, {2, {308, 309}}, {2, {310, 311}}, {2, {310, 311}}, {2, {313, 314}}, {2, {313, 314}}, {2, {315, 316}}, {2, {315, 316}}, {2, {317, 318}}, {2, {317, 318}}, {2, {319, 320}}, {2, {319, 320}}, {2, {321, 322}}, {2, {321, 322}}, {2, {323, 324}}, {2, {323, 324}}, {2, {325, 326}}, {2, {325, 326}}, {2, {327, 328}}, {2, {327, 328}}, {2, {330, 331}}, {2, {330, 331}}, {2, {332, 333}}, {2, {332, 333}}, {2, {334, 335}}, {2, {334, 335}}, {2, {336, 337}}, {2, {336, 337}}, {2, {338, 339}}, {2, {338, 339}}, {2, {340, 341}}, {2, {340, 341}}, {2, {342, 343}}, {2, {342, 343}}, {2, {344, 345}}, {2, {344, 345}}, {2, {346, 347}}, {2, {346, 347}}, {2, {348, 349}}, {2, {348, 349}}, {2, {350, 351}}, {2, {350, 351}}, {2, {352, 353}}, {2, {352, 353}}, {2, {354, 355}}, {2, {354, 355}}, {2, {356, 357}}, {2, {356, 357}}, {2, {358, 359}}, {2, {358, 359}}, {2, {360, 361}}, {2, {360, 361}}, {2, {362, 363}}, {2, {362, 363}}, {2, {364, 365}}, {2, {364, 365}}, {2, {366, 367}}, {2, {366, 367}}, {2, {368, 369}}, {2, {368, 369}}, {2, {370, 371}}, {2, {370, 371}}, {2, {372, 373}}, {2, {372, 373}}, {2, {374, 375}}, {2, {374, 375}}, {2, {255, 376}}, {2, {377, 378}}, {2, {377, 378}}, {2, {379, 380}}, {2, {379, 380}}, {2, {381, 382}}, {2, {381, 382}}, {2, {384, 579}}, {2, {385, 595}}, {2, {386, 387}}, {2, {386, 387}}, {2, {388, 389}}, {2, {388, 389}}, {2, {390, 596}}, {2, {391, 392}}, {2, {391, 392}}, {2, {393, 598}}, {2, {394, 599}}, {2, {395, 396}}, {2, {395, 396}}, {2, {398, 477}}, {2, {399, 601}}, {2, {400, 603}}, {2, {401, 402}}, {2, {401, 402}}, {2, {403, 608}}, {2, {404, 611}}, {2, {405, 502}}, {2, {406, 617}}, {2, {407, 616}}, {2, {408, 409}}, {2, {408, 409}}, {2, {410, 573}}, {2, {412, 623}}, {2, {413, 626}}, {2, {414, 544}}, {2, {415, 629}}, {2, {416, 417}}, {2, {416, 417}}, {2, {418, 419}}, {2, {418, 419}}, {2, {420, 421}}, {2, {420, 421}}, {2, {422, 640}}, {2, {423, 424}}, {2, {423, 424}}, {2, {425, 643}}, {2, {428, 429}}, {2, {428, 429}}, {2, {430, 648}}, {2, {431, 432}}, {2, {431, 432}}, {2, {433, 650}}, {2, {434, 651}}, {2, {435, 436}}, {2, {435, 436}}, {2, {437, 438}}, {2, {437, 438}}, {2, {439, 658}}, {2, {440, 441}}, {2, {440, 441}}, {2, {444, 445}}, {2, {444, 445}}, {2, {447, 503}}, {3, {452, 453, 454}}, {3, {452, 453, 454}}, {3, {452, 453, 454}}, {3, {455, 456, 457}}, {3, {455, 456, 457}}, {3, {455, 456, 457}}, {3, {458, 459, 460}}, {3, {458, 459, 460}}, {3, {458, 459, 460}}, {2, {461, 462}}, {2, {461, 462}}, {2, {463, 464}}, {2, {463, 464}}, {2, {465, 466}}, {2, {465, 466}}, {2, {467, 468}}, {2, {467, 468}}, {2, {469, 470}}, {2, {469, 470}}, {2, {471, 472}}, {2, {471, 472}}, {2, {473, 474}}, {2, {473, 474}}, {2, {475, 476}}, {2, {475, 476}}, {2, {398, 477}}, {2, {478, 479}}, {2, {478, 479}}, {2, {480, 481}}, {2, {480, 481}}, {2, {482, 483}}, {2, {482, 483}}, {2, {484, 485}}, {2, {484, 485}}, {2, {486, 487}}, {2, {486, 487}}, {2, {488, 489}}, {2, {488, 489}}, {2, {490, 491}}, {2, {490, 491}}, {2, {492, 493}}, {2, {492, 493}}, {2, {494, 495}}, {2, {494, 495}}, {3, {497, 498, 499}}, {3, {497, 498, 499}}, {3, {497, 498, 499}}, {2, {500, 501}}, {2, {500, 501}}, {2, {405, 502}}, {2, {447, 503}}, {2, {504, 505}}, {2, {504, 505}}, {2, {506, 507}}, {2, {506, 507}}, {2, {508, 509}}, {2, {508, 509}}, {2, {510, 511}}, {2, {510, 511}}, {2, {512, 513}}, {2, {512, 513}}, {2, {514, 515}}, {2, {514, 515}}, {2, {516, 517}}, {2, {516, 517}}, {2, {518, 519}}, {2, {518, 519}}, {2, {520, 521}}, {2, {520, 521}}, {2, {522, 523}}, {2, {522, 523}}, {2, {524, 525}}, {2, {524, 525}}, {2, {526, 527}}, {2, {526, 527}}, {2, {528, 529}}, {2, {528, 529}}, {2, {530, 531}}, {2, {530, 531}}, {2, {532, 533}}, {2, {532, 533}}, {2, {534, 535}}, {2, {534, 535}}, {2, {536, 537}}, {2, {536, 537}}, {2, {538, 539}}, {2, {538, 539}}, {2, {540, 541}}, {2, {540, 541}}, {2, {542, 543}}, {2, {542, 543}}, {2, {414, 544}}, {2, {546, 547}}, {2, {546, 547}}, {2, {548, 549}}, {2, {548, 549}}, {2, {550, 551}}, {2, {550, 551}}, {2, {552, 553}}, {2, {552, 553}}, {2, {554, 555}}, {2, {554, 555}}, {2, {556, 557}}, {2, {556, 557}}, {2, {558, 559}}, {2, {558, 559}}, {2, {560, 561}}, {2, {560, 561}}, {2, {562, 563}}, {2, {562, 563}}, {2, {570, 11365}}, {2, {571, 572}}, {2, {571, 572}}, {2, {410, 573}}, {2, {574, 11366}}, {2, {577, 578}}, {2, {577, 578}}, {2, {384, 579}}, {2, {580, 649}}, {2, {581, 652}}, {2, {582, 583}}, {2, {582, 583}}, {2, {584, 585}}, {2, {584, 585}}, {2, {586, 587}}, {2, {586, 587}}, {2, {588, 589}}, {2, {588, 589}}, {2, {590, 591}}, {2, {590, 591}}, {2, {385, 595}}, {2, {390, 596}}, {2, {393, 598}}, {2, {394, 599}}, {2, {399, 601}}, {2, {400, 603}}, {2, {403, 608}}, {2, {404, 611}}, {2, {407, 616}}, {2, {406, 617}}, {2, {619, 11362}}, {2, {412, 623}}, {2, {413, 626}}, {2, {415, 629}}, {2, {637, 11364}}, {2, {422, 640}}, {2, {425, 643}}, {2, {430, 648}}, {2, {580, 649}}, {2, {433, 650}}, {2, {434, 651}}, {2, {581, 652}}, {2, {439, 658}}, {4, {837, 921, 953, 8126}}, {2, {891, 1021}}, {2, {892, 1022}}, {2, {893, 1023}}, {2, {902, 940}}, {2, {904, 941}}, {2, {905, 942}}, {2, {906, 943}}, {2, {908, 972}}, {2, {910, 973}}, {2, {911, 974}}, {2, {913, 945}}, {3, {914, 946, 976}}, {2, {915, 947}}, {2, {916, 948}}, {3, {917, 949, 1013}}, {2, {918, 950}}, {2, {919, 951}}, {3, {920, 952, 977}}, {4, {837, 921, 953, 8126}}, {3, {922, 954, 1008}}, {2, {923, 955}}, {3, {181, 924, 956}}, {2, {925, 957}}, {2, {926, 958}}, {2, {927, 959}}, {3, {928, 960, 982}}, {3, {929, 961, 1009}}, {3, {931, 962, 963}}, {2, {932, 964}}, {2, {933, 965}}, {3, {934, 966, 981}}, {2, {935, 967}}, {2, {936, 968}}, {2, {937, 969}}, {2, {938, 970}}, {2, {939, 971}}, {2, {902, 940}}, {2, {904, 941}}, {2, {905, 942}}, {2, {906, 943}}, {2, {913, 945}}, {3, {914, 946, 976}}, {2, {915, 947}}, {2, {916, 948}}, {3, {917, 949, 1013}}, {2, {918, 950}}, {2, {919, 951}}, {3, {920, 952, 977}}, {4, {837, 921, 953, 8126}}, {3, {922, 954, 1008}}, {2, {923, 955}}, {3, {181, 924, 956}}, {2, {925, 957}}, {2, {926, 958}}, {2, {927, 959}}, {3, {928, 960, 982}}, {3, {929, 961, 1009}}, {3, {931, 962, 963}}, {3, {931, 962, 963}}, {2, {932, 964}}, {2, {933, 965}}, {3, {934, 966, 981}}, {2, {935, 967}}, {2, {936, 968}}, {2, {937, 969}}, {2, {938, 970}}, {2, {939, 971}}, {2, {908, 972}}, {2, {910, 973}}, {2, {911, 974}}, {3, {914, 946, 976}}, {3, {920, 952, 977}}, {3, {934, 966, 981}}, {3, {928, 960, 982}}, {2, {984, 985}}, {2, {984, 985}}, {2, {986, 987}}, {2, {986, 987}}, {2, {988, 989}}, {2, {988, 989}}, {2, {990, 991}}, {2, {990, 991}}, {2, {992, 993}}, {2, {992, 993}}, {2, {994, 995}}, {2, {994, 995}}, {2, {996, 997}}, {2, {996, 997}}, {2, {998, 999}}, {2, {998, 999}}, {2, {1000, 1001}}, {2, {1000, 1001}}, {2, {1002, 1003}}, {2, {1002, 1003}}, {2, {1004, 1005}}, {2, {1004, 1005}}, {2, {1006, 1007}}, {2, {1006, 1007}}, {3, {922, 954, 1008}}, {3, {929, 961, 1009}}, {2, {1010, 1017}}, {3, {917, 949, 1013}}, {2, {1015, 1016}}, {2, {1015, 1016}}, {2, {1010, 1017}}, {2, {1018, 1019}}, {2, {1018, 1019}}, {2, {891, 1021}}, {2, {892, 1022}}, {2, {893, 1023}}, {2, {1024, 1104}}, {2, {1025, 1105}}, {2, {1026, 1106}}, {2, {1027, 1107}}, {2, {1028, 1108}}, {2, {1029, 1109}}, {2, {1030, 1110}}, {2, {1031, 1111}}, {2, {1032, 1112}}, {2, {1033, 1113}}, {2, {1034, 1114}}, {2, {1035, 1115}}, {2, {1036, 1116}}, {2, {1037, 1117}}, {2, {1038, 1118}}, {2, {1039, 1119}}, {2, {1040, 1072}}, {2, {1041, 1073}}, {2, {1042, 1074}}, {2, {1043, 1075}}, {2, {1044, 1076}}, {2, {1045, 1077}}, {2, {1046, 1078}}, {2, {1047, 1079}}, {2, {1048, 1080}}, {2, {1049, 1081}}, {2, {1050, 1082}}, {2, {1051, 1083}}, {2, {1052, 1084}}, {2, {1053, 1085}}, {2, {1054, 1086}}, {2, {1055, 1087}}, {2, {1056, 1088}}, {2, {1057, 1089}}, {2, {1058, 1090}}, {2, {1059, 1091}}, {2, {1060, 1092}}, {2, {1061, 1093}}, {2, {1062, 1094}}, {2, {1063, 1095}}, {2, {1064, 1096}}, {2, {1065, 1097}}, {2, {1066, 1098}}, {2, {1067, 1099}}, {2, {1068, 1100}}, {2, {1069, 1101}}, {2, {1070, 1102}}, {2, {1071, 1103}}, {2, {1040, 1072}}, {2, {1041, 1073}}, {2, {1042, 1074}}, {2, {1043, 1075}}, {2, {1044, 1076}}, {2, {1045, 1077}}, {2, {1046, 1078}}, {2, {1047, 1079}}, {2, {1048, 1080}}, {2, {1049, 1081}}, {2, {1050, 1082}}, {2, {1051, 1083}}, {2, {1052, 1084}}, {2, {1053, 1085}}, {2, {1054, 1086}}, {2, {1055, 1087}}, {2, {1056, 1088}}, {2, {1057, 1089}}, {2, {1058, 1090}}, {2, {1059, 1091}}, {2, {1060, 1092}}, {2, {1061, 1093}}, {2, {1062, 1094}}, {2, {1063, 1095}}, {2, {1064, 1096}}, {2, {1065, 1097}}, {2, {1066, 1098}}, {2, {1067, 1099}}, {2, {1068, 1100}}, {2, {1069, 1101}}, {2, {1070, 1102}}, {2, {1071, 1103}}, {2, {1024, 1104}}, {2, {1025, 1105}}, {2, {1026, 1106}}, {2, {1027, 1107}}, {2, {1028, 1108}}, {2, {1029, 1109}}, {2, {1030, 1110}}, {2, {1031, 1111}}, {2, {1032, 1112}}, {2, {1033, 1113}}, {2, {1034, 1114}}, {2, {1035, 1115}}, {2, {1036, 1116}}, {2, {1037, 1117}}, {2, {1038, 1118}}, {2, {1039, 1119}}, {2, {1120, 1121}}, {2, {1120, 1121}}, {2, {1122, 1123}}, {2, {1122, 1123}}, {2, {1124, 1125}}, {2, {1124, 1125}}, {2, {1126, 1127}}, {2, {1126, 1127}}, {2, {1128, 1129}}, {2, {1128, 1129}}, {2, {1130, 1131}}, {2, {1130, 1131}}, {2, {1132, 1133}}, {2, {1132, 1133}}, {2, {1134, 1135}}, {2, {1134, 1135}}, {2, {1136, 1137}}, {2, {1136, 1137}}, {2, {1138, 1139}}, {2, {1138, 1139}}, {2, {1140, 1141}}, {2, {1140, 1141}}, {2, {1142, 1143}}, {2, {1142, 1143}}, {2, {1144, 1145}}, {2, {1144, 1145}}, {2, {1146, 1147}}, {2, {1146, 1147}}, {2, {1148, 1149}}, {2, {1148, 1149}}, {2, {1150, 1151}}, {2, {1150, 1151}}, {2, {1152, 1153}}, {2, {1152, 1153}}, {2, {1162, 1163}}, {2, {1162, 1163}}, {2, {1164, 1165}}, {2, {1164, 1165}}, {2, {1166, 1167}}, {2, {1166, 1167}}, {2, {1168, 1169}}, {2, {1168, 1169}}, {2, {1170, 1171}}, {2, {1170, 1171}}, {2, {1172, 1173}}, {2, {1172, 1173}}, {2, {1174, 1175}}, {2, {1174, 1175}}, {2, {1176, 1177}}, {2, {1176, 1177}}, {2, {1178, 1179}}, {2, {1178, 1179}}, {2, {1180, 1181}}, {2, {1180, 1181}}, {2, {1182, 1183}}, {2, {1182, 1183}}, {2, {1184, 1185}}, {2, {1184, 1185}}, {2, {1186, 1187}}, {2, {1186, 1187}}, {2, {1188, 1189}}, {2, {1188, 1189}}, {2, {1190, 1191}}, {2, {1190, 1191}}, {2, {1192, 1193}}, {2, {1192, 1193}}, {2, {1194, 1195}}, {2, {1194, 1195}}, {2, {1196, 1197}}, {2, {1196, 1197}}, {2, {1198, 1199}}, {2, {1198, 1199}}, {2, {1200, 1201}}, {2, {1200, 1201}}, {2, {1202, 1203}}, {2, {1202, 1203}}, {2, {1204, 1205}}, {2, {1204, 1205}}, {2, {1206, 1207}}, {2, {1206, 1207}}, {2, {1208, 1209}}, {2, {1208, 1209}}, {2, {1210, 1211}}, {2, {1210, 1211}}, {2, {1212, 1213}}, {2, {1212, 1213}}, {2, {1214, 1215}}, {2, {1214, 1215}}, {2, {1216, 1231}}, {2, {1217, 1218}}, {2, {1217, 1218}}, {2, {1219, 1220}}, {2, {1219, 1220}}, {2, {1221, 1222}}, {2, {1221, 1222}}, {2, {1223, 1224}}, {2, {1223, 1224}}, {2, {1225, 1226}}, {2, {1225, 1226}}, {2, {1227, 1228}}, {2, {1227, 1228}}, {2, {1229, 1230}}, {2, {1229, 1230}}, {2, {1216, 1231}}, {2, {1232, 1233}}, {2, {1232, 1233}}, {2, {1234, 1235}}, {2, {1234, 1235}}, {2, {1236, 1237}}, {2, {1236, 1237}}, {2, {1238, 1239}}, {2, {1238, 1239}}, {2, {1240, 1241}}, {2, {1240, 1241}}, {2, {1242, 1243}}, {2, {1242, 1243}}, {2, {1244, 1245}}, {2, {1244, 1245}}, {2, {1246, 1247}}, {2, {1246, 1247}}, {2, {1248, 1249}}, {2, {1248, 1249}}, {2, {1250, 1251}}, {2, {1250, 1251}}, {2, {1252, 1253}}, {2, {1252, 1253}}, {2, {1254, 1255}}, {2, {1254, 1255}}, {2, {1256, 1257}}, {2, {1256, 1257}}, {2, {1258, 1259}}, {2, {1258, 1259}}, {2, {1260, 1261}}, {2, {1260, 1261}}, {2, {1262, 1263}}, {2, {1262, 1263}}, {2, {1264, 1265}}, {2, {1264, 1265}}, {2, {1266, 1267}}, {2, {1266, 1267}}, {2, {1268, 1269}}, {2, {1268, 1269}}, {2, {1270, 1271}}, {2, {1270, 1271}}, {2, {1272, 1273}}, {2, {1272, 1273}}, {2, {1274, 1275}}, {2, {1274, 1275}}, {2, {1276, 1277}}, {2, {1276, 1277}}, {2, {1278, 1279}}, {2, {1278, 1279}}, {2, {1280, 1281}}, {2, {1280, 1281}}, {2, {1282, 1283}}, {2, {1282, 1283}}, {2, {1284, 1285}}, {2, {1284, 1285}}, {2, {1286, 1287}}, {2, {1286, 1287}}, {2, {1288, 1289}}, {2, {1288, 1289}}, {2, {1290, 1291}}, {2, {1290, 1291}}, {2, {1292, 1293}}, {2, {1292, 1293}}, {2, {1294, 1295}}, {2, {1294, 1295}}, {2, {1296, 1297}}, {2, {1296, 1297}}, {2, {1298, 1299}}, {2, {1298, 1299}}, {2, {1329, 1377}}, {2, {1330, 1378}}, {2, {1331, 1379}}, {2, {1332, 1380}}, {2, {1333, 1381}}, {2, {1334, 1382}}, {2, {1335, 1383}}, {2, {1336, 1384}}, {2, {1337, 1385}}, {2, {1338, 1386}}, {2, {1339, 1387}}, {2, {1340, 1388}}, {2, {1341, 1389}}, {2, {1342, 1390}}, {2, {1343, 1391}}, {2, {1344, 1392}}, {2, {1345, 1393}}, {2, {1346, 1394}}, {2, {1347, 1395}}, {2, {1348, 1396}}, {2, {1349, 1397}}, {2, {1350, 1398}}, {2, {1351, 1399}}, {2, {1352, 1400}}, {2, {1353, 1401}}, {2, {1354, 1402}}, {2, {1355, 1403}}, {2, {1356, 1404}}, {2, {1357, 1405}}, {2, {1358, 1406}}, {2, {1359, 1407}}, {2, {1360, 1408}}, {2, {1361, 1409}}, {2, {1362, 1410}}, {2, {1363, 1411}}, {2, {1364, 1412}}, {2, {1365, 1413}}, {2, {1366, 1414}}, {2, {1329, 1377}}, {2, {1330, 1378}}, {2, {1331, 1379}}, {2, {1332, 1380}}, {2, {1333, 1381}}, {2, {1334, 1382}}, {2, {1335, 1383}}, {2, {1336, 1384}}, {2, {1337, 1385}}, {2, {1338, 1386}}, {2, {1339, 1387}}, {2, {1340, 1388}}, {2, {1341, 1389}}, {2, {1342, 1390}}, {2, {1343, 1391}}, {2, {1344, 1392}}, {2, {1345, 1393}}, {2, {1346, 1394}}, {2, {1347, 1395}}, {2, {1348, 1396}}, {2, {1349, 1397}}, {2, {1350, 1398}}, {2, {1351, 1399}}, {2, {1352, 1400}}, {2, {1353, 1401}}, {2, {1354, 1402}}, {2, {1355, 1403}}, {2, {1356, 1404}}, {2, {1357, 1405}}, {2, {1358, 1406}}, {2, {1359, 1407}}, {2, {1360, 1408}}, {2, {1361, 1409}}, {2, {1362, 1410}}, {2, {1363, 1411}}, {2, {1364, 1412}}, {2, {1365, 1413}}, {2, {1366, 1414}}, {2, {4256, 11520}}, {2, {4257, 11521}}, {2, {4258, 11522}}, {2, {4259, 11523}}, {2, {4260, 11524}}, {2, {4261, 11525}}, {2, {4262, 11526}}, {2, {4263, 11527}}, {2, {4264, 11528}}, {2, {4265, 11529}}, {2, {4266, 11530}}, {2, {4267, 11531}}, {2, {4268, 11532}}, {2, {4269, 11533}}, {2, {4270, 11534}}, {2, {4271, 11535}}, {2, {4272, 11536}}, {2, {4273, 11537}}, {2, {4274, 11538}}, {2, {4275, 11539}}, {2, {4276, 11540}}, {2, {4277, 11541}}, {2, {4278, 11542}}, {2, {4279, 11543}}, {2, {4280, 11544}}, {2, {4281, 11545}}, {2, {4282, 11546}}, {2, {4283, 11547}}, {2, {4284, 11548}}, {2, {4285, 11549}}, {2, {4286, 11550}}, {2, {4287, 11551}}, {2, {4288, 11552}}, {2, {4289, 11553}}, {2, {4290, 11554}}, {2, {4291, 11555}}, {2, {4292, 11556}}, {2, {4293, 11557}}, {2, {7549, 11363}}, {2, {7680, 7681}}, {2, {7680, 7681}}, {2, {7682, 7683}}, {2, {7682, 7683}}, {2, {7684, 7685}}, {2, {7684, 7685}}, {2, {7686, 7687}}, {2, {7686, 7687}}, {2, {7688, 7689}}, {2, {7688, 7689}}, {2, {7690, 7691}}, {2, {7690, 7691}}, {2, {7692, 7693}}, {2, {7692, 7693}}, {2, {7694, 7695}}, {2, {7694, 7695}}, {2, {7696, 7697}}, {2, {7696, 7697}}, {2, {7698, 7699}}, {2, {7698, 7699}}, {2, {7700, 7701}}, {2, {7700, 7701}}, {2, {7702, 7703}}, {2, {7702, 7703}}, {2, {7704, 7705}}, {2, {7704, 7705}}, {2, {7706, 7707}}, {2, {7706, 7707}}, {2, {7708, 7709}}, {2, {7708, 7709}}, {2, {7710, 7711}}, {2, {7710, 7711}}, {2, {7712, 7713}}, {2, {7712, 7713}}, {2, {7714, 7715}}, {2, {7714, 7715}}, {2, {7716, 7717}}, {2, {7716, 7717}}, {2, {7718, 7719}}, {2, {7718, 7719}}, {2, {7720, 7721}}, {2, {7720, 7721}}, {2, {7722, 7723}}, {2, {7722, 7723}}, {2, {7724, 7725}}, {2, {7724, 7725}}, {2, {7726, 7727}}, {2, {7726, 7727}}, {2, {7728, 7729}}, {2, {7728, 7729}}, {2, {7730, 7731}}, {2, {7730, 7731}}, {2, {7732, 7733}}, {2, {7732, 7733}}, {2, {7734, 7735}}, {2, {7734, 7735}}, {2, {7736, 7737}}, {2, {7736, 7737}}, {2, {7738, 7739}}, {2, {7738, 7739}}, {2, {7740, 7741}}, {2, {7740, 7741}}, {2, {7742, 7743}}, {2, {7742, 7743}}, {2, {7744, 7745}}, {2, {7744, 7745}}, {2, {7746, 7747}}, {2, {7746, 7747}}, {2, {7748, 7749}}, {2, {7748, 7749}}, {2, {7750, 7751}}, {2, {7750, 7751}}, {2, {7752, 7753}}, {2, {7752, 7753}}, {2, {7754, 7755}}, {2, {7754, 7755}}, {2, {7756, 7757}}, {2, {7756, 7757}}, {2, {7758, 7759}}, {2, {7758, 7759}}, {2, {7760, 7761}}, {2, {7760, 7761}}, {2, {7762, 7763}}, {2, {7762, 7763}}, {2, {7764, 7765}}, {2, {7764, 7765}}, {2, {7766, 7767}}, {2, {7766, 7767}}, {2, {7768, 7769}}, {2, {7768, 7769}}, {2, {7770, 7771}}, {2, {7770, 7771}}, {2, {7772, 7773}}, {2, {7772, 7773}}, {2, {7774, 7775}}, {2, {7774, 7775}}, {3, {7776, 7777, 7835}}, {3, {7776, 7777, 7835}}, {2, {7778, 7779}}, {2, {7778, 7779}}, {2, {7780, 7781}}, {2, {7780, 7781}}, {2, {7782, 7783}}, {2, {7782, 7783}}, {2, {7784, 7785}}, {2, {7784, 7785}}, {2, {7786, 7787}}, {2, {7786, 7787}}, {2, {7788, 7789}}, {2, {7788, 7789}}, {2, {7790, 7791}}, {2, {7790, 7791}}, {2, {7792, 7793}}, {2, {7792, 7793}}, {2, {7794, 7795}}, {2, {7794, 7795}}, {2, {7796, 7797}}, {2, {7796, 7797}}, {2, {7798, 7799}}, {2, {7798, 7799}}, {2, {7800, 7801}}, {2, {7800, 7801}}, {2, {7802, 7803}}, {2, {7802, 7803}}, {2, {7804, 7805}}, {2, {7804, 7805}}, {2, {7806, 7807}}, {2, {7806, 7807}}, {2, {7808, 7809}}, {2, {7808, 7809}}, {2, {7810, 7811}}, {2, {7810, 7811}}, {2, {7812, 7813}}, {2, {7812, 7813}}, {2, {7814, 7815}}, {2, {7814, 7815}}, {2, {7816, 7817}}, {2, {7816, 7817}}, {2, {7818, 7819}}, {2, {7818, 7819}}, {2, {7820, 7821}}, {2, {7820, 7821}}, {2, {7822, 7823}}, {2, {7822, 7823}}, {2, {7824, 7825}}, {2, {7824, 7825}}, {2, {7826, 7827}}, {2, {7826, 7827}}, {2, {7828, 7829}}, {2, {7828, 7829}}, {3, {7776, 7777, 7835}}, {2, {7840, 7841}}, {2, {7840, 7841}}, {2, {7842, 7843}}, {2, {7842, 7843}}, {2, {7844, 7845}}, {2, {7844, 7845}}, {2, {7846, 7847}}, {2, {7846, 7847}}, {2, {7848, 7849}}, {2, {7848, 7849}}, {2, {7850, 7851}}, {2, {7850, 7851}}, {2, {7852, 7853}}, {2, {7852, 7853}}, {2, {7854, 7855}}, {2, {7854, 7855}}, {2, {7856, 7857}}, {2, {7856, 7857}}, {2, {7858, 7859}}, {2, {7858, 7859}}, {2, {7860, 7861}}, {2, {7860, 7861}}, {2, {7862, 7863}}, {2, {7862, 7863}}, {2, {7864, 7865}}, {2, {7864, 7865}}, {2, {7866, 7867}}, {2, {7866, 7867}}, {2, {7868, 7869}}, {2, {7868, 7869}}, {2, {7870, 7871}}, {2, {7870, 7871}}, {2, {7872, 7873}}, {2, {7872, 7873}}, {2, {7874, 7875}}, {2, {7874, 7875}}, {2, {7876, 7877}}, {2, {7876, 7877}}, {2, {7878, 7879}}, {2, {7878, 7879}}, {2, {7880, 7881}}, {2, {7880, 7881}}, {2, {7882, 7883}}, {2, {7882, 7883}}, {2, {7884, 7885}}, {2, {7884, 7885}}, {2, {7886, 7887}}, {2, {7886, 7887}}, {2, {7888, 7889}}, {2, {7888, 7889}}, {2, {7890, 7891}}, {2, {7890, 7891}}, {2, {7892, 7893}}, {2, {7892, 7893}}, {2, {7894, 7895}}, {2, {7894, 7895}}, {2, {7896, 7897}}, {2, {7896, 7897}}, {2, {7898, 7899}}, {2, {7898, 7899}}, {2, {7900, 7901}}, {2, {7900, 7901}}, {2, {7902, 7903}}, {2, {7902, 7903}}, {2, {7904, 7905}}, {2, {7904, 7905}}, {2, {7906, 7907}}, {2, {7906, 7907}}, {2, {7908, 7909}}, {2, {7908, 7909}}, {2, {7910, 7911}}, {2, {7910, 7911}}, {2, {7912, 7913}}, {2, {7912, 7913}}, {2, {7914, 7915}}, {2, {7914, 7915}}, {2, {7916, 7917}}, {2, {7916, 7917}}, {2, {7918, 7919}}, {2, {7918, 7919}}, {2, {7920, 7921}}, {2, {7920, 7921}}, {2, {7922, 7923}}, {2, {7922, 7923}}, {2, {7924, 7925}}, {2, {7924, 7925}}, {2, {7926, 7927}}, {2, {7926, 7927}}, {2, {7928, 7929}}, {2, {7928, 7929}}, {2, {7936, 7944}}, {2, {7937, 7945}}, {2, {7938, 7946}}, {2, {7939, 7947}}, {2, {7940, 7948}}, {2, {7941, 7949}}, {2, {7942, 7950}}, {2, {7943, 7951}}, {2, {7936, 7944}}, {2, {7937, 7945}}, {2, {7938, 7946}}, {2, {7939, 7947}}, {2, {7940, 7948}}, {2, {7941, 7949}}, {2, {7942, 7950}}, {2, {7943, 7951}}, {2, {7952, 7960}}, {2, {7953, 7961}}, {2, {7954, 7962}}, {2, {7955, 7963}}, {2, {7956, 7964}}, {2, {7957, 7965}}, {2, {7952, 7960}}, {2, {7953, 7961}}, {2, {7954, 7962}}, {2, {7955, 7963}}, {2, {7956, 7964}}, {2, {7957, 7965}}, {2, {7968, 7976}}, {2, {7969, 7977}}, {2, {7970, 7978}}, {2, {7971, 7979}}, {2, {7972, 7980}}, {2, {7973, 7981}}, {2, {7974, 7982}}, {2, {7975, 7983}}, {2, {7968, 7976}}, {2, {7969, 7977}}, {2, {7970, 7978}}, {2, {7971, 7979}}, {2, {7972, 7980}}, {2, {7973, 7981}}, {2, {7974, 7982}}, {2, {7975, 7983}}, {2, {7984, 7992}}, {2, {7985, 7993}}, {2, {7986, 7994}}, {2, {7987, 7995}}, {2, {7988, 7996}}, {2, {7989, 7997}}, {2, {7990, 7998}}, {2, {7991, 7999}}, {2, {7984, 7992}}, {2, {7985, 7993}}, {2, {7986, 7994}}, {2, {7987, 7995}}, {2, {7988, 7996}}, {2, {7989, 7997}}, {2, {7990, 7998}}, {2, {7991, 7999}}, {2, {8000, 8008}}, {2, {8001, 8009}}, {2, {8002, 8010}}, {2, {8003, 8011}}, {2, {8004, 8012}}, {2, {8005, 8013}}, {2, {8000, 8008}}, {2, {8001, 8009}}, {2, {8002, 8010}}, {2, {8003, 8011}}, {2, {8004, 8012}}, {2, {8005, 8013}}, {2, {8017, 8025}}, {2, {8019, 8027}}, {2, {8021, 8029}}, {2, {8023, 8031}}, {2, {8017, 8025}}, {2, {8019, 8027}}, {2, {8021, 8029}}, {2, {8023, 8031}}, {2, {8032, 8040}}, {2, {8033, 8041}}, {2, {8034, 8042}}, {2, {8035, 8043}}, {2, {8036, 8044}}, {2, {8037, 8045}}, {2, {8038, 8046}}, {2, {8039, 8047}}, {2, {8032, 8040}}, {2, {8033, 8041}}, {2, {8034, 8042}}, {2, {8035, 8043}}, {2, {8036, 8044}}, {2, {8037, 8045}}, {2, {8038, 8046}}, {2, {8039, 8047}}, {2, {8048, 8122}}, {2, {8049, 8123}}, {2, {8050, 8136}}, {2, {8051, 8137}}, {2, {8052, 8138}}, {2, {8053, 8139}}, {2, {8054, 8154}}, {2, {8055, 8155}}, {2, {8056, 8184}}, {2, {8057, 8185}}, {2, {8058, 8170}}, {2, {8059, 8171}}, {2, {8060, 8186}}, {2, {8061, 8187}}, {2, {8112, 8120}}, {2, {8113, 8121}}, {2, {8112, 8120}}, {2, {8113, 8121}}, {2, {8048, 8122}}, {2, {8049, 8123}}, {4, {837, 921, 953, 8126}}, {2, {8050, 8136}}, {2, {8051, 8137}}, {2, {8052, 8138}}, {2, {8053, 8139}}, {2, {8144, 8152}}, {2, {8145, 8153}}, {2, {8144, 8152}}, {2, {8145, 8153}}, {2, {8054, 8154}}, {2, {8055, 8155}}, {2, {8160, 8168}}, {2, {8161, 8169}}, {2, {8165, 8172}}, {2, {8160, 8168}}, {2, {8161, 8169}}, {2, {8058, 8170}}, {2, {8059, 8171}}, {2, {8165, 8172}}, {2, {8056, 8184}}, {2, {8057, 8185}}, {2, {8060, 8186}}, {2, {8061, 8187}}, {2, {8498, 8526}}, {2, {8498, 8526}}, {2, {8544, 8560}}, {2, {8545, 8561}}, {2, {8546, 8562}}, {2, {8547, 8563}}, {2, {8548, 8564}}, {2, {8549, 8565}}, {2, {8550, 8566}}, {2, {8551, 8567}}, {2, {8552, 8568}}, {2, {8553, 8569}}, {2, {8554, 8570}}, {2, {8555, 8571}}, {2, {8556, 8572}}, {2, {8557, 8573}}, {2, {8558, 8574}}, {2, {8559, 8575}}, {2, {8544, 8560}}, {2, {8545, 8561}}, {2, {8546, 8562}}, {2, {8547, 8563}}, {2, {8548, 8564}}, {2, {8549, 8565}}, {2, {8550, 8566}}, {2, {8551, 8567}}, {2, {8552, 8568}}, {2, {8553, 8569}}, {2, {8554, 8570}}, {2, {8555, 8571}}, {2, {8556, 8572}}, {2, {8557, 8573}}, {2, {8558, 8574}}, {2, {8559, 8575}}, {2, {8579, 8580}}, {2, {8579, 8580}}, {2, {9398, 9424}}, {2, {9399, 9425}}, {2, {9400, 9426}}, {2, {9401, 9427}}, {2, {9402, 9428}}, {2, {9403, 9429}}, {2, {9404, 9430}}, {2, {9405, 9431}}, {2, {9406, 9432}}, {2, {9407, 9433}}, {2, {9408, 9434}}, {2, {9409, 9435}}, {2, {9410, 9436}}, {2, {9411, 9437}}, {2, {9412, 9438}}, {2, {9413, 9439}}, {2, {9414, 9440}}, {2, {9415, 9441}}, {2, {9416, 9442}}, {2, {9417, 9443}}, {2, {9418, 9444}}, {2, {9419, 9445}}, {2, {9420, 9446}}, {2, {9421, 9447}}, {2, {9422, 9448}}, {2, {9423, 9449}}, {2, {9398, 9424}}, {2, {9399, 9425}}, {2, {9400, 9426}}, {2, {9401, 9427}}, {2, {9402, 9428}}, {2, {9403, 9429}}, {2, {9404, 9430}}, {2, {9405, 9431}}, {2, {9406, 9432}}, {2, {9407, 9433}}, {2, {9408, 9434}}, {2, {9409, 9435}}, {2, {9410, 9436}}, {2, {9411, 9437}}, {2, {9412, 9438}}, {2, {9413, 9439}}, {2, {9414, 9440}}, {2, {9415, 9441}}, {2, {9416, 9442}}, {2, {9417, 9443}}, {2, {9418, 9444}}, {2, {9419, 9445}}, {2, {9420, 9446}}, {2, {9421, 9447}}, {2, {9422, 9448}}, {2, {9423, 9449}}, {2, {11264, 11312}}, {2, {11265, 11313}}, {2, {11266, 11314}}, {2, {11267, 11315}}, {2, {11268, 11316}}, {2, {11269, 11317}}, {2, {11270, 11318}}, {2, {11271, 11319}}, {2, {11272, 11320}}, {2, {11273, 11321}}, {2, {11274, 11322}}, {2, {11275, 11323}}, {2, {11276, 11324}}, {2, {11277, 11325}}, {2, {11278, 11326}}, {2, {11279, 11327}}, {2, {11280, 11328}}, {2, {11281, 11329}}, {2, {11282, 11330}}, {2, {11283, 11331}}, {2, {11284, 11332}}, {2, {11285, 11333}}, {2, {11286, 11334}}, {2, {11287, 11335}}, {2, {11288, 11336}}, {2, {11289, 11337}}, {2, {11290, 11338}}, {2, {11291, 11339}}, {2, {11292, 11340}}, {2, {11293, 11341}}, {2, {11294, 11342}}, {2, {11295, 11343}}, {2, {11296, 11344}}, {2, {11297, 11345}}, {2, {11298, 11346}}, {2, {11299, 11347}}, {2, {11300, 11348}}, {2, {11301, 11349}}, {2, {11302, 11350}}, {2, {11303, 11351}}, {2, {11304, 11352}}, {2, {11305, 11353}}, {2, {11306, 11354}}, {2, {11307, 11355}}, {2, {11308, 11356}}, {2, {11309, 11357}}, {2, {11310, 11358}}, {2, {11264, 11312}}, {2, {11265, 11313}}, {2, {11266, 11314}}, {2, {11267, 11315}}, {2, {11268, 11316}}, {2, {11269, 11317}}, {2, {11270, 11318}}, {2, {11271, 11319}}, {2, {11272, 11320}}, {2, {11273, 11321}}, {2, {11274, 11322}}, {2, {11275, 11323}}, {2, {11276, 11324}}, {2, {11277, 11325}}, {2, {11278, 11326}}, {2, {11279, 11327}}, {2, {11280, 11328}}, {2, {11281, 11329}}, {2, {11282, 11330}}, {2, {11283, 11331}}, {2, {11284, 11332}}, {2, {11285, 11333}}, {2, {11286, 11334}}, {2, {11287, 11335}}, {2, {11288, 11336}}, {2, {11289, 11337}}, {2, {11290, 11338}}, {2, {11291, 11339}}, {2, {11292, 11340}}, {2, {11293, 11341}}, {2, {11294, 11342}}, {2, {11295, 11343}}, {2, {11296, 11344}}, {2, {11297, 11345}}, {2, {11298, 11346}}, {2, {11299, 11347}}, {2, {11300, 11348}}, {2, {11301, 11349}}, {2, {11302, 11350}}, {2, {11303, 11351}}, {2, {11304, 11352}}, {2, {11305, 11353}}, {2, {11306, 11354}}, {2, {11307, 11355}}, {2, {11308, 11356}}, {2, {11309, 11357}}, {2, {11310, 11358}}, {2, {11360, 11361}}, {2, {11360, 11361}}, {2, {619, 11362}}, {2, {7549, 11363}}, {2, {637, 11364}}, {2, {570, 11365}}, {2, {574, 11366}}, {2, {11367, 11368}}, {2, {11367, 11368}}, {2, {11369, 11370}}, {2, {11369, 11370}}, {2, {11371, 11372}}, {2, {11371, 11372}}, {2, {11381, 11382}}, {2, {11381, 11382}}, {2, {11392, 11393}}, {2, {11392, 11393}}, {2, {11394, 11395}}, {2, {11394, 11395}}, {2, {11396, 11397}}, {2, {11396, 11397}}, {2, {11398, 11399}}, {2, {11398, 11399}}, {2, {11400, 11401}}, {2, {11400, 11401}}, {2, {11402, 11403}}, {2, {11402, 11403}}, {2, {11404, 11405}}, {2, {11404, 11405}}, {2, {11406, 11407}}, {2, {11406, 11407}}, {2, {11408, 11409}}, {2, {11408, 11409}}, {2, {11410, 11411}}, {2, {11410, 11411}}, {2, {11412, 11413}}, {2, {11412, 11413}}, {2, {11414, 11415}}, {2, {11414, 11415}}, {2, {11416, 11417}}, {2, {11416, 11417}}, {2, {11418, 11419}}, {2, {11418, 11419}}, {2, {11420, 11421}}, {2, {11420, 11421}}, {2, {11422, 11423}}, {2, {11422, 11423}}, {2, {11424, 11425}}, {2, {11424, 11425}}, {2, {11426, 11427}}, {2, {11426, 11427}}, {2, {11428, 11429}}, {2, {11428, 11429}}, {2, {11430, 11431}}, {2, {11430, 11431}}, {2, {11432, 11433}}, {2, {11432, 11433}}, {2, {11434, 11435}}, {2, {11434, 11435}}, {2, {11436, 11437}}, {2, {11436, 11437}}, {2, {11438, 11439}}, {2, {11438, 11439}}, {2, {11440, 11441}}, {2, {11440, 11441}}, {2, {11442, 11443}}, {2, {11442, 11443}}, {2, {11444, 11445}}, {2, {11444, 11445}}, {2, {11446, 11447}}, {2, {11446, 11447}}, {2, {11448, 11449}}, {2, {11448, 11449}}, {2, {11450, 11451}}, {2, {11450, 11451}}, {2, {11452, 11453}}, {2, {11452, 11453}}, {2, {11454, 11455}}, {2, {11454, 11455}}, {2, {11456, 11457}}, {2, {11456, 11457}}, {2, {11458, 11459}}, {2, {11458, 11459}}, {2, {11460, 11461}}, {2, {11460, 11461}}, {2, {11462, 11463}}, {2, {11462, 11463}}, {2, {11464, 11465}}, {2, {11464, 11465}}, {2, {11466, 11467}}, {2, {11466, 11467}}, {2, {11468, 11469}}, {2, {11468, 11469}}, {2, {11470, 11471}}, {2, {11470, 11471}}, {2, {11472, 11473}}, {2, {11472, 11473}}, {2, {11474, 11475}}, {2, {11474, 11475}}, {2, {11476, 11477}}, {2, {11476, 11477}}, {2, {11478, 11479}}, {2, {11478, 11479}}, {2, {11480, 11481}}, {2, {11480, 11481}}, {2, {11482, 11483}}, {2, {11482, 11483}}, {2, {11484, 11485}}, {2, {11484, 11485}}, {2, {11486, 11487}}, {2, {11486, 11487}}, {2, {11488, 11489}}, {2, {11488, 11489}}, {2, {11490, 11491}}, {2, {11490, 11491}}, {2, {4256, 11520}}, {2, {4257, 11521}}, {2, {4258, 11522}}, {2, {4259, 11523}}, {2, {4260, 11524}}, {2, {4261, 11525}}, {2, {4262, 11526}}, {2, {4263, 11527}}, {2, {4264, 11528}}, {2, {4265, 11529}}, {2, {4266, 11530}}, {2, {4267, 11531}}, {2, {4268, 11532}}, {2, {4269, 11533}}, {2, {4270, 11534}}, {2, {4271, 11535}}, {2, {4272, 11536}}, {2, {4273, 11537}}, {2, {4274, 11538}}, {2, {4275, 11539}}, {2, {4276, 11540}}, {2, {4277, 11541}}, {2, {4278, 11542}}, {2, {4279, 11543}}, {2, {4280, 11544}}, {2, {4281, 11545}}, {2, {4282, 11546}}, {2, {4283, 11547}}, {2, {4284, 11548}}, {2, {4285, 11549}}, {2, {4286, 11550}}, {2, {4287, 11551}}, {2, {4288, 11552}}, {2, {4289, 11553}}, {2, {4290, 11554}}, {2, {4291, 11555}}, {2, {4292, 11556}}, {2, {4293, 11557}}, {0, {0}} }; // NOLINT
+static const uint16_t kEcma262UnCanonicalizeTable0Size = 1656;
+static const int32_t kEcma262UnCanonicalizeTable0[3312] = { 65, 1, 66, 5, 67, 9, 68, 13, 69, 17, 70, 21, 71, 25, 72, 29, 73, 33, 74, 37, 75, 41, 76, 45, 77, 49, 78, 53, 79, 57, 80, 61, 81, 65, 82, 69, 83, 73, 84, 77, 85, 81, 86, 85, 87, 89, 88, 93, 89, 97, 90, 101, 97, 105, 98, 109, 99, 113, 100, 117, 101, 121, 102, 125, 103, 129, 104, 133, 105, 137, 106, 141, 107, 145, 108, 149, 109, 153, 110, 157, 111, 161, 112, 165, 113, 169, 114, 173, 115, 177, 116, 181, 117, 185, 118, 189, 119, 193, 120, 197, 121, 201, 122, 205, 181, 209, 192, 213, 193, 217, 194, 221, 195, 225, 196, 229, 197, 233, 198, 237, 199, 241, 200, 245, 201, 249, 202, 253, 203, 257, 204, 261, 205, 265, 206, 269, 207, 273, 208, 277, 209, 281, 210, 285, 211, 289, 212, 293, 213, 297, 214, 301, 216, 305, 217, 309, 218, 313, 219, 317, 220, 321, 221, 325, 222, 329, 224, 333, 225, 337, 226, 341, 227, 345, 228, 349, 229, 353, 230, 357, 231, 361, 232, 365, 233, 369, 234, 373, 235, 377, 236, 381, 237, 385, 238, 389, 239, 393, 240, 397, 241, 401, 242, 405, 243, 409, 244, 413, 245, 417, 246, 421, 248, 425, 249, 429, 250, 433, 251, 437, 252, 441, 253, 445, 254, 449, 255, 453, 256, 457, 257, 461, 258, 465, 259, 469, 260, 473, 261, 477, 262, 481, 263, 485, 264, 489, 265, 493, 266, 497, 267, 501, 268, 505, 269, 509, 270, 513, 271, 517, 272, 521, 273, 525, 274, 529, 275, 533, 276, 537, 277, 541, 278, 545, 279, 549, 280, 553, 281, 557, 282, 561, 283, 565, 284, 569, 285, 573, 286, 577, 287, 581, 288, 585, 289, 589, 290, 593, 291, 597, 292, 601, 293, 605, 294, 609, 295, 613, 296, 617, 297, 621, 298, 625, 299, 629, 300, 633, 301, 637, 302, 641, 303, 645, 306, 649, 307, 653, 308, 657, 309, 661, 310, 665, 311, 669, 313, 673, 314, 677, 315, 681, 316, 685, 317, 689, 318, 693, 319, 697, 320, 701, 321, 705, 322, 709, 323, 713, 324, 717, 325, 721, 326, 725, 327, 729, 328, 733, 330, 737, 331, 741, 332, 745, 333, 749, 334, 753, 335, 757, 336, 761, 337, 765, 338, 769, 339, 773, 340, 777, 341, 781, 342, 785, 343, 789, 344, 793, 345, 797, 346, 801, 347, 805, 348, 809, 349, 813, 350, 817, 351, 821, 352, 825, 353, 829, 354, 833, 355, 837, 356, 841, 357, 845, 358, 849, 359, 853, 360, 857, 361, 861, 362, 865, 363, 869, 364, 873, 365, 877, 366, 881, 367, 885, 368, 889, 369, 893, 370, 897, 371, 901, 372, 905, 373, 909, 374, 913, 375, 917, 376, 921, 377, 925, 378, 929, 379, 933, 380, 937, 381, 941, 382, 945, 384, 949, 385, 953, 386, 957, 387, 961, 388, 965, 389, 969, 390, 973, 391, 977, 392, 981, 393, 985, 394, 989, 395, 993, 396, 997, 398, 1001, 399, 1005, 400, 1009, 401, 1013, 402, 1017, 403, 1021, 404, 1025, 405, 1029, 406, 1033, 407, 1037, 408, 1041, 409, 1045, 410, 1049, 412, 1053, 413, 1057, 414, 1061, 415, 1065, 416, 1069, 417, 1073, 418, 1077, 419, 1081, 420, 1085, 421, 1089, 422, 1093, 423, 1097, 424, 1101, 425, 1105, 428, 1109, 429, 1113, 430, 1117, 431, 1121, 432, 1125, 433, 1129, 434, 1133, 435, 1137, 436, 1141, 437, 1145, 438, 1149, 439, 1153, 440, 1157, 441, 1161, 444, 1165, 445, 1169, 447, 1173, 452, 1177, 453, 1181, 454, 1185, 455, 1189, 456, 1193, 457, 1197, 458, 1201, 459, 1205, 460, 1209, 461, 1213, 462, 1217, 463, 1221, 464, 1225, 465, 1229, 466, 1233, 467, 1237, 468, 1241, 469, 1245, 470, 1249, 471, 1253, 472, 1257, 473, 1261, 474, 1265, 475, 1269, 476, 1273, 477, 1277, 478, 1281, 479, 1285, 480, 1289, 481, 1293, 482, 1297, 483, 1301, 484, 1305, 485, 1309, 486, 1313, 487, 1317, 488, 1321, 489, 1325, 490, 1329, 491, 1333, 492, 1337, 493, 1341, 494, 1345, 495, 1349, 497, 1353, 498, 1357, 499, 1361, 500, 1365, 501, 1369, 502, 1373, 503, 1377, 504, 1381, 505, 1385, 506, 1389, 507, 1393, 508, 1397, 509, 1401, 510, 1405, 511, 1409, 512, 1413, 513, 1417, 514, 1421, 515, 1425, 516, 1429, 517, 1433, 518, 1437, 519, 1441, 520, 1445, 521, 1449, 522, 1453, 523, 1457, 524, 1461, 525, 1465, 526, 1469, 527, 1473, 528, 1477, 529, 1481, 530, 1485, 531, 1489, 532, 1493, 533, 1497, 534, 1501, 535, 1505, 536, 1509, 537, 1513, 538, 1517, 539, 1521, 540, 1525, 541, 1529, 542, 1533, 543, 1537, 544, 1541, 546, 1545, 547, 1549, 548, 1553, 549, 1557, 550, 1561, 551, 1565, 552, 1569, 553, 1573, 554, 1577, 555, 1581, 556, 1585, 557, 1589, 558, 1593, 559, 1597, 560, 1601, 561, 1605, 562, 1609, 563, 1613, 570, 1617, 571, 1621, 572, 1625, 573, 1629, 574, 1633, 577, 1637, 578, 1641, 579, 1645, 580, 1649, 581, 1653, 582, 1657, 583, 1661, 584, 1665, 585, 1669, 586, 1673, 587, 1677, 588, 1681, 589, 1685, 590, 1689, 591, 1693, 595, 1697, 596, 1701, 598, 1705, 599, 1709, 601, 1713, 603, 1717, 608, 1721, 611, 1725, 616, 1729, 617, 1733, 619, 1737, 623, 1741, 626, 1745, 629, 1749, 637, 1753, 640, 1757, 643, 1761, 648, 1765, 649, 1769, 650, 1773, 651, 1777, 652, 1781, 658, 1785, 837, 1789, 891, 1793, 892, 1797, 893, 1801, 902, 1805, 904, 1809, 905, 1813, 906, 1817, 908, 1821, 910, 1825, 911, 1829, 913, 1833, 914, 1837, 915, 1841, 916, 1845, 917, 1849, 918, 1853, 919, 1857, 920, 1861, 921, 1865, 922, 1869, 923, 1873, 924, 1877, 925, 1881, 926, 1885, 927, 1889, 928, 1893, 929, 1897, 931, 1901, 932, 1905, 933, 1909, 934, 1913, 935, 1917, 936, 1921, 937, 1925, 938, 1929, 939, 1933, 940, 1937, 941, 1941, 942, 1945, 943, 1949, 945, 1953, 946, 1957, 947, 1961, 948, 1965, 949, 1969, 950, 1973, 951, 1977, 952, 1981, 953, 1985, 954, 1989, 955, 1993, 956, 1997, 957, 2001, 958, 2005, 959, 2009, 960, 2013, 961, 2017, 962, 2021, 963, 2025, 964, 2029, 965, 2033, 966, 2037, 967, 2041, 968, 2045, 969, 2049, 970, 2053, 971, 2057, 972, 2061, 973, 2065, 974, 2069, 976, 2073, 977, 2077, 981, 2081, 982, 2085, 984, 2089, 985, 2093, 986, 2097, 987, 2101, 988, 2105, 989, 2109, 990, 2113, 991, 2117, 992, 2121, 993, 2125, 994, 2129, 995, 2133, 996, 2137, 997, 2141, 998, 2145, 999, 2149, 1000, 2153, 1001, 2157, 1002, 2161, 1003, 2165, 1004, 2169, 1005, 2173, 1006, 2177, 1007, 2181, 1008, 2185, 1009, 2189, 1010, 2193, 1013, 2197, 1015, 2201, 1016, 2205, 1017, 2209, 1018, 2213, 1019, 2217, 1021, 2221, 1022, 2225, 1023, 2229, 1024, 2233, 1025, 2237, 1026, 2241, 1027, 2245, 1028, 2249, 1029, 2253, 1030, 2257, 1031, 2261, 1032, 2265, 1033, 2269, 1034, 2273, 1035, 2277, 1036, 2281, 1037, 2285, 1038, 2289, 1039, 2293, 1040, 2297, 1041, 2301, 1042, 2305, 1043, 2309, 1044, 2313, 1045, 2317, 1046, 2321, 1047, 2325, 1048, 2329, 1049, 2333, 1050, 2337, 1051, 2341, 1052, 2345, 1053, 2349, 1054, 2353, 1055, 2357, 1056, 2361, 1057, 2365, 1058, 2369, 1059, 2373, 1060, 2377, 1061, 2381, 1062, 2385, 1063, 2389, 1064, 2393, 1065, 2397, 1066, 2401, 1067, 2405, 1068, 2409, 1069, 2413, 1070, 2417, 1071, 2421, 1072, 2425, 1073, 2429, 1074, 2433, 1075, 2437, 1076, 2441, 1077, 2445, 1078, 2449, 1079, 2453, 1080, 2457, 1081, 2461, 1082, 2465, 1083, 2469, 1084, 2473, 1085, 2477, 1086, 2481, 1087, 2485, 1088, 2489, 1089, 2493, 1090, 2497, 1091, 2501, 1092, 2505, 1093, 2509, 1094, 2513, 1095, 2517, 1096, 2521, 1097, 2525, 1098, 2529, 1099, 2533, 1100, 2537, 1101, 2541, 1102, 2545, 1103, 2549, 1104, 2553, 1105, 2557, 1106, 2561, 1107, 2565, 1108, 2569, 1109, 2573, 1110, 2577, 1111, 2581, 1112, 2585, 1113, 2589, 1114, 2593, 1115, 2597, 1116, 2601, 1117, 2605, 1118, 2609, 1119, 2613, 1120, 2617, 1121, 2621, 1122, 2625, 1123, 2629, 1124, 2633, 1125, 2637, 1126, 2641, 1127, 2645, 1128, 2649, 1129, 2653, 1130, 2657, 1131, 2661, 1132, 2665, 1133, 2669, 1134, 2673, 1135, 2677, 1136, 2681, 1137, 2685, 1138, 2689, 1139, 2693, 1140, 2697, 1141, 2701, 1142, 2705, 1143, 2709, 1144, 2713, 1145, 2717, 1146, 2721, 1147, 2725, 1148, 2729, 1149, 2733, 1150, 2737, 1151, 2741, 1152, 2745, 1153, 2749, 1162, 2753, 1163, 2757, 1164, 2761, 1165, 2765, 1166, 2769, 1167, 2773, 1168, 2777, 1169, 2781, 1170, 2785, 1171, 2789, 1172, 2793, 1173, 2797, 1174, 2801, 1175, 2805, 1176, 2809, 1177, 2813, 1178, 2817, 1179, 2821, 1180, 2825, 1181, 2829, 1182, 2833, 1183, 2837, 1184, 2841, 1185, 2845, 1186, 2849, 1187, 2853, 1188, 2857, 1189, 2861, 1190, 2865, 1191, 2869, 1192, 2873, 1193, 2877, 1194, 2881, 1195, 2885, 1196, 2889, 1197, 2893, 1198, 2897, 1199, 2901, 1200, 2905, 1201, 2909, 1202, 2913, 1203, 2917, 1204, 2921, 1205, 2925, 1206, 2929, 1207, 2933, 1208, 2937, 1209, 2941, 1210, 2945, 1211, 2949, 1212, 2953, 1213, 2957, 1214, 2961, 1215, 2965, 1216, 2969, 1217, 2973, 1218, 2977, 1219, 2981, 1220, 2985, 1221, 2989, 1222, 2993, 1223, 2997, 1224, 3001, 1225, 3005, 1226, 3009, 1227, 3013, 1228, 3017, 1229, 3021, 1230, 3025, 1231, 3029, 1232, 3033, 1233, 3037, 1234, 3041, 1235, 3045, 1236, 3049, 1237, 3053, 1238, 3057, 1239, 3061, 1240, 3065, 1241, 3069, 1242, 3073, 1243, 3077, 1244, 3081, 1245, 3085, 1246, 3089, 1247, 3093, 1248, 3097, 1249, 3101, 1250, 3105, 1251, 3109, 1252, 3113, 1253, 3117, 1254, 3121, 1255, 3125, 1256, 3129, 1257, 3133, 1258, 3137, 1259, 3141, 1260, 3145, 1261, 3149, 1262, 3153, 1263, 3157, 1264, 3161, 1265, 3165, 1266, 3169, 1267, 3173, 1268, 3177, 1269, 3181, 1270, 3185, 1271, 3189, 1272, 3193, 1273, 3197, 1274, 3201, 1275, 3205, 1276, 3209, 1277, 3213, 1278, 3217, 1279, 3221, 1280, 3225, 1281, 3229, 1282, 3233, 1283, 3237, 1284, 3241, 1285, 3245, 1286, 3249, 1287, 3253, 1288, 3257, 1289, 3261, 1290, 3265, 1291, 3269, 1292, 3273, 1293, 3277, 1294, 3281, 1295, 3285, 1296, 3289, 1297, 3293, 1298, 3297, 1299, 3301, 1329, 3305, 1330, 3309, 1331, 3313, 1332, 3317, 1333, 3321, 1334, 3325, 1335, 3329, 1336, 3333, 1337, 3337, 1338, 3341, 1339, 3345, 1340, 3349, 1341, 3353, 1342, 3357, 1343, 3361, 1344, 3365, 1345, 3369, 1346, 3373, 1347, 3377, 1348, 3381, 1349, 3385, 1350, 3389, 1351, 3393, 1352, 3397, 1353, 3401, 1354, 3405, 1355, 3409, 1356, 3413, 1357, 3417, 1358, 3421, 1359, 3425, 1360, 3429, 1361, 3433, 1362, 3437, 1363, 3441, 1364, 3445, 1365, 3449, 1366, 3453, 1377, 3457, 1378, 3461, 1379, 3465, 1380, 3469, 1381, 3473, 1382, 3477, 1383, 3481, 1384, 3485, 1385, 3489, 1386, 3493, 1387, 3497, 1388, 3501, 1389, 3505, 1390, 3509, 1391, 3513, 1392, 3517, 1393, 3521, 1394, 3525, 1395, 3529, 1396, 3533, 1397, 3537, 1398, 3541, 1399, 3545, 1400, 3549, 1401, 3553, 1402, 3557, 1403, 3561, 1404, 3565, 1405, 3569, 1406, 3573, 1407, 3577, 1408, 3581, 1409, 3585, 1410, 3589, 1411, 3593, 1412, 3597, 1413, 3601, 1414, 3605, 4256, 3609, 4257, 3613, 4258, 3617, 4259, 3621, 4260, 3625, 4261, 3629, 4262, 3633, 4263, 3637, 4264, 3641, 4265, 3645, 4266, 3649, 4267, 3653, 4268, 3657, 4269, 3661, 4270, 3665, 4271, 3669, 4272, 3673, 4273, 3677, 4274, 3681, 4275, 3685, 4276, 3689, 4277, 3693, 4278, 3697, 4279, 3701, 4280, 3705, 4281, 3709, 4282, 3713, 4283, 3717, 4284, 3721, 4285, 3725, 4286, 3729, 4287, 3733, 4288, 3737, 4289, 3741, 4290, 3745, 4291, 3749, 4292, 3753, 4293, 3757, 7549, 3761, 7680, 3765, 7681, 3769, 7682, 3773, 7683, 3777, 7684, 3781, 7685, 3785, 7686, 3789, 7687, 3793, 7688, 3797, 7689, 3801, 7690, 3805, 7691, 3809, 7692, 3813, 7693, 3817, 7694, 3821, 7695, 3825, 7696, 3829, 7697, 3833, 7698, 3837, 7699, 3841, 7700, 3845, 7701, 3849, 7702, 3853, 7703, 3857, 7704, 3861, 7705, 3865, 7706, 3869, 7707, 3873, 7708, 3877, 7709, 3881, 7710, 3885, 7711, 3889, 7712, 3893, 7713, 3897, 7714, 3901, 7715, 3905, 7716, 3909, 7717, 3913, 7718, 3917, 7719, 3921, 7720, 3925, 7721, 3929, 7722, 3933, 7723, 3937, 7724, 3941, 7725, 3945, 7726, 3949, 7727, 3953, 7728, 3957, 7729, 3961, 7730, 3965, 7731, 3969, 7732, 3973, 7733, 3977, 7734, 3981, 7735, 3985, 7736, 3989, 7737, 3993, 7738, 3997, 7739, 4001, 7740, 4005, 7741, 4009, 7742, 4013, 7743, 4017, 7744, 4021, 7745, 4025, 7746, 4029, 7747, 4033, 7748, 4037, 7749, 4041, 7750, 4045, 7751, 4049, 7752, 4053, 7753, 4057, 7754, 4061, 7755, 4065, 7756, 4069, 7757, 4073, 7758, 4077, 7759, 4081, 7760, 4085, 7761, 4089, 7762, 4093, 7763, 4097, 7764, 4101, 7765, 4105, 7766, 4109, 7767, 4113, 7768, 4117, 7769, 4121, 7770, 4125, 7771, 4129, 7772, 4133, 7773, 4137, 7774, 4141, 7775, 4145, 7776, 4149, 7777, 4153, 7778, 4157, 7779, 4161, 7780, 4165, 7781, 4169, 7782, 4173, 7783, 4177, 7784, 4181, 7785, 4185, 7786, 4189, 7787, 4193, 7788, 4197, 7789, 4201, 7790, 4205, 7791, 4209, 7792, 4213, 7793, 4217, 7794, 4221, 7795, 4225, 7796, 4229, 7797, 4233, 7798, 4237, 7799, 4241, 7800, 4245, 7801, 4249, 7802, 4253, 7803, 4257, 7804, 4261, 7805, 4265, 7806, 4269, 7807, 4273, 7808, 4277, 7809, 4281, 7810, 4285, 7811, 4289, 7812, 4293, 7813, 4297, 7814, 4301, 7815, 4305, 7816, 4309, 7817, 4313, 7818, 4317, 7819, 4321, 7820, 4325, 7821, 4329, 7822, 4333, 7823, 4337, 7824, 4341, 7825, 4345, 7826, 4349, 7827, 4353, 7828, 4357, 7829, 4361, 7835, 4365, 7840, 4369, 7841, 4373, 7842, 4377, 7843, 4381, 7844, 4385, 7845, 4389, 7846, 4393, 7847, 4397, 7848, 4401, 7849, 4405, 7850, 4409, 7851, 4413, 7852, 4417, 7853, 4421, 7854, 4425, 7855, 4429, 7856, 4433, 7857, 4437, 7858, 4441, 7859, 4445, 7860, 4449, 7861, 4453, 7862, 4457, 7863, 4461, 7864, 4465, 7865, 4469, 7866, 4473, 7867, 4477, 7868, 4481, 7869, 4485, 7870, 4489, 7871, 4493, 7872, 4497, 7873, 4501, 7874, 4505, 7875, 4509, 7876, 4513, 7877, 4517, 7878, 4521, 7879, 4525, 7880, 4529, 7881, 4533, 7882, 4537, 7883, 4541, 7884, 4545, 7885, 4549, 7886, 4553, 7887, 4557, 7888, 4561, 7889, 4565, 7890, 4569, 7891, 4573, 7892, 4577, 7893, 4581, 7894, 4585, 7895, 4589, 7896, 4593, 7897, 4597, 7898, 4601, 7899, 4605, 7900, 4609, 7901, 4613, 7902, 4617, 7903, 4621, 7904, 4625, 7905, 4629, 7906, 4633, 7907, 4637, 7908, 4641, 7909, 4645, 7910, 4649, 7911, 4653, 7912, 4657, 7913, 4661, 7914, 4665, 7915, 4669, 7916, 4673, 7917, 4677, 7918, 4681, 7919, 4685, 7920, 4689, 7921, 4693, 7922, 4697, 7923, 4701, 7924, 4705, 7925, 4709, 7926, 4713, 7927, 4717, 7928, 4721, 7929, 4725, 7936, 4729, 7937, 4733, 7938, 4737, 7939, 4741, 7940, 4745, 7941, 4749, 7942, 4753, 7943, 4757, 7944, 4761, 7945, 4765, 7946, 4769, 7947, 4773, 7948, 4777, 7949, 4781, 7950, 4785, 7951, 4789, 7952, 4793, 7953, 4797, 7954, 4801, 7955, 4805, 7956, 4809, 7957, 4813, 7960, 4817, 7961, 4821, 7962, 4825, 7963, 4829, 7964, 4833, 7965, 4837, 7968, 4841, 7969, 4845, 7970, 4849, 7971, 4853, 7972, 4857, 7973, 4861, 7974, 4865, 7975, 4869, 7976, 4873, 7977, 4877, 7978, 4881, 7979, 4885, 7980, 4889, 7981, 4893, 7982, 4897, 7983, 4901, 7984, 4905, 7985, 4909, 7986, 4913, 7987, 4917, 7988, 4921, 7989, 4925, 7990, 4929, 7991, 4933, 7992, 4937, 7993, 4941, 7994, 4945, 7995, 4949, 7996, 4953, 7997, 4957, 7998, 4961, 7999, 4965, 8000, 4969, 8001, 4973, 8002, 4977, 8003, 4981, 8004, 4985, 8005, 4989, 8008, 4993, 8009, 4997, 8010, 5001, 8011, 5005, 8012, 5009, 8013, 5013, 8017, 5017, 8019, 5021, 8021, 5025, 8023, 5029, 8025, 5033, 8027, 5037, 8029, 5041, 8031, 5045, 8032, 5049, 8033, 5053, 8034, 5057, 8035, 5061, 8036, 5065, 8037, 5069, 8038, 5073, 8039, 5077, 8040, 5081, 8041, 5085, 8042, 5089, 8043, 5093, 8044, 5097, 8045, 5101, 8046, 5105, 8047, 5109, 8048, 5113, 8049, 5117, 8050, 5121, 8051, 5125, 8052, 5129, 8053, 5133, 8054, 5137, 8055, 5141, 8056, 5145, 8057, 5149, 8058, 5153, 8059, 5157, 8060, 5161, 8061, 5165, 8112, 5169, 8113, 5173, 8120, 5177, 8121, 5181, 8122, 5185, 8123, 5189, 8126, 5193, 8136, 5197, 8137, 5201, 8138, 5205, 8139, 5209, 8144, 5213, 8145, 5217, 8152, 5221, 8153, 5225, 8154, 5229, 8155, 5233, 8160, 5237, 8161, 5241, 8165, 5245, 8168, 5249, 8169, 5253, 8170, 5257, 8171, 5261, 8172, 5265, 8184, 5269, 8185, 5273, 8186, 5277, 8187, 5281, 8498, 5285, 8526, 5289, 8544, 5293, 8545, 5297, 8546, 5301, 8547, 5305, 8548, 5309, 8549, 5313, 8550, 5317, 8551, 5321, 8552, 5325, 8553, 5329, 8554, 5333, 8555, 5337, 8556, 5341, 8557, 5345, 8558, 5349, 8559, 5353, 8560, 5357, 8561, 5361, 8562, 5365, 8563, 5369, 8564, 5373, 8565, 5377, 8566, 5381, 8567, 5385, 8568, 5389, 8569, 5393, 8570, 5397, 8571, 5401, 8572, 5405, 8573, 5409, 8574, 5413, 8575, 5417, 8579, 5421, 8580, 5425, 9398, 5429, 9399, 5433, 9400, 5437, 9401, 5441, 9402, 5445, 9403, 5449, 9404, 5453, 9405, 5457, 9406, 5461, 9407, 5465, 9408, 5469, 9409, 5473, 9410, 5477, 9411, 5481, 9412, 5485, 9413, 5489, 9414, 5493, 9415, 5497, 9416, 5501, 9417, 5505, 9418, 5509, 9419, 5513, 9420, 5517, 9421, 5521, 9422, 5525, 9423, 5529, 9424, 5533, 9425, 5537, 9426, 5541, 9427, 5545, 9428, 5549, 9429, 5553, 9430, 5557, 9431, 5561, 9432, 5565, 9433, 5569, 9434, 5573, 9435, 5577, 9436, 5581, 9437, 5585, 9438, 5589, 9439, 5593, 9440, 5597, 9441, 5601, 9442, 5605, 9443, 5609, 9444, 5613, 9445, 5617, 9446, 5621, 9447, 5625, 9448, 5629, 9449, 5633, 11264, 5637, 11265, 5641, 11266, 5645, 11267, 5649, 11268, 5653, 11269, 5657, 11270, 5661, 11271, 5665, 11272, 5669, 11273, 5673, 11274, 5677, 11275, 5681, 11276, 5685, 11277, 5689, 11278, 5693, 11279, 5697, 11280, 5701, 11281, 5705, 11282, 5709, 11283, 5713, 11284, 5717, 11285, 5721, 11286, 5725, 11287, 5729, 11288, 5733, 11289, 5737, 11290, 5741, 11291, 5745, 11292, 5749, 11293, 5753, 11294, 5757, 11295, 5761, 11296, 5765, 11297, 5769, 11298, 5773, 11299, 5777, 11300, 5781, 11301, 5785, 11302, 5789, 11303, 5793, 11304, 5797, 11305, 5801, 11306, 5805, 11307, 5809, 11308, 5813, 11309, 5817, 11310, 5821, 11312, 5825, 11313, 5829, 11314, 5833, 11315, 5837, 11316, 5841, 11317, 5845, 11318, 5849, 11319, 5853, 11320, 5857, 11321, 5861, 11322, 5865, 11323, 5869, 11324, 5873, 11325, 5877, 11326, 5881, 11327, 5885, 11328, 5889, 11329, 5893, 11330, 5897, 11331, 5901, 11332, 5905, 11333, 5909, 11334, 5913, 11335, 5917, 11336, 5921, 11337, 5925, 11338, 5929, 11339, 5933, 11340, 5937, 11341, 5941, 11342, 5945, 11343, 5949, 11344, 5953, 11345, 5957, 11346, 5961, 11347, 5965, 11348, 5969, 11349, 5973, 11350, 5977, 11351, 5981, 11352, 5985, 11353, 5989, 11354, 5993, 11355, 5997, 11356, 6001, 11357, 6005, 11358, 6009, 11360, 6013, 11361, 6017, 11362, 6021, 11363, 6025, 11364, 6029, 11365, 6033, 11366, 6037, 11367, 6041, 11368, 6045, 11369, 6049, 11370, 6053, 11371, 6057, 11372, 6061, 11381, 6065, 11382, 6069, 11392, 6073, 11393, 6077, 11394, 6081, 11395, 6085, 11396, 6089, 11397, 6093, 11398, 6097, 11399, 6101, 11400, 6105, 11401, 6109, 11402, 6113, 11403, 6117, 11404, 6121, 11405, 6125, 11406, 6129, 11407, 6133, 11408, 6137, 11409, 6141, 11410, 6145, 11411, 6149, 11412, 6153, 11413, 6157, 11414, 6161, 11415, 6165, 11416, 6169, 11417, 6173, 11418, 6177, 11419, 6181, 11420, 6185, 11421, 6189, 11422, 6193, 11423, 6197, 11424, 6201, 11425, 6205, 11426, 6209, 11427, 6213, 11428, 6217, 11429, 6221, 11430, 6225, 11431, 6229, 11432, 6233, 11433, 6237, 11434, 6241, 11435, 6245, 11436, 6249, 11437, 6253, 11438, 6257, 11439, 6261, 11440, 6265, 11441, 6269, 11442, 6273, 11443, 6277, 11444, 6281, 11445, 6285, 11446, 6289, 11447, 6293, 11448, 6297, 11449, 6301, 11450, 6305, 11451, 6309, 11452, 6313, 11453, 6317, 11454, 6321, 11455, 6325, 11456, 6329, 11457, 6333, 11458, 6337, 11459, 6341, 11460, 6345, 11461, 6349, 11462, 6353, 11463, 6357, 11464, 6361, 11465, 6365, 11466, 6369, 11467, 6373, 11468, 6377, 11469, 6381, 11470, 6385, 11471, 6389, 11472, 6393, 11473, 6397, 11474, 6401, 11475, 6405, 11476, 6409, 11477, 6413, 11478, 6417, 11479, 6421, 11480, 6425, 11481, 6429, 11482, 6433, 11483, 6437, 11484, 6441, 11485, 6445, 11486, 6449, 11487, 6453, 11488, 6457, 11489, 6461, 11490, 6465, 11491, 6469, 11520, 6473, 11521, 6477, 11522, 6481, 11523, 6485, 11524, 6489, 11525, 6493, 11526, 6497, 11527, 6501, 11528, 6505, 11529, 6509, 11530, 6513, 11531, 6517, 11532, 6521, 11533, 6525, 11534, 6529, 11535, 6533, 11536, 6537, 11537, 6541, 11538, 6545, 11539, 6549, 11540, 6553, 11541, 6557, 11542, 6561, 11543, 6565, 11544, 6569, 11545, 6573, 11546, 6577, 11547, 6581, 11548, 6585, 11549, 6589, 11550, 6593, 11551, 6597, 11552, 6601, 11553, 6605, 11554, 6609, 11555, 6613, 11556, 6617, 11557, 6621 }; // NOLINT
+static const MultiCharacterSpecialCase<4> kEcma262UnCanonicalizeMultiStrings1[] = { {2, {65313, 65345}}, {2, {65314, 65346}}, {2, {65315, 65347}}, {2, {65316, 65348}}, {2, {65317, 65349}}, {2, {65318, 65350}}, {2, {65319, 65351}}, {2, {65320, 65352}}, {2, {65321, 65353}}, {2, {65322, 65354}}, {2, {65323, 65355}}, {2, {65324, 65356}}, {2, {65325, 65357}}, {2, {65326, 65358}}, {2, {65327, 65359}}, {2, {65328, 65360}}, {2, {65329, 65361}}, {2, {65330, 65362}}, {2, {65331, 65363}}, {2, {65332, 65364}}, {2, {65333, 65365}}, {2, {65334, 65366}}, {2, {65335, 65367}}, {2, {65336, 65368}}, {2, {65337, 65369}}, {2, {65338, 65370}}, {2, {65313, 65345}}, {2, {65314, 65346}}, {2, {65315, 65347}}, {2, {65316, 65348}}, {2, {65317, 65349}}, {2, {65318, 65350}}, {2, {65319, 65351}}, {2, {65320, 65352}}, {2, {65321, 65353}}, {2, {65322, 65354}}, {2, {65323, 65355}}, {2, {65324, 65356}}, {2, {65325, 65357}}, {2, {65326, 65358}}, {2, {65327, 65359}}, {2, {65328, 65360}}, {2, {65329, 65361}}, {2, {65330, 65362}}, {2, {65331, 65363}}, {2, {65332, 65364}}, {2, {65333, 65365}}, {2, {65334, 65366}}, {2, {65335, 65367}}, {2, {65336, 65368}}, {2, {65337, 65369}}, {2, {65338, 65370}}, {0, {0}} }; // NOLINT
+static const uint16_t kEcma262UnCanonicalizeTable1Size = 52;
+static const int32_t kEcma262UnCanonicalizeTable1[104] = { 32545, 1, 32546, 5, 32547, 9, 32548, 13, 32549, 17, 32550, 21, 32551, 25, 32552, 29, 32553, 33, 32554, 37, 32555, 41, 32556, 45, 32557, 49, 32558, 53, 32559, 57, 32560, 61, 32561, 65, 32562, 69, 32563, 73, 32564, 77, 32565, 81, 32566, 85, 32567, 89, 32568, 93, 32569, 97, 32570, 101, 32577, 105, 32578, 109, 32579, 113, 32580, 117, 32581, 121, 32582, 125, 32583, 129, 32584, 133, 32585, 137, 32586, 141, 32587, 145, 32588, 149, 32589, 153, 32590, 157, 32591, 161, 32592, 165, 32593, 169, 32594, 173, 32595, 177, 32596, 181, 32597, 185, 32598, 189, 32599, 193, 32600, 197, 32601, 201, 32602, 205 }; // NOLINT
+static const MultiCharacterSpecialCase<4> kEcma262UnCanonicalizeMultiStrings2[] = { {2, {66560, 66600}}, {2, {66561, 66601}}, {2, {66562, 66602}}, {2, {66563, 66603}}, {2, {66564, 66604}}, {2, {66565, 66605}}, {2, {66566, 66606}}, {2, {66567, 66607}}, {2, {66568, 66608}}, {2, {66569, 66609}}, {2, {66570, 66610}}, {2, {66571, 66611}}, {2, {66572, 66612}}, {2, {66573, 66613}}, {2, {66574, 66614}}, {2, {66575, 66615}}, {2, {66576, 66616}}, {2, {66577, 66617}}, {2, {66578, 66618}}, {2, {66579, 66619}}, {2, {66580, 66620}}, {2, {66581, 66621}}, {2, {66582, 66622}}, {2, {66583, 66623}}, {2, {66584, 66624}}, {2, {66585, 66625}}, {2, {66586, 66626}}, {2, {66587, 66627}}, {2, {66588, 66628}}, {2, {66589, 66629}}, {2, {66590, 66630}}, {2, {66591, 66631}}, {2, {66592, 66632}}, {2, {66593, 66633}}, {2, {66594, 66634}}, {2, {66595, 66635}}, {2, {66596, 66636}}, {2, {66597, 66637}}, {2, {66598, 66638}}, {2, {66599, 66639}}, {2, {66560, 66600}}, {2, {66561, 66601}}, {2, {66562, 66602}}, {2, {66563, 66603}}, {2, {66564, 66604}}, {2, {66565, 66605}}, {2, {66566, 66606}}, {2, {66567, 66607}}, {2, {66568, 66608}}, {2, {66569, 66609}}, {2, {66570, 66610}}, {2, {66571, 66611}}, {2, {66572, 66612}}, {2, {66573, 66613}}, {2, {66574, 66614}}, {2, {66575, 66615}}, {2, {66576, 66616}}, {2, {66577, 66617}}, {2, {66578, 66618}}, {2, {66579, 66619}}, {2, {66580, 66620}}, {2, {66581, 66621}}, {2, {66582, 66622}}, {2, {66583, 66623}}, {2, {66584, 66624}}, {2, {66585, 66625}}, {2, {66586, 66626}}, {2, {66587, 66627}}, {2, {66588, 66628}}, {2, {66589, 66629}}, {2, {66590, 66630}}, {2, {66591, 66631}}, {2, {66592, 66632}}, {2, {66593, 66633}}, {2, {66594, 66634}}, {2, {66595, 66635}}, {2, {66596, 66636}}, {2, {66597, 66637}}, {2, {66598, 66638}}, {2, {66599, 66639}}, {0, {0}} }; // NOLINT
+static const uint16_t kEcma262UnCanonicalizeTable2Size = 80;
+static const int32_t kEcma262UnCanonicalizeTable2[160] = { 1024, 1, 1025, 5, 1026, 9, 1027, 13, 1028, 17, 1029, 21, 1030, 25, 1031, 29, 1032, 33, 1033, 37, 1034, 41, 1035, 45, 1036, 49, 1037, 53, 1038, 57, 1039, 61, 1040, 65, 1041, 69, 1042, 73, 1043, 77, 1044, 81, 1045, 85, 1046, 89, 1047, 93, 1048, 97, 1049, 101, 1050, 105, 1051, 109, 1052, 113, 1053, 117, 1054, 121, 1055, 125, 1056, 129, 1057, 133, 1058, 137, 1059, 141, 1060, 145, 1061, 149, 1062, 153, 1063, 157, 1064, 161, 1065, 165, 1066, 169, 1067, 173, 1068, 177, 1069, 181, 1070, 185, 1071, 189, 1072, 193, 1073, 197, 1074, 201, 1075, 205, 1076, 209, 1077, 213, 1078, 217, 1079, 221, 1080, 225, 1081, 229, 1082, 233, 1083, 237, 1084, 241, 1085, 245, 1086, 249, 1087, 253, 1088, 257, 1089, 261, 1090, 265, 1091, 269, 1092, 273, 1093, 277, 1094, 281, 1095, 285, 1096, 289, 1097, 293, 1098, 297, 1099, 301, 1100, 305, 1101, 309, 1102, 313, 1103, 317 }; // NOLINT
+int Ecma262UnCanonicalize::Convert(uchar c,
+                      uchar n,
+                      uchar* result,
+                      bool* allow_caching_ptr) {
+  int chunk_index = c >> 15;
+  switch (chunk_index) {
+    case 0: return LookupMapping(kEcma262UnCanonicalizeTable0,
+                                     kEcma262UnCanonicalizeTable0Size,
+                                     kEcma262UnCanonicalizeMultiStrings0,
+                                     c,
+                                     n,
+                                     result,
+                                     allow_caching_ptr);
+    case 1: return LookupMapping(kEcma262UnCanonicalizeTable1,
+                                     kEcma262UnCanonicalizeTable1Size,
+                                     kEcma262UnCanonicalizeMultiStrings1,
+                                     c,
+                                     n,
+                                     result,
+                                     allow_caching_ptr);
+    case 2: return LookupMapping(kEcma262UnCanonicalizeTable2,
+                                     kEcma262UnCanonicalizeTable2Size,
+                                     kEcma262UnCanonicalizeMultiStrings2,
+                                     c,
+                                     n,
+                                     result,
+                                     allow_caching_ptr);
+    default: return 0;
+  }
+}
+
+static const MultiCharacterSpecialCase<1> kCanonicalizationRangeMultiStrings0[] = { {0, {0}} }; // NOLINT
+static const uint16_t kCanonicalizationRangeTable0Size = 1831;
+static const int32_t kCanonicalizationRangeTable0[3662] = { 0, 67109124, 1073741825, 0, 64, 0, 65, 67108708, 1073741890, -260, 90, -260, 91, 67108524, 1073741916, -364, 96, -364, 97, 67108580, 1073741922, -388, 122, -388, 123, 67108604, 1073741948, -492, 180, -492, 181, 67108144, 182, 67108176, 1073742007, -728, 191, -728, 192, 67108188, 1073742017, -768, 214, -768, 215, 67108008, 216, 67108028, 1073742041, -864, 222, -864, 223, 67107976, 224, 67108060, 1073742049, -896, 246, -896, 247, 67107880, 248, 67107900, 1073742073, -992, 254, -992, 255, 67107848, 256, 67107844, 257, 67107840, 258, 67107836, 259, 67107832, 260, 67107828, 261, 67107824, 262, 67107820, 263, 67107816, 264, 67107812, 265, 67107808, 266, 67107804, 267, 67107800, 268, 67107796, 269, 67107792, 270, 67107788, 271, 67107784, 272, 67107780, 273, 67107776, 274, 67107772, 275, 67107768, 276, 67107764, 277, 67107760, 278, 67107756, 279, 67107752, 280, 67107748, 281, 67107744, 282, 67107740, 283, 67107736, 284, 67107732, 285, 67107728, 286, 67107724, 287, 67107720, 288, 67107716, 289, 67107712, 290, 67107708, 291, 67107704, 292, 67107700, 293, 67107696, 294, 67107692, 295, 67107688, 296, 67107684, 297, 67107680, 298, 67107676, 299, 67107672, 300, 67107668, 301, 67107664, 302, 67107660, 1073742127, 67107656, 304, 67107656, 305, -1216, 306, 67107644, 307, 67107640, 308, 67107636, 309, 67107632, 310, 67107628, 311, 67107624, 312, 67107620, 313, 67107616, 314, 67107612, 315, 67107608, 316, 67107604, 317, 67107600, 318, 67107596, 319, 67107592, 320, 67107588, 321, 67107584, 322, 67107580, 323, 67107576, 324, 67107572, 325, 67107568, 326, 67107564, 327, 67107560, 328, 67107556, 329, 67107552, 330, 67107548, 331, 67107544, 332, 67107540, 333, 67107536, 334, 67107532, 335, 67107528, 336, 67107524, 337, 67107520, 338, 67107516, 339, 67107512, 340, 67107508, 341, 67107504, 342, 67107500, 343, 67107496, 344, 67107492, 345, 67107488, 346, 67107484, 347, 67107480, 348, 67107476, 349, 67107472, 350, 67107468, 351, 67107464, 352, 67107460, 353, 67107456, 354, 67107452, 355, 67107448, 356, 67107444, 357, 67107440, 358, 67107436, 359, 67107432, 360, 67107428, 361, 67107424, 362, 67107420, 363, 67107416, 364, 67107412, 365, 67107408, 366, 67107404, 367, 67107400, 368, 67107396, 369, 67107392, 370, 67107388, 371, 67107384, 372, 67107380, 373, 67107376, 374, 67107372, 375, 67107368, 376, 67107364, 377, 67107360, 378, 67107356, 379, 67107352, 380, 67107348, 381, 67107344, 382, 67107340, 383, 67107336, 384, 67107332, 385, 67107328, 386, 67107324, 387, 67107320, 388, 67107316, 389, 67107312, 390, 67107308, 391, 67107304, 1073742216, 67107300, 393, 67107300, 394, -1572, 395, 67107288, 396, 67107284, 397, 67107280, 398, 67107276, 399, 67107272, 400, 67107268, 401, 67107264, 402, 67107260, 403, 67107256, 404, 67107252, 405, 67107248, 406, 67107244, 407, 67107240, 408, 67107236, 409, 67107232, 410, 67107228, 411, 67107224, 412, 67107220, 413, 67107216, 414, 67107212, 415, 67107208, 416, 67107204, 417, 67107200, 418, 67107196, 419, 67107192, 420, 67107188, 421, 67107184, 422, 67107180, 423, 67107176, 424, 67107172, 1073742249, 67107168, 426, 67107168, 427, -1704, 428, 67107156, 429, 67107152, 430, 67107148, 431, 67107144, 1073742256, 67107140, 433, 67107140, 434, -1732, 435, 67107128, 436, 67107124, 437, 67107120, 438, 67107116, 439, 67107112, 440, 67107108, 1073742265, 67107104, 442, 67107104, 443, -1768, 444, 67107092, 445, 67107088, 446, 67107084, 447, 67107080, 448, 67107088, 1073742273, -1792, 451, -1792, 452, 67107060, 453, 67107056, 454, 67107052, 455, 67107048, 456, 67107044, 457, 67107040, 458, 67107036, 459, 67107032, 460, 67107028, 461, 67107024, 462, 67107020, 463, 67107016, 464, 67107012, 465, 67107008, 466, 67107004, 467, 67107000, 468, 67106996, 469, 67106992, 470, 67106988, 471, 67106984, 472, 67106980, 473, 67106976, 474, 67106972, 475, 67106968, 476, 67106964, 477, 67106960, 478, 67106956, 479, 67106952, 480, 67106948, 481, 67106944, 482, 67106940, 483, 67106936, 484, 67106932, 485, 67106928, 486, 67106924, 487, 67106920, 488, 67106916, 489, 67106912, 490, 67106908, 491, 67106904, 492, 67106900, 493, 67106896, 494, 67106892, 495, 67106888, 496, 67106884, 497, 67106880, 498, 67106876, 499, 67106872, 500, 67106868, 501, 67106864, 502, 67106860, 503, 67106856, 504, 67106852, 505, 67106848, 506, 67106844, 507, 67106840, 508, 67106836, 509, 67106832, 510, 67106828, 511, 67106824, 512, 67106820, 513, 67106816, 514, 67106812, 515, 67106808, 516, 67106804, 517, 67106800, 518, 67106796, 519, 67106792, 520, 67106788, 521, 67106784, 522, 67106780, 523, 67106776, 524, 67106772, 525, 67106768, 526, 67106764, 527, 67106760, 528, 67106756, 529, 67106752, 530, 67106748, 531, 67106744, 532, 67106740, 533, 67106736, 534, 67106732, 535, 67106728, 536, 67106724, 537, 67106720, 538, 67106716, 539, 67106712, 540, 67106708, 541, 67106704, 542, 67106700, 543, 67106696, 544, 67106692, 545, 67106688, 546, 67106684, 547, 67106680, 548, 67106676, 549, 67106672, 550, 67106668, 551, 67106664, 552, 67106660, 553, 67106656, 554, 67106652, 555, 67106648, 556, 67106644, 557, 67106640, 558, 67106636, 559, 67106632, 560, 67106628, 561, 67106624, 562, 67106620, 563, 67106616, 564, 67106632, 1073742389, -2256, 569, -2256, 570, 67106588, 571, 67106584, 572, 67106580, 573, 67106576, 1073742398, 67106572, 575, 67106572, 576, -2300, 577, 67106560, 578, 67106556, 579, 67106552, 580, 67106548, 581, 67106544, 582, 67106540, 583, 67106536, 584, 67106532, 585, 67106528, 586, 67106524, 587, 67106520, 588, 67106516, 589, 67106512, 590, 67106508, 591, 67106504, 592, 67106508, 1073742417, -2368, 594, -2368, 595, 67106488, 596, 67106484, 1073742421, 67106480, 598, 67106480, 599, -2392, 600, 67106468, 601, 67106464, 602, 67106460, 603, 67106456, 604, 67106464, 1073742429, -2416, 607, -2416, 1073742432, 67106436, 609, 67106436, 610, -2436, 611, 67106424, 612, 67106432, 1073742437, -2448, 615, -2448, 616, 67106404, 617, 67106400, 618, 67106396, 619, 67106392, 620, 67106396, 1073742445, -2480, 622, -2480, 1073742447, 67106376, 624, 67106376, 625, -2496, 1073742450, 67106364, 627, 67106364, 628, -2508, 629, 67106352, 630, 67106372, 1073742455, -2520, 636, -2520, 1073742461, 67106320, 638, 67106320, 639, -2552, 1073742464, 67106308, 641, 67106308, 642, -2564, 643, 67106296, 644, 67106304, 1073742469, -2576, 647, -2576, 648, 67106276, 1073742473, 67106272, 650, 67106272, 651, -2600, 652, 67106260, 653, 67106272, 1073742478, -2612, 657, -2612, 658, 67106236, 659, 67106940, 1073742484, -2636, 836, -2636, 837, 67105520, 838, 67105724, 1073742663, -3352, 879, -3352, 1073742708, -3352, 885, -3352, 890, -3352, 891, 67105312, 1073742716, -3564, 893, -3564, 894, 67105320, 1073742724, -3576, 901, -3576, 902, 67105260, 903, 67105256, 904, 67105260, 1073742729, -3616, 906, -3616, 908, 67105236, 910, 67105232, 911, -3640, 912, 67105220, 913, 67105216, 1073742738, 67105212, 915, 67105212, 916, -3660, 1073742741, 67105200, 918, 67105200, 919, -3672, 920, 67105188, 921, 67105184, 922, 67105180, 923, 67105176, 924, 67105172, 925, 67105176, 1073742750, -3700, 927, -3700, 928, 67105156, 929, 67105152, 1073742755, 67105144, 932, 67105144, 933, -3728, 934, 67105132, 935, 67105144, 1073742760, -3740, 939, -3740, 940, 67105108, 941, 67105112, 1073742766, -3764, 943, -3764, 944, 67105092, 945, 67105088, 1073742770, 67105084, 947, 67105084, 948, -3788, 1073742773, 67105072, 950, 67105072, 951, -3800, 952, 67105060, 953, 67105056, 954, 67105052, 955, 67105048, 956, 67105044, 957, 67105048, 1073742782, -3828, 959, -3828, 960, 67105028, 961, 67105024, 962, 67105020, 1073742787, 67105016, 964, 67105016, 965, -3856, 966, 67105004, 967, 67105016, 1073742792, -3868, 971, -3868, 1073742796, 67104980, 973, 67104980, 974, -3892, 976, 67104964, 977, 67104960, 978, 67104964, 1073742803, -3912, 980, -3912, 981, 67104944, 982, 67104940, 983, 67104936, 984, 67104932, 985, 67104928, 986, 67104924, 987, 67104920, 988, 67104916, 989, 67104912, 990, 67104908, 991, 67104904, 992, 67104900, 993, 67104896, 994, 67104892, 995, 67104888, 996, 67104884, 997, 67104880, 998, 67104876, 999, 67104872, 1000, 67104868, 1001, 67104864, 1002, 67104860, 1003, 67104856, 1004, 67104852, 1005, 67104848, 1006, 67104844, 1007, 67104840, 1008, 67104836, 1009, 67104832, 1073742834, 67104828, 1011, 67104828, 1012, -4044, 1013, 67104816, 1014, 67104812, 1015, 67104808, 1016, 67104804, 1017, 67104800, 1018, 67104796, 1019, 67104792, 1020, 67104788, 1021, 67104792, 1073742846, -4084, 1023, -4084, 1024, 67104832, 1073742849, -4096, 1039, -4096, 1040, 67104832, 1073742865, -4160, 1071, -4160, 1072, 67104704, 1073742897, -4288, 1103, -4288, 1104, 67104512, 1073742929, -4416, 1119, -4416, 1120, 67104388, 1121, 67104384, 1122, 67104380, 1123, 67104376, 1124, 67104372, 1125, 67104368, 1126, 67104364, 1127, 67104360, 1128, 67104356, 1129, 67104352, 1130, 67104348, 1131, 67104344, 1132, 67104340, 1133, 67104336, 1134, 67104332, 1135, 67104328, 1136, 67104324, 1137, 67104320, 1138, 67104316, 1139, 67104312, 1140, 67104308, 1141, 67104304, 1142, 67104300, 1143, 67104296, 1144, 67104292, 1145, 67104288, 1146, 67104284, 1147, 67104280, 1148, 67104276, 1149, 67104272, 1150, 67104268, 1151, 67104264, 1152, 67104260, 1153, 67104256, 1154, 67104280, 1073742979, -4616, 1158, -4616, 1073742984, -4616, 1161, -4616, 1162, 67104220, 1163, 67104216, 1164, 67104212, 1165, 67104208, 1166, 67104204, 1167, 67104200, 1168, 67104196, 1169, 67104192, 1170, 67104188, 1171, 67104184, 1172, 67104180, 1173, 67104176, 1174, 67104172, 1175, 67104168, 1176, 67104164, 1177, 67104160, 1178, 67104156, 1179, 67104152, 1180, 67104148, 1181, 67104144, 1182, 67104140, 1183, 67104136, 1184, 67104132, 1185, 67104128, 1186, 67104124, 1187, 67104120, 1188, 67104116, 1189, 67104112, 1190, 67104108, 1191, 67104104, 1192, 67104100, 1193, 67104096, 1194, 67104092, 1195, 67104088, 1196, 67104084, 1197, 67104080, 1198, 67104076, 1199, 67104072, 1200, 67104068, 1201, 67104064, 1202, 67104060, 1203, 67104056, 1204, 67104052, 1205, 67104048, 1206, 67104044, 1207, 67104040, 1208, 67104036, 1209, 67104032, 1210, 67104028, 1211, 67104024, 1212, 67104020, 1213, 67104016, 1214, 67104012, 1215, 67104008, 1216, 67104004, 1217, 67104000, 1218, 67103996, 1219, 67103992, 1220, 67103988, 1221, 67103984, 1222, 67103980, 1223, 67103976, 1224, 67103972, 1225, 67103968, 1226, 67103964, 1227, 67103960, 1228, 67103956, 1229, 67103952, 1230, 67103948, 1231, 67103944, 1232, 67103940, 1233, 67103936, 1234, 67103932, 1235, 67103928, 1236, 67103924, 1237, 67103920, 1238, 67103916, 1239, 67103912, 1240, 67103908, 1241, 67103904, 1242, 67103900, 1243, 67103896, 1244, 67103892, 1245, 67103888, 1246, 67103884, 1247, 67103880, 1248, 67103876, 1249, 67103872, 1250, 67103868, 1251, 67103864, 1252, 67103860, 1253, 67103856, 1254, 67103852, 1255, 67103848, 1256, 67103844, 1257, 67103840, 1258, 67103836, 1259, 67103832, 1260, 67103828, 1261, 67103824, 1262, 67103820, 1263, 67103816, 1264, 67103812, 1265, 67103808, 1266, 67103804, 1267, 67103800, 1268, 67103796, 1269, 67103792, 1270, 67103788, 1271, 67103784, 1272, 67103780, 1273, 67103776, 1274, 67103772, 1275, 67103768, 1276, 67103764, 1277, 67103760, 1278, 67103756, 1279, 67103752, 1280, 67103748, 1281, 67103744, 1282, 67103740, 1283, 67103736, 1284, 67103732, 1285, 67103728, 1286, 67103724, 1287, 67103720, 1288, 67103716, 1289, 67103712, 1290, 67103708, 1291, 67103704, 1292, 67103700, 1293, 67103696, 1294, 67103692, 1295, 67103688, 1296, 67103684, 1297, 67103680, 1298, 67103676, 1299, 67103672, 1329, 67103700, 1073743154, -5316, 1366, -5316, 1073743193, -5468, 1375, -5468, 1377, 67103508, 1073743202, -5508, 1414, -5508, 1415, 67114568, 1073743241, -5660, 1418, -5660, 1073743249, -5660, 1479, -5660, 1073743312, -5660, 1514, -5660, 1073743344, -5660, 1524, -5660, 1073743360, -5660, 1539, -5660, 1073743371, -5660, 1557, -5660, 1563, -5660, 1073743390, -5660, 1567, -5660, 1073743393, -5660, 1594, -5660, 1073743424, -5660, 1630, -5660, 1073743456, -5660, 1805, -5660, 1073743631, -5660, 1866, -5660, 1073743693, -5660, 1901, -5660, 1073743744, -5660, 1969, -5660, 1073743808, -5660, 2042, -5660, 1073744129, -5660, 2361, -5660, 1073744188, -5660, 2381, -5660, 1073744208, -5660, 2388, -5660, 1073744216, -5660, 2416, -5660, 1073744251, -5660, 2431, -5660, 1073744257, -5660, 2435, -5660, 1073744261, -5660, 2444, -5660, 1073744271, -5660, 2448, -5660, 1073744275, -5660, 2472, -5660, 1073744298, -5660, 2480, -5660, 2482, -5660, 1073744310, -5660, 2489, -5660, 1073744316, -5660, 2500, -5660, 1073744327, -5660, 2504, -5660, 1073744331, -5660, 2510, -5660, 2519, -5660, 1073744348, -5660, 2525, -5660, 1073744351, -5660, 2531, -5660, 1073744358, -5660, 2554, -5660, 1073744385, -5660, 2563, -5660, 1073744389, -5660, 2570, -5660, 1073744399, -5660, 2576, -5660, 1073744403, -5660, 2600, -5660, 1073744426, -5660, 2608, -5660, 1073744434, -5660, 2611, -5660, 1073744437, -5660, 2614, -5660, 1073744440, -5660, 2617, -5660, 2620, -5660, 1073744446, -5660, 2626, -5660, 1073744455, -5660, 2632, -5660, 1073744459, -5660, 2637, -5660, 1073744473, -5660, 2652, -5660, 2654, -5660, 1073744486, -5660, 2676, -5660, 1073744513, -5660, 2691, -5660, 1073744517, -5660, 2701, -5660, 1073744527, -5660, 2705, -5660, 1073744531, -5660, 2728, -5660, 1073744554, -5660, 2736, -5660, 1073744562, -5660, 2739, -5660, 1073744565, -5660, 2745, -5660, 1073744572, -5660, 2757, -5660, 1073744583, -5660, 2761, -5660, 1073744587, -5660, 2765, -5660, 2768, -5660, 1073744608, -5660, 2787, -5660, 1073744614, -5660, 2799, -5660, 2801, -5660, 1073744641, -5660, 2819, -5660, 1073744645, -5660, 2828, -5660, 1073744655, -5660, 2832, -5660, 1073744659, -5660, 2856, -5660, 1073744682, -5660, 2864, -5660, 1073744690, -5660, 2867, -5660, 1073744693, -5660, 2873, -5660, 1073744700, -5660, 2883, -5660, 1073744711, -5660, 2888, -5660, 1073744715, -5660, 2893, -5660, 1073744726, -5660, 2903, -5660, 1073744732, -5660, 2909, -5660, 1073744735, -5660, 2913, -5660, 1073744742, -5660, 2929, -5660, 1073744770, -5660, 2947, -5660, 1073744773, -5660, 2954, -5660, 1073744782, -5660, 2960, -5660, 1073744786, -5660, 2965, -5660, 1073744793, -5660, 2970, -5660, 2972, -5660, 1073744798, -5660, 2975, -5660, 1073744803, -5660, 2980, -5660, 1073744808, -5660, 2986, -5660, 1073744814, -5660, 3001, -5660, 1073744830, -5660, 3010, -5660, 1073744838, -5660, 3016, -5660, 1073744842, -5660, 3021, -5660, 3031, -5660, 1073744870, -5660, 3066, -5660, 1073744897, -5660, 3075, -5660, 1073744901, -5660, 3084, -5660, 1073744910, -5660, 3088, -5660, 1073744914, -5660, 3112, -5660, 1073744938, -5660, 3123, -5660, 1073744949, -5660, 3129, -5660, 1073744958, -5660, 3140, -5660, 1073744966, -5660, 3144, -5660, 1073744970, -5660, 3149, -5660, 1073744981, -5660, 3158, -5660, 1073744992, -5660, 3169, -5660, 1073744998, -5660, 3183, -5660, 1073745026, -5660, 3203, -5660, 1073745029, -5660, 3212, -5660, 1073745038, -5660, 3216, -5660, 1073745042, -5660, 3240, -5660, 1073745066, -5660, 3251, -5660, 1073745077, -5660, 3257, -5660, 1073745084, -5660, 3268, -5660, 1073745094, -5660, 3272, -5660, 1073745098, -5660, 3277, -5660, 1073745109, -5660, 3286, -5660, 3294, -5660, 1073745120, -5660, 3299, -5660, 1073745126, -5660, 3311, -5660, 1073745137, -5660, 3314, -5660, 1073745154, -5660, 3331, -5660, 1073745157, -5660, 3340, -5660, 1073745166, -5660, 3344, -5660, 1073745170, -5660, 3368, -5660, 1073745194, -5660, 3385, -5660, 1073745214, -5660, 3395, -5660, 1073745222, -5660, 3400, -5660, 1073745226, -5660, 3405, -5660, 3415, -5660, 1073745248, -5660, 3425, -5660, 1073745254, -5660, 3439, -5660, 1073745282, -5660, 3459, -5660, 1073745285, -5660, 3478, -5660, 1073745306, -5660, 3505, -5660, 1073745331, -5660, 3515, -5660, 3517, -5660, 1073745344, -5660, 3526, -5660, 3530, -5660, 1073745359, -5660, 3540, -5660, 3542, -5660, 1073745368, -5660, 3551, -5660, 1073745394, -5660, 3572, -5660, 1073745409, -5660, 3642, -5660, 1073745471, -5660, 3675, -5660, 1073745537, -5660, 3714, -5660, 3716, -5660, 1073745543, -5660, 3720, -5660, 3722, -5660, 3725, -5660, 1073745556, -5660, 3735, -5660, 1073745561, -5660, 3743, -5660, 1073745569, -5660, 3747, -5660, 3749, -5660, 3751, -5660, 1073745578, -5660, 3755, -5660, 1073745581, -5660, 3769, -5660, 1073745595, -5660, 3773, -5660, 1073745600, -5660, 3780, -5660, 3782, -5660, 1073745608, -5660, 3789, -5660, 1073745616, -5660, 3801, -5660, 1073745628, -5660, 3805, -5660, 1073745664, -5660, 3911, -5660, 1073745737, -5660, 3946, -5660, 1073745777, -5660, 3979, -5660, 1073745808, -5660, 3991, -5660, 1073745817, -5660, 4028, -5660, 1073745854, -5660, 4044, -5660, 1073745871, -5660, 4049, -5660, 1073745920, -5660, 4129, -5660, 1073745955, -5660, 4135, -5660, 1073745961, -5660, 4138, -5660, 1073745964, -5660, 4146, -5660, 1073745974, -5660, 4153, -5660, 1073745984, -5660, 4185, -5660, 4256, 67091992, 1073746081, -17024, 4293, -17024, 1073746128, -17176, 4348, -17176, 1073746176, -17176, 4441, -17176, 1073746271, -17176, 4514, -17176, 1073746344, -17176, 4601, -17176, 1073746432, -17176, 4680, -17176, 1073746506, -17176, 4685, -17176, 1073746512, -17176, 4694, -17176, 4696, -17176, 1073746522, -17176, 4701, -17176, 1073746528, -17176, 4744, -17176, 1073746570, -17176, 4749, -17176, 1073746576, -17176, 4784, -17176, 1073746610, -17176, 4789, -17176, 1073746616, -17176, 4798, -17176, 4800, -17176, 1073746626, -17176, 4805, -17176, 1073746632, -17176, 4822, -17176, 1073746648, -17176, 4880, -17176, 1073746706, -17176, 4885, -17176, 1073746712, -17176, 4954, -17176, 1073746783, -17176, 4988, -17176, 1073746816, -17176, 5017, -17176, 1073746848, -17176, 5108, -17176, 1073746945, -17176, 5750, -17176, 1073747584, -17176, 5788, -17176, 1073747616, -17176, 5872, -17176, 1073747712, -17176, 5900, -17176, 1073747726, -17176, 5908, -17176, 1073747744, -17176, 5942, -17176, 1073747776, -17176, 5971, -17176, 1073747808, -17176, 5996, -17176, 1073747822, -17176, 6000, -17176, 1073747826, -17176, 6003, -17176, 1073747840, -17176, 6109, -17176, 1073747936, -17176, 6121, -17176, 1073747952, -17176, 6137, -17176, 1073747968, -17176, 6158, -17176, 1073747984, -17176, 6169, -17176, 1073748000, -17176, 6263, -17176, 1073748096, -17176, 6313, -17176, 1073748224, -17176, 6428, -17176, 1073748256, -17176, 6443, -17176, 1073748272, -17176, 6459, -17176, 6464, -17176, 1073748292, -17176, 6509, -17176, 1073748336, -17176, 6516, -17176, 1073748352, -17176, 6569, -17176, 1073748400, -17176, 6601, -17176, 1073748432, -17176, 6617, -17176, 1073748446, -17176, 6683, -17176, 1073748510, -17176, 6687, -17176, 1073748736, -17176, 6987, -17176, 1073748816, -17176, 7036, -17176, 1073749248, -17176, 7548, -17176, 7549, 67078672, 7550, 67079184, 1073749375, -30200, 7626, -30200, 1073749502, -30200, 7679, -30200, 7680, 67078148, 7681, 67078144, 7682, 67078140, 7683, 67078136, 7684, 67078132, 7685, 67078128, 7686, 67078124, 7687, 67078120, 7688, 67078116, 7689, 67078112, 7690, 67078108, 7691, 67078104, 7692, 67078100, 7693, 67078096, 7694, 67078092, 7695, 67078088, 7696, 67078084, 7697, 67078080, 7698, 67078076, 7699, 67078072, 7700, 67078068, 7701, 67078064, 7702, 67078060, 7703, 67078056, 7704, 67078052, 7705, 67078048, 7706, 67078044, 7707, 67078040, 7708, 67078036, 7709, 67078032, 7710, 67078028, 7711, 67078024, 7712, 67078020, 7713, 67078016, 7714, 67078012, 7715, 67078008, 7716, 67078004, 7717, 67078000, 7718, 67077996, 7719, 67077992, 7720, 67077988, 7721, 67077984, 7722, 67077980, 7723, 67077976, 7724, 67077972, 7725, 67077968, 7726, 67077964, 7727, 67077960, 7728, 67077956, 7729, 67077952, 7730, 67077948, 7731, 67077944, 7732, 67077940, 7733, 67077936, 7734, 67077932, 7735, 67077928, 7736, 67077924, 7737, 67077920, 7738, 67077916, 7739, 67077912, 7740, 67077908, 7741, 67077904, 7742, 67077900, 7743, 67077896, 7744, 67077892, 7745, 67077888, 7746, 67077884, 7747, 67077880, 7748, 67077876, 7749, 67077872, 7750, 67077868, 7751, 67077864, 7752, 67077860, 7753, 67077856, 7754, 67077852, 7755, 67077848, 7756, 67077844, 7757, 67077840, 7758, 67077836, 7759, 67077832, 7760, 67077828, 7761, 67077824, 7762, 67077820, 7763, 67077816, 7764, 67077812, 7765, 67077808, 7766, 67077804, 7767, 67077800, 7768, 67077796, 7769, 67077792, 7770, 67077788, 7771, 67077784, 7772, 67077780, 7773, 67077776, 7774, 67077772, 7775, 67077768, 7776, 67077764, 7777, 67077760, 7778, 67077756, 7779, 67077752, 7780, 67077748, 7781, 67077744, 7782, 67077740, 7783, 67077736, 7784, 67077732, 7785, 67077728, 7786, 67077724, 7787, 67077720, 7788, 67077716, 7789, 67077712, 7790, 67077708, 7791, 67077704, 7792, 67077700, 7793, 67077696, 7794, 67077692, 7795, 67077688, 7796, 67077684, 7797, 67077680, 7798, 67077676, 7799, 67077672, 7800, 67077668, 7801, 67077664, 7802, 67077660, 7803, 67077656, 7804, 67077652, 7805, 67077648, 7806, 67077644, 7807, 67077640, 7808, 67077636, 7809, 67077632, 7810, 67077628, 7811, 67077624, 7812, 67077620, 7813, 67077616, 7814, 67077612, 7815, 67077608, 7816, 67077604, 7817, 67077600, 7818, 67077596, 7819, 67077592, 7820, 67077588, 7821, 67077584, 7822, 67077580, 7823, 67077576, 7824, 67077572, 7825, 67077568, 7826, 67077564, 7827, 67077560, 7828, 67077556, 7829, 67077552, 7830, 67077564, 1073749655, -31320, 7834, -31320, 7835, 67077528, 7840, 67077508, 7841, 67077504, 7842, 67077500, 7843, 67077496, 7844, 67077492, 7845, 67077488, 7846, 67077484, 7847, 67077480, 7848, 67077476, 7849, 67077472, 7850, 67077468, 7851, 67077464, 7852, 67077460, 7853, 67077456, 7854, 67077452, 7855, 67077448, 7856, 67077444, 7857, 67077440, 7858, 67077436, 7859, 67077432, 7860, 67077428, 7861, 67077424, 7862, 67077420, 7863, 67077416, 7864, 67077412, 7865, 67077408, 7866, 67077404, 7867, 67077400, 7868, 67077396, 7869, 67077392, 7870, 67077388, 7871, 67077384, 7872, 67077380, 7873, 67077376, 7874, 67077372, 7875, 67077368, 7876, 67077364, 7877, 67077360, 7878, 67077356, 7879, 67077352, 7880, 67077348, 7881, 67077344, 7882, 67077340, 7883, 67077336, 7884, 67077332, 7885, 67077328, 7886, 67077324, 7887, 67077320, 7888, 67077316, 7889, 67077312, 7890, 67077308, 7891, 67077304, 7892, 67077300, 7893, 67077296, 7894, 67077292, 7895, 67077288, 7896, 67077284, 7897, 67077280, 7898, 67077276, 7899, 67077272, 7900, 67077268, 7901, 67077264, 7902, 67077260, 7903, 67077256, 7904, 67077252, 7905, 67077248, 7906, 67077244, 7907, 67077240, 7908, 67077236, 7909, 67077232, 7910, 67077228, 7911, 67077224, 7912, 67077220, 7913, 67077216, 7914, 67077212, 7915, 67077208, 7916, 67077204, 7917, 67077200, 7918, 67077196, 7919, 67077192, 7920, 67077188, 7921, 67077184, 7922, 67077180, 7923, 67077176, 7924, 67077172, 7925, 67077168, 7926, 67077164, 7927, 67077160, 7928, 67077156, 7929, 67077152, 7936, 67077152, 1073749761, -31744, 7943, -31744, 7944, 67077120, 1073749769, -31776, 7951, -31776, 7952, 67077080, 1073749777, -31808, 7957, -31808, 7960, 67077048, 1073749785, -31840, 7965, -31840, 7968, 67077024, 1073749793, -31872, 7975, -31872, 7976, 67076992, 1073749801, -31904, 7983, -31904, 7984, 67076960, 1073749809, -31936, 7991, -31936, 7992, 67076928, 1073749817, -31968, 7999, -31968, 8000, 67076888, 1073749825, -32000, 8005, -32000, 8008, 67076856, 1073749833, -32032, 8013, -32032, 8016, -32056, 8017, 67076800, 8018, 67076796, 8019, 67076792, 8020, 67076788, 8021, 67076784, 8022, 67076780, 8023, 67076776, 8025, 67076768, 8027, 67076760, 8029, 67076752, 8031, 67076744, 8032, 67076768, 1073749857, -32128, 8039, -32128, 8040, 67076736, 1073749865, -32160, 8047, -32160, 8048, 67076680, 8049, -32192, 8050, 67076680, 1073749875, -32200, 8053, -32200, 8054, 67076656, 8055, -32216, 8056, 67076648, 8057, -32224, 8058, 67076640, 8059, -32232, 8060, 67076632, 8061, -32240, 1073749888, -32248, 8111, -32248, 8112, 67076424, 8113, -32448, 8114, 67076432, 1073749939, -32456, 8116, -32456, 1073749942, -32456, 8119, -32456, 8120, 67076392, 8121, -32480, 8122, 67076384, 8123, -32488, 8124, 67076376, 8125, -32496, 8126, 67076364, 8127, 67076392, 1073749952, -32508, 8132, -32508, 1073749958, -32508, 8135, -32508, 8136, 67076336, 1073749961, -32544, 8139, -32544, 8140, 67076320, 1073749965, -32560, 8143, -32560, 8144, 67076296, 8145, -32576, 8146, 67076304, 8147, -32584, 1073749974, -32584, 8151, -32584, 8152, 67076264, 8153, -32608, 8154, 67076256, 8155, -32616, 1073749981, -32624, 8159, -32624, 8160, 67076232, 8161, -32640, 8162, 67076228, 1073749987, -32648, 8164, -32648, 1073749989, 67076208, 8166, 67076208, 8167, -32664, 8168, 67076200, 8169, -32672, 8170, 67076192, 8171, -32680, 8172, 67076180, 8173, 67076216, 1073749998, -32692, 8175, -32692, 1073750002, -32692, 8180, -32692, 1073750006, -32692, 8183, -32692, 8184, 67076136, 8185, -32736, 8186, 67076128, 8187, -32744, 8188, 67077352, 1073750013, -32752, 8190, -32752, 1073750016, -32752, 8291, -32752, 1073750122, -32752, 8305, -32752, 1073750132, -32752, 8334, -32752, 1073750160, -32752, 8340, -32752, 1073750176, -32752, 8373, -32752, 1073750224, -32752, 8431, -32752, 1073750272, -32752, 8497, -32752, 8498, 67074876, 8499, 67074976, 1073750324, -33996, 8525, -33996, 8526, 67074764, 1073750355, -34108, 8543, -34108, 8544, 67074752, 1073750369, -34176, 8559, -34176, 8560, 67074688, 1073750385, -34240, 8575, -34240, 8576, 67074572, 1073750401, -34304, 8578, -34304, 8579, 67074552, 8580, 67074548, 1073750416, -34324, 9191, -34324, 1073751040, -34324, 9254, -34324, 1073751104, -34324, 9290, -34324, 1073751136, -34324, 9397, -34324, 9398, 67071376, 1073751223, -37592, 9423, -37592, 9424, 67071272, 1073751249, -37696, 9449, -37696, 9450, 67078320, 1073751275, -37800, 9884, -37800, 1073751712, -37800, 9906, -37800, 1073751809, -37800, 9988, -37800, 1073751814, -37800, 9993, -37800, 1073751820, -37800, 10023, -37800, 1073751849, -37800, 10059, -37800, 10061, -37800, 1073751887, -37800, 10066, -37800, 10070, -37800, 1073751896, -37800, 10078, -37800, 1073751905, -37800, 10132, -37800, 1073751960, -37800, 10159, -37800, 1073751985, -37800, 10174, -37800, 1073752000, -37800, 10186, -37800, 1073752016, -37800, 10219, -37800, 1073752048, -37800, 11034, -37800, 1073752864, -37800, 11043, -37800, 11264, 67063996, 1073753089, -45056, 11310, -45056, 11312, 67063804, 1073753137, -45248, 11358, -45248, 11360, 67063428, 11361, 67063424, 11362, 67063420, 11363, 67063416, 11364, 67063412, 11365, 67063408, 11366, 67063404, 11367, 67063400, 11368, 67063396, 11369, 67063392, 11370, 67063388, 11371, 67063384, 11372, 67063380, 11380, -45492, 11381, 67063344, 11382, 67063340, 11383, 67063368, 11392, 67063300, 11393, 67063296, 11394, 67063292, 11395, 67063288, 11396, 67063284, 11397, 67063280, 11398, 67063276, 11399, 67063272, 11400, 67063268, 11401, 67063264, 11402, 67063260, 11403, 67063256, 11404, 67063252, 11405, 67063248, 11406, 67063244, 11407, 67063240, 11408, 67063236, 11409, 67063232, 11410, 67063228, 11411, 67063224, 11412, 67063220, 11413, 67063216, 11414, 67063212, 11415, 67063208, 11416, 67063204, 11417, 67063200, 11418, 67063196, 11419, 67063192, 11420, 67063188, 11421, 67063184, 11422, 67063180, 11423, 67063176, 11424, 67063172, 11425, 67063168, 11426, 67063164, 11427, 67063160, 11428, 67063156, 11429, 67063152, 11430, 67063148, 11431, 67063144, 11432, 67063140, 11433, 67063136, 11434, 67063132, 11435, 67063128, 11436, 67063124, 11437, 67063120, 11438, 67063116, 11439, 67063112, 11440, 67063108, 11441, 67063104, 11442, 67063100, 11443, 67063096, 11444, 67063092, 11445, 67063088, 11446, 67063084, 11447, 67063080, 11448, 67063076, 11449, 67063072, 11450, 67063068, 11451, 67063064, 11452, 67063060, 11453, 67063056, 11454, 67063052, 11455, 67063048, 11456, 67063044, 11457, 67063040, 11458, 67063036, 11459, 67063032, 11460, 67063028, 11461, 67063024, 11462, 67063020, 11463, 67063016, 11464, 67063012, 11465, 67063008, 11466, 67063004, 11467, 67063000, 11468, 67062996, 11469, 67062992, 11470, 67062988, 11471, 67062984, 11472, 67062980, 11473, 67062976, 11474, 67062972, 11475, 67062968, 11476, 67062964, 11477, 67062960, 11478, 67062956, 11479, 67062952, 11480, 67062948, 11481, 67062944, 11482, 67062940, 11483, 67062936, 11484, 67062932, 11485, 67062928, 11486, 67062924, 11487, 67062920, 11488, 67062916, 11489, 67062912, 11490, 67062908, 11491, 67062904, 11492, 67063008, 1073753317, -45968, 11498, -45968, 1073753337, -45968, 11519, -45968, 11520, 67062936, 1073753345, -46080, 11557, -46080, 1073753392, -46232, 11621, -46232, 11631, -46232, 1073753472, -46232, 11670, -46232, 1073753504, -46232, 11686, -46232, 1073753512, -46232, 11694, -46232, 1073753520, -46232, 11702, -46232, 1073753528, -46232, 11710, -46232, 1073753536, -46232, 11718, -46232, 1073753544, -46232, 11726, -46232, 1073753552, -46232, 11734, -46232, 1073753560, -46232, 11742, -46232, 1073753600, -46232, 11799, -46232, 1073753628, -46232, 11805, -46232, 1073753728, -46232, 11929, -46232, 1073753755, -46232, 12019, -46232, 1073753856, -46232, 12245, -46232, 1073754096, -46232, 12283, -46232, 1073754112, -46232, 12351, -46232, 1073754177, -46232, 12438, -46232, 1073754265, -46232, 12543, -46232, 1073754373, -46232, 12588, -46232, 1073754417, -46232, 12686, -46232, 1073754512, -46232, 12727, -46232, 1073754560, -46232, 12751, -46232, 1073754608, -46232, 12830, -46232, 1073754656, -46232, 12867, -46232, 1073754704, -46232, 13054, -46232, 1073754880, -46232, 19893, -46232, 1073761728, -46232, 32767, -46232 }; // NOLINT
+static const MultiCharacterSpecialCase<1> kCanonicalizationRangeMultiStrings1[] = { {0, {0}} }; // NOLINT
+static const uint16_t kCanonicalizationRangeTable1Size = 88;
+static const int32_t kCanonicalizationRangeTable1[176] = { 1073741824, -46232, 8123, -46232, 1073750016, -46232, 9356, -46232, 1073751184, -46232, 9414, -46232, 1073751808, -46232, 10010, -46232, 1073751840, -46232, 10017, -46232, 1073752064, -46232, 10283, -46232, 1073752128, -46232, 10359, -46232, 1073753088, -46232, 22435, -46232, 1073764352, -46232, 31277, -46232, 1073773104, -46232, 31338, -46232, 1073773168, -46232, 31449, -46232, 1073773312, -46232, 31494, -46232, 1073773331, -46232, 31511, -46232, 1073773341, -46232, 31542, -46232, 1073773368, -46232, 31548, -46232, 31550, -46232, 1073773376, -46232, 31553, -46232, 1073773379, -46232, 31556, -46232, 1073773382, -46232, 31665, -46232, 1073773523, -46232, 32063, -46232, 1073773904, -46232, 32143, -46232, 1073773970, -46232, 32199, -46232, 1073774064, -46232, 32253, -46232, 1073774080, -46232, 32281, -46232, 1073774112, -46232, 32291, -46232, 1073774128, -46232, 32338, -46232, 1073774164, -46232, 32358, -46232, 1073774184, -46232, 32363, -46232, 1073774192, -46232, 32372, -46232, 1073774198, -46232, 32508, -46232, 32511, -46232, 1073774337, -46232, 32544, -46232, 32545, 66847716, 1073774370, -261252, 32570, -261252, 32571, 66847532, 1073774396, -261356, 32576, -261356, 32577, 66847588, 1073774402, -261380, 32602, -261380, 32603, 66848040, 1073774428, -261484, 32702, -261484, 1073774530, -261484, 32711, -261484, 1073774538, -261484, 32719, -261484, 1073774546, -261484, 32727, -261484, 1073774554, -261484, 32732, -261484, 1073774560, -261484, 32742, -261484, 1073774568, -261484, 32750, -261484, 1073774585, -261484, 32765, -261484 }; // NOLINT
+int CanonicalizationRange::Convert(uchar c,
+                      uchar n,
+                      uchar* result,
+                      bool* allow_caching_ptr) {
+  int chunk_index = c >> 15;
+  switch (chunk_index) {
+    case 0: return LookupMapping(kCanonicalizationRangeTable0,
+                                     kCanonicalizationRangeTable0Size,
+                                     kCanonicalizationRangeMultiStrings0,
+                                     c,
+                                     n,
+                                     result,
+                                     allow_caching_ptr);
+    case 1: return LookupMapping(kCanonicalizationRangeTable1,
+                                     kCanonicalizationRangeTable1Size,
+                                     kCanonicalizationRangeMultiStrings1,
+                                     c,
+                                     n,
+                                     result,
+                                     allow_caching_ptr);
+    default: return 0;
+  }
+}
+
+
+uchar UnicodeData::kMaxCodePoint = 1114109;
+
+int UnicodeData::GetByteCount() {
+  return 0 + (sizeof(uint16_t) * kUppercaseTable0Size) + (sizeof(uint16_t) * kUppercaseTable1Size) + (sizeof(uint16_t) * kUppercaseTable2Size) + (sizeof(uint16_t) * kUppercaseTable3Size) + (sizeof(uint16_t) * kLowercaseTable0Size) + (sizeof(uint16_t) * kLowercaseTable1Size) + (sizeof(uint16_t) * kLowercaseTable2Size) + (sizeof(uint16_t) * kLowercaseTable3Size) + (sizeof(uint16_t) * kLetterTable0Size) + (sizeof(uint16_t) * kLetterTable1Size) + (sizeof(uint16_t) * kLetterTable2Size) + (sizeof(uint16_t) * kLetterTable3Size) + (sizeof(uint16_t) * kLetterTable4Size) + (sizeof(uint16_t) * kLetterTable5Size) + (sizeof(uint16_t) * kSpaceTable0Size) + (sizeof(uint16_t) * kNumberTable0Size) + (sizeof(uint16_t) * kNumberTable1Size) + (sizeof(uint16_t) * kNumberTable2Size) + (sizeof(uint16_t) * kNumberTable3Size) + (sizeof(uint16_t) * kWhiteSpaceTable0Size) + (sizeof(uint16_t) * kLineTerminatorTable0Size) + (sizeof(uint16_t) * kCombiningMarkTable0Size) + (sizeof(uint16_t) * kCombiningMarkTable1Size) + (sizeof(uint16_t) * kCombiningMarkTable2Size) + (sizeof(uint16_t) * kCombiningMarkTable3Size) + (sizeof(uint16_t) * kCombiningMarkTable28Size) + (sizeof(uint16_t) * kConnectorPunctuationTable0Size) + (sizeof(uint16_t) * kConnectorPunctuationTable1Size) + (sizeof(uint16_t) * kToLowercaseTable0Size) + (sizeof(uint16_t) * kToLowercaseTable1Size) + (sizeof(uint16_t) * kToLowercaseTable2Size) + (sizeof(uint16_t) * kToUppercaseTable0Size) + (sizeof(uint16_t) * kToUppercaseTable1Size) + (sizeof(uint16_t) * kToUppercaseTable2Size) + (sizeof(uint16_t) * kEcma262CanonicalizeTable0Size) + (sizeof(uint16_t) * kEcma262CanonicalizeTable1Size) + (sizeof(uint16_t) * kEcma262CanonicalizeTable2Size) + (sizeof(uint16_t) * kEcma262UnCanonicalizeTable0Size) + (sizeof(uint16_t) * kEcma262UnCanonicalizeTable1Size) + (sizeof(uint16_t) * kEcma262UnCanonicalizeTable2Size) + (sizeof(uint16_t) * kCanonicalizationRangeTable0Size) + (sizeof(uint16_t) * kCanonicalizationRangeTable1Size); // NOLINT
+}
+
+}  // namespace unicode
diff --git a/deps/v8/src/unicode.h b/deps/v8/src/unicode.h
new file mode 100644
index 0000000..86fd498
--- /dev/null
+++ b/deps/v8/src/unicode.h
@@ -0,0 +1,279 @@
+// 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.
+
+#ifndef __UNIBROW_H__
+#define __UNIBROW_H__
+
+#include <sys/types.h>
+
+/**
+ * \file
+ * Definitions and convenience functions for working with unicode.
+ */
+
+namespace unibrow {
+
+typedef unsigned int uchar;
+typedef unsigned char byte;
+
+/**
+ * The max length of the result of converting the case of a single
+ * character.
+ */
+static const int kMaxMappingSize = 4;
+
+template <class T, int size = 256>
+class Predicate {
+ public:
+  inline Predicate() { }
+  inline bool get(uchar c);
+ private:
+  friend class Test;
+  bool CalculateValue(uchar c);
+  struct CacheEntry {
+    inline CacheEntry() : code_point_(0), value_(0) { }
+    inline CacheEntry(uchar code_point, bool value)
+      : code_point_(code_point),
+        value_(value) { }
+    uchar code_point_ : 21;
+    bool value_ : 1;
+  };
+  static const int kSize = size;
+  static const int kMask = kSize - 1;
+  CacheEntry entries_[kSize];
+};
+
+// A cache used in case conversion.  It caches the value for characters
+// that either have no mapping or map to a single character independent
+// of context.  Characters that map to more than one character or that
+// map differently depending on context are always looked up.
+template <class T, int size = 256>
+class Mapping {
+ public:
+  inline Mapping() { }
+  inline int get(uchar c, uchar n, uchar* result);
+ private:
+  friend class Test;
+  int CalculateValue(uchar c, uchar n, uchar* result);
+  struct CacheEntry {
+    inline CacheEntry() : code_point_(kNoChar), offset_(0) { }
+    inline CacheEntry(uchar code_point, signed offset)
+      : code_point_(code_point),
+        offset_(offset) { }
+    uchar code_point_;
+    signed offset_;
+    static const int kNoChar = (1 << 21) - 1;
+  };
+  static const int kSize = size;
+  static const int kMask = kSize - 1;
+  CacheEntry entries_[kSize];
+};
+
+class UnicodeData {
+ private:
+  friend class Test;
+  static int GetByteCount();
+  static uchar kMaxCodePoint;
+};
+
+// --- U t f   8 ---
+
+template <typename Data>
+class Buffer {
+ public:
+  inline Buffer(Data data, unsigned length) : data_(data), length_(length) { }
+  inline Buffer() : data_(0), length_(0) { }
+  Data data() { return data_; }
+  unsigned length() { return length_; }
+ private:
+  Data data_;
+  unsigned length_;
+};
+
+class Utf8 {
+ public:
+  static inline uchar Length(uchar chr);
+  static inline unsigned Encode(char* out, uchar c);
+  static const byte* ReadBlock(Buffer<const char*> str, byte* buffer,
+      unsigned capacity, unsigned* chars_read, unsigned* offset);
+  static const uchar kBadChar = 0xFFFD;
+  static const unsigned kMaxEncodedSize   = 4;
+  static const unsigned kMaxOneByteChar   = 0x7f;
+  static const unsigned kMaxTwoByteChar   = 0x7ff;
+  static const unsigned kMaxThreeByteChar = 0xffff;
+  static const unsigned kMaxFourByteChar  = 0x1fffff;
+
+ private:
+  template <unsigned s> friend class Utf8InputBuffer;
+  friend class Test;
+  static inline uchar ValueOf(const byte* str,
+                              unsigned length,
+                              unsigned* cursor);
+  static uchar CalculateValue(const byte* str,
+                              unsigned length,
+                              unsigned* cursor);
+};
+
+// --- C h a r a c t e r   S t r e a m ---
+
+class CharacterStream {
+ public:
+  inline uchar GetNext();
+  inline bool has_more() { return remaining_ != 0; }
+  // Note that default implementation is not efficient.
+  virtual void Seek(unsigned);
+  unsigned Length();
+  virtual ~CharacterStream() { }
+  static inline bool EncodeCharacter(uchar c, byte* buffer, unsigned capacity,
+      unsigned& offset);
+  static inline bool EncodeAsciiCharacter(uchar c, byte* buffer,
+      unsigned capacity, unsigned& offset);
+  static inline bool EncodeNonAsciiCharacter(uchar c, byte* buffer,
+      unsigned capacity, unsigned& offset);
+  static inline uchar DecodeCharacter(const byte* buffer, unsigned* offset);
+  virtual void Rewind() = 0;
+ protected:
+  virtual void FillBuffer() = 0;
+  // The number of characters left in the current buffer
+  unsigned remaining_;
+  // The current offset within the buffer
+  unsigned cursor_;
+  // The buffer containing the decoded characters.
+  const byte* buffer_;
+};
+
+// --- I n p u t   B u f f e r ---
+
+/**
+ * Provides efficient access to encoded characters in strings.  It
+ * does so by reading characters one block at a time, rather than one
+ * character at a time, which gives string implementations an
+ * opportunity to optimize the decoding.
+ */
+template <class Reader, class Input = Reader*, unsigned kSize = 256>
+class InputBuffer : public CharacterStream {
+ public:
+  virtual void Rewind();
+  inline void Reset(Input input);
+  void Seek(unsigned position);
+  inline void Reset(unsigned position, Input input);
+ protected:
+  InputBuffer() { }
+  explicit InputBuffer(Input input) { Reset(input); }
+  virtual void FillBuffer();
+
+  // A custom offset that can be used by the string implementation to
+  // mark progress within the encoded string.
+  unsigned offset_;
+  // The input string
+  Input input_;
+  // To avoid heap allocation, we keep an internal buffer to which
+  // the encoded string can write its characters.  The string
+  // implementation is free to decide whether it wants to use this
+  // buffer or not.
+  byte util_buffer_[kSize];
+};
+
+// --- U t f 8   I n p u t   B u f f e r ---
+
+template <unsigned s = 256>
+class Utf8InputBuffer : public InputBuffer<Utf8, Buffer<const char*>, s> {
+ public:
+  inline Utf8InputBuffer() { }
+  inline Utf8InputBuffer(const char* data, unsigned length);
+  inline void Reset(const char* data, unsigned length) {
+    InputBuffer<Utf8, Buffer<const char*>, s>::Reset(
+        Buffer<const char*>(data, length));
+  }
+};
+
+struct Uppercase {
+  static bool Is(uchar c);
+};
+struct Lowercase {
+  static bool Is(uchar c);
+};
+struct Letter {
+  static bool Is(uchar c);
+};
+struct Space {
+  static bool Is(uchar c);
+};
+struct Number {
+  static bool Is(uchar c);
+};
+struct WhiteSpace {
+  static bool Is(uchar c);
+};
+struct LineTerminator {
+  static bool Is(uchar c);
+};
+struct CombiningMark {
+  static bool Is(uchar c);
+};
+struct ConnectorPunctuation {
+  static bool Is(uchar c);
+};
+struct ToLowercase {
+  static const int kMaxWidth = 3;
+  static int Convert(uchar c,
+                     uchar n,
+                     uchar* result,
+                     bool* allow_caching_ptr);
+};
+struct ToUppercase {
+  static const int kMaxWidth = 3;
+  static int Convert(uchar c,
+                     uchar n,
+                     uchar* result,
+                     bool* allow_caching_ptr);
+};
+struct Ecma262Canonicalize {
+  static const int kMaxWidth = 1;
+  static int Convert(uchar c,
+                     uchar n,
+                     uchar* result,
+                     bool* allow_caching_ptr);
+};
+struct Ecma262UnCanonicalize {
+  static const int kMaxWidth = 4;
+  static int Convert(uchar c,
+                     uchar n,
+                     uchar* result,
+                     bool* allow_caching_ptr);
+};
+struct CanonicalizationRange {
+  static const int kMaxWidth = 1;
+  static int Convert(uchar c,
+                     uchar n,
+                     uchar* result,
+                     bool* allow_caching_ptr);
+};
+
+}  // namespace unibrow
+
+#endif  // __UNIBROW_H__
diff --git a/deps/v8/src/uri.js b/deps/v8/src/uri.js
new file mode 100644
index 0000000..fe659aa
--- /dev/null
+++ b/deps/v8/src/uri.js
@@ -0,0 +1,409 @@
+// 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.
+
+// This file contains support for URI manipulations written in
+// JavaScript.
+
+// Expect $String = global.String;
+
+function URIAddEncodedOctetToBuffer(octet, result, index) {
+  result[index++] = 37; // Char code of '%'.
+  result[index++] = hexCharCodeArray[octet >> 4];
+  result[index++] = hexCharCodeArray[octet & 0x0F];
+  return index;
+}
+
+
+function URIEncodeOctets(octets, result, index) {
+  index = URIAddEncodedOctetToBuffer(octets[0], result, index);
+  if (octets[1]) index = URIAddEncodedOctetToBuffer(octets[1], result, index);
+  if (octets[2]) index = URIAddEncodedOctetToBuffer(octets[2], result, index);
+  if (octets[3]) index = URIAddEncodedOctetToBuffer(octets[3], result, index);
+  return index;
+}
+
+
+function URIEncodeSingle(cc, result, index) {
+  var x = (cc >> 12) & 0xF;
+  var y = (cc >> 6) & 63;
+  var z = cc & 63;
+  var octets = new $Array(3);
+  if (cc <= 0x007F) {
+    octets[0] = cc;
+  } else if (cc <= 0x07FF) {
+    octets[0] = y + 192;
+    octets[1] = z + 128;
+  } else {
+    octets[0] = x + 224;
+    octets[1] = y + 128;
+    octets[2] = z + 128;
+  }
+  return URIEncodeOctets(octets, result, index);
+}
+
+
+function URIEncodePair(cc1 , cc2, result, index) {
+  var u = ((cc1 >> 6) & 0xF) + 1;
+  var w = (cc1 >> 2) & 0xF;
+  var x = cc1 & 3;
+  var y = (cc2 >> 6) & 0xF;
+  var z = cc2 & 63;
+  var octets = new $Array(4);
+  octets[0] = (u >> 2) + 240;
+  octets[1] = (((u & 3) << 4) | w) + 128;
+  octets[2] = ((x << 4) | y) + 128;
+  octets[3] = z + 128;
+  return URIEncodeOctets(octets, result, index);
+}
+
+
+function URIHexCharsToCharCode(ch1, ch2) {
+  if (HexValueOf(ch1) == -1 || HexValueOf(ch2) == -1) {
+    throw new $URIError("URI malformed");
+  }
+  return HexStrToCharCode(ch1 + ch2);
+}
+
+
+function URIDecodeOctets(octets, result, index) {
+  var value;
+  var o0 = octets[0];
+  if (o0 < 0x80) {
+    value = o0;
+  } else if (o0 < 0xc2) {
+    throw new $URIError("URI malformed");
+  } else {
+    var o1 = octets[1];
+    if (o0 < 0xe0) {
+      var a = o0 & 0x1f;
+      if ((o1 < 0x80) || (o1 > 0xbf))
+        throw new $URIError("URI malformed");
+      var b = o1 & 0x3f;
+      value = (a << 6) + b;
+      if (value < 0x80 || value > 0x7ff)
+        throw new $URIError("URI malformed");
+    } else {
+      var o2 = octets[2];
+      if (o0 < 0xf0) {
+        var a = o0 & 0x0f;
+        if ((o1 < 0x80) || (o1 > 0xbf))
+          throw new $URIError("URI malformed");
+        var b = o1 & 0x3f;
+        if ((o2 < 0x80) || (o2 > 0xbf))
+          throw new $URIError("URI malformed");
+        var c = o2 & 0x3f;
+        value = (a << 12) + (b << 6) + c;
+        if ((value < 0x800) || (value > 0xffff))
+          throw new $URIError("URI malformed");
+      } else {
+        var o3 = octets[3];
+        if (o0 < 0xf8) {
+          var a = (o0 & 0x07);
+          if ((o1 < 0x80) || (o1 > 0xbf))
+            throw new $URIError("URI malformed");
+          var b = (o1 & 0x3f);
+          if ((o2 < 0x80) || (o2 > 0xbf))
+            throw new $URIError("URI malformed");
+          var c = (o2 & 0x3f);
+          if ((o3 < 0x80) || (o3 > 0xbf))
+            throw new $URIError("URI malformed");
+          var d = (o3 & 0x3f);
+          value = (a << 18) + (b << 12) + (c << 6) + d;
+          if ((value < 0x10000) || (value > 0x10ffff))
+            throw new $URIError("URI malformed");
+        } else {
+          throw new $URIError("URI malformed");
+        }
+      }
+    }
+  }
+  if (value < 0x10000) {
+    result[index++] = value;
+    return index;
+  } else {
+    result[index++] = (value >> 10) + 0xd7c0;
+    result[index++] = (value & 0x3ff) + 0xdc00;
+    return index;
+  }
+}
+
+
+// ECMA-262, section 15.1.3
+function Encode(uri, unescape) {
+  var uriLength = uri.length;
+  var result = new $Array(uriLength);
+  var index = 0;
+  for (var k = 0; k < uriLength; k++) {
+    var cc1 = uri.charCodeAt(k);
+    if (unescape(cc1)) {
+      result[index++] = cc1;
+    } else {
+      if (cc1 >= 0xDC00 && cc1 <= 0xDFFF) throw new $URIError("URI malformed");
+      if (cc1 < 0xD800 || cc1 > 0xDBFF) {
+        index = URIEncodeSingle(cc1, result, index);
+      } else {
+        k++;
+        if (k == uriLength) throw new $URIError("URI malformed");
+        var cc2 = uri.charCodeAt(k);
+        if (cc2 < 0xDC00 || cc2 > 0xDFFF) throw new $URIError("URI malformed");
+        index = URIEncodePair(cc1, cc2, result, index);
+      }
+    }
+  }
+  return %StringFromCharCodeArray(result);
+}
+
+
+// ECMA-262, section 15.1.3
+function Decode(uri, reserved) {
+  var uriLength = uri.length;
+  var result = new $Array(uriLength);
+  var index = 0;
+  for (var k = 0; k < uriLength; k++) {
+    var ch = uri.charAt(k);
+    if (ch == '%') {
+      if (k + 2 >= uriLength) throw new $URIError("URI malformed");
+      var cc = URIHexCharsToCharCode(uri.charAt(++k), uri.charAt(++k));
+      if (cc >> 7) {
+        var n = 0;
+        while (((cc << ++n) & 0x80) != 0) ;
+        if (n == 1 || n > 4) throw new $URIError("URI malformed");
+        var octets = new $Array(n);
+        octets[0] = cc;
+        if (k + 3 * (n - 1) >= uriLength) throw new $URIError("URI malformed");
+        for (var i = 1; i < n; i++) {
+          k++;
+          octets[i] = URIHexCharsToCharCode(uri.charAt(++k), uri.charAt(++k));
+        }
+        index = URIDecodeOctets(octets, result, index);
+      } else {
+        if (reserved(cc)) {
+          result[index++] = 37; // Char code of '%'.
+          result[index++] = uri.charCodeAt(k - 1);
+          result[index++] = uri.charCodeAt(k);
+        } else {
+          result[index++] = cc;
+        }
+      }
+    } else {
+      result[index++] = ch.charCodeAt(0);
+    }
+  }
+  result.length = index;
+  return %StringFromCharCodeArray(result);
+}
+
+
+// ECMA-262 - 15.1.3.1.
+function URIDecode(uri) {
+  function reservedPredicate(cc) {
+    // #$
+    if (35 <= cc && cc <= 36) return true;
+    // &
+    if (cc == 38) return true;
+    // +,
+    if (43 <= cc && cc <= 44) return true;
+    // /
+    if (cc == 47) return true;
+    // :;
+    if (58 <= cc && cc <= 59) return true;
+    // =
+    if (cc == 61) return true;
+    // ?@
+    if (63 <= cc && cc <= 64) return true;
+    
+    return false;
+  };
+  var string = ToString(uri);
+  return Decode(string, reservedPredicate);
+}
+
+
+// ECMA-262 - 15.1.3.2.
+function URIDecodeComponent(component) {
+  function reservedPredicate(cc) { return false; };
+  var string = ToString(component);
+  return Decode(string, reservedPredicate);
+}
+
+
+// Does the char code correspond to an alpha-numeric char.
+function isAlphaNumeric(cc) {
+  // a - z
+  if (97 <= cc && cc <= 122) return true;
+  // A - Z
+  if (65 <= cc && cc <= 90) return true;
+  // 0 - 9
+  if (48 <= cc && cc <= 57) return true;
+  
+  return false;
+}
+
+
+// ECMA-262 - 15.1.3.3.
+function URIEncode(uri) {
+  function unescapePredicate(cc) {
+    if (isAlphaNumeric(cc)) return true;
+    // !
+    if (cc == 33) return true;
+    // #$
+    if (35 <= cc && cc <= 36) return true;
+    // &'()*+,-./
+    if (38 <= cc && cc <= 47) return true;
+    // :;
+    if (58 <= cc && cc <= 59) return true;
+    // =
+    if (cc == 61) return true;
+    // ?@
+    if (63 <= cc && cc <= 64) return true;
+    // _
+    if (cc == 95) return true;
+    // ~
+    if (cc == 126) return true;
+    
+    return false;
+  };
+
+  var string = ToString(uri);
+  return Encode(string, unescapePredicate);
+}
+
+
+// ECMA-262 - 15.1.3.4
+function URIEncodeComponent(component) {
+  function unescapePredicate(cc) {
+    if (isAlphaNumeric(cc)) return true;
+    // !
+    if (cc == 33) return true;
+    // '()*
+    if (39 <= cc && cc <= 42) return true;
+    // -.
+    if (45 <= cc && cc <= 46) return true;
+    // _
+    if (cc == 95) return true;
+    // ~
+    if (cc == 126) return true;
+    
+    return false;
+  };
+
+  var string = ToString(component);
+  return Encode(string, unescapePredicate);
+}
+
+
+const hexCharArray = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+                      "A", "B", "C", "D", "E", "F"];
+
+const hexCharCodeArray = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+                          65, 66, 67, 68, 69, 70];
+
+
+function HexValueOf(c) {
+  var code = c.charCodeAt(0);
+  
+  // 0-9
+  if (code >= 48 && code <= 57) return code - 48;
+  // A-F
+  if (code >= 65 && code <= 70) return code - 55;
+  // a-f
+  if (code >= 97 && code <= 102) return code - 87;
+  
+  return -1;
+}
+
+
+// Convert a character code to 4-digit hex string representation
+// 64 -> 0040, 62234 -> F31A.
+function CharCodeToHex4Str(cc) {
+  var r = "";
+  for (var i = 0; i < 4; ++i) {
+    var c = hexCharArray[cc & 0x0F];
+    r = c + r;
+    cc = cc >>> 4;
+  }
+  return r;
+}
+
+
+// Converts hex string to char code. Not efficient.
+function HexStrToCharCode(s) {
+  var m = 0;
+  var r = 0;
+  for (var i = s.length - 1; i >= 0; --i) {
+    r = r + (HexValueOf(s.charAt(i)) << m);
+    m = m + 4;
+  }
+  return r;
+}
+
+
+// Returns true if all digits in string s are valid hex numbers
+function IsValidHex(s) {
+  for (var i = 0; i < s.length; ++i) {
+    var cc = s.charCodeAt(i);
+    if ((48 <= cc && cc <= 57) || (65 <= cc && cc <= 70) || (97 <= cc && cc <= 102)) {
+      // '0'..'9', 'A'..'F' and 'a' .. 'f'.
+    } else {
+      return false;
+    }
+  }
+  return true;
+}
+
+
+// ECMA-262 - B.2.1.
+function URIEscape(str) {
+  var s = ToString(str);
+  return %URIEscape(s);
+}
+
+
+// ECMA-262 - B.2.2.
+function URIUnescape(str) {
+  var s = ToString(str);
+  return %URIUnescape(s);
+}
+
+
+// -------------------------------------------------------------------
+
+function SetupURI() {
+  // Setup non-enumerable URI functions on the global object and set
+  // their names.
+  InstallFunctions(global, DONT_ENUM, $Array(
+    "escape", URIEscape,
+    "unescape", URIUnescape,
+    "decodeURI", URIDecode,
+    "decodeURIComponent", URIDecodeComponent,
+    "encodeURI", URIEncode,
+    "encodeURIComponent", URIEncodeComponent
+  ));
+}
+
+SetupURI();
+
diff --git a/deps/v8/src/usage-analyzer.cc b/deps/v8/src/usage-analyzer.cc
new file mode 100644
index 0000000..13176f7
--- /dev/null
+++ b/deps/v8/src/usage-analyzer.cc
@@ -0,0 +1,450 @@
+// 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.
+
+#include "v8.h"
+
+#include "ast.h"
+#include "scopes.h"
+#include "usage-analyzer.h"
+
+namespace v8 { namespace internal {
+
+// Weight boundaries
+static const int MinWeight = 1;
+static const int MaxWeight = 1000000;
+static const int InitialWeight = 100;
+
+
+class UsageComputer: public AstVisitor {
+ public:
+  static bool Traverse(Node* node);
+
+  void VisitBlock(Block* node);
+  void VisitDeclaration(Declaration* node);
+  void VisitExpressionStatement(ExpressionStatement* node);
+  void VisitEmptyStatement(EmptyStatement* node);
+  void VisitIfStatement(IfStatement* node);
+  void VisitContinueStatement(ContinueStatement* node);
+  void VisitBreakStatement(BreakStatement* node);
+  void VisitReturnStatement(ReturnStatement* node);
+  void VisitWithEnterStatement(WithEnterStatement* node);
+  void VisitWithExitStatement(WithExitStatement* node);
+  void VisitSwitchStatement(SwitchStatement* node);
+  void VisitLoopStatement(LoopStatement* node);
+  void VisitForInStatement(ForInStatement* node);
+  void VisitTryCatch(TryCatch* node);
+  void VisitTryFinally(TryFinally* node);
+  void VisitDebuggerStatement(DebuggerStatement* node);
+  void VisitFunctionLiteral(FunctionLiteral* node);
+  void VisitFunctionBoilerplateLiteral(FunctionBoilerplateLiteral* node);
+  void VisitConditional(Conditional* node);
+  void VisitSlot(Slot* node);
+  void VisitVariable(Variable* node);
+  void VisitVariableProxy(VariableProxy* node);
+  void VisitLiteral(Literal* node);
+  void VisitRegExpLiteral(RegExpLiteral* node);
+  void VisitObjectLiteral(ObjectLiteral* node);
+  void VisitArrayLiteral(ArrayLiteral* node);
+  void VisitCatchExtensionObject(CatchExtensionObject* node);
+  void VisitAssignment(Assignment* node);
+  void VisitThrow(Throw* node);
+  void VisitProperty(Property* node);
+  void VisitCall(Call* node);
+  void VisitCallEval(CallEval* node);
+  void VisitCallNew(CallNew* node);
+  void VisitCallRuntime(CallRuntime* node);
+  void VisitUnaryOperation(UnaryOperation* node);
+  void VisitCountOperation(CountOperation* node);
+  void VisitBinaryOperation(BinaryOperation* node);
+  void VisitCompareOperation(CompareOperation* node);
+  void VisitThisFunction(ThisFunction* node);
+
+ private:
+  int weight_;
+  bool is_write_;
+
+  UsageComputer(int weight, bool is_write);
+  virtual ~UsageComputer();
+
+  // Helper functions
+  void RecordUses(UseCount* uses);
+  void Read(Expression* x);
+  void Write(Expression* x);
+  void ReadList(ZoneList<Expression*>* list);
+  void ReadList(ZoneList<ObjectLiteral::Property*>* list);
+
+  friend class WeightScaler;
+};
+
+
+class WeightScaler BASE_EMBEDDED {
+ public:
+  WeightScaler(UsageComputer* uc, float scale);
+  ~WeightScaler();
+
+ private:
+  UsageComputer* uc_;
+  int old_weight_;
+};
+
+
+// ----------------------------------------------------------------------------
+// Implementation of UsageComputer
+
+bool UsageComputer::Traverse(Node* node) {
+  UsageComputer uc(InitialWeight, false);
+  uc.Visit(node);
+  return !uc.HasStackOverflow();
+}
+
+
+void UsageComputer::VisitBlock(Block* node) {
+  VisitStatements(node->statements());
+}
+
+
+void UsageComputer::VisitDeclaration(Declaration* node) {
+  Write(node->proxy());
+  if (node->fun() != NULL)
+    VisitFunctionLiteral(node->fun());
+}
+
+
+void UsageComputer::VisitExpressionStatement(ExpressionStatement* node) {
+  Visit(node->expression());
+}
+
+
+void UsageComputer::VisitEmptyStatement(EmptyStatement* node) {
+  // nothing to do
+}
+
+
+void UsageComputer::VisitIfStatement(IfStatement* node) {
+  Read(node->condition());
+  { WeightScaler ws(this, 0.5);  // executed 50% of the time
+    Visit(node->then_statement());
+    Visit(node->else_statement());
+  }
+}
+
+
+void UsageComputer::VisitContinueStatement(ContinueStatement* node) {
+  // nothing to do
+}
+
+
+void UsageComputer::VisitBreakStatement(BreakStatement* node) {
+  // nothing to do
+}
+
+
+void UsageComputer::VisitReturnStatement(ReturnStatement* node) {
+  Read(node->expression());
+}
+
+
+void UsageComputer::VisitWithEnterStatement(WithEnterStatement* node) {
+  Read(node->expression());
+}
+
+
+void UsageComputer::VisitWithExitStatement(WithExitStatement* node) {
+  // nothing to do
+}
+
+
+void UsageComputer::VisitSwitchStatement(SwitchStatement* node) {
+  Read(node->tag());
+  ZoneList<CaseClause*>* cases = node->cases();
+  for (int i = cases->length(); i-- > 0;) {
+    WeightScaler ws(this, static_cast<float>(1.0 / cases->length()));
+    CaseClause* clause = cases->at(i);
+    if (!clause->is_default())
+      Read(clause->label());
+    VisitStatements(clause->statements());
+  }
+}
+
+
+void UsageComputer::VisitLoopStatement(LoopStatement* node) {
+  if (node->init() != NULL)
+    Visit(node->init());
+  { WeightScaler ws(this, 10.0);  // executed in each iteration
+    if (node->cond() != NULL)
+      Read(node->cond());
+    if (node->next() != NULL)
+      Visit(node->next());
+    Visit(node->body());
+  }
+}
+
+
+void UsageComputer::VisitForInStatement(ForInStatement* node) {
+  WeightScaler ws(this, 10.0);
+  Write(node->each());
+  Read(node->enumerable());
+  Visit(node->body());
+}
+
+
+void UsageComputer::VisitTryCatch(TryCatch* node) {
+  Visit(node->try_block());
+  { WeightScaler ws(this, 0.25);
+    Write(node->catch_var());
+    Visit(node->catch_block());
+  }
+}
+
+
+void UsageComputer::VisitTryFinally(TryFinally* node) {
+  Visit(node->try_block());
+  Visit(node->finally_block());
+}
+
+
+void UsageComputer::VisitDebuggerStatement(DebuggerStatement* node) {
+}
+
+
+void UsageComputer::VisitFunctionLiteral(FunctionLiteral* node) {
+  ZoneList<Declaration*>* decls = node->scope()->declarations();
+  for (int i = 0; i < decls->length(); i++) VisitDeclaration(decls->at(i));
+  VisitStatements(node->body());
+}
+
+
+void UsageComputer::VisitFunctionBoilerplateLiteral(
+    FunctionBoilerplateLiteral* node) {
+  // Do nothing.
+}
+
+
+void UsageComputer::VisitConditional(Conditional* node) {
+  Read(node->condition());
+  { WeightScaler ws(this, 0.5);
+    Read(node->then_expression());
+    Read(node->else_expression());
+  }
+}
+
+
+void UsageComputer::VisitSlot(Slot* node) {
+  UNREACHABLE();
+}
+
+
+void UsageComputer::VisitVariable(Variable* node) {
+  RecordUses(node->var_uses());
+}
+
+
+void UsageComputer::VisitVariableProxy(VariableProxy* node) {
+  // The proxy may refer to a variable in which case it was bound via
+  // VariableProxy::BindTo.
+  RecordUses(node->var_uses());
+}
+
+
+void UsageComputer::VisitLiteral(Literal* node) {
+  // nothing to do
+}
+
+void UsageComputer::VisitRegExpLiteral(RegExpLiteral* node) {
+  // nothing to do
+}
+
+
+void UsageComputer::VisitObjectLiteral(ObjectLiteral* node) {
+  ReadList(node->properties());
+}
+
+
+void UsageComputer::VisitArrayLiteral(ArrayLiteral* node) {
+  ReadList(node->values());
+}
+
+
+void UsageComputer::VisitCatchExtensionObject(CatchExtensionObject* node) {
+  Read(node->value());
+}
+
+
+void UsageComputer::VisitAssignment(Assignment* node) {
+  if (node->op() != Token::ASSIGN)
+    Read(node->target());
+  Write(node->target());
+  Read(node->value());
+}
+
+
+void UsageComputer::VisitThrow(Throw* node) {
+  Read(node->exception());
+}
+
+
+void UsageComputer::VisitProperty(Property* node) {
+  // In any case (read or write) we read both the
+  // node's object and the key.
+  Read(node->obj());
+  Read(node->key());
+  // If the node's object is a variable proxy,
+  // we have a 'simple' object property access. We count
+  // the access via the variable or proxy's object uses.
+  VariableProxy* proxy = node->obj()->AsVariableProxy();
+  if (proxy != NULL) {
+    RecordUses(proxy->obj_uses());
+  }
+}
+
+
+void UsageComputer::VisitCall(Call* node) {
+  Read(node->expression());
+  ReadList(node->arguments());
+}
+
+
+void UsageComputer::VisitCallEval(CallEval* node) {
+  VisitCall(node);
+}
+
+
+void UsageComputer::VisitCallNew(CallNew* node) {
+  VisitCall(node);
+}
+
+
+void UsageComputer::VisitCallRuntime(CallRuntime* node) {
+  ReadList(node->arguments());
+}
+
+
+void UsageComputer::VisitUnaryOperation(UnaryOperation* node) {
+  Read(node->expression());
+}
+
+
+void UsageComputer::VisitCountOperation(CountOperation* node) {
+  Read(node->expression());
+  Write(node->expression());
+}
+
+
+void UsageComputer::VisitBinaryOperation(BinaryOperation* node) {
+  Read(node->left());
+  Read(node->right());
+}
+
+
+void UsageComputer::VisitCompareOperation(CompareOperation* node) {
+  Read(node->left());
+  Read(node->right());
+}
+
+
+void UsageComputer::VisitThisFunction(ThisFunction* node) {
+}
+
+
+UsageComputer::UsageComputer(int weight, bool is_write) {
+  weight_ = weight;
+  is_write_ = is_write;
+}
+
+
+UsageComputer::~UsageComputer() {
+  // nothing to do
+}
+
+
+void UsageComputer::RecordUses(UseCount* uses) {
+  if (is_write_)
+    uses->RecordWrite(weight_);
+  else
+    uses->RecordRead(weight_);
+}
+
+
+void UsageComputer::Read(Expression* x) {
+  if (is_write_) {
+    UsageComputer uc(weight_, false);
+    uc.Visit(x);
+  } else {
+    Visit(x);
+  }
+}
+
+
+void UsageComputer::Write(Expression* x) {
+  if (!is_write_) {
+    UsageComputer uc(weight_, true);
+    uc.Visit(x);
+  } else {
+    Visit(x);
+  }
+}
+
+
+void UsageComputer::ReadList(ZoneList<Expression*>* list) {
+  for (int i = list->length(); i-- > 0; )
+    Read(list->at(i));
+}
+
+
+void UsageComputer::ReadList(ZoneList<ObjectLiteral::Property*>* list) {
+  for (int i = list->length(); i-- > 0; )
+    Read(list->at(i)->value());
+}
+
+
+// ----------------------------------------------------------------------------
+// Implementation of WeightScaler
+
+WeightScaler::WeightScaler(UsageComputer* uc, float scale) {
+  uc_ = uc;
+  old_weight_ = uc->weight_;
+  int new_weight = static_cast<int>(uc->weight_ * scale);
+  if (new_weight <= 0) new_weight = MinWeight;
+  else if (new_weight > MaxWeight) new_weight = MaxWeight;
+  uc->weight_ = new_weight;
+}
+
+
+WeightScaler::~WeightScaler() {
+  uc_->weight_ = old_weight_;
+}
+
+
+// ----------------------------------------------------------------------------
+// Interface to variable usage analysis
+
+bool AnalyzeVariableUsage(FunctionLiteral* lit) {
+  if (!FLAG_usage_computation) return true;
+  return UsageComputer::Traverse(lit);
+}
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/usage-analyzer.h b/deps/v8/src/usage-analyzer.h
new file mode 100644
index 0000000..2732dd5
--- /dev/null
+++ b/deps/v8/src/usage-analyzer.h
@@ -0,0 +1,39 @@
+// 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_USAGE_ANALYSER_H_
+#define V8_USAGE_ANALYSER_H_
+
+namespace v8 { namespace internal {
+
+// Compute usage counts for all variables.
+// Used for variable allocation.
+bool AnalyzeVariableUsage(FunctionLiteral* lit);
+
+} }  // namespace v8::internal
+
+#endif  // V8_USAGE_ANALYSER_H_
diff --git a/deps/v8/src/utils.cc b/deps/v8/src/utils.cc
new file mode 100644
index 0000000..3920320
--- /dev/null
+++ b/deps/v8/src/utils.cc
@@ -0,0 +1,297 @@
+// 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.
+
+#include <stdarg.h>
+
+#include "v8.h"
+
+#include "platform.h"
+
+#include "sys/stat.h"
+
+namespace v8 { namespace internal {
+
+
+// Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.,
+// figure 3-3, page 48, where the function is called clp2.
+uint32_t RoundUpToPowerOf2(uint32_t x) {
+  x = x - 1;
+  x = x | (x >> 1);
+  x = x | (x >> 2);
+  x = x | (x >> 4);
+  x = x | (x >> 8);
+  x = x | (x >> 16);
+  return x + 1;
+}
+
+
+byte* EncodeInt(byte* p, int x) {
+  while (x < -64 || x >= 64) {
+    *p++ = static_cast<byte>(x & 127);
+    x = ArithmeticShiftRight(x, 7);
+  }
+  // -64 <= x && x < 64
+  *p++ = static_cast<byte>(x + 192);
+  return p;
+}
+
+
+byte* DecodeInt(byte* p, int* x) {
+  int r = 0;
+  unsigned int s = 0;
+  byte b = *p++;
+  while (b < 128) {
+    r |= static_cast<int>(b) << s;
+    s += 7;
+    b = *p++;
+  }
+  // b >= 128
+  *x = r | ((static_cast<int>(b) - 192) << s);
+  return p;
+}
+
+
+byte* EncodeUnsignedIntBackward(byte* p, unsigned int x) {
+  while (x >= 128) {
+    *--p = static_cast<byte>(x & 127);
+    x = x >> 7;
+  }
+  // x < 128
+  *--p = static_cast<byte>(x + 128);
+  return p;
+}
+
+
+void PrintF(const char* format, ...) {
+  va_list arguments;
+  va_start(arguments, format);
+  OS::VPrint(format, arguments);
+  va_end(arguments);
+}
+
+
+void Flush() {
+  fflush(stdout);
+}
+
+
+char* ReadLine(const char* prompt) {
+  char* result = NULL;
+  char line_buf[256];
+  int offset = 0;
+  bool keep_going = true;
+  fprintf(stdout, "%s", prompt);
+  fflush(stdout);
+  while (keep_going) {
+    if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) {
+      // fgets got an error. Just give up.
+      if (result != NULL) {
+        DeleteArray(result);
+      }
+      return NULL;
+    }
+    int len = strlen(line_buf);
+    if (len > 1 &&
+        line_buf[len - 2] == '\\' &&
+        line_buf[len - 1] == '\n') {
+      // When we read a line that ends with a "\" we remove the escape and
+      // append the remainder.
+      line_buf[len - 2] = '\n';
+      line_buf[len - 1] = 0;
+      len -= 1;
+    } else if ((len > 0) && (line_buf[len - 1] == '\n')) {
+      // Since we read a new line we are done reading the line. This
+      // will exit the loop after copying this buffer into the result.
+      keep_going = false;
+    }
+    if (result == NULL) {
+      // Allocate the initial result and make room for the terminating '\0'
+      result = NewArray<char>(len + 1);
+    } else {
+      // Allocate a new result with enough room for the new addition.
+      int new_len = offset + len + 1;
+      char* new_result = NewArray<char>(new_len);
+      // Copy the existing input into the new array and set the new
+      // array as the result.
+      memcpy(new_result, result, offset * kCharSize);
+      DeleteArray(result);
+      result = new_result;
+    }
+    // Copy the newly read line into the result.
+    memcpy(result + offset, line_buf, len * kCharSize);
+    offset += len;
+  }
+  ASSERT(result != NULL);
+  result[offset] = '\0';
+  return result;
+}
+
+
+char* ReadCharsFromFile(const char* filename,
+                        int* size,
+                        int extra_space,
+                        bool verbose) {
+  FILE* file = OS::FOpen(filename, "rb");
+  if (file == NULL || fseek(file, 0, SEEK_END) != 0) {
+    if (verbose) {
+      OS::PrintError("Cannot read from file %s.\n", filename);
+    }
+    return NULL;
+  }
+
+  // Get the size of the file and rewind it.
+  *size = ftell(file);
+  rewind(file);
+
+  char* result = NewArray<char>(*size + extra_space);
+  for (int i = 0; i < *size;) {
+    int read = fread(&result[i], 1, *size - i, file);
+    if (read <= 0) {
+      fclose(file);
+      DeleteArray(result);
+      return NULL;
+    }
+    i += read;
+  }
+  fclose(file);
+  return result;
+}
+
+
+byte* ReadBytes(const char* filename, int* size, bool verbose) {
+  char* chars = ReadCharsFromFile(filename, size, 0, verbose);
+  return reinterpret_cast<byte*>(chars);
+}
+
+
+Vector<const char> ReadFile(const char* filename,
+                            bool* exists,
+                            bool verbose) {
+  int size;
+  char* result = ReadCharsFromFile(filename, &size, 1, verbose);
+  if (!result) {
+    *exists = false;
+    return Vector<const char>::empty();
+  }
+  result[size] = '\0';
+  *exists = true;
+  return Vector<const char>(result, size);
+}
+
+
+int WriteCharsToFile(const char* str, int size, FILE* f) {
+  int total = 0;
+  while (total < size) {
+    int write = fwrite(str, 1, size - total, f);
+    if (write == 0) {
+      return total;
+    }
+    total += write;
+    str += write;
+  }
+  return total;
+}
+
+
+int WriteChars(const char* filename,
+               const char* str,
+               int size,
+               bool verbose) {
+  FILE* f = OS::FOpen(filename, "wb");
+  if (f == NULL) {
+    if (verbose) {
+      OS::PrintError("Cannot open file %s for reading.\n", filename);
+    }
+    return 0;
+  }
+  int written = WriteCharsToFile(str, size, f);
+  fclose(f);
+  return written;
+}
+
+
+int WriteBytes(const char* filename,
+               const byte* bytes,
+               int size,
+               bool verbose) {
+  const char* str = reinterpret_cast<const char*>(bytes);
+  return WriteChars(filename, str, size, verbose);
+}
+
+
+StringBuilder::StringBuilder(int size) {
+  buffer_ = Vector<char>::New(size);
+  position_ = 0;
+}
+
+
+void StringBuilder::AddString(const char* s) {
+  AddSubstring(s, strlen(s));
+}
+
+
+void StringBuilder::AddSubstring(const char* s, int n) {
+  ASSERT(!is_finalized() && position_ + n < buffer_.length());
+  ASSERT(static_cast<size_t>(n) <= strlen(s));
+  memcpy(&buffer_[position_], s, n * kCharSize);
+  position_ += n;
+}
+
+
+void StringBuilder::AddFormatted(const char* format, ...) {
+  ASSERT(!is_finalized() && position_ < buffer_.length());
+  va_list args;
+  va_start(args, format);
+  int n = OS::VSNPrintF(buffer_ + position_, format, args);
+  va_end(args);
+  if (n < 0 || n >= (buffer_.length() - position_)) {
+    position_ = buffer_.length();
+  } else {
+    position_ += n;
+  }
+}
+
+
+void StringBuilder::AddPadding(char c, int count) {
+  for (int i = 0; i < count; i++) {
+    AddCharacter(c);
+  }
+}
+
+
+char* StringBuilder::Finalize() {
+  ASSERT(!is_finalized() && position_ < buffer_.length());
+  buffer_[position_] = '\0';
+  // Make sure nobody managed to add a 0-character to the
+  // buffer while building the string.
+  ASSERT(strlen(buffer_.start()) == static_cast<size_t>(position_));
+  position_ = -1;
+  ASSERT(is_finalized());
+  return buffer_.start();
+}
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/utils.h b/deps/v8/src/utils.h
new file mode 100644
index 0000000..f62b47a
--- /dev/null
+++ b/deps/v8/src/utils.h
@@ -0,0 +1,540 @@
+// 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_UTILS_H_
+#define V8_UTILS_H_
+
+#include <stdlib.h>
+
+namespace v8 { namespace internal {
+
+// ----------------------------------------------------------------------------
+// General helper functions
+
+// Returns true iff x is a power of 2.  Does not work for zero.
+template <typename T>
+static inline bool IsPowerOf2(T x) {
+  return (x & (x - 1)) == 0;
+}
+
+
+
+
+// The C++ standard leaves the semantics of '>>' undefined for
+// negative signed operands. Most implementations do the right thing,
+// though.
+static inline int ArithmeticShiftRight(int x, int s) {
+  return x >> s;
+}
+
+
+// Compute the 0-relative offset of some absolute value x of type T.
+// This allows conversion of Addresses and integral types into
+// 0-relative int offsets.
+template <typename T>
+static inline int OffsetFrom(T x) {
+  return x - static_cast<T>(0);
+}
+
+
+// Compute the absolute value of type T for some 0-relative offset x.
+// This allows conversion of 0-relative int offsets into Addresses and
+// integral types.
+template <typename T>
+static inline T AddressFrom(int x) {
+  return static_cast<T>(0) + x;
+}
+
+
+// Return the largest multiple of m which is <= x.
+template <typename T>
+static inline T RoundDown(T x, int m) {
+  ASSERT(IsPowerOf2(m));
+  return AddressFrom<T>(OffsetFrom(x) & -m);
+}
+
+
+// Return the smallest multiple of m which is >= x.
+template <typename T>
+static inline T RoundUp(T x, int m) {
+  return RoundDown(x + m - 1, m);
+}
+
+
+template <typename T>
+static int Compare(const T& a, const T& b) {
+  if (a == b)
+    return 0;
+  else if (a < b)
+    return -1;
+  else
+    return 1;
+}
+
+
+template <typename T>
+static int PointerValueCompare(const T* a, const T* b) {
+  return Compare<T>(*a, *b);
+}
+
+
+// Returns the smallest power of two which is >= x. If you pass in a
+// number that is already a power of two, it is returned as is.
+uint32_t RoundUpToPowerOf2(uint32_t x);
+
+
+template <typename T>
+static inline bool IsAligned(T value, T alignment) {
+  ASSERT(IsPowerOf2(alignment));
+  return (value & (alignment - 1)) == 0;
+}
+
+
+// Returns true if (addr + offset) is aligned.
+static inline bool IsAddressAligned(Address addr, int alignment, int offset) {
+  int offs = OffsetFrom(addr + offset);
+  return IsAligned(offs, alignment);
+}
+
+
+// Returns the maximum of the two parameters.
+template <typename T>
+static T Max(T a, T b) {
+  return a < b ? b : a;
+}
+
+
+// Returns the minimum of the two parameters.
+template <typename T>
+static T Min(T a, T b) {
+  return a < b ? a : b;
+}
+
+
+// ----------------------------------------------------------------------------
+// BitField is a help template for encoding and decode bitfield with
+// unsigned content.
+template<class T, int shift, int size>
+class BitField {
+ public:
+  // Tells whether the provided value fits into the bit field.
+  static bool is_valid(T value) {
+    return (static_cast<uint32_t>(value) & ~((1U << (size)) - 1)) == 0;
+  }
+
+  // Returns a uint32_t mask of bit field.
+  static uint32_t mask() {
+    return (1U << (size + shift)) - (1U << shift);
+  }
+
+  // Returns a uint32_t with the bit field value encoded.
+  static uint32_t encode(T value) {
+    ASSERT(is_valid(value));
+    return static_cast<uint32_t>(value) << shift;
+  }
+
+  // Extracts the bit field from the value.
+  static T decode(uint32_t value) {
+    return static_cast<T>((value >> shift) & ((1U << (size)) - 1));
+  }
+};
+
+
+// ----------------------------------------------------------------------------
+// Support for compressed, machine-independent encoding
+// and decoding of integer values of arbitrary size.
+
+// Encoding and decoding from/to a buffer at position p;
+// the result is the position after the encoded integer.
+// Small signed integers in the range -64 <= x && x < 64
+// are encoded in 1 byte; larger values are encoded in 2
+// or more bytes. At most sizeof(int) + 1 bytes are used
+// in the worst case.
+byte* EncodeInt(byte* p, int x);
+byte* DecodeInt(byte* p, int* x);
+
+
+// Encoding and decoding from/to a buffer at position p - 1
+// moving backward; the result is the position of the last
+// byte written. These routines are useful to read/write
+// into a buffer starting at the end of the buffer.
+byte* EncodeUnsignedIntBackward(byte* p, unsigned int x);
+
+// The decoding function is inlined since its performance is
+// important to mark-sweep garbage collection.
+inline byte* DecodeUnsignedIntBackward(byte* p, unsigned int* x) {
+  byte b = *--p;
+  if (b >= 128) {
+    *x = static_cast<unsigned int>(b) - 128;
+    return p;
+  }
+  unsigned int r = static_cast<unsigned int>(b);
+  unsigned int s = 7;
+  b = *--p;
+  while (b < 128) {
+    r |= static_cast<unsigned int>(b) << s;
+    s += 7;
+    b = *--p;
+  }
+  // b >= 128
+  *x = r | ((static_cast<unsigned int>(b) - 128) << s);
+  return p;
+}
+
+
+// ----------------------------------------------------------------------------
+// I/O support.
+
+// Our version of printf(). Avoids compilation errors that we get
+// with standard printf when attempting to print pointers, etc.
+// (the errors are due to the extra compilation flags, which we
+// want elsewhere).
+void PrintF(const char* format, ...);
+
+// Our version of fflush.
+void Flush();
+
+
+// Read a line of characters after printing the prompt to stdout. The resulting
+// char* needs to be disposed off with DeleteArray by the caller.
+char* ReadLine(const char* prompt);
+
+
+// Read and return the raw bytes in a file. the size of the buffer is returned
+// in size.
+// The returned buffer must be freed by the caller.
+byte* ReadBytes(const char* filename, int* size, bool verbose = true);
+
+
+// Write size chars from str to the file given by filename.
+// The file is overwritten. Returns the number of chars written.
+int WriteChars(const char* filename,
+               const char* str,
+               int size,
+               bool verbose = true);
+
+
+// Write size bytes to the file given by filename.
+// The file is overwritten. Returns the number of bytes written.
+int WriteBytes(const char* filename,
+               const byte* bytes,
+               int size,
+               bool verbose = true);
+
+
+// Write the C code
+// const char* <varname> = "<str>";
+// const int <varname>_len = <len>;
+// to the file given by filename. Only the first len chars are written.
+int WriteAsCFile(const char* filename, const char* varname,
+                 const char* str, int size, bool verbose = true);
+
+
+// ----------------------------------------------------------------------------
+// Miscellaneous
+
+// A static resource holds a static instance that can be reserved in
+// a local scope using an instance of Access.  Attempts to re-reserve
+// the instance will cause an error.
+template <typename T>
+class StaticResource {
+ public:
+  StaticResource() : is_reserved_(false)  {}
+
+ private:
+  template <typename S> friend class Access;
+  T instance_;
+  bool is_reserved_;
+};
+
+
+// Locally scoped access to a static resource.
+template <typename T>
+class Access {
+ public:
+  explicit Access(StaticResource<T>* resource)
+    : resource_(resource)
+    , instance_(&resource->instance_) {
+    ASSERT(!resource->is_reserved_);
+    resource->is_reserved_ = true;
+  }
+
+  ~Access() {
+    resource_->is_reserved_ = false;
+    resource_ = NULL;
+    instance_ = NULL;
+  }
+
+  T* value()  { return instance_; }
+  T* operator -> ()  { return instance_; }
+
+ private:
+  StaticResource<T>* resource_;
+  T* instance_;
+};
+
+
+template <typename T>
+class Vector {
+ public:
+  Vector() : start_(NULL), length_(0) {}
+  Vector(T* data, int length) : start_(data), length_(length) {
+    ASSERT(length == 0 || (length > 0 && data != NULL));
+  }
+
+  static Vector<T> New(int length) {
+    return Vector<T>(NewArray<T>(length), length);
+  }
+
+  // Returns a vector using the same backing storage as this one,
+  // spanning from and including 'from', to but not including 'to'.
+  Vector<T> SubVector(int from, int to) {
+    ASSERT(from < length_);
+    ASSERT(to <= length_);
+    ASSERT(from < to);
+    return Vector<T>(start() + from, to - from);
+  }
+
+  // Returns the length of the vector.
+  int length() const { return length_; }
+
+  // Returns whether or not the vector is empty.
+  bool is_empty() const { return length_ == 0; }
+
+  // Returns the pointer to the start of the data in the vector.
+  T* start() const { return start_; }
+
+  // Access individual vector elements - checks bounds in debug mode.
+  T& operator[](int index) const {
+    ASSERT(0 <= index && index < length_);
+    return start_[index];
+  }
+
+  T& first() { return start_[0]; }
+
+  T& last() { return start_[length_ - 1]; }
+
+  // Returns a clone of this vector with a new backing store.
+  Vector<T> Clone() const {
+    T* result = NewArray<T>(length_);
+    for (int i = 0; i < length_; i++) result[i] = start_[i];
+    return Vector<T>(result, length_);
+  }
+
+  void Sort(int (*cmp)(const T*, const T*)) {
+    typedef int (*RawComparer)(const void*, const void*);
+    qsort(start(),
+          length(),
+          sizeof(T),
+          reinterpret_cast<RawComparer>(cmp));
+  }
+
+  void Sort() {
+    Sort(PointerValueCompare<T>);
+  }
+
+  // Releases the array underlying this vector. Once disposed the
+  // vector is empty.
+  void Dispose() {
+    if (is_empty()) return;
+    DeleteArray(start_);
+    start_ = NULL;
+    length_ = 0;
+  }
+
+  inline Vector<T> operator+(int offset) {
+    ASSERT(offset < length_);
+    return Vector<T>(start_ + offset, length_ - offset);
+  }
+
+  // Factory method for creating empty vectors.
+  static Vector<T> empty() { return Vector<T>(NULL, 0); }
+
+ private:
+  T* start_;
+  int length_;
+};
+
+
+// A temporary assignment sets a (non-local) variable to a value on
+// construction and resets it the value on destruction.
+template <typename T>
+class TempAssign {
+ public:
+  TempAssign(T* var, T value): var_(var), old_value_(*var) {
+    *var = value;
+  }
+
+  ~TempAssign() { *var_ = old_value_; }
+
+ private:
+  T* var_;
+  T old_value_;
+};
+
+
+template <typename T, int kSize>
+class EmbeddedVector : public Vector<T> {
+ public:
+  EmbeddedVector() : Vector<T>(buffer_, kSize) { }
+ private:
+  T buffer_[kSize];
+};
+
+
+inline Vector<const char> CStrVector(const char* data) {
+  return Vector<const char>(data, strlen(data));
+}
+
+inline Vector<char> MutableCStrVector(char* data) {
+  return Vector<char>(data, strlen(data));
+}
+
+inline Vector<char> MutableCStrVector(char* data, int max) {
+  int length = strlen(data);
+  return Vector<char>(data, (length < max) ? length : max);
+}
+
+template <typename T>
+inline Vector< Handle<Object> > HandleVector(v8::internal::Handle<T>* elms,
+                                             int length) {
+  return Vector< Handle<Object> >(
+      reinterpret_cast<v8::internal::Handle<Object>*>(elms), length);
+}
+
+
+// Simple support to read a file into a 0-terminated C-string.
+// The returned buffer must be freed by the caller.
+// On return, *exits tells whether the file existed.
+Vector<const char> ReadFile(const char* filename,
+                            bool* exists,
+                            bool verbose = true);
+
+
+// Simple wrapper that allows an ExternalString to refer to a
+// Vector<const char>. Doesn't assume ownership of the data.
+class AsciiStringAdapter: public v8::String::ExternalAsciiStringResource {
+ public:
+  explicit AsciiStringAdapter(Vector<const char> data) : data_(data) {}
+
+  virtual const char* data() const { return data_.start(); }
+
+  virtual size_t length() const { return data_.length(); }
+
+ private:
+  Vector<const char> data_;
+};
+
+
+// Helper class for building result strings in a character buffer. The
+// purpose of the class is to use safe operations that checks the
+// buffer bounds on all operations in debug mode.
+class StringBuilder {
+ public:
+  // Create a string builder with a buffer of the given size. The
+  // buffer is allocated through NewArray<char> and must be
+  // deallocated by the caller of Finalize().
+  explicit StringBuilder(int size);
+
+  StringBuilder(char* buffer, int size)
+      : buffer_(buffer, size), position_(0) { }
+
+  ~StringBuilder() { if (!is_finalized()) Finalize(); }
+
+  int size() const { return buffer_.length(); }
+
+  // Get the current position in the builder.
+  int position() const {
+    ASSERT(!is_finalized());
+    return position_;
+  }
+
+  // Reset the position.
+  void Reset() { position_ = 0; }
+
+  // Add a single character to the builder. It is not allowed to add
+  // 0-characters; use the Finalize() method to terminate the string
+  // instead.
+  void AddCharacter(char c) {
+    ASSERT(c != '\0');
+    ASSERT(!is_finalized() && position_ < buffer_.length());
+    buffer_[position_++] = c;
+  }
+
+  // Add an entire string to the builder. Uses strlen() internally to
+  // compute the length of the input string.
+  void AddString(const char* s);
+
+  // Add the first 'n' characters of the given string 's' to the
+  // builder. The input string must have enough characters.
+  void AddSubstring(const char* s, int n);
+
+  // Add formatted contents to the builder just like printf().
+  void AddFormatted(const char* format, ...);
+
+  // Add character padding to the builder. If count is non-positive,
+  // nothing is added to the builder.
+  void AddPadding(char c, int count);
+
+  // Finalize the string by 0-terminating it and returning the buffer.
+  char* Finalize();
+
+ private:
+  Vector<char> buffer_;
+  int position_;
+
+  bool is_finalized() const { return position_ < 0; }
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
+};
+
+
+// Copy from ASCII/16bit chars to ASCII/16bit chars.
+template <typename sourcechar, typename sinkchar>
+static inline void CopyChars(sinkchar* dest, const sourcechar* src, int chars) {
+  sinkchar* limit = dest + chars;
+#ifdef CAN_READ_UNALIGNED
+  if (sizeof(*dest) == sizeof(*src)) {
+    // Number of characters in a uint32_t.
+    static const int kStepSize = sizeof(uint32_t) / sizeof(*dest);  // NOLINT
+    while (dest <= limit - kStepSize) {
+      *reinterpret_cast<uint32_t*>(dest) =
+          *reinterpret_cast<const uint32_t*>(src);
+      dest += kStepSize;
+      src += kStepSize;
+    }
+  }
+#endif
+  while (dest < limit) {
+    *dest++ = static_cast<sinkchar>(*src++);
+  }
+}
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_UTILS_H_
diff --git a/deps/v8/src/v8-counters.cc b/deps/v8/src/v8-counters.cc
new file mode 100644
index 0000000..3a8286a
--- /dev/null
+++ b/deps/v8/src/v8-counters.cc
@@ -0,0 +1,54 @@
+// 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.
+
+#include "v8.h"
+
+#include "v8-counters.h"
+
+namespace v8 { namespace internal {
+
+#define HT(name, caption) \
+  HistogramTimer Counters::name = { #caption, NULL, false, 0, 0 }; \
+
+  HISTOGRAM_TIMER_LIST(HT)
+#undef SR
+
+#define SC(name, caption) \
+  StatsCounter Counters::name = { "c:" #caption, NULL, false };
+
+  STATS_COUNTER_LIST_1(SC)
+  STATS_COUNTER_LIST_2(SC)
+#undef SC
+
+StatsCounter Counters::state_counters[] = {
+#define COUNTER_NAME(name) \
+  { "c:V8.State" #name, NULL, false },
+  STATE_TAG_LIST(COUNTER_NAME)
+#undef COUNTER_NAME
+};
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/v8-counters.h b/deps/v8/src/v8-counters.h
new file mode 100644
index 0000000..6596dbf
--- /dev/null
+++ b/deps/v8/src/v8-counters.h
@@ -0,0 +1,162 @@
+// 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.
+
+#ifndef V8_V8_COUNTERS_H_
+#define V8_V8_COUNTERS_H_
+
+#include "counters.h"
+
+namespace v8 { namespace internal {
+
+#define HISTOGRAM_TIMER_LIST(HT)                                 \
+  HT(gc_compactor, V8.GCCompactor) /* GC Compactor time */       \
+  HT(gc_scavenger, V8.GCScavenger) /* GC Scavenger time */       \
+  HT(gc_context, V8.GCContext)     /* GC context cleanup time */ \
+  HT(compile, V8.Compile)          /* Compile time*/             \
+  HT(compile_eval, V8.CompileEval) /* Eval compile time */       \
+  HT(compile_lazy, V8.CompileLazy) /* Lazy compile time */       \
+  HT(parse, V8.Parse)              /* Parse time */              \
+  HT(parse_lazy, V8.ParseLazy)     /* Lazy parse time */         \
+  HT(pre_parse, V8.PreParse)       /* Pre-parse time */
+
+// WARNING: STATS_COUNTER_LIST_* is a very large macro that is causing MSVC
+// Intellisense to crash.  It was broken into two macros (each of length 40
+// lines) rather than one macro (of length about 80 lines) to work around
+// this problem.  Please avoid using recursive macros of this length when
+// possible.
+#define STATS_COUNTER_LIST_1(SC)                                 \
+  /* Global Handle Count*/                                       \
+  SC(global_handles, V8.GlobalHandles)                           \
+  /* Mallocs from PCRE */                                        \
+  SC(pcre_mallocs, V8.PcreMallocCount)                           \
+  /* OS Memory allocated */                                      \
+  SC(memory_allocated, V8.OsMemoryAllocated)                     \
+  SC(props_to_dictionary, V8.ObjectPropertiesToDictionary)       \
+  SC(elements_to_dictionary, V8.ObjectElementsToDictionary)      \
+  SC(alive_after_last_gc, V8.AliveAfterLastGC)                   \
+  SC(objs_since_last_young, V8.ObjsSinceLastYoung)               \
+  SC(objs_since_last_full, V8.ObjsSinceLastFull)                 \
+  SC(symbol_table_capacity, V8.SymbolTableCapacity)              \
+  SC(number_of_symbols, V8.NumberOfSymbols)                      \
+  /* Current amount of memory in external string buffers. */     \
+  SC(total_external_string_memory, V8.TotalExternalStringMemory) \
+  SC(script_wrappers, V8.ScriptWrappers)                         \
+  SC(call_initialize_stubs, V8.CallInitializeStubs)              \
+  SC(call_premonomorphic_stubs, V8.CallPreMonomorphicStubs)      \
+  SC(call_normal_stubs, V8.CallNormalStubs)                      \
+  SC(call_megamorphic_stubs, V8.CallMegamorphicStubs)            \
+  SC(arguments_adaptors, V8.ArgumentsAdaptors)                   \
+  SC(compilation_cache_hits, V8.CompilationCacheHits)            \
+  SC(compilation_cache_misses, V8.CompilationCacheMisses)        \
+  SC(regexp_cache_hits, V8.RegExpCacheHits)                      \
+  SC(regexp_cache_misses, V8.RegExpCacheMisses)                  \
+  /* Amount of evaled source code. */                            \
+  SC(total_eval_size, V8.TotalEvalSize)                          \
+  /* Amount of loaded source code. */                            \
+  SC(total_load_size, V8.TotalLoadSize)                          \
+  /* Amount of parsed source code. */                            \
+  SC(total_parse_size, V8.TotalParseSize)                        \
+  /* Amount of source code skipped over using preparsing. */     \
+  SC(total_preparse_skipped, V8.TotalPreparseSkipped)            \
+  /* Amount of compiled source code. */                          \
+  SC(total_compile_size, V8.TotalCompileSize)
+
+
+#define STATS_COUNTER_LIST_2(SC)                                    \
+  /* Number of code stubs. */                                       \
+  SC(code_stubs, V8.CodeStubs)                                      \
+  /* Amount of stub code. */                                        \
+  SC(total_stubs_code_size, V8.TotalStubsCodeSize)                  \
+  /* Amount of (JS) compiled code. */                               \
+  SC(total_compiled_code_size, V8.TotalCompiledCodeSize)            \
+  SC(gc_compactor_caused_by_request, V8.GCCompactorCausedByRequest) \
+  SC(gc_compactor_caused_by_promoted_data,                          \
+     V8.GCCompactorCausedByPromotedData)                            \
+  SC(gc_compactor_caused_by_oldspace_exhaustion,                    \
+     V8.GCCompactorCausedByOldspaceExhaustion)                      \
+  SC(gc_compactor_caused_by_weak_handles,                           \
+     V8.GCCompactorCausedByWeakHandles)                             \
+  SC(gc_last_resort_from_js, V8.GCLastResortFromJS)                 \
+  SC(gc_last_resort_from_handles, V8.GCLastResortFromHandles)       \
+  /* How is the generic keyed-load stub used? */                    \
+  SC(keyed_load_generic_smi, V8.KeyedLoadGenericSmi)                \
+  SC(keyed_load_generic_symbol, V8.KeyedLoadGenericSymbol)          \
+  SC(keyed_load_generic_slow, V8.KeyedLoadGenericSlow)              \
+  /* Count how much the monomorphic keyed-load stubs are hit. */    \
+  SC(keyed_load_function_prototype, V8.KeyedLoadFunctionPrototype)  \
+  SC(keyed_load_string_length, V8.KeyedLoadStringLength)            \
+  SC(keyed_load_array_length, V8.KeyedLoadArrayLength)              \
+  SC(keyed_load_constant_function, V8.KeyedLoadConstantFunction)    \
+  SC(keyed_load_field, V8.KeyedLoadField)                           \
+  SC(keyed_load_callback, V8.KeyedLoadCallback)                     \
+  SC(keyed_load_interceptor, V8.KeyedLoadInterceptor)               \
+  SC(keyed_load_inline, V8.KeyedLoadInline)                         \
+  SC(keyed_load_inline_miss, V8.KeyedLoadInlineMiss)                \
+  SC(keyed_store_field, V8.KeyedStoreField)                         \
+  SC(for_in, V8.ForIn)                                              \
+  SC(enum_cache_hits, V8.EnumCacheHits)                             \
+  SC(enum_cache_misses, V8.EnumCacheMisses)                         \
+  SC(reloc_info_count, V8.RelocInfoCount)                           \
+  SC(reloc_info_size, V8.RelocInfoSize)                             \
+  SC(zone_segment_bytes, V8.ZoneSegmentBytes)
+
+
+// This file contains all the v8 counters that are in use.
+class Counters : AllStatic {
+ public:
+#define HT(name, caption) \
+  static HistogramTimer name;
+  HISTOGRAM_TIMER_LIST(HT)
+#undef HT
+
+#define SC(name, caption) \
+  static StatsCounter name;
+  STATS_COUNTER_LIST_1(SC)
+  STATS_COUNTER_LIST_2(SC)
+#undef SC
+
+  enum Id {
+#define RATE_ID(name, caption) k_##name,
+    HISTOGRAM_TIMER_LIST(RATE_ID)
+#undef RATE_ID
+#define COUNTER_ID(name, caption) k_##name,
+  STATS_COUNTER_LIST_1(COUNTER_ID)
+  STATS_COUNTER_LIST_2(COUNTER_ID)
+#undef COUNTER_ID
+#define COUNTER_ID(name) k_##name,
+  STATE_TAG_LIST(COUNTER_ID)
+#undef COUNTER_ID
+    stats_counter_count
+  };
+
+  // Sliding state window counters.
+  static StatsCounter state_counters[];
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_COUNTERS_H_
diff --git a/deps/v8/src/v8.cc b/deps/v8/src/v8.cc
new file mode 100644
index 0000000..9158b52
--- /dev/null
+++ b/deps/v8/src/v8.cc
@@ -0,0 +1,120 @@
+// 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.
+
+#include "v8.h"
+
+#include "bootstrapper.h"
+#include "debug.h"
+#include "serialize.h"
+#include "stub-cache.h"
+#include "oprofile-agent.h"
+
+namespace v8 { namespace internal {
+
+bool V8::has_been_setup_ = false;
+bool V8::has_been_disposed_ = false;
+
+bool V8::Initialize(Deserializer *des) {
+  bool create_heap_objects = des == NULL;
+  if (HasBeenDisposed()) return false;
+  if (HasBeenSetup()) return true;
+  has_been_setup_ = true;
+#ifdef DEBUG
+  // The initialization process does not handle memory exhaustion.
+  DisallowAllocationFailure disallow_allocation_failure;
+#endif
+
+  // Enable logging before setting up the heap
+  Logger::Setup();
+  if (des) des->GetLog();
+
+  // Setup the platform OS support.
+  OS::Setup();
+
+  // Setup the object heap
+  ASSERT(!Heap::HasBeenSetup());
+  if (!Heap::Setup(create_heap_objects)) {
+    has_been_setup_ = false;
+    return false;
+  }
+
+  // Initialize other runtime facilities
+  Bootstrapper::Initialize(create_heap_objects);
+  Builtins::Setup(create_heap_objects);
+  Top::Initialize();
+
+  if (FLAG_preemption) {
+    v8::Locker locker;
+    v8::Locker::StartPreemption(100);
+  }
+
+  Debug::Setup(create_heap_objects);
+  StubCache::Initialize(create_heap_objects);
+
+  // If we are deserializing, read the state into the now-empty heap.
+  if (des != NULL) {
+    des->Deserialize();
+    StubCache::Clear();
+  }
+
+  // Setup the CPU support. Must be done after heap setup and after
+  // any deserialization because we have to have the initial heap
+  // objects in place for creating the code object used for probing.
+  CPU::Setup();
+
+  OProfileAgent::Initialize();
+
+  return true;
+}
+
+
+void V8::TearDown() {
+  if (HasBeenDisposed()) return;
+  if (!HasBeenSetup()) return;
+
+  OProfileAgent::TearDown();
+
+  if (FLAG_preemption) {
+    v8::Locker locker;
+    v8::Locker::StopPreemption();
+  }
+
+  Builtins::TearDown();
+  Bootstrapper::TearDown();
+
+  Top::TearDown();
+
+  Heap::TearDown();
+  Logger::TearDown();
+
+  Debugger::TearDown();
+
+  has_been_setup_ = false;
+  has_been_disposed_ = true;
+}
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/v8.h b/deps/v8/src/v8.h
new file mode 100644
index 0000000..4cf0b70
--- /dev/null
+++ b/deps/v8/src/v8.h
@@ -0,0 +1,97 @@
+// 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.
+
+//
+// Top include for all V8 .cc files.
+//
+
+#ifndef V8_V8_H_
+#define V8_V8_H_
+
+#if defined(GOOGLE3)
+// Google3 special flag handling.
+#if defined(DEBUG) && defined(NDEBUG)
+// If both are defined in Google3, then we are building an optimized v8 with
+// assertions enabled.
+#undef NDEBUG
+#elif !defined(DEBUG) && !defined(NDEBUG)
+// If neither is defined in Google3, then we are building a debug v8. Mark it
+// as such.
+#define DEBUG
+#endif
+#endif  // defined(GOOGLE3)
+
+// V8 only uses DEBUG, but included external files
+// may use NDEBUG - make sure they are consistent.
+#if defined(DEBUG) && defined(NDEBUG)
+#error both DEBUG and NDEBUG are set
+#endif
+
+// Basic includes
+#include "../include/v8.h"
+#include "globals.h"
+#include "checks.h"
+#include "allocation.h"
+#include "utils.h"
+#include "flags.h"
+
+// Objects & heap
+#include "objects.h"
+#include "spaces.h"
+#include "heap.h"
+#include "objects-inl.h"
+#include "spaces-inl.h"
+#include "heap-inl.h"
+#include "messages.h"
+
+namespace v8 { namespace internal {
+
+class V8 : public AllStatic {
+ public:
+  // Global actions.
+
+  // If Initialize is called with des == NULL, the
+  // initial state is created from scratch. If a non-null Deserializer
+  // is given, the initial state is created by reading the
+  // deserialized data into an empty heap.
+  static bool Initialize(Deserializer* des);
+  static void TearDown();
+  static bool HasBeenSetup() { return has_been_setup_; }
+  static bool HasBeenDisposed() { return has_been_disposed_; }
+
+  // Report process out of memory. Implementation found in api.cc.
+  static void FatalProcessOutOfMemory(const char* location);
+ private:
+  static bool has_been_setup_;
+  static bool has_been_disposed_;
+};
+
+} }  // namespace v8::internal
+
+namespace i = v8::internal;
+
+#endif  // V8_V8_H_
diff --git a/deps/v8/src/v8natives.js b/deps/v8/src/v8natives.js
new file mode 100644
index 0000000..9772e2f
--- /dev/null
+++ b/deps/v8/src/v8natives.js
@@ -0,0 +1,540 @@
+// 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.
+
+// This file relies on the fact that the following declarations have been made
+//
+// in runtime.js:
+// const $Object = global.Object;
+// const $Boolean = global.Boolean;
+// const $Number = global.Number;
+// const $Function = global.Function;
+// const $Array = global.Array;
+// const $NaN = 0/0;
+//
+// in math.js:
+// const $floor = MathFloor
+
+const $isNaN = GlobalIsNaN;
+const $isFinite = GlobalIsFinite;
+
+// ----------------------------------------------------------------------------
+
+
+// Helper function used to install functions on objects.
+function InstallFunctions(object, attributes, functions) {
+  for (var i = 0; i < functions.length; i += 2) {
+    var key = functions[i];
+    var f = functions[i + 1];
+    %FunctionSetName(f, key);
+    %SetProperty(object, key, f, attributes);
+  }
+}
+
+
+// ----------------------------------------------------------------------------
+
+
+// ECMA 262 - 15.1.4
+function GlobalIsNaN(number) {
+  var n = ToNumber(number);
+  return NUMBER_IS_NAN(n);
+}
+
+
+// ECMA 262 - 15.1.5
+function GlobalIsFinite(number) {
+  return %NumberIsFinite(ToNumber(number));
+}
+
+
+// ECMA-262 - 15.1.2.2
+function GlobalParseInt(string, radix) {
+  if (radix === void 0) {
+    // Some people use parseInt instead of Math.floor.  This
+    // optimization makes parseInt on a Smi 12 times faster (60ns
+    // vs 800ns).  The following optimization makes parseInt on a
+    // non-Smi number 9 times faster (230ns vs 2070ns).  Together
+    // they make parseInt on a string 1.4% slower (274ns vs 270ns).
+    if (%_IsSmi(string)) return string;
+    if (IS_NUMBER(string) &&
+        ((string < -0.01 && -1e9 < string) ||
+            (0.01 < string && string < 1e9))) {
+      // Truncate number.
+      return string | 0;
+    }
+    radix = 0;
+  } else {
+    radix = TO_INT32(radix);
+    if (!(radix == 0 || (2 <= radix && radix <= 36)))
+      return $NaN;
+  }
+  return %StringParseInt(ToString(string), radix);
+}
+
+
+// ECMA-262 - 15.1.2.3
+function GlobalParseFloat(string) {
+  return %StringParseFloat(ToString(string));
+}
+
+
+function GlobalEval(x) {
+  if (!IS_STRING(x)) return x;
+
+  if (this !== global && this !== %GlobalReceiver(global)) {
+    throw new $EvalError('The "this" object passed to eval must ' + 
+                         'be the global object from which eval originated');
+  }
+  
+  var f = %CompileString(x, 0);
+  if (!IS_FUNCTION(f)) return f;
+
+  return f.call(this);
+}
+
+
+// execScript for IE compatibility.
+function GlobalExecScript(expr, lang) {
+  // NOTE: We don't care about the character casing.
+  if (!lang || /javascript/i.test(lang)) {
+    var f = %CompileString(ToString(expr), 0);
+    f.call(%GlobalReceiver(global));
+  }
+  return null;
+}
+
+
+// ----------------------------------------------------------------------------
+
+
+function SetupGlobal() {
+  // ECMA 262 - 15.1.1.1.
+  %SetProperty(global, "NaN", $NaN, DONT_ENUM | DONT_DELETE);
+
+  // ECMA-262 - 15.1.1.2.
+  %SetProperty(global, "Infinity", 1/0, DONT_ENUM | DONT_DELETE);
+
+  // ECMA-262 - 15.1.1.3.
+  %SetProperty(global, "undefined", void 0, DONT_ENUM | DONT_DELETE);
+  
+  // Setup non-enumerable function on the global object.
+  InstallFunctions(global, DONT_ENUM, $Array(
+    "isNaN", GlobalIsNaN,
+    "isFinite", GlobalIsFinite,
+    "parseInt", GlobalParseInt,
+    "parseFloat", GlobalParseFloat,
+    "eval", GlobalEval,
+    "execScript", GlobalExecScript
+  ));
+}
+
+SetupGlobal();
+
+
+// ----------------------------------------------------------------------------
+// Boolean (first part of definition)
+
+
+%SetCode($Boolean, function(x) {
+  if (%IsConstructCall()) {
+    %_SetValueOf(this, ToBoolean(x));
+  } else {
+    return ToBoolean(x);
+  }
+});
+
+%FunctionSetPrototype($Boolean, new $Boolean(false));
+
+%SetProperty($Boolean.prototype, "constructor", $Boolean, DONT_ENUM);
+
+// ----------------------------------------------------------------------------
+// Object
+
+$Object.prototype.constructor = $Object;
+
+// ECMA-262 - 15.2.4.2
+function ObjectToString() {
+  var c = %ClassOf(this);
+  // Hide Arguments from the outside.
+  if (c === 'Arguments') c  = 'Object';
+  return "[object " + c + "]";
+}
+
+
+// ECMA-262 - 15.2.4.3
+function ObjectToLocaleString() {
+  return this.toString();
+}
+
+
+// ECMA-262 - 15.2.4.4
+function ObjectValueOf() {
+  return this;
+}
+
+
+// ECMA-262 - 15.2.4.5
+function ObjectHasOwnProperty(V) {
+  return %HasLocalProperty(ToObject(this), ToString(V));
+}
+
+
+// ECMA-262 - 15.2.4.6
+function ObjectIsPrototypeOf(V) {
+  if (!IS_OBJECT(V) && !IS_FUNCTION(V)) return false;
+  return %IsInPrototypeChain(this, V);
+}
+
+
+// ECMA-262 - 15.2.4.6
+function ObjectPropertyIsEnumerable(V) {
+  if (this == null) return false;
+  if (!IS_OBJECT(this) && !IS_FUNCTION(this)) return false;
+  return %IsPropertyEnumerable(this, ToString(V));
+}
+
+
+// Extensions for providing property getters and setters.
+function ObjectDefineGetter(name, fun) {
+  if (this == null) {
+    throw new $TypeError('Object.prototype.__defineGetter__: this is Null');
+  }
+  if (!IS_FUNCTION(fun)) {
+    throw new $TypeError('Object.prototype.__defineGetter__: Expecting function');
+  }
+  return %DefineAccessor(ToObject(this), ToString(name), GETTER, fun);
+}
+
+
+function ObjectLookupGetter(name) {
+  if (this == null) {
+    throw new $TypeError('Object.prototype.__lookupGetter__: this is Null');
+  }
+  return %LookupAccessor(ToObject(this), ToString(name), GETTER);
+}
+
+
+function ObjectDefineSetter(name, fun) {
+  if (this == null) {
+    throw new $TypeError('Object.prototype.__defineSetter__: this is Null');
+  }
+  if (!IS_FUNCTION(fun)) {
+    throw new $TypeError(
+        'Object.prototype.__defineSetter__: Expecting function');
+  }
+  return %DefineAccessor(ToObject(this), ToString(name), SETTER, fun);
+}
+
+
+function ObjectLookupSetter(name) {
+  if (this == null) {
+    throw new $TypeError('Object.prototype.__lookupSetter__: this is Null');
+  }
+  return %LookupAccessor(ToObject(this), ToString(name), SETTER);
+}
+
+
+%SetCode($Object, function(x) {
+  if (%IsConstructCall()) {
+    if (x == null) return this;
+    return ToObject(x);
+  } else {
+    if (x == null) return { };
+    return ToObject(x);
+  }
+});
+
+
+// ----------------------------------------------------------------------------
+
+
+function SetupObject() {
+  // Setup non-enumerable functions on the Object.prototype object.
+  InstallFunctions($Object.prototype, DONT_ENUM, $Array(
+    "toString", ObjectToString,
+    "toLocaleString", ObjectToLocaleString,
+    "valueOf", ObjectValueOf,
+    "hasOwnProperty", ObjectHasOwnProperty,
+    "isPrototypeOf", ObjectIsPrototypeOf,
+    "propertyIsEnumerable", ObjectPropertyIsEnumerable,
+    "__defineGetter__", ObjectDefineGetter,
+    "__lookupGetter__", ObjectLookupGetter,
+    "__defineSetter__", ObjectDefineSetter,
+    "__lookupSetter__", ObjectLookupSetter
+  ));
+}
+
+SetupObject();
+
+
+// ----------------------------------------------------------------------------
+// Boolean
+
+function BooleanToString() {
+  // NOTE: Both Boolean objects and values can enter here as
+  // 'this'. This is not as dictated by ECMA-262.
+  if (!IS_BOOLEAN(this) && !%HasBooleanClass(this))
+    throw new $TypeError('Boolean.prototype.toString is not generic');
+  return ToString(%_ValueOf(this));
+}
+
+
+function BooleanValueOf() {
+  // NOTE: Both Boolean objects and values can enter here as
+  // 'this'. This is not as dictated by ECMA-262.
+  if (!IS_BOOLEAN(this) && !%HasBooleanClass(this))
+    throw new $TypeError('Boolean.prototype.valueOf is not generic');
+  return %_ValueOf(this);
+}
+
+
+// ----------------------------------------------------------------------------
+
+
+function SetupBoolean() {
+  InstallFunctions($Boolean.prototype, DONT_ENUM, $Array(
+    "toString", BooleanToString,
+    "valueOf", BooleanValueOf
+  ));
+}
+
+SetupBoolean();
+
+// ----------------------------------------------------------------------------
+// Number
+
+// Set the Number function and constructor.
+%SetCode($Number, function(x) {
+  var value = %_ArgumentsLength() == 0 ? 0 : ToNumber(x);
+  if (%IsConstructCall()) {
+    %_SetValueOf(this, value);
+  } else {
+    return value;
+  }
+});
+
+%FunctionSetPrototype($Number, new $Number(0));
+
+// ECMA-262 section 15.7.4.2.
+function NumberToString(radix) {
+  // NOTE: Both Number objects and values can enter here as
+  // 'this'. This is not as dictated by ECMA-262.
+  var number = this;
+  if (!IS_NUMBER(this)) {
+    if (!%HasNumberClass(this))
+      throw new $TypeError('Number.prototype.toString is not generic');
+    // Get the value of this number in case it's an object.
+    number = %_ValueOf(this);
+  }
+  // Fast case: Convert number in radix 10.
+  if (IS_UNDEFINED(radix) || radix === 10) {
+    return ToString(number);
+  }
+
+  // Convert the radix to an integer and check the range.
+  radix = TO_INTEGER(radix);
+  if (radix < 2 || radix > 36) {
+    throw new $RangeError('toString() radix argument must be between 2 and 36');
+  }
+  // Convert the number to a string in the given radix.
+  return %NumberToRadixString(number, radix);
+}
+
+
+// ECMA-262 section 15.7.4.3
+function NumberToLocaleString() {
+  return this.toString();
+}
+
+
+// ECMA-262 section 15.7.4.4
+function NumberValueOf() {
+  // NOTE: Both Number objects and values can enter here as
+  // 'this'. This is not as dictated by ECMA-262.
+  if (!IS_NUMBER(this) && !%HasNumberClass(this))
+    throw new $TypeError('Number.prototype.valueOf is not generic');
+  return %_ValueOf(this);
+}
+
+
+// ECMA-262 section 15.7.4.5
+function NumberToFixed(fractionDigits) {
+  var f = TO_INTEGER(fractionDigits);
+  if (f < 0 || f > 20) {
+    throw new $RangeError("toFixed() digits argument must be between 0 and 20");
+  }
+  var x = ToNumber(this);
+  return %NumberToFixed(x, f);
+}
+
+
+// ECMA-262 section 15.7.4.6
+function NumberToExponential(fractionDigits) {
+  var f = -1;
+  if (!IS_UNDEFINED(fractionDigits)) {
+    f = TO_INTEGER(fractionDigits);
+    if (f < 0 || f > 20) {
+      throw new $RangeError("toExponential() argument must be between 0 and 20");
+    }
+  }
+  var x = ToNumber(this);
+  return %NumberToExponential(x, f);
+}
+
+
+// ECMA-262 section 15.7.4.7
+function NumberToPrecision(precision) {
+  if (IS_UNDEFINED(precision)) return ToString(%_ValueOf(this));
+  var p = TO_INTEGER(precision);
+  if (p < 1 || p > 21) {
+    throw new $RangeError("toPrecision() argument must be between 1 and 21");
+  }
+  var x = ToNumber(this);
+  return %NumberToPrecision(x, p);
+}
+
+
+// ----------------------------------------------------------------------------
+
+function SetupNumber() {
+  // Setup the constructor property on the Number prototype object.
+  %SetProperty($Number.prototype, "constructor", $Number, DONT_ENUM);
+
+  // ECMA-262 section 15.7.3.1.
+  %SetProperty($Number,
+               "MAX_VALUE",
+               1.7976931348623157e+308,
+               DONT_ENUM | DONT_DELETE | READ_ONLY);
+
+  // ECMA-262 section 15.7.3.2.
+  %SetProperty($Number, "MIN_VALUE", 5e-324, DONT_ENUM | DONT_DELETE | READ_ONLY);
+
+  // ECMA-262 section 15.7.3.3.
+  %SetProperty($Number, "NaN", $NaN, DONT_ENUM | DONT_DELETE | READ_ONLY);
+
+  // ECMA-262 section 15.7.3.4.
+  %SetProperty($Number,
+               "NEGATIVE_INFINITY",
+               -1/0,
+               DONT_ENUM | DONT_DELETE | READ_ONLY);
+
+  // ECMA-262 section 15.7.3.5.
+  %SetProperty($Number,
+               "POSITIVE_INFINITY",
+               1/0,
+               DONT_ENUM | DONT_DELETE | READ_ONLY);
+
+  // Setup non-enumerable functions on the Number prototype object.
+  InstallFunctions($Number.prototype, DONT_ENUM, $Array(
+    "toString", NumberToString,
+    "toLocaleString", NumberToLocaleString,
+    "valueOf", NumberValueOf,
+    "toFixed", NumberToFixed,
+    "toExponential", NumberToExponential,
+    "toPrecision", NumberToPrecision
+  ));
+}
+
+SetupNumber();
+
+
+
+// ----------------------------------------------------------------------------
+// Function
+
+$Function.prototype.constructor = $Function;
+
+function FunctionSourceString(func) {
+  // NOTE: Both Function objects and values can enter here as
+  // 'func'. This is not as dictated by ECMA-262.
+  if (!IS_FUNCTION(func) && !%HasFunctionClass(func))
+    throw new $TypeError('Function.prototype.toString is not generic');
+
+  var source = %FunctionGetSourceCode(func);
+  if (!IS_STRING(source)) {
+    var name = %FunctionGetName(func);
+    if (name) {
+      // Mimic what KJS does.
+      return 'function ' + name + '() { [native code] }';
+    } else {
+      return 'function () { [native code] }';
+    }
+  }
+
+  // Censor occurrences of internal calls.  We do that for all
+  // functions and don't cache under the assumption that people rarly
+  // convert functions to strings.  Note that we (apparently) can't
+  // use regular expression literals in natives files.
+  var regexp = ORIGINAL_REGEXP("%(\\w+\\()", "gm");
+  if (source.match(regexp)) source = source.replace(regexp, "$1");
+  var name = %FunctionGetName(func);
+  return 'function ' + name + source;
+}
+
+
+function FunctionToString() {
+  return FunctionSourceString(this);
+}
+
+
+function NewFunction(arg1) {  // length == 1
+  var n = %_ArgumentsLength();
+  var p = '';
+  if (n > 1) {
+    p = new $Array(n - 1);
+    // Explicitly convert all parameters to strings.
+    // Array.prototype.join replaces null with empty strings which is
+    // not appropriate.
+    for (var i = 0; i < n - 1; i++) p[i] = ToString(%_Arguments(i));
+    p = p.join(',');
+    // If the formal parameters string include ) - an illegal
+    // character - it may make the combined function expression
+    // compile. We avoid this problem by checking for this early on.
+    if (p.indexOf(')') != -1) throw MakeSyntaxError('unable_to_parse',[]);
+  }
+  var body = (n > 0) ? ToString(%_Arguments(n - 1)) : '';
+  var source = '(function(' + p + ') {\n' + body + '\n})';
+
+  // The call to SetNewFunctionAttributes will ensure the prototype
+  // property of the resulting function is enumerable (ECMA262, 15.3.5.2).
+  var f = %CompileString(source, -1)();
+  %FunctionSetName(f, "anonymous");
+  return %SetNewFunctionAttributes(f);
+}
+
+%SetCode($Function, NewFunction);
+
+// ----------------------------------------------------------------------------
+
+function SetupFunction() {
+  InstallFunctions($Function.prototype, DONT_ENUM, $Array(
+    "toString", FunctionToString
+  ));
+}
+
+SetupFunction();
+
diff --git a/deps/v8/src/v8threads.cc b/deps/v8/src/v8threads.cc
new file mode 100644
index 0000000..e8f6f9b
--- /dev/null
+++ b/deps/v8/src/v8threads.cc
@@ -0,0 +1,379 @@
+// Copyright 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.
+
+#include "v8.h"
+
+#include "api.h"
+#include "bootstrapper.h"
+#include "debug.h"
+#include "execution.h"
+#include "v8threads.h"
+#include "regexp-stack.h"
+
+namespace v8 {
+
+static internal::Thread::LocalStorageKey thread_state_key =
+    internal::Thread::CreateThreadLocalKey();
+static internal::Thread::LocalStorageKey thread_id_key =
+    internal::Thread::CreateThreadLocalKey();
+
+
+// Track whether this V8 instance has ever called v8::Locker. This allows the
+// API code to verify that the lock is always held when V8 is being entered.
+bool Locker::active_ = false;
+
+
+// Constructor for the Locker object.  Once the Locker is constructed the
+// current thread will be guaranteed to have the big V8 lock.
+Locker::Locker() : has_lock_(false), top_level_(true) {
+  // Record that the Locker has been used at least once.
+  active_ = true;
+  // Get the big lock if necessary.
+  if (!internal::ThreadManager::IsLockedByCurrentThread()) {
+    internal::ThreadManager::Lock();
+    has_lock_ = true;
+    // This may be a locker within an unlocker in which case we have to
+    // get the saved state for this thread and restore it.
+    if (internal::ThreadManager::RestoreThread()) {
+      top_level_ = false;
+    }
+  }
+  ASSERT(internal::ThreadManager::IsLockedByCurrentThread());
+
+  // Make sure this thread is assigned a thread id.
+  internal::ThreadManager::AssignId();
+}
+
+
+bool Locker::IsLocked() {
+  return internal::ThreadManager::IsLockedByCurrentThread();
+}
+
+
+Locker::~Locker() {
+  ASSERT(internal::ThreadManager::IsLockedByCurrentThread());
+  if (has_lock_) {
+    if (!top_level_) {
+      internal::ThreadManager::ArchiveThread();
+    }
+    internal::ThreadManager::Unlock();
+  }
+}
+
+
+Unlocker::Unlocker() {
+  ASSERT(internal::ThreadManager::IsLockedByCurrentThread());
+  internal::ThreadManager::ArchiveThread();
+  internal::ThreadManager::Unlock();
+}
+
+
+Unlocker::~Unlocker() {
+  ASSERT(!internal::ThreadManager::IsLockedByCurrentThread());
+  internal::ThreadManager::Lock();
+  internal::ThreadManager::RestoreThread();
+}
+
+
+void Locker::StartPreemption(int every_n_ms) {
+  v8::internal::ContextSwitcher::StartPreemption(every_n_ms);
+}
+
+
+void Locker::StopPreemption() {
+  v8::internal::ContextSwitcher::StopPreemption();
+}
+
+
+namespace internal {
+
+
+bool ThreadManager::RestoreThread() {
+  // First check whether the current thread has been 'lazily archived', ie
+  // not archived at all.  If that is the case we put the state storage we
+  // had prepared back in the free list, since we didn't need it after all.
+  if (lazily_archived_thread_.IsSelf()) {
+    lazily_archived_thread_.Initialize(ThreadHandle::INVALID);
+    ASSERT(Thread::GetThreadLocal(thread_state_key) ==
+           lazily_archived_thread_state_);
+    lazily_archived_thread_state_->set_id(kInvalidId);
+    lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST);
+    lazily_archived_thread_state_ = NULL;
+    Thread::SetThreadLocal(thread_state_key, NULL);
+    return true;
+  }
+
+  // Make sure that the preemption thread cannot modify the thread state while
+  // it is being archived or restored.
+  ExecutionAccess access;
+
+  // If there is another thread that was lazily archived then we have to really
+  // archive it now.
+  if (lazily_archived_thread_.IsValid()) {
+    EagerlyArchiveThread();
+  }
+  ThreadState* state =
+      reinterpret_cast<ThreadState*>(Thread::GetThreadLocal(thread_state_key));
+  if (state == NULL) {
+    return false;
+  }
+  char* from = state->data();
+  from = HandleScopeImplementer::RestoreThread(from);
+  from = Top::RestoreThread(from);
+  from = Debug::RestoreDebug(from);
+  from = StackGuard::RestoreStackGuard(from);
+  from = RegExpStack::RestoreStack(from);
+  from = Bootstrapper::RestoreState(from);
+  Thread::SetThreadLocal(thread_state_key, NULL);
+  state->set_id(kInvalidId);
+  state->Unlink();
+  state->LinkInto(ThreadState::FREE_LIST);
+  return true;
+}
+
+
+void ThreadManager::Lock() {
+  mutex_->Lock();
+  mutex_owner_.Initialize(ThreadHandle::SELF);
+  ASSERT(IsLockedByCurrentThread());
+}
+
+
+void ThreadManager::Unlock() {
+  mutex_owner_.Initialize(ThreadHandle::INVALID);
+  mutex_->Unlock();
+}
+
+
+static int ArchiveSpacePerThread() {
+  return HandleScopeImplementer::ArchiveSpacePerThread() +
+                            Top::ArchiveSpacePerThread() +
+                          Debug::ArchiveSpacePerThread() +
+                     StackGuard::ArchiveSpacePerThread() +
+                    RegExpStack::ArchiveSpacePerThread() +
+                   Bootstrapper::ArchiveSpacePerThread();
+}
+
+
+ThreadState* ThreadState::free_anchor_ = new ThreadState();
+ThreadState* ThreadState::in_use_anchor_ = new ThreadState();
+
+
+ThreadState::ThreadState() : id_(ThreadManager::kInvalidId),
+                             next_(this), previous_(this) {
+}
+
+
+void ThreadState::AllocateSpace() {
+  data_ = NewArray<char>(ArchiveSpacePerThread());
+}
+
+
+void ThreadState::Unlink() {
+  next_->previous_ = previous_;
+  previous_->next_ = next_;
+}
+
+
+void ThreadState::LinkInto(List list) {
+  ThreadState* flying_anchor =
+      list == FREE_LIST ? free_anchor_ : in_use_anchor_;
+  next_ = flying_anchor->next_;
+  previous_ = flying_anchor;
+  flying_anchor->next_ = this;
+  next_->previous_ = this;
+}
+
+
+ThreadState* ThreadState::GetFree() {
+  ThreadState* gotten = free_anchor_->next_;
+  if (gotten == free_anchor_) {
+    ThreadState* new_thread_state = new ThreadState();
+    new_thread_state->AllocateSpace();
+    return new_thread_state;
+  }
+  return gotten;
+}
+
+
+// Gets the first in the list of archived threads.
+ThreadState* ThreadState::FirstInUse() {
+  return in_use_anchor_->Next();
+}
+
+
+ThreadState* ThreadState::Next() {
+  if (next_ == in_use_anchor_) return NULL;
+  return next_;
+}
+
+
+int ThreadManager::next_id_ = 0;
+Mutex* ThreadManager::mutex_ = OS::CreateMutex();
+ThreadHandle ThreadManager::mutex_owner_(ThreadHandle::INVALID);
+ThreadHandle ThreadManager::lazily_archived_thread_(ThreadHandle::INVALID);
+ThreadState* ThreadManager::lazily_archived_thread_state_ = NULL;
+
+
+void ThreadManager::ArchiveThread() {
+  ASSERT(!lazily_archived_thread_.IsValid());
+  ASSERT(Thread::GetThreadLocal(thread_state_key) == NULL);
+  ThreadState* state = ThreadState::GetFree();
+  state->Unlink();
+  Thread::SetThreadLocal(thread_state_key, reinterpret_cast<void*>(state));
+  lazily_archived_thread_.Initialize(ThreadHandle::SELF);
+  lazily_archived_thread_state_ = state;
+  ASSERT(state->id() == kInvalidId);
+  state->set_id(CurrentId());
+  ASSERT(state->id() != kInvalidId);
+}
+
+
+void ThreadManager::EagerlyArchiveThread() {
+  ThreadState* state = lazily_archived_thread_state_;
+  state->LinkInto(ThreadState::IN_USE_LIST);
+  char* to = state->data();
+  to = HandleScopeImplementer::ArchiveThread(to);
+  to = Top::ArchiveThread(to);
+  to = Debug::ArchiveDebug(to);
+  to = StackGuard::ArchiveStackGuard(to);
+  to = RegExpStack::ArchiveStack(to);
+  to = Bootstrapper::ArchiveState(to);
+  lazily_archived_thread_.Initialize(ThreadHandle::INVALID);
+  lazily_archived_thread_state_ = NULL;
+}
+
+
+void ThreadManager::Iterate(ObjectVisitor* v) {
+  // Expecting no threads during serialization/deserialization
+  for (ThreadState* state = ThreadState::FirstInUse();
+       state != NULL;
+       state = state->Next()) {
+    char* data = state->data();
+    data = HandleScopeImplementer::Iterate(v, data);
+    data = Top::Iterate(v, data);
+  }
+}
+
+
+void ThreadManager::MarkCompactPrologue(bool is_compacting) {
+  for (ThreadState* state = ThreadState::FirstInUse();
+       state != NULL;
+       state = state->Next()) {
+    char* data = state->data();
+    data += HandleScopeImplementer::ArchiveSpacePerThread();
+    Top::MarkCompactPrologue(is_compacting, data);
+  }
+}
+
+
+void ThreadManager::MarkCompactEpilogue(bool is_compacting) {
+  for (ThreadState* state = ThreadState::FirstInUse();
+       state != NULL;
+       state = state->Next()) {
+    char* data = state->data();
+    data += HandleScopeImplementer::ArchiveSpacePerThread();
+    Top::MarkCompactEpilogue(is_compacting, data);
+  }
+}
+
+
+int ThreadManager::CurrentId() {
+  return bit_cast<int, void*>(Thread::GetThreadLocal(thread_id_key));
+}
+
+
+void ThreadManager::AssignId() {
+  if (Thread::GetThreadLocal(thread_id_key) == NULL) {
+    Thread::SetThreadLocal(thread_id_key, bit_cast<void*, int>(next_id_++));
+  }
+}
+
+
+// This is the ContextSwitcher singleton. There is at most a single thread
+// running which delivers preemption events to V8 threads.
+ContextSwitcher* ContextSwitcher::singleton_ = NULL;
+
+
+ContextSwitcher::ContextSwitcher(int every_n_ms)
+  : keep_going_(true),
+    sleep_ms_(every_n_ms) {
+}
+
+
+// Set the scheduling interval of V8 threads. This function starts the
+// ContextSwitcher thread if needed.
+void ContextSwitcher::StartPreemption(int every_n_ms) {
+  ASSERT(Locker::IsLocked());
+  if (singleton_ == NULL) {
+    // If the ContextSwitcher thread is not running at the moment start it now.
+    singleton_ = new ContextSwitcher(every_n_ms);
+    singleton_->Start();
+  } else {
+    // ContextSwitcher thread is already running, so we just change the
+    // scheduling interval.
+    singleton_->sleep_ms_ = every_n_ms;
+  }
+}
+
+
+// Disable preemption of V8 threads. If multiple threads want to use V8 they
+// must cooperatively schedule amongst them from this point on.
+void ContextSwitcher::StopPreemption() {
+  ASSERT(Locker::IsLocked());
+  if (singleton_ != NULL) {
+    // The ContextSwitcher thread is running. We need to stop it and release
+    // its resources.
+    singleton_->keep_going_ = false;
+    singleton_->Join();  // Wait for the ContextSwitcher thread to exit.
+    // Thread has exited, now we can delete it.
+    delete(singleton_);
+    singleton_ = NULL;
+  }
+}
+
+
+// Main loop of the ContextSwitcher thread: Preempt the currently running V8
+// thread at regular intervals.
+void ContextSwitcher::Run() {
+  while (keep_going_) {
+    OS::Sleep(sleep_ms_);
+    StackGuard::Preempt();
+  }
+}
+
+
+// Acknowledge the preemption by the receiving thread.
+void ContextSwitcher::PreemptionReceived() {
+  ASSERT(Locker::IsLocked());
+  // There is currently no accounting being done for this. But could be in the
+  // future, which is why we leave this in.
+}
+
+
+}  // namespace internal
+}  // namespace v8
diff --git a/deps/v8/src/v8threads.h b/deps/v8/src/v8threads.h
new file mode 100644
index 0000000..b651fc3
--- /dev/null
+++ b/deps/v8/src/v8threads.h
@@ -0,0 +1,131 @@
+// Copyright 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_V8THREADS_H_
+#define V8_V8THREADS_H_
+
+namespace v8 { namespace internal {
+
+
+class ThreadState {
+ public:
+  // Iterate over in-use states.
+  static ThreadState* FirstInUse();
+  // Returns NULL after the last one.
+  ThreadState* Next();
+
+  enum List {FREE_LIST, IN_USE_LIST};
+
+  void LinkInto(List list);
+  void Unlink();
+
+  static ThreadState* GetFree();
+
+  // Id of thread.
+  void set_id(int id) { id_ = id; }
+  int id() { return id_; }
+
+  // Get data area for archiving a thread.
+  char* data() { return data_; }
+ private:
+  ThreadState();
+
+  void AllocateSpace();
+
+  int id_;
+  char* data_;
+  ThreadState* next_;
+  ThreadState* previous_;
+
+  // In the following two lists there is always at least one object on the list.
+  // The first object is a flying anchor that is only there to simplify linking
+  // and unlinking.
+  // Head of linked list of free states.
+  static ThreadState* free_anchor_;
+  // Head of linked list of states in use.
+  static ThreadState* in_use_anchor_;
+};
+
+
+class ThreadManager : public AllStatic {
+ public:
+  static void Lock();
+  static void Unlock();
+
+  static void ArchiveThread();
+  static bool RestoreThread();
+
+  static void Iterate(ObjectVisitor* v);
+  static void MarkCompactPrologue(bool is_compacting);
+  static void MarkCompactEpilogue(bool is_compacting);
+  static bool IsLockedByCurrentThread() { return mutex_owner_.IsSelf(); }
+
+  static int CurrentId();
+  static void AssignId();
+
+  static const int kInvalidId = -1;
+ private:
+  static void EagerlyArchiveThread();
+
+  static int next_id_;  // V8 threads are identified through an integer.
+  static Mutex* mutex_;
+  static ThreadHandle mutex_owner_;
+  static ThreadHandle lazily_archived_thread_;
+  static ThreadState* lazily_archived_thread_state_;
+};
+
+
+// The ContextSwitcher thread is used to schedule regular preemptions to
+// multiple running V8 threads. Generally it is necessary to call
+// StartPreemption if there is more than one thread running. If not, a single
+// JavaScript can take full control of V8 and not allow other threads to run.
+class ContextSwitcher: public Thread {
+ public:
+  // Set the preemption interval for the ContextSwitcher thread.
+  static void StartPreemption(int every_n_ms);
+
+  // Stop sending preemption requests to threads.
+  static void StopPreemption();
+
+  // Preempted thread needs to call back to the ContextSwitcher to acknowledge
+  // the handling of a preemption request.
+  static void PreemptionReceived();
+
+ private:
+  explicit ContextSwitcher(int every_n_ms);
+
+  void Run();
+
+  bool keep_going_;
+  int sleep_ms_;
+
+  static ContextSwitcher* singleton_;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_V8THREADS_H_
diff --git a/deps/v8/src/variables.cc b/deps/v8/src/variables.cc
new file mode 100644
index 0000000..51eb8ca
--- /dev/null
+++ b/deps/v8/src/variables.cc
@@ -0,0 +1,162 @@
+// 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.
+
+#include "v8.h"
+
+#include "ast.h"
+#include "scopes.h"
+#include "variables.h"
+
+namespace v8 { namespace internal {
+
+// ----------------------------------------------------------------------------
+// Implementation UseCount.
+
+UseCount::UseCount()
+  : nreads_(0),
+    nwrites_(0) {
+}
+
+
+void UseCount::RecordRead(int weight) {
+  ASSERT(weight > 0);
+  nreads_ += weight;
+  // We must have a positive nreads_ here. Handle
+  // any kind of overflow by setting nreads_ to
+  // some large-ish value.
+  if (nreads_ <= 0) nreads_ = 1000000;
+  ASSERT(is_read() & is_used());
+}
+
+
+void UseCount::RecordWrite(int weight) {
+  ASSERT(weight > 0);
+  nwrites_ += weight;
+  // We must have a positive nwrites_ here. Handle
+  // any kind of overflow by setting nwrites_ to
+  // some large-ish value.
+  if (nwrites_ <= 0) nwrites_ = 1000000;
+  ASSERT(is_written() && is_used());
+}
+
+
+void UseCount::RecordAccess(int weight) {
+  RecordRead(weight);
+  RecordWrite(weight);
+}
+
+
+void UseCount::RecordUses(UseCount* uses) {
+  if (uses->nreads() > 0) RecordRead(uses->nreads());
+  if (uses->nwrites() > 0) RecordWrite(uses->nwrites());
+}
+
+
+#ifdef DEBUG
+void UseCount::Print() {
+  // PrintF("r = %d, w = %d", nreads_, nwrites_);
+  PrintF("%du = %dr + %dw", nuses(), nreads(), nwrites());
+}
+#endif
+
+
+// ----------------------------------------------------------------------------
+// Implementation SmiAnalysis.
+
+
+const char* SmiAnalysis::Type2String(SmiAnalysis* type) {
+  switch (type->kind_) {
+    case UNKNOWN:
+      return "UNKNOWN";
+    case LIKELY_SMI:
+      return "LIKELY_SMI";
+    default:
+      UNREACHABLE();
+  }
+  return "UNREACHABLE";
+}
+
+
+// ----------------------------------------------------------------------------
+// Implementation Variable.
+
+
+const char* Variable::Mode2String(Mode mode) {
+  switch (mode) {
+    case VAR: return "VAR";
+    case CONST: return "CONST";
+    case DYNAMIC: return "DYNAMIC";
+    case DYNAMIC_GLOBAL: return "DYNAMIC_GLOBAL";
+    case DYNAMIC_LOCAL: return "DYNAMIC_LOCAL";
+    case INTERNAL: return "INTERNAL";
+    case TEMPORARY: return "TEMPORARY";
+  }
+  UNREACHABLE();
+  return NULL;
+}
+
+
+Property* Variable::AsProperty() {
+  return rewrite_ == NULL ? NULL : rewrite_->AsProperty();
+}
+
+
+Variable* Variable::AsVariable()  {
+  return rewrite_ == NULL || rewrite_->AsSlot() != NULL ? this : NULL;
+}
+
+
+Slot* Variable::slot() const {
+  return rewrite_ != NULL ? rewrite_->AsSlot() : NULL;
+}
+
+
+Variable::Variable(Scope* scope,
+                   Handle<String> name,
+                   Mode mode,
+                   bool is_valid_LHS,
+                   bool is_this)
+  : scope_(scope),
+    name_(name),
+    mode_(mode),
+    is_valid_LHS_(is_valid_LHS),
+    is_this_(is_this),
+    local_if_not_shadowed_(NULL),
+    is_accessed_from_inner_scope_(false),
+    rewrite_(NULL) {
+  // names must be canonicalized for fast equality checks
+  ASSERT(name->IsSymbol());
+}
+
+
+bool Variable::is_global() const {
+  // Temporaries are never global, they must always be allocated in the
+  // activation frame.
+  return mode_ != TEMPORARY && scope_ != NULL && scope_->is_global_scope();
+}
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/variables.h b/deps/v8/src/variables.h
new file mode 100644
index 0000000..275f498
--- /dev/null
+++ b/deps/v8/src/variables.h
@@ -0,0 +1,223 @@
+// 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_VARIABLES_H_
+#define V8_VARIABLES_H_
+
+#include "zone.h"
+
+namespace v8 { namespace internal {
+
+class UseCount BASE_EMBEDDED {
+ public:
+  UseCount();
+
+  // Inform the node of a "use". The weight can be used to indicate
+  // heavier use, for instance if the variable is accessed inside a loop.
+  void RecordRead(int weight);
+  void RecordWrite(int weight);
+  void RecordAccess(int weight);  // records a read & write
+  void RecordUses(UseCount* uses);
+
+  int nreads() const  { return nreads_; }
+  int nwrites() const  { return nwrites_; }
+  int nuses() const  { return nreads_ + nwrites_; }
+
+  bool is_read() const  { return nreads() > 0; }
+  bool is_written() const  { return nwrites() > 0; }
+  bool is_used() const  { return nuses() > 0; }
+
+#ifdef DEBUG
+  void Print();
+#endif
+
+ private:
+  int nreads_;
+  int nwrites_;
+};
+
+
+// Variables and AST expression nodes can track their "type" to enable
+// optimizations and removal of redundant checks when generating code.
+
+class SmiAnalysis {
+ public:
+  enum Kind {
+    UNKNOWN,
+    LIKELY_SMI
+  };
+
+  SmiAnalysis() : kind_(UNKNOWN) {}
+
+  bool Is(Kind kind) const { return kind_ == kind; }
+
+  bool IsKnown() const { return !Is(UNKNOWN); }
+  bool IsUnknown() const { return Is(UNKNOWN); }
+  bool IsLikelySmi() const { return Is(LIKELY_SMI); }
+
+  void CopyFrom(SmiAnalysis* other) {
+    kind_ = other->kind_;
+  }
+
+  static const char* Type2String(SmiAnalysis* type);
+
+  // LIKELY_SMI accessors
+  void SetAsLikelySmi() {
+    kind_ = LIKELY_SMI;
+  }
+
+  void SetAsLikelySmiIfUnknown() {
+    if (IsUnknown()) {
+      SetAsLikelySmi();
+    }
+  }
+
+ private:
+  Kind kind_;
+
+  DISALLOW_COPY_AND_ASSIGN(SmiAnalysis);
+};
+
+
+// The AST refers to variables via VariableProxies - placeholders for the actual
+// variables. Variables themselves are never directly referred to from the AST,
+// they are maintained by scopes, and referred to from VariableProxies and Slots
+// after binding and variable allocation.
+
+class Variable: public ZoneObject {
+ public:
+  enum Mode {
+    // User declared variables:
+    VAR,       // declared via 'var', and 'function' declarations
+
+    CONST,     // declared via 'const' declarations
+
+    // Variables introduced by the compiler:
+    DYNAMIC,         // always require dynamic lookup (we don't know
+                     // the declaration)
+
+    DYNAMIC_GLOBAL,  // requires dynamic lookup, but we know that the
+                     // variable is global unless it has been shadowed
+                     // by an eval-introduced variable
+
+    DYNAMIC_LOCAL,   // requires dynamic lookup, but we know that the
+                     // variable is local and where it is unless it
+                     // has been shadowed by an eval-introduced
+                     // variable
+
+    INTERNAL,        // like VAR, but not user-visible (may or may not
+                     // be in a context)
+
+    TEMPORARY        // temporary variables (not user-visible), never
+                     // in a context
+  };
+
+  // Printing support
+  static const char* Mode2String(Mode mode);
+
+  // Type testing & conversion
+  Property* AsProperty();
+  Variable* AsVariable();
+  bool IsValidLeftHandSide() { return is_valid_LHS_; }
+
+  // The source code for an eval() call may refer to a variable that is
+  // in an outer scope about which we don't know anything (it may not
+  // be the global scope). scope() is NULL in that case. Currently the
+  // scope is only used to follow the context chain length.
+  Scope* scope() const  { return scope_; }
+  // If this assertion fails it means that some code has tried to
+  // treat the special this variable as an ordinary variable with
+  // the name "this".
+  Handle<String> name() const  { return name_; }
+  Mode mode() const  { return mode_; }
+  bool is_accessed_from_inner_scope() const  {
+    return is_accessed_from_inner_scope_;
+  }
+  UseCount* var_uses()  { return &var_uses_; }
+  UseCount* obj_uses()  { return &obj_uses_; }
+
+  bool IsVariable(Handle<String> n) {
+    return !is_this() && name().is_identical_to(n);
+  }
+
+  bool is_dynamic() const {
+    return (mode_ == DYNAMIC ||
+            mode_ == DYNAMIC_GLOBAL ||
+            mode_ == DYNAMIC_LOCAL);
+  }
+
+  bool is_global() const;
+  bool is_this() const { return is_this_; }
+
+  Variable* local_if_not_shadowed() const {
+    ASSERT(mode_ == DYNAMIC_LOCAL && local_if_not_shadowed_ != NULL);
+    return local_if_not_shadowed_;
+  }
+
+  void set_local_if_not_shadowed(Variable* local) {
+    local_if_not_shadowed_ = local;
+  }
+
+  Expression* rewrite() const  { return rewrite_; }
+  Slot* slot() const;
+
+  SmiAnalysis* type() { return &type_; }
+
+ private:
+  Variable(Scope* scope, Handle<String> name, Mode mode, bool is_valid_LHS,
+      bool is_this);
+
+  Scope* scope_;
+  Handle<String> name_;
+  Mode mode_;
+  bool is_valid_LHS_;
+  bool is_this_;
+
+  Variable* local_if_not_shadowed_;
+
+  // Usage info.
+  bool is_accessed_from_inner_scope_;  // set by variable resolver
+  UseCount var_uses_;  // uses of the variable value
+  UseCount obj_uses_;  // uses of the object the variable points to
+
+  // Static type information
+  SmiAnalysis type_;
+
+  // Code generation.
+  // rewrite_ is usually a Slot or a Property, but maybe any expression.
+  Expression* rewrite_;
+
+  friend class VariableProxy;
+  friend class Scope;
+  friend class LocalsMap;
+  friend class AstBuildingParser;
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_VARIABLES_H_
diff --git a/deps/v8/src/virtual-frame-arm.cc b/deps/v8/src/virtual-frame-arm.cc
new file mode 100644
index 0000000..baf0814
--- /dev/null
+++ b/deps/v8/src/virtual-frame-arm.cc
@@ -0,0 +1,437 @@
+// 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.
+
+#include "v8.h"
+
+#include "codegen-inl.h"
+#include "register-allocator-inl.h"
+#include "scopes.h"
+
+namespace v8 { namespace internal {
+
+// -------------------------------------------------------------------------
+// VirtualFrame implementation.
+
+#define __ masm_->
+
+// On entry to a function, the virtual frame already contains the
+// receiver and the parameters.  All initial frame elements are in
+// memory.
+VirtualFrame::VirtualFrame(CodeGenerator* cgen)
+    : cgen_(cgen),
+      masm_(cgen->masm()),
+      elements_(cgen->scope()->num_parameters()
+                + cgen->scope()->num_stack_slots()
+                + kPreallocatedElements),
+      parameter_count_(cgen->scope()->num_parameters()),
+      local_count_(0),
+      stack_pointer_(parameter_count_),  // 0-based index of TOS.
+      frame_pointer_(kIllegalIndex) {
+  for (int i = 0; i < parameter_count_ + 1; i++) {
+    elements_.Add(FrameElement::MemoryElement());
+  }
+  for (int i = 0; i < kNumRegisters; i++) {
+    register_locations_[i] = kIllegalIndex;
+  }
+}
+
+
+void VirtualFrame::SyncElementBelowStackPointer(int index) {
+  UNREACHABLE();
+}
+
+
+void VirtualFrame::SyncElementByPushing(int index) {
+  UNREACHABLE();
+}
+
+
+void VirtualFrame::MergeTo(VirtualFrame* expected) {
+  Comment cmnt(masm_, "[ Merge frame");
+  // We should always be merging the code generator's current frame to an
+  // expected frame.
+  ASSERT(cgen_->frame() == this);
+
+  // Adjust the stack pointer upward (toward the top of the virtual
+  // frame) if necessary.
+  if (stack_pointer_ < expected->stack_pointer_) {
+    int difference = expected->stack_pointer_ - stack_pointer_;
+    stack_pointer_ = expected->stack_pointer_;
+    __ sub(sp, sp, Operand(difference * kPointerSize));
+  }
+
+  MergeMoveRegistersToMemory(expected);
+  MergeMoveRegistersToRegisters(expected);
+  MergeMoveMemoryToRegisters(expected);
+
+  // Fix any sync bit problems from the bottom-up, stopping when we
+  // hit the stack pointer or the top of the frame if the stack
+  // pointer is floating above the frame.
+  int limit = Min(stack_pointer_, elements_.length() - 1);
+  for (int i = 0; i <= limit; i++) {
+    FrameElement source = elements_[i];
+    FrameElement target = expected->elements_[i];
+    if (source.is_synced() && !target.is_synced()) {
+      elements_[i].clear_sync();
+    } else if (!source.is_synced() && target.is_synced()) {
+      SyncElementAt(i);
+    }
+  }
+
+  // Adjust the stack point downard if necessary.
+  if (stack_pointer_ > expected->stack_pointer_) {
+    int difference = stack_pointer_ - expected->stack_pointer_;
+    stack_pointer_ = expected->stack_pointer_;
+    __ add(sp, sp, Operand(difference * kPointerSize));
+  }
+
+  // At this point, the frames should be identical.
+  ASSERT(Equals(expected));
+}
+
+
+void VirtualFrame::MergeMoveRegistersToMemory(VirtualFrame* expected) {
+  ASSERT(stack_pointer_ >= expected->stack_pointer_);
+
+  // Move registers, constants, and copies to memory.  Perform moves
+  // from the top downward in the frame in order to leave the backing
+  // stores of copies in registers.
+  // On ARM, all elements are in memory.
+
+#ifdef DEBUG
+  int start = Min(stack_pointer_, elements_.length() - 1);
+  for (int i = start; i >= 0; i--) {
+    ASSERT(elements_[i].is_memory());
+    ASSERT(expected->elements_[i].is_memory());
+  }
+#endif
+}
+
+
+void VirtualFrame::MergeMoveRegistersToRegisters(VirtualFrame* expected) {
+}
+
+
+void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame *expected) {
+}
+
+
+void VirtualFrame::Enter() {
+  Comment cmnt(masm_, "[ Enter JS frame");
+
+#ifdef DEBUG
+  // Verify that r1 contains a JS function.  The following code relies
+  // on r2 being available for use.
+  { Label map_check, done;
+    __ tst(r1, Operand(kSmiTagMask));
+    __ b(ne, &map_check);
+    __ stop("VirtualFrame::Enter - r1 is not a function (smi check).");
+    __ bind(&map_check);
+    __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+    __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
+    __ cmp(r2, Operand(JS_FUNCTION_TYPE));
+    __ b(eq, &done);
+    __ stop("VirtualFrame::Enter - r1 is not a function (map check).");
+    __ bind(&done);
+  }
+#endif  // DEBUG
+
+  // We are about to push four values to the frame.
+  Adjust(4);
+  __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
+  // Adjust FP to point to saved FP.
+  frame_pointer_ = elements_.length() - 2;
+  __ add(fp, sp, Operand(2 * kPointerSize));
+  cgen_->allocator()->Unuse(r1);
+  cgen_->allocator()->Unuse(lr);
+}
+
+
+void VirtualFrame::Exit() {
+  Comment cmnt(masm_, "[ Exit JS frame");
+  // Drop the execution stack down to the frame pointer and restore the caller
+  // frame pointer and return address.
+  __ mov(sp, fp);
+  __ ldm(ia_w, sp, fp.bit() | lr.bit());
+}
+
+
+void VirtualFrame::AllocateStackSlots(int count) {
+  ASSERT(height() == 0);
+  local_count_ = count;
+  Adjust(count);
+  if (count > 0) {
+    Comment cmnt(masm_, "[ Allocate space for locals");
+      // Initialize stack slots with 'undefined' value.
+    __ mov(ip, Operand(Factory::undefined_value()));
+    for (int i = 0; i < count; i++) {
+      __ push(ip);
+    }
+  }
+}
+
+
+void VirtualFrame::SaveContextRegister() {
+  UNIMPLEMENTED();
+}
+
+
+void VirtualFrame::RestoreContextRegister() {
+  UNIMPLEMENTED();
+}
+
+
+void VirtualFrame::PushReceiverSlotAddress() {
+  UNIMPLEMENTED();
+}
+
+
+int VirtualFrame::InvalidateFrameSlotAt(int index) {
+  UNIMPLEMENTED();
+  return kIllegalIndex;
+}
+
+
+void VirtualFrame::TakeFrameSlotAt(int index) {
+  UNIMPLEMENTED();
+}
+
+
+void VirtualFrame::StoreToFrameSlotAt(int index) {
+  UNIMPLEMENTED();
+}
+
+
+void VirtualFrame::PushTryHandler(HandlerType type) {
+  // Grow the expression stack by handler size less one (the return address
+  // is already pushed by a call instruction).
+  Adjust(kHandlerSize - 1);
+  __ PushTryHandler(IN_JAVASCRIPT, type);
+}
+
+
+Result VirtualFrame::RawCallStub(CodeStub* stub) {
+  ASSERT(cgen_->HasValidEntryRegisters());
+  __ CallStub(stub);
+  Result result = cgen_->allocator()->Allocate(r0);
+  ASSERT(result.is_valid());
+  return result;
+}
+
+
+Result VirtualFrame::CallStub(CodeStub* stub, Result* arg) {
+  PrepareForCall(0, 0);
+  arg->Unuse();
+  return RawCallStub(stub);
+}
+
+
+Result VirtualFrame::CallStub(CodeStub* stub, Result* arg0, Result* arg1) {
+  PrepareForCall(0, 0);
+  arg0->Unuse();
+  arg1->Unuse();
+  return RawCallStub(stub);
+}
+
+
+Result VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) {
+  PrepareForCall(arg_count, arg_count);
+  ASSERT(cgen_->HasValidEntryRegisters());
+  __ CallRuntime(f, arg_count);
+  Result result = cgen_->allocator()->Allocate(r0);
+  ASSERT(result.is_valid());
+  return result;
+}
+
+
+Result VirtualFrame::CallRuntime(Runtime::FunctionId id, int arg_count) {
+  PrepareForCall(arg_count, arg_count);
+  ASSERT(cgen_->HasValidEntryRegisters());
+  __ CallRuntime(id, arg_count);
+  Result result = cgen_->allocator()->Allocate(r0);
+  ASSERT(result.is_valid());
+  return result;
+}
+
+
+Result VirtualFrame::InvokeBuiltin(Builtins::JavaScript id,
+                                   InvokeJSFlags flags,
+                                   Result* arg_count_register,
+                                   int arg_count) {
+  ASSERT(arg_count_register->reg().is(r0));
+  PrepareForCall(arg_count, arg_count);
+  arg_count_register->Unuse();
+  __ InvokeBuiltin(id, flags);
+  Result result = cgen_->allocator()->Allocate(r0);
+  return result;
+}
+
+
+Result VirtualFrame::RawCallCodeObject(Handle<Code> code,
+                                       RelocInfo::Mode rmode) {
+  ASSERT(cgen_->HasValidEntryRegisters());
+  __ Call(code, rmode);
+  Result result = cgen_->allocator()->Allocate(r0);
+  ASSERT(result.is_valid());
+  return result;
+}
+
+
+Result VirtualFrame::CallCodeObject(Handle<Code> code,
+                                    RelocInfo::Mode rmode,
+                                    int dropped_args) {
+  int spilled_args = 0;
+  switch (code->kind()) {
+    case Code::CALL_IC:
+      spilled_args = dropped_args + 1;
+      break;
+    case Code::FUNCTION:
+      spilled_args = dropped_args + 1;
+      break;
+    case Code::KEYED_LOAD_IC:
+      ASSERT(dropped_args == 0);
+      spilled_args = 2;
+      break;
+    default:
+      // The other types of code objects are called with values
+      // in specific registers, and are handled in functions with
+      // a different signature.
+      UNREACHABLE();
+      break;
+  }
+  PrepareForCall(spilled_args, dropped_args);
+  return RawCallCodeObject(code, rmode);
+}
+
+
+Result VirtualFrame::CallCodeObject(Handle<Code> code,
+                                    RelocInfo::Mode rmode,
+                                    Result* arg,
+                                    int dropped_args) {
+  int spilled_args = 0;
+  switch (code->kind()) {
+    case Code::LOAD_IC:
+      ASSERT(arg->reg().is(r2));
+      ASSERT(dropped_args == 0);
+      spilled_args = 1;
+      break;
+    case Code::KEYED_STORE_IC:
+      ASSERT(arg->reg().is(r0));
+      ASSERT(dropped_args == 0);
+      spilled_args = 2;
+      break;
+    default:
+      // No other types of code objects are called with values
+      // in exactly one register.
+      UNREACHABLE();
+      break;
+  }
+  PrepareForCall(spilled_args, dropped_args);
+  arg->Unuse();
+  return RawCallCodeObject(code, rmode);
+}
+
+
+Result VirtualFrame::CallCodeObject(Handle<Code> code,
+                                    RelocInfo::Mode rmode,
+                                    Result* arg0,
+                                    Result* arg1,
+                                    int dropped_args) {
+  int spilled_args = 1;
+  switch (code->kind()) {
+    case Code::STORE_IC:
+      ASSERT(arg0->reg().is(r0));
+      ASSERT(arg1->reg().is(r2));
+      ASSERT(dropped_args == 0);
+      spilled_args = 1;
+      break;
+    case Code::BUILTIN:
+      ASSERT(*code == Builtins::builtin(Builtins::JSConstructCall));
+      ASSERT(arg0->reg().is(r0));
+      ASSERT(arg1->reg().is(r1));
+      spilled_args = dropped_args + 1;
+      break;
+    default:
+      // No other types of code objects are called with values
+      // in exactly two registers.
+      UNREACHABLE();
+      break;
+  }
+  PrepareForCall(spilled_args, dropped_args);
+  arg0->Unuse();
+  arg1->Unuse();
+  return RawCallCodeObject(code, rmode);
+}
+
+
+void VirtualFrame::Drop(int count) {
+  ASSERT(height() >= count);
+  int num_virtual_elements = (elements_.length() - 1) - stack_pointer_;
+
+  // Emit code to lower the stack pointer if necessary.
+  if (num_virtual_elements < count) {
+    int num_dropped = count - num_virtual_elements;
+    stack_pointer_ -= num_dropped;
+    __ add(sp, sp, Operand(num_dropped * kPointerSize));
+  }
+
+  // Discard elements from the virtual frame and free any registers.
+  for (int i = 0; i < count; i++) {
+    FrameElement dropped = elements_.RemoveLast();
+    if (dropped.is_register()) {
+      Unuse(dropped.reg());
+    }
+  }
+}
+
+
+Result VirtualFrame::Pop() {
+  UNIMPLEMENTED();
+  Result invalid(cgen_);
+  return invalid;
+}
+
+
+void VirtualFrame::EmitPop(Register reg) {
+  ASSERT(stack_pointer_ == elements_.length() - 1);
+  stack_pointer_--;
+  elements_.RemoveLast();
+  __ pop(reg);
+}
+
+
+void VirtualFrame::EmitPush(Register reg) {
+  ASSERT(stack_pointer_ == elements_.length() - 1);
+  elements_.Add(FrameElement::MemoryElement());
+  stack_pointer_++;
+  __ push(reg);
+}
+
+
+#undef __
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/virtual-frame-arm.h b/deps/v8/src/virtual-frame-arm.h
new file mode 100644
index 0000000..af3c08c
--- /dev/null
+++ b/deps/v8/src/virtual-frame-arm.h
@@ -0,0 +1,480 @@
+// 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.
+
+#ifndef V8_VIRTUAL_FRAME_ARM_H_
+#define V8_VIRTUAL_FRAME_ARM_H_
+
+#include "register-allocator.h"
+
+namespace v8 { namespace internal {
+
+// -------------------------------------------------------------------------
+// Virtual frames
+//
+// The virtual frame is an abstraction of the physical stack frame.  It
+// encapsulates the parameters, frame-allocated locals, and the expression
+// stack.  It supports push/pop operations on the expression stack, as well
+// as random access to the expression stack elements, locals, and
+// parameters.
+
+class VirtualFrame : public Malloced {
+ public:
+  // A utility class to introduce a scope where the virtual frame is
+  // expected to remain spilled.  The constructor spills the code
+  // generator's current frame, but no attempt is made to require it
+  // to stay spilled.  It is intended as documentation while the code
+  // generator is being transformed.
+  class SpilledScope BASE_EMBEDDED {
+   public:
+    explicit SpilledScope(CodeGenerator* cgen);
+
+    ~SpilledScope();
+
+   private:
+    CodeGenerator* cgen_;
+    bool previous_state_;
+  };
+
+  // An illegal index into the virtual frame.
+  static const int kIllegalIndex = -1;
+
+  // Construct an initial virtual frame on entry to a JS function.
+  explicit VirtualFrame(CodeGenerator* cgen);
+
+  // Construct a virtual frame as a clone of an existing one.
+  explicit VirtualFrame(VirtualFrame* original);
+
+  // Create a duplicate of an existing valid frame element.
+  FrameElement CopyElementAt(int index);
+
+  // The height of the virtual expression stack.
+  int height() const {
+    return elements_.length() - expression_base_index();
+  }
+
+  int register_index(Register reg) {
+    return register_locations_[reg.code()];
+  }
+
+  bool is_used(int reg_code) {
+    return register_locations_[reg_code] != kIllegalIndex;
+  }
+
+  bool is_used(Register reg) {
+    return is_used(reg.code());
+  }
+
+  // Add extra in-memory elements to the top of the frame to match an actual
+  // frame (eg, the frame after an exception handler is pushed).  No code is
+  // emitted.
+  void Adjust(int count);
+
+  // Forget elements from the top of the frame to match an actual frame (eg,
+  // the frame after a runtime call).  No code is emitted.
+  void Forget(int count);
+
+  // Forget count elements from the top of the frame without adjusting
+  // the stack pointer downward.  This is used, for example, before
+  // merging frames at break, continue, and return targets.
+  void ForgetElements(int count);
+
+  // Spill all values from the frame to memory.
+  void SpillAll();
+
+  // Spill all occurrences of a specific register from the frame.
+  void Spill(Register reg);
+
+  // Spill all occurrences of an arbitrary register if possible.  Return the
+  // register spilled or no_reg if it was not possible to free any register
+  // (ie, they all have frame-external references).
+  Register SpillAnyRegister();
+
+  // Prepare this virtual frame for merging to an expected frame by
+  // performing some state changes that do not require generating
+  // code.  It is guaranteed that no code will be generated.
+  void PrepareMergeTo(VirtualFrame* expected);
+
+  // Make this virtual frame have a state identical to an expected virtual
+  // frame.  As a side effect, code may be emitted to make this frame match
+  // the expected one.
+  void MergeTo(VirtualFrame* expected);
+
+  // Detach a frame from its code generator, perhaps temporarily.  This
+  // tells the register allocator that it is free to use frame-internal
+  // registers.  Used when the code generator's frame is switched from this
+  // one to NULL by an unconditional jump.
+  void DetachFromCodeGenerator();
+
+  // (Re)attach a frame to its code generator.  This informs the register
+  // allocator that the frame-internal register references are active again.
+  // Used when a code generator's frame is switched from NULL to this one by
+  // binding a label.
+  void AttachToCodeGenerator();
+
+  // Emit code for the physical JS entry and exit frame sequences.  After
+  // calling Enter, the virtual frame is ready for use; and after calling
+  // Exit it should not be used.  Note that Enter does not allocate space in
+  // the physical frame for storing frame-allocated locals.
+  void Enter();
+  void Exit();
+
+  // Prepare for returning from the frame by spilling locals and
+  // dropping all non-locals elements in the virtual frame.  This
+  // avoids generating unnecessary merge code when jumping to the
+  // shared return site.  Emits code for spills.
+  void PrepareForReturn();
+
+  // Allocate and initialize the frame-allocated locals.
+  void AllocateStackSlots(int count);
+
+  // The current top of the expression stack as an assembly operand.
+  MemOperand Top() const { return MemOperand(sp, 0); }
+
+  // An element of the expression stack as an assembly operand.
+  MemOperand ElementAt(int index) const {
+    return MemOperand(sp, index * kPointerSize);
+  }
+
+  // Random-access store to a frame-top relative frame element.  The result
+  // becomes owned by the frame and is invalidated.
+  void SetElementAt(int index, Result* value);
+
+  // Set a frame element to a constant.  The index is frame-top relative.
+  void SetElementAt(int index, Handle<Object> value) {
+    Result temp(value, cgen_);
+    SetElementAt(index, &temp);
+  }
+
+  void PushElementAt(int index) {
+    PushFrameSlotAt(elements_.length() - index - 1);
+  }
+
+  // A frame-allocated local as an assembly operand.
+  MemOperand LocalAt(int index) const {
+    ASSERT(0 <= index);
+    ASSERT(index < local_count_);
+    return MemOperand(fp, kLocal0Offset - index * kPointerSize);
+  }
+
+  // Push a copy of the value of a local frame slot on top of the frame.
+  void PushLocalAt(int index) {
+    PushFrameSlotAt(local0_index() + index);
+  }
+
+  // Push the value of a local frame slot on top of the frame and invalidate
+  // the local slot.  The slot should be written to before trying to read
+  // from it again.
+  void TakeLocalAt(int index) {
+    TakeFrameSlotAt(local0_index() + index);
+  }
+
+  // Store the top value on the virtual frame into a local frame slot.  The
+  // value is left in place on top of the frame.
+  void StoreToLocalAt(int index) {
+    StoreToFrameSlotAt(local0_index() + index);
+  }
+
+  // Push the address of the receiver slot on the frame.
+  void PushReceiverSlotAddress();
+
+  // The function frame slot.
+  MemOperand Function() const { return MemOperand(fp, kFunctionOffset); }
+
+  // Push the function on top of the frame.
+  void PushFunction() { PushFrameSlotAt(function_index()); }
+
+  // The context frame slot.
+  MemOperand Context() const { return MemOperand(fp, kContextOffset); }
+
+  // Save the value of the esi register to the context frame slot.
+  void SaveContextRegister();
+
+  // Restore the esi register from the value of the context frame
+  // slot.
+  void RestoreContextRegister();
+
+  // A parameter as an assembly operand.
+  MemOperand ParameterAt(int index) const {
+    // Index -1 corresponds to the receiver.
+    ASSERT(-1 <= index && index <= parameter_count_);
+    return MemOperand(fp, (1 + parameter_count_ - index) * kPointerSize);
+  }
+
+  // Push a copy of the value of a parameter frame slot on top of the frame.
+  void PushParameterAt(int index) {
+    PushFrameSlotAt(param0_index() + index);
+  }
+
+  // Push the value of a paramter frame slot on top of the frame and
+  // invalidate the parameter slot.  The slot should be written to before
+  // trying to read from it again.
+  void TakeParameterAt(int index) {
+    TakeFrameSlotAt(param0_index() + index);
+  }
+
+  // Store the top value on the virtual frame into a parameter frame slot.
+  // The value is left in place on top of the frame.
+  void StoreToParameterAt(int index) {
+    StoreToFrameSlotAt(param0_index() + index);
+  }
+
+  // The receiver frame slot.
+  MemOperand Receiver() const { return ParameterAt(-1); }
+
+  // Push a try-catch or try-finally handler on top of the virtual frame.
+  void PushTryHandler(HandlerType type);
+
+  // Call stub given the number of arguments it expects on (and
+  // removes from) the stack.
+  Result CallStub(CodeStub* stub, int arg_count);
+
+  // Call stub that expects its argument in r0.  The argument is given
+  // as a result which must be the register r0.
+  Result CallStub(CodeStub* stub, Result* arg);
+
+  // Call stub that expects its arguments in r1 and r0.  The arguments
+  // are given as results which must be the appropriate registers.
+  Result CallStub(CodeStub* stub, Result* arg0, Result* arg1);
+
+  // Call runtime given the number of arguments expected on (and
+  // removed from) the stack.
+  Result CallRuntime(Runtime::Function* f, int arg_count);
+  Result CallRuntime(Runtime::FunctionId id, int arg_count);
+
+  // Invoke builtin given the number of arguments it expects on (and
+  // removes from) the stack.
+  Result InvokeBuiltin(Builtins::JavaScript id,
+                       InvokeJSFlags flag,
+                       Result* arg_count_register,
+                       int arg_count);
+
+  // Call into an IC stub given the number of arguments it removes
+  // from the stack.  Register arguments are passed as results and
+  // consumed by the call.
+  Result CallCodeObject(Handle<Code> ic,
+                        RelocInfo::Mode rmode,
+                        int dropped_args);
+  Result CallCodeObject(Handle<Code> ic,
+                        RelocInfo::Mode rmode,
+                        Result* arg,
+                        int dropped_args);
+  Result CallCodeObject(Handle<Code> ic,
+                        RelocInfo::Mode rmode,
+                        Result* arg0,
+                        Result* arg1,
+                        int dropped_args);
+
+  // Drop a number of elements from the top of the expression stack.  May
+  // emit code to affect the physical frame.  Does not clobber any registers
+  // excepting possibly the stack pointer.
+  void Drop(int count);
+
+  // Drop one element.
+  void Drop() { Drop(1); }
+
+  // Duplicate the top element of the frame.
+  void Dup() { PushFrameSlotAt(elements_.length() - 1); }
+
+  // Pop an element from the top of the expression stack.  Returns a
+  // Result, which may be a constant or a register.
+  Result Pop();
+
+  // Pop and save an element from the top of the expression stack and
+  // emit a corresponding pop instruction.
+  void EmitPop(Register reg);
+
+  // Push an element on top of the expression stack and emit a
+  // corresponding push instruction.
+  void EmitPush(Register reg);
+
+  // Push an element on the virtual frame.
+  void Push(Register reg, StaticType static_type = StaticType());
+  void Push(Handle<Object> value);
+  void Push(Smi* value) { Push(Handle<Object>(value)); }
+
+  // Pushing a result invalidates it (its contents become owned by the frame).
+  void Push(Result* result);
+
+  // Nip removes zero or more elements from immediately below the top
+  // of the frame, leaving the previous top-of-frame value on top of
+  // the frame.  Nip(k) is equivalent to x = Pop(), Drop(k), Push(x).
+  void Nip(int num_dropped);
+
+ private:
+  static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
+  static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset;
+  static const int kContextOffset = StandardFrameConstants::kContextOffset;
+
+  static const int kHandlerSize = StackHandlerConstants::kSize / kPointerSize;
+  static const int kPreallocatedElements = 5 + 8;  // 8 expression stack slots.
+
+  CodeGenerator* cgen_;
+  MacroAssembler* masm_;
+
+  List<FrameElement> elements_;
+
+  // The number of frame-allocated locals and parameters respectively.
+  int parameter_count_;
+  int local_count_;
+
+  // The index of the element that is at the processor's stack pointer
+  // (the sp register).
+  int stack_pointer_;
+
+  // The index of the element that is at the processor's frame pointer
+  // (the fp register).
+  int frame_pointer_;
+
+  // The index of the register frame element using each register, or
+  // kIllegalIndex if a register is not on the frame.
+  int register_locations_[kNumRegisters];
+
+  // The index of the first parameter.  The receiver lies below the first
+  // parameter.
+  int param0_index() const { return 1; }
+
+  // The index of the context slot in the frame.
+  int context_index() const {
+    ASSERT(frame_pointer_ != kIllegalIndex);
+    return frame_pointer_ - 1;
+  }
+
+  // The index of the function slot in the frame.  It lies above the context
+  // slot.
+  int function_index() const {
+    ASSERT(frame_pointer_ != kIllegalIndex);
+    return frame_pointer_ - 2;
+  }
+
+  // The index of the first local.  Between the parameters and the locals
+  // lie the return address, the saved frame pointer, the context, and the
+  // function.
+  int local0_index() const {
+    ASSERT(frame_pointer_ != kIllegalIndex);
+    return frame_pointer_ + 2;
+  }
+
+  // The index of the base of the expression stack.
+  int expression_base_index() const { return local0_index() + local_count_; }
+
+  // Convert a frame index into a frame pointer relative offset into the
+  // actual stack.
+  int fp_relative(int index) const {
+    return (frame_pointer_ - index) * kPointerSize;
+  }
+
+  // Record an occurrence of a register in the virtual frame.  This has the
+  // effect of incrementing the register's external reference count and
+  // of updating the index of the register's location in the frame.
+  void Use(Register reg, int index);
+
+  // Record that a register reference has been dropped from the frame.  This
+  // decrements the register's external reference count and invalidates the
+  // index of the register's location in the frame.
+  void Unuse(Register reg);
+
+  // Spill the element at a particular index---write it to memory if
+  // necessary, free any associated register, and forget its value if
+  // constant.
+  void SpillElementAt(int index);
+
+  // Sync the element at a particular index.  If it is a register or
+  // constant that disagrees with the value on the stack, write it to memory.
+  // Keep the element type as register or constant, and clear the dirty bit.
+  void SyncElementAt(int index);
+
+  // Sync the range of elements in [begin, end).
+  void SyncRange(int begin, int end);
+
+  // Sync a single unsynced element that lies beneath or at the stack pointer.
+  void SyncElementBelowStackPointer(int index);
+
+  // Sync a single unsynced element that lies just above the stack pointer.
+  void SyncElementByPushing(int index);
+
+  // Push a copy of a frame slot (typically a local or parameter) on top of
+  // the frame.
+  void PushFrameSlotAt(int index);
+
+  // Push a the value of a frame slot (typically a local or parameter) on
+  // top of the frame and invalidate the slot.
+  void TakeFrameSlotAt(int index);
+
+  // Store the value on top of the frame to a frame slot (typically a local
+  // or parameter).
+  void StoreToFrameSlotAt(int index);
+
+  // Spill all elements in registers. Spill the top spilled_args elements
+  // on the frame.  Sync all other frame elements.
+  // Then drop dropped_args elements from the virtual frame, to match
+  // the effect of an upcoming call that will drop them from the stack.
+  void PrepareForCall(int spilled_args, int dropped_args);
+
+  // Move frame elements currently in registers or constants, that
+  // should be in memory in the expected frame, to memory.
+  void MergeMoveRegistersToMemory(VirtualFrame* expected);
+
+  // Make the register-to-register moves necessary to
+  // merge this frame with the expected frame.
+  // Register to memory moves must already have been made,
+  // and memory to register moves must follow this call.
+  // This is because some new memory-to-register moves are
+  // created in order to break cycles of register moves.
+  // Used in the implementation of MergeTo().
+  void MergeMoveRegistersToRegisters(VirtualFrame* expected);
+
+  // Make the memory-to-register and constant-to-register moves
+  // needed to make this frame equal the expected frame.
+  // Called after all register-to-memory and register-to-register
+  // moves have been made.  After this function returns, the frames
+  // should be equal.
+  void MergeMoveMemoryToRegisters(VirtualFrame* expected);
+
+  // Invalidates a frame slot (puts an invalid frame element in it).
+  // Copies on the frame are correctly handled, and if this slot was
+  // the backing store of copies, the index of the new backing store
+  // is returned.  Otherwise, returns kIllegalIndex.
+  // Register counts are correctly updated.
+  int InvalidateFrameSlotAt(int index);
+
+  // Call a code stub that has already been prepared for calling (via
+  // PrepareForCall).
+  Result RawCallStub(CodeStub* stub);
+
+  // Calls a code object which has already been prepared for calling
+  // (via PrepareForCall).
+  Result RawCallCodeObject(Handle<Code> code, RelocInfo::Mode rmode);
+
+  bool Equals(VirtualFrame* other);
+
+  friend class JumpTarget;
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_VIRTUAL_FRAME_ARM_H_
diff --git a/deps/v8/src/virtual-frame-ia32.cc b/deps/v8/src/virtual-frame-ia32.cc
new file mode 100644
index 0000000..eb3befc
--- /dev/null
+++ b/deps/v8/src/virtual-frame-ia32.cc
@@ -0,0 +1,1040 @@
+// 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.
+
+#include "v8.h"
+
+#include "codegen-inl.h"
+#include "register-allocator-inl.h"
+#include "scopes.h"
+
+namespace v8 { namespace internal {
+
+#define __ masm_->
+
+// -------------------------------------------------------------------------
+// VirtualFrame implementation.
+
+// On entry to a function, the virtual frame already contains the receiver,
+// the parameters, and a return address.  All frame elements are in memory.
+VirtualFrame::VirtualFrame(CodeGenerator* cgen)
+    : cgen_(cgen),
+      masm_(cgen->masm()),
+      elements_(cgen->scope()->num_parameters()
+                + cgen->scope()->num_stack_slots()
+                + kPreallocatedElements),
+      parameter_count_(cgen->scope()->num_parameters()),
+      local_count_(0),
+      stack_pointer_(parameter_count_ + 1),  // 0-based index of TOS.
+      frame_pointer_(kIllegalIndex) {
+  for (int i = 0; i < parameter_count_ + 2; i++) {
+    elements_.Add(FrameElement::MemoryElement());
+  }
+  for (int i = 0; i < kNumRegisters; i++) {
+    register_locations_[i] = kIllegalIndex;
+  }
+}
+
+
+void VirtualFrame::SyncElementBelowStackPointer(int index) {
+  // Emit code to write elements below the stack pointer to their
+  // (already allocated) stack address.
+  ASSERT(index <= stack_pointer_);
+  FrameElement element = elements_[index];
+  ASSERT(!element.is_synced());
+  switch (element.type()) {
+    case FrameElement::INVALID:
+      break;
+
+    case FrameElement::MEMORY:
+      // This function should not be called with synced elements.
+      // (memory elements are always synced).
+      UNREACHABLE();
+      break;
+
+    case FrameElement::REGISTER:
+      __ mov(Operand(ebp, fp_relative(index)), element.reg());
+      break;
+
+    case FrameElement::CONSTANT:
+      if (cgen_->IsUnsafeSmi(element.handle())) {
+        Result temp = cgen_->allocator()->Allocate();
+        ASSERT(temp.is_valid());
+        cgen_->LoadUnsafeSmi(temp.reg(), element.handle());
+        __ mov(Operand(ebp, fp_relative(index)), temp.reg());
+      } else {
+        __ Set(Operand(ebp, fp_relative(index)),
+               Immediate(element.handle()));
+      }
+      break;
+
+    case FrameElement::COPY: {
+      int backing_index = element.index();
+      FrameElement backing_element = elements_[backing_index];
+      if (backing_element.is_memory()) {
+        Result temp = cgen_->allocator()->Allocate();
+        ASSERT(temp.is_valid());
+        __ mov(temp.reg(), Operand(ebp, fp_relative(backing_index)));
+        __ mov(Operand(ebp, fp_relative(index)), temp.reg());
+      } else {
+        ASSERT(backing_element.is_register());
+        __ mov(Operand(ebp, fp_relative(index)), backing_element.reg());
+      }
+      break;
+    }
+  }
+  elements_[index].set_sync();
+}
+
+
+void VirtualFrame::SyncElementByPushing(int index) {
+  // Sync an element of the frame that is just above the stack pointer
+  // by pushing it.
+  ASSERT(index == stack_pointer_ + 1);
+  stack_pointer_++;
+  FrameElement element = elements_[index];
+
+  switch (element.type()) {
+    case FrameElement::INVALID:
+      __ push(Immediate(Smi::FromInt(0)));
+      break;
+
+    case FrameElement::MEMORY:
+      // No memory elements exist above the stack pointer.
+      UNREACHABLE();
+      break;
+
+    case FrameElement::REGISTER:
+      __ push(element.reg());
+      break;
+
+    case FrameElement::CONSTANT:
+      if (cgen_->IsUnsafeSmi(element.handle())) {
+        Result temp = cgen_->allocator()->Allocate();
+        ASSERT(temp.is_valid());
+        cgen_->LoadUnsafeSmi(temp.reg(), element.handle());
+        __ push(temp.reg());
+      } else {
+        __ push(Immediate(element.handle()));
+      }
+      break;
+
+    case FrameElement::COPY: {
+      int backing_index = element.index();
+      FrameElement backing = elements_[backing_index];
+      ASSERT(backing.is_memory() || backing.is_register());
+      if (backing.is_memory()) {
+        __ push(Operand(ebp, fp_relative(backing_index)));
+      } else {
+        __ push(backing.reg());
+      }
+      break;
+    }
+  }
+  elements_[index].set_sync();
+}
+
+
+void VirtualFrame::MergeTo(VirtualFrame* expected) {
+  Comment cmnt(masm_, "[ Merge frame");
+  // We should always be merging the code generator's current frame to an
+  // expected frame.
+  ASSERT(cgen_->frame() == this);
+
+  // Adjust the stack pointer upward (toward the top of the virtual
+  // frame) if necessary.
+  if (stack_pointer_ < expected->stack_pointer_) {
+    int difference = expected->stack_pointer_ - stack_pointer_;
+    stack_pointer_ = expected->stack_pointer_;
+    __ sub(Operand(esp), Immediate(difference * kPointerSize));
+  }
+
+  MergeMoveRegistersToMemory(expected);
+  MergeMoveRegistersToRegisters(expected);
+  MergeMoveMemoryToRegisters(expected);
+
+  // Fix any sync flag problems from the bottom-up and make the copied
+  // flags exact.  This assumes that the backing store of copies is
+  // always lower in the frame.
+  for (int i = 0; i < elements_.length(); i++) {
+    FrameElement source = elements_[i];
+    FrameElement target = expected->elements_[i];
+    if (source.is_synced() && !target.is_synced()) {
+      elements_[i].clear_sync();
+    } else if (!source.is_synced() && target.is_synced()) {
+      SyncElementAt(i);
+    }
+    elements_[i].clear_copied();
+    if (elements_[i].is_copy()) {
+      elements_[elements_[i].index()].set_copied();
+    }
+  }
+
+  // Adjust the stack pointer downward if necessary.
+  if (stack_pointer_ > expected->stack_pointer_) {
+    int difference = stack_pointer_ - expected->stack_pointer_;
+    stack_pointer_ = expected->stack_pointer_;
+    __ add(Operand(esp), Immediate(difference * kPointerSize));
+  }
+
+  // At this point, the frames should be identical.
+  ASSERT(Equals(expected));
+}
+
+
+void VirtualFrame::MergeMoveRegistersToMemory(VirtualFrame* expected) {
+  ASSERT(stack_pointer_ >= expected->stack_pointer_);
+
+  // Move registers, constants, and copies to memory.  Perform moves
+  // from the top downward in the frame in order to leave the backing
+  // stores of copies in registers.
+  //
+  // Moving memory-backed copies to memory requires a spare register
+  // for the memory-to-memory moves.  Since we are performing a merge,
+  // we use esi (which is already saved in the frame).  We keep track
+  // of the index of the frame element esi is caching or kIllegalIndex
+  // if esi has not been disturbed.
+  int esi_caches = kIllegalIndex;
+  // A "singleton" memory element.
+  FrameElement memory_element = FrameElement::MemoryElement();
+  // Loop downward from the stack pointer or the top of the frame if
+  // the stack pointer is floating above the frame.
+  int start = Min(stack_pointer_, elements_.length() - 1);
+  for (int i = start; i >= 0; i--) {
+    FrameElement target = expected->elements_[i];
+    if (target.is_memory()) {
+      FrameElement source = elements_[i];
+      switch (source.type()) {
+        case FrameElement::INVALID:
+          // Not a legal merge move.
+          UNREACHABLE();
+          break;
+
+        case FrameElement::MEMORY:
+          // Already in place.
+          break;
+
+        case FrameElement::REGISTER:
+          Unuse(source.reg());
+          if (!source.is_synced()) {
+            __ mov(Operand(ebp, fp_relative(i)), source.reg());
+          }
+          break;
+
+        case FrameElement::CONSTANT:
+          if (!source.is_synced()) {
+            if (cgen_->IsUnsafeSmi(source.handle())) {
+              esi_caches = i;
+              cgen_->LoadUnsafeSmi(esi, source.handle());
+              __ mov(Operand(ebp, fp_relative(i)), esi);
+            } else {
+              __ Set(Operand(ebp, fp_relative(i)), Immediate(source.handle()));
+            }
+          }
+          break;
+
+        case FrameElement::COPY:
+          if (!source.is_synced()) {
+            int backing_index = source.index();
+            FrameElement backing_element = elements_[backing_index];
+            if (backing_element.is_memory()) {
+              // If we have to spill a register, we spill esi.
+              if (esi_caches != backing_index) {
+                esi_caches = backing_index;
+                __ mov(esi, Operand(ebp, fp_relative(backing_index)));
+              }
+              __ mov(Operand(ebp, fp_relative(i)), esi);
+            } else {
+              ASSERT(backing_element.is_register());
+              __ mov(Operand(ebp, fp_relative(i)), backing_element.reg());
+            }
+          }
+          break;
+      }
+      elements_[i] = memory_element;
+    }
+  }
+
+  if (esi_caches != kIllegalIndex) {
+    __ mov(esi, Operand(ebp, fp_relative(context_index())));
+  }
+}
+
+
+void VirtualFrame::MergeMoveRegistersToRegisters(VirtualFrame* expected) {
+  // We have already done X-to-memory moves.
+  ASSERT(stack_pointer_ >= expected->stack_pointer_);
+
+  // Perform register-to-register moves.
+  int start = 0;
+  int end = elements_.length() - 1;
+  bool any_moves_blocked;  // Did we fail to make some moves this iteration?
+  bool should_break_cycles = false;
+  bool any_moves_made;  // Did we make any progress this iteration?
+  do {
+    any_moves_blocked = false;
+    any_moves_made = false;
+    int first_move_blocked = kIllegalIndex;
+    int last_move_blocked = kIllegalIndex;
+    for (int i = start; i <= end; i++) {
+      FrameElement source = elements_[i];
+      FrameElement target = expected->elements_[i];
+      if (source.is_register() && target.is_register()) {
+        if (target.reg().is(source.reg())) {
+          if (target.is_synced() && !source.is_synced()) {
+            __ mov(Operand(ebp, fp_relative(i)), source.reg());
+          }
+          elements_[i] = target;
+        } else {
+          // We need to move source to target.
+          if (is_used(target.reg())) {
+            // The move is blocked because the target contains valid data.
+            // If we are stuck with only cycles remaining, then we spill source.
+            // Otherwise, we just need more iterations.
+            if (should_break_cycles) {
+              SpillElementAt(i);
+              should_break_cycles = false;
+            } else {  // Record a blocked move.
+              if (!any_moves_blocked) {
+                first_move_blocked = i;
+              }
+              last_move_blocked = i;
+              any_moves_blocked = true;
+            }
+          } else {
+            // The move is not blocked.  This frame element can be moved from
+            // its source register to its target register.
+            if (target.is_synced() && !source.is_synced()) {
+              SyncElementAt(i);
+            }
+            Use(target.reg(), i);
+            Unuse(source.reg());
+            elements_[i] = target;
+            __ mov(target.reg(), source.reg());
+            any_moves_made = true;
+          }
+        }
+      }
+    }
+    // Update control flags for next iteration.
+    should_break_cycles = (any_moves_blocked && !any_moves_made);
+    if (any_moves_blocked) {
+      start = first_move_blocked;
+      end = last_move_blocked;
+    }
+  } while (any_moves_blocked);
+}
+
+
+void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame *expected) {
+  // Move memory, constants, and copies to registers.  This is the
+  // final step and is done from the bottom up so that the backing
+  // elements of copies are in their correct locations when we
+  // encounter the copies.
+  for (int i = 0; i < elements_.length(); i++) {
+    FrameElement source = elements_[i];
+    FrameElement target = expected->elements_[i];
+    if (target.is_register() && !source.is_register()) {
+      switch (source.type()) {
+        case FrameElement::INVALID:  // Fall through.
+        case FrameElement::REGISTER:
+          UNREACHABLE();
+          break;
+
+        case FrameElement::MEMORY:
+          ASSERT(i <= stack_pointer_);
+          __ mov(target.reg(), Operand(ebp, fp_relative(i)));
+          break;
+
+        case FrameElement::CONSTANT:
+          if (cgen_->IsUnsafeSmi(source.handle())) {
+            cgen_->LoadUnsafeSmi(target.reg(), source.handle());
+          } else {
+           __ Set(target.reg(), Immediate(source.handle()));
+          }
+          break;
+
+        case FrameElement::COPY: {
+          FrameElement backing = elements_[source.index()];
+          ASSERT(backing.is_memory() || backing.is_register());
+          if (backing.is_memory()) {
+            ASSERT(source.index() <= stack_pointer_);
+            __ mov(target.reg(), Operand(ebp, fp_relative(source.index())));
+          } else {
+            __ mov(target.reg(), backing.reg());
+          }
+        }
+      }
+      // Ensure the proper sync state.  If the source was memory no
+      // code needs to be emitted.
+      if (target.is_synced() && !source.is_memory()) {
+        SyncElementAt(i);
+      }
+      Use(target.reg(), i);
+      elements_[i] = target;
+    }
+  }
+}
+
+
+void VirtualFrame::Enter() {
+  // Registers live on entry: esp, ebp, esi, edi.
+  Comment cmnt(masm_, "[ Enter JS frame");
+
+#ifdef DEBUG
+  // Verify that edi contains a JS function.  The following code
+  // relies on eax being available for use.
+  __ test(edi, Immediate(kSmiTagMask));
+  __ Check(not_zero,
+           "VirtualFrame::Enter - edi is not a function (smi check).");
+  __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax);
+  __ Check(equal,
+           "VirtualFrame::Enter - edi is not a function (map check).");
+#endif
+
+  EmitPush(ebp);
+
+  frame_pointer_ = stack_pointer_;
+  __ mov(ebp, Operand(esp));
+
+  // Store the context in the frame.  The context is kept in esi and a
+  // copy is stored in the frame.  The external reference to esi
+  // remains.
+  EmitPush(esi);
+
+  // Store the function in the frame.  The frame owns the register
+  // reference now (ie, it can keep it in edi or spill it later).
+  Push(edi);
+  SyncElementAt(elements_.length() - 1);
+  cgen_->allocator()->Unuse(edi);
+}
+
+
+void VirtualFrame::Exit() {
+  Comment cmnt(masm_, "[ Exit JS frame");
+  // Record the location of the JS exit code for patching when setting
+  // break point.
+  __ RecordJSReturn();
+
+  // Avoid using the leave instruction here, because it is too
+  // short. We need the return sequence to be a least the size of a
+  // call instruction to support patching the exit code in the
+  // debugger. See VisitReturnStatement for the full return sequence.
+  __ mov(esp, Operand(ebp));
+  stack_pointer_ = frame_pointer_;
+  for (int i = elements_.length() - 1; i > stack_pointer_; i--) {
+    FrameElement last = elements_.RemoveLast();
+    if (last.is_register()) {
+      Unuse(last.reg());
+    }
+  }
+
+  frame_pointer_ = kIllegalIndex;
+  EmitPop(ebp);
+}
+
+
+void VirtualFrame::AllocateStackSlots(int count) {
+  ASSERT(height() == 0);
+  local_count_ = count;
+
+  if (count > 0) {
+    Comment cmnt(masm_, "[ Allocate space for locals");
+    // The locals are initialized to a constant (the undefined value), but
+    // we sync them with the actual frame to allocate space for spilling
+    // them later.  First sync everything above the stack pointer so we can
+    // use pushes to allocate and initialize the locals.
+    SyncRange(stack_pointer_ + 1, elements_.length());
+    Handle<Object> undefined = Factory::undefined_value();
+    FrameElement initial_value =
+        FrameElement::ConstantElement(undefined, FrameElement::SYNCED);
+    Result temp = cgen_->allocator()->Allocate();
+    ASSERT(temp.is_valid());
+    __ Set(temp.reg(), Immediate(undefined));
+    for (int i = 0; i < count; i++) {
+      elements_.Add(initial_value);
+      stack_pointer_++;
+      __ push(temp.reg());
+    }
+  }
+}
+
+
+void VirtualFrame::SaveContextRegister() {
+  ASSERT(elements_[context_index()].is_memory());
+  __ mov(Operand(ebp, fp_relative(context_index())), esi);
+}
+
+
+void VirtualFrame::RestoreContextRegister() {
+  ASSERT(elements_[context_index()].is_memory());
+  __ mov(esi, Operand(ebp, fp_relative(context_index())));
+}
+
+
+void VirtualFrame::PushReceiverSlotAddress() {
+  Result temp = cgen_->allocator()->Allocate();
+  ASSERT(temp.is_valid());
+  __ lea(temp.reg(), ParameterAt(-1));
+  Push(&temp);
+}
+
+
+int VirtualFrame::InvalidateFrameSlotAt(int index) {
+  FrameElement original = elements_[index];
+
+  // Is this element the backing store of any copies?
+  int new_backing_index = kIllegalIndex;
+  if (original.is_copied()) {
+    // Verify it is copied, and find first copy.
+    for (int i = index + 1; i < elements_.length(); i++) {
+      if (elements_[i].is_copy() && elements_[i].index() == index) {
+        new_backing_index = i;
+        break;
+      }
+    }
+  }
+
+  if (new_backing_index == kIllegalIndex) {
+    // No copies found, return kIllegalIndex.
+    if (original.is_register()) {
+      Unuse(original.reg());
+    }
+    elements_[index] = FrameElement::InvalidElement();
+    return kIllegalIndex;
+  }
+
+  // This is the backing store of copies.
+  Register backing_reg;
+  if (original.is_memory()) {
+    Result fresh = cgen_->allocator()->Allocate();
+    ASSERT(fresh.is_valid());
+    Use(fresh.reg(), new_backing_index);
+    backing_reg = fresh.reg();
+    __ mov(backing_reg, Operand(ebp, fp_relative(index)));
+  } else {
+    // The original was in a register.
+    backing_reg = original.reg();
+    register_locations_[backing_reg.code()] = new_backing_index;
+  }
+  // Invalidate the element at index.
+  elements_[index] = FrameElement::InvalidElement();
+  // Set the new backing element.
+  if (elements_[new_backing_index].is_synced()) {
+    elements_[new_backing_index] =
+        FrameElement::RegisterElement(backing_reg, FrameElement::SYNCED);
+  } else {
+    elements_[new_backing_index] =
+        FrameElement::RegisterElement(backing_reg, FrameElement::NOT_SYNCED);
+  }
+  // Update the other copies.
+  for (int i = new_backing_index + 1; i < elements_.length(); i++) {
+    if (elements_[i].is_copy() && elements_[i].index() == index) {
+      elements_[i].set_index(new_backing_index);
+      elements_[new_backing_index].set_copied();
+    }
+  }
+  return new_backing_index;
+}
+
+
+void VirtualFrame::TakeFrameSlotAt(int index) {
+  ASSERT(index >= 0);
+  ASSERT(index <= elements_.length());
+  FrameElement original = elements_[index];
+  int new_backing_store_index = InvalidateFrameSlotAt(index);
+  if (new_backing_store_index != kIllegalIndex) {
+    elements_.Add(CopyElementAt(new_backing_store_index));
+    return;
+  }
+
+  switch (original.type()) {
+    case FrameElement::MEMORY: {
+      // Emit code to load the original element's data into a register.
+      // Push that register as a FrameElement on top of the frame.
+      Result fresh = cgen_->allocator()->Allocate();
+      ASSERT(fresh.is_valid());
+      FrameElement new_element =
+          FrameElement::RegisterElement(fresh.reg(),
+                                        FrameElement::NOT_SYNCED);
+      Use(fresh.reg(), elements_.length());
+      elements_.Add(new_element);
+      __ mov(fresh.reg(), Operand(ebp, fp_relative(index)));
+      break;
+    }
+    case FrameElement::REGISTER:
+      Use(original.reg(), elements_.length());
+      // Fall through.
+    case FrameElement::CONSTANT:
+    case FrameElement::COPY:
+      original.clear_sync();
+      elements_.Add(original);
+      break;
+    case FrameElement::INVALID:
+      UNREACHABLE();
+      break;
+  }
+}
+
+
+void VirtualFrame::StoreToFrameSlotAt(int index) {
+  // Store the value on top of the frame to the virtual frame slot at
+  // a given index.  The value on top of the frame is left in place.
+  // This is a duplicating operation, so it can create copies.
+  ASSERT(index >= 0);
+  ASSERT(index < elements_.length());
+
+  int top_index = elements_.length() - 1;
+  FrameElement top = elements_[top_index];
+  FrameElement original = elements_[index];
+  if (top.is_copy() && top.index() == index) return;
+  ASSERT(top.is_valid());
+
+  InvalidateFrameSlotAt(index);
+
+  if (top.is_copy()) {
+    // There are two cases based on the relative positions of the
+    // stored-to slot and the backing slot of the top element.
+    int backing_index = top.index();
+    ASSERT(backing_index != index);
+    if (backing_index < index) {
+      // 1. The top element is a copy of a slot below the stored-to
+      // slot.  The stored-to slot becomes an unsynced copy of that
+      // same backing slot.
+      elements_[index] = CopyElementAt(backing_index);
+    } else {
+      // 2. The top element is a copy of a slot above the stored-to
+      // slot.  The stored-to slot becomes the new (unsynced) backing
+      // slot and both the top element and the element at the former
+      // backing slot become copies of it.  The sync state of the top
+      // and former backing elements is preserved.
+      FrameElement backing_element = elements_[backing_index];
+      ASSERT(backing_element.is_memory() || backing_element.is_register());
+      if (backing_element.is_memory()) {
+        // Because sets of copies are canonicalized to be backed by
+        // their lowest frame element, and because memory frame
+        // elements are backed by the corresponding stack address, we
+        // have to move the actual value down in the stack.
+        //
+        // TODO(209): considering allocating the stored-to slot to the
+        // temp register.  Alternatively, allow copies to appear in
+        // any order in the frame and lazily move the value down to
+        // the slot.
+        Result temp = cgen_->allocator()->Allocate();
+        ASSERT(temp.is_valid());
+        __ mov(temp.reg(), Operand(ebp, fp_relative(backing_index)));
+        __ mov(Operand(ebp, fp_relative(index)), temp.reg());
+      } else {
+        register_locations_[backing_element.reg().code()] = index;
+        if (backing_element.is_synced()) {
+          // If the element is a register, we will not actually move
+          // anything on the stack but only update the virtual frame
+          // element.
+          backing_element.clear_sync();
+        }
+      }
+      elements_[index] = backing_element;
+
+      // The old backing element becomes a copy of the new backing
+      // element.
+      FrameElement new_element = CopyElementAt(index);
+      elements_[backing_index] = new_element;
+      if (backing_element.is_synced()) {
+        elements_[backing_index].set_sync();
+      }
+
+      // All the copies of the old backing element (including the top
+      // element) become copies of the new backing element.
+      for (int i = backing_index + 1; i < elements_.length(); i++) {
+        if (elements_[i].is_copy() && elements_[i].index() == backing_index) {
+          elements_[i].set_index(index);
+        }
+      }
+    }
+    return;
+  }
+
+  // Move the top element to the stored-to slot and replace it (the
+  // top element) with a copy.
+  elements_[index] = top;
+  if (top.is_memory()) {
+    // TODO(209): consider allocating the stored-to slot to the temp
+    // register.  Alternatively, allow copies to appear in any order
+    // in the frame and lazily move the value down to the slot.
+    FrameElement new_top = CopyElementAt(index);
+    new_top.set_sync();
+    elements_[top_index] = new_top;
+
+    // The sync state of the former top element is correct (synced).
+    // Emit code to move the value down in the frame.
+    Result temp = cgen_->allocator()->Allocate();
+    ASSERT(temp.is_valid());
+    __ mov(temp.reg(), Operand(esp, 0));
+    __ mov(Operand(ebp, fp_relative(index)), temp.reg());
+  } else if (top.is_register()) {
+    register_locations_[top.reg().code()] = index;
+    // The stored-to slot has the (unsynced) register reference and
+    // the top element becomes a copy.  The sync state of the top is
+    // preserved.
+    FrameElement new_top = CopyElementAt(index);
+    if (top.is_synced()) {
+      new_top.set_sync();
+      elements_[index].clear_sync();
+    }
+    elements_[top_index] = new_top;
+  } else {
+    // The stored-to slot holds the same value as the top but
+    // unsynced.  (We do not have copies of constants yet.)
+    ASSERT(top.is_constant());
+    elements_[index].clear_sync();
+  }
+}
+
+
+void VirtualFrame::PushTryHandler(HandlerType type) {
+  ASSERT(cgen_->HasValidEntryRegisters());
+  // Grow the expression stack by handler size less two (the return address
+  // is already pushed by a call instruction, and PushTryHandler from the
+  // macro assembler will leave the top of stack in the eax register to be
+  // pushed separately).
+  Adjust(kHandlerSize - 2);
+  __ PushTryHandler(IN_JAVASCRIPT, type);
+  // TODO(1222589): remove the reliance of PushTryHandler on a cached TOS
+  EmitPush(eax);
+}
+
+
+Result VirtualFrame::RawCallStub(CodeStub* stub) {
+  ASSERT(cgen_->HasValidEntryRegisters());
+  __ CallStub(stub);
+  Result result = cgen_->allocator()->Allocate(eax);
+  ASSERT(result.is_valid());
+  return result;
+}
+
+
+Result VirtualFrame::CallStub(CodeStub* stub, Result* arg) {
+  PrepareForCall(0, 0);
+  arg->ToRegister(eax);
+  arg->Unuse();
+  return RawCallStub(stub);
+}
+
+
+Result VirtualFrame::CallStub(CodeStub* stub, Result* arg0, Result* arg1) {
+  PrepareForCall(0, 0);
+
+  if (arg0->is_register() && arg0->reg().is(eax)) {
+    if (arg1->is_register() && arg1->reg().is(edx)) {
+      // Wrong registers.
+      __ xchg(eax, edx);
+    } else {
+      // Register edx is free for arg0, which frees eax for arg1.
+      arg0->ToRegister(edx);
+      arg1->ToRegister(eax);
+    }
+  } else {
+    // Register eax is free for arg1, which guarantees edx is free for
+    // arg0.
+    arg1->ToRegister(eax);
+    arg0->ToRegister(edx);
+  }
+
+  arg0->Unuse();
+  arg1->Unuse();
+  return RawCallStub(stub);
+}
+
+
+Result VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) {
+  PrepareForCall(arg_count, arg_count);
+  ASSERT(cgen_->HasValidEntryRegisters());
+  __ CallRuntime(f, arg_count);
+  Result result = cgen_->allocator()->Allocate(eax);
+  ASSERT(result.is_valid());
+  return result;
+}
+
+
+Result VirtualFrame::CallRuntime(Runtime::FunctionId id, int arg_count) {
+  PrepareForCall(arg_count, arg_count);
+  ASSERT(cgen_->HasValidEntryRegisters());
+  __ CallRuntime(id, arg_count);
+  Result result = cgen_->allocator()->Allocate(eax);
+  ASSERT(result.is_valid());
+  return result;
+}
+
+
+Result VirtualFrame::InvokeBuiltin(Builtins::JavaScript id,
+                                   InvokeFlag flag,
+                                   int arg_count) {
+  PrepareForCall(arg_count, arg_count);
+  ASSERT(cgen_->HasValidEntryRegisters());
+  __ InvokeBuiltin(id, flag);
+  Result result = cgen_->allocator()->Allocate(eax);
+  ASSERT(result.is_valid());
+  return result;
+}
+
+
+Result VirtualFrame::RawCallCodeObject(Handle<Code> code,
+                                       RelocInfo::Mode rmode) {
+  ASSERT(cgen_->HasValidEntryRegisters());
+  __ call(code, rmode);
+  Result result = cgen_->allocator()->Allocate(eax);
+  ASSERT(result.is_valid());
+  return result;
+}
+
+
+Result VirtualFrame::CallLoadIC(RelocInfo::Mode mode) {
+  // Name and receiver are on the top of the frame.  The IC expects
+  // name in ecx and receiver on the stack.  It does not drop the
+  // receiver.
+  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+  Result name = Pop();
+  PrepareForCall(1, 0);  // One stack arg, not callee-dropped.
+  name.ToRegister(ecx);
+  name.Unuse();
+  return RawCallCodeObject(ic, mode);
+}
+
+
+Result VirtualFrame::CallKeyedLoadIC(RelocInfo::Mode mode) {
+  // Key and receiver are on top of the frame.  The IC expects them on
+  // the stack.  It does not drop them.
+  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+  PrepareForCall(2, 0);  // Two stack args, neither callee-dropped.
+  return RawCallCodeObject(ic, mode);
+}
+
+
+Result VirtualFrame::CallStoreIC() {
+  // Name, value, and receiver are on top of the frame.  The IC
+  // expects name in ecx, value in eax, and receiver on the stack.  It
+  // does not drop the receiver.
+  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+  Result name = Pop();
+  Result value = Pop();
+  PrepareForCall(1, 0);  // One stack arg, not callee-dropped.
+
+  if (value.is_register() && value.reg().is(ecx)) {
+    if (name.is_register() && name.reg().is(eax)) {
+      // Wrong registers.
+      __ xchg(eax, ecx);
+    } else {
+      // Register eax is free for value, which frees ecx for name.
+      value.ToRegister(eax);
+      name.ToRegister(ecx);
+    }
+  } else {
+    // Register ecx is free for name, which guarantees eax is free for
+    // value.
+    name.ToRegister(ecx);
+    value.ToRegister(eax);
+  }
+
+  name.Unuse();
+  value.Unuse();
+  return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
+}
+
+
+Result VirtualFrame::CallKeyedStoreIC() {
+  // Value, key, and receiver are on the top of the frame.  The IC
+  // expects value in eax and key and receiver on the stack.  It does
+  // not drop the key and receiver.
+  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  // TODO(1222589): Make the IC grab the values from the stack.
+  Result value = Pop();
+  PrepareForCall(2, 0);  // Two stack args, neither callee-dropped.
+  value.ToRegister(eax);
+  value.Unuse();
+  return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
+}
+
+
+Result VirtualFrame::CallCallIC(RelocInfo::Mode mode,
+                                int arg_count,
+                                int loop_nesting) {
+  // Arguments, receiver, and function name are on top of the frame.
+  // The IC expects them on the stack.  It does not drop the function
+  // name slot (but it does drop the rest).
+  Handle<Code> ic = (loop_nesting > 0)
+                    ? cgen_->ComputeCallInitializeInLoop(arg_count)
+                    : cgen_->ComputeCallInitialize(arg_count);
+  // Spill args, receiver, and function.  The call will drop args and
+  // receiver.
+  PrepareForCall(arg_count + 2, arg_count + 1);
+  return RawCallCodeObject(ic, mode);
+}
+
+
+Result VirtualFrame::CallConstructor(int arg_count) {
+  // Arguments, receiver, and function are on top of the frame.  The
+  // IC expects arg count in eax, function in edi, and the arguments
+  // and receiver on the stack.
+  Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall));
+  // Duplicate the function before preparing the frame.
+  PushElementAt(arg_count + 1);
+  Result function = Pop();
+  PrepareForCall(arg_count + 1, arg_count + 1);  // Spill args and receiver.
+  function.ToRegister(edi);
+
+  // Constructors are called with the number of arguments in register
+  // eax for now. Another option would be to have separate construct
+  // call trampolines per different arguments counts encountered.
+  Result num_args = cgen_->allocator()->Allocate(eax);
+  ASSERT(num_args.is_valid());
+  __ Set(num_args.reg(), Immediate(arg_count));
+
+  function.Unuse();
+  num_args.Unuse();
+  return RawCallCodeObject(ic, RelocInfo::CONSTRUCT_CALL);
+}
+
+
+void VirtualFrame::Drop(int count) {
+  ASSERT(height() >= count);
+  int num_virtual_elements = (elements_.length() - 1) - stack_pointer_;
+
+  // Emit code to lower the stack pointer if necessary.
+  if (num_virtual_elements < count) {
+    int num_dropped = count - num_virtual_elements;
+    stack_pointer_ -= num_dropped;
+    __ add(Operand(esp), Immediate(num_dropped * kPointerSize));
+  }
+
+  // Discard elements from the virtual frame and free any registers.
+  for (int i = 0; i < count; i++) {
+    FrameElement dropped = elements_.RemoveLast();
+    if (dropped.is_register()) {
+      Unuse(dropped.reg());
+    }
+  }
+}
+
+
+Result VirtualFrame::Pop() {
+  FrameElement element = elements_.RemoveLast();
+  int index = elements_.length();
+  ASSERT(element.is_valid());
+
+  bool pop_needed = (stack_pointer_ == index);
+  if (pop_needed) {
+    stack_pointer_--;
+    if (element.is_memory()) {
+      Result temp = cgen_->allocator()->Allocate();
+      ASSERT(temp.is_valid());
+      temp.set_static_type(element.static_type());
+      __ pop(temp.reg());
+      return temp;
+    }
+
+    __ add(Operand(esp), Immediate(kPointerSize));
+  }
+  ASSERT(!element.is_memory());
+
+  // The top element is a register, constant, or a copy.  Unuse
+  // registers and follow copies to their backing store.
+  if (element.is_register()) {
+    Unuse(element.reg());
+  } else if (element.is_copy()) {
+    ASSERT(element.index() < index);
+    index = element.index();
+    element = elements_[index];
+  }
+  ASSERT(!element.is_copy());
+
+  // The element is memory, a register, or a constant.
+  if (element.is_memory()) {
+    // Memory elements could only be the backing store of a copy.
+    // Allocate the original to a register.
+    ASSERT(index <= stack_pointer_);
+    Result temp = cgen_->allocator()->Allocate();
+    ASSERT(temp.is_valid());
+    Use(temp.reg(), index);
+    FrameElement new_element =
+        FrameElement::RegisterElement(temp.reg(), FrameElement::SYNCED);
+    // Preserve the copy flag on the element.
+    if (element.is_copied()) new_element.set_copied();
+    new_element.set_static_type(element.static_type());
+    elements_[index] = new_element;
+    __ mov(temp.reg(), Operand(ebp, fp_relative(index)));
+    return Result(temp.reg(), cgen_, element.static_type());
+  } else if (element.is_register()) {
+    return Result(element.reg(), cgen_, element.static_type());
+  } else {
+    ASSERT(element.is_constant());
+    return Result(element.handle(), cgen_);
+  }
+}
+
+
+void VirtualFrame::EmitPop(Register reg) {
+  ASSERT(stack_pointer_ == elements_.length() - 1);
+  stack_pointer_--;
+  elements_.RemoveLast();
+  __ pop(reg);
+}
+
+
+void VirtualFrame::EmitPop(Operand operand) {
+  ASSERT(stack_pointer_ == elements_.length() - 1);
+  stack_pointer_--;
+  elements_.RemoveLast();
+  __ pop(operand);
+}
+
+
+void VirtualFrame::EmitPush(Register reg) {
+  ASSERT(stack_pointer_ == elements_.length() - 1);
+  elements_.Add(FrameElement::MemoryElement());
+  stack_pointer_++;
+  __ push(reg);
+}
+
+
+void VirtualFrame::EmitPush(Operand operand) {
+  ASSERT(stack_pointer_ == elements_.length() - 1);
+  elements_.Add(FrameElement::MemoryElement());
+  stack_pointer_++;
+  __ push(operand);
+}
+
+
+void VirtualFrame::EmitPush(Immediate immediate) {
+  ASSERT(stack_pointer_ == elements_.length() - 1);
+  elements_.Add(FrameElement::MemoryElement());
+  stack_pointer_++;
+  __ push(immediate);
+}
+
+
+#undef __
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/virtual-frame-ia32.h b/deps/v8/src/virtual-frame-ia32.h
new file mode 100644
index 0000000..113ccc6
--- /dev/null
+++ b/deps/v8/src/virtual-frame-ia32.h
@@ -0,0 +1,493 @@
+// 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.
+
+#ifndef V8_VIRTUAL_FRAME_IA32_H_
+#define V8_VIRTUAL_FRAME_IA32_H_
+
+#include "register-allocator.h"
+
+namespace v8 { namespace internal {
+
+// -------------------------------------------------------------------------
+// Virtual frames
+//
+// The virtual frame is an abstraction of the physical stack frame.  It
+// encapsulates the parameters, frame-allocated locals, and the expression
+// stack.  It supports push/pop operations on the expression stack, as well
+// as random access to the expression stack elements, locals, and
+// parameters.
+
+class VirtualFrame : public Malloced {
+ public:
+  // A utility class to introduce a scope where the virtual frame is
+  // expected to remain spilled.  The constructor spills the code
+  // generator's current frame, but no attempt is made to require it
+  // to stay spilled.  It is intended as documentation while the code
+  // generator is being transformed.
+  class SpilledScope BASE_EMBEDDED {
+   public:
+    explicit SpilledScope(CodeGenerator* cgen);
+
+    ~SpilledScope();
+
+   private:
+    CodeGenerator* cgen_;
+    bool previous_state_;
+  };
+
+  // An illegal index into the virtual frame.
+  static const int kIllegalIndex = -1;
+
+  // Construct an initial virtual frame on entry to a JS function.
+  explicit VirtualFrame(CodeGenerator* cgen);
+
+  // Construct a virtual frame as a clone of an existing one.
+  explicit VirtualFrame(VirtualFrame* original);
+
+  // Create a duplicate of an existing valid frame element.
+  FrameElement CopyElementAt(int index);
+
+  // The height of the virtual expression stack.
+  int height() const {
+    return elements_.length() - expression_base_index();
+  }
+
+  int register_index(Register reg) {
+    return register_locations_[reg.code()];
+  }
+
+  bool is_used(int reg_code) {
+    return register_locations_[reg_code] != kIllegalIndex;
+  }
+
+  bool is_used(Register reg) {
+    return is_used(reg.code());
+  }
+
+  // Add extra in-memory elements to the top of the frame to match an actual
+  // frame (eg, the frame after an exception handler is pushed).  No code is
+  // emitted.
+  void Adjust(int count);
+
+  // Forget count elements from the top of the frame all in-memory
+  // (including synced) and adjust the stack pointer downward, to
+  // match an external frame effect (examples include a call removing
+  // its arguments, and exiting a try/catch removing an exception
+  // handler).  No code will be emitted.
+  void Forget(int count);
+
+  // Forget count elements from the top of the frame without adjusting
+  // the stack pointer downward.  This is used, for example, before
+  // merging frames at break, continue, and return targets.
+  void ForgetElements(int count);
+
+  // Spill all values from the frame to memory.
+  void SpillAll();
+
+  // Spill all occurrences of a specific register from the frame.
+  void Spill(Register reg);
+
+  // Spill all occurrences of an arbitrary register if possible.  Return the
+  // register spilled or no_reg if it was not possible to free any register
+  // (ie, they all have frame-external references).
+  Register SpillAnyRegister();
+
+  // Prepare this virtual frame for merging to an expected frame by
+  // performing some state changes that do not require generating
+  // code.  It is guaranteed that no code will be generated.
+  void PrepareMergeTo(VirtualFrame* expected);
+
+  // Make this virtual frame have a state identical to an expected virtual
+  // frame.  As a side effect, code may be emitted to make this frame match
+  // the expected one.
+  void MergeTo(VirtualFrame* expected);
+
+  // Detach a frame from its code generator, perhaps temporarily.  This
+  // tells the register allocator that it is free to use frame-internal
+  // registers.  Used when the code generator's frame is switched from this
+  // one to NULL by an unconditional jump.
+  void DetachFromCodeGenerator();
+
+  // (Re)attach a frame to its code generator.  This informs the register
+  // allocator that the frame-internal register references are active again.
+  // Used when a code generator's frame is switched from NULL to this one by
+  // binding a label.
+  void AttachToCodeGenerator();
+
+  // Emit code for the physical JS entry and exit frame sequences.  After
+  // calling Enter, the virtual frame is ready for use; and after calling
+  // Exit it should not be used.  Note that Enter does not allocate space in
+  // the physical frame for storing frame-allocated locals.
+  void Enter();
+  void Exit();
+
+  // Prepare for returning from the frame by spilling locals.  This
+  // avoids generating unnecessary merge code when jumping to the
+  // shared return site.  Emits code for spills.
+  void PrepareForReturn();
+
+  // Allocate and initialize the frame-allocated locals.
+  void AllocateStackSlots(int count);
+
+  // An element of the expression stack as an assembly operand.
+  Operand ElementAt(int index) const {
+    return Operand(esp, index * kPointerSize);
+  }
+
+  // Random-access store to a frame-top relative frame element.  The result
+  // becomes owned by the frame and is invalidated.
+  void SetElementAt(int index, Result* value);
+
+  // Set a frame element to a constant.  The index is frame-top relative.
+  void SetElementAt(int index, Handle<Object> value) {
+    Result temp(value, cgen_);
+    SetElementAt(index, &temp);
+  }
+
+  void PushElementAt(int index) {
+    PushFrameSlotAt(elements_.length() - index - 1);
+  }
+
+  void StoreToElementAt(int index) {
+    StoreToFrameSlotAt(elements_.length() - index - 1);
+  }
+
+  // A frame-allocated local as an assembly operand.
+  Operand LocalAt(int index) const {
+    ASSERT(0 <= index);
+    ASSERT(index < local_count_);
+    return Operand(ebp, kLocal0Offset - index * kPointerSize);
+  }
+
+  // Push a copy of the value of a local frame slot on top of the frame.
+  void PushLocalAt(int index) {
+    PushFrameSlotAt(local0_index() + index);
+  }
+
+  // Push the value of a local frame slot on top of the frame and invalidate
+  // the local slot.  The slot should be written to before trying to read
+  // from it again.
+  void TakeLocalAt(int index) {
+    TakeFrameSlotAt(local0_index() + index);
+  }
+
+  // Store the top value on the virtual frame into a local frame slot.  The
+  // value is left in place on top of the frame.
+  void StoreToLocalAt(int index) {
+    StoreToFrameSlotAt(local0_index() + index);
+  }
+
+  // Push the address of the receiver slot on the frame.
+  void PushReceiverSlotAddress();
+
+  // Push the function on top of the frame.
+  void PushFunction() { PushFrameSlotAt(function_index()); }
+
+  // Save the value of the esi register to the context frame slot.
+  void SaveContextRegister();
+
+  // Restore the esi register from the value of the context frame
+  // slot.
+  void RestoreContextRegister();
+
+  // A parameter as an assembly operand.
+  Operand ParameterAt(int index) const {
+    ASSERT(-1 <= index);  // -1 is the receiver.
+    ASSERT(index < parameter_count_);
+    return Operand(ebp, (1 + parameter_count_ - index) * kPointerSize);
+  }
+
+  // Push a copy of the value of a parameter frame slot on top of the frame.
+  void PushParameterAt(int index) {
+    PushFrameSlotAt(param0_index() + index);
+  }
+
+  // Push the value of a paramter frame slot on top of the frame and
+  // invalidate the parameter slot.  The slot should be written to before
+  // trying to read from it again.
+  void TakeParameterAt(int index) {
+    TakeFrameSlotAt(param0_index() + index);
+  }
+
+  // Store the top value on the virtual frame into a parameter frame slot.
+  // The value is left in place on top of the frame.
+  void StoreToParameterAt(int index) {
+    StoreToFrameSlotAt(param0_index() + index);
+  }
+
+  // The receiver frame slot.
+  Operand Receiver() const { return ParameterAt(-1); }
+
+  // Push a try-catch or try-finally handler on top of the virtual frame.
+  void PushTryHandler(HandlerType type);
+
+  // Call stub given the number of arguments it expects on (and
+  // removes from) the stack.
+  Result CallStub(CodeStub* stub, int arg_count);
+
+  // Call stub that takes a single argument passed in eax.  The
+  // argument is given as a result which does not have to be eax or
+  // even a register.  The argument is consumed by the call.
+  Result CallStub(CodeStub* stub, Result* arg);
+
+  // Call stub that takes a pair of arguments passed in edx (arg0) and
+  // eax (arg1).  The arguments are given as results which do not have
+  // to be in the proper registers or even in registers.  The
+  // arguments are consumed by the call.
+  Result CallStub(CodeStub* stub, Result* arg0, Result* arg1);
+
+  // Call runtime given the number of arguments expected on (and
+  // removed from) the stack.
+  Result CallRuntime(Runtime::Function* f, int arg_count);
+  Result CallRuntime(Runtime::FunctionId id, int arg_count);
+
+  // Invoke builtin given the number of arguments it expects on (and
+  // removes from) the stack.
+  Result InvokeBuiltin(Builtins::JavaScript id,
+                       InvokeFlag flag,
+                       int arg_count);
+
+  // Call load IC.  Name and receiver are found on top of the frame.
+  // Receiver is not dropped.
+  Result CallLoadIC(RelocInfo::Mode mode);
+
+  // Call keyed load IC.  Key and receiver are found on top of the
+  // frame.  They are not dropped.
+  Result CallKeyedLoadIC(RelocInfo::Mode mode);
+
+  // Call store IC.  Name, value, and receiver are found on top of the
+  // frame.  Receiver is not dropped.
+  Result CallStoreIC();
+
+  // Call keyed store IC.  Value, key, and receiver are found on top
+  // of the frame.  Key and receiver are not dropped.
+  Result CallKeyedStoreIC();
+
+  // Call call IC.  Arguments, reciever, and function name are found
+  // on top of the frame.  Function name slot is not dropped.  The
+  // argument count does not include the receiver.
+  Result CallCallIC(RelocInfo::Mode mode, int arg_count, int loop_nesting);
+
+  // Allocate and call JS function as constructor.  Arguments,
+  // receiver (global object), and function are found on top of the
+  // frame.  Function is not dropped.  The argument count does not
+  // include the receiver.
+  Result CallConstructor(int arg_count);
+
+  // Drop a number of elements from the top of the expression stack.  May
+  // emit code to affect the physical frame.  Does not clobber any registers
+  // excepting possibly the stack pointer.
+  void Drop(int count);
+
+  // Drop one element.
+  void Drop() { Drop(1); }
+
+  // Duplicate the top element of the frame.
+  void Dup() { PushFrameSlotAt(elements_.length() - 1); }
+
+  // Pop an element from the top of the expression stack.  Returns a
+  // Result, which may be a constant or a register.
+  Result Pop();
+
+  // Pop and save an element from the top of the expression stack and
+  // emit a corresponding pop instruction.
+  void EmitPop(Register reg);
+  void EmitPop(Operand operand);
+
+  // Push an element on top of the expression stack and emit a
+  // corresponding push instruction.
+  void EmitPush(Register reg);
+  void EmitPush(Operand operand);
+  void EmitPush(Immediate immediate);
+
+  // Push an element on the virtual frame.
+  void Push(Register reg, StaticType static_type = StaticType());
+  void Push(Handle<Object> value);
+  void Push(Smi* value) { Push(Handle<Object>(value)); }
+
+  // Pushing a result invalidates it (its contents become owned by the
+  // frame).
+  void Push(Result* result);
+
+  // Nip removes zero or more elements from immediately below the top
+  // of the frame, leaving the previous top-of-frame value on top of
+  // the frame.  Nip(k) is equivalent to x = Pop(), Drop(k), Push(x).
+  void Nip(int num_dropped);
+
+ private:
+  static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
+  static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset;
+  static const int kContextOffset = StandardFrameConstants::kContextOffset;
+
+  static const int kHandlerSize = StackHandlerConstants::kSize / kPointerSize;
+  static const int kPreallocatedElements = 5 + 8;  // 8 expression stack slots.
+
+  CodeGenerator* cgen_;
+  MacroAssembler* masm_;
+
+  List<FrameElement> elements_;
+
+  // The number of frame-allocated locals and parameters respectively.
+  int parameter_count_;
+  int local_count_;
+
+  // The index of the element that is at the processor's stack pointer
+  // (the esp register).
+  int stack_pointer_;
+
+  // The index of the element that is at the processor's frame pointer
+  // (the ebp register).
+  int frame_pointer_;
+
+  // The index of the register frame element using each register, or
+  // kIllegalIndex if a register is not on the frame.
+  int register_locations_[kNumRegisters];
+
+  // The index of the first parameter.  The receiver lies below the first
+  // parameter.
+  int param0_index() const { return 1; }
+
+  // The index of the context slot in the frame.
+  int context_index() const {
+    ASSERT(frame_pointer_ != kIllegalIndex);
+    return frame_pointer_ + 1;
+  }
+
+  // The index of the function slot in the frame.  It lies above the context
+  // slot.
+  int function_index() const {
+    ASSERT(frame_pointer_ != kIllegalIndex);
+    return frame_pointer_ + 2;
+  }
+
+  // The index of the first local.  Between the parameters and the locals
+  // lie the return address, the saved frame pointer, the context, and the
+  // function.
+  int local0_index() const {
+    ASSERT(frame_pointer_ != kIllegalIndex);
+    return frame_pointer_ + 3;
+  }
+
+  // The index of the base of the expression stack.
+  int expression_base_index() const { return local0_index() + local_count_; }
+
+  // Convert a frame index into a frame pointer relative offset into the
+  // actual stack.
+  int fp_relative(int index) const {
+    return (frame_pointer_ - index) * kPointerSize;
+  }
+
+  // Record an occurrence of a register in the virtual frame.  This has the
+  // effect of incrementing the register's external reference count and
+  // of updating the index of the register's location in the frame.
+  void Use(Register reg, int index);
+
+  // Record that a register reference has been dropped from the frame.  This
+  // decrements the register's external reference count and invalidates the
+  // index of the register's location in the frame.
+  void Unuse(Register reg);
+
+  // Spill the element at a particular index---write it to memory if
+  // necessary, free any associated register, and forget its value if
+  // constant.
+  void SpillElementAt(int index);
+
+  // Sync the element at a particular index.  If it is a register or
+  // constant that disagrees with the value on the stack, write it to memory.
+  // Keep the element type as register or constant, and clear the dirty bit.
+  void SyncElementAt(int index);
+
+  // Sync the range of elements in [begin, end).
+  void SyncRange(int begin, int end);
+
+  // Sync a single unsynced element that lies beneath or at the stack pointer.
+  void SyncElementBelowStackPointer(int index);
+
+  // Sync a single unsynced element that lies just above the stack pointer.
+  void SyncElementByPushing(int index);
+
+  // Push a copy of a frame slot (typically a local or parameter) on top of
+  // the frame.
+  void PushFrameSlotAt(int index);
+
+  // Push a the value of a frame slot (typically a local or parameter) on
+  // top of the frame and invalidate the slot.
+  void TakeFrameSlotAt(int index);
+
+  // Store the value on top of the frame to a frame slot (typically a local
+  // or parameter).
+  void StoreToFrameSlotAt(int index);
+
+  // Spill all elements in registers. Spill the top spilled_args elements
+  // on the frame.  Sync all other frame elements.
+  // Then drop dropped_args elements from the virtual frame, to match
+  // the effect of an upcoming call that will drop them from the stack.
+  void PrepareForCall(int spilled_args, int dropped_args);
+
+  // Move frame elements currently in registers or constants, that
+  // should be in memory in the expected frame, to memory.
+  void MergeMoveRegistersToMemory(VirtualFrame* expected);
+
+  // Make the register-to-register moves necessary to
+  // merge this frame with the expected frame.
+  // Register to memory moves must already have been made,
+  // and memory to register moves must follow this call.
+  // This is because some new memory-to-register moves are
+  // created in order to break cycles of register moves.
+  // Used in the implementation of MergeTo().
+  void MergeMoveRegistersToRegisters(VirtualFrame* expected);
+
+  // Make the memory-to-register and constant-to-register moves
+  // needed to make this frame equal the expected frame.
+  // Called after all register-to-memory and register-to-register
+  // moves have been made.  After this function returns, the frames
+  // should be equal.
+  void MergeMoveMemoryToRegisters(VirtualFrame* expected);
+
+  // Invalidates a frame slot (puts an invalid frame element in it).
+  // Copies on the frame are correctly handled, and if this slot was
+  // the backing store of copies, the index of the new backing store
+  // is returned.  Otherwise, returns kIllegalIndex.
+  // Register counts are correctly updated.
+  int InvalidateFrameSlotAt(int index);
+
+  // Call a code stub that has already been prepared for calling (via
+  // PrepareForCall).
+  Result RawCallStub(CodeStub* stub);
+
+  // Calls a code object which has already been prepared for calling
+  // (via PrepareForCall).
+  Result RawCallCodeObject(Handle<Code> code, RelocInfo::Mode rmode);
+
+  bool Equals(VirtualFrame* other);
+
+  friend class JumpTarget;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_VIRTUAL_FRAME_IA32_H_
diff --git a/deps/v8/src/virtual-frame.cc b/deps/v8/src/virtual-frame.cc
new file mode 100644
index 0000000..a03e31a
--- /dev/null
+++ b/deps/v8/src/virtual-frame.cc
@@ -0,0 +1,536 @@
+// 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.
+
+#include "v8.h"
+
+#include "codegen-inl.h"
+#include "register-allocator-inl.h"
+
+namespace v8 { namespace internal {
+
+// -------------------------------------------------------------------------
+// VirtualFrame implementation.
+
+VirtualFrame::SpilledScope::SpilledScope(CodeGenerator* cgen)
+    : cgen_(cgen),
+      previous_state_(cgen->in_spilled_code()) {
+  ASSERT(cgen->has_valid_frame());
+  cgen->frame()->SpillAll();
+  cgen->set_in_spilled_code(true);
+}
+
+
+VirtualFrame::SpilledScope::~SpilledScope() {
+  cgen_->set_in_spilled_code(previous_state_);
+}
+
+
+// When cloned, a frame is a deep copy of the original.
+VirtualFrame::VirtualFrame(VirtualFrame* original)
+    : cgen_(original->cgen_),
+      masm_(original->masm_),
+      elements_(original->elements_.capacity()),
+      parameter_count_(original->parameter_count_),
+      local_count_(original->local_count_),
+      stack_pointer_(original->stack_pointer_),
+      frame_pointer_(original->frame_pointer_) {
+  // Copy all the elements from the original.
+  for (int i = 0; i < original->elements_.length(); i++) {
+    elements_.Add(original->elements_[i]);
+  }
+  for (int i = 0; i < kNumRegisters; i++) {
+    register_locations_[i] = original->register_locations_[i];
+  }
+}
+
+
+FrameElement VirtualFrame::CopyElementAt(int index) {
+  ASSERT(index >= 0);
+  ASSERT(index < elements_.length());
+
+  FrameElement target = elements_[index];
+  FrameElement result;
+
+  switch (target.type()) {
+    case FrameElement::CONSTANT:
+      // We do not copy constants and instead return a fresh unsynced
+      // constant.
+      result = FrameElement::ConstantElement(target.handle(),
+                                             FrameElement::NOT_SYNCED);
+      break;
+
+    case FrameElement::COPY:
+      // We do not allow copies of copies, so we follow one link to
+      // the actual backing store of a copy before making a copy.
+      index = target.index();
+      ASSERT(elements_[index].is_memory() || elements_[index].is_register());
+      // Fall through.
+
+    case FrameElement::MEMORY:  // Fall through.
+    case FrameElement::REGISTER:
+      // All copies are backed by memory or register locations.
+      result.set_static_type(target.static_type());
+      result.type_ = FrameElement::COPY;
+      result.copied_ = false;
+      result.synced_ = false;
+      result.data_.index_ = index;
+      elements_[index].set_copied();
+      break;
+
+    case FrameElement::INVALID:
+      // We should not try to copy invalid elements.
+      UNREACHABLE();
+      break;
+  }
+  return result;
+}
+
+
+// Modify the state of the virtual frame to match the actual frame by adding
+// extra in-memory elements to the top of the virtual frame.  The extra
+// elements will be externally materialized on the actual frame (eg, by
+// pushing an exception handler).  No code is emitted.
+void VirtualFrame::Adjust(int count) {
+  ASSERT(count >= 0);
+  ASSERT(stack_pointer_ == elements_.length() - 1);
+
+  for (int i = 0; i < count; i++) {
+    elements_.Add(FrameElement::MemoryElement());
+  }
+  stack_pointer_ += count;
+}
+
+
+// Modify the state of the virtual frame to match the actual frame by
+// removing elements from the top of the virtual frame.  The elements will
+// be externally popped from the actual frame (eg, by a runtime call).  No
+// code is emitted.
+void VirtualFrame::Forget(int count) {
+  ASSERT(count >= 0);
+  ASSERT(stack_pointer_ == elements_.length() - 1);
+
+  stack_pointer_ -= count;
+  ForgetElements(count);
+}
+
+
+void VirtualFrame::ForgetElements(int count) {
+  ASSERT(count >= 0);
+  ASSERT(elements_.length() >= count);
+
+  for (int i = 0; i < count; i++) {
+    FrameElement last = elements_.RemoveLast();
+    if (last.is_register()) {
+      // A hack to properly count register references for the code
+      // generator's current frame and also for other frames.  The
+      // same code appears in PrepareMergeTo.
+      if (cgen_->frame() == this) {
+        Unuse(last.reg());
+      } else {
+        register_locations_[last.reg().code()] = kIllegalIndex;
+      }
+    }
+  }
+}
+
+
+void VirtualFrame::Use(Register reg, int index) {
+  ASSERT(register_locations_[reg.code()] == kIllegalIndex);
+  register_locations_[reg.code()] = index;
+  cgen_->allocator()->Use(reg);
+}
+
+
+void VirtualFrame::Unuse(Register reg) {
+  ASSERT(register_locations_[reg.code()] != kIllegalIndex);
+  register_locations_[reg.code()] = kIllegalIndex;
+  cgen_->allocator()->Unuse(reg);
+}
+
+
+void VirtualFrame::Spill(Register target) {
+  if (is_used(target)) {
+    SpillElementAt(register_index(target));
+  }
+}
+
+
+// If there are any registers referenced only by the frame, spill one.
+Register VirtualFrame::SpillAnyRegister() {
+  // Find the leftmost (ordered by register code) register whose only
+  // reference is in the frame.
+  for (int i = 0; i < kNumRegisters; i++) {
+    if (is_used(i) && cgen_->allocator()->count(i) == 1) {
+      Register result = { i };
+      Spill(result);
+      ASSERT(!cgen_->allocator()->is_used(result));
+      return result;
+    }
+  }
+  return no_reg;
+}
+
+
+// Make the type of the element at a given index be MEMORY.
+void VirtualFrame::SpillElementAt(int index) {
+  if (!elements_[index].is_valid()) return;
+
+  SyncElementAt(index);
+  // The element is now in memory.  Its copied flag is preserved.
+  FrameElement new_element = FrameElement::MemoryElement();
+  if (elements_[index].is_copied()) {
+    new_element.set_copied();
+  }
+  if (elements_[index].is_register()) {
+    Unuse(elements_[index].reg());
+  }
+  new_element.set_static_type(elements_[index].static_type());
+  elements_[index] = new_element;
+}
+
+
+// Clear the dirty bits for the range of elements in
+// [min(stack_pointer_ + 1,begin), end).
+void VirtualFrame::SyncRange(int begin, int end) {
+  ASSERT(begin >= 0);
+  ASSERT(end <= elements_.length());
+  if (begin > stack_pointer_) {
+    // Elements between stack_pointer_ + 1 and begin must also be synced.
+    for (int i = stack_pointer_ + 1; i < end; i++) {
+      SyncElementByPushing(i);
+    }
+  } else if (end <= stack_pointer_ + 1) {
+    for (int i = begin; i < end; i++) {
+      if (!elements_[i].is_synced()) {
+          SyncElementBelowStackPointer(i);
+      }
+    }
+  } else {
+    // Split into two ranges that each satisfy a condition above.
+    SyncRange(begin, stack_pointer_ + 1);
+    SyncRange(stack_pointer_ + 1, end);
+  }
+}
+
+
+// Clear the dirty bit for the element at a given index.
+void VirtualFrame::SyncElementAt(int index) {
+  if (index <= stack_pointer_) {
+    if (!elements_[index].is_synced()) {
+      SyncElementBelowStackPointer(index);
+    }
+  } else {
+    for (int i = stack_pointer_ + 1; i <= index; i++) {
+      SyncElementByPushing(i);
+    }
+  }
+}
+
+
+// Make the type of all elements be MEMORY.
+void VirtualFrame::SpillAll() {
+  for (int i = 0; i < elements_.length(); i++) {
+    SpillElementAt(i);
+  }
+}
+
+
+void VirtualFrame::PrepareMergeTo(VirtualFrame* expected) {
+  // Perform state changes on this frame that will make merge to the
+  // expected frame simpler or else increase the likelihood that his
+  // frame will match another.
+  for (int i = 0; i < elements_.length(); i++) {
+    FrameElement source = elements_[i];
+    FrameElement target = expected->elements_[i];
+
+    if (!target.is_valid() ||
+        (target.is_memory() && !source.is_memory() && source.is_synced())) {
+      // No code needs to be generated to invalidate valid elements.
+      // No code needs to be generated to move values to memory if
+      // they are already synced.  We perform those moves here, before
+      // merging.
+      if (source.is_register()) {
+        // If the frame is the code generator's current frame, we have
+        // to decrement both the frame-internal and global register
+        // counts.
+        if (cgen_->frame() == this) {
+          Unuse(source.reg());
+        } else {
+          register_locations_[source.reg().code()] = kIllegalIndex;
+        }
+      }
+      elements_[i] = target;
+    } else if (target.is_register() && !target.is_synced() &&
+               !source.is_memory()) {
+      // If an element's target is a register that doesn't need to be
+      // synced, and the element is not in memory, then the sync state
+      // of the element is irrelevant.  We clear the sync bit.
+      ASSERT(source.is_valid());
+      elements_[i].clear_sync();
+    }
+
+    elements_[i].clear_copied();
+    if (elements_[i].is_copy()) {
+      elements_[elements_[i].index()].set_copied();
+    }
+
+    // No code needs to be generated to change the static type of an
+    // element.
+    elements_[i].set_static_type(target.static_type());
+  }
+}
+
+
+void VirtualFrame::PrepareForCall(int spilled_args, int dropped_args) {
+  ASSERT(height() >= dropped_args);
+  ASSERT(height() >= spilled_args);
+  ASSERT(dropped_args <= spilled_args);
+
+  SyncRange(0, elements_.length());
+  // Spill registers.
+  for (int i = 0; i < kNumRegisters; i++) {
+    if (is_used(i)) {
+      SpillElementAt(register_locations_[i]);
+    }
+  }
+
+  // Spill the arguments.
+  for (int i = elements_.length() - spilled_args; i < elements_.length(); i++) {
+    if (!elements_[i].is_memory()) {
+      SpillElementAt(i);
+    }
+  }
+
+  // Forget the frame elements that will be popped by the call.
+  Forget(dropped_args);
+}
+
+
+void VirtualFrame::DetachFromCodeGenerator() {
+  // Tell the global register allocator that it is free to reallocate all
+  // register references contained in this frame.  The frame elements remain
+  // register references, so the frame-internal reference count is not
+  // decremented.
+  for (int i = 0; i < elements_.length(); i++) {
+    if (elements_[i].is_register()) {
+      cgen_->allocator()->Unuse(elements_[i].reg());
+    }
+  }
+}
+
+
+void VirtualFrame::AttachToCodeGenerator() {
+  // Tell the global register allocator that the frame-internal register
+  // references are live again.
+  for (int i = 0; i < elements_.length(); i++) {
+    if (elements_[i].is_register()) {
+      cgen_->allocator()->Use(elements_[i].reg());
+    }
+  }
+}
+
+
+void VirtualFrame::PrepareForReturn() {
+  // Spill all locals. This is necessary to make sure all locals have
+  // the right value when breaking at the return site in the debugger.
+  //
+  // TODO(203): It is also necessary to ensure that merging at the
+  // return site does not generate code to overwrite eax, where the
+  // return value is kept in a non-refcounted register reference.
+  for (int i = 0; i < expression_base_index(); i++) SpillElementAt(i);
+}
+
+
+void VirtualFrame::SetElementAt(int index, Result* value) {
+  int frame_index = elements_.length() - index - 1;
+  ASSERT(frame_index >= 0);
+  ASSERT(frame_index < elements_.length());
+  ASSERT(value->is_valid());
+  FrameElement original = elements_[frame_index];
+
+  // Early exit if the element is the same as the one being set.
+  bool same_register = original.is_register()
+                    && value->is_register()
+                    && original.reg().is(value->reg());
+  bool same_constant = original.is_constant()
+                    && value->is_constant()
+                    && original.handle().is_identical_to(value->handle());
+  if (same_register || same_constant) {
+    value->Unuse();
+    return;
+  }
+
+  InvalidateFrameSlotAt(frame_index);
+
+  FrameElement new_element;
+  if (value->is_register()) {
+    if (is_used(value->reg())) {
+      // The register already appears on the frame.  Either the existing
+      // register element, or the new element at frame_index, must be made
+      // a copy.
+      int i = register_index(value->reg());
+      ASSERT(value->static_type() == elements_[i].static_type());
+
+      if (i < frame_index) {
+        // The register FrameElement is lower in the frame than the new copy.
+        elements_[frame_index] = CopyElementAt(i);
+      } else {
+        // There was an early bailout for the case of setting a
+        // register element to itself.
+        ASSERT(i != frame_index);
+        elements_[frame_index] = elements_[i];
+        elements_[i] = CopyElementAt(frame_index);
+        if (elements_[frame_index].is_synced()) {
+          elements_[i].set_sync();
+        }
+        elements_[frame_index].clear_sync();
+        register_locations_[value->reg().code()] = frame_index;
+        for (int j = i + 1; j < elements_.length(); j++) {
+          if (elements_[j].is_copy() && elements_[j].index() == i) {
+            elements_[j].set_index(frame_index);
+          }
+        }
+      }
+    } else {
+      // The register value->reg() was not already used on the frame.
+      Use(value->reg(), frame_index);
+      elements_[frame_index] =
+          FrameElement::RegisterElement(value->reg(),
+                                        FrameElement::NOT_SYNCED,
+                                        value->static_type());
+    }
+  } else {
+    ASSERT(value->is_constant());
+    elements_[frame_index] =
+        FrameElement::ConstantElement(value->handle(),
+                                      FrameElement::NOT_SYNCED);
+  }
+  value->Unuse();
+}
+
+
+void VirtualFrame::PushFrameSlotAt(int index) {
+  FrameElement new_element = CopyElementAt(index);
+  elements_.Add(new_element);
+}
+
+
+Result VirtualFrame::CallStub(CodeStub* stub, int arg_count) {
+  PrepareForCall(arg_count, arg_count);
+  return RawCallStub(stub);
+}
+
+
+void VirtualFrame::Push(Register reg, StaticType static_type) {
+  if (is_used(reg)) {
+    int index = register_index(reg);
+    FrameElement element = CopyElementAt(index);
+    ASSERT(static_type.merge(element.static_type()) == element.static_type());
+    elements_.Add(element);
+  } else {
+    Use(reg, elements_.length());
+    FrameElement element =
+        FrameElement::RegisterElement(reg,
+                                      FrameElement::NOT_SYNCED,
+                                      static_type);
+    elements_.Add(element);
+  }
+}
+
+
+void VirtualFrame::Push(Handle<Object> value) {
+  FrameElement element =
+      FrameElement::ConstantElement(value, FrameElement::NOT_SYNCED);
+  elements_.Add(element);
+}
+
+
+void VirtualFrame::Push(Result* result) {
+  if (result->is_register()) {
+    Push(result->reg(), result->static_type());
+  } else {
+    ASSERT(result->is_constant());
+    Push(result->handle());
+  }
+  result->Unuse();
+}
+
+
+void VirtualFrame::Nip(int num_dropped) {
+  ASSERT(num_dropped >= 0);
+  if (num_dropped == 0) return;
+  Result tos = Pop();
+  if (num_dropped > 1) {
+    Drop(num_dropped - 1);
+  }
+  SetElementAt(0, &tos);
+}
+
+
+bool FrameElement::Equals(FrameElement other) {
+  if (type_ != other.type_ ||
+      copied_ != other.copied_ ||
+      synced_ != other.synced_) return false;
+
+  if (is_register()) {
+    if (!reg().is(other.reg())) return false;
+  } else if (is_constant()) {
+    if (!handle().is_identical_to(other.handle())) return false;
+  } else if (is_copy()) {
+    if (index() != other.index()) return false;
+  }
+
+  return true;
+}
+
+
+bool VirtualFrame::Equals(VirtualFrame* other) {
+#ifdef DEBUG
+  // These are sanity checks in debug builds, but we do not need to
+  // use them to distinguish frames at merge points.
+  if (cgen_ != other->cgen_) return false;
+  if (masm_ != other->masm_) return false;
+  if (parameter_count_ != other->parameter_count_) return false;
+  if (local_count_ != other->local_count_) return false;
+  if (frame_pointer_ != other->frame_pointer_) return false;
+
+  for (int i = 0; i < kNumRegisters; i++) {
+    if (register_locations_[i] != other->register_locations_[i]) {
+      return false;
+    }
+  }
+  if (elements_.length() != other->elements_.length()) return false;
+#endif
+  if (stack_pointer_ != other->stack_pointer_) return false;
+  for (int i = 0; i < elements_.length(); i++) {
+    if (!elements_[i].Equals(other->elements_[i])) return false;
+  }
+
+  return true;
+}
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/virtual-frame.h b/deps/v8/src/virtual-frame.h
new file mode 100644
index 0000000..99b4f76
--- /dev/null
+++ b/deps/v8/src/virtual-frame.h
@@ -0,0 +1,206 @@
+// Copyright 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_VIRTUAL_FRAME_H_
+#define V8_VIRTUAL_FRAME_H_
+
+#include "macro-assembler.h"
+
+namespace v8 { namespace internal {
+
+// -------------------------------------------------------------------------
+// Virtual frame elements
+//
+// The internal elements of the virtual frames.  There are several kinds of
+// elements:
+//   * Invalid: elements that are uninitialized or not actually part
+//     of the virtual frame.  They should not be read.
+//   * Memory: an element that resides in the actual frame.  Its address is
+//     given by its position in the virtual frame.
+//   * Register: an element that resides in a register.
+//   * Constant: an element whose value is known at compile time.
+
+class FrameElement BASE_EMBEDDED {
+ public:
+  enum SyncFlag {
+    NOT_SYNCED,
+    SYNCED
+  };
+
+  // The default constructor creates an invalid frame element.
+  FrameElement()
+      : static_type_(), type_(INVALID), copied_(false), synced_(false) {
+    data_.reg_ = no_reg;
+  }
+
+  // Factory function to construct an invalid frame element.
+  static FrameElement InvalidElement() {
+    FrameElement result;
+    return result;
+  }
+
+  // Factory function to construct an in-memory frame element.
+  static FrameElement MemoryElement() {
+    FrameElement result(MEMORY, no_reg, SYNCED);
+    return result;
+  }
+
+  // Factory function to construct an in-register frame element.
+  static FrameElement RegisterElement(Register reg,
+                                      SyncFlag is_synced,
+                                      StaticType static_type = StaticType()) {
+    return FrameElement(REGISTER, reg, is_synced, static_type);
+  }
+
+  // Factory function to construct a frame element whose value is known at
+  // compile time.
+  static FrameElement ConstantElement(Handle<Object> value,
+                                      SyncFlag is_synced) {
+    FrameElement result(value, is_synced);
+    return result;
+  }
+
+  bool is_synced() const { return synced_; }
+
+  void set_sync() {
+    ASSERT(type() != MEMORY);
+    synced_ = true;
+  }
+
+  void clear_sync() {
+    ASSERT(type() != MEMORY);
+    synced_ = false;
+  }
+
+  bool is_valid() const { return type() != INVALID; }
+  bool is_memory() const { return type() == MEMORY; }
+  bool is_register() const { return type() == REGISTER; }
+  bool is_constant() const { return type() == CONSTANT; }
+  bool is_copy() const { return type() == COPY; }
+
+  bool is_copied() const { return copied_; }
+  void set_copied() { copied_ = true; }
+  void clear_copied() { copied_ = false; }
+
+  Register reg() const {
+    ASSERT(is_register());
+    return data_.reg_;
+  }
+
+  Handle<Object> handle() const {
+    ASSERT(is_constant());
+    return Handle<Object>(data_.handle_);
+  }
+
+  int index() const {
+    ASSERT(is_copy());
+    return data_.index_;
+  }
+
+  bool Equals(FrameElement other);
+
+  StaticType static_type() { return static_type_; }
+
+  void set_static_type(StaticType static_type) {
+    // TODO(lrn): If it's s copy, it would be better to update the real one,
+    // but we can't from here. The caller must handle this.
+    static_type_ = static_type;
+  }
+
+ private:
+  enum Type {
+    INVALID,
+    MEMORY,
+    REGISTER,
+    CONSTANT,
+    COPY
+  };
+
+  Type type() const { return static_cast<Type>(type_); }
+
+  StaticType static_type_;
+
+  // The element's type.
+  byte type_;
+
+  bool copied_;
+
+  // The element's dirty-bit. The dirty bit can be cleared
+  // for non-memory elements to indicate that the element agrees with
+  // the value in memory in the actual frame.
+  bool synced_;
+
+  union {
+    Register reg_;
+    Object** handle_;
+    int index_;
+  } data_;
+
+  // Used to construct memory and register elements.
+  FrameElement(Type type, Register reg, SyncFlag is_synced)
+      : static_type_(),
+        type_(type),
+        copied_(false),
+        synced_(is_synced  != NOT_SYNCED) {
+    data_.reg_ = reg;
+  }
+
+  FrameElement(Type type, Register reg, SyncFlag is_synced, StaticType stype)
+      : static_type_(stype),
+        type_(type),
+        copied_(false),
+        synced_(is_synced != NOT_SYNCED) {
+    data_.reg_ = reg;
+  }
+
+  // Used to construct constant elements.
+  FrameElement(Handle<Object> value, SyncFlag is_synced)
+      : static_type_(StaticType::TypeOf(*value)),
+        type_(CONSTANT),
+        copied_(false),
+        synced_(is_synced != NOT_SYNCED) {
+    data_.handle_ = value.location();
+  }
+
+  void set_index(int new_index) {
+    ASSERT(is_copy());
+    data_.index_ = new_index;
+  }
+
+  friend class VirtualFrame;
+};
+
+
+} }  // namespace v8::internal
+
+#ifdef ARM
+#include "virtual-frame-arm.h"
+#else  // ia32
+#include "virtual-frame-ia32.h"
+#endif
+
+#endif  // V8_VIRTUAL_FRAME_H_
diff --git a/deps/v8/src/zone-inl.h b/deps/v8/src/zone-inl.h
new file mode 100644
index 0000000..69b9a0a
--- /dev/null
+++ b/deps/v8/src/zone-inl.h
@@ -0,0 +1,72 @@
+// 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_ZONE_INL_H_
+#define V8_ZONE_INL_H_
+
+#include "zone.h"
+#include "v8-counters.h"
+
+namespace v8 { namespace internal {
+
+
+inline void* Zone::New(int size) {
+  ASSERT(AssertNoZoneAllocation::allow_allocation());
+  ASSERT(ZoneScope::nesting() > 0);
+  // Round up the requested size to fit the alignment.
+  size = RoundUp(size, kAlignment);
+
+  // Check if the requested size is available without expanding.
+  Address result = position_;
+  if ((position_ += size) > limit_) result = NewExpand(size);
+
+  // Check that the result has the proper alignment and return it.
+  ASSERT(IsAddressAligned(result, kAlignment, 0));
+  return reinterpret_cast<void*>(result);
+}
+
+
+template <typename T>
+T* Zone::NewArray(int length) {
+  return static_cast<T*>(Zone::New(length * sizeof(T)));
+}
+
+
+bool Zone::excess_allocation() {
+  return segment_bytes_allocated_ > zone_excess_limit_;
+}
+
+
+void Zone::adjust_segment_bytes_allocated(int delta) {
+  segment_bytes_allocated_ += delta;
+  Counters::zone_segment_bytes.Set(segment_bytes_allocated_);
+}
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_ZONE_INL_H_
diff --git a/deps/v8/src/zone.cc b/deps/v8/src/zone.cc
new file mode 100644
index 0000000..c8f9c85
--- /dev/null
+++ b/deps/v8/src/zone.cc
@@ -0,0 +1,189 @@
+// 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.
+
+#include "v8.h"
+
+#include "zone-inl.h"
+
+namespace v8 { namespace internal {
+
+
+Address Zone::position_ = 0;
+Address Zone::limit_ = 0;
+int Zone::zone_excess_limit_ = 256 * MB;
+int Zone::segment_bytes_allocated_ = 0;
+
+bool AssertNoZoneAllocation::allow_allocation_ = true;
+
+int ZoneScope::nesting_ = 0;
+
+// Segments represent chunks of memory: They have starting address
+// (encoded in the this pointer) and a size in bytes. Segments are
+// chained together forming a LIFO structure with the newest segment
+// available as Segment::head(). Segments are allocated using malloc()
+// and de-allocated using free().
+
+class Segment {
+ public:
+  Segment* next() const { return next_; }
+  void clear_next() { next_ = NULL; }
+
+  int size() const { return size_; }
+  int capacity() const { return size_ - sizeof(Segment); }
+
+  Address start() const { return address(sizeof(Segment)); }
+  Address end() const { return address(size_); }
+
+  static Segment* head() { return head_; }
+  static void set_head(Segment* head) { head_ = head; }
+
+  // Creates a new segment, sets it size, and pushes it to the front
+  // of the segment chain. Returns the new segment.
+  static Segment* New(int size) {
+    Segment* result = reinterpret_cast<Segment*>(Malloced::New(size));
+    Zone::adjust_segment_bytes_allocated(size);
+    if (result != NULL) {
+      result->next_ = head_;
+      result->size_ = size;
+      head_ = result;
+    }
+    return result;
+  }
+
+  // Deletes the given segment. Does not touch the segment chain.
+  static void Delete(Segment* segment, int size) {
+    Zone::adjust_segment_bytes_allocated(-size);
+    Malloced::Delete(segment);
+  }
+
+  static int bytes_allocated() { return bytes_allocated_; }
+
+ private:
+  // Computes the address of the nth byte in this segment.
+  Address address(int n) const {
+    return Address(this) + n;
+  }
+
+  static Segment* head_;
+  static int bytes_allocated_;
+  Segment* next_;
+  int size_;
+};
+
+
+Segment* Segment::head_ = NULL;
+int Segment::bytes_allocated_ = 0;
+
+
+void Zone::DeleteAll() {
+#ifdef DEBUG
+  // Constant byte value used for zapping dead memory in debug mode.
+  static const unsigned char kZapDeadByte = 0xcd;
+#endif
+
+  // Find a segment with a suitable size to keep around.
+  Segment* keep = Segment::head();
+  while (keep != NULL && keep->size() > kMaximumKeptSegmentSize) {
+    keep = keep->next();
+  }
+
+  // Traverse the chained list of segments, zapping (in debug mode)
+  // and freeing every segment except the one we wish to keep.
+  Segment* current = Segment::head();
+  while (current != NULL) {
+    Segment* next = current->next();
+    if (current == keep) {
+      // Unlink the segment we wish to keep from the list.
+      current->clear_next();
+    } else {
+      int size = current->size();
+#ifdef DEBUG
+      // Zap the entire current segment (including the header).
+      memset(current, kZapDeadByte, size);
+#endif
+      Segment::Delete(current, size);
+    }
+    current = next;
+  }
+
+  // If we have found a segment we want to keep, we must recompute the
+  // variables 'position' and 'limit' to prepare for future allocate
+  // attempts. Otherwise, we must clear the position and limit to
+  // force a new segment to be allocated on demand.
+  if (keep != NULL) {
+    Address start = keep->start();
+    position_ = RoundUp(start, kAlignment);
+    limit_ = keep->end();
+#ifdef DEBUG
+    // Zap the contents of the kept segment (but not the header).
+    memset(start, kZapDeadByte, keep->capacity());
+#endif
+  } else {
+    position_ = limit_ = 0;
+  }
+
+  // Update the head segment to be the kept segment (if any).
+  Segment::set_head(keep);
+}
+
+
+Address Zone::NewExpand(int size) {
+  // Make sure the requested size is already properly aligned and that
+  // there isn't enough room in the Zone to satisfy the request.
+  ASSERT(size == RoundDown(size, kAlignment));
+  ASSERT(position_ + size > limit_);
+
+  // Compute the new segment size. We use a 'high water mark'
+  // strategy, where we increase the segment size every time we expand
+  // except that we employ a maximum segment size when we delete. This
+  // is to avoid excessive malloc() and free() overhead.
+  Segment* head = Segment::head();
+  int old_size = (head == NULL) ? 0 : head->size();
+  static const int kSegmentOverhead = sizeof(Segment) + kAlignment;
+  int new_size = kSegmentOverhead + size + (old_size << 1);
+  if (new_size < kMinimumSegmentSize) {
+    new_size = kMinimumSegmentSize;
+  } else if (new_size > kMaximumSegmentSize) {
+    // Limit the size of new segments to avoid growing the segment size
+    // exponentially, thus putting pressure on contiguous virtual address space.
+    // All the while making sure to allocate a segment large enough to hold the
+    // requested size.
+    new_size = Max(kSegmentOverhead + size, kMaximumSegmentSize);
+  }
+  Segment* segment = Segment::New(new_size);
+  if (segment == NULL) V8::FatalProcessOutOfMemory("Zone");
+
+  // Recompute 'top' and 'limit' based on the new segment.
+  Address result = RoundUp(segment->start(), kAlignment);
+  position_ = result + size;
+  limit_ = segment->end();
+  ASSERT(position_ <= limit_);
+  return result;
+}
+
+
+} }  // namespace v8::internal
diff --git a/deps/v8/src/zone.h b/deps/v8/src/zone.h
new file mode 100644
index 0000000..df69155
--- /dev/null
+++ b/deps/v8/src/zone.h
@@ -0,0 +1,203 @@
+// 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_ZONE_H_
+#define V8_ZONE_H_
+
+namespace v8 { namespace internal {
+
+
+// Zone scopes are in one of two modes.  Either they delete the zone
+// on exit or they do not.
+enum ZoneScopeMode {
+  DELETE_ON_EXIT,
+  DONT_DELETE_ON_EXIT
+};
+
+
+// The Zone supports very fast allocation of small chunks of
+// memory. The chunks cannot be deallocated individually, but instead
+// the Zone supports deallocating all chunks in one fast
+// operation. The Zone is used to hold temporary data structures like
+// the abstract syntax tree, which is deallocated after compilation.
+
+// Note: There is no need to initialize the Zone; the first time an
+// allocation is attempted, a segment of memory will be requested
+// through a call to malloc().
+
+// Note: The implementation is inherently not thread safe. Do not use
+// from multi-threaded code.
+
+class Zone {
+ public:
+  // Allocate 'size' bytes of memory in the Zone; expands the Zone by
+  // allocating new segments of memory on demand using malloc().
+  static inline void* New(int size);
+
+  template <typename T>
+  static inline T* NewArray(int length);
+
+  // Delete all objects and free all memory allocated in the Zone.
+  static void DeleteAll();
+
+  // Returns true if more memory has been allocated in zones than
+  // the limit allows.
+  static inline bool excess_allocation();
+
+  static inline void adjust_segment_bytes_allocated(int delta);
+
+ private:
+
+  // All pointers returned from New() have this alignment.
+  static const int kAlignment = kPointerSize;
+
+  // Never allocate segments smaller than this size in bytes.
+  static const int kMinimumSegmentSize = 8 * KB;
+
+  // Never allocate segments larger than this size in bytes.
+  static const int kMaximumSegmentSize = 1 * MB;
+
+  // Never keep segments larger than this size in bytes around.
+  static const int kMaximumKeptSegmentSize = 64 * KB;
+
+  // Report zone excess when allocation exceeds this limit.
+  static int zone_excess_limit_;
+
+  // The number of bytes allocated in segments.  Note that this number
+  // includes memory allocated from the OS but not yet allocated from
+  // the zone.
+  static int segment_bytes_allocated_;
+
+  // The Zone is intentionally a singleton; you should not try to
+  // allocate instances of the class.
+  Zone() { UNREACHABLE(); }
+
+
+  // Expand the Zone to hold at least 'size' more bytes and allocate
+  // the bytes. Returns the address of the newly allocated chunk of
+  // memory in the Zone. Should only be called if there isn't enough
+  // room in the Zone already.
+  static Address NewExpand(int size);
+
+
+  // The free region in the current (front) segment is represented as
+  // the half-open interval [position, limit). The 'position' variable
+  // is guaranteed to be aligned as dictated by kAlignment.
+  static Address position_;
+  static Address limit_;
+};
+
+
+// ZoneObject is an abstraction that helps define classes of objects
+// allocated in the Zone. Use it as a base class; see ast.h.
+class ZoneObject {
+ public:
+  // Allocate a new ZoneObject of 'size' bytes in the Zone.
+  void* operator new(size_t size) { return Zone::New(size); }
+
+  // Ideally, the delete operator should be private instead of
+  // public, but unfortunately the compiler sometimes synthesizes
+  // (unused) destructors for classes derived from ZoneObject, which
+  // require the operator to be visible. MSVC requires the delete
+  // operator to be public.
+
+  // ZoneObjects should never be deleted individually; use
+  // Zone::DeleteAll() to delete all zone objects in one go.
+  void operator delete(void*, size_t) { UNREACHABLE(); }
+};
+
+
+class AssertNoZoneAllocation {
+ public:
+  AssertNoZoneAllocation() : prev_(allow_allocation_) {
+    allow_allocation_ = false;
+  }
+  ~AssertNoZoneAllocation() { allow_allocation_ = prev_; }
+  static bool allow_allocation() { return allow_allocation_; }
+ private:
+  bool prev_;
+  static bool allow_allocation_;
+};
+
+
+// The ZoneListAllocationPolicy is used to specialize the GenericList
+// implementation to allocate ZoneLists and their elements in the
+// Zone.
+class ZoneListAllocationPolicy {
+ public:
+  // Allocate 'size' bytes of memory in the zone.
+  static void* New(int size) {  return Zone::New(size); }
+
+  // De-allocation attempts are silently ignored.
+  static void Delete(void* p) { }
+};
+
+
+// ZoneLists are growable lists with constant-time access to the
+// elements. The list itself and all its elements are allocated in the
+// Zone. ZoneLists cannot be deleted individually; you can delete all
+// objects in the Zone by calling Zone::DeleteAll().
+template<typename T>
+class ZoneList: public List<T, ZoneListAllocationPolicy> {
+ public:
+  // Construct a new ZoneList with the given capacity; the length is
+  // always zero. The capacity must be non-negative.
+  explicit ZoneList(int capacity)
+      : List<T, ZoneListAllocationPolicy>(capacity) { }
+};
+
+
+// ZoneScopes keep track of the current parsing and compilation
+// nesting and cleans up generated ASTs in the Zone when exiting the
+// outer-most scope.
+class ZoneScope BASE_EMBEDDED {
+ public:
+  explicit ZoneScope(ZoneScopeMode mode) : mode_(mode) {
+    nesting_++;
+  }
+
+  ~ZoneScope() {
+    if (--nesting_ == 0 && mode_ == DELETE_ON_EXIT) Zone::DeleteAll();
+  }
+
+  // For ZoneScopes that do not delete on exit by default, call this
+  // method to request deletion on exit.
+  void DeleteOnExit() {
+    mode_ = DELETE_ON_EXIT;
+  }
+
+  static int nesting() { return nesting_; }
+
+ private:
+  ZoneScopeMode mode_;
+  static int nesting_;
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_ZONE_H_
diff --git a/deps/v8/test/cctest/SConscript b/deps/v8/test/cctest/SConscript
new file mode 100644
index 0000000..f66f72b
--- /dev/null
+++ b/deps/v8/test/cctest/SConscript
@@ -0,0 +1,85 @@
+# Copyright 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.
+
+import sys
+from os.path import join, dirname, abspath
+root_dir = dirname(File('SConstruct').rfile().abspath)
+sys.path.append(join(root_dir, 'tools'))
+Import('context object_files')
+
+
+SOURCES = {
+  'all': [
+    'test-alloc.cc',
+    'test-api.cc',
+    'test-ast.cc',
+    'test-compiler.cc',
+    'test-conversions.cc',
+    'test-debug.cc',
+    'test-decls.cc',
+    'test-flags.cc',
+    'test-func-name-inference.cc',
+    'test-hashmap.cc',
+    'test-heap.cc',
+    'test-list.cc',
+    'test-lock.cc',
+    'test-mark-compact.cc',
+    'test-regexp.cc',
+    'test-serialize.cc',
+    'test-sockets.cc',
+    'test-spaces.cc',
+    'test-strings.cc',
+    'test-threads.cc',
+    'test-utils.cc'
+  ],
+  'arch:arm':  ['test-assembler-arm.cc', 'test-disasm-arm.cc'],
+  'arch:ia32': [
+    'test-assembler-ia32.cc',
+    'test-disasm-ia32.cc',
+    'test-log-ia32.cc'
+  ],
+  'os:linux':  ['test-platform-linux.cc'],
+  'os:macos':  ['test-platform-macos.cc'],
+  'os:nullos': ['test-platform-nullos.cc'],
+  'os:win32':  ['test-platform-win32.cc']
+}
+
+
+def Build():
+  cctest_files = context.GetRelevantSources(SOURCES)
+  env = Environment()
+  env.Replace(**context.flags['cctest'])
+  context.ApplyEnvOverrides(env)
+  # There seems to be a glitch in the way scons decides where to put
+  # PDB files when compiling using MSVC so we specify it manually.
+  # This should not affect any other platforms.
+  return env.Program('cctest', ['cctest.cc', cctest_files, object_files],
+      PDB='cctest.exe.pdb')
+
+
+program = Build()
+Return('program')
diff --git a/deps/v8/test/cctest/cctest.cc b/deps/v8/test/cctest/cctest.cc
new file mode 100644
index 0000000..2807c8b
--- /dev/null
+++ b/deps/v8/test/cctest/cctest.cc
@@ -0,0 +1,126 @@
+// Copyright 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.
+
+#include <v8.h>
+#include <cstdlib>
+#include <cstring>
+#include <cstdio>
+#include "cctest.h"
+#include "debug.h"
+
+
+CcTest* CcTest::last_ = NULL;
+
+
+CcTest::CcTest(TestFunction* callback, const char* file, const char* name,
+               const char* dependency, bool enabled)
+    : callback_(callback), name_(name), dependency_(dependency), prev_(last_) {
+  // Find the base name of this test (const_cast required on Windows).
+  char *basename = strrchr(const_cast<char *>(file), '/');
+  if (!basename) {
+    basename = strrchr(const_cast<char *>(file), '\\');
+  }
+  if (!basename) {
+    basename = v8::internal::StrDup(file);
+  } else {
+    basename = v8::internal::StrDup(basename + 1);
+  }
+  // Drop the extension, if there is one.
+  char *extension = strrchr(basename, '.');
+  if (extension) *extension = 0;
+  // Install this test in the list of tests
+  file_ = basename;
+  enabled_ = enabled;
+  prev_ = last_;
+  last_ = this;
+}
+
+
+static void PrintTestList(CcTest* current) {
+  if (current == NULL) return;
+  PrintTestList(current->prev());
+  if (current->dependency() != NULL) {
+    printf("%s/%s<%s\n",
+           current->file(), current->name(), current->dependency());
+  } else {
+    printf("%s/%s<\n", current->file(), current->name());
+  }
+}
+
+
+int main(int argc, char* argv[]) {
+  v8::internal::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
+  int tests_run = 0;
+  bool print_run_count = true;
+  for (int i = 1; i < argc; i++) {
+    char* arg = argv[i];
+    if (strcmp(arg, "--list") == 0) {
+      PrintTestList(CcTest::last());
+      print_run_count = false;
+
+    } else {
+      char* arg_copy = v8::internal::StrDup(arg);
+      char* testname = strchr(arg_copy, '/');
+      if (testname) {
+        // Split the string in two by nulling the slash and then run
+        // exact matches.
+        *testname = 0;
+        char* file = arg_copy;
+        char* name = testname + 1;
+        CcTest* test = CcTest::last();
+        while (test != NULL) {
+          if (test->enabled()
+              && strcmp(test->file(), file) == 0
+              && strcmp(test->name(), name) == 0) {
+            test->Run();
+            tests_run++;
+          }
+          test = test->prev();
+        }
+
+      } else {
+        // Run all tests with the specified file or test name.
+        char* file_or_name = arg_copy;
+        CcTest* test = CcTest::last();
+        while (test != NULL) {
+          if (test->enabled()
+              && (strcmp(test->file(), file_or_name) == 0
+                  || strcmp(test->name(), file_or_name) == 0)) {
+            test->Run();
+            tests_run++;
+          }
+          test = test->prev();
+        }
+      }
+      v8::internal::DeleteArray<char>(arg_copy);
+    }
+  }
+  if (print_run_count && tests_run != 1)
+    printf("Ran %i tests.\n", tests_run);
+  v8::V8::Dispose();
+  return 0;
+}
diff --git a/deps/v8/test/cctest/cctest.h b/deps/v8/test/cctest/cctest.h
new file mode 100644
index 0000000..a95645e
--- /dev/null
+++ b/deps/v8/test/cctest/cctest.h
@@ -0,0 +1,75 @@
+// Copyright 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 CCTEST_H_
+#define CCTEST_H_
+
+#ifndef TEST
+#define TEST(Name)                                                       \
+  static void Test##Name();                                              \
+  CcTest register_test_##Name(Test##Name, __FILE__, #Name, NULL, true);  \
+  static void Test##Name()
+#endif
+
+#ifndef DEPENDENT_TEST
+#define DEPENDENT_TEST(Name, Dep)                                        \
+  static void Test##Name();                                              \
+  CcTest register_test_##Name(Test##Name, __FILE__, #Name, #Dep, true);  \
+  static void Test##Name()
+#endif
+
+#ifndef DISABLED_TEST
+#define DISABLED_TEST(Name)                                              \
+  static void Test##Name();                                              \
+  CcTest register_test_##Name(Test##Name, __FILE__, #Name, NULL, false); \
+  static void Test##Name()
+#endif
+
+class CcTest {
+ public:
+  typedef void (TestFunction)();
+  CcTest(TestFunction* callback, const char* file, const char* name,
+         const char* dependency, bool enabled);
+  void Run() { callback_(); }
+  static int test_count();
+  static CcTest* last() { return last_; }
+  CcTest* prev() { return prev_; }
+  const char* file() { return file_; }
+  const char* name() { return name_; }
+  const char* dependency() { return dependency_; }
+  bool enabled() { return enabled_; }
+ private:
+  TestFunction* callback_;
+  const char* file_;
+  const char* name_;
+  const char* dependency_;
+  bool enabled_;
+  static CcTest* last_;
+  CcTest* prev_;
+};
+
+#endif  // ifndef CCTEST_H_
diff --git a/deps/v8/test/cctest/cctest.status b/deps/v8/test/cctest/cctest.status
new file mode 100644
index 0000000..9a3f819
--- /dev/null
+++ b/deps/v8/test/cctest/cctest.status
@@ -0,0 +1,50 @@
+# Copyright 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.
+
+prefix cctest
+
+# BUG(96): Fix this flaky test.
+test-debug/ThreadedDebugging: PASS || FAIL
+
+# BUG(281): This test fails on some Linuxes.
+test-debug/DebuggerAgent: PASS, (PASS || FAIL) if $system == linux
+
+[ $arch == arm ]
+
+test-debug: SKIP
+
+# BUG(113): Test seems flaky on ARM.
+test-spaces/LargeObjectSpace: PASS || FAIL
+
+# BUG(240): Test seems flaky on ARM.
+test-api/RegExpInterruption: SKIP
+
+# BUG(271): During exception propagation, we compare pointers into the
+# stack.  These tests fail on the ARM simulator because the C++ and
+# the JavaScript stacks are separate.
+test-api/ExceptionOrder: PASS || FAIL
+test-api/TryCatchInTryFinally: PASS || FAIL
diff --git a/deps/v8/test/cctest/test-alloc.cc b/deps/v8/test/cctest/test-alloc.cc
new file mode 100644
index 0000000..9996eeb
--- /dev/null
+++ b/deps/v8/test/cctest/test-alloc.cc
@@ -0,0 +1,146 @@
+// 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.
+
+#include "v8.h"
+#include "accessors.h"
+#include "top.h"
+
+#include "cctest.h"
+
+
+using namespace v8::internal;
+
+
+static Object* AllocateAfterFailures() {
+  static int attempts = 0;
+  if (++attempts < 3) return Failure::RetryAfterGC(0);
+
+  // New space.
+  NewSpace* new_space = Heap::new_space();
+  static const int kNewSpaceFillerSize = ByteArray::SizeFor(0);
+  while (new_space->Available() > kNewSpaceFillerSize) {
+    CHECK(!Heap::AllocateByteArray(0)->IsFailure());
+  }
+  CHECK(!Heap::AllocateByteArray(100)->IsFailure());
+  CHECK(!Heap::AllocateFixedArray(100, NOT_TENURED)->IsFailure());
+
+  // Make sure we can allocate through optimized allocation functions
+  // for specific kinds.
+  CHECK(!Heap::AllocateFixedArray(100)->IsFailure());
+  CHECK(!Heap::AllocateHeapNumber(0.42)->IsFailure());
+  CHECK(!Heap::AllocateArgumentsObject(Smi::FromInt(87), 10)->IsFailure());
+  Object* object = Heap::AllocateJSObject(*Top::object_function());
+  CHECK(!Heap::CopyJSObject(JSObject::cast(object))->IsFailure());
+
+  // Old data space.
+  OldSpace* old_data_space = Heap::old_data_space();
+  static const int kOldDataSpaceFillerSize = SeqAsciiString::SizeFor(0);
+  while (old_data_space->Available() > kOldDataSpaceFillerSize) {
+    CHECK(!Heap::AllocateRawAsciiString(0, TENURED)->IsFailure());
+  }
+  CHECK(!Heap::AllocateRawAsciiString(100, TENURED)->IsFailure());
+
+  // Large object space.
+  while (!Heap::OldGenerationAllocationLimitReached()) {
+    CHECK(!Heap::AllocateFixedArray(10000, TENURED)->IsFailure());
+  }
+  CHECK(!Heap::AllocateFixedArray(10000, TENURED)->IsFailure());
+
+  // Map space.
+  MapSpace* map_space = Heap::map_space();
+  static const int kMapSpaceFillerSize = Map::kSize;
+  InstanceType instance_type = JS_OBJECT_TYPE;
+  int instance_size = JSObject::kHeaderSize;
+  while (map_space->Available() > kMapSpaceFillerSize) {
+    CHECK(!Heap::AllocateMap(instance_type, instance_size)->IsFailure());
+  }
+  CHECK(!Heap::AllocateMap(instance_type, instance_size)->IsFailure());
+
+  // Test that we can allocate in old pointer space and code space.
+  CHECK(!Heap::AllocateFixedArray(100, TENURED)->IsFailure());
+  CHECK(!Heap::CopyCode(Builtins::builtin(Builtins::Illegal))->IsFailure());
+
+  // Return success.
+  return Smi::FromInt(42);
+}
+
+
+static Handle<Object> Test() {
+  CALL_HEAP_FUNCTION(AllocateAfterFailures(), Object);
+}
+
+
+TEST(StressHandles) {
+  v8::Persistent<v8::Context> env = v8::Context::New();
+  v8::HandleScope scope;
+  env->Enter();
+  Handle<Object> o = Test();
+  CHECK(o->IsSmi() && Smi::cast(*o)->value() == 42);
+  env->Exit();
+}
+
+
+static Object* TestAccessorGet(Object* object, void*) {
+  return AllocateAfterFailures();
+}
+
+
+const AccessorDescriptor kDescriptor = {
+  TestAccessorGet,
+  0,
+  0
+};
+
+
+TEST(StressJS) {
+  v8::Persistent<v8::Context> env = v8::Context::New();
+  v8::HandleScope scope;
+  env->Enter();
+  Handle<JSFunction> function =
+      Factory::NewFunction(Factory::function_symbol(), Factory::null_value());
+  // Force the creation of an initial map and set the code to
+  // something empty.
+  Factory::NewJSObject(function);
+  function->set_code(Builtins::builtin(Builtins::EmptyFunction));
+  // Patch the map to have an accessor for "get".
+  Handle<Map> map(function->initial_map());
+  Handle<DescriptorArray> instance_descriptors(map->instance_descriptors());
+  Handle<Proxy> proxy = Factory::NewProxy(&kDescriptor);
+  instance_descriptors = Factory::CopyAppendProxyDescriptor(
+      instance_descriptors,
+      Factory::NewStringFromAscii(Vector<const char>("get", 3)),
+      proxy,
+      static_cast<PropertyAttributes>(0));
+  map->set_instance_descriptors(*instance_descriptors);
+  // Add the Foo constructor the global object.
+  env->Global()->Set(v8::String::New("Foo"), v8::Utils::ToLocal(function));
+  // Call the accessor through JavaScript.
+  v8::Handle<v8::Value> result =
+      v8::Script::Compile(v8::String::New("(new Foo).get"))->Run();
+  CHECK_EQ(42, result->Int32Value());
+  env->Exit();
+}
diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc
new file mode 100644
index 0000000..23e57d5
--- /dev/null
+++ b/deps/v8/test/cctest/test-api.cc
@@ -0,0 +1,6189 @@
+// 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.
+
+#include <stdlib.h>
+
+#include <map>
+#include <string>
+
+#include "v8.h"
+
+#include "api.h"
+#include "snapshot.h"
+#include "platform.h"
+#include "top.h"
+#include "cctest.h"
+
+static bool IsNaN(double x) {
+#ifdef WIN32
+  return _isnan(x);
+#else
+  return isnan(x);
+#endif
+}
+
+using ::v8::ObjectTemplate;
+using ::v8::Value;
+using ::v8::Context;
+using ::v8::Local;
+using ::v8::String;
+using ::v8::Script;
+using ::v8::Function;
+using ::v8::AccessorInfo;
+using ::v8::Extension;
+
+namespace i = ::v8::internal;
+
+static Local<Value> v8_num(double x) {
+  return v8::Number::New(x);
+}
+
+
+static Local<String> v8_str(const char* x) {
+  return String::New(x);
+}
+
+
+static Local<Script> v8_compile(const char* x) {
+  return Script::Compile(v8_str(x));
+}
+
+
+// A LocalContext holds a reference to a v8::Context.
+class LocalContext {
+ public:
+  LocalContext(v8::ExtensionConfiguration* extensions = 0,
+               v8::Handle<ObjectTemplate> global_template =
+                   v8::Handle<ObjectTemplate>(),
+               v8::Handle<Value> global_object = v8::Handle<Value>())
+    : context_(Context::New(extensions, global_template, global_object)) {
+    context_->Enter();
+  }
+
+  virtual ~LocalContext() {
+    context_->Exit();
+    context_.Dispose();
+  }
+
+  Context* operator->() { return *context_; }
+  Context* operator*() { return *context_; }
+  Local<Context> local() { return Local<Context>::New(context_); }
+  bool IsReady() { return !context_.IsEmpty(); }
+
+ private:
+  v8::Persistent<Context> context_;
+};
+
+
+// Switches between all the Api tests using the threading support.
+// In order to get a surprising but repeatable pattern of thread
+// switching it has extra semaphores to control the order in which
+// the tests alternate, not relying solely on the big V8 lock.
+//
+// A test is augmented with calls to ApiTestFuzzer::Fuzz() in its
+// callbacks.  This will have no effect when we are not running the
+// thread fuzzing test.  In the thread fuzzing test it will
+// pseudorandomly select a successor thread and switch execution
+// to that thread, suspending the current test.
+class ApiTestFuzzer: public v8::internal::Thread {
+ public:
+  void CallTest();
+  explicit ApiTestFuzzer(int num)
+      : test_number_(num),
+        gate_(v8::internal::OS::CreateSemaphore(0)),
+        active_(true) {
+  }
+  ~ApiTestFuzzer() { delete gate_; }
+
+  // The ApiTestFuzzer is also a Thread, so it has a Run method.
+  virtual void Run();
+
+  enum PartOfTest { FIRST_PART, SECOND_PART };
+
+  static void Setup(PartOfTest part);
+  static void RunAllTests();
+  static void TearDown();
+  // This method switches threads if we are running the Threading test.
+  // Otherwise it does nothing.
+  static void Fuzz();
+ private:
+  static bool fuzzing_;
+  static int tests_being_run_;
+  static int current_;
+  static int active_tests_;
+  static bool NextThread();
+  int test_number_;
+  v8::internal::Semaphore* gate_;
+  bool active_;
+  void ContextSwitch();
+  static int GetNextTestNumber();
+  static v8::internal::Semaphore* all_tests_done_;
+};
+
+
+#define THREADED_TEST(Name)                                          \
+  static void Test##Name();                                          \
+  RegisterThreadedTest register_##Name(Test##Name);                  \
+  /* */ TEST(Name)
+
+
+class RegisterThreadedTest {
+ public:
+  explicit RegisterThreadedTest(CcTest::TestFunction* callback)
+      : fuzzer_(NULL), callback_(callback) {
+    prev_ = first_;
+    first_ = this;
+    count_++;
+  }
+  static int count() { return count_; }
+  static RegisterThreadedTest* nth(int i) {
+    ASSERT(i < count());
+    RegisterThreadedTest* current = first_;
+    while (i > 0) {
+      i--;
+      current = current->prev_;
+    }
+    return current;
+  }
+  CcTest::TestFunction* callback() { return callback_; }
+  ApiTestFuzzer* fuzzer_;
+
+ private:
+  static RegisterThreadedTest* first_;
+  static int count_;
+  CcTest::TestFunction* callback_;
+  RegisterThreadedTest* prev_;
+};
+
+
+RegisterThreadedTest *RegisterThreadedTest::first_ = NULL;
+int RegisterThreadedTest::count_ = 0;
+
+
+static int signature_callback_count;
+static v8::Handle<Value> IncrementingSignatureCallback(
+    const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  signature_callback_count++;
+  v8::Handle<v8::Array> result = v8::Array::New(args.Length());
+  for (int i = 0; i < args.Length(); i++)
+    result->Set(v8::Integer::New(i), args[i]);
+  return result;
+}
+
+
+static v8::Handle<Value> SignatureCallback(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  v8::Handle<v8::Array> result = v8::Array::New(args.Length());
+  for (int i = 0; i < args.Length(); i++) {
+    result->Set(v8::Integer::New(i), args[i]);
+  }
+  return result;
+}
+
+
+THREADED_TEST(Handles) {
+  v8::HandleScope scope;
+  Local<Context> local_env;
+  {
+    LocalContext env;
+    local_env = env.local();
+  }
+
+  // Local context should still be live.
+  CHECK(!local_env.IsEmpty());
+  local_env->Enter();
+
+  v8::Handle<v8::Primitive> undef = v8::Undefined();
+  CHECK(!undef.IsEmpty());
+  CHECK(undef->IsUndefined());
+
+  const char* c_source = "1 + 2 + 3";
+  Local<String> source = String::New(c_source);
+  Local<Script> script = Script::Compile(source);
+  CHECK_EQ(6, script->Run()->Int32Value());
+
+  local_env->Exit();
+}
+
+
+// Helper function that compiles and runs the source.
+static Local<Value> CompileRun(const char* source) {
+  return Script::Compile(String::New(source))->Run();
+}
+
+THREADED_TEST(ReceiverSignature) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New();
+  v8::Handle<v8::Signature> sig = v8::Signature::New(fun);
+  fun->PrototypeTemplate()->Set(
+      v8_str("m"),
+      v8::FunctionTemplate::New(IncrementingSignatureCallback,
+                                v8::Handle<Value>(),
+                                sig));
+  env->Global()->Set(v8_str("Fun"), fun->GetFunction());
+  signature_callback_count = 0;
+  CompileRun(
+      "var o = new Fun();"
+      "o.m();");
+  CHECK_EQ(1, signature_callback_count);
+  v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New();
+  sub_fun->Inherit(fun);
+  env->Global()->Set(v8_str("SubFun"), sub_fun->GetFunction());
+  CompileRun(
+      "var o = new SubFun();"
+      "o.m();");
+  CHECK_EQ(2, signature_callback_count);
+
+  v8::TryCatch try_catch;
+  CompileRun(
+      "var o = { };"
+      "o.m = Fun.prototype.m;"
+      "o.m();");
+  CHECK_EQ(2, signature_callback_count);
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+  v8::Handle<v8::FunctionTemplate> unrel_fun = v8::FunctionTemplate::New();
+  sub_fun->Inherit(fun);
+  env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
+  CompileRun(
+      "var o = new UnrelFun();"
+      "o.m = Fun.prototype.m;"
+      "o.m();");
+  CHECK_EQ(2, signature_callback_count);
+  CHECK(try_catch.HasCaught());
+}
+
+
+
+
+THREADED_TEST(ArgumentSignature) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::Handle<v8::FunctionTemplate> cons = v8::FunctionTemplate::New();
+  cons->SetClassName(v8_str("Cons"));
+  v8::Handle<v8::Signature> sig =
+      v8::Signature::New(v8::Handle<v8::FunctionTemplate>(), 1, &cons);
+  v8::Handle<v8::FunctionTemplate> fun =
+      v8::FunctionTemplate::New(SignatureCallback, v8::Handle<Value>(), sig);
+  env->Global()->Set(v8_str("Cons"), cons->GetFunction());
+  env->Global()->Set(v8_str("Fun1"), fun->GetFunction());
+
+  v8::Handle<Value> value1 = CompileRun("Fun1(4) == '';");
+  ASSERT(value1->IsTrue());
+
+  v8::Handle<Value> value2 = CompileRun("Fun1(new Cons()) == '[object Cons]';");
+  ASSERT(value2->IsTrue());
+
+  v8::Handle<Value> value3 = CompileRun("Fun1() == '';");
+  ASSERT(value3->IsTrue());
+
+  v8::Handle<v8::FunctionTemplate> cons1 = v8::FunctionTemplate::New();
+  cons1->SetClassName(v8_str("Cons1"));
+  v8::Handle<v8::FunctionTemplate> cons2 = v8::FunctionTemplate::New();
+  cons2->SetClassName(v8_str("Cons2"));
+  v8::Handle<v8::FunctionTemplate> cons3 = v8::FunctionTemplate::New();
+  cons3->SetClassName(v8_str("Cons3"));
+
+  v8::Handle<v8::FunctionTemplate> args[3] = { cons1, cons2, cons3 };
+  v8::Handle<v8::Signature> wsig =
+      v8::Signature::New(v8::Handle<v8::FunctionTemplate>(), 3, args);
+  v8::Handle<v8::FunctionTemplate> fun2 =
+      v8::FunctionTemplate::New(SignatureCallback, v8::Handle<Value>(), wsig);
+
+  env->Global()->Set(v8_str("Cons1"), cons1->GetFunction());
+  env->Global()->Set(v8_str("Cons2"), cons2->GetFunction());
+  env->Global()->Set(v8_str("Cons3"), cons3->GetFunction());
+  env->Global()->Set(v8_str("Fun2"), fun2->GetFunction());
+  v8::Handle<Value> value4 = CompileRun(
+      "Fun2(new Cons1(), new Cons2(), new Cons3()) =="
+      "'[object Cons1],[object Cons2],[object Cons3]'");
+  ASSERT(value4->IsTrue());
+
+  v8::Handle<Value> value5 = CompileRun(
+      "Fun2(new Cons1(), new Cons2(), 5) == '[object Cons1],[object Cons2],'");
+  ASSERT(value5->IsTrue());
+
+  v8::Handle<Value> value6 = CompileRun(
+      "Fun2(new Cons3(), new Cons2(), new Cons1()) == ',[object Cons2],'");
+  ASSERT(value6->IsTrue());
+
+  v8::Handle<Value> value7 = CompileRun(
+      "Fun2(new Cons1(), new Cons2(), new Cons3(), 'd') == "
+      "'[object Cons1],[object Cons2],[object Cons3],d';");
+  ASSERT(value7->IsTrue());
+
+  v8::Handle<Value> value8 = CompileRun(
+      "Fun2(new Cons1(), new Cons2()) == '[object Cons1],[object Cons2]'");
+  ASSERT(value8->IsTrue());
+}
+
+
+THREADED_TEST(HulIgennem) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::Handle<v8::Primitive> undef = v8::Undefined();
+  Local<String> undef_str = undef->ToString();
+  char* value = i::NewArray<char>(undef_str->Length() + 1);
+  undef_str->WriteAscii(value);
+  CHECK_EQ(0, strcmp(value, "undefined"));
+  i::DeleteArray(value);
+}
+
+
+THREADED_TEST(Access) {
+  v8::HandleScope scope;
+  LocalContext env;
+  Local<v8::Object> obj = v8::Object::New();
+  Local<Value> foo_before = obj->Get(v8_str("foo"));
+  CHECK(foo_before->IsUndefined());
+  Local<String> bar_str = v8_str("bar");
+  obj->Set(v8_str("foo"), bar_str);
+  Local<Value> foo_after = obj->Get(v8_str("foo"));
+  CHECK(!foo_after->IsUndefined());
+  CHECK(foo_after->IsString());
+  CHECK_EQ(bar_str, foo_after);
+}
+
+
+THREADED_TEST(Script) {
+  v8::HandleScope scope;
+  LocalContext env;
+  const char* c_source = "1 + 2 + 3";
+  Local<String> source = String::New(c_source);
+  Local<Script> script = Script::Compile(source);
+  CHECK_EQ(6, script->Run()->Int32Value());
+}
+
+
+static uint16_t* AsciiToTwoByteString(const char* source) {
+  size_t array_length = strlen(source) + 1;
+  uint16_t* converted = i::NewArray<uint16_t>(array_length);
+  for (size_t i = 0; i < array_length; i++) converted[i] = source[i];
+  return converted;
+}
+
+
+class TestResource: public String::ExternalStringResource {
+ public:
+  static int dispose_count;
+
+  explicit TestResource(uint16_t* data)
+      : data_(data), length_(0) {
+    while (data[length_]) ++length_;
+  }
+
+  ~TestResource() {
+    i::DeleteArray(data_);
+    ++dispose_count;
+  }
+
+  const uint16_t* data() const {
+    return data_;
+  }
+
+  size_t length() const {
+    return length_;
+  }
+ private:
+  uint16_t* data_;
+  size_t length_;
+};
+
+
+int TestResource::dispose_count = 0;
+
+
+class TestAsciiResource: public String::ExternalAsciiStringResource {
+ public:
+  static int dispose_count;
+
+  explicit TestAsciiResource(char* data)
+      : data_(data),
+        length_(strlen(data)) { }
+
+  ~TestAsciiResource() {
+    i::DeleteArray(data_);
+    ++dispose_count;
+  }
+
+  const char* data() const {
+    return data_;
+  }
+
+  size_t length() const {
+    return length_;
+  }
+ private:
+  char* data_;
+  size_t length_;
+};
+
+
+int TestAsciiResource::dispose_count = 0;
+
+
+THREADED_TEST(ScriptUsingStringResource) {
+  TestResource::dispose_count = 0;
+  const char* c_source = "1 + 2 * 3";
+  uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
+  {
+    v8::HandleScope scope;
+    LocalContext env;
+    TestResource* resource = new TestResource(two_byte_source);
+    Local<String> source = String::NewExternal(resource);
+    Local<Script> script = Script::Compile(source);
+    Local<Value> value = script->Run();
+    CHECK(value->IsNumber());
+    CHECK_EQ(7, value->Int32Value());
+    CHECK(source->IsExternal());
+    CHECK_EQ(resource,
+             static_cast<TestResource*>(source->GetExternalStringResource()));
+    v8::internal::Heap::CollectAllGarbage();
+    CHECK_EQ(0, TestResource::dispose_count);
+  }
+  v8::internal::Heap::CollectAllGarbage();
+  CHECK_EQ(1, TestResource::dispose_count);
+}
+
+
+THREADED_TEST(ScriptUsingAsciiStringResource) {
+  TestAsciiResource::dispose_count = 0;
+  const char* c_source = "1 + 2 * 3";
+  {
+    v8::HandleScope scope;
+    LocalContext env;
+    Local<String> source =
+        String::NewExternal(new TestAsciiResource(i::StrDup(c_source)));
+    Local<Script> script = Script::Compile(source);
+    Local<Value> value = script->Run();
+    CHECK(value->IsNumber());
+    CHECK_EQ(7, value->Int32Value());
+    v8::internal::Heap::CollectAllGarbage();
+    CHECK_EQ(0, TestAsciiResource::dispose_count);
+  }
+  v8::internal::Heap::CollectAllGarbage();
+  CHECK_EQ(1, TestAsciiResource::dispose_count);
+}
+
+
+THREADED_TEST(ScriptMakingExternalString) {
+  TestResource::dispose_count = 0;
+  uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
+  {
+    v8::HandleScope scope;
+    LocalContext env;
+    Local<String> source = String::New(two_byte_source);
+    bool success = source->MakeExternal(new TestResource(two_byte_source));
+    CHECK(success);
+    Local<Script> script = Script::Compile(source);
+    Local<Value> value = script->Run();
+    CHECK(value->IsNumber());
+    CHECK_EQ(7, value->Int32Value());
+    v8::internal::Heap::CollectAllGarbage();
+    CHECK_EQ(0, TestResource::dispose_count);
+  }
+  v8::internal::Heap::CollectAllGarbage();
+  CHECK_EQ(1, TestResource::dispose_count);
+}
+
+
+THREADED_TEST(ScriptMakingExternalAsciiString) {
+  TestAsciiResource::dispose_count = 0;
+  const char* c_source = "1 + 2 * 3";
+  {
+    v8::HandleScope scope;
+    LocalContext env;
+    Local<String> source = v8_str(c_source);
+    bool success = source->MakeExternal(
+        new TestAsciiResource(i::StrDup(c_source)));
+    CHECK(success);
+    Local<Script> script = Script::Compile(source);
+    Local<Value> value = script->Run();
+    CHECK(value->IsNumber());
+    CHECK_EQ(7, value->Int32Value());
+    v8::internal::Heap::CollectAllGarbage();
+    CHECK_EQ(0, TestAsciiResource::dispose_count);
+  }
+  v8::internal::Heap::CollectAllGarbage();
+  CHECK_EQ(1, TestAsciiResource::dispose_count);
+}
+
+
+THREADED_TEST(UsingExternalString) {
+  v8::HandleScope scope;
+  uint16_t* two_byte_string = AsciiToTwoByteString("test string");
+  Local<String> string = String::NewExternal(new TestResource(two_byte_string));
+  i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
+  // Trigger GCs so that the newly allocated string moves to old gen.
+  i::Heap::CollectGarbage(0, i::NEW_SPACE);  // in survivor space now
+  i::Heap::CollectGarbage(0, i::NEW_SPACE);  // in old gen now
+  i::Handle<i::String> isymbol = i::Factory::SymbolFromString(istring);
+  CHECK(isymbol->IsSymbol());
+}
+
+
+THREADED_TEST(UsingExternalAsciiString) {
+  v8::HandleScope scope;
+  const char* one_byte_string = "test string";
+  Local<String> string = String::NewExternal(
+      new TestAsciiResource(i::StrDup(one_byte_string)));
+  i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
+  // Trigger GCs so that the newly allocated string moves to old gen.
+  i::Heap::CollectGarbage(0, i::NEW_SPACE);  // in survivor space now
+  i::Heap::CollectGarbage(0, i::NEW_SPACE);  // in old gen now
+  i::Handle<i::String> isymbol = i::Factory::SymbolFromString(istring);
+  CHECK(isymbol->IsSymbol());
+}
+
+
+THREADED_TEST(GlobalProperties) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::Handle<v8::Object> global = env->Global();
+  global->Set(v8_str("pi"), v8_num(3.1415926));
+  Local<Value> pi = global->Get(v8_str("pi"));
+  CHECK_EQ(3.1415926, pi->NumberValue());
+}
+
+
+static v8::Handle<Value> handle_call(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(102);
+}
+
+
+static v8::Handle<Value> construct_call(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  args.This()->Set(v8_str("x"), v8_num(1));
+  args.This()->Set(v8_str("y"), v8_num(2));
+  return args.This();
+}
+
+THREADED_TEST(FunctionTemplate) {
+  v8::HandleScope scope;
+  LocalContext env;
+  {
+    Local<v8::FunctionTemplate> fun_templ =
+        v8::FunctionTemplate::New(handle_call);
+    Local<Function> fun = fun_templ->GetFunction();
+    env->Global()->Set(v8_str("obj"), fun);
+    Local<Script> script = v8_compile("obj()");
+    CHECK_EQ(102, script->Run()->Int32Value());
+  }
+  // Use SetCallHandler to initialize a function template, should work like the
+  // previous one.
+  {
+    Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
+    fun_templ->SetCallHandler(handle_call);
+    Local<Function> fun = fun_templ->GetFunction();
+    env->Global()->Set(v8_str("obj"), fun);
+    Local<Script> script = v8_compile("obj()");
+    CHECK_EQ(102, script->Run()->Int32Value());
+  }
+  // Test constructor calls.
+  {
+    Local<v8::FunctionTemplate> fun_templ =
+        v8::FunctionTemplate::New(construct_call);
+    fun_templ->SetClassName(v8_str("funky"));
+    Local<Function> fun = fun_templ->GetFunction();
+    env->Global()->Set(v8_str("obj"), fun);
+    Local<Script> script = v8_compile("var s = new obj(); s.x");
+    CHECK_EQ(1, script->Run()->Int32Value());
+
+    Local<Value> result = v8_compile("(new obj()).toString()")->Run();
+    CHECK_EQ(v8_str("[object funky]"), result);
+  }
+}
+
+
+static v8::Handle<Value> handle_property(Local<String> name,
+                                         const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(900);
+}
+
+
+THREADED_TEST(PropertyHandler) {
+  v8::HandleScope scope;
+  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
+  fun_templ->InstanceTemplate()->SetAccessor(v8_str("foo"), handle_property);
+  LocalContext env;
+  Local<Function> fun = fun_templ->GetFunction();
+  env->Global()->Set(v8_str("Fun"), fun);
+  Local<Script> getter = v8_compile("var obj = new Fun(); obj.foo;");
+  CHECK_EQ(900, getter->Run()->Int32Value());
+  Local<Script> setter = v8_compile("obj.foo = 901;");
+  CHECK_EQ(901, setter->Run()->Int32Value());
+}
+
+
+THREADED_TEST(Number) {
+  v8::HandleScope scope;
+  LocalContext env;
+  double PI = 3.1415926;
+  Local<v8::Number> pi_obj = v8::Number::New(PI);
+  CHECK_EQ(PI, pi_obj->NumberValue());
+}
+
+
+THREADED_TEST(ToNumber) {
+  v8::HandleScope scope;
+  LocalContext env;
+  Local<String> str = v8_str("3.1415926");
+  CHECK_EQ(3.1415926, str->NumberValue());
+  v8::Handle<v8::Boolean> t = v8::True();
+  CHECK_EQ(1.0, t->NumberValue());
+  v8::Handle<v8::Boolean> f = v8::False();
+  CHECK_EQ(0.0, f->NumberValue());
+}
+
+
+THREADED_TEST(Date) {
+  v8::HandleScope scope;
+  LocalContext env;
+  double PI = 3.1415926;
+  Local<Value> date_obj = v8::Date::New(PI);
+  CHECK_EQ(3.0, date_obj->NumberValue());
+}
+
+
+THREADED_TEST(Boolean) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::Handle<v8::Boolean> t = v8::True();
+  CHECK(t->Value());
+  v8::Handle<v8::Boolean> f = v8::False();
+  CHECK(!f->Value());
+  v8::Handle<v8::Primitive> u = v8::Undefined();
+  CHECK(!u->BooleanValue());
+  v8::Handle<v8::Primitive> n = v8::Null();
+  CHECK(!n->BooleanValue());
+  v8::Handle<String> str1 = v8_str("");
+  CHECK(!str1->BooleanValue());
+  v8::Handle<String> str2 = v8_str("x");
+  CHECK(str2->BooleanValue());
+  CHECK(!v8::Number::New(0)->BooleanValue());
+  CHECK(v8::Number::New(-1)->BooleanValue());
+  CHECK(v8::Number::New(1)->BooleanValue());
+  CHECK(v8::Number::New(42)->BooleanValue());
+  CHECK(!v8_compile("NaN")->Run()->BooleanValue());
+}
+
+
+static v8::Handle<Value> DummyCallHandler(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(13.4);
+}
+
+
+static v8::Handle<Value> GetM(Local<String> name, const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(876);
+}
+
+
+THREADED_TEST(GlobalPrototype) {
+  v8::HandleScope scope;
+  v8::Handle<v8::FunctionTemplate> func_templ = v8::FunctionTemplate::New();
+  func_templ->PrototypeTemplate()->Set(
+      "dummy",
+      v8::FunctionTemplate::New(DummyCallHandler));
+  v8::Handle<ObjectTemplate> templ = func_templ->InstanceTemplate();
+  templ->Set("x", v8_num(200));
+  templ->SetAccessor(v8_str("m"), GetM);
+  LocalContext env(0, templ);
+  v8::Handle<v8::Object> obj = env->Global();
+  v8::Handle<Script> script = v8_compile("dummy()");
+  v8::Handle<Value> result = script->Run();
+  CHECK_EQ(13.4, result->NumberValue());
+  CHECK_EQ(200, v8_compile("x")->Run()->Int32Value());
+  CHECK_EQ(876, v8_compile("m")->Run()->Int32Value());
+}
+
+
+static v8::Handle<Value> GetIntValue(Local<String> property,
+                                     const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  int* value =
+      static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
+  return v8_num(*value);
+}
+
+static void SetIntValue(Local<String> property,
+                        Local<Value> value,
+                        const AccessorInfo& info) {
+  int* field =
+      static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
+  *field = value->Int32Value();
+}
+
+int foo, bar, baz;
+
+THREADED_TEST(GlobalVariableAccess) {
+  foo = 0;
+  bar = -4;
+  baz = 10;
+  v8::HandleScope scope;
+  v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  templ->InstanceTemplate()->SetAccessor(v8_str("foo"),
+                                         GetIntValue,
+                                         SetIntValue,
+                                         v8::External::New(&foo));
+  templ->InstanceTemplate()->SetAccessor(v8_str("bar"),
+                                         GetIntValue,
+                                         SetIntValue,
+                                         v8::External::New(&bar));
+  templ->InstanceTemplate()->SetAccessor(v8_str("baz"),
+                                         GetIntValue,
+                                         SetIntValue,
+                                         v8::External::New(&baz));
+  LocalContext env(0, templ->InstanceTemplate());
+  v8_compile("foo = (++bar) + baz")->Run();
+  CHECK_EQ(bar, -3);
+  CHECK_EQ(foo, 7);
+}
+
+
+THREADED_TEST(ObjectTemplate) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ1 = ObjectTemplate::New();
+  templ1->Set("x", v8_num(10));
+  templ1->Set("y", v8_num(13));
+  LocalContext env;
+  Local<v8::Object> instance1 = templ1->NewInstance();
+  env->Global()->Set(v8_str("p"), instance1);
+  CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
+  CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
+  Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New();
+  fun->PrototypeTemplate()->Set("nirk", v8_num(123));
+  Local<ObjectTemplate> templ2 = fun->InstanceTemplate();
+  templ2->Set("a", v8_num(12));
+  templ2->Set("b", templ1);
+  Local<v8::Object> instance2 = templ2->NewInstance();
+  env->Global()->Set(v8_str("q"), instance2);
+  CHECK(v8_compile("(q.nirk == 123)")->Run()->BooleanValue());
+  CHECK(v8_compile("(q.a == 12)")->Run()->BooleanValue());
+  CHECK(v8_compile("(q.b.x == 10)")->Run()->BooleanValue());
+  CHECK(v8_compile("(q.b.y == 13)")->Run()->BooleanValue());
+}
+
+
+static v8::Handle<Value> GetFlabby(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(17.2);
+}
+
+
+static v8::Handle<Value> GetKnurd(Local<String> property, const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(15.2);
+}
+
+
+THREADED_TEST(DescriptorInheritance) {
+  v8::HandleScope scope;
+  v8::Handle<v8::FunctionTemplate> super = v8::FunctionTemplate::New();
+  super->PrototypeTemplate()->Set("flabby",
+                                  v8::FunctionTemplate::New(GetFlabby));
+  super->PrototypeTemplate()->Set("PI", v8_num(3.14));
+
+  super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
+
+  v8::Handle<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New();
+  base1->Inherit(super);
+  base1->PrototypeTemplate()->Set("v1", v8_num(20.1));
+
+  v8::Handle<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New();
+  base2->Inherit(super);
+  base2->PrototypeTemplate()->Set("v2", v8_num(10.1));
+
+  LocalContext env;
+
+  env->Global()->Set(v8_str("s"), super->GetFunction());
+  env->Global()->Set(v8_str("base1"), base1->GetFunction());
+  env->Global()->Set(v8_str("base2"), base2->GetFunction());
+
+  // Checks right __proto__ chain.
+  CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")->BooleanValue());
+  CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")->BooleanValue());
+
+  CHECK(v8_compile("s.prototype.PI == 3.14")->Run()->BooleanValue());
+
+  // Instance accessor should not be visible on function object or its prototype
+  CHECK(CompileRun("s.knurd == undefined")->BooleanValue());
+  CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue());
+  CHECK(CompileRun("base1.prototype.knurd == undefined")->BooleanValue());
+
+  env->Global()->Set(v8_str("obj"),
+                     base1->GetFunction()->NewInstance());
+  CHECK_EQ(17.2, v8_compile("obj.flabby()")->Run()->NumberValue());
+  CHECK(v8_compile("'flabby' in obj")->Run()->BooleanValue());
+  CHECK_EQ(15.2, v8_compile("obj.knurd")->Run()->NumberValue());
+  CHECK(v8_compile("'knurd' in obj")->Run()->BooleanValue());
+  CHECK_EQ(20.1, v8_compile("obj.v1")->Run()->NumberValue());
+
+  env->Global()->Set(v8_str("obj2"),
+                     base2->GetFunction()->NewInstance());
+  CHECK_EQ(17.2, v8_compile("obj2.flabby()")->Run()->NumberValue());
+  CHECK(v8_compile("'flabby' in obj2")->Run()->BooleanValue());
+  CHECK_EQ(15.2, v8_compile("obj2.knurd")->Run()->NumberValue());
+  CHECK(v8_compile("'knurd' in obj2")->Run()->BooleanValue());
+  CHECK_EQ(10.1, v8_compile("obj2.v2")->Run()->NumberValue());
+
+  // base1 and base2 cannot cross reference to each's prototype
+  CHECK(v8_compile("obj.v2")->Run()->IsUndefined());
+  CHECK(v8_compile("obj2.v1")->Run()->IsUndefined());
+}
+
+
+int echo_named_call_count;
+
+
+static v8::Handle<Value> EchoNamedProperty(Local<String> name,
+                                           const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK_EQ(v8_str("data"), info.Data());
+  echo_named_call_count++;
+  return name;
+}
+
+
+THREADED_TEST(NamedPropertyHandlerGetter) {
+  echo_named_call_count = 0;
+  v8::HandleScope scope;
+  v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  templ->InstanceTemplate()->SetNamedPropertyHandler(EchoNamedProperty,
+                                                     0, 0, 0, 0,
+                                                     v8_str("data"));
+  LocalContext env;
+  env->Global()->Set(v8_str("obj"),
+                     templ->GetFunction()->NewInstance());
+  CHECK_EQ(echo_named_call_count, 0);
+  v8_compile("obj.x")->Run();
+  CHECK_EQ(echo_named_call_count, 1);
+  const char* code = "var str = 'oddle'; obj[str] + obj.poddle;";
+  v8::Handle<Value> str = CompileRun(code);
+  String::AsciiValue value(str);
+  CHECK_EQ(*value, "oddlepoddle");
+  // Check default behavior
+  CHECK_EQ(v8_compile("obj.flob = 10;")->Run()->Int32Value(), 10);
+  CHECK(v8_compile("'myProperty' in obj")->Run()->BooleanValue());
+  CHECK(v8_compile("delete obj.myProperty")->Run()->BooleanValue());
+}
+
+
+int echo_indexed_call_count = 0;
+
+
+static v8::Handle<Value> EchoIndexedProperty(uint32_t index,
+                                             const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK_EQ(v8_num(637), info.Data());
+  echo_indexed_call_count++;
+  return v8_num(index);
+}
+
+
+THREADED_TEST(IndexedPropertyHandlerGetter) {
+  v8::HandleScope scope;
+  v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  templ->InstanceTemplate()->SetIndexedPropertyHandler(EchoIndexedProperty,
+                                                       0, 0, 0, 0,
+                                                       v8_num(637));
+  LocalContext env;
+  env->Global()->Set(v8_str("obj"),
+                     templ->GetFunction()->NewInstance());
+  Local<Script> script = v8_compile("obj[900]");
+  CHECK_EQ(script->Run()->Int32Value(), 900);
+}
+
+
+v8::Handle<v8::Object> bottom;
+
+static v8::Handle<Value> CheckThisIndexedPropertyHandler(
+    uint32_t index,
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.This()->Equals(bottom));
+  return v8::Handle<Value>();
+}
+
+static v8::Handle<Value> CheckThisNamedPropertyHandler(
+    Local<String> name,
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.This()->Equals(bottom));
+  return v8::Handle<Value>();
+}
+
+
+v8::Handle<Value> CheckThisIndexedPropertySetter(uint32_t index,
+                                                 Local<Value> value,
+                                                 const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.This()->Equals(bottom));
+  return v8::Handle<Value>();
+}
+
+
+v8::Handle<Value> CheckThisNamedPropertySetter(Local<String> property,
+                                               Local<Value> value,
+                                               const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.This()->Equals(bottom));
+  return v8::Handle<Value>();
+}
+
+v8::Handle<v8::Boolean> CheckThisIndexedPropertyQuery(
+    uint32_t index,
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.This()->Equals(bottom));
+  return v8::Handle<v8::Boolean>();
+}
+
+
+v8::Handle<v8::Boolean> CheckThisNamedPropertyQuery(Local<String> property,
+                                                    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.This()->Equals(bottom));
+  return v8::Handle<v8::Boolean>();
+}
+
+
+v8::Handle<v8::Boolean> CheckThisIndexedPropertyDeleter(
+    uint32_t index,
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.This()->Equals(bottom));
+  return v8::Handle<v8::Boolean>();
+}
+
+
+v8::Handle<v8::Boolean> CheckThisNamedPropertyDeleter(
+    Local<String> property,
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.This()->Equals(bottom));
+  return v8::Handle<v8::Boolean>();
+}
+
+
+v8::Handle<v8::Array> CheckThisIndexedPropertyEnumerator(
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.This()->Equals(bottom));
+  return v8::Handle<v8::Array>();
+}
+
+
+v8::Handle<v8::Array> CheckThisNamedPropertyEnumerator(
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.This()->Equals(bottom));
+  return v8::Handle<v8::Array>();
+}
+
+
+THREADED_TEST(PropertyHandlerInPrototype) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  // Set up a prototype chain with three interceptors.
+  v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  templ->InstanceTemplate()->SetIndexedPropertyHandler(
+      CheckThisIndexedPropertyHandler,
+      CheckThisIndexedPropertySetter,
+      CheckThisIndexedPropertyQuery,
+      CheckThisIndexedPropertyDeleter,
+      CheckThisIndexedPropertyEnumerator);
+
+  templ->InstanceTemplate()->SetNamedPropertyHandler(
+      CheckThisNamedPropertyHandler,
+      CheckThisNamedPropertySetter,
+      CheckThisNamedPropertyQuery,
+      CheckThisNamedPropertyDeleter,
+      CheckThisNamedPropertyEnumerator);
+
+  bottom = templ->GetFunction()->NewInstance();
+  Local<v8::Object> top = templ->GetFunction()->NewInstance();
+  Local<v8::Object> middle = templ->GetFunction()->NewInstance();
+
+  bottom->Set(v8_str("__proto__"), middle);
+  middle->Set(v8_str("__proto__"), top);
+  env->Global()->Set(v8_str("obj"), bottom);
+
+  // Indexed and named get.
+  Script::Compile(v8_str("obj[0]"))->Run();
+  Script::Compile(v8_str("obj.x"))->Run();
+
+  // Indexed and named set.
+  Script::Compile(v8_str("obj[1] = 42"))->Run();
+  Script::Compile(v8_str("obj.y = 42"))->Run();
+
+  // Indexed and named query.
+  Script::Compile(v8_str("0 in obj"))->Run();
+  Script::Compile(v8_str("'x' in obj"))->Run();
+
+  // Indexed and named deleter.
+  Script::Compile(v8_str("delete obj[0]"))->Run();
+  Script::Compile(v8_str("delete obj.x"))->Run();
+
+  // Enumerators.
+  Script::Compile(v8_str("for (var p in obj) ;"))->Run();
+}
+
+
+static v8::Handle<Value> PrePropertyHandlerGet(Local<String> key,
+                                               const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  if (v8_str("pre")->Equals(key)) {
+    return v8_str("PrePropertyHandler: pre");
+  }
+  return v8::Handle<String>();
+}
+
+
+static v8::Handle<v8::Boolean> PrePropertyHandlerHas(Local<String> key,
+                                                     const AccessorInfo&) {
+  if (v8_str("pre")->Equals(key)) {
+    return v8::True();
+  }
+
+  return v8::Handle<v8::Boolean>();  // do not intercept the call
+}
+
+
+THREADED_TEST(PrePropertyHandler) {
+  v8::HandleScope scope;
+  v8::Handle<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
+  desc->InstanceTemplate()->SetNamedPropertyHandler(PrePropertyHandlerGet,
+                                                    0,
+                                                    PrePropertyHandlerHas);
+  LocalContext env(NULL, desc->InstanceTemplate());
+  Script::Compile(v8_str(
+      "var pre = 'Object: pre'; var on = 'Object: on';"))->Run();
+  v8::Handle<Value> result_pre = Script::Compile(v8_str("pre"))->Run();
+  CHECK_EQ(v8_str("PrePropertyHandler: pre"), result_pre);
+  v8::Handle<Value> result_on = Script::Compile(v8_str("on"))->Run();
+  CHECK_EQ(v8_str("Object: on"), result_on);
+  v8::Handle<Value> result_post = Script::Compile(v8_str("post"))->Run();
+  CHECK(result_post.IsEmpty());
+}
+
+
+THREADED_TEST(UndefinedIsNotEnumerable) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::Handle<Value> result = Script::Compile(v8_str(
+      "this.propertyIsEnumerable(undefined)"))->Run();
+  CHECK(result->IsFalse());
+}
+
+
+v8::Handle<Script> call_recursively_script;
+static const int kTargetRecursionDepth = 300;  // near maximum
+
+
+static v8::Handle<Value> CallScriptRecursivelyCall(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  int depth = args.This()->Get(v8_str("depth"))->Int32Value();
+  if (depth == kTargetRecursionDepth) return v8::Undefined();
+  args.This()->Set(v8_str("depth"), v8::Integer::New(depth + 1));
+  return call_recursively_script->Run();
+}
+
+
+static v8::Handle<Value> CallFunctionRecursivelyCall(
+    const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  int depth = args.This()->Get(v8_str("depth"))->Int32Value();
+  if (depth == kTargetRecursionDepth) {
+    printf("[depth = %d]\n", depth);
+    return v8::Undefined();
+  }
+  args.This()->Set(v8_str("depth"), v8::Integer::New(depth + 1));
+  v8::Handle<Value> function =
+      args.This()->Get(v8_str("callFunctionRecursively"));
+  return v8::Handle<Function>::Cast(function)->Call(args.This(), 0, NULL);
+}
+
+
+THREADED_TEST(DeepCrossLanguageRecursion) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New();
+  global->Set(v8_str("callScriptRecursively"),
+              v8::FunctionTemplate::New(CallScriptRecursivelyCall));
+  global->Set(v8_str("callFunctionRecursively"),
+              v8::FunctionTemplate::New(CallFunctionRecursivelyCall));
+  LocalContext env(NULL, global);
+
+  env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
+  call_recursively_script = v8_compile("callScriptRecursively()");
+  v8::Handle<Value> result = call_recursively_script->Run();
+  call_recursively_script = v8::Handle<Script>();
+
+  env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
+  Script::Compile(v8_str("callFunctionRecursively()"))->Run();
+}
+
+
+static v8::Handle<Value>
+    ThrowingPropertyHandlerGet(Local<String> key, const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  return v8::ThrowException(key);
+}
+
+
+static v8::Handle<Value> ThrowingPropertyHandlerSet(Local<String> key,
+                                                    Local<Value>,
+                                                    const AccessorInfo&) {
+  v8::ThrowException(key);
+  return v8::Undefined();  // not the same as v8::Handle<v8::Value>()
+}
+
+
+THREADED_TEST(CallbackExceptionRegression) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+  obj->SetNamedPropertyHandler(ThrowingPropertyHandlerGet,
+                               ThrowingPropertyHandlerSet);
+  LocalContext env;
+  env->Global()->Set(v8_str("obj"), obj->NewInstance());
+  v8::Handle<Value> otto = Script::Compile(v8_str(
+      "try { with (obj) { otto; } } catch (e) { e; }"))->Run();
+  CHECK_EQ(v8_str("otto"), otto);
+  v8::Handle<Value> netto = Script::Compile(v8_str(
+      "try { with (obj) { netto = 4; } } catch (e) { e; }"))->Run();
+  CHECK_EQ(v8_str("netto"), netto);
+}
+
+
+static v8::Handle<Value> ThrowingGetAccessor(Local<String> name,
+                                             const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  return v8::ThrowException(v8_str("g"));
+}
+
+
+static void ThrowingSetAccessor(Local<String> name,
+                                Local<Value> value,
+                                const AccessorInfo& info) {
+  v8::ThrowException(value);
+}
+
+
+THREADED_TEST(Regress1054726) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+  obj->SetAccessor(v8_str("x"),
+                   ThrowingGetAccessor,
+                   ThrowingSetAccessor,
+                   Local<Value>());
+
+  LocalContext env;
+  env->Global()->Set(v8_str("obj"), obj->NewInstance());
+
+  // Use the throwing property setter/getter in a loop to force
+  // the accessor ICs to be initialized.
+  v8::Handle<Value> result;
+  result = Script::Compile(v8_str(
+      "var result = '';"
+      "for (var i = 0; i < 5; i++) {"
+      "  try { obj.x; } catch (e) { result += e; }"
+      "}; result"))->Run();
+  CHECK_EQ(v8_str("ggggg"), result);
+
+  result = Script::Compile(String::New(
+      "var result = '';"
+      "for (var i = 0; i < 5; i++) {"
+      "  try { obj.x = i; } catch (e) { result += e; }"
+      "}; result"))->Run();
+  CHECK_EQ(v8_str("01234"), result);
+}
+
+
+THREADED_TEST(FunctionPrototype) {
+  v8::HandleScope scope;
+  Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New();
+  Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
+  LocalContext env;
+  env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
+  Local<Script> script = Script::Compile(v8_str("Foo.prototype.plak"));
+  CHECK_EQ(script->Run()->Int32Value(), 321);
+}
+
+
+THREADED_TEST(InternalFields) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
+  instance_templ->SetInternalFieldCount(1);
+  Local<v8::Object> obj = templ->GetFunction()->NewInstance();
+  CHECK_EQ(1, obj->InternalFieldCount());
+  CHECK(obj->GetInternalField(0)->IsUndefined());
+  obj->SetInternalField(0, v8_num(17));
+  CHECK_EQ(17, obj->GetInternalField(0)->Int32Value());
+}
+
+
+THREADED_TEST(IdentityHash) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  // Ensure that the test starts with an fresh heap to test whether the hash
+  // code is based on the address.
+  i::Heap::CollectAllGarbage();
+  Local<v8::Object> obj = v8::Object::New();
+  int hash = obj->GetIdentityHash();
+  int hash1 = obj->GetIdentityHash();
+  CHECK_EQ(hash, hash1);
+  int hash2 = v8::Object::New()->GetIdentityHash();
+  // Since the identity hash is essentially a random number two consecutive
+  // objects should not be assigned the same hash code. If the test below fails
+  // the random number generator should be evaluated.
+  CHECK_NE(hash, hash2);
+  i::Heap::CollectAllGarbage();
+  int hash3 = v8::Object::New()->GetIdentityHash();
+  // Make sure that the identity hash is not based on the initial address of
+  // the object alone. If the test below fails the random number generator
+  // should be evaluated.
+  CHECK_NE(hash, hash3);
+  int hash4 = obj->GetIdentityHash();
+  CHECK_EQ(hash, hash4);
+}
+
+
+THREADED_TEST(HiddenProperties) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  v8::Local<v8::Object> obj = v8::Object::New();
+  v8::Local<v8::String> key = v8_str("api-test::hidden-key");
+  v8::Local<v8::String> empty = v8_str("");
+  v8::Local<v8::String> prop_name = v8_str("prop_name");
+
+  i::Heap::CollectAllGarbage();
+
+  // Make sure delete of a non-existent hidden value works
+  CHECK(obj->DeleteHiddenValue(key));
+
+  CHECK(obj->SetHiddenValue(key, v8::Integer::New(1503)));
+  CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value());
+  CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002)));
+  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
+
+  i::Heap::CollectAllGarbage();
+
+  // Make sure we do not find the hidden property.
+  CHECK(!obj->Has(empty));
+  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
+  CHECK(obj->Get(empty)->IsUndefined());
+  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
+  CHECK(obj->Set(empty, v8::Integer::New(2003)));
+  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
+  CHECK_EQ(2003, obj->Get(empty)->Int32Value());
+
+  i::Heap::CollectAllGarbage();
+
+  // Add another property and delete it afterwards to force the object in
+  // slow case.
+  CHECK(obj->Set(prop_name, v8::Integer::New(2008)));
+  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
+  CHECK_EQ(2008, obj->Get(prop_name)->Int32Value());
+  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
+  CHECK(obj->Delete(prop_name));
+  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
+
+  i::Heap::CollectAllGarbage();
+
+  CHECK(obj->DeleteHiddenValue(key));
+  CHECK(obj->GetHiddenValue(key).IsEmpty());
+}
+
+
+THREADED_TEST(External) {
+  v8::HandleScope scope;
+  int x = 3;
+  Local<v8::External> ext = v8::External::New(&x);
+  LocalContext env;
+  env->Global()->Set(v8_str("ext"), ext);
+  Local<Value> reext_obj = Script::Compile(v8_str("this.ext"))->Run();
+  v8::Handle<v8::External> reext = v8::Handle<v8::External>::Cast(reext_obj);
+  int* ptr = static_cast<int*>(reext->Value());
+  CHECK_EQ(x, 3);
+  *ptr = 10;
+  CHECK_EQ(x, 10);
+
+  // Make sure unaligned pointers are wrapped properly.
+  char* data = i::StrDup("0123456789");
+  Local<v8::Value> zero = v8::External::Wrap(&data[0]);
+  Local<v8::Value> one = v8::External::Wrap(&data[1]);
+  Local<v8::Value> two = v8::External::Wrap(&data[2]);
+  Local<v8::Value> three = v8::External::Wrap(&data[3]);
+
+  char* char_ptr = reinterpret_cast<char*>(v8::External::Unwrap(zero));
+  CHECK_EQ('0', *char_ptr);
+  char_ptr = reinterpret_cast<char*>(v8::External::Unwrap(one));
+  CHECK_EQ('1', *char_ptr);
+  char_ptr = reinterpret_cast<char*>(v8::External::Unwrap(two));
+  CHECK_EQ('2', *char_ptr);
+  char_ptr = reinterpret_cast<char*>(v8::External::Unwrap(three));
+  CHECK_EQ('3', *char_ptr);
+  i::DeleteArray(data);
+}
+
+
+THREADED_TEST(GlobalHandle) {
+  v8::Persistent<String> global;
+  {
+    v8::HandleScope scope;
+    Local<String> str = v8_str("str");
+    global = v8::Persistent<String>::New(str);
+  }
+  CHECK_EQ(global->Length(), 3);
+  global.Dispose();
+}
+
+
+THREADED_TEST(ScriptException) {
+  v8::HandleScope scope;
+  LocalContext env;
+  Local<Script> script = Script::Compile(v8_str("throw 'panama!';"));
+  v8::TryCatch try_catch;
+  Local<Value> result = script->Run();
+  CHECK(result.IsEmpty());
+  CHECK(try_catch.HasCaught());
+  String::AsciiValue exception_value(try_catch.Exception());
+  CHECK_EQ(*exception_value, "panama!");
+}
+
+
+bool message_received;
+
+
+static void check_message(v8::Handle<v8::Message> message,
+                          v8::Handle<Value> data) {
+  CHECK_EQ(5.76, data->NumberValue());
+  CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
+  message_received = true;
+}
+
+
+THREADED_TEST(MessageHandlerData) {
+  message_received = false;
+  v8::HandleScope scope;
+  CHECK(!message_received);
+  v8::V8::AddMessageListener(check_message, v8_num(5.76));
+  LocalContext context;
+  v8::ScriptOrigin origin =
+      v8::ScriptOrigin(v8_str("6.75"));
+  Script::Compile(v8_str("throw 'error'"), &origin)->Run();
+  CHECK(message_received);
+  // clear out the message listener
+  v8::V8::RemoveMessageListeners(check_message);
+}
+
+
+THREADED_TEST(GetSetProperty) {
+  v8::HandleScope scope;
+  LocalContext context;
+  context->Global()->Set(v8_str("foo"), v8_num(14));
+  context->Global()->Set(v8_str("12"), v8_num(92));
+  context->Global()->Set(v8::Integer::New(16), v8_num(32));
+  context->Global()->Set(v8_num(13), v8_num(56));
+  Local<Value> foo = Script::Compile(v8_str("this.foo"))->Run();
+  CHECK_EQ(14, foo->Int32Value());
+  Local<Value> twelve = Script::Compile(v8_str("this[12]"))->Run();
+  CHECK_EQ(92, twelve->Int32Value());
+  Local<Value> sixteen = Script::Compile(v8_str("this[16]"))->Run();
+  CHECK_EQ(32, sixteen->Int32Value());
+  Local<Value> thirteen = Script::Compile(v8_str("this[13]"))->Run();
+  CHECK_EQ(56, thirteen->Int32Value());
+  CHECK_EQ(92, context->Global()->Get(v8::Integer::New(12))->Int32Value());
+  CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
+  CHECK_EQ(92, context->Global()->Get(v8_num(12))->Int32Value());
+  CHECK_EQ(32, context->Global()->Get(v8::Integer::New(16))->Int32Value());
+  CHECK_EQ(32, context->Global()->Get(v8_str("16"))->Int32Value());
+  CHECK_EQ(32, context->Global()->Get(v8_num(16))->Int32Value());
+  CHECK_EQ(56, context->Global()->Get(v8::Integer::New(13))->Int32Value());
+  CHECK_EQ(56, context->Global()->Get(v8_str("13"))->Int32Value());
+  CHECK_EQ(56, context->Global()->Get(v8_num(13))->Int32Value());
+}
+
+
+THREADED_TEST(PropertyAttributes) {
+  v8::HandleScope scope;
+  LocalContext context;
+  // read-only
+  Local<String> prop = v8_str("read_only");
+  context->Global()->Set(prop, v8_num(7), v8::ReadOnly);
+  CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
+  Script::Compile(v8_str("read_only = 9"))->Run();
+  CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
+  context->Global()->Set(prop, v8_num(10));
+  CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
+  // dont-delete
+  prop = v8_str("dont_delete");
+  context->Global()->Set(prop, v8_num(13), v8::DontDelete);
+  CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
+  Script::Compile(v8_str("delete dont_delete"))->Run();
+  CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
+}
+
+
+THREADED_TEST(Array) {
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<v8::Array> array = v8::Array::New();
+  CHECK_EQ(0, array->Length());
+  CHECK(array->Get(v8::Integer::New(0))->IsUndefined());
+  CHECK(!array->Has(0));
+  CHECK(array->Get(v8::Integer::New(100))->IsUndefined());
+  CHECK(!array->Has(100));
+  array->Set(v8::Integer::New(2), v8_num(7));
+  CHECK_EQ(3, array->Length());
+  CHECK(!array->Has(0));
+  CHECK(!array->Has(1));
+  CHECK(array->Has(2));
+  CHECK_EQ(7, array->Get(v8::Integer::New(2))->Int32Value());
+  Local<Value> obj = Script::Compile(v8_str("[1, 2, 3]"))->Run();
+  Local<v8::Array> arr = Local<v8::Array>::Cast(obj);
+  CHECK_EQ(3, arr->Length());
+  CHECK_EQ(1, arr->Get(v8::Integer::New(0))->Int32Value());
+  CHECK_EQ(2, arr->Get(v8::Integer::New(1))->Int32Value());
+  CHECK_EQ(3, arr->Get(v8::Integer::New(2))->Int32Value());
+}
+
+
+v8::Handle<Value> HandleF(const v8::Arguments& args) {
+  v8::HandleScope scope;
+  ApiTestFuzzer::Fuzz();
+  Local<v8::Array> result = v8::Array::New(args.Length());
+  for (int i = 0; i < args.Length(); i++)
+    result->Set(v8::Integer::New(i), args[i]);
+  return scope.Close(result);
+}
+
+
+THREADED_TEST(Vector) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> global = ObjectTemplate::New();
+  global->Set(v8_str("f"), v8::FunctionTemplate::New(HandleF));
+  LocalContext context(0, global);
+
+  const char* fun = "f()";
+  Local<v8::Array> a0 =
+      Local<v8::Array>::Cast(Script::Compile(String::New(fun))->Run());
+  CHECK_EQ(0, a0->Length());
+
+  const char* fun2 = "f(11)";
+  Local<v8::Array> a1 =
+      Local<v8::Array>::Cast(Script::Compile(String::New(fun2))->Run());
+  CHECK_EQ(1, a1->Length());
+  CHECK_EQ(11, a1->Get(v8::Integer::New(0))->Int32Value());
+
+  const char* fun3 = "f(12, 13)";
+  Local<v8::Array> a2 =
+      Local<v8::Array>::Cast(Script::Compile(String::New(fun3))->Run());
+  CHECK_EQ(2, a2->Length());
+  CHECK_EQ(12, a2->Get(v8::Integer::New(0))->Int32Value());
+  CHECK_EQ(13, a2->Get(v8::Integer::New(1))->Int32Value());
+
+  const char* fun4 = "f(14, 15, 16)";
+  Local<v8::Array> a3 =
+      Local<v8::Array>::Cast(Script::Compile(String::New(fun4))->Run());
+  CHECK_EQ(3, a3->Length());
+  CHECK_EQ(14, a3->Get(v8::Integer::New(0))->Int32Value());
+  CHECK_EQ(15, a3->Get(v8::Integer::New(1))->Int32Value());
+  CHECK_EQ(16, a3->Get(v8::Integer::New(2))->Int32Value());
+
+  const char* fun5 = "f(17, 18, 19, 20)";
+  Local<v8::Array> a4 =
+      Local<v8::Array>::Cast(Script::Compile(String::New(fun5))->Run());
+  CHECK_EQ(4, a4->Length());
+  CHECK_EQ(17, a4->Get(v8::Integer::New(0))->Int32Value());
+  CHECK_EQ(18, a4->Get(v8::Integer::New(1))->Int32Value());
+  CHECK_EQ(19, a4->Get(v8::Integer::New(2))->Int32Value());
+  CHECK_EQ(20, a4->Get(v8::Integer::New(3))->Int32Value());
+}
+
+
+THREADED_TEST(FunctionCall) {
+  v8::HandleScope scope;
+  LocalContext context;
+  CompileRun(
+    "function Foo() {"
+    "  var result = [];"
+    "  for (var i = 0; i < arguments.length; i++) {"
+    "    result.push(arguments[i]);"
+    "  }"
+    "  return result;"
+    "}");
+  Local<Function> Foo =
+      Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
+
+  v8::Handle<Value>* args0 = NULL;
+  Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
+  CHECK_EQ(0, a0->Length());
+
+  v8::Handle<Value> args1[] = { v8_num(1.1) };
+  Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->Call(Foo, 1, args1));
+  CHECK_EQ(1, a1->Length());
+  CHECK_EQ(1.1, a1->Get(v8::Integer::New(0))->NumberValue());
+
+  v8::Handle<Value> args2[] = { v8_num(2.2),
+                                v8_num(3.3) };
+  Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->Call(Foo, 2, args2));
+  CHECK_EQ(2, a2->Length());
+  CHECK_EQ(2.2, a2->Get(v8::Integer::New(0))->NumberValue());
+  CHECK_EQ(3.3, a2->Get(v8::Integer::New(1))->NumberValue());
+
+  v8::Handle<Value> args3[] = { v8_num(4.4),
+                                v8_num(5.5),
+                                v8_num(6.6) };
+  Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->Call(Foo, 3, args3));
+  CHECK_EQ(3, a3->Length());
+  CHECK_EQ(4.4, a3->Get(v8::Integer::New(0))->NumberValue());
+  CHECK_EQ(5.5, a3->Get(v8::Integer::New(1))->NumberValue());
+  CHECK_EQ(6.6, a3->Get(v8::Integer::New(2))->NumberValue());
+
+  v8::Handle<Value> args4[] = { v8_num(7.7),
+                                v8_num(8.8),
+                                v8_num(9.9),
+                                v8_num(10.11) };
+  Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->Call(Foo, 4, args4));
+  CHECK_EQ(4, a4->Length());
+  CHECK_EQ(7.7, a4->Get(v8::Integer::New(0))->NumberValue());
+  CHECK_EQ(8.8, a4->Get(v8::Integer::New(1))->NumberValue());
+  CHECK_EQ(9.9, a4->Get(v8::Integer::New(2))->NumberValue());
+  CHECK_EQ(10.11, a4->Get(v8::Integer::New(3))->NumberValue());
+}
+
+
+static const char* js_code_causing_out_of_memory =
+    "var a = new Array(); while(true) a.push(a);";
+
+
+// These tests run for a long time and prevent us from running tests
+// that come after them so they cannot run in parallel.
+TEST(OutOfMemory) {
+  // It's not possible to read a snapshot into a heap with different dimensions.
+  if (v8::internal::Snapshot::IsEnabled()) return;
+  // Set heap limits.
+  static const int K = 1024;
+  v8::ResourceConstraints constraints;
+  constraints.set_max_young_space_size(256 * K);
+  constraints.set_max_old_space_size(4 * K * K);
+  v8::SetResourceConstraints(&constraints);
+
+  // Execute a script that causes out of memory.
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::V8::IgnoreOutOfMemoryException();
+  Local<Script> script =
+      Script::Compile(String::New(js_code_causing_out_of_memory));
+  Local<Value> result = script->Run();
+
+  // Check for out of memory state.
+  CHECK(result.IsEmpty());
+  CHECK(context->HasOutOfMemoryException());
+}
+
+
+v8::Handle<Value> ProvokeOutOfMemory(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<Script> script =
+      Script::Compile(String::New(js_code_causing_out_of_memory));
+  Local<Value> result = script->Run();
+
+  // Check for out of memory state.
+  CHECK(result.IsEmpty());
+  CHECK(context->HasOutOfMemoryException());
+
+  return result;
+}
+
+
+TEST(OutOfMemoryNested) {
+  // It's not possible to read a snapshot into a heap with different dimensions.
+  if (v8::internal::Snapshot::IsEnabled()) return;
+  // Set heap limits.
+  static const int K = 1024;
+  v8::ResourceConstraints constraints;
+  constraints.set_max_young_space_size(256 * K);
+  constraints.set_max_old_space_size(4 * K * K);
+  v8::SetResourceConstraints(&constraints);
+
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("ProvokeOutOfMemory"),
+             v8::FunctionTemplate::New(ProvokeOutOfMemory));
+  LocalContext context(0, templ);
+  v8::V8::IgnoreOutOfMemoryException();
+  Local<Value> result = CompileRun(
+    "var thrown = false;"
+    "try {"
+    "  ProvokeOutOfMemory();"
+    "} catch (e) {"
+    "  thrown = true;"
+    "}");
+  // Check for out of memory state.
+  CHECK(result.IsEmpty());
+  CHECK(context->HasOutOfMemoryException());
+}
+
+
+TEST(HugeConsStringOutOfMemory) {
+  // It's not possible to read a snapshot into a heap with different dimensions.
+  if (v8::internal::Snapshot::IsEnabled()) return;
+  v8::HandleScope scope;
+  LocalContext context;
+  // Set heap limits.
+  static const int K = 1024;
+  v8::ResourceConstraints constraints;
+  constraints.set_max_young_space_size(256 * K);
+  constraints.set_max_old_space_size(2 * K * K);
+  v8::SetResourceConstraints(&constraints);
+
+  // Execute a script that causes out of memory.
+  v8::V8::IgnoreOutOfMemoryException();
+
+  // Build huge string. This should fail with out of memory exception.
+  Local<Value> result = CompileRun(
+    "var str = Array.prototype.join.call({length: 513}, \"A\").toUpperCase();"
+    "for (var i = 0; i < 21; i++) { str = str + str; }");
+
+  // Check for out of memory state.
+  CHECK(result.IsEmpty());
+  CHECK(context->HasOutOfMemoryException());
+}
+
+
+THREADED_TEST(ConstructCall) {
+  v8::HandleScope scope;
+  LocalContext context;
+  CompileRun(
+    "function Foo() {"
+    "  var result = [];"
+    "  for (var i = 0; i < arguments.length; i++) {"
+    "    result.push(arguments[i]);"
+    "  }"
+    "  return result;"
+    "}");
+  Local<Function> Foo =
+      Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
+
+  v8::Handle<Value>* args0 = NULL;
+  Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->NewInstance(0, args0));
+  CHECK_EQ(0, a0->Length());
+
+  v8::Handle<Value> args1[] = { v8_num(1.1) };
+  Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->NewInstance(1, args1));
+  CHECK_EQ(1, a1->Length());
+  CHECK_EQ(1.1, a1->Get(v8::Integer::New(0))->NumberValue());
+
+  v8::Handle<Value> args2[] = { v8_num(2.2),
+                                v8_num(3.3) };
+  Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->NewInstance(2, args2));
+  CHECK_EQ(2, a2->Length());
+  CHECK_EQ(2.2, a2->Get(v8::Integer::New(0))->NumberValue());
+  CHECK_EQ(3.3, a2->Get(v8::Integer::New(1))->NumberValue());
+
+  v8::Handle<Value> args3[] = { v8_num(4.4),
+                                v8_num(5.5),
+                                v8_num(6.6) };
+  Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->NewInstance(3, args3));
+  CHECK_EQ(3, a3->Length());
+  CHECK_EQ(4.4, a3->Get(v8::Integer::New(0))->NumberValue());
+  CHECK_EQ(5.5, a3->Get(v8::Integer::New(1))->NumberValue());
+  CHECK_EQ(6.6, a3->Get(v8::Integer::New(2))->NumberValue());
+
+  v8::Handle<Value> args4[] = { v8_num(7.7),
+                                v8_num(8.8),
+                                v8_num(9.9),
+                                v8_num(10.11) };
+  Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->NewInstance(4, args4));
+  CHECK_EQ(4, a4->Length());
+  CHECK_EQ(7.7, a4->Get(v8::Integer::New(0))->NumberValue());
+  CHECK_EQ(8.8, a4->Get(v8::Integer::New(1))->NumberValue());
+  CHECK_EQ(9.9, a4->Get(v8::Integer::New(2))->NumberValue());
+  CHECK_EQ(10.11, a4->Get(v8::Integer::New(3))->NumberValue());
+}
+
+
+static void CheckUncle(v8::TryCatch* try_catch) {
+  CHECK(try_catch->HasCaught());
+  String::AsciiValue str_value(try_catch->Exception());
+  CHECK_EQ(*str_value, "uncle?");
+  try_catch->Reset();
+}
+
+
+THREADED_TEST(ConversionException) {
+  v8::HandleScope scope;
+  LocalContext env;
+  CompileRun(
+    "function TestClass() { };"
+    "TestClass.prototype.toString = function () { throw 'uncle?'; };"
+    "var obj = new TestClass();");
+  Local<Value> obj = env->Global()->Get(v8_str("obj"));
+
+  v8::TryCatch try_catch;
+
+  Local<Value> to_string_result = obj->ToString();
+  CHECK(to_string_result.IsEmpty());
+  CheckUncle(&try_catch);
+
+  Local<Value> to_number_result = obj->ToNumber();
+  CHECK(to_number_result.IsEmpty());
+  CheckUncle(&try_catch);
+
+  Local<Value> to_integer_result = obj->ToInteger();
+  CHECK(to_integer_result.IsEmpty());
+  CheckUncle(&try_catch);
+
+  Local<Value> to_uint32_result = obj->ToUint32();
+  CHECK(to_uint32_result.IsEmpty());
+  CheckUncle(&try_catch);
+
+  Local<Value> to_int32_result = obj->ToInt32();
+  CHECK(to_int32_result.IsEmpty());
+  CheckUncle(&try_catch);
+
+  Local<Value> to_object_result = v8::Undefined()->ToObject();
+  CHECK(to_object_result.IsEmpty());
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+
+  int32_t int32_value = obj->Int32Value();
+  CHECK_EQ(0, int32_value);
+  CheckUncle(&try_catch);
+
+  uint32_t uint32_value = obj->Uint32Value();
+  CHECK_EQ(0, uint32_value);
+  CheckUncle(&try_catch);
+
+  double number_value = obj->NumberValue();
+  CHECK_NE(0, IsNaN(number_value));
+  CheckUncle(&try_catch);
+
+  int64_t integer_value = obj->IntegerValue();
+  CHECK_EQ(0.0, static_cast<double>(integer_value));
+  CheckUncle(&try_catch);
+}
+
+
+v8::Handle<Value> ThrowFromC(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  return v8::ThrowException(v8_str("konto"));
+}
+
+
+v8::Handle<Value> CCatcher(const v8::Arguments& args) {
+  if (args.Length() < 1) return v8::Boolean::New(false);
+  v8::HandleScope scope;
+  v8::TryCatch try_catch;
+  Local<Value> result = v8::Script::Compile(args[0]->ToString())->Run();
+  CHECK(!try_catch.HasCaught() || result.IsEmpty());
+  return v8::Boolean::New(try_catch.HasCaught());
+}
+
+
+THREADED_TEST(APICatch) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("ThrowFromC"),
+             v8::FunctionTemplate::New(ThrowFromC));
+  LocalContext context(0, templ);
+  CompileRun(
+    "var thrown = false;"
+    "try {"
+    "  ThrowFromC();"
+    "} catch (e) {"
+    "  thrown = true;"
+    "}");
+  Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
+  CHECK(thrown->BooleanValue());
+}
+
+
+THREADED_TEST(APIThrowTryCatch) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("ThrowFromC"),
+             v8::FunctionTemplate::New(ThrowFromC));
+  LocalContext context(0, templ);
+  v8::TryCatch try_catch;
+  CompileRun("ThrowFromC();");
+  CHECK(try_catch.HasCaught());
+}
+
+
+// Test that a try-finally block doesn't shadow a try-catch block
+// when setting up an external handler.
+//
+// BUG(271): Some of the exception propagation does not work on the
+// ARM simulator because the simulator separates the C++ stack and the
+// JS stack.  This test therefore fails on the simulator.  The test is
+// not threaded to allow the threading tests to run on the simulator.
+TEST(TryCatchInTryFinally) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("CCatcher"),
+             v8::FunctionTemplate::New(CCatcher));
+  LocalContext context(0, templ);
+  Local<Value> result = CompileRun("try {"
+                                   "  try {"
+                                   "    CCatcher('throw 7;');"
+                                   "  } finally {"
+                                   "  }"
+                                   "} catch (e) {"
+                                   "}");
+  CHECK(result->IsTrue());
+}
+
+
+static void receive_message(v8::Handle<v8::Message> message,
+                            v8::Handle<v8::Value> data) {
+  message->Get();
+  message_received = true;
+}
+
+
+TEST(APIThrowMessage) {
+  message_received = false;
+  v8::HandleScope scope;
+  v8::V8::AddMessageListener(receive_message);
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("ThrowFromC"),
+             v8::FunctionTemplate::New(ThrowFromC));
+  LocalContext context(0, templ);
+  CompileRun("ThrowFromC();");
+  CHECK(message_received);
+  v8::V8::RemoveMessageListeners(check_message);
+}
+
+
+TEST(APIThrowMessageAndVerboseTryCatch) {
+  message_received = false;
+  v8::HandleScope scope;
+  v8::V8::AddMessageListener(receive_message);
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("ThrowFromC"),
+             v8::FunctionTemplate::New(ThrowFromC));
+  LocalContext context(0, templ);
+  v8::TryCatch try_catch;
+  try_catch.SetVerbose(true);
+  Local<Value> result = CompileRun("ThrowFromC();");
+  CHECK(try_catch.HasCaught());
+  CHECK(result.IsEmpty());
+  CHECK(message_received);
+  v8::V8::RemoveMessageListeners(check_message);
+}
+
+
+THREADED_TEST(ExternalScriptException) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("ThrowFromC"),
+             v8::FunctionTemplate::New(ThrowFromC));
+  LocalContext context(0, templ);
+
+  v8::TryCatch try_catch;
+  Local<Script> script
+      = Script::Compile(v8_str("ThrowFromC(); throw 'panama';"));
+  Local<Value> result = script->Run();
+  CHECK(result.IsEmpty());
+  CHECK(try_catch.HasCaught());
+  String::AsciiValue exception_value(try_catch.Exception());
+  CHECK_EQ("konto", *exception_value);
+}
+
+
+
+v8::Handle<Value> CThrowCountDown(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  CHECK_EQ(4, args.Length());
+  int count = args[0]->Int32Value();
+  int cInterval = args[2]->Int32Value();
+  if (count == 0) {
+    return v8::ThrowException(v8_str("FromC"));
+  } else {
+    Local<v8::Object> global = Context::GetCurrent()->Global();
+    Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
+    v8::Handle<Value> argv[] = { v8_num(count - 1),
+                                 args[1],
+                                 args[2],
+                                 args[3] };
+    if (count % cInterval == 0) {
+      v8::TryCatch try_catch;
+      Local<Value> result =
+          v8::Handle<Function>::Cast(fun)->Call(global, 4, argv);
+      int expected = args[3]->Int32Value();
+      if (try_catch.HasCaught()) {
+        CHECK_EQ(expected, count);
+        CHECK(result.IsEmpty());
+        CHECK(!i::Top::has_scheduled_exception());
+      } else {
+        CHECK_NE(expected, count);
+      }
+      return result;
+    } else {
+      return v8::Handle<Function>::Cast(fun)->Call(global, 4, argv);
+    }
+  }
+}
+
+
+v8::Handle<Value> JSCheck(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  CHECK_EQ(3, args.Length());
+  bool equality = args[0]->BooleanValue();
+  int count = args[1]->Int32Value();
+  int expected = args[2]->Int32Value();
+  if (equality) {
+    CHECK_EQ(count, expected);
+  } else {
+    CHECK_NE(count, expected);
+  }
+  return v8::Undefined();
+}
+
+
+THREADED_TEST(EvalInTryFinally) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::TryCatch try_catch;
+  CompileRun("(function() {"
+             "  try {"
+             "    eval('asldkf (*&^&*^');"
+             "  } finally {"
+             "    return;"
+             "  }"
+             "})()");
+  CHECK(!try_catch.HasCaught());
+}
+
+
+// This test works by making a stack of alternating JavaScript and C
+// activations.  These activations set up exception handlers with regular
+// intervals, one interval for C activations and another for JavaScript
+// activations.  When enough activations have been created an exception is
+// thrown and we check that the right activation catches the exception and that
+// no other activations do.  The right activation is always the topmost one with
+// a handler, regardless of whether it is in JavaScript or C.
+//
+// The notation used to describe a test case looks like this:
+//
+//    *JS[4] *C[3] @JS[2] C[1] JS[0]
+//
+// Each entry is an activation, either JS or C.  The index is the count at that
+// level.  Stars identify activations with exception handlers, the @ identifies
+// the exception handler that should catch the exception.
+//
+// BUG(271): Some of the exception propagation does not work on the
+// ARM simulator because the simulator separates the C++ stack and the
+// JS stack.  This test therefore fails on the simulator.  The test is
+// not threaded to allow the threading tests to run on the simulator.
+TEST(ExceptionOrder) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("check"), v8::FunctionTemplate::New(JSCheck));
+  templ->Set(v8_str("CThrowCountDown"),
+             v8::FunctionTemplate::New(CThrowCountDown));
+  LocalContext context(0, templ);
+  CompileRun(
+    "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
+    "  if (count == 0) throw 'FromJS';"
+    "  if (count % jsInterval == 0) {"
+    "    try {"
+    "      var value = CThrowCountDown(count - 1,"
+    "                                  jsInterval,"
+    "                                  cInterval,"
+    "                                  expected);"
+    "      check(false, count, expected);"
+    "      return value;"
+    "    } catch (e) {"
+    "      check(true, count, expected);"
+    "    }"
+    "  } else {"
+    "    return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
+    "  }"
+    "}");
+  Local<Function> fun =
+      Local<Function>::Cast(context->Global()->Get(v8_str("JSThrowCountDown")));
+
+  const int argc = 4;
+  //                             count      jsInterval cInterval  expected
+
+  // *JS[4] *C[3] @JS[2] C[1] JS[0]
+  v8::Handle<Value> a0[argc] = { v8_num(4), v8_num(2), v8_num(3), v8_num(2) };
+  fun->Call(fun, argc, a0);
+
+  // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
+  v8::Handle<Value> a1[argc] = { v8_num(5), v8_num(6), v8_num(1), v8_num(2) };
+  fun->Call(fun, argc, a1);
+
+  // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
+  v8::Handle<Value> a2[argc] = { v8_num(6), v8_num(7), v8_num(5), v8_num(5) };
+  fun->Call(fun, argc, a2);
+
+  // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
+  v8::Handle<Value> a3[argc] = { v8_num(6), v8_num(6), v8_num(7), v8_num(6) };
+  fun->Call(fun, argc, a3);
+
+  // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
+  v8::Handle<Value> a4[argc] = { v8_num(6), v8_num(4), v8_num(5), v8_num(4) };
+  fun->Call(fun, argc, a4);
+
+  // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
+  v8::Handle<Value> a5[argc] = { v8_num(6), v8_num(4), v8_num(3), v8_num(3) };
+  fun->Call(fun, argc, a5);
+}
+
+
+v8::Handle<Value> ThrowValue(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  CHECK_EQ(1, args.Length());
+  return v8::ThrowException(args[0]);
+}
+
+
+THREADED_TEST(ThrowValues) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(ThrowValue));
+  LocalContext context(0, templ);
+  v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
+    "function Run(obj) {"
+    "  try {"
+    "    Throw(obj);"
+    "  } catch (e) {"
+    "    return e;"
+    "  }"
+    "  return 'no exception';"
+    "}"
+    "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
+  CHECK_EQ(5, result->Length());
+  CHECK(result->Get(v8::Integer::New(0))->IsString());
+  CHECK(result->Get(v8::Integer::New(1))->IsNumber());
+  CHECK_EQ(1, result->Get(v8::Integer::New(1))->Int32Value());
+  CHECK(result->Get(v8::Integer::New(2))->IsNumber());
+  CHECK_EQ(0, result->Get(v8::Integer::New(2))->Int32Value());
+  CHECK(result->Get(v8::Integer::New(3))->IsNull());
+  CHECK(result->Get(v8::Integer::New(4))->IsUndefined());
+}
+
+
+THREADED_TEST(CatchZero) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::TryCatch try_catch;
+  CHECK(!try_catch.HasCaught());
+  Script::Compile(v8_str("throw 10"))->Run();
+  CHECK(try_catch.HasCaught());
+  CHECK_EQ(10, try_catch.Exception()->Int32Value());
+  try_catch.Reset();
+  CHECK(!try_catch.HasCaught());
+  Script::Compile(v8_str("throw 0"))->Run();
+  CHECK(try_catch.HasCaught());
+  CHECK_EQ(0, try_catch.Exception()->Int32Value());
+}
+
+
+THREADED_TEST(CatchExceptionFromWith) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::TryCatch try_catch;
+  CHECK(!try_catch.HasCaught());
+  Script::Compile(v8_str("var o = {}; with (o) { throw 42; }"))->Run();
+  CHECK(try_catch.HasCaught());
+}
+
+
+THREADED_TEST(Equality) {
+  v8::HandleScope scope;
+  LocalContext context;
+  // Check that equality works at all before relying on CHECK_EQ
+  CHECK(v8_str("a")->Equals(v8_str("a")));
+  CHECK(!v8_str("a")->Equals(v8_str("b")));
+
+  CHECK_EQ(v8_str("a"), v8_str("a"));
+  CHECK_NE(v8_str("a"), v8_str("b"));
+  CHECK_EQ(v8_num(1), v8_num(1));
+  CHECK_EQ(v8_num(1.00), v8_num(1));
+  CHECK_NE(v8_num(1), v8_num(2));
+
+  // Assume String is not symbol.
+  CHECK(v8_str("a")->StrictEquals(v8_str("a")));
+  CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
+  CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
+  CHECK(v8_num(1)->StrictEquals(v8_num(1)));
+  CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
+  CHECK(v8_num(0)->StrictEquals(v8_num(-0)));
+  Local<Value> not_a_number = v8_num(i::OS::nan_value());
+  CHECK(!not_a_number->StrictEquals(not_a_number));
+  CHECK(v8::False()->StrictEquals(v8::False()));
+  CHECK(!v8::False()->StrictEquals(v8::Undefined()));
+
+  v8::Handle<v8::Object> obj = v8::Object::New();
+  v8::Persistent<v8::Object> alias = v8::Persistent<v8::Object>::New(obj);
+  CHECK(alias->StrictEquals(obj));
+  alias.Dispose();
+}
+
+
+THREADED_TEST(MultiRun) {
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<Script> script = Script::Compile(v8_str("x"));
+  for (int i = 0; i < 10; i++)
+    script->Run();
+}
+
+
+static v8::Handle<Value> GetXValue(Local<String> name,
+                                   const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK_EQ(info.Data(), v8_str("donut"));
+  CHECK_EQ(name, v8_str("x"));
+  return name;
+}
+
+
+THREADED_TEST(SimplePropertyRead) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
+  LocalContext context;
+  context->Global()->Set(v8_str("obj"), templ->NewInstance());
+  Local<Script> script = Script::Compile(v8_str("obj.x"));
+  for (int i = 0; i < 10; i++) {
+    Local<Value> result = script->Run();
+    CHECK_EQ(result, v8_str("x"));
+  }
+}
+
+
+v8::Persistent<Value> xValue;
+
+
+static void SetXValue(Local<String> name,
+                      Local<Value> value,
+                      const AccessorInfo& info) {
+  CHECK_EQ(value, v8_num(4));
+  CHECK_EQ(info.Data(), v8_str("donut"));
+  CHECK_EQ(name, v8_str("x"));
+  CHECK(xValue.IsEmpty());
+  xValue = v8::Persistent<Value>::New(value);
+}
+
+
+THREADED_TEST(SimplePropertyWrite) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
+  LocalContext context;
+  context->Global()->Set(v8_str("obj"), templ->NewInstance());
+  Local<Script> script = Script::Compile(v8_str("obj.x = 4"));
+  for (int i = 0; i < 10; i++) {
+    CHECK(xValue.IsEmpty());
+    script->Run();
+    CHECK_EQ(v8_num(4), xValue);
+    xValue.Dispose();
+    xValue = v8::Persistent<Value>();
+  }
+}
+
+
+static v8::Handle<Value> XPropertyGetter(Local<String> property,
+                                         const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(info.Data()->IsUndefined());
+  return property;
+}
+
+
+THREADED_TEST(NamedInterceporPropertyRead) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(XPropertyGetter);
+  LocalContext context;
+  context->Global()->Set(v8_str("obj"), templ->NewInstance());
+  Local<Script> script = Script::Compile(v8_str("obj.x"));
+  for (int i = 0; i < 10; i++) {
+    Local<Value> result = script->Run();
+    CHECK_EQ(result, v8_str("x"));
+  }
+}
+
+THREADED_TEST(MultiContexts) {
+  v8::HandleScope scope;
+  v8::Handle<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("dummy"), v8::FunctionTemplate::New(DummyCallHandler));
+
+  Local<String> password = v8_str("Password");
+
+  // Create an environment
+  LocalContext context0(0, templ);
+  context0->SetSecurityToken(password);
+  v8::Handle<v8::Object> global0 = context0->Global();
+  global0->Set(v8_str("custom"), v8_num(1234));
+  CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
+
+  // Create an independent environment
+  LocalContext context1(0, templ);
+  context1->SetSecurityToken(password);
+  v8::Handle<v8::Object> global1 = context1->Global();
+  global1->Set(v8_str("custom"), v8_num(1234));
+  CHECK_NE(global0, global1);
+  CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
+  CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
+
+  // Now create a new context with the old global
+  LocalContext context2(0, templ, global1);
+  context2->SetSecurityToken(password);
+  v8::Handle<v8::Object> global2 = context2->Global();
+  CHECK_EQ(global1, global2);
+  CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
+  CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
+}
+
+
+THREADED_TEST(FunctionPrototypeAcrossContexts) {
+  // Make sure that functions created by cloning boilerplates cannot
+  // communicate through their __proto__ field.
+
+  v8::HandleScope scope;
+
+  LocalContext env0;
+  v8::Handle<v8::Object> global0 =
+      env0->Global();
+  v8::Handle<v8::Object> object0 =
+      v8::Handle<v8::Object>::Cast(global0->Get(v8_str("Object")));
+  v8::Handle<v8::Object> tostring0 =
+      v8::Handle<v8::Object>::Cast(object0->Get(v8_str("toString")));
+  v8::Handle<v8::Object> proto0 =
+      v8::Handle<v8::Object>::Cast(tostring0->Get(v8_str("__proto__")));
+  proto0->Set(v8_str("custom"), v8_num(1234));
+
+  LocalContext env1;
+  v8::Handle<v8::Object> global1 =
+      env1->Global();
+  v8::Handle<v8::Object> object1 =
+      v8::Handle<v8::Object>::Cast(global1->Get(v8_str("Object")));
+  v8::Handle<v8::Object> tostring1 =
+      v8::Handle<v8::Object>::Cast(object1->Get(v8_str("toString")));
+  v8::Handle<v8::Object> proto1 =
+      v8::Handle<v8::Object>::Cast(tostring1->Get(v8_str("__proto__")));
+  CHECK(!proto1->Has(v8_str("custom")));
+}
+
+
+THREADED_TEST(Regress892105) {
+  // Make sure that object and array literals created by cloning
+  // boilerplates cannot communicate through their __proto__
+  // field. This is rather difficult to check, but we try to add stuff
+  // to Object.prototype and Array.prototype and create a new
+  // environment. This should succeed.
+
+  v8::HandleScope scope;
+
+  Local<String> source = v8_str("Object.prototype.obj = 1234;"
+                                "Array.prototype.arr = 4567;"
+                                "8901");
+
+  LocalContext env0;
+  Local<Script> script0 = Script::Compile(source);
+  CHECK_EQ(8901.0, script0->Run()->NumberValue());
+
+  LocalContext env1;
+  Local<Script> script1 = Script::Compile(source);
+  CHECK_EQ(8901.0, script1->Run()->NumberValue());
+}
+
+
+static void ExpectString(const char* code, const char* expected) {
+  Local<Value> result = CompileRun(code);
+  CHECK(result->IsString());
+  String::AsciiValue ascii(result);
+  CHECK_EQ(0, strcmp(*ascii, expected));
+}
+
+
+static void ExpectBoolean(const char* code, bool expected) {
+  Local<Value> result = CompileRun(code);
+  CHECK(result->IsBoolean());
+  CHECK_EQ(expected, result->BooleanValue());
+}
+
+
+static void ExpectObject(const char* code, Local<Value> expected) {
+  Local<Value> result = CompileRun(code);
+  CHECK(result->Equals(expected));
+}
+
+
+THREADED_TEST(UndetectableObject) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  Local<v8::FunctionTemplate> desc =
+      v8::FunctionTemplate::New(0, v8::Handle<Value>());
+  desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
+
+  Local<v8::Object> obj = desc->GetFunction()->NewInstance();
+  env->Global()->Set(v8_str("undetectable"), obj);
+
+  ExpectString("undetectable.toString()", "[object Object]");
+  ExpectString("typeof undetectable", "undefined");
+  ExpectString("typeof(undetectable)", "undefined");
+  ExpectBoolean("typeof undetectable == 'undefined'", true);
+  ExpectBoolean("typeof undetectable == 'object'", false);
+  ExpectBoolean("if (undetectable) { true; } else { false; }", false);
+  ExpectBoolean("!undetectable", true);
+
+  ExpectObject("true&&undetectable", obj);
+  ExpectBoolean("false&&undetectable", false);
+  ExpectBoolean("true||undetectable", true);
+  ExpectObject("false||undetectable", obj);
+
+  ExpectObject("undetectable&&true", obj);
+  ExpectObject("undetectable&&false", obj);
+  ExpectBoolean("undetectable||true", true);
+  ExpectBoolean("undetectable||false", false);
+
+  ExpectBoolean("undetectable==null", true);
+  ExpectBoolean("null==undetectable", true);
+  ExpectBoolean("undetectable==undefined", true);
+  ExpectBoolean("undefined==undetectable", true);
+  ExpectBoolean("undetectable==undetectable", true);
+
+
+  ExpectBoolean("undetectable===null", false);
+  ExpectBoolean("null===undetectable", false);
+  ExpectBoolean("undetectable===undefined", false);
+  ExpectBoolean("undefined===undetectable", false);
+  ExpectBoolean("undetectable===undetectable", true);
+}
+
+
+THREADED_TEST(UndetectableString) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  Local<String> obj = String::NewUndetectable("foo");
+  env->Global()->Set(v8_str("undetectable"), obj);
+
+  ExpectString("undetectable", "foo");
+  ExpectString("typeof undetectable", "undefined");
+  ExpectString("typeof(undetectable)", "undefined");
+  ExpectBoolean("typeof undetectable == 'undefined'", true);
+  ExpectBoolean("typeof undetectable == 'string'", false);
+  ExpectBoolean("if (undetectable) { true; } else { false; }", false);
+  ExpectBoolean("!undetectable", true);
+
+  ExpectObject("true&&undetectable", obj);
+  ExpectBoolean("false&&undetectable", false);
+  ExpectBoolean("true||undetectable", true);
+  ExpectObject("false||undetectable", obj);
+
+  ExpectObject("undetectable&&true", obj);
+  ExpectObject("undetectable&&false", obj);
+  ExpectBoolean("undetectable||true", true);
+  ExpectBoolean("undetectable||false", false);
+
+  ExpectBoolean("undetectable==null", true);
+  ExpectBoolean("null==undetectable", true);
+  ExpectBoolean("undetectable==undefined", true);
+  ExpectBoolean("undefined==undetectable", true);
+  ExpectBoolean("undetectable==undetectable", true);
+
+
+  ExpectBoolean("undetectable===null", false);
+  ExpectBoolean("null===undetectable", false);
+  ExpectBoolean("undetectable===undefined", false);
+  ExpectBoolean("undefined===undetectable", false);
+  ExpectBoolean("undetectable===undetectable", true);
+}
+
+
+template <typename T> static void USE(T) { }
+
+
+// This test is not intended to be run, just type checked.
+static void PersistentHandles() {
+  USE(PersistentHandles);
+  Local<String> str = v8_str("foo");
+  v8::Persistent<String> p_str = v8::Persistent<String>::New(str);
+  USE(p_str);
+  Local<Script> scr = Script::Compile(v8_str(""));
+  v8::Persistent<Script> p_scr = v8::Persistent<Script>::New(scr);
+  USE(p_scr);
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  v8::Persistent<ObjectTemplate> p_templ =
+    v8::Persistent<ObjectTemplate>::New(templ);
+  USE(p_templ);
+}
+
+
+static v8::Handle<Value> HandleLogDelegator(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  return v8::Undefined();
+}
+
+
+THREADED_TEST(GlobalObjectTemplate) {
+  v8::HandleScope handle_scope;
+  Local<ObjectTemplate> global_template = ObjectTemplate::New();
+  global_template->Set(v8_str("JSNI_Log"),
+                       v8::FunctionTemplate::New(HandleLogDelegator));
+  v8::Persistent<Context> context = Context::New(0, global_template);
+  Context::Scope context_scope(context);
+  Script::Compile(v8_str("JSNI_Log('LOG')"))->Run();
+  context.Dispose();
+}
+
+
+static const char* kSimpleExtensionSource =
+  "function Foo() {"
+  "  return 4;"
+  "}";
+
+
+THREADED_TEST(SimpleExtensions) {
+  v8::HandleScope handle_scope;
+  v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
+  const char* extension_names[] = { "simpletest" };
+  v8::ExtensionConfiguration extensions(1, extension_names);
+  v8::Handle<Context> context = Context::New(&extensions);
+  Context::Scope lock(context);
+  v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
+  CHECK_EQ(result, v8::Integer::New(4));
+}
+
+
+static const char* kEvalExtensionSource =
+  "function UseEval() {"
+  "  var x = 42;"
+  "  return eval('x');"
+  "}";
+
+
+THREADED_TEST(UseEvalFromExtension) {
+  v8::HandleScope handle_scope;
+  v8::RegisterExtension(new Extension("evaltest", kEvalExtensionSource));
+  const char* extension_names[] = { "evaltest" };
+  v8::ExtensionConfiguration extensions(1, extension_names);
+  v8::Handle<Context> context = Context::New(&extensions);
+  Context::Scope lock(context);
+  v8::Handle<Value> result = Script::Compile(v8_str("UseEval()"))->Run();
+  CHECK_EQ(result, v8::Integer::New(42));
+}
+
+
+static const char* kWithExtensionSource =
+  "function UseWith() {"
+  "  var x = 42;"
+  "  with({x:87}) { return x; }"
+  "}";
+
+
+THREADED_TEST(UseWithFromExtension) {
+  v8::HandleScope handle_scope;
+  v8::RegisterExtension(new Extension("withtest", kWithExtensionSource));
+  const char* extension_names[] = { "withtest" };
+  v8::ExtensionConfiguration extensions(1, extension_names);
+  v8::Handle<Context> context = Context::New(&extensions);
+  Context::Scope lock(context);
+  v8::Handle<Value> result = Script::Compile(v8_str("UseWith()"))->Run();
+  CHECK_EQ(result, v8::Integer::New(87));
+}
+
+
+THREADED_TEST(AutoExtensions) {
+  v8::HandleScope handle_scope;
+  Extension* extension = new Extension("autotest", kSimpleExtensionSource);
+  extension->set_auto_enable(true);
+  v8::RegisterExtension(extension);
+  v8::Handle<Context> context = Context::New();
+  Context::Scope lock(context);
+  v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
+  CHECK_EQ(result, v8::Integer::New(4));
+}
+
+
+static void CheckDependencies(const char* name, const char* expected) {
+  v8::HandleScope handle_scope;
+  v8::ExtensionConfiguration config(1, &name);
+  LocalContext context(&config);
+  CHECK_EQ(String::New(expected), context->Global()->Get(v8_str("loaded")));
+}
+
+
+/*
+ * Configuration:
+ *
+ *     /-- B <--\
+ * A <-          -- D <-- E
+ *     \-- C <--/
+ */
+THREADED_TEST(ExtensionDependency) {
+  static const char* kEDeps[] = { "D" };
+  v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
+  static const char* kDDeps[] = { "B", "C" };
+  v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
+  static const char* kBCDeps[] = { "A" };
+  v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
+  v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
+  v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
+  CheckDependencies("A", "undefinedA");
+  CheckDependencies("B", "undefinedAB");
+  CheckDependencies("C", "undefinedAC");
+  CheckDependencies("D", "undefinedABCD");
+  CheckDependencies("E", "undefinedABCDE");
+  v8::HandleScope handle_scope;
+  static const char* exts[2] = { "C", "E" };
+  v8::ExtensionConfiguration config(2, exts);
+  LocalContext context(&config);
+  CHECK_EQ(v8_str("undefinedACBDE"), context->Global()->Get(v8_str("loaded")));
+}
+
+
+static const char* kExtensionTestScript =
+  "native function A();"
+  "native function B();"
+  "native function C();"
+  "function Foo(i) {"
+  "  if (i == 0) return A();"
+  "  if (i == 1) return B();"
+  "  if (i == 2) return C();"
+  "}";
+
+
+static v8::Handle<Value> CallFun(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  return args.Data();
+}
+
+
+class FunctionExtension : public Extension {
+ public:
+  FunctionExtension() : Extension("functiontest", kExtensionTestScript) { }
+  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
+      v8::Handle<String> name);
+};
+
+
+static int lookup_count = 0;
+v8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunction(
+      v8::Handle<String> name) {
+  lookup_count++;
+  if (name->Equals(v8_str("A"))) {
+    return v8::FunctionTemplate::New(CallFun, v8::Integer::New(8));
+  } else if (name->Equals(v8_str("B"))) {
+    return v8::FunctionTemplate::New(CallFun, v8::Integer::New(7));
+  } else if (name->Equals(v8_str("C"))) {
+    return v8::FunctionTemplate::New(CallFun, v8::Integer::New(6));
+  } else {
+    return v8::Handle<v8::FunctionTemplate>();
+  }
+}
+
+
+THREADED_TEST(FunctionLookup) {
+  v8::RegisterExtension(new FunctionExtension());
+  v8::HandleScope handle_scope;
+  static const char* exts[1] = { "functiontest" };
+  v8::ExtensionConfiguration config(1, exts);
+  LocalContext context(&config);
+  CHECK_EQ(3, lookup_count);
+  CHECK_EQ(v8::Integer::New(8), Script::Compile(v8_str("Foo(0)"))->Run());
+  CHECK_EQ(v8::Integer::New(7), Script::Compile(v8_str("Foo(1)"))->Run());
+  CHECK_EQ(v8::Integer::New(6), Script::Compile(v8_str("Foo(2)"))->Run());
+}
+
+
+static const char* last_location;
+static const char* last_message;
+void StoringErrorCallback(const char* location, const char* message) {
+  if (last_location == NULL) {
+    last_location = location;
+    last_message = message;
+  }
+}
+
+
+// ErrorReporting creates a circular extensions configuration and
+// tests that the fatal error handler gets called.  This renders V8
+// unusable and therefore this test cannot be run in parallel.
+TEST(ErrorReporting) {
+  v8::V8::SetFatalErrorHandler(StoringErrorCallback);
+  static const char* aDeps[] = { "B" };
+  v8::RegisterExtension(new Extension("A", "", 1, aDeps));
+  static const char* bDeps[] = { "A" };
+  v8::RegisterExtension(new Extension("B", "", 1, bDeps));
+  last_location = NULL;
+  v8::ExtensionConfiguration config(1, bDeps);
+  v8::Handle<Context> context = Context::New(&config);
+  CHECK(context.IsEmpty());
+  CHECK_NE(last_location, NULL);
+}
+
+
+static const char* js_code_causing_huge_string_flattening =
+    "var str = 'X';"
+    "for (var i = 0; i < 29; i++) {"
+    "  str = str + str;"
+    "}"
+    "str.match(/X/);";
+
+
+void OOMCallback(const char* location, const char* message) {
+  exit(0);
+}
+
+
+TEST(RegexpOutOfMemory) {
+  // Execute a script that causes out of memory when flattening a string.
+  v8::HandleScope scope;
+  v8::V8::SetFatalErrorHandler(OOMCallback);
+  LocalContext context;
+  Local<Script> script =
+      Script::Compile(String::New(js_code_causing_huge_string_flattening));
+  last_location = NULL;
+  Local<Value> result = script->Run();
+
+  CHECK(false);  // Should not return.
+}
+
+
+static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
+                                             v8::Handle<Value> data) {
+  CHECK_EQ(v8::Undefined(), data);
+  CHECK(message->GetScriptResourceName()->IsUndefined());
+  CHECK_EQ(v8::Undefined(), message->GetScriptResourceName());
+  message->GetLineNumber();
+  message->GetSourceLine();
+}
+
+
+THREADED_TEST(ErrorWithMissingScriptInfo) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
+  Script::Compile(v8_str("throw Error()"))->Run();
+  v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
+}
+
+
+int global_index = 0;
+
+class Snorkel {
+ public:
+  Snorkel() { index_ = global_index++; }
+  int index_;
+};
+
+class Whammy {
+ public:
+  Whammy() {
+    cursor_ = 0;
+  }
+  ~Whammy() {
+    script_.Dispose();
+  }
+  v8::Handle<Script> getScript() {
+    if (script_.IsEmpty())
+      script_ = v8::Persistent<Script>::New(v8_compile("({}).blammo"));
+    return Local<Script>(*script_);
+  }
+
+ public:
+  static const int kObjectCount = 256;
+  int cursor_;
+  v8::Persistent<v8::Object> objects_[kObjectCount];
+  v8::Persistent<Script> script_;
+};
+
+static void HandleWeakReference(v8::Persistent<v8::Value> obj, void* data) {
+  Snorkel* snorkel = reinterpret_cast<Snorkel*>(data);
+  delete snorkel;
+  obj.ClearWeak();
+}
+
+v8::Handle<Value> WhammyPropertyGetter(Local<String> name,
+                                       const AccessorInfo& info) {
+  Whammy* whammy =
+    static_cast<Whammy*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
+
+  v8::Persistent<v8::Object> prev = whammy->objects_[whammy->cursor_];
+
+  v8::Handle<v8::Object> obj = v8::Object::New();
+  v8::Persistent<v8::Object> global = v8::Persistent<v8::Object>::New(obj);
+  if (!prev.IsEmpty()) {
+    prev->Set(v8_str("next"), obj);
+    prev.MakeWeak(new Snorkel(), &HandleWeakReference);
+    whammy->objects_[whammy->cursor_].Clear();
+  }
+  whammy->objects_[whammy->cursor_] = global;
+  whammy->cursor_ = (whammy->cursor_ + 1) % Whammy::kObjectCount;
+  return whammy->getScript()->Run();
+}
+
+THREADED_TEST(WeakReference) {
+  v8::HandleScope handle_scope;
+  v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(WhammyPropertyGetter,
+                                 0, 0, 0, 0,
+                                 v8::External::New(new Whammy()));
+  const char* extension_list[] = { "v8/gc" };
+  v8::ExtensionConfiguration extensions(1, extension_list);
+  v8::Persistent<Context> context = Context::New(&extensions);
+  Context::Scope context_scope(context);
+
+  v8::Handle<v8::Object> interceptor = templ->NewInstance();
+  context->Global()->Set(v8_str("whammy"), interceptor);
+  const char* code =
+      "var last;"
+      "for (var i = 0; i < 10000; i++) {"
+      "  var obj = whammy.length;"
+      "  if (last) last.next = obj;"
+      "  last = obj;"
+      "}"
+      "gc();"
+      "4";
+  v8::Handle<Value> result = CompileRun(code);
+  CHECK_EQ(4.0, result->NumberValue());
+
+  context.Dispose();
+}
+
+
+v8::Handle<Function> args_fun;
+
+
+static v8::Handle<Value> ArgumentsTestCallback(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  CHECK_EQ(args_fun, args.Callee());
+  CHECK_EQ(3, args.Length());
+  CHECK_EQ(v8::Integer::New(1), args[0]);
+  CHECK_EQ(v8::Integer::New(2), args[1]);
+  CHECK_EQ(v8::Integer::New(3), args[2]);
+  CHECK_EQ(v8::Undefined(), args[3]);
+  v8::HandleScope scope;
+  i::Heap::CollectAllGarbage();
+  return v8::Undefined();
+}
+
+
+THREADED_TEST(Arguments) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New();
+  global->Set(v8_str("f"), v8::FunctionTemplate::New(ArgumentsTestCallback));
+  LocalContext context(NULL, global);
+  args_fun = v8::Handle<Function>::Cast(context->Global()->Get(v8_str("f")));
+  v8_compile("f(1, 2, 3)")->Run();
+}
+
+
+static int x_register = 0;
+static v8::Handle<v8::Object> x_receiver;
+static v8::Handle<v8::Object> x_holder;
+
+
+static v8::Handle<Value> XGetter(Local<String> name, const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK_EQ(x_receiver, info.This());
+  CHECK_EQ(x_holder, info.Holder());
+  return v8_num(x_register);
+}
+
+
+static void XSetter(Local<String> name,
+                    Local<Value> value,
+                    const AccessorInfo& info) {
+  CHECK_EQ(x_holder, info.This());
+  CHECK_EQ(x_holder, info.Holder());
+  x_register = value->Int32Value();
+}
+
+
+THREADED_TEST(AccessorIC) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+  obj->SetAccessor(v8_str("x"), XGetter, XSetter);
+  LocalContext context;
+  x_holder = obj->NewInstance();
+  context->Global()->Set(v8_str("holder"), x_holder);
+  x_receiver = v8::Object::New();
+  context->Global()->Set(v8_str("obj"), x_receiver);
+  v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(CompileRun(
+    "obj.__proto__ = holder;"
+    "var result = [];"
+    "for (var i = 0; i < 10; i++) {"
+    "  holder.x = i;"
+    "  result.push(obj.x);"
+    "}"
+    "result"));
+  CHECK_EQ(10, array->Length());
+  for (int i = 0; i < 10; i++) {
+    v8::Handle<Value> entry = array->Get(v8::Integer::New(i));
+    CHECK_EQ(v8::Integer::New(i), entry);
+  }
+}
+
+
+static v8::Handle<Value> NoBlockGetterX(Local<String> name,
+                                        const AccessorInfo&) {
+  return v8::Handle<Value>();
+}
+
+
+static v8::Handle<Value> NoBlockGetterI(uint32_t index,
+                                        const AccessorInfo&) {
+  return v8::Handle<Value>();
+}
+
+
+static v8::Handle<v8::Boolean> PDeleter(Local<String> name,
+                                        const AccessorInfo&) {
+  if (!name->Equals(v8_str("foo"))) {
+    return v8::Handle<v8::Boolean>();  // not intercepted
+  }
+
+  return v8::False();  // intercepted, and don't delete the property
+}
+
+
+static v8::Handle<v8::Boolean> IDeleter(uint32_t index, const AccessorInfo&) {
+  if (index != 2) {
+    return v8::Handle<v8::Boolean>();  // not intercepted
+  }
+
+  return v8::False();  // intercepted, and don't delete the property
+}
+
+
+THREADED_TEST(Deleter) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+  obj->SetNamedPropertyHandler(NoBlockGetterX, NULL, NULL, PDeleter, NULL);
+  obj->SetIndexedPropertyHandler(NoBlockGetterI, NULL, NULL, IDeleter, NULL);
+  LocalContext context;
+  context->Global()->Set(v8_str("k"), obj->NewInstance());
+  CompileRun(
+    "k.foo = 'foo';"
+    "k.bar = 'bar';"
+    "k[2] = 2;"
+    "k[4] = 4;");
+  CHECK(v8_compile("delete k.foo")->Run()->IsFalse());
+  CHECK(v8_compile("delete k.bar")->Run()->IsTrue());
+
+  CHECK_EQ(v8_compile("k.foo")->Run(), v8_str("foo"));
+  CHECK(v8_compile("k.bar")->Run()->IsUndefined());
+
+  CHECK(v8_compile("delete k[2]")->Run()->IsFalse());
+  CHECK(v8_compile("delete k[4]")->Run()->IsTrue());
+
+  CHECK_EQ(v8_compile("k[2]")->Run(), v8_num(2));
+  CHECK(v8_compile("k[4]")->Run()->IsUndefined());
+}
+
+
+static v8::Handle<Value> GetK(Local<String> name, const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  return v8::Undefined();
+}
+
+
+static v8::Handle<v8::Array> NamedEnum(const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  v8::Handle<v8::Array> result = v8::Array::New(3);
+  result->Set(v8::Integer::New(0), v8_str("foo"));
+  result->Set(v8::Integer::New(1), v8_str("bar"));
+  result->Set(v8::Integer::New(2), v8_str("baz"));
+  return result;
+}
+
+
+static v8::Handle<v8::Array> IndexedEnum(const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  v8::Handle<v8::Array> result = v8::Array::New(2);
+  result->Set(v8::Integer::New(0), v8_str("hat"));
+  result->Set(v8::Integer::New(1), v8_str("gyt"));
+  return result;
+}
+
+
+THREADED_TEST(Enumerators) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+  obj->SetNamedPropertyHandler(GetK, NULL, NULL, NULL, NamedEnum);
+  obj->SetIndexedPropertyHandler(NULL, NULL, NULL, NULL, IndexedEnum);
+  LocalContext context;
+  context->Global()->Set(v8_str("k"), obj->NewInstance());
+  v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
+    "var result = [];"
+    "for (var prop in k) {"
+    "  result.push(prop);"
+    "}"
+    "result"));
+  CHECK_EQ(5, result->Length());
+  CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(0)));
+  CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(1)));
+  CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(2)));
+  CHECK_EQ(v8_str("hat"), result->Get(v8::Integer::New(3)));
+  CHECK_EQ(v8_str("gyt"), result->Get(v8::Integer::New(4)));
+}
+
+
+int p_getter_count;
+int p_getter_count2;
+
+
+static v8::Handle<Value> PGetter(Local<String> name, const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  p_getter_count++;
+  v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
+  CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
+  if (name->Equals(v8_str("p1"))) {
+    CHECK_EQ(info.This(), global->Get(v8_str("o1")));
+  } else if (name->Equals(v8_str("p2"))) {
+    CHECK_EQ(info.This(), global->Get(v8_str("o2")));
+  } else if (name->Equals(v8_str("p3"))) {
+    CHECK_EQ(info.This(), global->Get(v8_str("o3")));
+  } else if (name->Equals(v8_str("p4"))) {
+    CHECK_EQ(info.This(), global->Get(v8_str("o4")));
+  }
+  return v8::Undefined();
+}
+
+
+static void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
+  ApiTestFuzzer::Fuzz();
+  LocalContext context;
+  context->Global()->Set(v8_str("o1"), obj->NewInstance());
+  CompileRun(
+    "o1.__proto__ = { };"
+    "var o2 = { __proto__: o1 };"
+    "var o3 = { __proto__: o2 };"
+    "var o4 = { __proto__: o3 };"
+    "for (var i = 0; i < 10; i++) o4.p4;"
+    "for (var i = 0; i < 10; i++) o3.p3;"
+    "for (var i = 0; i < 10; i++) o2.p2;"
+    "for (var i = 0; i < 10; i++) o1.p1;");
+}
+
+
+static v8::Handle<Value> PGetter2(Local<String> name,
+                                  const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  p_getter_count2++;
+  v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
+  CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
+  if (name->Equals(v8_str("p1"))) {
+    CHECK_EQ(info.This(), global->Get(v8_str("o1")));
+  } else if (name->Equals(v8_str("p2"))) {
+    CHECK_EQ(info.This(), global->Get(v8_str("o2")));
+  } else if (name->Equals(v8_str("p3"))) {
+    CHECK_EQ(info.This(), global->Get(v8_str("o3")));
+  } else if (name->Equals(v8_str("p4"))) {
+    CHECK_EQ(info.This(), global->Get(v8_str("o4")));
+  }
+  return v8::Undefined();
+}
+
+
+THREADED_TEST(GetterHolders) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+  obj->SetAccessor(v8_str("p1"), PGetter);
+  obj->SetAccessor(v8_str("p2"), PGetter);
+  obj->SetAccessor(v8_str("p3"), PGetter);
+  obj->SetAccessor(v8_str("p4"), PGetter);
+  p_getter_count = 0;
+  RunHolderTest(obj);
+  CHECK_EQ(40, p_getter_count);
+}
+
+
+THREADED_TEST(PreInterceptorHolders) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+  obj->SetNamedPropertyHandler(PGetter2);
+  p_getter_count2 = 0;
+  RunHolderTest(obj);
+  CHECK_EQ(40, p_getter_count2);
+}
+
+
+THREADED_TEST(ObjectInstantiation) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetAccessor(v8_str("t"), PGetter2);
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ->NewInstance());
+  for (int i = 0; i < 100; i++) {
+    v8::HandleScope inner_scope;
+    v8::Handle<v8::Object> obj = templ->NewInstance();
+    CHECK_NE(obj, context->Global()->Get(v8_str("o")));
+    context->Global()->Set(v8_str("o2"), obj);
+    v8::Handle<Value> value =
+        Script::Compile(v8_str("o.__proto__ === o2.__proto__"))->Run();
+    CHECK_EQ(v8::True(), value);
+    context->Global()->Set(v8_str("o"), obj);
+  }
+}
+
+
+THREADED_TEST(StringWrite) {
+  v8::HandleScope scope;
+  v8::Handle<String> str = v8_str("abcde");
+
+  char buf[100];
+  int len;
+
+  memset(buf, 0x1, sizeof(buf));
+  len = str->WriteAscii(buf);
+  CHECK_EQ(len, 5);
+  CHECK_EQ(strncmp("abcde\0", buf, 6), 0);
+
+  memset(buf, 0x1, sizeof(buf));
+  len = str->WriteAscii(buf, 0, 4);
+  CHECK_EQ(len, 4);
+  CHECK_EQ(strncmp("abcd\1", buf, 5), 0);
+
+  memset(buf, 0x1, sizeof(buf));
+  len = str->WriteAscii(buf, 0, 5);
+  CHECK_EQ(len, 5);
+  CHECK_EQ(strncmp("abcde\1", buf, 6), 0);
+
+  memset(buf, 0x1, sizeof(buf));
+  len = str->WriteAscii(buf, 0, 6);
+  CHECK_EQ(len, 5);
+  CHECK_EQ(strncmp("abcde\0", buf, 6), 0);
+
+  memset(buf, 0x1, sizeof(buf));
+  len = str->WriteAscii(buf, 4, -1);
+  CHECK_EQ(len, 1);
+  CHECK_EQ(strncmp("e\0", buf, 2), 0);
+
+  memset(buf, 0x1, sizeof(buf));
+  len = str->WriteAscii(buf, 4, 6);
+  CHECK_EQ(len, 1);
+  CHECK_EQ(strncmp("e\0", buf, 2), 0);
+
+  memset(buf, 0x1, sizeof(buf));
+  len = str->WriteAscii(buf, 4, 1);
+  CHECK_EQ(len, 1);
+  CHECK_EQ(strncmp("e\1", buf, 2), 0);
+}
+
+
+THREADED_TEST(ToArrayIndex) {
+  v8::HandleScope scope;
+  LocalContext context;
+
+  v8::Handle<String> str = v8_str("42");
+  v8::Handle<v8::Uint32> index = str->ToArrayIndex();
+  CHECK(!index.IsEmpty());
+  CHECK_EQ(42.0, index->Uint32Value());
+  str = v8_str("42asdf");
+  index = str->ToArrayIndex();
+  CHECK(index.IsEmpty());
+  str = v8_str("-42");
+  index = str->ToArrayIndex();
+  CHECK(index.IsEmpty());
+  str = v8_str("4294967295");
+  index = str->ToArrayIndex();
+  CHECK(!index.IsEmpty());
+  CHECK_EQ(4294967295.0, index->Uint32Value());
+  v8::Handle<v8::Number> num = v8::Number::New(1);
+  index = num->ToArrayIndex();
+  CHECK(!index.IsEmpty());
+  CHECK_EQ(1.0, index->Uint32Value());
+  num = v8::Number::New(-1);
+  index = num->ToArrayIndex();
+  CHECK(index.IsEmpty());
+  v8::Handle<v8::Object> obj = v8::Object::New();
+  index = obj->ToArrayIndex();
+  CHECK(index.IsEmpty());
+}
+
+
+THREADED_TEST(ErrorConstruction) {
+  v8::HandleScope scope;
+  LocalContext context;
+
+  v8::Handle<String> foo = v8_str("foo");
+  v8::Handle<String> message = v8_str("message");
+  v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
+  CHECK(range_error->IsObject());
+  v8::Handle<v8::Object> range_obj(v8::Handle<v8::Object>::Cast(range_error));
+  CHECK(v8::Handle<v8::Object>::Cast(range_error)->Get(message)->Equals(foo));
+  v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
+  CHECK(reference_error->IsObject());
+  CHECK(
+      v8::Handle<v8::Object>::Cast(reference_error)->Get(message)->Equals(foo));
+  v8::Handle<Value> syntax_error = v8::Exception::SyntaxError(foo);
+  CHECK(syntax_error->IsObject());
+  CHECK(v8::Handle<v8::Object>::Cast(syntax_error)->Get(message)->Equals(foo));
+  v8::Handle<Value> type_error = v8::Exception::TypeError(foo);
+  CHECK(type_error->IsObject());
+  CHECK(v8::Handle<v8::Object>::Cast(type_error)->Get(message)->Equals(foo));
+  v8::Handle<Value> error = v8::Exception::Error(foo);
+  CHECK(error->IsObject());
+  CHECK(v8::Handle<v8::Object>::Cast(error)->Get(message)->Equals(foo));
+}
+
+
+static v8::Handle<Value> YGetter(Local<String> name, const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(10);
+}
+
+
+static void YSetter(Local<String> name,
+                    Local<Value> value,
+                    const AccessorInfo& info) {
+  if (info.This()->Has(name)) {
+    info.This()->Delete(name);
+  }
+  info.This()->Set(name, value);
+}
+
+
+THREADED_TEST(DeleteAccessor) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+  obj->SetAccessor(v8_str("y"), YGetter, YSetter);
+  LocalContext context;
+  v8::Handle<v8::Object> holder = obj->NewInstance();
+  context->Global()->Set(v8_str("holder"), holder);
+  v8::Handle<Value> result = CompileRun(
+      "holder.y = 11; holder.y = 12; holder.y");
+  CHECK_EQ(12, result->Uint32Value());
+}
+
+
+THREADED_TEST(TypeSwitch) {
+  v8::HandleScope scope;
+  v8::Handle<v8::FunctionTemplate> templ1 = v8::FunctionTemplate::New();
+  v8::Handle<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New();
+  v8::Handle<v8::FunctionTemplate> templ3 = v8::FunctionTemplate::New();
+  v8::Handle<v8::FunctionTemplate> templs[3] = { templ1, templ2, templ3 };
+  v8::Handle<v8::TypeSwitch> type_switch = v8::TypeSwitch::New(3, templs);
+  LocalContext context;
+  v8::Handle<v8::Object> obj0 = v8::Object::New();
+  v8::Handle<v8::Object> obj1 = templ1->GetFunction()->NewInstance();
+  v8::Handle<v8::Object> obj2 = templ2->GetFunction()->NewInstance();
+  v8::Handle<v8::Object> obj3 = templ3->GetFunction()->NewInstance();
+  for (int i = 0; i < 10; i++) {
+    CHECK_EQ(0, type_switch->match(obj0));
+    CHECK_EQ(1, type_switch->match(obj1));
+    CHECK_EQ(2, type_switch->match(obj2));
+    CHECK_EQ(3, type_switch->match(obj3));
+    CHECK_EQ(3, type_switch->match(obj3));
+    CHECK_EQ(2, type_switch->match(obj2));
+    CHECK_EQ(1, type_switch->match(obj1));
+    CHECK_EQ(0, type_switch->match(obj0));
+  }
+}
+
+
+// For use within the TestSecurityHandler() test.
+static bool g_security_callback_result = false;
+static bool NamedSecurityTestCallback(Local<v8::Object> global,
+                                      Local<Value> name,
+                                      v8::AccessType type,
+                                      Local<Value> data) {
+  // Always allow read access.
+  if (type == v8::ACCESS_GET)
+    return true;
+
+  // Sometimes allow other access.
+  return g_security_callback_result;
+}
+
+
+static bool IndexedSecurityTestCallback(Local<v8::Object> global,
+                                        uint32_t key,
+                                        v8::AccessType type,
+                                        Local<Value> data) {
+  // Always allow read access.
+  if (type == v8::ACCESS_GET)
+    return true;
+
+  // Sometimes allow other access.
+  return g_security_callback_result;
+}
+
+
+static int trouble_nesting = 0;
+static v8::Handle<Value> TroubleCallback(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  trouble_nesting++;
+
+  // Call a JS function that throws an uncaught exception.
+  Local<v8::Object> arg_this = Context::GetCurrent()->Global();
+  Local<Value> trouble_callee = (trouble_nesting == 3) ?
+    arg_this->Get(v8_str("trouble_callee")) :
+    arg_this->Get(v8_str("trouble_caller"));
+  CHECK(trouble_callee->IsFunction());
+  return Function::Cast(*trouble_callee)->Call(arg_this, 0, NULL);
+}
+
+
+static int report_count = 0;
+static void ApiUncaughtExceptionTestListener(v8::Handle<v8::Message>,
+                                             v8::Handle<Value>) {
+  report_count++;
+}
+
+
+// Counts uncaught exceptions, but other tests running in parallel
+// also have uncaught exceptions.
+TEST(ApiUncaughtException) {
+  report_count = 0;
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
+
+  Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(TroubleCallback);
+  v8::Local<v8::Object> global = env->Global();
+  global->Set(v8_str("trouble"), fun->GetFunction());
+
+  Script::Compile(v8_str("function trouble_callee() {"
+                         "  var x = null;"
+                         "  return x.foo;"
+                         "};"
+                         "function trouble_caller() {"
+                         "  trouble();"
+                         "};"))->Run();
+  Local<Value> trouble = global->Get(v8_str("trouble"));
+  CHECK(trouble->IsFunction());
+  Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
+  CHECK(trouble_callee->IsFunction());
+  Local<Value> trouble_caller = global->Get(v8_str("trouble_caller"));
+  CHECK(trouble_caller->IsFunction());
+  Function::Cast(*trouble_caller)->Call(global, 0, NULL);
+  CHECK_EQ(1, report_count);
+  v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
+}
+
+
+TEST(CompilationErrorUsingTryCatchHandler) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::TryCatch try_catch;
+  Script::Compile(v8_str("This doesn't &*&@#$&*^ compile."));
+  CHECK_NE(NULL, *try_catch.Exception());
+  CHECK(try_catch.HasCaught());
+}
+
+
+TEST(TryCatchFinallyUsingTryCatchHandler) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::TryCatch try_catch;
+  Script::Compile(v8_str("try { throw ''; } catch (e) {}"))->Run();
+  CHECK(!try_catch.HasCaught());
+  Script::Compile(v8_str("try { throw ''; } finally {}"))->Run();
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+  Script::Compile(v8_str("(function() {"
+                         "try { throw ''; } finally { return; }"
+                         "})()"))->Run();
+  CHECK(!try_catch.HasCaught());
+  Script::Compile(v8_str("(function()"
+                         "  { try { throw ''; } finally { throw 0; }"
+                         "})()"))->Run();
+  CHECK(try_catch.HasCaught());
+}
+
+
+// SecurityHandler can't be run twice
+TEST(SecurityHandler) {
+  v8::HandleScope scope0;
+  v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
+  global_template->SetAccessCheckCallbacks(NamedSecurityTestCallback,
+                                           IndexedSecurityTestCallback);
+  // Create an environment
+  v8::Persistent<Context> context0 =
+    Context::New(NULL, global_template);
+  context0->Enter();
+
+  v8::Handle<v8::Object> global0 = context0->Global();
+  v8::Handle<Script> script0 = v8_compile("foo = 111");
+  script0->Run();
+  global0->Set(v8_str("0"), v8_num(999));
+  v8::Handle<Value> foo0 = global0->Get(v8_str("foo"));
+  CHECK_EQ(111, foo0->Int32Value());
+  v8::Handle<Value> z0 = global0->Get(v8_str("0"));
+  CHECK_EQ(999, z0->Int32Value());
+
+  // Create another environment, should fail security checks.
+  v8::HandleScope scope1;
+
+  v8::Persistent<Context> context1 =
+    Context::New(NULL, global_template);
+  context1->Enter();
+
+  v8::Handle<v8::Object> global1 = context1->Global();
+  global1->Set(v8_str("othercontext"), global0);
+  // This set will fail the security check.
+  v8::Handle<Script> script1 =
+    v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
+  script1->Run();
+  // This read will pass the security check.
+  v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
+  CHECK_EQ(111, foo1->Int32Value());
+  // This read will pass the security check.
+  v8::Handle<Value> z1 = global0->Get(v8_str("0"));
+  CHECK_EQ(999, z1->Int32Value());
+
+  // Create another environment, should pass security checks.
+  { g_security_callback_result = true;  // allow security handler to pass.
+    v8::HandleScope scope2;
+    LocalContext context2;
+    v8::Handle<v8::Object> global2 = context2->Global();
+    global2->Set(v8_str("othercontext"), global0);
+    v8::Handle<Script> script2 =
+        v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
+    script2->Run();
+    v8::Handle<Value> foo2 = global0->Get(v8_str("foo"));
+    CHECK_EQ(333, foo2->Int32Value());
+    v8::Handle<Value> z2 = global0->Get(v8_str("0"));
+    CHECK_EQ(888, z2->Int32Value());
+  }
+
+  context1->Exit();
+  context1.Dispose();
+
+  context0->Exit();
+  context0.Dispose();
+}
+
+
+THREADED_TEST(SecurityChecks) {
+  v8::HandleScope handle_scope;
+  LocalContext env1;
+  v8::Persistent<Context> env2 = Context::New();
+
+  Local<Value> foo = v8_str("foo");
+  Local<Value> bar = v8_str("bar");
+
+  // Set to the same domain.
+  env1->SetSecurityToken(foo);
+
+  // Create a function in env1.
+  Script::Compile(v8_str("spy=function(){return spy;}"))->Run();
+  Local<Value> spy = env1->Global()->Get(v8_str("spy"));
+  CHECK(spy->IsFunction());
+
+  // Create another function accessing global objects.
+  Script::Compile(v8_str("spy2=function(){return new this.Array();}"))->Run();
+  Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
+  CHECK(spy2->IsFunction());
+
+  // Switch to env2 in the same domain and invoke spy on env2.
+  {
+    env2->SetSecurityToken(foo);
+    // Enter env2
+    Context::Scope scope_env2(env2);
+    Local<Value> result = Function::Cast(*spy)->Call(env2->Global(), 0, NULL);
+    CHECK(result->IsFunction());
+  }
+
+  {
+    env2->SetSecurityToken(bar);
+    Context::Scope scope_env2(env2);
+
+    // Call cross_domain_call, it should throw an exception
+    v8::TryCatch try_catch;
+    Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
+    CHECK(try_catch.HasCaught());
+  }
+
+  env2.Dispose();
+}
+
+
+// Regression test case for issue 1183439.
+THREADED_TEST(SecurityChecksForPrototypeChain) {
+  v8::HandleScope scope;
+  LocalContext current;
+  v8::Persistent<Context> other = Context::New();
+
+  // Change context to be able to get to the Object function in the
+  // other context without hitting the security checks.
+  v8::Local<Value> other_object;
+  { Context::Scope scope(other);
+    other_object = other->Global()->Get(v8_str("Object"));
+    other->Global()->Set(v8_num(42), v8_num(87));
+  }
+
+  current->Global()->Set(v8_str("other"), other->Global());
+  CHECK(v8_compile("other")->Run()->Equals(other->Global()));
+
+  // Make sure the security check fails here and we get an undefined
+  // result instead of getting the Object function. Repeat in a loop
+  // to make sure to exercise the IC code.
+  v8::Local<Script> access_other0 = v8_compile("other.Object");
+  v8::Local<Script> access_other1 = v8_compile("other[42]");
+  for (int i = 0; i < 5; i++) {
+    CHECK(!access_other0->Run()->Equals(other_object));
+    CHECK(access_other0->Run()->IsUndefined());
+    CHECK(!access_other1->Run()->Equals(v8_num(87)));
+    CHECK(access_other1->Run()->IsUndefined());
+  }
+
+  // Create an object that has 'other' in its prototype chain and make
+  // sure we cannot access the Object function indirectly through
+  // that. Repeat in a loop to make sure to exercise the IC code.
+  v8_compile("function F() { };"
+             "F.prototype = other;"
+             "var f = new F();")->Run();
+  v8::Local<Script> access_f0 = v8_compile("f.Object");
+  v8::Local<Script> access_f1 = v8_compile("f[42]");
+  for (int j = 0; j < 5; j++) {
+    CHECK(!access_f0->Run()->Equals(other_object));
+    CHECK(access_f0->Run()->IsUndefined());
+    CHECK(!access_f1->Run()->Equals(v8_num(87)));
+    CHECK(access_f1->Run()->IsUndefined());
+  }
+
+  // Now it gets hairy: Set the prototype for the other global object
+  // to be the current global object. The prototype chain for 'f' now
+  // goes through 'other' but ends up in the current global object.
+  { Context::Scope scope(other);
+    other->Global()->Set(v8_str("__proto__"), current->Global());
+  }
+  // Set a named and an index property on the current global
+  // object. To force the lookup to go through the other global object,
+  // the properties must not exist in the other global object.
+  current->Global()->Set(v8_str("foo"), v8_num(100));
+  current->Global()->Set(v8_num(99), v8_num(101));
+  // Try to read the properties from f and make sure that the access
+  // gets stopped by the security checks on the other global object.
+  Local<Script> access_f2 = v8_compile("f.foo");
+  Local<Script> access_f3 = v8_compile("f[99]");
+  for (int k = 0; k < 5; k++) {
+    CHECK(!access_f2->Run()->Equals(v8_num(100)));
+    CHECK(access_f2->Run()->IsUndefined());
+    CHECK(!access_f3->Run()->Equals(v8_num(101)));
+    CHECK(access_f3->Run()->IsUndefined());
+  }
+  other.Dispose();
+}
+
+
+THREADED_TEST(CrossDomainDelete) {
+  v8::HandleScope handle_scope;
+  LocalContext env1;
+  v8::Persistent<Context> env2 = Context::New();
+
+  Local<Value> foo = v8_str("foo");
+  Local<Value> bar = v8_str("bar");
+
+  // Set to the same domain.
+  env1->SetSecurityToken(foo);
+  env2->SetSecurityToken(foo);
+
+  env1->Global()->Set(v8_str("prop"), v8_num(3));
+  env2->Global()->Set(v8_str("env1"), env1->Global());
+
+  // Change env2 to a different domain and delete env1.prop.
+  env2->SetSecurityToken(bar);
+  {
+    Context::Scope scope_env2(env2);
+    Local<Value> result =
+        Script::Compile(v8_str("delete env1.prop"))->Run();
+    CHECK(result->IsFalse());
+  }
+
+  // Check that env1.prop still exists.
+  Local<Value> v = env1->Global()->Get(v8_str("prop"));
+  CHECK(v->IsNumber());
+  CHECK_EQ(3, v->Int32Value());
+
+  env2.Dispose();
+}
+
+
+THREADED_TEST(CrossDomainIsPropertyEnumerable) {
+  v8::HandleScope handle_scope;
+  LocalContext env1;
+  v8::Persistent<Context> env2 = Context::New();
+
+  Local<Value> foo = v8_str("foo");
+  Local<Value> bar = v8_str("bar");
+
+  // Set to the same domain.
+  env1->SetSecurityToken(foo);
+  env2->SetSecurityToken(foo);
+
+  env1->Global()->Set(v8_str("prop"), v8_num(3));
+  env2->Global()->Set(v8_str("env1"), env1->Global());
+
+  // env1.prop is enumerable in env2.
+  Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
+  {
+    Context::Scope scope_env2(env2);
+    Local<Value> result = Script::Compile(test)->Run();
+    CHECK(result->IsTrue());
+  }
+
+  // Change env2 to a different domain and test again.
+  env2->SetSecurityToken(bar);
+  {
+    Context::Scope scope_env2(env2);
+    Local<Value> result = Script::Compile(test)->Run();
+    CHECK(result->IsFalse());
+  }
+
+  env2.Dispose();
+}
+
+
+THREADED_TEST(CrossDomainForIn) {
+  v8::HandleScope handle_scope;
+  LocalContext env1;
+  v8::Persistent<Context> env2 = Context::New();
+
+  Local<Value> foo = v8_str("foo");
+  Local<Value> bar = v8_str("bar");
+
+  // Set to the same domain.
+  env1->SetSecurityToken(foo);
+  env2->SetSecurityToken(foo);
+
+  env1->Global()->Set(v8_str("prop"), v8_num(3));
+  env2->Global()->Set(v8_str("env1"), env1->Global());
+
+  // Change env2 to a different domain and set env1's global object
+  // as the __proto__ of an object in env2 and enumerate properties
+  // in for-in. It shouldn't enumerate properties on env1's global
+  // object.
+  env2->SetSecurityToken(bar);
+  {
+    Context::Scope scope_env2(env2);
+    Local<Value> result =
+        CompileRun("(function(){var obj = {'__proto__':env1};"
+                   "for (var p in obj)"
+                   "   if (p == 'prop') return false;"
+                   "return true;})()");
+    CHECK(result->IsTrue());
+  }
+  env2.Dispose();
+}
+
+
+TEST(ContextDetachGlobal) {
+  v8::HandleScope handle_scope;
+  LocalContext env1;
+  v8::Persistent<Context> env2 = Context::New();
+
+  Local<v8::Object> global1 = env1->Global();
+
+  Local<Value> foo = v8_str("foo");
+
+  // Set to the same domain.
+  env1->SetSecurityToken(foo);
+  env2->SetSecurityToken(foo);
+
+  // Enter env2
+  env2->Enter();
+
+  // Create a function in env1
+  Local<v8::Object> global2 = env2->Global();
+  global2->Set(v8_str("prop"), v8::Integer::New(1));
+  CompileRun("function getProp() {return prop;}");
+
+  env1->Global()->Set(v8_str("getProp"),
+                      global2->Get(v8_str("getProp")));
+
+  // Detach env1's global, and reuse the global object of env1
+  env2->Exit();
+  env2->DetachGlobal();
+  // env2 has a new global object.
+  CHECK(!env2->Global()->Equals(global2));
+
+  v8::Persistent<Context> env3 =
+      Context::New(0, v8::Handle<v8::ObjectTemplate>(), global2);
+  env3->SetSecurityToken(v8_str("bar"));
+  env3->Enter();
+
+  Local<v8::Object> global3 = env3->Global();
+  CHECK_EQ(global2, global3);
+  CHECK(global3->Get(v8_str("prop"))->IsUndefined());
+  CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
+  global3->Set(v8_str("prop"), v8::Integer::New(-1));
+  global3->Set(v8_str("prop2"), v8::Integer::New(2));
+  env3->Exit();
+
+  // Call getProp in env1, and it should return the value 1
+  {
+    Local<Value> get_prop = global1->Get(v8_str("getProp"));
+    CHECK(get_prop->IsFunction());
+    v8::TryCatch try_catch;
+    Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
+    CHECK(!try_catch.HasCaught());
+    CHECK_EQ(1, r->Int32Value());
+  }
+
+  // Check that env3 is not accessible from env1
+  {
+    Local<Value> r = global3->Get(v8_str("prop2"));
+    CHECK(r->IsUndefined());
+  }
+
+  env2.Dispose();
+  env3.Dispose();
+}
+
+
+static bool NamedAccessBlocker(Local<v8::Object> global,
+                               Local<Value> name,
+                               v8::AccessType type,
+                               Local<Value> data) {
+  return Context::GetCurrent()->Global()->Equals(global);
+}
+
+
+static bool IndexedAccessBlocker(Local<v8::Object> global,
+                                 uint32_t key,
+                                 v8::AccessType type,
+                                 Local<Value> data) {
+  return Context::GetCurrent()->Global()->Equals(global);
+}
+
+
+static int g_echo_value = -1;
+static v8::Handle<Value> EchoGetter(Local<String> name,
+                                    const AccessorInfo& info) {
+  return v8_num(g_echo_value);
+}
+
+
+static void EchoSetter(Local<String> name,
+                       Local<Value> value,
+                       const AccessorInfo&) {
+  if (value->IsNumber())
+    g_echo_value = value->Int32Value();
+}
+
+
+static v8::Handle<Value> UnreachableGetter(Local<String> name,
+                                           const AccessorInfo& info) {
+  CHECK(false);  // This function should not be called..
+  return v8::Undefined();
+}
+
+
+static void UnreachableSetter(Local<String>, Local<Value>,
+                              const AccessorInfo&) {
+  CHECK(false);  // This function should nto be called.
+}
+
+
+THREADED_TEST(AccessControl) {
+  v8::HandleScope handle_scope;
+  v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
+
+  global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
+                                           IndexedAccessBlocker);
+
+  // Add an accessor accessible by cross-domain JS code.
+  global_template->SetAccessor(
+      v8_str("accessible_prop"),
+      EchoGetter, EchoSetter,
+      v8::Handle<Value>(),
+      v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
+
+  // Add an accessor that is not accessible by cross-domain JS code.
+  global_template->SetAccessor(v8_str("blocked_prop"),
+                               UnreachableGetter, UnreachableSetter,
+                               v8::Handle<Value>(),
+                               v8::DEFAULT);
+
+  // Create an environment
+  v8::Persistent<Context> context0 = Context::New(NULL, global_template);
+  context0->Enter();
+
+  v8::Handle<v8::Object> global0 = context0->Global();
+
+  v8::HandleScope scope1;
+
+  v8::Persistent<Context> context1 = Context::New();
+  context1->Enter();
+
+  v8::Handle<v8::Object> global1 = context1->Global();
+  global1->Set(v8_str("other"), global0);
+
+  v8::Handle<Value> value;
+
+  // Access blocked property
+  value = v8_compile("other.blocked_prop = 1")->Run();
+  value = v8_compile("other.blocked_prop")->Run();
+  CHECK(value->IsUndefined());
+
+  value = v8_compile("propertyIsEnumerable.call(other, 'blocked_prop')")->Run();
+  CHECK(value->IsFalse());
+
+  // Access accessible property
+  value = v8_compile("other.accessible_prop = 3")->Run();
+  CHECK(value->IsNumber());
+  CHECK_EQ(3, value->Int32Value());
+
+  value = v8_compile("other.accessible_prop")->Run();
+  CHECK(value->IsNumber());
+  CHECK_EQ(3, value->Int32Value());
+
+  value =
+    v8_compile("propertyIsEnumerable.call(other, 'accessible_prop')")->Run();
+  CHECK(value->IsTrue());
+
+  // Enumeration doesn't enumerate accessors from inaccessible objects in
+  // the prototype chain even if the accessors are in themselves accessible.
+  Local<Value> result =
+      CompileRun("(function(){var obj = {'__proto__':other};"
+                 "for (var p in obj)"
+                 "   if (p == 'accessible_prop' || p == 'blocked_prop') {"
+                 "     return false;"
+                 "   }"
+                 "return true;})()");
+  CHECK(result->IsTrue());
+
+  context1->Exit();
+  context0->Exit();
+  context1.Dispose();
+  context0.Dispose();
+}
+
+
+static v8::Handle<Value> ConstTenGetter(Local<String> name,
+                                        const AccessorInfo& info) {
+  return v8_num(10);
+}
+
+
+THREADED_TEST(CrossDomainAccessors) {
+  v8::HandleScope handle_scope;
+
+  v8::Handle<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New();
+
+  v8::Handle<v8::ObjectTemplate> global_template =
+      func_template->InstanceTemplate();
+
+  v8::Handle<v8::ObjectTemplate> proto_template =
+      func_template->PrototypeTemplate();
+
+  // Add an accessor to proto that's accessible by cross-domain JS code.
+  proto_template->SetAccessor(v8_str("accessible"),
+                              ConstTenGetter, 0,
+                              v8::Handle<Value>(),
+                              v8::ALL_CAN_READ);
+
+  // Add an accessor that is not accessible by cross-domain JS code.
+  global_template->SetAccessor(v8_str("unreachable"),
+                               UnreachableGetter, 0,
+                               v8::Handle<Value>(),
+                               v8::DEFAULT);
+
+  v8::Persistent<Context> context0 = Context::New(NULL, global_template);
+  context0->Enter();
+
+  Local<v8::Object> global = context0->Global();
+  // Add a normal property that shadows 'accessible'
+  global->Set(v8_str("accessible"), v8_num(11));
+
+  // Enter a new context.
+  v8::HandleScope scope1;
+  v8::Persistent<Context> context1 = Context::New();
+  context1->Enter();
+
+  v8::Handle<v8::Object> global1 = context1->Global();
+  global1->Set(v8_str("other"), global);
+
+  // Should return 10, instead of 11
+  v8::Handle<Value> value = v8_compile("other.accessible")->Run();
+  CHECK(value->IsNumber());
+  CHECK_EQ(10, value->Int32Value());
+
+  value = v8_compile("other.unreachable")->Run();
+  CHECK(value->IsUndefined());
+
+  context1->Exit();
+  context0->Exit();
+  context1.Dispose();
+  context0.Dispose();
+}
+
+
+static int named_access_count = 0;
+static int indexed_access_count = 0;
+
+static bool NamedAccessCounter(Local<v8::Object> global,
+                               Local<Value> name,
+                               v8::AccessType type,
+                               Local<Value> data) {
+  named_access_count++;
+  return true;
+}
+
+
+static bool IndexedAccessCounter(Local<v8::Object> global,
+                                 uint32_t key,
+                                 v8::AccessType type,
+                                 Local<Value> data) {
+  indexed_access_count++;
+  return true;
+}
+
+
+// This one is too easily disturbed by other tests.
+TEST(AccessControlIC) {
+  named_access_count = 0;
+  indexed_access_count = 0;
+
+  v8::HandleScope handle_scope;
+
+  // Create an environment.
+  v8::Persistent<Context> context0 = Context::New();
+  context0->Enter();
+
+  // Create an object that requires access-check functions to be
+  // called for cross-domain access.
+  v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
+  object_template->SetAccessCheckCallbacks(NamedAccessCounter,
+                                           IndexedAccessCounter);
+  Local<v8::Object> object = object_template->NewInstance();
+
+  v8::HandleScope scope1;
+
+  // Create another environment.
+  v8::Persistent<Context> context1 = Context::New();
+  context1->Enter();
+
+  // Make easy access to the object from the other environment.
+  v8::Handle<v8::Object> global1 = context1->Global();
+  global1->Set(v8_str("obj"), object);
+
+  v8::Handle<Value> value;
+
+  // Check that the named access-control function is called every time.
+  CompileRun("function testProp(obj) {"
+             "  for (var i = 0; i < 10; i++) obj.prop = 1;"
+             "  for (var j = 0; j < 10; j++) obj.prop;"
+             "  return obj.prop"
+             "}");
+  value = CompileRun("testProp(obj)");
+  CHECK(value->IsNumber());
+  CHECK_EQ(1, value->Int32Value());
+  CHECK_EQ(21, named_access_count);
+
+  // Check that the named access-control function is called every time.
+  CompileRun("var p = 'prop';"
+             "function testKeyed(obj) {"
+             "  for (var i = 0; i < 10; i++) obj[p] = 1;"
+             "  for (var j = 0; j < 10; j++) obj[p];"
+             "  return obj[p];"
+             "}");
+  // Use obj which requires access checks.  No inline caching is used
+  // in that case.
+  value = CompileRun("testKeyed(obj)");
+  CHECK(value->IsNumber());
+  CHECK_EQ(1, value->Int32Value());
+  CHECK_EQ(42, named_access_count);
+  // Force the inline caches into generic state and try again.
+  CompileRun("testKeyed({ a: 0 })");
+  CompileRun("testKeyed({ b: 0 })");
+  value = CompileRun("testKeyed(obj)");
+  CHECK(value->IsNumber());
+  CHECK_EQ(1, value->Int32Value());
+  CHECK_EQ(63, named_access_count);
+
+  // Check that the indexed access-control function is called every time.
+  CompileRun("function testIndexed(obj) {"
+             "  for (var i = 0; i < 10; i++) obj[0] = 1;"
+             "  for (var j = 0; j < 10; j++) obj[0];"
+             "  return obj[0]"
+             "}");
+  value = CompileRun("testIndexed(obj)");
+  CHECK(value->IsNumber());
+  CHECK_EQ(1, value->Int32Value());
+  CHECK_EQ(21, indexed_access_count);
+  // Force the inline caches into generic state.
+  CompileRun("testIndexed(new Array(1))");
+  // Test that the indexed access check is called.
+  value = CompileRun("testIndexed(obj)");
+  CHECK(value->IsNumber());
+  CHECK_EQ(1, value->Int32Value());
+  CHECK_EQ(42, indexed_access_count);
+
+  // Check that the named access check is called when invoking
+  // functions on an object that requires access checks.
+  CompileRun("obj.f = function() {}");
+  CompileRun("function testCallNormal(obj) {"
+             "  for (var i = 0; i < 10; i++) obj.f();"
+             "}");
+  CompileRun("testCallNormal(obj)");
+  CHECK_EQ(74, named_access_count);
+
+  // Force obj into slow case.
+  value = CompileRun("delete obj.prop");
+  CHECK(value->BooleanValue());
+  // Force inline caches into dictionary probing mode.
+  CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
+  // Test that the named access check is called.
+  value = CompileRun("testProp(obj);");
+  CHECK(value->IsNumber());
+  CHECK_EQ(1, value->Int32Value());
+  CHECK_EQ(96, named_access_count);
+
+  // Force the call inline cache into dictionary probing mode.
+  CompileRun("o.f = function() {}; testCallNormal(o)");
+  // Test that the named access check is still called for each
+  // invocation of the function.
+  value = CompileRun("testCallNormal(obj)");
+  CHECK_EQ(106, named_access_count);
+
+  context1->Exit();
+  context0->Exit();
+  context1.Dispose();
+  context0.Dispose();
+}
+
+
+static bool NamedAccessFlatten(Local<v8::Object> global,
+                               Local<Value> name,
+                               v8::AccessType type,
+                               Local<Value> data) {
+  char buf[100];
+  int len;
+
+  CHECK(name->IsString());
+
+  memset(buf, 0x1, sizeof(buf));
+  len = Local<String>::Cast(name)->WriteAscii(buf);
+  CHECK_EQ(4, len);
+
+  uint16_t buf2[100];
+
+  memset(buf, 0x1, sizeof(buf));
+  len = Local<String>::Cast(name)->Write(buf2);
+  CHECK_EQ(4, len);
+
+  return true;
+}
+
+
+static bool IndexedAccessFlatten(Local<v8::Object> global,
+                                 uint32_t key,
+                                 v8::AccessType type,
+                                 Local<Value> data) {
+  return true;
+}
+
+
+// Regression test.  In access checks, operations that may cause
+// garbage collection are not allowed.  It used to be the case that
+// using the Write operation on a string could cause a garbage
+// collection due to flattening of the string.  This is no longer the
+// case.
+THREADED_TEST(AccessControlFlatten) {
+  named_access_count = 0;
+  indexed_access_count = 0;
+
+  v8::HandleScope handle_scope;
+
+  // Create an environment.
+  v8::Persistent<Context> context0 = Context::New();
+  context0->Enter();
+
+  // Create an object that requires access-check functions to be
+  // called for cross-domain access.
+  v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
+  object_template->SetAccessCheckCallbacks(NamedAccessFlatten,
+                                           IndexedAccessFlatten);
+  Local<v8::Object> object = object_template->NewInstance();
+
+  v8::HandleScope scope1;
+
+  // Create another environment.
+  v8::Persistent<Context> context1 = Context::New();
+  context1->Enter();
+
+  // Make easy access to the object from the other environment.
+  v8::Handle<v8::Object> global1 = context1->Global();
+  global1->Set(v8_str("obj"), object);
+
+  v8::Handle<Value> value;
+
+  value = v8_compile("var p = 'as' + 'df';")->Run();
+  value = v8_compile("obj[p];")->Run();
+
+  context1->Exit();
+  context0->Exit();
+  context1.Dispose();
+  context0.Dispose();
+}
+
+
+static v8::Handle<Value> AccessControlNamedGetter(
+    Local<String>, const AccessorInfo&) {
+  return v8::Integer::New(42);
+}
+
+
+static v8::Handle<Value> AccessControlNamedSetter(
+    Local<String>, Local<Value> value, const AccessorInfo&) {
+  return value;
+}
+
+
+static v8::Handle<Value> AccessControlIndexedGetter(
+      uint32_t index,
+      const AccessorInfo& info) {
+  return v8_num(42);
+}
+
+
+static v8::Handle<Value> AccessControlIndexedSetter(
+    uint32_t, Local<Value> value, const AccessorInfo&) {
+  return value;
+}
+
+
+THREADED_TEST(AccessControlInterceptorIC) {
+  named_access_count = 0;
+  indexed_access_count = 0;
+
+  v8::HandleScope handle_scope;
+
+  // Create an environment.
+  v8::Persistent<Context> context0 = Context::New();
+  context0->Enter();
+
+  // Create an object that requires access-check functions to be
+  // called for cross-domain access.  The object also has interceptors
+  // interceptor.
+  v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
+  object_template->SetAccessCheckCallbacks(NamedAccessCounter,
+                                           IndexedAccessCounter);
+  object_template->SetNamedPropertyHandler(AccessControlNamedGetter,
+                                           AccessControlNamedSetter);
+  object_template->SetIndexedPropertyHandler(AccessControlIndexedGetter,
+                                             AccessControlIndexedSetter);
+  Local<v8::Object> object = object_template->NewInstance();
+
+  v8::HandleScope scope1;
+
+  // Create another environment.
+  v8::Persistent<Context> context1 = Context::New();
+  context1->Enter();
+
+  // Make easy access to the object from the other environment.
+  v8::Handle<v8::Object> global1 = context1->Global();
+  global1->Set(v8_str("obj"), object);
+
+  v8::Handle<Value> value;
+
+  // Check that the named access-control function is called every time
+  // eventhough there is an interceptor on the object.
+  value = v8_compile("for (var i = 0; i < 10; i++) obj.x = 1;")->Run();
+  value = v8_compile("for (var i = 0; i < 10; i++) obj.x;"
+                     "obj.x")->Run();
+  CHECK(value->IsNumber());
+  CHECK_EQ(42, value->Int32Value());
+  CHECK_EQ(21, named_access_count);
+
+  value = v8_compile("var p = 'x';")->Run();
+  value = v8_compile("for (var i = 0; i < 10; i++) obj[p] = 1;")->Run();
+  value = v8_compile("for (var i = 0; i < 10; i++) obj[p];"
+                     "obj[p]")->Run();
+  CHECK(value->IsNumber());
+  CHECK_EQ(42, value->Int32Value());
+  CHECK_EQ(42, named_access_count);
+
+  // Check that the indexed access-control function is called every
+  // time eventhough there is an interceptor on the object.
+  value = v8_compile("for (var i = 0; i < 10; i++) obj[0] = 1;")->Run();
+  value = v8_compile("for (var i = 0; i < 10; i++) obj[0];"
+                     "obj[0]")->Run();
+  CHECK(value->IsNumber());
+  CHECK_EQ(42, value->Int32Value());
+  CHECK_EQ(21, indexed_access_count);
+
+  context1->Exit();
+  context0->Exit();
+  context1.Dispose();
+  context0.Dispose();
+}
+
+
+THREADED_TEST(Version) {
+  v8::V8::GetVersion();
+}
+
+
+static v8::Handle<Value> InstanceFunctionCallback(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(12);
+}
+
+
+THREADED_TEST(InstanceProperties) {
+  v8::HandleScope handle_scope;
+  LocalContext context;
+
+  Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
+  Local<ObjectTemplate> instance = t->InstanceTemplate();
+
+  instance->Set(v8_str("x"), v8_num(42));
+  instance->Set(v8_str("f"),
+                v8::FunctionTemplate::New(InstanceFunctionCallback));
+
+  Local<Value> o = t->GetFunction()->NewInstance();
+
+  context->Global()->Set(v8_str("i"), o);
+  Local<Value> value = Script::Compile(v8_str("i.x"))->Run();
+  CHECK_EQ(42, value->Int32Value());
+
+  value = Script::Compile(v8_str("i.f()"))->Run();
+  CHECK_EQ(12, value->Int32Value());
+}
+
+
+static v8::Handle<Value>
+GlobalObjectInstancePropertiesGet(Local<String> key, const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  return v8::Handle<Value>();
+}
+
+
+THREADED_TEST(GlobalObjectInstanceProperties) {
+  v8::HandleScope handle_scope;
+
+  Local<Value> global_object;
+
+  Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
+  t->InstanceTemplate()->SetNamedPropertyHandler(
+      GlobalObjectInstancePropertiesGet);
+  Local<ObjectTemplate> instance_template = t->InstanceTemplate();
+  instance_template->Set(v8_str("x"), v8_num(42));
+  instance_template->Set(v8_str("f"),
+                         v8::FunctionTemplate::New(InstanceFunctionCallback));
+
+  {
+    LocalContext env(NULL, instance_template);
+    // Hold on to the global object so it can be used again in another
+    // environment initialization.
+    global_object = env->Global();
+
+    Local<Value> value = Script::Compile(v8_str("x"))->Run();
+    CHECK_EQ(42, value->Int32Value());
+    value = Script::Compile(v8_str("f()"))->Run();
+    CHECK_EQ(12, value->Int32Value());
+  }
+
+  {
+    // Create new environment reusing the global object.
+    LocalContext env(NULL, instance_template, global_object);
+    Local<Value> value = Script::Compile(v8_str("x"))->Run();
+    CHECK_EQ(42, value->Int32Value());
+    value = Script::Compile(v8_str("f()"))->Run();
+    CHECK_EQ(12, value->Int32Value());
+  }
+}
+
+
+static v8::Handle<Value> ShadowFunctionCallback(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(42);
+}
+
+
+static int shadow_y;
+static int shadow_y_setter_call_count;
+static int shadow_y_getter_call_count;
+
+
+static void ShadowYSetter(Local<String>, Local<Value>, const AccessorInfo&) {
+  shadow_y_setter_call_count++;
+  shadow_y = 42;
+}
+
+
+static v8::Handle<Value> ShadowYGetter(Local<String> name,
+                                       const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  shadow_y_getter_call_count++;
+  return v8_num(shadow_y);
+}
+
+
+static v8::Handle<Value> ShadowIndexedGet(uint32_t index,
+                                          const AccessorInfo& info) {
+  return v8::Handle<Value>();
+}
+
+
+static v8::Handle<Value> ShadowNamedGet(Local<String> key,
+                                        const AccessorInfo&) {
+  return v8::Handle<Value>();
+}
+
+
+THREADED_TEST(ShadowObject) {
+  shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
+  v8::HandleScope handle_scope;
+
+  Local<ObjectTemplate> global_template = v8::ObjectTemplate::New();
+  LocalContext context(NULL, global_template);
+
+  Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
+  t->InstanceTemplate()->SetNamedPropertyHandler(ShadowNamedGet);
+  t->InstanceTemplate()->SetIndexedPropertyHandler(ShadowIndexedGet);
+  Local<ObjectTemplate> proto = t->PrototypeTemplate();
+  Local<ObjectTemplate> instance = t->InstanceTemplate();
+
+  // Only allow calls of f on instances of t.
+  Local<v8::Signature> signature = v8::Signature::New(t);
+  proto->Set(v8_str("f"),
+             v8::FunctionTemplate::New(ShadowFunctionCallback,
+                                       Local<Value>(),
+                                       signature));
+  proto->Set(v8_str("x"), v8_num(12));
+
+  instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
+
+  Local<Value> o = t->GetFunction()->NewInstance();
+  context->Global()->Set(v8_str("__proto__"), o);
+
+  Local<Value> value =
+      Script::Compile(v8_str("propertyIsEnumerable(0)"))->Run();
+  CHECK(value->IsBoolean());
+  CHECK(!value->BooleanValue());
+
+  value = Script::Compile(v8_str("x"))->Run();
+  CHECK_EQ(12, value->Int32Value());
+
+  value = Script::Compile(v8_str("f()"))->Run();
+  CHECK_EQ(42, value->Int32Value());
+
+  Script::Compile(v8_str("y = 42"))->Run();
+  CHECK_EQ(1, shadow_y_setter_call_count);
+  value = Script::Compile(v8_str("y"))->Run();
+  CHECK_EQ(1, shadow_y_getter_call_count);
+  CHECK_EQ(42, value->Int32Value());
+}
+
+
+THREADED_TEST(HiddenPrototype) {
+  v8::HandleScope handle_scope;
+  LocalContext context;
+
+  Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
+  t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
+  Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
+  t1->SetHiddenPrototype(true);
+  t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
+  Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
+  t2->SetHiddenPrototype(true);
+  t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
+  Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
+  t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
+
+  Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
+  Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
+  Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
+  Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
+
+  // Setting the prototype on an object skips hidden prototypes.
+  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
+  o0->Set(v8_str("__proto__"), o1);
+  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
+  CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
+  o0->Set(v8_str("__proto__"), o2);
+  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
+  CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
+  CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
+  o0->Set(v8_str("__proto__"), o3);
+  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
+  CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
+  CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
+  CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
+
+  // Getting the prototype of o0 should get the first visible one
+  // which is o3.  Therefore, z should not be defined on the prototype
+  // object.
+  Local<Value> proto = o0->Get(v8_str("__proto__"));
+  CHECK(proto->IsObject());
+  CHECK(Local<v8::Object>::Cast(proto)->Get(v8_str("z"))->IsUndefined());
+}
+
+
+THREADED_TEST(GetterSetterExceptions) {
+  v8::HandleScope handle_scope;
+  LocalContext context;
+  CompileRun(
+    "function Foo() { };"
+    "function Throw() { throw 5; };"
+    "var x = { };"
+    "x.__defineSetter__('set', Throw);"
+    "x.__defineGetter__('get', Throw);");
+  Local<v8::Object> x =
+      Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
+  v8::TryCatch try_catch;
+  x->Set(v8_str("set"), v8::Integer::New(8));
+  x->Get(v8_str("get"));
+  x->Set(v8_str("set"), v8::Integer::New(8));
+  x->Get(v8_str("get"));
+  x->Set(v8_str("set"), v8::Integer::New(8));
+  x->Get(v8_str("get"));
+  x->Set(v8_str("set"), v8::Integer::New(8));
+  x->Get(v8_str("get"));
+}
+
+
+THREADED_TEST(Constructor) {
+  v8::HandleScope handle_scope;
+  LocalContext context;
+  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  templ->SetClassName(v8_str("Fun"));
+  Local<Function> cons = templ->GetFunction();
+  context->Global()->Set(v8_str("Fun"), cons);
+  Local<v8::Object> inst = cons->NewInstance();
+  i::Handle<i::JSObject> obj = v8::Utils::OpenHandle(*inst);
+  Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
+  CHECK(value->BooleanValue());
+}
+
+THREADED_TEST(FunctionDescriptorException) {
+  v8::HandleScope handle_scope;
+  LocalContext context;
+  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  templ->SetClassName(v8_str("Fun"));
+  Local<Function> cons = templ->GetFunction();
+  context->Global()->Set(v8_str("Fun"), cons);
+  Local<Value> value = CompileRun(
+    "function test() {"
+    "  try {"
+    "    (new Fun()).blah()"
+    "  } catch (e) {"
+    "    var str = String(e);"
+    "    if (str.indexOf('TypeError') == -1) return 1;"
+    "    if (str.indexOf('[object Fun]') != -1) return 2;"
+    "    if (str.indexOf('#<a Fun>') == -1) return 3;"
+    "    return 0;"
+    "  }"
+    "  return 4;"
+    "}"
+    "test();");
+  CHECK_EQ(0, value->Int32Value());
+}
+
+
+THREADED_TEST(EvalAliasedDynamic) {
+  v8::HandleScope scope;
+  LocalContext current;
+
+  // This sets 'global' to the real global object (as opposed to the
+  // proxy). It is highly implementation dependent, so take care.
+  current->Global()->Set(v8_str("global"), current->Global()->GetPrototype());
+
+  // Tests where aliased eval can only be resolved dynamically.
+  Local<Script> script =
+      Script::Compile(v8_str("function f(x) { "
+                             "  var foo = 2;"
+                             "  with (x) { return eval('foo'); }"
+                             "}"
+                             "foo = 0;"
+                             "result1 = f(new Object());"
+                             "result2 = f(global);"
+                             "var x = new Object();"
+                             "x.eval = function(x) { return 1; };"
+                             "result3 = f(x);"));
+  script->Run();
+  CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
+  CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
+  CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
+
+  v8::TryCatch try_catch;
+  script =
+    Script::Compile(v8_str("function f(x) { "
+                           "  var bar = 2;"
+                           "  with (x) { return eval('bar'); }"
+                           "}"
+                           "f(global)"));
+  script->Run();
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+}
+
+
+THREADED_TEST(CrossEval) {
+  v8::HandleScope scope;
+  LocalContext other;
+  LocalContext current;
+
+  Local<String> token = v8_str("<security token>");
+  other->SetSecurityToken(token);
+  current->SetSecurityToken(token);
+
+  // Setup reference from current to other.
+  current->Global()->Set(v8_str("other"), other->Global());
+
+  // Check that new variables are introduced in other context.
+  Local<Script> script =
+      Script::Compile(v8_str("other.eval('var foo = 1234')"));
+  script->Run();
+  Local<Value> foo = other->Global()->Get(v8_str("foo"));
+  CHECK_EQ(1234, foo->Int32Value());
+  CHECK(!current->Global()->Has(v8_str("foo")));
+
+  // Check that writing to non-existing properties introduces them in
+  // the other context.
+  script =
+      Script::Compile(v8_str("other.eval('na = 1234')"));
+  script->Run();
+  CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
+  CHECK(!current->Global()->Has(v8_str("na")));
+
+  // Check that global variables in current context are not visible in other
+  // context.
+  v8::TryCatch try_catch;
+  script =
+      Script::Compile(v8_str("var bar = 42; other.eval('bar');"));
+  Local<Value> result = script->Run();
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+
+  // Check that local variables in current context are not visible in other
+  // context.
+  script =
+      Script::Compile(v8_str("(function() { "
+                             "  var baz = 87;"
+                             "  return other.eval('baz');"
+                             "})();"));
+  result = script->Run();
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+
+  // Check that global variables in the other environment are visible
+  // when evaluting code.
+  other->Global()->Set(v8_str("bis"), v8_num(1234));
+  script = Script::Compile(v8_str("other.eval('bis')"));
+  CHECK_EQ(1234, script->Run()->Int32Value());
+  CHECK(!try_catch.HasCaught());
+
+  // Check that the 'this' pointer points to the global object evaluating
+  // code.
+  other->Global()->Set(v8_str("t"), other->Global());
+  script = Script::Compile(v8_str("other.eval('this == t')"));
+  result = script->Run();
+  CHECK(result->IsTrue());
+  CHECK(!try_catch.HasCaught());
+
+  // Check that variables introduced in with-statement are not visible in
+  // other context.
+  script =
+      Script::Compile(v8_str("with({x:2}){other.eval('x')}"));
+  result = script->Run();
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+
+  // Check that you cannot use 'eval.call' with another object than the
+  // current global object.
+  script =
+      Script::Compile(v8_str("other.y = 1; eval.call(other, 'y')"));
+  result = script->Run();
+  CHECK(try_catch.HasCaught());
+}
+
+
+THREADED_TEST(CrossLazyLoad) {
+  v8::HandleScope scope;
+  LocalContext other;
+  LocalContext current;
+
+  Local<String> token = v8_str("<security token>");
+  other->SetSecurityToken(token);
+  current->SetSecurityToken(token);
+
+  // Setup reference from current to other.
+  current->Global()->Set(v8_str("other"), other->Global());
+
+  // Trigger lazy loading in other context.
+  Local<Script> script =
+      Script::Compile(v8_str("other.eval('new Date(42)')"));
+  Local<Value> value = script->Run();
+  CHECK_EQ(42.0, value->NumberValue());
+}
+
+
+static v8::Handle<Value> call_as_function(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  return args[0];
+}
+
+
+// Test that a call handler can be set for objects which will allow
+// non-function objects created through the API to be called as
+// functions.
+THREADED_TEST(CallAsFunction) {
+  v8::HandleScope scope;
+  LocalContext context;
+
+  Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
+  Local<ObjectTemplate> instance_template = t->InstanceTemplate();
+  instance_template->SetCallAsFunctionHandler(call_as_function);
+  Local<v8::Object> instance = t->GetFunction()->NewInstance();
+  context->Global()->Set(v8_str("obj"), instance);
+  v8::TryCatch try_catch;
+  Local<Value> value;
+  CHECK(!try_catch.HasCaught());
+
+  value = Script::Compile(v8_str("obj(42)"))->Run();
+  CHECK(!try_catch.HasCaught());
+  CHECK_EQ(42, value->Int32Value());
+
+  value = Script::Compile(v8_str("(function(o){return o(49)})(obj)"))->Run();
+  CHECK(!try_catch.HasCaught());
+  CHECK_EQ(49, value->Int32Value());
+
+  // test special case of call as function
+  value = Script::Compile(v8_str("[obj]['0'](45)"))->Run();
+  CHECK(!try_catch.HasCaught());
+  CHECK_EQ(45, value->Int32Value());
+
+  value = Script::Compile(v8_str("obj.call = Function.prototype.call;"
+                                 "obj.call(null, 87)"))->Run();
+  CHECK(!try_catch.HasCaught());
+  CHECK_EQ(87, value->Int32Value());
+
+  // Regression tests for bug #1116356: Calling call through call/apply
+  // must work for non-function receivers.
+  const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
+  value = Script::Compile(v8_str(apply_99))->Run();
+  CHECK(!try_catch.HasCaught());
+  CHECK_EQ(99, value->Int32Value());
+
+  const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
+  value = Script::Compile(v8_str(call_17))->Run();
+  CHECK(!try_catch.HasCaught());
+  CHECK_EQ(17, value->Int32Value());
+
+  // Try something that will cause an exception: Call the object as a
+  // constructor. This should be the last test.
+  value = Script::Compile(v8_str("new obj(42)"))->Run();
+  CHECK(try_catch.HasCaught());
+}
+
+
+static int CountHandles() {
+  return v8::HandleScope::NumberOfHandles();
+}
+
+
+static int Recurse(int depth, int iterations) {
+  v8::HandleScope scope;
+  if (depth == 0) return CountHandles();
+  for (int i = 0; i < iterations; i++) {
+    Local<v8::Number> n = v8::Integer::New(42);
+  }
+  return Recurse(depth - 1, iterations);
+}
+
+
+THREADED_TEST(HandleIteration) {
+  static const int kIterations = 500;
+  static const int kNesting = 200;
+  CHECK_EQ(0, CountHandles());
+  {
+    v8::HandleScope scope1;
+    CHECK_EQ(0, CountHandles());
+    for (int i = 0; i < kIterations; i++) {
+      Local<v8::Number> n = v8::Integer::New(42);
+      CHECK_EQ(i + 1, CountHandles());
+    }
+
+    CHECK_EQ(kIterations, CountHandles());
+    {
+      v8::HandleScope scope2;
+      for (int j = 0; j < kIterations; j++) {
+        Local<v8::Number> n = v8::Integer::New(42);
+        CHECK_EQ(j + 1 + kIterations, CountHandles());
+      }
+    }
+    CHECK_EQ(kIterations, CountHandles());
+  }
+  CHECK_EQ(0, CountHandles());
+  CHECK_EQ(kNesting * kIterations, Recurse(kNesting, kIterations));
+}
+
+
+static v8::Handle<Value> InterceptorHasOwnPropertyGetter(
+    Local<String> name,
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  return v8::Handle<Value>();
+}
+
+
+THREADED_TEST(InterceptorHasOwnProperty) {
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
+  Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
+  instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetter);
+  Local<Function> function = fun_templ->GetFunction();
+  context->Global()->Set(v8_str("constructor"), function);
+  v8::Handle<Value> value = CompileRun(
+      "var o = new constructor();"
+      "o.hasOwnProperty('ostehaps');");
+  CHECK_EQ(false, value->BooleanValue());
+  value = CompileRun(
+      "o.ostehaps = 42;"
+      "o.hasOwnProperty('ostehaps');");
+  CHECK_EQ(true, value->BooleanValue());
+  value = CompileRun(
+      "var p = new constructor();"
+      "p.hasOwnProperty('ostehaps');");
+  CHECK_EQ(false, value->BooleanValue());
+}
+
+
+static v8::Handle<Value> InterceptorLoadICGetter(Local<String> name,
+                                                 const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(v8_str("x")->Equals(name));
+  return v8::Integer::New(42);
+}
+
+
+// This test should hit the load IC for the interceptor case.
+THREADED_TEST(InterceptorLoadIC) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(InterceptorLoadICGetter);
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ->NewInstance());
+  v8::Handle<Value> value = CompileRun(
+    "var result = 0;"
+    "for (var i = 0; i < 1000; i++) {"
+    "  result = o.x;"
+    "}");
+  CHECK_EQ(42, value->Int32Value());
+}
+
+
+static v8::Handle<Value> InterceptorStoreICSetter(
+    Local<String> key, Local<Value> value, const AccessorInfo&) {
+  CHECK(v8_str("x")->Equals(key));
+  CHECK_EQ(42, value->Int32Value());
+  return value;
+}
+
+
+// This test should hit the store IC for the interceptor case.
+THREADED_TEST(InterceptorStoreIC) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(InterceptorLoadICGetter,
+                                 InterceptorStoreICSetter);
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ->NewInstance());
+  v8::Handle<Value> value = CompileRun(
+    "for (var i = 0; i < 1000; i++) {"
+    "  o.x = 42;"
+    "}");
+}
+
+
+
+v8::Handle<Value> call_ic_function;
+v8::Handle<Value> call_ic_function2;
+v8::Handle<Value> call_ic_function3;
+
+static v8::Handle<Value> InterceptorCallICGetter(Local<String> name,
+                                                 const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(v8_str("x")->Equals(name));
+  return call_ic_function;
+}
+
+
+// This test should hit the call IC for the interceptor case.
+THREADED_TEST(InterceptorCallIC) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(InterceptorCallICGetter);
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ->NewInstance());
+  call_ic_function =
+      v8_compile("function f(x) { return x + 1; }; f")->Run();
+  v8::Handle<Value> value = CompileRun(
+    "var result = 0;"
+    "for (var i = 0; i < 1000; i++) {"
+    "  result = o.x(41);"
+    "}");
+  CHECK_EQ(42, value->Int32Value());
+}
+
+static int interceptor_call_count = 0;
+
+static v8::Handle<Value> InterceptorICRefErrorGetter(Local<String> name,
+                                                     const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) {
+    return call_ic_function2;
+  }
+  return v8::Handle<Value>();
+}
+
+
+// This test should hit load and call ICs for the interceptor case.
+// Once in a while, the interceptor will reply that a property was not
+// found in which case we should get a reference error.
+THREADED_TEST(InterceptorICReferenceErrors) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(InterceptorICRefErrorGetter);
+  LocalContext context(0, templ, v8::Handle<Value>());
+  call_ic_function2 = v8_compile("function h(x) { return x; }; h")->Run();
+  v8::Handle<Value> value = CompileRun(
+    "function f() {"
+    "  for (var i = 0; i < 1000; i++) {"
+    "    try { x; } catch(e) { return true; }"
+    "  }"
+    "  return false;"
+    "};"
+    "f();");
+  CHECK_EQ(true, value->BooleanValue());
+  interceptor_call_count = 0;
+  value = CompileRun(
+    "function g() {"
+    "  for (var i = 0; i < 1000; i++) {"
+    "    try { x(42); } catch(e) { return true; }"
+    "  }"
+    "  return false;"
+    "};"
+    "g();");
+  CHECK_EQ(true, value->BooleanValue());
+}
+
+
+static int interceptor_ic_exception_get_count = 0;
+
+static v8::Handle<Value> InterceptorICExceptionGetter(
+    Local<String> name,
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  if (v8_str("x")->Equals(name) && ++interceptor_ic_exception_get_count < 20) {
+    return call_ic_function3;
+  }
+  if (interceptor_ic_exception_get_count == 20) {
+    return v8::ThrowException(v8_num(42));
+  }
+  // Do not handle get for properties other than x.
+  return v8::Handle<Value>();
+}
+
+// Test interceptor load/call IC where the interceptor throws an
+// exception once in a while.
+THREADED_TEST(InterceptorICGetterExceptions) {
+  interceptor_ic_exception_get_count = 0;
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(InterceptorICExceptionGetter);
+  LocalContext context(0, templ, v8::Handle<Value>());
+  call_ic_function3 = v8_compile("function h(x) { return x; }; h")->Run();
+  v8::Handle<Value> value = CompileRun(
+    "function f() {"
+    "  for (var i = 0; i < 100; i++) {"
+    "    try { x; } catch(e) { return true; }"
+    "  }"
+    "  return false;"
+    "};"
+    "f();");
+  CHECK_EQ(true, value->BooleanValue());
+  interceptor_ic_exception_get_count = 0;
+  value = CompileRun(
+    "function f() {"
+    "  for (var i = 0; i < 100; i++) {"
+    "    try { x(42); } catch(e) { return true; }"
+    "  }"
+    "  return false;"
+    "};"
+    "f();");
+  CHECK_EQ(true, value->BooleanValue());
+}
+
+
+static int interceptor_ic_exception_set_count = 0;
+
+static v8::Handle<Value> InterceptorICExceptionSetter(
+      Local<String> key, Local<Value> value, const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  if (++interceptor_ic_exception_set_count > 20) {
+    return v8::ThrowException(v8_num(42));
+  }
+  // Do not actually handle setting.
+  return v8::Handle<Value>();
+}
+
+// Test interceptor store IC where the interceptor throws an exception
+// once in a while.
+THREADED_TEST(InterceptorICSetterExceptions) {
+  interceptor_ic_exception_set_count = 0;
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(0, InterceptorICExceptionSetter);
+  LocalContext context(0, templ, v8::Handle<Value>());
+  v8::Handle<Value> value = CompileRun(
+    "function f() {"
+    "  for (var i = 0; i < 100; i++) {"
+    "    try { x = 42; } catch(e) { return true; }"
+    "  }"
+    "  return false;"
+    "};"
+    "f();");
+  CHECK_EQ(true, value->BooleanValue());
+}
+
+
+// Test that we ignore null interceptors.
+THREADED_TEST(NullNamedInterceptor) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(0);
+  LocalContext context;
+  templ->Set("x", v8_num(42));
+  v8::Handle<v8::Object> obj = templ->NewInstance();
+  context->Global()->Set(v8_str("obj"), obj);
+  v8::Handle<Value> value = CompileRun("obj.x");
+  CHECK(value->IsInt32());
+  CHECK_EQ(42, value->Int32Value());
+}
+
+
+// Test that we ignore null interceptors.
+THREADED_TEST(NullIndexedInterceptor) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetIndexedPropertyHandler(0);
+  LocalContext context;
+  templ->Set("42", v8_num(42));
+  v8::Handle<v8::Object> obj = templ->NewInstance();
+  context->Global()->Set(v8_str("obj"), obj);
+  v8::Handle<Value> value = CompileRun("obj[42]");
+  CHECK(value->IsInt32());
+  CHECK_EQ(42, value->Int32Value());
+}
+
+
+static v8::Handle<Value> ParentGetter(Local<String> name,
+                                      const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(1);
+}
+
+
+static v8::Handle<Value> ChildGetter(Local<String> name,
+                                     const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(42);
+}
+
+
+THREADED_TEST(Overriding) {
+  v8::HandleScope scope;
+  LocalContext context;
+
+  // Parent template.
+  Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New();
+  Local<ObjectTemplate> parent_instance_templ =
+      parent_templ->InstanceTemplate();
+  parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
+
+  // Template that inherits from the parent template.
+  Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New();
+  Local<ObjectTemplate> child_instance_templ =
+      child_templ->InstanceTemplate();
+  child_templ->Inherit(parent_templ);
+  // Override 'f'.  The child version of 'f' should get called for child
+  // instances.
+  child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
+  // Add 'g' twice.  The 'g' added last should get called for instances.
+  child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
+  child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
+
+  // Add 'h' as an accessor to the proto template with ReadOnly attributes
+  // so 'h' can be shadowed on the instance object.
+  Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
+  child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
+      v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
+
+  // Add 'i' as an accessor to the instance template with ReadOnly attributes
+  // but the attribute does not have effect because it is duplicated with
+  // NULL setter.
+  child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
+      v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
+
+
+
+  // Instantiate the child template.
+  Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
+
+  // Check that the child function overrides the parent one.
+  context->Global()->Set(v8_str("o"), instance);
+  Local<Value> value = v8_compile("o.f")->Run();
+  // Check that the 'g' that was added last is hit.
+  CHECK_EQ(42, value->Int32Value());
+  value = v8_compile("o.g")->Run();
+  CHECK_EQ(42, value->Int32Value());
+
+  // Check 'h' can be shadowed.
+  value = v8_compile("o.h = 3; o.h")->Run();
+  CHECK_EQ(3, value->Int32Value());
+
+  // Check 'i' is cannot be shadowed or changed.
+  value = v8_compile("o.i = 3; o.i")->Run();
+  CHECK_EQ(42, value->Int32Value());
+}
+
+
+static v8::Handle<Value> IsConstructHandler(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  if (args.IsConstructCall()) {
+    return v8::Boolean::New(true);
+  }
+  return v8::Boolean::New(false);
+}
+
+
+THREADED_TEST(IsConstructCall) {
+  v8::HandleScope scope;
+
+  // Function template with call handler.
+  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  templ->SetCallHandler(IsConstructHandler);
+
+  LocalContext context;
+
+  context->Global()->Set(v8_str("f"), templ->GetFunction());
+  Local<Value> value = v8_compile("f()")->Run();
+  CHECK(!value->BooleanValue());
+  value = v8_compile("new f()")->Run();
+  CHECK(value->BooleanValue());
+}
+
+
+THREADED_TEST(ObjectProtoToString) {
+  v8::HandleScope scope;
+  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  templ->SetClassName(v8_str("MyClass"));
+
+  LocalContext context;
+
+  Local<String> customized_tostring = v8_str("customized toString");
+
+  // Replace Object.prototype.toString
+  v8_compile("Object.prototype.toString = function() {"
+                  "  return 'customized toString';"
+                  "}")->Run();
+
+  // Normal ToString call should call replaced Object.prototype.toString
+  Local<v8::Object> instance = templ->GetFunction()->NewInstance();
+  Local<String> value = instance->ToString();
+  CHECK(value->IsString() && value->Equals(customized_tostring));
+
+  // ObjectProtoToString should not call replace toString function.
+  value = instance->ObjectProtoToString();
+  CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
+
+  // Check global
+  value = context->Global()->ObjectProtoToString();
+  CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
+
+  // Check ordinary object
+  Local<Value> object = v8_compile("new Object()")->Run();
+  value = Local<v8::Object>::Cast(object)->ObjectProtoToString();
+  CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
+}
+
+
+bool ApiTestFuzzer::fuzzing_ = false;
+v8::internal::Semaphore* ApiTestFuzzer::all_tests_done_=
+  v8::internal::OS::CreateSemaphore(0);
+int ApiTestFuzzer::active_tests_;
+int ApiTestFuzzer::tests_being_run_;
+int ApiTestFuzzer::current_;
+
+
+// We are in a callback and want to switch to another thread (if we
+// are currently running the thread fuzzing test).
+void ApiTestFuzzer::Fuzz() {
+  if (!fuzzing_) return;
+  ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
+  test->ContextSwitch();
+}
+
+
+// Let the next thread go.  Since it is also waiting on the V8 lock it may
+// not start immediately.
+bool ApiTestFuzzer::NextThread() {
+  int test_position = GetNextTestNumber();
+  int test_number = RegisterThreadedTest::nth(current_)->fuzzer_->test_number_;
+  if (test_position == current_) {
+    printf("Stay with %d\n", test_number);
+    return false;
+  }
+  printf("Switch from %d to %d\n",
+         current_ < 0 ? 0 : test_number, test_position < 0 ? 0 : test_number);
+  current_ = test_position;
+  RegisterThreadedTest::nth(current_)->fuzzer_->gate_->Signal();
+  return true;
+}
+
+
+void ApiTestFuzzer::Run() {
+  // When it is our turn...
+  gate_->Wait();
+  {
+    // ... get the V8 lock and start running the test.
+    v8::Locker locker;
+    CallTest();
+  }
+  // This test finished.
+  active_ = false;
+  active_tests_--;
+  // If it was the last then signal that fact.
+  if (active_tests_ == 0) {
+    all_tests_done_->Signal();
+  } else {
+    // Otherwise select a new test and start that.
+    NextThread();
+  }
+}
+
+
+static unsigned linear_congruential_generator;
+
+
+void ApiTestFuzzer::Setup(PartOfTest part) {
+  linear_congruential_generator = i::FLAG_testing_prng_seed;
+  fuzzing_ = true;
+  int start = (part == FIRST_PART) ? 0 : (RegisterThreadedTest::count() >> 1);
+  int end = (part == FIRST_PART)
+      ? (RegisterThreadedTest::count() >> 1)
+      : RegisterThreadedTest::count();
+  active_tests_ = tests_being_run_ = end - start;
+  for (int i = 0; i < tests_being_run_; i++) {
+    RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
+  }
+  for (int i = 0; i < active_tests_; i++) {
+    RegisterThreadedTest::nth(i)->fuzzer_->Start();
+  }
+}
+
+
+static void CallTestNumber(int test_number) {
+  (RegisterThreadedTest::nth(test_number)->callback())();
+}
+
+
+void ApiTestFuzzer::RunAllTests() {
+  // Set off the first test.
+  current_ = -1;
+  NextThread();
+  // Wait till they are all done.
+  all_tests_done_->Wait();
+}
+
+
+int ApiTestFuzzer::GetNextTestNumber() {
+  int next_test;
+  do {
+    next_test = (linear_congruential_generator >> 16) % tests_being_run_;
+    linear_congruential_generator *= 1664525u;
+    linear_congruential_generator += 1013904223u;
+  } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
+  return next_test;
+}
+
+
+void ApiTestFuzzer::ContextSwitch() {
+  // If the new thread is the same as the current thread there is nothing to do.
+  if (NextThread()) {
+    // Now it can start.
+    v8::Unlocker unlocker;
+    // Wait till someone starts us again.
+    gate_->Wait();
+    // And we're off.
+  }
+}
+
+
+void ApiTestFuzzer::TearDown() {
+  fuzzing_ = false;
+  for (int i = 0; i < RegisterThreadedTest::count(); i++) {
+    ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
+    if (fuzzer != NULL) fuzzer->Join();
+  }
+}
+
+
+// Lets not be needlessly self-referential.
+TEST(Threading) {
+  ApiTestFuzzer::Setup(ApiTestFuzzer::FIRST_PART);
+  ApiTestFuzzer::RunAllTests();
+  ApiTestFuzzer::TearDown();
+}
+
+TEST(Threading2) {
+  ApiTestFuzzer::Setup(ApiTestFuzzer::SECOND_PART);
+  ApiTestFuzzer::RunAllTests();
+  ApiTestFuzzer::TearDown();
+}
+
+
+void ApiTestFuzzer::CallTest() {
+  printf("Start test %d\n", test_number_);
+  CallTestNumber(test_number_);
+  printf("End test %d\n", test_number_);
+}
+
+
+static v8::Handle<Value> ThrowInJS(const v8::Arguments& args) {
+  CHECK(v8::Locker::IsLocked());
+  ApiTestFuzzer::Fuzz();
+  v8::Unlocker unlocker;
+  const char* code = "throw 7;";
+  {
+    v8::Locker nested_locker;
+    v8::HandleScope scope;
+    v8::Handle<Value> exception;
+    { v8::TryCatch try_catch;
+      v8::Handle<Value> value = CompileRun(code);
+      CHECK(value.IsEmpty());
+      CHECK(try_catch.HasCaught());
+      // Make sure to wrap the exception in a new handle because
+      // the handle returned from the TryCatch is destroyed
+      // when the TryCatch is destroyed.
+      exception = Local<Value>::New(try_catch.Exception());
+    }
+    return v8::ThrowException(exception);
+  }
+}
+
+
+static v8::Handle<Value> ThrowInJSNoCatch(const v8::Arguments& args) {
+  CHECK(v8::Locker::IsLocked());
+  ApiTestFuzzer::Fuzz();
+  v8::Unlocker unlocker;
+  const char* code = "throw 7;";
+  {
+    v8::Locker nested_locker;
+    v8::HandleScope scope;
+    v8::Handle<Value> value = CompileRun(code);
+    CHECK(value.IsEmpty());
+    return v8_str("foo");
+  }
+}
+
+
+// These are locking tests that don't need to be run again
+// as part of the locking aggregation tests.
+TEST(NestedLockers) {
+  v8::Locker locker;
+  CHECK(v8::Locker::IsLocked());
+  v8::HandleScope scope;
+  LocalContext env;
+  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(ThrowInJS);
+  Local<Function> fun = fun_templ->GetFunction();
+  env->Global()->Set(v8_str("throw_in_js"), fun);
+  Local<Script> script = v8_compile("(function () {"
+                                    "  try {"
+                                    "    throw_in_js();"
+                                    "    return 42;"
+                                    "  } catch (e) {"
+                                    "    return e * 13;"
+                                    "  }"
+                                    "})();");
+  CHECK_EQ(91, script->Run()->Int32Value());
+}
+
+
+// These are locking tests that don't need to be run again
+// as part of the locking aggregation tests.
+TEST(NestedLockersNoTryCatch) {
+  v8::Locker locker;
+  v8::HandleScope scope;
+  LocalContext env;
+  Local<v8::FunctionTemplate> fun_templ =
+      v8::FunctionTemplate::New(ThrowInJSNoCatch);
+  Local<Function> fun = fun_templ->GetFunction();
+  env->Global()->Set(v8_str("throw_in_js"), fun);
+  Local<Script> script = v8_compile("(function () {"
+                                    "  try {"
+                                    "    throw_in_js();"
+                                    "    return 42;"
+                                    "  } catch (e) {"
+                                    "    return e * 13;"
+                                    "  }"
+                                    "})();");
+  CHECK_EQ(91, script->Run()->Int32Value());
+}
+
+
+THREADED_TEST(RecursiveLocking) {
+  v8::Locker locker;
+  {
+    v8::Locker locker2;
+    CHECK(v8::Locker::IsLocked());
+  }
+}
+
+
+static v8::Handle<Value> UnlockForAMoment(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  v8::Unlocker unlocker;
+  return v8::Undefined();
+}
+
+
+THREADED_TEST(LockUnlockLock) {
+  {
+    v8::Locker locker;
+    v8::HandleScope scope;
+    LocalContext env;
+    Local<v8::FunctionTemplate> fun_templ =
+        v8::FunctionTemplate::New(UnlockForAMoment);
+    Local<Function> fun = fun_templ->GetFunction();
+    env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
+    Local<Script> script = v8_compile("(function () {"
+                                      "  unlock_for_a_moment();"
+                                      "  return 42;"
+                                      "})();");
+    CHECK_EQ(42, script->Run()->Int32Value());
+  }
+  {
+    v8::Locker locker;
+    v8::HandleScope scope;
+    LocalContext env;
+    Local<v8::FunctionTemplate> fun_templ =
+        v8::FunctionTemplate::New(UnlockForAMoment);
+    Local<Function> fun = fun_templ->GetFunction();
+    env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
+    Local<Script> script = v8_compile("(function () {"
+                                      "  unlock_for_a_moment();"
+                                      "  return 42;"
+                                      "})();");
+    CHECK_EQ(42, script->Run()->Int32Value());
+  }
+}
+
+
+static int GetSurvivingGlobalObjectsCount() {
+  int count = 0;
+  // We need to collect all garbage twice to be sure that everything
+  // has been collected.  This is because inline caches are cleared in
+  // the first garbage collection but some of the maps have already
+  // been marked at that point.  Therefore some of the maps are not
+  // collected until the second garbage collection.
+  v8::internal::Heap::CollectAllGarbage();
+  v8::internal::Heap::CollectAllGarbage();
+  v8::internal::HeapIterator it;
+  while (it.has_next()) {
+    v8::internal::HeapObject* object = it.next();
+    if (object->IsJSGlobalObject()) {
+      count++;
+    }
+  }
+#ifdef DEBUG
+  if (count > 0) v8::internal::Heap::TracePathToGlobal();
+#endif
+  return count;
+}
+
+
+TEST(DontLeakGlobalObjects) {
+  // Regression test for issues 1139850 and 1174891.
+
+  v8::V8::Initialize();
+
+  int count = GetSurvivingGlobalObjectsCount();
+
+  for (int i = 0; i < 5; i++) {
+    { v8::HandleScope scope;
+      LocalContext context;
+    }
+    CHECK_EQ(count, GetSurvivingGlobalObjectsCount());
+
+    { v8::HandleScope scope;
+      LocalContext context;
+      v8_compile("Date")->Run();
+    }
+    CHECK_EQ(count, GetSurvivingGlobalObjectsCount());
+
+    { v8::HandleScope scope;
+      LocalContext context;
+      v8_compile("/aaa/")->Run();
+    }
+    CHECK_EQ(count, GetSurvivingGlobalObjectsCount());
+
+    { v8::HandleScope scope;
+      const char* extension_list[] = { "v8/gc" };
+      v8::ExtensionConfiguration extensions(1, extension_list);
+      LocalContext context(&extensions);
+      v8_compile("gc();")->Run();
+    }
+    CHECK_EQ(count, GetSurvivingGlobalObjectsCount());
+  }
+}
+
+
+THREADED_TEST(CheckForCrossContextObjectLiterals) {
+  v8::V8::Initialize();
+
+  const int nof = 2;
+  const char* sources[nof] = {
+    "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
+    "Object()"
+  };
+
+  for (int i = 0; i < nof; i++) {
+    const char* source = sources[i];
+    { v8::HandleScope scope;
+      LocalContext context;
+      CompileRun(source);
+    }
+    { v8::HandleScope scope;
+      LocalContext context;
+      CompileRun(source);
+    }
+  }
+}
+
+
+static v8::Handle<Value> NestedScope(v8::Persistent<Context> env) {
+  v8::HandleScope inner;
+  env->Enter();
+  v8::Handle<Value> three = v8_num(3);
+  v8::Handle<Value> value = inner.Close(three);
+  env->Exit();
+  return value;
+}
+
+
+THREADED_TEST(NestedHandleScopeAndContexts) {
+  v8::HandleScope outer;
+  v8::Persistent<Context> env = Context::New();
+  env->Enter();
+  v8::Handle<Value> value = NestedScope(env);
+  v8::Handle<String> str = value->ToString();
+  env->Exit();
+  env.Dispose();
+}
+
+
+THREADED_TEST(ExternalAllocatedMemory) {
+  v8::HandleScope outer;
+  const int kSize = 1024*1024;
+  CHECK_EQ(v8::V8::AdjustAmountOfExternalAllocatedMemory(kSize), kSize);
+  CHECK_EQ(v8::V8::AdjustAmountOfExternalAllocatedMemory(-kSize), 0);
+}
+
+
+THREADED_TEST(DisposeEnteredContext) {
+  v8::HandleScope scope;
+  LocalContext outer;
+  { v8::Persistent<v8::Context> inner = v8::Context::New();
+    inner->Enter();
+    inner.Dispose();
+    inner.Clear();
+    inner->Exit();
+  }
+}
+
+
+// Regression test for issue 54, object templates with internal fields
+// but no accessors or interceptors did not get their internal field
+// count set on instances.
+THREADED_TEST(Regress54) {
+  v8::HandleScope outer;
+  LocalContext context;
+  static v8::Persistent<v8::ObjectTemplate> templ;
+  if (templ.IsEmpty()) {
+    v8::HandleScope inner;
+    v8::Handle<v8::ObjectTemplate> local = v8::ObjectTemplate::New();
+    local->SetInternalFieldCount(1);
+    templ = v8::Persistent<v8::ObjectTemplate>::New(inner.Close(local));
+  }
+  v8::Handle<v8::Object> result = templ->NewInstance();
+  CHECK_EQ(1, result->InternalFieldCount());
+}
+
+
+// If part of the threaded tests, this test makes ThreadingTest fail
+// on mac.
+TEST(CatchStackOverflow) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::TryCatch try_catch;
+  v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(
+    "function f() {"
+    "  return f();"
+    "}"
+    ""
+    "f();"));
+  v8::Handle<v8::Value> result = script->Run();
+  CHECK(result.IsEmpty());
+}
+
+
+static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
+                                    const char* resource_name,
+                                    int line_offset) {
+  v8::HandleScope scope;
+  v8::TryCatch try_catch;
+  v8::Handle<v8::Value> result = script->Run();
+  CHECK(result.IsEmpty());
+  CHECK(try_catch.HasCaught());
+  v8::Handle<v8::Message> message = try_catch.Message();
+  CHECK(!message.IsEmpty());
+  CHECK_EQ(10 + line_offset, message->GetLineNumber());
+  CHECK_EQ(91, message->GetStartPosition());
+  CHECK_EQ(92, message->GetEndPosition());
+  CHECK_EQ(2, message->GetStartColumn());
+  CHECK_EQ(3, message->GetEndColumn());
+  v8::String::AsciiValue line(message->GetSourceLine());
+  CHECK_EQ("  throw 'nirk';", *line);
+  v8::String::AsciiValue name(message->GetScriptResourceName());
+  CHECK_EQ(resource_name, *name);
+}
+
+
+THREADED_TEST(TryCatchSourceInfo) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::Handle<v8::String> source = v8::String::New(
+      "function Foo() {\n"
+      "  return Bar();\n"
+      "}\n"
+      "\n"
+      "function Bar() {\n"
+      "  return Baz();\n"
+      "}\n"
+      "\n"
+      "function Baz() {\n"
+      "  throw 'nirk';\n"
+      "}\n"
+      "\n"
+      "Foo();\n");
+
+  const char* resource_name;
+  v8::Handle<v8::Script> script;
+  resource_name = "test.js";
+  script = v8::Script::Compile(source, v8::String::New(resource_name));
+  CheckTryCatchSourceInfo(script, resource_name, 0);
+
+  resource_name = "test1.js";
+  v8::ScriptOrigin origin1(v8::String::New(resource_name));
+  script = v8::Script::Compile(source, &origin1);
+  CheckTryCatchSourceInfo(script, resource_name, 0);
+
+  resource_name = "test2.js";
+  v8::ScriptOrigin origin2(v8::String::New(resource_name), v8::Integer::New(7));
+  script = v8::Script::Compile(source, &origin2);
+  CheckTryCatchSourceInfo(script, resource_name, 7);
+}
+
+
+THREADED_TEST(CompilationCache) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::Handle<v8::String> source0 = v8::String::New("1234");
+  v8::Handle<v8::String> source1 = v8::String::New("1234");
+  v8::Handle<v8::Script> script0 =
+      v8::Script::Compile(source0, v8::String::New("test.js"));
+  v8::Handle<v8::Script> script1 =
+      v8::Script::Compile(source1, v8::String::New("test.js"));
+  v8::Handle<v8::Script> script2 =
+      v8::Script::Compile(source0);  // different origin
+  CHECK_EQ(1234, script0->Run()->Int32Value());
+  CHECK_EQ(1234, script1->Run()->Int32Value());
+  CHECK_EQ(1234, script2->Run()->Int32Value());
+}
+
+
+static v8::Handle<Value> FunctionNameCallback(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(42);
+}
+
+
+THREADED_TEST(CallbackFunctionName) {
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<ObjectTemplate> t = ObjectTemplate::New();
+  t->Set(v8_str("asdf"), v8::FunctionTemplate::New(FunctionNameCallback));
+  context->Global()->Set(v8_str("obj"), t->NewInstance());
+  v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
+  CHECK(value->IsString());
+  v8::String::AsciiValue name(value);
+  CHECK_EQ("asdf", *name);
+}
+
+
+THREADED_TEST(DateAccess) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::Handle<v8::Value> date = v8::Date::New(1224744689038.0);
+  CHECK(date->IsDate());
+  CHECK_EQ(1224744689038.0, v8::Handle<v8::Date>::Cast(date)->NumberValue());
+}
+
+
+void CheckProperties(v8::Handle<v8::Value> val, int elmc, const char* elmv[]) {
+  v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(val);
+  v8::Handle<v8::Array> props = obj->GetPropertyNames();
+  CHECK_EQ(elmc, props->Length());
+  for (int i = 0; i < elmc; i++) {
+    v8::String::Utf8Value elm(props->Get(v8::Integer::New(i)));
+    CHECK_EQ(elmv[i], *elm);
+  }
+}
+
+
+THREADED_TEST(PropertyEnumeration) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::New(
+      "var result = [];"
+      "result[0] = {};"
+      "result[1] = {a: 1, b: 2};"
+      "result[2] = [1, 2, 3];"
+      "var proto = {x: 1, y: 2, z: 3};"
+      "var x = { __proto__: proto, w: 0, z: 1 };"
+      "result[3] = x;"
+      "result;"))->Run();
+  v8::Handle<v8::Array> elms = v8::Handle<v8::Array>::Cast(obj);
+  CHECK_EQ(4, elms->Length());
+  int elmc0 = 0;
+  const char** elmv0 = NULL;
+  CheckProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
+  int elmc1 = 2;
+  const char* elmv1[] = {"a", "b"};
+  CheckProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1);
+  int elmc2 = 3;
+  const char* elmv2[] = {"0", "1", "2"};
+  CheckProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2);
+  int elmc3 = 4;
+  const char* elmv3[] = {"w", "z", "x", "y"};
+  CheckProperties(elms->Get(v8::Integer::New(3)), elmc3, elmv3);
+}
+
+
+static v8::Handle<Value> AccessorProhibitsOverwritingGetter(
+    Local<String> name,
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  return v8::True();
+}
+
+
+THREADED_TEST(AccessorProhibitsOverwriting) {
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetAccessor(v8_str("x"),
+                     AccessorProhibitsOverwritingGetter,
+                     0,
+                     v8::Handle<Value>(),
+                     v8::PROHIBITS_OVERWRITING,
+                     v8::ReadOnly);
+  Local<v8::Object> instance = templ->NewInstance();
+  context->Global()->Set(v8_str("obj"), instance);
+  Local<Value> value = CompileRun(
+      "obj.__defineGetter__('x', function() { return false; });"
+      "obj.x");
+  CHECK(value->BooleanValue());
+  value = CompileRun(
+      "var setter_called = false;"
+      "obj.__defineSetter__('x', function() { setter_called = true; });"
+      "obj.x = 42;"
+      "setter_called");
+  CHECK(!value->BooleanValue());
+  value = CompileRun(
+      "obj2 = {};"
+      "obj2.__proto__ = obj;"
+      "obj2.__defineGetter__('x', function() { return false; });"
+      "obj2.x");
+  CHECK(value->BooleanValue());
+  value = CompileRun(
+      "var setter_called = false;"
+      "obj2 = {};"
+      "obj2.__proto__ = obj;"
+      "obj2.__defineSetter__('x', function() { setter_called = true; });"
+      "obj2.x = 42;"
+      "setter_called");
+  CHECK(!value->BooleanValue());
+}
+
+
+static bool NamedSetAccessBlocker(Local<v8::Object> obj,
+                                  Local<Value> name,
+                                  v8::AccessType type,
+                                  Local<Value> data) {
+  return type != v8::ACCESS_SET;
+}
+
+
+static bool IndexedSetAccessBlocker(Local<v8::Object> obj,
+                                    uint32_t key,
+                                    v8::AccessType type,
+                                    Local<Value> data) {
+  return type != v8::ACCESS_SET;
+}
+
+
+THREADED_TEST(DisableAccessChecksWhileConfiguring) {
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
+                                 IndexedSetAccessBlocker);
+  templ->Set(v8_str("x"), v8::True());
+  Local<v8::Object> instance = templ->NewInstance();
+  context->Global()->Set(v8_str("obj"), instance);
+  Local<Value> value = CompileRun("obj.x");
+  CHECK(value->BooleanValue());
+}
+
+static bool NamedGetAccessBlocker(Local<v8::Object> obj,
+                                  Local<Value> name,
+                                  v8::AccessType type,
+                                  Local<Value> data) {
+  return false;
+}
+
+
+static bool IndexedGetAccessBlocker(Local<v8::Object> obj,
+                                    uint32_t key,
+                                    v8::AccessType type,
+                                    Local<Value> data) {
+  return false;
+}
+
+
+
+THREADED_TEST(AccessChecksReenabledCorrectly) {
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetAccessCheckCallbacks(NamedGetAccessBlocker,
+                                 IndexedGetAccessBlocker);
+  templ->Set(v8_str("a"), v8_str("a"));
+  // Add more than 8 (see kMaxFastProperties) properties
+  // so that the constructor will force copying map.
+  // Cannot sprintf, gcc complains unsafety.
+  char buf[4];
+  for (char i = '0'; i <= '9' ; i++) {
+    buf[0] = i;
+    for (char j = '0'; j <= '9'; j++) {
+      buf[1] = j;
+      for (char k = '0'; k <= '9'; k++) {
+        buf[2] = k;
+        buf[3] = 0;
+        templ->Set(v8_str(buf), v8::Number::New(k));
+      }
+    }
+  }
+
+  Local<v8::Object> instance_1 = templ->NewInstance();
+  context->Global()->Set(v8_str("obj_1"), instance_1);
+
+  Local<Value> value_1 = CompileRun("obj_1.a");
+  CHECK(value_1->IsUndefined());
+
+  Local<v8::Object> instance_2 = templ->NewInstance();
+  context->Global()->Set(v8_str("obj_2"), instance_2);
+
+  Local<Value> value_2 = CompileRun("obj_2.a");
+  CHECK(value_2->IsUndefined());
+}
+
+// This tests that access check information remains on the global
+// object template when creating contexts.
+THREADED_TEST(AccessControlRepeatedContextCreation) {
+  v8::HandleScope handle_scope;
+  v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
+  global_template->SetAccessCheckCallbacks(NamedSetAccessBlocker,
+                                           IndexedSetAccessBlocker);
+  i::Handle<i::ObjectTemplateInfo> internal_template =
+      v8::Utils::OpenHandle(*global_template);
+  CHECK(!internal_template->constructor()->IsUndefined());
+  i::Handle<i::FunctionTemplateInfo> constructor(
+      i::FunctionTemplateInfo::cast(internal_template->constructor()));
+  CHECK(!constructor->access_check_info()->IsUndefined());
+  v8::Persistent<Context> context0 = Context::New(NULL, global_template);
+  CHECK(!constructor->access_check_info()->IsUndefined());
+}
+
+
+// This test verifies that pre-compilation (aka preparsing) can be called
+// without initializing the whole VM. Thus we cannot run this test in a
+// multi-threaded setup.
+TEST(PreCompile) {
+  // TODO(155): This test would break without the initialization of V8. This is
+  // a workaround for now to make this test not fail.
+  v8::V8::Initialize();
+  const char *script = "function foo(a) { return a+1; }";
+  v8::ScriptData *sd = v8::ScriptData::PreCompile(script, strlen(script));
+  CHECK_NE(sd->Length(), 0);
+  CHECK_NE(sd->Data(), NULL);
+  delete sd;
+}
+
+
+// This tests that we do not allow dictionary load/call inline caches
+// to use functions that have not yet been compiled.  The potential
+// problem of loading a function that has not yet been compiled can
+// arise because we share code between contexts via the compilation
+// cache.
+THREADED_TEST(DictionaryICLoadedFunction) {
+  v8::HandleScope scope;
+  // Test LoadIC.
+  for (int i = 0; i < 2; i++) {
+    LocalContext context;
+    context->Global()->Set(v8_str("tmp"), v8::True());
+    context->Global()->Delete(v8_str("tmp"));
+    CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
+  }
+  // Test CallIC.
+  for (int i = 0; i < 2; i++) {
+    LocalContext context;
+    context->Global()->Set(v8_str("tmp"), v8::True());
+    context->Global()->Delete(v8_str("tmp"));
+    CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
+  }
+}
+
+
+// Test that cross-context new calls use the context of the callee to
+// create the new JavaScript object.
+THREADED_TEST(CrossContextNew) {
+  v8::HandleScope scope;
+  v8::Persistent<Context> context0 = Context::New();
+  v8::Persistent<Context> context1 = Context::New();
+
+  // Allow cross-domain access.
+  Local<String> token = v8_str("<security token>");
+  context0->SetSecurityToken(token);
+  context1->SetSecurityToken(token);
+
+  // Set an 'x' property on the Object prototype and define a
+  // constructor function in context0.
+  context0->Enter();
+  CompileRun("Object.prototype.x = 42; function C() {};");
+  context0->Exit();
+
+  // Call the constructor function from context0 and check that the
+  // result has the 'x' property.
+  context1->Enter();
+  context1->Global()->Set(v8_str("other"), context0->Global());
+  Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
+  CHECK(value->IsInt32());
+  CHECK_EQ(42, value->Int32Value());
+  context1->Exit();
+
+  // Dispose the contexts to allow them to be garbage collected.
+  context0.Dispose();
+  context1.Dispose();
+}
+
+
+class RegExpInterruptTest {
+ public:
+  RegExpInterruptTest() : block_(NULL) {}
+  ~RegExpInterruptTest() { delete block_; }
+  void RunTest() {
+    block_ = i::OS::CreateSemaphore(0);
+    gc_count_ = 0;
+    gc_during_regexp_ = 0;
+    regexp_success_ = false;
+    gc_success_ = false;
+    GCThread gc_thread(this);
+    gc_thread.Start();
+    v8::Locker::StartPreemption(1);
+
+    LongRunningRegExp();
+    {
+      v8::Unlocker unlock;
+      gc_thread.Join();
+    }
+    v8::Locker::StopPreemption();
+    CHECK(regexp_success_);
+    CHECK(gc_success_);
+  }
+ private:
+  // Number of garbage collections required.
+  static const int kRequiredGCs = 5;
+
+  class GCThread : public i::Thread {
+   public:
+    explicit GCThread(RegExpInterruptTest* test)
+        : test_(test) {}
+    virtual void Run() {
+      test_->CollectGarbage();
+    }
+   private:
+     RegExpInterruptTest* test_;
+  };
+
+  void CollectGarbage() {
+    block_->Wait();
+    while (gc_during_regexp_ < kRequiredGCs) {
+      {
+        v8::Locker lock;
+        // TODO(lrn): Perhaps create some garbage before collecting.
+        i::Heap::CollectAllGarbage();
+        gc_count_++;
+      }
+      i::OS::Sleep(1);
+    }
+    gc_success_ = true;
+  }
+
+  void LongRunningRegExp() {
+    block_->Signal();  // Enable garbage collection thread on next preemption.
+    int rounds = 0;
+    while (gc_during_regexp_ < kRequiredGCs) {
+      int gc_before = gc_count_;
+      {
+        // Match 15-30 "a"'s against 14 and a "b".
+        const char* c_source =
+            "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
+            ".exec('aaaaaaaaaaaaaaab') === null";
+        Local<String> source = String::New(c_source);
+        Local<Script> script = Script::Compile(source);
+        Local<Value> result = script->Run();
+        if (!result->BooleanValue()) {
+          gc_during_regexp_ = kRequiredGCs;  // Allow gc thread to exit.
+          return;
+        }
+      }
+      {
+        // Match 15-30 "a"'s against 15 and a "b".
+        const char* c_source =
+            "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
+            ".exec('aaaaaaaaaaaaaaaab')[0] === 'aaaaaaaaaaaaaaaa'";
+        Local<String> source = String::New(c_source);
+        Local<Script> script = Script::Compile(source);
+        Local<Value> result = script->Run();
+        if (!result->BooleanValue()) {
+          gc_during_regexp_ = kRequiredGCs;
+          return;
+        }
+      }
+      int gc_after = gc_count_;
+      gc_during_regexp_ += gc_after - gc_before;
+      rounds++;
+      i::OS::Sleep(1);
+    }
+    regexp_success_ = true;
+  }
+
+  i::Semaphore* block_;
+  int gc_count_;
+  int gc_during_regexp_;
+  bool regexp_success_;
+  bool gc_success_;
+};
+
+
+// Test that a regular expression execution can be interrupted and
+// survive a garbage collection.
+TEST(RegExpInterruption) {
+  v8::Locker lock;
+  v8::V8::Initialize();
+  v8::HandleScope scope;
+  Local<Context> local_env;
+  {
+    LocalContext env;
+    local_env = env.local();
+  }
+
+  // Local context should still be live.
+  CHECK(!local_env.IsEmpty());
+  local_env->Enter();
+
+  // Should complete without problems.
+  RegExpInterruptTest().RunTest();
+
+  local_env->Exit();
+}
+
+
+// Verify that we can clone an object
+TEST(ObjectClone) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  const char* sample =
+    "var rv = {};"      \
+    "rv.alpha = 'hello';" \
+    "rv.beta = 123;"     \
+    "rv;";
+
+  // Create an object, verify basics.
+  Local<Value> val = CompileRun(sample);
+  CHECK(val->IsObject());
+  Local<v8::Object> obj = Local<v8::Object>::Cast(val);
+  obj->Set(v8_str("gamma"), v8_str("cloneme"));
+
+  CHECK_EQ(v8_str("hello"), obj->Get(v8_str("alpha")));
+  CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta")));
+  CHECK_EQ(v8_str("cloneme"), obj->Get(v8_str("gamma")));
+
+  // Clone it.
+  Local<v8::Object> clone = obj->Clone();
+  CHECK_EQ(v8_str("hello"), clone->Get(v8_str("alpha")));
+  CHECK_EQ(v8::Integer::New(123), clone->Get(v8_str("beta")));
+  CHECK_EQ(v8_str("cloneme"), clone->Get(v8_str("gamma")));
+
+  // Set a property on the clone, verify each object.
+  clone->Set(v8_str("beta"), v8::Integer::New(456));
+  CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta")));
+  CHECK_EQ(v8::Integer::New(456), clone->Get(v8_str("beta")));
+}
+
+
+class RegExpStringModificationTest {
+ public:
+  RegExpStringModificationTest()
+      : block_(i::OS::CreateSemaphore(0)),
+        morphs_(0),
+        morphs_during_regexp_(0),
+        ascii_resource_(i::Vector<const char>("aaaaaaaaaaaaaab", 15)),
+        uc16_resource_(i::Vector<const uint16_t>(two_byte_content_, 15)) {}
+  ~RegExpStringModificationTest() { delete block_; }
+  void RunTest() {
+    regexp_success_ = false;
+    morph_success_ = false;
+
+    // Initialize the contents of two_byte_content_ to be a uc16 representation
+    // of "aaaaaaaaaaaaaab".
+    for (int i = 0; i < 14; i++) {
+      two_byte_content_[i] = 'a';
+    }
+    two_byte_content_[14] = 'b';
+
+    // Create the input string for the regexp - the one we are going to change
+    // properties of.
+    input_ = i::Factory::NewExternalStringFromAscii(&ascii_resource_);
+
+    // Inject the input as a global variable.
+    i::Handle<i::String> input_name =
+        i::Factory::NewStringFromAscii(i::Vector<const char>("input", 5));
+    i::Top::global_context()->global()->SetProperty(*input_name, *input_, NONE);
+
+
+    MorphThread morph_thread(this);
+    morph_thread.Start();
+    v8::Locker::StartPreemption(1);
+    LongRunningRegExp();
+    {
+      v8::Unlocker unlock;
+      morph_thread.Join();
+    }
+    v8::Locker::StopPreemption();
+    CHECK(regexp_success_);
+    CHECK(morph_success_);
+  }
+ private:
+
+  class AsciiVectorResource : public v8::String::ExternalAsciiStringResource {
+   public:
+    explicit AsciiVectorResource(i::Vector<const char> vector)
+        : data_(vector) {}
+    virtual ~AsciiVectorResource() {}
+    virtual size_t length() const { return data_.length(); }
+    virtual const char* data() const { return data_.start(); }
+   private:
+    i::Vector<const char> data_;
+  };
+  class UC16VectorResource : public v8::String::ExternalStringResource {
+   public:
+    explicit UC16VectorResource(i::Vector<const i::uc16> vector)
+        : data_(vector) {}
+    virtual ~UC16VectorResource() {}
+    virtual size_t length() const { return data_.length(); }
+    virtual const i::uc16* data() const { return data_.start(); }
+   private:
+    i::Vector<const i::uc16> data_;
+  };
+  // Number of string modifications required.
+  static const int kRequiredModifications = 5;
+  static const int kMaxModifications = 100;
+
+  class MorphThread : public i::Thread {
+   public:
+    explicit MorphThread(RegExpStringModificationTest* test)
+        : test_(test) {}
+    virtual void Run() {
+      test_->MorphString();
+    }
+   private:
+     RegExpStringModificationTest* test_;
+  };
+
+  void MorphString() {
+    block_->Wait();
+    while (morphs_during_regexp_ < kRequiredModifications &&
+           morphs_ < kMaxModifications) {
+      {
+        v8::Locker lock;
+        // Swap string between ascii and two-byte representation.
+        i::String* string = *input_;
+        CHECK(i::StringShape(string).IsExternal());
+        if (i::StringShape(string).IsAsciiRepresentation()) {
+          // Morph external string to be TwoByte string.
+          i::ExternalAsciiString* ext_string =
+              i::ExternalAsciiString::cast(string);
+          i::ExternalTwoByteString* morphed =
+              reinterpret_cast<i::ExternalTwoByteString*>(ext_string);
+          morphed->map()->set_instance_type(i::SHORT_EXTERNAL_STRING_TYPE);
+          morphed->set_resource(&uc16_resource_);
+        } else {
+          // Morph external string to be ASCII string.
+          i::ExternalTwoByteString* ext_string =
+              i::ExternalTwoByteString::cast(string);
+          i::ExternalAsciiString* morphed =
+              reinterpret_cast<i::ExternalAsciiString*>(ext_string);
+          morphed->map()->set_instance_type(
+              i::SHORT_EXTERNAL_ASCII_STRING_TYPE);
+          morphed->set_resource(&ascii_resource_);
+        }
+        morphs_++;
+      }
+      i::OS::Sleep(1);
+    }
+    morph_success_ = true;
+  }
+
+  void LongRunningRegExp() {
+    block_->Signal();  // Enable morphing thread on next preemption.
+    while (morphs_during_regexp_ < kRequiredModifications &&
+           morphs_ < kMaxModifications) {
+      int morphs_before = morphs_;
+      {
+        // Match 15-30 "a"'s against 14 and a "b".
+        const char* c_source =
+            "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
+            ".exec(input) === null";
+        Local<String> source = String::New(c_source);
+        Local<Script> script = Script::Compile(source);
+        Local<Value> result = script->Run();
+        CHECK(result->IsTrue());
+      }
+      int morphs_after = morphs_;
+      morphs_during_regexp_ += morphs_after - morphs_before;
+    }
+    regexp_success_ = true;
+  }
+
+  i::uc16 two_byte_content_[15];
+  i::Semaphore* block_;
+  int morphs_;
+  int morphs_during_regexp_;
+  bool regexp_success_;
+  bool morph_success_;
+  i::Handle<i::String> input_;
+  AsciiVectorResource ascii_resource_;
+  UC16VectorResource uc16_resource_;
+};
+
+
+// Test that a regular expression execution can be interrupted and
+// the string changed without failing.
+TEST(RegExpStringModification) {
+  v8::Locker lock;
+  v8::V8::Initialize();
+  v8::HandleScope scope;
+  Local<Context> local_env;
+  {
+    LocalContext env;
+    local_env = env.local();
+  }
+
+  // Local context should still be live.
+  CHECK(!local_env.IsEmpty());
+  local_env->Enter();
+
+  // Should complete without problems.
+  RegExpStringModificationTest().RunTest();
+
+  local_env->Exit();
+}
+
+
+// Test that we can set a property on the global object even if there
+// is a read-only property in the prototype chain.
+TEST(ReadOnlyPropertyInGlobalProto) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
+  LocalContext context(0, templ);
+  v8::Handle<v8::Object> global = context->Global();
+  v8::Handle<v8::Object> global_proto =
+      v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
+  global_proto->Set(v8_str("x"), v8::Integer::New(0), v8::ReadOnly);
+  global_proto->Set(v8_str("y"), v8::Integer::New(0), v8::ReadOnly);
+  // Check without 'eval' or 'with'.
+  v8::Handle<v8::Value> res =
+      CompileRun("function f() { x = 42; return x; }; f()");
+  // Check with 'eval'.
+  res = CompileRun("function f() { eval('1'); y = 42; return y; }; f()");
+  CHECK_EQ(v8::Integer::New(42), res);
+  // Check with 'with'.
+  res = CompileRun("function f() { with (this) { y = 42 }; return y; }; f()");
+  CHECK_EQ(v8::Integer::New(42), res);
+}
diff --git a/deps/v8/test/cctest/test-assembler-arm.cc b/deps/v8/test/cctest/test-assembler-arm.cc
new file mode 100644
index 0000000..bd75a04
--- /dev/null
+++ b/deps/v8/test/cctest/test-assembler-arm.cc
@@ -0,0 +1,227 @@
+// 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.
+
+#include "v8.h"
+
+#include "disassembler.h"
+#include "factory.h"
+#include "simulator-arm.h"
+#include "assembler-arm-inl.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+
+// Define these function prototypes to match JSEntryFunction in execution.cc.
+typedef int (*F1)(int x, int p1, int p2, int p3, int p4);
+typedef int (*F2)(int x, int y, int p2, int p3, int p4);
+typedef int (*F3)(void* p, int p1, int p2, int p3, int p4);
+
+
+static v8::Persistent<v8::Context> env;
+
+
+// The test framework does not accept flags on the command line, so we set them
+static void InitializeVM() {
+  // disable compilation of natives by specifying an empty natives file
+  FLAG_natives_file = "";
+
+  // enable generation of comments
+  FLAG_debug_code = true;
+
+  if (env.IsEmpty()) {
+    env = v8::Context::New();
+  }
+}
+
+
+#define __ assm.
+
+TEST(0) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  Assembler assm(NULL, 0);
+
+  __ add(r0, r0, Operand(r1));
+  __ mov(pc, Operand(lr));
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code = Heap::CreateCode(desc,
+                                  NULL,
+                                  Code::ComputeFlags(Code::STUB),
+                                  Handle<Object>(Heap::undefined_value()));
+  CHECK(code->IsCode());
+#ifdef DEBUG
+  Code::cast(code)->Print();
+#endif
+  F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
+  int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 3, 4, 0, 0, 0));
+  ::printf("f() = %d\n", res);
+  CHECK_EQ(7, res);
+}
+
+
+TEST(1) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  Assembler assm(NULL, 0);
+  Label L, C;
+
+  __ mov(r1, Operand(r0));
+  __ mov(r0, Operand(0));
+  __ b(&C);
+
+  __ bind(&L);
+  __ add(r0, r0, Operand(r1));
+  __ sub(r1, r1, Operand(1));
+
+  __ bind(&C);
+  __ teq(r1, Operand(0));
+  __ b(ne, &L);
+  __ mov(pc, Operand(lr));
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code = Heap::CreateCode(desc,
+                                  NULL,
+                                  Code::ComputeFlags(Code::STUB),
+                                  Handle<Object>(Heap::undefined_value()));
+  CHECK(code->IsCode());
+#ifdef DEBUG
+  Code::cast(code)->Print();
+#endif
+  F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
+  int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 100, 0, 0, 0, 0));
+  ::printf("f() = %d\n", res);
+  CHECK_EQ(5050, res);
+}
+
+
+TEST(2) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  Assembler assm(NULL, 0);
+  Label L, C;
+
+  __ mov(r1, Operand(r0));
+  __ mov(r0, Operand(1));
+  __ b(&C);
+
+  __ bind(&L);
+  __ mul(r0, r1, r0);
+  __ sub(r1, r1, Operand(1));
+
+  __ bind(&C);
+  __ teq(r1, Operand(0));
+  __ b(ne, &L);
+  __ mov(pc, Operand(lr));
+
+  // some relocated stuff here, not executed
+  __ RecordComment("dead code, just testing relocations");
+  __ mov(r0, Operand(Factory::true_value()));
+  __ RecordComment("dead code, just testing immediate operands");
+  __ mov(r0, Operand(-1));
+  __ mov(r0, Operand(0xFF000000));
+  __ mov(r0, Operand(0xF0F0F0F0));
+  __ mov(r0, Operand(0xFFF0FFFF));
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code = Heap::CreateCode(desc,
+                                  NULL,
+                                  Code::ComputeFlags(Code::STUB),
+                                  Handle<Object>(Heap::undefined_value()));
+  CHECK(code->IsCode());
+#ifdef DEBUG
+  Code::cast(code)->Print();
+#endif
+  F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
+  int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 10, 0, 0, 0, 0));
+  ::printf("f() = %d\n", res);
+  CHECK_EQ(3628800, res);
+}
+
+
+TEST(3) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  typedef struct {
+    int i;
+    char c;
+    int16_t s;
+  } T;
+  T t;
+
+  Assembler assm(NULL, 0);
+  Label L, C;
+
+  __ mov(ip, Operand(sp));
+  __ stm(db_w, sp, r4.bit() | fp.bit() | sp.bit() | lr.bit());
+  __ sub(fp, ip, Operand(4));
+  __ mov(r4, Operand(r0));
+  __ ldr(r0, MemOperand(r4, OFFSET_OF(T, i)));
+  __ mov(r2, Operand(r0, ASR, 1));
+  __ str(r2, MemOperand(r4, OFFSET_OF(T, i)));
+  __ ldrsb(r2, MemOperand(r4, OFFSET_OF(T, c)));
+  __ add(r0, r2, Operand(r0));
+  __ mov(r2, Operand(r2, LSL, 2));
+  __ strb(r2, MemOperand(r4, OFFSET_OF(T, c)));
+  __ ldrsh(r2, MemOperand(r4, OFFSET_OF(T, s)));
+  __ add(r0, r2, Operand(r0));
+  __ mov(r2, Operand(r2, ASR, 3));
+  __ strh(r2, MemOperand(r4, OFFSET_OF(T, s)));
+  __ ldm(ia, sp, r4.bit() | fp.bit() | sp.bit() | pc.bit());
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code = Heap::CreateCode(desc,
+                                  NULL,
+                                  Code::ComputeFlags(Code::STUB),
+                                  Handle<Object>(Heap::undefined_value()));
+  CHECK(code->IsCode());
+#ifdef DEBUG
+  Code::cast(code)->Print();
+#endif
+  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+  t.i = 100000;
+  t.c = 10;
+  t.s = 1000;
+  int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0));
+  ::printf("f() = %d\n", res);
+  CHECK_EQ(101010, res);
+  CHECK_EQ(100000/2, t.i);
+  CHECK_EQ(10*4, t.c);
+  CHECK_EQ(1000/8, t.s);
+}
+
+
+#undef __
diff --git a/deps/v8/test/cctest/test-assembler-ia32.cc b/deps/v8/test/cctest/test-assembler-ia32.cc
new file mode 100644
index 0000000..9ad7c76
--- /dev/null
+++ b/deps/v8/test/cctest/test-assembler-ia32.cc
@@ -0,0 +1,395 @@
+// 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.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "disassembler.h"
+#include "factory.h"
+#include "macro-assembler.h"
+#include "platform.h"
+#include "serialize.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+
+typedef int (*F0)();
+typedef int (*F1)(int x);
+typedef int (*F2)(int x, int y);
+
+
+static v8::Persistent<v8::Context> env;
+
+
+static void InitializeVM() {
+  if (env.IsEmpty()) {
+    env = v8::Context::New();
+  }
+}
+
+
+#define __ assm.
+
+TEST(AssemblerIa320) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  v8::internal::byte buffer[256];
+  Assembler assm(buffer, sizeof buffer);
+
+  __ mov(eax, Operand(esp, 4));
+  __ add(eax, Operand(esp, 8));
+  __ ret(0);
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code = Heap::CreateCode(desc,
+                                  NULL,
+                                  Code::ComputeFlags(Code::STUB),
+                                  Handle<Object>(Heap::undefined_value()));
+  CHECK(code->IsCode());
+#ifdef DEBUG
+  Code::cast(code)->Print();
+#endif
+  F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
+  int res = f(3, 4);
+  ::printf("f() = %d\n", res);
+  CHECK_EQ(7, res);
+}
+
+
+TEST(AssemblerIa321) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  v8::internal::byte buffer[256];
+  Assembler assm(buffer, sizeof buffer);
+  Label L, C;
+
+  __ mov(edx, Operand(esp, 4));
+  __ xor_(eax, Operand(eax));  // clear eax
+  __ jmp(&C);
+
+  __ bind(&L);
+  __ add(eax, Operand(edx));
+  __ sub(Operand(edx), Immediate(1));
+
+  __ bind(&C);
+  __ test(edx, Operand(edx));
+  __ j(not_zero, &L, taken);
+  __ ret(0);
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code = Heap::CreateCode(desc,
+                                  NULL,
+                                  Code::ComputeFlags(Code::STUB),
+                                  Handle<Object>(Heap::undefined_value()));
+  CHECK(code->IsCode());
+#ifdef DEBUG
+  Code::cast(code)->Print();
+#endif
+  F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
+  int res = f(100);
+  ::printf("f() = %d\n", res);
+  CHECK_EQ(5050, res);
+}
+
+
+TEST(AssemblerIa322) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  v8::internal::byte buffer[256];
+  Assembler assm(buffer, sizeof buffer);
+  Label L, C;
+
+  __ mov(edx, Operand(esp, 4));
+  __ mov(eax, 1);
+  __ jmp(&C);
+
+  __ bind(&L);
+  __ imul(eax, Operand(edx));
+  __ sub(Operand(edx), Immediate(1));
+
+  __ bind(&C);
+  __ test(edx, Operand(edx));
+  __ j(not_zero, &L, taken);
+  __ ret(0);
+
+  // some relocated stuff here, not executed
+  __ mov(eax, Factory::true_value());
+  __ jmp(NULL, RelocInfo::RUNTIME_ENTRY);
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code = Heap::CreateCode(desc,
+                                  NULL,
+                                  Code::ComputeFlags(Code::STUB),
+                                  Handle<Object>(Heap::undefined_value()));
+  CHECK(code->IsCode());
+#ifdef DEBUG
+  Code::cast(code)->Print();
+#endif
+  F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
+  int res = f(10);
+  ::printf("f() = %d\n", res);
+  CHECK_EQ(3628800, res);
+}
+
+
+typedef int (*F3)(float x);
+
+TEST(AssemblerIa323) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  v8::internal::byte buffer[256];
+  Assembler assm(buffer, sizeof buffer);
+
+  CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2));
+  { CpuFeatures::Scope fscope(CpuFeatures::SSE2);
+    __ cvttss2si(eax, Operand(esp, 4));
+    __ ret(0);
+  }
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Code* code =
+      Code::cast(Heap::CreateCode(desc,
+                                  NULL,
+                                  Code::ComputeFlags(Code::STUB),
+                                  Handle<Object>(Heap::undefined_value())));
+  // don't print the code - our disassembler can't handle cvttss2si
+  // instead print bytes
+  Disassembler::Dump(stdout,
+                     code->instruction_start(),
+                     code->instruction_start() + code->instruction_size());
+  F3 f = FUNCTION_CAST<F3>(code->entry());
+  int res = f(static_cast<float>(-3.1415));
+  ::printf("f() = %d\n", res);
+  CHECK_EQ(-3, res);
+}
+
+
+typedef int (*F4)(double x);
+
+TEST(AssemblerIa324) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  v8::internal::byte buffer[256];
+  Assembler assm(buffer, sizeof buffer);
+
+  CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2));
+  CpuFeatures::Scope fscope(CpuFeatures::SSE2);
+  __ cvttsd2si(eax, Operand(esp, 4));
+  __ ret(0);
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Code* code =
+      Code::cast(Heap::CreateCode(desc,
+                                  NULL,
+                                  Code::ComputeFlags(Code::STUB),
+                                  Handle<Object>(Heap::undefined_value())));
+  // don't print the code - our disassembler can't handle cvttsd2si
+  // instead print bytes
+  Disassembler::Dump(stdout,
+                     code->instruction_start(),
+                     code->instruction_start() + code->instruction_size());
+  F4 f = FUNCTION_CAST<F4>(code->entry());
+  int res = f(2.718281828);
+  ::printf("f() = %d\n", res);
+  CHECK_EQ(2, res);
+}
+
+
+static int baz = 42;
+TEST(AssemblerIa325) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  v8::internal::byte buffer[256];
+  Assembler assm(buffer, sizeof buffer);
+
+  __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE));
+  __ ret(0);
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Code* code =
+      Code::cast(Heap::CreateCode(desc,
+                                  NULL,
+                                  Code::ComputeFlags(Code::STUB),
+                                  Handle<Object>(Heap::undefined_value())));
+  F0 f = FUNCTION_CAST<F0>(code->entry());
+  int res = f();
+  CHECK_EQ(42, res);
+}
+
+
+typedef double (*F5)(double x, double y);
+
+TEST(AssemblerIa326) {
+  InitializeVM();
+  v8::HandleScope scope;
+  CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2));
+  CpuFeatures::Scope fscope(CpuFeatures::SSE2);
+  v8::internal::byte buffer[256];
+  Assembler assm(buffer, sizeof buffer);
+
+  __ movdbl(xmm0, Operand(esp, 1 * kPointerSize));
+  __ movdbl(xmm1, Operand(esp, 3 * kPointerSize));
+  __ addsd(xmm0, xmm1);
+  __ mulsd(xmm0, xmm1);
+  __ subsd(xmm0, xmm1);
+  __ divsd(xmm0, xmm1);
+  // Copy xmm0 to st(0) using eight bytes of stack.
+  __ sub(Operand(esp), Immediate(8));
+  __ movdbl(Operand(esp, 0), xmm0);
+  __ fld_d(Operand(esp, 0));
+  __ add(Operand(esp), Immediate(8));
+  __ ret(0);
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Code* code =
+      Code::cast(Heap::CreateCode(desc,
+                                  NULL,
+                                  Code::ComputeFlags(Code::STUB),
+                                  Handle<Object>(Heap::undefined_value())));
+#ifdef DEBUG
+  ::printf("\n---\n");
+  // don't print the code - our disassembler can't handle SSE instructions
+  // instead print bytes
+  Disassembler::Dump(stdout,
+                     code->instruction_start(),
+                     code->instruction_start() + code->instruction_size());
+#endif
+  F5 f = FUNCTION_CAST<F5>(code->entry());
+  double res = f(2.2, 1.1);
+  ::printf("f() = %f\n", res);
+  CHECK(2.29 < res && res < 2.31);
+}
+
+
+typedef double (*F6)(int x);
+
+TEST(AssemblerIa328) {
+  InitializeVM();
+  v8::HandleScope scope;
+  CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2));
+  CpuFeatures::Scope fscope(CpuFeatures::SSE2);
+  v8::internal::byte buffer[256];
+  Assembler assm(buffer, sizeof buffer);
+  __ mov(eax, Operand(esp, 4));
+  __ cvtsi2sd(xmm0, Operand(eax));
+  // Copy xmm0 to st(0) using eight bytes of stack.
+  __ sub(Operand(esp), Immediate(8));
+  __ movdbl(Operand(esp, 0), xmm0);
+  __ fld_d(Operand(esp, 0));
+  __ add(Operand(esp), Immediate(8));
+  __ ret(0);
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Code* code =
+      Code::cast(Heap::CreateCode(desc,
+                                  NULL,
+                                  Code::ComputeFlags(Code::STUB),
+                                  Handle<Object>(Heap::undefined_value())));
+  CHECK(code->IsCode());
+#ifdef DEBUG
+  Code::cast(code)->Print();
+#endif
+  F6 f = FUNCTION_CAST<F6>(Code::cast(code)->entry());
+  double res = f(12);
+
+  ::printf("f() = %f\n", res);
+  CHECK(11.99 < res && res < 12.001);
+}
+
+
+typedef int (*F7)(double x, double y);
+
+TEST(AssemblerIa329) {
+  InitializeVM();
+  v8::HandleScope scope;
+  v8::internal::byte buffer[256];
+  MacroAssembler assm(buffer, sizeof buffer);
+  enum { kEqual = 0, kGreater = 1, kLess = 2, kNaN = 3, kUndefined = 4 };
+  Label equal_l, less_l, greater_l, nan_l;
+  __ fld_d(Operand(esp, 3 * kPointerSize));
+  __ fld_d(Operand(esp, 1 * kPointerSize));
+  __ FCmp();
+  __ j(parity_even, &nan_l, taken);
+  __ j(equal, &equal_l, taken);
+  __ j(below, &less_l, taken);
+  __ j(above, &greater_l, taken);
+
+  __ mov(eax, kUndefined);
+  __ ret(0);
+
+  __ bind(&equal_l);
+  __ mov(eax, kEqual);
+  __ ret(0);
+
+  __ bind(&greater_l);
+  __ mov(eax, kGreater);
+  __ ret(0);
+
+  __ bind(&less_l);
+  __ mov(eax, kLess);
+  __ ret(0);
+
+  __ bind(&nan_l);
+  __ mov(eax, kNaN);
+  __ ret(0);
+
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Code* code =
+      Code::cast(Heap::CreateCode(desc,
+                                  NULL,
+                                  Code::ComputeFlags(Code::STUB),
+                                  Handle<Object>(Heap::undefined_value())));
+  CHECK(code->IsCode());
+#ifdef DEBUG
+  Code::cast(code)->Print();
+#endif
+
+  F7 f = FUNCTION_CAST<F7>(Code::cast(code)->entry());
+  CHECK_EQ(kLess, f(1.1, 2.2));
+  CHECK_EQ(kEqual, f(2.2, 2.2));
+  CHECK_EQ(kGreater, f(3.3, 2.2));
+  CHECK_EQ(kNaN, f(OS::nan_value(), 1.1));
+}
+
+#undef __
diff --git a/deps/v8/test/cctest/test-ast.cc b/deps/v8/test/cctest/test-ast.cc
new file mode 100644
index 0000000..2054348
--- /dev/null
+++ b/deps/v8/test/cctest/test-ast.cc
@@ -0,0 +1,97 @@
+// 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.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "ast.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+TEST(List) {
+  List<Node*>* list = new List<Node*>(0);
+  CHECK_EQ(0, list->length());
+
+  ZoneScope zone_scope(DELETE_ON_EXIT);
+  Node* node = new EmptyStatement();
+  list->Add(node);
+  CHECK_EQ(1, list->length());
+  CHECK_EQ(node, list->at(0));
+  CHECK_EQ(node, list->last());
+
+  const int kElements = 100;
+  for (int i = 0; i < kElements; i++) {
+    list->Add(node);
+  }
+  CHECK_EQ(1 + kElements, list->length());
+
+  list->Clear();
+  CHECK_EQ(0, list->length());
+  delete list;
+}
+
+
+TEST(RemoveLast) {
+  List<int> list(4);
+  CHECK_EQ(0, list.length());
+  list.Add(1);
+  CHECK_EQ(1, list.length());
+  CHECK_EQ(1, list.last());
+  list.RemoveLast();
+  CHECK_EQ(0, list.length());
+  list.Add(2);
+  list.Add(3);
+  CHECK_EQ(2, list.length());
+  CHECK_EQ(3, list.last());
+  list.RemoveLast();
+  CHECK_EQ(1, list.length());
+  CHECK_EQ(2, list.last());
+  list.RemoveLast();
+  CHECK_EQ(0, list.length());
+
+  const int kElements = 100;
+  for (int i = 0; i < kElements; i++) list.Add(i);
+  for (int j = kElements - 1; j >= 0; j--) {
+    CHECK_EQ(j + 1, list.length());
+    CHECK_EQ(j, list.last());
+    list.RemoveLast();
+    CHECK_EQ(j, list.length());
+  }
+}
+
+
+TEST(DeleteEmpty) {
+  {
+    List<int>* list = new List<int>(0);
+    delete list;
+  }
+  {
+    List<int> list(0);
+  }
+}
diff --git a/deps/v8/test/cctest/test-compiler.cc b/deps/v8/test/cctest/test-compiler.cc
new file mode 100644
index 0000000..08037b3
--- /dev/null
+++ b/deps/v8/test/cctest/test-compiler.cc
@@ -0,0 +1,318 @@
+// 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.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "compiler.h"
+#include "execution.h"
+#include "factory.h"
+#include "platform.h"
+#include "top.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+static v8::Persistent<v8::Context> env;
+
+// --- P r i n t   E x t e n s i o n ---
+
+class PrintExtension : public v8::Extension {
+ public:
+  PrintExtension() : v8::Extension("v8/print", kSource) { }
+  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
+      v8::Handle<v8::String> name);
+  static v8::Handle<v8::Value> Print(const v8::Arguments& args);
+ private:
+  static const char* kSource;
+};
+
+
+const char* PrintExtension::kSource = "native function print();";
+
+
+v8::Handle<v8::FunctionTemplate> PrintExtension::GetNativeFunction(
+    v8::Handle<v8::String> str) {
+  return v8::FunctionTemplate::New(PrintExtension::Print);
+}
+
+
+v8::Handle<v8::Value> PrintExtension::Print(const v8::Arguments& args) {
+  for (int i = 0; i < args.Length(); i++) {
+    if (i != 0) printf(" ");
+    v8::HandleScope scope;
+    v8::Handle<v8::Value> arg = args[i];
+    v8::Handle<v8::String> string_obj = arg->ToString();
+    if (string_obj.IsEmpty()) return string_obj;
+    int length = string_obj->Length();
+    uint16_t* string = NewArray<uint16_t>(length + 1);
+    string_obj->Write(string);
+    for (int j = 0; j < length; j++)
+      printf("%lc", string[j]);
+    DeleteArray(string);
+  }
+  printf("\n");
+  return v8::Undefined();
+}
+
+
+static PrintExtension kPrintExtension;
+v8::DeclareExtension kPrintExtensionDeclaration(&kPrintExtension);
+
+
+static void InitializeVM() {
+  if (env.IsEmpty()) {
+    v8::HandleScope scope;
+    const char* extensions[] = { "v8/print", "v8/gc" };
+    v8::ExtensionConfiguration config(2, extensions);
+    env = v8::Context::New(&config);
+  }
+  v8::HandleScope scope;
+  env->Enter();
+}
+
+
+static Object* GetGlobalProperty(const char* name) {
+  Handle<String> symbol = Factory::LookupAsciiSymbol(name);
+  return Top::context()->global()->GetProperty(*symbol);
+}
+
+
+static void SetGlobalProperty(const char* name, Object* value) {
+  Handle<Object> object(value);
+  Handle<String> symbol = Factory::LookupAsciiSymbol(name);
+  Handle<JSObject> global(Top::context()->global());
+  SetProperty(global, symbol, object, NONE);
+}
+
+
+static Handle<JSFunction> Compile(const char* source) {
+  Handle<String> source_code(Factory::NewStringFromUtf8(CStrVector(source)));
+  Handle<JSFunction> boilerplate =
+      Compiler::Compile(source_code, Handle<String>(), 0, 0, NULL, NULL);
+  return Factory::NewFunctionFromBoilerplate(boilerplate,
+                                             Top::global_context());
+}
+
+
+static double Inc(int x) {
+  const char* source = "result = %d + 1;";
+  EmbeddedVector<char, 512> buffer;
+  OS::SNPrintF(buffer, source, x);
+
+  Handle<JSFunction> fun = Compile(buffer.start());
+  if (fun.is_null()) return -1;
+
+  bool has_pending_exception;
+  Handle<JSObject> global(Top::context()->global());
+  Execution::Call(fun, global, 0, NULL, &has_pending_exception);
+  CHECK(!has_pending_exception);
+  return GetGlobalProperty("result")->Number();
+}
+
+
+TEST(Inc) {
+  InitializeVM();
+  v8::HandleScope scope;
+  CHECK_EQ(4.0, Inc(3));
+}
+
+
+static double Add(int x, int y) {
+  Handle<JSFunction> fun = Compile("result = x + y;");
+  if (fun.is_null()) return -1;
+
+  SetGlobalProperty("x", Smi::FromInt(x));
+  SetGlobalProperty("y", Smi::FromInt(y));
+  bool has_pending_exception;
+  Handle<JSObject> global(Top::context()->global());
+  Execution::Call(fun, global, 0, NULL, &has_pending_exception);
+  CHECK(!has_pending_exception);
+  return GetGlobalProperty("result")->Number();
+}
+
+
+TEST(Add) {
+  InitializeVM();
+  v8::HandleScope scope;
+  CHECK_EQ(5.0, Add(2, 3));
+}
+
+
+static double Abs(int x) {
+  Handle<JSFunction> fun = Compile("if (x < 0) result = -x; else result = x;");
+  if (fun.is_null()) return -1;
+
+  SetGlobalProperty("x", Smi::FromInt(x));
+  bool has_pending_exception;
+  Handle<JSObject> global(Top::context()->global());
+  Execution::Call(fun, global, 0, NULL, &has_pending_exception);
+  CHECK(!has_pending_exception);
+  return GetGlobalProperty("result")->Number();
+}
+
+
+TEST(Abs) {
+  InitializeVM();
+  v8::HandleScope scope;
+  CHECK_EQ(3.0, Abs(-3));
+}
+
+
+static double Sum(int n) {
+  Handle<JSFunction> fun =
+      Compile("s = 0; while (n > 0) { s += n; n -= 1; }; result = s;");
+  if (fun.is_null()) return -1;
+
+  SetGlobalProperty("n", Smi::FromInt(n));
+  bool has_pending_exception;
+  Handle<JSObject> global(Top::context()->global());
+  Execution::Call(fun, global, 0, NULL, &has_pending_exception);
+  CHECK(!has_pending_exception);
+  return GetGlobalProperty("result")->Number();
+}
+
+
+TEST(Sum) {
+  InitializeVM();
+  v8::HandleScope scope;
+  CHECK_EQ(5050.0, Sum(100));
+}
+
+
+TEST(Print) {
+  InitializeVM();
+  v8::HandleScope scope;
+  const char* source = "for (n = 0; n < 100; ++n) print(n, 1, 2);";
+  Handle<JSFunction> fun = Compile(source);
+  if (fun.is_null()) return;
+  bool has_pending_exception;
+  Handle<JSObject> global(Top::context()->global());
+  Execution::Call(fun, global, 0, NULL, &has_pending_exception);
+  CHECK(!has_pending_exception);
+}
+
+
+// The following test method stems from my coding efforts today. It
+// tests all the functionality I have added to the compiler today
+TEST(Stuff) {
+  InitializeVM();
+  v8::HandleScope scope;
+  const char* source =
+    "r = 0;\n"
+    "a = new Object;\n"
+    "if (a == a) r+=1;\n"  // 1
+    "if (a != new Object()) r+=2;\n"  // 2
+    "a.x = 42;\n"
+    "if (a.x == 42) r+=4;\n"  // 4
+    "function foo() { var x = 87; return x; }\n"
+    "if (foo() == 87) r+=8;\n"  // 8
+    "function bar() { var x; x = 99; return x; }\n"
+    "if (bar() == 99) r+=16;\n"  // 16
+    "function baz() { var x = 1, y, z = 2; y = 3; return x + y + z; }\n"
+    "if (baz() == 6) r+=32;\n"  // 32
+    "function Cons0() { this.x = 42; this.y = 87; }\n"
+    "if (new Cons0().x == 42) r+=64;\n"  // 64
+    "if (new Cons0().y == 87) r+=128;\n"  // 128
+    "function Cons2(x, y) { this.sum = x + y; }\n"
+    "if (new Cons2(3,4).sum == 7) r+=256;";  // 256
+
+  Handle<JSFunction> fun = Compile(source);
+  CHECK(!fun.is_null());
+  bool has_pending_exception;
+  Handle<JSObject> global(Top::context()->global());
+  Execution::Call(fun, global, 0, NULL, &has_pending_exception);
+  CHECK(!has_pending_exception);
+  CHECK_EQ(511.0, GetGlobalProperty("r")->Number());
+}
+
+
+TEST(UncaughtThrow) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  const char* source = "throw 42;";
+  Handle<JSFunction> fun = Compile(source);
+  CHECK(!fun.is_null());
+  bool has_pending_exception;
+  Handle<JSObject> global(Top::context()->global());
+  Handle<Object> result =
+      Execution::Call(fun, global, 0, NULL, &has_pending_exception);
+  CHECK(has_pending_exception);
+  CHECK_EQ(42.0, Top::pending_exception()->Number());
+}
+
+
+// Tests calling a builtin function from C/C++ code, and the builtin function
+// performs GC. It creates a stack frame looks like following:
+//   | C (PerformGC) |
+//   |   JS-to-C     |
+//   |      JS       |
+//   |   C-to-JS     |
+TEST(C2JSFrames) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  const char* source = "function foo(a) { gc(), print(a); }";
+
+  Handle<JSFunction> fun0 = Compile(source);
+  CHECK(!fun0.is_null());
+
+  // Run the generated code to populate the global object with 'foo'.
+  bool has_pending_exception;
+  Handle<JSObject> global(Top::context()->global());
+  Execution::Call(fun0, global, 0, NULL, &has_pending_exception);
+  CHECK(!has_pending_exception);
+
+  Handle<Object> fun1 =
+      Handle<Object>(
+          Top::context()->global()->GetProperty(
+              *Factory::LookupAsciiSymbol("foo")));
+  CHECK(fun1->IsJSFunction());
+
+  Object** argv[1] = {
+    Handle<Object>::cast(Factory::LookupAsciiSymbol("hello")).location()
+  };
+  Execution::Call(Handle<JSFunction>::cast(fun1), global, 1, argv,
+                  &has_pending_exception);
+  CHECK(!has_pending_exception);
+}
+
+
+// Regression 236. Calling InitLineEnds on a Script with undefined
+// source resulted in crash.
+TEST(Regression236) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  Handle<Script> script = Factory::NewScript(Factory::empty_string());
+  script->set_source(Heap::undefined_value());
+  CHECK_EQ(-1, GetScriptLineNumber(script, 0));
+  CHECK_EQ(-1, GetScriptLineNumber(script, 100));
+  CHECK_EQ(-1, GetScriptLineNumber(script, -1));
+}
diff --git a/deps/v8/test/cctest/test-conversions.cc b/deps/v8/test/cctest/test-conversions.cc
new file mode 100644
index 0000000..6c0b9a6
--- /dev/null
+++ b/deps/v8/test/cctest/test-conversions.cc
@@ -0,0 +1,130 @@
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "platform.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+
+TEST(Hex) {
+  CHECK_EQ(0.0, StringToDouble("0x0", ALLOW_HEX | ALLOW_OCTALS));
+  CHECK_EQ(0.0, StringToDouble("0X0", ALLOW_HEX | ALLOW_OCTALS));
+  CHECK_EQ(1.0, StringToDouble("0x1", ALLOW_HEX | ALLOW_OCTALS));
+  CHECK_EQ(16.0, StringToDouble("0x10", ALLOW_HEX | ALLOW_OCTALS));
+  CHECK_EQ(255.0, StringToDouble("0xff", ALLOW_HEX | ALLOW_OCTALS));
+  CHECK_EQ(175.0, StringToDouble("0xAF", ALLOW_HEX | ALLOW_OCTALS));
+
+  CHECK_EQ(0.0, StringToDouble("0x0", ALLOW_HEX));
+  CHECK_EQ(0.0, StringToDouble("0X0", ALLOW_HEX));
+  CHECK_EQ(1.0, StringToDouble("0x1", ALLOW_HEX));
+  CHECK_EQ(16.0, StringToDouble("0x10", ALLOW_HEX));
+  CHECK_EQ(255.0, StringToDouble("0xff", ALLOW_HEX));
+  CHECK_EQ(175.0, StringToDouble("0xAF", ALLOW_HEX));
+}
+
+
+TEST(Octal) {
+  CHECK_EQ(0.0, StringToDouble("0", ALLOW_HEX | ALLOW_OCTALS));
+  CHECK_EQ(0.0, StringToDouble("00", ALLOW_HEX | ALLOW_OCTALS));
+  CHECK_EQ(1.0, StringToDouble("01", ALLOW_HEX | ALLOW_OCTALS));
+  CHECK_EQ(7.0, StringToDouble("07", ALLOW_HEX | ALLOW_OCTALS));
+  CHECK_EQ(8.0, StringToDouble("010", ALLOW_HEX | ALLOW_OCTALS));
+  CHECK_EQ(63.0, StringToDouble("077", ALLOW_HEX | ALLOW_OCTALS));
+
+  CHECK_EQ(0.0, StringToDouble("0", ALLOW_HEX));
+  CHECK_EQ(0.0, StringToDouble("00", ALLOW_HEX));
+  CHECK_EQ(1.0, StringToDouble("01", ALLOW_HEX));
+  CHECK_EQ(7.0, StringToDouble("07", ALLOW_HEX));
+  CHECK_EQ(10.0, StringToDouble("010", ALLOW_HEX));
+  CHECK_EQ(77.0, StringToDouble("077", ALLOW_HEX));
+}
+
+
+TEST(MalformedOctal) {
+  CHECK_EQ(8.0, StringToDouble("08", ALLOW_HEX | ALLOW_OCTALS));
+  CHECK_EQ(81.0, StringToDouble("081", ALLOW_HEX | ALLOW_OCTALS));
+  CHECK_EQ(78.0, StringToDouble("078", ALLOW_HEX | ALLOW_OCTALS));
+
+  CHECK(isnan(StringToDouble("07.7", ALLOW_HEX | ALLOW_OCTALS)));
+  CHECK(isnan(StringToDouble("07.8", ALLOW_HEX | ALLOW_OCTALS)));
+  CHECK(isnan(StringToDouble("07e8", ALLOW_HEX | ALLOW_OCTALS)));
+  CHECK(isnan(StringToDouble("07e7", ALLOW_HEX | ALLOW_OCTALS)));
+
+  CHECK_EQ(8.7, StringToDouble("08.7", ALLOW_HEX | ALLOW_OCTALS));
+  CHECK_EQ(8e7, StringToDouble("08e7", ALLOW_HEX | ALLOW_OCTALS));
+
+  CHECK_EQ(0.001, StringToDouble("0.001", ALLOW_HEX | ALLOW_OCTALS));
+  CHECK_EQ(0.713, StringToDouble("0.713", ALLOW_HEX | ALLOW_OCTALS));
+
+  CHECK_EQ(8.0, StringToDouble("08", ALLOW_HEX));
+  CHECK_EQ(81.0, StringToDouble("081", ALLOW_HEX));
+  CHECK_EQ(78.0, StringToDouble("078", ALLOW_HEX));
+
+  CHECK_EQ(7.7, StringToDouble("07.7", ALLOW_HEX));
+  CHECK_EQ(7.8, StringToDouble("07.8", ALLOW_HEX));
+  CHECK_EQ(7e8, StringToDouble("07e8", ALLOW_HEX));
+  CHECK_EQ(7e7, StringToDouble("07e7", ALLOW_HEX));
+
+  CHECK_EQ(8.7, StringToDouble("08.7", ALLOW_HEX));
+  CHECK_EQ(8e7, StringToDouble("08e7", ALLOW_HEX));
+
+  CHECK_EQ(0.001, StringToDouble("0.001", ALLOW_HEX));
+  CHECK_EQ(0.713, StringToDouble("0.713", ALLOW_HEX));
+}
+
+
+TEST(TrailingJunk) {
+  CHECK_EQ(8.0, StringToDouble("8q", ALLOW_TRAILING_JUNK));
+  CHECK_EQ(63.0, StringToDouble("077qqq", ALLOW_OCTALS | ALLOW_TRAILING_JUNK));
+}
+
+
+TEST(NonStrDecimalLiteral) {
+  CHECK(isnan(StringToDouble(" ", NO_FLAGS, OS::nan_value())));
+  CHECK(isnan(StringToDouble("", NO_FLAGS, OS::nan_value())));
+  CHECK(isnan(StringToDouble(" ", NO_FLAGS, OS::nan_value())));
+  CHECK_EQ(0.0, StringToDouble("", NO_FLAGS));
+  CHECK_EQ(0.0, StringToDouble(" ", NO_FLAGS));
+}
+
+
+TEST(BitField) {
+  uint32_t x;
+
+  // One bit bit field can hold values 0 and 1.
+  class OneBit1: public BitField<uint32_t, 0, 1> {};
+  class OneBit2: public BitField<uint32_t, 7, 1> {};
+  CHECK(!OneBit1::is_valid(static_cast<uint32_t>(-1)));
+  CHECK(!OneBit2::is_valid(static_cast<uint32_t>(-1)));
+  for (int i = 0; i < 2; i++) {
+    CHECK(OneBit1::is_valid(i));
+    x = OneBit1::encode(i);
+    CHECK_EQ(i, OneBit1::decode(x));
+
+    CHECK(OneBit2::is_valid(i));
+    x = OneBit2::encode(i);
+    CHECK_EQ(i, OneBit2::decode(x));
+  }
+  CHECK(!OneBit1::is_valid(2));
+  CHECK(!OneBit2::is_valid(2));
+
+  // Eight bit bit field can hold values from 0 tp 255.
+  class EightBit1: public BitField<uint32_t, 0, 8> {};
+  class EightBit2: public BitField<uint32_t, 13, 8> {};
+  CHECK(!EightBit1::is_valid(static_cast<uint32_t>(-1)));
+  CHECK(!EightBit2::is_valid(static_cast<uint32_t>(-1)));
+  for (int i = 0; i < 256; i++) {
+    CHECK(EightBit1::is_valid(i));
+    x = EightBit1::encode(i);
+    CHECK_EQ(i, EightBit1::decode(x));
+    CHECK(EightBit2::is_valid(i));
+    x = EightBit2::encode(i);
+    CHECK_EQ(i, EightBit2::decode(x));
+  }
+  CHECK(!EightBit1::is_valid(256));
+  CHECK(!EightBit2::is_valid(256));
+}
diff --git a/deps/v8/test/cctest/test-debug.cc b/deps/v8/test/cctest/test-debug.cc
new file mode 100644
index 0000000..e482c7f
--- /dev/null
+++ b/deps/v8/test/cctest/test-debug.cc
@@ -0,0 +1,4251 @@
+// 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.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "api.h"
+#include "debug.h"
+#include "platform.h"
+#include "stub-cache.h"
+#include "cctest.h"
+
+
+using ::v8::internal::EmbeddedVector;
+using ::v8::internal::Object;
+using ::v8::internal::OS;
+using ::v8::internal::Handle;
+using ::v8::internal::Heap;
+using ::v8::internal::JSGlobalProxy;
+using ::v8::internal::Code;
+using ::v8::internal::Debug;
+using ::v8::internal::Debugger;
+using ::v8::internal::StepAction;
+using ::v8::internal::StepIn;  // From StepAction enum
+using ::v8::internal::StepNext;  // From StepAction enum
+using ::v8::internal::StepOut;  // From StepAction enum
+
+
+// Size of temp buffer for formatting small strings.
+#define SMALL_STRING_BUFFER_SIZE 80
+
+// --- A d d i t i o n a l   C h e c k   H e l p e r s
+
+
+// Helper function used by the CHECK_EQ function when given Address
+// arguments.  Should not be called directly.
+static inline void CheckEqualsHelper(const char* file, int line,
+                                     const char* expected_source,
+                                     ::v8::internal::Address expected,
+                                     const char* value_source,
+                                     ::v8::internal::Address value) {
+  if (expected != value) {
+    V8_Fatal(file, line, "CHECK_EQ(%s, %s) failed\n#   "
+                         "Expected: %i\n#   Found: %i",
+             expected_source, value_source, expected, value);
+  }
+}
+
+
+// Helper function used by the CHECK_NE function when given Address
+// arguments.  Should not be called directly.
+static inline void CheckNonEqualsHelper(const char* file, int line,
+                                        const char* unexpected_source,
+                                        ::v8::internal::Address unexpected,
+                                        const char* value_source,
+                                        ::v8::internal::Address value) {
+  if (unexpected == value) {
+    V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n#   Value: %i",
+             unexpected_source, value_source, value);
+  }
+}
+
+
+// Helper function used by the CHECK function when given code
+// arguments.  Should not be called directly.
+static inline void CheckEqualsHelper(const char* file, int line,
+                                     const char* expected_source,
+                                     const Code* expected,
+                                     const char* value_source,
+                                     const Code* value) {
+  if (expected != value) {
+    V8_Fatal(file, line, "CHECK_EQ(%s, %s) failed\n#   "
+                         "Expected: %p\n#   Found: %p",
+             expected_source, value_source, expected, value);
+  }
+}
+
+
+static inline void CheckNonEqualsHelper(const char* file, int line,
+                                        const char* expected_source,
+                                        const Code* expected,
+                                        const char* value_source,
+                                        const Code* value) {
+  if (expected == value) {
+    V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n#   Value: %p",
+             expected_source, value_source, value);
+  }
+}
+
+
+// --- H e l p e r   C l a s s e s
+
+
+// Helper class for creating a V8 enviromnent for running tests
+class DebugLocalContext {
+ public:
+  inline DebugLocalContext(
+      v8::ExtensionConfiguration* extensions = 0,
+      v8::Handle<v8::ObjectTemplate> global_template =
+          v8::Handle<v8::ObjectTemplate>(),
+      v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>())
+      : context_(v8::Context::New(extensions, global_template, global_object)) {
+    context_->Enter();
+  }
+  inline ~DebugLocalContext() {
+    context_->Exit();
+    context_.Dispose();
+  }
+  inline v8::Context* operator->() { return *context_; }
+  inline v8::Context* operator*() { return *context_; }
+  inline bool IsReady() { return !context_.IsEmpty(); }
+  void ExposeDebug() {
+    // Expose the debug context global object in the global object for testing.
+    Debug::Load();
+    Debug::debug_context()->set_security_token(
+        v8::Utils::OpenHandle(*context_)->security_token());
+
+    Handle<JSGlobalProxy> global(Handle<JSGlobalProxy>::cast(
+        v8::Utils::OpenHandle(*context_->Global())));
+    Handle<v8::internal::String> debug_string =
+        v8::internal::Factory::LookupAsciiSymbol("debug");
+    SetProperty(global, debug_string,
+        Handle<Object>(Debug::debug_context()->global_proxy()), DONT_ENUM);
+  }
+ private:
+  v8::Persistent<v8::Context> context_;
+};
+
+
+// --- H e l p e r   F u n c t i o n s
+
+
+// Compile and run the supplied source and return the fequested function.
+static v8::Local<v8::Function> CompileFunction(DebugLocalContext* env,
+                                               const char* source,
+                                               const char* function_name) {
+  v8::Script::Compile(v8::String::New(source))->Run();
+  return v8::Local<v8::Function>::Cast(
+      (*env)->Global()->Get(v8::String::New(function_name)));
+}
+
+// Helper function that compiles and runs the source.
+static v8::Local<v8::Value> CompileRun(const char* source) {
+  return v8::Script::Compile(v8::String::New(source))->Run();
+}
+
+// Is there any debug info for the function?
+static bool HasDebugInfo(v8::Handle<v8::Function> fun) {
+  Handle<v8::internal::JSFunction> f = v8::Utils::OpenHandle(*fun);
+  Handle<v8::internal::SharedFunctionInfo> shared(f->shared());
+  return Debug::HasDebugInfo(shared);
+}
+
+
+// Set a break point in a function and return the associated break point
+// number.
+static int SetBreakPoint(Handle<v8::internal::JSFunction> fun, int position) {
+  static int break_point = 0;
+  Handle<v8::internal::SharedFunctionInfo> shared(fun->shared());
+  Debug::SetBreakPoint(
+      shared, position,
+      Handle<Object>(v8::internal::Smi::FromInt(++break_point)));
+  return break_point;
+}
+
+
+// Set a break point in a function and return the associated break point
+// number.
+static int SetBreakPoint(v8::Handle<v8::Function> fun, int position) {
+  return SetBreakPoint(v8::Utils::OpenHandle(*fun), position);
+}
+
+
+// Set a break point in a function using the Debug object and return the
+// associated break point number.
+static int SetBreakPointFromJS(const char* function_name,
+                               int line, int position) {
+  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
+  OS::SNPrintF(buffer,
+               "debug.Debug.setBreakPoint(%s,%d,%d)",
+               function_name, line, position);
+  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
+  v8::Handle<v8::String> str = v8::String::New(buffer.start());
+  return v8::Script::Compile(str)->Run()->Int32Value();
+}
+
+
+// Set a break point in a script identified by id using the global Debug object.
+static int SetScriptBreakPointByIdFromJS(int script_id, int line, int column) {
+  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
+  if (column >= 0) {
+    // Column specified set script break point on precise location.
+    OS::SNPrintF(buffer,
+                 "debug.Debug.setScriptBreakPointById(%d,%d,%d)",
+                 script_id, line, column);
+  } else {
+    // Column not specified set script break point on line.
+    OS::SNPrintF(buffer,
+                 "debug.Debug.setScriptBreakPointById(%d,%d)",
+                 script_id, line);
+  }
+  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
+  {
+    v8::TryCatch try_catch;
+    v8::Handle<v8::String> str = v8::String::New(buffer.start());
+    v8::Handle<v8::Value> value = v8::Script::Compile(str)->Run();
+    ASSERT(!try_catch.HasCaught());
+    return value->Int32Value();
+  }
+}
+
+
+// Set a break point in a script identified by name using the global Debug
+// object.
+static int SetScriptBreakPointByNameFromJS(const char* script_name,
+                                           int line, int column) {
+  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
+  if (column >= 0) {
+    // Column specified set script break point on precise location.
+    OS::SNPrintF(buffer,
+                 "debug.Debug.setScriptBreakPointByName(\"%s\",%d,%d)",
+                 script_name, line, column);
+  } else {
+    // Column not specified set script break point on line.
+    OS::SNPrintF(buffer,
+                 "debug.Debug.setScriptBreakPointByName(\"%s\",%d)",
+                 script_name, line);
+  }
+  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
+  {
+    v8::TryCatch try_catch;
+    v8::Handle<v8::String> str = v8::String::New(buffer.start());
+    v8::Handle<v8::Value> value = v8::Script::Compile(str)->Run();
+    ASSERT(!try_catch.HasCaught());
+    return value->Int32Value();
+  }
+}
+
+
+// Clear a break point.
+static void ClearBreakPoint(int break_point) {
+  Debug::ClearBreakPoint(
+      Handle<Object>(v8::internal::Smi::FromInt(break_point)));
+}
+
+
+// Clear a break point using the global Debug object.
+static void ClearBreakPointFromJS(int break_point_number) {
+  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
+  OS::SNPrintF(buffer,
+               "debug.Debug.clearBreakPoint(%d)",
+               break_point_number);
+  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
+  v8::Script::Compile(v8::String::New(buffer.start()))->Run();
+}
+
+
+static void EnableScriptBreakPointFromJS(int break_point_number) {
+  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
+  OS::SNPrintF(buffer,
+               "debug.Debug.enableScriptBreakPoint(%d)",
+               break_point_number);
+  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
+  v8::Script::Compile(v8::String::New(buffer.start()))->Run();
+}
+
+
+static void DisableScriptBreakPointFromJS(int break_point_number) {
+  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
+  OS::SNPrintF(buffer,
+               "debug.Debug.disableScriptBreakPoint(%d)",
+               break_point_number);
+  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
+  v8::Script::Compile(v8::String::New(buffer.start()))->Run();
+}
+
+
+static void ChangeScriptBreakPointConditionFromJS(int break_point_number,
+                                                  const char* condition) {
+  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
+  OS::SNPrintF(buffer,
+               "debug.Debug.changeScriptBreakPointCondition(%d, \"%s\")",
+               break_point_number, condition);
+  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
+  v8::Script::Compile(v8::String::New(buffer.start()))->Run();
+}
+
+
+static void ChangeScriptBreakPointIgnoreCountFromJS(int break_point_number,
+                                                    int ignoreCount) {
+  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
+  OS::SNPrintF(buffer,
+               "debug.Debug.changeScriptBreakPointIgnoreCount(%d, %d)",
+               break_point_number, ignoreCount);
+  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
+  v8::Script::Compile(v8::String::New(buffer.start()))->Run();
+}
+
+
+// Change break on exception.
+static void ChangeBreakOnException(bool caught, bool uncaught) {
+  Debug::ChangeBreakOnException(v8::internal::BreakException, caught);
+  Debug::ChangeBreakOnException(v8::internal::BreakUncaughtException, uncaught);
+}
+
+
+// Change break on exception using the global Debug object.
+static void ChangeBreakOnExceptionFromJS(bool caught, bool uncaught) {
+  if (caught) {
+    v8::Script::Compile(
+        v8::String::New("debug.Debug.setBreakOnException()"))->Run();
+  } else {
+    v8::Script::Compile(
+        v8::String::New("debug.Debug.clearBreakOnException()"))->Run();
+  }
+  if (uncaught) {
+    v8::Script::Compile(
+        v8::String::New("debug.Debug.setBreakOnUncaughtException()"))->Run();
+  } else {
+    v8::Script::Compile(
+        v8::String::New("debug.Debug.clearBreakOnUncaughtException()"))->Run();
+  }
+}
+
+
+// Prepare to step to next break location.
+static void PrepareStep(StepAction step_action) {
+  Debug::PrepareStep(step_action, 1);
+}
+
+
+// This function is in namespace v8::internal to be friend with class
+// v8::internal::Debug.
+namespace v8 { namespace internal {  // NOLINT
+
+// Collect the currently debugged functions.
+Handle<FixedArray> GetDebuggedFunctions() {
+  v8::internal::DebugInfoListNode* node = Debug::debug_info_list_;
+
+  // Find the number of debugged functions.
+  int count = 0;
+  while (node) {
+    count++;
+    node = node->next();
+  }
+
+  // Allocate array for the debugged functions
+  Handle<FixedArray> debugged_functions =
+      v8::internal::Factory::NewFixedArray(count);
+
+  // Run through the debug info objects and collect all functions.
+  count = 0;
+  while (node) {
+    debugged_functions->set(count++, *node->debug_info());
+    node = node->next();
+  }
+
+  return debugged_functions;
+}
+
+
+static Handle<Code> ComputeCallDebugBreak(int argc) {
+  CALL_HEAP_FUNCTION(v8::internal::StubCache::ComputeCallDebugBreak(argc),
+                     Code);
+}
+
+
+// Check that the debugger has been fully unloaded.
+void CheckDebuggerUnloaded(bool check_functions) {
+  // Check that the debugger context is cleared and that there is no debug
+  // information stored for the debugger.
+  CHECK(Debug::debug_context().is_null());
+  CHECK_EQ(NULL, Debug::debug_info_list_);
+
+  // Collect garbage to ensure weak handles are cleared.
+  Heap::CollectAllGarbage();
+  Heap::CollectAllGarbage();
+
+  // Iterate the head and check that there are no debugger related objects left.
+  HeapIterator iterator;
+  while (iterator.has_next()) {
+    HeapObject* obj = iterator.next();
+    CHECK(obj != NULL);
+    CHECK(!obj->IsDebugInfo());
+    CHECK(!obj->IsBreakPointInfo());
+
+    // If deep check of functions is requested check that no debug break code
+    // is left in all functions.
+    if (check_functions) {
+      if (obj->IsJSFunction()) {
+        JSFunction* fun = JSFunction::cast(obj);
+        for (RelocIterator it(fun->shared()->code()); !it.done(); it.next()) {
+          RelocInfo::Mode rmode = it.rinfo()->rmode();
+          if (RelocInfo::IsCodeTarget(rmode)) {
+            CHECK(!Debug::IsDebugBreak(it.rinfo()->target_address()));
+          } else if (RelocInfo::IsJSReturn(rmode)) {
+            CHECK(!Debug::IsDebugBreakAtReturn(it.rinfo()));
+          }
+        }
+      }
+    }
+  }
+}
+
+
+} }  // namespace v8::internal
+
+
+// Check that the debugger has been fully unloaded.
+static void CheckDebuggerUnloaded(bool check_functions = false) {
+  v8::internal::CheckDebuggerUnloaded(check_functions);
+}
+
+
+// Inherit from BreakLocationIterator to get access to protected parts for
+// testing.
+class TestBreakLocationIterator: public v8::internal::BreakLocationIterator {
+ public:
+  explicit TestBreakLocationIterator(Handle<v8::internal::DebugInfo> debug_info)
+    : BreakLocationIterator(debug_info, v8::internal::SOURCE_BREAK_LOCATIONS) {}
+  v8::internal::RelocIterator* it() { return reloc_iterator_; }
+  v8::internal::RelocIterator* it_original() {
+    return reloc_iterator_original_;
+  }
+};
+
+
+// Compile a function, set a break point and check that the call at the break
+// location in the code is the expected debug_break function.
+void CheckDebugBreakFunction(DebugLocalContext* env,
+                             const char* source, const char* name,
+                             int position, v8::internal::RelocInfo::Mode mode,
+                             Code* debug_break) {
+  // Create function and set the break point.
+  Handle<v8::internal::JSFunction> fun = v8::Utils::OpenHandle(
+      *CompileFunction(env, source, name));
+  int bp = SetBreakPoint(fun, position);
+
+  // Check that the debug break function is as expected.
+  Handle<v8::internal::SharedFunctionInfo> shared(fun->shared());
+  CHECK(Debug::HasDebugInfo(shared));
+  TestBreakLocationIterator it1(Debug::GetDebugInfo(shared));
+  it1.FindBreakLocationFromPosition(position);
+  CHECK_EQ(mode, it1.it()->rinfo()->rmode());
+  if (mode != v8::internal::RelocInfo::JS_RETURN) {
+    CHECK_EQ(debug_break,
+        Code::GetCodeFromTargetAddress(it1.it()->rinfo()->target_address()));
+  } else {
+    // TODO(1240753): Make the test architecture independent or split
+    // parts of the debugger into architecture dependent files.
+    CHECK_EQ(0xE8, *(it1.rinfo()->pc()));
+  }
+
+  // Clear the break point and check that the debug break function is no longer
+  // there
+  ClearBreakPoint(bp);
+  CHECK(!Debug::HasDebugInfo(shared));
+  CHECK(Debug::EnsureDebugInfo(shared));
+  TestBreakLocationIterator it2(Debug::GetDebugInfo(shared));
+  it2.FindBreakLocationFromPosition(position);
+  CHECK_EQ(mode, it2.it()->rinfo()->rmode());
+  if (mode == v8::internal::RelocInfo::JS_RETURN) {
+    // TODO(1240753): Make the test architecture independent or split
+    // parts of the debugger into architecture dependent files.
+    CHECK_NE(0xE8, *(it2.rinfo()->pc()));
+  }
+}
+
+
+// --- D e b u g   E v e n t   H a n d l e r s
+// ---
+// --- The different tests uses a number of debug event handlers.
+// ---
+
+
+// Source for The JavaScript function which picks out the function name of the
+// top frame.
+const char* frame_function_name_source =
+    "function frame_function_name(exec_state) {"
+    "  return exec_state.frame(0).func().name();"
+    "}";
+v8::Local<v8::Function> frame_function_name;
+
+
+// Source for The JavaScript function which picks out the source line for the
+// top frame.
+const char* frame_source_line_source =
+    "function frame_source_line(exec_state) {"
+    "  return exec_state.frame(0).sourceLine();"
+    "}";
+v8::Local<v8::Function> frame_source_line;
+
+
+// Source for The JavaScript function which picks out the source column for the
+// top frame.
+const char* frame_source_column_source =
+    "function frame_source_column(exec_state) {"
+    "  return exec_state.frame(0).sourceColumn();"
+    "}";
+v8::Local<v8::Function> frame_source_column;
+
+
+// Source for The JavaScript function which returns the number of frames.
+static const char* frame_count_source =
+    "function frame_count(exec_state) {"
+    "  return exec_state.frameCount();"
+    "}";
+v8::Handle<v8::Function> frame_count;
+
+
+// Global variable to store the last function hit - used by some tests.
+char last_function_hit[80];
+
+// Global variables to store the last source position - used by some tests.
+int last_source_line = -1;
+int last_source_column = -1;
+
+// Debug event handler which counts the break points which have been hit.
+int break_point_hit_count = 0;
+static void DebugEventBreakPointHitCount(v8::DebugEvent event,
+                                         v8::Handle<v8::Object> exec_state,
+                                         v8::Handle<v8::Object> event_data,
+                                         v8::Handle<v8::Value> data) {
+  // When hitting a debug event listener there must be a break set.
+  CHECK_NE(v8::internal::Debug::break_id(), 0);
+
+  // Count the number of breaks.
+  if (event == v8::Break) {
+    break_point_hit_count++;
+    if (!frame_function_name.IsEmpty()) {
+      // Get the name of the function.
+      const int argc = 1;
+      v8::Handle<v8::Value> argv[argc] = { exec_state };
+      v8::Handle<v8::Value> result = frame_function_name->Call(exec_state,
+                                                               argc, argv);
+      if (result->IsUndefined()) {
+        last_function_hit[0] = '\0';
+      } else {
+        CHECK(result->IsString());
+        v8::Handle<v8::String> function_name(result->ToString());
+        function_name->WriteAscii(last_function_hit);
+      }
+    }
+
+    if (!frame_source_line.IsEmpty()) {
+      // Get the source line.
+      const int argc = 1;
+      v8::Handle<v8::Value> argv[argc] = { exec_state };
+      v8::Handle<v8::Value> result = frame_source_line->Call(exec_state,
+                                                             argc, argv);
+      CHECK(result->IsNumber());
+      last_source_line = result->Int32Value();
+    }
+
+    if (!frame_source_column.IsEmpty()) {
+      // Get the source column.
+      const int argc = 1;
+      v8::Handle<v8::Value> argv[argc] = { exec_state };
+      v8::Handle<v8::Value> result = frame_source_column->Call(exec_state,
+                                                               argc, argv);
+      CHECK(result->IsNumber());
+      last_source_column = result->Int32Value();
+    }
+  }
+}
+
+
+// Debug event handler which counts a number of events and collects the stack
+// height if there is a function compiled for that.
+int exception_hit_count = 0;
+int uncaught_exception_hit_count = 0;
+int last_js_stack_height = -1;
+
+static void DebugEventCounterClear() {
+  break_point_hit_count = 0;
+  exception_hit_count = 0;
+  uncaught_exception_hit_count = 0;
+}
+
+static void DebugEventCounter(v8::DebugEvent event,
+                              v8::Handle<v8::Object> exec_state,
+                              v8::Handle<v8::Object> event_data,
+                              v8::Handle<v8::Value> data) {
+  // When hitting a debug event listener there must be a break set.
+  CHECK_NE(v8::internal::Debug::break_id(), 0);
+
+  // Count the number of breaks.
+  if (event == v8::Break) {
+    break_point_hit_count++;
+  } else if (event == v8::Exception) {
+    exception_hit_count++;
+
+    // Check whether the exception was uncaught.
+    v8::Local<v8::String> fun_name = v8::String::New("uncaught");
+    v8::Local<v8::Function> fun =
+        v8::Function::Cast(*event_data->Get(fun_name));
+    v8::Local<v8::Value> result = *fun->Call(event_data, 0, NULL);
+    if (result->IsTrue()) {
+      uncaught_exception_hit_count++;
+    }
+  }
+
+  // Collect the JavsScript stack height if the function frame_count is
+  // compiled.
+  if (!frame_count.IsEmpty()) {
+    static const int kArgc = 1;
+    v8::Handle<v8::Value> argv[kArgc] = { exec_state };
+    // Using exec_state as receiver is just to have a receiver.
+    v8::Handle<v8::Value> result =  frame_count->Call(exec_state, kArgc, argv);
+    last_js_stack_height = result->Int32Value();
+  }
+}
+
+
+// Debug event handler which evaluates a number of expressions when a break
+// point is hit. Each evaluated expression is compared with an expected value.
+// For this debug event handler to work the following two global varaibles
+// must be initialized.
+//   checks: An array of expressions and expected results
+//   evaluate_check_function: A JavaScript function (see below)
+
+// Structure for holding checks to do.
+struct EvaluateCheck {
+  const char* expr;  // An expression to evaluate when a break point is hit.
+  v8::Handle<v8::Value> expected;  // The expected result.
+};
+// Array of checks to do.
+struct EvaluateCheck* checks = NULL;
+// Source for The JavaScript function which can do the evaluation when a break
+// point is hit.
+const char* evaluate_check_source =
+    "function evaluate_check(exec_state, expr, expected) {"
+    "  return exec_state.frame(0).evaluate(expr).value() === expected;"
+    "}";
+v8::Local<v8::Function> evaluate_check_function;
+
+// The actual debug event described by the longer comment above.
+static void DebugEventEvaluate(v8::DebugEvent event,
+                               v8::Handle<v8::Object> exec_state,
+                               v8::Handle<v8::Object> event_data,
+                               v8::Handle<v8::Value> data) {
+  // When hitting a debug event listener there must be a break set.
+  CHECK_NE(v8::internal::Debug::break_id(), 0);
+
+  if (event == v8::Break) {
+    for (int i = 0; checks[i].expr != NULL; i++) {
+      const int argc = 3;
+      v8::Handle<v8::Value> argv[argc] = { exec_state,
+                                           v8::String::New(checks[i].expr),
+                                           checks[i].expected };
+      v8::Handle<v8::Value> result =
+          evaluate_check_function->Call(exec_state, argc, argv);
+      if (!result->IsTrue()) {
+        v8::String::AsciiValue ascii(checks[i].expected->ToString());
+        V8_Fatal(__FILE__, __LINE__, "%s != %s", checks[i].expr, *ascii);
+      }
+    }
+  }
+}
+
+
+// This debug event listener removes a breakpoint in a function
+int debug_event_remove_break_point = 0;
+static void DebugEventRemoveBreakPoint(v8::DebugEvent event,
+                                       v8::Handle<v8::Object> exec_state,
+                                       v8::Handle<v8::Object> event_data,
+                                       v8::Handle<v8::Value> data) {
+  // When hitting a debug event listener there must be a break set.
+  CHECK_NE(v8::internal::Debug::break_id(), 0);
+
+  if (event == v8::Break) {
+    break_point_hit_count++;
+    v8::Handle<v8::Function> fun = v8::Handle<v8::Function>::Cast(data);
+    ClearBreakPoint(debug_event_remove_break_point);
+  }
+}
+
+
+// Debug event handler which counts break points hit and performs a step
+// afterwards.
+StepAction step_action = StepIn;  // Step action to perform when stepping.
+static void DebugEventStep(v8::DebugEvent event,
+                           v8::Handle<v8::Object> exec_state,
+                           v8::Handle<v8::Object> event_data,
+                           v8::Handle<v8::Value> data) {
+  // When hitting a debug event listener there must be a break set.
+  CHECK_NE(v8::internal::Debug::break_id(), 0);
+
+  if (event == v8::Break) {
+    break_point_hit_count++;
+    PrepareStep(step_action);
+  }
+}
+
+
+// Debug event handler which counts break points hit and performs a step
+// afterwards. For each call the expected function is checked.
+// For this debug event handler to work the following two global varaibles
+// must be initialized.
+//   expected_step_sequence: An array of the expected function call sequence.
+//   frame_function_name: A JavaScript function (see below).
+
+// String containing the expected function call sequence. Note: this only works
+// if functions have name length of one.
+const char* expected_step_sequence = NULL;
+
+// The actual debug event described by the longer comment above.
+static void DebugEventStepSequence(v8::DebugEvent event,
+                                   v8::Handle<v8::Object> exec_state,
+                                   v8::Handle<v8::Object> event_data,
+                                   v8::Handle<v8::Value> data) {
+  // When hitting a debug event listener there must be a break set.
+  CHECK_NE(v8::internal::Debug::break_id(), 0);
+
+  if (event == v8::Break || event == v8::Exception) {
+    // Check that the current function is the expected.
+    CHECK(break_point_hit_count <
+          static_cast<int>(strlen(expected_step_sequence)));
+    const int argc = 1;
+    v8::Handle<v8::Value> argv[argc] = { exec_state };
+    v8::Handle<v8::Value> result = frame_function_name->Call(exec_state,
+                                                             argc, argv);
+    CHECK(result->IsString());
+    v8::String::AsciiValue function_name(result->ToString());
+    CHECK_EQ(1, strlen(*function_name));
+    CHECK_EQ((*function_name)[0],
+              expected_step_sequence[break_point_hit_count]);
+
+    // Perform step.
+    break_point_hit_count++;
+    PrepareStep(step_action);
+  }
+}
+
+
+// Debug event handler which performs a garbage collection.
+static void DebugEventBreakPointCollectGarbage(
+    v8::DebugEvent event,
+    v8::Handle<v8::Object> exec_state,
+    v8::Handle<v8::Object> event_data,
+    v8::Handle<v8::Value> data) {
+  // When hitting a debug event listener there must be a break set.
+  CHECK_NE(v8::internal::Debug::break_id(), 0);
+
+  // Perform a garbage collection when break point is hit and continue. Based
+  // on the number of break points hit either scavenge or mark compact
+  // collector is used.
+  if (event == v8::Break) {
+    break_point_hit_count++;
+    if (break_point_hit_count % 2 == 0) {
+      // Scavenge.
+      Heap::CollectGarbage(0, v8::internal::NEW_SPACE);
+    } else {
+      // Mark sweep (and perhaps compact).
+      Heap::CollectAllGarbage();
+    }
+  }
+}
+
+
+// Debug event handler which re-issues a debug break and calls the garbage
+// collector to have the heap verified.
+static void DebugEventBreak(v8::DebugEvent event,
+                            v8::Handle<v8::Object> exec_state,
+                            v8::Handle<v8::Object> event_data,
+                            v8::Handle<v8::Value> data) {
+  // When hitting a debug event listener there must be a break set.
+  CHECK_NE(v8::internal::Debug::break_id(), 0);
+
+  if (event == v8::Break) {
+    // Count the number of breaks.
+    break_point_hit_count++;
+
+    // Run the garbage collector to enforce heap verification if option
+    // --verify-heap is set.
+    Heap::CollectGarbage(0, v8::internal::NEW_SPACE);
+
+    // Set the break flag again to come back here as soon as possible.
+    v8::Debug::DebugBreak();
+  }
+}
+
+
+// --- M e s s a g e   C a l l b a c k
+
+
+// Message callback which counts the number of messages.
+int message_callback_count = 0;
+
+static void MessageCallbackCountClear() {
+  message_callback_count = 0;
+}
+
+static void MessageCallbackCount(v8::Handle<v8::Message> message,
+                                 v8::Handle<v8::Value> data) {
+  message_callback_count++;
+}
+
+
+// --- T h e   A c t u a l   T e s t s
+
+
+// Test that the debug break function is the expected one for different kinds
+// of break locations.
+TEST(DebugStub) {
+  using ::v8::internal::Builtins;
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  CheckDebugBreakFunction(&env,
+                          "function f1(){}", "f1",
+                          0,
+                          v8::internal::RelocInfo::JS_RETURN,
+                          NULL);
+  CheckDebugBreakFunction(&env,
+                          "function f2(){x=1;}", "f2",
+                          0,
+                          v8::internal::RelocInfo::CODE_TARGET,
+                          Builtins::builtin(Builtins::StoreIC_DebugBreak));
+  CheckDebugBreakFunction(&env,
+                          "function f3(){var a=x;}", "f3",
+                          0,
+                          v8::internal::RelocInfo::CODE_TARGET_CONTEXT,
+                          Builtins::builtin(Builtins::LoadIC_DebugBreak));
+
+// TODO(1240753): Make the test architecture independent or split
+// parts of the debugger into architecture dependent files. This
+// part currently disabled as it is not portable between IA32/ARM.
+// Currently on ICs for keyed store/load on ARM.
+#if !defined (__arm__) && !defined(__thumb__)
+  CheckDebugBreakFunction(
+      &env,
+      "function f4(){var index='propertyName'; var a={}; a[index] = 'x';}",
+      "f4",
+      0,
+      v8::internal::RelocInfo::CODE_TARGET,
+      Builtins::builtin(Builtins::KeyedStoreIC_DebugBreak));
+  CheckDebugBreakFunction(
+      &env,
+      "function f5(){var index='propertyName'; var a={}; return a[index];}",
+      "f5",
+      0,
+      v8::internal::RelocInfo::CODE_TARGET,
+      Builtins::builtin(Builtins::KeyedLoadIC_DebugBreak));
+#endif
+
+  // Check the debug break code stubs for call ICs with different number of
+  // parameters.
+  Handle<Code> debug_break_0 = v8::internal::ComputeCallDebugBreak(0);
+  Handle<Code> debug_break_1 = v8::internal::ComputeCallDebugBreak(1);
+  Handle<Code> debug_break_4 = v8::internal::ComputeCallDebugBreak(4);
+
+  CheckDebugBreakFunction(&env,
+                          "function f4_0(){x();}", "f4_0",
+                          0,
+                          v8::internal::RelocInfo::CODE_TARGET_CONTEXT,
+                          *debug_break_0);
+
+  CheckDebugBreakFunction(&env,
+                          "function f4_1(){x(1);}", "f4_1",
+                          0,
+                          v8::internal::RelocInfo::CODE_TARGET_CONTEXT,
+                          *debug_break_1);
+
+  CheckDebugBreakFunction(&env,
+                          "function f4_4(){x(1,2,3,4);}", "f4_4",
+                          0,
+                          v8::internal::RelocInfo::CODE_TARGET_CONTEXT,
+                          *debug_break_4);
+}
+
+
+// Test that the debug info in the VM is in sync with the functions being
+// debugged.
+TEST(DebugInfo) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  // Create a couple of functions for the test.
+  v8::Local<v8::Function> foo =
+      CompileFunction(&env, "function foo(){}", "foo");
+  v8::Local<v8::Function> bar =
+      CompileFunction(&env, "function bar(){}", "bar");
+  // Initially no functions are debugged.
+  CHECK_EQ(0, v8::internal::GetDebuggedFunctions()->length());
+  CHECK(!HasDebugInfo(foo));
+  CHECK(!HasDebugInfo(bar));
+  // One function (foo) is debugged.
+  int bp1 = SetBreakPoint(foo, 0);
+  CHECK_EQ(1, v8::internal::GetDebuggedFunctions()->length());
+  CHECK(HasDebugInfo(foo));
+  CHECK(!HasDebugInfo(bar));
+  // Two functions are debugged.
+  int bp2 = SetBreakPoint(bar, 0);
+  CHECK_EQ(2, v8::internal::GetDebuggedFunctions()->length());
+  CHECK(HasDebugInfo(foo));
+  CHECK(HasDebugInfo(bar));
+  // One function (bar) is debugged.
+  ClearBreakPoint(bp1);
+  CHECK_EQ(1, v8::internal::GetDebuggedFunctions()->length());
+  CHECK(!HasDebugInfo(foo));
+  CHECK(HasDebugInfo(bar));
+  // No functions are debugged.
+  ClearBreakPoint(bp2);
+  CHECK_EQ(0, v8::internal::GetDebuggedFunctions()->length());
+  CHECK(!HasDebugInfo(foo));
+  CHECK(!HasDebugInfo(bar));
+}
+
+
+// Test that a break point can be set at an IC store location.
+TEST(BreakPointICStore) {
+  break_point_hit_count = 0;
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+                                   v8::Undefined());
+  v8::Script::Compile(v8::String::New("function foo(){bar=0;}"))->Run();
+  v8::Local<v8::Function> foo =
+      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo")));
+
+  // Run without breakpoints.
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+
+  // Run with breakpoint
+  int bp = SetBreakPoint(foo, 0);
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, break_point_hit_count);
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+
+  // Run without breakpoints.
+  ClearBreakPoint(bp);
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+// Test that a break point can be set at an IC load location.
+TEST(BreakPointICLoad) {
+  break_point_hit_count = 0;
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+                                   v8::Undefined());
+  v8::Script::Compile(v8::String::New("bar=1"))->Run();
+  v8::Script::Compile(v8::String::New("function foo(){var x=bar;}"))->Run();
+  v8::Local<v8::Function> foo =
+      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo")));
+
+  // Run without breakpoints.
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+
+  // Run with breakpoint
+  int bp = SetBreakPoint(foo, 0);
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, break_point_hit_count);
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+
+  // Run without breakpoints.
+  ClearBreakPoint(bp);
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+// Test that a break point can be set at an IC call location.
+TEST(BreakPointICCall) {
+  break_point_hit_count = 0;
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+                                   v8::Undefined());
+  v8::Script::Compile(v8::String::New("function bar(){}"))->Run();
+  v8::Script::Compile(v8::String::New("function foo(){bar();}"))->Run();
+  v8::Local<v8::Function> foo =
+      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo")));
+
+  // Run without breakpoints.
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+
+  // Run with breakpoint
+  int bp = SetBreakPoint(foo, 0);
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, break_point_hit_count);
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+
+  // Run without breakpoints.
+  ClearBreakPoint(bp);
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+// Test that a break point can be set at a return store location.
+TEST(BreakPointReturn) {
+  break_point_hit_count = 0;
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Create a functions for checking the source line and column when hitting
+  // a break point.
+  frame_source_line = CompileFunction(&env,
+                                      frame_source_line_source,
+                                      "frame_source_line");
+  frame_source_column = CompileFunction(&env,
+                                        frame_source_column_source,
+                                        "frame_source_column");
+
+
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+                                   v8::Undefined());
+  v8::Script::Compile(v8::String::New("function foo(){}"))->Run();
+  v8::Local<v8::Function> foo =
+      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo")));
+
+  // Run without breakpoints.
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+
+  // Run with breakpoint
+  int bp = SetBreakPoint(foo, 0);
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, break_point_hit_count);
+  CHECK_EQ(0, last_source_line);
+  CHECK_EQ(16, last_source_column);
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+  CHECK_EQ(0, last_source_line);
+  CHECK_EQ(16, last_source_column);
+
+  // Run without breakpoints.
+  ClearBreakPoint(bp);
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+static void CallWithBreakPoints(v8::Local<v8::Object> recv,
+                                v8::Local<v8::Function> f,
+                                int break_point_count,
+                                int call_count) {
+  break_point_hit_count = 0;
+  for (int i = 0; i < call_count; i++) {
+    f->Call(recv, 0, NULL);
+    CHECK_EQ((i + 1) * break_point_count, break_point_hit_count);
+  }
+}
+
+// Test GC during break point processing.
+TEST(GCDuringBreakPointProcessing) {
+  break_point_hit_count = 0;
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointCollectGarbage,
+                                   v8::Undefined());
+  v8::Local<v8::Function> foo;
+
+  // Test IC store break point with garbage collection.
+  foo = CompileFunction(&env, "function foo(){bar=0;}", "foo");
+  SetBreakPoint(foo, 0);
+  CallWithBreakPoints(env->Global(), foo, 1, 10);
+
+  // Test IC load break point with garbage collection.
+  foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo");
+  SetBreakPoint(foo, 0);
+  CallWithBreakPoints(env->Global(), foo, 1, 10);
+
+  // Test IC call break point with garbage collection.
+  foo = CompileFunction(&env, "function bar(){};function foo(){bar();}", "foo");
+  SetBreakPoint(foo, 0);
+  CallWithBreakPoints(env->Global(), foo, 1, 10);
+
+  // Test return break point with garbage collection.
+  foo = CompileFunction(&env, "function foo(){}", "foo");
+  SetBreakPoint(foo, 0);
+  CallWithBreakPoints(env->Global(), foo, 1, 25);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+// Call the function three times with different garbage collections in between
+// and make sure that the break point survives.
+static void CallAndGC(v8::Local<v8::Object> recv, v8::Local<v8::Function> f) {
+  break_point_hit_count = 0;
+
+  for (int i = 0; i < 3; i++) {
+    // Call function.
+    f->Call(recv, 0, NULL);
+    CHECK_EQ(1 + i * 3, break_point_hit_count);
+
+    // Scavenge and call function.
+    Heap::CollectGarbage(0, v8::internal::NEW_SPACE);
+    f->Call(recv, 0, NULL);
+    CHECK_EQ(2 + i * 3, break_point_hit_count);
+
+    // Mark sweep (and perhaps compact) and call function.
+    Heap::CollectAllGarbage();
+    f->Call(recv, 0, NULL);
+    CHECK_EQ(3 + i * 3, break_point_hit_count);
+  }
+}
+
+
+// Test that a break point can be set at a return store location.
+TEST(BreakPointSurviveGC) {
+  break_point_hit_count = 0;
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+                                   v8::Undefined());
+  v8::Local<v8::Function> foo;
+
+  // Test IC store break point with garbage collection.
+  foo = CompileFunction(&env, "function foo(){bar=0;}", "foo");
+  SetBreakPoint(foo, 0);
+  CallAndGC(env->Global(), foo);
+
+  // Test IC load break point with garbage collection.
+  foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo");
+  SetBreakPoint(foo, 0);
+  CallAndGC(env->Global(), foo);
+
+  // Test IC call break point with garbage collection.
+  foo = CompileFunction(&env, "function bar(){};function foo(){bar();}", "foo");
+  SetBreakPoint(foo, 0);
+  CallAndGC(env->Global(), foo);
+
+  // Test return break point with garbage collection.
+  foo = CompileFunction(&env, "function foo(){}", "foo");
+  SetBreakPoint(foo, 0);
+  CallAndGC(env->Global(), foo);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+// Test that break points can be set using the global Debug object.
+TEST(BreakPointThroughJavaScript) {
+  break_point_hit_count = 0;
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  env.ExposeDebug();
+
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+                                   v8::Undefined());
+  v8::Script::Compile(v8::String::New("function bar(){}"))->Run();
+  v8::Script::Compile(v8::String::New("function foo(){bar();bar();}"))->Run();
+  //                                               012345678901234567890
+  //                                                         1         2
+  // Break points are set at position 3 and 9
+  v8::Local<v8::Script> foo = v8::Script::Compile(v8::String::New("foo()"));
+
+  // Run without breakpoints.
+  foo->Run();
+  CHECK_EQ(0, break_point_hit_count);
+
+  // Run with one breakpoint
+  int bp1 = SetBreakPointFromJS("foo", 0, 3);
+  foo->Run();
+  CHECK_EQ(1, break_point_hit_count);
+  foo->Run();
+  CHECK_EQ(2, break_point_hit_count);
+
+  // Run with two breakpoints
+  int bp2 = SetBreakPointFromJS("foo", 0, 9);
+  foo->Run();
+  CHECK_EQ(4, break_point_hit_count);
+  foo->Run();
+  CHECK_EQ(6, break_point_hit_count);
+
+  // Run with one breakpoint
+  ClearBreakPointFromJS(bp2);
+  foo->Run();
+  CHECK_EQ(7, break_point_hit_count);
+  foo->Run();
+  CHECK_EQ(8, break_point_hit_count);
+
+  // Run without breakpoints.
+  ClearBreakPointFromJS(bp1);
+  foo->Run();
+  CHECK_EQ(8, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+
+  // Make sure that the break point numbers are consecutive.
+  CHECK_EQ(1, bp1);
+  CHECK_EQ(2, bp2);
+}
+
+
+// Test that break points on scripts identified by name can be set using the
+// global Debug object.
+TEST(ScriptBreakPointByNameThroughJavaScript) {
+  break_point_hit_count = 0;
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  env.ExposeDebug();
+
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+                                   v8::Undefined());
+
+  v8::Local<v8::String> script = v8::String::New(
+    "function f() {\n"
+    "  function h() {\n"
+    "    a = 0;  // line 2\n"
+    "  }\n"
+    "  b = 1;  // line 4\n"
+    "  return h();\n"
+    "}\n"
+    "\n"
+    "function g() {\n"
+    "  function h() {\n"
+    "    a = 0;\n"
+    "  }\n"
+    "  b = 2;  // line 12\n"
+    "  h();\n"
+    "  b = 3;  // line 14\n"
+    "  f();    // line 15\n"
+    "}");
+
+  // Compile the script and get the two functions.
+  v8::ScriptOrigin origin =
+      v8::ScriptOrigin(v8::String::New("test"));
+  v8::Script::Compile(script, &origin)->Run();
+  v8::Local<v8::Function> f =
+      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+  v8::Local<v8::Function> g =
+      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("g")));
+
+  // Call f and g without break points.
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+  g->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+
+  // Call f and g with break point on line 12.
+  int sbp1 = SetScriptBreakPointByNameFromJS("test", 12, 0);
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+  g->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, break_point_hit_count);
+
+  // Remove the break point again.
+  break_point_hit_count = 0;
+  ClearBreakPointFromJS(sbp1);
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+  g->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+
+  // Call f and g with break point on line 2.
+  int sbp2 = SetScriptBreakPointByNameFromJS("test", 2, 0);
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, break_point_hit_count);
+  g->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+
+  // Call f and g with break point on line 2, 4, 12, 14 and 15.
+  int sbp3 = SetScriptBreakPointByNameFromJS("test", 4, 0);
+  int sbp4 = SetScriptBreakPointByNameFromJS("test", 12, 0);
+  int sbp5 = SetScriptBreakPointByNameFromJS("test", 14, 0);
+  int sbp6 = SetScriptBreakPointByNameFromJS("test", 15, 0);
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+  g->Call(env->Global(), 0, NULL);
+  CHECK_EQ(7, break_point_hit_count);
+
+  // Remove all the break points again.
+  break_point_hit_count = 0;
+  ClearBreakPointFromJS(sbp2);
+  ClearBreakPointFromJS(sbp3);
+  ClearBreakPointFromJS(sbp4);
+  ClearBreakPointFromJS(sbp5);
+  ClearBreakPointFromJS(sbp6);
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+  g->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+
+  // Make sure that the break point numbers are consecutive.
+  CHECK_EQ(1, sbp1);
+  CHECK_EQ(2, sbp2);
+  CHECK_EQ(3, sbp3);
+  CHECK_EQ(4, sbp4);
+  CHECK_EQ(5, sbp5);
+  CHECK_EQ(6, sbp6);
+}
+
+
+TEST(ScriptBreakPointByIdThroughJavaScript) {
+  break_point_hit_count = 0;
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  env.ExposeDebug();
+
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+                                   v8::Undefined());
+
+  v8::Local<v8::String> source = v8::String::New(
+    "function f() {\n"
+    "  function h() {\n"
+    "    a = 0;  // line 2\n"
+    "  }\n"
+    "  b = 1;  // line 4\n"
+    "  return h();\n"
+    "}\n"
+    "\n"
+    "function g() {\n"
+    "  function h() {\n"
+    "    a = 0;\n"
+    "  }\n"
+    "  b = 2;  // line 12\n"
+    "  h();\n"
+    "  b = 3;  // line 14\n"
+    "  f();    // line 15\n"
+    "}");
+
+  // Compile the script and get the two functions.
+  v8::ScriptOrigin origin =
+      v8::ScriptOrigin(v8::String::New("test"));
+  v8::Local<v8::Script> script = v8::Script::Compile(source, &origin);
+  script->Run();
+  v8::Local<v8::Function> f =
+      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+  v8::Local<v8::Function> g =
+      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("g")));
+
+  // Get the script id knowing that internally it is a 32 integer.
+  uint32_t script_id = script->Id()->Uint32Value();
+
+  // Call f and g without break points.
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+  g->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+
+  // Call f and g with break point on line 12.
+  int sbp1 = SetScriptBreakPointByIdFromJS(script_id, 12, 0);
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+  g->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, break_point_hit_count);
+
+  // Remove the break point again.
+  break_point_hit_count = 0;
+  ClearBreakPointFromJS(sbp1);
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+  g->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+
+  // Call f and g with break point on line 2.
+  int sbp2 = SetScriptBreakPointByIdFromJS(script_id, 2, 0);
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, break_point_hit_count);
+  g->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+
+  // Call f and g with break point on line 2, 4, 12, 14 and 15.
+  int sbp3 = SetScriptBreakPointByIdFromJS(script_id, 4, 0);
+  int sbp4 = SetScriptBreakPointByIdFromJS(script_id, 12, 0);
+  int sbp5 = SetScriptBreakPointByIdFromJS(script_id, 14, 0);
+  int sbp6 = SetScriptBreakPointByIdFromJS(script_id, 15, 0);
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+  g->Call(env->Global(), 0, NULL);
+  CHECK_EQ(7, break_point_hit_count);
+
+  // Remove all the break points again.
+  break_point_hit_count = 0;
+  ClearBreakPointFromJS(sbp2);
+  ClearBreakPointFromJS(sbp3);
+  ClearBreakPointFromJS(sbp4);
+  ClearBreakPointFromJS(sbp5);
+  ClearBreakPointFromJS(sbp6);
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+  g->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+
+  // Make sure that the break point numbers are consecutive.
+  CHECK_EQ(1, sbp1);
+  CHECK_EQ(2, sbp2);
+  CHECK_EQ(3, sbp3);
+  CHECK_EQ(4, sbp4);
+  CHECK_EQ(5, sbp5);
+  CHECK_EQ(6, sbp6);
+}
+
+
+// Test conditional script break points.
+TEST(EnableDisableScriptBreakPoint) {
+  break_point_hit_count = 0;
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  env.ExposeDebug();
+
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+                                   v8::Undefined());
+
+  v8::Local<v8::String> script = v8::String::New(
+    "function f() {\n"
+    "  a = 0;  // line 1\n"
+    "};");
+
+  // Compile the script and get function f.
+  v8::ScriptOrigin origin =
+      v8::ScriptOrigin(v8::String::New("test"));
+  v8::Script::Compile(script, &origin)->Run();
+  v8::Local<v8::Function> f =
+      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+
+  // Set script break point on line 1 (in function f).
+  int sbp = SetScriptBreakPointByNameFromJS("test", 1, 0);
+
+  // Call f while enabeling and disabling the script break point.
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, break_point_hit_count);
+
+  DisableScriptBreakPointFromJS(sbp);
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, break_point_hit_count);
+
+  EnableScriptBreakPointFromJS(sbp);
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+
+  DisableScriptBreakPointFromJS(sbp);
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+
+  // Reload the script and get f again checking that the disabeling survives.
+  v8::Script::Compile(script, &origin)->Run();
+  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+
+  EnableScriptBreakPointFromJS(sbp);
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(3, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+// Test conditional script break points.
+TEST(ConditionalScriptBreakPoint) {
+  break_point_hit_count = 0;
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  env.ExposeDebug();
+
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+                                   v8::Undefined());
+
+  v8::Local<v8::String> script = v8::String::New(
+    "count = 0;\n"
+    "function f() {\n"
+    "  g(count++);  // line 2\n"
+    "};\n"
+    "function g(x) {\n"
+    "  var a=x;  // line 5\n"
+    "};");
+
+  // Compile the script and get function f.
+  v8::ScriptOrigin origin =
+      v8::ScriptOrigin(v8::String::New("test"));
+  v8::Script::Compile(script, &origin)->Run();
+  v8::Local<v8::Function> f =
+      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+
+  // Set script break point on line 5 (in function g).
+  int sbp1 = SetScriptBreakPointByNameFromJS("test", 5, 0);
+
+  // Call f with different conditions on the script break point.
+  break_point_hit_count = 0;
+  ChangeScriptBreakPointConditionFromJS(sbp1, "false");
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+
+  ChangeScriptBreakPointConditionFromJS(sbp1, "true");
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, break_point_hit_count);
+
+  ChangeScriptBreakPointConditionFromJS(sbp1, "a % 2 == 0");
+  break_point_hit_count = 0;
+  for (int i = 0; i < 10; i++) {
+    f->Call(env->Global(), 0, NULL);
+  }
+  CHECK_EQ(5, break_point_hit_count);
+
+  // Reload the script and get f again checking that the condition survives.
+  v8::Script::Compile(script, &origin)->Run();
+  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+
+  break_point_hit_count = 0;
+  for (int i = 0; i < 10; i++) {
+    f->Call(env->Global(), 0, NULL);
+  }
+  CHECK_EQ(5, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+// Test ignore count on script break points.
+TEST(ScriptBreakPointIgnoreCount) {
+  break_point_hit_count = 0;
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  env.ExposeDebug();
+
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+                                   v8::Undefined());
+
+  v8::Local<v8::String> script = v8::String::New(
+    "function f() {\n"
+    "  a = 0;  // line 1\n"
+    "};");
+
+  // Compile the script and get function f.
+  v8::ScriptOrigin origin =
+      v8::ScriptOrigin(v8::String::New("test"));
+  v8::Script::Compile(script, &origin)->Run();
+  v8::Local<v8::Function> f =
+      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+
+  // Set script break point on line 1 (in function f).
+  int sbp = SetScriptBreakPointByNameFromJS("test", 1, 0);
+
+  // Call f with different ignores on the script break point.
+  break_point_hit_count = 0;
+  ChangeScriptBreakPointIgnoreCountFromJS(sbp, 1);
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, break_point_hit_count);
+
+  ChangeScriptBreakPointIgnoreCountFromJS(sbp, 5);
+  break_point_hit_count = 0;
+  for (int i = 0; i < 10; i++) {
+    f->Call(env->Global(), 0, NULL);
+  }
+  CHECK_EQ(5, break_point_hit_count);
+
+  // Reload the script and get f again checking that the ignore survives.
+  v8::Script::Compile(script, &origin)->Run();
+  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+
+  break_point_hit_count = 0;
+  for (int i = 0; i < 10; i++) {
+    f->Call(env->Global(), 0, NULL);
+  }
+  CHECK_EQ(5, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+// Test that script break points survive when a script is reloaded.
+TEST(ScriptBreakPointReload) {
+  break_point_hit_count = 0;
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  env.ExposeDebug();
+
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+                                   v8::Undefined());
+
+  v8::Local<v8::Function> f;
+  v8::Local<v8::String> script = v8::String::New(
+    "function f() {\n"
+    "  function h() {\n"
+    "    a = 0;  // line 2\n"
+    "  }\n"
+    "  b = 1;  // line 4\n"
+    "  return h();\n"
+    "}");
+
+  v8::ScriptOrigin origin_1 = v8::ScriptOrigin(v8::String::New("1"));
+  v8::ScriptOrigin origin_2 = v8::ScriptOrigin(v8::String::New("2"));
+
+  // Set a script break point before the script is loaded.
+  SetScriptBreakPointByNameFromJS("1", 2, 0);
+
+  // Compile the script and get the function.
+  v8::Script::Compile(script, &origin_1)->Run();
+  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+
+  // Call f and check that the script break point is active.
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, break_point_hit_count);
+
+  // Compile the script again with a different script data and get the
+  // function.
+  v8::Script::Compile(script, &origin_2)->Run();
+  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+
+  // Call f and check that no break points are set.
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+
+  // Compile the script again and get the function.
+  v8::Script::Compile(script, &origin_1)->Run();
+  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+
+  // Call f and check that the script break point is active.
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+// Test when several scripts has the same script data
+TEST(ScriptBreakPointMultiple) {
+  break_point_hit_count = 0;
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  env.ExposeDebug();
+
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+                                   v8::Undefined());
+
+  v8::Local<v8::Function> f;
+  v8::Local<v8::String> script_f = v8::String::New(
+    "function f() {\n"
+    "  a = 0;  // line 1\n"
+    "}");
+
+  v8::Local<v8::Function> g;
+  v8::Local<v8::String> script_g = v8::String::New(
+    "function g() {\n"
+    "  b = 0;  // line 1\n"
+    "}");
+
+  v8::ScriptOrigin origin =
+      v8::ScriptOrigin(v8::String::New("test"));
+
+  // Set a script break point before the scripts are loaded.
+  int sbp = SetScriptBreakPointByNameFromJS("test", 1, 0);
+
+  // Compile the scripts with same script data and get the functions.
+  v8::Script::Compile(script_f, &origin)->Run();
+  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+  v8::Script::Compile(script_g, &origin)->Run();
+  g = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("g")));
+
+  // Call f and g and check that the script break point is active.
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, break_point_hit_count);
+  g->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+
+  // Clear the script break point.
+  ClearBreakPointFromJS(sbp);
+
+  // Call f and g and check that the script break point is no longer active.
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+  g->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+
+  // Set script break point with the scripts loaded.
+  sbp = SetScriptBreakPointByNameFromJS("test", 1, 0);
+
+  // Call f and g and check that the script break point is active.
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, break_point_hit_count);
+  g->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+// Test the script origin which has both name and line offset.
+TEST(ScriptBreakPointLineOffset) {
+  break_point_hit_count = 0;
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  env.ExposeDebug();
+
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+                                   v8::Undefined());
+
+  v8::Local<v8::Function> f;
+  v8::Local<v8::String> script = v8::String::New(
+    "function f() {\n"
+    "  a = 0;  // line 8 as this script has line offset 7\n"
+    "  b = 0;  // line 9 as this script has line offset 7\n"
+    "}");
+
+  // Create script origin both name and line offset.
+  v8::ScriptOrigin origin(v8::String::New("test.html"),
+                          v8::Integer::New(7));
+
+  // Set two script break points before the script is loaded.
+  int sbp1 = SetScriptBreakPointByNameFromJS("test.html", 8, 0);
+  int sbp2 = SetScriptBreakPointByNameFromJS("test.html", 9, 0);
+
+  // Compile the script and get the function.
+  v8::Script::Compile(script, &origin)->Run();
+  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+
+  // Call f and check that the script break point is active.
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+
+  // Clear the script break points.
+  ClearBreakPointFromJS(sbp1);
+  ClearBreakPointFromJS(sbp2);
+
+  // Call f and check that no script break points are active.
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+
+  // Set a script break point with the script loaded.
+  sbp1 = SetScriptBreakPointByNameFromJS("test.html", 9, 0);
+
+  // Call f and check that the script break point is active.
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+// Test script break points set on lines.
+TEST(ScriptBreakPointLine) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  env.ExposeDebug();
+
+  // Create a function for checking the function when hitting a break point.
+  frame_function_name = CompileFunction(&env,
+                                        frame_function_name_source,
+                                        "frame_function_name");
+
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+                                   v8::Undefined());
+
+  v8::Local<v8::Function> f;
+  v8::Local<v8::Function> g;
+  v8::Local<v8::String> script = v8::String::New(
+    "a = 0                      // line 0\n"
+    "function f() {\n"
+    "  a = 1;                   // line 2\n"
+    "}\n"
+    " a = 2;                    // line 4\n"
+    "  /* xx */ function g() {  // line 5\n"
+    "    function h() {         // line 6\n"
+    "      a = 3;               // line 7\n"
+    "    }\n"
+    "    h();                   // line 9\n"
+    "    a = 4;                 // line 10\n"
+    "  }\n"
+    " a=5;                      // line 12");
+
+  // Set a couple script break point before the script is loaded.
+  int sbp1 = SetScriptBreakPointByNameFromJS("test.html", 0, -1);
+  int sbp2 = SetScriptBreakPointByNameFromJS("test.html", 1, -1);
+  int sbp3 = SetScriptBreakPointByNameFromJS("test.html", 5, -1);
+
+  // Compile the script and get the function.
+  break_point_hit_count = 0;
+  v8::ScriptOrigin origin(v8::String::New("test.html"), v8::Integer::New(0));
+  v8::Script::Compile(script, &origin)->Run();
+  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+  g = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("g")));
+
+  // Chesk that a break point was hit when the script was run.
+  CHECK_EQ(1, break_point_hit_count);
+  CHECK_EQ(0, strlen(last_function_hit));
+
+  // Call f and check that the script break point.
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+  CHECK_EQ("f", last_function_hit);
+
+  // Call g and check that the script break point.
+  g->Call(env->Global(), 0, NULL);
+  CHECK_EQ(3, break_point_hit_count);
+  CHECK_EQ("g", last_function_hit);
+
+  // Clear the script break point on g and set one on h.
+  ClearBreakPointFromJS(sbp3);
+  int sbp4 = SetScriptBreakPointByNameFromJS("test.html", 6, -1);
+
+  // Call g and check that the script break point in h is hit.
+  g->Call(env->Global(), 0, NULL);
+  CHECK_EQ(4, break_point_hit_count);
+  CHECK_EQ("h", last_function_hit);
+
+  // Clear break points in f and h. Set a new one in the script between
+  // functions f and g and test that there is no break points in f and g any
+  // more.
+  ClearBreakPointFromJS(sbp2);
+  ClearBreakPointFromJS(sbp4);
+  int sbp5 = SetScriptBreakPointByNameFromJS("test.html", 4, -1);
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  g->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+
+  // Reload the script which should hit two break points.
+  break_point_hit_count = 0;
+  v8::Script::Compile(script, &origin)->Run();
+  CHECK_EQ(2, break_point_hit_count);
+  CHECK_EQ(0, strlen(last_function_hit));
+
+  // Set a break point in the code after the last function decleration.
+  int sbp6 = SetScriptBreakPointByNameFromJS("test.html", 12, -1);
+
+  // Reload the script which should hit three break points.
+  break_point_hit_count = 0;
+  v8::Script::Compile(script, &origin)->Run();
+  CHECK_EQ(3, break_point_hit_count);
+  CHECK_EQ(0, strlen(last_function_hit));
+
+  // Clear the last break points, and reload the script which should not hit any
+  // break points.
+  ClearBreakPointFromJS(sbp1);
+  ClearBreakPointFromJS(sbp5);
+  ClearBreakPointFromJS(sbp6);
+  break_point_hit_count = 0;
+  v8::Script::Compile(script, &origin)->Run();
+  CHECK_EQ(0, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+// Test that it is possible to remove the last break point for a function
+// inside the break handling of that break point.
+TEST(RemoveBreakPointInBreak) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  v8::Local<v8::Function> foo =
+      CompileFunction(&env, "function foo(){a=1;}", "foo");
+  debug_event_remove_break_point = SetBreakPoint(foo, 0);
+
+  // Register the debug event listener pasing the function
+  v8::Debug::SetDebugEventListener(DebugEventRemoveBreakPoint, foo);
+
+  break_point_hit_count = 0;
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, break_point_hit_count);
+
+  break_point_hit_count = 0;
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+// Test that the debugger statement causes a break.
+TEST(DebuggerStatement) {
+  break_point_hit_count = 0;
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+                                   v8::Undefined());
+  v8::Script::Compile(v8::String::New("function bar(){debugger}"))->Run();
+  v8::Script::Compile(v8::String::New(
+      "function foo(){debugger;debugger;}"))->Run();
+  v8::Local<v8::Function> foo =
+      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo")));
+  v8::Local<v8::Function> bar =
+      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("bar")));
+
+  // Run function with debugger statement
+  bar->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, break_point_hit_count);
+
+  // Run function with two debugger statement
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(3, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+// Thest that the evaluation of expressions when a break point is hit generates
+// the correct results.
+TEST(DebugEvaluate) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  env.ExposeDebug();
+
+  // Create a function for checking the evaluation when hitting a break point.
+  evaluate_check_function = CompileFunction(&env,
+                                            evaluate_check_source,
+                                            "evaluate_check");
+  // Register the debug event listener
+  v8::Debug::SetDebugEventListener(DebugEventEvaluate);
+
+  // Different expected vaules of x and a when in a break point (u = undefined,
+  // d = Hello, world!).
+  struct EvaluateCheck checks_uu[] = {
+    {"x", v8::Undefined()},
+    {"a", v8::Undefined()},
+    {NULL, v8::Handle<v8::Value>()}
+  };
+  struct EvaluateCheck checks_hu[] = {
+    {"x", v8::String::New("Hello, world!")},
+    {"a", v8::Undefined()},
+    {NULL, v8::Handle<v8::Value>()}
+  };
+  struct EvaluateCheck checks_hh[] = {
+    {"x", v8::String::New("Hello, world!")},
+    {"a", v8::String::New("Hello, world!")},
+    {NULL, v8::Handle<v8::Value>()}
+  };
+
+  // Simple test function. The "y=0" is in the function foo to provide a break
+  // location. For "y=0" the "y" is at position 15 in the barbar function
+  // therefore setting breakpoint at position 15 will break at "y=0" and
+  // setting it higher will break after.
+  v8::Local<v8::Function> foo = CompileFunction(&env,
+    "function foo(x) {"
+    "  var a;"
+    "  y=0; /* To ensure break location.*/"
+    "  a=x;"
+    "}",
+    "foo");
+  const int foo_break_position = 15;
+
+  // Arguments with one parameter "Hello, world!"
+  v8::Handle<v8::Value> argv_foo[1] = { v8::String::New("Hello, world!") };
+
+  // Call foo with breakpoint set before a=x and undefined as parameter.
+  int bp = SetBreakPoint(foo, foo_break_position);
+  checks = checks_uu;
+  foo->Call(env->Global(), 0, NULL);
+
+  // Call foo with breakpoint set before a=x and parameter "Hello, world!".
+  checks = checks_hu;
+  foo->Call(env->Global(), 1, argv_foo);
+
+  // Call foo with breakpoint set after a=x and parameter "Hello, world!".
+  ClearBreakPoint(bp);
+  SetBreakPoint(foo, foo_break_position + 1);
+  checks = checks_hh;
+  foo->Call(env->Global(), 1, argv_foo);
+
+  // Test function with an inner function. The "y=0" is in function barbar
+  // to provide a break location. For "y=0" the "y" is at position 8 in the
+  // barbar function therefore setting breakpoint at position 8 will break at
+  // "y=0" and setting it higher will break after.
+  v8::Local<v8::Function> bar = CompileFunction(&env,
+    "y = 0;"
+    "x = 'Goodbye, world!';"
+    "function bar(x, b) {"
+    "  var a;"
+    "  function barbar() {"
+    "    y=0; /* To ensure break location.*/"
+    "    a=x;"
+    "  };"
+    "  debug.Debug.clearAllBreakPoints();"
+    "  barbar();"
+    "  y=0;a=x;"
+    "}",
+    "bar");
+  const int barbar_break_position = 8;
+
+  // Call bar setting breakpoint before a=x in barbar and undefined as
+  // parameter.
+  checks = checks_uu;
+  v8::Handle<v8::Value> argv_bar_1[2] = {
+    v8::Undefined(),
+    v8::Number::New(barbar_break_position)
+  };
+  bar->Call(env->Global(), 2, argv_bar_1);
+
+  // Call bar setting breakpoint before a=x in barbar and parameter
+  // "Hello, world!".
+  checks = checks_hu;
+  v8::Handle<v8::Value> argv_bar_2[2] = {
+    v8::String::New("Hello, world!"),
+    v8::Number::New(barbar_break_position)
+  };
+  bar->Call(env->Global(), 2, argv_bar_2);
+
+  // Call bar setting breakpoint after a=x in barbar and parameter
+  // "Hello, world!".
+  checks = checks_hh;
+  v8::Handle<v8::Value> argv_bar_3[2] = {
+    v8::String::New("Hello, world!"),
+    v8::Number::New(barbar_break_position + 1)
+  };
+  bar->Call(env->Global(), 2, argv_bar_3);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+// Simple test of the stepping mechanism using only store ICs.
+TEST(DebugStepLinear) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Create a function for testing stepping.
+  v8::Local<v8::Function> foo = CompileFunction(&env,
+                                                "function foo(){a=1;b=1;c=1;}",
+                                                "foo");
+  SetBreakPoint(foo, 3);
+
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStep);
+
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  foo->Call(env->Global(), 0, NULL);
+
+  // With stepping all break locations are hit.
+  CHECK_EQ(4, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+
+  // Register a debug event listener which just counts.
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
+
+  SetBreakPoint(foo, 3);
+  break_point_hit_count = 0;
+  foo->Call(env->Global(), 0, NULL);
+
+  // Without stepping only active break points are hit.
+  CHECK_EQ(1, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+// Test the stepping mechanism with different ICs.
+TEST(DebugStepLinearMixedICs) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Create a function for testing stepping.
+  v8::Local<v8::Function> foo = CompileFunction(&env,
+      "function bar() {};"
+      "function foo() {"
+      "  var x;"
+      "  var index='name';"
+      "  var y = {};"
+      "  a=1;b=2;x=a;y[index]=3;x=y[index];bar();}", "foo");
+  SetBreakPoint(foo, 0);
+
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStep);
+
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  foo->Call(env->Global(), 0, NULL);
+
+  // With stepping all break locations are hit. For ARM the keyed load/store
+  // is not hit as they are not implemented as ICs.
+#if defined (__arm__) || defined(__thumb__)
+  CHECK_EQ(6, break_point_hit_count);
+#else
+  CHECK_EQ(8, break_point_hit_count);
+#endif
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+
+  // Register a debug event listener which just counts.
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
+
+  SetBreakPoint(foo, 0);
+  break_point_hit_count = 0;
+  foo->Call(env->Global(), 0, NULL);
+
+  // Without stepping only active break points are hit.
+  CHECK_EQ(1, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+TEST(DebugStepIf) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStep);
+
+  // Create a function for testing stepping.
+  const int argc = 1;
+  const char* src = "function foo(x) { "
+                    "  a = 1;"
+                    "  if (x) {"
+                    "    b = 1;"
+                    "  } else {"
+                    "    c = 1;"
+                    "    d = 1;"
+                    "  }"
+                    "}";
+  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
+  SetBreakPoint(foo, 0);
+
+  // Stepping through the true part.
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  v8::Handle<v8::Value> argv_true[argc] = { v8::True() };
+  foo->Call(env->Global(), argc, argv_true);
+  CHECK_EQ(3, break_point_hit_count);
+
+  // Stepping through the false part.
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  v8::Handle<v8::Value> argv_false[argc] = { v8::False() };
+  foo->Call(env->Global(), argc, argv_false);
+  CHECK_EQ(4, break_point_hit_count);
+
+  // Get rid of the debug event listener.
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+TEST(DebugStepSwitch) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStep);
+
+  // Create a function for testing stepping.
+  const int argc = 1;
+  const char* src = "function foo(x) { "
+                    "  a = 1;"
+                    "  switch (x) {"
+                    "    case 1:"
+                    "      b = 1;"
+                    "    case 2:"
+                    "      c = 1;"
+                    "      break;"
+                    "    case 3:"
+                    "      d = 1;"
+                    "      e = 1;"
+                    "      break;"
+                    "  }"
+                    "}";
+  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
+  SetBreakPoint(foo, 0);
+
+  // One case with fall-through.
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  v8::Handle<v8::Value> argv_1[argc] = { v8::Number::New(1) };
+  foo->Call(env->Global(), argc, argv_1);
+  CHECK_EQ(4, break_point_hit_count);
+
+  // Another case.
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  v8::Handle<v8::Value> argv_2[argc] = { v8::Number::New(2) };
+  foo->Call(env->Global(), argc, argv_2);
+  CHECK_EQ(3, break_point_hit_count);
+
+  // Last case.
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  v8::Handle<v8::Value> argv_3[argc] = { v8::Number::New(3) };
+  foo->Call(env->Global(), argc, argv_3);
+  CHECK_EQ(4, break_point_hit_count);
+
+  // Get rid of the debug event listener.
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+TEST(DebugStepFor) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStep);
+
+  // Create a function for testing stepping.
+  const int argc = 1;
+  const char* src = "function foo(x) { "
+                    "  a = 1;"
+                    "  for (i = 0; i < x; i++) {"
+                    "    b = 1;"
+                    "  }"
+                    "}";
+  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
+  SetBreakPoint(foo, 8);  // "a = 1;"
+
+  // Looping 10 times.
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(10) };
+  foo->Call(env->Global(), argc, argv_10);
+  CHECK_EQ(23, break_point_hit_count);
+
+  // Looping 100 times.
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(100) };
+  foo->Call(env->Global(), argc, argv_100);
+  CHECK_EQ(203, break_point_hit_count);
+
+  // Get rid of the debug event listener.
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+TEST(StepInOutSimple) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Create a function for checking the function when hitting a break point.
+  frame_function_name = CompileFunction(&env,
+                                        frame_function_name_source,
+                                        "frame_function_name");
+
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStepSequence);
+
+  // Create functions for testing stepping.
+  const char* src = "function a() {b();c();}; "
+                    "function b() {c();}; "
+                    "function c() {}; ";
+  v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
+  SetBreakPoint(a, 0);
+
+  // Step through invocation of a with step in.
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  expected_step_sequence = "abcbaca";
+  a->Call(env->Global(), 0, NULL);
+  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+
+  // Step through invocation of a with step next.
+  step_action = StepNext;
+  break_point_hit_count = 0;
+  expected_step_sequence = "aaa";
+  a->Call(env->Global(), 0, NULL);
+  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+
+  // Step through invocation of a with step out.
+  step_action = StepOut;
+  break_point_hit_count = 0;
+  expected_step_sequence = "a";
+  a->Call(env->Global(), 0, NULL);
+  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+
+  // Get rid of the debug event listener.
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+TEST(StepInOutTree) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Create a function for checking the function when hitting a break point.
+  frame_function_name = CompileFunction(&env,
+                                        frame_function_name_source,
+                                        "frame_function_name");
+
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStepSequence);
+
+  // Create functions for testing stepping.
+  const char* src = "function a() {b(c(d()),d());c(d());d()}; "
+                    "function b(x,y) {c();}; "
+                    "function c(x) {}; "
+                    "function d() {}; ";
+  v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
+  SetBreakPoint(a, 0);
+
+  // Step through invocation of a with step in.
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  expected_step_sequence = "adacadabcbadacada";
+  a->Call(env->Global(), 0, NULL);
+  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+
+  // Step through invocation of a with step next.
+  step_action = StepNext;
+  break_point_hit_count = 0;
+  expected_step_sequence = "aaaa";
+  a->Call(env->Global(), 0, NULL);
+  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+
+  // Step through invocation of a with step out.
+  step_action = StepOut;
+  break_point_hit_count = 0;
+  expected_step_sequence = "a";
+  a->Call(env->Global(), 0, NULL);
+  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+
+  // Get rid of the debug event listener.
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded(true);
+}
+
+
+TEST(StepInOutBranch) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Create a function for checking the function when hitting a break point.
+  frame_function_name = CompileFunction(&env,
+                                        frame_function_name_source,
+                                        "frame_function_name");
+
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStepSequence);
+
+  // Create functions for testing stepping.
+  const char* src = "function a() {b(false);c();}; "
+                    "function b(x) {if(x){c();};}; "
+                    "function c() {}; ";
+  v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
+  SetBreakPoint(a, 0);
+
+  // Step through invocation of a.
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  expected_step_sequence = "abaca";
+  a->Call(env->Global(), 0, NULL);
+  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+
+  // Get rid of the debug event listener.
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+// Test that step in does not step into native functions.
+TEST(DebugStepNatives) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Create a function for testing stepping.
+  v8::Local<v8::Function> foo = CompileFunction(
+      &env,
+      "function foo(){debugger;Math.sin(1);}",
+      "foo");
+
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStep);
+
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  foo->Call(env->Global(), 0, NULL);
+
+  // With stepping all break locations are hit.
+  CHECK_EQ(3, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+
+  // Register a debug event listener which just counts.
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
+
+  break_point_hit_count = 0;
+  foo->Call(env->Global(), 0, NULL);
+
+  // Without stepping only active break points are hit.
+  CHECK_EQ(1, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+// Test that step in works with function.apply.
+TEST(DebugStepFunctionApply) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Create a function for testing stepping.
+  v8::Local<v8::Function> foo = CompileFunction(
+      &env,
+      "function bar(x, y, z) { if (x == 1) { a = y; b = z; } }"
+      "function foo(){ debugger; bar.apply(this, [1,2,3]); }",
+      "foo");
+
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStep);
+
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  foo->Call(env->Global(), 0, NULL);
+
+  // With stepping all break locations are hit.
+  CHECK_EQ(6, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+
+  // Register a debug event listener which just counts.
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
+
+  break_point_hit_count = 0;
+  foo->Call(env->Global(), 0, NULL);
+
+  // Without stepping only the debugger statement is hit.
+  CHECK_EQ(1, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+// Test that step in works with function.call.
+TEST(DebugStepFunctionCall) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Create a function for testing stepping.
+  v8::Local<v8::Function> foo = CompileFunction(
+      &env,
+      "function bar(x, y, z) { if (x == 1) { a = y; b = z; } }"
+      "function foo(a){ debugger;"
+      "                 if (a) {"
+      "                   bar.call(this, 1, 2, 3);"
+      "                 } else {"
+      "                   bar.call(this, 0);"
+      "                 }"
+      "}",
+      "foo");
+
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStep);
+  step_action = StepIn;
+
+  // Check stepping where the if condition in bar is false.
+  break_point_hit_count = 0;
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(4, break_point_hit_count);
+
+  // Check stepping where the if condition in bar is true.
+  break_point_hit_count = 0;
+  const int argc = 1;
+  v8::Handle<v8::Value> argv[argc] = { v8::True() };
+  foo->Call(env->Global(), argc, argv);
+  CHECK_EQ(6, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+
+  // Register a debug event listener which just counts.
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
+
+  break_point_hit_count = 0;
+  foo->Call(env->Global(), 0, NULL);
+
+  // Without stepping only the debugger statement is hit.
+  CHECK_EQ(1, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+// Test break on exceptions. For each exception break combination the number
+// of debug event exception callbacks and message callbacks are collected. The
+// number of debug event exception callbacks are used to check that the
+// debugger is called correctly and the number of message callbacks is used to
+// check that uncaught exceptions are still returned even if there is a break
+// for them.
+TEST(BreakOnException) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  env.ExposeDebug();
+
+  v8::internal::Top::TraceException(false);
+
+  // Create functions for testing break on exception.
+  v8::Local<v8::Function> throws =
+      CompileFunction(&env, "function throws(){throw 1;}", "throws");
+  v8::Local<v8::Function> caught =
+      CompileFunction(&env,
+                      "function caught(){try {throws();} catch(e) {};}",
+                      "caught");
+  v8::Local<v8::Function> notCaught =
+      CompileFunction(&env, "function notCaught(){throws();}", "notCaught");
+
+  v8::V8::AddMessageListener(MessageCallbackCount);
+  v8::Debug::SetDebugEventListener(DebugEventCounter);
+
+  // Initial state should be break on uncaught exception.
+  DebugEventCounterClear();
+  MessageCallbackCountClear();
+  caught->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, exception_hit_count);
+  CHECK_EQ(0, uncaught_exception_hit_count);
+  CHECK_EQ(0, message_callback_count);
+  notCaught->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, exception_hit_count);
+  CHECK_EQ(1, uncaught_exception_hit_count);
+  CHECK_EQ(1, message_callback_count);
+
+  // No break on exception
+  DebugEventCounterClear();
+  MessageCallbackCountClear();
+  ChangeBreakOnException(false, false);
+  caught->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, exception_hit_count);
+  CHECK_EQ(0, uncaught_exception_hit_count);
+  CHECK_EQ(0, message_callback_count);
+  notCaught->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, exception_hit_count);
+  CHECK_EQ(0, uncaught_exception_hit_count);
+  CHECK_EQ(1, message_callback_count);
+
+  // Break on uncaught exception
+  DebugEventCounterClear();
+  MessageCallbackCountClear();
+  ChangeBreakOnException(false, true);
+  caught->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, exception_hit_count);
+  CHECK_EQ(0, uncaught_exception_hit_count);
+  CHECK_EQ(0, message_callback_count);
+  notCaught->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, exception_hit_count);
+  CHECK_EQ(1, uncaught_exception_hit_count);
+  CHECK_EQ(1, message_callback_count);
+
+  // Break on exception and uncaught exception
+  DebugEventCounterClear();
+  MessageCallbackCountClear();
+  ChangeBreakOnException(true, true);
+  caught->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, exception_hit_count);
+  CHECK_EQ(0, uncaught_exception_hit_count);
+  CHECK_EQ(0, message_callback_count);
+  notCaught->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, exception_hit_count);
+  CHECK_EQ(1, uncaught_exception_hit_count);
+  CHECK_EQ(1, message_callback_count);
+
+  // Break on exception
+  DebugEventCounterClear();
+  MessageCallbackCountClear();
+  ChangeBreakOnException(true, false);
+  caught->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, exception_hit_count);
+  CHECK_EQ(0, uncaught_exception_hit_count);
+  CHECK_EQ(0, message_callback_count);
+  notCaught->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, exception_hit_count);
+  CHECK_EQ(1, uncaught_exception_hit_count);
+  CHECK_EQ(1, message_callback_count);
+
+  // No break on exception using JavaScript
+  DebugEventCounterClear();
+  MessageCallbackCountClear();
+  ChangeBreakOnExceptionFromJS(false, false);
+  caught->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, exception_hit_count);
+  CHECK_EQ(0, uncaught_exception_hit_count);
+  CHECK_EQ(0, message_callback_count);
+  notCaught->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, exception_hit_count);
+  CHECK_EQ(0, uncaught_exception_hit_count);
+  CHECK_EQ(1, message_callback_count);
+
+  // Break on uncaught exception using JavaScript
+  DebugEventCounterClear();
+  MessageCallbackCountClear();
+  ChangeBreakOnExceptionFromJS(false, true);
+  caught->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, exception_hit_count);
+  CHECK_EQ(0, uncaught_exception_hit_count);
+  CHECK_EQ(0, message_callback_count);
+  notCaught->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, exception_hit_count);
+  CHECK_EQ(1, uncaught_exception_hit_count);
+  CHECK_EQ(1, message_callback_count);
+
+  // Break on exception and uncaught exception using JavaScript
+  DebugEventCounterClear();
+  MessageCallbackCountClear();
+  ChangeBreakOnExceptionFromJS(true, true);
+  caught->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, exception_hit_count);
+  CHECK_EQ(0, message_callback_count);
+  CHECK_EQ(0, uncaught_exception_hit_count);
+  notCaught->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, exception_hit_count);
+  CHECK_EQ(1, uncaught_exception_hit_count);
+  CHECK_EQ(1, message_callback_count);
+
+  // Break on exception using JavaScript
+  DebugEventCounterClear();
+  MessageCallbackCountClear();
+  ChangeBreakOnExceptionFromJS(true, false);
+  caught->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, exception_hit_count);
+  CHECK_EQ(0, uncaught_exception_hit_count);
+  CHECK_EQ(0, message_callback_count);
+  notCaught->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, exception_hit_count);
+  CHECK_EQ(1, uncaught_exception_hit_count);
+  CHECK_EQ(1, message_callback_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+  v8::V8::RemoveMessageListeners(MessageCallbackCount);
+}
+
+
+// Test break on exception from compiler errors. When compiling using
+// v8::Script::Compile there is no JavaScript stack whereas when compiling using
+// eval there are JavaScript frames.
+TEST(BreakOnCompileException) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  v8::internal::Top::TraceException(false);
+
+  // Create a function for checking the function when hitting a break point.
+  frame_count = CompileFunction(&env, frame_count_source, "frame_count");
+
+  v8::V8::AddMessageListener(MessageCallbackCount);
+  v8::Debug::SetDebugEventListener(DebugEventCounter);
+
+  DebugEventCounterClear();
+  MessageCallbackCountClear();
+
+  // Check initial state.
+  CHECK_EQ(0, exception_hit_count);
+  CHECK_EQ(0, uncaught_exception_hit_count);
+  CHECK_EQ(0, message_callback_count);
+  CHECK_EQ(-1, last_js_stack_height);
+
+  // Throws SyntaxError: Unexpected end of input
+  v8::Script::Compile(v8::String::New("+++"));
+  CHECK_EQ(1, exception_hit_count);
+  CHECK_EQ(1, uncaught_exception_hit_count);
+  CHECK_EQ(1, message_callback_count);
+  CHECK_EQ(0, last_js_stack_height);  // No JavaScript stack.
+
+  // Throws SyntaxError: Unexpected identifier
+  v8::Script::Compile(v8::String::New("x x"));
+  CHECK_EQ(2, exception_hit_count);
+  CHECK_EQ(2, uncaught_exception_hit_count);
+  CHECK_EQ(2, message_callback_count);
+  CHECK_EQ(0, last_js_stack_height);  // No JavaScript stack.
+
+  // Throws SyntaxError: Unexpected end of input
+  v8::Script::Compile(v8::String::New("eval('+++')"))->Run();
+  CHECK_EQ(3, exception_hit_count);
+  CHECK_EQ(3, uncaught_exception_hit_count);
+  CHECK_EQ(3, message_callback_count);
+  CHECK_EQ(1, last_js_stack_height);
+
+  // Throws SyntaxError: Unexpected identifier
+  v8::Script::Compile(v8::String::New("eval('x x')"))->Run();
+  CHECK_EQ(4, exception_hit_count);
+  CHECK_EQ(4, uncaught_exception_hit_count);
+  CHECK_EQ(4, message_callback_count);
+  CHECK_EQ(1, last_js_stack_height);
+}
+
+
+TEST(StepWithException) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Create a function for checking the function when hitting a break point.
+  frame_function_name = CompileFunction(&env,
+                                        frame_function_name_source,
+                                        "frame_function_name");
+
+  // Register a debug event listener which steps and counts.
+  v8::Debug::SetDebugEventListener(DebugEventStepSequence);
+
+  // Create functions for testing stepping.
+  const char* src = "function a() { n(); }; "
+                    "function b() { c(); }; "
+                    "function c() { n(); }; "
+                    "function d() { x = 1; try { e(); } catch(x) { x = 2; } }; "
+                    "function e() { n(); }; "
+                    "function f() { x = 1; try { g(); } catch(x) { x = 2; } }; "
+                    "function g() { h(); }; "
+                    "function h() { x = 1; throw 1; }; ";
+
+  // Step through invocation of a.
+  v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
+  SetBreakPoint(a, 0);
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  expected_step_sequence = "aa";
+  a->Call(env->Global(), 0, NULL);
+  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+
+  // Step through invocation of b + c.
+  v8::Local<v8::Function> b = CompileFunction(&env, src, "b");
+  SetBreakPoint(b, 0);
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  expected_step_sequence = "bcc";
+  b->Call(env->Global(), 0, NULL);
+  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+
+  // Step through invocation of d + e.
+  v8::Local<v8::Function> d = CompileFunction(&env, src, "d");
+  SetBreakPoint(d, 0);
+  ChangeBreakOnException(false, true);
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  expected_step_sequence = "dded";
+  d->Call(env->Global(), 0, NULL);
+  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+
+  // Step through invocation of d + e now with break on caught exceptions.
+  ChangeBreakOnException(true, true);
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  expected_step_sequence = "ddeed";
+  d->Call(env->Global(), 0, NULL);
+  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+
+  // Step through invocation of f + g + h.
+  v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
+  SetBreakPoint(f, 0);
+  ChangeBreakOnException(false, true);
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  expected_step_sequence = "ffghf";
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+
+  // Step through invocation of f + g + h now with break on caught exceptions.
+  ChangeBreakOnException(true, true);
+  step_action = StepIn;
+  break_point_hit_count = 0;
+  expected_step_sequence = "ffghhf";
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
+
+  // Get rid of the debug event listener.
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+TEST(DebugBreak) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // This test should be run with option --verify-heap. This is an ASSERT and
+  // not a CHECK as --verify-heap is only available in debug mode.
+  ASSERT(v8::internal::FLAG_verify_heap);
+
+  // Register a debug event listener which sets the break flag and counts.
+  v8::Debug::SetDebugEventListener(DebugEventBreak);
+
+  // Create a function for testing stepping.
+  const char* src = "function f0() {}"
+                    "function f1(x1) {}"
+                    "function f2(x1,x2) {}"
+                    "function f3(x1,x2,x3) {}";
+  v8::Local<v8::Function> f0 = CompileFunction(&env, src, "f0");
+  v8::Local<v8::Function> f1 = CompileFunction(&env, src, "f1");
+  v8::Local<v8::Function> f2 = CompileFunction(&env, src, "f2");
+  v8::Local<v8::Function> f3 = CompileFunction(&env, src, "f3");
+
+  // Call the function to make sure it is compiled.
+  v8::Handle<v8::Value> argv[] = { v8::Number::New(1),
+                                   v8::Number::New(1),
+                                   v8::Number::New(1),
+                                   v8::Number::New(1) };
+
+  // Call all functions to make sure that they are compiled.
+  f0->Call(env->Global(), 0, NULL);
+  f1->Call(env->Global(), 0, NULL);
+  f2->Call(env->Global(), 0, NULL);
+  f3->Call(env->Global(), 0, NULL);
+
+  // Set the debug break flag.
+  v8::Debug::DebugBreak();
+
+  // Call all functions with different argument count.
+  break_point_hit_count = 0;
+  for (unsigned int i = 0; i < ARRAY_SIZE(argv); i++) {
+    f0->Call(env->Global(), i, argv);
+    f1->Call(env->Global(), i, argv);
+    f2->Call(env->Global(), i, argv);
+    f3->Call(env->Global(), i, argv);
+  }
+
+  // One break for each function called.
+  CHECK_EQ(4 * ARRAY_SIZE(argv), break_point_hit_count);
+
+  // Get rid of the debug event listener.
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+// Test to ensure that JavaScript code keeps running while the debug break
+// through the stack limit flag is set but breaks are disabled.
+TEST(DisableBreak) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Register a debug event listener which sets the break flag and counts.
+  v8::Debug::SetDebugEventListener(DebugEventCounter);
+
+  // Create a function for testing stepping.
+  const char* src = "function f() {g()};function g(){i=0; while(i<10){i++}}";
+  v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
+
+  // Set the debug break flag.
+  v8::Debug::DebugBreak();
+
+  // Call all functions with different argument count.
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(1, break_point_hit_count);
+
+  {
+    v8::Debug::DebugBreak();
+    v8::internal::DisableBreak disable_break(true);
+    f->Call(env->Global(), 0, NULL);
+    CHECK_EQ(1, break_point_hit_count);
+  }
+
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+
+  // Get rid of the debug event listener.
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
+static v8::Handle<v8::Array> NamedEnum(const v8::AccessorInfo&) {
+  v8::Handle<v8::Array> result = v8::Array::New(3);
+  result->Set(v8::Integer::New(0), v8::String::New("a"));
+  result->Set(v8::Integer::New(1), v8::String::New("b"));
+  result->Set(v8::Integer::New(2), v8::String::New("c"));
+  return result;
+}
+
+
+static v8::Handle<v8::Array> IndexedEnum(const v8::AccessorInfo&) {
+  v8::Handle<v8::Array> result = v8::Array::New(2);
+  result->Set(v8::Integer::New(0), v8::Number::New(1));
+  result->Set(v8::Integer::New(1), v8::Number::New(10));
+  return result;
+}
+
+
+static v8::Handle<v8::Value> NamedGetter(v8::Local<v8::String> name,
+                                         const v8::AccessorInfo& info) {
+  v8::String::AsciiValue n(name);
+  if (strcmp(*n, "a") == 0) {
+    return v8::String::New("AA");
+  } else if (strcmp(*n, "b") == 0) {
+    return v8::String::New("BB");
+  } else if (strcmp(*n, "c") == 0) {
+    return v8::String::New("CC");
+  } else {
+    return v8::Undefined();
+  }
+
+  return name;
+}
+
+
+static v8::Handle<v8::Value> IndexedGetter(uint32_t index,
+                                           const v8::AccessorInfo& info) {
+  return v8::Number::New(index + 1);
+}
+
+
+TEST(InterceptorPropertyMirror) {
+  // Create a V8 environment with debug access.
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  env.ExposeDebug();
+
+  // Create object with named interceptor.
+  v8::Handle<v8::ObjectTemplate> named = v8::ObjectTemplate::New();
+  named->SetNamedPropertyHandler(NamedGetter, NULL, NULL, NULL, NamedEnum);
+  env->Global()->Set(v8::String::New("intercepted_named"),
+                     named->NewInstance());
+
+  // Create object with indexed interceptor.
+  v8::Handle<v8::ObjectTemplate> indexed = v8::ObjectTemplate::New();
+  indexed->SetIndexedPropertyHandler(IndexedGetter,
+                                     NULL,
+                                     NULL,
+                                     NULL,
+                                     IndexedEnum);
+  env->Global()->Set(v8::String::New("intercepted_indexed"),
+                     indexed->NewInstance());
+
+  // Create object with both named and indexed interceptor.
+  v8::Handle<v8::ObjectTemplate> both = v8::ObjectTemplate::New();
+  both->SetNamedPropertyHandler(NamedGetter, NULL, NULL, NULL, NamedEnum);
+  both->SetIndexedPropertyHandler(IndexedGetter, NULL, NULL, NULL, IndexedEnum);
+  env->Global()->Set(v8::String::New("intercepted_both"), both->NewInstance());
+
+  // Get mirrors for the three objects with interceptor.
+  CompileRun(
+      "named_mirror = debug.MakeMirror(intercepted_named);"
+      "indexed_mirror = debug.MakeMirror(intercepted_indexed);"
+      "both_mirror = debug.MakeMirror(intercepted_both)");
+  CHECK(CompileRun(
+       "named_mirror instanceof debug.ObjectMirror")->BooleanValue());
+  CHECK(CompileRun(
+        "indexed_mirror instanceof debug.ObjectMirror")->BooleanValue());
+  CHECK(CompileRun(
+        "both_mirror instanceof debug.ObjectMirror")->BooleanValue());
+
+  // Get the property names from the interceptors
+  CompileRun(
+      "named_names = named_mirror.propertyNames();"
+      "indexed_names = indexed_mirror.propertyNames();"
+      "both_names = both_mirror.propertyNames()");
+  CHECK_EQ(3, CompileRun("named_names.length")->Int32Value());
+  CHECK_EQ(2, CompileRun("indexed_names.length")->Int32Value());
+  CHECK_EQ(5, CompileRun("both_names.length")->Int32Value());
+
+  // Check the expected number of properties.
+  const char* source;
+  source = "named_mirror.properties().length";
+  CHECK_EQ(3, CompileRun(source)->Int32Value());
+
+  source = "indexed_mirror.properties().length";
+  CHECK_EQ(2, CompileRun(source)->Int32Value());
+
+  source = "both_mirror.properties().length";
+  CHECK_EQ(5, CompileRun(source)->Int32Value());
+
+  // 1 is PropertyKind.Named;
+  source = "both_mirror.properties(1).length";
+  CHECK_EQ(3, CompileRun(source)->Int32Value());
+
+  // 2 is PropertyKind.Indexed;
+  source = "both_mirror.properties(2).length";
+  CHECK_EQ(2, CompileRun(source)->Int32Value());
+
+  // 3 is PropertyKind.Named  | PropertyKind.Indexed;
+  source = "both_mirror.properties(3).length";
+  CHECK_EQ(5, CompileRun(source)->Int32Value());
+
+  // Get the interceptor properties for the object with only named interceptor.
+  CompileRun("named_values = named_mirror.properties()");
+
+  // Check that the properties are interceptor properties.
+  for (int i = 0; i < 3; i++) {
+    EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
+    OS::SNPrintF(buffer,
+                 "named_values[%d] instanceof debug.PropertyMirror", i);
+    CHECK(CompileRun(buffer.start())->BooleanValue());
+
+    // 4 is PropertyType.Interceptor
+    OS::SNPrintF(buffer, "named_values[%d].propertyType()", i);
+    CHECK_EQ(4, CompileRun(buffer.start())->Int32Value());
+
+    OS::SNPrintF(buffer, "named_values[%d].isNative()", i);
+    CHECK(CompileRun(buffer.start())->BooleanValue());
+  }
+
+  // Get the interceptor properties for the object with only indexed
+  // interceptor.
+  CompileRun("indexed_values = indexed_mirror.properties()");
+
+  // Check that the properties are interceptor properties.
+  for (int i = 0; i < 2; i++) {
+    EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
+    OS::SNPrintF(buffer,
+                 "indexed_values[%d] instanceof debug.PropertyMirror", i);
+    CHECK(CompileRun(buffer.start())->BooleanValue());
+  }
+
+  // Get the interceptor properties for the object with both types of
+  // interceptors.
+  CompileRun("both_values = both_mirror.properties()");
+
+  // Check that the properties are interceptor properties.
+  for (int i = 0; i < 5; i++) {
+    EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
+    OS::SNPrintF(buffer, "both_values[%d] instanceof debug.PropertyMirror", i);
+    CHECK(CompileRun(buffer.start())->BooleanValue());
+  }
+
+  // Check the property names.
+  source = "both_values[0].name() == 'a'";
+  CHECK(CompileRun(source)->BooleanValue());
+
+  source = "both_values[1].name() == 'b'";
+  CHECK(CompileRun(source)->BooleanValue());
+
+  source = "both_values[2].name() == 'c'";
+  CHECK(CompileRun(source)->BooleanValue());
+
+  source = "both_values[3].name() == 1";
+  CHECK(CompileRun(source)->BooleanValue());
+
+  source = "both_values[4].name() == 10";
+  CHECK(CompileRun(source)->BooleanValue());
+}
+
+
+TEST(HiddenPrototypePropertyMirror) {
+  // Create a V8 environment with debug access.
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  env.ExposeDebug();
+
+  v8::Handle<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
+  t0->InstanceTemplate()->Set(v8::String::New("x"), v8::Number::New(0));
+  v8::Handle<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
+  t1->SetHiddenPrototype(true);
+  t1->InstanceTemplate()->Set(v8::String::New("y"), v8::Number::New(1));
+  v8::Handle<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
+  t2->SetHiddenPrototype(true);
+  t2->InstanceTemplate()->Set(v8::String::New("z"), v8::Number::New(2));
+  v8::Handle<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
+  t3->InstanceTemplate()->Set(v8::String::New("u"), v8::Number::New(3));
+
+  // Create object and set them on the global object.
+  v8::Handle<v8::Object> o0 = t0->GetFunction()->NewInstance();
+  env->Global()->Set(v8::String::New("o0"), o0);
+  v8::Handle<v8::Object> o1 = t1->GetFunction()->NewInstance();
+  env->Global()->Set(v8::String::New("o1"), o1);
+  v8::Handle<v8::Object> o2 = t2->GetFunction()->NewInstance();
+  env->Global()->Set(v8::String::New("o2"), o2);
+  v8::Handle<v8::Object> o3 = t3->GetFunction()->NewInstance();
+  env->Global()->Set(v8::String::New("o3"), o3);
+
+  // Get mirrors for the four objects.
+  CompileRun(
+      "o0_mirror = debug.MakeMirror(o0);"
+      "o1_mirror = debug.MakeMirror(o1);"
+      "o2_mirror = debug.MakeMirror(o2);"
+      "o3_mirror = debug.MakeMirror(o3)");
+  CHECK(CompileRun("o0_mirror instanceof debug.ObjectMirror")->BooleanValue());
+  CHECK(CompileRun("o1_mirror instanceof debug.ObjectMirror")->BooleanValue());
+  CHECK(CompileRun("o2_mirror instanceof debug.ObjectMirror")->BooleanValue());
+  CHECK(CompileRun("o3_mirror instanceof debug.ObjectMirror")->BooleanValue());
+
+  // Check that each object has one property.
+  CHECK_EQ(1, CompileRun(
+              "o0_mirror.propertyNames().length")->Int32Value());
+  CHECK_EQ(1, CompileRun(
+              "o1_mirror.propertyNames().length")->Int32Value());
+  CHECK_EQ(1, CompileRun(
+              "o2_mirror.propertyNames().length")->Int32Value());
+  CHECK_EQ(1, CompileRun(
+              "o3_mirror.propertyNames().length")->Int32Value());
+
+  // Set o1 as prototype for o0. o1 has the hidden prototype flag so all
+  // properties on o1 should be seen on o0.
+  o0->Set(v8::String::New("__proto__"), o1);
+  CHECK_EQ(2, CompileRun(
+              "o0_mirror.propertyNames().length")->Int32Value());
+  CHECK_EQ(0, CompileRun(
+              "o0_mirror.property('x').value().value()")->Int32Value());
+  CHECK_EQ(1, CompileRun(
+              "o0_mirror.property('y').value().value()")->Int32Value());
+
+  // Set o2 as prototype for o0 (it will end up after o1 as o1 has the hidden
+  // prototype flag. o2 also has the hidden prototype flag so all properties
+  // on o2 should be seen on o0 as well as properties on o1.
+  o0->Set(v8::String::New("__proto__"), o2);
+  CHECK_EQ(3, CompileRun(
+              "o0_mirror.propertyNames().length")->Int32Value());
+  CHECK_EQ(0, CompileRun(
+              "o0_mirror.property('x').value().value()")->Int32Value());
+  CHECK_EQ(1, CompileRun(
+              "o0_mirror.property('y').value().value()")->Int32Value());
+  CHECK_EQ(2, CompileRun(
+              "o0_mirror.property('z').value().value()")->Int32Value());
+
+  // Set o3 as prototype for o0 (it will end up after o1 and o2 as both o1 and
+  // o2 has the hidden prototype flag. o3 does not have the hidden prototype
+  // flag so properties on o3 should not be seen on o0 whereas the properties
+  // from o1 and o2 should still be seen on o0.
+  // Final prototype chain: o0 -> o1 -> o2 -> o3
+  // Hidden prototypes:           ^^    ^^
+  o0->Set(v8::String::New("__proto__"), o3);
+  CHECK_EQ(3, CompileRun(
+              "o0_mirror.propertyNames().length")->Int32Value());
+  CHECK_EQ(1, CompileRun(
+              "o3_mirror.propertyNames().length")->Int32Value());
+  CHECK_EQ(0, CompileRun(
+              "o0_mirror.property('x').value().value()")->Int32Value());
+  CHECK_EQ(1, CompileRun(
+              "o0_mirror.property('y').value().value()")->Int32Value());
+  CHECK_EQ(2, CompileRun(
+              "o0_mirror.property('z').value().value()")->Int32Value());
+  CHECK(CompileRun("o0_mirror.property('u').isUndefined()")->BooleanValue());
+
+  // The prototype (__proto__) for o0 should be o3 as o1 and o2 are hidden.
+  CHECK(CompileRun("o0_mirror.protoObject() == o3_mirror")->BooleanValue());
+}
+
+
+// Multithreaded tests of JSON debugger protocol
+
+// Support classes
+
+// Copies a C string to a 16-bit string.  Does not check for buffer overflow.
+// Does not use the V8 engine to convert strings, so it can be used
+// in any thread.  Returns the length of the string.
+int AsciiToUtf16(const char* input_buffer, uint16_t* output_buffer) {
+  int i;
+  for (i = 0; input_buffer[i] != '\0'; ++i) {
+    // ASCII does not use chars > 127, but be careful anyway.
+    output_buffer[i] = static_cast<unsigned char>(input_buffer[i]);
+  }
+  output_buffer[i] = 0;
+  return i;
+}
+
+// Copies a 16-bit string to a C string by dropping the high byte of
+// each character.  Does not check for buffer overflow.
+// Can be used in any thread.  Requires string length as an input.
+int Utf16ToAscii(const uint16_t* input_buffer, int length,
+                 char* output_buffer) {
+  for (int i = 0; i < length; ++i) {
+    output_buffer[i] = static_cast<char>(input_buffer[i]);
+  }
+  output_buffer[length] = '\0';
+  return length;
+}
+
+// Provides synchronization between k threads, where k is an input to the
+// constructor.  The Wait() call blocks a thread until it is called for the
+// k'th time, then all calls return.  Each ThreadBarrier object can only
+// be used once.
+class ThreadBarrier {
+ public:
+  explicit ThreadBarrier(int num_threads);
+  ~ThreadBarrier();
+  void Wait();
+ private:
+  int num_threads_;
+  int num_blocked_;
+  v8::internal::Mutex* lock_;
+  v8::internal::Semaphore* sem_;
+  bool invalid_;
+};
+
+ThreadBarrier::ThreadBarrier(int num_threads)
+    : num_threads_(num_threads), num_blocked_(0) {
+  lock_ = OS::CreateMutex();
+  sem_ = OS::CreateSemaphore(0);
+  invalid_ = false;  // A barrier may only be used once.  Then it is invalid.
+}
+
+// Do not call, due to race condition with Wait().
+// Could be resolved with Pthread condition variables.
+ThreadBarrier::~ThreadBarrier() {
+  lock_->Lock();
+  delete lock_;
+  delete sem_;
+}
+
+void ThreadBarrier::Wait() {
+  lock_->Lock();
+  ASSERT(!invalid_);
+  if (num_blocked_ == num_threads_ - 1) {
+    // Signal and unblock all waiting threads.
+    for (int i = 0; i < num_threads_ - 1; ++i) {
+      sem_->Signal();
+    }
+    invalid_ = true;
+    printf("BARRIER\n\n");
+    fflush(stdout);
+    lock_->Unlock();
+  } else {  // Wait for the semaphore.
+    ++num_blocked_;
+    lock_->Unlock();  // Potential race condition with destructor because
+    sem_->Wait();  // these two lines are not atomic.
+  }
+}
+
+// A set containing enough barriers and semaphores for any of the tests.
+class Barriers {
+ public:
+  Barriers();
+  void Initialize();
+  ThreadBarrier barrier_1;
+  ThreadBarrier barrier_2;
+  ThreadBarrier barrier_3;
+  ThreadBarrier barrier_4;
+  ThreadBarrier barrier_5;
+  v8::internal::Semaphore* semaphore_1;
+  v8::internal::Semaphore* semaphore_2;
+};
+
+Barriers::Barriers() : barrier_1(2), barrier_2(2),
+    barrier_3(2), barrier_4(2), barrier_5(2) {}
+
+void Barriers::Initialize() {
+  semaphore_1 = OS::CreateSemaphore(0);
+  semaphore_2 = OS::CreateSemaphore(0);
+}
+
+
+// We match parts of the message to decide if it is a break message.
+bool IsBreakEventMessage(char *message) {
+  const char* type_event = "\"type\":\"event\"";
+  const char* event_break = "\"event\":\"break\"";
+  // Does the message contain both type:event and event:break?
+  return strstr(message, type_event) != NULL &&
+         strstr(message, event_break) != NULL;
+}
+
+
+/* Test MessageQueues */
+/* Tests the message queues that hold debugger commands and
+ * response messages to the debugger.  Fills queues and makes
+ * them grow.
+ */
+Barriers message_queue_barriers;
+
+// This is the debugger thread, that executes no v8 calls except
+// placing JSON debugger commands in the queue.
+class MessageQueueDebuggerThread : public v8::internal::Thread {
+ public:
+  void Run();
+};
+
+static void MessageHandler(const uint16_t* message, int length, void *data) {
+  static char print_buffer[1000];
+  Utf16ToAscii(message, length, print_buffer);
+  if (IsBreakEventMessage(print_buffer)) {
+    // Lets test script wait until break occurs to send commands.
+    // Signals when a break is reported.
+    message_queue_barriers.semaphore_2->Signal();
+  }
+  // Allow message handler to block on a semaphore, to test queueing of
+  // messages while blocked.
+  message_queue_barriers.semaphore_1->Wait();
+  printf("%s\n", print_buffer);
+  fflush(stdout);
+}
+
+
+void MessageQueueDebuggerThread::Run() {
+  const int kBufferSize = 1000;
+  uint16_t buffer_1[kBufferSize];
+  uint16_t buffer_2[kBufferSize];
+  const char* command_1 =
+      "{\"seq\":117,"
+       "\"type\":\"request\","
+       "\"command\":\"evaluate\","
+       "\"arguments\":{\"expression\":\"1+2\"}}";
+  const char* command_2 =
+    "{\"seq\":118,"
+     "\"type\":\"request\","
+     "\"command\":\"evaluate\","
+     "\"arguments\":{\"expression\":\"1+a\"}}";
+  const char* command_3 =
+    "{\"seq\":119,"
+     "\"type\":\"request\","
+     "\"command\":\"evaluate\","
+     "\"arguments\":{\"expression\":\"c.d * b\"}}";
+  const char* command_continue =
+    "{\"seq\":106,"
+     "\"type\":\"request\","
+     "\"command\":\"continue\"}";
+  const char* command_single_step =
+    "{\"seq\":107,"
+     "\"type\":\"request\","
+     "\"command\":\"continue\","
+     "\"arguments\":{\"stepaction\":\"next\"}}";
+
+  /* Interleaved sequence of actions by the two threads:*/
+  // Main thread compiles and runs source_1
+  message_queue_barriers.barrier_1.Wait();
+  // Post 6 commands, filling the command queue and making it expand.
+  // These calls return immediately, but the commands stay on the queue
+  // until the execution of source_2.
+  // Note: AsciiToUtf16 executes before SendCommand, so command is copied
+  // to buffer before buffer is sent to SendCommand.
+  v8::Debug::SendCommand(buffer_1, AsciiToUtf16(command_1, buffer_1));
+  v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_2, buffer_2));
+  v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_3, buffer_2));
+  v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_3, buffer_2));
+  v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_3, buffer_2));
+  message_queue_barriers.barrier_2.Wait();
+  // Main thread compiles and runs source_2.
+  // Queued commands are executed at the start of compilation of source_2.
+  message_queue_barriers.barrier_3.Wait();
+  // Free the message handler to process all the messages from the queue.
+  for (int i = 0; i < 20 ; ++i) {
+    message_queue_barriers.semaphore_1->Signal();
+  }
+  // Main thread compiles and runs source_3.
+  // source_3 includes a debugger statement, which causes a break event.
+  // Wait on break event from hitting "debugger" statement
+  message_queue_barriers.semaphore_2->Wait();
+  // These should execute after the "debugger" statement in source_2
+  v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_single_step, buffer_2));
+  // Wait on break event after a single step executes.
+  message_queue_barriers.semaphore_2->Wait();
+  v8::Debug::SendCommand(buffer_1, AsciiToUtf16(command_2, buffer_1));
+  v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_continue, buffer_2));
+  // Main thread continues running source_3 to end, waits for this thread.
+}
+
+MessageQueueDebuggerThread message_queue_debugger_thread;
+
+// This thread runs the v8 engine.
+TEST(MessageQueues) {
+  // Create a V8 environment
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  message_queue_barriers.Initialize();
+  v8::Debug::SetMessageHandler(MessageHandler);
+  message_queue_debugger_thread.Start();
+
+  const char* source_1 = "a = 3; b = 4; c = new Object(); c.d = 5;";
+  const char* source_2 = "e = 17;";
+  const char* source_3 = "a = 4; debugger; a = 5; a = 6; a = 7;";
+
+  // See MessageQueueDebuggerThread::Run for interleaved sequence of
+  // API calls and events in the two threads.
+  CompileRun(source_1);
+  message_queue_barriers.barrier_1.Wait();
+  message_queue_barriers.barrier_2.Wait();
+  CompileRun(source_2);
+  message_queue_barriers.barrier_3.Wait();
+  CompileRun(source_3);
+  message_queue_debugger_thread.Join();
+  fflush(stdout);
+}
+
+/* Test ThreadedDebugging */
+/* This test interrupts a running infinite loop that is
+ * occupying the v8 thread by a break command from the
+ * debugger thread.  It then changes the value of a
+ * global object, to make the loop terminate.
+ */
+
+Barriers threaded_debugging_barriers;
+
+class V8Thread : public v8::internal::Thread {
+ public:
+  void Run();
+};
+
+class DebuggerThread : public v8::internal::Thread {
+ public:
+  void Run();
+};
+
+
+static v8::Handle<v8::Value> ThreadedAtBarrier1(const v8::Arguments& args) {
+  threaded_debugging_barriers.barrier_1.Wait();
+  return v8::Undefined();
+}
+
+
+static void ThreadedMessageHandler(const uint16_t* message, int length,
+                                   void *data) {
+  static char print_buffer[1000];
+  Utf16ToAscii(message, length, print_buffer);
+  if (IsBreakEventMessage(print_buffer)) {
+    threaded_debugging_barriers.barrier_2.Wait();
+  }
+  printf("%s\n", print_buffer);
+  fflush(stdout);
+}
+
+
+void V8Thread::Run() {
+  const char* source =
+      "flag = true;\n"
+      "function bar( new_value ) {\n"
+      "  flag = new_value;\n"
+      "  return \"Return from bar(\" + new_value + \")\";\n"
+      "}\n"
+      "\n"
+      "function foo() {\n"
+      "  var x = 1;\n"
+      "  while ( flag == true ) {\n"
+      "    if ( x == 1 ) {\n"
+      "      ThreadedAtBarrier1();\n"
+      "    }\n"
+      "    x = x + 1;\n"
+      "  }\n"
+      "}\n"
+      "\n"
+      "foo();\n";
+
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  v8::Debug::SetMessageHandler(&ThreadedMessageHandler);
+  v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
+  global_template->Set(v8::String::New("ThreadedAtBarrier1"),
+                       v8::FunctionTemplate::New(ThreadedAtBarrier1));
+  v8::Handle<v8::Context> context = v8::Context::New(NULL, global_template);
+  v8::Context::Scope context_scope(context);
+
+  CompileRun(source);
+}
+
+void DebuggerThread::Run() {
+  const int kBufSize = 1000;
+  uint16_t buffer[kBufSize];
+
+  const char* command_1 = "{\"seq\":102,"
+      "\"type\":\"request\","
+      "\"command\":\"evaluate\","
+      "\"arguments\":{\"expression\":\"bar(false)\"}}";
+  const char* command_2 = "{\"seq\":103,"
+      "\"type\":\"request\","
+      "\"command\":\"continue\"}";
+
+  threaded_debugging_barriers.barrier_1.Wait();
+  v8::Debug::DebugBreak();
+  threaded_debugging_barriers.barrier_2.Wait();
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_1, buffer));
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer));
+}
+
+DebuggerThread debugger_thread;
+V8Thread v8_thread;
+
+TEST(ThreadedDebugging) {
+  // Create a V8 environment
+  threaded_debugging_barriers.Initialize();
+
+  v8_thread.Start();
+  debugger_thread.Start();
+
+  v8_thread.Join();
+  debugger_thread.Join();
+}
+
+/* Test RecursiveBreakpoints */
+/* In this test, the debugger evaluates a function with a breakpoint, after
+ * hitting a breakpoint in another function.  We do this with both values
+ * of the flag enabling recursive breakpoints, and verify that the second
+ * breakpoint is hit when enabled, and missed when disabled.
+ */
+
+class BreakpointsV8Thread : public v8::internal::Thread {
+ public:
+  void Run();
+};
+
+class BreakpointsDebuggerThread : public v8::internal::Thread {
+ public:
+  void Run();
+};
+
+
+Barriers* breakpoints_barriers;
+
+static void BreakpointsMessageHandler(const uint16_t* message,
+                                      int length,
+                                      void *data) {
+  static char print_buffer[1000];
+  Utf16ToAscii(message, length, print_buffer);
+  printf("%s\n", print_buffer);
+  fflush(stdout);
+
+  // Is break_template a prefix of the message?
+  if (IsBreakEventMessage(print_buffer)) {
+    breakpoints_barriers->semaphore_1->Signal();
+  }
+}
+
+
+void BreakpointsV8Thread::Run() {
+  const char* source_1 = "var y_global = 3;\n"
+    "function cat( new_value ) {\n"
+    "  var x = new_value;\n"
+    "  y_global = 4;\n"
+    "  x = 3 * x + 1;\n"
+    "  y_global = 5;\n"
+    "  return x;\n"
+    "}\n"
+    "\n"
+    "function dog() {\n"
+    "  var x = 1;\n"
+    "  x = y_global;"
+    "  var z = 3;"
+    "  x += 100;\n"
+    "  return x;\n"
+    "}\n"
+    "\n";
+  const char* source_2 = "cat(17);\n"
+    "cat(19);\n";
+
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  v8::Debug::SetMessageHandler(&BreakpointsMessageHandler);
+
+  CompileRun(source_1);
+  breakpoints_barriers->barrier_1.Wait();
+  breakpoints_barriers->barrier_2.Wait();
+  CompileRun(source_2);
+}
+
+
+void BreakpointsDebuggerThread::Run() {
+  const int kBufSize = 1000;
+  uint16_t buffer[kBufSize];
+
+  const char* command_1 = "{\"seq\":101,"
+      "\"type\":\"request\","
+      "\"command\":\"setbreakpoint\","
+      "\"arguments\":{\"type\":\"function\",\"target\":\"cat\",\"line\":3}}";
+  const char* command_2 = "{\"seq\":102,"
+      "\"type\":\"request\","
+      "\"command\":\"setbreakpoint\","
+      "\"arguments\":{\"type\":\"function\",\"target\":\"dog\",\"line\":3}}";
+  const char* command_3 = "{\"seq\":104,"
+      "\"type\":\"request\","
+      "\"command\":\"evaluate\","
+      "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":false}}";
+  const char* command_4 = "{\"seq\":105,"
+      "\"type\":\"request\","
+      "\"command\":\"evaluate\","
+      "\"arguments\":{\"expression\":\"x\",\"disable_break\":true}}";
+  const char* command_5 = "{\"seq\":106,"
+      "\"type\":\"request\","
+      "\"command\":\"continue\"}";
+  const char* command_6 = "{\"seq\":107,"
+      "\"type\":\"request\","
+      "\"command\":\"continue\"}";
+  const char* command_7 = "{\"seq\":108,"
+     "\"type\":\"request\","
+     "\"command\":\"evaluate\","
+     "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":true}}";
+  const char* command_8 = "{\"seq\":109,"
+      "\"type\":\"request\","
+      "\"command\":\"continue\"}";
+
+
+  // v8 thread initializes, runs source_1
+  breakpoints_barriers->barrier_1.Wait();
+  // 1:Set breakpoint in cat().
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_1, buffer));
+  // 2:Set breakpoint in dog()
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer));
+  breakpoints_barriers->barrier_2.Wait();
+  // v8 thread starts compiling source_2.
+  // Automatic break happens, to run queued commands
+  // breakpoints_barriers->semaphore_1->Wait();
+  // Commands 1 through 3 run, thread continues.
+  // v8 thread runs source_2 to breakpoint in cat().
+  // message callback receives break event.
+  breakpoints_barriers->semaphore_1->Wait();
+  // 4:Evaluate dog() (which has a breakpoint).
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_3, buffer));
+  // v8 thread hits breakpoint in dog()
+  breakpoints_barriers->semaphore_1->Wait();  // wait for break event
+  // 5:Evaluate x
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_4, buffer));
+  // 6:Continue evaluation of dog()
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_5, buffer));
+  // dog() finishes.
+  // 7:Continue evaluation of source_2, finish cat(17), hit breakpoint
+  // in cat(19).
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_6, buffer));
+  // message callback gets break event
+  breakpoints_barriers->semaphore_1->Wait();  // wait for break event
+  // 8: Evaluate dog() with breaks disabled
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_7, buffer));
+  // 9: Continue evaluation of source2, reach end.
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_8, buffer));
+}
+
+BreakpointsDebuggerThread breakpoints_debugger_thread;
+BreakpointsV8Thread breakpoints_v8_thread;
+
+TEST(RecursiveBreakpoints) {
+  i::FLAG_debugger_auto_break = true;
+
+  // Create a V8 environment
+  Barriers stack_allocated_breakpoints_barriers;
+  stack_allocated_breakpoints_barriers.Initialize();
+  breakpoints_barriers = &stack_allocated_breakpoints_barriers;
+
+  breakpoints_v8_thread.Start();
+  breakpoints_debugger_thread.Start();
+
+  breakpoints_v8_thread.Join();
+  breakpoints_debugger_thread.Join();
+}
+
+
+static void DummyDebugEventListener(v8::DebugEvent event,
+                                    v8::Handle<v8::Object> exec_state,
+                                    v8::Handle<v8::Object> event_data,
+                                    v8::Handle<v8::Value> data) {
+}
+
+
+TEST(SetDebugEventListenerOnUninitializedVM) {
+  v8::Debug::SetDebugEventListener(DummyDebugEventListener);
+}
+
+
+static void DummyMessageHandler(const uint16_t* message,
+                                int length, void *data) {
+}
+
+
+TEST(SetMessageHandlerOnUninitializedVM) {
+  v8::Debug::SetMessageHandler(DummyMessageHandler);
+}
+
+
+TEST(DebugBreakOnUninitializedVM) {
+  v8::Debug::DebugBreak();
+}
+
+
+TEST(SendCommandToUninitializedVM) {
+  const char* dummy_command = "{}";
+  uint16_t dummy_buffer[80];
+  int dummy_length = AsciiToUtf16(dummy_command, dummy_buffer);
+  v8::Debug::SendCommand(dummy_buffer, dummy_length);
+}
+
+
+// Source for a JavaScript function which returns the data parameter of a
+// function called in the context of the debugger. If no data parameter is
+// passed it throws an exception.
+static const char* debugger_call_with_data_source =
+    "function debugger_call_with_data(exec_state, data) {"
+    "  if (data) return data;"
+    "  throw 'No data!'"
+    "}";
+v8::Handle<v8::Function> debugger_call_with_data;
+
+
+// Source for a JavaScript function which returns the data parameter of a
+// function called in the context of the debugger. If no data parameter is
+// passed it throws an exception.
+static const char* debugger_call_with_closure_source =
+    "var x = 3;"
+    "function (exec_state) {"
+    "  if (exec_state.y) return x - 1;"
+    "  exec_state.y = x;"
+    "  return exec_state.y"
+    "}";
+v8::Handle<v8::Function> debugger_call_with_closure;
+
+// Function to retrieve the number of JavaScript frames by calling a JavaScript
+// in the debugger.
+static v8::Handle<v8::Value> CheckFrameCount(const v8::Arguments& args) {
+  CHECK(v8::Debug::Call(frame_count)->IsNumber());
+  CHECK_EQ(args[0]->Int32Value(),
+           v8::Debug::Call(frame_count)->Int32Value());
+  return v8::Undefined();
+}
+
+
+// Function to retrieve the source line of the top JavaScript frame by calling a
+// JavaScript function in the debugger.
+static v8::Handle<v8::Value> CheckSourceLine(const v8::Arguments& args) {
+  CHECK(v8::Debug::Call(frame_source_line)->IsNumber());
+  CHECK_EQ(args[0]->Int32Value(),
+           v8::Debug::Call(frame_source_line)->Int32Value());
+  return v8::Undefined();
+}
+
+
+// Function to test passing an additional parameter to a JavaScript function
+// called in the debugger. It also tests that functions called in the debugger
+// can throw exceptions.
+static v8::Handle<v8::Value> CheckDataParameter(const v8::Arguments& args) {
+  v8::Handle<v8::String> data = v8::String::New("Test");
+  CHECK(v8::Debug::Call(debugger_call_with_data, data)->IsString());
+
+  CHECK(v8::Debug::Call(debugger_call_with_data).IsEmpty());
+  CHECK(v8::Debug::Call(debugger_call_with_data).IsEmpty());
+
+  v8::TryCatch catcher;
+  v8::Debug::Call(debugger_call_with_data);
+  CHECK(catcher.HasCaught());
+  CHECK(catcher.Exception()->IsString());
+
+  return v8::Undefined();
+}
+
+
+// Function to test using a JavaScript with closure in the debugger.
+static v8::Handle<v8::Value> CheckClosure(const v8::Arguments& args) {
+  CHECK(v8::Debug::Call(debugger_call_with_closure)->IsNumber());
+  CHECK_EQ(3, v8::Debug::Call(debugger_call_with_closure)->Int32Value());
+  return v8::Undefined();
+}
+
+
+// Test functions called through the debugger.
+TEST(CallFunctionInDebugger) {
+  // Create and enter a context with the functions CheckFrameCount,
+  // CheckSourceLine and CheckDataParameter installed.
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
+  global_template->Set(v8::String::New("CheckFrameCount"),
+                       v8::FunctionTemplate::New(CheckFrameCount));
+  global_template->Set(v8::String::New("CheckSourceLine"),
+                       v8::FunctionTemplate::New(CheckSourceLine));
+  global_template->Set(v8::String::New("CheckDataParameter"),
+                       v8::FunctionTemplate::New(CheckDataParameter));
+  global_template->Set(v8::String::New("CheckClosure"),
+                       v8::FunctionTemplate::New(CheckClosure));
+  v8::Handle<v8::Context> context = v8::Context::New(NULL, global_template);
+  v8::Context::Scope context_scope(context);
+
+  // Compile a function for checking the number of JavaScript frames.
+  v8::Script::Compile(v8::String::New(frame_count_source))->Run();
+  frame_count = v8::Local<v8::Function>::Cast(
+      context->Global()->Get(v8::String::New("frame_count")));
+
+  // Compile a function for returning the source line for the top frame.
+  v8::Script::Compile(v8::String::New(frame_source_line_source))->Run();
+  frame_source_line = v8::Local<v8::Function>::Cast(
+      context->Global()->Get(v8::String::New("frame_source_line")));
+
+  // Compile a function returning the data parameter.
+  v8::Script::Compile(v8::String::New(debugger_call_with_data_source))->Run();
+  debugger_call_with_data = v8::Local<v8::Function>::Cast(
+      context->Global()->Get(v8::String::New("debugger_call_with_data")));
+
+  // Compile a function capturing closure.
+  debugger_call_with_closure = v8::Local<v8::Function>::Cast(
+      v8::Script::Compile(
+          v8::String::New(debugger_call_with_closure_source))->Run());
+
+  // Calling a function through the debugger returns undefined if there are no
+  // JavaScript frames.
+  CHECK(v8::Debug::Call(frame_count)->IsUndefined());
+  CHECK(v8::Debug::Call(frame_source_line)->IsUndefined());
+  CHECK(v8::Debug::Call(debugger_call_with_data)->IsUndefined());
+
+  // Test that the number of frames can be retrieved.
+  v8::Script::Compile(v8::String::New("CheckFrameCount(1)"))->Run();
+  v8::Script::Compile(v8::String::New("function f() {"
+                                      "  CheckFrameCount(2);"
+                                      "}; f()"))->Run();
+
+  // Test that the source line can be retrieved.
+  v8::Script::Compile(v8::String::New("CheckSourceLine(0)"))->Run();
+  v8::Script::Compile(v8::String::New("function f() {\n"
+                                      "  CheckSourceLine(1)\n"
+                                      "  CheckSourceLine(2)\n"
+                                      "  CheckSourceLine(3)\n"
+                                      "}; f()"))->Run();
+
+  // Test that a parameter can be passed to a function called in the debugger.
+  v8::Script::Compile(v8::String::New("CheckDataParameter()"))->Run();
+
+  // Test that a function with closure can be run in the debugger.
+  v8::Script::Compile(v8::String::New("CheckClosure()"))->Run();
+
+
+  // Test that the source line is correct when there is a line offset.
+  v8::ScriptOrigin origin(v8::String::New("test"),
+                          v8::Integer::New(7));
+  v8::Script::Compile(v8::String::New("CheckSourceLine(7)"), &origin)->Run();
+  v8::Script::Compile(v8::String::New("function f() {\n"
+                                      "  CheckSourceLine(8)\n"
+                                      "  CheckSourceLine(9)\n"
+                                      "  CheckSourceLine(10)\n"
+                                      "}; f()"), &origin)->Run();
+}
+
+
+// Test that clearing the debug event listener actually clears all break points
+// and related information.
+TEST(DebuggerUnload) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Check debugger is unloaded before it is used.
+  CheckDebuggerUnloaded();
+
+  // Add debug event listener.
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+                                   v8::Undefined());
+  // Create a couple of functions for the test.
+  v8::Local<v8::Function> foo =
+      CompileFunction(&env, "function foo(){x=1}", "foo");
+  v8::Local<v8::Function> bar =
+      CompileFunction(&env, "function bar(){y=2}", "bar");
+
+  // Set some break points.
+  SetBreakPoint(foo, 0);
+  SetBreakPoint(foo, 4);
+  SetBreakPoint(bar, 0);
+  SetBreakPoint(bar, 4);
+
+  // Make sure that the break points are there.
+  break_point_hit_count = 0;
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+  bar->Call(env->Global(), 0, NULL);
+  CHECK_EQ(4, break_point_hit_count);
+
+  // Remove the debug event listener without clearing breakpoints.
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded(true);
+
+  // Set a new debug event listener.
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+                                   v8::Undefined());
+  // Check that the break points was actually cleared.
+  break_point_hit_count = 0;
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+
+  // Set break points and run again.
+  SetBreakPoint(foo, 0);
+  SetBreakPoint(foo, 4);
+  foo->Call(env->Global(), 0, NULL);
+  CHECK_EQ(2, break_point_hit_count);
+
+  // Remove the debug event listener without clearing breakpoints again.
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded(true);
+}
+
+
+// Debugger message handler which counts the number of times it is called.
+static int message_handler_hit_count = 0;
+static void MessageHandlerHitCount(const uint16_t* message,
+                                   int length, void* data) {
+  message_handler_hit_count++;
+
+  const int kBufferSize = 1000;
+  uint16_t buffer[kBufferSize];
+  const char* command_continue =
+    "{\"seq\":0,"
+     "\"type\":\"request\","
+     "\"command\":\"continue\"}";
+
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_continue, buffer));
+}
+
+
+// Test clearing the debug message handler.
+TEST(DebuggerClearMessageHandler) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Check debugger is unloaded before it is used.
+  CheckDebuggerUnloaded();
+
+  // Set a debug message handler.
+  v8::Debug::SetMessageHandler(MessageHandlerHitCount);
+
+  // Run code to throw a unhandled exception. This should end up in the message
+  // handler.
+  CompileRun("throw 1");
+
+  // The message handler should be called.
+  CHECK_GT(message_handler_hit_count, 0);
+
+  // Clear debug message handler.
+  message_handler_hit_count = 0;
+  v8::Debug::SetMessageHandler(NULL);
+
+  // Run code to throw a unhandled exception. This should end up in the message
+  // handler.
+  CompileRun("throw 1");
+
+  // The message handler should not be called more.
+  CHECK_EQ(0, message_handler_hit_count);
+
+  CheckDebuggerUnloaded(true);
+}
+
+
+// Debugger message handler which clears the message handler while active.
+static void MessageHandlerClearingMessageHandler(const uint16_t* message,
+                                                 int length,
+                                                 void* data) {
+  message_handler_hit_count++;
+
+  // Clear debug message handler.
+  v8::Debug::SetMessageHandler(NULL);
+}
+
+
+// Test clearing the debug message handler while processing a debug event.
+TEST(DebuggerClearMessageHandlerWhileActive) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  // Check debugger is unloaded before it is used.
+  CheckDebuggerUnloaded();
+
+  // Set a debug message handler.
+  v8::Debug::SetMessageHandler(MessageHandlerClearingMessageHandler);
+
+  // Run code to throw a unhandled exception. This should end up in the message
+  // handler.
+  CompileRun("throw 1");
+
+  // The message handler should be called.
+  CHECK_EQ(1, message_handler_hit_count);
+
+  CheckDebuggerUnloaded(true);
+}
+
+
+int host_dispatch_hit_count = 0;
+static void HostDispatchHandlerHitCount(void* dispatch, void *data) {
+  host_dispatch_hit_count++;
+}
+
+
+// Test that clearing the debug event listener actually clears all break points
+// and related information.
+TEST(DebuggerHostDispatch) {
+  i::FLAG_debugger_auto_break = true;
+
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  const int kBufferSize = 1000;
+  uint16_t buffer[kBufferSize];
+  const char* command_continue =
+    "{\"seq\":0,"
+     "\"type\":\"request\","
+     "\"command\":\"continue\"}";
+
+  // Create an empty function to call for processing debug commands
+  v8::Local<v8::Function> empty =
+      CompileFunction(&env, "function empty(){}", "empty");
+
+  // Setup message and host dispatch handlers.
+  v8::Debug::SetMessageHandler(DummyMessageHandler);
+  v8::Debug::SetHostDispatchHandler(HostDispatchHandlerHitCount,
+                                    NULL);
+
+  // Send a host dispatch by itself.
+  v8::Debug::SendHostDispatch(NULL);
+  empty->Call(env->Global(), 0, NULL);  // Run JavaScript to activate debugger.
+  CHECK_EQ(1, host_dispatch_hit_count);
+
+  // Fill a host dispatch and a continue command on the command queue.
+  v8::Debug::SendHostDispatch(NULL);
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_continue, buffer));
+  empty->Call(env->Global(), 0, NULL);  // Run JavaScript to activate debugger.
+
+  // Fill a continue command and a host dispatch on the command queue.
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_continue, buffer));
+  v8::Debug::SendHostDispatch(NULL);
+  empty->Call(env->Global(), 0, NULL);  // Run JavaScript to activate debugger.
+  empty->Call(env->Global(), 0, NULL);  // Run JavaScript to activate debugger.
+
+  // All the host dispatch callback should be called.
+  CHECK_EQ(3, host_dispatch_hit_count);
+}
+
+
+TEST(DebuggerAgent) {
+  // Make sure this port is not used by other tests to allow tests to run in
+  // parallel.
+  const int kPort = 5858;
+
+  // Make a string with the port number.
+  const int kPortBufferLen = 6;
+  char port_str[kPortBufferLen];
+  OS::SNPrintF(i::Vector<char>(port_str, kPortBufferLen), "%d", kPort);
+
+  bool ok;
+
+  // Initialize the socket library.
+  i::Socket::Setup();
+
+  // Test starting and stopping the agent without any client connection.
+  i::Debugger::StartAgent("test", kPort);
+  i::Debugger::StopAgent();
+
+  // Test starting the agent, connecting a client and shutting down the agent
+  // with the client connected.
+  ok = i::Debugger::StartAgent("test", kPort);
+  CHECK(ok);
+  i::Socket* client = i::OS::CreateSocket();
+  ok = client->Connect("localhost", port_str);
+  CHECK(ok);
+  i::Debugger::StopAgent();
+  delete client;
+
+  // Test starting and stopping the agent with the required port already
+  // occoupied.
+  i::Socket* server = i::OS::CreateSocket();
+  server->Bind(kPort);
+
+  i::Debugger::StartAgent("test", kPort);
+  i::Debugger::StopAgent();
+
+  delete server;
+}
+
+
+class DebuggerAgentProtocolServerThread : public i::Thread {
+ public:
+  explicit DebuggerAgentProtocolServerThread(int port)
+      : port_(port), server_(NULL), client_(NULL),
+        listening_(OS::CreateSemaphore(0)) {
+  }
+  ~DebuggerAgentProtocolServerThread() {
+    // Close both sockets.
+    delete client_;
+    delete server_;
+    delete listening_;
+  }
+
+  void Run();
+  void WaitForListening() { listening_->Wait(); }
+  char* body() { return *body_; }
+
+ private:
+  int port_;
+  i::SmartPointer<char> body_;
+  i::Socket* server_;  // Server socket used for bind/accept.
+  i::Socket* client_;  // Single client connection used by the test.
+  i::Semaphore* listening_;  // Signalled when the server is in listen mode.
+};
+
+
+void DebuggerAgentProtocolServerThread::Run() {
+  bool ok;
+
+  // Create the server socket and bind it to the requested port.
+  server_ = i::OS::CreateSocket();
+  CHECK(server_ != NULL);
+  ok = server_->Bind(port_);
+  CHECK(ok);
+
+  // Listen for new connections.
+  ok = server_->Listen(1);
+  CHECK(ok);
+  listening_->Signal();
+
+  // Accept a connection.
+  client_ = server_->Accept();
+  CHECK(client_ != NULL);
+
+  // Receive a debugger agent protocol message.
+  i::DebuggerAgentUtil::ReceiveMessage(client_);
+}
+
+
+TEST(DebuggerAgentProtocolOverflowHeader) {
+  // Make sure this port is not used by other tests to allow tests to run in
+  // parallel.
+  const int kPort = 5860;
+  static const char* kLocalhost = "localhost";
+
+  // Make a string with the port number.
+  const int kPortBufferLen = 6;
+  char port_str[kPortBufferLen];
+  OS::SNPrintF(i::Vector<char>(port_str, kPortBufferLen), "%d", kPort);
+
+  // Initialize the socket library.
+  i::Socket::Setup();
+
+  // Create a socket server to receive a debugger agent message.
+  DebuggerAgentProtocolServerThread* server =
+      new DebuggerAgentProtocolServerThread(kPort);
+  server->Start();
+  server->WaitForListening();
+
+  // Connect.
+  i::Socket* client = i::OS::CreateSocket();
+  CHECK(client != NULL);
+  bool ok = client->Connect(kLocalhost, port_str);
+  CHECK(ok);
+
+  // Send headers which overflow the receive buffer.
+  static const int kBufferSize = 1000;
+  char buffer[kBufferSize];
+
+  // Long key and short value: XXXX....XXXX:0\r\n.
+  for (int i = 0; i < kBufferSize - 4; i++) {
+    buffer[i] = 'X';
+  }
+  buffer[kBufferSize - 4] = ':';
+  buffer[kBufferSize - 3] = '0';
+  buffer[kBufferSize - 2] = '\r';
+  buffer[kBufferSize - 1] = '\n';
+  client->Send(buffer, kBufferSize);
+
+  // Short key and long value: X:XXXX....XXXX\r\n.
+  buffer[0] = 'X';
+  buffer[1] = ':';
+  for (int i = 2; i < kBufferSize - 2; i++) {
+    buffer[i] = 'X';
+  }
+  buffer[kBufferSize - 2] = '\r';
+  buffer[kBufferSize - 1] = '\n';
+  client->Send(buffer, kBufferSize);
+
+  // Add empty body to request.
+  const char* content_length_zero_header = "Content-Length:0\r\n";
+  client->Send(content_length_zero_header, strlen(content_length_zero_header));
+  client->Send("\r\n", 2);
+
+  // Wait until data is received.
+  server->Join();
+
+  // Check for empty body.
+  CHECK(server->body() == NULL);
+
+  // Close the client before the server to avoid TIME_WAIT issues.
+  client->Shutdown();
+  delete client;
+  delete server;
+}
+
+
+// Test for issue http://code.google.com/p/v8/issues/detail?id=289.
+// Make sure that DebugGetLoadedScripts doesn't return scripts
+// with disposed external source.
+class EmptyExternalStringResource : public v8::String::ExternalStringResource {
+ public:
+  EmptyExternalStringResource() { empty_[0] = 0; }
+  virtual ~EmptyExternalStringResource() {}
+  virtual size_t length() const { return empty_.length(); }
+  virtual const uint16_t* data() const { return empty_.start(); }
+ private:
+  ::v8::internal::EmbeddedVector<uint16_t, 1> empty_;
+};
+
+
+TEST(DebugGetLoadedScripts) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  EmptyExternalStringResource source_ext_str;
+  v8::Local<v8::String> source = v8::String::NewExternal(&source_ext_str);
+  v8::Handle<v8::Script> evil_script = v8::Script::Compile(source);
+  Handle<i::ExternalTwoByteString> i_source(
+      i::ExternalTwoByteString::cast(*v8::Utils::OpenHandle(*source)));
+  // This situation can happen if source was an external string disposed
+  // by its owner.
+  i_source->set_resource(0);
+
+  bool allow_natives_syntax = i::FLAG_allow_natives_syntax;
+  i::FLAG_allow_natives_syntax = true;
+  CompileRun(
+      "var scripts = %DebugGetLoadedScripts();"
+      "for (var i = 0; i < scripts.length; ++i) {"
+      "    scripts[i].line_ends;"
+      "}");
+  // Must not crash while accessing line_ends.
+  i::FLAG_allow_natives_syntax = allow_natives_syntax;
+}
diff --git a/deps/v8/test/cctest/test-decls.cc b/deps/v8/test/cctest/test-decls.cc
new file mode 100644
index 0000000..e798fee
--- /dev/null
+++ b/deps/v8/test/cctest/test-decls.cc
@@ -0,0 +1,594 @@
+// 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.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "heap.h"
+#include "cctest.h"
+
+using namespace v8;
+
+
+enum Expectations {
+  EXPECT_RESULT,
+  EXPECT_EXCEPTION
+};
+
+
+// A DeclarationContext holds a reference to a v8::Context and keeps
+// track of various declaration related counters to make it easier to
+// track if global declarations in the presence of interceptors behave
+// the right way.
+class DeclarationContext {
+ public:
+  DeclarationContext();
+
+  virtual ~DeclarationContext() {
+    if (is_initialized_) {
+      context_->Exit();
+      context_.Dispose();
+    }
+  }
+
+  void Check(const char* source,
+             int get, int set, int has,
+             Expectations expectations,
+             v8::Handle<Value> value = Local<Value>());
+
+  int get_count() const { return get_count_; }
+  int set_count() const { return set_count_; }
+  int has_count() const { return has_count_; }
+
+ protected:
+  virtual v8::Handle<Value> Get(Local<String> key);
+  virtual v8::Handle<Value> Set(Local<String> key, Local<Value> value);
+  virtual v8::Handle<Boolean> Has(Local<String> key);
+
+  void InitializeIfNeeded();
+
+  // Get the holder for the interceptor. Default to the instance template
+  // but may be overwritten.
+  virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
+    return function->InstanceTemplate();
+  }
+
+  // The handlers are called as static functions that forward
+  // to the instance specific virtual methods.
+  static v8::Handle<Value> HandleGet(Local<String> key,
+                                     const AccessorInfo& info);
+  static v8::Handle<Value> HandleSet(Local<String> key,
+                                     Local<Value> value,
+                                     const AccessorInfo& info);
+  static v8::Handle<Boolean> HandleHas(Local<String> key,
+                                       const AccessorInfo& info);
+
+ private:
+  bool is_initialized_;
+  Persistent<Context> context_;
+  Local<String> property_;
+
+  int get_count_;
+  int set_count_;
+  int has_count_;
+
+  static DeclarationContext* GetInstance(const AccessorInfo& info);
+};
+
+
+DeclarationContext::DeclarationContext()
+    : is_initialized_(false), get_count_(0), set_count_(0), has_count_(0) {
+  // Do nothing.
+}
+
+
+void DeclarationContext::InitializeIfNeeded() {
+  if (is_initialized_) return;
+  HandleScope scope;
+  Local<FunctionTemplate> function = FunctionTemplate::New();
+  Local<Value> data = Integer::New(reinterpret_cast<intptr_t>(this));
+  GetHolder(function)->SetNamedPropertyHandler(&HandleGet,
+                                               &HandleSet,
+                                               &HandleHas,
+                                               0, 0,
+                                               data);
+  context_ = Context::New(0, function->InstanceTemplate(), Local<Value>());
+  context_->Enter();
+  is_initialized_ = true;
+}
+
+
+void DeclarationContext::Check(const char* source,
+                               int get, int set, int has,
+                               Expectations expectations,
+                               v8::Handle<Value> value) {
+  InitializeIfNeeded();
+  // A retry after a GC may pollute the counts, so perform gc now
+  // to avoid that.
+  v8::internal::Heap::CollectGarbage(0, v8::internal::NEW_SPACE);
+  HandleScope scope;
+  TryCatch catcher;
+  catcher.SetVerbose(true);
+  Local<Value> result = Script::Compile(String::New(source))->Run();
+  CHECK_EQ(get, get_count());
+  CHECK_EQ(set, set_count());
+  CHECK_EQ(has, has_count());
+  if (expectations == EXPECT_RESULT) {
+    CHECK(!catcher.HasCaught());
+    if (!value.IsEmpty()) {
+      CHECK_EQ(value, result);
+    }
+  } else {
+    CHECK(expectations == EXPECT_EXCEPTION);
+    CHECK(catcher.HasCaught());
+    if (!value.IsEmpty()) {
+      CHECK_EQ(value, catcher.Exception());
+    }
+  }
+}
+
+
+v8::Handle<Value> DeclarationContext::HandleGet(Local<String> key,
+                                                const AccessorInfo& info) {
+  DeclarationContext* context = GetInstance(info);
+  context->get_count_++;
+  return context->Get(key);
+}
+
+
+v8::Handle<Value> DeclarationContext::HandleSet(Local<String> key,
+                                                Local<Value> value,
+                                                const AccessorInfo& info) {
+  DeclarationContext* context = GetInstance(info);
+  context->set_count_++;
+  return context->Set(key, value);
+}
+
+
+v8::Handle<Boolean> DeclarationContext::HandleHas(Local<String> key,
+                                                  const AccessorInfo& info) {
+  DeclarationContext* context = GetInstance(info);
+  context->has_count_++;
+  return context->Has(key);
+}
+
+
+DeclarationContext* DeclarationContext::GetInstance(const AccessorInfo& info) {
+  Local<Value> data = info.Data();
+  return reinterpret_cast<DeclarationContext*>(Int32::Cast(*data)->Value());
+}
+
+
+v8::Handle<Value> DeclarationContext::Get(Local<String> key) {
+  return v8::Handle<Value>();
+}
+
+
+v8::Handle<Value> DeclarationContext::Set(Local<String> key,
+                                          Local<Value> value) {
+  return v8::Handle<Value>();
+}
+
+
+v8::Handle<Boolean> DeclarationContext::Has(Local<String> key) {
+  return v8::Handle<Boolean>();
+}
+
+
+// Test global declaration of a property the interceptor doesn't know
+// about and doesn't handle.
+TEST(Unknown) {
+  HandleScope scope;
+
+  { DeclarationContext context;
+    context.Check("var x; x",
+                  1,  // access
+                  1,  // declaration
+                  2,  // declaration + initialization
+                  EXPECT_RESULT, Undefined());
+  }
+
+  { DeclarationContext context;
+    context.Check("var x = 0; x",
+                  1,  // access
+                  2,  // declaration + initialization
+                  2,  // declaration + initialization
+                  EXPECT_RESULT, Number::New(0));
+  }
+
+  { DeclarationContext context;
+    context.Check("function x() { }; x",
+                  1,  // access
+                  1,  // declaration
+                  0,
+                  EXPECT_RESULT);
+  }
+
+  { DeclarationContext context;
+    context.Check("const x; x",
+                  1,  // access
+                  2,  // declaration + initialization
+                  2,  // declaration + initialization
+                  EXPECT_RESULT, Undefined());
+  }
+
+  { DeclarationContext context;
+    context.Check("const x = 0; x",
+                  1,  // access
+                  2,  // declaration + initialization
+                  2,  // declaration + initialization
+                  EXPECT_RESULT, Undefined());  // SB 0 - BUG 1213579
+  }
+}
+
+
+
+class PresentPropertyContext: public DeclarationContext {
+ protected:
+  virtual v8::Handle<Boolean> Has(Local<String> key) {
+    return True();
+  }
+};
+
+
+
+TEST(Present) {
+  HandleScope scope;
+
+  { PresentPropertyContext context;
+    context.Check("var x; x",
+                  1,  // access
+                  0,
+                  2,  // declaration + initialization
+                  EXPECT_EXCEPTION);  // x is not defined!
+  }
+
+  { PresentPropertyContext context;
+    context.Check("var x = 0; x",
+                  1,  // access
+                  1,  // initialization
+                  2,  // declaration + initialization
+                  EXPECT_RESULT, Number::New(0));
+  }
+
+  { PresentPropertyContext context;
+    context.Check("function x() { }; x",
+                  1,  // access
+                  1,  // declaration
+                  0,
+                  EXPECT_RESULT);
+  }
+
+  { PresentPropertyContext context;
+    context.Check("const x; x",
+                  0,
+                  0,
+                  1,  // (re-)declaration
+                  EXPECT_EXCEPTION);  // x has already been declared!
+  }
+
+  { PresentPropertyContext context;
+    context.Check("const x = 0; x",
+                  0,
+                  0,
+                  1,  // (re-)declaration
+                  EXPECT_EXCEPTION);  // x has already been declared!
+  }
+}
+
+
+
+class AbsentPropertyContext: public DeclarationContext {
+ protected:
+  virtual v8::Handle<Boolean> Has(Local<String> key) {
+    return False();
+  }
+};
+
+
+TEST(Absent) {
+  HandleScope scope;
+
+  { AbsentPropertyContext context;
+    context.Check("var x; x",
+                  1,  // access
+                  2,  // declaration + initialization
+                  2,  // declaration + initialization
+                  EXPECT_RESULT, Undefined());
+  }
+
+  { AbsentPropertyContext context;
+    context.Check("var x = 0; x",
+                  1,  // access
+                  2,  // declaration + initialization
+                  2,  // declaration + initialization
+                  EXPECT_RESULT, Number::New(0));
+  }
+
+  { AbsentPropertyContext context;
+    context.Check("function x() { }; x",
+                  1,  // access
+                  1,  // declaration
+                  0,
+                  EXPECT_RESULT);
+  }
+
+  { AbsentPropertyContext context;
+    context.Check("const x; x",
+                  1,  // access
+                  2,  // declaration + initialization
+                  2,  // declaration + initializetion
+                  EXPECT_RESULT, Undefined());
+  }
+
+  { AbsentPropertyContext context;
+    context.Check("const x = 0; x",
+                  1,  // access
+                  2,  // declaration + initialization
+                  2,  // declaration + initialization
+                  EXPECT_RESULT, Undefined());  // SB 0 - BUG 1213579
+  }
+
+  { AbsentPropertyContext context;
+    context.Check("if (false) { var x = 0 }; x",
+                  1,  // access
+                  1,  // declaration
+                  1,  // declaration + initialization
+                  EXPECT_RESULT, Undefined());
+  }
+}
+
+
+
+class AppearingPropertyContext: public DeclarationContext {
+ public:
+  enum State {
+    DECLARE,
+    INITIALIZE_IF_ASSIGN,
+    UNKNOWN
+  };
+
+  AppearingPropertyContext() : state_(DECLARE) { }
+
+ protected:
+  virtual v8::Handle<Boolean> Has(Local<String> key) {
+    switch (state_) {
+      case DECLARE:
+        // Force declaration by returning that the
+        // property is absent.
+        state_ = INITIALIZE_IF_ASSIGN;
+        return False();
+      case INITIALIZE_IF_ASSIGN:
+        // Return that the property is present so we only get the
+        // setter called when initializing with a value.
+        state_ = UNKNOWN;
+        return True();
+      default:
+        ASSERT(state_ == UNKNOWN);
+        break;
+    }
+    // Do the lookup in the object.
+    return v8::Local<Boolean>();
+  }
+
+ private:
+  State state_;
+};
+
+
+TEST(Appearing) {
+  HandleScope scope;
+
+  { AppearingPropertyContext context;
+    context.Check("var x; x",
+                  1,  // access
+                  1,  // declaration
+                  2,  // declaration + initialization
+                  EXPECT_RESULT, Undefined());
+  }
+
+  { AppearingPropertyContext context;
+    context.Check("var x = 0; x",
+                  1,  // access
+                  2,  // declaration + initialization
+                  2,  // declaration + initialization
+                  EXPECT_RESULT, Number::New(0));
+  }
+
+  { AppearingPropertyContext context;
+    context.Check("function x() { }; x",
+                  1,  // access
+                  1,  // declaration
+                  0,
+                  EXPECT_RESULT);
+  }
+
+  { AppearingPropertyContext context;
+    context.Check("const x; x",
+                  0,
+                  1,  // declaration
+                  2,  // declaration + initialization
+                  EXPECT_EXCEPTION);  // x has already been declared!
+  }
+
+  { AppearingPropertyContext context;
+    context.Check("const x = 0; x",
+                  0,
+                  1,  // declaration
+                  2,  // declaration + initialization
+                  EXPECT_EXCEPTION);  //  x has already been declared!
+  }
+}
+
+
+
+class ReappearingPropertyContext: public DeclarationContext {
+ public:
+  enum State {
+    DECLARE,
+    DONT_DECLARE,
+    INITIALIZE,
+    UNKNOWN
+  };
+
+  ReappearingPropertyContext() : state_(DECLARE) { }
+
+ protected:
+  virtual v8::Handle<Boolean> Has(Local<String> key) {
+    switch (state_) {
+      case DECLARE:
+        // Force the first declaration by returning that
+        // the property is absent.
+        state_ = DONT_DECLARE;
+        return False();
+      case DONT_DECLARE:
+        // Ignore the second declaration by returning
+        // that the property is already there.
+        state_ = INITIALIZE;
+        return True();
+      case INITIALIZE:
+        // Force an initialization by returning that
+        // the property is absent. This will make sure
+        // that the setter is called and it will not
+        // lead to redeclaration conflicts (yet).
+        state_ = UNKNOWN;
+        return False();
+      default:
+        ASSERT(state_ == UNKNOWN);
+        break;
+    }
+    // Do the lookup in the object.
+    return v8::Local<Boolean>();
+  }
+
+ private:
+  State state_;
+};
+
+
+TEST(Reappearing) {
+  HandleScope scope;
+
+  { ReappearingPropertyContext context;
+    context.Check("const x; var x = 0",
+                  0,
+                  2,  // var declaration + const initialization
+                  4,  // 2 x declaration + 2 x initialization
+                  EXPECT_EXCEPTION);  // x has already been declared!
+  }
+}
+
+
+
+class ExistsInPrototypeContext: public DeclarationContext {
+ protected:
+  virtual v8::Handle<Boolean> Has(Local<String> key) {
+    // Let it seem that the property exists in the prototype object.
+    return True();
+  }
+
+  // Use the prototype as the holder for the interceptors.
+  virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
+    return function->PrototypeTemplate();
+  }
+};
+
+
+TEST(ExistsInPrototype) {
+  HandleScope scope;
+
+  // Sanity check to make sure that the holder of the interceptor
+  // really is the prototype object.
+  { ExistsInPrototypeContext context;
+    context.Check("this.x = 87; this.x",
+                  0,
+                  0,
+                  0,
+                  EXPECT_RESULT, Number::New(87));
+  }
+
+  { ExistsInPrototypeContext context;
+    context.Check("var x; x",
+                  0,
+                  0,
+                  1,  // declaration
+                  EXPECT_RESULT, Undefined());
+  }
+
+  { ExistsInPrototypeContext context;
+    context.Check("var x = 0; x",
+                  0,
+                  0,
+                  1,  // declaration
+                  EXPECT_RESULT, Number::New(0));
+  }
+
+  { ExistsInPrototypeContext context;
+    context.Check("const x; x",
+                  0,
+                  0,
+                  1,  // declaration
+                  EXPECT_RESULT, Undefined());
+  }
+
+  { ExistsInPrototypeContext context;
+    context.Check("const x = 0; x",
+                  0,
+                  0,
+                  1,  // declaration
+                  EXPECT_RESULT, Number::New(0));
+  }
+}
+
+
+
+class AbsentInPrototypeContext: public DeclarationContext {
+ protected:
+  virtual v8::Handle<Boolean> Has(Local<String> key) {
+    // Let it seem that the property is absent in the prototype object.
+    return False();
+  }
+
+  // Use the prototype as the holder for the interceptors.
+  virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
+    return function->PrototypeTemplate();
+  }
+};
+
+
+TEST(AbsentInPrototype) {
+  HandleScope scope;
+
+  { AbsentInPrototypeContext context;
+    context.Check("if (false) { var x = 0; }; x",
+                  0,
+                  0,
+                  1,  // declaration
+                  EXPECT_RESULT, Undefined());
+  }
+}
diff --git a/deps/v8/test/cctest/test-disasm-arm.cc b/deps/v8/test/cctest/test-disasm-arm.cc
new file mode 100644
index 0000000..1cca17d
--- /dev/null
+++ b/deps/v8/test/cctest/test-disasm-arm.cc
@@ -0,0 +1,281 @@
+// 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.
+//
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "debug.h"
+#include "disasm.h"
+#include "disassembler.h"
+#include "macro-assembler.h"
+#include "serialize.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+
+static v8::Persistent<v8::Context> env;
+
+static void InitializeVM() {
+  if (env.IsEmpty()) {
+    env = v8::Context::New();
+  }
+}
+
+
+bool DisassembleAndCompare(byte* pc, const char* compare_string) {
+  disasm::NameConverter converter;
+  disasm::Disassembler disasm(converter);
+  EmbeddedVector<char, 128> disasm_buffer;
+
+  disasm.InstructionDecode(disasm_buffer, pc);
+
+  if (strcmp(compare_string, disasm_buffer.start()) != 0) {
+    fprintf(stderr,
+            "expected: \n"
+            "%s\n"
+            "disassembled: \n"
+            "%s\n\n",
+            compare_string, disasm_buffer.start());
+    return false;
+  }
+  return true;
+}
+
+
+// Setup V8 to a state where we can at least run the assembler and
+// disassembler. Declare the variables and allocate the data structures used
+// in the rest of the macros.
+#define SETUP() \
+  InitializeVM(); \
+  v8::HandleScope scope; \
+  byte *buffer = reinterpret_cast<byte*>(malloc(4*1024)); \
+  Assembler assm(buffer, 4*1024); \
+  bool failure = false;
+
+
+// This macro assembles one instruction using the preallocated assembler and
+// disassembles the generated instruction, comparing the output to the expected
+// value. If the comparison fails an error message is printed, but the test
+// continues to run until the end.
+#define COMPARE(asm_, compare_string) \
+  { \
+    int pc_offset = assm.pc_offset(); \
+    byte *pc = &buffer[pc_offset]; \
+    assm.asm_; \
+    if (!DisassembleAndCompare(pc, compare_string)) failure = true; \
+  }
+
+
+// Verify that all invocations of the COMPARE macro passed successfully.
+// Exit with a failure if at least one of the tests failed.
+#define VERIFY_RUN() \
+if (failure) { \
+    V8_Fatal(__FILE__, __LINE__, "ARM Disassembler tests failed.\n"); \
+  }
+
+
+TEST(Type0) {
+  SETUP();
+
+  COMPARE(and_(r0, r1, Operand(r2)),
+          "e0010002       and r0, r1, r2");
+  COMPARE(and_(r1, r2, Operand(r3), LeaveCC),
+          "e0021003       and r1, r2, r3");
+  COMPARE(and_(r2, r3, Operand(r4), SetCC),
+          "e0132004       ands r2, r3, r4");
+  COMPARE(and_(r3, r4, Operand(r5), LeaveCC, eq),
+          "00043005       andeq r3, r4, r5");
+
+  COMPARE(eor(r4, r5, Operand(r6, LSL, 0)),
+          "e0254006       eor r4, r5, r6");
+  COMPARE(eor(r4, r5, Operand(r7, LSL, 1), SetCC),
+          "e0354087       eors r4, r5, r7, lsl #1");
+  COMPARE(eor(r4, r5, Operand(r8, LSL, 2), LeaveCC, ne),
+          "10254108       eorne r4, r5, r8, lsl #2");
+  COMPARE(eor(r4, r5, Operand(r9, LSL, 3), SetCC, cs),
+          "20354189       eorcss r4, r5, r9, lsl #3");
+
+  COMPARE(sub(r5, r6, Operand(r10, LSL, 31), LeaveCC, hs),
+          "20465f8a       subcs r5, r6, sl, lsl #31");
+  COMPARE(sub(r5, r6, Operand(r10, LSL, 30), SetCC, cc),
+          "30565f0a       subccs r5, r6, sl, lsl #30");
+  COMPARE(sub(r5, r6, Operand(r10, LSL, 24), LeaveCC, lo),
+          "30465c0a       subcc r5, r6, sl, lsl #24");
+  COMPARE(sub(r5, r6, Operand(r10, LSL, 16), SetCC, mi),
+          "4056580a       submis r5, r6, sl, lsl #16");
+
+  COMPARE(rsb(r6, r7, Operand(fp)),
+          "e067600b       rsb r6, r7, fp");
+  COMPARE(rsb(r6, r7, Operand(fp, LSR, 1)),
+          "e06760ab       rsb r6, r7, fp, lsr #1");
+  COMPARE(rsb(r6, r7, Operand(fp, LSR, 0), SetCC),
+          "e077602b       rsbs r6, r7, fp, lsr #32");
+  COMPARE(rsb(r6, r7, Operand(fp, LSR, 31), LeaveCC, pl),
+          "50676fab       rsbpl r6, r7, fp, lsr #31");
+
+  COMPARE(add(r7, r8, Operand(ip, ASR, 1)),
+          "e08870cc       add r7, r8, ip, asr #1");
+  COMPARE(add(r7, r8, Operand(ip, ASR, 0)),
+          "e088704c       add r7, r8, ip, asr #32");
+  COMPARE(add(r7, r8, Operand(ip), SetCC),
+          "e098700c       adds r7, r8, ip");
+  COMPARE(add(r7, r8, Operand(ip, ASR, 31), SetCC, vs),
+          "60987fcc       addvss r7, r8, ip, asr #31");
+
+  COMPARE(adc(r7, fp, Operand(ip, ASR, 5)),
+          "e0ab72cc       adc r7, fp, ip, asr #5");
+  COMPARE(adc(r4, ip, Operand(ip, ASR, 1), LeaveCC, vc),
+          "70ac40cc       adcvc r4, ip, ip, asr #1");
+  COMPARE(adc(r5, sp, Operand(ip), SetCC),
+          "e0bd500c       adcs r5, sp, ip");
+  COMPARE(adc(r8, lr, Operand(ip, ASR, 31), SetCC, vc),
+          "70be8fcc       adcvcs r8, lr, ip, asr #31");
+
+  COMPARE(sbc(r7, r1, Operand(ip, ROR, 1), LeaveCC, hi),
+          "80c170ec       sbchi r7, r1, ip, ror #1");
+  COMPARE(sbc(r7, r9, Operand(ip, ROR, 4)),
+          "e0c9726c       sbc r7, r9, ip, ror #4");
+  COMPARE(sbc(r7, r10, Operand(ip), SetCC),
+          "e0da700c       sbcs r7, sl, ip");
+  COMPARE(sbc(r7, ip, Operand(ip, ROR, 31), SetCC, hi),
+          "80dc7fec       sbchis r7, ip, ip, ror #31");
+
+  COMPARE(rsc(r7, r8, Operand(ip, LSL, r0)),
+          "e0e8701c       rsc r7, r8, ip, lsl r0");
+  COMPARE(rsc(r7, r8, Operand(ip, LSL, r1)),
+          "e0e8711c       rsc r7, r8, ip, lsl r1");
+  COMPARE(rsc(r7, r8, Operand(ip), SetCC),
+          "e0f8700c       rscs r7, r8, ip");
+  COMPARE(rsc(r7, r8, Operand(ip, LSL, r3), SetCC, ls),
+          "90f8731c       rsclss r7, r8, ip, lsl r3");
+
+  COMPARE(tst(r7, Operand(r5, ASR, ip), ge),
+          "a1170c55       tstge r7, r5, asr ip");
+  COMPARE(tst(r7, Operand(r6, ASR, sp)),
+          "e1170d56       tst r7, r6, asr sp");
+  COMPARE(tst(r7, Operand(r7), ge),
+          "a1170007       tstge r7, r7");
+  COMPARE(tst(r7, Operand(r8, ASR, fp), ge),
+          "a1170b58       tstge r7, r8, asr fp");
+
+  COMPARE(teq(r7, Operand(r5, ROR, r0), lt),
+          "b1370075       teqlt r7, r5, ror r0");
+  COMPARE(teq(r7, Operand(r6, ROR, lr)),
+          "e1370e76       teq r7, r6, ror lr");
+  COMPARE(teq(r7, Operand(r7), lt),
+          "b1370007       teqlt r7, r7");
+  COMPARE(teq(r7, Operand(r8, ROR, r1)),
+          "e1370178       teq r7, r8, ror r1");
+
+  COMPARE(cmp(r7, Operand(r4)),
+          "e1570004       cmp r7, r4");
+  COMPARE(cmp(r7, Operand(r6, LSL, 1), gt),
+          "c1570086       cmpgt r7, r6, lsl #1");
+  COMPARE(cmp(r7, Operand(r8, LSR, 3), gt),
+          "c15701a8       cmpgt r7, r8, lsr #3");
+  COMPARE(cmp(r7, Operand(r8, ASR, 19)),
+          "e15709c8       cmp r7, r8, asr #19");
+
+  COMPARE(cmn(r0, Operand(r4)),
+          "e1700004       cmn r0, r4");
+  COMPARE(cmn(r1, Operand(r6, ROR, 1)),
+          "e17100e6       cmn r1, r6, ror #1");
+  COMPARE(cmn(r2, Operand(r8)),
+          "e1720008       cmn r2, r8");
+  COMPARE(cmn(r3, Operand(fp), le),
+          "d173000b       cmnle r3, fp");
+
+  COMPARE(orr(r7, r8, Operand(lr), LeaveCC, al),
+          "e188700e       orr r7, r8, lr");
+  COMPARE(orr(r7, r8, Operand(fp)),
+          "e188700b       orr r7, r8, fp");
+  COMPARE(orr(r7, r8, Operand(sp), SetCC),
+          "e198700d       orrs r7, r8, sp");
+  COMPARE(orr(r7, r8, Operand(ip), SetCC, al),
+          "e198700c       orrs r7, r8, ip");
+
+  COMPARE(mov(r0, Operand(r1), LeaveCC, eq),
+          "01a00001       moveq r0, r1");
+  COMPARE(mov(r0, Operand(r2)),
+          "e1a00002       mov r0, r2");
+  COMPARE(mov(r0, Operand(r3), SetCC),
+          "e1b00003       movs r0, r3");
+  COMPARE(mov(r0, Operand(r4), SetCC, pl),
+          "51b00004       movpls r0, r4");
+
+  COMPARE(bic(r0, lr, Operand(r1), LeaveCC, vs),
+          "61ce0001       bicvs r0, lr, r1");
+  COMPARE(bic(r0, r9, Operand(r2), LeaveCC, vc),
+          "71c90002       bicvc r0, r9, r2");
+  COMPARE(bic(r0, r5, Operand(r3), SetCC),
+          "e1d50003       bics r0, r5, r3");
+  COMPARE(bic(r0, r1, Operand(r4), SetCC, pl),
+          "51d10004       bicpls r0, r1, r4");
+
+  COMPARE(mvn(r10, Operand(r1)),
+          "e1e0a001       mvn sl, r1");
+  COMPARE(mvn(r9, Operand(r2)),
+          "e1e09002       mvn r9, r2");
+  COMPARE(mvn(r0, Operand(r3), SetCC),
+          "e1f00003       mvns r0, r3");
+  COMPARE(mvn(r5, Operand(r4), SetCC, cc),
+          "31f05004       mvnccs r5, r4");
+
+  VERIFY_RUN();
+}
+
+
+TEST(Type1) {
+  SETUP();
+
+  COMPARE(and_(r0, r1, Operand(0x00000000)),
+          "e2010000       and r0, r1, #0");
+  COMPARE(and_(r1, r2, Operand(0x00000001), LeaveCC),
+          "e2021001       and r1, r2, #1");
+  COMPARE(and_(r2, r3, Operand(0x00000010), SetCC),
+          "e2132010       ands r2, r3, #16");
+  COMPARE(and_(r3, r4, Operand(0x00000100), LeaveCC, eq),
+          "02043c01       andeq r3, r4, #256");
+  COMPARE(and_(r4, r5, Operand(0x00001000), SetCC, ne),
+          "12154a01       andnes r4, r5, #4096");
+
+  COMPARE(eor(r4, r5, Operand(0x00001000)),
+          "e2254a01       eor r4, r5, #4096");
+  COMPARE(eor(r4, r4, Operand(0x00010000), LeaveCC),
+          "e2244801       eor r4, r4, #65536");
+  COMPARE(eor(r4, r3, Operand(0x00100000), SetCC),
+          "e2334601       eors r4, r3, #1048576");
+  COMPARE(eor(r4, r2, Operand(0x01000000), LeaveCC, cs),
+          "22224401       eorcs r4, r2, #16777216");
+  COMPARE(eor(r4, r1, Operand(0x10000000), SetCC, cc),
+          "32314201       eorccs r4, r1, #268435456");
+
+  VERIFY_RUN();
+}
diff --git a/deps/v8/test/cctest/test-disasm-ia32.cc b/deps/v8/test/cctest/test-disasm-ia32.cc
new file mode 100644
index 0000000..af9fb97
--- /dev/null
+++ b/deps/v8/test/cctest/test-disasm-ia32.cc
@@ -0,0 +1,384 @@
+// 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.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "debug.h"
+#include "disasm.h"
+#include "disassembler.h"
+#include "macro-assembler.h"
+#include "serialize.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+static v8::Persistent<v8::Context> env;
+
+static void InitializeVM() {
+  if (env.IsEmpty()) {
+    env = v8::Context::New();
+  }
+}
+
+
+#define __ assm.
+
+
+static void DummyStaticFunction(Object* result) {
+}
+
+
+TEST(DisasmIa320) {
+  InitializeVM();
+  v8::HandleScope scope;
+  v8::internal::byte buffer[1024];
+  Assembler assm(buffer, sizeof buffer);
+  DummyStaticFunction(NULL);  // just bloody use it (DELETE; debugging)
+
+  // Short immediate instructions
+  __ adc(eax, 12345678);
+  __ add(Operand(eax), Immediate(12345678));
+  __ or_(eax, 12345678);
+  __ sub(Operand(eax), Immediate(12345678));
+  __ xor_(eax, 12345678);
+  __ and_(eax, 12345678);
+  Handle<FixedArray> foo = Factory::NewFixedArray(10, TENURED);
+  __ cmp(eax, foo);
+
+  // ---- This one caused crash
+  __ mov(ebx,  Operand(esp, ecx, times_2, 0));  // [esp+ecx*4]
+
+  // ---- All instructions that I can think of
+  __ add(edx, Operand(ebx));
+  __ add(edx, Operand(12, RelocInfo::NONE));
+  __ add(edx, Operand(ebx, 0));
+  __ add(edx, Operand(ebx, 16));
+  __ add(edx, Operand(ebx, 1999));
+  __ add(edx, Operand(esp, 0));
+  __ add(edx, Operand(esp, 16));
+  __ add(edx, Operand(esp, 1999));
+  __ nop();
+  __ add(edi, Operand(ebp, ecx, times_4, 0));
+  __ add(edi, Operand(ebp, ecx, times_4, 12));
+  __ add(Operand(ebp, ecx, times_4, 12), Immediate(12));
+
+  __ nop();
+  __ add(Operand(ebx), Immediate(12));
+  __ nop();
+  __ adc(ecx, 12);
+  __ adc(ecx, 1000);
+  __ nop();
+  __ and_(edx, 3);
+  __ and_(edx, Operand(esp, 4));
+  __ cmp(edx, 3);
+  __ cmp(edx, Operand(esp, 4));
+  __ cmp(Operand(ebp, ecx, times_4, 0), Immediate(1000));
+  Handle<FixedArray> foo2 = Factory::NewFixedArray(10, TENURED);
+  __ cmp(ebx, foo2);
+  __ or_(edx, 3);
+  __ xor_(edx, 3);
+  __ nop();
+  {
+    CHECK(CpuFeatures::IsSupported(CpuFeatures::CPUID));
+    CpuFeatures::Scope fscope(CpuFeatures::CPUID);
+    __ cpuid();
+  }
+  {
+    CHECK(CpuFeatures::IsSupported(CpuFeatures::RDTSC));
+    CpuFeatures::Scope fscope(CpuFeatures::RDTSC);
+    __ rdtsc();
+  }
+  __ movsx_b(edx, Operand(ecx));
+  __ movsx_w(edx, Operand(ecx));
+  __ movzx_b(edx, Operand(ecx));
+  __ movzx_w(edx, Operand(ecx));
+
+  __ nop();
+  __ imul(edx, Operand(ecx));
+  __ shld(edx, Operand(ecx));
+  __ shrd(edx, Operand(ecx));
+  __ bts(Operand(edx), ecx);
+  __ bts(Operand(ebx, ecx, times_4, 0), ecx);
+  __ nop();
+  __ pushad();
+  __ popad();
+  __ pushfd();
+  __ popfd();
+  __ push(Immediate(12));
+  __ push(Immediate(23456));
+  __ push(ecx);
+  __ push(esi);
+  __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
+  __ push(Operand(ebx, ecx, times_4, 0));
+  __ push(Operand(ebx, ecx, times_4, 0));
+  __ push(Operand(ebx, ecx, times_4, 10000));
+  __ pop(edx);
+  __ pop(eax);
+  __ pop(Operand(ebx, ecx, times_4, 0));
+  __ nop();
+
+  __ add(edx, Operand(esp, 16));
+  __ add(edx, Operand(ecx));
+  __ mov_b(edx, Operand(ecx));
+  __ mov_b(Operand(ecx), 6);
+  __ mov_b(Operand(ebx, ecx, times_4, 10000), 6);
+  __ mov_b(Operand(esp, 16), edx);
+  __ mov_w(edx, Operand(esp, 16));
+  __ mov_w(Operand(esp, 16), edx);
+  __ nop();
+  __ movsx_w(edx, Operand(esp, 12));
+  __ movsx_b(edx, Operand(esp, 12));
+  __ movzx_w(edx, Operand(esp, 12));
+  __ movzx_b(edx, Operand(esp, 12));
+  __ nop();
+  __ mov(edx, 1234567);
+  __ mov(edx, Operand(esp, 12));
+  __ mov(Operand(ebx, ecx, times_4, 10000), Immediate(12345));
+  __ mov(Operand(ebx, ecx, times_4, 10000), edx);
+  __ nop();
+  __ dec_b(edx);
+  __ dec(edx);
+  __ cdq();
+
+  __ nop();
+  __ idiv(edx);
+  __ mul(edx);
+  __ neg(edx);
+  __ not_(edx);
+  __ test(Operand(ebx, ecx, times_4, 10000), Immediate(123456));
+
+  __ imul(edx, Operand(ebx, ecx, times_4, 10000));
+  __ imul(edx, ecx, 12);
+  __ imul(edx, ecx, 1000);
+
+  __ inc(edx);
+  __ inc(Operand(ebx, ecx, times_4, 10000));
+  __ push(Operand(ebx, ecx, times_4, 10000));
+  __ pop(Operand(ebx, ecx, times_4, 10000));
+  __ call(Operand(ebx, ecx, times_4, 10000));
+  __ jmp(Operand(ebx, ecx, times_4, 10000));
+
+  __ lea(edx, Operand(ebx, ecx, times_4, 10000));
+  __ or_(edx, 12345);
+  __ or_(edx, Operand(ebx, ecx, times_4, 10000));
+
+  __ nop();
+
+  __ rcl(edx, 1);
+  __ rcl(edx, 7);
+  __ sar(edx, 1);
+  __ sar(edx, 6);
+  __ sar(edx);
+  __ sbb(edx, Operand(ebx, ecx, times_4, 10000));
+  __ shld(edx, Operand(ebx, ecx, times_4, 10000));
+  __ shl(edx, 1);
+  __ shl(edx, 6);
+  __ shl(edx);
+  __ shrd(edx, Operand(ebx, ecx, times_4, 10000));
+  __ shr(edx, 7);
+  __ shr(edx);
+
+
+  // Immediates
+
+  __ adc(edx, 12345);
+
+  __ add(Operand(ebx), Immediate(12));
+  __ add(Operand(edx, ecx, times_4, 10000), Immediate(12));
+
+  __ and_(ebx, 12345);
+
+  __ cmp(ebx, 12345);
+  __ cmp(Operand(ebx), Immediate(12));
+  __ cmp(Operand(edx, ecx, times_4, 10000), Immediate(12));
+
+  __ or_(ebx, 12345);
+
+  __ sub(Operand(ebx), Immediate(12));
+  __ sub(Operand(edx, ecx, times_4, 10000), Immediate(12));
+
+  __ xor_(ebx, 12345);
+
+  __ imul(edx, ecx, 12);
+  __ imul(edx, ecx, 1000);
+
+
+
+  __ sub(edx, Operand(ebx, ecx, times_4, 10000));
+  __ sub(edx, Operand(ebx));
+
+  __ test(edx, Immediate(12345));
+  __ test(edx, Operand(ebx, ecx, times_8, 10000));
+  __ nop();
+
+  __ xor_(edx, 12345);
+  __ xor_(edx, Operand(ebx, ecx, times_8, 10000));
+  __ bts(Operand(ebx, ecx, times_8, 10000), edx);
+  __ hlt();
+  __ int3();
+  __ ret(0);
+  __ ret(8);
+
+  // Calls
+
+  Label L1, L2;
+  __ bind(&L1);
+  __ nop();
+  __ call(&L1);
+  __ call(&L2);
+  __ nop();
+  __ bind(&L2);
+  __ call(Operand(ebx, ecx, times_4, 10000));
+  __ nop();
+  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+  __ call(ic, RelocInfo::CODE_TARGET);
+  __ nop();
+  __ call(FUNCTION_ADDR(DummyStaticFunction), RelocInfo::RUNTIME_ENTRY);
+  __ nop();
+
+  __ jmp(&L1);
+  __ jmp(Operand(ebx, ecx, times_4, 10000));
+  ExternalReference after_break_target =
+      ExternalReference(Debug_Address::AfterBreakTarget());
+  __ jmp(Operand::StaticVariable(after_break_target));
+  __ jmp(ic, RelocInfo::CODE_TARGET);
+  __ nop();
+
+
+  Label Ljcc;
+  __ nop();
+  // long jumps
+  __ j(overflow, &Ljcc);
+  __ j(no_overflow, &Ljcc);
+  __ j(below, &Ljcc);
+  __ j(above_equal, &Ljcc);
+  __ j(equal, &Ljcc);
+  __ j(not_equal, &Ljcc);
+  __ j(below_equal, &Ljcc);
+  __ j(above, &Ljcc);
+  __ j(sign, &Ljcc);
+  __ j(not_sign, &Ljcc);
+  __ j(parity_even, &Ljcc);
+  __ j(parity_odd, &Ljcc);
+  __ j(less, &Ljcc);
+  __ j(greater_equal, &Ljcc);
+  __ j(less_equal, &Ljcc);
+  __ j(greater, &Ljcc);
+  __ nop();
+  __ bind(&Ljcc);
+  // short jumps
+  __ j(overflow, &Ljcc);
+  __ j(no_overflow, &Ljcc);
+  __ j(below, &Ljcc);
+  __ j(above_equal, &Ljcc);
+  __ j(equal, &Ljcc);
+  __ j(not_equal, &Ljcc);
+  __ j(below_equal, &Ljcc);
+  __ j(above, &Ljcc);
+  __ j(sign, &Ljcc);
+  __ j(not_sign, &Ljcc);
+  __ j(parity_even, &Ljcc);
+  __ j(parity_odd, &Ljcc);
+  __ j(less, &Ljcc);
+  __ j(greater_equal, &Ljcc);
+  __ j(less_equal, &Ljcc);
+  __ j(greater, &Ljcc);
+
+  // checking hints
+  __ j(zero, &Ljcc, taken);
+  __ j(zero, &Ljcc, not_taken);
+
+  // __ mov(Operand::StaticVariable(Top::handler_address()), eax);
+  // 0xD9 instructions
+  __ nop();
+
+  __ fld1();
+  __ fldz();
+  __ fabs();
+  __ fchs();
+  __ fprem();
+  __ fprem1();
+  __ fincstp();
+  __ ftst();
+  __ fxch(3);
+  __ fld_s(Operand(ebx, ecx, times_4, 10000));
+  __ fstp_s(Operand(ebx, ecx, times_4, 10000));
+  __ ffree(3);
+  __ fld_d(Operand(ebx, ecx, times_4, 10000));
+  __ fstp_d(Operand(ebx, ecx, times_4, 10000));
+  __ nop();
+
+  __ fild_s(Operand(ebx, ecx, times_4, 10000));
+  __ fistp_s(Operand(ebx, ecx, times_4, 10000));
+  __ fild_d(Operand(ebx, ecx, times_4, 10000));
+  __ fistp_d(Operand(ebx, ecx, times_4, 10000));
+  __ fnstsw_ax();
+  __ nop();
+  __ fadd(3);
+  __ fsub(3);
+  __ fmul(3);
+  __ fdiv(3);
+
+  __ faddp(3);
+  __ fsubp(3);
+  __ fmulp(3);
+  __ fdivp(3);
+  __ fcompp();
+  __ fwait();
+  __ nop();
+  {
+    CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2));
+    CpuFeatures::Scope fscope(CpuFeatures::SSE2);
+    __ cvttss2si(edx, Operand(ebx, ecx, times_4, 10000));
+    __ cvtsi2sd(xmm1, Operand(ebx, ecx, times_4, 10000));
+    __ addsd(xmm1, xmm0);
+    __ mulsd(xmm1, xmm0);
+    __ subsd(xmm1, xmm0);
+    __ divsd(xmm1, xmm0);
+    __ movdbl(xmm1, Operand(ebx, ecx, times_4, 10000));
+    __ movdbl(Operand(ebx, ecx, times_4, 10000), xmm1);
+  }
+  __ ret(0);
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code = Heap::CreateCode(desc,
+                                  NULL,
+                                  Code::ComputeFlags(Code::STUB),
+                                  Handle<Object>(Heap::undefined_value()));
+  CHECK(code->IsCode());
+#ifdef DEBUG
+  Code::cast(code)->Print();
+  byte* begin = Code::cast(code)->instruction_start();
+  byte* end = begin + Code::cast(code)->instruction_size();
+  disasm::Disassembler::Disassemble(stdout, begin, end);
+#endif
+}
+
+#undef __
diff --git a/deps/v8/test/cctest/test-flags.cc b/deps/v8/test/cctest/test-flags.cc
new file mode 100644
index 0000000..9019a89
--- /dev/null
+++ b/deps/v8/test/cctest/test-flags.cc
@@ -0,0 +1,234 @@
+// 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.
+
+#include <stdlib.h>
+
+#include "v8.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+// This test must be executed first!
+TEST(Default) {
+  CHECK(FLAG_testing_bool_flag);
+  CHECK_EQ(13, FLAG_testing_int_flag);
+  CHECK_EQ(2.5, FLAG_testing_float_flag);
+  CHECK_EQ(0, strcmp(FLAG_testing_string_flag, "Hello, world!"));
+}
+
+
+static void SetFlagsToDefault() {
+  FlagList::ResetAllFlags();
+  TestDefault();
+}
+
+
+TEST(Flags1) {
+  FlagList::PrintHelp();
+}
+
+
+TEST(Flags2) {
+  SetFlagsToDefault();
+  int argc = 7;
+  const char* argv[] = { "Test2", "-notesting-bool-flag", "notaflag",
+                         "--testing_int_flag=77", "-testing_float_flag=.25",
+                         "--testing_string_flag", "no way!" };
+  CHECK_EQ(0, FlagList::SetFlagsFromCommandLine(&argc,
+                                                const_cast<char **>(argv),
+                                                false));
+  CHECK_EQ(7, argc);
+  CHECK(!FLAG_testing_bool_flag);
+  CHECK_EQ(77, FLAG_testing_int_flag);
+  CHECK_EQ(.25, FLAG_testing_float_flag);
+  CHECK_EQ(0, strcmp(FLAG_testing_string_flag, "no way!"));
+}
+
+
+TEST(Flags2b) {
+  SetFlagsToDefault();
+  const char* str =
+      " -notesting-bool-flag notaflag   --testing_int_flag=77 "
+      "-testing_float_flag=.25  "
+      "--testing_string_flag   no_way!  ";
+  CHECK_EQ(0, FlagList::SetFlagsFromString(str, strlen(str)));
+  CHECK(!FLAG_testing_bool_flag);
+  CHECK_EQ(77, FLAG_testing_int_flag);
+  CHECK_EQ(.25, FLAG_testing_float_flag);
+  CHECK_EQ(0, strcmp(FLAG_testing_string_flag, "no_way!"));
+}
+
+
+TEST(Flags3) {
+  SetFlagsToDefault();
+  int argc = 8;
+  const char* argv[] =
+      { "Test3", "--testing_bool_flag", "notaflag",
+        "--testing_int_flag", "-666",
+        "--testing_float_flag", "-12E10", "-testing-string-flag=foo-bar" };
+  CHECK_EQ(0, FlagList::SetFlagsFromCommandLine(&argc,
+                                                const_cast<char **>(argv),
+                                                true));
+  CHECK_EQ(2, argc);
+  CHECK(FLAG_testing_bool_flag);
+  CHECK_EQ(-666, FLAG_testing_int_flag);
+  CHECK_EQ(-12E10, FLAG_testing_float_flag);
+  CHECK_EQ(0, strcmp(FLAG_testing_string_flag, "foo-bar"));
+}
+
+
+TEST(Flags3b) {
+  SetFlagsToDefault();
+  const char* str =
+      "--testing_bool_flag notaflag --testing_int_flag -666 "
+      "--testing_float_flag -12E10 "
+      "-testing-string-flag=foo-bar";
+  CHECK_EQ(0, FlagList::SetFlagsFromString(str, strlen(str)));
+  CHECK(FLAG_testing_bool_flag);
+  CHECK_EQ(-666, FLAG_testing_int_flag);
+  CHECK_EQ(-12E10, FLAG_testing_float_flag);
+  CHECK_EQ(0, strcmp(FLAG_testing_string_flag, "foo-bar"));
+}
+
+
+TEST(Flags4) {
+  SetFlagsToDefault();
+  int argc = 3;
+  const char* argv[] = { "Test4", "--testing_bool_flag", "--foo" };
+  CHECK_EQ(0, FlagList::SetFlagsFromCommandLine(&argc,
+                                                const_cast<char **>(argv),
+                                                true));
+  CHECK_EQ(2, argc);
+}
+
+
+TEST(Flags4b) {
+  SetFlagsToDefault();
+  const char* str = "--testing_bool_flag --foo";
+  CHECK_EQ(2, FlagList::SetFlagsFromString(str, strlen(str)));
+}
+
+
+TEST(Flags5) {
+  SetFlagsToDefault();
+  int argc = 2;
+  const char* argv[] = { "Test5", "--testing_int_flag=\"foobar\"" };
+  CHECK_EQ(1, FlagList::SetFlagsFromCommandLine(&argc,
+                                                const_cast<char **>(argv),
+                                                true));
+  CHECK_EQ(2, argc);
+}
+
+
+TEST(Flags5b) {
+  SetFlagsToDefault();
+  const char* str = "                     --testing_int_flag=\"foobar\"";
+  CHECK_EQ(1, FlagList::SetFlagsFromString(str, strlen(str)));
+}
+
+
+TEST(Flags6) {
+  SetFlagsToDefault();
+  int argc = 4;
+  const char* argv[] = { "Test5", "--testing-int-flag", "0",
+                         "--testing_float_flag" };
+  CHECK_EQ(3, FlagList::SetFlagsFromCommandLine(&argc,
+                                                const_cast<char **>(argv),
+                                                true));
+  CHECK_EQ(4, argc);
+}
+
+
+TEST(Flags6b) {
+  SetFlagsToDefault();
+  const char* str = "       --testing-int-flag 0      --testing_float_flag    ";
+  CHECK_EQ(3, FlagList::SetFlagsFromString(str, strlen(str)));
+}
+
+
+TEST(FlagsJSArguments1) {
+  SetFlagsToDefault();
+  int argc = 6;
+  const char* argv[] = {"TestJSArgs1",
+                        "--testing-int-flag", "42",
+                        "--", "testing-float-flag", "7"};
+  CHECK_EQ(0, FlagList::SetFlagsFromCommandLine(&argc,
+                                                const_cast<char **>(argv),
+                                                true));
+  CHECK_EQ(42, FLAG_testing_int_flag);
+  CHECK_EQ(2.5, FLAG_testing_float_flag);
+  CHECK_EQ(2, FLAG_js_arguments.argc());
+  CHECK_EQ(0, strcmp(FLAG_js_arguments[0], "testing-float-flag"));
+  CHECK_EQ(0, strcmp(FLAG_js_arguments[1], "7"));
+  CHECK_EQ(1, argc);
+}
+
+
+TEST(FlagsJSArguments1b) {
+  SetFlagsToDefault();
+  const char* str = "--testing-int-flag 42 -- testing-float-flag 7";
+  CHECK_EQ(0, FlagList::SetFlagsFromString(str, strlen(str)));
+  CHECK_EQ(42, FLAG_testing_int_flag);
+  CHECK_EQ(2.5, FLAG_testing_float_flag);
+  CHECK_EQ(2, FLAG_js_arguments.argc());
+  CHECK_EQ(0, strcmp(FLAG_js_arguments[0], "testing-float-flag"));
+  CHECK_EQ(0, strcmp(FLAG_js_arguments[1], "7"));
+}
+
+
+TEST(FlagsJSArguments2) {
+  SetFlagsToDefault();
+  const char* str = "--testing-int-flag 42 --js-arguments testing-float-flag 7";
+  CHECK_EQ(0, FlagList::SetFlagsFromString(str, strlen(str)));
+  CHECK_EQ(42, FLAG_testing_int_flag);
+  CHECK_EQ(2.5, FLAG_testing_float_flag);
+  CHECK_EQ(2, FLAG_js_arguments.argc());
+  CHECK_EQ(0, strcmp(FLAG_js_arguments[0], "testing-float-flag"));
+  CHECK_EQ(0, strcmp(FLAG_js_arguments[1], "7"));
+}
+
+
+TEST(FlagsJSArguments3) {
+  SetFlagsToDefault();
+  const char* str = "--testing-int-flag 42 --js-arguments=testing-float-flag 7";
+  CHECK_EQ(0, FlagList::SetFlagsFromString(str, strlen(str)));
+  CHECK_EQ(42, FLAG_testing_int_flag);
+  CHECK_EQ(2.5, FLAG_testing_float_flag);
+  CHECK_EQ(2, FLAG_js_arguments.argc());
+  CHECK_EQ(0, strcmp(FLAG_js_arguments[0], "testing-float-flag"));
+  CHECK_EQ(0, strcmp(FLAG_js_arguments[1], "7"));
+}
+
+
+TEST(FlagsJSArguments4) {
+  SetFlagsToDefault();
+  const char* str = "--testing-int-flag 42 --";
+  CHECK_EQ(0, FlagList::SetFlagsFromString(str, strlen(str)));
+  CHECK_EQ(42, FLAG_testing_int_flag);
+  CHECK_EQ(0, FLAG_js_arguments.argc());
+}
+
diff --git a/deps/v8/test/cctest/test-func-name-inference.cc b/deps/v8/test/cctest/test-func-name-inference.cc
new file mode 100644
index 0000000..5058629
--- /dev/null
+++ b/deps/v8/test/cctest/test-func-name-inference.cc
@@ -0,0 +1,223 @@
+// Copyright 2007-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.
+
+#include "v8.h"
+
+#include "api.h"
+#include "runtime.h"
+#include "cctest.h"
+
+
+using ::v8::internal::Handle;
+using ::v8::internal::JSFunction;
+using ::v8::internal::Object;
+using ::v8::internal::Script;
+using ::v8::internal::SharedFunctionInfo;
+using ::v8::internal::String;
+
+namespace i = ::v8::internal;
+
+
+static v8::Persistent<v8::Context> env;
+
+
+static void InitializeVM() {
+  if (env.IsEmpty()) {
+    v8::HandleScope scope;
+    env = v8::Context::New();
+  }
+  v8::HandleScope scope;
+  env->Enter();
+}
+
+
+static void CheckFunctionName(v8::Handle<v8::Script> script,
+                              const char* func_pos_src,
+                              const char* ref_inferred_name) {
+  // Get script source.
+  Handle<JSFunction> fun = v8::Utils::OpenHandle(*script);
+  Handle<Script> i_script(Script::cast(fun->shared()->script()));
+  CHECK(i_script->source()->IsString());
+  Handle<String> script_src(String::cast(i_script->source()));
+
+  // Find the position of a given func source substring in the source.
+  Handle<String> func_pos_str =
+      i::Factory::NewStringFromAscii(i::CStrVector(func_pos_src));
+  int func_pos = i::Runtime::StringMatch(script_src, func_pos_str, 0);
+  CHECK_NE(0, func_pos);
+
+  // Obtain SharedFunctionInfo for the function.
+  Object* shared_func_info_ptr =
+      i::Runtime::FindSharedFunctionInfoInScript(i_script, func_pos);
+  CHECK(shared_func_info_ptr != i::Heap::undefined_value());
+  Handle<SharedFunctionInfo> shared_func_info(
+      SharedFunctionInfo::cast(shared_func_info_ptr));
+
+  // Verify inferred function name.
+  i::SmartPointer<char> inferred_name =
+      shared_func_info->inferred_name()->ToCString();
+  CHECK_EQ(ref_inferred_name, *inferred_name);
+}
+
+
+static v8::Handle<v8::Script> Compile(const char* src) {
+  return v8::Script::Compile(v8::String::New(src));
+}
+
+
+TEST(GlobalProperty) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  v8::Handle<v8::Script> script = Compile(
+      "fun1 = function() { return 1; }\n"
+      "fun2 = function() { return 2; }\n");
+  CheckFunctionName(script, "return 1", "fun1");
+  CheckFunctionName(script, "return 2", "fun2");
+}
+
+
+TEST(GlobalVar) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  v8::Handle<v8::Script> script = Compile(
+      "var fun1 = function() { return 1; }\n"
+      "var fun2 = function() { return 2; }\n");
+  CheckFunctionName(script, "return 1", "fun1");
+  CheckFunctionName(script, "return 2", "fun2");
+}
+
+
+TEST(LocalVar) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  v8::Handle<v8::Script> script = Compile(
+      "function outer() {\n"
+      "  var fun1 = function() { return 1; }\n"
+      "  var fun2 = function() { return 2; }\n"
+      "}");
+  CheckFunctionName(script, "return 1", "fun1");
+  CheckFunctionName(script, "return 2", "fun2");
+}
+
+
+TEST(InConstructor) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  v8::Handle<v8::Script> script = Compile(
+      "function MyClass() {\n"
+      "  this.method1 = function() { return 1; }\n"
+      "  this.method2 = function() { return 2; }\n"
+      "}");
+  CheckFunctionName(script, "return 1", "MyClass.method1");
+  CheckFunctionName(script, "return 2", "MyClass.method2");
+}
+
+
+TEST(Factory) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  v8::Handle<v8::Script> script = Compile(
+      "function createMyObj() {\n"
+      "  var obj = {};\n"
+      "  obj.method1 = function() { return 1; }\n"
+      "  obj.method2 = function() { return 2; }\n"
+      "  return obj;\n"
+      "}");
+  CheckFunctionName(script, "return 1", "obj.method1");
+  CheckFunctionName(script, "return 2", "obj.method2");
+}
+
+
+TEST(Static) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  v8::Handle<v8::Script> script = Compile(
+      "function MyClass() {}\n"
+      "MyClass.static1 = function() { return 1; }\n"
+      "MyClass.static2 = function() { return 2; }\n"
+      "MyClass.MyInnerClass = {}\n"
+      "MyClass.MyInnerClass.static3 = function() { return 3; }\n"
+      "MyClass.MyInnerClass.static4 = function() { return 4; }");
+  CheckFunctionName(script, "return 1", "MyClass.static1");
+  CheckFunctionName(script, "return 2", "MyClass.static2");
+  CheckFunctionName(script, "return 3", "MyClass.MyInnerClass.static3");
+  CheckFunctionName(script, "return 4", "MyClass.MyInnerClass.static4");
+}
+
+
+TEST(Prototype) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  v8::Handle<v8::Script> script = Compile(
+      "function MyClass() {}\n"
+      "MyClass.prototype.method1 = function() { return 1; }\n"
+      "MyClass.prototype.method2 = function() { return 2; }\n"
+      "MyClass.MyInnerClass = function() {}\n"
+      "MyClass.MyInnerClass.prototype.method3 = function() { return 3; }\n"
+      "MyClass.MyInnerClass.prototype.method4 = function() { return 4; }");
+  CheckFunctionName(script, "return 1", "MyClass.method1");
+  CheckFunctionName(script, "return 2", "MyClass.method2");
+  CheckFunctionName(script, "return 3", "MyClass.MyInnerClass.method3");
+  CheckFunctionName(script, "return 4", "MyClass.MyInnerClass.method4");
+}
+
+
+TEST(ObjectLiteral) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  v8::Handle<v8::Script> script = Compile(
+      "function MyClass() {}\n"
+      "MyClass.prototype = {\n"
+      "  method1: function() { return 1; },\n"
+      "  method2: function() { return 2; } }");
+  CheckFunctionName(script, "return 1", "MyClass.method1");
+  CheckFunctionName(script, "return 2", "MyClass.method2");
+}
+
+
+TEST(AsParameter) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  v8::Handle<v8::Script> script = Compile(
+      "function f1(a) { return a(); }\n"
+      "function f2(a, b) { return a() + b(); }\n"
+      "var result1 = f1(function() { return 1; })\n"
+      "var result2 = f2(function() { return 2; }, function() { return 3; })");
+  // Can't infer names here.
+  CheckFunctionName(script, "return 1", "");
+  CheckFunctionName(script, "return 2", "");
+  CheckFunctionName(script, "return 3", "");
+}
diff --git a/deps/v8/test/cctest/test-hashmap.cc b/deps/v8/test/cctest/test-hashmap.cc
new file mode 100644
index 0000000..4918d5d
--- /dev/null
+++ b/deps/v8/test/cctest/test-hashmap.cc
@@ -0,0 +1,123 @@
+// Copyright 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.
+
+#include <stdlib.h>
+
+#include "v8.h"
+#include "hashmap.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+static bool DefaultMatchFun(void* a, void* b) {
+  return a == b;
+}
+
+
+class IntSet {
+ public:
+  IntSet() : map_(DefaultMatchFun)  {}
+
+  void Insert(int x) {
+    ASSERT(x != 0);  // 0 corresponds to (void*)NULL - illegal key value
+    HashMap::Entry* p = map_.Lookup(reinterpret_cast<void*>(x), Hash(x), true);
+    CHECK(p != NULL);  // insert is set!
+    CHECK_EQ(reinterpret_cast<void*>(x), p->key);
+    // we don't care about p->value
+  }
+
+  bool Present(int x) {
+    HashMap::Entry* p = map_.Lookup(reinterpret_cast<void*>(x), Hash(x), false);
+    if (p != NULL) {
+      CHECK_EQ(reinterpret_cast<void*>(x), p->key);
+    }
+    return p != NULL;
+  }
+
+  void Clear() {
+    map_.Clear();
+  }
+
+  uint32_t occupancy() const {
+    uint32_t count = 0;
+    for (HashMap::Entry* p = map_.Start(); p != NULL; p = map_.Next(p)) {
+      count++;
+    }
+    CHECK_EQ(map_.occupancy(), static_cast<double>(count));
+    return count;
+  }
+
+ private:
+  HashMap map_;
+  static uint32_t Hash(uint32_t key)  { return key * 23; }
+};
+
+
+TEST(Set) {
+  IntSet set;
+  CHECK_EQ(0, set.occupancy());
+
+  set.Insert(1);
+  set.Insert(2);
+  set.Insert(3);
+  CHECK_EQ(3, set.occupancy());
+
+  set.Insert(2);
+  set.Insert(3);
+  CHECK_EQ(3, set.occupancy());
+
+  CHECK(set.Present(1));
+  CHECK(set.Present(2));
+  CHECK(set.Present(3));
+  CHECK(!set.Present(4));
+  CHECK_EQ(3, set.occupancy());
+
+  set.Clear();
+  CHECK_EQ(0, set.occupancy());
+
+  // Insert a long series of values.
+  const int start = 453;
+  const int factor = 13;
+  const int offset = 7;
+  const uint32_t n = 1000;
+
+  int x = start;
+  for (uint32_t i = 0; i < n; i++) {
+    CHECK_EQ(i, static_cast<double>(set.occupancy()));
+    set.Insert(x);
+    x = x*factor + offset;
+  }
+
+  // Verify the same sequence of values.
+  x = start;
+  for (uint32_t i = 0; i < n; i++) {
+    CHECK(set.Present(x));
+    x = x*factor + offset;
+  }
+
+  CHECK_EQ(n, static_cast<double>(set.occupancy()));
+}
diff --git a/deps/v8/test/cctest/test-heap.cc b/deps/v8/test/cctest/test-heap.cc
new file mode 100644
index 0000000..e35ac5f
--- /dev/null
+++ b/deps/v8/test/cctest/test-heap.cc
@@ -0,0 +1,785 @@
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "execution.h"
+#include "factory.h"
+#include "macro-assembler.h"
+#include "global-handles.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+static v8::Persistent<v8::Context> env;
+
+static void InitializeVM() {
+  if (env.IsEmpty()) env = v8::Context::New();
+  v8::HandleScope scope;
+  env->Enter();
+}
+
+
+static void CheckMap(Map* map, int type, int instance_size) {
+  CHECK(map->IsHeapObject());
+#ifdef DEBUG
+  CHECK(Heap::Contains(map));
+#endif
+  CHECK_EQ(Heap::meta_map(), map->map());
+  CHECK_EQ(type, map->instance_type());
+  CHECK_EQ(instance_size, map->instance_size());
+}
+
+
+TEST(HeapMaps) {
+  InitializeVM();
+  CheckMap(Heap::meta_map(), MAP_TYPE, Map::kSize);
+  CheckMap(Heap::heap_number_map(), HEAP_NUMBER_TYPE, HeapNumber::kSize);
+  CheckMap(Heap::fixed_array_map(), FIXED_ARRAY_TYPE, Array::kHeaderSize);
+  CheckMap(Heap::long_string_map(), LONG_STRING_TYPE,
+           SeqTwoByteString::kHeaderSize);
+}
+
+
+static void CheckOddball(Object* obj, const char* string) {
+  CHECK(obj->IsOddball());
+  bool exc;
+  Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
+  CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
+}
+
+
+static void CheckSmi(int value, const char* string) {
+  bool exc;
+  Object* print_string =
+      *Execution::ToString(Handle<Object>(Smi::FromInt(value)), &exc);
+  CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
+}
+
+
+static void CheckNumber(double value, const char* string) {
+  Object* obj = Heap::NumberFromDouble(value);
+  CHECK(obj->IsNumber());
+  bool exc;
+  Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
+  CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
+}
+
+
+static void CheckFindCodeObject() {
+  // Test FindCodeObject
+#define __ assm.
+
+  Assembler assm(NULL, 0);
+
+  __ nop();  // supported on all architectures
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code = Heap::CreateCode(desc,
+                                  NULL,
+                                  Code::ComputeFlags(Code::STUB),
+                                  Handle<Object>(Heap::undefined_value()));
+  CHECK(code->IsCode());
+
+  HeapObject* obj = HeapObject::cast(code);
+  Address obj_addr = obj->address();
+
+  for (int i = 0; i < obj->Size(); i += kPointerSize) {
+    Object* found = Heap::FindCodeObject(obj_addr + i);
+    CHECK_EQ(code, found);
+  }
+
+  Object* copy = Heap::CreateCode(desc,
+                                  NULL,
+                                  Code::ComputeFlags(Code::STUB),
+                                  Handle<Object>(Heap::undefined_value()));
+  CHECK(copy->IsCode());
+  HeapObject* obj_copy = HeapObject::cast(copy);
+  Object* not_right = Heap::FindCodeObject(obj_copy->address() +
+                                           obj_copy->Size() / 2);
+  CHECK(not_right != code);
+}
+
+
+TEST(HeapObjects) {
+  InitializeVM();
+
+  v8::HandleScope sc;
+  Object* value = Heap::NumberFromDouble(1.000123);
+  CHECK(value->IsHeapNumber());
+  CHECK(value->IsNumber());
+  CHECK_EQ(1.000123, value->Number());
+
+  value = Heap::NumberFromDouble(1.0);
+  CHECK(value->IsSmi());
+  CHECK(value->IsNumber());
+  CHECK_EQ(1.0, value->Number());
+
+  value = Heap::NumberFromInt32(1024);
+  CHECK(value->IsSmi());
+  CHECK(value->IsNumber());
+  CHECK_EQ(1024.0, value->Number());
+
+  value = Heap::NumberFromInt32(Smi::kMinValue);
+  CHECK(value->IsSmi());
+  CHECK(value->IsNumber());
+  CHECK_EQ(Smi::kMinValue, Smi::cast(value)->value());
+
+  value = Heap::NumberFromInt32(Smi::kMaxValue);
+  CHECK(value->IsSmi());
+  CHECK(value->IsNumber());
+  CHECK_EQ(Smi::kMaxValue, Smi::cast(value)->value());
+
+  value = Heap::NumberFromInt32(Smi::kMinValue - 1);
+  CHECK(value->IsHeapNumber());
+  CHECK(value->IsNumber());
+  CHECK_EQ(static_cast<double>(Smi::kMinValue - 1), value->Number());
+
+  value = Heap::NumberFromInt32(Smi::kMaxValue + 1);
+  CHECK(value->IsHeapNumber());
+  CHECK(value->IsNumber());
+  CHECK_EQ(static_cast<double>(Smi::kMaxValue + 1), value->Number());
+
+  // nan oddball checks
+  CHECK(Heap::nan_value()->IsNumber());
+  CHECK(isnan(Heap::nan_value()->Number()));
+
+  Object* str = Heap::AllocateStringFromAscii(CStrVector("fisk hest "));
+  if (!str->IsFailure()) {
+    String* s =  String::cast(str);
+    CHECK(s->IsString());
+    CHECK_EQ(10, s->length());
+  } else {
+    CHECK(false);
+  }
+
+  String* object_symbol = String::cast(Heap::Object_symbol());
+  CHECK(Top::context()->global()->HasLocalProperty(object_symbol));
+
+  // Check ToString for oddballs
+  CheckOddball(Heap::true_value(), "true");
+  CheckOddball(Heap::false_value(), "false");
+  CheckOddball(Heap::null_value(), "null");
+  CheckOddball(Heap::undefined_value(), "undefined");
+
+  // Check ToString for Smis
+  CheckSmi(0, "0");
+  CheckSmi(42, "42");
+  CheckSmi(-42, "-42");
+
+  // Check ToString for Numbers
+  CheckNumber(1.1, "1.1");
+
+  CheckFindCodeObject();
+}
+
+
+TEST(Tagging) {
+  InitializeVM();
+  CHECK(Smi::FromInt(42)->IsSmi());
+  CHECK(Failure::RetryAfterGC(12, NEW_SPACE)->IsFailure());
+  CHECK_EQ(12, Failure::RetryAfterGC(12, NEW_SPACE)->requested());
+  CHECK_EQ(NEW_SPACE, Failure::RetryAfterGC(12, NEW_SPACE)->allocation_space());
+  CHECK_EQ(OLD_POINTER_SPACE,
+           Failure::RetryAfterGC(12, OLD_POINTER_SPACE)->allocation_space());
+  CHECK(Failure::Exception()->IsFailure());
+  CHECK(Smi::FromInt(Smi::kMinValue)->IsSmi());
+  CHECK(Smi::FromInt(Smi::kMaxValue)->IsSmi());
+}
+
+
+TEST(GarbageCollection) {
+  InitializeVM();
+
+  v8::HandleScope sc;
+  // check GC when heap is empty
+  int free_bytes = Heap::MaxHeapObjectSize();
+  CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE));
+
+  // allocate a function and keep it in global object's property
+  String* func_name  = String::cast(Heap::LookupAsciiSymbol("theFunction"));
+  SharedFunctionInfo* function_share =
+    SharedFunctionInfo::cast(Heap::AllocateSharedFunctionInfo(func_name));
+  JSFunction* function =
+      JSFunction::cast(Heap::AllocateFunction(*Top::function_map(),
+                                              function_share,
+                                              Heap::undefined_value()));
+  Map* initial_map =
+      Map::cast(Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize));
+  function->set_initial_map(initial_map);
+  Top::context()->global()->SetProperty(func_name, function, NONE);
+
+  // allocate an object, but it is unrooted
+  String* prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
+  String* prop_namex = String::cast(Heap::LookupAsciiSymbol("theSlotx"));
+  JSObject* obj = JSObject::cast(Heap::AllocateJSObject(function));
+  obj->SetProperty(prop_name, Smi::FromInt(23), NONE);
+  obj->SetProperty(prop_namex, Smi::FromInt(24), NONE);
+
+  CHECK_EQ(Smi::FromInt(23), obj->GetProperty(prop_name));
+  CHECK_EQ(Smi::FromInt(24), obj->GetProperty(prop_namex));
+
+  CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE));
+
+  // function should be alive, func_name might be invalid after GC
+  func_name  = String::cast(Heap::LookupAsciiSymbol("theFunction"));
+  CHECK(Top::context()->global()->HasLocalProperty(func_name));
+  // check function is retained
+  Object* func_value = Top::context()->global()->GetProperty(func_name);
+  CHECK(func_value->IsJSFunction());
+  // old function pointer may not be valid
+  function = JSFunction::cast(func_value);
+
+  // allocate another object, make it reachable from global
+  obj = JSObject::cast(Heap::AllocateJSObject(function));
+  String* obj_name = String::cast(Heap::LookupAsciiSymbol("theObject"));
+  Top::context()->global()->SetProperty(obj_name, obj, NONE);
+  // set property
+  prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
+  obj->SetProperty(prop_name, Smi::FromInt(23), NONE);
+
+  // after gc, it should survive
+  CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE));
+
+  obj_name = String::cast(Heap::LookupAsciiSymbol("theObject"));
+  CHECK(Top::context()->global()->HasLocalProperty(obj_name));
+  CHECK(Top::context()->global()->GetProperty(obj_name)->IsJSObject());
+  obj = JSObject::cast(Top::context()->global()->GetProperty(obj_name));
+  prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
+  CHECK_EQ(Smi::FromInt(23), obj->GetProperty(prop_name));
+}
+
+
+static void VerifyStringAllocation(const char* string) {
+  String* s = String::cast(Heap::AllocateStringFromUtf8(CStrVector(string)));
+  CHECK_EQ(static_cast<int>(strlen(string)), s->length());
+  for (int index = 0; index < s->length(); index++) {
+    CHECK_EQ(static_cast<uint16_t>(string[index]), s->Get(index));  }
+}
+
+
+TEST(String) {
+  InitializeVM();
+
+  VerifyStringAllocation("a");
+  VerifyStringAllocation("ab");
+  VerifyStringAllocation("abc");
+  VerifyStringAllocation("abcd");
+  VerifyStringAllocation("fiskerdrengen er paa havet");
+}
+
+
+TEST(LocalHandles) {
+  InitializeVM();
+
+  v8::HandleScope scope;
+  const char* name = "Kasper the spunky";
+  Handle<String> string = Factory::NewStringFromAscii(CStrVector(name));
+  CHECK_EQ(static_cast<int>(strlen(name)), string->length());
+}
+
+
+TEST(GlobalHandles) {
+  InitializeVM();
+
+  Object* i = Heap::AllocateStringFromAscii(CStrVector("fisk"));
+  Object* u = Heap::AllocateHeapNumber(1.12344);
+
+  Handle<Object> h1 = GlobalHandles::Create(i);
+  Handle<Object> h2 = GlobalHandles::Create(u);
+  Handle<Object> h3 = GlobalHandles::Create(i);
+  Handle<Object> h4 = GlobalHandles::Create(u);
+
+  // after gc, it should survive
+  CHECK(Heap::CollectGarbage(0, NEW_SPACE));
+
+  CHECK((*h1)->IsString());
+  CHECK((*h2)->IsHeapNumber());
+  CHECK((*h3)->IsString());
+  CHECK((*h4)->IsHeapNumber());
+
+  CHECK_EQ(*h3, *h1);
+  GlobalHandles::Destroy(h1.location());
+  GlobalHandles::Destroy(h3.location());
+
+  CHECK_EQ(*h4, *h2);
+  GlobalHandles::Destroy(h2.location());
+  GlobalHandles::Destroy(h4.location());
+}
+
+
+static bool WeakPointerCleared = false;
+
+static void TestWeakGlobalHandleCallback(v8::Persistent<v8::Value> handle,
+                                         void* id) {
+  USE(handle);
+  if (1234 == reinterpret_cast<int>(id)) WeakPointerCleared = true;
+}
+
+
+TEST(WeakGlobalHandlesScavenge) {
+  InitializeVM();
+
+  WeakPointerCleared = false;
+
+  Object* i = Heap::AllocateStringFromAscii(CStrVector("fisk"));
+  Object* u = Heap::AllocateHeapNumber(1.12344);
+
+  Handle<Object> h1 = GlobalHandles::Create(i);
+  Handle<Object> h2 = GlobalHandles::Create(u);
+
+  GlobalHandles::MakeWeak(h2.location(),
+                          reinterpret_cast<void*>(1234),
+                          &TestWeakGlobalHandleCallback);
+
+  // Scavenge treats weak pointers as normal roots.
+  Heap::PerformScavenge();
+
+  CHECK((*h1)->IsString());
+  CHECK((*h2)->IsHeapNumber());
+
+  CHECK(!WeakPointerCleared);
+  CHECK(!GlobalHandles::IsNearDeath(h2.location()));
+  CHECK(!GlobalHandles::IsNearDeath(h1.location()));
+
+  GlobalHandles::Destroy(h1.location());
+  GlobalHandles::Destroy(h2.location());
+}
+
+
+TEST(WeakGlobalHandlesMark) {
+  InitializeVM();
+
+  WeakPointerCleared = false;
+
+  Object* i = Heap::AllocateStringFromAscii(CStrVector("fisk"));
+  Object* u = Heap::AllocateHeapNumber(1.12344);
+
+  Handle<Object> h1 = GlobalHandles::Create(i);
+  Handle<Object> h2 = GlobalHandles::Create(u);
+
+  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
+  CHECK(Heap::CollectGarbage(0, NEW_SPACE));
+  // Make sure the object is promoted.
+
+  GlobalHandles::MakeWeak(h2.location(),
+                          reinterpret_cast<void*>(1234),
+                          &TestWeakGlobalHandleCallback);
+  CHECK(!GlobalHandles::IsNearDeath(h1.location()));
+  CHECK(!GlobalHandles::IsNearDeath(h2.location()));
+
+  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
+
+  CHECK((*h1)->IsString());
+
+  CHECK(WeakPointerCleared);
+  CHECK(!GlobalHandles::IsNearDeath(h1.location()));
+  CHECK(GlobalHandles::IsNearDeath(h2.location()));
+
+  GlobalHandles::Destroy(h1.location());
+  GlobalHandles::Destroy(h2.location());
+}
+
+static void TestDeleteWeakGlobalHandleCallback(
+    v8::Persistent<v8::Value> handle,
+    void* id) {
+  if (1234 == reinterpret_cast<int>(id)) WeakPointerCleared = true;
+  handle.Dispose();
+}
+
+TEST(DeleteWeakGlobalHandle) {
+  InitializeVM();
+
+  WeakPointerCleared = false;
+
+  Object* i = Heap::AllocateStringFromAscii(CStrVector("fisk"));
+  Handle<Object> h = GlobalHandles::Create(i);
+
+  GlobalHandles::MakeWeak(h.location(),
+                          reinterpret_cast<void*>(1234),
+                          &TestDeleteWeakGlobalHandleCallback);
+
+  // Scanvenge does not recognize weak reference.
+  Heap::PerformScavenge();
+
+  CHECK(!WeakPointerCleared);
+
+  // Mark-compact treats weak reference properly.
+  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
+
+  CHECK(WeakPointerCleared);
+}
+
+static const char* not_so_random_string_table[] = {
+  "abstract",
+  "boolean",
+  "break",
+  "byte",
+  "case",
+  "catch",
+  "char",
+  "class",
+  "const",
+  "continue",
+  "debugger",
+  "default",
+  "delete",
+  "do",
+  "double",
+  "else",
+  "enum",
+  "export",
+  "extends",
+  "false",
+  "final",
+  "finally",
+  "float",
+  "for",
+  "function",
+  "goto",
+  "if",
+  "implements",
+  "import",
+  "in",
+  "instanceof",
+  "int",
+  "interface",
+  "long",
+  "native",
+  "new",
+  "null",
+  "package",
+  "private",
+  "protected",
+  "public",
+  "return",
+  "short",
+  "static",
+  "super",
+  "switch",
+  "synchronized",
+  "this",
+  "throw",
+  "throws",
+  "transient",
+  "true",
+  "try",
+  "typeof",
+  "var",
+  "void",
+  "volatile",
+  "while",
+  "with",
+  0
+};
+
+
+static void CheckSymbols(const char** strings) {
+  for (const char* string = *strings; *strings != 0; string = *strings++) {
+    Object* a = Heap::LookupAsciiSymbol(string);
+    CHECK(a->IsSymbol());
+    Object* b = Heap::LookupAsciiSymbol(string);
+    CHECK_EQ(b, a);
+    CHECK(String::cast(b)->IsEqualTo(CStrVector(string)));
+  }
+}
+
+
+TEST(SymbolTable) {
+  InitializeVM();
+
+  CheckSymbols(not_so_random_string_table);
+  CheckSymbols(not_so_random_string_table);
+}
+
+
+TEST(FunctionAllocation) {
+  InitializeVM();
+
+  v8::HandleScope sc;
+  String* name  = String::cast(Heap::LookupAsciiSymbol("theFunction"));
+  SharedFunctionInfo* function_share =
+    SharedFunctionInfo::cast(Heap::AllocateSharedFunctionInfo(name));
+  JSFunction* function =
+    JSFunction::cast(Heap::AllocateFunction(*Top::function_map(),
+                                            function_share,
+                                            Heap::undefined_value()));
+  Map* initial_map =
+      Map::cast(Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize));
+  function->set_initial_map(initial_map);
+
+  String* prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
+  JSObject* obj = JSObject::cast(Heap::AllocateJSObject(function));
+  obj->SetProperty(prop_name, Smi::FromInt(23), NONE);
+  CHECK_EQ(Smi::FromInt(23), obj->GetProperty(prop_name));
+  // Check that we can add properties to function objects.
+  function->SetProperty(prop_name, Smi::FromInt(24), NONE);
+  CHECK_EQ(Smi::FromInt(24), function->GetProperty(prop_name));
+}
+
+
+TEST(ObjectProperties) {
+  InitializeVM();
+
+  v8::HandleScope sc;
+  JSFunction* constructor =
+      JSFunction::cast(
+          Top::context()->global()->GetProperty(String::cast(
+                                                    Heap::Object_symbol())));
+  JSObject* obj = JSObject::cast(Heap::AllocateJSObject(constructor));
+  String* first = String::cast(Heap::LookupAsciiSymbol("first"));
+  String* second = String::cast(Heap::LookupAsciiSymbol("second"));
+
+  // check for empty
+  CHECK(!obj->HasLocalProperty(first));
+
+  // add first
+  obj->SetProperty(first, Smi::FromInt(1), NONE);
+  CHECK(obj->HasLocalProperty(first));
+
+  // delete first
+  CHECK(obj->DeleteProperty(first));
+  CHECK(!obj->HasLocalProperty(first));
+
+  // add first and then second
+  obj->SetProperty(first, Smi::FromInt(1), NONE);
+  obj->SetProperty(second, Smi::FromInt(2), NONE);
+  CHECK(obj->HasLocalProperty(first));
+  CHECK(obj->HasLocalProperty(second));
+
+  // delete first and then second
+  CHECK(obj->DeleteProperty(first));
+  CHECK(obj->HasLocalProperty(second));
+  CHECK(obj->DeleteProperty(second));
+  CHECK(!obj->HasLocalProperty(first));
+  CHECK(!obj->HasLocalProperty(second));
+
+  // add first and then second
+  obj->SetProperty(first, Smi::FromInt(1), NONE);
+  obj->SetProperty(second, Smi::FromInt(2), NONE);
+  CHECK(obj->HasLocalProperty(first));
+  CHECK(obj->HasLocalProperty(second));
+
+  // delete second and then first
+  CHECK(obj->DeleteProperty(second));
+  CHECK(obj->HasLocalProperty(first));
+  CHECK(obj->DeleteProperty(first));
+  CHECK(!obj->HasLocalProperty(first));
+  CHECK(!obj->HasLocalProperty(second));
+
+  // check string and symbol match
+  static const char* string1 = "fisk";
+  String* s1 =
+      String::cast(Heap::AllocateStringFromAscii(CStrVector(string1)));
+  obj->SetProperty(s1, Smi::FromInt(1), NONE);
+  CHECK(obj->HasLocalProperty(String::cast(Heap::LookupAsciiSymbol(string1))));
+
+  // check symbol and string match
+  static const char* string2 = "fugl";
+  String* s2 = String::cast(Heap::LookupAsciiSymbol(string2));
+  obj->SetProperty(s2, Smi::FromInt(1), NONE);
+  CHECK(obj->HasLocalProperty(
+            String::cast(Heap::AllocateStringFromAscii(CStrVector(string2)))));
+}
+
+
+TEST(JSObjectMaps) {
+  InitializeVM();
+
+  v8::HandleScope sc;
+  String* name  = String::cast(Heap::LookupAsciiSymbol("theFunction"));
+  SharedFunctionInfo* function_share =
+    SharedFunctionInfo::cast(Heap::AllocateSharedFunctionInfo(name));
+  JSFunction* function =
+    JSFunction::cast(Heap::AllocateFunction(*Top::function_map(),
+                                            function_share,
+                                            Heap::undefined_value()));
+  Map* initial_map =
+      Map::cast(Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize));
+  function->set_initial_map(initial_map);
+  String* prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
+  JSObject* obj = JSObject::cast(Heap::AllocateJSObject(function));
+
+  // Set a propery
+  obj->SetProperty(prop_name, Smi::FromInt(23), NONE);
+  CHECK_EQ(Smi::FromInt(23), obj->GetProperty(prop_name));
+
+  // Check the map has changed
+  CHECK(initial_map != obj->map());
+}
+
+
+TEST(JSArray) {
+  InitializeVM();
+
+  v8::HandleScope sc;
+  String* name = String::cast(Heap::LookupAsciiSymbol("Array"));
+  JSFunction* function =
+      JSFunction::cast(Top::context()->global()->GetProperty(name));
+
+  // Allocate the object.
+  JSArray* array = JSArray::cast(Heap::AllocateJSObject(function));
+  array->Initialize(0);
+
+  // Set array length to 0.
+  array->SetElementsLength(Smi::FromInt(0));
+  CHECK_EQ(Smi::FromInt(0), array->length());
+  CHECK(array->HasFastElements());  // Must be in fast mode.
+
+  // array[length] = name.
+  array->SetElement(0, name);
+  CHECK_EQ(Smi::FromInt(1), array->length());
+  CHECK_EQ(array->GetElement(0), name);
+
+  // Set array length with larger than smi value.
+  Object* length = Heap::NumberFromInt32(Smi::kMaxValue + 1);
+  array->SetElementsLength(length);
+
+  uint32_t int_length = 0;
+  CHECK(Array::IndexFromObject(length, &int_length));
+  CHECK_EQ(length, array->length());
+  CHECK(!array->HasFastElements());  // Must be in slow mode.
+
+  // array[length] = name.
+  array->SetElement(int_length, name);
+  uint32_t new_int_length = 0;
+  CHECK(Array::IndexFromObject(array->length(), &new_int_length));
+  CHECK_EQ(static_cast<double>(int_length), new_int_length - 1);
+  CHECK_EQ(array->GetElement(int_length), name);
+  CHECK_EQ(array->GetElement(0), name);
+}
+
+
+TEST(JSObjectCopy) {
+  InitializeVM();
+
+  v8::HandleScope sc;
+  String* name = String::cast(Heap::Object_symbol());
+  JSFunction* constructor =
+      JSFunction::cast(Top::context()->global()->GetProperty(name));
+  JSObject* obj = JSObject::cast(Heap::AllocateJSObject(constructor));
+  String* first = String::cast(Heap::LookupAsciiSymbol("first"));
+  String* second = String::cast(Heap::LookupAsciiSymbol("second"));
+
+  obj->SetProperty(first, Smi::FromInt(1), NONE);
+  obj->SetProperty(second, Smi::FromInt(2), NONE);
+
+  obj->SetElement(0, first);
+  obj->SetElement(1, second);
+
+  // Make the clone.
+  JSObject* clone = JSObject::cast(Heap::CopyJSObject(obj));
+  CHECK(clone != obj);
+
+  CHECK_EQ(obj->GetElement(0), clone->GetElement(0));
+  CHECK_EQ(obj->GetElement(1), clone->GetElement(1));
+
+  CHECK_EQ(obj->GetProperty(first), clone->GetProperty(first));
+  CHECK_EQ(obj->GetProperty(second), clone->GetProperty(second));
+
+  // Flip the values.
+  clone->SetProperty(first, Smi::FromInt(2), NONE);
+  clone->SetProperty(second, Smi::FromInt(1), NONE);
+
+  clone->SetElement(0, second);
+  clone->SetElement(1, first);
+
+  CHECK_EQ(obj->GetElement(1), clone->GetElement(0));
+  CHECK_EQ(obj->GetElement(0), clone->GetElement(1));
+
+  CHECK_EQ(obj->GetProperty(second), clone->GetProperty(first));
+  CHECK_EQ(obj->GetProperty(first), clone->GetProperty(second));
+}
+
+
+TEST(StringAllocation) {
+  InitializeVM();
+
+
+  const unsigned char chars[] = { 0xe5, 0xa4, 0xa7 };
+  for (int length = 0; length < 100; length++) {
+    v8::HandleScope scope;
+    char* non_ascii = NewArray<char>(3 * length + 1);
+    char* ascii = NewArray<char>(length + 1);
+    non_ascii[3 * length] = 0;
+    ascii[length] = 0;
+    for (int i = 0; i < length; i++) {
+      ascii[i] = 'a';
+      non_ascii[3 * i] = chars[0];
+      non_ascii[3 * i + 1] = chars[1];
+      non_ascii[3 * i + 2] = chars[2];
+    }
+    Handle<String> non_ascii_sym =
+        Factory::LookupSymbol(Vector<const char>(non_ascii, 3 * length));
+    CHECK_EQ(length, non_ascii_sym->length());
+    Handle<String> ascii_sym =
+        Factory::LookupSymbol(Vector<const char>(ascii, length));
+    CHECK_EQ(length, ascii_sym->length());
+    Handle<String> non_ascii_str =
+        Factory::NewStringFromUtf8(Vector<const char>(non_ascii, 3 * length));
+    non_ascii_str->Hash();
+    CHECK_EQ(length, non_ascii_str->length());
+    Handle<String> ascii_str =
+        Factory::NewStringFromUtf8(Vector<const char>(ascii, length));
+    ascii_str->Hash();
+    CHECK_EQ(length, ascii_str->length());
+    DeleteArray(non_ascii);
+    DeleteArray(ascii);
+  }
+}
+
+
+static int ObjectsFoundInHeap(Handle<Object> objs[], int size) {
+  // Count the number of objects found in the heap.
+  int found_count = 0;
+  HeapIterator iterator;
+  while (iterator.has_next()) {
+    HeapObject* obj = iterator.next();
+    CHECK(obj != NULL);
+    for (int i = 0; i < size; i++) {
+      if (*objs[i] == obj) {
+        found_count++;
+      }
+    }
+  }
+  CHECK(!iterator.has_next());
+  return found_count;
+}
+
+
+TEST(Iteration) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  // Array of objects to scan haep for.
+  const int objs_count = 6;
+  Handle<Object> objs[objs_count];
+  int next_objs_index = 0;
+
+  // Allocate a JS array to OLD_POINTER_SPACE and NEW_SPACE
+  objs[next_objs_index++] = Factory::NewJSArray(10);
+  objs[next_objs_index++] = Factory::NewJSArray(10, TENURED);
+
+  // Allocate a small string to OLD_DATA_SPACE and NEW_SPACE
+  objs[next_objs_index++] =
+      Factory::NewStringFromAscii(CStrVector("abcdefghij"));
+  objs[next_objs_index++] =
+      Factory::NewStringFromAscii(CStrVector("abcdefghij"), TENURED);
+
+  // Allocate a large string (for large object space).
+  int large_size = Heap::MaxHeapObjectSize() + 1;
+  char* str = new char[large_size];
+  for (int i = 0; i < large_size - 1; ++i) str[i] = 'a';
+  str[large_size - 1] = '\0';
+  objs[next_objs_index++] =
+      Factory::NewStringFromAscii(CStrVector(str), TENURED);
+  delete[] str;
+
+  // Add a Map object to look for.
+  objs[next_objs_index++] = Handle<Map>(HeapObject::cast(*objs[0])->map());
+
+  CHECK_EQ(objs_count, next_objs_index);
+  CHECK_EQ(objs_count, ObjectsFoundInHeap(objs, objs_count));
+}
diff --git a/deps/v8/test/cctest/test-list.cc b/deps/v8/test/cctest/test-list.cc
new file mode 100644
index 0000000..d10cdd7
--- /dev/null
+++ b/deps/v8/test/cctest/test-list.cc
@@ -0,0 +1,67 @@
+// 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.
+
+#include <stdlib.h>
+#include <string.h>
+#include "v8.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+// Use a testing allocator that clears memory before deletion.
+class ZeroingAllocationPolicy {
+ public:
+  static void* New(size_t size) {
+    // Stash the size in the first word to use for Delete.
+    size_t true_size = size + sizeof(size_t);
+    size_t* result = reinterpret_cast<size_t*>(malloc(true_size));
+    if (result == NULL) return result;
+    *result = true_size;
+    return result + 1;
+  }
+
+  static void Delete(void* ptr) {
+    size_t* true_ptr = reinterpret_cast<size_t*>(ptr) - 1;
+    memset(true_ptr, 0, *true_ptr);
+    free(true_ptr);
+  }
+};
+
+// Check that we can add (a reference to) an element of the list
+// itself.
+TEST(ListAdd) {
+  // Add elements to the list to grow it to its capacity.
+  List<int, ZeroingAllocationPolicy> list(4);
+  list.Add(1);
+  list.Add(2);
+  list.Add(3);
+  list.Add(4);
+
+  // Add an existing element, the backing store should have to grow.
+  list.Add(list[0]);
+  ASSERT(list[4] == 1);
+}
diff --git a/deps/v8/test/cctest/test-lock.cc b/deps/v8/test/cctest/test-lock.cc
new file mode 100644
index 0000000..5eecfce
--- /dev/null
+++ b/deps/v8/test/cctest/test-lock.cc
@@ -0,0 +1,63 @@
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+//
+// Tests of the TokenLock class from lock.h
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "platform.h"
+#include "cctest.h"
+
+
+using namespace ::v8::internal;
+
+
+// Simple test of locking logic
+TEST(Simple) {
+  Mutex* mutex = OS::CreateMutex();
+  CHECK_EQ(0, mutex->Lock());  // acquire the lock with the right token
+  CHECK_EQ(0, mutex->Unlock());  // can unlock with the right token
+  delete mutex;
+}
+
+
+TEST(MultiLock) {
+  Mutex* mutex = OS::CreateMutex();
+  CHECK_EQ(0, mutex->Lock());
+  CHECK_EQ(0, mutex->Unlock());
+  delete mutex;
+}
+
+
+TEST(ShallowLock) {
+  Mutex* mutex = OS::CreateMutex();
+  CHECK_EQ(0, mutex->Lock());
+  CHECK_EQ(0, mutex->Unlock());
+  CHECK_EQ(0, mutex->Lock());
+  CHECK_EQ(0, mutex->Unlock());
+  delete mutex;
+}
+
+
+TEST(SemaphoreTimeout) {
+  bool ok;
+  Semaphore* sem = OS::CreateSemaphore(0);
+
+  // Semaphore not signalled - timeout.
+  ok = sem->Wait(0);
+  CHECK(!ok);
+  ok = sem->Wait(100);
+  CHECK(!ok);
+  ok = sem->Wait(1000);
+  CHECK(!ok);
+
+  // Semaphore signalled - no timeout.
+  sem->Signal();
+  ok = sem->Wait(0);
+  sem->Signal();
+  ok = sem->Wait(100);
+  sem->Signal();
+  ok = sem->Wait(1000);
+  CHECK(ok);
+}
diff --git a/deps/v8/test/cctest/test-log-ia32.cc b/deps/v8/test/cctest/test-log-ia32.cc
new file mode 100644
index 0000000..b171339
--- /dev/null
+++ b/deps/v8/test/cctest/test-log-ia32.cc
@@ -0,0 +1,314 @@
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
+//
+// Tests of profiler-related functions from log.h
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "log.h"
+#include "top.h"
+#include "cctest.h"
+
+using v8::Function;
+using v8::Local;
+using v8::Object;
+using v8::Script;
+using v8::String;
+using v8::Value;
+
+using v8::internal::byte;
+using v8::internal::Handle;
+using v8::internal::JSFunction;
+using v8::internal::StackTracer;
+using v8::internal::TickSample;
+using v8::internal::Top;
+
+
+static v8::Persistent<v8::Context> env;
+
+
+static struct {
+  StackTracer* tracer;
+  TickSample* sample;
+} trace_env = { NULL, NULL };
+
+
+static void InitTraceEnv(StackTracer* tracer, TickSample* sample) {
+  trace_env.tracer = tracer;
+  trace_env.sample = sample;
+}
+
+
+static void DoTrace(unsigned int fp) {
+  trace_env.sample->fp = fp;
+  // sp is only used to define stack high bound
+  trace_env.sample->sp =
+      reinterpret_cast<unsigned int>(trace_env.sample) - 10240;
+  trace_env.tracer->Trace(trace_env.sample);
+}
+
+
+// Hide c_entry_fp to emulate situation when sampling is done while
+// pure JS code is being executed
+static void DoTraceHideCEntryFPAddress(unsigned int fp) {
+  v8::internal::Address saved_c_frame_fp = *(Top::c_entry_fp_address());
+  CHECK(saved_c_frame_fp);
+  *(Top::c_entry_fp_address()) = 0;
+  DoTrace(fp);
+  *(Top::c_entry_fp_address()) = saved_c_frame_fp;
+}
+
+
+static void CheckRetAddrIsInFunction(const char* func_name,
+                                     unsigned int ret_addr,
+                                     unsigned int func_start_addr,
+                                     unsigned int func_len) {
+  printf("CheckRetAddrIsInFunction \"%s\": %08x %08x %08x\n",
+         func_name, func_start_addr, ret_addr, func_start_addr + func_len);
+  CHECK_GE(ret_addr, func_start_addr);
+  CHECK_GE(func_start_addr + func_len, ret_addr);
+}
+
+
+static void CheckRetAddrIsInJSFunction(const char* func_name,
+                                       unsigned int ret_addr,
+                                       Handle<JSFunction> func) {
+  v8::internal::Code* func_code = func->code();
+  CheckRetAddrIsInFunction(
+      func_name, ret_addr,
+      reinterpret_cast<unsigned int>(func_code->instruction_start()),
+      func_code->ExecutableSize());
+}
+
+
+// --- T r a c e   E x t e n s i o n ---
+
+class TraceExtension : public v8::Extension {
+ public:
+  TraceExtension() : v8::Extension("v8/trace", kSource) { }
+  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
+      v8::Handle<String> name);
+  static v8::Handle<v8::Value> Trace(const v8::Arguments& args);
+  static v8::Handle<v8::Value> JSTrace(const v8::Arguments& args);
+ private:
+  static unsigned int GetFP(const v8::Arguments& args);
+  static const char* kSource;
+};
+
+
+const char* TraceExtension::kSource =
+    "native function trace();"
+    "native function js_trace();";
+
+
+v8::Handle<v8::FunctionTemplate> TraceExtension::GetNativeFunction(
+    v8::Handle<String> name) {
+  if (name->Equals(String::New("trace"))) {
+    return v8::FunctionTemplate::New(TraceExtension::Trace);
+  } else if (name->Equals(String::New("js_trace"))) {
+    return v8::FunctionTemplate::New(TraceExtension::JSTrace);
+  } else {
+    CHECK(false);
+    return v8::Handle<v8::FunctionTemplate>();
+  }
+}
+
+
+unsigned int TraceExtension::GetFP(const v8::Arguments& args) {
+  CHECK_EQ(1, args.Length());
+  unsigned int fp = args[0]->Int32Value() << 2;
+  printf("Trace: %08x\n", fp);
+  return fp;
+}
+
+
+v8::Handle<v8::Value> TraceExtension::Trace(const v8::Arguments& args) {
+  DoTrace(GetFP(args));
+  return v8::Undefined();
+}
+
+
+v8::Handle<v8::Value> TraceExtension::JSTrace(const v8::Arguments& args) {
+  DoTraceHideCEntryFPAddress(GetFP(args));
+  return v8::Undefined();
+}
+
+
+static TraceExtension kTraceExtension;
+v8::DeclareExtension kTraceExtensionDeclaration(&kTraceExtension);
+
+
+static void InitializeVM() {
+  if (env.IsEmpty()) {
+    v8::HandleScope scope;
+    const char* extensions[] = { "v8/trace" };
+    v8::ExtensionConfiguration config(1, extensions);
+    env = v8::Context::New(&config);
+  }
+  v8::HandleScope scope;
+  env->Enter();
+}
+
+
+static Handle<JSFunction> CompileFunction(const char* source) {
+  return v8::Utils::OpenHandle(*Script::Compile(String::New(source)));
+}
+
+
+static void CompileRun(const char* source) {
+  Script::Compile(String::New(source))->Run();
+}
+
+
+static Local<Value> GetGlobalProperty(const char* name) {
+  return env->Global()->Get(String::New(name));
+}
+
+
+static Handle<JSFunction> GetGlobalJSFunction(const char* name) {
+  Handle<JSFunction> js_func(JSFunction::cast(
+                                 *(v8::Utils::OpenHandle(
+                                       *GetGlobalProperty(name)))));
+  return js_func;
+}
+
+
+static void CheckRetAddrIsInJSFunction(const char* func_name,
+                                       unsigned int ret_addr) {
+  CheckRetAddrIsInJSFunction(func_name, ret_addr,
+                             GetGlobalJSFunction(func_name));
+}
+
+
+static void SetGlobalProperty(const char* name, Local<Value> value) {
+  env->Global()->Set(String::New(name), value);
+}
+
+
+static bool Patch(byte* from,
+                  size_t num,
+                  byte* original,
+                  byte* patch,
+                  size_t patch_len) {
+  byte* to = from + num;
+  do {
+    from = static_cast<byte*>(memchr(from, *original, to - from));
+    CHECK(from != NULL);
+    if (memcmp(original, from, patch_len) == 0) {
+      memcpy(from, patch, patch_len);
+      return true;
+    } else {
+      from++;
+    }
+  } while (to - from > 0);
+  return false;
+}
+
+
+// Creates a global function named 'func_name' that calls the tracing
+// function 'trace_func_name' with an actual EBP register value,
+// shifted right to be presented as Smi.
+static void CreateTraceCallerFunction(const char* func_name,
+                                      const char* trace_func_name) {
+  ::v8::internal::EmbeddedVector<char, 256> trace_call_buf;
+  ::v8::internal::OS::SNPrintF(trace_call_buf, "%s(0x6666);", trace_func_name);
+  Handle<JSFunction> func = CompileFunction(trace_call_buf.start());
+  CHECK(!func.is_null());
+  v8::internal::Code* func_code = func->code();
+  CHECK(func_code->IsCode());
+
+  // push 0xcccc (= 0x6666 << 1)
+  byte original[] = { 0x68, 0xcc, 0xcc, 0x00, 0x00 };
+  // mov eax,ebp; shr eax; push eax;
+  byte patch[] = { 0x89, 0xe8, 0xd1, 0xe8, 0x50 };
+  // Patch generated code to replace pushing of a constant with
+  // pushing of ebp contents in a Smi
+  CHECK(Patch(func_code->instruction_start(),
+              func_code->instruction_size(),
+              original, patch, sizeof(patch)));
+
+  SetGlobalProperty(func_name, v8::ToApi<Value>(func));
+}
+
+
+TEST(CFromJSStackTrace) {
+  TickSample sample;
+  StackTracer tracer(reinterpret_cast<unsigned int>(&sample));
+  InitTraceEnv(&tracer, &sample);
+
+  InitializeVM();
+  v8::HandleScope scope;
+  CreateTraceCallerFunction("JSFuncDoTrace", "trace");
+  CompileRun(
+      "function JSTrace() {"
+      "  JSFuncDoTrace();"
+      "};\n"
+      "JSTrace();");
+  CHECK_GT(sample.frames_count, 1);
+  // Stack sampling will start from the first JS function, i.e. "JSFuncDoTrace"
+  CheckRetAddrIsInJSFunction("JSFuncDoTrace",
+                             reinterpret_cast<unsigned int>(sample.stack[0]));
+  CheckRetAddrIsInJSFunction("JSTrace",
+                             reinterpret_cast<unsigned int>(sample.stack[1]));
+}
+
+
+TEST(PureJSStackTrace) {
+  TickSample sample;
+  StackTracer tracer(reinterpret_cast<unsigned int>(&sample));
+  InitTraceEnv(&tracer, &sample);
+
+  InitializeVM();
+  v8::HandleScope scope;
+  CreateTraceCallerFunction("JSFuncDoTrace", "js_trace");
+  CompileRun(
+      "function JSTrace() {"
+      "  JSFuncDoTrace();"
+      "};\n"
+      "function OuterJSTrace() {"
+      "  JSTrace();"
+      "};\n"
+      "OuterJSTrace();");
+  CHECK_GT(sample.frames_count, 1);
+  // Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace"
+  CheckRetAddrIsInJSFunction("JSTrace",
+                             reinterpret_cast<unsigned int>(sample.stack[0]));
+  CheckRetAddrIsInJSFunction("OuterJSTrace",
+                             reinterpret_cast<unsigned int>(sample.stack[1]));
+}
+
+
+static void CFuncDoTrace() {
+  unsigned int fp;
+#ifdef __GNUC__
+  fp = reinterpret_cast<unsigned int>(__builtin_frame_address(0));
+#elif defined _MSC_VER
+  __asm mov [fp], ebp  // NOLINT
+#endif
+  DoTrace(fp);
+}
+
+
+static int CFunc(int depth) {
+  if (depth <= 0) {
+    CFuncDoTrace();
+    return 0;
+  } else {
+    return CFunc(depth - 1) + 1;
+  }
+}
+
+
+TEST(PureCStackTrace) {
+  TickSample sample;
+  StackTracer tracer(reinterpret_cast<unsigned int>(&sample));
+  InitTraceEnv(&tracer, &sample);
+  // Check that sampler doesn't crash
+  CHECK_EQ(10, CFunc(10));
+}
+
+
+#endif  // ENABLE_LOGGING_AND_PROFILING
diff --git a/deps/v8/test/cctest/test-mark-compact.cc b/deps/v8/test/cctest/test-mark-compact.cc
new file mode 100644
index 0000000..53cff68
--- /dev/null
+++ b/deps/v8/test/cctest/test-mark-compact.cc
@@ -0,0 +1,314 @@
+// 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.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "global-handles.h"
+#include "snapshot.h"
+#include "top.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+static v8::Persistent<v8::Context> env;
+
+static void InitializeVM() {
+  if (env.IsEmpty()) env = v8::Context::New();
+  v8::HandleScope scope;
+  env->Enter();
+}
+
+
+TEST(MarkingStack) {
+  int mem_size = 20 * kPointerSize;
+  byte* mem = NewArray<byte>(20*kPointerSize);
+  Address low = reinterpret_cast<Address>(mem);
+  Address high = low + mem_size;
+  MarkingStack s;
+  s.Initialize(low, high);
+
+  Address address = NULL;
+  while (!s.is_full()) {
+    s.Push(HeapObject::FromAddress(address));
+    address += kPointerSize;
+  }
+
+  while (!s.is_empty()) {
+    Address value = s.Pop()->address();
+    address -= kPointerSize;
+    CHECK_EQ(address, value);
+  }
+
+  CHECK_EQ(NULL, address);
+  DeleteArray(mem);
+}
+
+
+TEST(Promotion) {
+  // Test the situation that some objects in new space are promoted to the
+  // old space
+  if (Snapshot::IsEnabled()) return;
+
+  // Ensure that we get a compacting collection so that objects are promoted
+  // from new space.
+  FLAG_gc_global = true;
+  FLAG_always_compact = true;
+  Heap::ConfigureHeap(2*256*KB, 4*MB);
+
+  InitializeVM();
+
+  v8::HandleScope sc;
+
+  // Allocate a fixed array in the new space.
+  int array_size =
+      (Heap::MaxHeapObjectSize() - Array::kHeaderSize) / (kPointerSize * 4);
+  Object* obj = Heap::AllocateFixedArray(array_size);
+  CHECK(!obj->IsFailure());
+
+  Handle<FixedArray> array(FixedArray::cast(obj));
+
+  // Array should be in the new space.
+  CHECK(Heap::InSpace(*array, NEW_SPACE));
+
+  // Call the m-c collector, so array becomes an old object.
+  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
+
+  // Array now sits in the old space
+  CHECK(Heap::InSpace(*array, OLD_POINTER_SPACE));
+}
+
+
+TEST(NoPromotion) {
+  if (Snapshot::IsEnabled()) return;
+  Heap::ConfigureHeap(2*256*KB, 4*MB);
+
+  // Test the situation that some objects in new space are promoted to
+  // the old space
+  InitializeVM();
+
+  v8::HandleScope sc;
+
+  // Do a mark compact GC to shrink the heap.
+  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
+
+  // Allocate a big Fixed array in the new space.
+  int size = (Heap::MaxHeapObjectSize() - Array::kHeaderSize) / kPointerSize;
+  Object* obj = Heap::AllocateFixedArray(size);
+
+  Handle<FixedArray> array(FixedArray::cast(obj));
+
+  // Array still stays in the new space.
+  CHECK(Heap::InSpace(*array, NEW_SPACE));
+
+  // Allocate objects in the old space until out of memory.
+  FixedArray* host = *array;
+  while (true) {
+    Object* obj = Heap::AllocateFixedArray(100, TENURED);
+    if (obj->IsFailure()) break;
+
+    host->set(0, obj);
+    host = FixedArray::cast(obj);
+  }
+
+  // Call mark compact GC, and it should pass.
+  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
+
+  // array should not be promoted because the old space is full.
+  CHECK(Heap::InSpace(*array, NEW_SPACE));
+}
+
+
+TEST(MarkCompactCollector) {
+  InitializeVM();
+
+  v8::HandleScope sc;
+  // call mark-compact when heap is empty
+  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
+
+  // keep allocating garbage in new space until it fails
+  const int ARRAY_SIZE = 100;
+  Object* array;
+  do {
+    array = Heap::AllocateFixedArray(ARRAY_SIZE);
+  } while (!array->IsFailure());
+  CHECK(Heap::CollectGarbage(0, NEW_SPACE));
+
+  array = Heap::AllocateFixedArray(ARRAY_SIZE);
+  CHECK(!array->IsFailure());
+
+  // keep allocating maps until it fails
+  Object* mapp;
+  do {
+    mapp = Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
+  } while (!mapp->IsFailure());
+  CHECK(Heap::CollectGarbage(0, MAP_SPACE));
+  mapp = Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
+  CHECK(!mapp->IsFailure());
+
+  // allocate a garbage
+  String* func_name = String::cast(Heap::LookupAsciiSymbol("theFunction"));
+  SharedFunctionInfo* function_share =
+    SharedFunctionInfo::cast(Heap::AllocateSharedFunctionInfo(func_name));
+  JSFunction* function =
+    JSFunction::cast(Heap::AllocateFunction(*Top::function_map(),
+                                            function_share,
+                                            Heap::undefined_value()));
+  Map* initial_map =
+      Map::cast(Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize));
+  function->set_initial_map(initial_map);
+  Top::context()->global()->SetProperty(func_name, function, NONE);
+
+  JSObject* obj = JSObject::cast(Heap::AllocateJSObject(function));
+  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
+
+  func_name = String::cast(Heap::LookupAsciiSymbol("theFunction"));
+  CHECK(Top::context()->global()->HasLocalProperty(func_name));
+  Object* func_value = Top::context()->global()->GetProperty(func_name);
+  CHECK(func_value->IsJSFunction());
+  function = JSFunction::cast(func_value);
+
+  obj = JSObject::cast(Heap::AllocateJSObject(function));
+  String* obj_name = String::cast(Heap::LookupAsciiSymbol("theObject"));
+  Top::context()->global()->SetProperty(obj_name, obj, NONE);
+  String* prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
+  obj->SetProperty(prop_name, Smi::FromInt(23), NONE);
+
+  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
+
+  obj_name = String::cast(Heap::LookupAsciiSymbol("theObject"));
+  CHECK(Top::context()->global()->HasLocalProperty(obj_name));
+  CHECK(Top::context()->global()->GetProperty(obj_name)->IsJSObject());
+  obj = JSObject::cast(Top::context()->global()->GetProperty(obj_name));
+  prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
+  CHECK(obj->GetProperty(prop_name) == Smi::FromInt(23));
+}
+
+
+static int gc_starts = 0;
+static int gc_ends = 0;
+
+static void GCPrologueCallbackFunc() {
+  CHECK(gc_starts == gc_ends);
+  gc_starts++;
+}
+
+
+static void GCEpilogueCallbackFunc() {
+  CHECK(gc_starts == gc_ends + 1);
+  gc_ends++;
+}
+
+
+TEST(GCCallback) {
+  InitializeVM();
+
+  Heap::SetGlobalGCPrologueCallback(&GCPrologueCallbackFunc);
+  Heap::SetGlobalGCEpilogueCallback(&GCEpilogueCallbackFunc);
+
+  // Scavenge does not call GC callback functions.
+  Heap::PerformScavenge();
+
+  CHECK_EQ(0, gc_starts);
+  CHECK_EQ(gc_ends, gc_starts);
+
+  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
+  CHECK_EQ(1, gc_starts);
+  CHECK_EQ(gc_ends, gc_starts);
+}
+
+
+static int NumberOfWeakCalls = 0;
+static void WeakPointerCallback(v8::Persistent<v8::Value> handle, void* id) {
+  NumberOfWeakCalls++;
+}
+
+TEST(ObjectGroups) {
+  InitializeVM();
+
+  NumberOfWeakCalls = 0;
+  v8::HandleScope handle_scope;
+
+  Handle<Object> g1s1 =
+    GlobalHandles::Create(Heap::AllocateFixedArray(1));
+  Handle<Object> g1s2 =
+    GlobalHandles::Create(Heap::AllocateFixedArray(1));
+  GlobalHandles::MakeWeak(g1s1.location(),
+                          reinterpret_cast<void*>(1234),
+                          &WeakPointerCallback);
+  GlobalHandles::MakeWeak(g1s2.location(),
+                          reinterpret_cast<void*>(1234),
+                          &WeakPointerCallback);
+
+  Handle<Object> g2s1 =
+    GlobalHandles::Create(Heap::AllocateFixedArray(1));
+  Handle<Object> g2s2 =
+    GlobalHandles::Create(Heap::AllocateFixedArray(1));
+  GlobalHandles::MakeWeak(g2s1.location(),
+                          reinterpret_cast<void*>(1234),
+                          &WeakPointerCallback);
+  GlobalHandles::MakeWeak(g2s2.location(),
+                          reinterpret_cast<void*>(1234),
+                          &WeakPointerCallback);
+
+  Handle<Object> root = GlobalHandles::Create(*g1s1);  // make a root.
+
+  // Connect group 1 and 2, make a cycle.
+  Handle<FixedArray>::cast(g1s2)->set(0, *g2s2);
+  Handle<FixedArray>::cast(g2s1)->set(0, *g1s1);
+
+  {
+    Object** g1_objects[] = { g1s1.location(), g1s2.location() };
+    Object** g2_objects[] = { g2s1.location(), g2s2.location() };
+    GlobalHandles::AddGroup(g1_objects, 2);
+    GlobalHandles::AddGroup(g2_objects, 2);
+  }
+  // Do a full GC
+  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
+
+  // All object should be alive.
+  CHECK_EQ(0, NumberOfWeakCalls);
+
+  // Weaken the root.
+  GlobalHandles::MakeWeak(root.location(),
+                          reinterpret_cast<void*>(1234),
+                          &WeakPointerCallback);
+
+  // Groups are deleted, rebuild groups.
+  {
+    Object** g1_objects[] = { g1s1.location(), g1s2.location() };
+    Object** g2_objects[] = { g2s1.location(), g2s2.location() };
+    GlobalHandles::AddGroup(g1_objects, 2);
+    GlobalHandles::AddGroup(g2_objects, 2);
+  }
+
+  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
+
+  // All objects should be gone. 5 global handles in total.
+  CHECK_EQ(5, NumberOfWeakCalls);
+}
diff --git a/deps/v8/test/cctest/test-platform-linux.cc b/deps/v8/test/cctest/test-platform-linux.cc
new file mode 100644
index 0000000..e1a00e1
--- /dev/null
+++ b/deps/v8/test/cctest/test-platform-linux.cc
@@ -0,0 +1,80 @@
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+//
+// Tests of the TokenLock class from lock.h
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <unistd.h>  // for usleep()
+
+#include "v8.h"
+
+#include "platform.h"
+#include "cctest.h"
+
+using namespace ::v8::internal;
+
+
+static void yield() {
+  usleep(1);
+}
+
+static const int kLockCounterLimit = 50;
+static int busy_lock_counter = 0;
+
+
+static void LoopIncrement(Mutex* mutex, int rem) {
+  while (true) {
+    int count = 0;
+    int last_count = -1;
+    do {
+      CHECK_EQ(0, mutex->Lock());
+      count = busy_lock_counter;
+      CHECK_EQ(0, mutex->Unlock());
+      yield();
+    } while (count % 2 == rem && count < kLockCounterLimit);
+    if (count >= kLockCounterLimit) break;
+    CHECK_EQ(0, mutex->Lock());
+    CHECK_EQ(count, busy_lock_counter);
+    CHECK(last_count == -1 || count == last_count + 1);
+    busy_lock_counter++;
+    last_count = count;
+    CHECK_EQ(0, mutex->Unlock());
+    yield();
+  }
+}
+
+
+static void* RunTestBusyLock(void* arg) {
+  LoopIncrement(static_cast<Mutex*>(arg), 0);
+  return 0;
+}
+
+
+// Runs two threads that repeatedly acquire the lock and conditionally
+// increment a variable.
+TEST(BusyLock) {
+  pthread_t other;
+  Mutex* mutex = OS::CreateMutex();
+  int thread_created = pthread_create(&other,
+                                      NULL,
+                                      &RunTestBusyLock,
+                                      mutex);
+  CHECK_EQ(0, thread_created);
+  LoopIncrement(mutex, 1);
+  pthread_join(other, NULL);
+  delete mutex;
+}
+
+
+TEST(VirtualMemory) {
+  VirtualMemory* vm = new VirtualMemory(1 * MB);
+  CHECK(vm->IsReserved());
+  void* block_addr = vm->address();
+  size_t block_size = 4 * KB;
+  CHECK(vm->Commit(block_addr, block_size, false));
+  // Check whether we can write to memory.
+  int* addr = static_cast<int*>(block_addr);
+  addr[KB-1] = 2;
+  CHECK(vm->Uncommit(block_addr, block_size));
+  delete vm;
+}
diff --git a/deps/v8/test/cctest/test-platform-macos.cc b/deps/v8/test/cctest/test-platform-macos.cc
new file mode 100644
index 0000000..d80fa54
--- /dev/null
+++ b/deps/v8/test/cctest/test-platform-macos.cc
@@ -0,0 +1,10 @@
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+//
+// Tests of the TokenLock class from lock.h
+
+#include <stdlib.h>
+
+#include "v8.h"
+#include "cctest.h"
+
+using namespace ::v8::internal;
diff --git a/deps/v8/test/cctest/test-platform-nullos.cc b/deps/v8/test/cctest/test-platform-nullos.cc
new file mode 100644
index 0000000..c0d6ae5
--- /dev/null
+++ b/deps/v8/test/cctest/test-platform-nullos.cc
@@ -0,0 +1,80 @@
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+//
+// Tests of the TokenLock class from lock.h
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <unistd.h>  // for usleep()
+
+#include "v8.h"
+
+#include "platform.h"
+#include "cctest.h"
+
+using namespace ::v8::internal;
+
+
+static void yield() {
+  UNIMPLEMENTED();
+}
+
+static const int kLockCounterLimit = 50;
+static int busy_lock_counter = 0;
+
+
+static void LoopIncrement(Mutex* mutex, int rem) {
+  while (true) {
+    int count = 0;
+    int last_count = -1;
+    do {
+      CHECK_EQ(0, mutex->Lock());
+      count = busy_lock_counter;
+      CHECK_EQ(0, mutex->Unlock());
+      yield();
+    } while (count % 2 == rem && count < kLockCounterLimit);
+    if (count >= kLockCounterLimit) break;
+    CHECK_EQ(0, mutex->Lock());
+    CHECK_EQ(count, busy_lock_counter);
+    CHECK(last_count == -1 || count == last_count + 1);
+    busy_lock_counter++;
+    last_count = count;
+    CHECK_EQ(0, mutex->Unlock());
+    yield();
+  }
+}
+
+
+static void* RunTestBusyLock(void* arg) {
+  LoopIncrement(static_cast<Mutex*>(arg), 0);
+  return 0;
+}
+
+
+// Runs two threads that repeatedly acquire the lock and conditionally
+// increment a variable.
+TEST(BusyLock) {
+  pthread_t other;
+  Mutex* mutex = OS::CreateMutex();
+  int thread_created = pthread_create(&other,
+                                      NULL,
+                                      &RunTestBusyLock,
+                                      mutex);
+  CHECK_EQ(0, thread_created);
+  LoopIncrement(mutex, 1);
+  pthread_join(other, NULL);
+  delete mutex;
+}
+
+
+TEST(VirtualMemory) {
+  VirtualMemory* vm = new VirtualMemory(1 * MB);
+  CHECK(vm->IsReserved());
+  void* block_addr = vm->address();
+  size_t block_size = 4 * KB;
+  CHECK(vm->Commit(block_addr, block_size, false));
+  // Check whether we can write to memory.
+  int* addr = static_cast<int*>(block_addr);
+  addr[KB-1] = 2;
+  CHECK(vm->Uncommit(block_addr, block_size));
+  delete vm;
+}
diff --git a/deps/v8/test/cctest/test-platform-win32.cc b/deps/v8/test/cctest/test-platform-win32.cc
new file mode 100644
index 0000000..a5a6dd5
--- /dev/null
+++ b/deps/v8/test/cctest/test-platform-win32.cc
@@ -0,0 +1,26 @@
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+//
+// Tests of the TokenLock class from lock.h
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "platform.h"
+#include "cctest.h"
+
+using namespace ::v8::internal;
+
+
+TEST(VirtualMemory) {
+  VirtualMemory* vm = new VirtualMemory(1 * MB);
+  CHECK(vm->IsReserved());
+  void* block_addr = vm->address();
+  size_t block_size = 4 * KB;
+  CHECK(vm->Commit(block_addr, block_size, false));
+  // Check whether we can write to memory.
+  int* addr = static_cast<int*>(block_addr);
+  addr[KB-1] = 2;
+  CHECK(vm->Uncommit(block_addr, block_size));
+  delete vm;
+}
diff --git a/deps/v8/test/cctest/test-regexp.cc b/deps/v8/test/cctest/test-regexp.cc
new file mode 100644
index 0000000..afd9679
--- /dev/null
+++ b/deps/v8/test/cctest/test-regexp.cc
@@ -0,0 +1,1536 @@
+// Copyright 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.
+
+
+#include <stdlib.h>
+#include <set>
+
+#include "v8.h"
+
+#include "string-stream.h"
+#include "cctest.h"
+#include "zone-inl.h"
+#include "parser.h"
+#include "ast.h"
+#include "jsregexp-inl.h"
+#include "regexp-macro-assembler.h"
+#include "regexp-macro-assembler-irregexp.h"
+#ifdef ARM
+#include "regexp-macro-assembler-arm.h"
+#else  // IA32
+#include "macro-assembler-ia32.h"
+#include "regexp-macro-assembler-ia32.h"
+#endif
+#include "interpreter-irregexp.h"
+
+
+using namespace v8::internal;
+
+
+static SmartPointer<const char> Parse(const char* input) {
+  V8::Initialize(NULL);
+  v8::HandleScope scope;
+  ZoneScope zone_scope(DELETE_ON_EXIT);
+  FlatStringReader reader(CStrVector(input));
+  RegExpCompileData result;
+  CHECK(v8::internal::ParseRegExp(&reader, false, &result));
+  CHECK(result.tree != NULL);
+  CHECK(result.error.is_null());
+  SmartPointer<const char> output = result.tree->ToString();
+  return output;
+}
+
+static bool CheckSimple(const char* input) {
+  V8::Initialize(NULL);
+  v8::HandleScope scope;
+  unibrow::Utf8InputBuffer<> buffer(input, strlen(input));
+  ZoneScope zone_scope(DELETE_ON_EXIT);
+  FlatStringReader reader(CStrVector(input));
+  RegExpCompileData result;
+  CHECK(v8::internal::ParseRegExp(&reader, false, &result));
+  CHECK(result.tree != NULL);
+  CHECK(result.error.is_null());
+  return result.simple;
+}
+
+struct MinMaxPair {
+  int min_match;
+  int max_match;
+};
+
+static MinMaxPair CheckMinMaxMatch(const char* input) {
+  V8::Initialize(NULL);
+  v8::HandleScope scope;
+  unibrow::Utf8InputBuffer<> buffer(input, strlen(input));
+  ZoneScope zone_scope(DELETE_ON_EXIT);
+  FlatStringReader reader(CStrVector(input));
+  RegExpCompileData result;
+  CHECK(v8::internal::ParseRegExp(&reader, false, &result));
+  CHECK(result.tree != NULL);
+  CHECK(result.error.is_null());
+  int min_match = result.tree->min_match();
+  int max_match = result.tree->max_match();
+  MinMaxPair pair = { min_match, max_match };
+  return pair;
+}
+
+
+
+#define CHECK_PARSE_EQ(input, expected) CHECK_EQ(expected, *Parse(input))
+#define CHECK_SIMPLE(input, simple) CHECK_EQ(simple, CheckSimple(input));
+#define CHECK_MIN_MAX(input, min, max)                                         \
+  { MinMaxPair min_max = CheckMinMaxMatch(input);                              \
+    CHECK_EQ(min, min_max.min_match);                                          \
+    CHECK_EQ(max, min_max.max_match);                                          \
+  }
+
+TEST(Parser) {
+  V8::Initialize(NULL);
+  CHECK_PARSE_EQ("abc", "'abc'");
+  CHECK_PARSE_EQ("", "%");
+  CHECK_PARSE_EQ("abc|def", "(| 'abc' 'def')");
+  CHECK_PARSE_EQ("abc|def|ghi", "(| 'abc' 'def' 'ghi')");
+  CHECK_PARSE_EQ("^xxx$", "(: @^i 'xxx' @$i)");
+  CHECK_PARSE_EQ("ab\\b\\d\\bcd", "(: 'ab' @b [0-9] @b 'cd')");
+  CHECK_PARSE_EQ("\\w|\\d", "(| [0-9 A-Z _ a-z] [0-9])");
+  CHECK_PARSE_EQ("a*", "(# 0 - g 'a')");
+  CHECK_PARSE_EQ("a*?", "(# 0 - n 'a')");
+  CHECK_PARSE_EQ("abc+", "(: 'ab' (# 1 - g 'c'))");
+  CHECK_PARSE_EQ("abc+?", "(: 'ab' (# 1 - n 'c'))");
+  CHECK_PARSE_EQ("xyz?", "(: 'xy' (# 0 1 g 'z'))");
+  CHECK_PARSE_EQ("xyz??", "(: 'xy' (# 0 1 n 'z'))");
+  CHECK_PARSE_EQ("xyz{0,1}", "(: 'xy' (# 0 1 g 'z'))");
+  CHECK_PARSE_EQ("xyz{0,1}?", "(: 'xy' (# 0 1 n 'z'))");
+  CHECK_PARSE_EQ("xyz{93}", "(: 'xy' (# 93 93 g 'z'))");
+  CHECK_PARSE_EQ("xyz{93}?", "(: 'xy' (# 93 93 n 'z'))");
+  CHECK_PARSE_EQ("xyz{1,32}", "(: 'xy' (# 1 32 g 'z'))");
+  CHECK_PARSE_EQ("xyz{1,32}?", "(: 'xy' (# 1 32 n 'z'))");
+  CHECK_PARSE_EQ("xyz{1,}", "(: 'xy' (# 1 - g 'z'))");
+  CHECK_PARSE_EQ("xyz{1,}?", "(: 'xy' (# 1 - n 'z'))");
+  CHECK_PARSE_EQ("a\\fb\\nc\\rd\\te\\vf", "'a\\x0cb\\x0ac\\x0dd\\x09e\\x0bf'");
+  CHECK_PARSE_EQ("a\\nb\\bc", "(: 'a\\x0ab' @b 'c')");
+  CHECK_PARSE_EQ("(?:foo)", "'foo'");
+  CHECK_PARSE_EQ("(?: foo )", "' foo '");
+  CHECK_PARSE_EQ("(foo|bar|baz)", "(^ (| 'foo' 'bar' 'baz'))");
+  CHECK_PARSE_EQ("foo|(bar|baz)|quux", "(| 'foo' (^ (| 'bar' 'baz')) 'quux')");
+  CHECK_PARSE_EQ("foo(?=bar)baz", "(: 'foo' (-> + 'bar') 'baz')");
+  CHECK_PARSE_EQ("foo(?!bar)baz", "(: 'foo' (-> - 'bar') 'baz')");
+  CHECK_PARSE_EQ("()", "(^ %)");
+  CHECK_PARSE_EQ("(?=)", "(-> + %)");
+  CHECK_PARSE_EQ("[]", "^[\\x00-\\uffff]");   // Doesn't compile on windows
+  CHECK_PARSE_EQ("[^]", "[\\x00-\\uffff]");   // \uffff isn't in codepage 1252
+  CHECK_PARSE_EQ("[x]", "[x]");
+  CHECK_PARSE_EQ("[xyz]", "[x y z]");
+  CHECK_PARSE_EQ("[a-zA-Z0-9]", "[a-z A-Z 0-9]");
+  CHECK_PARSE_EQ("[-123]", "[- 1 2 3]");
+  CHECK_PARSE_EQ("[^123]", "^[1 2 3]");
+  CHECK_PARSE_EQ("]", "']'");
+  CHECK_PARSE_EQ("}", "'}'");
+  CHECK_PARSE_EQ("[a-b-c]", "[a-b - c]");
+  CHECK_PARSE_EQ("[\\d]", "[0-9]");
+  CHECK_PARSE_EQ("[x\\dz]", "[x 0-9 z]");
+  CHECK_PARSE_EQ("[\\d-z]", "[0-9 - z]");
+  CHECK_PARSE_EQ("[\\d-\\d]", "[0-9 - 0-9]");
+  CHECK_PARSE_EQ("[z-\\d]", "[z - 0-9]");
+  CHECK_PARSE_EQ("\\cj\\cJ\\ci\\cI\\ck\\cK",
+                 "'\\x0a\\x0a\\x09\\x09\\x0b\\x0b'");
+  CHECK_PARSE_EQ("\\c!", "'c!'");
+  CHECK_PARSE_EQ("\\c_", "'c_'");
+  CHECK_PARSE_EQ("\\c~", "'c~'");
+  CHECK_PARSE_EQ("[a\\]c]", "[a ] c]");
+  CHECK_PARSE_EQ("\\[\\]\\{\\}\\(\\)\\%\\^\\#\\ ", "'[]{}()%^# '");
+  CHECK_PARSE_EQ("[\\[\\]\\{\\}\\(\\)\\%\\^\\#\\ ]", "[[ ] { } ( ) % ^ #  ]");
+  CHECK_PARSE_EQ("\\0", "'\\x00'");
+  CHECK_PARSE_EQ("\\8", "'8'");
+  CHECK_PARSE_EQ("\\9", "'9'");
+  CHECK_PARSE_EQ("\\11", "'\\x09'");
+  CHECK_PARSE_EQ("\\11a", "'\\x09a'");
+  CHECK_PARSE_EQ("\\011", "'\\x09'");
+  CHECK_PARSE_EQ("\\00011", "'\\x0011'");
+  CHECK_PARSE_EQ("\\118", "'\\x098'");
+  CHECK_PARSE_EQ("\\111", "'I'");
+  CHECK_PARSE_EQ("\\1111", "'I1'");
+  CHECK_PARSE_EQ("(x)(x)(x)\\1", "(: (^ 'x') (^ 'x') (^ 'x') (<- 1))");
+  CHECK_PARSE_EQ("(x)(x)(x)\\2", "(: (^ 'x') (^ 'x') (^ 'x') (<- 2))");
+  CHECK_PARSE_EQ("(x)(x)(x)\\3", "(: (^ 'x') (^ 'x') (^ 'x') (<- 3))");
+  CHECK_PARSE_EQ("(x)(x)(x)\\4", "(: (^ 'x') (^ 'x') (^ 'x') '\\x04')");
+  CHECK_PARSE_EQ("(x)(x)(x)\\1*", "(: (^ 'x') (^ 'x') (^ 'x')"
+                               " (# 0 - g (<- 1)))");
+  CHECK_PARSE_EQ("(x)(x)(x)\\2*", "(: (^ 'x') (^ 'x') (^ 'x')"
+                               " (# 0 - g (<- 2)))");
+  CHECK_PARSE_EQ("(x)(x)(x)\\3*", "(: (^ 'x') (^ 'x') (^ 'x')"
+                               " (# 0 - g (<- 3)))");
+  CHECK_PARSE_EQ("(x)(x)(x)\\4*", "(: (^ 'x') (^ 'x') (^ 'x')"
+                               " (# 0 - g '\\x04'))");
+  CHECK_PARSE_EQ("(x)(x)(x)(x)(x)(x)(x)(x)(x)(x)\\10",
+              "(: (^ 'x') (^ 'x') (^ 'x') (^ 'x') (^ 'x') (^ 'x')"
+              " (^ 'x') (^ 'x') (^ 'x') (^ 'x') (<- 10))");
+  CHECK_PARSE_EQ("(x)(x)(x)(x)(x)(x)(x)(x)(x)(x)\\11",
+              "(: (^ 'x') (^ 'x') (^ 'x') (^ 'x') (^ 'x') (^ 'x')"
+              " (^ 'x') (^ 'x') (^ 'x') (^ 'x') '\\x09')");
+  CHECK_PARSE_EQ("(a)\\1", "(: (^ 'a') (<- 1))");
+  CHECK_PARSE_EQ("(a\\1)", "(^ 'a')");
+  CHECK_PARSE_EQ("(\\1a)", "(^ 'a')");
+  CHECK_PARSE_EQ("(?=a)?a", "'a'");
+  CHECK_PARSE_EQ("(?=a){0,10}a", "'a'");
+  CHECK_PARSE_EQ("(?=a){1,10}a", "(: (-> + 'a') 'a')");
+  CHECK_PARSE_EQ("(?=a){9,10}a", "(: (-> + 'a') 'a')");
+  CHECK_PARSE_EQ("(?!a)?a", "'a'");
+  CHECK_PARSE_EQ("\\1(a)", "(^ 'a')");
+  CHECK_PARSE_EQ("(?!(a))\\1", "(-> - (^ 'a'))");
+  CHECK_PARSE_EQ("(?!\\1(a\\1)\\1)\\1", "(-> - (: (^ 'a') (<- 1)))");
+  CHECK_PARSE_EQ("[\\0]", "[\\x00]");
+  CHECK_PARSE_EQ("[\\11]", "[\\x09]");
+  CHECK_PARSE_EQ("[\\11a]", "[\\x09 a]");
+  CHECK_PARSE_EQ("[\\011]", "[\\x09]");
+  CHECK_PARSE_EQ("[\\00011]", "[\\x00 1 1]");
+  CHECK_PARSE_EQ("[\\118]", "[\\x09 8]");
+  CHECK_PARSE_EQ("[\\111]", "[I]");
+  CHECK_PARSE_EQ("[\\1111]", "[I 1]");
+  CHECK_PARSE_EQ("\\x34", "'\x34'");
+  CHECK_PARSE_EQ("\\x60", "'\x60'");
+  CHECK_PARSE_EQ("\\x3z", "'x3z'");
+  CHECK_PARSE_EQ("\\c", "'c'");
+  CHECK_PARSE_EQ("\\u0034", "'\x34'");
+  CHECK_PARSE_EQ("\\u003z", "'u003z'");
+  CHECK_PARSE_EQ("foo[z]*", "(: 'foo' (# 0 - g [z]))");
+
+  CHECK_SIMPLE("a", true);
+  CHECK_SIMPLE("a|b", false);
+  CHECK_SIMPLE("a\\n", false);
+  CHECK_SIMPLE("^a", false);
+  CHECK_SIMPLE("a$", false);
+  CHECK_SIMPLE("a\\b!", false);
+  CHECK_SIMPLE("a\\Bb", false);
+  CHECK_SIMPLE("a*", false);
+  CHECK_SIMPLE("a*?", false);
+  CHECK_SIMPLE("a?", false);
+  CHECK_SIMPLE("a??", false);
+  CHECK_SIMPLE("a{0,1}?", false);
+  CHECK_SIMPLE("a{1,1}?", false);
+  CHECK_SIMPLE("a{1,2}?", false);
+  CHECK_SIMPLE("a+?", false);
+  CHECK_SIMPLE("(a)", false);
+  CHECK_SIMPLE("(a)\\1", false);
+  CHECK_SIMPLE("(\\1a)", false);
+  CHECK_SIMPLE("\\1(a)", false);
+  CHECK_SIMPLE("a\\s", false);
+  CHECK_SIMPLE("a\\S", false);
+  CHECK_SIMPLE("a\\d", false);
+  CHECK_SIMPLE("a\\D", false);
+  CHECK_SIMPLE("a\\w", false);
+  CHECK_SIMPLE("a\\W", false);
+  CHECK_SIMPLE("a.", false);
+  CHECK_SIMPLE("a\\q", false);
+  CHECK_SIMPLE("a[a]", false);
+  CHECK_SIMPLE("a[^a]", false);
+  CHECK_SIMPLE("a[a-z]", false);
+  CHECK_SIMPLE("a[\\q]", false);
+  CHECK_SIMPLE("a(?:b)", false);
+  CHECK_SIMPLE("a(?=b)", false);
+  CHECK_SIMPLE("a(?!b)", false);
+  CHECK_SIMPLE("\\x60", false);
+  CHECK_SIMPLE("\\u0060", false);
+  CHECK_SIMPLE("\\cA", false);
+  CHECK_SIMPLE("\\q", false);
+  CHECK_SIMPLE("\\1112", false);
+  CHECK_SIMPLE("\\0", false);
+  CHECK_SIMPLE("(a)\\1", false);
+  CHECK_SIMPLE("(?=a)?a", false);
+  CHECK_SIMPLE("(?!a)?a\\1", false);
+  CHECK_SIMPLE("(?:(?=a))a\\1", false);
+
+  CHECK_PARSE_EQ("a{}", "'a{}'");
+  CHECK_PARSE_EQ("a{,}", "'a{,}'");
+  CHECK_PARSE_EQ("a{", "'a{'");
+  CHECK_PARSE_EQ("a{z}", "'a{z}'");
+  CHECK_PARSE_EQ("a{1z}", "'a{1z}'");
+  CHECK_PARSE_EQ("a{12z}", "'a{12z}'");
+  CHECK_PARSE_EQ("a{12,", "'a{12,'");
+  CHECK_PARSE_EQ("a{12,3b", "'a{12,3b'");
+  CHECK_PARSE_EQ("{}", "'{}'");
+  CHECK_PARSE_EQ("{,}", "'{,}'");
+  CHECK_PARSE_EQ("{", "'{'");
+  CHECK_PARSE_EQ("{z}", "'{z}'");
+  CHECK_PARSE_EQ("{1z}", "'{1z}'");
+  CHECK_PARSE_EQ("{12z}", "'{12z}'");
+  CHECK_PARSE_EQ("{12,", "'{12,'");
+  CHECK_PARSE_EQ("{12,3b", "'{12,3b'");
+
+  CHECK_MIN_MAX("a", 1, 1);
+  CHECK_MIN_MAX("abc", 3, 3);
+  CHECK_MIN_MAX("a[bc]d", 3, 3);
+  CHECK_MIN_MAX("a|bc", 1, 2);
+  CHECK_MIN_MAX("ab|c", 1, 2);
+  CHECK_MIN_MAX("a||bc", 0, 2);
+  CHECK_MIN_MAX("|", 0, 0);
+  CHECK_MIN_MAX("(?:ab)", 2, 2);
+  CHECK_MIN_MAX("(?:ab|cde)", 2, 3);
+  CHECK_MIN_MAX("(?:ab)|cde", 2, 3);
+  CHECK_MIN_MAX("(ab)", 2, 2);
+  CHECK_MIN_MAX("(ab|cde)", 2, 3);
+  CHECK_MIN_MAX("(ab)\\1", 2, 4);
+  CHECK_MIN_MAX("(ab|cde)\\1", 2, 6);
+  CHECK_MIN_MAX("(?:ab)?", 0, 2);
+  CHECK_MIN_MAX("(?:ab)*", 0, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:ab)+", 2, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("a?", 0, 1);
+  CHECK_MIN_MAX("a*", 0, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("a+", 1, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("a??", 0, 1);
+  CHECK_MIN_MAX("a*?", 0, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("a+?", 1, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:a?)?", 0, 1);
+  CHECK_MIN_MAX("(?:a*)?", 0, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:a+)?", 0, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:a?)+", 0, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:a*)+", 0, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:a+)+", 1, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:a?)*", 0, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:a*)*", 0, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:a+)*", 0, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("a{0}", 0, 0);
+  CHECK_MIN_MAX("(?:a+){0}", 0, 0);
+  CHECK_MIN_MAX("(?:a+){0,0}", 0, 0);
+  CHECK_MIN_MAX("a*b", 1, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("a+b", 2, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("a*b|c", 1, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("a+b|c", 1, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:a{5,1000000}){3,1000000}", 15, RegExpTree::kInfinity);
+  CHECK_MIN_MAX("(?:ab){4,7}", 8, 14);
+  CHECK_MIN_MAX("a\\bc", 2, 2);
+  CHECK_MIN_MAX("a\\Bc", 2, 2);
+  CHECK_MIN_MAX("a\\sc", 3, 3);
+  CHECK_MIN_MAX("a\\Sc", 3, 3);
+  CHECK_MIN_MAX("a(?=b)c", 2, 2);
+  CHECK_MIN_MAX("a(?=bbb|bb)c", 2, 2);
+  CHECK_MIN_MAX("a(?!bbb|bb)c", 2, 2);
+}
+
+TEST(ParserRegression) {
+  CHECK_PARSE_EQ("[A-Z$-][x]", "(! [A-Z $ -] [x])");
+  CHECK_PARSE_EQ("a{3,4*}", "(: 'a{3,' (# 0 - g '4') '}')");
+  CHECK_PARSE_EQ("{", "'{'");
+  CHECK_PARSE_EQ("a|", "(| 'a' %)");
+}
+
+static void ExpectError(const char* input,
+                        const char* expected) {
+  V8::Initialize(NULL);
+  v8::HandleScope scope;
+  ZoneScope zone_scope(DELETE_ON_EXIT);
+  FlatStringReader reader(CStrVector(input));
+  RegExpCompileData result;
+  CHECK_EQ(false, v8::internal::ParseRegExp(&reader, false, &result));
+  CHECK(result.tree == NULL);
+  CHECK(!result.error.is_null());
+  SmartPointer<char> str = result.error->ToCString(ALLOW_NULLS);
+  CHECK_EQ(expected, *str);
+}
+
+
+TEST(Errors) {
+  V8::Initialize(NULL);
+  const char* kEndBackslash = "\\ at end of pattern";
+  ExpectError("\\", kEndBackslash);
+  const char* kUnterminatedGroup = "Unterminated group";
+  ExpectError("(foo", kUnterminatedGroup);
+  const char* kInvalidGroup = "Invalid group";
+  ExpectError("(?", kInvalidGroup);
+  const char* kUnterminatedCharacterClass = "Unterminated character class";
+  ExpectError("[", kUnterminatedCharacterClass);
+  ExpectError("[a-", kUnterminatedCharacterClass);
+  const char* kNothingToRepeat = "Nothing to repeat";
+  ExpectError("*", kNothingToRepeat);
+  ExpectError("?", kNothingToRepeat);
+  ExpectError("+", kNothingToRepeat);
+  ExpectError("{1}", kNothingToRepeat);
+  ExpectError("{1,2}", kNothingToRepeat);
+  ExpectError("{1,}", kNothingToRepeat);
+
+  // Check that we don't allow more than kMaxCapture captures
+  const int kMaxCaptures = 1 << 16;  // Must match RegExpParser::kMaxCaptures.
+  const char* kTooManyCaptures = "Too many captures";
+  HeapStringAllocator allocator;
+  StringStream accumulator(&allocator);
+  for (int i = 0; i <= kMaxCaptures; i++) {
+    accumulator.Add("()");
+  }
+  SmartPointer<const char> many_captures(accumulator.ToCString());
+  ExpectError(*many_captures, kTooManyCaptures);
+}
+
+
+static bool IsDigit(uc16 c) {
+  return ('0' <= c && c <= '9');
+}
+
+
+static bool NotDigit(uc16 c) {
+  return !IsDigit(c);
+}
+
+
+static bool IsWhiteSpace(uc16 c) {
+  switch (c) {
+    case 0x09:
+    case 0x0A:
+    case 0x0B:
+    case 0x0C:
+    case 0x0d:
+    case 0x20:
+    case 0xA0:
+    case 0x2028:
+    case 0x2029:
+      return true;
+    default:
+      return unibrow::Space::Is(c);
+  }
+}
+
+
+static bool NotWhiteSpace(uc16 c) {
+  return !IsWhiteSpace(c);
+}
+
+
+static bool NotWord(uc16 c) {
+  return !IsRegExpWord(c);
+}
+
+
+static void TestCharacterClassEscapes(uc16 c, bool (pred)(uc16 c)) {
+  ZoneScope scope(DELETE_ON_EXIT);
+  ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
+  CharacterRange::AddClassEscape(c, ranges);
+  for (unsigned i = 0; i < (1 << 16); i++) {
+    bool in_class = false;
+    for (int j = 0; !in_class && j < ranges->length(); j++) {
+      CharacterRange& range = ranges->at(j);
+      in_class = (range.from() <= i && i <= range.to());
+    }
+    CHECK_EQ(pred(i), in_class);
+  }
+}
+
+
+TEST(CharacterClassEscapes) {
+  TestCharacterClassEscapes('.', IsRegExpNewline);
+  TestCharacterClassEscapes('d', IsDigit);
+  TestCharacterClassEscapes('D', NotDigit);
+  TestCharacterClassEscapes('s', IsWhiteSpace);
+  TestCharacterClassEscapes('S', NotWhiteSpace);
+  TestCharacterClassEscapes('w', IsRegExpWord);
+  TestCharacterClassEscapes('W', NotWord);
+}
+
+
+static RegExpNode* Compile(const char* input, bool multiline, bool is_ascii) {
+  V8::Initialize(NULL);
+  FlatStringReader reader(CStrVector(input));
+  RegExpCompileData compile_data;
+  if (!v8::internal::ParseRegExp(&reader, multiline, &compile_data))
+    return NULL;
+  Handle<String> pattern = Factory::NewStringFromUtf8(CStrVector(input));
+  RegExpEngine::Compile(&compile_data, false, multiline, pattern, is_ascii);
+  return compile_data.node;
+}
+
+
+static void Execute(const char* input,
+                    bool multiline,
+                    bool is_ascii,
+                    bool dot_output = false) {
+  v8::HandleScope scope;
+  ZoneScope zone_scope(DELETE_ON_EXIT);
+  RegExpNode* node = Compile(input, multiline, is_ascii);
+  USE(node);
+#ifdef DEBUG
+  if (dot_output) {
+    RegExpEngine::DotPrint(input, node, false);
+    exit(0);
+  }
+#endif  // DEBUG
+}
+
+
+class TestConfig {
+ public:
+  typedef int Key;
+  typedef int Value;
+  static const int kNoKey;
+  static const int kNoValue;
+  static inline int Compare(int a, int b) {
+    if (a < b)
+      return -1;
+    else if (a > b)
+      return 1;
+    else
+      return 0;
+  }
+};
+
+
+const int TestConfig::kNoKey = 0;
+const int TestConfig::kNoValue = 0;
+
+
+static int PseudoRandom(int i, int j) {
+  return ~(~((i * 781) ^ (j * 329)));
+}
+
+
+TEST(SplayTreeSimple) {
+  static const int kLimit = 1000;
+  ZoneScope zone_scope(DELETE_ON_EXIT);
+  ZoneSplayTree<TestConfig> tree;
+  std::set<int> seen;
+#define CHECK_MAPS_EQUAL() do {                                      \
+    for (int k = 0; k < kLimit; k++)                                 \
+      CHECK_EQ(seen.find(k) != seen.end(), tree.Find(k, &loc));      \
+  } while (false)
+  for (int i = 0; i < 50; i++) {
+    for (int j = 0; j < 50; j++) {
+      int next = PseudoRandom(i, j) % kLimit;
+      if (seen.find(next) != seen.end()) {
+        // We've already seen this one.  Check the value and remove
+        // it.
+        ZoneSplayTree<TestConfig>::Locator loc;
+        CHECK(tree.Find(next, &loc));
+        CHECK_EQ(next, loc.key());
+        CHECK_EQ(3 * next, loc.value());
+        tree.Remove(next);
+        seen.erase(next);
+        CHECK_MAPS_EQUAL();
+      } else {
+        // Check that it wasn't there already and then add it.
+        ZoneSplayTree<TestConfig>::Locator loc;
+        CHECK(!tree.Find(next, &loc));
+        CHECK(tree.Insert(next, &loc));
+        CHECK_EQ(next, loc.key());
+        loc.set_value(3 * next);
+        seen.insert(next);
+        CHECK_MAPS_EQUAL();
+      }
+      int val = PseudoRandom(j, i) % kLimit;
+      for (int k = val; k >= 0; k--) {
+        if (seen.find(val) != seen.end()) {
+          ZoneSplayTree<TestConfig>::Locator loc;
+          CHECK(tree.FindGreatestLessThan(val, &loc));
+          CHECK_EQ(loc.key(), val);
+          break;
+        }
+      }
+      val = PseudoRandom(i + j, i - j) % kLimit;
+      for (int k = val; k < kLimit; k++) {
+        if (seen.find(val) != seen.end()) {
+          ZoneSplayTree<TestConfig>::Locator loc;
+          CHECK(tree.FindLeastGreaterThan(val, &loc));
+          CHECK_EQ(loc.key(), val);
+          break;
+        }
+      }
+    }
+  }
+}
+
+
+TEST(DispatchTableConstruction) {
+  // Initialize test data.
+  static const int kLimit = 1000;
+  static const int kRangeCount = 8;
+  static const int kRangeSize = 16;
+  uc16 ranges[kRangeCount][2 * kRangeSize];
+  for (int i = 0; i < kRangeCount; i++) {
+    Vector<uc16> range(ranges[i], 2 * kRangeSize);
+    for (int j = 0; j < 2 * kRangeSize; j++) {
+      range[j] = PseudoRandom(i + 25, j + 87) % kLimit;
+    }
+    range.Sort();
+    for (int j = 1; j < 2 * kRangeSize; j++) {
+      CHECK(range[j-1] <= range[j]);
+    }
+  }
+  // Enter test data into dispatch table.
+  ZoneScope zone_scope(DELETE_ON_EXIT);
+  DispatchTable table;
+  for (int i = 0; i < kRangeCount; i++) {
+    uc16* range = ranges[i];
+    for (int j = 0; j < 2 * kRangeSize; j += 2)
+      table.AddRange(CharacterRange(range[j], range[j + 1]), i);
+  }
+  // Check that the table looks as we would expect
+  for (int p = 0; p < kLimit; p++) {
+    OutSet* outs = table.Get(p);
+    for (int j = 0; j < kRangeCount; j++) {
+      uc16* range = ranges[j];
+      bool is_on = false;
+      for (int k = 0; !is_on && (k < 2 * kRangeSize); k += 2)
+        is_on = (range[k] <= p && p <= range[k + 1]);
+      CHECK_EQ(is_on, outs->Get(j));
+    }
+  }
+}
+
+
+TEST(MacroAssembler) {
+  V8::Initialize(NULL);
+  byte codes[1024];
+  RegExpMacroAssemblerIrregexp m(Vector<byte>(codes, 1024));
+  // ^f(o)o.
+  Label fail, fail2, start;
+  uc16 foo_chars[3];
+  foo_chars[0] = 'f';
+  foo_chars[1] = 'o';
+  foo_chars[2] = 'o';
+  Vector<const uc16> foo(foo_chars, 3);
+  m.SetRegister(4, 42);
+  m.PushRegister(4, RegExpMacroAssembler::kNoStackLimitCheck);
+  m.AdvanceRegister(4, 42);
+  m.GoTo(&start);
+  m.Fail();
+  m.Bind(&start);
+  m.PushBacktrack(&fail2);
+  m.CheckCharacters(foo, 0, &fail, true);
+  m.WriteCurrentPositionToRegister(0, 0);
+  m.PushCurrentPosition();
+  m.AdvanceCurrentPosition(3);
+  m.WriteCurrentPositionToRegister(1, 0);
+  m.PopCurrentPosition();
+  m.AdvanceCurrentPosition(1);
+  m.WriteCurrentPositionToRegister(2, 0);
+  m.AdvanceCurrentPosition(1);
+  m.WriteCurrentPositionToRegister(3, 0);
+  m.Succeed();
+
+  m.Bind(&fail);
+  m.Backtrack();
+  m.Succeed();
+
+  m.Bind(&fail2);
+  m.PopRegister(0);
+  m.Fail();
+
+  v8::HandleScope scope;
+
+  Handle<String> source = Factory::NewStringFromAscii(CStrVector("^f(o)o"));
+  Handle<ByteArray> array = Handle<ByteArray>::cast(m.GetCode(source));
+  int captures[5];
+
+  const uc16 str1[] = {'f', 'o', 'o', 'b', 'a', 'r'};
+  Handle<String> f1_16 =
+      Factory::NewStringFromTwoByte(Vector<const uc16>(str1, 6));
+
+  CHECK(IrregexpInterpreter::Match(array, f1_16, captures, 0));
+  CHECK_EQ(0, captures[0]);
+  CHECK_EQ(3, captures[1]);
+  CHECK_EQ(1, captures[2]);
+  CHECK_EQ(2, captures[3]);
+  CHECK_EQ(84, captures[4]);
+
+  const uc16 str2[] = {'b', 'a', 'r', 'f', 'o', 'o'};
+  Handle<String> f2_16 =
+      Factory::NewStringFromTwoByte(Vector<const uc16>(str2, 6));
+
+  CHECK(!IrregexpInterpreter::Match(array, f2_16, captures, 0));
+  CHECK_EQ(42, captures[0]);
+}
+
+
+#ifndef ARM  // IA32 only tests.
+
+class ContextInitializer {
+ public:
+  ContextInitializer() : env_(), scope_(), stack_guard_() {
+    env_ = v8::Context::New();
+    env_->Enter();
+  }
+  ~ContextInitializer() {
+    env_->Exit();
+    env_.Dispose();
+  }
+ private:
+  v8::Persistent<v8::Context> env_;
+  v8::HandleScope scope_;
+  v8::internal::StackGuard stack_guard_;
+};
+
+
+static RegExpMacroAssemblerIA32::Result ExecuteIA32(Code* code,
+                                                    String* input,
+                                                    int start_offset,
+                                                    const byte* input_start,
+                                                    const byte* input_end,
+                                                    int* captures,
+                                                    bool at_start) {
+  return RegExpMacroAssemblerIA32::Execute(
+      code,
+      input,
+      start_offset,
+      input_start,
+      input_end,
+      captures,
+      at_start);
+}
+
+
+TEST(MacroAssemblerIA32Success) {
+  v8::V8::Initialize();
+  ContextInitializer initializer;
+
+  RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 4);
+
+  m.Succeed();
+
+  Handle<String> source = Factory::NewStringFromAscii(CStrVector(""));
+  Handle<Object> code_object = m.GetCode(source);
+  Handle<Code> code = Handle<Code>::cast(code_object);
+
+  int captures[4] = {42, 37, 87, 117};
+  Handle<String> input = Factory::NewStringFromAscii(CStrVector("foofoo"));
+  Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
+  const byte* start_adr =
+      reinterpret_cast<const byte*>(seq_input->GetCharsAddress());
+
+  RegExpMacroAssemblerIA32::Result result =
+      ExecuteIA32(*code,
+                  *input,
+                  0,
+                  start_adr,
+                  start_adr + seq_input->length(),
+                  captures,
+                  true);
+
+  CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
+  CHECK_EQ(-1, captures[0]);
+  CHECK_EQ(-1, captures[1]);
+  CHECK_EQ(-1, captures[2]);
+  CHECK_EQ(-1, captures[3]);
+}
+
+
+TEST(MacroAssemblerIA32Simple) {
+  v8::V8::Initialize();
+  ContextInitializer initializer;
+
+  RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 4);
+
+  uc16 foo_chars[3] = {'f', 'o', 'o'};
+  Vector<const uc16> foo(foo_chars, 3);
+
+  Label fail;
+  m.CheckCharacters(foo, 0, &fail, true);
+  m.WriteCurrentPositionToRegister(0, 0);
+  m.AdvanceCurrentPosition(3);
+  m.WriteCurrentPositionToRegister(1, 0);
+  m.Succeed();
+  m.Bind(&fail);
+  m.Fail();
+
+  Handle<String> source = Factory::NewStringFromAscii(CStrVector("^foo"));
+  Handle<Object> code_object = m.GetCode(source);
+  Handle<Code> code = Handle<Code>::cast(code_object);
+
+  int captures[4] = {42, 37, 87, 117};
+  Handle<String> input = Factory::NewStringFromAscii(CStrVector("foofoo"));
+  Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
+  Address start_adr = seq_input->GetCharsAddress();
+
+  RegExpMacroAssemblerIA32::Result result =
+      ExecuteIA32(*code,
+                  *input,
+                  0,
+                  start_adr,
+                  start_adr + input->length(),
+                  captures,
+                  true);
+
+  CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
+  CHECK_EQ(0, captures[0]);
+  CHECK_EQ(3, captures[1]);
+  CHECK_EQ(-1, captures[2]);
+  CHECK_EQ(-1, captures[3]);
+
+  input = Factory::NewStringFromAscii(CStrVector("barbarbar"));
+  seq_input = Handle<SeqAsciiString>::cast(input);
+  start_adr = seq_input->GetCharsAddress();
+
+  result = ExecuteIA32(*code,
+                       *input,
+                       0,
+                       start_adr,
+                       start_adr + input->length(),
+                       captures,
+                       true);
+
+  CHECK_EQ(RegExpMacroAssemblerIA32::FAILURE, result);
+}
+
+
+TEST(MacroAssemblerIA32SimpleUC16) {
+  v8::V8::Initialize();
+  ContextInitializer initializer;
+
+  RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::UC16, 4);
+
+  uc16 foo_chars[3] = {'f', 'o', 'o'};
+  Vector<const uc16> foo(foo_chars, 3);
+
+  Label fail;
+  m.CheckCharacters(foo, 0, &fail, true);
+  m.WriteCurrentPositionToRegister(0, 0);
+  m.AdvanceCurrentPosition(3);
+  m.WriteCurrentPositionToRegister(1, 0);
+  m.Succeed();
+  m.Bind(&fail);
+  m.Fail();
+
+  Handle<String> source = Factory::NewStringFromAscii(CStrVector("^foo"));
+  Handle<Object> code_object = m.GetCode(source);
+  Handle<Code> code = Handle<Code>::cast(code_object);
+
+  int captures[4] = {42, 37, 87, 117};
+  const uc16 input_data[6] = {'f', 'o', 'o', 'f', 'o', '\xa0'};
+  Handle<String> input =
+      Factory::NewStringFromTwoByte(Vector<const uc16>(input_data, 6));
+  Handle<SeqTwoByteString> seq_input = Handle<SeqTwoByteString>::cast(input);
+  Address start_adr = seq_input->GetCharsAddress();
+
+  RegExpMacroAssemblerIA32::Result result =
+      ExecuteIA32(*code,
+                  *input,
+                  0,
+                  start_adr,
+                  start_adr + input->length(),
+                  captures,
+                  true);
+
+  CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
+  CHECK_EQ(0, captures[0]);
+  CHECK_EQ(3, captures[1]);
+  CHECK_EQ(-1, captures[2]);
+  CHECK_EQ(-1, captures[3]);
+
+  const uc16 input_data2[9] = {'b', 'a', 'r', 'b', 'a', 'r', 'b', 'a', '\xa0'};
+  input = Factory::NewStringFromTwoByte(Vector<const uc16>(input_data2, 9));
+  seq_input = Handle<SeqTwoByteString>::cast(input);
+  start_adr = seq_input->GetCharsAddress();
+
+  result = ExecuteIA32(*code,
+                       *input,
+                       0,
+                       start_adr,
+                       start_adr + input->length() * 2,
+                       captures,
+                       true);
+
+  CHECK_EQ(RegExpMacroAssemblerIA32::FAILURE, result);
+}
+
+
+TEST(MacroAssemblerIA32Backtrack) {
+  v8::V8::Initialize();
+  ContextInitializer initializer;
+
+  RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 0);
+
+  Label fail;
+  Label backtrack;
+  m.LoadCurrentCharacter(10, &fail);
+  m.Succeed();
+  m.Bind(&fail);
+  m.PushBacktrack(&backtrack);
+  m.LoadCurrentCharacter(10, NULL);
+  m.Succeed();
+  m.Bind(&backtrack);
+  m.Fail();
+
+  Handle<String> source = Factory::NewStringFromAscii(CStrVector(".........."));
+  Handle<Object> code_object = m.GetCode(source);
+  Handle<Code> code = Handle<Code>::cast(code_object);
+
+  Handle<String> input = Factory::NewStringFromAscii(CStrVector("foofoo"));
+  Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
+  Address start_adr = seq_input->GetCharsAddress();
+
+  RegExpMacroAssemblerIA32::Result result =
+      ExecuteIA32(*code,
+                  *input,
+                  0,
+                  start_adr,
+                  start_adr + input->length(),
+                  NULL,
+                  true);
+
+  CHECK_EQ(RegExpMacroAssemblerIA32::FAILURE, result);
+}
+
+
+TEST(MacroAssemblerIA32BackReferenceASCII) {
+  v8::V8::Initialize();
+  ContextInitializer initializer;
+
+  RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 3);
+
+  m.WriteCurrentPositionToRegister(0, 0);
+  m.AdvanceCurrentPosition(2);
+  m.WriteCurrentPositionToRegister(1, 0);
+  Label nomatch;
+  m.CheckNotBackReference(0, &nomatch);
+  m.Fail();
+  m.Bind(&nomatch);
+  m.AdvanceCurrentPosition(2);
+  Label missing_match;
+  m.CheckNotBackReference(0, &missing_match);
+  m.WriteCurrentPositionToRegister(2, 0);
+  m.Succeed();
+  m.Bind(&missing_match);
+  m.Fail();
+
+  Handle<String> source = Factory::NewStringFromAscii(CStrVector("^(..)..\1"));
+  Handle<Object> code_object = m.GetCode(source);
+  Handle<Code> code = Handle<Code>::cast(code_object);
+
+  Handle<String> input = Factory::NewStringFromAscii(CStrVector("fooofo"));
+  Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
+  Address start_adr = seq_input->GetCharsAddress();
+
+  int output[3];
+  RegExpMacroAssemblerIA32::Result result =
+      ExecuteIA32(*code,
+                  *input,
+                  0,
+                  start_adr,
+                  start_adr + input->length(),
+                  output,
+                  true);
+
+  CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
+  CHECK_EQ(0, output[0]);
+  CHECK_EQ(2, output[1]);
+  CHECK_EQ(6, output[2]);
+}
+
+
+TEST(MacroAssemblerIA32BackReferenceUC16) {
+  v8::V8::Initialize();
+  ContextInitializer initializer;
+
+  RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::UC16, 3);
+
+  m.WriteCurrentPositionToRegister(0, 0);
+  m.AdvanceCurrentPosition(2);
+  m.WriteCurrentPositionToRegister(1, 0);
+  Label nomatch;
+  m.CheckNotBackReference(0, &nomatch);
+  m.Fail();
+  m.Bind(&nomatch);
+  m.AdvanceCurrentPosition(2);
+  Label missing_match;
+  m.CheckNotBackReference(0, &missing_match);
+  m.WriteCurrentPositionToRegister(2, 0);
+  m.Succeed();
+  m.Bind(&missing_match);
+  m.Fail();
+
+  Handle<String> source = Factory::NewStringFromAscii(CStrVector("^(..)..\1"));
+  Handle<Object> code_object = m.GetCode(source);
+  Handle<Code> code = Handle<Code>::cast(code_object);
+
+  const uc16 input_data[6] = {'f', 0x2028, 'o', 'o', 'f', 0x2028};
+  Handle<String> input =
+      Factory::NewStringFromTwoByte(Vector<const uc16>(input_data, 6));
+  Handle<SeqTwoByteString> seq_input = Handle<SeqTwoByteString>::cast(input);
+  Address start_adr = seq_input->GetCharsAddress();
+
+  int output[3];
+  RegExpMacroAssemblerIA32::Result result =
+      ExecuteIA32(*code,
+                  *input,
+                  0,
+                  start_adr,
+                  start_adr + input->length() * 2,
+                  output,
+                  true);
+
+  CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
+  CHECK_EQ(0, output[0]);
+  CHECK_EQ(2, output[1]);
+  CHECK_EQ(6, output[2]);
+}
+
+
+
+TEST(MacroAssemblerIA32AtStart) {
+  v8::V8::Initialize();
+  ContextInitializer initializer;
+
+  RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 0);
+
+  Label not_at_start, newline, fail;
+  m.CheckNotAtStart(&not_at_start);
+  // Check that prevchar = '\n' and current = 'f'.
+  m.CheckCharacter('\n', &newline);
+  m.Bind(&fail);
+  m.Fail();
+  m.Bind(&newline);
+  m.LoadCurrentCharacter(0, &fail);
+  m.CheckNotCharacter('f', &fail);
+  m.Succeed();
+
+  m.Bind(&not_at_start);
+  // Check that prevchar = 'o' and current = 'b'.
+  Label prevo;
+  m.CheckCharacter('o', &prevo);
+  m.Fail();
+  m.Bind(&prevo);
+  m.LoadCurrentCharacter(0, &fail);
+  m.CheckNotCharacter('b', &fail);
+  m.Succeed();
+
+  Handle<String> source = Factory::NewStringFromAscii(CStrVector("(^f|ob)"));
+  Handle<Object> code_object = m.GetCode(source);
+  Handle<Code> code = Handle<Code>::cast(code_object);
+
+  Handle<String> input = Factory::NewStringFromAscii(CStrVector("foobar"));
+  Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
+  Address start_adr = seq_input->GetCharsAddress();
+
+  RegExpMacroAssemblerIA32::Result result =
+      ExecuteIA32(*code,
+                  *input,
+                  0,
+                  start_adr,
+                  start_adr + input->length(),
+                  NULL,
+                  true);
+
+  CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
+
+  result = ExecuteIA32(*code,
+                       *input,
+                       3,
+                       start_adr + 3,
+                       start_adr + input->length(),
+                       NULL,
+                       false);
+
+  CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
+}
+
+
+TEST(MacroAssemblerIA32BackRefNoCase) {
+  v8::V8::Initialize();
+  ContextInitializer initializer;
+
+  RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 4);
+
+  Label fail, succ;
+
+  m.WriteCurrentPositionToRegister(0, 0);
+  m.WriteCurrentPositionToRegister(2, 0);
+  m.AdvanceCurrentPosition(3);
+  m.WriteCurrentPositionToRegister(3, 0);
+  m.CheckNotBackReferenceIgnoreCase(2, &fail);  // Match "AbC".
+  m.CheckNotBackReferenceIgnoreCase(2, &fail);  // Match "ABC".
+  Label expected_fail;
+  m.CheckNotBackReferenceIgnoreCase(2, &expected_fail);
+  m.Bind(&fail);
+  m.Fail();
+
+  m.Bind(&expected_fail);
+  m.AdvanceCurrentPosition(3);  // Skip "xYz"
+  m.CheckNotBackReferenceIgnoreCase(2, &succ);
+  m.Fail();
+
+  m.Bind(&succ);
+  m.WriteCurrentPositionToRegister(1, 0);
+  m.Succeed();
+
+  Handle<String> source =
+      Factory::NewStringFromAscii(CStrVector("^(abc)\1\1(?!\1)...(?!\1)"));
+  Handle<Object> code_object = m.GetCode(source);
+  Handle<Code> code = Handle<Code>::cast(code_object);
+
+  Handle<String> input =
+      Factory::NewStringFromAscii(CStrVector("aBcAbCABCxYzab"));
+  Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
+  Address start_adr = seq_input->GetCharsAddress();
+
+  int output[4];
+  RegExpMacroAssemblerIA32::Result result =
+      ExecuteIA32(*code,
+                  *input,
+                  0,
+                  start_adr,
+                  start_adr + input->length(),
+                  output,
+                  true);
+
+  CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
+  CHECK_EQ(0, output[0]);
+  CHECK_EQ(12, output[1]);
+  CHECK_EQ(0, output[2]);
+  CHECK_EQ(3, output[3]);
+}
+
+
+
+TEST(MacroAssemblerIA32Registers) {
+  v8::V8::Initialize();
+  ContextInitializer initializer;
+
+  RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 5);
+
+  uc16 foo_chars[3] = {'f', 'o', 'o'};
+  Vector<const uc16> foo(foo_chars, 3);
+
+  enum registers { out1, out2, out3, out4, out5, sp, loop_cnt };
+  Label fail;
+  Label backtrack;
+  m.WriteCurrentPositionToRegister(out1, 0);  // Output: [0]
+  m.PushRegister(out1, RegExpMacroAssembler::kNoStackLimitCheck);
+  m.PushBacktrack(&backtrack);
+  m.WriteStackPointerToRegister(sp);
+  // Fill stack and registers
+  m.AdvanceCurrentPosition(2);
+  m.WriteCurrentPositionToRegister(out1, 0);
+  m.PushRegister(out1, RegExpMacroAssembler::kNoStackLimitCheck);
+  m.PushBacktrack(&fail);
+  // Drop backtrack stack frames.
+  m.ReadStackPointerFromRegister(sp);
+  // And take the first backtrack (to &backtrack)
+  m.Backtrack();
+
+  m.PushCurrentPosition();
+  m.AdvanceCurrentPosition(2);
+  m.PopCurrentPosition();
+
+  m.Bind(&backtrack);
+  m.PopRegister(out1);
+  m.ReadCurrentPositionFromRegister(out1);
+  m.AdvanceCurrentPosition(3);
+  m.WriteCurrentPositionToRegister(out2, 0);  // [0,3]
+
+  Label loop;
+  m.SetRegister(loop_cnt, 0);  // loop counter
+  m.Bind(&loop);
+  m.AdvanceRegister(loop_cnt, 1);
+  m.AdvanceCurrentPosition(1);
+  m.IfRegisterLT(loop_cnt, 3, &loop);
+  m.WriteCurrentPositionToRegister(out3, 0);  // [0,3,6]
+
+  Label loop2;
+  m.SetRegister(loop_cnt, 2);  // loop counter
+  m.Bind(&loop2);
+  m.AdvanceRegister(loop_cnt, -1);
+  m.AdvanceCurrentPosition(1);
+  m.IfRegisterGE(loop_cnt, 0, &loop2);
+  m.WriteCurrentPositionToRegister(out4, 0);  // [0,3,6,9]
+
+  Label loop3;
+  Label exit_loop3;
+  m.PushRegister(out4, RegExpMacroAssembler::kNoStackLimitCheck);
+  m.PushRegister(out4, RegExpMacroAssembler::kNoStackLimitCheck);
+  m.ReadCurrentPositionFromRegister(out3);
+  m.Bind(&loop3);
+  m.AdvanceCurrentPosition(1);
+  m.CheckGreedyLoop(&exit_loop3);
+  m.GoTo(&loop3);
+  m.Bind(&exit_loop3);
+  m.PopCurrentPosition();
+  m.WriteCurrentPositionToRegister(out5, 0);  // [0,3,6,9,9]
+
+  m.Succeed();
+
+  m.Bind(&fail);
+  m.Fail();
+
+  Handle<String> source =
+      Factory::NewStringFromAscii(CStrVector("<loop test>"));
+  Handle<Object> code_object = m.GetCode(source);
+  Handle<Code> code = Handle<Code>::cast(code_object);
+
+  // String long enough for test (content doesn't matter).
+  Handle<String> input =
+      Factory::NewStringFromAscii(CStrVector("foofoofoofoofoo"));
+  Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
+  Address start_adr = seq_input->GetCharsAddress();
+
+  int output[5];
+  RegExpMacroAssemblerIA32::Result result =
+      ExecuteIA32(*code,
+                  *input,
+                  0,
+                  start_adr,
+                  start_adr + input->length(),
+                  output,
+                  true);
+
+  CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
+  CHECK_EQ(0, output[0]);
+  CHECK_EQ(3, output[1]);
+  CHECK_EQ(6, output[2]);
+  CHECK_EQ(9, output[3]);
+  CHECK_EQ(9, output[4]);
+}
+
+
+TEST(MacroAssemblerIA32StackOverflow) {
+  v8::V8::Initialize();
+  ContextInitializer initializer;
+
+  RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 0);
+
+  Label loop;
+  m.Bind(&loop);
+  m.PushBacktrack(&loop);
+  m.GoTo(&loop);
+
+  Handle<String> source =
+      Factory::NewStringFromAscii(CStrVector("<stack overflow test>"));
+  Handle<Object> code_object = m.GetCode(source);
+  Handle<Code> code = Handle<Code>::cast(code_object);
+
+  // String long enough for test (content doesn't matter).
+  Handle<String> input =
+      Factory::NewStringFromAscii(CStrVector("dummy"));
+  Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
+  Address start_adr = seq_input->GetCharsAddress();
+
+  RegExpMacroAssemblerIA32::Result result =
+      ExecuteIA32(*code,
+                  *input,
+                  0,
+                  start_adr,
+                  start_adr + input->length(),
+                  NULL,
+                  true);
+
+  CHECK_EQ(RegExpMacroAssemblerIA32::EXCEPTION, result);
+  CHECK(Top::has_pending_exception());
+  Top::clear_pending_exception();
+}
+
+
+TEST(MacroAssemblerIA32LotsOfRegisters) {
+  v8::V8::Initialize();
+  ContextInitializer initializer;
+
+  RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 2);
+
+  // At least 2048, to ensure the allocated space for registers
+  // span one full page.
+  const int large_number = 8000;
+  m.WriteCurrentPositionToRegister(large_number, 42);
+  m.WriteCurrentPositionToRegister(0, 0);
+  m.WriteCurrentPositionToRegister(1, 1);
+  Label done;
+  m.CheckNotBackReference(0, &done);  // Performs a system-stack push.
+  m.Bind(&done);
+  m.PushRegister(large_number, RegExpMacroAssembler::kNoStackLimitCheck);
+  m.PopRegister(1);
+  m.Succeed();
+
+  Handle<String> source =
+      Factory::NewStringFromAscii(CStrVector("<huge register space test>"));
+  Handle<Object> code_object = m.GetCode(source);
+  Handle<Code> code = Handle<Code>::cast(code_object);
+
+  // String long enough for test (content doesn't matter).
+  Handle<String> input =
+      Factory::NewStringFromAscii(CStrVector("sample text"));
+  Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
+  Address start_adr = seq_input->GetCharsAddress();
+
+  int captures[2];
+  RegExpMacroAssemblerIA32::Result result =
+      ExecuteIA32(*code,
+                  *input,
+                  0,
+                  start_adr,
+                  start_adr + input->length(),
+                  captures,
+                  true);
+
+  CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
+  CHECK_EQ(0, captures[0]);
+  CHECK_EQ(42, captures[1]);
+
+  Top::clear_pending_exception();
+}
+
+
+
+#endif  // !defined ARM
+
+TEST(AddInverseToTable) {
+  static const int kLimit = 1000;
+  static const int kRangeCount = 16;
+  for (int t = 0; t < 10; t++) {
+    ZoneScope zone_scope(DELETE_ON_EXIT);
+    ZoneList<CharacterRange>* ranges =
+        new ZoneList<CharacterRange>(kRangeCount);
+    for (int i = 0; i < kRangeCount; i++) {
+      int from = PseudoRandom(t + 87, i + 25) % kLimit;
+      int to = from + (PseudoRandom(i + 87, t + 25) % (kLimit / 20));
+      if (to > kLimit) to = kLimit;
+      ranges->Add(CharacterRange(from, to));
+    }
+    DispatchTable table;
+    DispatchTableConstructor cons(&table, false);
+    cons.set_choice_index(0);
+    cons.AddInverse(ranges);
+    for (int i = 0; i < kLimit; i++) {
+      bool is_on = false;
+      for (int j = 0; !is_on && j < kRangeCount; j++)
+        is_on = ranges->at(j).Contains(i);
+      OutSet* set = table.Get(i);
+      CHECK_EQ(is_on, set->Get(0) == false);
+    }
+  }
+  ZoneScope zone_scope(DELETE_ON_EXIT);
+  ZoneList<CharacterRange>* ranges =
+          new ZoneList<CharacterRange>(1);
+  ranges->Add(CharacterRange(0xFFF0, 0xFFFE));
+  DispatchTable table;
+  DispatchTableConstructor cons(&table, false);
+  cons.set_choice_index(0);
+  cons.AddInverse(ranges);
+  CHECK(!table.Get(0xFFFE)->Get(0));
+  CHECK(table.Get(0xFFFF)->Get(0));
+}
+
+
+static uc32 canonicalize(uc32 c) {
+  unibrow::uchar canon[unibrow::Ecma262Canonicalize::kMaxWidth];
+  int count = unibrow::Ecma262Canonicalize::Convert(c, '\0', canon, NULL);
+  if (count == 0) {
+    return c;
+  } else {
+    CHECK_EQ(1, count);
+    return canon[0];
+  }
+}
+
+
+TEST(LatinCanonicalize) {
+  unibrow::Mapping<unibrow::Ecma262UnCanonicalize> un_canonicalize;
+  for (char lower = 'a'; lower <= 'z'; lower++) {
+    char upper = lower + ('A' - 'a');
+    CHECK_EQ(canonicalize(lower), canonicalize(upper));
+    unibrow::uchar uncanon[unibrow::Ecma262UnCanonicalize::kMaxWidth];
+    int length = un_canonicalize.get(lower, '\0', uncanon);
+    CHECK_EQ(2, length);
+    CHECK_EQ(upper, uncanon[0]);
+    CHECK_EQ(lower, uncanon[1]);
+  }
+  for (uc32 c = 128; c < (1 << 21); c++)
+    CHECK_GE(canonicalize(c), 128);
+  unibrow::Mapping<unibrow::ToUppercase> to_upper;
+  for (uc32 c = 0; c < (1 << 21); c++) {
+    unibrow::uchar upper[unibrow::ToUppercase::kMaxWidth];
+    int length = to_upper.get(c, '\0', upper);
+    if (length == 0) {
+      length = 1;
+      upper[0] = c;
+    }
+    uc32 u = upper[0];
+    if (length > 1 || (c >= 128 && u < 128))
+      u = c;
+    CHECK_EQ(u, canonicalize(c));
+  }
+}
+
+
+static uc32 CanonRange(uc32 c) {
+  unibrow::uchar canon[unibrow::CanonicalizationRange::kMaxWidth];
+  int count = unibrow::CanonicalizationRange::Convert(c, '\0', canon, NULL);
+  if (count == 0) {
+    return c;
+  } else {
+    CHECK_EQ(1, count);
+    return canon[0];
+  }
+}
+
+
+TEST(RangeCanonicalization) {
+  CHECK_NE(CanonRange(0) & CharacterRange::kStartMarker, 0);
+  // Check that we arrive at the same result when using the basic
+  // range canonicalization primitives as when using immediate
+  // canonicalization.
+  unibrow::Mapping<unibrow::Ecma262UnCanonicalize> un_canonicalize;
+  for (int i = 0; i < CharacterRange::kRangeCanonicalizeMax; i++) {
+    int range = CanonRange(i);
+    int indirect_length = 0;
+    unibrow::uchar indirect[unibrow::Ecma262UnCanonicalize::kMaxWidth];
+    if ((range & CharacterRange::kStartMarker) == 0) {
+      indirect_length = un_canonicalize.get(i - range, '\0', indirect);
+      for (int i = 0; i < indirect_length; i++)
+        indirect[i] += range;
+    } else {
+      indirect_length = un_canonicalize.get(i, '\0', indirect);
+    }
+    unibrow::uchar direct[unibrow::Ecma262UnCanonicalize::kMaxWidth];
+    int direct_length = un_canonicalize.get(i, '\0', direct);
+    CHECK_EQ(direct_length, indirect_length);
+  }
+  // Check that we arrive at the same results when skipping over
+  // canonicalization ranges.
+  int next_block = 0;
+  while (next_block < CharacterRange::kRangeCanonicalizeMax) {
+    uc32 start = CanonRange(next_block);
+    CHECK_NE((start & CharacterRange::kStartMarker), 0);
+    unsigned dist = start & CharacterRange::kPayloadMask;
+    unibrow::uchar first[unibrow::Ecma262UnCanonicalize::kMaxWidth];
+    int first_length = un_canonicalize.get(next_block, '\0', first);
+    for (unsigned i = 1; i < dist; i++) {
+      CHECK_EQ(i, CanonRange(next_block + i));
+      unibrow::uchar succ[unibrow::Ecma262UnCanonicalize::kMaxWidth];
+      int succ_length = un_canonicalize.get(next_block + i, '\0', succ);
+      CHECK_EQ(first_length, succ_length);
+      for (int j = 0; j < succ_length; j++) {
+        int calc = first[j] + i;
+        int found = succ[j];
+        CHECK_EQ(calc, found);
+      }
+    }
+    next_block = next_block + dist;
+  }
+}
+
+
+TEST(UncanonicalizeEquivalence) {
+  unibrow::Mapping<unibrow::Ecma262UnCanonicalize> un_canonicalize;
+  unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
+  for (int i = 0; i < (1 << 16); i++) {
+    int length = un_canonicalize.get(i, '\0', chars);
+    for (int j = 0; j < length; j++) {
+      unibrow::uchar chars2[unibrow::Ecma262UnCanonicalize::kMaxWidth];
+      int length2 = un_canonicalize.get(chars[j], '\0', chars2);
+      CHECK_EQ(length, length2);
+      for (int k = 0; k < length; k++)
+        CHECK_EQ(static_cast<int>(chars[k]), static_cast<int>(chars2[k]));
+    }
+  }
+}
+
+
+static void TestRangeCaseIndependence(CharacterRange input,
+                                      Vector<CharacterRange> expected) {
+  ZoneScope zone_scope(DELETE_ON_EXIT);
+  int count = expected.length();
+  ZoneList<CharacterRange>* list = new ZoneList<CharacterRange>(count);
+  input.AddCaseEquivalents(list);
+  CHECK_EQ(count, list->length());
+  for (int i = 0; i < list->length(); i++) {
+    CHECK_EQ(expected[i].from(), list->at(i).from());
+    CHECK_EQ(expected[i].to(), list->at(i).to());
+  }
+}
+
+
+static void TestSimpleRangeCaseIndependence(CharacterRange input,
+                                            CharacterRange expected) {
+  EmbeddedVector<CharacterRange, 1> vector;
+  vector[0] = expected;
+  TestRangeCaseIndependence(input, vector);
+}
+
+
+TEST(CharacterRangeCaseIndependence) {
+  TestSimpleRangeCaseIndependence(CharacterRange::Singleton('a'),
+                                  CharacterRange::Singleton('A'));
+  TestSimpleRangeCaseIndependence(CharacterRange::Singleton('z'),
+                                  CharacterRange::Singleton('Z'));
+  TestSimpleRangeCaseIndependence(CharacterRange('a', 'z'),
+                                  CharacterRange('A', 'Z'));
+  TestSimpleRangeCaseIndependence(CharacterRange('c', 'f'),
+                                  CharacterRange('C', 'F'));
+  TestSimpleRangeCaseIndependence(CharacterRange('a', 'b'),
+                                  CharacterRange('A', 'B'));
+  TestSimpleRangeCaseIndependence(CharacterRange('y', 'z'),
+                                  CharacterRange('Y', 'Z'));
+  TestSimpleRangeCaseIndependence(CharacterRange('a' - 1, 'z' + 1),
+                                  CharacterRange('A', 'Z'));
+  TestSimpleRangeCaseIndependence(CharacterRange('A', 'Z'),
+                                  CharacterRange('a', 'z'));
+  TestSimpleRangeCaseIndependence(CharacterRange('C', 'F'),
+                                  CharacterRange('c', 'f'));
+  TestSimpleRangeCaseIndependence(CharacterRange('A' - 1, 'Z' + 1),
+                                  CharacterRange('a', 'z'));
+  // Here we need to add [l-z] to complete the case independence of
+  // [A-Za-z] but we expect [a-z] to be added since we always add a
+  // whole block at a time.
+  TestSimpleRangeCaseIndependence(CharacterRange('A', 'k'),
+                                  CharacterRange('a', 'z'));
+}
+
+
+static bool InClass(uc16 c, ZoneList<CharacterRange>* ranges) {
+  if (ranges == NULL)
+    return false;
+  for (int i = 0; i < ranges->length(); i++) {
+    CharacterRange range = ranges->at(i);
+    if (range.from() <= c && c <= range.to())
+      return true;
+  }
+  return false;
+}
+
+
+TEST(CharClassDifference) {
+  ZoneScope zone_scope(DELETE_ON_EXIT);
+  ZoneList<CharacterRange>* base = new ZoneList<CharacterRange>(1);
+  base->Add(CharacterRange::Everything());
+  Vector<const uc16> overlay = CharacterRange::GetWordBounds();
+  ZoneList<CharacterRange>* included = NULL;
+  ZoneList<CharacterRange>* excluded = NULL;
+  CharacterRange::Split(base, overlay, &included, &excluded);
+  for (int i = 0; i < (1 << 16); i++) {
+    bool in_base = InClass(i, base);
+    if (in_base) {
+      bool in_overlay = false;
+      for (int j = 0; !in_overlay && j < overlay.length(); j += 2) {
+        if (overlay[j] <= i && i <= overlay[j+1])
+          in_overlay = true;
+      }
+      CHECK_EQ(in_overlay, InClass(i, included));
+      CHECK_EQ(!in_overlay, InClass(i, excluded));
+    } else {
+      CHECK(!InClass(i, included));
+      CHECK(!InClass(i, excluded));
+    }
+  }
+}
+
+
+TEST(Graph) {
+  V8::Initialize(NULL);
+  Execute("(?:(?:x(.))?\1)+$", false, true, true);
+}
diff --git a/deps/v8/test/cctest/test-serialize.cc b/deps/v8/test/cctest/test-serialize.cc
new file mode 100644
index 0000000..56727dc
--- /dev/null
+++ b/deps/v8/test/cctest/test-serialize.cc
@@ -0,0 +1,268 @@
+// 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.
+
+#include <signal.h>
+#include <map>
+#include <string>
+
+#include "sys/stat.h"
+#include "v8.h"
+
+#include "debug.h"
+#include "ic-inl.h"
+#include "runtime.h"
+#include "serialize.h"
+#include "scopeinfo.h"
+#include "snapshot.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+static int local_counters[256];
+static int counter_count = 0;
+static std::map<std::string, int> counter_table;
+
+
+// Callback receiver to track counters in test.
+static int* counter_function(const char* name) {
+  std::string counter(name);
+  if (counter_table.find(counter) == counter_table.end()) {
+    local_counters[counter_count] = 0;
+    counter_table[counter] = counter_count++;
+  }
+
+  return &local_counters[counter_table[counter]];
+}
+
+
+template <class T>
+static Address AddressOf(T id) {
+  return ExternalReference(id).address();
+}
+
+
+template <class T>
+static uint32_t Encode(const ExternalReferenceEncoder& encoder, T id) {
+  return encoder.Encode(AddressOf(id));
+}
+
+
+static int make_code(TypeCode type, int id) {
+  return static_cast<uint32_t>(type) << kReferenceTypeShift | id;
+}
+
+
+static int register_code(int reg) {
+  return Debug::k_register_address << kDebugIdShift | reg;
+}
+
+
+TEST(ExternalReferenceEncoder) {
+  StatsTable::SetCounterFunction(counter_function);
+  Heap::Setup(false);
+  ExternalReferenceEncoder encoder;
+  CHECK_EQ(make_code(BUILTIN, Builtins::ArrayCode),
+           Encode(encoder, Builtins::ArrayCode));
+  CHECK_EQ(make_code(RUNTIME_FUNCTION, Runtime::kAbort),
+           Encode(encoder, Runtime::kAbort));
+  CHECK_EQ(make_code(IC_UTILITY, IC::kLoadCallbackProperty),
+           Encode(encoder, IC_Utility(IC::kLoadCallbackProperty)));
+  CHECK_EQ(make_code(DEBUG_ADDRESS, register_code(3)),
+           Encode(encoder, Debug_Address(Debug::k_register_address, 3)));
+  ExternalReference keyed_load_function_prototype =
+      ExternalReference(&Counters::keyed_load_function_prototype);
+  CHECK_EQ(make_code(STATS_COUNTER, Counters::k_keyed_load_function_prototype),
+           encoder.Encode(keyed_load_function_prototype.address()));
+  ExternalReference passed_function =
+      ExternalReference::builtin_passed_function();
+  CHECK_EQ(make_code(UNCLASSIFIED, 1),
+           encoder.Encode(passed_function.address()));
+  ExternalReference the_hole_value_location =
+      ExternalReference::the_hole_value_location();
+  CHECK_EQ(make_code(UNCLASSIFIED, 2),
+           encoder.Encode(the_hole_value_location.address()));
+  ExternalReference stack_guard_limit_address =
+      ExternalReference::address_of_stack_guard_limit();
+  CHECK_EQ(make_code(UNCLASSIFIED, 3),
+           encoder.Encode(stack_guard_limit_address.address()));
+  CHECK_EQ(make_code(UNCLASSIFIED, 5),
+           encoder.Encode(ExternalReference::debug_break().address()));
+  CHECK_EQ(make_code(UNCLASSIFIED, 6),
+           encoder.Encode(ExternalReference::new_space_start().address()));
+}
+
+
+TEST(ExternalReferenceDecoder) {
+  StatsTable::SetCounterFunction(counter_function);
+  Heap::Setup(false);
+  ExternalReferenceDecoder decoder;
+  CHECK_EQ(AddressOf(Builtins::ArrayCode),
+           decoder.Decode(make_code(BUILTIN, Builtins::ArrayCode)));
+  CHECK_EQ(AddressOf(Runtime::kAbort),
+           decoder.Decode(make_code(RUNTIME_FUNCTION, Runtime::kAbort)));
+  CHECK_EQ(AddressOf(IC_Utility(IC::kLoadCallbackProperty)),
+           decoder.Decode(make_code(IC_UTILITY, IC::kLoadCallbackProperty)));
+  CHECK_EQ(AddressOf(Debug_Address(Debug::k_register_address, 3)),
+           decoder.Decode(make_code(DEBUG_ADDRESS, register_code(3))));
+  ExternalReference keyed_load_function =
+      ExternalReference(&Counters::keyed_load_function_prototype);
+  CHECK_EQ(keyed_load_function.address(),
+           decoder.Decode(
+               make_code(STATS_COUNTER,
+                         Counters::k_keyed_load_function_prototype)));
+  CHECK_EQ(ExternalReference::builtin_passed_function().address(),
+           decoder.Decode(make_code(UNCLASSIFIED, 1)));
+  CHECK_EQ(ExternalReference::the_hole_value_location().address(),
+           decoder.Decode(make_code(UNCLASSIFIED, 2)));
+  CHECK_EQ(ExternalReference::address_of_stack_guard_limit().address(),
+           decoder.Decode(make_code(UNCLASSIFIED, 3)));
+  CHECK_EQ(ExternalReference::debug_break().address(),
+           decoder.Decode(make_code(UNCLASSIFIED, 5)));
+  CHECK_EQ(ExternalReference::new_space_start().address(),
+           decoder.Decode(make_code(UNCLASSIFIED, 6)));
+}
+
+
+static void Serialize() {
+#ifdef DEBUG
+  FLAG_debug_serialization = true;
+#endif
+  StatsTable::SetCounterFunction(counter_function);
+
+  v8::HandleScope scope;
+  const int kExtensionCount = 1;
+  const char* extension_list[kExtensionCount] = { "v8/gc" };
+  v8::ExtensionConfiguration extensions(kExtensionCount, extension_list);
+  Serializer::Enable();
+  v8::Persistent<v8::Context> env = v8::Context::New(&extensions);
+  env->Enter();
+
+  Snapshot::WriteToFile(FLAG_testing_serialization_file);
+}
+
+
+// Test that the whole heap can be serialized when running from the
+// internal snapshot.
+// (Smoke test.)
+TEST(SerializeInternal) {
+  Snapshot::Initialize(NULL);
+  Serialize();
+}
+
+
+// Test that the whole heap can be serialized when running from a
+// bootstrapped heap.
+// (Smoke test.)
+TEST(Serialize) {
+  if (Snapshot::IsEnabled()) return;
+  Serialize();
+}
+
+
+// Test that the heap isn't destroyed after a serialization.
+TEST(SerializeNondestructive) {
+  if (Snapshot::IsEnabled()) return;
+  StatsTable::SetCounterFunction(counter_function);
+  v8::HandleScope scope;
+  Serializer::Enable();
+  v8::Persistent<v8::Context> env = v8::Context::New();
+  v8::Context::Scope context_scope(env);
+  Serializer().Serialize();
+  const char* c_source = "\"abcd\".charAt(2) == 'c'";
+  v8::Local<v8::String> source = v8::String::New(c_source);
+  v8::Local<v8::Script> script = v8::Script::Compile(source);
+  v8::Local<v8::Value> value = script->Run();
+  CHECK(value->BooleanValue());
+}
+
+//----------------------------------------------------------------------------
+// Tests that the heap can be deserialized.
+
+static void Deserialize() {
+#ifdef DEBUG
+  FLAG_debug_serialization = true;
+#endif
+  CHECK(Snapshot::Initialize(FLAG_testing_serialization_file));
+}
+
+
+static void SanityCheck() {
+  v8::HandleScope scope;
+#ifdef DEBUG
+  Heap::Verify();
+#endif
+  CHECK(Top::global()->IsJSObject());
+  CHECK(Top::global_context()->IsContext());
+  CHECK(Top::special_function_table()->IsFixedArray());
+  CHECK(Heap::symbol_table()->IsSymbolTable());
+  CHECK(!Factory::LookupAsciiSymbol("Empty")->IsFailure());
+}
+
+
+DEPENDENT_TEST(Deserialize, Serialize) {
+  v8::HandleScope scope;
+
+  Deserialize();
+
+  SanityCheck();
+}
+
+DEPENDENT_TEST(DeserializeAndRunScript, Serialize) {
+  v8::HandleScope scope;
+
+  Deserialize();
+
+  const char* c_source = "\"1234\".length";
+  v8::Local<v8::String> source = v8::String::New(c_source);
+  v8::Local<v8::Script> script = v8::Script::Compile(source);
+  CHECK_EQ(4, script->Run()->Int32Value());
+}
+
+
+DEPENDENT_TEST(DeserializeNatives, Serialize) {
+  v8::HandleScope scope;
+
+  Deserialize();
+
+  const char* c_source = "\"abcd\".charAt(2) == 'c'";
+  v8::Local<v8::String> source = v8::String::New(c_source);
+  v8::Local<v8::Script> script = v8::Script::Compile(source);
+  v8::Local<v8::Value> value = script->Run();
+  CHECK(value->BooleanValue());
+}
+
+
+DEPENDENT_TEST(DeserializeExtensions, Serialize) {
+  v8::HandleScope scope;
+
+  Deserialize();
+  const char* c_source = "gc();";
+  v8::Local<v8::String> source = v8::String::New(c_source);
+  v8::Local<v8::Script> script = v8::Script::Compile(source);
+  v8::Local<v8::Value> value = script->Run();
+  CHECK(value->IsUndefined());
+}
diff --git a/deps/v8/test/cctest/test-sockets.cc b/deps/v8/test/cctest/test-sockets.cc
new file mode 100644
index 0000000..a4b2285
--- /dev/null
+++ b/deps/v8/test/cctest/test-sockets.cc
@@ -0,0 +1,161 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+
+#include "v8.h"
+#include "platform.h"
+#include "cctest.h"
+
+
+using namespace ::v8::internal;
+
+
+class SocketListenerThread : public Thread {
+ public:
+  explicit SocketListenerThread(int port, int data_size)
+      : port_(port), data_size_(data_size), server_(NULL), client_(NULL),
+        listening_(OS::CreateSemaphore(0)) {
+    data_ = new char[data_size_];
+  }
+  ~SocketListenerThread() {
+    // Close both sockets.
+    delete client_;
+    delete server_;
+    delete listening_;
+    delete[] data_;
+  }
+
+  void Run();
+  void WaitForListening() { listening_->Wait(); }
+  char* data() { return data_; }
+
+ private:
+  int port_;
+  char* data_;
+  int data_size_;
+  Socket* server_;  // Server socket used for bind/accept.
+  Socket* client_;  // Single client connection used by the test.
+  Semaphore* listening_;  // Signalled when the server socket is in listen mode.
+};
+
+
+void SocketListenerThread::Run() {
+  bool ok;
+
+  // Create the server socket and bind it to the requested port.
+  server_ = OS::CreateSocket();
+  CHECK(server_ != NULL);
+  ok = server_->Bind(port_);
+  CHECK(ok);
+
+  // Listen for new connections.
+  ok = server_->Listen(1);
+  CHECK(ok);
+  listening_->Signal();
+
+  // Accept a connection.
+  client_ = server_->Accept();
+  CHECK(client_ != NULL);
+
+  // Read the expected niumber of bytes of data.
+  int bytes_read = 0;
+  while (bytes_read < data_size_) {
+    bytes_read += client_->Receive(data_ + bytes_read, data_size_ - bytes_read);
+  }
+}
+
+
+static bool SendAll(Socket* socket, const char* data, int len) {
+  int sent_len = 0;
+  while (sent_len < len) {
+    int status = socket->Send(data, len);
+    if (status <= 0) {
+      return false;
+    }
+    sent_len += status;
+  }
+  return true;
+}
+
+
+static void SendAndReceive(int port, char *data, int len) {
+  static const char* kLocalhost = "localhost";
+
+  bool ok;
+
+  // Make a string with the port number.
+  const int kPortBuferLen = 6;
+  char port_str[kPortBuferLen];
+  OS::SNPrintF(Vector<char>(port_str, kPortBuferLen), "%d", port);
+
+  // Create a socket listener.
+  SocketListenerThread* listener = new SocketListenerThread(port, len);
+  listener->Start();
+  listener->WaitForListening();
+
+  // Connect and write some data.
+  Socket* client = OS::CreateSocket();
+  CHECK(client != NULL);
+  ok = client->Connect(kLocalhost, port_str);
+  CHECK(ok);
+
+  // Send all the data.
+  ok = SendAll(client, data, len);
+  CHECK(ok);
+
+  // Wait until data is received.
+  listener->Join();
+
+  // Check that data received is the same as data send.
+  for (int i = 0; i < len; i++) {
+    CHECK(data[i] == listener->data()[i]);
+  }
+
+  // Close the client before the listener to avoid TIME_WAIT issues.
+  client->Shutdown();
+  delete client;
+  delete listener;
+}
+
+
+TEST(Socket) {
+  // Make sure this port is not used by other tests to allow tests to run in
+  // parallel.
+  static const int kPort = 5859;
+
+  bool ok;
+
+  // Initialize socket support.
+  ok = Socket::Setup();
+  CHECK(ok);
+
+  // Send and receive some data.
+  static const int kBufferSizeSmall = 20;
+  char small_data[kBufferSizeSmall + 1] = "1234567890abcdefghij";
+  SendAndReceive(kPort, small_data, kBufferSizeSmall);
+
+  // Send and receive some more data.
+  static const int kBufferSizeMedium = 10000;
+  char* medium_data = new char[kBufferSizeMedium];
+  for (int i = 0; i < kBufferSizeMedium; i++) {
+    medium_data[i] = i % 256;
+  }
+  SendAndReceive(kPort, medium_data, kBufferSizeMedium);
+  delete[] medium_data;
+
+  // Send and receive even more data.
+  static const int kBufferSizeLarge = 1000000;
+  char* large_data = new char[kBufferSizeLarge];
+  for (int i = 0; i < kBufferSizeLarge; i++) {
+    large_data[i] = i % 256;
+  }
+  SendAndReceive(kPort, large_data, kBufferSizeLarge);
+  delete[] large_data;
+}
+
+
+TEST(HToNNToH) {
+  uint16_t x = 1234;
+  CHECK_EQ(x, Socket::NToH(Socket::HToN(x)));
+
+  uint32_t y = 12345678;
+  CHECK(y == Socket::NToH(Socket::HToN(y)));
+}
diff --git a/deps/v8/test/cctest/test-spaces.cc b/deps/v8/test/cctest/test-spaces.cc
new file mode 100644
index 0000000..d946a7f
--- /dev/null
+++ b/deps/v8/test/cctest/test-spaces.cc
@@ -0,0 +1,248 @@
+// 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.
+
+#include <stdlib.h>
+
+#include "v8.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+static void VerifyRSet(Address page_start) {
+#ifdef DEBUG
+  Page::set_rset_state(Page::IN_USE);
+#endif
+
+  Page* p = Page::FromAddress(page_start);
+
+  p->ClearRSet();
+
+  for (Address addr = p->ObjectAreaStart();
+       addr < p->ObjectAreaEnd();
+       addr += kPointerSize) {
+    CHECK(!Page::IsRSetSet(addr, 0));
+  }
+
+  for (Address addr = p->ObjectAreaStart();
+       addr < p->ObjectAreaEnd();
+       addr += kPointerSize) {
+    Page::SetRSet(addr, 0);
+  }
+
+  for (Address addr = p->ObjectAreaStart();
+       addr < p->ObjectAreaEnd();
+       addr += kPointerSize) {
+    CHECK(Page::IsRSetSet(addr, 0));
+  }
+}
+
+
+TEST(Page) {
+#ifdef DEBUG
+  Page::set_rset_state(Page::NOT_IN_USE);
+#endif
+
+  byte* mem = NewArray<byte>(2*Page::kPageSize);
+  CHECK(mem != NULL);
+
+  Address start = reinterpret_cast<Address>(mem);
+  Address page_start = RoundUp(start, Page::kPageSize);
+
+  Page* p = Page::FromAddress(page_start);
+  CHECK(p->address() == page_start);
+  CHECK(p->is_valid());
+
+  p->opaque_header = 0;
+  p->is_normal_page = 0x1;
+  CHECK(!p->next_page()->is_valid());
+
+  CHECK(p->ObjectAreaStart() == page_start + Page::kObjectStartOffset);
+  CHECK(p->ObjectAreaEnd() == page_start + Page::kPageSize);
+
+  CHECK(p->Offset(page_start + Page::kObjectStartOffset) ==
+        Page::kObjectStartOffset);
+  CHECK(p->Offset(page_start + Page::kPageSize) == Page::kPageSize);
+
+  CHECK(p->OffsetToAddress(Page::kObjectStartOffset) == p->ObjectAreaStart());
+  CHECK(p->OffsetToAddress(Page::kPageSize) == p->ObjectAreaEnd());
+
+  // test remember set
+  VerifyRSet(page_start);
+
+  DeleteArray(mem);
+}
+
+
+TEST(MemoryAllocator) {
+  CHECK(Heap::ConfigureHeapDefault());
+  CHECK(MemoryAllocator::Setup(Heap::MaxCapacity()));
+
+  OldSpace faked_space(Heap::MaxCapacity(), OLD_POINTER_SPACE, NOT_EXECUTABLE);
+  int total_pages = 0;
+  int requested = 2;
+  int allocated;
+  // If we request two pages, we should get one or two.
+  Page* first_page =
+      MemoryAllocator::AllocatePages(requested, &allocated, &faked_space);
+  CHECK(first_page->is_valid());
+  CHECK(allocated > 0 && allocated <= 2);
+  total_pages += allocated;
+
+  Page* last_page = first_page;
+  for (Page* p = first_page; p->is_valid(); p = p->next_page()) {
+    CHECK(MemoryAllocator::IsPageInSpace(p, &faked_space));
+    last_page = p;
+  }
+
+  // Again, we should get one or two pages.
+  Page* others =
+      MemoryAllocator::AllocatePages(requested, &allocated, &faked_space);
+  CHECK(others->is_valid());
+  CHECK(allocated > 0 && allocated <= 2);
+  total_pages += allocated;
+
+  MemoryAllocator::SetNextPage(last_page, others);
+  int page_count = 0;
+  for (Page* p = first_page; p->is_valid(); p = p->next_page()) {
+    CHECK(MemoryAllocator::IsPageInSpace(p, &faked_space));
+    page_count++;
+  }
+  CHECK(total_pages == page_count);
+
+  Page* second_page = first_page->next_page();
+  CHECK(second_page->is_valid());
+
+  // Freeing pages at the first chunk starting at or after the second page
+  // should free the entire second chunk.  It will return the last page in the
+  // first chunk (if the second page was in the first chunk) or else an
+  // invalid page (if the second page was the start of the second chunk).
+  Page* free_return = MemoryAllocator::FreePages(second_page);
+  CHECK(free_return == last_page || !free_return->is_valid());
+  MemoryAllocator::SetNextPage(first_page, free_return);
+
+  // Freeing pages in the first chunk starting at the first page should free
+  // the first chunk and return an invalid page.
+  Page* invalid_page = MemoryAllocator::FreePages(first_page);
+  CHECK(!invalid_page->is_valid());
+
+  MemoryAllocator::TearDown();
+}
+
+
+TEST(NewSpace) {
+  CHECK(Heap::ConfigureHeapDefault());
+  CHECK(MemoryAllocator::Setup(Heap::MaxCapacity()));
+
+  NewSpace new_space;
+
+  void* chunk =
+      MemoryAllocator::ReserveInitialChunk(2 * Heap::YoungGenerationSize());
+  CHECK(chunk != NULL);
+  Address start = RoundUp(static_cast<Address>(chunk),
+                          Heap::YoungGenerationSize());
+  CHECK(new_space.Setup(start, Heap::YoungGenerationSize()));
+  CHECK(new_space.HasBeenSetup());
+
+  while (new_space.Available() >= Page::kMaxHeapObjectSize) {
+    Object* obj = new_space.AllocateRaw(Page::kMaxHeapObjectSize);
+    CHECK(!obj->IsFailure());
+    CHECK(new_space.Contains(HeapObject::cast(obj)));
+  }
+
+  new_space.TearDown();
+  MemoryAllocator::TearDown();
+}
+
+
+TEST(OldSpace) {
+  CHECK(Heap::ConfigureHeapDefault());
+  CHECK(MemoryAllocator::Setup(Heap::MaxCapacity()));
+
+  OldSpace* s = new OldSpace(Heap::OldGenerationSize(),
+                             OLD_POINTER_SPACE,
+                             NOT_EXECUTABLE);
+  CHECK(s != NULL);
+
+  void* chunk =
+      MemoryAllocator::ReserveInitialChunk(2 * Heap::YoungGenerationSize());
+  CHECK(chunk != NULL);
+  Address start = static_cast<Address>(chunk);
+  size_t size = RoundUp(start, Heap::YoungGenerationSize()) - start;
+
+  CHECK(s->Setup(start, size));
+
+  while (s->Available() > 0) {
+    Object* obj = s->AllocateRaw(Page::kMaxHeapObjectSize);
+    CHECK(!obj->IsFailure());
+  }
+
+  s->TearDown();
+  delete s;
+  MemoryAllocator::TearDown();
+}
+
+
+TEST(LargeObjectSpace) {
+  CHECK(Heap::Setup(false));
+
+  LargeObjectSpace* lo = Heap::lo_space();
+  CHECK(lo != NULL);
+
+  Map* faked_map = reinterpret_cast<Map*>(HeapObject::FromAddress(0));
+  int lo_size = Page::kPageSize;
+
+  Object* obj = lo->AllocateRaw(lo_size);
+  CHECK(!obj->IsFailure());
+  CHECK(obj->IsHeapObject());
+
+  HeapObject* ho = HeapObject::cast(obj);
+  ho->set_map(faked_map);
+
+  CHECK(lo->Contains(HeapObject::cast(obj)));
+
+  CHECK(lo->FindObject(ho->address()) == obj);
+
+  CHECK(lo->Contains(ho));
+
+  while (true) {
+    int available = lo->Available();
+    obj = lo->AllocateRaw(lo_size);
+    if (obj->IsFailure()) break;
+    HeapObject::cast(obj)->set_map(faked_map);
+    CHECK(lo->Available() < available);
+  };
+
+  CHECK(!lo->IsEmpty());
+
+  obj = lo->AllocateRaw(lo_size);
+  CHECK(obj->IsFailure());
+
+  lo->TearDown();
+  delete lo;
+
+  MemoryAllocator::TearDown();
+}
diff --git a/deps/v8/test/cctest/test-strings.cc b/deps/v8/test/cctest/test-strings.cc
new file mode 100644
index 0000000..3be5d62
--- /dev/null
+++ b/deps/v8/test/cctest/test-strings.cc
@@ -0,0 +1,446 @@
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+
+// Check that we can traverse very deep stacks of ConsStrings using
+// StringInputBuffer.  Check that Get(int) works on very deep stacks
+// of ConsStrings.  These operations may not be very fast, but they
+// should be possible without getting errors due to too deep recursion.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "factory.h"
+#include "cctest.h"
+#include "zone-inl.h"
+
+unsigned int seed = 123;
+
+static uint32_t gen() {
+        uint64_t z;
+        z = seed;
+        z *= 279470273;
+        z %= 4294967291U;
+        seed = static_cast<unsigned int>(z);
+        return static_cast<uint32_t>(seed >> 16);
+}
+
+
+using namespace v8::internal;
+
+static v8::Persistent<v8::Context> env;
+
+
+static void InitializeVM() {
+  if (env.IsEmpty()) {
+    v8::HandleScope scope;
+    const char* extensions[] = { "v8/print" };
+    v8::ExtensionConfiguration config(1, extensions);
+    env = v8::Context::New(&config);
+  }
+  v8::HandleScope scope;
+  env->Enter();
+}
+
+
+static const int NUMBER_OF_BUILDING_BLOCKS = 128;
+static const int DEEP_DEPTH = 8 * 1024;
+static const int SUPER_DEEP_DEPTH = 80 * 1024;
+
+
+static void InitializeBuildingBlocks(
+    Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS]) {
+  // A list of pointers that we don't have any interest in cleaning up.
+  // If they are reachable from a root then leak detection won't complain.
+  for (int i = 0; i < NUMBER_OF_BUILDING_BLOCKS; i++) {
+    int len = gen() % 16;
+    if (len > 14) {
+      len += 1234;
+    }
+    switch (gen() % 4) {
+      case 0: {
+        uc16 buf[2000];
+        for (int j = 0; j < len; j++) {
+          buf[j] = gen() % 65536;
+        }
+        building_blocks[i] =
+            Factory::NewStringFromTwoByte(Vector<const uc16>(buf, len));
+        for (int j = 0; j < len; j++) {
+          CHECK_EQ(buf[j], building_blocks[i]->Get(j));
+        }
+        break;
+      }
+      case 1: {
+        char buf[2000];
+        for (int j = 0; j < len; j++) {
+          buf[j] = gen() % 128;
+        }
+        building_blocks[i] =
+            Factory::NewStringFromAscii(Vector<const char>(buf, len));
+        for (int j = 0; j < len; j++) {
+          CHECK_EQ(buf[j], building_blocks[i]->Get(j));
+        }
+        break;
+      }
+      case 2: {
+        class Resource: public v8::String::ExternalStringResource,
+                        public ZoneObject {
+         public:
+          explicit Resource(Vector<const uc16> string): data_(string.start()) {
+            length_ = string.length();
+          }
+          virtual const uint16_t* data() const { return data_; }
+          virtual size_t length() const { return length_; }
+
+         private:
+          const uc16* data_;
+          size_t length_;
+        };
+        uc16* buf = Zone::NewArray<uc16>(len);
+        for (int j = 0; j < len; j++) {
+          buf[j] = gen() % 65536;
+        }
+        Resource* resource = new Resource(Vector<const uc16>(buf, len));
+        building_blocks[i] = Factory::NewExternalStringFromTwoByte(resource);
+        for (int j = 0; j < len; j++) {
+          CHECK_EQ(buf[j], building_blocks[i]->Get(j));
+        }
+        break;
+      }
+      case 3: {
+        char* buf = NewArray<char>(len);
+        for (int j = 0; j < len; j++) {
+          buf[j] = gen() % 128;
+        }
+        building_blocks[i] =
+            Factory::NewStringFromAscii(Vector<const char>(buf, len));
+        for (int j = 0; j < len; j++) {
+          CHECK_EQ(buf[j], building_blocks[i]->Get(j));
+        }
+        DeleteArray<char>(buf);
+        break;
+      }
+    }
+  }
+}
+
+
+static Handle<String> ConstructLeft(
+    Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
+    int depth) {
+  Handle<String> answer = Factory::NewStringFromAscii(CStrVector(""));
+  for (int i = 0; i < depth; i++) {
+    answer = Factory::NewConsString(
+        answer,
+        building_blocks[i % NUMBER_OF_BUILDING_BLOCKS]);
+  }
+  return answer;
+}
+
+
+static Handle<String> ConstructRight(
+    Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
+    int depth) {
+  Handle<String> answer = Factory::NewStringFromAscii(CStrVector(""));
+  for (int i = depth - 1; i >= 0; i--) {
+    answer = Factory::NewConsString(
+        building_blocks[i % NUMBER_OF_BUILDING_BLOCKS],
+        answer);
+  }
+  return answer;
+}
+
+
+static Handle<String> ConstructBalancedHelper(
+    Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
+    int from,
+    int to) {
+  ASSERT(to > from);
+  if (to - from == 1) {
+    return building_blocks[from % NUMBER_OF_BUILDING_BLOCKS];
+  }
+  if (to - from == 2) {
+    return Factory::NewConsString(
+        building_blocks[from % NUMBER_OF_BUILDING_BLOCKS],
+        building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS]);
+  }
+  Handle<String> part1 =
+    ConstructBalancedHelper(building_blocks, from, from + ((to - from) / 2));
+  Handle<String> part2 =
+    ConstructBalancedHelper(building_blocks, from + ((to - from) / 2), to);
+  return Factory::NewConsString(part1, part2);
+}
+
+
+static Handle<String> ConstructBalanced(
+    Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS]) {
+  return ConstructBalancedHelper(building_blocks, 0, DEEP_DEPTH);
+}
+
+
+static StringInputBuffer buffer;
+
+
+static void Traverse(Handle<String> s1, Handle<String> s2) {
+  int i = 0;
+  buffer.Reset(*s1);
+  StringInputBuffer buffer2(*s2);
+  while (buffer.has_more()) {
+    CHECK(buffer2.has_more());
+    uint16_t c = buffer.GetNext();
+    CHECK_EQ(c, buffer2.GetNext());
+    i++;
+  }
+  CHECK_EQ(s1->length(), i);
+  CHECK_EQ(s2->length(), i);
+}
+
+
+static void TraverseFirst(Handle<String> s1, Handle<String> s2, int chars) {
+  int i = 0;
+  buffer.Reset(*s1);
+  StringInputBuffer buffer2(*s2);
+  while (buffer.has_more() && i < chars) {
+    CHECK(buffer2.has_more());
+    uint16_t c = buffer.GetNext();
+    CHECK_EQ(c, buffer2.GetNext());
+    i++;
+  }
+  s1->Get(s1->length() - 1);
+  s2->Get(s2->length() - 1);
+}
+
+
+TEST(Traverse) {
+  printf("TestTraverse\n");
+  InitializeVM();
+  v8::HandleScope scope;
+  Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS];
+  ZoneScope zone(DELETE_ON_EXIT);
+  InitializeBuildingBlocks(building_blocks);
+  Handle<String> flat = ConstructBalanced(building_blocks);
+  FlattenString(flat);
+  Handle<String> left_asymmetric = ConstructLeft(building_blocks, DEEP_DEPTH);
+  Handle<String> right_asymmetric = ConstructRight(building_blocks, DEEP_DEPTH);
+  Handle<String> symmetric = ConstructBalanced(building_blocks);
+  printf("1\n");
+  Traverse(flat, symmetric);
+  printf("2\n");
+  Traverse(flat, left_asymmetric);
+  printf("3\n");
+  Traverse(flat, right_asymmetric);
+  printf("4\n");
+  Handle<String> left_deep_asymmetric =
+      ConstructLeft(building_blocks, SUPER_DEEP_DEPTH);
+  Handle<String> right_deep_asymmetric =
+      ConstructRight(building_blocks, SUPER_DEEP_DEPTH);
+  printf("5\n");
+  TraverseFirst(left_asymmetric, left_deep_asymmetric, 1050);
+  printf("6\n");
+  TraverseFirst(left_asymmetric, right_deep_asymmetric, 65536);
+  printf("7\n");
+  Handle<String> right_deep_slice =
+      Factory::NewStringSlice(left_deep_asymmetric,
+                              left_deep_asymmetric->length() - 1050,
+                              left_deep_asymmetric->length() - 50);
+  Handle<String> left_deep_slice =
+      Factory::NewStringSlice(right_deep_asymmetric,
+                              right_deep_asymmetric->length() - 1050,
+                              right_deep_asymmetric->length() - 50);
+  printf("8\n");
+  Traverse(right_deep_slice, left_deep_slice);
+  printf("9\n");
+  FlattenString(left_asymmetric);
+  printf("10\n");
+  Traverse(flat, left_asymmetric);
+  printf("11\n");
+  FlattenString(right_asymmetric);
+  printf("12\n");
+  Traverse(flat, right_asymmetric);
+  printf("14\n");
+  FlattenString(symmetric);
+  printf("15\n");
+  Traverse(flat, symmetric);
+  printf("16\n");
+  FlattenString(left_deep_asymmetric);
+  printf("18\n");
+}
+
+
+static Handle<String> SliceOf(Handle<String> underlying) {
+  int start = gen() % underlying->length();
+  int end = start + gen() % (underlying->length() - start);
+  return Factory::NewStringSlice(underlying,
+                                 start,
+                                 end);
+}
+
+
+static Handle<String> ConstructSliceTree(
+    Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
+    int from,
+    int to) {
+  ASSERT(to > from);
+  if (to - from <= 1)
+    return SliceOf(building_blocks[from % NUMBER_OF_BUILDING_BLOCKS]);
+  if (to - from == 2) {
+    Handle<String> lhs = building_blocks[from % NUMBER_OF_BUILDING_BLOCKS];
+    if (gen() % 2 == 0)
+      lhs = SliceOf(lhs);
+    Handle<String> rhs = building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS];
+    if (gen() % 2 == 0)
+      rhs = SliceOf(rhs);
+    return Factory::NewConsString(lhs, rhs);
+  }
+  Handle<String> part1 =
+    ConstructBalancedHelper(building_blocks, from, from + ((to - from) / 2));
+  Handle<String> part2 =
+    ConstructBalancedHelper(building_blocks, from + ((to - from) / 2), to);
+  Handle<String> branch = Factory::NewConsString(part1, part2);
+  if (gen() % 2 == 0)
+    return branch;
+  return(SliceOf(branch));
+}
+
+
+TEST(Slice) {
+  printf("TestSlice\n");
+  InitializeVM();
+  v8::HandleScope scope;
+  Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS];
+  ZoneScope zone(DELETE_ON_EXIT);
+  InitializeBuildingBlocks(building_blocks);
+
+  seed = 42;
+  Handle<String> slice_tree =
+      ConstructSliceTree(building_blocks, 0, DEEP_DEPTH);
+  seed = 42;
+  Handle<String> flat_slice_tree =
+      ConstructSliceTree(building_blocks, 0, DEEP_DEPTH);
+  FlattenString(flat_slice_tree);
+  Traverse(flat_slice_tree, slice_tree);
+}
+
+static const int DEEP_ASCII_DEPTH = 100000;
+
+
+TEST(DeepAscii) {
+  printf("TestDeepAscii\n");
+  InitializeVM();
+  v8::HandleScope scope;
+
+  char* foo = NewArray<char>(DEEP_ASCII_DEPTH);
+  for (int i = 0; i < DEEP_ASCII_DEPTH; i++) {
+    foo[i] = "foo "[i % 4];
+  }
+  Handle<String> string =
+      Factory::NewStringFromAscii(Vector<const char>(foo, DEEP_ASCII_DEPTH));
+  Handle<String> foo_string = Factory::NewStringFromAscii(CStrVector("foo"));
+  for (int i = 0; i < DEEP_ASCII_DEPTH; i += 10) {
+    string = Factory::NewConsString(string, foo_string);
+  }
+  Handle<String> flat_string = Factory::NewConsString(string, foo_string);
+  FlattenString(flat_string);
+
+  for (int i = 0; i < 500; i++) {
+    TraverseFirst(flat_string, string, DEEP_ASCII_DEPTH);
+  }
+  DeleteArray<char>(foo);
+}
+
+
+TEST(Utf8Conversion) {
+  // Smoke test for converting strings to utf-8.
+  InitializeVM();
+  v8::HandleScope handle_scope;
+  // A simple ascii string
+  const char* ascii_string = "abcdef12345";
+  int len = v8::String::New(ascii_string, strlen(ascii_string))->Utf8Length();
+  CHECK_EQ(strlen(ascii_string), len);
+  // A mixed ascii and non-ascii string
+  // U+02E4 -> CB A4
+  // U+0064 -> 64
+  // U+12E4 -> E1 8B A4
+  // U+0030 -> 30
+  // U+3045 -> E3 81 85
+  const uint16_t mixed_string[] = {0x02E4, 0x0064, 0x12E4, 0x0030, 0x3045};
+  // The characters we expect to be output
+  const unsigned char as_utf8[11] = {0xCB, 0xA4, 0x64, 0xE1, 0x8B, 0xA4, 0x30,
+      0xE3, 0x81, 0x85, 0x00};
+  // The number of bytes expected to be written for each length
+  const int lengths[12] = {0, 0, 2, 3, 3, 3, 6, 7, 7, 7, 10, 11};
+  v8::Handle<v8::String> mixed = v8::String::New(mixed_string, 5);
+  CHECK_EQ(10, mixed->Utf8Length());
+  // Try encoding the string with all capacities
+  char buffer[11];
+  const char kNoChar = static_cast<char>(-1);
+  for (int i = 0; i <= 11; i++) {
+    // Clear the buffer before reusing it
+    for (int j = 0; j < 11; j++)
+      buffer[j] = kNoChar;
+    int written = mixed->WriteUtf8(buffer, i);
+    CHECK_EQ(lengths[i], written);
+    // Check that the contents are correct
+    for (int j = 0; j < lengths[i]; j++)
+      CHECK_EQ(as_utf8[j], static_cast<unsigned char>(buffer[j]));
+    // Check that the rest of the buffer hasn't been touched
+    for (int j = lengths[i]; j < 11; j++)
+      CHECK_EQ(kNoChar, buffer[j]);
+  }
+}
+
+
+class TwoByteResource: public v8::String::ExternalStringResource {
+ public:
+  explicit TwoByteResource(const uint16_t* data, size_t length)
+      : data_(data), length_(length) { }
+  virtual ~TwoByteResource() { }
+
+  const uint16_t* data() const { return data_; }
+  size_t length() const { return length_; }
+
+ private:
+  const uint16_t* data_;
+  size_t length_;
+};
+
+
+TEST(ExternalCrBug9746) {
+  InitializeVM();
+  v8::HandleScope handle_scope;
+
+  // This set of tests verifies that the workaround for Chromium bug 9746
+  // works correctly. In certain situations the external resource of a symbol
+  // is collected while the symbol is still part of the symbol table.
+  static uint16_t two_byte_data[] = {
+    't', 'w', 'o', '-', 'b', 'y', 't', 'e', ' ', 'd', 'a', 't', 'a'
+  };
+  static size_t two_byte_length =
+      sizeof(two_byte_data) / sizeof(two_byte_data[0]);
+  static const char* one_byte_data = "two-byte data";
+
+  // Allocate an external string resource and external string.
+  TwoByteResource* resource = new TwoByteResource(two_byte_data,
+                                                  two_byte_length);
+  Handle<String> string = Factory::NewExternalStringFromTwoByte(resource);
+  Vector<const char> one_byte_vec = CStrVector(one_byte_data);
+  Handle<String> compare = Factory::NewStringFromAscii(one_byte_vec);
+
+  // Verify the correct behaviour before "collecting" the external resource.
+  CHECK(string->IsEqualTo(one_byte_vec));
+  CHECK(string->Equals(*compare));
+
+  // "Collect" the external resource manually by setting the external resource
+  // pointer to NULL. Then redo the comparisons, they should not match AND
+  // not crash.
+  Handle<ExternalTwoByteString> external(ExternalTwoByteString::cast(*string));
+  external->set_resource(NULL);
+  CHECK_EQ(false, string->IsEqualTo(one_byte_vec));
+#if !defined(DEBUG)
+  // These tests only work in non-debug as there are ASSERTs in the code that
+  // do prevent the ability to even get into the broken code when running the
+  // debug version of V8.
+  CHECK_EQ(false, string->Equals(*compare));
+  CHECK_EQ(false, compare->Equals(*string));
+  CHECK_EQ(false, string->Equals(Heap::empty_string()));
+#endif  // !defined(DEBUG)
+}
diff --git a/deps/v8/test/cctest/test-threads.cc b/deps/v8/test/cctest/test-threads.cc
new file mode 100644
index 0000000..c0d55f2
--- /dev/null
+++ b/deps/v8/test/cctest/test-threads.cc
@@ -0,0 +1,54 @@
+// Copyright 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.
+
+#include "v8.h"
+
+#include "platform.h"
+
+#include "cctest.h"
+
+
+TEST(Preemption) {
+  v8::Locker locker;
+  v8::V8::Initialize();
+  v8::HandleScope scope;
+  v8::Context::Scope context_scope(v8::Context::New());
+
+  v8::Locker::StartPreemption(100);
+
+  v8::Handle<v8::Script> script = v8::Script::Compile(
+      v8::String::New("var count = 0; var obj = new Object(); count++;\n"));
+
+  script->Run();
+
+  v8::Locker::StopPreemption();
+  v8::internal::OS::Sleep(500);  // Make sure the timer fires.
+
+  script->Run();
+}
+
+
diff --git a/deps/v8/test/cctest/test-utils.cc b/deps/v8/test/cctest/test-utils.cc
new file mode 100644
index 0000000..acb5d3c
--- /dev/null
+++ b/deps/v8/test/cctest/test-utils.cc
@@ -0,0 +1,179 @@
+// 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.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "platform.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+
+enum Mode {
+  forward,
+  backward_unsigned
+};
+
+
+static v8::internal::byte* Write(v8::internal::byte* p, Mode m, int x) {
+  v8::internal::byte* q = NULL;
+  switch (m) {
+    case forward:
+      q = EncodeInt(p, x);
+      CHECK(q <= p + sizeof(x) + 1);
+      break;
+    case backward_unsigned:
+      q = EncodeUnsignedIntBackward(p, x);
+      CHECK(q >= p - sizeof(x) - 1);
+      break;
+  }
+  return q;
+}
+
+
+static v8::internal::byte* Read(v8::internal::byte* p, Mode m, int x) {
+  v8::internal::byte* q = NULL;
+  int y;
+  switch (m) {
+    case forward:
+      q = DecodeInt(p, &y);
+      CHECK(q <= p + sizeof(y) + 1);
+      break;
+    case backward_unsigned: {
+      unsigned int uy;
+      q = DecodeUnsignedIntBackward(p, &uy);
+      y = uy;
+      CHECK(q >= p - sizeof(uy) - 1);
+      break;
+    }
+  }
+  CHECK(y == x);
+  return q;
+}
+
+
+static v8::internal::byte* WriteMany(v8::internal::byte* p, Mode m, int x) {
+  p = Write(p, m, x - 7);
+  p = Write(p, m, x - 1);
+  p = Write(p, m, x);
+  p = Write(p, m, x + 1);
+  p = Write(p, m, x + 2);
+  p = Write(p, m, -x - 5);
+  p = Write(p, m, -x - 1);
+  p = Write(p, m, -x);
+  p = Write(p, m, -x + 1);
+  p = Write(p, m, -x + 3);
+
+  return p;
+}
+
+
+static v8::internal::byte* ReadMany(v8::internal::byte* p, Mode m, int x) {
+  p = Read(p, m, x - 7);
+  p = Read(p, m, x - 1);
+  p = Read(p, m, x);
+  p = Read(p, m, x + 1);
+  p = Read(p, m, x + 2);
+  p = Read(p, m, -x - 5);
+  p = Read(p, m, -x - 1);
+  p = Read(p, m, -x);
+  p = Read(p, m, -x + 1);
+  p = Read(p, m, -x + 3);
+
+  return p;
+}
+
+
+void ProcessValues(int* values, int n, Mode m) {
+  v8::internal::byte buf[4 * KB];  // make this big enough
+  v8::internal::byte* p0 = (m == forward ? buf : buf + ARRAY_SIZE(buf));
+
+  v8::internal::byte* p = p0;
+  for (int i = 0; i < n; i++) {
+    p = WriteMany(p, m, values[i]);
+  }
+
+  v8::internal::byte* q = p0;
+  for (int i = 0; i < n; i++) {
+    q = ReadMany(q, m, values[i]);
+  }
+
+  CHECK(p == q);
+}
+
+
+TEST(Utils0) {
+  int values[] = {
+    0, 1, 10, 16, 32, 64, 128, 256, 512, 1024, 1234, 5731,
+    10000, 100000, 1000000, 10000000, 100000000, 1000000000
+  };
+  const int n = ARRAY_SIZE(values);
+
+  ProcessValues(values, n, forward);
+  ProcessValues(values, n, backward_unsigned);
+}
+
+
+TEST(Utils1) {
+  CHECK_EQ(-1000000, FastD2I(-1000000.0));
+  CHECK_EQ(-1, FastD2I(-1.0));
+  CHECK_EQ(0, FastD2I(0.0));
+  CHECK_EQ(1, FastD2I(1.0));
+  CHECK_EQ(1000000, FastD2I(1000000.0));
+
+  CHECK_EQ(-1000000, FastD2I(-1000000.123));
+  CHECK_EQ(-1, FastD2I(-1.234));
+  CHECK_EQ(0, FastD2I(0.345));
+  CHECK_EQ(1, FastD2I(1.234));
+  CHECK_EQ(1000000, FastD2I(1000000.123));
+}
+
+
+TEST(SNPrintF) {
+  // Make sure that strings that are truncated because of too small
+  // buffers are zero-terminated anyway.
+  const char* s = "the quick lazy .... oh forget it!";
+  int length = strlen(s);
+  for (int i = 1; i < length * 2; i++) {
+    static const char kMarker = static_cast<char>(42);
+    Vector<char> buffer = Vector<char>::New(i + 1);
+    buffer[i] = kMarker;
+    int n = OS::SNPrintF(Vector<char>(buffer.start(), i), "%s", s);
+    CHECK(n <= i);
+    CHECK(n == length || n == -1);
+    CHECK_EQ(0, strncmp(buffer.start(), s, i - 1));
+    CHECK_EQ(kMarker, buffer[i]);
+    if (i <= length) {
+      CHECK_EQ(i - 1, strlen(buffer.start()));
+    } else {
+      CHECK_EQ(length, strlen(buffer.start()));
+    }
+    buffer.Dispose();
+  }
+}
diff --git a/deps/v8/test/cctest/testcfg.py b/deps/v8/test/cctest/testcfg.py
new file mode 100644
index 0000000..75377db
--- /dev/null
+++ b/deps/v8/test/cctest/testcfg.py
@@ -0,0 +1,108 @@
+# Copyright 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.
+
+import test
+import os
+from os.path import join, dirname, exists
+import platform
+import utils
+
+DEBUG_FLAGS = ['--enable-slow-asserts', '--debug-code', '--verify-heap']
+
+
+class CcTestCase(test.TestCase):
+
+  def __init__(self, path, executable, mode, raw_name, dependency, context):
+    super(CcTestCase, self).__init__(context, path)
+    self.executable = executable
+    self.mode = mode
+    self.raw_name = raw_name
+    self.dependency = dependency
+
+  def GetLabel(self):
+    return "%s %s %s" % (self.mode, self.path[-2], self.path[-1])
+
+  def GetName(self):
+    return self.path[-1]
+
+  def BuildCommand(self, name):
+    serialization_file = join('obj', 'test', self.mode, 'serdes')
+    serialization_file += '_' + self.GetName()
+    serialization_option = '--testing_serialization_file=' + serialization_file
+    result = [ self.executable, name, serialization_option ]
+    if self.mode == 'debug':
+      result += DEBUG_FLAGS
+    return result
+
+  def GetCommand(self):
+    return self.BuildCommand(self.raw_name)
+
+  def Run(self):
+    if self.dependency != '':
+      dependent_command = self.BuildCommand(self.dependency)
+      output = self.RunCommand(dependent_command)
+      if output.HasFailed():
+        return output
+    return test.TestCase.Run(self)
+
+
+class CcTestConfiguration(test.TestConfiguration):
+
+  def __init__(self, context, root):
+    super(CcTestConfiguration, self).__init__(context, root)
+
+  def GetBuildRequirements(self):
+    return ['cctests']
+
+  def ListTests(self, current_path, path, mode):
+    executable = join('obj', 'test', mode, 'cctest')
+    if utils.IsWindows():
+      executable += '.exe'
+    output = test.Execute([executable, '--list'], self.context)
+    if output.exit_code != 0:
+      print output.stdout
+      print output.stderr
+      return []
+    result = []
+    for test_desc in output.stdout.strip().split():
+      raw_test, dependency = test_desc.split('<')
+      relative_path = raw_test.split('/')
+      full_path = current_path + relative_path
+      if dependency != '':
+        dependency = relative_path[0] + '/' + dependency
+      if self.Contains(path, full_path):
+        result.append(CcTestCase(full_path, executable, mode, raw_test, dependency, self.context))
+    return result
+
+  def GetTestStatus(self, sections, defs):
+    status_file = join(self.root, 'cctest.status')
+    if exists(status_file):
+      test.ReadConfigurationInto(status_file, sections, defs)
+
+
+def GetConfiguration(context, root):
+  return CcTestConfiguration(context, root)
diff --git a/deps/v8/test/message/message.status b/deps/v8/test/message/message.status
new file mode 100644
index 0000000..fc2896b
--- /dev/null
+++ b/deps/v8/test/message/message.status
@@ -0,0 +1,31 @@
+# Copyright 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.
+
+prefix message
+
+# All tests in the bug directory are expected to fail.
+bugs: FAIL
diff --git a/deps/v8/test/message/regress/regress-73.js b/deps/v8/test/message/regress/regress-73.js
new file mode 100644
index 0000000..72652d7
--- /dev/null
+++ b/deps/v8/test/message/regress/regress-73.js
@@ -0,0 +1,33 @@
+// Copyright 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.
+
+try {
+  throw 'a';
+} catch (e) {
+  throw 'b';
+  print('c');
+}
diff --git a/deps/v8/test/message/regress/regress-73.out b/deps/v8/test/message/regress/regress-73.out
new file mode 100644
index 0000000..28606dd
--- /dev/null
+++ b/deps/v8/test/message/regress/regress-73.out
@@ -0,0 +1,30 @@
+# Copyright 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.
+
+*%(basename)s:31: b
+  throw 'b';
+  ^
diff --git a/deps/v8/test/message/regress/regress-75.js b/deps/v8/test/message/regress/regress-75.js
new file mode 100644
index 0000000..428fac9
--- /dev/null
+++ b/deps/v8/test/message/regress/regress-75.js
@@ -0,0 +1,32 @@
+// Copyright 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.
+
+try {
+  throw "foo";
+} finally {
+  "bar";
+}
diff --git a/deps/v8/test/message/regress/regress-75.out b/deps/v8/test/message/regress/regress-75.out
new file mode 100644
index 0000000..336d4ce
--- /dev/null
+++ b/deps/v8/test/message/regress/regress-75.out
@@ -0,0 +1,30 @@
+# Copyright 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.
+
+*%(basename)s:29: foo
+  throw "foo";
+  ^
diff --git a/deps/v8/test/message/simple-throw.js b/deps/v8/test/message/simple-throw.js
new file mode 100644
index 0000000..7b3b4ca
--- /dev/null
+++ b/deps/v8/test/message/simple-throw.js
@@ -0,0 +1,28 @@
+// Copyright 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.
+
+throw "wow";
diff --git a/deps/v8/test/message/simple-throw.out b/deps/v8/test/message/simple-throw.out
new file mode 100644
index 0000000..0f359cf
--- /dev/null
+++ b/deps/v8/test/message/simple-throw.out
@@ -0,0 +1,30 @@
+# Copyright 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.
+
+*%(basename)s:28: wow
+throw "wow";
+^
diff --git a/deps/v8/test/message/testcfg.py b/deps/v8/test/message/testcfg.py
new file mode 100644
index 0000000..6004282
--- /dev/null
+++ b/deps/v8/test/message/testcfg.py
@@ -0,0 +1,135 @@
+# Copyright 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.
+
+import test
+import os
+from os.path import join, dirname, exists, basename, isdir
+import re
+
+FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)")
+
+class MessageTestCase(test.TestCase):
+
+  def __init__(self, path, file, expected, mode, context, config):
+    super(MessageTestCase, self).__init__(context, path)
+    self.file = file
+    self.expected = expected
+    self.config = config
+    self.mode = mode
+
+  def IgnoreLine(self, str):
+    """Ignore empty lines and valgrind output."""
+    if not str: return True
+    else: return str.startswith('==') or str.startswith('**')
+
+  def IsFailureOutput(self, output):
+    f = file(self.expected)
+    # Skip initial '#' comment and spaces
+    for line in f:
+      if (not line.startswith('#')) and (not line.strip()):
+        break
+    # Convert output lines to regexps that we can match
+    env = { 'basename': basename(self.file) }
+    patterns = [ ]
+    for line in f:
+      if not line.strip():
+        continue
+      pattern = re.escape(line.rstrip() % env)
+      pattern = pattern.replace('\\*', '.*')
+      pattern = '^%s$' % pattern
+      patterns.append(pattern)
+    # Compare actual output with the expected
+    raw_lines = output.stdout.split('\n')
+    outlines = [ s for s in raw_lines if not self.IgnoreLine(s) ]
+    if len(outlines) != len(patterns):
+      return True
+    for i in xrange(len(patterns)):
+      if not re.match(patterns[i], outlines[i]):
+        return True
+    return False
+
+  def GetLabel(self):
+    return "%s %s" % (self.mode, self.GetName())
+
+  def GetName(self):
+    return self.path[-1]
+
+  def GetCommand(self):
+    result = [self.config.context.GetVm(self.mode)]
+    source = open(self.file).read()
+    flags_match = FLAGS_PATTERN.search(source)
+    if flags_match:
+      result += flags_match.group(1).strip().split()
+    result.append(self.file)
+    return result
+
+  def GetSource(self):
+    return (open(self.file).read()
+          + "\n--- expected output ---\n"
+          + open(self.expected).read())
+
+
+class MessageTestConfiguration(test.TestConfiguration):
+
+  def __init__(self, context, root):
+    super(MessageTestConfiguration, self).__init__(context, root)
+
+  def Ls(self, path):
+    if isdir(path):
+        return [f[:-3] for f in os.listdir(path) if f.endswith('.js')]
+    else:
+        return []
+
+  def ListTests(self, current_path, path, mode):
+    mjsunit = [current_path + [t] for t in self.Ls(self.root)]
+    regress = [current_path + ['regress', t] for t in self.Ls(join(self.root, 'regress'))]
+    bugs = [current_path + ['bugs', t] for t in self.Ls(join(self.root, 'bugs'))]
+    all_tests = mjsunit + regress + bugs
+    result = []
+    for test in all_tests:
+      if self.Contains(path, test):
+        file_prefix = join(self.root, reduce(join, test[1:], ""))
+        file_path = file_prefix + ".js"
+        output_path = file_prefix + ".out"
+        if not exists(output_path):
+          print "Could not find %s" % output_path
+          continue
+        result.append(MessageTestCase(test, file_path, output_path, mode,
+                                      self.context, self))
+    return result
+
+  def GetBuildRequirements(self):
+    return ['sample', 'sample=shell']
+
+  def GetTestStatus(self, sections, defs):
+    status_file = join(self.root, 'message.status')
+    if exists(status_file):
+      test.ReadConfigurationInto(status_file, sections, defs)
+
+
+def GetConfiguration(context, root):
+  return MessageTestConfiguration(context, root)
diff --git a/deps/v8/test/message/try-catch-finally-no-message.js b/deps/v8/test/message/try-catch-finally-no-message.js
new file mode 100644
index 0000000..6459ed8
--- /dev/null
+++ b/deps/v8/test/message/try-catch-finally-no-message.js
@@ -0,0 +1,51 @@
+// Copyright 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.
+
+function f() {
+  try {
+    throw "foo";
+  } catch (e) {
+    throw "bar";
+  } finally {
+    return 4;
+  }
+}
+
+function g() {
+  while (true) {
+    try {
+      throw "foo";
+    } catch (e) {
+      throw "bar";
+    } finally {
+      break;
+    }
+  }
+}
+
+f();
+g();
diff --git a/deps/v8/test/message/try-catch-finally-no-message.out b/deps/v8/test/message/try-catch-finally-no-message.out
new file mode 100644
index 0000000..d85fc7d
--- /dev/null
+++ b/deps/v8/test/message/try-catch-finally-no-message.out
@@ -0,0 +1,26 @@
+// Copyright 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.
diff --git a/deps/v8/test/message/try-catch-finally-return-in-finally.js b/deps/v8/test/message/try-catch-finally-return-in-finally.js
new file mode 100644
index 0000000..d23fe35
--- /dev/null
+++ b/deps/v8/test/message/try-catch-finally-return-in-finally.js
@@ -0,0 +1,39 @@
+// Copyright 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.
+
+function f() {
+  try {
+    throw "foo";
+    return 7;
+  } catch (e) {
+    "bar"
+  } finally {
+    return 42;
+  }
+}
+
+print(f());
diff --git a/deps/v8/test/message/try-catch-finally-return-in-finally.out b/deps/v8/test/message/try-catch-finally-return-in-finally.out
new file mode 100644
index 0000000..1c42ee0
--- /dev/null
+++ b/deps/v8/test/message/try-catch-finally-return-in-finally.out
@@ -0,0 +1,28 @@
+# Copyright 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.
+
+42
diff --git a/deps/v8/test/message/try-catch-finally-throw-in-catch-and-finally.js b/deps/v8/test/message/try-catch-finally-throw-in-catch-and-finally.js
new file mode 100644
index 0000000..164ab69
--- /dev/null
+++ b/deps/v8/test/message/try-catch-finally-throw-in-catch-and-finally.js
@@ -0,0 +1,34 @@
+// Copyright 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.
+
+try {
+  throw "foo";
+} catch (e) {
+  throw "bar";
+} finally {
+  throw "baz";
+}
diff --git a/deps/v8/test/message/try-catch-finally-throw-in-catch-and-finally.out b/deps/v8/test/message/try-catch-finally-throw-in-catch-and-finally.out
new file mode 100644
index 0000000..e3e2348
--- /dev/null
+++ b/deps/v8/test/message/try-catch-finally-throw-in-catch-and-finally.out
@@ -0,0 +1,30 @@
+# Copyright 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.
+
+*%(basename)s:33: baz
+  throw "baz";
+  ^
diff --git a/deps/v8/test/message/try-catch-finally-throw-in-catch.js b/deps/v8/test/message/try-catch-finally-throw-in-catch.js
new file mode 100644
index 0000000..afba12c
--- /dev/null
+++ b/deps/v8/test/message/try-catch-finally-throw-in-catch.js
@@ -0,0 +1,34 @@
+// Copyright 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.
+
+try {
+  throw "foo";
+} catch (e) {
+  throw "bar";
+} finally {
+  "baz";
+}
diff --git a/deps/v8/test/message/try-catch-finally-throw-in-catch.out b/deps/v8/test/message/try-catch-finally-throw-in-catch.out
new file mode 100644
index 0000000..618c13c
--- /dev/null
+++ b/deps/v8/test/message/try-catch-finally-throw-in-catch.out
@@ -0,0 +1,30 @@
+# Copyright 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.
+
+*%(basename)s:31: bar
+  throw "bar";
+  ^
diff --git a/deps/v8/test/message/try-catch-finally-throw-in-finally.js b/deps/v8/test/message/try-catch-finally-throw-in-finally.js
new file mode 100644
index 0000000..387df7a
--- /dev/null
+++ b/deps/v8/test/message/try-catch-finally-throw-in-finally.js
@@ -0,0 +1,34 @@
+// Copyright 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.
+
+try {
+  throw "foo";
+} catch (e) {
+  "bar"
+} finally {
+  throw "baz";
+}
diff --git a/deps/v8/test/message/try-catch-finally-throw-in-finally.out b/deps/v8/test/message/try-catch-finally-throw-in-finally.out
new file mode 100644
index 0000000..e3e2348
--- /dev/null
+++ b/deps/v8/test/message/try-catch-finally-throw-in-finally.out
@@ -0,0 +1,30 @@
+# Copyright 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.
+
+*%(basename)s:33: baz
+  throw "baz";
+  ^
diff --git a/deps/v8/test/message/try-finally-return-in-finally.js b/deps/v8/test/message/try-finally-return-in-finally.js
new file mode 100644
index 0000000..6ec8970
--- /dev/null
+++ b/deps/v8/test/message/try-finally-return-in-finally.js
@@ -0,0 +1,37 @@
+// Copyright 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.
+
+function f() {
+  try {
+    throw "foo";
+    return 7;
+  } finally {
+    return 42;
+  }
+}
+
+print(f());
diff --git a/deps/v8/test/message/try-finally-return-in-finally.out b/deps/v8/test/message/try-finally-return-in-finally.out
new file mode 100644
index 0000000..1c42ee0
--- /dev/null
+++ b/deps/v8/test/message/try-finally-return-in-finally.out
@@ -0,0 +1,28 @@
+# Copyright 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.
+
+42
diff --git a/deps/v8/test/message/try-finally-throw-in-finally.js b/deps/v8/test/message/try-finally-throw-in-finally.js
new file mode 100644
index 0000000..fbd5764
--- /dev/null
+++ b/deps/v8/test/message/try-finally-throw-in-finally.js
@@ -0,0 +1,32 @@
+// Copyright 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.
+
+try {
+  "foo";
+} finally {
+  throw "bar";
+}
diff --git a/deps/v8/test/message/try-finally-throw-in-finally.out b/deps/v8/test/message/try-finally-throw-in-finally.out
new file mode 100644
index 0000000..618c13c
--- /dev/null
+++ b/deps/v8/test/message/try-finally-throw-in-finally.out
@@ -0,0 +1,30 @@
+# Copyright 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.
+
+*%(basename)s:31: bar
+  throw "bar";
+  ^
diff --git a/deps/v8/test/message/try-finally-throw-in-try-and-finally.js b/deps/v8/test/message/try-finally-throw-in-try-and-finally.js
new file mode 100644
index 0000000..1a9660c
--- /dev/null
+++ b/deps/v8/test/message/try-finally-throw-in-try-and-finally.js
@@ -0,0 +1,32 @@
+// Copyright 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.
+
+try {
+  throw "foo";
+} finally {
+  throw "bar";
+}
diff --git a/deps/v8/test/message/try-finally-throw-in-try-and-finally.out b/deps/v8/test/message/try-finally-throw-in-try-and-finally.out
new file mode 100644
index 0000000..618c13c
--- /dev/null
+++ b/deps/v8/test/message/try-finally-throw-in-try-and-finally.out
@@ -0,0 +1,30 @@
+# Copyright 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.
+
+*%(basename)s:31: bar
+  throw "bar";
+  ^
diff --git a/deps/v8/test/message/try-finally-throw-in-try.js b/deps/v8/test/message/try-finally-throw-in-try.js
new file mode 100644
index 0000000..428fac9
--- /dev/null
+++ b/deps/v8/test/message/try-finally-throw-in-try.js
@@ -0,0 +1,32 @@
+// Copyright 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.
+
+try {
+  throw "foo";
+} finally {
+  "bar";
+}
diff --git a/deps/v8/test/message/try-finally-throw-in-try.out b/deps/v8/test/message/try-finally-throw-in-try.out
new file mode 100644
index 0000000..336d4ce
--- /dev/null
+++ b/deps/v8/test/message/try-finally-throw-in-try.out
@@ -0,0 +1,30 @@
+# Copyright 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.
+
+*%(basename)s:29: foo
+  throw "foo";
+  ^
diff --git a/deps/v8/test/mjsunit/api-call-after-bypassed-exception.js b/deps/v8/test/mjsunit/api-call-after-bypassed-exception.js
new file mode 100644
index 0000000..f77b514
--- /dev/null
+++ b/deps/v8/test/mjsunit/api-call-after-bypassed-exception.js
@@ -0,0 +1,39 @@
+// Copyright 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.
+
+// This is a test of making an API call after an exception thrown in JavaScript
+// has been bypassed by a return in the finally block.
+function foo() {
+  try {
+    throw "bar";
+  } finally {
+    return "baz";
+  }
+}
+
+foo();
+print({});
diff --git a/deps/v8/test/mjsunit/apply.js b/deps/v8/test/mjsunit/apply.js
new file mode 100644
index 0000000..1d9dde9
--- /dev/null
+++ b/deps/v8/test/mjsunit/apply.js
@@ -0,0 +1,184 @@
+// Copyright 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.
+
+function f0() {
+  return this;
+}
+
+function f1(a) {
+  return a;
+}
+
+assertTrue(this === f0.apply(), "1-0");
+
+assertTrue(this === f0.apply(this), "2a");
+assertTrue(this === f0.apply(this, new Array(1)), "2b");
+assertTrue(this === f0.apply(this, new Array(2)), "2c");
+assertTrue(this === f0.apply(this, new Array(4242)), "2c");
+
+assertTrue(this === f0.apply(null), "3a");
+assertTrue(this === f0.apply(null, new Array(1)), "3b");
+assertTrue(this === f0.apply(null, new Array(2)), "3c");
+assertTrue(this === f0.apply(this, new Array(4242)), "2c");
+
+assertTrue(this === f0.apply(void 0), "4a");
+assertTrue(this === f0.apply(void 0, new Array(1)), "4b");
+assertTrue(this === f0.apply(void 0, new Array(2)), "4c");
+
+assertTrue(void 0 === f1.apply(), "1-1");
+
+assertTrue(void 0 === f1.apply(this), "2a");
+assertTrue(void 0 === f1.apply(this, new Array(1)), "2b");
+assertTrue(void 0 === f1.apply(this, new Array(2)), "2c");
+assertTrue(void 0 === f1.apply(this, new Array(4242)), "2c");
+assertTrue(42 === f1.apply(this, new Array(42, 43)), "2c");
+assertEquals("foo", f1.apply(this, new Array("foo", "bar", "baz", "boo")), "2c");
+
+assertTrue(void 0 === f1.apply(null), "3a");
+assertTrue(void 0 === f1.apply(null, new Array(1)), "3b");
+assertTrue(void 0 === f1.apply(null, new Array(2)), "3c");
+assertTrue(void 0 === f1.apply(null, new Array(4242)), "2c");
+assertTrue(42 === f1.apply(null, new Array(42, 43)), "2c");
+assertEquals("foo", f1.apply(null, new Array("foo", "bar", "baz", "boo")), "2c");
+
+assertTrue(void 0 === f1.apply(void 0), "4a");
+assertTrue(void 0 === f1.apply(void 0, new Array(1)), "4b");
+assertTrue(void 0 === f1.apply(void 0, new Array(2)), "4c");
+assertTrue(void 0 === f1.apply(void 0, new Array(4242)), "4c");
+assertTrue(42 === f1.apply(void 0, new Array(42, 43)), "2c");
+assertEquals("foo", f1.apply(void 0, new Array("foo", "bar", "baz", "boo")), "2c");
+
+var arr = new Array(42, "foo", "fish", "horse");
+function j(a, b, c, d, e, f, g, h, i, j, k, l) {
+  return "" + a + b + c + d + e + f + g + h + i + j + k + l;
+}
+
+
+var expect = "42foofishhorse";
+for (var i = 0; i < 8; i++)
+  expect += "undefined";
+assertEquals(expect, j.apply(undefined, arr));
+
+assertThrows("f0.apply(this, 1);");
+assertThrows("f0.apply(this, 1, 2);");
+assertThrows("f0.apply(this, 1, new Array(2));");
+
+function f() {
+  var doo = "";
+  for (var i = 0; i < arguments.length; i++) {
+    doo += arguments[i];
+  }
+  return doo;
+}
+  
+assertEquals("42foofishhorse", f.apply(this, arr));
+
+function s() {
+  var doo = this;
+  for (var i = 0; i < arguments.length; i++) {
+    doo += arguments[i];
+  }
+  return doo;
+}
+
+assertEquals("bar42foofishhorse", s.apply("bar", arr));
+
+function al() {
+  assertEquals(345, this);
+  return arguments.length + arguments[arguments.length - 1];
+}
+
+for (var j = 1; j < 0x40000000; j <<= 1) {
+  try {
+    var a = new Array(j);
+    a[j - 1] = 42;
+    assertEquals(42 + j, al.apply(345, a));
+  } catch (e) {
+    assertTrue(e.toString().indexOf("Function.prototype.apply") != -1);
+    for (; j < 0x40000000; j <<= 1) {
+      var caught = false;
+      try {
+        a = new Array(j);
+        a[j - 1] = 42;
+        al.apply(345, a);
+        assertEquals("Shouldn't get", "here");
+      } catch (e) {
+        assertTrue(e.toString().indexOf("Function.prototype.apply") != -1);
+        caught = true;
+      }
+      assertTrue(caught);
+    }
+    break;
+  }
+}
+
+var primes = new Array(0);
+
+function isPrime(possible_prime) {
+  for (var d = 0; d < primes.length; d++) {
+    var p = primes[d];
+    if (possible_prime % p == 0)
+      return false;
+    if (p * p > possible_prime)
+      return true;
+  }
+  return true;
+}
+
+for (var i = 2; i < 10000; i++) {
+  if (isPrime(i)) {
+    primes.push(i);
+  }
+}
+
+assertEquals(1229, primes.length);
+
+var same_primes = Array.prototype.constructor.apply(Array, primes);
+
+for (var i = 0; i < primes.length; i++)
+  assertEquals(primes[i], same_primes[i]);
+assertEquals(primes.length, same_primes.length);
+
+
+Array.prototype["1"] = "sep";
+
+var holey = new Array(3);
+holey[0] = "mor";
+holey[2] = "er";
+
+assertEquals("morseper", String.prototype.concat.apply("", holey));
+assertEquals("morseper", String.prototype.concat.apply("", holey, 1));
+assertEquals("morseper", String.prototype.concat.apply("", holey, 1, 2));
+assertEquals("morseper", String.prototype.concat.apply("", holey, 1, 2, 3));
+assertEquals("morseper", String.prototype.concat.apply("", holey, 1, 2, 3, 4));
+
+primes[0] = "";
+primes[1] = holey;
+assertThrows("String.prototype.concat.apply.apply('foo', primes)");
+assertEquals("morseper", String.prototype.concat.apply.apply(String.prototype.concat, primes));
+
+delete(Array.prototype["1"]);
diff --git a/deps/v8/test/mjsunit/arguments-call-apply.js b/deps/v8/test/mjsunit/arguments-call-apply.js
new file mode 100644
index 0000000..a5cadf5
--- /dev/null
+++ b/deps/v8/test/mjsunit/arguments-call-apply.js
@@ -0,0 +1,41 @@
+// Copyright 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.
+
+function sum(a, b, c) {
+  var result = 0;
+  for (var i = 0; i < arguments.length; i++) {
+    result += arguments[i];
+  }
+  return result;
+}
+
+// Try invoking call before sum has been compiled lazily.
+assertEquals(6, sum.call(this, 1, 2, 3), "lazy call");
+
+assertEquals(6, sum(1, 2, 3), "normal");
+assertEquals(6, sum.call(this, 1, 2, 3), "call");
+assertEquals(6, sum.apply(this, [1, 2, 3]), "apply");
diff --git a/deps/v8/test/mjsunit/arguments-enum.js b/deps/v8/test/mjsunit/arguments-enum.js
new file mode 100644
index 0000000..f76240f
--- /dev/null
+++ b/deps/v8/test/mjsunit/arguments-enum.js
@@ -0,0 +1,52 @@
+// Copyright 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.
+
+function countArguments() {
+  var count = 0;
+  for (var prop in arguments)
+    count++;
+  return count;
+}
+
+function setArgumentCount() {
+  arguments[10] = 5;
+  arguments.x = 4;
+  var count = 0;
+  for (var prop in arguments)
+    count++;
+  return count;
+}
+
+assertEquals(0, countArguments());
+assertEquals(0, countArguments(1));
+assertEquals(0, countArguments(1, 2));
+assertEquals(0, countArguments(1, 2, 3, 4, 5));
+
+assertEquals(0, setArgumentCount());
+assertEquals(0, setArgumentCount(1));
+assertEquals(0, setArgumentCount(1, 2));
+assertEquals(0, setArgumentCount(1, 2, 3, 4, 5));
diff --git a/deps/v8/test/mjsunit/arguments-indirect.js b/deps/v8/test/mjsunit/arguments-indirect.js
new file mode 100644
index 0000000..2d37027
--- /dev/null
+++ b/deps/v8/test/mjsunit/arguments-indirect.js
@@ -0,0 +1,47 @@
+// Copyright 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.
+
+function f1() {
+  g(f1);
+}
+
+function f2(x) {
+  var a = arguments;
+  x++;
+  g(f2);
+}
+
+
+function g(f) {
+  assertEquals(3, f.arguments.length);
+  assertEquals(1, f.arguments[0]);
+  assertEquals(2, f.arguments[1]);
+  assertEquals(3, f.arguments[2]);
+}
+
+f1(1,2,3);
+f2(0,2,3);
diff --git a/deps/v8/test/mjsunit/arguments-opt.js b/deps/v8/test/mjsunit/arguments-opt.js
new file mode 100644
index 0000000..c74fc75
--- /dev/null
+++ b/deps/v8/test/mjsunit/arguments-opt.js
@@ -0,0 +1,130 @@
+// Copyright 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.
+
+// Flags: --allow-natives-syntax
+
+function L0() {
+  return %_ArgumentsLength();
+}
+
+function L1(a) {
+  return %_ArgumentsLength();
+}
+
+function L5(a,b,c,d,e) {
+  return %_ArgumentsLength();
+}
+
+
+assertEquals(0, L0());
+assertEquals(1, L0(1));
+assertEquals(2, L0(1,2));
+assertEquals(5, L0(1,2,3,4,5));
+
+assertEquals(0, L1());
+assertEquals(1, L1(1));
+assertEquals(2, L1(1,2));
+assertEquals(5, L1(1,2,3,4,5));
+
+assertEquals(0, L5());
+assertEquals(1, L5(1));
+assertEquals(2, L5(1,2));
+assertEquals(5, L5(1,2,3,4,5));
+
+
+function A(key) {
+  return %_Arguments(key);
+}
+
+// Integer access.
+assertEquals(0, A(0));
+assertEquals(0, A(0,1));
+assertEquals(2, A(1,2));
+assertEquals(2, A(1,2,3,4,5));
+assertEquals(5, A(4,2,3,4,5));
+assertTrue(typeof A(1) == 'undefined');
+assertTrue(typeof A(3,2,1) == 'undefined');
+
+// Out-of-bounds integer access with and without argument
+// adaptor frames.
+assertTrue(typeof(A(-10000)) == 'undefined');
+assertTrue(typeof(A(-10000, 0)) == 'undefined');
+assertTrue(typeof(A(-1)) == 'undefined');
+assertTrue(typeof(A(-1, 0)) == 'undefined');
+assertTrue(typeof(A(10000)) == 'undefined');
+assertTrue(typeof(A(10000, 0)) == 'undefined');
+
+// String access.
+assertEquals(0, A('0'));
+assertEquals(0, A('0',1));
+assertEquals(2, A('1',2));
+assertEquals(2, A('1',2,3,4,5));
+assertEquals(5, A('4',2,3,4,5));
+assertTrue(typeof A('1') == 'undefined');
+assertTrue(typeof A('3',2,1) == 'undefined');
+assertEquals(A, A('callee'));
+assertEquals(1, A('length'));
+assertEquals(2, A('length',2));
+assertEquals(5, A('length',2,3,4,5));
+assertEquals({}.toString, A('toString'));
+assertEquals({}.isPrototypeOf, A('isPrototypeOf'));
+assertTrue(typeof A('xxx') == 'undefined');
+
+// Object access.
+function O(key) {
+  return { toString: function() { return key; } };
+}
+
+assertEquals(0, A(O(0)));
+assertEquals(0, A(O(0),1));
+assertEquals(2, A(O(1),2));
+assertEquals(2, A(O(1),2,3,4,5));
+assertEquals(5, A(O(4),2,3,4,5));
+assertTrue(typeof A(O(1)) == 'undefined');
+assertTrue(typeof A(O(3),2,1) == 'undefined');
+
+assertEquals(0, A(O('0')));
+assertEquals(0, A(O('0'),1));
+assertEquals(2, A(O('1'),2));
+assertEquals(2, A(O('1'),2,3,4,5));
+assertEquals(5, A(O('4'),2,3,4,5));
+assertTrue(typeof A(O('1')) == 'undefined');
+assertTrue(typeof A(O('3'),2,1) == 'undefined');
+assertEquals(A, A(O('callee')));
+assertEquals(1, A(O('length')));
+assertEquals(2, A(O('length'),2));
+assertEquals(5, A(O('length'),2,3,4,5));
+assertEquals({}.toString, A(O('toString')));
+assertEquals({}.isPrototypeOf, A(O('isPrototypeOf')));
+assertTrue(typeof A(O('xxx')) == 'undefined');
+
+// Make sure that out-of-bounds access do lookups in the
+// prototype chain.
+Object.prototype[5] = 42;
+assertEquals(42, A(5));
+Object.prototype[-5] = 87;
+assertEquals(87, A(-5));
diff --git a/deps/v8/test/mjsunit/arguments.js b/deps/v8/test/mjsunit/arguments.js
new file mode 100644
index 0000000..0302739
--- /dev/null
+++ b/deps/v8/test/mjsunit/arguments.js
@@ -0,0 +1,97 @@
+// Copyright 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.
+
+function argc0() {
+  return arguments.length;
+}
+
+function argc1(i) {
+  return arguments.length;
+}
+
+function argc2(i, j) {
+  return arguments.length;
+}
+
+assertEquals(0, argc0());
+assertEquals(1, argc0(1));
+assertEquals(2, argc0(1, 2));
+assertEquals(3, argc0(1, 2, 3));
+assertEquals(0, argc1());
+assertEquals(1, argc1(1));
+assertEquals(2, argc1(1, 2));
+assertEquals(3, argc1(1, 2, 3));
+assertEquals(0, argc2());
+assertEquals(1, argc2(1));
+assertEquals(2, argc2(1, 2));
+assertEquals(3, argc2(1, 2, 3));
+
+
+
+var index;
+
+function argv0() {
+  return arguments[index];
+}
+
+function argv1(i) {
+  return arguments[index];
+}
+
+function argv2(i, j) {
+  return arguments[index];
+}
+
+index = 0;
+assertEquals(7, argv0(7));
+assertEquals(7, argv0(7, 8));
+assertEquals(7, argv0(7, 8, 9));
+assertEquals(7, argv1(7));
+assertEquals(7, argv1(7, 8));
+assertEquals(7, argv1(7, 8, 9));
+assertEquals(7, argv2(7));
+assertEquals(7, argv2(7, 8));
+assertEquals(7, argv2(7, 8, 9));
+
+index = 1;
+assertEquals(8, argv0(7, 8));
+assertEquals(8, argv0(7, 8));
+assertEquals(8, argv1(7, 8, 9));
+assertEquals(8, argv1(7, 8, 9));
+assertEquals(8, argv2(7, 8, 9));
+assertEquals(8, argv2(7, 8, 9));
+
+index = 2;
+assertEquals(9, argv0(7, 8, 9));
+assertEquals(9, argv1(7, 8, 9));
+assertEquals(9, argv2(7, 8, 9));
+
+
+// Test that calling a lazily compiled function with
+// an unexpected number of arguments works.
+function f(a) { return arguments.length; };
+assertEquals(3, f(1, 2, 3));
diff --git a/deps/v8/test/mjsunit/array-concat.js b/deps/v8/test/mjsunit/array-concat.js
new file mode 100644
index 0000000..2346c8d
--- /dev/null
+++ b/deps/v8/test/mjsunit/array-concat.js
@@ -0,0 +1,120 @@
+// Copyright 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.
+
+/**
+ * @fileoverview Test concat on small and large arrays
+ */
+
+var poses = [140, 4000000000];
+while (pos = poses.shift()) {
+  var a = new Array(pos);
+  assertEquals(pos, a.length);
+  a.push('foo');
+  assertEquals(pos + 1, a.length);
+  var b = ['bar'];
+  var c = a.concat(b);
+  assertEquals(pos + 2, c.length);
+  assertEquals("undefined", typeof(c[pos - 1]));
+  assertEquals("foo", c[pos]);
+  assertEquals("bar", c[pos + 1]);
+
+  // Can we fool the system by putting a number in a string?
+  var onetwofour = "124";
+  a[onetwofour] = 'doo';
+  assertEquals(a[124], 'doo');
+  c = a.concat(b);
+  assertEquals(c[124], 'doo');
+
+  // If we put a number in the prototype, then the spec says it should be
+  // copied on concat.
+  Array.prototype["123"] = 'baz';
+  assertEquals(a[123], 'baz');
+
+  c = a.concat(b);
+  assertEquals(pos + 2, c.length);
+  assertEquals("baz", c[123]);
+  assertEquals("undefined", typeof(c[pos - 1]));
+  assertEquals("foo", c[pos]);
+  assertEquals("bar", c[pos + 1]);
+
+  // When we take the number off the prototype it disappears from a, but
+  // the concat put it in c itself.
+  Array.prototype["123"] = undefined;
+  assertEquals("undefined", typeof(a[123]));
+  assertEquals("baz", c[123]);
+
+  // If the element of prototype is shadowed, the element on the instance
+  // should be copied, but not the one on the prototype.
+  Array.prototype[123] = 'baz';
+  a[123] = 'xyz';
+  assertEquals('xyz', a[123]);
+  c = a.concat(b);
+  assertEquals('xyz', c[123]);
+
+  // Non-numeric properties on the prototype or the array shouldn't get
+  // copied.
+  Array.prototype.moe = 'joe';
+  a.ben = 'jerry';
+  assertEquals(a["moe"], 'joe');
+  assertEquals(a["ben"], 'jerry');
+  c = a.concat(b);
+  // ben was not copied
+  assertEquals("undefined", typeof(c.ben));
+  // moe was not copied, but we can see it through the prototype
+  assertEquals("joe", c.moe);
+
+  // When we take moe off the prototype it disappears from all arrays.
+  Array.prototype.moe = undefined;
+  assertEquals("undefined", typeof(c.moe));
+
+  // Negative indeces don't get concated.
+  a[-1] = 'minus1';
+  assertEquals("minus1", a[-1]);
+  assertEquals("undefined", typeof(a[0xffffffff]));
+  c = a.concat(b);
+  assertEquals("undefined", typeof(c[-1]));
+  assertEquals("undefined", typeof(c[0xffffffff]));
+  assertEquals(c.length, a.length + 1);
+
+}
+
+a = [];
+c = a.concat('Hello');
+assertEquals(1, c.length);
+assertEquals("Hello", c[0]);
+assertEquals("Hello", c.toString());
+
+// Check that concat preserves holes.
+var holey = [void 0,'a',,'c'].concat(['d',,'f',[0,,2],void 0])
+assertEquals(9, holey.length);  // hole in embedded array is ignored
+for (var i = 0; i < holey.length; i++) {
+  if (i == 2 || i == 5) {
+    assertFalse(i in holey);
+  } else {
+    assertTrue(i in holey);
+  }
+}
diff --git a/deps/v8/test/mjsunit/array-functions-prototype.js b/deps/v8/test/mjsunit/array-functions-prototype.js
new file mode 100644
index 0000000..ea0dc61
--- /dev/null
+++ b/deps/v8/test/mjsunit/array-functions-prototype.js
@@ -0,0 +1,159 @@
+// Copyright 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.
+
+// This file contains a number of tests of array functions and their
+// interaction with properties in the prototype chain.
+//
+// The behavior of SpiderMonkey is slightly different for arrays (see
+// below).  Our behavior is consistent and matches the bahavior of
+// KJS.
+
+var proto = { length:3, 0:'zero', 1:'one', 2:'two' }
+function constructor() {};
+constructor.prototype = proto;
+
+// Set elements on the array prototype.
+Array.prototype[0] = 'zero';
+Array.prototype[1] = 'one';
+Array.prototype[2] = 'two';
+
+// ----------------------------------------------------------------------
+// Helper functions.
+// ----------------------------------------------------------------------
+function assertHasOwnProperties(object, limit) {
+  for (var i = 0; i < limit; i++) {
+    assertTrue(object.hasOwnProperty(i));
+  }
+}
+
+
+// ----------------------------------------------------------------------
+// shift.
+// ----------------------------------------------------------------------
+
+function runTest() {
+  var nonArray = new constructor();
+  var array = ['zero', , 'two'];
+  // Shift away the zero.
+  assertEquals('zero', array.shift());
+  assertEquals('zero', Array.prototype.shift.call(nonArray));
+  // Check that the local object has properties 0 and 1 with the right
+  // values.
+  assertEquals(2, array.length);
+  assertEquals(2, nonArray.length);
+  assertHasOwnProperties(array, 2);
+  assertHasOwnProperties(nonArray, 2);
+  // Note: Spidermonkey is inconsistent here.  It treats arrays
+  // differently from non-arrays.  It only consults the prototype for
+  // non-arrays.  Therefore, array[0] is undefined in Spidermonkey and
+  // 'one' in V8 and KJS.
+  assertEquals('one', array[0]);
+  assertEquals('one', nonArray[0]);
+  assertEquals('two', array[1]);
+  assertEquals('two', nonArray[1]);
+  // Get index 2 from the prototype.
+  assertEquals('two', array[2]);
+  assertEquals('two', nonArray[2]);
+}
+
+runTest();
+
+// ----------------------------------------------------------------------
+// unshift.
+// ----------------------------------------------------------------------
+
+runTest = function() {
+  var nonArray = new constructor();
+  var array = ['zero', , 'two'];
+  // Unshift a new 'zero'.
+  assertEquals(4, array.unshift('zero'));
+  assertEquals(4, Array.prototype.unshift.call(nonArray, 'zero'));
+  // Check that the local object has properties 0 through 3 with the
+  // right values.
+  assertEquals(4, array.length);
+  assertEquals(4, nonArray.length);
+  assertHasOwnProperties(array, 4);
+  assertHasOwnProperties(nonArray, 4);
+  assertEquals('zero', array[0]);
+  assertEquals('zero', nonArray[0]);
+  assertEquals('zero', array[1]);
+  assertEquals('zero', nonArray[1]);
+  // Again Spidermonkey is inconsistent.  array[2] is undefined
+  // instead of 'one'.
+  assertEquals('one', array[2]);
+  assertEquals('one', nonArray[2]);
+  assertEquals('two', array[3]);
+  assertEquals('two', nonArray[3]);
+}
+
+runTest();
+
+
+// ----------------------------------------------------------------------
+// splice
+// ----------------------------------------------------------------------
+
+runTest = function() {
+  var nonArray = new constructor();
+  var array = ['zero', , 'two'];
+  // Delete the first element by splicing in nothing.
+  assertArrayEquals(['zero'], array.splice(0, 1));
+  assertArrayEquals(['zero'], Array.prototype.splice.call(nonArray, 0, 1));
+  // Check that the local object has properties 0 and 1 with the right
+  // values.
+  assertEquals(2, array.length);
+  assertEquals(2, nonArray.length);
+  assertHasOwnProperties(array, 2);
+  assertHasOwnProperties(nonArray, 2);
+  // Again Spidermonkey is inconsistent.  array[0] is undefined
+  // instead of 'one'.
+  assertEquals('one', array[0]);
+  assertEquals('one', nonArray[0]);
+  assertEquals('two', array[1]);
+  assertEquals('two', nonArray[1]);
+  // Get index 2 from the prototype.
+  assertEquals('two', array[2]);
+  assertEquals('two', nonArray[2]);
+};
+
+runTest();
+
+
+// ----------------------------------------------------------------------
+// slice
+// ----------------------------------------------------------------------
+
+runTest = function() {
+  var nonArray = new constructor();
+  var array = ['zero', , 'two'];
+  // Again Spidermonkey is inconsistent.  (array.slice(0, 3))[1] is
+  // undefined instead of 'one'.
+  assertArrayEquals(['zero', 'one', 'two'], array.slice(0, 3));
+  assertArrayEquals(['zero', 'one', 'two'], Array.prototype.slice.call(nonArray, 0, 3));
+};
+
+runTest();
diff --git a/deps/v8/test/mjsunit/array-indexing.js b/deps/v8/test/mjsunit/array-indexing.js
new file mode 100644
index 0000000..2322c54
--- /dev/null
+++ b/deps/v8/test/mjsunit/array-indexing.js
@@ -0,0 +1,66 @@
+// Copyright 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.
+
+var array = [1,2,3,1,2,3,1,2,3,1,2,3];
+
+// ----------------------------------------------------------------------
+// Array.prototype.indexOf.
+// ----------------------------------------------------------------------
+
+// Negative cases.
+assertEquals([].indexOf(1), -1);
+assertEquals(array.indexOf(4), -1);
+assertEquals(array.indexOf(3, array.length), -1);
+
+assertEquals(array.indexOf(3), 2);
+// Negative index out of range.
+assertEquals(array.indexOf(1, -17), 0);
+// Negative index in rage.
+assertEquals(array.indexOf(1, -11), 3);
+// Index in range.
+assertEquals(array.indexOf(1, 1), 3);
+assertEquals(array.indexOf(1, 3), 3);
+assertEquals(array.indexOf(1, 4), 6);
+
+// ----------------------------------------------------------------------
+// Array.prototype.lastIndexOf.
+// ----------------------------------------------------------------------
+
+// Negative cases.
+assertEquals([].lastIndexOf(1), -1);
+assertEquals(array.lastIndexOf(1, -17), -1);
+
+assertEquals(array.lastIndexOf(1), 9);
+// Index out of range.
+assertEquals(array.lastIndexOf(1, array.length), 9);
+// Index in range.
+assertEquals(array.lastIndexOf(1, 2), 0);
+assertEquals(array.lastIndexOf(1, 4), 3);
+assertEquals(array.lastIndexOf(1, 3), 3);
+// Negative index in range.
+assertEquals(array.lastIndexOf(1, -11), 0);
+
diff --git a/deps/v8/test/mjsunit/array-iteration.js b/deps/v8/test/mjsunit/array-iteration.js
new file mode 100644
index 0000000..f11b51c
--- /dev/null
+++ b/deps/v8/test/mjsunit/array-iteration.js
@@ -0,0 +1,228 @@
+// Copyright 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.
+
+// Tests for non-standard array iteration functions.
+//
+// See
+//
+// <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array>
+//
+// for an explanation of each of the functions.
+
+//
+// Array.prototype.filter
+//
+(function() {
+  // Simple use.
+  var a = [0,1];
+  assertArrayEquals([0], a.filter(function(n) { return n == 0; }));
+  assertArrayEquals(a, a);
+
+  // Use specified object as this object when calling the function.
+  var o = { value: 42 }
+  a = [1,42,3,42,4];
+  assertArrayEquals([42,42], a.filter(function(n) { return this.value == n }, o))
+
+  // Modify original array.
+  a = [1,42,3,42,4];
+  assertArrayEquals([42,42], a.filter(function(n, index, array) { array[index] = 43; return 42 == n; }));
+  assertArrayEquals([43,43,43,43,43], a);
+
+  // Only loop through initial part of array eventhough elements are
+  // added.
+  a = [1,1];
+  assertArrayEquals([], a.filter(function(n, index, array) { array.push(n+1); return n == 2; }));
+  assertArrayEquals([1,1,2,2], a);
+
+  // Respect holes.
+  a = new Array(20);
+  var count = 0;
+  a[2] = 2;
+  a[15] = 2;
+  a[17] = 4;
+  var a = a.filter(function(n) { count++; return n == 2; });
+  assertEquals(3, count);
+  for (var i in a) assertEquals(2, a[i]);
+
+})();
+
+
+//
+// Array.prototype.forEach
+//
+(function() {
+  // Simple use.
+  var a = [0,1];
+  var count = 0;
+  a.forEach(function(n) { count++; });
+  assertEquals(2, count);
+
+  // Use specified object as this object when calling the function.
+  var o = { value: 42 }
+  var result = [];
+  a.forEach(function(n) { result.push(this.value); }, o);
+  assertArrayEquals([42,42], result);
+
+  // Modify original array.
+  a = [0,1];
+  count = 0;
+  a.forEach(function(n, index, array) { array[index] = n + 1; count++; });
+  assertEquals(2, count);
+  assertArrayEquals([1,2], a);
+
+  // Only loop through initial part of array eventhough elements are
+  // added.
+  a = [1,1];
+  count = 0;
+  a.forEach(function(n, index, array) { array.push(n+1); count++; });
+  assertEquals(2, count);
+  assertArrayEquals([1,1,2,2], a);
+
+  // Respect holes.
+  a = new Array(20);
+  count = 0;
+  a[15] = 2;
+  a.forEach(function(n) { count++; });
+  assertEquals(1, count);
+
+})();
+
+
+//
+// Array.prototype.every
+//
+(function() {
+  // Simple use.
+  var a = [0,1];
+  assertFalse(a.every(function(n) { return n == 0 }));
+  a = [0,0];
+  assertTrue(a.every(function(n) { return n == 0 }));
+  assertTrue([].every(function(n) { return n == 0}));
+
+  // Use specified object as this object when calling the function.
+  var o = { value: 42 }
+  a = [0];
+  assertFalse(a.every(function(n) { return this.value == n; }, o));
+  a = [42];
+  assertTrue(a.every(function(n) { return this.value == n; }, o));
+
+  // Modify original array.
+  a = [0,1];
+  assertFalse(a.every(function(n, index, array) { array[index] = n + 1; return n == 1;}));
+  assertArrayEquals([1,1], a);
+  
+  // Only loop through initial part of array eventhough elements are
+  // added.
+  a = [1,1];
+  assertTrue(a.every(function(n, index, array) { array.push(n + 1); return n == 1;}));
+  assertArrayEquals([1,1,2,2], a);
+
+  // Respect holes.
+  a = new Array(20);
+  var count = 0;
+  a[2] = 2;
+  a[15] = 2;
+  assertTrue(a.every(function(n) { count++; return n == 2; }));
+  assertEquals(2, count);
+
+})();
+
+//
+// Array.prototype.map
+//
+(function() {
+  var a = [0,1,2,3,4];
+  
+  // Simple use.
+  var result = [1,2,3,4,5];
+  assertArrayEquals(result, a.map(function(n) { return n + 1; }));
+  assertEquals(a, a);
+  
+  // Use specified object as this object when calling the function.
+  var o = { delta: 42 }
+  result = [42,43,44,45,46];
+  assertArrayEquals(result, a.map(function(n) { return this.delta + n; }, o));
+  
+  // Modify original array.
+  a = [0,1,2,3,4];
+  result = [1,2,3,4,5];
+  assertArrayEquals(result, a.map(function(n, index, array) { array[index] = n + 1; return n + 1;}));
+  assertArrayEquals(result, a);
+  
+  // Only loop through initial part of array eventhough elements are
+  // added.
+  a = [0,1,2,3,4];
+  result = [1,2,3,4,5];
+  assertArrayEquals(result, a.map(function(n, index, array) { array.push(n); return n + 1;}));
+  assertArrayEquals([0,1,2,3,4,0,1,2,3,4], a);
+
+  // Respect holes.
+  a = new Array(20);
+  a[15] = 2;
+  a = a.map(function(n) { return 2*n; });
+  for (var i in a) assertEquals(4, a[i]);
+
+})();
+
+//
+// Array.prototype.some
+//
+(function() {
+  var a = [0,1,2,3,4];
+
+  // Simple use.
+  assertTrue(a.some(function(n) { return n == 3}));
+  assertFalse(a.some(function(n) { return n == 5}));
+  
+  // Use specified object as this object when calling the function.
+  var o = { element: 42 };
+  a = [1,42,3];
+  assertTrue(a.some(function(n) { return this.element == n; }, o));
+  a = [1];
+  assertFalse(a.some(function(n) { return this.element == n; }, o));
+
+  // Modify original array.
+  a = [0,1,2,3];
+  assertTrue(a.some(function(n, index, array) { array[index] = n + 1; return n == 2; }));
+  assertArrayEquals([1,2,3,3], a);
+
+  // Only loop through initial part when elements are added.
+  a = [0,1,2];
+  assertFalse(a.some(function(n, index, array) { array.push(42); return n == 42; }));
+  assertArrayEquals([0,1,2,42,42,42], a);
+
+  // Respect holes.
+  a = new Array(20);
+  var count = 0;
+  a[2] = 42;
+  a[10] = 2;
+  a[15] = 42;
+  assertTrue(a.some(function(n) { count++; return n == 2; }));
+  assertEquals(2, count);
+
+})();
+
diff --git a/deps/v8/test/mjsunit/array-join.js b/deps/v8/test/mjsunit/array-join.js
new file mode 100644
index 0000000..c66e462
--- /dev/null
+++ b/deps/v8/test/mjsunit/array-join.js
@@ -0,0 +1,45 @@
+// Copyright 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.
+
+// Test that array join calls toString on subarrays.
+var a = [[1,2],3,4,[5,6]];
+assertEquals('1,2*3*4*5,6', a.join('*'));
+
+// Create a cycle.
+a.push(a);
+assertEquals('1,2*3*4*5,6*', a.join('*'));
+
+// Replace array.prototype.toString.
+Array.prototype.toString = function() { return "array"; }
+assertEquals('array*3*4*array*array', a.join('*'));
+
+Array.prototype.toString = function() { throw 42; }
+assertThrows("a.join('*')");
+
+Array.prototype.toString = function() { return "array"; }
+assertEquals('array*3*4*array*array', a.join('*'));
+
diff --git a/deps/v8/test/mjsunit/array-length-number-conversion.js b/deps/v8/test/mjsunit/array-length-number-conversion.js
new file mode 100644
index 0000000..11808af
--- /dev/null
+++ b/deps/v8/test/mjsunit/array-length-number-conversion.js
@@ -0,0 +1,53 @@
+// Copyright 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.
+
+// A reduced test case from Acid3 test 95.
+// When an object is assigned to an array length field,
+// it is converted to a number.
+
+function CheckSetArrayLength(x, expected) {
+  var a = [];
+  a.length = x;
+
+  assertEquals("number", typeof a.length);
+  assertEquals(expected, a.length);
+}
+
+CheckSetArrayLength(2147483648, 2147483648);
+CheckSetArrayLength("2147483648", 2147483648);
+CheckSetArrayLength(null, 0);
+CheckSetArrayLength(false, 0);
+CheckSetArrayLength(true, 1);
+CheckSetArrayLength({valueOf : function() { return 42; }}, 42);
+CheckSetArrayLength({toString : function() { return '42'; }}, 42);
+
+// Test invalid values
+assertThrows("var y = []; y.length = 'abc';");
+assertThrows("var y = []; y.length = undefined;");
+assertThrows("var y = []; y.length = {};");
+assertThrows("var y = []; y.length = -1;");
+assertThrows("var y = []; y.length = {valueOf:function() { throw new Error(); }};");
diff --git a/deps/v8/test/mjsunit/array-length.js b/deps/v8/test/mjsunit/array-length.js
new file mode 100644
index 0000000..9731e7a
--- /dev/null
+++ b/deps/v8/test/mjsunit/array-length.js
@@ -0,0 +1,111 @@
+// Copyright 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.
+
+var a = [0,1,2,3];
+a.length = 0;
+
+assertEquals('undefined', typeof a[0]);
+assertEquals('undefined', typeof a[1]);
+assertEquals('undefined', typeof a[2]);
+assertEquals('undefined', typeof a[3]);
+
+
+var a = [0,1,2,3];
+a.length = 2;
+
+assertEquals(0, a[0]);
+assertEquals(1, a[1]);
+assertEquals('undefined', typeof a[2]);
+assertEquals('undefined', typeof a[3]);
+
+
+var a = new Array();
+a[0] = 0;
+a[1000] = 1000;
+a[1000000] = 1000000;
+a[2000000] = 2000000;
+
+assertEquals(2000001, a.length);
+a.length = 0;
+assertEquals(0, a.length);
+assertEquals('undefined', typeof a[0]);
+assertEquals('undefined', typeof a[1000]);
+assertEquals('undefined', typeof a[1000000]);
+assertEquals('undefined', typeof a[2000000]);
+
+
+var a = new Array();
+a[0] = 0;
+a[1000] = 1000;
+a[1000000] = 1000000;
+a[2000000] = 2000000;
+
+assertEquals(2000001, a.length);
+a.length = 2000;
+assertEquals(2000, a.length);
+assertEquals(0, a[0]);
+assertEquals(1000, a[1000]);
+assertEquals('undefined', typeof a[1000000]);
+assertEquals('undefined', typeof a[2000000]);
+
+
+var a = new Array();
+a[Math.pow(2,31)-1] = 0;
+a[Math.pow(2,30)-1] = 0;
+assertEquals(Math.pow(2,31), a.length);
+
+
+var a = new Array();
+a[0] = 0;
+a[1000] = 1000;
+a[Math.pow(2,30)-1] = Math.pow(2,30)-1;
+a[Math.pow(2,31)-1] = Math.pow(2,31)-1;
+a[Math.pow(2,32)-2] = Math.pow(2,32)-2;
+
+assertEquals(Math.pow(2,30)-1, a[Math.pow(2,30)-1]);
+assertEquals(Math.pow(2,31)-1, a[Math.pow(2,31)-1]);
+assertEquals(Math.pow(2,32)-2, a[Math.pow(2,32)-2]);
+
+assertEquals(Math.pow(2,32)-1, a.length);
+a.length = Math.pow(2,30)+1;  // not a smi!
+assertEquals(Math.pow(2,30)+1, a.length);
+
+assertEquals(0, a[0]);
+assertEquals(1000, a[1000]);
+assertEquals(Math.pow(2,30)-1, a[Math.pow(2,30)-1]);
+assertEquals('undefined', typeof a[Math.pow(2,31)-1]);
+assertEquals('undefined', typeof a[Math.pow(2,32)-2], "top");
+
+
+var a = new Array();
+a.length = new Number(12);
+assertEquals(12, a.length);
+
+
+var o = { length: -23 };
+Array.prototype.pop.apply(o);
+assertEquals(4294967272, o.length);
diff --git a/deps/v8/test/mjsunit/array-sort.js b/deps/v8/test/mjsunit/array-sort.js
new file mode 100644
index 0000000..dfa4590
--- /dev/null
+++ b/deps/v8/test/mjsunit/array-sort.js
@@ -0,0 +1,154 @@
+// Copyright 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.
+
+// Flags: --allow-natives-syntax
+
+// Test array sort.
+
+// Test counter-intuitive default number sorting.
+function TestNumberSort() {
+  var a = [ 200, 45, 7 ];
+
+  // Default sort converts each element to string and orders
+  // lexicographically.
+  a.sort();
+  assertArrayEquals([ 200, 45, 7 ], a);
+  // Sort numbers by value using a compare functions.
+  a.sort(function(x, y) { return x - y; });
+  assertArrayEquals([ 7, 45, 200 ], a);
+
+  // Default sort on negative numbers.
+  a = [-12345,-123,-1234,-123456];
+  a.sort();
+  assertArrayEquals([-123,-1234,-12345,-123456], a);
+
+  // Default sort on negative and non-negative numbers.
+  a = [123456,0,-12345,-123,123,1234,-1234,0,12345,-123456];
+  a.sort();
+  assertArrayEquals([-123,-1234,-12345,-123456,0,0,123,1234,12345,123456], a);
+
+  // Tricky case avoiding integer overflow in Runtime_SmiLexicographicCompare.
+  a = [9, 1000000000].sort();
+  assertArrayEquals([1000000000, 9], a);
+  a = [1000000000, 1].sort();
+  assertArrayEquals([1, 1000000000], a);
+  a = [1000000000, 0].sort();
+  assertArrayEquals([0, 1000000000], a);
+
+  // One string is a prefix of the other.
+  a = [1230, 123].sort();
+  assertArrayEquals([123, 1230], a);
+  a = [1231, 123].sort();
+  assertArrayEquals([123, 1231], a);
+
+  // Default sort on Smis and non-Smis.
+  a = [1000000000, 10000000000, 1000000001, -1000000000, -10000000000, -1000000001];
+  a.sort();
+  assertArrayEquals([-1000000000, -10000000000, -1000000001, 1000000000, 10000000000, 1000000001], a);
+
+
+  for (var xb = 1; xb <= 1000 * 1000 * 1000; xb *= 10) {
+    for (var xf = 0; xf <= 9; xf++) {
+      for (var xo = -1; xo <= 1; xo++) {
+        for (var yb = 1; yb <= 1000 * 1000 * 1000; yb *= 10) {
+          for (var yf = 0; yf <= 9; yf++) {
+            for (var yo = -1; yo <= 1; yo++) {
+              var x = xb * xf + xo;
+              var y = yb * yf + yo;
+              if (!%_IsSmi(x)) continue;
+              if (!%_IsSmi(y)) continue;
+              var lex = %SmiLexicographicCompare(x, y);
+              if (lex < 0) lex = -1;
+              if (lex > 0) lex = 1;
+              assertEquals(lex, (x == y) ? 0 : ((x + "") < (y + "") ? -1 : 1), x + " < " + y);
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+TestNumberSort();
+
+
+// Test lexicographical string sorting.
+function TestStringSort() {
+  var a = [ "cc", "c", "aa", "a", "bb", "b", "ab", "ac" ];
+  a.sort();
+  assertArrayEquals([ "a", "aa", "ab", "ac", "b", "bb", "c", "cc" ], a);
+}
+
+TestStringSort();
+
+
+// Test object sorting.  Calls toString on each element and sorts
+// lexicographically.
+function TestObjectSort() {
+  var obj0 = { toString: function() { return "a"; } };
+  var obj1 = { toString: function() { return "b"; } };
+  var obj2 = { toString: function() { return "c"; } };
+  var a = [ obj2, obj0, obj1 ];
+  a.sort();
+  assertArrayEquals([ obj0, obj1, obj2 ], a);
+}
+
+TestObjectSort();
+
+// Test array sorting with holes in the array.
+function TestArraySortingWithHoles() {
+  var a = [];
+  a[4] = "18";
+  a[10] = "12";
+  a.sort();
+  assertEquals(11, a.length);
+  assertEquals("12", a[0]);
+  assertEquals("18", a[1]);
+}
+
+TestArraySortingWithHoles();
+
+// Test array sorting with undefined elemeents in the array.
+function TestArraySortingWithUndefined() {
+  var a = [ 3, void 0, 2 ];
+  a.sort();
+  assertArrayEquals([ 2, 3, void 0 ], a);
+}
+
+TestArraySortingWithUndefined();
+
+// Test that sorting using an unsound comparison function still gives a
+// sane result, i.e. it terminates without error and retains the elements
+// in the array.
+function TestArraySortingWithUnsoundComparisonFunction() {
+  var a = [ 3, void 0, 2 ];
+  a.sort(function(x, y) { return 1; });
+  a.sort();
+  assertArrayEquals([ 2, 3, void 0 ], a);
+}
+
+TestArraySortingWithUnsoundComparisonFunction();
diff --git a/deps/v8/test/mjsunit/array-splice-webkit.js b/deps/v8/test/mjsunit/array-splice-webkit.js
new file mode 100644
index 0000000..113a56a
--- /dev/null
+++ b/deps/v8/test/mjsunit/array-splice-webkit.js
@@ -0,0 +1,60 @@
+// Copyright 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.
+
+// Simple splice tests based on webkit layout tests.
+var arr = ['a','b','c','d'];
+assertArrayEquals(['a','b','c','d'], arr);
+assertArrayEquals(['c','d'], arr.splice(2));
+assertArrayEquals(['a','b'], arr);
+assertArrayEquals(['a','b'], arr.splice(0));
+assertArrayEquals([], arr)
+
+arr = ['a','b','c','d'];
+assertEquals(undefined, arr.splice())
+assertArrayEquals(['a','b','c','d'], arr);
+assertArrayEquals(['a','b','c','d'], arr.splice(undefined))
+assertArrayEquals([], arr);
+
+arr = ['a','b','c','d'];
+assertArrayEquals(['a','b','c','d'], arr.splice(null))
+assertArrayEquals([], arr);
+
+arr = ['a','b','c','d'];
+assertArrayEquals([], arr.splice(100))
+assertArrayEquals(['a','b','c','d'], arr);
+assertArrayEquals(['d'], arr.splice(-1))
+assertArrayEquals(['a','b','c'], arr);
+
+assertArrayEquals([], arr.splice(2, undefined))
+assertArrayEquals([], arr.splice(2, null))
+assertArrayEquals([], arr.splice(2, -1))
+assertArrayEquals([], arr.splice(2, 0))
+assertArrayEquals(['a','b','c'], arr);
+assertArrayEquals(['c'], arr.splice(2, 100))
+assertArrayEquals(['a','b'], arr);
+
+
diff --git a/deps/v8/test/mjsunit/array-splice.js b/deps/v8/test/mjsunit/array-splice.js
new file mode 100644
index 0000000..d308ef5
--- /dev/null
+++ b/deps/v8/test/mjsunit/array-splice.js
@@ -0,0 +1,311 @@
+// Copyright 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.
+
+/**
+ * @fileoverview Test splice, shift, unshift, slice and join on small
+ * and large arrays.  Some of these methods are specified such that they
+ * should work on other objects too, so we test that too.
+ */
+
+var LARGE = 40000000;
+var VERYLARGE = 4000000000;
+
+// Nicer for firefox 1.5.  Unless you uncomment the following two lines,
+// smjs will appear to hang on this file.
+//var LARGE = 40000;
+//var VERYLARGE = 40000;
+
+var fourhundredth = LARGE/400;
+
+function PseudoArray() {
+};
+
+for (var use_real_arrays = 0; use_real_arrays <= 1; use_real_arrays++) {
+  var poses = [0, 140, 20000, VERYLARGE];
+  var the_prototype;
+  var new_function;
+  var push_function;
+  var concat_function;
+  var slice_function;
+  var splice_function;
+  var splice_function_2;
+  var unshift_function;
+  var unshift_function_2;
+  var shift_function;
+  if (use_real_arrays) {
+    new_function = function(length) {
+      return new Array(length);
+    };
+    the_prototype = Array.prototype;
+    push_function = function(array, elt) {
+      return array.push(elt);
+    };
+    concat_function = function(array, other) {
+      return array.concat(other);
+    };
+    slice_function = function(array, start, len) {
+      return array.slice(start, len);
+    };
+    splice_function = function(array, start, len) {
+      return array.splice(start, len);
+    };
+    splice_function_2 = function(array, start, len, elt) {
+      return array.splice(start, len, elt);
+    };
+    unshift_function = function(array, elt) {
+      return array.unshift(elt);
+    };
+    unshift_function_2 = function(array, elt1, elt2) {
+      return array.unshift(elt1, elt2);
+    };
+    shift_function = function(array) {
+      return array.shift();
+    };
+  } else {
+    // Don't run largest size on non-arrays or we'll be here for ever.
+    poses.pop();
+    new_function = function(length) {
+      var obj = new PseudoArray();
+      obj.length = length;
+      return obj;
+    };
+    the_prototype = PseudoArray.prototype;
+    push_function = function(array, elt) {
+      array[array.length] = elt;
+      array.length++;
+    };
+    concat_function = function(array, other) {
+      return Array.prototype.concat.call(array, other);
+    };
+    slice_function = function(array, start, len) {
+      return Array.prototype.slice.call(array, start, len);
+    };
+    splice_function = function(array, start, len) {
+      return Array.prototype.splice.call(array, start, len);
+    };
+    splice_function_2 = function(array, start, len, elt) {
+      return Array.prototype.splice.call(array, start, len, elt);
+    };
+    unshift_function = function(array, elt) {
+      return Array.prototype.unshift.call(array, elt);
+    };
+    unshift_function_2 = function(array, elt1, elt2) {
+      return Array.prototype.unshift.call(array, elt1, elt2);
+    };
+    shift_function = function(array) {
+      return Array.prototype.shift.call(array);
+    };
+  }
+
+  for (var pos_pos = 0; pos_pos < poses.length; pos_pos++) {
+    var pos = poses[pos_pos];
+    if (pos > 100) {
+      var a = new_function(pos);
+      assertEquals(pos, a.length);
+      push_function(a, 'foo');
+      assertEquals(pos + 1, a.length);
+      var b = ['bar'];
+      // Delete a huge number of holes.
+      var c = splice_function(a, 10, pos - 20);
+      assertEquals(pos - 20, c.length);
+      assertEquals(21, a.length);
+    }
+
+    // Add a numeric property to the prototype of the array class.  This
+    // allows us to test some borderline stuff relative to the standard.
+    the_prototype["" + (pos + 1)] = 'baz';
+
+    if (use_real_arrays) {
+      // It seems quite clear from ECMAScript spec 15.4.4.5.  Just call Get on
+      // every integer in the range.
+      // IE, Safari get this right.
+      // FF, Opera get this wrong.
+      var a = ['zero', ,'two'];
+      if (pos == 0) {
+        assertEquals("zero,baz,two", a.join(","));
+      }
+
+      // Concat only applies to real arrays, unlike most of the other methods.
+      var a = new_function(pos);
+      push_function(a, "con");
+      assertEquals("con", a[pos]);
+      assertEquals(pos + 1, a.length);
+      var b = new_function(0);
+      push_function(b, "cat");
+      assertEquals("cat", b[0]);
+      var ab = concat_function(a, b);
+      assertEquals("con", ab[pos]);
+      assertEquals(pos + 2, ab.length);
+      assertEquals("cat", ab[pos + 1]);
+      var ba = concat_function(b, a);
+      assertEquals("con", ba[pos + 1]);
+      assertEquals(pos + 2, ba.length);
+      assertEquals("cat", ba[0]);
+
+      // Join with '' as separator.
+      var join = a.join('');
+      assertEquals("con", join);
+      join = b.join('');
+      assertEquals("cat", join);
+      join = ab.join('');
+      assertEquals("concat", join);
+      join = ba.join('');
+      assertEquals("catcon", join);
+
+      var sparse = [];
+      sparse[pos + 1000] = 'is ';
+      sparse[pos + 271828] = 'time ';
+      sparse[pos + 31415] = 'the ';
+      sparse[pos + 012260199] = 'all ';
+      sparse[-1] = 'foo';
+      sparse[pos + 22591927] = 'good ';
+      sparse[pos + 1618033] = 'for ';
+      sparse[pos + 91] = ': Now ';
+      sparse[pos + 86720199] = 'men.';
+      sparse.hest = 'fisk';
+
+      assertEquals("baz: Now is the time for all good men.", sparse.join(''));
+    }
+
+    a = new_function(pos);
+    push_function(a, 'zero');
+    push_function(a, void 0);
+    push_function(a, 'two');
+
+    // Splice works differently from join.
+    // IE, Safari get this wrong.
+    // FF, Opera get this right.
+    // 15.4.4.12 line 24 says the object itself has to have the property...
+    var zero = splice_function(a, pos, 1);
+    assertEquals("undefined", typeof(a[pos]));
+    assertEquals("two", a[pos+1], "pos1:" + pos);
+    assertEquals(pos + 2, a.length, "a length");
+    assertEquals(1, zero.length, "zero length");
+    assertEquals("zero", zero[0]);
+
+    // 15.4.4.12 line 41 says the object itself has to have the property...
+    a = new_function(pos);
+    push_function(a, 'zero');
+    push_function(a, void 0);
+    push_function(a, 'two');
+    var nothing = splice_function_2(a, pos, 0, 'minus1');
+    assertEquals("minus1", a[pos]);
+    assertEquals("zero", a[pos+1]);
+    assertEquals("undefined", typeof(a[pos+2]), "toot!");
+    assertEquals("two", a[pos+3], "pos3");
+    assertEquals(pos + 4, a.length);
+    assertEquals(1, zero.length);
+    assertEquals("zero", zero[0]);
+
+    // 15.4.4.12 line 10 says the object itself has to have the property...
+    a = new_function(pos);
+    push_function(a, 'zero');
+    push_function(a, void 0);
+    push_function(a, 'two');
+    var one = splice_function(a, pos + 1, 1);
+    assertEquals("", one.join(","));
+    assertEquals(pos + 2, a.length);
+    assertEquals("zero", a[pos]);
+    assertEquals("two", a[pos+1]);
+
+    // Set things back to the way they were.
+    the_prototype[pos + 1] = undefined;
+
+    // Unshift.
+    var a = new_function(pos);
+    push_function(a, "foo");
+    assertEquals("foo", a[pos]);
+    assertEquals(pos + 1, a.length);
+    unshift_function(a, "bar");
+    assertEquals("foo", a[pos+1]);
+    assertEquals(pos + 2, a.length);
+    assertEquals("bar", a[0]);
+    unshift_function_2(a, "baz", "boo");
+    assertEquals("foo", a[pos+3]);
+    assertEquals(pos + 4, a.length);
+    assertEquals("baz", a[0]);
+    assertEquals("boo", a[1]);
+    assertEquals("bar", a[2]);
+
+    // Shift.
+    var baz = shift_function(a);
+    assertEquals("baz", baz);
+    assertEquals("boo", a[0]);
+    assertEquals(pos + 3, a.length);
+    assertEquals("foo", a[pos + 2]);
+
+    // Slice.
+    var bar = slice_function(a, 1, 0);  // don't throw an exception please.
+    bar = slice_function(a, 1, 2);
+    assertEquals("bar", bar[0]);
+    assertEquals(1, bar.length);
+    assertEquals("bar", a[1]);
+
+  }
+}
+
+// Lets see if performance is reasonable.
+
+var a = new Array(LARGE + 10);
+for (var i = 0; i < a.length; i += 1000) {
+  a[i] = i;
+}
+
+// Take something near the end of the array.
+for (var i = 0; i < 100; i++) {
+  var top = a.splice(LARGE, 5);
+  assertEquals(5, top.length);
+  assertEquals(LARGE, top[0]);
+  assertEquals("undefined", typeof(top[1]));
+  assertEquals(LARGE + 5, a.length);
+  a.splice(LARGE, 0, LARGE);
+  a.length = LARGE + 10;
+}
+
+var a = new Array(LARGE + 10);
+for (var i = 0; i < a.length; i += fourhundredth) {
+  a[i] = i;
+}
+
+// Take something near the middle of the array.
+for (var i = 0; i < 10; i++) {
+  var top = a.splice(LARGE >> 1, 5);
+  assertEquals(5, top.length);
+  assertEquals(LARGE >> 1, top[0]);
+  assertEquals("undefined", typeof(top[1]));
+  assertEquals(LARGE + 5, a.length);
+  a.splice(LARGE >> 1, 0, LARGE >> 1, void 0, void 0, void 0, void 0);
+}
+
+
+// Test http://b/issue?id=1202711
+arr = [0];
+arr.length = 2;
+Array.prototype[1] = 1;
+assertEquals(1, arr.pop());
+assertEquals(0, arr.pop());
+Array.prototype[1] = undefined;
diff --git a/deps/v8/test/mjsunit/ascii-regexp-subject.js b/deps/v8/test/mjsunit/ascii-regexp-subject.js
new file mode 100644
index 0000000..e0c2f84
--- /dev/null
+++ b/deps/v8/test/mjsunit/ascii-regexp-subject.js
@@ -0,0 +1,49 @@
+// Copyright 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.
+
+/**
+ * @fileoverview Check that an initial ^ will result in a faster match fail.
+ */
+
+
+var s = "foo";
+var i;
+
+for (i = 0; i < 18; i++) {
+  s = s + s;
+}
+
+function repeatRegexp(re) {
+  for (i = 0; i < 1000; i++) {
+    re.test(s);
+  }
+}
+
+repeatRegexp(/^bar/);
+repeatRegexp(/^foo|^bar|^baz/);
+repeatRegexp(/(^bar)/);
+repeatRegexp(/(?=^bar)\w+/);
diff --git a/deps/v8/test/mjsunit/big-array-literal.js b/deps/v8/test/mjsunit/big-array-literal.js
new file mode 100644
index 0000000..d64c968
--- /dev/null
+++ b/deps/v8/test/mjsunit/big-array-literal.js
@@ -0,0 +1,111 @@
+// 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.
+
+// Test that we can make large object literals that work.
+// Also test that we can attempt to make even larger object literals without
+// crashing.
+function testLiteral(size, array_in_middle) {
+  print(size);
+
+  var f;
+
+  // Build object-literal string.
+  var literal = "function f() { return ";
+
+  for (var i = 0; i < size; i++) {
+    literal += "[";
+  }
+
+  literal += array_in_middle ? " [42.2]" : "{a:42.2}";
+
+  for (var i = 0; i < size; i++) {
+    literal += "]";
+  }
+
+  literal += "; }";
+
+  // Create the object literal.
+  eval(literal);
+
+  var x = f();
+
+  // Check that the properties have the expected values.
+  for (var i = 0; i < size; i++) {
+    x = x[0];
+  }
+
+  if (array_in_middle) {
+    assertEquals(42.2, x[0]), "x array in middle";
+    x[0] = 41.2;
+  } else {
+    assertEquals(42.2, x.a, "x object in middle");
+    x.a = 41.2;
+  }
+
+  var y = f();
+  for (var i = 0; i < size; i++) {
+    y = y[0];
+  }
+
+  if (array_in_middle) {
+    assertEquals(42.2, y[0], "y array in middle");
+    y[0] = 41.2;
+  } else {
+    assertEquals(42.2, y.a, "y object in middle");
+    y.a = 41.2;
+  }
+}
+
+// The sizes to test.
+var sizes = [1, 2, 100, 200, 400];
+
+// Run the test.
+for (var i = 0; i < sizes.length; i++) {
+  testLiteral(sizes[i], false);
+  testLiteral(sizes[i], true);
+}
+
+function testLiteralAndCatch(size) {
+  var big_enough = false;
+  try {
+    testLiteral(size, false);
+  } catch (e) {
+    big_enough = true;
+  }
+  try {
+    testLiteral(size, true);
+  } catch (e) {
+    big_enough = true;
+  }
+  return big_enough;
+}
+
+// Catch stack overflows.
+
+testLiteralAndCatch(1000) ||
+testLiteralAndCatch(20000) ||
+testLiteralAndCatch(200000);
diff --git a/deps/v8/test/mjsunit/big-object-literal.js b/deps/v8/test/mjsunit/big-object-literal.js
new file mode 100644
index 0000000..0099ce9
--- /dev/null
+++ b/deps/v8/test/mjsunit/big-object-literal.js
@@ -0,0 +1,114 @@
+// 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.
+
+// Test that we can make large object literals that work.
+// Also test that we can attempt to make even larger object literals without
+// crashing.
+function testLiteral(size, array_in_middle) {
+  print(size);
+
+  var f;
+
+  // Build object-literal string.
+  var literal = "function f() { return ";
+
+  for (var i = 0; i < size; i++) {
+    literal += "{a:";
+  }
+
+  literal += array_in_middle ? " [42.2]" : "{a:42.2}";
+
+  for (var i = 0; i < size; i++) {
+    literal += "}";
+    if (i < size - 1) {
+      literal += ", b:42, c:/asd/, x:'foo', y:[], z:new Object()";
+    }
+  }
+
+  literal += "; }";
+
+  // Create the object literal.
+  eval(literal);
+
+  var x = f();
+
+  // Check that the properties have the expected values.
+  for (var i = 0; i < size; i++) {
+    x = x.a;
+  }
+
+  if (array_in_middle) {
+    assertEquals(42.2, x[0]), "x array in middle";
+    x[0] = 41.2;
+  } else {
+    assertEquals(42.2, x.a, "x object in middle");
+    x.a = 41.2;
+  }
+
+  var y = f();
+  for (var i = 0; i < size; i++) {
+    y = y.a;
+  }
+
+  if (array_in_middle) {
+    assertEquals(42.2, y[0], "y array in middle");
+    y[0] = 41.2;
+  } else {
+    assertEquals(42.2, y.a, "y object in middle");
+    y.a = 41.2;
+  }
+}
+
+// The sizes to test.
+var sizes = [1, 2, 100, 200, 400];
+
+// Run the test.
+for (var i = 0; i < sizes.length; i++) {
+  testLiteral(sizes[i], false);
+  testLiteral(sizes[i], true);
+}
+
+function testLiteralAndCatch(size) {
+  var big_enough = false;
+  try {
+    testLiteral(size, false);
+  } catch (e) {
+    big_enough = true;
+  }
+  try {
+    testLiteral(size, true);
+  } catch (e) {
+    big_enough = true;
+  }
+  return big_enough;
+}
+
+// Catch stack overflows.
+
+testLiteralAndCatch(1000) ||
+testLiteralAndCatch(20000) ||
+testLiteralAndCatch(200000);
diff --git a/deps/v8/test/mjsunit/binary-operation-overwrite.js b/deps/v8/test/mjsunit/binary-operation-overwrite.js
new file mode 100644
index 0000000..8d217c5
--- /dev/null
+++ b/deps/v8/test/mjsunit/binary-operation-overwrite.js
@@ -0,0 +1,36 @@
+// Copyright 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.
+
+// Ensure that literals are not overwritten.
+function f1() { return (1.2, 3.4) + 5.6; }
+function f2() { return (1, 2) + 3; }
+function f3() { return (1.2 || 3.4) + 5.6; }
+function f4() { return (1 || 2) + 3; }
+assertTrue(f1() === f1());
+assertTrue(f2() === f2());
+assertTrue(f3() === f3());
+assertTrue(f4() === f4());
diff --git a/deps/v8/test/mjsunit/body-not-visible.js b/deps/v8/test/mjsunit/body-not-visible.js
new file mode 100644
index 0000000..c681ab3
--- /dev/null
+++ b/deps/v8/test/mjsunit/body-not-visible.js
@@ -0,0 +1,39 @@
+// Copyright 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.
+
+// Make sure we cannot see the local variables in NewFunction when
+// compiling functions using new Function().
+
+var caught = false;
+try {
+  (new Function("return body;"))();
+  assertTrue(false);
+} catch (e) {
+  caught = true;
+  assertTrue(e instanceof ReferenceError);
+}
+assertTrue(caught);
diff --git a/deps/v8/test/mjsunit/bugs/bug-1344252.js b/deps/v8/test/mjsunit/bugs/bug-1344252.js
new file mode 100644
index 0000000..1723834
--- /dev/null
+++ b/deps/v8/test/mjsunit/bugs/bug-1344252.js
@@ -0,0 +1,79 @@
+// Copyright 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.
+
+// Test that setter accessors added to the prototype chain are called
+// when setting properties.
+
+// Test that accessors added to the prototype chain are called
+// eventhough there are inline caches for setting the property
+
+function F() {
+  this.x = 42;
+  this.y = 87;
+}
+
+// Force the inline caches to monomorphic state.
+new F(); new F();
+
+// Add a setter for x to Object.prototype and make sure it gets
+// called.
+var result_x;
+Object.prototype.__defineSetter__('x', function(value) { result_x = value; });
+var f = new F();
+assertEquals(42, result_x);
+assertTrue(typeof f.x == 'undefined');
+
+// Add a setter for y by changing the prototype of f and make sure
+// that gets called too.
+var result_y;
+var proto = new Object();
+proto.__defineSetter__('y', function (value) { result_y = value; });
+var f = new F();
+f.y = undefined;
+f.__proto__ = proto;
+F.call(f);
+assertEquals(87, result_y);
+assertTrue(typeof f.y == 'undefined');
+
+
+// Test the same issue in the runtime system.  Make sure that
+// accessors added to the prototype chain are called instead of
+// following map transitions.
+//
+// Create two objects.
+var result_z;
+var o1 = new Object();
+var o2 = new Object();
+// Add a z property to o1 to create a map transition.
+o1.z = 32;
+// Add a z accessor in the prototype chain for o1 and o2.
+Object.prototype.__defineSetter__('z', function(value) { result_z = value; });
+// The accessor should be called for o2.
+o2.z = 27;
+assertEquals(27, result_z);
+assertTrue(typeof o2.z == 'undefined');
+
diff --git a/deps/v8/test/mjsunit/bugs/bug-222.js b/deps/v8/test/mjsunit/bugs/bug-222.js
new file mode 100644
index 0000000..0df7dd6
--- /dev/null
+++ b/deps/v8/test/mjsunit/bugs/bug-222.js
@@ -0,0 +1,42 @@
+// Copyright 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.
+
+function Foo(a, b) { }
+Foo();
+var oldArgs = Foo.arguments;
+Foo();
+var newArgs = Foo.arguments
+
+assertTrue(oldArgs !== newArgs);
+
+// Don't allow arguments to be overwritten.
+Foo.arguments = oldArgs;
+assertEquals(Foo.arguments, newArgs);
+
+// Don't allow arguments to be deleted.
+assertFalse(delete Foo.arguments);
+assertEquals(Foo.arguments, newArgs);
diff --git a/deps/v8/test/mjsunit/bugs/bug-223.js b/deps/v8/test/mjsunit/bugs/bug-223.js
new file mode 100644
index 0000000..04b296b
--- /dev/null
+++ b/deps/v8/test/mjsunit/bugs/bug-223.js
@@ -0,0 +1,39 @@
+// Copyright 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.
+
+// When calling user-defined functions on strings, booleans or
+// numbers, we should create a wrapper object.
+
+function TypeOfThis() { return typeof this; }
+
+String.prototype.TypeOfThis = TypeOfThis;
+Boolean.prototype.TypeOfThis = TypeOfThis;
+Number.prototype.TypeOfThis = TypeOfThis;
+
+assertEquals('object', 'xxx'.TypeOfThis());
+assertEquals('object', true.TypeOfThis());
+assertEquals('object', (42).TypeOfThis());
diff --git a/deps/v8/test/mjsunit/bugs/bug-900066.js b/deps/v8/test/mjsunit/bugs/bug-900066.js
new file mode 100644
index 0000000..3b7cc3f
--- /dev/null
+++ b/deps/v8/test/mjsunit/bugs/bug-900066.js
@@ -0,0 +1,38 @@
+// Copyright 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.
+
+// When a property of the arguments array is deleted, it
+// must be "disconnected" from the corresponding parameter.
+// Re-introducing the property does not connect to the parameter.
+
+function f(x) {
+  delete arguments[0];
+  arguments[0] = 100;
+  return x;
+}
+
+assertEquals(10, f(10));
diff --git a/deps/v8/test/mjsunit/bugs/bug-941049.js b/deps/v8/test/mjsunit/bugs/bug-941049.js
new file mode 100644
index 0000000..f68c37a
--- /dev/null
+++ b/deps/v8/test/mjsunit/bugs/bug-941049.js
@@ -0,0 +1,100 @@
+// Copyright 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.
+
+// This test fails because we copy the arguments array on indirect
+// access
+
+function g(f) {
+  assertEquals(100, f.arguments = 100);  // read-only
+  assertEquals(3, f.arguments.length);
+  assertEquals(1, f.arguments[0]);
+  assertEquals(2, f.arguments[1]);
+  assertEquals(3, f.arguments[2]);
+  f.arguments[0] = 999;
+  f.arguments.extra = 'kallevip';
+}
+
+function h(f) {
+  assertEquals('kallevip', f.arguments.extra);
+  return f.arguments;
+}
+
+// Test function with a materialized arguments array.
+function f0() {
+  g(f0);
+  var result = h(f0);
+  var a = arguments;
+  assertEquals(999, a[0]);
+  return result;
+}
+
+
+// Test function without a materialized arguments array.
+function f1(x) {
+  g(f1);
+  var result = h(f1);
+  assertEquals(999, x);
+  return result;
+}
+
+
+function test(f) {
+  assertTrue(null === f.arguments);
+  var args = f(1,2,3);
+  assertTrue(null === f.arguments);
+
+  assertEquals(3, args.length);
+  assertEquals(999, args[0]);
+  assertEquals(2, args[1]);
+  assertEquals(3, args[2]);
+  assertEquals('kallevip', args.extra);
+}
+
+test(f0);
+test(f1);
+
+
+
+
+function w() {
+  return q.arguments;
+}
+
+function q(x, y) {
+  x = 2;
+  var result = w();
+  y = 3;
+  return result;
+}
+
+var a = q(0, 1);
+// x is set locally *before* the last use of arguments before the
+// activation of q is popped from the stack.
+assertEquals(2, a[0]);
+// y is set locally *after* the last use of arguments before the
+// activation of q is popped from the stack.
+assertEquals(1, a[1]);
diff --git a/deps/v8/test/mjsunit/call-non-function-call.js b/deps/v8/test/mjsunit/call-non-function-call.js
new file mode 100644
index 0000000..6088fc3
--- /dev/null
+++ b/deps/v8/test/mjsunit/call-non-function-call.js
@@ -0,0 +1,38 @@
+// Copyright 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.
+
+// Throw exception when invoking Function.prototype.call with a
+// non-function receiver.
+var caught = false;
+try {
+  Function.prototype.call.call({});
+  assertTrue(false);
+} catch (e) {
+  caught = true;
+  assertTrue(e instanceof TypeError);
+}
+assertTrue(caught);
diff --git a/deps/v8/test/mjsunit/call-non-function.js b/deps/v8/test/mjsunit/call-non-function.js
new file mode 100644
index 0000000..8ed5ccb
--- /dev/null
+++ b/deps/v8/test/mjsunit/call-non-function.js
@@ -0,0 +1,54 @@
+// Copyright 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.
+
+function TryCall(x) {
+  var caught = [];
+  try {
+    x();
+  } catch (e) {
+    caught.push(e);
+  }
+
+  try {
+    new x();
+  } catch (e) {
+    caught.push(e);
+  }
+
+  assertTrue(caught[0] instanceof TypeError);
+  assertTrue(caught[1] instanceof TypeError);
+};
+
+
+TryCall(this);
+TryCall(Math);
+TryCall(true);
+TryCall(1234);
+TryCall("hest");
+
+
+
diff --git a/deps/v8/test/mjsunit/call.js b/deps/v8/test/mjsunit/call.js
new file mode 100644
index 0000000..b873d7d
--- /dev/null
+++ b/deps/v8/test/mjsunit/call.js
@@ -0,0 +1,87 @@
+// Copyright 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.
+
+function f0() {
+  return this;
+}
+
+assertTrue(this === f0.call(), "1");
+
+assertTrue(this === f0.call(this), "w");
+assertTrue(this === f0.call(this, 1), "w");
+assertTrue(this === f0.call(this, 1, 2), "w");
+
+assertTrue(this === f0.call(null), "3a");
+assertTrue(this === f0.call(null, 1), "3b");
+assertTrue(this === f0.call(null, 1, 2), "3c");
+
+assertTrue(this === f0.call(void 0), "4a");
+assertTrue(this === f0.call(void 0, 1), "4b");
+assertTrue(this === f0.call(void 0, 1, 2), "4c");
+
+var x = {};
+assertTrue(x === f0.call(x));
+assertTrue(x === f0.call(x, 1));
+assertTrue(x === f0.call(x, 1, 2));
+
+
+function f1(a) {
+  a = a || 'i';
+  return this[a];
+}
+
+assertEquals(1, f1.call({i:1}));
+assertEquals(42, f1.call({i:42}, 'i'));
+assertEquals(87, f1.call({j:87}, 'j', 1));
+assertEquals(99, f1.call({k:99}, 'k', 1, 2));
+
+
+function f2(a, b) {
+  a = a || 'n';
+  b = b || 2;
+  return this[a] + b;
+}
+
+var x = {n: 1};
+assertEquals(3, f2.call(x));
+assertEquals(14, f2.call({i:12}, 'i'));
+assertEquals(42, f2.call(x, 'n', 41));
+assertEquals(87, f2.call(x, 'n', 86, 1));
+assertEquals(99, f2.call(x, 'n', 98, 1, 2));
+
+
+function fn() {
+  return arguments.length;
+}
+
+assertEquals(0, fn.call());
+assertEquals(0, fn.call(this));
+assertEquals(0, fn.call(null));
+assertEquals(0, fn.call(void 0));
+assertEquals(1, fn.call(this, 1));
+assertEquals(2, fn.call(this, 1, 2));
+assertEquals(3, fn.call(this, 1, 2, 3));
diff --git a/deps/v8/test/mjsunit/char-escape.js b/deps/v8/test/mjsunit/char-escape.js
new file mode 100644
index 0000000..a1b3429
--- /dev/null
+++ b/deps/v8/test/mjsunit/char-escape.js
@@ -0,0 +1,53 @@
+// Copyright 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.
+
+// Check that character escapes are understood as one char
+var escapes = ["\b", "\t", "\n", "\v", "\f", "\r", "\"", "\'", "\\", "\x4a", "\u005f"];
+for (var i = 0; i < escapes.length; i++) {
+  var str = escapes[i];
+  assertEquals(1, str.length);
+  assertEquals(str, str.charAt(0));
+}
+
+function code(str) {
+  return str.charCodeAt(0);
+}
+
+// Do the single escape chars have the right value?
+assertEquals(0x08, code("\b"));
+assertEquals(0x09, code("\t"));
+assertEquals(0x0A, code("\n"));
+assertEquals(0x0B, code("\v"));
+assertEquals(0x0C, code("\f"));
+assertEquals(0x0D, code("\r"));
+assertEquals(0x22, code("\""));
+assertEquals(0x27, code("\'"));
+assertEquals(0x5c, code("\\"));
+
+// Do the hex and unicode escape chars have the right value?
+assertEquals(0x4a, code("\x4a"));
+assertEquals(0x5f, code("\u005f"));
diff --git a/deps/v8/test/mjsunit/class-of-builtins.js b/deps/v8/test/mjsunit/class-of-builtins.js
new file mode 100644
index 0000000..40c958c
--- /dev/null
+++ b/deps/v8/test/mjsunit/class-of-builtins.js
@@ -0,0 +1,50 @@
+// Copyright 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.
+
+// The [[Class]] property of (instances of) builtin functions must be
+// correctly set.
+var funs = {
+  Object:   [ Object ],
+  Function: [ Function ],
+  Array:    [ Array ],
+  String:   [ String ],
+  Boolean:  [ Boolean ],
+  Number:   [ Number ],
+  Date:     [ Date ],
+  RegExp:   [ RegExp ],  
+  Error:    [ Error, TypeError, RangeError, SyntaxError, ReferenceError, EvalError, URIError ]
+}
+for (f in funs) {
+  for (i in funs[f]) {
+    assertEquals("[object " + f + "]",
+                 Object.prototype.toString.call(new funs[f][i]),
+                 funs[f][i]);
+    assertEquals("[object Function]",
+                 Object.prototype.toString.call(funs[f][i]),
+                 funs[f][i]);
+  }
+}
diff --git a/deps/v8/test/mjsunit/closure.js b/deps/v8/test/mjsunit/closure.js
new file mode 100644
index 0000000..b1460d3
--- /dev/null
+++ b/deps/v8/test/mjsunit/closure.js
@@ -0,0 +1,37 @@
+// Copyright 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.
+
+// This test is lifted an old bug (ic_context_bug.js).
+
+function f(n) {
+  return function () { return n; }
+}
+
+for (var i = 0; i < 10; i++) {
+  var a = f(i);
+  assertEquals(i, a());
+}
diff --git a/deps/v8/test/mjsunit/compare-nan.js b/deps/v8/test/mjsunit/compare-nan.js
new file mode 100644
index 0000000..29818c8
--- /dev/null
+++ b/deps/v8/test/mjsunit/compare-nan.js
@@ -0,0 +1,44 @@
+// Copyright 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.
+
+var a = [NaN, -1, 0, 1, 1.2, -7.9, true, false, 'foo', '0', 'NaN' ];
+for (var i in a) {
+  var x = a[i];
+  assertFalse(NaN == x); 
+  assertFalse(NaN === x); 
+  assertFalse(NaN < x);
+  assertFalse(NaN > x);
+  assertFalse(NaN <= x);
+  assertFalse(NaN >= x);
+
+  assertFalse(x == NaN); 
+  assertFalse(x === NaN); 
+  assertFalse(x < NaN);
+  assertFalse(x > NaN);
+  assertFalse(x <= NaN);
+  assertFalse(x >= NaN);
+}
diff --git a/deps/v8/test/mjsunit/const-declaration.js b/deps/v8/test/mjsunit/const-declaration.js
new file mode 100644
index 0000000..48c0cf2
--- /dev/null
+++ b/deps/v8/test/mjsunit/const-declaration.js
@@ -0,0 +1,172 @@
+// 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.
+
+// Test handling of const variables in various settings.
+
+(function () {
+  function f() {
+    function g() {
+      x = 42;  //  should be ignored
+      return x;  // force x into context
+    }
+    x = 43;  // should be ignored
+    assertEquals(undefined, g());
+    x = 44;  // should be ignored
+    const x = 0;
+    x = 45;  // should be ignored
+    assertEquals(0, g());
+  }
+  f();
+})();
+
+
+(function () {
+  function f() {
+    function g() {
+      with ({foo: 0}) {
+        x = 42;  //  should be ignored
+        return x;  // force x into context
+      }
+    }
+    x = 43;  // should be ignored
+    assertEquals(undefined, g());
+    x = 44;  // should be ignored
+    const x = 0;
+    x = 45;  // should be ignored
+    assertEquals(0, g());
+  }
+  f();
+})();
+
+
+(function () {
+  function f() {
+    function g(s) {
+      eval(s);
+      return x;  // force x into context
+    }
+    x = 43;  // should be ignored
+    assertEquals(undefined, g("x = 42;"));
+    x = 44;  // should be ignored
+    const x = 0;
+    x = 45;  // should be ignored
+    assertEquals(0, g("x = 46;"));
+  }
+  f();
+})();
+
+
+(function () {
+  function f() {
+    function g(s) {
+      with ({foo: 0}) {
+        eval(s);
+        return x;  // force x into context
+      }
+    }
+    x = 43;  // should be ignored
+    assertEquals(undefined, g("x = 42;"));
+    x = 44;  // should be ignored
+    const x = 0;
+    x = 45;  // should be ignored
+    assertEquals(0, g("x = 46;"));
+  }
+  f();
+})();
+
+
+(function () {
+  function f(s) {
+    function g() {
+      x = 42;  // assign to global x, or to const x
+      return x;
+    }
+    x = 43;  // declare global x
+    assertEquals(42, g());
+    x = 44;  // assign to global x
+    eval(s);
+    x = 45;  // should be ignored (assign to const x)
+    assertEquals(0, g());
+  }
+  f("const x = 0;");
+})();
+
+
+(function () {
+  function f(s) {
+    function g() {
+      with ({foo: 0}) {
+        x = 42;  // assign to global x, or to const x
+        return x;
+      }
+    }
+    x = 43;  // declare global x
+    assertEquals(42, g());
+    x = 44;  // assign to global x
+    eval(s);
+    x = 45;  // should be ignored (assign to const x)
+    assertEquals(0, g());
+  }
+  f("const x = 0;");
+})();
+
+
+(function () {
+  function f(s) {
+    function g(s) {
+      eval(s);
+      return x;
+    }
+    x = 43;  // declare global x
+    assertEquals(42, g("x = 42;"));
+    x = 44;  // assign to global x
+    eval(s);
+    x = 45;  // should be ignored (assign to const x)
+    assertEquals(0, g("x = 46;"));
+  }
+  f("const x = 0;");
+})();
+
+
+(function () {
+  function f(s) {
+    function g(s) {
+      with ({foo: 0}) {
+        eval(s);
+        return x;
+      }
+    }
+    x = 43;  // declare global x
+    assertEquals(42, g("x = 42;"));
+    x = 44;  // assign to global x
+    eval(s);
+    x = 45;  // should be ignored (assign to const x)
+    assertEquals(0, g("x = 46;"));
+  }
+  f("const x = 0;");
+})();
+
diff --git a/deps/v8/test/mjsunit/const-eval-init.js b/deps/v8/test/mjsunit/const-eval-init.js
new file mode 100644
index 0000000..d3636de
--- /dev/null
+++ b/deps/v8/test/mjsunit/const-eval-init.js
@@ -0,0 +1,111 @@
+// 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.
+
+// Test the handling of initialization of deleted const variables.
+// This only makes sense in local scopes since the declaration and
+// initialization of consts in the global scope happen at the same
+// time.
+
+function testIntroduceGlobal() {
+  var source =
+      // Deleting 'x' removes the local const property.
+      "delete x;" +
+      // Initialization turns into assignment to global 'x'.
+      "const x = 3; assertEquals(3, x);" +
+      // No constness of the global 'x'.
+      "x = 4; assertEquals(4, x);";
+  eval(source);
+}
+
+testIntroduceGlobal();
+assertEquals(4, x);
+
+function testAssignExistingGlobal() {
+  var source =
+      // Delete 'x' to remove the local const property.
+      "delete x;" +
+      // Initialization turns into assignment to global 'x'.
+      "const x = 5; assertEquals(5, x);" +
+      // No constness of the global 'x'.
+      "x = 6; assertEquals(6, x);";
+  eval(source);
+}
+
+testAssignExistingGlobal();
+assertEquals(6, x);
+
+function testAssignmentArgument(x) {
+  function local() {
+    var source = "delete x; const x = 7; assertEquals(7, x)";
+    eval(source);
+  }
+  local();
+  assertEquals(7, x);
+}
+
+testAssignmentArgument();
+assertEquals(6, x);
+
+__defineSetter__('x', function() { throw 42; });
+function testAssignGlobalThrows() {
+  // Initialization turns into assignment to global 'x' which
+  // throws an exception.
+  var source = "delete x; const x = 8";
+  eval(source);
+}
+
+assertThrows("testAssignGlobalThrows()");
+
+function testInitFastCaseExtension() {
+  var source = "const x = 9; assertEquals(9, x); x = 10; assertEquals(9, x)";
+  eval(source);
+}
+
+testInitFastCaseExtension();
+
+function testInitSlowCaseExtension() {
+  var source = "";
+  // Introduce 100 properties on the context extension object to force
+  // it in slow case.
+  for (var i = 0; i < 100; i++) source += ("var a" + i + " = i;");
+  source += "const x = 10; assertEquals(10, x); x = 11; assertEquals(10, x)";
+  eval(source);
+}
+
+testInitSlowCaseExtension();
+
+function testAssignSurroundingContextSlot() {
+  var x = 12;
+  function local() {
+    var source = "delete x; const x = 13; assertEquals(13, x)";
+    eval(source);
+  }
+  local();
+  assertEquals(13, x);
+}
+
+testAssignSurroundingContextSlot();
diff --git a/deps/v8/test/mjsunit/const-redecl.js b/deps/v8/test/mjsunit/const-redecl.js
new file mode 100644
index 0000000..26d765b
--- /dev/null
+++ b/deps/v8/test/mjsunit/const-redecl.js
@@ -0,0 +1,220 @@
+// Copyright 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.
+
+// Test for const semantics.
+
+
+function CheckException(e) {
+  var string = e.toString();
+  var index = string.indexOf(':');
+  assertTrue(index >= 0);
+  var name = string.slice(0, index);
+  assertTrue(string.indexOf("has already been declared") >= 0 ||
+             string.indexOf("redeclaration") >= 0);
+  if (name == 'SyntaxError') return 'TypeError';
+  return name;
+}
+
+
+function TestLocal(s,e) {
+  try {
+    return eval("(function(){" + s + ";return " + e + "})")();
+  } catch (x) {
+    return CheckException(x);
+  }
+}
+
+
+// NOTE: TestGlobal usually only tests the given string in the context
+// of a global object in dictionary mode. This is because we use
+// delete to get rid of any added properties.
+function TestGlobal(s,e) {
+  // Collect the global properties before the call.
+  var properties = [];
+  for (var key in this) properties.push(key); 
+  // Compute the result.
+  var result;
+  try {
+    var code = s + (e ? "; $$$result=" + e : "");
+    if (this.execScript) {
+      execScript(code);
+    } else {
+      this.eval(code);
+    }
+    // Avoid issues if $$$result is not defined by
+    // reading it through this.
+    result = this.$$$result;
+  } catch (x) {
+    result = CheckException(x);
+  }
+  // Get rid of any introduced global properties before
+  // returning the result.
+  for (var key in this) {
+    if (properties.indexOf(key) == -1) delete this[key];
+  }
+  return result;
+}
+
+
+function TestContext(s,e) {
+  try {
+    // Use a with-statement to force the system to do dynamic
+    // declarations of the introduced variables or constants.
+    with ({}) {
+      return eval(s + ";" + e);
+    }
+  } catch (x) {
+    return CheckException(x);
+  }
+}
+
+
+function TestAll(expected,s,opt_e) {
+  var e = "";
+  var msg = s;
+  if (opt_e) { e = opt_e; msg += "; " + opt_e; }
+  assertEquals(expected, TestLocal(s,e), "local:'" + msg + "'");
+  assertEquals(expected, TestGlobal(s,e), "global:'" + msg + "'");
+  assertEquals(expected, TestContext(s,e), "context:'" + msg + "'");
+}
+
+
+function TestConflict(def0, def1) {
+  // No eval.
+  TestAll("TypeError", def0 +'; ' + def1);
+  // Eval everything.
+  TestAll("TypeError", 'eval("' + def0 + '; ' + def1 + '")');
+  // Eval first definition.
+  TestAll("TypeError", 'eval("' + def0 +'"); ' + def1);
+  // Eval second definition.
+  TestAll("TypeError", def0 + '; eval("' + def1 + '")');
+  // Eval both definitions separately.
+  TestAll("TypeError", 'eval("' + def0 +'"); eval("' + def1 + '")');  
+}
+
+
+// Test conflicting definitions.
+TestConflict("const x", "var x");
+TestConflict("const x = 0", "var x");
+TestConflict("const x", "var x = 0");
+TestConflict("const x = 0", "var x = 0");
+
+TestConflict("var x", "const x");
+TestConflict("var x = 0", "const x");
+TestConflict("var x", "const x = 0");
+TestConflict("var x = 0", "const x = 0");
+
+TestConflict("const x = undefined", "var x");
+TestConflict("const x", "var x = undefined");
+TestConflict("const x = undefined", "var x = undefined");
+
+TestConflict("var x = undefined", "const x");
+TestConflict("var x", "const x = undefined");
+TestConflict("var x = undefined", "const x = undefined");
+
+TestConflict("const x = undefined", "var x = 0");
+TestConflict("const x = 0", "var x = undefined");
+
+TestConflict("var x = undefined", "const x = 0");
+TestConflict("var x = 0", "const x = undefined");
+
+TestConflict("const x", "function x() { }");
+TestConflict("const x = 0", "function x() { }");
+TestConflict("const x = undefined", "function x() { }");
+
+TestConflict("function x() { }", "const x");
+TestConflict("function x() { }", "const x = 0");
+TestConflict("function x() { }", "const x = undefined");
+
+TestConflict("const x, y", "var x");
+TestConflict("const x, y", "var y");
+TestConflict("const x = 0, y", "var x");
+TestConflict("const x = 0, y", "var y");
+TestConflict("const x, y = 0", "var x");
+TestConflict("const x, y = 0", "var y");
+TestConflict("const x = 0, y = 0", "var x");
+TestConflict("const x = 0, y = 0", "var y");
+
+TestConflict("var x", "const x, y");
+TestConflict("var y", "const x, y");
+TestConflict("var x", "const x = 0, y");
+TestConflict("var y", "const x = 0, y");
+TestConflict("var x", "const x, y = 0");
+TestConflict("var y", "const x, y = 0");
+TestConflict("var x", "const x = 0, y = 0");
+TestConflict("var y", "const x = 0, y = 0");
+
+
+// Test that multiple conflicts do not cause issues.
+TestConflict("var x, y", "const x, y");
+
+
+// Test that repeated const declarations throw redeclaration errors.
+TestConflict("const x", "const x");
+TestConflict("const x = 0", "const x");
+TestConflict("const x", "const x = 0");
+TestConflict("const x = 0", "const x = 0");
+
+TestConflict("const x = undefined", "const x");
+TestConflict("const x", "const x = undefined");
+TestConflict("const x = undefined", "const x = undefined");
+
+TestConflict("const x = undefined", "const x = 0");
+TestConflict("const x = 0", "const x = undefined");
+
+TestConflict("const x, y", "const x");
+TestConflict("const x, y", "const y");
+TestConflict("const x = 0, y", "const x");
+TestConflict("const x = 0, y", "const y");
+TestConflict("const x, y = 0", "const x");
+TestConflict("const x, y = 0", "const y");
+TestConflict("const x = 0, y = 0", "const x");
+TestConflict("const x = 0, y = 0", "const y");
+
+TestConflict("const x", "const x, y");
+TestConflict("const y", "const x, y");
+TestConflict("const x", "const x = 0, y");
+TestConflict("const y", "const x = 0, y");
+TestConflict("const x", "const x, y = 0");
+TestConflict("const y", "const x, y = 0");
+TestConflict("const x", "const x = 0, y = 0");
+TestConflict("const y", "const x = 0, y = 0");
+
+
+// Test that multiple const conflicts do not cause issues.
+TestConflict("const x, y", "const x, y");
+
+
+// Test that const inside loop behaves correctly.
+var loop = "for (var i = 0; i < 3; i++) { const x = i; }";
+TestAll(0, loop, "x");
+TestAll(0, "var a,b,c,d,e,f,g,h; " + loop, "x");
+
+
+// Test that const inside with behaves correctly.
+TestAll(87, "with ({x:42}) { const x = 87; }", "x");
+TestAll(undefined, "with ({x:42}) { const x; }", "x");
diff --git a/deps/v8/test/mjsunit/const.js b/deps/v8/test/mjsunit/const.js
new file mode 100644
index 0000000..a48e82d
--- /dev/null
+++ b/deps/v8/test/mjsunit/const.js
@@ -0,0 +1,70 @@
+// Copyright 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.
+
+// Test const properties and pre/postfix operation.
+function f() {
+  const x = 1;
+  x++;
+  assertEquals(1, x);
+  x--;
+  assertEquals(1, x);
+  ++x;
+  assertEquals(1, x);
+  --x;
+  assertEquals(1, x);
+  assertEquals(1, x++);
+  assertEquals(1, x--);
+  assertEquals(2, ++x);
+  assertEquals(0, --x);
+}
+
+f();
+
+// Test that the value is read eventhough assignment is disallowed.
+// Spidermonkey does not do this, but it seems like the right thing to
+// do so that 'o++' is equivalent to 'o = o + 1'.
+var valueOfCount = 0;
+
+function g() {
+  const o = { valueOf: function() { valueOfCount++; return 42; } }
+  assertEquals(42, o);
+  assertEquals(1, valueOfCount);
+  o++;
+  assertEquals(42, o);
+  assertEquals(3, valueOfCount);
+  ++o;
+  assertEquals(42, o);
+  assertEquals(5, valueOfCount);
+  o--;
+  assertEquals(42, o);
+  assertEquals(7, valueOfCount);
+  --o;
+  assertEquals(42, o);
+  assertEquals(9, valueOfCount);
+}
+
+g();
diff --git a/deps/v8/test/mjsunit/constant-folding.js b/deps/v8/test/mjsunit/constant-folding.js
new file mode 100644
index 0000000..41b632f
--- /dev/null
+++ b/deps/v8/test/mjsunit/constant-folding.js
@@ -0,0 +1,171 @@
+// 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.
+
+// Test operations that involve one or more constants.
+// The code generator now handles compile-time constants specially.
+// Test the code generated when operands are known at compile time
+
+// Test count operations involving constants
+function test_count() {
+  var x = "foo";
+  var y = "3";
+
+  x += x++;  // ++ and -- apply ToNumber to their operand, even for postfix.
+  assertEquals(x, "fooNaN", "fooNaN test");
+  x = "luft";
+  x += ++x;
+  assertEquals(x, "luftNaN", "luftNaN test");
+
+  assertTrue(y++ === 3, "y++ === 3, where y = \"3\"");
+  y = 3;
+  assertEquals(y++, 3, "y++ == 3, where y = 3");
+  y = "7.1";
+  assertTrue(y++ === 7.1, "y++ === 7.1, where y = \"7.1\"");
+  var z = y = x = "9";
+  assertEquals( z++ + (++y) + x++, 28, "z++ + (++y) + x++ == 28");
+  z = y = x = 13;
+  assertEquals( z++ + (++y) + x++, 40, "z++ + (++y) + x++ == 40");
+  z = y = x = -5.5;
+  assertEquals( z++ + (++y) + x++, -15.5, "z++ + (++y) + x++ == -15.5");
+
+  assertEquals(y, -4.5);
+  z = y;
+  z++;
+  assertEquals(y, -4.5);
+  z = y;
+  y++;
+  assertEquals(z, -4.5);
+
+  y = 20;
+  z = y;
+  z++;
+  assertEquals(y, 20);
+  z = y;
+  y++;
+  assertEquals(z, 20);
+
+  const w = 30;
+  assertEquals(w++, 30);
+  assertEquals(++w, 31);
+  assertEquals(++w, 31);
+}
+
+test_count();
+
+// Test comparison operations that involve one or two constant smis.
+
+function test() {
+  var i = 5;
+  var j = 3;
+
+  assertTrue( j < i );
+  i = 5; j = 3;
+  assertTrue( j <= i );
+  i = 5; j = 3;
+  assertTrue( i > j );
+  i = 5; j = 3;
+  assertTrue( i >= j );
+  i = 5; j = 3;
+  assertTrue( i != j );
+  i = 5; j = 3;
+  assertTrue( i == i );
+  i = 5; j = 3;
+  assertFalse( i < j );
+  i = 5; j = 3;
+  assertFalse( i <= j );
+  i = 5; j = 3;
+  assertFalse( j > i );
+  i = 5; j = 3;
+  assertFalse(j >= i );
+  i = 5; j = 3;
+  assertFalse( j == i);
+  i = 5; j = 3;
+  assertFalse( i != i);
+
+  i = 10 * 10;
+  while ( i < 107 ) {
+    ++i;
+  }
+  j = 21;
+
+  assertTrue( j < i );
+  j = 21;
+  assertTrue( j <= i );
+  j = 21;
+  assertTrue( i > j );
+  j = 21;
+  assertTrue( i >= j );
+  j = 21;
+  assertTrue( i != j );
+  j = 21;
+  assertTrue( i == i );
+  j = 21;
+  assertFalse( i < j );
+  j = 21;
+  assertFalse( i <= j );
+  j = 21;
+  assertFalse( j > i );
+  j = 21;
+  assertFalse(j >= i );
+  j = 21;
+  assertFalse( j == i);
+  j = 21;
+  assertFalse( i != i);
+  j = 21;
+  assertTrue( j == j );
+  j = 21;
+  assertFalse( j != j );
+
+  assertTrue( 100 > 99 );
+  assertTrue( 101 >= 90 );
+  assertTrue( 11111 > -234 );
+  assertTrue( -888 <= -20 );
+
+  while ( 234 > 456 ) {
+    i = i + 1;
+  }
+
+  switch(3) {
+    case 5:
+      assertUnreachable();
+      break;
+    case 3:
+      j = 13;
+    default:
+      i = 2;
+    case 7:
+      j = 17;
+      break;
+    case 9:
+      j = 19;
+      assertUnreachable();
+      break;
+  }
+  assertEquals(17, j, "switch with constant value");
+}
+
+test();
diff --git a/deps/v8/test/mjsunit/context-variable-assignments.js b/deps/v8/test/mjsunit/context-variable-assignments.js
new file mode 100644
index 0000000..930b969
--- /dev/null
+++ b/deps/v8/test/mjsunit/context-variable-assignments.js
@@ -0,0 +1,37 @@
+// Copyright 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.
+
+function foo() {
+  var a, b;
+  var bar = function() {
+    a = b = "hello world";
+  }
+  bar();
+  return a;
+}
+
+assertEquals("hello world", foo());
diff --git a/deps/v8/test/mjsunit/cyclic-array-to-string.js b/deps/v8/test/mjsunit/cyclic-array-to-string.js
new file mode 100644
index 0000000..0a2d6e3
--- /dev/null
+++ b/deps/v8/test/mjsunit/cyclic-array-to-string.js
@@ -0,0 +1,65 @@
+// Copyright 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.
+
+// Test printing of cyclic arrays.
+
+var a1 = [1,2];
+assertEquals("1,2", a1.toString());
+assertEquals("1,2", a1.toLocaleString());
+assertEquals("1,2", a1.join());
+a1.push(a1);
+assertEquals("1,2,", a1.toString());
+assertEquals("1,2,", a1.toLocaleString());
+assertEquals("1,2,", a1.join());
+a1.push(1);
+assertEquals("1,2,,1", a1.toString());
+assertEquals("1,2,,1", a1.toLocaleString());
+assertEquals("1,2,,1", a1.join());
+a1.push(a1);
+assertEquals("1,2,,1,", a1.toString());
+assertEquals("1,2,,1,", a1.toLocaleString());
+assertEquals("1,2,,1,", a1.join());
+
+a1 = [1,2];
+var a2 = [3,4];
+a1.push(a2);
+a1.push(a2);
+assertEquals("1,2,3,4,3,4", a1.toString());
+assertEquals("1,2,3,4,3,4", a1.toLocaleString());
+assertEquals("1,2,3,4,3,4", a1.join());
+a2.push(a1);
+assertEquals("1,2,3,4,,3,4,", a1.toString());
+assertEquals("1,2,3,4,,3,4,", a1.toLocaleString());
+assertEquals("1,2,3,4,,3,4,", a1.join());
+
+a1 = [];
+a2 = [a1];
+a1.push(a2);
+assertEquals("", a1.toString());
+assertEquals("", a1.toLocaleString());
+assertEquals("", a1.join());
+
diff --git a/deps/v8/test/mjsunit/d8-os.js b/deps/v8/test/mjsunit/d8-os.js
new file mode 100644
index 0000000..630a39e
--- /dev/null
+++ b/deps/v8/test/mjsunit/d8-os.js
@@ -0,0 +1,180 @@
+// 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.
+
+// Test the OS module of d8.  This test only makes sense with d8.  It
+// only does non-trivial work on Unix since os.system() is not currently
+// implemented on Windows, and even if it were then many of the things
+// we are calling would not be available.
+
+function arg_error(str) {
+  try {
+    eval(str);
+  } catch (e) {
+    assertTrue(/rgument/.test(e), str);
+  }
+}
+
+
+function str_error(str) {
+  var e = new Object();
+  e.toString = function() { throw new Error("foo bar"); }
+  try {
+    eval(str);
+  } catch (exception) {
+    assertTrue(/tring conversion/.test(exception), str);
+  }
+}
+
+
+if (this.os && os.system) {
+  try {
+    // Delete the dir if it is lying around from last time.
+    os.system("ls", ["d8-os-test-directory"]);
+    os.system("rm", ["-r", "d8-os-test-directory"]);
+  } catch (e) {
+  }
+  os.mkdirp("d8-os-test-directory");
+  os.chdir("d8-os-test-directory");
+  // Check the chdir worked.
+  os.system('ls', ['../d8-os-test-directory']);
+  // Simple create dir.
+  os.mkdirp("dir");
+  // Create dir in dir.
+  os.mkdirp("dir/foo");
+  // Check that they are there.
+  os.system('ls', ['dir/foo']);
+  // Check that we can detect when something is not there.
+  assertThrows("os.system('ls', ['dir/bar']);", "dir not there");
+  // Check that mkdirp makes intermediate directories.
+  os.mkdirp("dir2/foo");
+  os.system("ls", ["dir2/foo"]);
+  // Check that mkdirp doesn't mind if the dir is already there.
+  os.mkdirp("dir2/foo");
+  os.mkdirp("dir2/foo/");
+  // Check that mkdirp can cope with trailing /
+  os.mkdirp("dir3/");
+  os.system("ls", ["dir3"]);
+  // Check that we get an error if the name is taken by a file.
+  os.system("sh", ["-c", "echo foo > file1"]);
+  os.system("ls", ["file1"]);
+  assertThrows("os.mkdirp('file1');", "mkdir over file1");
+  assertThrows("os.mkdirp('file1/foo');", "mkdir over file2");
+  assertThrows("os.mkdirp('file1/');", "mkdir over file3");
+  assertThrows("os.mkdirp('file1/foo/');", "mkdir over file4");
+  // Create a dir we cannot read.
+  os.mkdirp("dir4", 0);
+  // This test fails if you are root since root can read any dir.
+  assertThrows("os.chdir('dir4');", "chdir dir4 I");
+  os.rmdir("dir4");
+  assertThrows("os.chdir('dir4');", "chdir dir4 II");
+  // Set umask.
+  var old_umask = os.umask(0777);
+  // Create a dir we cannot read.
+  os.mkdirp("dir5");
+  // This test fails if you are root since root can read any dir.
+  assertThrows("os.chdir('dir5');", "cd dir5 I");
+  os.rmdir("dir5");
+  assertThrows("os.chdir('dir5');", "chdir dir5 II");
+  os.umask(old_umask);
+
+  os.mkdirp("hest/fisk/../fisk/ged");
+  os.system("ls", ["hest/fisk/ged"]);
+
+  os.setenv("FOO", "bar");
+  var environment = os.system("printenv");
+  assertTrue(/FOO=bar/.test(environment));
+
+  // Check we time out.
+  var have_sleep = true;
+  var have_echo = true;
+  try {
+    os.system("ls", ["/bin/sleep"]);
+  } catch (e) {
+    have_sleep = false;
+  }
+  try {
+    os.system("ls", ["/bin/echo"]);
+  } catch (e) {
+    have_echo = false;
+  }
+  if (have_sleep) {
+    assertThrows("os.system('sleep', ['2000'], 200);", "sleep 1");
+
+    // Check we time out with total time.
+    assertThrows("os.system('sleep', ['2000'], -1, 200);", "sleep 2");
+
+    // Check that -1 means no timeout.
+    os.system('sleep', ['1'], -1, -1);
+
+  }
+
+  // Check that we don't fill up the process table with zombies.
+  // Disabled because it's too slow.
+  if (have_echo) {
+    //for (var i = 0; i < 65536; i++) {
+      assertEquals("baz\n", os.system("echo", ["baz"]));
+    //}
+  }
+
+  os.chdir("..");
+  os.system("rm", ["-r", "d8-os-test-directory"]);
+
+  // Too few args.
+  arg_error("os.umask();");
+  arg_error("os.system();");
+  arg_error("os.mkdirp();");
+  arg_error("os.chdir();");
+  arg_error("os.setenv();");
+  arg_error("os.rmdir();");
+
+  // Too many args.
+  arg_error("os.setenv('FOO=bar');");
+  arg_error("os.umask(0, 0);");
+  arg_error("os.system('ls', [], -1, -1, -1);");
+  arg_error("os.mkdirp('foo', 0, 0)");
+  arg_error("os.chdir('foo', 'bar')");
+  arg_error("os.rmdir('foo', 'bar');");
+
+  // Wrong kind of args.
+  arg_error("os.umask([]);");
+  arg_error("os.system('ls', 'foo');");
+  arg_error("os.system('ls', 123);");
+  arg_error("os.system('ls', [], 'foo');");
+  arg_error("os.system('ls', [], -1, 'foo');");
+  arg_error("os.mkdirp('foo', 'bar');");
+
+  // Test broken toString().
+  str_error("os.system(e);");
+  str_error("os.system('ls', [e]);");
+  str_error("os.system('ls', ['.', e]);");
+  str_error("os.system('ls', [e, '.']);");
+  str_error("os.mkdirp(e);");
+  str_error("os.setenv(e, 'goo');");
+  str_error("os.setenv('goo', e);");
+  str_error("os.chdir(e);");
+  str_error("os.rmdir(e);");
+}
diff --git a/deps/v8/test/mjsunit/date-parse.js b/deps/v8/test/mjsunit/date-parse.js
new file mode 100644
index 0000000..4464727
--- /dev/null
+++ b/deps/v8/test/mjsunit/date-parse.js
@@ -0,0 +1,268 @@
+// Copyright 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.
+
+// Test that we can parse dates in all the different formats that we
+// have to support.
+//
+// These formats are all supported by KJS but a lot of them are not
+// supported by Spidermonkey.
+
+function testDateParse(string) {
+  var d = Date.parse(string);
+  assertEquals(946713600000, d, string);
+};
+
+
+// For local time we just test that parsing returns non-NaN positive
+// number of milliseconds to make it timezone independent.
+function testDateParseLocalTime(string) {
+  var d = Date.parse(string);
+  assertTrue(!isNaN(d), string + " is NaN.");
+  assertTrue(d > 0, string + " <= 0.");
+};
+
+
+function testDateParseMisc(array) {
+  assertEquals(2, array.length, "array [" + array + "] length != 2.");
+  var string = array[0];
+  var expected = array[1];
+  var d = Date.parse(string);
+  assertEquals(expected, d, string);
+}
+
+
+//
+// Test all the formats in UT timezone.
+//
+var testCasesUT = [
+    'Sat, 01-Jan-2000 08:00:00 UT',
+    'Sat, 01 Jan 2000 08:00:00 UT',
+    'Jan 01 2000 08:00:00 UT',
+    'Jan 01 08:00:00 UT 2000',
+    'Saturday, 01-Jan-00 08:00:00 UT',
+    '01 Jan 00 08:00 +0000',
+    // Ignore weekdays.
+    'Mon, 01 Jan 2000 08:00:00 UT',
+    'Tue, 01 Jan 2000 08:00:00 UT',
+    // Ignore prefix that is not part of a date.
+    '[Saturday] Jan 01 08:00:00 UT 2000',
+    'Ignore all of this stuff because it is annoying 01 Jan 2000 08:00:00 UT',
+    '[Saturday] Jan 01 2000 08:00:00 UT',
+    'All of this stuff is really annnoying, so it will be ignored Jan 01 2000 08:00:00 UT',
+    // If the three first letters of the month is a
+    // month name we are happy - ignore the rest.
+    'Sat, 01-Janisamonth-2000 08:00:00 UT',
+    'Sat, 01 Janisamonth 2000 08:00:00 UT',
+    'Janisamonth 01 2000 08:00:00 UT',
+    'Janisamonth 01 08:00:00 UT 2000',
+    'Saturday, 01-Janisamonth-00 08:00:00 UT',
+    '01 Janisamonth 00 08:00 +0000',
+    // Allow missing space between month and day.
+    'Janisamonthandtherestisignored01 2000 08:00:00 UT',
+    'Jan01 2000 08:00:00 UT',
+    // Allow year/month/day format.
+    'Sat, 2000/01/01 08:00:00 UT',
+    // Allow month/day/year format.
+    'Sat, 01/01/2000 08:00:00 UT',
+    // Allow month/day year format.
+    'Sat, 01/01 2000 08:00:00 UT',
+    // Allow comma instead of space after day, month and year.
+    'Sat, 01,Jan,2000,08:00:00 UT',
+    // Seconds are optional.
+    'Sat, 01-Jan-2000 08:00 UT',
+    'Sat, 01 Jan 2000 08:00 UT',
+    'Jan 01 2000 08:00 UT',
+    'Jan 01 08:00 UT 2000',
+    'Saturday, 01-Jan-00 08:00 UT',
+    '01 Jan 00 08:00 +0000',
+    // Allow AM/PM after the time.
+    'Sat, 01-Jan-2000 08:00 AM UT',
+    'Sat, 01 Jan 2000 08:00 AM UT',
+    'Jan 01 2000 08:00 AM UT',
+    'Jan 01 08:00 AM UT 2000',
+    'Saturday, 01-Jan-00 08:00 AM UT',
+    '01 Jan 00 08:00 AM +0000',
+    // White space and stuff in parenthesis is
+    // apparently allowed in most places where white
+    // space is allowed.
+    '   Sat,   01-Jan-2000   08:00:00   UT  ',
+    '  Sat,   01   Jan   2000   08:00:00   UT  ',
+    '  Saturday,   01-Jan-00   08:00:00   UT  ',
+    '  01    Jan   00    08:00   +0000   ',
+    ' ()(Sat, 01-Jan-2000)  Sat,   01-Jan-2000   08:00:00   UT  ',
+    '  Sat()(Sat, 01-Jan-2000)01   Jan   2000   08:00:00   UT  ',
+    '  Sat,(02)01   Jan   2000   08:00:00   UT  ',
+    '  Sat,  01(02)Jan   2000   08:00:00   UT  ',
+    '  Sat,  01  Jan  2000 (2001)08:00:00   UT  ',
+    '  Sat,  01  Jan  2000 (01)08:00:00   UT  ',
+    '  Sat,  01  Jan  2000 (01:00:00)08:00:00   UT  ',
+    '  Sat,  01  Jan  2000  08:00:00 (CDT)UT  ',
+    '  Sat,  01  Jan  2000  08:00:00  UT((((CDT))))',
+    '  Saturday,   01-Jan-00 ()(((asfd)))(Sat, 01-Jan-2000)08:00:00   UT  ',
+    '  01    Jan   00    08:00 ()(((asdf)))(Sat, 01-Jan-2000)+0000   ',
+    '  01    Jan   00    08:00   +0000()((asfd)(Sat, 01-Jan-2000)) '];
+
+//
+// Test that we do the right correction for different time zones.
+// I'll assume that we can handle the same formats as for UT and only
+// test a few formats for each of the timezones.
+//
+
+// GMT = UT
+var testCasesGMT = [
+    'Sat, 01-Jan-2000 08:00:00 GMT',
+    'Sat, 01-Jan-2000 08:00:00 GMT+0',
+    'Sat, 01-Jan-2000 08:00:00 GMT+00',
+    'Sat, 01-Jan-2000 08:00:00 GMT+000',
+    'Sat, 01-Jan-2000 08:00:00 GMT+0000',
+    'Sat, 01-Jan-2000 08:00:00 GMT+00:00', // Interestingly, KJS cannot handle this.
+    'Sat, 01 Jan 2000 08:00:00 GMT',
+    'Saturday, 01-Jan-00 08:00:00 GMT',
+    '01 Jan 00 08:00 -0000',
+    '01 Jan 00 08:00 +0000'];
+
+// EST = UT minus 5 hours.
+var testCasesEST = [
+    'Sat, 01-Jan-2000 03:00:00 UTC-0500',
+    'Sat, 01-Jan-2000 03:00:00 UTC-05:00', // Interestingly, KJS cannot handle this.
+    'Sat, 01-Jan-2000 03:00:00 EST',
+    'Sat, 01 Jan 2000 03:00:00 EST',
+    'Saturday, 01-Jan-00 03:00:00 EST',
+    '01 Jan 00 03:00 -0500'];
+
+// EDT = UT minus 4 hours.
+var testCasesEDT = [
+    'Sat, 01-Jan-2000 04:00:00 EDT',
+    'Sat, 01 Jan 2000 04:00:00 EDT',
+    'Saturday, 01-Jan-00 04:00:00 EDT',
+    '01 Jan 00 04:00 -0400'];
+
+// CST = UT minus 6 hours.
+var testCasesCST = [
+    'Sat, 01-Jan-2000 02:00:00 CST',
+    'Sat, 01 Jan 2000 02:00:00 CST',
+    'Saturday, 01-Jan-00 02:00:00 CST',
+    '01 Jan 00 02:00 -0600'];
+
+// CDT = UT minus 5 hours.
+var testCasesCDT = [
+    'Sat, 01-Jan-2000 03:00:00 CDT',
+    'Sat, 01 Jan 2000 03:00:00 CDT',
+    'Saturday, 01-Jan-00 03:00:00 CDT',
+    '01 Jan 00 03:00 -0500'];
+
+// MST = UT minus 7 hours.
+var testCasesMST = [
+    'Sat, 01-Jan-2000 01:00:00 MST',
+    'Sat, 01 Jan 2000 01:00:00 MST',
+    'Saturday, 01-Jan-00 01:00:00 MST',
+    '01 Jan 00 01:00 -0700'];
+
+// MDT = UT minus 6 hours.
+var testCasesMDT = [
+    'Sat, 01-Jan-2000 02:00:00 MDT',
+    'Sat, 01 Jan 2000 02:00:00 MDT',
+    'Saturday, 01-Jan-00 02:00:00 MDT',
+    '01 Jan 00 02:00 -0600'];
+
+// PST = UT minus 8 hours.
+var testCasesPST = [
+    'Sat, 01-Jan-2000 00:00:00 PST',
+    'Sat, 01 Jan 2000 00:00:00 PST',
+    'Saturday, 01-Jan-00 00:00:00 PST',
+    '01 Jan 00 00:00 -0800',
+    // Allow missing time.
+    'Sat, 01-Jan-2000 PST'];
+
+// PDT = UT minus 7 hours.
+var testCasesPDT = [
+    'Sat, 01-Jan-2000 01:00:00 PDT',
+    'Sat, 01 Jan 2000 01:00:00 PDT',
+    'Saturday, 01-Jan-00 01:00:00 PDT',
+    '01 Jan 00 01:00 -0700'];
+
+
+// Local time cases.
+var testCasesLocalTime = [
+    // Allow timezone ommision.
+    'Sat, 01-Jan-2000 08:00:00',
+    'Sat, 01 Jan 2000 08:00:00',
+    'Jan 01 2000 08:00:00',
+    'Jan 01 08:00:00 2000',
+    'Saturday, 01-Jan-00 08:00:00',
+    '01 Jan 00 08:00'];
+
+
+// Misc. test cases that result in a different time value.
+var testCasesMisc = [
+    // Special handling for years in the [0, 100) range.
+    ['Sat, 01 Jan 0 08:00:00 UT', 946713600000], // year 2000
+    ['Sat, 01 Jan 49 08:00:00 UT', 2493100800000], // year 2049
+    ['Sat, 01 Jan 50 08:00:00 UT', -631123200000], // year 1950
+    ['Sat, 01 Jan 99 08:00:00 UT', 915177600000], // year 1999
+    ['Sat, 01 Jan 100 08:00:00 UT', -59011430400000], // year 100
+    // Test PM after time.
+    ['Sat, 01-Jan-2000 08:00 PM UT', 946756800000],
+    ['Sat, 01 Jan 2000 08:00 PM UT', 946756800000],
+    ['Jan 01 2000 08:00 PM UT', 946756800000],
+    ['Jan 01 08:00 PM UT 2000', 946756800000],
+    ['Saturday, 01-Jan-00 08:00 PM UT', 946756800000],
+    ['01 Jan 00 08:00 PM +0000', 946756800000]];
+
+
+// Run all the tests.
+testCasesUT.forEach(testDateParse);
+testCasesGMT.forEach(testDateParse);
+testCasesEST.forEach(testDateParse);
+testCasesEDT.forEach(testDateParse);
+testCasesCST.forEach(testDateParse);
+testCasesCDT.forEach(testDateParse);
+testCasesMST.forEach(testDateParse);
+testCasesMDT.forEach(testDateParse);
+testCasesPST.forEach(testDateParse);
+testCasesPDT.forEach(testDateParse);
+testCasesLocalTime.forEach(testDateParseLocalTime);
+testCasesMisc.forEach(testDateParseMisc);
+
+
+// Test that we can parse our own date format.
+// (Dates from 1970 to ~2070 with 95h steps.)
+for (var i = 0; i < 24 * 365 * 100; i += 95) {
+  var ms = i * (3600 * 1000);
+  var s = (new Date(ms)).toString();
+  assertEquals(ms, Date.parse(s), s);
+}
+
+// Negative tests.
+var testCasesNegative = [
+    'May 25 2008 1:30 (PM)) UTC',
+    'May 25 2008 1:30( )AM (PM)',
+    'May 25 2008 AAA (GMT)'];
+
+testCasesNegative.forEach(function (s) {
+    assertTrue(isNaN(Date.parse(s)), s + " is not NaN.");
+});
diff --git a/deps/v8/test/mjsunit/date.js b/deps/v8/test/mjsunit/date.js
new file mode 100644
index 0000000..8c53910
--- /dev/null
+++ b/deps/v8/test/mjsunit/date.js
@@ -0,0 +1,149 @@
+// Copyright 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.
+
+// Test date construction from other dates.
+var date0 = new Date(1111);
+var date1 = new Date(date0);
+assertEquals(1111, date0.getTime());
+assertEquals(date0.getTime(), date1.getTime());
+var date2 = new Date(date0.toString());
+assertEquals(1000, date2.getTime());
+
+// Test that dates may contain commas.
+var date0 = Date.parse("Dec 25 1995 1:30");
+var date1 = Date.parse("Dec 25, 1995 1:30");
+var date2 = Date.parse("Dec 25 1995, 1:30");
+var date3 = Date.parse("Dec 25, 1995, 1:30");
+assertEquals(date0, date1);
+assertEquals(date1, date2);
+assertEquals(date2, date3);
+
+// Test limits (+/-1e8 days from epoch)
+
+var dMax = new Date(8.64e15);
+assertEquals(8.64e15, dMax.getTime());
+
+var dOverflow = new Date(8.64e15+1);
+assertTrue(isNaN(dOverflow.getTime()));
+
+var dMin = new Date(-8.64e15);
+assertEquals(-8.64e15, dMin.getTime());
+
+var dUnderflow = new Date(-8.64e15-1);
+assertTrue(isNaN(dUnderflow.getTime()));
+
+
+// Tests inspired by js1_5/Date/regress-346363.js
+
+// Year
+var a = new Date();
+a.setFullYear();
+a.setFullYear(2006);
+assertEquals(2006, a.getFullYear());
+
+var b = new Date();
+b.setUTCFullYear();
+b.setUTCFullYear(2006);
+assertEquals(2006, b.getUTCFullYear());
+
+// Month
+var c = new Date();
+c.setMonth();
+c.setMonth(2);
+assertTrue(isNaN(c.getMonth()));
+
+var d = new Date();
+d.setUTCMonth();
+d.setUTCMonth(2);
+assertTrue(isNaN(d.getUTCMonth()));
+
+// Date
+var e = new Date();
+e.setDate();
+e.setDate(2);
+assertTrue(isNaN(e.getDate()));
+
+var f = new Date();
+f.setUTCDate();
+f.setUTCDate(2);
+assertTrue(isNaN(f.getUTCDate()));
+
+// Hours
+var g = new Date();
+g.setHours();
+g.setHours(2);
+assertTrue(isNaN(g.getHours()));
+
+var h = new Date();
+h.setUTCHours();
+h.setUTCHours(2);
+assertTrue(isNaN(h.getUTCHours()));
+
+// Minutes
+var g = new Date();
+g.setMinutes();
+g.setMinutes(2);
+assertTrue(isNaN(g.getMinutes()));
+
+var h = new Date();
+h.setUTCHours();
+h.setUTCHours(2);
+assertTrue(isNaN(h.getUTCHours()));
+
+
+// Seconds
+var i = new Date();
+i.setSeconds();
+i.setSeconds(2);
+assertTrue(isNaN(i.getSeconds()));
+
+var j = new Date();
+j.setUTCSeconds();
+j.setUTCSeconds(2);
+assertTrue(isNaN(j.getUTCSeconds()));
+
+
+// Milliseconds
+var k = new Date();
+k.setMilliseconds();
+k.setMilliseconds(2);
+assertTrue(isNaN(k.getMilliseconds()));
+
+var l = new Date();
+l.setUTCMilliseconds();
+l.setUTCMilliseconds(2);
+assertTrue(isNaN(l.getUTCMilliseconds()));
+
+// Test that toLocaleTimeString only returns the time portion of the
+// date without the timezone information.
+function testToLocaleTimeString() {
+  var d = new Date();
+  var s = d.toLocaleTimeString();
+  assertEquals(8, s.length);
+}
+
+testToLocaleTimeString();
diff --git a/deps/v8/test/mjsunit/debug-backtrace-text.js b/deps/v8/test/mjsunit/debug-backtrace-text.js
new file mode 100644
index 0000000..67c6746
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-backtrace-text.js
@@ -0,0 +1,122 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+
+// The functions used for testing backtraces.
+function Point(x, y) {
+  this.x = x;
+  this.y = y;
+};
+
+Point.prototype.distanceTo = function(p) {
+  debugger;
+  return Math.sqrt(Math.pow(Math.abs(this.x - p.x), 2) + Math.pow(Math.abs(this.y - p.y), 2))
+}
+
+p1 = new Point(1,1);
+p2 = new Point(2,2);
+
+p1.distanceTo = function(p) {
+  return p.distanceTo(this);
+}
+
+function distance(p, q) {
+  return p.distanceTo(q);
+}
+
+function createPoint(x, y) {
+  return new Point(x, y);
+}
+
+a=[1,2,distance];
+
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+testConstructor = false;  // Flag to control which part of the test is run.
+listenerCalled = false;
+exception = false;
+
+function safeEval(code) {
+  try {
+    return eval('(' + code + ')');
+  } catch (e) {
+    return undefined;
+  }
+}
+
+function listener(event, exec_state, event_data, data) {
+  try {
+  if (event == Debug.DebugEvent.Break)
+  {
+    if (!testConstructor) {
+      // The expected backtrace is
+      // 0: Call distance on Point where distance is a property on the prototype
+      // 1: Call distance on Point where distance is a direct property
+      // 2: Call on function an array element 2
+      // 3: [anonymous]
+      assertEquals("#<a Point>.distanceTo(p=#<a Point>)", exec_state.frame(0).invocationText());
+      assertEquals("#<a Point>.distanceTo(p=#<a Point>)", exec_state.frame(1).invocationText());
+      assertEquals("#<an Array>[2](aka distance)(p=#<a Point>, q=#<a Point>)", exec_state.frame(2).invocationText());
+      assertEquals("[anonymous]()", exec_state.frame(3).invocationText());
+      listenerCalled = true;
+    } else {
+      // The expected backtrace is
+      // 0: Call Point constructor
+      // 1: Call on global function createPoint
+      // 2: [anonymous]
+      assertEquals("new Point(x=0, y=0)", exec_state.frame(0).invocationText());
+      assertEquals("createPoint(x=0, y=0)", exec_state.frame(1).invocationText());
+      assertEquals("[anonymous]()", exec_state.frame(2).invocationText());
+      listenerCalled = true;
+    }
+  }
+  } catch (e) {
+    exception = e
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Set a break point and call to invoke the debug event listener.
+a[2](p1, p2)
+
+// Make sure that the debug event listener vas invoked.
+assertTrue(listenerCalled);
+assertFalse(exception, "exception in listener")
+
+// Set a break point and call to invoke the debug event listener.
+listenerCalled = false;
+testConstructor = true;
+Debug.setBreakPoint(Point, 0, 0);
+createPoint(0, 0);
+
+// Make sure that the debug event listener vas invoked (again).
+assertTrue(listenerCalled);
+assertFalse(exception, "exception in listener")
diff --git a/deps/v8/test/mjsunit/debug-backtrace.js b/deps/v8/test/mjsunit/debug-backtrace.js
new file mode 100644
index 0000000..940c4cb
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-backtrace.js
@@ -0,0 +1,227 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// The functions used for testing backtraces. They are at the top to make the
+// testing of source line/column easier.
+function f(x, y) {
+  a=1;
+};
+
+function g() {
+  new f(1);
+};
+
+
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+listenerCalled = false;
+exception = false;
+
+
+function ParsedResponse(json) {
+  this.response_ = eval('(' + json + ')');
+  this.refs_ = [];
+  if (this.response_.refs) {
+    for (var i = 0; i < this.response_.refs.length; i++) {
+      this.refs_[this.response_.refs[i].handle] = this.response_.refs[i];
+    }
+  }
+}
+
+
+ParsedResponse.prototype.response = function() {
+  return this.response_;
+}
+
+
+ParsedResponse.prototype.body = function() {
+  return this.response_.body;
+}
+
+
+ParsedResponse.prototype.lookup = function(handle) {
+  return this.refs_[handle];
+}
+
+
+function listener(event, exec_state, event_data, data) {
+  try {
+  if (event == Debug.DebugEvent.Break)
+  {
+    // The expected backtrace is
+    // 0: f
+    // 1: g
+    // 2: [anonymous]
+    
+    var response;
+    var backtrace;
+    var frame;
+    var source;
+    
+    // Get the debug command processor.
+    var dcp = exec_state.debugCommandProcessor();
+
+    // Get the backtrace.
+    var json;
+    json = '{"seq":0,"type":"request","command":"backtrace"}'
+    response = new ParsedResponse(dcp.processDebugJSONRequest(json));
+    backtrace = response.body();
+    assertEquals(0, backtrace.fromFrame);
+    assertEquals(3, backtrace.toFrame);
+    assertEquals(3, backtrace.totalFrames);
+    var frames = backtrace.frames;
+    assertEquals(3, frames.length);
+    for (var i = 0; i < frames.length; i++) {
+      assertEquals('frame', frames[i].type);
+    }
+    assertEquals(0, frames[0].index);
+    assertEquals("f", response.lookup(frames[0].func.ref).name);
+    assertEquals(1, frames[1].index);
+    assertEquals("g", response.lookup(frames[1].func.ref).name);
+    assertEquals(2, frames[2].index);
+    assertEquals("", response.lookup(frames[2].func.ref).name);
+
+    // Get backtrace with two frames.
+    json = '{"seq":0,"type":"request","command":"backtrace","arguments":{"fromFrame":1,"toFrame":3}}'
+    response = new ParsedResponse(dcp.processDebugJSONRequest(json));
+    backtrace = response.body();
+    assertEquals(1, backtrace.fromFrame);
+    assertEquals(3, backtrace.toFrame);
+    assertEquals(3, backtrace.totalFrames);
+    var frames = backtrace.frames;
+    assertEquals(2, frames.length);
+    for (var i = 0; i < frames.length; i++) {
+      assertEquals('frame', frames[i].type);
+    }
+    assertEquals(1, frames[0].index);
+    assertEquals("g", response.lookup(frames[0].func.ref).name);
+    assertEquals(2, frames[1].index);
+    assertEquals("", response.lookup(frames[1].func.ref).name);
+
+    // Get the individual frames.
+    json = '{"seq":0,"type":"request","command":"frame"}'
+    response = new ParsedResponse(dcp.processDebugJSONRequest(json));
+    frame = response.body();
+    assertEquals(0, frame.index);
+    assertEquals("f", response.lookup(frame.func.ref).name);
+    assertTrue(frame.constructCall);
+    assertEquals(31, frame.line);
+    assertEquals(3, frame.column);
+    assertEquals(2, frame.arguments.length);
+    assertEquals('x', frame.arguments[0].name);
+    assertEquals('number', response.lookup(frame.arguments[0].value.ref).type);
+    assertEquals(1, response.lookup(frame.arguments[0].value.ref).value);
+    assertEquals('y', frame.arguments[1].name);
+    assertEquals('undefined', response.lookup(frame.arguments[1].value.ref).type);
+
+    json = '{"seq":0,"type":"request","command":"frame","arguments":{"number":0}}'
+    response = new ParsedResponse(dcp.processDebugJSONRequest(json));
+    frame = response.body();
+    assertEquals(0, frame.index);
+    assertEquals("f", response.lookup(frame.func.ref).name);
+    assertEquals(31, frame.line);
+    assertEquals(3, frame.column);
+    assertEquals(2, frame.arguments.length);
+    assertEquals('x', frame.arguments[0].name);
+    assertEquals('number', response.lookup(frame.arguments[0].value.ref).type);
+    assertEquals(1, response.lookup(frame.arguments[0].value.ref).value);
+    assertEquals('y', frame.arguments[1].name);
+    assertEquals('undefined', response.lookup(frame.arguments[1].value.ref).type);
+
+    json = '{"seq":0,"type":"request","command":"frame","arguments":{"number":1}}'
+    response = new ParsedResponse(dcp.processDebugJSONRequest(json));
+    frame = response.body();
+    assertEquals(1, frame.index);
+    assertEquals("g", response.lookup(frame.func.ref).name);
+    assertFalse(frame.constructCall);
+    assertEquals(35, frame.line);
+    assertEquals(2, frame.column);
+    assertEquals(0, frame.arguments.length);
+
+    json = '{"seq":0,"type":"request","command":"frame","arguments":{"number":2}}'
+    response = new ParsedResponse(dcp.processDebugJSONRequest(json));
+    frame = response.body();
+    assertEquals(2, frame.index);
+    assertEquals("", response.lookup(frame.func.ref).name);
+
+    // Source slices for the individual frames (they all refer to this script).
+    json = '{"seq":0,"type":"request","command":"source",' +
+            '"arguments":{"frame":0,"fromLine":30,"toLine":32}}'
+    response = new ParsedResponse(dcp.processDebugJSONRequest(json));
+    source = response.body();
+    assertEquals("function f(x, y) {", source.source.substring(0, 18));
+    assertEquals(30, source.fromLine);
+    assertEquals(32, source.toLine);
+    
+    json = '{"seq":0,"type":"request","command":"source",' +
+            '"arguments":{"frame":1,"fromLine":31,"toLine":32}}'
+    response = new ParsedResponse(dcp.processDebugJSONRequest(json));
+    source = response.body();
+    assertEquals("  a=1;", source.source.substring(0, 6));
+    assertEquals(31, source.fromLine);
+    assertEquals(32, source.toLine);
+    
+    json = '{"seq":0,"type":"request","command":"source",' +
+            '"arguments":{"frame":2,"fromLine":35,"toLine":36}}'
+    response = new ParsedResponse(dcp.processDebugJSONRequest(json));
+    source = response.body();
+    assertEquals("  new f(1);", source.source.substring(0, 11));
+    assertEquals(35, source.fromLine);
+    assertEquals(36, source.toLine);
+    
+    // Test line interval way beyond this script will result in an error.
+    json = '{"seq":0,"type":"request","command":"source",' +
+            '"arguments":{"frame":0,"fromLine":10000,"toLine":20000}}'
+    response = new ParsedResponse(dcp.processDebugJSONRequest(json));
+    assertFalse(response.response().success);
+    
+    // Test without arguments.
+    json = '{"seq":0,"type":"request","command":"source"}'
+    response = new ParsedResponse(dcp.processDebugJSONRequest(json));
+    source = response.body();
+    assertEquals(Debug.findScript(f).source, source.source);
+    
+    listenerCalled = true;
+  }
+  } catch (e) {
+    exception = e
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Set a break point and call to invoke the debug event listener.
+Debug.setBreakPoint(f, 0, 0);
+g();
+
+// Make sure that the debug event listener vas invoked.
+assertFalse(exception, "exception in listener");
+assertTrue(listenerCalled);
+
diff --git a/deps/v8/test/mjsunit/debug-breakpoints.js b/deps/v8/test/mjsunit/debug-breakpoints.js
new file mode 100644
index 0000000..c332f1e
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-breakpoints.js
@@ -0,0 +1,120 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+function f() {a=1;b=2};
+function g() {
+  a=1;
+  b=2;
+}
+
+bp = Debug.setBreakPoint(f, 0, 0);
+assertEquals("() {[B0]a=1;b=2}", Debug.showBreakPoints(f));
+Debug.clearBreakPoint(bp);
+assertEquals("() {a=1;b=2}", Debug.showBreakPoints(f));
+bp1 = Debug.setBreakPoint(f, 0, 8);
+assertEquals("() {a=1;[B0]b=2}", Debug.showBreakPoints(f));
+bp2 = Debug.setBreakPoint(f, 0, 4);
+assertEquals("() {[B0]a=1;[B1]b=2}", Debug.showBreakPoints(f));
+bp3 = Debug.setBreakPoint(f, 0, 12);
+assertEquals("() {[B0]a=1;[B1]b=2}[B2]", Debug.showBreakPoints(f));
+Debug.clearBreakPoint(bp1);
+assertEquals("() {[B0]a=1;b=2}[B1]", Debug.showBreakPoints(f));
+Debug.clearBreakPoint(bp2);
+assertEquals("() {a=1;b=2}[B0]", Debug.showBreakPoints(f));
+Debug.clearBreakPoint(bp3);
+assertEquals("() {a=1;b=2}", Debug.showBreakPoints(f));
+
+// The following test checks that the Debug.showBreakPoints(g) produces output
+// like follows when changein breakpoints.
+//
+// function g() {
+//   [BX]a=1;
+//   [BX]b=2;
+// }[BX]
+
+// Test set and clear breakpoint at the first possible location (line 0,
+// position 0).
+bp = Debug.setBreakPoint(g, 0, 0);
+// function g() {
+//   [B0]a=1;
+//   b=2;
+// }
+assertTrue(Debug.showBreakPoints(g).indexOf("[B0]a=1;") > 0);
+Debug.clearBreakPoint(bp);
+// function g() {
+//   a=1;
+//   b=2;
+// }
+assertTrue(Debug.showBreakPoints(g).indexOf("[B0]") < 0);
+
+// Second test set and clear breakpoints on lines 1, 2 and 3 (position = 0).
+bp1 = Debug.setBreakPoint(g, 2, 0);
+// function g() {
+//   a=1;
+//   [B0]b=2;
+// }
+assertTrue(Debug.showBreakPoints(g).indexOf("[B0]b=2;") > 0);
+bp2 = Debug.setBreakPoint(g, 1, 0);
+// function g() {
+//   [B0]a=1;
+//   [B1]b=2;
+// }
+assertTrue(Debug.showBreakPoints(g).indexOf("[B0]a=1;") > 0);
+assertTrue(Debug.showBreakPoints(g).indexOf("[B1]b=2;") > 0);
+bp3 = Debug.setBreakPoint(g, 3, 0);
+// function g() {
+//   [B0]a=1;
+//   [B1]b=2;
+// }[B2]
+assertTrue(Debug.showBreakPoints(g).indexOf("[B0]a=1;") > 0);
+assertTrue(Debug.showBreakPoints(g).indexOf("[B1]b=2;") > 0);
+assertTrue(Debug.showBreakPoints(g).indexOf("}[B2]") > 0);
+Debug.clearBreakPoint(bp1);
+// function g() {
+//   [B0]a=1;
+//   b=2;
+// }[B1]
+assertTrue(Debug.showBreakPoints(g).indexOf("[B0]a=1;") > 0);
+assertTrue(Debug.showBreakPoints(g).indexOf("}[B1]") > 0);
+assertTrue(Debug.showBreakPoints(g).indexOf("[B2]") < 0);
+Debug.clearBreakPoint(bp2);
+// function g() {
+//   a=1;
+//   b=2;
+// }[B0]
+assertTrue(Debug.showBreakPoints(g).indexOf("}[B0]") > 0);
+assertTrue(Debug.showBreakPoints(g).indexOf("[B1]") < 0);
+Debug.clearBreakPoint(bp3);
+// function g() {
+//   a=1;
+//   b=2;
+// }
+assertTrue(Debug.showBreakPoints(g).indexOf("[B0]") < 0);
diff --git a/deps/v8/test/mjsunit/debug-changebreakpoint.js b/deps/v8/test/mjsunit/debug-changebreakpoint.js
new file mode 100644
index 0000000..477c908
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-changebreakpoint.js
@@ -0,0 +1,108 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// Simple function which stores the last debug event.
+listenerComplete = false;
+exception = false;
+
+var base_request = '"seq":0,"type":"request","command":"changebreakpoint"'
+
+function safeEval(code) {
+  try {
+    return eval('(' + code + ')');
+  } catch (e) {
+    assertEquals(void 0, e);
+    return undefined;
+  }
+}
+
+function testArguments(dcp, arguments, success) {
+  var request = '{' + base_request + ',"arguments":' + arguments + '}'
+  var json_response = dcp.processDebugJSONRequest(request);
+  var response = safeEval(json_response);
+  if (success) {
+    assertTrue(response.success, json_response);
+  } else {
+    assertFalse(response.success, json_response);
+  }
+}
+
+function listener(event, exec_state, event_data, data) {
+  try {
+  if (event == Debug.DebugEvent.Break) {
+    // Get the debug command processor.
+    var dcp = exec_state.debugCommandProcessor();
+
+    // Test some illegal clearbreakpoint requests.
+    var request = '{' + base_request + '}'
+    var response = safeEval(dcp.processDebugJSONRequest(request));
+    assertFalse(response.success);
+
+    testArguments(dcp, '{}', false);
+    testArguments(dcp, '{"breakpoint":0,"condition":"false"}', false);
+    // TODO(1241036) change this to 2 when break points have been restructured.
+    testArguments(dcp, '{"breakpoint":3,"condition":"false"}', false);
+    testArguments(dcp, '{"breakpoint":"xx","condition":"false"}', false);
+
+    // Test some legal clearbreakpoint requests.
+    testArguments(dcp, '{"breakpoint":1}', true);
+    testArguments(dcp, '{"breakpoint":1,"enabled":"true"}', true);
+    testArguments(dcp, '{"breakpoint":1,"enabled":"false"}', true);
+    testArguments(dcp, '{"breakpoint":1,"condition":"1==2"}', true);
+    testArguments(dcp, '{"breakpoint":1,"condition":"false"}', true);
+    testArguments(dcp, '{"breakpoint":1,"ignoreCount":7}', true);
+    testArguments(dcp, '{"breakpoint":1,"ignoreCount":0}', true);
+    testArguments(
+        dcp,
+        '{"breakpoint":1,"enabled":"true","condition":"false","ignoreCount":0}',
+        true);
+
+    // Indicate that all was processed.
+    listenerComplete = true;
+  }
+  } catch (e) {
+    exception = e
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function g() {};
+
+// Set a break point and call to invoke the debug event listener.
+bp = Debug.setBreakPoint(g, 0, 0);
+assertEquals(1, bp);
+g();
+
+// Make sure that the debug event listener vas invoked.
+assertTrue(listenerComplete, "listener did not run to completion");
+assertFalse(exception, "exception in listener")
diff --git a/deps/v8/test/mjsunit/debug-clearbreakpoint.js b/deps/v8/test/mjsunit/debug-clearbreakpoint.js
new file mode 100644
index 0000000..28920c5
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-clearbreakpoint.js
@@ -0,0 +1,101 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// Simple function which stores the last debug event.
+listenerComplete = false;
+exception = false;
+
+var base_request = '"seq":0,"type":"request","command":"clearbreakpoint"'
+
+function safeEval(code) {
+  try {
+    return eval('(' + code + ')');
+  } catch (e) {
+    assertEquals(void 0, e);
+    return undefined;
+  }
+}
+
+function testArguments(dcp, arguments, success) {
+  var request = '{' + base_request + ',"arguments":' + arguments + '}'
+  var json_response = dcp.processDebugJSONRequest(request);
+  var response = safeEval(json_response);
+  if (success) {
+    assertTrue(response.success, json_response);
+  } else {
+    assertFalse(response.success, json_response);
+  }
+}
+
+function listener(event, exec_state, event_data, data) {
+  try {
+  if (event == Debug.DebugEvent.Break) {
+    // Get the debug command processor.
+    var dcp = exec_state.debugCommandProcessor();
+
+    // Test some illegal clearbreakpoint requests.
+    var request = '{' + base_request + '}'
+    var response = safeEval(dcp.processDebugJSONRequest(request));
+    assertFalse(response.success);
+
+    testArguments(dcp, '{}', false);
+    testArguments(dcp, '{"breakpoint":0}', false);
+    // TODO(1241036) change this to 2 when break points have been restructured.
+    testArguments(dcp, '{"breakpoint":3}', false);
+    testArguments(dcp, '{"breakpoint":"xx"}', false);
+
+    // Test some legal clearbreakpoint requests.
+    testArguments(dcp, '{"breakpoint":1}', true);
+
+    // Cannot clear the same break point twice.
+    testArguments(dcp, '{"breakpoint":1}', false);
+
+    // Indicate that all was processed.
+    listenerComplete = true;
+  }
+  } catch (e) {
+    exception = e
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function g() {};
+
+// Set a break point and call to invoke the debug event listener.
+bp = Debug.setBreakPoint(g, 0, 0);
+assertEquals(1, bp);
+g();
+
+// Make sure that the debug event listener vas invoked.
+assertTrue(listenerComplete, "listener did not run to completion");
+assertFalse(exception, "exception in listener")
diff --git a/deps/v8/test/mjsunit/debug-compile-event.js b/deps/v8/test/mjsunit/debug-compile-event.js
new file mode 100644
index 0000000..035e36c
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-compile-event.js
@@ -0,0 +1,95 @@
+// 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+var exception = false;  // Exception in debug event listener.
+var before_compile_count = 0;
+var after_compile_count = 0;
+var current_source = '';  // Current source compiled.
+var source_count = 0;  // Total number of scource sompiled.
+
+
+function compileSource(source) {
+  current_source = source;
+  eval(current_source);
+  source_count++;
+}
+
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.BeforeCompile ||
+        event == Debug.DebugEvent.AfterCompile) {
+      // Count the events.
+      if (event == Debug.DebugEvent.BeforeCompile) {
+        before_compile_count++;
+      } else {
+        after_compile_count++;
+      }
+      
+      // If the compiled source contains 'eval' there will be additional compile
+      // events for the source inside eval.
+      if (current_source.indexOf('eval') == 0) {
+        // For source with 'eval' there will be compile events with substrings
+        // as well as with with the exact source.
+        assertTrue(current_source.indexOf(event_data.script().source()) >= 0);
+      } else {
+        // For source without 'eval' there will be a compile events with the
+        // exact source.
+        assertEquals(current_source, event_data.script().source());
+      }
+    }
+  } catch (e) {
+    exception = e
+  }
+};
+
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Compile different sources.
+compileSource('a=1');
+compileSource('function(){}');
+compileSource('eval("a=2")');
+source_count++;  // Using eval causes additional compilation event.
+compileSource('eval("eval(\'function(){return a;}\')")');
+source_count += 2;  // Using eval causes additional compilation event.
+
+// Make sure that the debug event listener was invoked.
+assertFalse(exception, "exception in listener")
+
+// Number of before and after compile events should be the same.
+assertEquals(before_compile_count, after_compile_count);
+
+// Check the actual number of events.
+assertEquals(source_count, after_compile_count);
+
+Debug.setListener(null);
diff --git a/deps/v8/test/mjsunit/debug-conditional-breakpoints.js b/deps/v8/test/mjsunit/debug-conditional-breakpoints.js
new file mode 100644
index 0000000..5859451
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-conditional-breakpoints.js
@@ -0,0 +1,171 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// Simple debug event handler which just counts the number of break points hit.
+var break_point_hit_count;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    break_point_hit_count++;
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Test functions.
+count = 0;
+function f() {};
+function g() {h(count++)};
+function h(x) {var a=x;};
+
+
+// Conditional breakpoint which syntax error.
+break_point_hit_count = 0;
+bp = Debug.setBreakPoint(f, 0, 0, '{{{');
+f();
+assertEquals(0, break_point_hit_count);
+assertEquals(0, Debug.findBreakPoint(bp, false).hit_count());
+Debug.clearBreakPoint(bp);
+
+// Conditional breakpoint which evaluates to false.
+break_point_hit_count = 0;
+bp = Debug.setBreakPoint(f, 0, 0, 'false');
+f();
+assertEquals(0, break_point_hit_count);
+assertEquals(0, Debug.findBreakPoint(bp, false).hit_count());
+Debug.clearBreakPoint(bp);
+
+// Conditional breakpoint which evaluates to true.
+break_point_hit_count = 0;
+bp = Debug.setBreakPoint(f, 0, 0, 'true');
+f();
+assertEquals(1, break_point_hit_count);
+assertEquals(1, Debug.findBreakPoint(bp, false).hit_count());
+Debug.clearBreakPoint(bp);
+
+// Conditional breakpoint which different types of quotes.
+break_point_hit_count = 0;
+bp = Debug.setBreakPoint(f, 0, 0, '"a" == "a"');
+f();
+assertEquals(1, break_point_hit_count);
+assertEquals(1, Debug.findBreakPoint(bp, false).hit_count());
+Debug.clearBreakPoint(bp);
+break_point_hit_count = 0;
+bp = Debug.setBreakPoint(f, 0, 0, "'a' == 'a'");
+f();
+assertEquals(1, break_point_hit_count);
+assertEquals(1, Debug.findBreakPoint(bp, false).hit_count());
+Debug.clearBreakPoint(bp);
+
+// Changing condition.
+break_point_hit_count = 0;
+bp = Debug.setBreakPoint(f, 0, 0, '"ab".indexOf("b") > 0');
+f();
+assertEquals(1, break_point_hit_count);
+assertEquals(1, Debug.findBreakPoint(bp, false).hit_count());
+Debug.changeBreakPointCondition(bp, 'Math.sin(Math.PI/2) > 1');
+f();
+assertEquals(1, break_point_hit_count);
+assertEquals(1, Debug.findBreakPoint(bp, false).hit_count());
+Debug.changeBreakPointCondition(bp, '1==1');
+f();
+assertEquals(2, break_point_hit_count);
+assertEquals(2, Debug.findBreakPoint(bp, false).hit_count());
+Debug.clearBreakPoint(bp);
+
+// Conditional breakpoint which checks global variable.
+break_point_hit_count = 0;
+bp = Debug.setBreakPoint(f, 0, 0, 'x==1');
+f();
+assertEquals(0, break_point_hit_count);
+assertEquals(0, Debug.findBreakPoint(bp, false).hit_count());
+x=1;
+f();
+assertEquals(1, break_point_hit_count);
+assertEquals(1, Debug.findBreakPoint(bp, false).hit_count());
+Debug.clearBreakPoint(bp);
+
+// Conditional breakpoint which checks global variable.
+break_point_hit_count = 0;
+bp = Debug.setBreakPoint(g, 0, 0, 'count % 2 == 0');
+for (var i = 0; i < 10; i++) {
+  g();
+}
+assertEquals(5, break_point_hit_count);
+assertEquals(5, Debug.findBreakPoint(bp, false).hit_count());
+Debug.clearBreakPoint(bp);
+
+// Conditional breakpoint which checks a parameter.
+break_point_hit_count = 0;
+bp = Debug.setBreakPoint(h, 0, 0, 'x % 2 == 0');
+for (var i = 0; i < 10; i++) {
+  g();
+}
+assertEquals(5, break_point_hit_count);
+assertEquals(5, Debug.findBreakPoint(bp, false).hit_count());
+Debug.clearBreakPoint(bp);
+
+// Conditional breakpoint which checks a local variable.
+break_point_hit_count = 0;
+bp = Debug.setBreakPoint(h, 0, 0, 'a % 2 == 0');
+for (var i = 0; i < 10; i++) {
+  g();
+}
+assertEquals(5, break_point_hit_count);
+assertEquals(5, Debug.findBreakPoint(bp, false).hit_count());
+Debug.clearBreakPoint(bp);
+
+// Multiple conditional breakpoint which the same condition.
+break_point_hit_count = 0;
+bp1 = Debug.setBreakPoint(h, 0, 0, 'a % 2 == 0');
+bp2 = Debug.setBreakPoint(h, 0, 0, 'a % 2 == 0');
+for (var i = 0; i < 10; i++) {
+  g();
+}
+assertEquals(5, break_point_hit_count);
+assertEquals(5, Debug.findBreakPoint(bp1, false).hit_count());
+assertEquals(5, Debug.findBreakPoint(bp2, false).hit_count());
+Debug.clearBreakPoint(bp1);
+Debug.clearBreakPoint(bp2);
+
+// Multiple conditional breakpoint which different conditions.
+break_point_hit_count = 0;
+bp1 = Debug.setBreakPoint(h, 0, 0, 'a % 2 == 0');
+bp2 = Debug.setBreakPoint(h, 0, 0, '(a + 1) % 2 == 0');
+for (var i = 0; i < 10; i++) {
+  g();
+}
+assertEquals(10, break_point_hit_count);
+assertEquals(5, Debug.findBreakPoint(bp1, false).hit_count());
+assertEquals(5, Debug.findBreakPoint(bp2, false).hit_count());
+Debug.clearBreakPoint(bp1);
+Debug.clearBreakPoint(bp2);
diff --git a/deps/v8/test/mjsunit/debug-constructed-by.js b/deps/v8/test/mjsunit/debug-constructed-by.js
new file mode 100644
index 0000000..c904e25
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-constructed-by.js
@@ -0,0 +1,60 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// Simple constructor.
+function Point(x,y) {}
+
+// Create mirror for the constructor.
+var ctor = debug.MakeMirror(Point);
+
+// Initially no instances.
+assertEquals(0, ctor.constructedBy().length);
+assertEquals(0, ctor.constructedBy(0).length);
+assertEquals(0, ctor.constructedBy(1).length);
+assertEquals(0, ctor.constructedBy(10).length);
+
+// Create an instance.
+var p = new Point();
+assertEquals(1, ctor.constructedBy().length);
+assertEquals(1, ctor.constructedBy(0).length);
+assertEquals(1, ctor.constructedBy(1).length);
+assertEquals(1, ctor.constructedBy(10).length);
+
+
+// Create 10 more instances making for 11.
+ps = [];
+for (var i = 0; i < 10; i++) {
+  ps.push(new Point());
+}
+assertEquals(11, ctor.constructedBy().length);
+assertEquals(11, ctor.constructedBy(0).length);
+assertEquals(1, ctor.constructedBy(1).length);
+assertEquals(10, ctor.constructedBy(10).length);
diff --git a/deps/v8/test/mjsunit/debug-constructor.js b/deps/v8/test/mjsunit/debug-constructor.js
new file mode 100644
index 0000000..38028aa
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-constructor.js
@@ -0,0 +1,78 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// Simple function which collects a simple call graph.
+var call_graph = "";
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break)
+  {
+    call_graph += exec_state.frame().func().name();
+    exec_state.prepareStep();
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Test debug event for constructor.
+function a() {
+  new c();
+}
+
+function b() {
+  x = 1;
+  new c();
+}
+
+function c() {
+  this.x = 1;
+  d();
+}
+
+function d() {
+}
+
+// Break point stops on "new c()" and steps into c.
+Debug.setBreakPoint(a, 1);
+call_graph = "";
+a();
+Debug.clearStepping();  // Clear stepping as the listener leaves it on.
+assertEquals("accdca", call_graph);
+
+// Break point stops on "x = 1" and steps to "new c()" and then into c.
+Debug.setBreakPoint(b, 1);
+call_graph = "";
+b();
+Debug.clearStepping();  // Clear stepping as the listener leaves it on.
+assertEquals("bbccdcb", call_graph);
+
+// Get rid of the debug event listener.
+Debug.setListener(null);
\ No newline at end of file
diff --git a/deps/v8/test/mjsunit/debug-continue.js b/deps/v8/test/mjsunit/debug-continue.js
new file mode 100644
index 0000000..0c11abc
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-continue.js
@@ -0,0 +1,113 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// Simple function which stores the last debug event.
+listenerComplete = false;
+exception = false;
+
+var base_request = '"seq":0,"type":"request","command":"continue"'
+
+function safeEval(code) {
+  try {
+    return eval('(' + code + ')');
+  } catch (e) {
+    assertEquals(void 0, e);
+    return undefined;
+  }
+}
+
+function testArguments(dcp, arguments, success) {
+  // Generate request with the supplied arguments
+  var request;
+  if (arguments) {
+    request = '{' + base_request + ',"arguments":' + arguments + '}';
+  } else {
+    request = '{' + base_request + '}'
+  }
+  var response = safeEval(dcp.processDebugJSONRequest(request));
+  if (success) {
+    assertTrue(response.success, request + ' -> ' + response.message);
+    assertTrue(response.running, request + ' -> expected running');
+  } else {
+    assertFalse(response.success, request + ' -> ' + response.message);
+    assertFalse(response.running, request + ' -> expected not running');
+  }
+}
+
+function listener(event, exec_state, event_data, data) {
+  try {
+  if (event == Debug.DebugEvent.Break) {
+    // Get the debug command processor.
+    var dcp = exec_state.debugCommandProcessor();
+
+    // Test simple continue request.
+    testArguments(dcp, void 0, true);
+
+    // Test some illegal continue requests.
+    testArguments(dcp, '{"stepaction":"maybe"}', false);
+    testArguments(dcp, '{"stepcount":-1}', false);
+
+    // Test some legal continue requests.
+    testArguments(dcp, '{"stepaction":"in"}', true);
+    testArguments(dcp, '{"stepaction":"min"}', true);
+    testArguments(dcp, '{"stepaction":"next"}', true);
+    testArguments(dcp, '{"stepaction":"out"}', true);
+    testArguments(dcp, '{"stepcount":1}', true);
+    testArguments(dcp, '{"stepcount":10}', true);
+    testArguments(dcp, '{"stepcount":"10"}', true);
+    testArguments(dcp, '{"stepaction":"next","stepcount":10}', true);
+
+    // Indicate that all was processed.
+    listenerComplete = true;
+  }
+  } catch (e) {
+    exception = e
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function f() {
+  a=1
+};
+
+function g() {
+  f();
+};
+
+// Set a break point and call to invoke the debug event listener.
+Debug.setBreakPoint(g, 0, 0);
+g();
+
+// Make sure that the debug event listener vas invoked.
+assertTrue(listenerComplete, "listener did not run to completion");
+assertFalse(exception, "exception in listener")
diff --git a/deps/v8/test/mjsunit/debug-enable-disable-breakpoints.js b/deps/v8/test/mjsunit/debug-enable-disable-breakpoints.js
new file mode 100644
index 0000000..071397b
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-enable-disable-breakpoints.js
@@ -0,0 +1,90 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// Simple debug event handler which just counts the number of break points hit.
+var break_point_hit_count;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    break_point_hit_count++;
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Test function.
+function f() {a=1;b=2;};
+
+// This tests enabeling and disabling of break points including the case
+// with several break points in the same location.
+break_point_hit_count = 0;
+
+// Set a breakpoint in f.
+bp1 = Debug.setBreakPoint(f);
+f();
+assertEquals(1, break_point_hit_count);
+
+// Disable the breakpoint.
+Debug.disableBreakPoint(bp1);
+f();
+assertEquals(1, break_point_hit_count);
+
+// Enable the breakpoint.
+Debug.enableBreakPoint(bp1);
+f();
+assertEquals(2, break_point_hit_count);
+
+// Set another breakpoint in f at the same place.
+bp2 = Debug.setBreakPoint(f);
+f();
+assertEquals(3, break_point_hit_count);
+
+// Disable the second breakpoint.
+Debug.disableBreakPoint(bp2);
+f();
+assertEquals(4, break_point_hit_count);
+
+// Disable the first breakpoint.
+Debug.disableBreakPoint(bp1);
+f();
+assertEquals(4, break_point_hit_count);
+
+// Enable both breakpoints.
+Debug.enableBreakPoint(bp1);
+Debug.enableBreakPoint(bp2);
+f();
+assertEquals(5, break_point_hit_count);
+
+// Disable the first breakpoint.
+Debug.disableBreakPoint(bp1);
+f();
+assertEquals(6, break_point_hit_count);
diff --git a/deps/v8/test/mjsunit/debug-evaluate-arguments.js b/deps/v8/test/mjsunit/debug-evaluate-arguments.js
new file mode 100644
index 0000000..92b745f
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-evaluate-arguments.js
@@ -0,0 +1,93 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+listenerComplete = false;
+exception = false;
+
+function checkArguments(frame, names, values) {
+  var argc = Math.max(names.length, values.length);
+  assertEquals(argc, frame.argumentCount());
+  for (var i = 0; i < argc; i++) {
+    if (i < names.length) {
+      assertEquals(names[i], frame.argumentName(i));
+    } else {
+      assertEquals(void 0, frame.argumentName(i));
+    }
+
+    if (i < values.length) {
+      assertEquals(values[i], frame.argumentValue(i).value());
+    } else {
+      assertEquals(void 0, frame.argumentValue(i).value());
+    }
+  }
+}
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break)
+    {
+      // Frame 0 - called with less parameters than arguments.
+      checkArguments(exec_state.frame(0), ['x', 'y'], [1]);
+
+      // Frame 1 - called with more parameters than arguments.
+      checkArguments(exec_state.frame(1), ['x', 'y'], [1, 2, 3]);
+
+      // Frame 2 - called with same number of parameters than arguments.
+      checkArguments(exec_state.frame(2), ['x', 'y', 'z'], [1, 2, 3]);
+
+      // Indicate that all was processed.
+      listenerComplete = true;
+    }
+  } catch (e) {
+    exception = e
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function h(x, y) {
+  debugger;  // Breakpoint.
+};
+
+function g(x, y) {
+  h(x);
+};
+
+function f(x, y, z) {
+  g.apply(null, [x, y, z]);
+};
+
+f(1, 2, 3);
+
+// Make sure that the debug event listener vas invoked.
+assertTrue(listenerComplete);
+assertFalse(exception, "exception in listener")
diff --git a/deps/v8/test/mjsunit/debug-evaluate-locals.js b/deps/v8/test/mjsunit/debug-evaluate-locals.js
new file mode 100644
index 0000000..4b87829
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-evaluate-locals.js
@@ -0,0 +1,132 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+listenerComplete = false;
+exception = false;
+
+
+function checkFrame0(name, value) {
+  assertTrue(name == 'a' || name == 'b');
+  if (name == 'a') {
+    assertEquals(1, value);
+  }
+  if (name == 'b') {
+    assertEquals(2, value);
+  }
+}
+
+
+function checkFrame1(name, value) {
+  assertTrue(name == '.arguments' || name == 'a');
+  if (name == 'a') {
+    assertEquals(3, value);
+  }
+}
+
+
+function checkFrame2(name, value) {
+  assertTrue(name == '.arguments' || name == 'a' ||
+             name == 'arguments' || name == 'b');
+  if (name == 'a') {
+    assertEquals(5, value);
+  }
+  if (name == 'b') {
+    assertEquals(0, value);
+  }
+}
+
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break)
+    {
+      // Frame 0 has normal variables a and b.
+      var frame0 = exec_state.frame(0);
+      checkFrame0(frame0.localName(0), frame0.localValue(0).value());
+      checkFrame0(frame0.localName(1), frame0.localValue(1).value());
+
+      // Frame 1 has normal variable a (and the .arguments variable).
+      var frame1 = exec_state.frame(1);
+      checkFrame1(frame1.localName(0), frame1.localValue(0).value());
+      checkFrame1(frame1.localName(1), frame1.localValue(1).value());
+
+      // Frame 2 has normal variables a and b (and both the .arguments and
+      // arguments variable).
+      var frame2 = exec_state.frame(2);
+      checkFrame2(frame2.localName(0), frame2.localValue(0).value());
+      checkFrame2(frame2.localName(1), frame2.localValue(1).value());
+      checkFrame2(frame2.localName(2), frame2.localValue(2).value());
+      checkFrame2(frame2.localName(3), frame2.localValue(3).value());
+
+      // Evaluating a and b on frames 0, 1 and 2 produces 1, 2, 3, 4, 5 and 6.
+      assertEquals(1, exec_state.frame(0).evaluate('a').value());
+      assertEquals(2, exec_state.frame(0).evaluate('b').value());
+      assertEquals(3, exec_state.frame(1).evaluate('a').value());
+      assertEquals(4, exec_state.frame(1).evaluate('b').value());
+      assertEquals(5, exec_state.frame(2).evaluate('a').value());
+      assertEquals(6, exec_state.frame(2).evaluate('b').value());
+
+      // Indicate that all was processed.
+      listenerComplete = true;
+    }
+  } catch (e) {
+    exception = e
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function h() {
+  var a = 1;
+  var b = 2;
+  debugger;  // Breakpoint.
+};
+
+function g() {
+  var a = 3;
+  eval("var b = 4;");
+  h();
+};
+
+function f() {
+  var a = 5;
+  var b = 0;
+  with ({b:6}) {
+    g();
+  }
+};
+
+f();
+
+// Make sure that the debug event listener vas invoked.
+assertTrue(listenerComplete);
+assertFalse(exception, "exception in listener")
diff --git a/deps/v8/test/mjsunit/debug-evaluate-recursive.js b/deps/v8/test/mjsunit/debug-evaluate-recursive.js
new file mode 100644
index 0000000..9f037e5
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-evaluate-recursive.js
@@ -0,0 +1,167 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+listenerComplete = false;
+exception = false;
+
+// The base part of all evaluate requests.
+var base_request = '"seq":0,"type":"request","command":"evaluate"'
+
+function safeEval(code) {
+  try {
+    return eval('(' + code + ')');
+  } catch (e) {
+    assertEquals(void 0, e);
+    return undefined;
+  }
+}
+
+function testRequest(dcp, arguments, success, result) {
+  // Generate request with the supplied arguments.
+  var request;
+  if (arguments) {
+    request = '{' + base_request + ',"arguments":' + arguments + '}';
+  } else {
+    request = '{' + base_request + '}'
+  }
+  var response = safeEval(dcp.processDebugJSONRequest(request));
+  if (success) {
+    assertTrue(response.success, request + ' -> ' + response.message);
+    assertEquals(result, response.body.value);
+  } else {
+    assertFalse(response.success, request + ' -> ' + response.message);
+  }
+  assertFalse(response.running, request + ' -> expected not running');
+}
+
+
+// Event listener which evaluates with break disabled.
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break)
+    {
+      // Call functions with break using the FrameMirror directly.
+      assertEquals(1, exec_state.evaluateGlobal('f()', true).value());
+      assertEquals(2, exec_state.evaluateGlobal('g()', true).value());
+      assertEquals(1, exec_state.frame(0).evaluate('f()', true).value());
+      assertEquals(2, exec_state.frame(0).evaluate('g()', true).value());
+
+      // Get the debug command processor.
+      var dcp = exec_state.debugCommandProcessor();
+
+      // Call functions with break using the JSON protocol. Tests that argument
+      // disable_break is default true.
+      testRequest(dcp, '{"expression":"f()"}', true, 1);
+      testRequest(dcp, '{"expression":"f()","frame":0}',  true, 1);
+      testRequest(dcp, '{"expression":"g()"}', true, 2);
+      testRequest(dcp, '{"expression":"g()","frame":0}',  true, 2);
+
+      // Call functions with break using the JSON protocol. Tests passing
+      // argument disable_break is default true.
+      testRequest(dcp, '{"expression":"f()","disable_break":true}', true, 1);
+      testRequest(dcp, '{"expression":"f()","frame":0,"disable_break":true}',
+                  true, 1);
+      testRequest(dcp, '{"expression":"g()","disable_break":true}', true, 2);
+      testRequest(dcp, '{"expression":"g()","frame":0,"disable_break":true}',
+                  true, 2);
+
+      // Indicate that all was processed.
+      listenerComplete = true;
+    }
+  } catch (e) {
+    exception = e
+  };
+};
+
+
+// Event listener which evaluates with break enabled one time and the second
+// time evaluates with break disabled.
+var break_count = 0;
+function listener_recurse(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break)
+    {
+      break_count++;
+      
+      // Call functions with break using the FrameMirror directly.
+      if (break_count == 1) {
+        // First break event evaluates with break enabled.
+        assertEquals(1, exec_state.frame(0).evaluate('f()', false).value());
+        listenerComplete = true;
+      } else {
+        // Second break event evaluates with break disabled.
+        assertEquals(2, break_count);
+        assertFalse(listenerComplete);
+        assertEquals(1, exec_state.frame(0).evaluate('f()', true).value());
+      }
+    }
+  } catch (e) {
+    exception = e
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Test functions - one with break point and one with debugger statement.
+function f() {
+  return 1;
+};
+
+function g() {
+  debugger;
+  return 2;
+};
+
+Debug.setBreakPoint(f, 2, 0);
+
+// Cause a debug break event.
+debugger;
+
+// Make sure that the debug event listener vas invoked.
+assertTrue(listenerComplete);
+assertFalse(exception, "exception in listener")
+
+// Remove the debug event listener.
+Debug.setListener(null);
+
+// Set debug event listener wich uses recursive breaks.
+Debug.setListener(listener_recurse);
+listenerComplete = false;
+
+Debug.setBreakPoint(f, 2, 0);
+
+debugger;
+
+// Make sure that the debug event listener vas invoked.
+assertTrue(listenerComplete);
+assertFalse(exception, "exception in listener")
+assertEquals(2, break_count);
diff --git a/deps/v8/test/mjsunit/debug-evaluate-with.js b/deps/v8/test/mjsunit/debug-evaluate-with.js
new file mode 100644
index 0000000..9d95a9f
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-evaluate-with.js
@@ -0,0 +1,77 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+listenerComplete = false;
+exception = false;
+breakPointCount = 0;
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break)
+    {
+      breakPointCount++;
+      if (breakPointCount == 1) {
+        // Break point in first with block.
+        assertEquals(2, exec_state.frame(0).evaluate('a').value());
+        assertEquals(2, exec_state.frame(0).evaluate('b').value());
+      } else {
+        // Break point in second with block.
+        assertEquals(3, exec_state.frame(0).evaluate('a').value());
+        assertEquals(1, exec_state.frame(0).evaluate('b').value());
+
+        // Indicate that all was processed.
+        listenerComplete = true;
+      }
+    }
+  } catch (e) {
+    exception = e
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function f() {
+  var a = 1;
+  var b = 2;
+  with ({a:2}) {
+    debugger;  // Breakpoint.
+    x = {a:3,b:1};
+    with (x) {
+      debugger;  // Breakpoint.
+    }
+  }
+};
+
+f();
+// Make sure that the debug event listener vas invoked.
+assertTrue(listenerComplete);
+assertFalse(exception, "exception in listener")
diff --git a/deps/v8/test/mjsunit/debug-evaluate.js b/deps/v8/test/mjsunit/debug-evaluate.js
new file mode 100644
index 0000000..5c5734f
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-evaluate.js
@@ -0,0 +1,117 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+listenerComplete = false;
+exception = false;
+
+// The base part of all evaluate requests.
+var base_request = '"seq":0,"type":"request","command":"evaluate"'
+
+function safeEval(code) {
+  try {
+    return eval('(' + code + ')');
+  } catch (e) {
+    assertEquals(void 0, e);
+    return undefined;
+  }
+}
+
+function testRequest(dcp, arguments, success, result) {
+  // Generate request with the supplied arguments.
+  var request;
+  if (arguments) {
+    request = '{' + base_request + ',"arguments":' + arguments + '}';
+  } else {
+    request = '{' + base_request + '}'
+  }
+  var response = safeEval(dcp.processDebugJSONRequest(request));
+  if (success) {
+    assertTrue(response.success, request + ' -> ' + response.message);
+    assertEquals(result, response.body.value);
+  } else {
+    assertFalse(response.success, request + ' -> ' + response.message);
+  }
+  assertFalse(response.running, request + ' -> expected not running');
+}
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      // Get the debug command processor.
+      var dcp = exec_state.debugCommandProcessor();
+
+      // Test some illegal evaluate requests.
+      testRequest(dcp, void 0, false);
+      testRequest(dcp, '{"expression":"1","global"=true}', false);
+      testRequest(dcp, '{"expression":"a","frame":4}', false);
+
+      // Test some legal evaluate requests.
+      testRequest(dcp, '{"expression":"1+2"}', true, 3);
+      testRequest(dcp, '{"expression":"a+2"}', true, 5);
+      testRequest(dcp, '{"expression":"({\\"a\\":1,\\"b\\":2}).b+2"}', true, 4);
+
+      // Test evaluation of a in the stack frames and the global context.
+      testRequest(dcp, '{"expression":"a"}', true, 3);
+      testRequest(dcp, '{"expression":"a","frame":0}', true, 3);
+      testRequest(dcp, '{"expression":"a","frame":1}', true, 2);
+      testRequest(dcp, '{"expression":"a","frame":2}', true, 1);
+      testRequest(dcp, '{"expression":"a","global":true}', true, 1);
+      testRequest(dcp, '{"expression":"this.a","global":true}', true, 1);
+
+      // Indicate that all was processed.
+      listenerComplete = true;
+    }
+  } catch (e) {
+   exception = e
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function f() {
+  var a = 3;
+};
+
+function g() {
+  var a = 2;
+  f();
+};
+
+a = 1;
+
+// Set a break point at return in f and invoke g to hit the breakpoint.
+Debug.setBreakPoint(f, 2, 0);
+g();
+
+// Make sure that the debug event listener vas invoked.
+assertTrue(listenerComplete, "listener did not run to completion");
+assertFalse(exception, "exception in listener")
diff --git a/deps/v8/test/mjsunit/debug-event-listener.js b/deps/v8/test/mjsunit/debug-event-listener.js
new file mode 100644
index 0000000..a2eb5f0
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-event-listener.js
@@ -0,0 +1,73 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// Simple function which stores the last debug event.
+lastDebugEvent = new Object();
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break ||
+      event == Debug.DebugEvent.Exception)
+  {
+    lastDebugEvent.event = event;
+    lastDebugEvent.frameFuncName = exec_state.frame().func().name();
+    lastDebugEvent.event_data = event_data;
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+// Get events from handled exceptions.
+Debug.setBreakOnException();
+
+// Test debug event for handled exception.
+(function f(){
+  try {
+    x();
+  } catch(e) {
+    // Do nothing. Ignore exception.
+  }
+})();
+assertTrue(lastDebugEvent.event == Debug.DebugEvent.Exception);
+assertEquals(lastDebugEvent.frameFuncName, "f");
+assertFalse(lastDebugEvent.event_data.uncaught());
+Debug.clearBreakOnException();
+
+// Test debug event for break point.
+function a() {
+  x = 1;
+  y = 2;
+  z = 3;
+};
+Debug.setBreakPoint(a, 1);
+a();
+assertTrue(lastDebugEvent.event == Debug.DebugEvent.Break);
+assertEquals(lastDebugEvent.frameFuncName, "a");
+
+Debug.setListener(null);
diff --git a/deps/v8/test/mjsunit/debug-handle.js b/deps/v8/test/mjsunit/debug-handle.js
new file mode 100644
index 0000000..64a68a8
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-handle.js
@@ -0,0 +1,199 @@
+// 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+listenerComplete = false;
+exception = false;
+
+function safeEval(code) {
+  try {
+    return eval('(' + code + ')');
+  } catch (e) {
+    assertEquals(void 0, e);
+    return undefined;
+  }
+}
+
+
+// Send an evaluation request and return the handle of the result.
+function evaluateRequest(dcp, arguments) {
+  // The base part of all evaluate requests.
+  var base_request = '"seq":0,"type":"request","command":"evaluate"'
+
+  // Generate request with the supplied arguments.
+  var request;
+  if (arguments) {
+    request = '{' + base_request + ',"arguments":' + arguments + '}';
+  } else {
+    request = '{' + base_request + '}'
+  }
+
+  var response = safeEval(dcp.processDebugJSONRequest(request));
+  assertTrue(response.success, request + ' -> ' + response.message);
+
+  return response.body.handle;
+}
+
+
+// Send a lookup request and return the evaluated JSON response.
+function lookupRequest(dcp, arguments, success) {
+  // The base part of all lookup requests.
+  var base_request = '"seq":0,"type":"request","command":"lookup"'
+  
+  // Generate request with the supplied arguments.
+  var request;
+  if (arguments) {
+    request = '{' + base_request + ',"arguments":' + arguments + '}';
+  } else {
+    request = '{' + base_request + '}'
+  }
+
+  var response = safeEval(dcp.processDebugJSONRequest(request));
+  if (success) {
+    assertTrue(response.success, request + ' -> ' + response.message);
+  } else {
+    assertFalse(response.success, request + ' -> ' + response.message);
+  }
+  assertFalse(response.running, request + ' -> expected not running');
+
+  return response;
+}
+
+
+function listener(event, exec_state, event_data, data) {
+  try {
+  if (event == Debug.DebugEvent.Break) {
+    // Get the debug command processor.
+    var dcp = exec_state.debugCommandProcessor();
+
+    // Test some illegal lookup requests.
+    lookupRequest(dcp, void 0, false);
+    lookupRequest(dcp, '{"handle":"a"}', false);
+    lookupRequest(dcp, '{"handle":-1}', false);
+
+    // Evaluate and get some handles.
+    var handle_o = evaluateRequest(dcp, '{"expression":"o"}');
+    var handle_p = evaluateRequest(dcp, '{"expression":"p"}');
+    var handle_b = evaluateRequest(dcp, '{"expression":"a"}');
+    var handle_a = evaluateRequest(dcp, '{"expression":"b","frame":1}');
+    assertEquals(handle_o, handle_a);
+    assertEquals(handle_a, handle_b);
+    assertFalse(handle_o == handle_p, "o and p have he same handle");
+
+    var response;
+    var count;
+    response = lookupRequest(dcp, '{"handle":' + handle_o + '}', true);
+    assertEquals(handle_o, response.body.handle);
+    count = 0;
+    for (i in response.body.properties) {
+      switch (response.body.properties[i].name) {
+        case 'o':
+          response.body.properties[i].ref = handle_o;
+          count++;
+          break;
+        case 'p':
+          response.body.properties[i].ref = handle_p;
+          count++;
+          break;
+      }
+    }
+    assertEquals(2, count, 'Either "o" or "p" not found');
+    response = lookupRequest(dcp, '{"handle":' + handle_p + '}', true);
+    assertEquals(handle_p, response.body.handle);
+
+    // Check handles for functions on the stack.
+    var handle_f = evaluateRequest(dcp, '{"expression":"f"}');
+    var handle_g = evaluateRequest(dcp, '{"expression":"g"}');
+    var handle_caller = evaluateRequest(dcp, '{"expression":"f.caller"}');
+
+    assertFalse(handle_f == handle_g, "f and g have he same handle");
+    assertEquals(handle_g, handle_caller, "caller for f should be g");
+
+    response = lookupRequest(dcp, '{"handle":' + handle_f + '}', true);
+    assertEquals(handle_f, response.body.handle);
+    count = 0;
+    for (i in response.body.properties) {
+      var arguments = '{"handle":' + response.body.properties[i].ref + '}'
+      switch (response.body.properties[i].name) {
+        case 'name':
+          var response_name;
+          response_name = lookupRequest(dcp, arguments, true);
+          assertEquals('string', response_name.body.type);
+          assertEquals("f", response_name.body.value);
+          count++;
+          break;
+        case 'length':
+          var response_length;
+          response_length = lookupRequest(dcp, arguments, true);
+          assertEquals('number', response_length.body.type);
+          assertEquals(1, response_length.body.value);
+          count++;
+          break;
+        case 'caller':
+          assertEquals(handle_g, response.body.properties[i].ref);
+          count++;
+          break;
+      }
+    }
+    assertEquals(3, count, 'Either "name", "length" or "caller" not found');
+
+
+    // Indicate that all was processed.
+    listenerComplete = true;
+  }
+  } catch (e) {
+    exception = e
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function f(a) {
+  debugger;
+};
+
+function g(b) {
+  f(b);
+};
+
+// Set a break point at return in f and invoke g to hit the breakpoint.
+Debug.setBreakPoint(f, 2, 0);
+o = {};
+p = {}
+o.o = o;
+o.p = p;
+p.o = o;
+p.p = p;
+g(o);
+
+// Make sure that the debug event listener vas invoked.
+assertTrue(listenerComplete, "listener did not run to completion");
+assertFalse(exception, "exception in listener")
diff --git a/deps/v8/test/mjsunit/debug-ignore-breakpoints.js b/deps/v8/test/mjsunit/debug-ignore-breakpoints.js
new file mode 100644
index 0000000..96c6044
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-ignore-breakpoints.js
@@ -0,0 +1,89 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// Simple debug event handler which just counts the number of break points hit.
+var break_point_hit_count;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    break_point_hit_count++;
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Test function.
+function f() {};
+
+// This tests ignore of break points including the case with several
+// break points in the same location.
+break_point_hit_count = 0;
+
+// Set a breakpoint in f.
+bp1 = Debug.setBreakPoint(f);
+
+// Try ignore count of 1.
+Debug.changeBreakPointIgnoreCount(bp1, 1);
+f();
+assertEquals(0, break_point_hit_count);
+f();
+assertEquals(1, break_point_hit_count);
+
+// Set another breakpoint in f at the same place.
+bp2 = Debug.setBreakPoint(f);
+f();
+assertEquals(2, break_point_hit_count);
+
+// Set different ignore counts.
+Debug.changeBreakPointIgnoreCount(bp1, 2);
+Debug.changeBreakPointIgnoreCount(bp2, 4);
+f();
+assertEquals(2, break_point_hit_count);
+f();
+assertEquals(2, break_point_hit_count);
+f();
+assertEquals(3, break_point_hit_count);
+f();
+assertEquals(4, break_point_hit_count);
+
+// Set different ignore counts (opposite).
+Debug.changeBreakPointIgnoreCount(bp1, 4);
+Debug.changeBreakPointIgnoreCount(bp2, 2);
+f();
+assertEquals(4, break_point_hit_count);
+f();
+assertEquals(4, break_point_hit_count);
+f();
+assertEquals(5, break_point_hit_count);
+f();
+assertEquals(6, break_point_hit_count);
+
diff --git a/deps/v8/test/mjsunit/debug-mirror-cache.js b/deps/v8/test/mjsunit/debug-mirror-cache.js
new file mode 100644
index 0000000..d15146f
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-mirror-cache.js
@@ -0,0 +1,85 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// The functions used for testing backtraces. They are at the top to make the
+// testing of source line/column easier.
+function f(x, y) {
+  a=1;
+};
+
+function g() {
+  new f(1);
+};
+
+
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+listenerCallCount = 0;
+listenerExceptionCount = 0;
+
+
+function listener(event, exec_state, event_data, data) {
+  try {
+  if (event == Debug.DebugEvent.Break)
+  {
+    listenerCallCount++;
+
+    // Check that mirror cache is cleared when entering debugger.
+    assertEquals(0, debug.next_handle_, "Mirror cache not cleared");
+    assertEquals(0, debug.mirror_cache_.length, "Mirror cache not cleared");
+
+    // Get the debug command processor.
+    var dcp = exec_state.debugCommandProcessor();
+
+    // Make a backtrace request to create some mirrors.
+    var json;
+    json = '{"seq":0,"type":"request","command":"backtrace"}'
+    dcp.processDebugJSONRequest(json);
+
+    // Some mirrors where cached.
+    assertFalse(debug.next_handle_ == 0, "Mirror cache not used");
+    assertFalse(debug.mirror_cache_.length == 0, "Mirror cache not used");
+  }
+  } catch (e) {
+    print(e);
+    listenerExceptionCount++;
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Enter the debugger twice.
+debugger;
+debugger;
+
+// Make sure that the debug event listener vas invoked.
+assertEquals(2, listenerCallCount, "Listener not called");
+assertEquals(0, listenerExceptionCount, "Exception in listener");
+
diff --git a/deps/v8/test/mjsunit/debug-multiple-breakpoints.js b/deps/v8/test/mjsunit/debug-multiple-breakpoints.js
new file mode 100644
index 0000000..1047410
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-multiple-breakpoints.js
@@ -0,0 +1,105 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// Simple debug event handler which just counts the number of break points hit.
+var break_point_hit_count;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    break_point_hit_count++;
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Test functions
+function f() {a=1;b=2;};
+function g() {f();}
+function h() {}
+
+// This test sets several break points at the same place and checks that
+// several break points at the same place only makes one debug break event
+// and that when the last break point is removed no more debug break events
+// occours.
+break_point_hit_count = 0;
+
+// Set a breakpoint in f.
+bp1 = Debug.setBreakPoint(f);
+f();
+assertEquals(1, break_point_hit_count);
+
+// Set another breakpoint in f at the same place.
+bp2 = Debug.setBreakPoint(f);
+f();
+assertEquals(2, break_point_hit_count);
+
+// Remove one of the break points.
+Debug.clearBreakPoint(bp1);
+f();
+assertEquals(3, break_point_hit_count);
+
+// Remove the second break point.
+Debug.clearBreakPoint(bp2);
+f();
+assertEquals(3, break_point_hit_count);
+
+// Perform the same test using function g (this time removing the break points
+// in the another order).
+break_point_hit_count = 0;
+bp1 = Debug.setBreakPoint(g);
+g();
+assertEquals(1, break_point_hit_count);
+bp2 = Debug.setBreakPoint(g);
+g();
+assertEquals(2, break_point_hit_count);
+Debug.clearBreakPoint(bp2);
+g();
+assertEquals(3, break_point_hit_count);
+Debug.clearBreakPoint(bp1);
+g();
+assertEquals(3, break_point_hit_count);
+
+// Finally test with many break points.
+test_count = 100;
+bps = new Array(test_count);
+break_point_hit_count = 0;
+for (var i = 0; i < test_count; i++) {
+  bps[i] = Debug.setBreakPoint(h);
+  h();
+}
+for (var i = 0; i < test_count; i++) {
+  h();
+  Debug.clearBreakPoint(bps[i]);
+}
+assertEquals(test_count * 2, break_point_hit_count);
+h();
+assertEquals(test_count * 2, break_point_hit_count);
diff --git a/deps/v8/test/mjsunit/debug-referenced-by.js b/deps/v8/test/mjsunit/debug-referenced-by.js
new file mode 100644
index 0000000..915a0c7
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-referenced-by.js
@@ -0,0 +1,112 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// Simple object.
+var a = {};
+
+// Create mirror for the object.
+var mirror = debug.MakeMirror(a);
+
+// Initially one reference from the global object.
+assertEquals(1, mirror.referencedBy().length);
+assertEquals(1, mirror.referencedBy(0).length);
+assertEquals(1, mirror.referencedBy(1).length);
+assertEquals(1, mirror.referencedBy(10).length);
+
+// Add some more references from simple objects and arrays.
+var b = {}
+b.a = a;
+assertEquals(2, mirror.referencedBy().length);
+var c = {}
+c.a = a;
+c.aa = a;
+c.aaa = a;
+assertEquals(3, mirror.referencedBy().length);
+function d(){};
+d.a = a
+assertEquals(4, mirror.referencedBy().length);
+e = [a,b,c,d];
+assertEquals(5, mirror.referencedBy().length);
+
+
+// Simple closure.
+function closure_simple(p) {
+  return function() { p = null; };
+}
+
+// This adds a reference (function context).
+f = closure_simple(a);
+assertEquals(6, mirror.referencedBy().length);
+// This clears the reference (in function context).
+f()
+assertEquals(5, mirror.referencedBy().length);
+
+// Use closure with eval - creates arguments array.
+function closure_eval(p, s) {
+  if (s) {
+    eval(s);
+  }
+  return function e(s) { eval(s); };
+}
+
+// This adds a references (function context).
+g = closure_eval(a);
+assertEquals(6, mirror.referencedBy().length);
+
+// Dynamically create a variable. This should create a context extension.
+h = closure_eval(null, "var x_");
+assertEquals(6, mirror.referencedBy().length);
+// Adds a reference when set.
+h("x_ = a");
+var x = mirror.referencedBy();
+assertEquals(7, mirror.referencedBy().length);
+// Removes a reference when cleared.
+h("x_ = null");
+assertEquals(6, mirror.referencedBy().length);
+
+// Check circular references.
+x = {}
+mirror = debug.MakeMirror(x);
+assertEquals(1, mirror.referencedBy().length);
+x.x = x;
+assertEquals(2, mirror.referencedBy().length);
+x = null;
+assertEquals(0, mirror.referencedBy().length);
+
+// Check many references.
+y = {}
+mirror = debug.MakeMirror(y);
+refs = [];
+for (var i = 0; i < 200; i++) {
+  refs[i] = {'y': y};
+}
+y = null;
+assertEquals(200, mirror.referencedBy().length);
diff --git a/deps/v8/test/mjsunit/debug-references.js b/deps/v8/test/mjsunit/debug-references.js
new file mode 100644
index 0000000..dedc3ef
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-references.js
@@ -0,0 +1,118 @@
+// 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+listenerComplete = false;
+exception = false;
+
+// The base part of all evaluate requests.
+var base_request = '"seq":0,"type":"request","command":"references"'
+
+function safeEval(code) {
+  try {
+    return eval('(' + code + ')');
+  } catch (e) {
+    assertEquals(void 0, e);
+    return undefined;
+  }
+}
+
+function testRequest(dcp, arguments, success, count) {
+  // Generate request with the supplied arguments.
+  var request;
+  if (arguments) {
+    request = '{' + base_request + ',"arguments":' + arguments + '}';
+  } else {
+    request = '{' + base_request + '}'
+  }
+  
+  // Process the request and check expectation.
+  var response = safeEval(dcp.processDebugJSONRequest(request));
+  if (success) {
+    assertTrue(response.success, request + ' -> ' + response.message);
+    assertTrue(response.body instanceof Array);
+    if (count) {
+      assertEquals(count, response.body.length);
+    } else {
+      assertTrue(response.body.length > 0);
+    }
+  } else {
+    assertFalse(response.success, request + ' -> ' + response.message);
+  }
+  assertFalse(response.running, request + ' -> expected not running');
+}
+
+function listener(event, exec_state, event_data, data) {
+  try {
+  if (event == Debug.DebugEvent.Break) {
+    // Get the debug command processor.
+    var dcp = exec_state.debugCommandProcessor();
+
+    // Test some illegal references requests.
+    testRequest(dcp, void 0, false);
+    testRequest(dcp, '{"handle":"a"}', false);
+    testRequest(dcp, '{"handle":1}', false);
+    testRequest(dcp, '{"type":"referencedBy"}', false);
+    testRequest(dcp, '{"type":"constructedBy"}', false);
+
+    // Evaluate Point.
+    var evaluate_point = '{"seq":0,"type":"request","command":"evaluate",' +
+                         '"arguments":{"expression":"Point"}}';
+    var response = safeEval(dcp.processDebugJSONRequest(evaluate_point));
+    assertTrue(response.success, "Evaluation of Point failed");
+    var handle = response.body.handle;
+    
+    // Test some legal references requests.
+    testRequest(dcp, '{"handle":' + handle + ',"type":"referencedBy"}', true);
+    testRequest(dcp, '{"handle":' + handle + ',"type":"constructedBy"}',
+                true, 2);
+
+    // Indicate that all was processed.
+    listenerComplete = true;
+  }
+  } catch (e) {
+    exception = e
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Test constructor and objects.
+function Point(x, y) { this.x_ = x; this.y_ = y;}
+p = new Point(0,0);
+q = new Point(1,2);
+
+// Enter debugger causing the event listener to be called.
+debugger;
+
+// Make sure that the debug event listener vas invoked.
+assertFalse(exception, "exception in listener")
+assertTrue(listenerComplete, "listener did not run to completion");
diff --git a/deps/v8/test/mjsunit/debug-script-breakpoints.js b/deps/v8/test/mjsunit/debug-script-breakpoints.js
new file mode 100644
index 0000000..ec9656c
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-script-breakpoints.js
@@ -0,0 +1,112 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// Set and remove a script break point for a named script.
+var sbp = Debug.setScriptBreakPointByName("1", 2, 3);
+assertEquals(1, Debug.scriptBreakPoints().length);
+assertEquals("1", Debug.scriptBreakPoints()[0].script_name());
+assertEquals(2, Debug.scriptBreakPoints()[0].line());
+assertEquals(3, Debug.scriptBreakPoints()[0].column());
+Debug.clearBreakPoint(sbp);
+assertEquals(0, Debug.scriptBreakPoints().length);
+
+// Set three script break points for named scripts.
+var sbp1 = Debug.setScriptBreakPointByName("1", 2, 3);
+var sbp2 = Debug.setScriptBreakPointByName("2", 3, 4);
+var sbp3 = Debug.setScriptBreakPointByName("3", 4, 5);
+
+// Check the content of the script break points.
+assertEquals(3, Debug.scriptBreakPoints().length);
+for (var i = 0; i < Debug.scriptBreakPoints().length; i++) {
+  var x = Debug.scriptBreakPoints()[i];
+  if ("1" == x.script_name()) {
+    assertEquals(2, x.line());
+    assertEquals(3, x.column());
+  } else if ("2" == x.script_name()) {
+    assertEquals(3, x.line());
+    assertEquals(4, x.column());
+  } else if ("3" == x.script_name()) {
+    assertEquals(4, x.line());
+    assertEquals(5, x.column());
+  } else {
+    assertUnreachable("unecpected script_name " + x.script_name());
+  }
+}
+
+// Remove script break points (in another order than they where added).
+assertEquals(3, Debug.scriptBreakPoints().length);
+Debug.clearBreakPoint(sbp1);
+assertEquals(2, Debug.scriptBreakPoints().length);
+Debug.clearBreakPoint(sbp3);
+assertEquals(1, Debug.scriptBreakPoints().length);
+Debug.clearBreakPoint(sbp2);
+assertEquals(0, Debug.scriptBreakPoints().length);
+
+// Set and remove a script break point for a script id.
+var sbp = Debug.setScriptBreakPointById(1, 2, 3);
+assertEquals(1, Debug.scriptBreakPoints().length);
+assertEquals(1, Debug.scriptBreakPoints()[0].script_id());
+assertEquals(2, Debug.scriptBreakPoints()[0].line());
+assertEquals(3, Debug.scriptBreakPoints()[0].column());
+Debug.clearBreakPoint(sbp);
+assertEquals(0, Debug.scriptBreakPoints().length);
+
+// Set three script break points for script ids.
+var sbp1 = Debug.setScriptBreakPointById(1, 2, 3);
+var sbp2 = Debug.setScriptBreakPointById(2, 3, 4);
+var sbp3 = Debug.setScriptBreakPointById(3, 4, 5);
+
+// Check the content of the script break points.
+assertEquals(3, Debug.scriptBreakPoints().length);
+for (var i = 0; i < Debug.scriptBreakPoints().length; i++) {
+  var x = Debug.scriptBreakPoints()[i];
+  if (1 == x.script_id()) {
+    assertEquals(2, x.line());
+    assertEquals(3, x.column());
+  } else if (2 == x.script_id()) {
+    assertEquals(3, x.line());
+    assertEquals(4, x.column());
+  } else if (3 == x.script_id()) {
+    assertEquals(4, x.line());
+    assertEquals(5, x.column());
+  } else {
+    assertUnreachable("unecpected script_id " + x.script_id());
+  }
+}
+
+// Remove script break points (in another order than they where added).
+assertEquals(3, Debug.scriptBreakPoints().length);
+Debug.clearBreakPoint(sbp1);
+assertEquals(2, Debug.scriptBreakPoints().length);
+Debug.clearBreakPoint(sbp3);
+assertEquals(1, Debug.scriptBreakPoints().length);
+Debug.clearBreakPoint(sbp2);
+assertEquals(0, Debug.scriptBreakPoints().length);
diff --git a/deps/v8/test/mjsunit/debug-script.js b/deps/v8/test/mjsunit/debug-script.js
new file mode 100644
index 0000000..effa145
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-script.js
@@ -0,0 +1,92 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug --expose-gc
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+Date();
+RegExp();
+
+// Count script types.
+var named_native_count = 0;
+var extension_count = 0;
+var normal_count = 0;
+var scripts = Debug.scripts();
+for (i = 0; i < scripts.length; i++) {
+  if (scripts[i].type == Debug.ScriptType.Native) {
+    if (scripts[i].name) {
+      named_native_count++;
+    }
+  } else if (scripts[i].type == Debug.ScriptType.Extension) {
+    extension_count++;
+  } else if (scripts[i].type == Debug.ScriptType.Normal) {
+    normal_count++;
+  } else {
+    assertUnreachable('Unexpected type ' + scripts[i].type);
+  }
+}
+
+// This has to be updated if the number of native scripts change.
+assertEquals(12, named_native_count);
+// If no snapshot is used, only the 'gc' extension is loaded.
+// If snapshot is used, all extensions are cached in the snapshot.
+assertTrue(extension_count == 1 || extension_count == 5);
+// This script and mjsunit.js has been loaded.  If using d8, d8 loads
+// a normal script during startup too.
+assertTrue(normal_count == 2 || normal_count == 3);
+
+// Test a builtins script.
+var math_script = Debug.findScript('native math.js');
+assertEquals('native math.js', math_script.name);
+assertEquals(Debug.ScriptType.Native, math_script.type);
+
+// Test a builtins delay loaded script.
+var date_delay_script = Debug.findScript('native date.js');
+assertEquals('native date.js', date_delay_script.name);
+assertEquals(Debug.ScriptType.Native, date_delay_script.type);
+
+// Test a debugger script.
+var debug_delay_script = Debug.findScript('native debug.js');
+assertEquals('native debug.js', debug_delay_script.name);
+assertEquals(Debug.ScriptType.Native, debug_delay_script.type);
+
+// Test an extension script.
+var extension_gc_script = Debug.findScript('v8/gc');
+if (extension_gc_script) {
+  assertEquals('v8/gc', extension_gc_script.name);
+  assertEquals(Debug.ScriptType.Extension, extension_gc_script.type);
+}
+
+// Test a normal script.
+var mjsunit_js_script = Debug.findScript(/mjsunit.js/);
+assertTrue(/mjsunit.js/.test(mjsunit_js_script.name));
+assertEquals(Debug.ScriptType.Normal, mjsunit_js_script.type);
+
+// Check a nonexistent script.
+var dummy_script = Debug.findScript('dummy.js');
+assertTrue(typeof dummy_script == 'undefined');
diff --git a/deps/v8/test/mjsunit/debug-scripts-request.js b/deps/v8/test/mjsunit/debug-scripts-request.js
new file mode 100644
index 0000000..cf1615b
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-scripts-request.js
@@ -0,0 +1,95 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// State to check that the listener code was invoked and that no exceptions
+// occoured.
+listenerComplete = false;
+exception = false;
+
+var base_request = '"seq":0,"type":"request","command":"scripts"'
+
+function safeEval(code) {
+  try {
+    return eval('(' + code + ')');
+  } catch (e) {
+    assertEquals(void 0, e);
+    return undefined;
+  }
+}
+
+function testArguments(dcp, arguments, success) {
+  var request = '{' + base_request + ',"arguments":' + arguments + '}'
+  var json_response = dcp.processDebugJSONRequest(request);
+  var response = safeEval(json_response);
+  if (success) {
+    assertTrue(response.success, json_response);
+  } else {
+    assertFalse(response.success, json_response);
+  }
+}
+
+function listener(event, exec_state, event_data, data) {
+  try {
+  if (event == Debug.DebugEvent.Break) {
+    // Get the debug command processor.
+    var dcp = exec_state.debugCommandProcessor();
+
+    // Test illegal scripts requests.
+    testArguments(dcp, '{"types":"xx"}', false);
+
+    // Test legal scripts requests.
+    var request = '{' + base_request + '}'
+    var response = safeEval(dcp.processDebugJSONRequest(request));
+    assertTrue(response.success);
+    testArguments(dcp, '{}', true);
+    testArguments(dcp, '{"types":1}', true);
+    testArguments(dcp, '{"types":2}', true);
+    testArguments(dcp, '{"types":4}', true);
+    testArguments(dcp, '{"types":7}', true);
+    testArguments(dcp, '{"types":0xFF}', true);
+
+    // Indicate that all was processed.
+    listenerComplete = true;
+  }
+  } catch (e) {
+    exception = e
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Call debugger to invoke the debug event listener.
+debugger;
+
+// Make sure that the debug event listener vas invoked with no exceptions.
+assertTrue(listenerComplete, "listener did not run to completion");
+assertFalse(exception, "exception in listener")
diff --git a/deps/v8/test/mjsunit/debug-setbreakpoint.js b/deps/v8/test/mjsunit/debug-setbreakpoint.js
new file mode 100644
index 0000000..904ec18
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-setbreakpoint.js
@@ -0,0 +1,153 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// Simple function which stores the last debug event.
+var listenerComplete = false;
+var exception = false;
+var f_script_id = 0;
+var g_script_id = 0;
+var h_script_id = 0;
+var f_line = 0;
+var g_line = 0;
+
+var base_request = '"seq":0,"type":"request","command":"setbreakpoint"'
+
+function safeEval(code) {
+  try {
+    return eval('(' + code + ')');
+  } catch (e) {
+    assertEquals(void 0, e);
+    return undefined;
+  }
+}
+
+function testArguments(dcp, arguments, success, is_script) {
+  var request = '{' + base_request + ',"arguments":' + arguments + '}'
+  var json_response = dcp.processDebugJSONRequest(request);
+  var response = safeEval(json_response);
+  if (success) {
+    assertTrue(response.success, json_response);
+    if (is_script) {
+      assertEquals('scriptName', response.body.type, json_response);
+    } else {
+      assertEquals('scriptId', response.body.type, json_response);
+    }
+  } else {
+    assertFalse(response.success, json_response);
+  }
+}
+
+function listener(event, exec_state, event_data, data) {
+  try {
+  if (event == Debug.DebugEvent.Break) {
+    // Get the debug command processor.
+    var dcp = exec_state.debugCommandProcessor();
+
+    // Test some illegal setbreakpoint requests.
+    var request = '{' + base_request + '}'
+    var response = safeEval(dcp.processDebugJSONRequest(request));
+    assertFalse(response.success);
+
+    testArguments(dcp, '{}', false);
+    testArguments(dcp, '{"type":"xx"}', false);
+    testArguments(dcp, '{"type":"function"}', false);
+    testArguments(dcp, '{"type":"script"}', false);
+    testArguments(dcp, '{"target":"f"}', false);
+    testArguments(dcp, '{"type":"xx","target":"xx"}', false);
+    testArguments(dcp, '{"type":"function","target":1}', false);
+    testArguments(dcp, '{"type":"function","target":"f","line":-1}', false);
+    testArguments(dcp, '{"type":"function","target":"f","column":-1}', false);
+    testArguments(dcp, '{"type":"function","target":"f","ignoreCount":-1}', false);
+
+    // Test some legal setbreakpoint requests.
+    testArguments(dcp, '{"type":"function","target":"f"}', true, false);
+    testArguments(dcp, '{"type":"function","target":"h"}', true, false);
+    testArguments(dcp, '{"type":"function","target":"f","line":1}', true, false);
+    testArguments(dcp, '{"type":"function","target":"f","position":1}', true, false);
+    testArguments(dcp, '{"type":"function","target":"f","condition":"i == 1"}', true, false);
+    testArguments(dcp, '{"type":"function","target":"f","enabled":true}', true, false);
+    testArguments(dcp, '{"type":"function","target":"f","enabled":false}', true, false);
+    testArguments(dcp, '{"type":"function","target":"f","ignoreCount":7}', true, false);
+
+    testArguments(dcp, '{"type":"script","target":"test"}', true, true);
+    testArguments(dcp, '{"type":"script","target":"test"}', true, true);
+    testArguments(dcp, '{"type":"script","target":"test","line":1}', true, true);
+    testArguments(dcp, '{"type":"script","target":"test","column":1}', true, true);
+
+    testArguments(dcp, '{"type":"scriptId","target":' + f_script_id + ',"line":' + f_line + '}', true, false);
+    testArguments(dcp, '{"type":"scriptId","target":' + g_script_id + ',"line":' + g_line + '}', true, false);
+    testArguments(dcp, '{"type":"scriptId","target":' + h_script_id + ',"line":' + h_line + '}', true, false);
+
+    // Indicate that all was processed.
+    listenerComplete = true;
+  }
+  } catch (e) {
+    exception = e
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function f() {
+  a=1
+};
+
+function g() {
+  f();
+};
+
+eval('function h(){}');
+
+// Check the script ids for the test functions.
+f_script_id = Debug.findScript(f).id;
+g_script_id = Debug.findScript(g).id;
+h_script_id = Debug.findScript(h).id;
+assertTrue(f_script_id > 0, "invalid script id for f");
+assertTrue(g_script_id > 0, "invalid script id for g");
+assertTrue(h_script_id > 0, "invalid script id for h");
+assertEquals(f_script_id, g_script_id);
+
+// Get the source line for the test functions.
+f_line = Debug.findFunctionSourceLocation(f).line;
+g_line = Debug.findFunctionSourceLocation(g).line;
+h_line = Debug.findFunctionSourceLocation(h).line;
+assertTrue(f_line > 0, "invalid line for f");
+assertTrue(g_line > 0, "invalid line for g");
+assertTrue(f_line < g_line);
+assertEquals(h_line, 0, "invalid line for h");
+
+// Set a break point and call to invoke the debug event listener.
+Debug.setBreakPoint(g, 0, 0);
+g();
+
+// Make sure that the debug event listener vas invoked.
+assertTrue(listenerComplete, "listener did not run to completion: " + exception);
diff --git a/deps/v8/test/mjsunit/debug-sourceinfo.js b/deps/v8/test/mjsunit/debug-sourceinfo.js
new file mode 100644
index 0000000..36e9f03
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-sourceinfo.js
@@ -0,0 +1,276 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// For this test to work this file MUST have CR LF line endings.
+function a() { b(); };
+function    b() {
+  c(true);
+};
+  function c(x) {
+    if (x) {
+      return 1;
+    } else {
+      return 1;
+    }
+  };
+
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// This is the number of comment lines above the first test function.
+var comment_lines = 29;
+
+// This magic number is the length or the first line comment (actually number
+// of characters before 'function a(...'.
+var comment_line_length = 1726;
+var start_a = 10 + comment_line_length;
+var start_b = 37 + comment_line_length;
+var start_c = 71 + comment_line_length;
+
+assertEquals(start_a, Debug.sourcePosition(a));
+assertEquals(start_b, Debug.sourcePosition(b));
+assertEquals(start_c, Debug.sourcePosition(c));
+
+var script = Debug.findScript(a);
+assertTrue(script.data === Debug.findScript(b).data);
+assertTrue(script.data === Debug.findScript(c).data);
+assertTrue(script.source === Debug.findScript(b).source);
+assertTrue(script.source === Debug.findScript(c).source);
+
+// Test that when running through source positions the position, line and
+// column progresses as expected.
+var position;
+var line;
+var column;
+for (var p = 0; p < 100; p++) {
+  var location = script.locationFromPosition(p);
+  if (p > 0) {
+    assertEquals(position + 1, location.position);
+    if (line == location.line) {
+      assertEquals(column + 1, location.column);
+    } else {
+      assertEquals(line + 1, location.line);
+      assertEquals(0, location.column);
+    }
+  } else {
+    assertEquals(0, location.position);
+    assertEquals(0, location.line);
+    assertEquals(0, location.column);
+  }
+
+  // Remember the location.
+  position = location.position;
+  line = location.line;
+  column = location.column;
+}
+
+// Test first position.
+assertEquals(0, script.locationFromPosition(0).position);
+assertEquals(0, script.locationFromPosition(0).line);
+assertEquals(0, script.locationFromPosition(0).column);
+
+// Test second position.
+assertEquals(1, script.locationFromPosition(1).position);
+assertEquals(0, script.locationFromPosition(1).line);
+assertEquals(1, script.locationFromPosition(1).column);
+
+// Test first position in finction a.
+assertEquals(start_a, script.locationFromPosition(start_a).position);
+assertEquals(0, script.locationFromPosition(start_a).line - comment_lines);
+assertEquals(10, script.locationFromPosition(start_a).column);
+
+// Test first position in finction b.
+assertEquals(start_b, script.locationFromPosition(start_b).position);
+assertEquals(1, script.locationFromPosition(start_b).line - comment_lines);
+assertEquals(13, script.locationFromPosition(start_b).column);
+
+// Test first position in finction b.
+assertEquals(start_c, script.locationFromPosition(start_c).position);
+assertEquals(4, script.locationFromPosition(start_c).line - comment_lines);
+assertEquals(12, script.locationFromPosition(start_c).column);
+
+// Test first line.
+assertEquals(0, script.locationFromLine().position);
+assertEquals(0, script.locationFromLine().line);
+assertEquals(0, script.locationFromLine().column);
+assertEquals(0, script.locationFromLine(0).position);
+assertEquals(0, script.locationFromLine(0).line);
+assertEquals(0, script.locationFromLine(0).column);
+
+// Test first line column 1
+assertEquals(1, script.locationFromLine(0, 1).position);
+assertEquals(0, script.locationFromLine(0, 1).line);
+assertEquals(1, script.locationFromLine(0, 1).column);
+
+// Test first line offset 1
+assertEquals(1, script.locationFromLine(0, 0, 1).position);
+assertEquals(0, script.locationFromLine(0, 0, 1).line);
+assertEquals(1, script.locationFromLine(0, 0, 1).column);
+
+// Test offset function a
+assertEquals(start_a, script.locationFromLine(void 0, void 0, start_a).position);
+assertEquals(0, script.locationFromLine(void 0, void 0, start_a).line - comment_lines);
+assertEquals(10, script.locationFromLine(void 0, void 0, start_a).column);
+assertEquals(start_a, script.locationFromLine(0, void 0, start_a).position);
+assertEquals(0, script.locationFromLine(0, void 0, start_a).line - comment_lines);
+assertEquals(10, script.locationFromLine(0, void 0, start_a).column);
+assertEquals(start_a, script.locationFromLine(0, 0, start_a).position);
+assertEquals(0, script.locationFromLine(0, 0, start_a).line - comment_lines);
+assertEquals(10, script.locationFromLine(0, 0, start_a).column);
+
+// Test second line offset function a
+assertEquals(start_a + 14, script.locationFromLine(1, 0, start_a).position);
+assertEquals(1, script.locationFromLine(1, 0, start_a).line - comment_lines);
+assertEquals(0, script.locationFromLine(1, 0, start_a).column);
+
+// Test second line column 2 offset function a
+assertEquals(start_a + 14 + 2, script.locationFromLine(1, 2, start_a).position);
+assertEquals(1, script.locationFromLine(1, 2, start_a).line - comment_lines);
+assertEquals(2, script.locationFromLine(1, 2, start_a).column);
+
+// Test offset function b
+assertEquals(start_b, script.locationFromLine(0, 0, start_b).position);
+assertEquals(1, script.locationFromLine(0, 0, start_b).line - comment_lines);
+assertEquals(13, script.locationFromLine(0, 0, start_b).column);
+
+// Test second line offset function b
+assertEquals(start_b + 6, script.locationFromLine(1, 0, start_b).position);
+assertEquals(2, script.locationFromLine(1, 0, start_b).line - comment_lines);
+assertEquals(0, script.locationFromLine(1, 0, start_b).column);
+
+// Test second line column 11 offset function b
+assertEquals(start_b + 6 + 11, script.locationFromLine(1, 11, start_b).position);
+assertEquals(2, script.locationFromLine(1, 11, start_b).line - comment_lines);
+assertEquals(11, script.locationFromLine(1, 11, start_b).column);
+
+// Test second line column 12 offset function b. Second line in b is 11 long
+// using column 12 wraps to next line.
+assertEquals(start_b + 6 + 12, script.locationFromLine(1, 12, start_b).position);
+assertEquals(3, script.locationFromLine(1, 12, start_b).line - comment_lines);
+assertEquals(0, script.locationFromLine(1, 12, start_b).column);
+
+// Test the Debug.findSourcePosition which wraps SourceManager.
+assertEquals(0 + start_a, Debug.findFunctionSourceLocation(a, 0, 0).position);
+assertEquals(0 + start_b, Debug.findFunctionSourceLocation(b, 0, 0).position);
+assertEquals(6 + start_b, Debug.findFunctionSourceLocation(b, 1, 0).position);
+assertEquals(8 + start_b, Debug.findFunctionSourceLocation(b, 1, 2).position);
+assertEquals(18 + start_b, Debug.findFunctionSourceLocation(b, 2, 0).position);
+assertEquals(0 + start_c, Debug.findFunctionSourceLocation(c, 0, 0).position);
+assertEquals(7 + start_c, Debug.findFunctionSourceLocation(c, 1, 0).position);
+assertEquals(21 + start_c, Debug.findFunctionSourceLocation(c, 2, 0).position);
+assertEquals(38 + start_c, Debug.findFunctionSourceLocation(c, 3, 0).position);
+assertEquals(52 + start_c, Debug.findFunctionSourceLocation(c, 4, 0).position);
+assertEquals(69 + start_c, Debug.findFunctionSourceLocation(c, 5, 0).position);
+assertEquals(76 + start_c, Debug.findFunctionSourceLocation(c, 6, 0).position);
+
+// Test source line and restriction. All the following tests start from line 1
+// column 2 in function b, which is the call to c.
+//   c(true);
+//   ^
+
+var location;
+
+location = script.locationFromLine(1, 0, start_b);
+assertEquals('  c(true);', location.sourceText());
+
+result = ['c', ' c', ' c(', '  c(', '  c(t']
+for (var i = 1; i <= 5; i++) {
+  location = script.locationFromLine(1, 2, start_b);
+  location.restrict(i);
+  assertEquals(result[i - 1], location.sourceText());
+}
+
+location = script.locationFromLine(1, 2, start_b);
+location.restrict(1, 0);
+assertEquals('c', location.sourceText());
+
+location = script.locationFromLine(1, 2, start_b);
+location.restrict(2, 0);
+assertEquals('c(', location.sourceText());
+
+location = script.locationFromLine(1, 2, start_b);
+location.restrict(2, 1);
+assertEquals(' c', location.sourceText());
+
+location = script.locationFromLine(1, 2, start_b);
+location.restrict(2, 2);
+assertEquals(' c', location.sourceText());
+
+location = script.locationFromLine(1, 2, start_b);
+location.restrict(2, 3);
+assertEquals(' c', location.sourceText());
+
+location = script.locationFromLine(1, 2, start_b);
+location.restrict(3, 1);
+assertEquals(' c(', location.sourceText());
+
+location = script.locationFromLine(1, 2, start_b);
+location.restrict(5, 0);
+assertEquals('c(tru', location.sourceText());
+
+location = script.locationFromLine(1, 2, start_b);
+location.restrict(5, 2);
+assertEquals('  c(t', location.sourceText());
+
+location = script.locationFromLine(1, 2, start_b);
+location.restrict(5, 4);
+assertEquals('  c(t', location.sourceText());
+
+// All the following tests start from line 1 column 10 in function b, which is
+// the final character.
+//   c(true);
+//          ^
+
+location = script.locationFromLine(1, 10, start_b);
+location.restrict(5, 0);
+assertEquals('rue);', location.sourceText());
+
+location = script.locationFromLine(1, 10, start_b);
+location.restrict(7, 0);
+assertEquals('(true);', location.sourceText());
+
+// All the following tests start from line 1 column 0 in function b, which is
+// the first character.
+//   c(true);
+//^
+
+location = script.locationFromLine(1, 0, start_b);
+location.restrict(5, 0);
+assertEquals('  c(t', location.sourceText());
+
+location = script.locationFromLine(1, 0, start_b);
+location.restrict(5, 4);
+assertEquals('  c(t', location.sourceText());
+
+location = script.locationFromLine(1, 0, start_b);
+location.restrict(7, 0);
+assertEquals('  c(tru', location.sourceText());
+
+location = script.locationFromLine(1, 0, start_b);
+location.restrict(7, 6);
+assertEquals('  c(tru', location.sourceText());
diff --git a/deps/v8/test/mjsunit/debug-sourceslice.js b/deps/v8/test/mjsunit/debug-sourceslice.js
new file mode 100644
index 0000000..db9a3e7
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-sourceslice.js
@@ -0,0 +1,74 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Source lines for test.
+var lines = [ 'function a() { b(); };\n',
+              'function    b() {\n',
+              '  c(true);\n',
+              '};\n',
+              '  function c(x) {\n',
+              '    if (x) {\n',
+              '      return 1;\n',
+              '    } else {\n',
+              '      return 1;\n',
+              '    }\n',
+              '  };\n' ];
+
+// Build source by putting all lines together
+var source = '';
+for (var i = 0; i < lines.length; i++) {
+  source += lines[i];
+}
+eval(source);
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// Get the script object from one of the functions in the source.
+var script = Debug.findScript(a);
+
+// Make sure that the source is as expected.
+assertEquals(source, script.source);
+assertEquals(source, script.sourceSlice().sourceText());
+
+// Try all possible line interval slices.
+for (var slice_size = 0; slice_size < lines.length; slice_size++) {
+  for (var n = 0; n < lines.length - slice_size; n++) {
+    var slice = script.sourceSlice(n, n + slice_size);
+    assertEquals(n, slice.from_line);
+    assertEquals(n + slice_size, slice.to_line);
+
+    var text = slice.sourceText();
+    var expected = '';
+    for (var i = 0; i < slice_size; i++) {
+      expected += lines[n + i];
+    }
+    assertEquals(expected, text);
+  }
+}
diff --git a/deps/v8/test/mjsunit/debug-step-stub-callfunction.js b/deps/v8/test/mjsunit/debug-step-stub-callfunction.js
new file mode 100644
index 0000000..fbb8078
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-step-stub-callfunction.js
@@ -0,0 +1,73 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// Simple debug event handler which counts the number of breaks hit and steps.
+var break_break_point_hit_count = 0;
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    break_break_point_hit_count++;
+    // Continue stepping until returned to bottom frame.
+    if (exec_state.frameCount() > 1) {
+      exec_state.prepareStep(Debug.StepAction.StepIn);
+    }
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Use 'eval' to ensure that the call to print is through CodeStub CallFunction.
+// See Ia32CodeGenerator::VisitCall and Ia32CodeGenerator::CallWithArguments.
+function f() {
+  debugger;
+  eval('');
+  print('Hello, world!');
+};
+
+break_break_point_hit_count = 0;
+f();
+assertEquals(5, break_break_point_hit_count);
+
+// Use an inner function to ensure that the function call is through CodeStub
+// CallFunction see Ia32CodeGenerator::VisitCall and
+// Ia32CodeGenerator::CallWithArguments.
+function g() {
+  function h() {}
+  debugger;
+  h();
+};
+
+break_break_point_hit_count = 0;
+g();
+assertEquals(4, break_break_point_hit_count);
+
+// Get rid of the debug event listener.
+Debug.setListener(null);
diff --git a/deps/v8/test/mjsunit/debug-step.js b/deps/v8/test/mjsunit/debug-step.js
new file mode 100644
index 0000000..4534218
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-step.js
@@ -0,0 +1,82 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// Simple debug event handler which first time hit will perform 1000 steps and
+// second time hit will evaluate and store the value of "i". If requires that
+// the global property "state" is initially zero.
+
+var bp1, bp2;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    if (state == 0) {
+      exec_state.prepareStep(Debug.StepAction.StepIn, 1000);
+      state = 1;
+    } else if (state == 1) {
+      result = exec_state.frame().evaluate("i").value();
+      // Clear the break point on line 2 if set.
+      if (bp2) {
+        Debug.clearBreakPoint(bp2);
+      }
+    }
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Test debug event for break point.
+function f() {
+  for (i = 0; i < 1000; i++) {  //  Line 1.
+    x = 1;                      //  Line 2.
+  }
+};
+
+// Set a breakpoint on the for statement (line 1).
+bp1 = Debug.setBreakPoint(f, 1);
+
+// Check that performing 1000 steps will make i 499.
+state = 0;
+result = -1;
+f();
+assertEquals(499, result);
+
+// Check that performing 1000 steps with a break point on the statement in the
+// for loop (line 2) will only make i 0 as a real break point breaks even when
+// multiple steps have been requested.
+state = 0;
+result = -1;
+bp2 = Debug.setBreakPoint(f, 2);
+f();
+assertEquals(0, result);
+
+// Get rid of the debug event listener.
+Debug.setListener(null);
\ No newline at end of file
diff --git a/deps/v8/test/mjsunit/debug-stepin-constructor.js b/deps/v8/test/mjsunit/debug-stepin-constructor.js
new file mode 100644
index 0000000..6dbe5d1
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-stepin-constructor.js
@@ -0,0 +1,74 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// Simple debug event handler which counts the number of breaks hit and steps.
+var break_break_point_hit_count = 0;
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    break_break_point_hit_count++;
+    // Continue stepping until returned to bottom frame.
+    if (exec_state.frameCount() > 1) {
+      exec_state.prepareStep(Debug.StepAction.StepIn);
+    }
+    
+    // Test that there is a script.
+    assertTrue(typeof(event_data.func().script()) == 'object');
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Test step into constructor with simple constructor.
+function X() {
+}
+
+function f() {
+  debugger;
+  new X();
+};
+
+break_break_point_hit_count = 0;
+f();
+assertEquals(5, break_break_point_hit_count);
+
+// Test step into constructor with builtin constructor.
+function g() {
+  debugger;
+  new Date();
+};
+
+break_break_point_hit_count = 0;
+g();
+assertEquals(4, break_break_point_hit_count);
+
+// Get rid of the debug event listener.
+Debug.setListener(null);
diff --git a/deps/v8/test/mjsunit/declare-locally.js b/deps/v8/test/mjsunit/declare-locally.js
new file mode 100644
index 0000000..93fcb85
--- /dev/null
+++ b/deps/v8/test/mjsunit/declare-locally.js
@@ -0,0 +1,43 @@
+// Copyright 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.
+
+// Make sure that we're not overwriting global
+// properties defined in the prototype chain too
+// early when shadowing them with var/const
+// declarations.
+
+// This exercises the code in runtime.cc in
+// DeclareGlobal...Locally().
+
+this.__proto__.foo = 42;
+this.__proto__.bar = 87;
+
+eval("assertEquals(42, foo); var foo = 87;");
+assertEquals(87, foo);
+
+eval("assertEquals(87, bar); const bar = 42;");
+assertEquals(42, bar);
diff --git a/deps/v8/test/mjsunit/deep-recursion.js b/deps/v8/test/mjsunit/deep-recursion.js
new file mode 100644
index 0000000..a8093eb
--- /dev/null
+++ b/deps/v8/test/mjsunit/deep-recursion.js
@@ -0,0 +1,64 @@
+// Copyright 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.
+
+/**
+ * @fileoverview Check that flattening deep trees of cons strings does not
+ * cause stack overflows.
+ */
+
+var depth = 110000;
+
+function newdeep(start) {
+  var d = start;
+  for (var i = 0; i < depth; i++) {
+    d = d + "f";
+  }
+  return d;
+}
+
+var deep = newdeep("foo");
+assertEquals('f', deep[0]);
+
+var cmp1 = newdeep("a");
+var cmp2 = newdeep("b");
+
+assertEquals(-1, cmp1.localeCompare(cmp2), "ab");
+
+var cmp2empty = newdeep("c");
+assertTrue(cmp2empty.localeCompare("") > 0, "c");
+
+var cmp3empty = newdeep("d");
+assertTrue("".localeCompare(cmp3empty) < 0), "d";
+
+var slicer = newdeep("slice");
+
+for (i = 0; i < depth + 4; i += 2) {
+  slicer =  slicer.slice(1, -1);
+}
+
+assertEquals("f", slicer[0]);
+assertEquals(1, slicer.length);
diff --git a/deps/v8/test/mjsunit/delay-syntax-error.js b/deps/v8/test/mjsunit/delay-syntax-error.js
new file mode 100644
index 0000000..4fcb143
--- /dev/null
+++ b/deps/v8/test/mjsunit/delay-syntax-error.js
@@ -0,0 +1,41 @@
+// Copyright 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.
+
+// To be compatible with KJS syntax errors for illegal return, break
+// and continue should be delayed to runtime.
+
+// Do not throw syntax errors for illegal return, break and continue
+// at compile time.
+assertDoesNotThrow("if (false) return;");
+assertDoesNotThrow("if (false) break;");
+assertDoesNotThrow("if (false) continue;");
+
+// Throw syntax errors for illegal return, break and continue at
+// compile time.
+assertThrows("return;");
+assertThrows("break;");
+assertThrows("continue;");
diff --git a/deps/v8/test/mjsunit/delete-global-properties.js b/deps/v8/test/mjsunit/delete-global-properties.js
new file mode 100644
index 0000000..b3813dc
--- /dev/null
+++ b/deps/v8/test/mjsunit/delete-global-properties.js
@@ -0,0 +1,37 @@
+// Copyright 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.
+
+// Global properties declared with 'var' or 'function' should not be
+// deleteable.
+var tmp;
+assertFalse(delete tmp);  // should be DONT_DELETE
+assertTrue("tmp" in this);
+function f() { return 1; }
+assertFalse(delete f);  // should be DONT_DELETE
+assertEquals(1, f());  
+
+/* Perhaps related to bugs/11? */
diff --git a/deps/v8/test/mjsunit/delete-in-eval.js b/deps/v8/test/mjsunit/delete-in-eval.js
new file mode 100644
index 0000000..9278013
--- /dev/null
+++ b/deps/v8/test/mjsunit/delete-in-eval.js
@@ -0,0 +1,32 @@
+// Copyright 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.
+
+// Should be able to delete properties in the context through eval().
+tmp = 0;
+assertTrue(eval("delete XXX"));  // non-existing
+assertTrue(eval("delete tmp"));  // existing
+assertFalse("tmp" in this);
diff --git a/deps/v8/test/mjsunit/delete-in-with.js b/deps/v8/test/mjsunit/delete-in-with.js
new file mode 100644
index 0000000..1efc18d
--- /dev/null
+++ b/deps/v8/test/mjsunit/delete-in-with.js
@@ -0,0 +1,34 @@
+// Copyright 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.
+
+// It should be possible to delete properties of 'with' context
+// objects from within 'with' statements.
+(function(){
+  var tmp = { x: 12 };
+  with (tmp) { assertTrue(delete x); }  
+  assertFalse("x" in tmp);
+})();
diff --git a/deps/v8/test/mjsunit/delete-vars-from-eval.js b/deps/v8/test/mjsunit/delete-vars-from-eval.js
new file mode 100644
index 0000000..a457466
--- /dev/null
+++ b/deps/v8/test/mjsunit/delete-vars-from-eval.js
@@ -0,0 +1,40 @@
+// Copyright 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.
+
+// Variable declarations in eval() must introduce delete-able vars;
+// even when they are local to a function.
+(function() {
+  eval("var tmp0 = 0");
+  assertEquals(0, tmp0);
+  assertTrue(delete tmp0);
+  assertTrue(typeof(tmp0) == 'undefined');
+})();
+
+eval("var tmp1 = 1");
+assertEquals(1, tmp1);
+assertTrue(delete tmp1);
+assertTrue(typeof(tmp1) == 'undefined');
diff --git a/deps/v8/test/mjsunit/delete.js b/deps/v8/test/mjsunit/delete.js
new file mode 100644
index 0000000..6fc15e9
--- /dev/null
+++ b/deps/v8/test/mjsunit/delete.js
@@ -0,0 +1,163 @@
+// Copyright 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.
+
+// We use the has() function to avoid relying on a functioning
+// implementation of 'in'.
+function has(o, k) { return typeof o[k] !== 'undefined'; }
+
+assertTrue(delete null);
+assertTrue(delete 2);
+assertTrue(delete 'foo');
+assertTrue(delete Number(7));
+assertTrue(delete new Number(8));
+
+assertTrue(delete {}.x);
+assertTrue(delete {}.y);
+assertTrue(delete {}.toString);
+
+x = 42;
+assertEquals(42, x);
+assertTrue(delete x);
+assertTrue(typeof x === 'undefined', "x is gone");
+
+/**** 
+ * This test relies on DontDelete attributes. This is not 
+ * working yet.
+
+var y = 87; // should have DontDelete attribute
+assertEquals(87, y);
+assertFalse(delete y, "don't delete");
+assertFalse(typeof y === 'undefined');
+assertEquals(87, y);
+*/
+
+var o = { x: 42, y: 87 };
+assertTrue(has(o, 'x'));
+assertTrue(has(o, 'y'));
+assertTrue(delete o.x);
+assertFalse(has(o, 'x'));
+assertTrue(has(o, 'y'));
+assertTrue(delete o['y']);
+assertFalse(has(o, 'x'));
+assertFalse(has(o, 'y'));
+
+
+var o = {};
+for (var i = 0x0020; i < 0x02ff; i+=2) {
+  o[String.fromCharCode(i)] = i;
+  o[String.fromCharCode(i+1)] = i+1;
+}
+for (var i = 0x0020; i < 0x02ff; i+=2) {
+  assertTrue(delete o[String.fromCharCode(i)]);
+}
+for (var i = 0x0020; i < 0x02ff; i+=2) {
+  assertFalse(has(o, String.fromCharCode(i)), "deleted (" + i + ")");
+  assertTrue(has(o, String.fromCharCode(i+1)), "still here (" + i + ")");
+}
+
+
+var a = [0,1,2];
+assertTrue(has(a, 0));
+assertTrue(delete a[0]);
+assertFalse(has(a, 0), "delete 0");
+assertEquals(1, a[1]);
+assertEquals(2, a[2]);
+assertTrue(delete a[100], "delete 100");
+assertTrue(delete a[Math.pow(2,31)-1], "delete 2^31-1");
+assertFalse(has(a, 0), "delete 0");
+assertEquals(1, a[1]);
+assertEquals(2, a[2]);
+
+
+var a = [0,1,2];
+assertEquals(3, a.length);
+assertTrue(delete a[2]);
+assertEquals(3, a.length);
+assertTrue(delete a[0]);
+assertEquals(3, a.length);
+assertTrue(delete a[1]);
+assertEquals(3, a.length);
+
+
+var o = {};
+o[Math.pow(2,30)-1] = 0;
+o[Math.pow(2,31)-1] = 0;
+o[1] = 0;
+assertTrue(delete o[0]);
+assertTrue(delete o[Math.pow(2,30)]);
+assertFalse(has(o, 0), "delete 0");
+assertFalse(has(o, Math.pow(2,30)));
+assertTrue(has(o, 1));
+assertTrue(has(o, Math.pow(2,30)-1));
+assertTrue(has(o, Math.pow(2,31)-1));
+
+assertTrue(delete o[Math.pow(2,30)-1]);
+assertTrue(has(o, 1));
+assertFalse(has(o, Math.pow(2,30)-1), "delete 2^30-1");
+assertTrue(has(o, Math.pow(2,31)-1));
+
+assertTrue(delete o[1]);
+assertFalse(has(o, 1), "delete 1");
+assertFalse(has(o, Math.pow(2,30)-1), "delete 2^30-1");
+assertTrue(has(o, Math.pow(2,31)-1));
+
+assertTrue(delete o[Math.pow(2,31)-1]);
+assertFalse(has(o, 1), "delete 1");
+assertFalse(has(o, Math.pow(2,30)-1), "delete 2^30-1");
+assertFalse(has(o, Math.pow(2,31)-1), "delete 2^31-1");
+
+
+var a = [];
+a[Math.pow(2,30)-1] = 0;
+a[Math.pow(2,31)-1] = 0;
+a[1] = 0;
+assertTrue(delete a[0]);
+assertTrue(delete a[Math.pow(2,30)]);
+assertFalse(has(a, 0), "delete 0");
+assertFalse(has(a, Math.pow(2,30)), "delete 2^30");
+assertTrue(has(a, 1));
+assertTrue(has(a, Math.pow(2,30)-1));
+assertTrue(has(a, Math.pow(2,31)-1));
+assertEquals(Math.pow(2,31), a.length);
+
+assertTrue(delete a[Math.pow(2,30)-1]);
+assertTrue(has(a, 1));
+assertFalse(has(a, Math.pow(2,30)-1), "delete 2^30-1");
+assertTrue(has(a, Math.pow(2,31)-1));
+assertEquals(Math.pow(2,31), a.length);
+
+assertTrue(delete a[1]);
+assertFalse(has(a, 1), "delete 1");
+assertFalse(has(a, Math.pow(2,30)-1), "delete 2^30-1");
+assertTrue(has(a, Math.pow(2,31)-1));
+assertEquals(Math.pow(2,31), a.length);
+
+assertTrue(delete a[Math.pow(2,31)-1]);
+assertFalse(has(a, 1), "delete 1");
+assertFalse(has(a, Math.pow(2,30)-1), "delete 2^30-1");
+assertFalse(has(a, Math.pow(2,31)-1), "delete 2^31-1");
+assertEquals(Math.pow(2,31), a.length);
diff --git a/deps/v8/test/mjsunit/do-not-strip-fc.js b/deps/v8/test/mjsunit/do-not-strip-fc.js
new file mode 100644
index 0000000..1aef28c
--- /dev/null
+++ b/deps/v8/test/mjsunit/do-not-strip-fc.js
@@ -0,0 +1,31 @@
+// Copyright 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.
+
+// Make sure we do not remove unicode format-control characters
+// from string literals.
+assertEquals(7, eval("'foo\u200dbar'").length);
+assertEquals(7, eval("'foo\u200cbar'").length);
diff --git a/deps/v8/test/mjsunit/dont-enum-array-holes.js b/deps/v8/test/mjsunit/dont-enum-array-holes.js
new file mode 100644
index 0000000..4761dc4
--- /dev/null
+++ b/deps/v8/test/mjsunit/dont-enum-array-holes.js
@@ -0,0 +1,35 @@
+// Copyright 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.
+
+// Do not enum holes in arrays.
+var count = 0;
+for (var i in [,1,,3]) count++;
+assertEquals(2, count);
+
+count = 0;
+for (var i in new Array(10)) count++;
+assertEquals(0, count);
diff --git a/deps/v8/test/mjsunit/dont-reinit-global-var.js b/deps/v8/test/mjsunit/dont-reinit-global-var.js
new file mode 100644
index 0000000..1e3c1a0
--- /dev/null
+++ b/deps/v8/test/mjsunit/dont-reinit-global-var.js
@@ -0,0 +1,47 @@
+// Copyright 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.
+
+var foo = 'fisk';
+assertEquals('fisk', foo);
+var foo;
+assertEquals('fisk', foo);
+var foo = 'hest';
+assertEquals('hest', foo);
+
+this.bar = 'fisk';
+assertEquals('fisk', bar);
+var bar;
+assertEquals('fisk', bar);
+var bar = 'hest';
+assertEquals('hest', bar);
+
+this.baz = 'fisk';
+assertEquals('fisk', baz);
+eval('var baz;');
+assertEquals('fisk', baz);
+eval('var baz = "hest";');
+assertEquals('hest', baz);
diff --git a/deps/v8/test/mjsunit/double-equals.js b/deps/v8/test/mjsunit/double-equals.js
new file mode 100644
index 0000000..a68d7ea
--- /dev/null
+++ b/deps/v8/test/mjsunit/double-equals.js
@@ -0,0 +1,114 @@
+// Copyright 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.
+
+/**
+ * This test uses assert{True,False}(... == ...) instead of
+ * assertEquals(..., ...) to not rely on the details of the
+ * implementation of assertEquals.
+ */
+
+assertTrue (void 0 == void 0, "void 0 == void 0");
+assertTrue (null == null,     "null == null");
+assertFalse(NaN == NaN,       "NaN == NaN");
+assertFalse(NaN == 0,         "NaN == 0");
+assertFalse(0 == NaN,         "0 == NaN");
+assertFalse(NaN == Infinity,  "NaN == Inf");
+assertFalse(Infinity == NaN,  "Inf == NaN");
+
+assertTrue(Number.MAX_VALUE == Number.MAX_VALUE, "MAX == MAX");
+assertTrue(Number.MIN_VALUE == Number.MIN_VALUE, "MIN == MIN");
+assertTrue(Infinity == Infinity,                 "Inf == Inf");
+assertTrue(-Infinity == -Infinity,               "-Inf == -Inf");
+
+assertTrue(0 == 0,   "0 == 0");
+assertTrue(0 == -0,  "0 == -0");
+assertTrue(-0 == 0,  "-0 == 0");
+assertTrue(-0 == -0, "-0 == -0");
+
+assertFalse(0.9 == 1,             "0.9 == 1");
+assertFalse(0.999999 == 1,        "0.999999 == 1");
+assertFalse(0.9999999999 == 1,    "0.9999999999 == 1");
+assertFalse(0.9999999999999 == 1, "0.9999999999999 == 1");
+
+assertTrue('hello' == 'hello', "'hello' == 'hello'");
+
+assertTrue (true == true,   "true == true");
+assertTrue (false == false, "false == false");
+assertFalse(true == false,  "true == false");
+assertFalse(false == true,  "false == true");
+
+assertFalse(new Wrapper(null) == new Wrapper(null),   "new Wrapper(null) == new Wrapper(null)");
+assertFalse(new Boolean(true) == new Boolean(true),   "new Boolean(true) == new Boolean(true)");
+assertFalse(new Boolean(false) == new Boolean(false), "new Boolean(false) == new Boolean(false)");
+
+(function () {
+  var x = new Wrapper(null);
+  var y = x, z = x;
+  assertTrue(y == x);
+})();
+
+(function () {
+  var x = new Boolean(true);
+  var y = x, z = x;
+  assertTrue(y == x);
+})();
+
+(function () {
+  var x = new Boolean(false);
+  var y = x, z = x;
+  assertTrue(y == x);
+})();
+
+assertTrue(null == void 0,             "null == void 0");
+assertTrue(void 0 == null,             "void 0 == null");
+assertFalse(new Wrapper(null) == null, "new Wrapper(null) == null");
+assertFalse(null == new Wrapper(null), "null == new Wrapper(null)");
+
+assertTrue(1 == '1',       "1 == '1");
+assertTrue(255 == '0xff',  "255 == '0xff'");
+assertTrue(0 == '\r',      "0 == '\\r'");
+assertTrue(1e19 == '1e19', "1e19 == '1e19'");
+
+assertTrue(new Boolean(true) == true,   "new Boolean(true) == true");
+assertTrue(new Boolean(false) == false, "new Boolean(false) == false");
+assertTrue(true == new Boolean(true),   "true == new Boolean(true)");
+assertTrue(false == new Boolean(false), "false == new Boolean(false)");
+
+assertTrue(Boolean(true) == true,   "Boolean(true) == true");
+assertTrue(Boolean(false) == false, "Boolean(false) == false");
+assertTrue(true == Boolean(true),   "true == Boolean(true)");
+assertTrue(false == Boolean(false), "false == Boolean(false)");
+
+assertTrue(new Wrapper(true) == true,   "new Wrapper(true) == true");
+assertTrue(new Wrapper(false) == false, "new Wrapper(false) == false");
+assertTrue(true == new Wrapper(true),   "true = new Wrapper(true)");
+assertTrue(false == new Wrapper(false), "false = new Wrapper(false)");
+
+function Wrapper(value) {
+  this.value = value;
+  this.valueOf = function () { return this.value; };
+}
diff --git a/deps/v8/test/mjsunit/dtoa.js b/deps/v8/test/mjsunit/dtoa.js
new file mode 100644
index 0000000..80167b7
--- /dev/null
+++ b/deps/v8/test/mjsunit/dtoa.js
@@ -0,0 +1,32 @@
+// Copyright 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.c used to contain a bogus assertions that got triggered when
+// passed very small numbers.  This test therefore used to fail in
+// debug mode.
+
+assertEquals(0, 1e-500);
diff --git a/deps/v8/test/mjsunit/enumeration-order.js b/deps/v8/test/mjsunit/enumeration-order.js
new file mode 100644
index 0000000..699a636
--- /dev/null
+++ b/deps/v8/test/mjsunit/enumeration-order.js
@@ -0,0 +1,59 @@
+// Copyright 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.
+
+function check_enumeration_order(obj)  {
+  var value = 0; 
+  for (var name in obj) assertTrue(value < obj[name]);
+  value = obj[name];
+}
+
+function make_object(size)  {
+  var a = new Object();
+  
+  for (var i = 0; i < size; i++) a["a_" + i] = i + 1;
+  check_enumeration_order(a);
+  
+  for (var i = 0; i < size; i +=3) delete a["a_" + i];
+  check_enumeration_order(a);
+}
+
+// Validate the enumeration order for object up to 100 named properties.
+for (var j = 1; j< 100; j++) make_object(j);
+
+
+function make_literal_object(size)  {
+  var code = "{ ";
+  for (var i = 0; i < size-1; i++) code += " a_" + i + " : " + (i + 1) + ", ";
+  code += "a_" + (size - 1) + " : " + size;
+  code += " }";
+  eval("var a = " + code);
+  check_enumeration_order(a);  
+}
+
+// Validate the enumeration order for object literals up to 100 named properties.
+for (var j = 1; j< 100; j++) make_literal_object(j);
+
diff --git a/deps/v8/test/mjsunit/error-constructors.js b/deps/v8/test/mjsunit/error-constructors.js
new file mode 100644
index 0000000..ca2aa06
--- /dev/null
+++ b/deps/v8/test/mjsunit/error-constructors.js
@@ -0,0 +1,32 @@
+// 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.
+
+var e = new Error();
+assertFalse(e.hasOwnProperty('message'));
+Error.prototype.toString = Object.prototype.toString;
+assertEquals("[object Error]", Error.prototype.toString());
+assertEquals(Object.prototype, Error.prototype.__proto__);
diff --git a/deps/v8/test/mjsunit/escape.js b/deps/v8/test/mjsunit/escape.js
new file mode 100644
index 0000000..5732ce3
--- /dev/null
+++ b/deps/v8/test/mjsunit/escape.js
@@ -0,0 +1,118 @@
+// Copyright 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.
+
+/**
+ * @fileoverview Check that the global escape and unescape functions work
+ * right.
+ */
+
+// Section B.2.1 of ECMAScript 3
+var unescaped = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@*_+-./";
+
+// Check the unescape chars are not escaped
+assertEquals(unescaped, escape(unescaped));
+// Check spaces are escaped
+assertEquals("%20/%20", escape(" / "));
+// Check that null chars are escaped and do not terminate the string
+assertEquals("%000", escape("\0" + "0"));
+// Check a unicode escape
+assertEquals("A%20B%u1234%00%20C", escape(String.fromCharCode(0x41, 0x20, 0x42, 0x1234, 0, 0x20, 0x43)));
+// Check unicode escapes have a leading zero to pad to 4 digits
+assertEquals("%u0123", escape(String.fromCharCode(0x123)));
+// Check escapes are upper case
+assertEquals("%uABCD", escape(String.fromCharCode(0xabcd)));
+assertEquals("%AB", escape(String.fromCharCode(0xab)));
+assertEquals("%0A", escape("\n"));
+
+// Check first 1000 chars individually for escaped/not escaped
+for (var i = 0; i < 1000; i++) {
+  var s = String.fromCharCode(i);
+  if (unescaped.indexOf(s, 0) == -1) {
+    assertFalse(s == escape(s));
+  } else {
+    assertTrue(s == escape(s));
+  }
+}
+
+// Check all chars up to 1000 in groups of 10 using unescape as a check
+for (var i = 0; i < 1000; i += 10) {
+  var s = String.fromCharCode(i, i+1, i+2, i+3, i+4, i+5, i+6, i+7, i+8, i+9);
+  assertEquals(s, unescape(escape(s)));
+}
+
+// Benchmark
+var example = "Now is the time for all good men to come to the aid of the party.";
+example = example + String.fromCharCode(267, 0x1234, 0x6667, 0xabcd);
+example = example + " The quick brown fox jumps over the lazy dog."
+example = example + String.fromCharCode(171, 172, 173, 174, 175, 176, 178, 179);
+
+for (var i = 0; i < 3000; i++) {
+  assertEquals(example, unescape(escape(example)));
+}
+
+// Check unescape can cope with upper and lower case
+assertEquals(unescape("%41%4A%4a"), "AJJ");
+
+// Check upper case U
+assertEquals("%U1234", unescape("%U1234"));
+
+// Check malformed unescapes
+assertEquals("%", unescape("%"));
+assertEquals("%4", unescape("%4"));
+assertEquals("%u", unescape("%u"));
+assertEquals("%u4", unescape("%u4"));
+assertEquals("%u44", unescape("%u44"));
+assertEquals("%u444", unescape("%u444"));
+assertEquals("%4z", unescape("%4z"));
+assertEquals("%uzzzz", unescape("%uzzzz"));
+assertEquals("%u4zzz", unescape("%u4zzz"));
+assertEquals("%u44zz", unescape("%u44zz"));
+assertEquals("%u444z", unescape("%u444z"));
+assertEquals("%4<", unescape("%4<"));
+assertEquals("%u<<<<", unescape("%u<<<<"));
+assertEquals("%u4<<<", unescape("%u4<<<"));
+assertEquals("%u44<<", unescape("%u44<<"));
+assertEquals("%u444<", unescape("%u444<"));
+assertEquals("foo%4<", unescape("foo%4<"));
+assertEquals("foo%u<<<<", unescape("foo%u<<<<"));
+assertEquals("foo%u4<<<", unescape("foo%u4<<<"));
+assertEquals("foo%u44<<", unescape("foo%u44<<"));
+assertEquals("foo%u444<", unescape("foo%u444<"));
+assertEquals("foo%4<bar", unescape("foo%4<bar"));
+assertEquals("foo%u<<<<bar", unescape("foo%u<<<<bar"));
+assertEquals("foo%u4<<<bar", unescape("foo%u4<<<bar"));
+assertEquals("foo%u44<<bar", unescape("foo%u44<<bar"));
+assertEquals("foo%u444<bar", unescape("foo%u444<bar"));
+assertEquals("% ", unescape("%%20"));
+assertEquals("%% ", unescape("%%%20"));
+
+// Unescape stress
+var eexample = escape(example);
+
+for (var i = 1; i < 3000; i++) {
+  assertEquals(example, unescape(eexample));
+}
diff --git a/deps/v8/test/mjsunit/eval-typeof-non-existing.js b/deps/v8/test/mjsunit/eval-typeof-non-existing.js
new file mode 100644
index 0000000..3513767
--- /dev/null
+++ b/deps/v8/test/mjsunit/eval-typeof-non-existing.js
@@ -0,0 +1,32 @@
+// Copyright 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.
+
+// Typeof expression must resolve to undefined when it used on a
+// non-existing property. It is *not* allowed to throw a
+// ReferenceError.
+assertEquals('undefined', typeof xxx);
+assertEquals('undefined', eval('typeof xxx'));
diff --git a/deps/v8/test/mjsunit/eval.js b/deps/v8/test/mjsunit/eval.js
new file mode 100644
index 0000000..08bd3d0
--- /dev/null
+++ b/deps/v8/test/mjsunit/eval.js
@@ -0,0 +1,136 @@
+// Copyright 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.
+
+assertEquals(void 0, eval());
+assertEquals(4, eval(4));
+
+function f() { return 'The f function'; };
+assertTrue(f === eval(f));
+
+function g(x, y) { return 4; };
+
+count = 0;
+assertEquals(4, eval('2 + 2', count++));
+assertEquals(1, count);
+
+try {
+  eval('hest 7 &*^*&^');
+  assertTrue(false, 'Did not throw on syntax error.');
+} catch (e) {
+  assertEquals('SyntaxError', e.name);
+}
+
+
+// eval has special evaluation order for consistency with other browsers.
+global_eval = eval;
+assertEquals(void 0, eval(eval("var eval = function f(x) { return 'hest';}")))
+eval = global_eval;
+
+//Test eval with different number of parameters.
+global_eval = eval;
+eval = function(x, y) { return x + y; };
+assertEquals(4, eval(2, 2));
+eval = global_eval;
+
+// Test that un-aliased eval reads from local context.
+foo = 0;
+result = 
+  (function() {
+    var foo = 2;
+    return eval('foo');
+  })();
+assertEquals(2, result);
+
+//Test that un-aliased eval writes to local context.
+foo = 0;
+result = 
+  (function() {
+    var foo = 1;
+    eval('foo = 2');
+    return foo;
+  })();
+assertEquals(2, result);
+assertEquals(0, foo);
+
+// Test that un-aliased eval has right receiver.
+function MyObject() { this.self = eval('this'); }
+var o = new MyObject();
+assertTrue(o === o.self);
+
+// Test that aliased eval reads from global context.
+var e = eval;
+foo = 0;
+result = 
+  (function() {
+    var foo = 2;
+    return e('foo');
+  })();
+assertEquals(0, result);
+
+// Test that aliased eval writes to global context.
+var e = eval;
+foo = 0;
+(function() { e('var foo = 2;'); })();
+assertEquals(2, foo);
+
+// Test that aliased eval has right receiver.
+function MyOtherObject() { this.self = e('this'); }
+var o = new MyOtherObject();
+assertTrue(this === o.self);
+
+// Try to cheat the 'aliased eval' detection.
+var x = this;
+foo = 0;
+result = 
+  (function() {
+    var foo = 2;
+    return x.eval('foo');
+  })();
+assertEquals(0, result);
+
+foo = 0;
+result = 
+  (function() {
+    var eval = function(x) { return x; };
+    var foo = eval(2);
+    return e('foo');
+  })();
+assertEquals(0, result);
+
+result =
+  (function() {
+    var eval = function(x) { return 2 * x; };
+    return (function() { return eval(2); })();
+  })();
+assertEquals(4, result);
+
+eval = function(x) { return 2 * x; };
+result = 
+  (function() {
+    return (function() { return eval(2); })();
+  })();
+assertEquals(4, result);
diff --git a/deps/v8/test/mjsunit/execScript-case-insensitive.js b/deps/v8/test/mjsunit/execScript-case-insensitive.js
new file mode 100644
index 0000000..468d657
--- /dev/null
+++ b/deps/v8/test/mjsunit/execScript-case-insensitive.js
@@ -0,0 +1,34 @@
+// Copyright 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.
+
+var x  = 0;
+execScript('x = 1', 'javascript');
+assertEquals(1, x);
+
+execScript('x = 2', 'JavaScript');
+assertEquals(2, x);
+
diff --git a/deps/v8/test/mjsunit/extra-arguments.js b/deps/v8/test/mjsunit/extra-arguments.js
new file mode 100644
index 0000000..186277a
--- /dev/null
+++ b/deps/v8/test/mjsunit/extra-arguments.js
@@ -0,0 +1,54 @@
+// Copyright 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.
+
+function f() {
+  return g();
+};
+
+function g() {
+  var result = 0;
+  var array = f.arguments;
+  for (var i = 0; i < array.length; i++) {
+    result += array[i];
+  }
+  return result;
+};
+
+
+// Make sure we can pass any number of arguments to f and read them
+// from g.
+for (var i = 0; i < 25; i++) {
+  var array = new Array(i);
+  var expected = 0;
+  for (var j = 0; j < i; j++) {
+    expected += j;
+    array[j] = j;
+  }
+  assertEquals(expected, f.apply(null, array), String(i));
+}
+
+
diff --git a/deps/v8/test/mjsunit/extra-commas.js b/deps/v8/test/mjsunit/extra-commas.js
new file mode 100644
index 0000000..6fed04c
--- /dev/null
+++ b/deps/v8/test/mjsunit/extra-commas.js
@@ -0,0 +1,46 @@
+// Copyright 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.
+
+function assertSyntaxError(x) {
+  var caught = false;
+  try {
+    eval(x);
+  } catch (e) {
+    caught = true;
+    assertTrue(e instanceof SyntaxError, "is syntax error");
+  }
+  assertTrue(caught, "throws exception");
+};
+
+
+assertSyntaxError("f(,)");
+assertSyntaxError("f(1,)");
+assertSyntaxError("f(1,2,)");
+
+assertSyntaxError("function f(,) {}");
+assertSyntaxError("function f(1,) {}");
+assertSyntaxError("function f(1,2,) {}");
diff --git a/deps/v8/test/mjsunit/for-in-null-or-undefined.js b/deps/v8/test/mjsunit/for-in-null-or-undefined.js
new file mode 100644
index 0000000..b12d1b0
--- /dev/null
+++ b/deps/v8/test/mjsunit/for-in-null-or-undefined.js
@@ -0,0 +1,33 @@
+// Copyright 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.
+
+// At least Spidermonkey and IE allow for-in iteration over null and
+// undefined. They never executed the statement block.
+var count = 0;
+for (var p in null) { count++; }
+for (var p in void 0) { count++; }
+assertEquals(0, count);
diff --git a/deps/v8/test/mjsunit/for-in-special-cases.js b/deps/v8/test/mjsunit/for-in-special-cases.js
new file mode 100644
index 0000000..3c54256
--- /dev/null
+++ b/deps/v8/test/mjsunit/for-in-special-cases.js
@@ -0,0 +1,64 @@
+// Copyright 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.
+
+// Flags: --expose-gc
+
+function for_in_null() {
+  try {
+    for (var x in null) {
+      return false;
+    }
+  } catch(e) {
+    return false;
+  }
+  return true;
+}
+
+function for_in_undefined() {
+  try {
+    for (var x in undefined) {
+      return false;
+    }
+  } catch(e) {
+    return false;
+  }
+  return true;
+}
+
+for (var i = 0; i < 10; ++i) {
+  assertTrue(for_in_null());
+  gc();
+}
+
+for (var j = 0; j < 10; ++j) {
+  assertTrue(for_in_undefined());
+  gc();
+}
+
+assertEquals(10, i);
+assertEquals(10, j);
+
diff --git a/deps/v8/test/mjsunit/for-in.js b/deps/v8/test/mjsunit/for-in.js
new file mode 100644
index 0000000..dfe721d
--- /dev/null
+++ b/deps/v8/test/mjsunit/for-in.js
@@ -0,0 +1,86 @@
+// Copyright 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.
+
+function props(x) {
+  var array = [];
+  for (var p in x) array.push(p);
+  return array.sort();
+}
+
+assertEquals(0, props({}).length);
+assertEquals(1, props({x:1}).length);
+assertEquals(2, props({x:1, y:2}).length);
+
+assertArrayEquals(["x"], props({x:1}));
+assertArrayEquals(["x", "y"], props({x:1, y:2}));
+assertArrayEquals(["x", "y", "zoom"], props({x:1, y:2, zoom:3}));
+
+assertEquals(0, props([]).length);
+assertEquals(1, props([1]).length);
+assertEquals(2, props([1,2]).length);
+
+assertArrayEquals(["0"], props([1]));
+assertArrayEquals(["0", "1"], props([1,2]));
+assertArrayEquals(["0", "1", "2"], props([1,2,3]));
+
+var o = {};
+var a = [];
+for (var i = 0x0020; i < 0x01ff; i+=2) {
+  var s = 'char:' + String.fromCharCode(i);
+  a.push(s);
+  o[s] = i;
+}
+assertArrayEquals(a, props(o));
+
+var a = [];
+assertEquals(0, props(a).length);
+a[Math.pow(2,30)-1] = 0;
+assertEquals(1, props(a).length);
+a[Math.pow(2,31)-1] = 0;
+assertEquals(2, props(a).length);
+a[1] = 0;
+assertEquals(3, props(a).length);
+
+for (var hest = 'hest' in {}) { }
+assertEquals('hest', hest);
+
+var result = '';
+for (var p in {a : [0], b : 1}) { result += p; }
+assertEquals('ab', result);
+
+var result = '';
+for (var p in {a : {v:1}, b : 1}) { result += p; }
+assertEquals('ab', result);
+
+var result = '';
+for (var p in { get a() {}, b : 1}) { result += p; }
+assertEquals('ab', result);
+
+var result = '';
+for (var p in { get a() {}, set a(x) {}, b : 1}) { result += p; }
+assertEquals('ab', result);
+
diff --git a/deps/v8/test/mjsunit/fun-as-prototype.js b/deps/v8/test/mjsunit/fun-as-prototype.js
new file mode 100644
index 0000000..fbe995a
--- /dev/null
+++ b/deps/v8/test/mjsunit/fun-as-prototype.js
@@ -0,0 +1,36 @@
+// Copyright 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.
+
+var x = 0;
+function Funky(a, b, c) { return 7; }
+Number.prototype.__proto__ = Funky;
+assertEquals(3, x.length);
+assertEquals("Funky", x.name);
+assertEquals(Funky.prototype, x.prototype);
+
+Number.prototype.__proto__ = [1, 2, 3];
+assertEquals(3, x.length);
diff --git a/deps/v8/test/mjsunit/fun-name.js b/deps/v8/test/mjsunit/fun-name.js
new file mode 100644
index 0000000..676daaa
--- /dev/null
+++ b/deps/v8/test/mjsunit/fun-name.js
@@ -0,0 +1,34 @@
+// Copyright 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.
+
+function strip(s) {
+  return s.replace(/\s/g, '');
+}
+
+assertEquals('function(){}', strip((function () { }).toString()));
+assertEquals('functionanonymous(){}', strip(new Function().toString()));
+
diff --git a/deps/v8/test/mjsunit/function-arguments-null.js b/deps/v8/test/mjsunit/function-arguments-null.js
new file mode 100644
index 0000000..21e542f
--- /dev/null
+++ b/deps/v8/test/mjsunit/function-arguments-null.js
@@ -0,0 +1,30 @@
+// Copyright 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.
+
+// The arguments property of functions should be null when not
+// executing inside the function.
+assertTrue(toString.arguments === null);
diff --git a/deps/v8/test/mjsunit/function-caller.js b/deps/v8/test/mjsunit/function-caller.js
new file mode 100644
index 0000000..ddc7b5d
--- /dev/null
+++ b/deps/v8/test/mjsunit/function-caller.js
@@ -0,0 +1,48 @@
+// Copyright 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.
+
+function f(match) {
+  g(match);
+}
+
+function g(match) {
+  assertEquals(f, g.caller);
+  assertEquals(match, f.caller);
+}
+
+// Check called from function.
+function h() {
+  f(h);
+}
+h();
+
+// Check called from top-level.
+f(null);
+
+// Check called from eval.
+eval('f(null)');
+
diff --git a/deps/v8/test/mjsunit/function-names.js b/deps/v8/test/mjsunit/function-names.js
new file mode 100644
index 0000000..c083f18
--- /dev/null
+++ b/deps/v8/test/mjsunit/function-names.js
@@ -0,0 +1,133 @@
+// Copyright 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.
+
+
+function TestFunctionNames(object, names) {
+  for (var i = 0; i < names.length; i++) {
+    assertEquals(names[i], object[names[i]].name);
+  }
+}
+
+
+// Array.prototype functions.
+var arrayPrototypeFunctions = [
+    "toString", "toLocaleString", "join", "pop", "push", "concat", "reverse",
+    "shift", "unshift", "slice", "splice", "sort", "filter", "forEach",
+    "some", "every", "map", "indexOf", "lastIndexOf"];
+
+TestFunctionNames(Array.prototype, arrayPrototypeFunctions);
+
+
+// Boolean prototype functions.
+var booleanPrototypeFunctions = [ "toString", "valueOf" ];
+
+TestFunctionNames(Boolean.prototype, booleanPrototypeFunctions);
+
+
+// Date functions.
+var dateFunctions = ["UTC", "parse", "now"];
+
+TestFunctionNames(Date, dateFunctions);
+
+
+// Date.prototype functions.
+var datePrototypeFunctions = [
+    "toString", "toDateString", "toTimeString", "toLocaleString",
+    "toLocaleDateString", "toLocaleTimeString", "valueOf", "getTime",
+    "getFullYear", "getUTCFullYear", "getMonth", "getUTCMonth",
+    "getDate", "getUTCDate", "getDay", "getUTCDay", "getHours",
+    "getUTCHours", "getMinutes", "getUTCMinutes", "getSeconds",
+    "getUTCSeconds", "getMilliseconds", "getUTCMilliseconds",
+    "getTimezoneOffset", "setTime", "setMilliseconds",
+    "setUTCMilliseconds", "setSeconds", "setUTCSeconds", "setMinutes",
+    "setUTCMinutes", "setHours", "setUTCHours", "setDate", "setUTCDate",
+    "setMonth", "setUTCMonth", "setFullYear", "setUTCFullYear", "toGMTString",
+    "toUTCString", "getYear", "setYear"];
+
+TestFunctionNames(Date.prototype, datePrototypeFunctions);
+
+
+// Function.prototype functions.
+var functionPrototypeFunctions = [ "toString", "apply", "call" ];
+
+TestFunctionNames(Function.prototype, functionPrototypeFunctions);
+
+// Math functions.
+var mathFunctions = [
+    "random", "abs", "acos", "asin", "atan", "ceil", "cos", "exp", "floor",
+    "log", "round", "sin", "sqrt", "tan", "atan2", "pow", "max", "min"];
+
+TestFunctionNames(Math, mathFunctions);
+
+
+// Number.prototype functions.
+var numberPrototypeFunctions = [
+    "toString", "toLocaleString", "valueOf", "toFixed", "toExponential",
+    "toPrecision"];
+
+TestFunctionNames(Number.prototype, numberPrototypeFunctions);
+
+// Object.prototype functions.
+var objectPrototypeFunctions = [
+    "toString", "toLocaleString", "valueOf", "hasOwnProperty", "isPrototypeOf",
+    "propertyIsEnumerable", "__defineGetter__", "__lookupGetter__",
+    "__defineSetter__", "__lookupSetter__"];
+
+TestFunctionNames(Object.prototype, objectPrototypeFunctions);
+
+// RegExp.prototype functions.
+var regExpPrototypeFunctions = ["exec", "test", "toString", "compile"];
+
+TestFunctionNames(RegExp.prototype, regExpPrototypeFunctions);
+
+// String functions.
+var stringFunctions = ["fromCharCode"];
+
+TestFunctionNames(String, stringFunctions);
+
+
+// String.prototype functions.
+var stringPrototypeFunctions = [
+    "toString", "valueOf", "charAt", "charCodeAt", "concat", "indexOf",
+    "lastIndexOf", "localeCompare", "match", "replace", "search", "slice",
+    "split", "substring", "substr", "toLowerCase", "toLocaleLowerCase",
+    "toUpperCase", "toLocaleUpperCase", "link", "anchor", "fontcolor",
+    "fontsize", "big", "blink", "bold", "fixed", "italics", "small",
+    "strike", "sub", "sup"];
+
+TestFunctionNames(String.prototype, stringPrototypeFunctions);
+
+
+// Global functions.
+var globalFunctions = [
+    "escape", "unescape", "decodeURI", "decodeURIComponent",
+    "encodeURI", "encodeURIComponent", "Error", "TypeError",
+    "RangeError", "SyntaxError", "ReferenceError", "EvalError",
+    "URIError", "isNaN", "isFinite", "parseInt", "parseFloat",
+    "eval", "execScript"];
+
+TestFunctionNames(this, globalFunctions);
diff --git a/deps/v8/test/mjsunit/function-property.js b/deps/v8/test/mjsunit/function-property.js
new file mode 100644
index 0000000..a657f64
--- /dev/null
+++ b/deps/v8/test/mjsunit/function-property.js
@@ -0,0 +1,29 @@
+// Copyright 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.
+
+function f() { };
+assertEquals(5, f = 5);
diff --git a/deps/v8/test/mjsunit/function-prototype.js b/deps/v8/test/mjsunit/function-prototype.js
new file mode 100644
index 0000000..371311e
--- /dev/null
+++ b/deps/v8/test/mjsunit/function-prototype.js
@@ -0,0 +1,97 @@
+// Copyright 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.
+
+// Test that we can set function prototypes to non-object values.  The
+// prototype used for instances in that case should be the initial
+// object prototype.  ECMA-262 13.2.2.
+function TestNonObjectPrototype(value) {
+  function F() {};
+  F.prototype = value;
+  var f = new F();
+  assertEquals(value, F.prototype);
+  assertEquals(Object.prototype, f.__proto__);
+}
+
+var values = [123, "asdf", true];
+
+values.forEach(TestNonObjectPrototype);
+
+
+// Test moving between non-object and object values.
+function F() {};
+var f = new F();
+assertEquals(f.__proto__, F.prototype);
+F.prototype = 42;
+f = new F();
+assertEquals(Object.prototype, f.__proto__);
+assertEquals(42, F.prototype);
+F.prototype = { a: 42 };
+f = new F();
+assertEquals(42, F.prototype.a);
+assertEquals(f.__proto__, F.prototype);
+
+
+// Test that the fast case optimizations can handle non-functions,
+// functions with no prototypes (yet), non-object prototypes,
+// functions without initial maps, and the fully initialized
+// functions.
+function GetPrototypeOf(f) {
+  return f.prototype;
+};
+
+// Seed the GetPrototypeOf function to enable the fast case
+// optimizations.
+var p = GetPrototypeOf(GetPrototypeOf);
+
+// Check that getting the prototype of a tagged integer works.
+assertTrue(typeof GetPrototypeOf(1) == 'undefined');
+
+function NoPrototypeYet() { }
+var p = GetPrototypeOf(NoPrototypeYet);
+assertEquals(NoPrototypeYet.prototype, p);
+
+function NonObjectPrototype() { }
+NonObjectPrototype.prototype = 42;
+assertEquals(42, GetPrototypeOf(NonObjectPrototype));
+
+function NoInitialMap() { }
+var p = NoInitialMap.prototype;
+assertEquals(p, GetPrototypeOf(NoInitialMap));
+
+// Check the standard fast case.
+assertEquals(F.prototype, GetPrototypeOf(F));
+
+// Check that getting the prototype of a non-function works. This must
+// be the last thing we do because this will clobber the optimizations
+// in GetPrototypeOf and go to a monomorphic IC load instead.
+assertEquals(87, GetPrototypeOf({prototype:87}));
+
+// Check the prototype is enumerable as specified in ECMA262, 15.3.5.2
+var foo = new Function("return x");
+var result  = ""
+for (var n in foo) result += n;
+assertEquals(result, "prototype");
diff --git a/deps/v8/test/mjsunit/function-source.js b/deps/v8/test/mjsunit/function-source.js
new file mode 100644
index 0000000..7525775
--- /dev/null
+++ b/deps/v8/test/mjsunit/function-source.js
@@ -0,0 +1,49 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// Check that the script source for all functions in a script is the same.
+function f() {
+  function h() {
+    assertEquals(Debug.scriptSource(f), Debug.scriptSource(h));
+  }
+  h();
+}
+  
+function g() {
+  function h() {
+    assertEquals(Debug.scriptSource(f), Debug.scriptSource(h));
+  }
+  h();
+}
+
+assertEquals(Debug.scriptSource(f), Debug.scriptSource(g));
+f();
+g();
diff --git a/deps/v8/test/mjsunit/function.js b/deps/v8/test/mjsunit/function.js
new file mode 100644
index 0000000..b5e83db
--- /dev/null
+++ b/deps/v8/test/mjsunit/function.js
@@ -0,0 +1,83 @@
+// Copyright 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.
+
+var f = Function();
+assertTrue(typeof f() == 'undefined');
+f = new Function();
+assertTrue(typeof f() == 'undefined');
+
+f = Function('return 1');
+assertEquals(1, f());
+f = new Function('return 1');
+assertEquals(1, f());
+
+f = Function('return true');
+assertTrue(f());
+f = new Function('return true');
+assertTrue(f());
+
+f = Function('x', 'return x');
+assertEquals(1, f(1));
+assertEquals('bar', f('bar'));
+assertTrue(typeof f() == 'undefined');
+var x = {};
+assertTrue(x === f(x));
+
+f = Function('x', 'return x // comment');
+assertEquals(1, f(1));
+
+f = Function('return typeof anonymous');
+assertEquals('undefined', f());
+
+var anonymous = 42;
+f = Function('return anonymous;');
+assertEquals(42, f());
+
+f = new Function('x', 'return x')
+assertEquals(1, f(1));
+assertEquals('bar', f('bar'));
+assertTrue(typeof f() == 'undefined');
+var x = {};
+assertTrue(x === f(x));
+
+f = Function('x', 'y', 'return x+y');
+assertEquals(5, f(2, 3));
+assertEquals('foobar', f('foo', 'bar'));
+f = new Function('x', 'y', 'return x+y');
+assertEquals(5, f(2, 3));
+assertEquals('foobar', f('foo', 'bar'));
+
+var x = {}; x.toString = function() { return 'x'; };
+var y = {}; y.toString = function() { return 'y'; };
+var z = {}; z.toString = function() { return 'return x*y'; }
+var f = Function(x, y, z);
+assertEquals(25, f(5, 5));
+assertEquals(42, f(2, 21));
+f = new Function(x, y, z);
+assertEquals(25, f(5, 5));
+assertEquals(42, f(2, 21));
+
diff --git a/deps/v8/test/mjsunit/fuzz-accessors.js b/deps/v8/test/mjsunit/fuzz-accessors.js
new file mode 100644
index 0000000..f3602cc
--- /dev/null
+++ b/deps/v8/test/mjsunit/fuzz-accessors.js
@@ -0,0 +1,85 @@
+// Copyright 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.
+
+var builtInPropertyNames = [
+  'prototype', 'length', 'caller', 0, 1, '$1', 'arguments', 'name', 'message', 'constructor'
+];
+
+function getAnException() {
+  try {
+    ("str")();
+  } catch (e) {
+    return e;
+  }
+}
+
+function getSpecialObjects() {
+  return [
+    function () { },
+    [1, 2, 3],
+    /xxx/,
+    RegExp,
+    "blah",
+    9,
+    new Date(),
+    getAnException()
+  ];
+}
+
+var object = { };
+var fun = function () { };
+var someException = getAnException();
+var someDate = new Date();
+
+var objects = [
+  [1, Number.prototype],
+  ["foo", String.prototype],
+  [true, Boolean.prototype],
+  [object, object],
+  [fun, fun],
+  [someException, someException],
+  [someDate, someDate]
+];
+
+function runTest(fun) {
+  for (var i in objects) {
+    var obj = objects[i][0];
+    var chain = objects[i][1];
+    var specialObjects = getSpecialObjects();
+    for (var j in specialObjects) {
+      var special = specialObjects[j];
+      chain.__proto__ = special;
+      for (var k in builtInPropertyNames) {
+        var propertyName = builtInPropertyNames[k];
+        fun(obj, propertyName);
+      }
+    }
+  }
+}
+
+runTest(function (obj, name) { return obj[name]; });
+runTest(function (obj, name) { return obj[name] = { }; });
diff --git a/deps/v8/test/mjsunit/fuzz-natives.js b/deps/v8/test/mjsunit/fuzz-natives.js
new file mode 100644
index 0000000..debcc9a
--- /dev/null
+++ b/deps/v8/test/mjsunit/fuzz-natives.js
@@ -0,0 +1,151 @@
+// Copyright 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.
+
+// Flags: --allow-natives-syntax
+
+function makeArguments() {
+  var result = [ ];
+  result.push(17);
+  result.push(-31);
+  result.push(new Array(100));
+  result.push(new Array(100003));
+  result.push(Number.MIN_VALUE);
+  result.push("whoops");
+  result.push("x");
+  result.push({"x": 1, "y": 2});
+  var slowCaseObj = {"a": 3, "b": 4, "c": 5};
+  delete slowCaseObj.c;
+  result.push(slowCaseObj);
+  result.push(function () { return 8; });
+  return result;
+}
+
+var kArgObjects = makeArguments().length;
+
+function makeFunction(name, argc) {
+  var args = [];
+  for (var i = 0; i < argc; i++)
+    args.push("x" + i);
+  var argsStr = args.join(", ");
+  return new Function(args.join(", "), "return %" + name + "(" + argsStr + ");");
+}
+
+function testArgumentCount(name) {
+  for (var i = 0; i < 10; i++) {
+    var func = makeFunction(name, i);
+    var args = [ ];
+    for (var j = 0; j < i; j++)
+      args.push(0);
+    try {
+      func.apply(void 0, args);
+    } catch (e) {
+      // we don't care what happens as long as we don't crash
+    }
+  }
+}
+
+function testArgumentTypes(name, argc) {
+  var type = 0;
+  var hasMore = true;
+  var func = makeFunction(name, argc);
+  while (hasMore) {
+    var argPool = makeArguments();
+    var current = type;
+    var hasMore = false;
+    var argList = [ ];
+    for (var i = 0; i < argc; i++) {
+      var index = current % kArgObjects;
+      current = (current / kArgObjects) << 0;
+      if (index != (kArgObjects - 1))
+        hasMore = true;
+      argList.push(argPool[index]);
+    }
+    try {
+      func.apply(void 0, argList);
+    } catch (e) {
+      // we don't care what happens as long as we don't crash
+    }
+    type++;
+  }
+}
+
+var knownProblems = {
+  "Abort": true,
+  
+  // These functions use pseudo-stack-pointers and are not robust
+  // to unexpected integer values.
+  "DebugEvaluate": true,
+
+  // These functions do nontrivial error checking in recursive calls,
+  // which means that we have to propagate errors back.
+  "SetFunctionBreakPoint": true,
+  "SetScriptBreakPoint": true,
+  "ChangeBreakOnException": true,
+  "PrepareStep": true,
+
+  // Too slow.
+  "DebugReferencedBy": true,
+
+  // Calling disable/enable access checks may interfere with the
+  // the rest of the tests.
+  "DisableAccessChecks": true,
+  "EnableAccessChecks": true,
+  
+  // These functions should not be callable as runtime functions.
+  "NewContext": true,
+  "NewArgumentsFast": true,
+  "PushContext": true,
+  "LazyCompile": true,
+  "CreateObjectLiteralBoilerplate": true,
+  "CloneLiteralBoilerplate": true,
+  "CloneShallowLiteralBoilerplate": true,
+  "CreateArrayLiteralBoilerplate": true,
+  "IS_VAR": true,
+  "ResolvePossiblyDirectEval": true,
+  "Log": true
+};
+
+var currentlyUncallable = {
+  // We need to find a way to test this without breaking the system.
+  "SystemBreak": true
+};
+
+function testNatives() {
+  var allNatives = %ListNatives();
+  for (var i = 0; i < allNatives.length; i++) {
+    var nativeInfo = allNatives[i];
+    var name = nativeInfo[0];
+    if (name in knownProblems || name in currentlyUncallable)
+      continue;
+    print(name);
+    var argc = nativeInfo[1];
+    testArgumentCount(name);
+    testArgumentTypes(name, argc);
+  }
+}
+
+testNatives();
diff --git a/deps/v8/test/mjsunit/getter-in-prototype.js b/deps/v8/test/mjsunit/getter-in-prototype.js
new file mode 100644
index 0000000..dd26c53
--- /dev/null
+++ b/deps/v8/test/mjsunit/getter-in-prototype.js
@@ -0,0 +1,50 @@
+// 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.
+
+// Test that exceptions are thrown when setting properties on object
+// that have only a getter in a prototype object.
+
+var o = {};
+var p = {};
+p.__defineGetter__('x', function(){});
+o.__proto__ = p;
+
+assertThrows("o.x = 42");
+
+function f() {
+  with(o) {
+    x = 42;
+  }
+}
+assertThrows("f()");
+
+__proto__ = p;
+function g() {
+  eval('1');
+  x = 42;
+}
+assertThrows("g()");
diff --git a/deps/v8/test/mjsunit/getter-in-value-prototype.js b/deps/v8/test/mjsunit/getter-in-value-prototype.js
new file mode 100644
index 0000000..b55320a
--- /dev/null
+++ b/deps/v8/test/mjsunit/getter-in-value-prototype.js
@@ -0,0 +1,35 @@
+// Copyright 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.
+
+// Test that getters can be defined and called on value prototypes.
+//
+// This used to fail because of an invalid cast of the receiver to a
+// JSObject.
+
+String.prototype.__defineGetter__('x', function() { return this; });
+assertEquals('asdf', 'asdf'.x);
+
diff --git a/deps/v8/test/mjsunit/global-const-var-conflicts.js b/deps/v8/test/mjsunit/global-const-var-conflicts.js
new file mode 100644
index 0000000..d38d0ee
--- /dev/null
+++ b/deps/v8/test/mjsunit/global-const-var-conflicts.js
@@ -0,0 +1,57 @@
+// Copyright 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.
+
+// Check that dynamically introducing conflicting consts/vars
+// leads to exceptions.
+
+var caught = 0;
+
+eval("const a");
+try { eval("var a"); } catch (e) { caught++; assertTrue(e instanceof TypeError); }
+assertTrue(typeof a == 'undefined');
+try { eval("var a = 1"); } catch (e) { caught++; assertTrue(e instanceof TypeError); }
+assertTrue(typeof a == 'undefined');
+
+eval("const b = 0");
+try { eval("var b"); } catch (e) { caught++; assertTrue(e instanceof TypeError); }
+assertEquals(0, b);
+try { eval("var b = 1"); } catch (e) { caught++; assertTrue(e instanceof TypeError); }
+assertEquals(0, b);
+
+eval("var c");
+try { eval("const c"); } catch (e) { caught++; assertTrue(e instanceof TypeError); }
+assertTrue(typeof c == 'undefined');
+try { eval("const c = 1"); } catch (e) { caught++; assertTrue(e instanceof TypeError); }
+assertTrue(typeof c == 'undefined');
+
+eval("var d = 0");
+try { eval("const d"); } catch (e) { caught++; assertTrue(e instanceof TypeError); }
+assertEquals(0, d);
+try { eval("const d = 1"); } catch (e) { caught++; assertTrue(e instanceof TypeError); }
+assertEquals(0, d);
+
+assertEquals(8, caught);
diff --git a/deps/v8/test/mjsunit/global-load-from-eval-in-with.js b/deps/v8/test/mjsunit/global-load-from-eval-in-with.js
new file mode 100644
index 0000000..d733f6c
--- /dev/null
+++ b/deps/v8/test/mjsunit/global-load-from-eval-in-with.js
@@ -0,0 +1,59 @@
+// 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.
+
+// Tests global loads from eval inside of a with statement.
+
+var x = 27;
+
+function test(obj, source) {
+  with (obj) {
+    eval(source);
+  }
+}
+
+// Test shadowing in eval scope.
+test({ x: 42 }, "assertEquals(42, x)");
+test({ y: 42 }, "assertEquals(27, x)");
+
+// Test shadowing in local scope inside an eval scope.
+test({ x: 42 }, "function f() { assertEquals(42, x) }; f();");
+test({ y: 42 }, "function f() { assertEquals(27, x) }; f();");
+
+// Test shadowing in local scope inside an eval scope.  Deeper nesting
+// this time.
+test({ x: 42 }, "function f() { function g() { assertEquals(42, x) }; g() }; f();");
+test({ y: 42 }, "function f() { function g() { assertEquals(27, x) }; g() }; f();");
+
+// Test shadowing in local scope inside an eval scope with eval calls in the eval scopes.
+test({ x: 42 }, "function f() { eval('1'); assertEquals(42, x) }; f();");
+test({ y: 42 }, "function f() { eval('1'); assertEquals(27, x) }; f();");
+
+// Test shadowing in local scope inside an eval scope with eval calls
+// in the eval scopes.  Deeper nesting this time.
+test({ x: 42 }, "function f() { function g() { eval('1'); assertEquals(42, x) }; g() }; f();");
+test({ y: 42 }, "function f() { function g() { eval('1'); assertEquals(27, x) }; g() }; f();");
+
diff --git a/deps/v8/test/mjsunit/global-load-from-eval.js b/deps/v8/test/mjsunit/global-load-from-eval.js
new file mode 100644
index 0000000..ad40932
--- /dev/null
+++ b/deps/v8/test/mjsunit/global-load-from-eval.js
@@ -0,0 +1,85 @@
+// 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.
+
+// Tests global loads from eval.
+
+var x = 27;
+
+function test() {
+  function g() {
+    assertEquals(27, eval('x'));
+    function h() {
+      // Shadow with local variable.
+      var x = 22;
+      assertEquals(22, eval('x'));
+      function i(x) {
+        // Shadow with parameter.
+        assertEquals(44, eval('x'));
+        function j() {
+          assertEquals(x, eval('x'));
+          // Shadow with function name.
+          function x() {
+            assertEquals(x, eval('x'));
+          }
+          x();
+        }
+        j();
+      }
+      i(44);
+    }
+    h();
+  }
+  g();
+}
+
+test();
+
+// Test loading of globals from deeply nested eval.  This code is a
+// bit complicated, but the complication is needed to check that the
+// code that loads the global variable accounts for the fact that the
+// global variable becomes shadowed by an eval-introduced variable.
+var result = 0;
+function testDeep(source, load, test) {
+  eval(source);
+  function f() {
+    var y = 23;
+    function g() {
+      var z = 25;
+      function h() {
+        eval(load);
+        eval(test);
+      }
+      h();
+    }
+    g();
+  }
+  f();
+}
+testDeep('1', 'result = x', 'assertEquals(27, result)');
+// Because of the eval-cache, the 'result = x' code gets reused.  This
+// time in a context where the 'x' variable has been shadowed.
+testDeep('var x = 1', 'result = x', 'assertEquals(1, result)');
diff --git a/deps/v8/test/mjsunit/global-load-from-nested-eval.js b/deps/v8/test/mjsunit/global-load-from-nested-eval.js
new file mode 100644
index 0000000..3c7ff75
--- /dev/null
+++ b/deps/v8/test/mjsunit/global-load-from-nested-eval.js
@@ -0,0 +1,66 @@
+// 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.
+
+// Tests global loads from nested eval.
+
+var x = 42;
+
+// Load the global.
+function test(source) {
+  eval('eval(' + source +')');
+}
+test('assertEquals(42, x)');
+
+// Shadow variable with a with statement.
+function testWith(source) {
+  with ({ x: 1 }) {
+    eval('eval(' + source +')');
+  }
+}
+testWith('assertEquals(1, x)');
+
+// Shadow variable with an eval-introduced variable.
+function testEval(source) {
+  eval('var x = 1');
+  function f() {
+    eval('eval('+ source + ')');
+  }
+  f();
+}
+testEval('assertEquals(1, x)');
+
+// Eval that does not shadow.
+function testEvalDontShadow(source) {
+  eval('1');
+  eval('eval(' + source +')');
+}
+testEvalDontShadow('assertEquals(42, x)');
+
+
+
+
+
diff --git a/deps/v8/test/mjsunit/global-vars-eval.js b/deps/v8/test/mjsunit/global-vars-eval.js
new file mode 100644
index 0000000..900f7be
--- /dev/null
+++ b/deps/v8/test/mjsunit/global-vars-eval.js
@@ -0,0 +1,34 @@
+// Copyright 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.
+
+eval("" + "");
+this.bar = 'fisk';
+assertEquals('fisk', bar, "1");
+var bar;
+assertEquals('fisk', bar, "2");
+var bar = 'hest';
+assertEquals('hest', bar, "3");
diff --git a/deps/v8/test/mjsunit/global-vars-with.js b/deps/v8/test/mjsunit/global-vars-with.js
new file mode 100644
index 0000000..05ca6b6
--- /dev/null
+++ b/deps/v8/test/mjsunit/global-vars-with.js
@@ -0,0 +1,43 @@
+// Copyright 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.
+
+with ({}) { }
+this.bar = 'fisk';
+assertEquals('fisk', bar);
+var bar;
+assertEquals('fisk', bar);
+var bar = 'hest';
+assertEquals('hest', bar);
+
+with ({}) {
+  this.baz = 'fisk';
+  assertEquals('fisk', baz);
+  var baz;
+  assertEquals('fisk', baz);
+  var baz = 'hest';
+  assertEquals('hest', baz);
+}
diff --git a/deps/v8/test/mjsunit/greedy.js b/deps/v8/test/mjsunit/greedy.js
new file mode 100644
index 0000000..d357f0c
--- /dev/null
+++ b/deps/v8/test/mjsunit/greedy.js
@@ -0,0 +1,60 @@
+// Copyright 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.
+
+// Flags: --gc-greedy
+
+function IterativeFib(n) {
+  var f0 = 0, f1 = 1;
+  for (; n > 0; --n) {
+    var f2 = f0 + f1;
+    f0 = f1; f1 = f2;
+  }
+  return f0;
+}
+
+function RecursiveFib(n) {
+  if (n <= 1) return n;
+  return RecursiveFib(n - 1) + RecursiveFib(n - 2);
+}
+
+function Check(n, expected) {
+  var i = IterativeFib(n);
+  var r = RecursiveFib(n);
+  assertEquals(i, expected);
+  assertEquals(r, expected);
+}
+
+Check(0, 0);
+Check(1, 1);
+Check(2, 1);
+Check(3, 1 + 1);
+Check(4, 2 + 1);
+Check(5, 3 + 2);
+Check(10, 55);
+Check(15, 610);
+Check(20, 6765);
+assertEquals(IterativeFib(75), 2111485077978050);
diff --git a/deps/v8/test/mjsunit/has-own-property.js b/deps/v8/test/mjsunit/has-own-property.js
new file mode 100644
index 0000000..5ff8db5
--- /dev/null
+++ b/deps/v8/test/mjsunit/has-own-property.js
@@ -0,0 +1,38 @@
+// Copyright 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.
+
+// Check for objects.
+assertTrue({x:12}.hasOwnProperty('x'));
+assertFalse({x:12}.hasOwnProperty('y'));
+
+// Check for strings.
+assertTrue(''.hasOwnProperty('length'));
+assertTrue(Object.prototype.hasOwnProperty.call('', 'length'));
+
+// Check for numbers.
+assertFalse((123).hasOwnProperty('length'));
+assertFalse(Object.prototype.hasOwnProperty.call(123, 'length'));
diff --git a/deps/v8/test/mjsunit/html-comments.js b/deps/v8/test/mjsunit/html-comments.js
new file mode 100644
index 0000000..f39271a
--- /dev/null
+++ b/deps/v8/test/mjsunit/html-comments.js
@@ -0,0 +1,57 @@
+--> must work at beginning of file!
+
+// Copyright 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.
+
+var x = 1;
+--> this must be ignored...
+   --> so must this...
+	--> and this.
+x-->0;
+assertEquals(0, x);
+
+
+var x = 0; x <!-- x
+assertEquals(0, x);
+
+var x = 1; x <!--x
+assertEquals(1, x);
+
+var x = 2; x <!-- x; x = 42;
+assertEquals(2, x);
+
+var x = 1; x <! x--;
+assertEquals(0, x);
+
+var x = 1; x <!- x--;
+assertEquals(0, x);
+
+var b = true <! true;
+assertFalse(b);
+
+var b = true <!- true;
+assertFalse(b);
diff --git a/deps/v8/test/mjsunit/html-string-funcs.js b/deps/v8/test/mjsunit/html-string-funcs.js
new file mode 100644
index 0000000..213b7f3
--- /dev/null
+++ b/deps/v8/test/mjsunit/html-string-funcs.js
@@ -0,0 +1,47 @@
+// Copyright 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.
+
+// Spidermonkey and IE has some string functions useable for building
+// HTML.
+function CheckSimple(f, tag) {
+  assertEquals('<' + tag + '>foo</' + tag + '>',
+               "foo"[f]().toLowerCase()); 
+};
+var simple = { big: 'big', blink: 'blink', bold: 'b',
+               fixed: 'tt', italics: 'i', small: 'small',
+               strike: 'strike', sub: 'sub', sup: 'sup' };
+for (var i in simple) CheckSimple(i, simple[i]);
+
+
+function CheckCompound(f, tag, att) {
+  assertEquals('<' + tag + ' ' + att + '="bar">foo</' + tag + '>',
+               "foo"[f]("bar").toLowerCase());
+};
+CheckCompound('anchor', 'a', 'name');
+CheckCompound('link', 'a', 'href');
+CheckCompound('fontcolor', 'font', 'color');
+CheckCompound('fontsize', 'font', 'size');
diff --git a/deps/v8/test/mjsunit/if-in-undefined.js b/deps/v8/test/mjsunit/if-in-undefined.js
new file mode 100644
index 0000000..5bfa42e
--- /dev/null
+++ b/deps/v8/test/mjsunit/if-in-undefined.js
@@ -0,0 +1,36 @@
+// Copyright 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.
+
+// ECMA-252 11.8.7
+//
+// If the ShiftExpression is not an object, should throw an TypeError.
+// Should throw an exception, but not crash VM.
+
+assertThrows("if ('p' in undefined) { }");
+assertThrows("if ('p' in null) { }")
+assertThrows("if ('p' in true) { }");
+assertThrows("if ('p' in 5) { }");
diff --git a/deps/v8/test/mjsunit/in.js b/deps/v8/test/mjsunit/in.js
new file mode 100644
index 0000000..f98db42
--- /dev/null
+++ b/deps/v8/test/mjsunit/in.js
@@ -0,0 +1,159 @@
+// Copyright 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.
+
+// ----------------
+// Check fast objects
+
+var o = { };
+assertFalse(0 in o);
+assertFalse('x' in o);
+assertFalse('y' in o);
+assertTrue('toString' in o, "toString");
+
+var o = { x: 12 };
+assertFalse(0 in o);
+assertTrue('x' in o);
+assertFalse('y' in o);
+assertTrue('toString' in o, "toString");
+
+var o = { x: 12, y: 15 };
+assertFalse(0 in o);
+assertTrue('x' in o);
+assertTrue('y' in o);
+assertTrue('toString' in o, "toString");
+
+
+// ----------------
+// Check dense arrays
+
+var a = [ ];
+assertFalse(0 in a);
+assertFalse(1 in a);
+assertFalse('0' in a);
+assertFalse('1' in a);
+assertTrue('toString' in a, "toString");
+
+var a = [ 1 ];
+assertTrue(0 in a);
+assertFalse(1 in a);
+assertTrue('0' in a);
+assertFalse('1' in a);
+assertTrue('toString' in a, "toString");
+
+var a = [ 1, 2 ];
+assertTrue(0 in a);
+assertTrue(1 in a);
+assertTrue('0' in a);
+assertTrue('1' in a);
+assertTrue('toString' in a, "toString");
+
+var a = [ 1, 2 ];
+assertFalse(0.001 in a);
+assertTrue(-0 in a);
+assertTrue(+0 in a);
+assertFalse('0.0' in a);
+assertFalse('1.0' in a);
+assertFalse(NaN in a);
+assertFalse(Infinity in a);
+assertFalse(-Infinity in a);
+
+var a = [];
+a[1] = 2;
+assertFalse(0 in a);
+assertTrue(1 in a);
+assertFalse(2 in a);
+assertFalse('0' in a); 
+assertTrue('1' in a);
+assertFalse('2' in a);
+assertTrue('toString' in a, "toString");
+
+
+// ----------------
+// Check dictionary ("normalized") objects
+
+var o = {};
+for (var i = 0x0020; i < 0x02ff; i += 2) {
+  o['char:' + String.fromCharCode(i)] = i;
+}
+for (var i = 0x0020; i < 0x02ff; i += 2) {
+  assertTrue('char:' + String.fromCharCode(i) in o);
+  assertFalse('char:' + String.fromCharCode(i + 1) in o);
+}
+assertTrue('toString' in o, "toString");
+
+var o = {};
+o[Math.pow(2,30)-1] = 0;
+o[Math.pow(2,31)-1] = 0;
+o[1] = 0;
+assertFalse(0 in o);
+assertTrue(1 in o);
+assertFalse(2 in o);
+assertFalse(Math.pow(2,30)-2 in o);
+assertTrue(Math.pow(2,30)-1 in o);
+assertFalse(Math.pow(2,30)-0 in o);
+assertTrue(Math.pow(2,31)-1 in o);
+assertFalse(0.001 in o);
+assertFalse('0.0' in o);
+assertFalse('1.0' in o);
+assertFalse(NaN in o);
+assertFalse(Infinity in o);
+assertFalse(-Infinity in o);
+assertFalse(-0 in o);
+assertFalse(+0 in o);
+assertTrue('toString' in o, "toString");
+
+
+// ----------------
+// Check sparse arrays
+
+var a = [];
+a[Math.pow(2,30)-1] = 0;
+a[Math.pow(2,31)-1] = 0;
+a[1] = 0;
+assertFalse(0 in a, "0 in a");
+assertTrue(1 in a, "1 in a");
+assertFalse(2 in a, "2 in a");
+assertFalse(Math.pow(2,30)-2 in a, "Math.pow(2,30)-2 in a");
+assertTrue(Math.pow(2,30)-1 in a, "Math.pow(2,30)-1 in a");
+assertFalse(Math.pow(2,30)-0 in a, "Math.pow(2,30)-0 in a");
+assertTrue(Math.pow(2,31)-1 in a, "Math.pow(2,31)-1 in a");
+assertFalse(0.001 in a, "0.001 in a");
+assertFalse('0.0' in a,"'0.0' in a");
+assertFalse('1.0' in a,"'1.0' in a");
+assertFalse(NaN in a,"NaN in a");
+assertFalse(Infinity in a,"Infinity in a");
+assertFalse(-Infinity in a,"-Infinity in a");
+assertFalse(-0 in a,"-0 in a");
+assertFalse(+0 in a,"+0 in a");
+assertTrue('toString' in a, "toString");
+
+// -------------
+// Check negative indices in arrays.
+var a = [];
+assertFalse(-1 in a);
+a[-1] = 43;
+assertTrue(-1 in a);
diff --git a/deps/v8/test/mjsunit/indexed-accessors.js b/deps/v8/test/mjsunit/indexed-accessors.js
new file mode 100644
index 0000000..395f2ab
--- /dev/null
+++ b/deps/v8/test/mjsunit/indexed-accessors.js
@@ -0,0 +1,120 @@
+// 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.
+
+// Test that getters can be defined and called with an index as a parameter.
+
+var o = {};
+o.x = 42;
+o.__defineGetter__('0', function() { return o.x; });
+assertEquals(o.x, o[0]);
+assertEquals(o.x, o.__lookupGetter__('0')());
+
+o.__defineSetter__('0', function(y) { o.x = y; });
+assertEquals(o.x, o[0]);
+assertEquals(o.x, o.__lookupGetter__('0')());
+o[0] = 21;
+assertEquals(21, o.x);
+o.__lookupSetter__(0)(7);
+assertEquals(7, o.x);
+
+function Pair(x, y) {
+  this.x = x;
+  this.y = y;
+};
+Pair.prototype.__defineGetter__('0', function() { return this.x; });
+Pair.prototype.__defineGetter__('1', function() { return this.y; });
+Pair.prototype.__defineSetter__('0', function(x) { this.x = x; });
+Pair.prototype.__defineSetter__('1', function(y) { this.y = y; });
+
+var p = new Pair(2, 3);
+assertEquals(2, p[0]);
+assertEquals(3, p[1]);
+p.x = 7;
+p[1] = 8;
+assertEquals(7, p[0]);
+assertEquals(7, p.x);
+assertEquals(8, p[1]);
+assertEquals(8, p.y);
+
+
+// Testing that a defined getter doesn't get lost due to inline caching.
+var expected = {};
+var actual = {};
+for (var i = 0; i < 10; i++) {
+  expected[i] = actual[i] = i;
+}
+function testArray() {
+  for (var i = 0; i < 10; i++) {
+    assertEquals(expected[i], actual[i]);
+  }
+}
+actual[1000000] = -1;
+testArray();
+testArray();
+actual.__defineGetter__('0', function() { return expected[0]; });
+expected[0] = 42;
+testArray();
+expected[0] = 111;
+testArray();
+
+// The functionality is not implemented for arrays due to performance issues.
+var a = [ 1 ];
+a.__defineGetter__('2', function() { return 7; });
+assertEquals(undefined, a[2]);
+assertEquals(1, a.length);
+var b = 0;
+a.__defineSetter__('5', function(y) { b = y; });
+assertEquals(1, a.length);
+a[5] = 42;
+assertEquals(0, b);
+assertEquals(42, a[5]);
+assertEquals(6, a.length);
+
+// Using a setter where only a getter is defined throws an exception.
+var q = {};
+q.__defineGetter__('0', function() { return 42; });
+assertThrows('q[0] = 7');
+
+// Using a getter where only a setter is defined returns undefined.
+var q1 = {};
+q1.__defineSetter__('0', function() {q1.b = 17;});
+assertEquals(q1[0], undefined);
+// Setter works
+q1[0] = 3;
+assertEquals(q1[0], undefined);
+assertEquals(q1.b, 17);
+
+// Complex case of using an undefined getter.
+// From http://code.google.com/p/v8/issues/detail?id=298
+// Reported by nth10sd.
+
+a = function() {};
+__defineSetter__("0", function() {});
+if (a |= '') {};
+assertThrows('this[a].__parent__');
+assertEquals(a, 0);
+assertEquals(this[a], undefined);
diff --git a/deps/v8/test/mjsunit/instanceof.js b/deps/v8/test/mjsunit/instanceof.js
new file mode 100644
index 0000000..01ea426
--- /dev/null
+++ b/deps/v8/test/mjsunit/instanceof.js
@@ -0,0 +1,93 @@
+// Copyright 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.
+
+assertTrue({} instanceof Object);
+assertTrue([] instanceof Object);
+
+assertFalse({} instanceof Array);
+assertTrue([] instanceof Array);
+
+function TestChains() {
+  var A = {};
+  var B = {};
+  var C = {};
+  B.__proto__ = A;
+  C.__proto__ = B;
+
+  function F() { }
+  F.prototype = A;
+  assertTrue(C instanceof F);
+  assertTrue(B instanceof F);
+  assertFalse(A instanceof F);
+
+  F.prototype = B;
+  assertTrue(C instanceof F);
+  assertFalse(B instanceof F);
+  assertFalse(A instanceof F);
+
+  F.prototype = C;
+  assertFalse(C instanceof F);
+  assertFalse(B instanceof F);
+  assertFalse(A instanceof F);
+}
+
+TestChains();
+
+
+function TestExceptions() {
+  function F() { }
+  var items = [ 1, new Number(42), 
+                true, 
+                'string', new String('hest'),
+                {}, [], 
+                F, new F(),
+                Object, String ];
+
+  var exceptions = 0;
+  var instanceofs = 0;
+
+  for (var i = 0; i < items.length; i++) {
+    for (var j = 0; j < items.length; j++) {
+      try {
+        if (items[i] instanceof items[j]) instanceofs++;
+      } catch (e) {
+        assertTrue(e instanceof TypeError);
+        exceptions++;
+      }
+    }
+  }
+  assertEquals(10, instanceofs);
+  assertEquals(88, exceptions);
+
+  // Make sure to throw an exception if the function prototype
+  // isn't a proper JavaScript object.
+  function G() { }
+  G.prototype = undefined;
+  assertThrows("({} instanceof G)");
+}
+
+TestExceptions();
diff --git a/deps/v8/test/mjsunit/integer-to-string.js b/deps/v8/test/mjsunit/integer-to-string.js
new file mode 100644
index 0000000..3076bc4
--- /dev/null
+++ b/deps/v8/test/mjsunit/integer-to-string.js
@@ -0,0 +1,35 @@
+// Copyright 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.
+
+function TestIntToString() {
+  for (var i = -1000; i < 1000; i++)
+    assertEquals(i, parseInt(""+i));
+  for (var i = -5e9; i < 5e9; i += (1e6 - 1))
+    assertEquals(i, parseInt(""+i));
+}
+
+TestIntToString();
diff --git a/deps/v8/test/mjsunit/invalid-lhs.js b/deps/v8/test/mjsunit/invalid-lhs.js
new file mode 100644
index 0000000..bbd19f2
--- /dev/null
+++ b/deps/v8/test/mjsunit/invalid-lhs.js
@@ -0,0 +1,68 @@
+// Copyright 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.
+
+// Test that we get exceptions for invalid left-hand sides.  Also
+// tests that if the invalid left-hand side is a function call, the
+// exception is delayed until runtime.
+
+// Normal assignments:
+assertThrows("12 = 12");
+assertThrows("x++ = 12");
+assertThrows("eval('var x') = 12");
+assertDoesNotThrow("if (false) eval('var x') = 12");
+
+// Pre- and post-fix operations:
+assertThrows("12++");
+assertThrows("12--");
+assertThrows("--12");
+assertThrows("++12");
+assertThrows("++(eval('12'))");
+assertThrows("(eval('12'))++");
+assertDoesNotThrow("if (false) ++(eval('12'))");
+assertDoesNotThrow("if (false) (eval('12'))++");
+
+// For in:
+assertThrows("for (12 in [1]) print(12);");
+assertThrows("for (eval('var x') in [1]) print(12);");
+assertDoesNotThrow("if (false) for (eval('var x') in [1]) print(12);");
+
+// For:
+assertThrows("for (12 = 1;;) print(12);");
+assertThrows("for (eval('var x') = 1;;) print(12);");
+assertDoesNotThrow("if (false) for (eval('var x') = 1;;) print(12);");
+
+// Assignments to 'this'.
+assertThrows("this = 42");
+assertThrows("function f() { this = 12; }");
+assertThrows("for (this in Array) ;");
+assertThrows("for (this = 0;;) ;");
+assertThrows("this++");
+assertThrows("++this");
+assertThrows("this--");
+assertThrows("--this");
+
+
diff --git a/deps/v8/test/mjsunit/keyed-ic.js b/deps/v8/test/mjsunit/keyed-ic.js
new file mode 100644
index 0000000..d37bd03
--- /dev/null
+++ b/deps/v8/test/mjsunit/keyed-ic.js
@@ -0,0 +1,207 @@
+// Copyright 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.
+
+// This test attempts to test the inline caching for keyed access.
+
+// ----------------------------------------------------------------------
+// Prototype accessor.
+// ----------------------------------------------------------------------
+var runTest = function() {
+  var initial_P = 'prototype';
+  var P = initial_P;
+  var H = 'hasOwnProperty';
+
+  var f = function() {};
+
+  function prototypeTest(change_index) {
+    for (var i = 0; i < 10; i++) {
+      var property = f[P];
+      if (i <= change_index) {
+        assertEquals(f.prototype, property);
+      } else {
+        assertEquals(f.hasOwnProperty, property);
+      }
+      if (i == change_index) P = H;
+    }
+    P = initial_P;
+  }
+
+  for (var i = 0; i < 10; i++) prototypeTest(i);
+
+  f.prototype = 43;
+
+  for (var i = 0; i < 10; i++) prototypeTest(i);
+}
+
+runTest();
+
+// ----------------------------------------------------------------------
+// Array length accessor.
+// ----------------------------------------------------------------------
+runTest = function() {
+  var initial_L = 'length';
+  var L = initial_L;
+  var zero = '0';
+
+  var a = new Array(10);
+
+  function arrayLengthTest(change_index) {
+    for (var i = 0; i < 10; i++) {
+      var l = a[L];
+      if (i <= change_index) {
+        assertEquals(10, l);
+      } else {
+        assertEquals(undefined, l);
+      }
+      if (i == change_index) L = zero;
+    }
+    L = initial_L;
+  }
+
+  for (var i = 0; i < 10; i++) arrayLengthTest(i);
+}
+
+runTest();
+
+// ----------------------------------------------------------------------
+// String length accessor.
+// ----------------------------------------------------------------------
+runTest = function() {
+  var initial_L = 'length';
+  var L = initial_L;
+  var zero = '0';
+
+  var s = "asdf"
+
+  function stringLengthTest(change_index) {
+    for (var i = 0; i < 10; i++) {
+      var l = s[L];
+      if (i <= change_index) {
+        assertEquals(4, l);
+      } else {
+        assertEquals('a', l);
+      }
+      if (i == change_index) L = zero;
+    }
+    L = initial_L;
+  }
+
+  for (var i = 0; i < 10; i++) stringLengthTest(i);
+}
+
+runTest();
+
+// ----------------------------------------------------------------------
+// Field access.
+// ----------------------------------------------------------------------
+runTest = function() {
+  var o = { x: 42, y: 43 }
+
+  var initial_X = 'x';
+  var X = initial_X;
+  var Y = 'y';
+
+  function fieldTest(change_index) {
+    for (var i = 0; i < 10; i++) {
+      var property = o[X];
+      if (i <= change_index) {
+        assertEquals(42, property);
+      } else {
+        assertEquals(43, property);
+      }
+      if (i == change_index) X = Y;
+    }
+    X = initial_X;
+  };
+
+  for (var i = 0; i < 10; i++) fieldTest(i);
+}
+
+runTest();
+
+
+// ----------------------------------------------------------------------
+// Constant function access.
+// ----------------------------------------------------------------------
+runTest = function() {
+  function fun() { };
+
+  var o = new Object();
+  o.f = fun;
+  o.x = 42;
+
+  var initial_F = 'f';
+  var F = initial_F;
+  var X = 'x'
+
+  function constantFunctionTest(change_index) {
+    for (var i = 0; i < 10; i++) {
+      var property = o[F];
+      if (i <= change_index) {
+        assertEquals(fun, property);
+      } else {
+        assertEquals(42, property);
+      }
+      if (i == change_index) F = X;
+    }
+    F = initial_F;
+  };
+
+  for (var i = 0; i < 10; i++) constantFunctionTest(i);
+}
+
+runTest();
+
+// ----------------------------------------------------------------------
+// Keyed store field.
+// ----------------------------------------------------------------------
+
+runTest = function() {
+  var o = { x: 42, y: 43 }
+
+  var initial_X = 'x';
+  var X = initial_X;
+  var Y = 'y';
+
+  function fieldTest(change_index) {
+    for (var i = 0; i < 10; i++) {
+      o[X] = X;
+      var property = o[X];
+      if (i <= change_index) {
+        assertEquals('x', property);
+      } else {
+        assertEquals('y', property);
+      }
+      if (i == change_index) X = Y;
+    }
+    X = initial_X;
+  };
+
+  for (var i = 0; i < 10; i++) fieldTest(i);
+}
+
+runTest();
diff --git a/deps/v8/test/mjsunit/keyed-storage-extend.js b/deps/v8/test/mjsunit/keyed-storage-extend.js
new file mode 100644
index 0000000..04d2f04
--- /dev/null
+++ b/deps/v8/test/mjsunit/keyed-storage-extend.js
@@ -0,0 +1,55 @@
+// Copyright 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.
+
+function F() { }
+
+function GrowNamed(o) {
+  o.a = 1;
+  o.b = 2;
+  o.c = 3;
+  o.d = 4;
+  o.e = 5;
+  o.f = 6;
+}
+
+function GrowKeyed(o) {
+  var names = ['a','b','c','d','e','f']; 
+  var i = 0;
+  o[names[i++]] = i;
+  o[names[i++]] = i;
+  o[names[i++]] = i;
+  o[names[i++]] = i;
+  o[names[i++]] = i;
+  o[names[i++]] = i;
+}
+
+GrowNamed(new F());
+GrowNamed(new F());
+GrowNamed(new F());
+GrowKeyed(new F());
+GrowKeyed(new F());
+GrowKeyed(new F());
diff --git a/deps/v8/test/mjsunit/large-object-allocation.js b/deps/v8/test/mjsunit/large-object-allocation.js
new file mode 100644
index 0000000..c2b717c
--- /dev/null
+++ b/deps/v8/test/mjsunit/large-object-allocation.js
@@ -0,0 +1,300 @@
+// Copyright 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.
+
+// Allocate a very large object that is guaranteed to overflow the
+// instance_size field in the map resulting in an object that is smaller
+// than what was called for.
+function LargeObject(i) {
+  this.a = i;
+  this.b = i;
+  this.c = i;
+  this.d = i;
+  this.e = i;
+  this.f = i;
+  this.g = i;
+  this.h = i;
+  this.i = i;
+  this.j = i;
+  this.k = i;
+  this.l = i;
+  this.m = i;
+  this.n = i;
+  this.o = i;
+  this.p = i;
+  this.q = i;
+  this.r = i;
+  this.s = i;
+  this.t = i;
+  this.u = i;
+  this.v = i;
+  this.w = i;
+  this.x = i;
+  this.y = i;
+  this.z = i;
+  this.a1 = i;
+  this.b1 = i;
+  this.c1 = i;
+  this.d1 = i;
+  this.e1 = i;
+  this.f1 = i;
+  this.g1 = i;
+  this.h1 = i;
+  this.i1 = i;
+  this.j1 = i;
+  this.k1 = i;
+  this.l1 = i;
+  this.m1 = i;
+  this.n1 = i;
+  this.o1 = i;
+  this.p1 = i;
+  this.q1 = i;
+  this.r1 = i;
+  this.s1 = i;
+  this.t1 = i;
+  this.u1 = i;
+  this.v1 = i;
+  this.w1 = i;
+  this.x1 = i;
+  this.y1 = i;
+  this.z1 = i;
+  this.a2 = i;
+  this.b2 = i;
+  this.c2 = i;
+  this.d2 = i;
+  this.e2 = i;
+  this.f2 = i;
+  this.g2 = i;
+  this.h2 = i;
+  this.i2 = i;
+  this.j2 = i;
+  this.k2 = i;
+  this.l2 = i;
+  this.m2 = i;
+  this.n2 = i;
+  this.o2 = i;
+  this.p2 = i;
+  this.q2 = i;
+  this.r2 = i;
+  this.s2 = i;
+  this.t2 = i;
+  this.u2 = i;
+  this.v2 = i;
+  this.w2 = i;
+  this.x2 = i;
+  this.y2 = i;
+  this.z2 = i;
+  this.a3 = i;
+  this.b3 = i;
+  this.c3 = i;
+  this.d3 = i;
+  this.e3 = i;
+  this.f3 = i;
+  this.g3 = i;
+  this.h3 = i;
+  this.i3 = i;
+  this.j3 = i;
+  this.k3 = i;
+  this.l3 = i;
+  this.m3 = i;
+  this.n3 = i;
+  this.o3 = i;
+  this.p3 = i;
+  this.q3 = i;
+  this.r3 = i;
+  this.s3 = i;
+  this.t3 = i;
+  this.u3 = i;
+  this.v3 = i;
+  this.w3 = i;
+  this.x3 = i;
+  this.y3 = i;
+  this.z3 = i;
+  this.a4 = i;
+  this.b4 = i;
+  this.c4 = i;
+  this.d4 = i;
+  this.e4 = i;
+  this.f4 = i;
+  this.g4 = i;
+  this.h4 = i;
+  this.i4 = i;
+  this.j4 = i;
+  this.k4 = i;
+  this.l4 = i;
+  this.m4 = i;
+  this.n4 = i;
+  this.o4 = i;
+  this.p4 = i;
+  this.q4 = i;
+  this.r4 = i;
+  this.s4 = i;
+  this.t4 = i;
+  this.u4 = i;
+  this.v4 = i;
+  this.w4 = i;
+  this.x4 = i;
+  this.y4 = i;
+  this.z4 = i;
+  this.a5 = i;
+  this.b5 = i;
+  this.c5 = i;
+  this.d5 = i;
+  this.e5 = i;
+  this.f5 = i;
+  this.g5 = i;
+  this.h5 = i;
+  this.i5 = i;
+  this.j5 = i;
+  this.k5 = i;
+  this.l5 = i;
+  this.m5 = i;
+  this.n5 = i;
+  this.o5 = i;
+  this.p5 = i;
+  this.q5 = i;
+  this.r5 = i;
+  this.s5 = i;
+  this.t5 = i;
+  this.u5 = i;
+  this.v5 = i;
+  this.w5 = i;
+  this.x5 = i;
+  this.y5 = i;
+  this.z5 = i;
+  this.a6 = i;
+  this.b6 = i;
+  this.c6 = i;
+  this.d6 = i;
+  this.e6 = i;
+  this.f6 = i;
+  this.g6 = i;
+  this.h6 = i;
+  this.i6 = i;
+  this.j6 = i;
+  this.k6 = i;
+  this.l6 = i;
+  this.m6 = i;
+  this.n6 = i;
+  this.o6 = i;
+  this.p6 = i;
+  this.q6 = i;
+  this.r6 = i;
+  this.s6 = i;
+  this.t6 = i;
+  this.u6 = i;
+  this.v6 = i;
+  this.w6 = i;
+  this.x6 = i;
+  this.y6 = i;
+  this.z6 = i;
+  this.a7 = i;
+  this.b7 = i;
+  this.c7 = i;
+  this.d7 = i;
+  this.e7 = i;
+  this.f7 = i;
+  this.g7 = i;
+  this.h7 = i;
+  this.i7 = i;
+  this.j7 = i;
+  this.k7 = i;
+  this.l7 = i;
+  this.m7 = i;
+  this.n7 = i;
+  this.o7 = i;
+  this.p7 = i;
+  this.q7 = i;
+  this.r7 = i;
+  this.s7 = i;
+  this.t7 = i;
+  this.u7 = i;
+  this.v7 = i;
+  this.w7 = i;
+  this.x7 = i;
+  this.y7 = i;
+  this.z7 = i;
+  this.a8 = i;
+  this.b8 = i;
+  this.c8 = i;
+  this.d8 = i;
+  this.e8 = i;
+  this.f8 = i;
+  this.g8 = i;
+  this.h8 = i;
+  this.i8 = i;
+  this.j8 = i;
+  this.k8 = i;
+  this.l8 = i;
+  this.m8 = i;
+  this.n8 = i;
+  this.o8 = i;
+  this.p8 = i;
+  this.q8 = i;
+  this.r8 = i;
+  this.s8 = i;
+  this.t8 = i;
+  this.u8 = i;
+  this.v8 = i;
+  this.w8 = i;
+  this.x8 = i;
+  this.y8 = i;
+  this.z8 = i;
+  this.a9 = i;
+  this.b9 = i;
+  this.c9 = i;
+  this.d9 = i;
+  this.e9 = i;
+  this.f9 = i;
+  this.g9 = i;
+  this.h9 = i;
+  this.i9 = i;
+  this.j9 = i;
+  this.k9 = i;
+  this.l9 = i;
+  this.m9 = i;
+  this.n9 = i;
+  this.o9 = i;
+  this.p9 = i;
+  this.q9 = i;
+  // With this number of properties the object perfectly wraps around if the
+  // instance size is not checked when allocating the initial map for MultiProp.
+  // Meaning that the instance will be smaller than a minimal JSObject and we
+  // will suffer a bus error in the release build or an assertion in the debug
+  // build.
+}
+
+function ExpectAllFields(o, val) {
+  for (var x in o) {
+    assertEquals(o[x], val);
+  }
+}
+
+var a = new LargeObject(1);
+var b = new LargeObject(2);
+
+ExpectAllFields(a, 1);
+ExpectAllFields(b, 2);
diff --git a/deps/v8/test/mjsunit/large-object-literal.js b/deps/v8/test/mjsunit/large-object-literal.js
new file mode 100644
index 0000000..70a2769
--- /dev/null
+++ b/deps/v8/test/mjsunit/large-object-literal.js
@@ -0,0 +1,56 @@
+// Copyright 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.
+
+// Test that we can create object literals of various sizes.
+function testLiteral(size) {
+
+  // Build object-literal string.
+  var literal = "var o = { ";
+
+  for (var i = 0; i < size; i++) {
+    if (i > 0) literal += ",";
+    literal += ("a" + i + ":" + i);
+  }
+  literal += "}";
+
+  // Create the object literal.
+  eval(literal);
+
+  // Check that the properties have the expected values.
+  for (var i = 0; i < size; i++) {
+    assertEquals(i, o["a"+i]);
+  }
+}
+
+// The sizes to test.
+var sizes = [0, 1, 2, 100, 200, 400, 1000];
+
+// Run the test.
+for (var i = 0; i < sizes.length; i++) {
+  testLiteral(sizes[i]);
+}
+
diff --git a/deps/v8/test/mjsunit/lazy-load.js b/deps/v8/test/mjsunit/lazy-load.js
new file mode 100644
index 0000000..c384331
--- /dev/null
+++ b/deps/v8/test/mjsunit/lazy-load.js
@@ -0,0 +1,34 @@
+// Copyright 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.
+
+// Test unusual way of accessing Date.
+var date0 = new this["Date"](1111);
+assertEquals(1111, date0.getTime());
+
+// Check that regexp literals use original RegExp (non-ECMA-262).
+RegExp = 42;
+var re = /test/;
diff --git a/deps/v8/test/mjsunit/leakcheck.js b/deps/v8/test/mjsunit/leakcheck.js
new file mode 100644
index 0000000..7cbb2e5
--- /dev/null
+++ b/deps/v8/test/mjsunit/leakcheck.js
@@ -0,0 +1,53 @@
+// Copyright 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.
+
+/**
+ * This test is run with leak detection when running special tests.
+ * Don't do too much work here or running it will take forever.
+ */
+
+function fac(n) {
+  if (n > 0) return fac(n - 1) * n;
+  else return 1;
+}
+
+function testFac() {
+  if (fac(6) != 720) throw "Error";
+}
+
+function testRegExp() {
+  var input = "123456789";
+  var result = input.replace(/[4-6]+/g, "xxx");
+  if (result != "123xxx789") throw "Error";
+}
+
+function main() {
+  testFac();
+  testRegExp();
+}
+
+main();
diff --git a/deps/v8/test/mjsunit/length.js b/deps/v8/test/mjsunit/length.js
new file mode 100644
index 0000000..3331564
--- /dev/null
+++ b/deps/v8/test/mjsunit/length.js
@@ -0,0 +1,78 @@
+// Copyright 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.
+
+/**
+ * @fileoverview Assert we match ES3 and Safari.
+ */
+
+assertEquals(0, Array.prototype.length, "Array.prototype.length");
+assertEquals(1, Array.length, "Array.length");
+assertEquals(1, Array.prototype.concat.length, "Array.prototype.concat.length");
+assertEquals(1, Array.prototype.join.length, "Array.prototype.join.length");
+assertEquals(1, Array.prototype.push.length, "Array.prototype.push.length");
+assertEquals(1, Array.prototype.unshift.length, "Array.prototype.unshift.length");
+assertEquals(1, Boolean.length, "Boolean.length");
+assertEquals(1, Error.length, "Error.length");
+assertEquals(1, EvalError.length, "EvalError.length");
+assertEquals(1, Function.length, "Function.length");
+assertEquals(1, Function.prototype.call.length, "Function.prototype.call.length");
+assertEquals(1, Number.length, "Number.length");
+assertEquals(1, Number.prototype.toExponential.length, "Number.prototype.toExponential.length");
+assertEquals(1, Number.prototype.toFixed.length, "Number.prototype.toFixed.length");
+assertEquals(1, Number.prototype.toPrecision.length, "Number.prototype.toPrecision.length");
+assertEquals(1, Object.length, "Object.length");
+assertEquals(1, RangeError.length, "RangeError.length");
+assertEquals(1, ReferenceError.length, "ReferenceError.length");
+assertEquals(1, String.fromCharCode.length, "String.fromCharCode.length");
+assertEquals(1, String.length, "String.length");
+assertEquals(1, String.prototype.concat.length, "String.prototype.concat.length");
+assertEquals(1, String.prototype.indexOf.length, "String.prototype.indexOf.length");
+assertEquals(1, String.prototype.lastIndexOf.length, "String.prototype.lastIndexOf.length");
+assertEquals(1, SyntaxError.length, "SyntaxError.length");
+assertEquals(1, TypeError.length, "TypeError.length");
+assertEquals(2, Array.prototype.slice.length, "Array.prototype.slice.length");
+assertEquals(2, Array.prototype.splice.length, "Array.prototype.splice.length");
+assertEquals(2, Date.prototype.setMonth.length, "Date.prototype.setMonth.length");
+assertEquals(2, Date.prototype.setSeconds.length, "Date.prototype.setSeconds.length");
+assertEquals(2, Date.prototype.setUTCMonth.length, "Date.prototype.setUTCMonth.length");
+assertEquals(2, Date.prototype.setUTCSeconds.length, "Date.prototype.setUTCSeconds.length");
+assertEquals(2, Function.prototype.apply.length, "Function.prototype.apply.length");
+assertEquals(2, Math.max.length, "Math.max.length");
+assertEquals(2, Math.min.length, "Math.min.length");
+assertEquals(2, RegExp.length, "RegExp.length");
+assertEquals(2, String.prototype.slice.length, "String.prototype.slice.length");
+assertEquals(2, String.prototype.split.length, "String.prototype.split.length");
+assertEquals(2, String.prototype.substr.length, "String.prototype.substr.length");
+assertEquals(2, String.prototype.substring.length, "String.prototype.substring.length");
+assertEquals(3, Date.prototype.setFullYear.length, "Date.prototype.setFullYear.length");
+assertEquals(3, Date.prototype.setMinutes.length, "Date.prototype.setMinutes.length");
+assertEquals(3, Date.prototype.setUTCFullYear.length, "Date.prototype.setUTCFullYear.length");
+assertEquals(3, Date.prototype.setUTCMinutes.length, "Date.prototype.setUTCMinutes.length");
+assertEquals(4, Date.prototype.setHours.length, "Date.prototype.setHours.length");
+assertEquals(4, Date.prototype.setUTCHours.length, "Date.prototype.setUTCHours.length");
+assertEquals(7, Date.UTC.length, "Date.UTC.length");
+assertEquals(7, Date.length, "Date.length");
diff --git a/deps/v8/test/mjsunit/local-load-from-eval.js b/deps/v8/test/mjsunit/local-load-from-eval.js
new file mode 100644
index 0000000..0fdac9a
--- /dev/null
+++ b/deps/v8/test/mjsunit/local-load-from-eval.js
@@ -0,0 +1,39 @@
+// 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.
+
+// Tests loads of local properties from eval.
+
+function test(source) {
+  var x = 27;
+  eval(source);
+}
+
+test("assertEquals(27, x);");
+test("(function() { assertEquals(27, x) })();");
+test("(function() { var y = 42; eval('1'); assertEquals(42, y); })();");
+test("(function() { var y = 42; eval('var y = 2; var z = 2;'); assertEquals(2, y); })();");
+
diff --git a/deps/v8/test/mjsunit/math-min-max.js b/deps/v8/test/mjsunit/math-min-max.js
new file mode 100644
index 0000000..0ed9912
--- /dev/null
+++ b/deps/v8/test/mjsunit/math-min-max.js
@@ -0,0 +1,72 @@
+// Copyright 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.
+
+// Test Math.min().
+
+assertEquals(Number.POSITIVE_INFINITY, Math.min());
+assertEquals(1, Math.min(1));
+assertEquals(1, Math.min(1, 2));
+assertEquals(1, Math.min(2, 1));
+assertEquals(1, Math.min(1, 2, 3));
+assertEquals(1, Math.min(3, 2, 1));
+assertEquals(1, Math.min(2, 3, 1));
+
+var o = {};
+o.valueOf = function() { return 1; };
+assertEquals(1, Math.min(2, 3, '1'));
+assertEquals(1, Math.min(3, o, 2));
+assertEquals(Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY / Math.min(-0, +0));
+assertEquals(Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY / Math.min(+0, -0));
+assertEquals(Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY / Math.min(+0, -0, 1));
+assertEquals(-1, Math.min(+0, -0, -1));
+assertEquals(-1, Math.min(-1, +0, -0));
+assertEquals(-1, Math.min(+0, -1, -0));
+assertEquals(-1, Math.min(-0, -1, +0));
+
+
+
+// Test Math.max().
+
+assertEquals(Number.NEGATIVE_INFINITY, Math.max());
+assertEquals(1, Math.max(1));
+assertEquals(2, Math.max(1, 2));
+assertEquals(2, Math.max(2, 1));
+assertEquals(3, Math.max(1, 2, 3));
+assertEquals(3, Math.max(3, 2, 1));
+assertEquals(3, Math.max(2, 3, 1));
+
+var o = {};
+o.valueOf = function() { return 3; };
+assertEquals(3, Math.max(2, '3', 1));
+assertEquals(3, Math.max(1, o, 2));
+assertEquals(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY / Math.max(-0, +0));
+assertEquals(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY / Math.max(+0, -0));
+assertEquals(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY / Math.max(+0, -0, -1));
+assertEquals(1, Math.max(+0, -0, +1));
+assertEquals(1, Math.max(+1, +0, -0));
+assertEquals(1, Math.max(+0, +1, -0));
+assertEquals(1, Math.max(-0, +1, +0));
\ No newline at end of file
diff --git a/deps/v8/test/mjsunit/megamorphic-callbacks.js b/deps/v8/test/mjsunit/megamorphic-callbacks.js
new file mode 100644
index 0000000..8829df0
--- /dev/null
+++ b/deps/v8/test/mjsunit/megamorphic-callbacks.js
@@ -0,0 +1,70 @@
+// Copyright 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.
+
+function load(o) {
+  return o.x;
+};
+
+function store(o) {
+  o.y = 42;
+};
+
+function call(o) {
+  return o.f();
+};
+
+// Create a slow-case object (with hashed properties).
+var o = { x: 42, f: function() { }, z: 100 };
+delete o.z;
+
+// Initialize IC stubs.
+load(o);
+store(o);
+call(o);
+
+
+// Create a new slow-case object (with hashed properties) and add
+// setter and getter properties to the object.
+var o = { z: 100 };
+delete o.z;
+o.__defineGetter__("x", function() { return 100; });
+o.__defineSetter__("y", function(value) { this.y_mirror = value; });
+o.__defineGetter__("f", function() { return function() { return 300; }});
+
+// Perform the load checks.
+assertEquals(100, o.x, "normal load");
+assertEquals(100, load(o), "ic load");
+
+// Perform the store checks.
+o.y = 200;
+assertEquals(200, o.y_mirror, "normal store");
+store(o);
+assertEquals(42, o.y_mirror, "ic store");
+
+// Perform the call checks.
+assertEquals(300, o.f(), "normal call");
+assertEquals(300, call(o), "ic call");
diff --git a/deps/v8/test/mjsunit/mirror-array.js b/deps/v8/test/mjsunit/mirror-array.js
new file mode 100644
index 0000000..1873d1e
--- /dev/null
+++ b/deps/v8/test/mjsunit/mirror-array.js
@@ -0,0 +1,137 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Test the mirror object for objects
+
+function MirrorRefCache(json_refs) {
+  var tmp = eval('(' + json_refs + ')');
+  this.refs_ = [];
+  for (var i = 0; i < tmp.length; i++) {
+    this.refs_[tmp[i].handle] = tmp[i];
+  }
+}
+
+MirrorRefCache.prototype.lookup = function(handle) {
+  return this.refs_[handle];
+}
+
+function testArrayMirror(a, names) {
+  // Create mirror and JSON representation.
+  var mirror = debug.MakeMirror(a);
+  var serializer = debug.MakeMirrorSerializer();
+  var json = serializer.serializeValue(mirror);
+  var refs = new MirrorRefCache(serializer.serializeReferencedObjects());
+
+  // Check the mirror hierachy.
+  assertTrue(mirror instanceof debug.Mirror, 'Unexpected mirror hierachy');
+  assertTrue(mirror instanceof debug.ValueMirror, 'Unexpected mirror hierachy');
+  assertTrue(mirror instanceof debug.ObjectMirror, 'Unexpected mirror hierachy');
+  assertTrue(mirror instanceof debug.ArrayMirror, 'Unexpected mirror hierachy');
+
+  // Check the mirror properties.
+  assertTrue(mirror.isArray(), 'Unexpected mirror');
+  assertEquals('object', mirror.type(), 'Unexpected mirror type');
+  assertFalse(mirror.isPrimitive(), 'Unexpected primitive mirror');
+  assertEquals('Array', mirror.className(), 'Unexpected mirror class name');
+  assertTrue(mirror.constructorFunction() instanceof debug.ObjectMirror, 'Unexpected mirror hierachy');
+  assertEquals('Array', mirror.constructorFunction().name(), 'Unexpected constructor function name');
+  assertTrue(mirror.protoObject() instanceof debug.Mirror, 'Unexpected mirror hierachy');
+  assertTrue(mirror.prototypeObject() instanceof debug.Mirror, 'Unexpected mirror hierachy');
+  assertEquals(mirror.length(), a.length, "Length mismatch");
+  
+  var indexedProperties = mirror.indexedPropertiesFromRange();
+  assertEquals(indexedProperties.length, a.length);
+  for (var i = 0; i < indexedProperties.length; i++) {
+    assertTrue(indexedProperties[i] instanceof debug.Mirror, 'Unexpected mirror hierachy');
+    assertTrue(indexedProperties[i] instanceof debug.PropertyMirror, 'Unexpected mirror hierachy');
+  }
+
+  // Parse JSON representation and check.
+  var fromJSON = eval('(' + json + ')');
+  assertEquals('object', fromJSON.type, 'Unexpected mirror type in JSON');
+  assertEquals('Array', fromJSON.className, 'Unexpected mirror class name in JSON');
+  assertEquals(mirror.constructorFunction().handle(), fromJSON.constructorFunction.ref, 'Unexpected constructor function handle in JSON');
+  assertEquals('function', refs.lookup(fromJSON.constructorFunction.ref).type, 'Unexpected constructor function type in JSON');
+  assertEquals('Array', refs.lookup(fromJSON.constructorFunction.ref).name, 'Unexpected constructor function name in JSON');
+  assertEquals(void 0, fromJSON.namedInterceptor, 'No named interceptor expected in JSON');
+  assertEquals(void 0, fromJSON.indexedInterceptor, 'No indexed interceptor expected in JSON');
+
+  // Check that the serialization contains all indexed properties and the length property.
+  var length_found = false;
+  for (var i = 0; i < fromJSON.properties.length; i++) {
+    if (fromJSON.properties[i].name == 'length') {
+      length_found = true;
+      assertEquals('number', refs.lookup(fromJSON.properties[i].ref).type, "Unexpected type of the length property");
+      assertEquals(a.length, refs.lookup(fromJSON.properties[i].ref).value, "Length mismatch in parsed JSON");
+    } else {
+      var index = parseInt(fromJSON.properties[i].name);
+        print(index);
+      if (!isNaN(index)) {
+        print(index);
+        // This test assumes that the order of the indexeed properties is in the
+        // same order in the serialization as returned from
+        // indexedPropertiesFromRange()
+        assertEquals(indexedProperties[index].name(), index);
+        assertEquals(indexedProperties[index].value().type(), refs.lookup(fromJSON.properties[i].ref).type, 'Unexpected serialized type');
+      }
+    }
+  }
+  assertTrue(length_found, 'Property length not found');
+
+  // Check that the serialization contains all names properties.
+  if (names) {
+    for (var i = 0; i < names.length; i++) {
+      var found = false;
+      for (var j = 0; j < fromJSON.properties.length; j++) {
+        if (names[i] == fromJSON.properties[j].name) {
+          found = true; 
+        }
+      }
+      assertTrue(found, names[i])
+    }
+  }
+}
+
+
+// Test a number of different arrays.
+testArrayMirror([]);
+testArrayMirror([1]);
+testArrayMirror([1,2]);
+testArrayMirror(["a", function(){}, [1,2], 2, /[ab]/]);
+
+a=[1];
+a[100]=7;
+testArrayMirror(a);
+
+a=[1,2,3];
+a.x=2.2;
+a.y=function(){return null;}
+testArrayMirror(a, ['x','y']);
+
+var a = []; a.push(a);
+testArrayMirror(a);
diff --git a/deps/v8/test/mjsunit/mirror-boolean.js b/deps/v8/test/mjsunit/mirror-boolean.js
new file mode 100644
index 0000000..4f93089
--- /dev/null
+++ b/deps/v8/test/mjsunit/mirror-boolean.js
@@ -0,0 +1,59 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Test the mirror object for boolean values
+
+function testBooleanMirror(b) {
+  // Create mirror and JSON representation.
+  var mirror = debug.MakeMirror(b);
+  var serializer = debug.MakeMirrorSerializer();
+  var json = serializer.serializeValue(mirror);
+
+  // Check the mirror hierachy.
+  assertTrue(mirror instanceof debug.Mirror);
+  assertTrue(mirror instanceof debug.ValueMirror);
+  assertTrue(mirror instanceof debug.BooleanMirror);
+
+  // Check the mirror properties.
+  assertTrue(mirror.isBoolean());
+  assertEquals('boolean', mirror.type());
+  assertTrue(mirror.isPrimitive());
+
+  // Test text representation
+  assertEquals(b ? 'true' : 'false', mirror.toText());
+
+  // Parse JSON representation and check.
+  var fromJSON = eval('(' + json + ')');
+  assertEquals('boolean', fromJSON.type, json);
+  assertEquals(b, fromJSON.value, json);
+}
+
+
+// Test all boolean values.
+testBooleanMirror(true);
+testBooleanMirror(false);
\ No newline at end of file
diff --git a/deps/v8/test/mjsunit/mirror-date.js b/deps/v8/test/mjsunit/mirror-date.js
new file mode 100644
index 0000000..a6334d0
--- /dev/null
+++ b/deps/v8/test/mjsunit/mirror-date.js
@@ -0,0 +1,75 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Test the mirror object for boolean values
+
+function testDateMirror(d, iso8601) {
+  // Create mirror and JSON representation.
+  var mirror = debug.MakeMirror(d);
+  var serializer = debug.MakeMirrorSerializer();
+  var json = serializer.serializeValue(mirror);
+
+  // Check the mirror hierachy.
+  assertTrue(mirror instanceof debug.Mirror);
+  assertTrue(mirror instanceof debug.ValueMirror);
+  assertTrue(mirror instanceof debug.ObjectMirror);
+  assertTrue(mirror instanceof debug.DateMirror);
+
+  // Check the mirror properties.
+  assertTrue(mirror.isDate());
+  assertEquals('object', mirror.type());
+  assertFalse(mirror.isPrimitive());
+
+  // Test text representation
+  assertEquals(iso8601, mirror.toText());
+
+  // Parse JSON representation and check.
+  var fromJSON = eval('(' + json + ')');
+  assertEquals('object', fromJSON.type);
+  assertEquals('Date', fromJSON.className);
+  assertEquals(iso8601, fromJSON.value);
+}
+
+
+// Test Date values.
+testDateMirror(new Date(Date.parse("Dec 25, 1995 1:30 UTC")), "1995-12-25T01:30:00.000Z");
+d = new Date();
+d.setUTCFullYear(1967);
+d.setUTCMonth(0); // January.
+d.setUTCDate(17);
+d.setUTCHours(9);
+d.setUTCMinutes(22);
+d.setUTCSeconds(59);
+d.setUTCMilliseconds(0);
+testDateMirror(d, "1967-01-17T09:22:59.000Z");
+d.setUTCMilliseconds(1);
+testDateMirror(d, "1967-01-17T09:22:59.001Z");
+d.setUTCMilliseconds(12);
+testDateMirror(d, "1967-01-17T09:22:59.012Z");
+d.setUTCMilliseconds(123);
+testDateMirror(d, "1967-01-17T09:22:59.123Z");
diff --git a/deps/v8/test/mjsunit/mirror-error.js b/deps/v8/test/mjsunit/mirror-error.js
new file mode 100644
index 0000000..37ec46c
--- /dev/null
+++ b/deps/v8/test/mjsunit/mirror-error.js
@@ -0,0 +1,93 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Test the mirror object for regular error objects
+
+function MirrorRefCache(json_refs) {
+  var tmp = eval('(' + json_refs + ')');
+  this.refs_ = [];
+  for (var i = 0; i < tmp.length; i++) {
+    this.refs_[tmp[i].handle] = tmp[i];
+  }
+}
+
+MirrorRefCache.prototype.lookup = function(handle) {
+  return this.refs_[handle];
+}
+
+function testErrorMirror(e) {
+  // Create mirror and JSON representation.
+  var mirror = debug.MakeMirror(e);
+  var serializer = debug.MakeMirrorSerializer();
+  var json = serializer.serializeValue(mirror);
+  var refs = new MirrorRefCache(serializer.serializeReferencedObjects());
+
+  // Check the mirror hierachy.
+  assertTrue(mirror instanceof debug.Mirror);
+  assertTrue(mirror instanceof debug.ValueMirror);
+  assertTrue(mirror instanceof debug.ObjectMirror);
+  assertTrue(mirror instanceof debug.ErrorMirror);
+
+  // Check the mirror properties.
+  assertTrue(mirror.isError());
+  assertEquals('error', mirror.type());
+  assertFalse(mirror.isPrimitive());
+  assertEquals(mirror.message(), e.message, 'source');
+
+  // Parse JSON representation and check.
+  var fromJSON = eval('(' + json + ')');
+  assertEquals('error', fromJSON.type);
+  assertEquals('Error', fromJSON.className);
+  if (e.message) {
+    var found_message = false;
+    for (var i in fromJSON.properties) {
+      var p = fromJSON.properties[i];
+      print(p.name);
+      if (p.name == 'message') {
+        assertEquals(e.message, refs.lookup(p.ref).value);
+        found_message = true;
+      }
+    }
+    assertTrue(found_message, 'Property message not found');
+  }
+  
+  // Check the formatted text (regress 1231579).
+  assertEquals(fromJSON.text, e.toString(), 'toString');
+}
+
+
+// Test Date values.
+testErrorMirror(new Error());
+testErrorMirror(new Error('This does not work'));
+testErrorMirror(new Error(123+456));
+testErrorMirror(new EvalError('EvalError'));
+testErrorMirror(new RangeError('RangeError'));
+testErrorMirror(new ReferenceError('ReferenceError'));
+testErrorMirror(new SyntaxError('SyntaxError'));
+testErrorMirror(new TypeError('TypeError'));
+testErrorMirror(new URIError('URIError'));
diff --git a/deps/v8/test/mjsunit/mirror-function.js b/deps/v8/test/mjsunit/mirror-function.js
new file mode 100644
index 0000000..59d9e78
--- /dev/null
+++ b/deps/v8/test/mjsunit/mirror-function.js
@@ -0,0 +1,89 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Test the mirror object for functions.
+
+function MirrorRefCache(json_refs) {
+  var tmp = eval('(' + json_refs + ')');
+  this.refs_ = [];
+  for (var i = 0; i < tmp.length; i++) {
+    this.refs_[tmp[i].handle] = tmp[i];
+  }
+}
+
+MirrorRefCache.prototype.lookup = function(handle) {
+  return this.refs_[handle];
+}
+
+function testFunctionMirror(f) {
+  // Create mirror and JSON representation.
+  var mirror = debug.MakeMirror(f);
+  var serializer = debug.MakeMirrorSerializer();
+  var json = serializer.serializeValue(mirror);
+  var refs = new MirrorRefCache(serializer.serializeReferencedObjects());
+
+  // Check the mirror hierachy.
+  assertTrue(mirror instanceof debug.Mirror);
+  assertTrue(mirror instanceof debug.ValueMirror);
+  assertTrue(mirror instanceof debug.ObjectMirror);
+  assertTrue(mirror instanceof debug.FunctionMirror);
+
+  // Check the mirror properties.
+  assertTrue(mirror.isFunction());
+  assertEquals('function', mirror.type());
+  assertFalse(mirror.isPrimitive());
+  assertEquals("Function", mirror.className());
+  assertEquals(f.name, mirror.name());
+  assertTrue(mirror.resolved());
+  assertEquals(f.toString(), mirror.source());
+  assertTrue(mirror.constructorFunction() instanceof debug.ObjectMirror);
+  assertTrue(mirror.protoObject() instanceof debug.Mirror);
+  assertTrue(mirror.prototypeObject() instanceof debug.Mirror);
+  
+  // Test text representation
+  assertEquals(f.toString(), mirror.toText());
+
+  // Parse JSON representation and check.
+  var fromJSON = eval('(' + json + ')');
+  assertEquals('function', fromJSON.type);
+  assertEquals('Function', fromJSON.className);
+  assertEquals('function', refs.lookup(fromJSON.constructorFunction.ref).type);
+  assertEquals('Function', refs.lookup(fromJSON.constructorFunction.ref).name);
+  assertTrue(fromJSON.resolved);
+  assertEquals(f.name, fromJSON.name);
+  assertEquals(f.toString(), fromJSON.source);
+
+  // Check the formatted text (regress 1142074).
+  assertEquals(f.toString(), fromJSON.text);
+}
+
+
+// Test a number of different functions.
+testFunctionMirror(function(){});
+testFunctionMirror(function a(){return 1;});
+testFunctionMirror(Math.sin);
diff --git a/deps/v8/test/mjsunit/mirror-null.js b/deps/v8/test/mjsunit/mirror-null.js
new file mode 100644
index 0000000..db68966
--- /dev/null
+++ b/deps/v8/test/mjsunit/mirror-null.js
@@ -0,0 +1,50 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Test the mirror object for null
+
+// Create mirror and JSON representation.
+var mirror = debug.MakeMirror(null);
+var serializer = debug.MakeMirrorSerializer();
+var json = serializer.serializeValue(mirror);
+
+// Check the mirror hierachy.
+assertTrue(mirror instanceof debug.Mirror);
+assertTrue(mirror instanceof debug.NullMirror);
+
+// Check the mirror properties.
+assertTrue(mirror.isNull());
+assertEquals('null', mirror.type());
+assertTrue(mirror.isPrimitive());
+
+// Test text representation
+assertEquals('null', mirror.toText());
+
+// Parse JSON representation and check.
+var fromJSON = eval('(' + json + ')');
+assertEquals('null', fromJSON.type);
diff --git a/deps/v8/test/mjsunit/mirror-number.js b/deps/v8/test/mjsunit/mirror-number.js
new file mode 100644
index 0000000..68eb0d7
--- /dev/null
+++ b/deps/v8/test/mjsunit/mirror-number.js
@@ -0,0 +1,77 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Test the mirror object for number values
+
+function testNumberMirror(n) {
+  // Create mirror and JSON representation.
+  var mirror = debug.MakeMirror(n);
+  var serializer = debug.MakeMirrorSerializer();
+  var json = serializer.serializeValue(mirror);
+
+  // Check the mirror hierachy.
+  assertTrue(mirror instanceof debug.Mirror);
+  assertTrue(mirror instanceof debug.ValueMirror);
+  assertTrue(mirror instanceof debug.NumberMirror);
+
+  // Check the mirror properties.
+  assertTrue(mirror.isNumber());
+  assertEquals('number', mirror.type());
+  assertTrue(mirror.isPrimitive());
+
+  // Test text representation
+  assertEquals(String(n), mirror.toText());
+
+  // Parse JSON representation and check.
+  var fromJSON = eval('(' + json + ')');
+  assertEquals('number', fromJSON.type);
+  if (!isNaN(n)) {
+    assertEquals(n, fromJSON.value);
+  } else {
+    // NaN values are encoded as strings.
+    assertTrue(typeof fromJSON.value == 'string');
+    if (n === Infinity) {
+      assertEquals('Infinity', fromJSON.value);
+    } else if (n === -Infinity) {
+      assertEquals('-Infinity', fromJSON.value);
+    } else {
+      assertEquals('NaN', fromJSON.value);
+    }
+  }
+}
+
+
+// Test a number of different numbers.
+testNumberMirror(-7);
+testNumberMirror(-6.5);
+testNumberMirror(0);
+testNumberMirror(42);
+testNumberMirror(100.0002);
+testNumberMirror(Infinity);
+testNumberMirror(-Infinity);
+testNumberMirror(NaN);
diff --git a/deps/v8/test/mjsunit/mirror-object.js b/deps/v8/test/mjsunit/mirror-object.js
new file mode 100644
index 0000000..e829a0e
--- /dev/null
+++ b/deps/v8/test/mjsunit/mirror-object.js
@@ -0,0 +1,227 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Test the mirror object for objects
+
+function MirrorRefCache(json_refs) {
+  var tmp = eval('(' + json_refs + ')');
+  this.refs_ = [];
+  for (var i = 0; i < tmp.length; i++) {
+    this.refs_[tmp[i].handle] = tmp[i];
+  }
+}
+
+MirrorRefCache.prototype.lookup = function(handle) {
+  return this.refs_[handle];
+}
+
+function testObjectMirror(obj, cls_name, ctor_name, hasSpecialProperties) {
+  // Create mirror and JSON representation.
+  var mirror = debug.MakeMirror(obj);
+  var serializer = debug.MakeMirrorSerializer();
+  var json = serializer.serializeValue(mirror);
+  var refs = new MirrorRefCache(serializer.serializeReferencedObjects());
+
+  // Check the mirror hierachy.
+  assertTrue(mirror instanceof debug.Mirror, 'Unexpected mirror hierachy');
+  assertTrue(mirror instanceof debug.ValueMirror, 'Unexpected mirror hierachy');
+  assertTrue(mirror instanceof debug.ObjectMirror, 'Unexpected mirror hierachy');
+
+  // Check the mirror properties.
+  assertTrue(mirror.isObject(), 'Unexpected mirror');
+  assertEquals('object', mirror.type(), 'Unexpected mirror type');
+  assertFalse(mirror.isPrimitive(), 'Unexpected primitive mirror');
+  assertEquals(cls_name, mirror.className(), 'Unexpected mirror class name');
+  assertTrue(mirror.constructorFunction() instanceof debug.ObjectMirror, 'Unexpected mirror hierachy');
+  assertEquals(ctor_name, mirror.constructorFunction().name(), 'Unexpected constructor function name');
+  assertTrue(mirror.protoObject() instanceof debug.Mirror, 'Unexpected mirror hierachy');
+  assertTrue(mirror.prototypeObject() instanceof debug.Mirror, 'Unexpected mirror hierachy');
+  assertFalse(mirror.hasNamedInterceptor(), 'No named interceptor expected');
+  assertFalse(mirror.hasIndexedInterceptor(), 'No indexed interceptor expected');
+
+  var names = mirror.propertyNames();
+  var properties = mirror.properties()
+  assertEquals(names.length, properties.length);
+  for (var i = 0; i < properties.length; i++) {
+    assertTrue(properties[i] instanceof debug.Mirror, 'Unexpected mirror hierachy');
+    assertTrue(properties[i] instanceof debug.PropertyMirror, 'Unexpected mirror hierachy');
+    assertEquals('property', properties[i].type(), 'Unexpected mirror type');
+    assertEquals(names[i], properties[i].name(), 'Unexpected property name');
+  }
+  
+  for (var p in obj) {
+    var property_mirror = mirror.property(p);
+    assertTrue(property_mirror instanceof debug.PropertyMirror);
+    assertEquals(p, property_mirror.name());
+    // If the object has some special properties don't test for these.
+    if (!hasSpecialProperties) {
+      assertEquals(0, property_mirror.attributes(), property_mirror.name());
+      assertFalse(property_mirror.isReadOnly());
+      assertTrue(property_mirror.isEnum());
+      assertTrue(property_mirror.canDelete());
+    }
+  }
+
+  // Parse JSON representation and check.
+  var fromJSON = eval('(' + json + ')');
+  assertEquals('object', fromJSON.type, 'Unexpected mirror type in JSON');
+  assertEquals(cls_name, fromJSON.className, 'Unexpected mirror class name in JSON');
+  assertEquals(mirror.constructorFunction().handle(), fromJSON.constructorFunction.ref, 'Unexpected constructor function handle in JSON');
+  assertEquals('function', refs.lookup(fromJSON.constructorFunction.ref).type, 'Unexpected constructor function type in JSON');
+  assertEquals(ctor_name, refs.lookup(fromJSON.constructorFunction.ref).name, 'Unexpected constructor function name in JSON');
+  assertEquals(mirror.protoObject().handle(), fromJSON.protoObject.ref, 'Unexpected proto object handle in JSON');
+  assertEquals(mirror.protoObject().type(), refs.lookup(fromJSON.protoObject.ref).type, 'Unexpected proto object type in JSON');
+  assertEquals(mirror.prototypeObject().handle(), fromJSON.prototypeObject.ref, 'Unexpected prototype object handle in JSON');
+  assertEquals(mirror.prototypeObject().type(), refs.lookup(fromJSON.prototypeObject.ref).type, 'Unexpected prototype object type in JSON');
+  assertEquals(void 0, fromJSON.namedInterceptor, 'No named interceptor expected in JSON');
+  assertEquals(void 0, fromJSON.indexedInterceptor, 'No indexed interceptor expected in JSON');
+
+  // Check that the serialization contains all properties.
+  assertEquals(names.length, fromJSON.properties.length, 'Some properties missing in JSON');
+  for (var i = 0; i < fromJSON.properties.length; i++) {
+    var name = fromJSON.properties[i].name;
+    if (!name) name = fromJSON.properties[i].index;
+    var found = false;
+    for (var j = 0; j < names.length; j++) {
+      if (names[j] == name) {
+        // Check that serialized handle is correct.
+        assertEquals(properties[i].value().handle(), fromJSON.properties[i].ref, 'Unexpected serialized handle');
+
+        // Check that serialized name is correct.
+        assertEquals(properties[i].name(), fromJSON.properties[i].name, 'Unexpected serialized name');
+
+        // If property type is normal property type is not serialized.
+        if (properties[i].propertyType() != debug.PropertyType.Normal) {
+          assertEquals(properties[i].propertyType(), fromJSON.properties[i].propertyType, 'Unexpected serialized property type');
+        } else {
+          assertTrue(typeof(fromJSON.properties[i].propertyType) === 'undefined', 'Unexpected serialized property type');
+        }
+
+        // If there are no attributes attributes are not serialized.
+        if (properties[i].attributes() != debug.PropertyAttribute.None) {
+          assertEquals(properties[i].attributes(), fromJSON.properties[i].attributes, 'Unexpected serialized attributes');
+        } else {
+          assertTrue(typeof(fromJSON.properties[i].attributes) === 'undefined', 'Unexpected serialized attributes');
+        }
+
+        // Lookup the serialized object from the handle reference.        
+        var o = refs.lookup(fromJSON.properties[i].ref);
+        assertTrue(o != void 0, 'Referenced object is not serialized');
+
+        assertEquals(properties[i].value().type(), o.type, 'Unexpected serialized property type for ' + name);
+        if (properties[i].value().isPrimitive()) {
+          // Special check for NaN as NaN == NaN is false.
+          if (properties[i].value().isNumber() && isNaN(properties[i].value().value())) {
+            assertEquals('NaN', o.value, 'Unexpected serialized property value for ' + name);
+          } else {
+            assertEquals(properties[i].value().value(), o.value, 'Unexpected serialized property value for ' + name);
+          }
+        } else if (properties[i].value().isFunction()) {
+          assertEquals(properties[i].value().source(), o.source, 'Unexpected serialized property value for ' + name);
+        }
+        found = true;
+      }
+    }
+    assertTrue(found, '"' + name + '" not found (' + json + ')');
+  }
+}
+
+
+function Point(x,y) {
+  this.x_ = x;
+  this.y_ = y;
+}
+
+
+// Test a number of different objects.
+testObjectMirror({}, 'Object', 'Object');
+testObjectMirror({'a':1,'b':2}, 'Object', 'Object');
+testObjectMirror({'1':void 0,'2':null,'f':function pow(x,y){return Math.pow(x,y);}}, 'Object', 'Object');
+testObjectMirror(new Point(-1.2,2.003), 'Object', 'Point');
+testObjectMirror(this, 'global', '', true);  // Global object has special properties
+testObjectMirror(this.__proto__, 'Object', '');
+testObjectMirror([], 'Array', 'Array');
+testObjectMirror([1,2], 'Array', 'Array');
+
+// Test circular references.
+o = {};
+o.o = o;
+testObjectMirror(o, 'Object', 'Object');
+
+// Test that non enumerable properties are part of the mirror
+global_mirror = debug.MakeMirror(this);
+assertEquals('property', global_mirror.property("Math").type());
+assertFalse(global_mirror.property("Math").isEnum(), "Math is enumerable" + global_mirror.property("Math").attributes());
+
+math_mirror = global_mirror.property("Math").value();
+assertEquals('property', math_mirror.property("E").type());
+assertFalse(math_mirror.property("E").isEnum(), "Math.E is enumerable");
+assertTrue(math_mirror.property("E").isReadOnly());
+assertFalse(math_mirror.property("E").canDelete());
+
+// Test objects with JavaScript accessors.
+o = {}
+o.__defineGetter__('a', function(){return 'a';});
+o.__defineSetter__('b', function(){});
+o.__defineGetter__('c', function(){throw 'c';});
+o.__defineSetter__('c', function(){throw 'c';});
+testObjectMirror(o, 'Object', 'Object');
+mirror = debug.MakeMirror(o);
+// a has getter but no setter.
+assertTrue(mirror.property('a').hasGetter());
+assertFalse(mirror.property('a').hasSetter());
+assertEquals(debug.PropertyType.Callbacks, mirror.property('a').propertyType());
+assertEquals('function', mirror.property('a').getter().type());
+assertEquals('undefined', mirror.property('a').setter().type());
+assertEquals('function (){return \'a\';}', mirror.property('a').getter().source());
+// b has setter but no getter.
+assertFalse(mirror.property('b').hasGetter());
+assertTrue(mirror.property('b').hasSetter());
+assertEquals(debug.PropertyType.Callbacks, mirror.property('b').propertyType());
+assertEquals('undefined', mirror.property('b').getter().type());
+assertEquals('function', mirror.property('b').setter().type());
+assertEquals('function (){}', mirror.property('b').setter().source());
+assertFalse(mirror.property('b').isException());
+// c has both getter and setter. The getter throws an exception.
+assertTrue(mirror.property('c').hasGetter());
+assertTrue(mirror.property('c').hasSetter());
+assertEquals(debug.PropertyType.Callbacks, mirror.property('c').propertyType());
+assertEquals('function', mirror.property('c').getter().type());
+assertEquals('function', mirror.property('c').setter().type());
+assertEquals('function (){throw \'c\';}', mirror.property('c').getter().source());
+assertEquals('function (){throw \'c\';}', mirror.property('c').setter().source());
+
+// Test objects with native accessors.
+mirror = debug.MakeMirror(new String('abc'));
+assertTrue(mirror instanceof debug.ObjectMirror);
+assertFalse(mirror.property('length').hasGetter());
+assertFalse(mirror.property('length').hasSetter());
+assertTrue(mirror.property('length').isNative());
+assertEquals('a', mirror.property(0).value().value());
+assertEquals('b', mirror.property(1).value().value());
+assertEquals('c', mirror.property(2).value().value());
diff --git a/deps/v8/test/mjsunit/mirror-regexp.js b/deps/v8/test/mjsunit/mirror-regexp.js
new file mode 100644
index 0000000..0490b17
--- /dev/null
+++ b/deps/v8/test/mjsunit/mirror-regexp.js
@@ -0,0 +1,109 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Test the mirror object for regular expression values
+
+var all_attributes = debug.PropertyAttribute.ReadOnly |
+                     debug.PropertyAttribute.DontEnum |
+                     debug.PropertyAttribute.DontDelete;
+var expected_attributes = {
+  'source': all_attributes,
+  'global': all_attributes,
+  'ignoreCase': all_attributes,
+  'multiline': all_attributes,
+  'lastIndex': debug.PropertyAttribute.DontEnum | debug.PropertyAttribute.DontDelete
+};
+
+function MirrorRefCache(json_refs) {
+  var tmp = eval('(' + json_refs + ')');
+  this.refs_ = [];
+  for (var i = 0; i < tmp.length; i++) {
+    this.refs_[tmp[i].handle] = tmp[i];
+  }
+}
+
+MirrorRefCache.prototype.lookup = function(handle) {
+  return this.refs_[handle];
+}
+
+function testRegExpMirror(r) {
+  // Create mirror and JSON representation.
+  var mirror = debug.MakeMirror(r);
+  var serializer = debug.MakeMirrorSerializer();
+  var json = serializer.serializeValue(mirror);
+  var refs = new MirrorRefCache(serializer.serializeReferencedObjects());
+
+  // Check the mirror hierachy.
+  assertTrue(mirror instanceof debug.Mirror);
+  assertTrue(mirror instanceof debug.ValueMirror);
+  assertTrue(mirror instanceof debug.ObjectMirror);
+  assertTrue(mirror instanceof debug.RegExpMirror);
+
+  // Check the mirror properties.
+  assertTrue(mirror.isRegExp());
+  assertEquals('regexp', mirror.type());
+  assertFalse(mirror.isPrimitive());
+  for (var p in expected_attributes) {
+    assertEquals(mirror.property(p).attributes(),
+                 expected_attributes[p],
+                 p + ' attributes');
+  }
+
+  // Test text representation
+  assertEquals('/' + r.source + '/', mirror.toText());
+
+  // Parse JSON representation and check.
+  var fromJSON = eval('(' + json + ')');
+  assertEquals('regexp', fromJSON.type);
+  assertEquals('RegExp', fromJSON.className);
+  for (var p in expected_attributes) {
+    for (var i = 0; i < fromJSON.properties.length; i++) {
+      if (fromJSON.properties[i].name == p) {
+        assertEquals(expected_attributes[p],
+                     fromJSON.properties[i].attributes,
+                     'Unexpected value for ' + p + ' attributes');
+        assertEquals(mirror.property(p).propertyType(),
+                     fromJSON.properties[i].propertyType,
+                     'Unexpected value for ' + p + ' propertyType');
+        assertEquals(mirror.property(p).value().handle(),
+                     fromJSON.properties[i].ref,
+                     'Unexpected handle for ' + p);
+        assertEquals(mirror.property(p).value().value(),
+                     refs.lookup(fromJSON.properties[i].ref).value,
+                     'Unexpected value for ' + p);
+      }
+    }
+  }
+}
+
+
+// Test Date values.
+testRegExpMirror(/x/);
+testRegExpMirror(/[abc]/);
+testRegExpMirror(/[\r\n]/g);
+testRegExpMirror(/a*b/gmi);
diff --git a/deps/v8/test/mjsunit/mirror-script.js b/deps/v8/test/mjsunit/mirror-script.js
new file mode 100644
index 0000000..61f0f3a
--- /dev/null
+++ b/deps/v8/test/mjsunit/mirror-script.js
@@ -0,0 +1,92 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Test the mirror object for scripts.
+
+function testScriptMirror(f, file_name, file_lines, script_type, script_source) {
+  // Create mirror and JSON representation.
+  var mirror = debug.MakeMirror(f).script();
+  var serializer = debug.MakeMirrorSerializer();
+  var json = serializer.serializeValue(mirror);
+
+  // Check the mirror hierachy.
+  assertTrue(mirror instanceof debug.Mirror);
+  assertFalse(mirror instanceof debug.ValueMirror);
+  assertTrue(mirror instanceof debug.ScriptMirror);
+
+  // Check the mirror properties.
+  assertTrue(mirror.isScript());
+  assertEquals('script', mirror.type());
+  var name = mirror.name();
+  if (name) {
+    assertEquals(file_name, name.substring(name.length - file_name.length));
+  } else {
+    assertTrue(file_name === null);
+  }
+  assertEquals(0, mirror.lineOffset());
+  assertEquals(0, mirror.columnOffset());
+  if (file_lines > 0) {
+    assertEquals(file_lines, mirror.lineCount());
+  }
+  assertEquals(script_type, mirror.scriptType());
+  if (script_source) {
+    assertEquals(script_source, mirror.source());
+  }
+  
+  // Parse JSON representation and check.
+  var fromJSON = eval('(' + json + ')');
+  assertEquals('script', fromJSON.type);
+  name = fromJSON.name;
+  if (name) {
+    assertEquals(file_name, name.substring(name.length - file_name.length));
+  } else {
+    assertTrue(file_name === null);
+  }
+  assertEquals(0, fromJSON.lineOffset);
+  assertEquals(0, fromJSON.columnOffset);
+  if (file_lines > 0) {
+    assertEquals(file_lines, fromJSON.lineCount);
+  }
+  assertEquals(script_type, fromJSON.scriptType);  
+}
+
+
+// Test the script mirror for different functions.
+testScriptMirror(function(){}, 'mirror-script.js', 92, 2);
+testScriptMirror(Math.sin, 'native math.js', -1, 0);
+testScriptMirror(eval('function(){}'), null, 1, 2, 'function(){}');
+testScriptMirror(eval('function(){\n  }'), null, 2, 2, 'function(){\n  }');
+
+// Test taking slices of source.
+var mirror = debug.MakeMirror(eval('function(){\n  1;\n}')).script();
+assertEquals('function(){\n', mirror.sourceSlice(0, 1).sourceText());
+assertEquals('  1;\n', mirror.sourceSlice(1, 2).sourceText());
+assertEquals('}', mirror.sourceSlice(2, 3).sourceText());
+assertEquals('function(){\n  1;\n', mirror.sourceSlice(0, 2).sourceText());
+assertEquals('  1;\n}', mirror.sourceSlice(1, 3).sourceText());
+assertEquals('function(){\n  1;\n}', mirror.sourceSlice(0, 3).sourceText());
diff --git a/deps/v8/test/mjsunit/mirror-string.js b/deps/v8/test/mjsunit/mirror-string.js
new file mode 100644
index 0000000..eeabc5f
--- /dev/null
+++ b/deps/v8/test/mjsunit/mirror-string.js
@@ -0,0 +1,89 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Test the mirror object for string values
+
+const kMaxProtocolStringLength = 80; // Constant from mirror-delay.js
+
+function testStringMirror(s) {
+  // Create mirror and JSON representation.
+  var mirror = debug.MakeMirror(s);
+  var serializer = debug.MakeMirrorSerializer();
+  var json = serializer.serializeValue(mirror);
+
+  // Check the mirror hierachy.
+  assertTrue(mirror instanceof debug.Mirror);
+  assertTrue(mirror instanceof debug.ValueMirror);
+  assertTrue(mirror instanceof debug.StringMirror);
+
+  // Check the mirror properties.
+  assertTrue(mirror.isString());
+  assertEquals('string', mirror.type());
+  assertTrue(mirror.isPrimitive());
+
+  // Test text representation
+  if (s.length <= kMaxProtocolStringLength) {
+    assertEquals(s, mirror.toText());
+  } else {
+    assertEquals(s.substring(0, kMaxProtocolStringLength),
+                 mirror.toText().substring(0, kMaxProtocolStringLength));
+  }
+
+  // Parse JSON representation and check.
+  var fromJSON = eval('(' + json + ')');
+  assertEquals('string', fromJSON.type);
+  if (s.length <= kMaxProtocolStringLength) {
+    assertEquals(s, fromJSON.value);
+  } else {
+    assertEquals(s.substring(0, kMaxProtocolStringLength),
+                 fromJSON.value.substring(0, kMaxProtocolStringLength));
+    assertEquals(fromJSON.fromIndex, 0);
+    assertEquals(fromJSON.toIndex, kMaxProtocolStringLength);
+  }
+}
+
+// Test a number of different strings.
+testStringMirror('');
+testStringMirror('abcdABCD');
+testStringMirror('1234');
+testStringMirror('"');
+testStringMirror('"""');
+testStringMirror("'");
+testStringMirror("'''");
+testStringMirror("'\"'");
+testStringMirror('\\');
+testStringMirror('\b\t\n\f\r');
+testStringMirror('\u0001\u0002\u001E\u001F');
+testStringMirror('"a":1,"b":2');
+
+var s = "1234567890"
+s = s + s + s + s + s + s + s + s;
+assertEquals(kMaxProtocolStringLength, s.length);
+testStringMirror(s);
+s = s + 'X';
+testStringMirror(s);
diff --git a/deps/v8/test/mjsunit/mirror-undefined.js b/deps/v8/test/mjsunit/mirror-undefined.js
new file mode 100644
index 0000000..2b5b84c
--- /dev/null
+++ b/deps/v8/test/mjsunit/mirror-undefined.js
@@ -0,0 +1,50 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Test the mirror object for undefined
+
+// Create mirror and JSON representation.
+var mirror = debug.MakeMirror(void 0);
+var serializer = debug.MakeMirrorSerializer();
+var json = serializer.serializeValue(mirror);
+
+// Check the mirror hierachy.
+assertTrue(mirror instanceof debug.Mirror);
+assertTrue(mirror instanceof debug.UndefinedMirror);
+
+// Check the mirror properties.
+assertTrue(mirror.isUndefined());
+assertEquals('undefined', mirror.type());
+assertTrue(mirror.isPrimitive());
+
+// Test text representation
+assertEquals('undefined', mirror.toText());
+
+// Parse JSON representation and check.
+var fromJSON = eval('(' + json + ')');
+assertEquals('undefined', fromJSON.type);
\ No newline at end of file
diff --git a/deps/v8/test/mjsunit/mirror-unresolved-function.js b/deps/v8/test/mjsunit/mirror-unresolved-function.js
new file mode 100644
index 0000000..21d0e56
--- /dev/null
+++ b/deps/v8/test/mjsunit/mirror-unresolved-function.js
@@ -0,0 +1,78 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Test the mirror object for unresolved functions.
+
+function MirrorRefCache(json_refs) {
+  var tmp = eval('(' + json_refs + ')');
+  this.refs_ = [];
+  for (var i = 0; i < tmp.length; i++) {
+    this.refs_[tmp[i].handle] = tmp[i];
+  }
+}
+
+MirrorRefCache.prototype.lookup = function(handle) {
+  return this.refs_[handle];
+}
+
+var mirror = new debug.UnresolvedFunctionMirror("f");
+var serializer = debug.MakeMirrorSerializer();
+var json = serializer.serializeValue(mirror);
+var refs = new MirrorRefCache(serializer.serializeReferencedObjects());
+
+// Check the mirror hierachy for unresolved functions.
+assertTrue(mirror instanceof debug.Mirror);
+assertTrue(mirror instanceof debug.ValueMirror);
+assertTrue(mirror instanceof debug.ObjectMirror);
+assertTrue(mirror instanceof debug.FunctionMirror);
+
+// Check the mirror properties for unresolved functions.
+assertTrue(mirror.isUnresolvedFunction());
+assertEquals('function', mirror.type());
+assertFalse(mirror.isPrimitive());
+assertEquals("Function", mirror.className());
+assertEquals("f", mirror.name());
+assertFalse(mirror.resolved());
+assertEquals(void 0, mirror.source());
+assertEquals('undefined', mirror.constructorFunction().type());
+assertEquals('undefined', mirror.protoObject().type());
+assertEquals('undefined', mirror.prototypeObject().type());
+  
+// Parse JSON representation of unresolved functions and check.
+var fromJSON = eval('(' + json + ')');
+assertEquals('function', fromJSON.type, 'Unexpected mirror type in JSON');
+assertEquals('Function', fromJSON.className, 'Unexpected mirror class name in JSON');
+assertEquals(mirror.constructorFunction().handle(), fromJSON.constructorFunction.ref, 'Unexpected constructor function handle in JSON');
+assertEquals('undefined', refs.lookup(fromJSON.constructorFunction.ref).type, 'Unexpected constructor function type in JSON');
+assertEquals(mirror.protoObject().handle(), fromJSON.protoObject.ref, 'Unexpected proto object handle in JSON');
+assertEquals('undefined', refs.lookup(fromJSON.protoObject.ref).type, 'Unexpected proto object type in JSON');
+assertEquals(mirror.prototypeObject().handle(), fromJSON.prototypeObject.ref, 'Unexpected prototype object handle in JSON');
+assertEquals('undefined', refs.lookup(fromJSON.prototypeObject.ref).type, 'Unexpected prototype object type in JSON');
+assertFalse(fromJSON.resolved);
+assertEquals("f", fromJSON.name);
+assertEquals(void 0, fromJSON.source);
diff --git a/deps/v8/test/mjsunit/mjsunit.js b/deps/v8/test/mjsunit/mjsunit.js
new file mode 100644
index 0000000..3570d68
--- /dev/null
+++ b/deps/v8/test/mjsunit/mjsunit.js
@@ -0,0 +1,151 @@
+// Copyright 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.
+
+function MjsUnitAssertionError(message) {
+  this.message = message;
+}
+
+MjsUnitAssertionError.prototype.toString = function () {
+  return this.message;
+}
+
+/*
+ * This file is included in all mini jsunit test cases.  The test
+ * framework expects lines that signal failed tests to start with
+ * the f-word and ignore all other lines.
+ */
+
+function fail(expected, found, name_opt) {
+  var start;
+  if (name_opt) {
+    // Fix this when we ditch the old test runner.
+    start = "Fail" + "ure (" + name_opt + "): ";
+  } else {
+    start = "Fail" + "ure:";
+  }
+  throw new MjsUnitAssertionError(start + " expected <" + expected + "> found <" + found + ">");
+}
+
+
+function deepEquals(a, b) {
+  if (a == b) return true;
+  if ((typeof a) !== 'object' || (typeof b) !== 'object' ||
+      (a === null) || (b === null))
+    return false;
+  if (a.constructor === Array) {
+    if (b.constructor !== Array)
+      return false;
+    if (a.length != b.length)
+      return false;
+    for (var i = 0; i < a.length; i++) {
+      if (i in a) {
+        if (!(i in b) || !(deepEquals(a[i], b[i])))
+          return false;
+      } else if (i in b) {
+        return false;
+      }
+    }
+    return true;
+  }
+  return false;
+}
+
+
+function assertEquals(expected, found, name_opt) {
+  if (!deepEquals(found, expected)) {
+    fail(expected, found, name_opt);
+  }
+}
+
+
+function assertArrayEquals(expected, found, name_opt) {
+  var start = "";
+  if (name_opt) {
+    start = name_opt + " - ";
+  }
+  assertEquals(expected.length, found.length, start + "array length");
+  if (expected.length == found.length) {
+    for (var i = 0; i < expected.length; ++i) {
+      assertEquals(expected[i], found[i], start + "array element at index " + i);
+    }
+  }
+}
+
+
+function assertTrue(value, name_opt) {
+  assertEquals(true, value, name_opt);
+}
+
+
+function assertFalse(value, name_opt) {
+  assertEquals(false, value, name_opt);
+}
+
+
+function assertNaN(value, name_opt) {
+  if (!isNaN(value)) {
+    fail("NaN", value, name_opt);
+  }
+}
+
+
+function assertThrows(code) {
+  var threwException = true;
+  try {
+    eval(code);
+    threwException = false;
+  } catch (e) {
+    // Do nothing.
+  }
+  if (!threwException) assertTrue(false, "did not throw exception");
+}
+
+
+function assertInstanceof(obj, type) {
+  if (!(obj instanceof type)) {
+    assertTrue(false, "Object <" + obj + "> is not an instance of <" + type + ">");
+  }
+}
+
+
+function assertDoesNotThrow(code) {
+  try {
+    eval(code);
+  } catch (e) {
+    assertTrue(false, "threw an exception");
+  }
+}
+
+
+function assertUnreachable(name_opt) {
+  // Fix this when we ditch the old test runner.
+  var message = "Fail" + "ure: unreachable"
+  if (name_opt) {
+    message += " - " + name_opt;
+  }
+  throw new MjsUnitAssertionError(message);
+}
diff --git a/deps/v8/test/mjsunit/mjsunit.status b/deps/v8/test/mjsunit/mjsunit.status
new file mode 100644
index 0000000..5a76078
--- /dev/null
+++ b/deps/v8/test/mjsunit/mjsunit.status
@@ -0,0 +1,68 @@
+# Copyright 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.
+
+prefix mjsunit
+
+# All tests in the bug directory are expected to fail.
+bugs: FAIL
+
+# This one uses a built-in that's only present in debug mode. It takes
+# too long to run in debug mode on ARM.
+fuzz-natives: PASS, SKIP if ($mode == release || $arch == arm)
+
+big-object-literal: PASS, SKIP if ($arch == arm)
+
+[ $arch == arm ]
+
+# Slow tests which times out in debug mode.
+try: PASS, SKIP if $mode == debug
+debug-scripts-request: PASS, SKIP if $mode == debug
+
+# Flaky test that can hit compilation-time stack overflow in debug mode.
+unicode-test: PASS, (PASS || FAIL) if $mode == debug
+
+# Bug number 1020483: Debug tests fail on ARM.
+debug-constructor: CRASH, FAIL
+debug-continue: SKIP
+debug-evaluate-recursive: CRASH, FAIL if $mode == debug
+debug-changebreakpoint: CRASH, FAIL if $mode == debug
+debug-clearbreakpoint: CRASH, FAIL if $mode == debug
+debug-conditional-breakpoints: CRASH, FAIL if $mode == debug
+debug-evaluate: CRASH, FAIL if $mode == debug
+debug-ignore-breakpoints: CRASH, FAIL if $mode == debug
+debug-multiple-breakpoints: CRASH, FAIL if $mode == debug
+debug-setbreakpoint: CRASH, FAIL if $mode == debug
+debug-step-stub-callfunction: SKIP
+debug-stepin-constructor: CRASH, FAIL
+debug-step: SKIP
+debug-breakpoints: PASS || FAIL
+debug-handle: CRASH, FAIL if $mode == debug
+regress/regress-269: SKIP
+
+# Bug number 130 http://code.google.com/p/v8/issues/detail?id=130
+# Fails on real ARM hardware but not on the simulator.
+string-compare-alignment: PASS || FAIL
diff --git a/deps/v8/test/mjsunit/mul-exhaustive.js b/deps/v8/test/mjsunit/mul-exhaustive.js
new file mode 100644
index 0000000..452f933
--- /dev/null
+++ b/deps/v8/test/mjsunit/mul-exhaustive.js
@@ -0,0 +1,4511 @@
+// Copyright 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.
+
+var x;
+var y;
+var a;
+
+function f(a, y) {
+  assertEquals(a, x * y);
+  assertEquals(a, -x * -y);
+  assertEquals(-a, -x * y);
+  assertEquals(-a, x * -y);
+  assertEquals(a, y * x);
+  assertEquals(a, -y * -x);
+  assertEquals(-a, y * -x);
+  assertEquals(-a, -y * x);
+}
+
+x = 1;
+f(1, 1);
+x = 2;
+f(2, 1);
+f(4, 2);
+x = 3;
+f(3, 1);
+f(6, 2);
+f(9, 3);
+x = 4;
+f(4, 1);
+f(8, 2);
+f(12, 3);
+f(16, 4);
+x = 5;
+f(5, 1);
+f(10, 2);
+f(15, 3);
+f(20, 4);
+f(25, 5);
+x = 7;
+f(7, 1);
+f(14, 2);
+f(21, 3);
+f(28, 4);
+f(35, 5);
+f(49, 7);
+x = 8;
+f(8, 1);
+f(16, 2);
+f(24, 3);
+f(32, 4);
+f(40, 5);
+f(56, 7);
+f(64, 8);
+x = 9;
+f(9, 1);
+f(18, 2);
+f(27, 3);
+f(36, 4);
+f(45, 5);
+f(63, 7);
+f(72, 8);
+f(81, 9);
+x = 15;
+f(15, 1);
+f(30, 2);
+f(45, 3);
+f(60, 4);
+f(75, 5);
+f(105, 7);
+f(120, 8);
+f(135, 9);
+f(225, 15);
+x = 16;
+f(16, 1);
+f(32, 2);
+f(48, 3);
+f(64, 4);
+f(80, 5);
+f(112, 7);
+f(128, 8);
+f(144, 9);
+f(240, 15);
+f(256, 16);
+x = 17;
+f(17, 1);
+f(34, 2);
+f(51, 3);
+f(68, 4);
+f(85, 5);
+f(119, 7);
+f(136, 8);
+f(153, 9);
+f(255, 15);
+f(272, 16);
+f(289, 17);
+x = 31;
+f(31, 1);
+f(62, 2);
+f(93, 3);
+f(124, 4);
+f(155, 5);
+f(217, 7);
+f(248, 8);
+f(279, 9);
+f(465, 15);
+f(496, 16);
+f(527, 17);
+f(961, 31);
+x = 32;
+f(32, 1);
+f(64, 2);
+f(96, 3);
+f(128, 4);
+f(160, 5);
+f(224, 7);
+f(256, 8);
+f(288, 9);
+f(480, 15);
+f(512, 16);
+f(544, 17);
+f(992, 31);
+f(1024, 32);
+x = 33;
+f(33, 1);
+f(66, 2);
+f(99, 3);
+f(132, 4);
+f(165, 5);
+f(231, 7);
+f(264, 8);
+f(297, 9);
+f(495, 15);
+f(528, 16);
+f(561, 17);
+f(1023, 31);
+f(1056, 32);
+f(1089, 33);
+x = 63;
+f(63, 1);
+f(126, 2);
+f(189, 3);
+f(252, 4);
+f(315, 5);
+f(441, 7);
+f(504, 8);
+f(567, 9);
+f(945, 15);
+f(1008, 16);
+f(1071, 17);
+f(1953, 31);
+f(2016, 32);
+f(2079, 33);
+f(3969, 63);
+x = 64;
+f(64, 1);
+f(128, 2);
+f(192, 3);
+f(256, 4);
+f(320, 5);
+f(448, 7);
+f(512, 8);
+f(576, 9);
+f(960, 15);
+f(1024, 16);
+f(1088, 17);
+f(1984, 31);
+f(2048, 32);
+f(2112, 33);
+f(4032, 63);
+f(4096, 64);
+x = 65;
+f(65, 1);
+f(130, 2);
+f(195, 3);
+f(260, 4);
+f(325, 5);
+f(455, 7);
+f(520, 8);
+f(585, 9);
+f(975, 15);
+f(1040, 16);
+f(1105, 17);
+f(2015, 31);
+f(2080, 32);
+f(2145, 33);
+f(4095, 63);
+f(4160, 64);
+f(4225, 65);
+x = 127;
+f(127, 1);
+f(254, 2);
+f(381, 3);
+f(508, 4);
+f(635, 5);
+f(889, 7);
+f(1016, 8);
+f(1143, 9);
+f(1905, 15);
+f(2032, 16);
+f(2159, 17);
+f(3937, 31);
+f(4064, 32);
+f(4191, 33);
+f(8001, 63);
+f(8128, 64);
+f(8255, 65);
+f(16129, 127);
+x = 128;
+f(128, 1);
+f(256, 2);
+f(384, 3);
+f(512, 4);
+f(640, 5);
+f(896, 7);
+f(1024, 8);
+f(1152, 9);
+f(1920, 15);
+f(2048, 16);
+f(2176, 17);
+f(3968, 31);
+f(4096, 32);
+f(4224, 33);
+f(8064, 63);
+f(8192, 64);
+f(8320, 65);
+f(16256, 127);
+f(16384, 128);
+x = 129;
+f(129, 1);
+f(258, 2);
+f(387, 3);
+f(516, 4);
+f(645, 5);
+f(903, 7);
+f(1032, 8);
+f(1161, 9);
+f(1935, 15);
+f(2064, 16);
+f(2193, 17);
+f(3999, 31);
+f(4128, 32);
+f(4257, 33);
+f(8127, 63);
+f(8256, 64);
+f(8385, 65);
+f(16383, 127);
+f(16512, 128);
+f(16641, 129);
+x = 255;
+f(255, 1);
+f(510, 2);
+f(765, 3);
+f(1020, 4);
+f(1275, 5);
+f(1785, 7);
+f(2040, 8);
+f(2295, 9);
+f(3825, 15);
+f(4080, 16);
+f(4335, 17);
+f(7905, 31);
+f(8160, 32);
+f(8415, 33);
+f(16065, 63);
+f(16320, 64);
+f(16575, 65);
+f(32385, 127);
+f(32640, 128);
+f(32895, 129);
+f(65025, 255);
+x = 256;
+f(256, 1);
+f(512, 2);
+f(768, 3);
+f(1024, 4);
+f(1280, 5);
+f(1792, 7);
+f(2048, 8);
+f(2304, 9);
+f(3840, 15);
+f(4096, 16);
+f(4352, 17);
+f(7936, 31);
+f(8192, 32);
+f(8448, 33);
+f(16128, 63);
+f(16384, 64);
+f(16640, 65);
+f(32512, 127);
+f(32768, 128);
+f(33024, 129);
+f(65280, 255);
+f(65536, 256);
+x = 257;
+f(257, 1);
+f(514, 2);
+f(771, 3);
+f(1028, 4);
+f(1285, 5);
+f(1799, 7);
+f(2056, 8);
+f(2313, 9);
+f(3855, 15);
+f(4112, 16);
+f(4369, 17);
+f(7967, 31);
+f(8224, 32);
+f(8481, 33);
+f(16191, 63);
+f(16448, 64);
+f(16705, 65);
+f(32639, 127);
+f(32896, 128);
+f(33153, 129);
+f(65535, 255);
+f(65792, 256);
+f(66049, 257);
+x = 511;
+f(511, 1);
+f(1022, 2);
+f(1533, 3);
+f(2044, 4);
+f(2555, 5);
+f(3577, 7);
+f(4088, 8);
+f(4599, 9);
+f(7665, 15);
+f(8176, 16);
+f(8687, 17);
+f(15841, 31);
+f(16352, 32);
+f(16863, 33);
+f(32193, 63);
+f(32704, 64);
+f(33215, 65);
+f(64897, 127);
+f(65408, 128);
+f(65919, 129);
+f(130305, 255);
+f(130816, 256);
+f(131327, 257);
+f(261121, 511);
+x = 512;
+f(512, 1);
+f(1024, 2);
+f(1536, 3);
+f(2048, 4);
+f(2560, 5);
+f(3584, 7);
+f(4096, 8);
+f(4608, 9);
+f(7680, 15);
+f(8192, 16);
+f(8704, 17);
+f(15872, 31);
+f(16384, 32);
+f(16896, 33);
+f(32256, 63);
+f(32768, 64);
+f(33280, 65);
+f(65024, 127);
+f(65536, 128);
+f(66048, 129);
+f(130560, 255);
+f(131072, 256);
+f(131584, 257);
+f(261632, 511);
+f(262144, 512);
+x = 513;
+f(513, 1);
+f(1026, 2);
+f(1539, 3);
+f(2052, 4);
+f(2565, 5);
+f(3591, 7);
+f(4104, 8);
+f(4617, 9);
+f(7695, 15);
+f(8208, 16);
+f(8721, 17);
+f(15903, 31);
+f(16416, 32);
+f(16929, 33);
+f(32319, 63);
+f(32832, 64);
+f(33345, 65);
+f(65151, 127);
+f(65664, 128);
+f(66177, 129);
+f(130815, 255);
+f(131328, 256);
+f(131841, 257);
+f(262143, 511);
+f(262656, 512);
+f(263169, 513);
+x = 1023;
+f(1023, 1);
+f(2046, 2);
+f(3069, 3);
+f(4092, 4);
+f(5115, 5);
+f(7161, 7);
+f(8184, 8);
+f(9207, 9);
+f(15345, 15);
+f(16368, 16);
+f(17391, 17);
+f(31713, 31);
+f(32736, 32);
+f(33759, 33);
+f(64449, 63);
+f(65472, 64);
+f(66495, 65);
+f(129921, 127);
+f(130944, 128);
+f(131967, 129);
+f(260865, 255);
+f(261888, 256);
+f(262911, 257);
+f(522753, 511);
+f(523776, 512);
+f(524799, 513);
+f(1046529, 1023);
+x = 1024;
+f(1024, 1);
+f(2048, 2);
+f(3072, 3);
+f(4096, 4);
+f(5120, 5);
+f(7168, 7);
+f(8192, 8);
+f(9216, 9);
+f(15360, 15);
+f(16384, 16);
+f(17408, 17);
+f(31744, 31);
+f(32768, 32);
+f(33792, 33);
+f(64512, 63);
+f(65536, 64);
+f(66560, 65);
+f(130048, 127);
+f(131072, 128);
+f(132096, 129);
+f(261120, 255);
+f(262144, 256);
+f(263168, 257);
+f(523264, 511);
+f(524288, 512);
+f(525312, 513);
+f(1047552, 1023);
+f(1048576, 1024);
+x = 1025;
+f(1025, 1);
+f(2050, 2);
+f(3075, 3);
+f(4100, 4);
+f(5125, 5);
+f(7175, 7);
+f(8200, 8);
+f(9225, 9);
+f(15375, 15);
+f(16400, 16);
+f(17425, 17);
+f(31775, 31);
+f(32800, 32);
+f(33825, 33);
+f(64575, 63);
+f(65600, 64);
+f(66625, 65);
+f(130175, 127);
+f(131200, 128);
+f(132225, 129);
+f(261375, 255);
+f(262400, 256);
+f(263425, 257);
+f(523775, 511);
+f(524800, 512);
+f(525825, 513);
+f(1048575, 1023);
+f(1049600, 1024);
+f(1050625, 1025);
+x = 2047;
+f(2047, 1);
+f(4094, 2);
+f(6141, 3);
+f(8188, 4);
+f(10235, 5);
+f(14329, 7);
+f(16376, 8);
+f(18423, 9);
+f(30705, 15);
+f(32752, 16);
+f(34799, 17);
+f(63457, 31);
+f(65504, 32);
+f(67551, 33);
+f(128961, 63);
+f(131008, 64);
+f(133055, 65);
+f(259969, 127);
+f(262016, 128);
+f(264063, 129);
+f(521985, 255);
+f(524032, 256);
+f(526079, 257);
+f(1046017, 511);
+f(1048064, 512);
+f(1050111, 513);
+f(2094081, 1023);
+f(2096128, 1024);
+f(2098175, 1025);
+f(4190209, 2047);
+x = 2048;
+f(2048, 1);
+f(4096, 2);
+f(6144, 3);
+f(8192, 4);
+f(10240, 5);
+f(14336, 7);
+f(16384, 8);
+f(18432, 9);
+f(30720, 15);
+f(32768, 16);
+f(34816, 17);
+f(63488, 31);
+f(65536, 32);
+f(67584, 33);
+f(129024, 63);
+f(131072, 64);
+f(133120, 65);
+f(260096, 127);
+f(262144, 128);
+f(264192, 129);
+f(522240, 255);
+f(524288, 256);
+f(526336, 257);
+f(1046528, 511);
+f(1048576, 512);
+f(1050624, 513);
+f(2095104, 1023);
+f(2097152, 1024);
+f(2099200, 1025);
+f(4192256, 2047);
+f(4194304, 2048);
+x = 2049;
+f(2049, 1);
+f(4098, 2);
+f(6147, 3);
+f(8196, 4);
+f(10245, 5);
+f(14343, 7);
+f(16392, 8);
+f(18441, 9);
+f(30735, 15);
+f(32784, 16);
+f(34833, 17);
+f(63519, 31);
+f(65568, 32);
+f(67617, 33);
+f(129087, 63);
+f(131136, 64);
+f(133185, 65);
+f(260223, 127);
+f(262272, 128);
+f(264321, 129);
+f(522495, 255);
+f(524544, 256);
+f(526593, 257);
+f(1047039, 511);
+f(1049088, 512);
+f(1051137, 513);
+f(2096127, 1023);
+f(2098176, 1024);
+f(2100225, 1025);
+f(4194303, 2047);
+f(4196352, 2048);
+f(4198401, 2049);
+x = 4095;
+f(4095, 1);
+f(8190, 2);
+f(12285, 3);
+f(16380, 4);
+f(20475, 5);
+f(28665, 7);
+f(32760, 8);
+f(36855, 9);
+f(61425, 15);
+f(65520, 16);
+f(69615, 17);
+f(126945, 31);
+f(131040, 32);
+f(135135, 33);
+f(257985, 63);
+f(262080, 64);
+f(266175, 65);
+f(520065, 127);
+f(524160, 128);
+f(528255, 129);
+f(1044225, 255);
+f(1048320, 256);
+f(1052415, 257);
+f(2092545, 511);
+f(2096640, 512);
+f(2100735, 513);
+f(4189185, 1023);
+f(4193280, 1024);
+f(4197375, 1025);
+f(8382465, 2047);
+f(8386560, 2048);
+f(8390655, 2049);
+f(16769025, 4095);
+x = 4096;
+f(4096, 1);
+f(8192, 2);
+f(12288, 3);
+f(16384, 4);
+f(20480, 5);
+f(28672, 7);
+f(32768, 8);
+f(36864, 9);
+f(61440, 15);
+f(65536, 16);
+f(69632, 17);
+f(126976, 31);
+f(131072, 32);
+f(135168, 33);
+f(258048, 63);
+f(262144, 64);
+f(266240, 65);
+f(520192, 127);
+f(524288, 128);
+f(528384, 129);
+f(1044480, 255);
+f(1048576, 256);
+f(1052672, 257);
+f(2093056, 511);
+f(2097152, 512);
+f(2101248, 513);
+f(4190208, 1023);
+f(4194304, 1024);
+f(4198400, 1025);
+f(8384512, 2047);
+f(8388608, 2048);
+f(8392704, 2049);
+f(16773120, 4095);
+f(16777216, 4096);
+x = 4097;
+f(4097, 1);
+f(8194, 2);
+f(12291, 3);
+f(16388, 4);
+f(20485, 5);
+f(28679, 7);
+f(32776, 8);
+f(36873, 9);
+f(61455, 15);
+f(65552, 16);
+f(69649, 17);
+f(127007, 31);
+f(131104, 32);
+f(135201, 33);
+f(258111, 63);
+f(262208, 64);
+f(266305, 65);
+f(520319, 127);
+f(524416, 128);
+f(528513, 129);
+f(1044735, 255);
+f(1048832, 256);
+f(1052929, 257);
+f(2093567, 511);
+f(2097664, 512);
+f(2101761, 513);
+f(4191231, 1023);
+f(4195328, 1024);
+f(4199425, 1025);
+f(8386559, 2047);
+f(8390656, 2048);
+f(8394753, 2049);
+f(16777215, 4095);
+f(16781312, 4096);
+f(16785409, 4097);
+x = 8191;
+f(8191, 1);
+f(16382, 2);
+f(24573, 3);
+f(32764, 4);
+f(40955, 5);
+f(57337, 7);
+f(65528, 8);
+f(73719, 9);
+f(122865, 15);
+f(131056, 16);
+f(139247, 17);
+f(253921, 31);
+f(262112, 32);
+f(270303, 33);
+f(516033, 63);
+f(524224, 64);
+f(532415, 65);
+f(1040257, 127);
+f(1048448, 128);
+f(1056639, 129);
+f(2088705, 255);
+f(2096896, 256);
+f(2105087, 257);
+f(4185601, 511);
+f(4193792, 512);
+f(4201983, 513);
+f(8379393, 1023);
+f(8387584, 1024);
+f(8395775, 1025);
+f(16766977, 2047);
+f(16775168, 2048);
+f(16783359, 2049);
+f(33542145, 4095);
+f(33550336, 4096);
+f(33558527, 4097);
+f(67092481, 8191);
+x = 8192;
+f(8192, 1);
+f(16384, 2);
+f(24576, 3);
+f(32768, 4);
+f(40960, 5);
+f(57344, 7);
+f(65536, 8);
+f(73728, 9);
+f(122880, 15);
+f(131072, 16);
+f(139264, 17);
+f(253952, 31);
+f(262144, 32);
+f(270336, 33);
+f(516096, 63);
+f(524288, 64);
+f(532480, 65);
+f(1040384, 127);
+f(1048576, 128);
+f(1056768, 129);
+f(2088960, 255);
+f(2097152, 256);
+f(2105344, 257);
+f(4186112, 511);
+f(4194304, 512);
+f(4202496, 513);
+f(8380416, 1023);
+f(8388608, 1024);
+f(8396800, 1025);
+f(16769024, 2047);
+f(16777216, 2048);
+f(16785408, 2049);
+f(33546240, 4095);
+f(33554432, 4096);
+f(33562624, 4097);
+f(67100672, 8191);
+f(67108864, 8192);
+x = 8193;
+f(8193, 1);
+f(16386, 2);
+f(24579, 3);
+f(32772, 4);
+f(40965, 5);
+f(57351, 7);
+f(65544, 8);
+f(73737, 9);
+f(122895, 15);
+f(131088, 16);
+f(139281, 17);
+f(253983, 31);
+f(262176, 32);
+f(270369, 33);
+f(516159, 63);
+f(524352, 64);
+f(532545, 65);
+f(1040511, 127);
+f(1048704, 128);
+f(1056897, 129);
+f(2089215, 255);
+f(2097408, 256);
+f(2105601, 257);
+f(4186623, 511);
+f(4194816, 512);
+f(4203009, 513);
+f(8381439, 1023);
+f(8389632, 1024);
+f(8397825, 1025);
+f(16771071, 2047);
+f(16779264, 2048);
+f(16787457, 2049);
+f(33550335, 4095);
+f(33558528, 4096);
+f(33566721, 4097);
+f(67108863, 8191);
+f(67117056, 8192);
+f(67125249, 8193);
+x = 16383;
+f(16383, 1);
+f(32766, 2);
+f(49149, 3);
+f(65532, 4);
+f(81915, 5);
+f(114681, 7);
+f(131064, 8);
+f(147447, 9);
+f(245745, 15);
+f(262128, 16);
+f(278511, 17);
+f(507873, 31);
+f(524256, 32);
+f(540639, 33);
+f(1032129, 63);
+f(1048512, 64);
+f(1064895, 65);
+f(2080641, 127);
+f(2097024, 128);
+f(2113407, 129);
+f(4177665, 255);
+f(4194048, 256);
+f(4210431, 257);
+f(8371713, 511);
+f(8388096, 512);
+f(8404479, 513);
+f(16759809, 1023);
+f(16776192, 1024);
+f(16792575, 1025);
+f(33536001, 2047);
+f(33552384, 2048);
+f(33568767, 2049);
+f(67088385, 4095);
+f(67104768, 4096);
+f(67121151, 4097);
+f(134193153, 8191);
+f(134209536, 8192);
+f(134225919, 8193);
+f(268402689, 16383);
+x = 16384;
+f(16384, 1);
+f(32768, 2);
+f(49152, 3);
+f(65536, 4);
+f(81920, 5);
+f(114688, 7);
+f(131072, 8);
+f(147456, 9);
+f(245760, 15);
+f(262144, 16);
+f(278528, 17);
+f(507904, 31);
+f(524288, 32);
+f(540672, 33);
+f(1032192, 63);
+f(1048576, 64);
+f(1064960, 65);
+f(2080768, 127);
+f(2097152, 128);
+f(2113536, 129);
+f(4177920, 255);
+f(4194304, 256);
+f(4210688, 257);
+f(8372224, 511);
+f(8388608, 512);
+f(8404992, 513);
+f(16760832, 1023);
+f(16777216, 1024);
+f(16793600, 1025);
+f(33538048, 2047);
+f(33554432, 2048);
+f(33570816, 2049);
+f(67092480, 4095);
+f(67108864, 4096);
+f(67125248, 4097);
+f(134201344, 8191);
+f(134217728, 8192);
+f(134234112, 8193);
+f(268419072, 16383);
+f(268435456, 16384);
+x = 16385;
+f(16385, 1);
+f(32770, 2);
+f(49155, 3);
+f(65540, 4);
+f(81925, 5);
+f(114695, 7);
+f(131080, 8);
+f(147465, 9);
+f(245775, 15);
+f(262160, 16);
+f(278545, 17);
+f(507935, 31);
+f(524320, 32);
+f(540705, 33);
+f(1032255, 63);
+f(1048640, 64);
+f(1065025, 65);
+f(2080895, 127);
+f(2097280, 128);
+f(2113665, 129);
+f(4178175, 255);
+f(4194560, 256);
+f(4210945, 257);
+f(8372735, 511);
+f(8389120, 512);
+f(8405505, 513);
+f(16761855, 1023);
+f(16778240, 1024);
+f(16794625, 1025);
+f(33540095, 2047);
+f(33556480, 2048);
+f(33572865, 2049);
+f(67096575, 4095);
+f(67112960, 4096);
+f(67129345, 4097);
+f(134209535, 8191);
+f(134225920, 8192);
+f(134242305, 8193);
+f(268435455, 16383);
+f(268451840, 16384);
+f(268468225, 16385);
+x = 32767;
+f(32767, 1);
+f(65534, 2);
+f(98301, 3);
+f(131068, 4);
+f(163835, 5);
+f(229369, 7);
+f(262136, 8);
+f(294903, 9);
+f(491505, 15);
+f(524272, 16);
+f(557039, 17);
+f(1015777, 31);
+f(1048544, 32);
+f(1081311, 33);
+f(2064321, 63);
+f(2097088, 64);
+f(2129855, 65);
+f(4161409, 127);
+f(4194176, 128);
+f(4226943, 129);
+f(8355585, 255);
+f(8388352, 256);
+f(8421119, 257);
+f(16743937, 511);
+f(16776704, 512);
+f(16809471, 513);
+f(33520641, 1023);
+f(33553408, 1024);
+f(33586175, 1025);
+f(67074049, 2047);
+f(67106816, 2048);
+f(67139583, 2049);
+f(134180865, 4095);
+f(134213632, 4096);
+f(134246399, 4097);
+f(268394497, 8191);
+f(268427264, 8192);
+f(268460031, 8193);
+f(536821761, 16383);
+f(536854528, 16384);
+f(536887295, 16385);
+f(1073676289, 32767);
+x = 32768;
+f(32768, 1);
+f(65536, 2);
+f(98304, 3);
+f(131072, 4);
+f(163840, 5);
+f(229376, 7);
+f(262144, 8);
+f(294912, 9);
+f(491520, 15);
+f(524288, 16);
+f(557056, 17);
+f(1015808, 31);
+f(1048576, 32);
+f(1081344, 33);
+f(2064384, 63);
+f(2097152, 64);
+f(2129920, 65);
+f(4161536, 127);
+f(4194304, 128);
+f(4227072, 129);
+f(8355840, 255);
+f(8388608, 256);
+f(8421376, 257);
+f(16744448, 511);
+f(16777216, 512);
+f(16809984, 513);
+f(33521664, 1023);
+f(33554432, 1024);
+f(33587200, 1025);
+f(67076096, 2047);
+f(67108864, 2048);
+f(67141632, 2049);
+f(134184960, 4095);
+f(134217728, 4096);
+f(134250496, 4097);
+f(268402688, 8191);
+f(268435456, 8192);
+f(268468224, 8193);
+f(536838144, 16383);
+f(536870912, 16384);
+f(536903680, 16385);
+f(1073709056, 32767);
+f(1073741824, 32768);
+x = 32769;
+f(32769, 1);
+f(65538, 2);
+f(98307, 3);
+f(131076, 4);
+f(163845, 5);
+f(229383, 7);
+f(262152, 8);
+f(294921, 9);
+f(491535, 15);
+f(524304, 16);
+f(557073, 17);
+f(1015839, 31);
+f(1048608, 32);
+f(1081377, 33);
+f(2064447, 63);
+f(2097216, 64);
+f(2129985, 65);
+f(4161663, 127);
+f(4194432, 128);
+f(4227201, 129);
+f(8356095, 255);
+f(8388864, 256);
+f(8421633, 257);
+f(16744959, 511);
+f(16777728, 512);
+f(16810497, 513);
+f(33522687, 1023);
+f(33555456, 1024);
+f(33588225, 1025);
+f(67078143, 2047);
+f(67110912, 2048);
+f(67143681, 2049);
+f(134189055, 4095);
+f(134221824, 4096);
+f(134254593, 4097);
+f(268410879, 8191);
+f(268443648, 8192);
+f(268476417, 8193);
+f(536854527, 16383);
+f(536887296, 16384);
+f(536920065, 16385);
+f(1073741823, 32767);
+f(1073774592, 32768);
+f(1073807361, 32769);
+x = 65535;
+f(65535, 1);
+f(131070, 2);
+f(196605, 3);
+f(262140, 4);
+f(327675, 5);
+f(458745, 7);
+f(524280, 8);
+f(589815, 9);
+f(983025, 15);
+f(1048560, 16);
+f(1114095, 17);
+f(2031585, 31);
+f(2097120, 32);
+f(2162655, 33);
+f(4128705, 63);
+f(4194240, 64);
+f(4259775, 65);
+f(8322945, 127);
+f(8388480, 128);
+f(8454015, 129);
+f(16711425, 255);
+f(16776960, 256);
+f(16842495, 257);
+f(33488385, 511);
+f(33553920, 512);
+f(33619455, 513);
+f(67042305, 1023);
+f(67107840, 1024);
+f(67173375, 1025);
+f(134150145, 2047);
+f(134215680, 2048);
+f(134281215, 2049);
+f(268365825, 4095);
+f(268431360, 4096);
+f(268496895, 4097);
+f(536797185, 8191);
+f(536862720, 8192);
+f(536928255, 8193);
+f(1073659905, 16383);
+f(1073725440, 16384);
+f(1073790975, 16385);
+f(2147385345, 32767);
+f(2147450880, 32768);
+f(2147516415, 32769);
+f(4294836225, 65535);
+x = 65536;
+f(65536, 1);
+f(131072, 2);
+f(196608, 3);
+f(262144, 4);
+f(327680, 5);
+f(458752, 7);
+f(524288, 8);
+f(589824, 9);
+f(983040, 15);
+f(1048576, 16);
+f(1114112, 17);
+f(2031616, 31);
+f(2097152, 32);
+f(2162688, 33);
+f(4128768, 63);
+f(4194304, 64);
+f(4259840, 65);
+f(8323072, 127);
+f(8388608, 128);
+f(8454144, 129);
+f(16711680, 255);
+f(16777216, 256);
+f(16842752, 257);
+f(33488896, 511);
+f(33554432, 512);
+f(33619968, 513);
+f(67043328, 1023);
+f(67108864, 1024);
+f(67174400, 1025);
+f(134152192, 2047);
+f(134217728, 2048);
+f(134283264, 2049);
+f(268369920, 4095);
+f(268435456, 4096);
+f(268500992, 4097);
+f(536805376, 8191);
+f(536870912, 8192);
+f(536936448, 8193);
+f(1073676288, 16383);
+f(1073741824, 16384);
+f(1073807360, 16385);
+f(2147418112, 32767);
+f(2147483648, 32768);
+f(2147549184, 32769);
+f(4294901760, 65535);
+f(4294967296, 65536);
+x = 65537;
+f(65537, 1);
+f(131074, 2);
+f(196611, 3);
+f(262148, 4);
+f(327685, 5);
+f(458759, 7);
+f(524296, 8);
+f(589833, 9);
+f(983055, 15);
+f(1048592, 16);
+f(1114129, 17);
+f(2031647, 31);
+f(2097184, 32);
+f(2162721, 33);
+f(4128831, 63);
+f(4194368, 64);
+f(4259905, 65);
+f(8323199, 127);
+f(8388736, 128);
+f(8454273, 129);
+f(16711935, 255);
+f(16777472, 256);
+f(16843009, 257);
+f(33489407, 511);
+f(33554944, 512);
+f(33620481, 513);
+f(67044351, 1023);
+f(67109888, 1024);
+f(67175425, 1025);
+f(134154239, 2047);
+f(134219776, 2048);
+f(134285313, 2049);
+f(268374015, 4095);
+f(268439552, 4096);
+f(268505089, 4097);
+f(536813567, 8191);
+f(536879104, 8192);
+f(536944641, 8193);
+f(1073692671, 16383);
+f(1073758208, 16384);
+f(1073823745, 16385);
+f(2147450879, 32767);
+f(2147516416, 32768);
+f(2147581953, 32769);
+f(4294967295, 65535);
+f(4295032832, 65536);
+f(4295098369, 65537);
+x = 131071;
+f(131071, 1);
+f(262142, 2);
+f(393213, 3);
+f(524284, 4);
+f(655355, 5);
+f(917497, 7);
+f(1048568, 8);
+f(1179639, 9);
+f(1966065, 15);
+f(2097136, 16);
+f(2228207, 17);
+f(4063201, 31);
+f(4194272, 32);
+f(4325343, 33);
+f(8257473, 63);
+f(8388544, 64);
+f(8519615, 65);
+f(16646017, 127);
+f(16777088, 128);
+f(16908159, 129);
+f(33423105, 255);
+f(33554176, 256);
+f(33685247, 257);
+f(66977281, 511);
+f(67108352, 512);
+f(67239423, 513);
+f(134085633, 1023);
+f(134216704, 1024);
+f(134347775, 1025);
+f(268302337, 2047);
+f(268433408, 2048);
+f(268564479, 2049);
+f(536735745, 4095);
+f(536866816, 4096);
+f(536997887, 4097);
+f(1073602561, 8191);
+f(1073733632, 8192);
+f(1073864703, 8193);
+f(2147336193, 16383);
+f(2147467264, 16384);
+f(2147598335, 16385);
+f(4294803457, 32767);
+f(4294934528, 32768);
+f(4295065599, 32769);
+f(8589737985, 65535);
+f(8589869056, 65536);
+f(8590000127, 65537);
+f(17179607041, 131071);
+x = 131072;
+f(131072, 1);
+f(262144, 2);
+f(393216, 3);
+f(524288, 4);
+f(655360, 5);
+f(917504, 7);
+f(1048576, 8);
+f(1179648, 9);
+f(1966080, 15);
+f(2097152, 16);
+f(2228224, 17);
+f(4063232, 31);
+f(4194304, 32);
+f(4325376, 33);
+f(8257536, 63);
+f(8388608, 64);
+f(8519680, 65);
+f(16646144, 127);
+f(16777216, 128);
+f(16908288, 129);
+f(33423360, 255);
+f(33554432, 256);
+f(33685504, 257);
+f(66977792, 511);
+f(67108864, 512);
+f(67239936, 513);
+f(134086656, 1023);
+f(134217728, 1024);
+f(134348800, 1025);
+f(268304384, 2047);
+f(268435456, 2048);
+f(268566528, 2049);
+f(536739840, 4095);
+f(536870912, 4096);
+f(537001984, 4097);
+f(1073610752, 8191);
+f(1073741824, 8192);
+f(1073872896, 8193);
+f(2147352576, 16383);
+f(2147483648, 16384);
+f(2147614720, 16385);
+f(4294836224, 32767);
+f(4294967296, 32768);
+f(4295098368, 32769);
+f(8589803520, 65535);
+f(8589934592, 65536);
+f(8590065664, 65537);
+f(17179738112, 131071);
+f(17179869184, 131072);
+x = 131073;
+f(131073, 1);
+f(262146, 2);
+f(393219, 3);
+f(524292, 4);
+f(655365, 5);
+f(917511, 7);
+f(1048584, 8);
+f(1179657, 9);
+f(1966095, 15);
+f(2097168, 16);
+f(2228241, 17);
+f(4063263, 31);
+f(4194336, 32);
+f(4325409, 33);
+f(8257599, 63);
+f(8388672, 64);
+f(8519745, 65);
+f(16646271, 127);
+f(16777344, 128);
+f(16908417, 129);
+f(33423615, 255);
+f(33554688, 256);
+f(33685761, 257);
+f(66978303, 511);
+f(67109376, 512);
+f(67240449, 513);
+f(134087679, 1023);
+f(134218752, 1024);
+f(134349825, 1025);
+f(268306431, 2047);
+f(268437504, 2048);
+f(268568577, 2049);
+f(536743935, 4095);
+f(536875008, 4096);
+f(537006081, 4097);
+f(1073618943, 8191);
+f(1073750016, 8192);
+f(1073881089, 8193);
+f(2147368959, 16383);
+f(2147500032, 16384);
+f(2147631105, 16385);
+f(4294868991, 32767);
+f(4295000064, 32768);
+f(4295131137, 32769);
+f(8589869055, 65535);
+f(8590000128, 65536);
+f(8590131201, 65537);
+f(17179869183, 131071);
+f(17180000256, 131072);
+f(17180131329, 131073);
+x = 262143;
+f(262143, 1);
+f(524286, 2);
+f(786429, 3);
+f(1048572, 4);
+f(1310715, 5);
+f(1835001, 7);
+f(2097144, 8);
+f(2359287, 9);
+f(3932145, 15);
+f(4194288, 16);
+f(4456431, 17);
+f(8126433, 31);
+f(8388576, 32);
+f(8650719, 33);
+f(16515009, 63);
+f(16777152, 64);
+f(17039295, 65);
+f(33292161, 127);
+f(33554304, 128);
+f(33816447, 129);
+f(66846465, 255);
+f(67108608, 256);
+f(67370751, 257);
+f(133955073, 511);
+f(134217216, 512);
+f(134479359, 513);
+f(268172289, 1023);
+f(268434432, 1024);
+f(268696575, 1025);
+f(536606721, 2047);
+f(536868864, 2048);
+f(537131007, 2049);
+f(1073475585, 4095);
+f(1073737728, 4096);
+f(1073999871, 4097);
+f(2147213313, 8191);
+f(2147475456, 8192);
+f(2147737599, 8193);
+f(4294688769, 16383);
+f(4294950912, 16384);
+f(4295213055, 16385);
+f(8589639681, 32767);
+f(8589901824, 32768);
+f(8590163967, 32769);
+f(17179541505, 65535);
+f(17179803648, 65536);
+f(17180065791, 65537);
+f(34359345153, 131071);
+f(34359607296, 131072);
+f(34359869439, 131073);
+f(68718952449, 262143);
+x = 262144;
+f(262144, 1);
+f(524288, 2);
+f(786432, 3);
+f(1048576, 4);
+f(1310720, 5);
+f(1835008, 7);
+f(2097152, 8);
+f(2359296, 9);
+f(3932160, 15);
+f(4194304, 16);
+f(4456448, 17);
+f(8126464, 31);
+f(8388608, 32);
+f(8650752, 33);
+f(16515072, 63);
+f(16777216, 64);
+f(17039360, 65);
+f(33292288, 127);
+f(33554432, 128);
+f(33816576, 129);
+f(66846720, 255);
+f(67108864, 256);
+f(67371008, 257);
+f(133955584, 511);
+f(134217728, 512);
+f(134479872, 513);
+f(268173312, 1023);
+f(268435456, 1024);
+f(268697600, 1025);
+f(536608768, 2047);
+f(536870912, 2048);
+f(537133056, 2049);
+f(1073479680, 4095);
+f(1073741824, 4096);
+f(1074003968, 4097);
+f(2147221504, 8191);
+f(2147483648, 8192);
+f(2147745792, 8193);
+f(4294705152, 16383);
+f(4294967296, 16384);
+f(4295229440, 16385);
+f(8589672448, 32767);
+f(8589934592, 32768);
+f(8590196736, 32769);
+f(17179607040, 65535);
+f(17179869184, 65536);
+f(17180131328, 65537);
+f(34359476224, 131071);
+f(34359738368, 131072);
+f(34360000512, 131073);
+f(68719214592, 262143);
+f(68719476736, 262144);
+x = 262145;
+f(262145, 1);
+f(524290, 2);
+f(786435, 3);
+f(1048580, 4);
+f(1310725, 5);
+f(1835015, 7);
+f(2097160, 8);
+f(2359305, 9);
+f(3932175, 15);
+f(4194320, 16);
+f(4456465, 17);
+f(8126495, 31);
+f(8388640, 32);
+f(8650785, 33);
+f(16515135, 63);
+f(16777280, 64);
+f(17039425, 65);
+f(33292415, 127);
+f(33554560, 128);
+f(33816705, 129);
+f(66846975, 255);
+f(67109120, 256);
+f(67371265, 257);
+f(133956095, 511);
+f(134218240, 512);
+f(134480385, 513);
+f(268174335, 1023);
+f(268436480, 1024);
+f(268698625, 1025);
+f(536610815, 2047);
+f(536872960, 2048);
+f(537135105, 2049);
+f(1073483775, 4095);
+f(1073745920, 4096);
+f(1074008065, 4097);
+f(2147229695, 8191);
+f(2147491840, 8192);
+f(2147753985, 8193);
+f(4294721535, 16383);
+f(4294983680, 16384);
+f(4295245825, 16385);
+f(8589705215, 32767);
+f(8589967360, 32768);
+f(8590229505, 32769);
+f(17179672575, 65535);
+f(17179934720, 65536);
+f(17180196865, 65537);
+f(34359607295, 131071);
+f(34359869440, 131072);
+f(34360131585, 131073);
+f(68719476735, 262143);
+f(68719738880, 262144);
+f(68720001025, 262145);
+x = 524287;
+f(524287, 1);
+f(1048574, 2);
+f(1572861, 3);
+f(2097148, 4);
+f(2621435, 5);
+f(3670009, 7);
+f(4194296, 8);
+f(4718583, 9);
+f(7864305, 15);
+f(8388592, 16);
+f(8912879, 17);
+f(16252897, 31);
+f(16777184, 32);
+f(17301471, 33);
+f(33030081, 63);
+f(33554368, 64);
+f(34078655, 65);
+f(66584449, 127);
+f(67108736, 128);
+f(67633023, 129);
+f(133693185, 255);
+f(134217472, 256);
+f(134741759, 257);
+f(267910657, 511);
+f(268434944, 512);
+f(268959231, 513);
+f(536345601, 1023);
+f(536869888, 1024);
+f(537394175, 1025);
+f(1073215489, 2047);
+f(1073739776, 2048);
+f(1074264063, 2049);
+f(2146955265, 4095);
+f(2147479552, 4096);
+f(2148003839, 4097);
+f(4294434817, 8191);
+f(4294959104, 8192);
+f(4295483391, 8193);
+f(8589393921, 16383);
+f(8589918208, 16384);
+f(8590442495, 16385);
+f(17179312129, 32767);
+f(17179836416, 32768);
+f(17180360703, 32769);
+f(34359148545, 65535);
+f(34359672832, 65536);
+f(34360197119, 65537);
+f(68718821377, 131071);
+f(68719345664, 131072);
+f(68719869951, 131073);
+f(137438167041, 262143);
+f(137438691328, 262144);
+f(137439215615, 262145);
+f(274876858369, 524287);
+x = 524288;
+f(524288, 1);
+f(1048576, 2);
+f(1572864, 3);
+f(2097152, 4);
+f(2621440, 5);
+f(3670016, 7);
+f(4194304, 8);
+f(4718592, 9);
+f(7864320, 15);
+f(8388608, 16);
+f(8912896, 17);
+f(16252928, 31);
+f(16777216, 32);
+f(17301504, 33);
+f(33030144, 63);
+f(33554432, 64);
+f(34078720, 65);
+f(66584576, 127);
+f(67108864, 128);
+f(67633152, 129);
+f(133693440, 255);
+f(134217728, 256);
+f(134742016, 257);
+f(267911168, 511);
+f(268435456, 512);
+f(268959744, 513);
+f(536346624, 1023);
+f(536870912, 1024);
+f(537395200, 1025);
+f(1073217536, 2047);
+f(1073741824, 2048);
+f(1074266112, 2049);
+f(2146959360, 4095);
+f(2147483648, 4096);
+f(2148007936, 4097);
+f(4294443008, 8191);
+f(4294967296, 8192);
+f(4295491584, 8193);
+f(8589410304, 16383);
+f(8589934592, 16384);
+f(8590458880, 16385);
+f(17179344896, 32767);
+f(17179869184, 32768);
+f(17180393472, 32769);
+f(34359214080, 65535);
+f(34359738368, 65536);
+f(34360262656, 65537);
+f(68718952448, 131071);
+f(68719476736, 131072);
+f(68720001024, 131073);
+f(137438429184, 262143);
+f(137438953472, 262144);
+f(137439477760, 262145);
+f(274877382656, 524287);
+f(274877906944, 524288);
+x = 524289;
+f(524289, 1);
+f(1048578, 2);
+f(1572867, 3);
+f(2097156, 4);
+f(2621445, 5);
+f(3670023, 7);
+f(4194312, 8);
+f(4718601, 9);
+f(7864335, 15);
+f(8388624, 16);
+f(8912913, 17);
+f(16252959, 31);
+f(16777248, 32);
+f(17301537, 33);
+f(33030207, 63);
+f(33554496, 64);
+f(34078785, 65);
+f(66584703, 127);
+f(67108992, 128);
+f(67633281, 129);
+f(133693695, 255);
+f(134217984, 256);
+f(134742273, 257);
+f(267911679, 511);
+f(268435968, 512);
+f(268960257, 513);
+f(536347647, 1023);
+f(536871936, 1024);
+f(537396225, 1025);
+f(1073219583, 2047);
+f(1073743872, 2048);
+f(1074268161, 2049);
+f(2146963455, 4095);
+f(2147487744, 4096);
+f(2148012033, 4097);
+f(4294451199, 8191);
+f(4294975488, 8192);
+f(4295499777, 8193);
+f(8589426687, 16383);
+f(8589950976, 16384);
+f(8590475265, 16385);
+f(17179377663, 32767);
+f(17179901952, 32768);
+f(17180426241, 32769);
+f(34359279615, 65535);
+f(34359803904, 65536);
+f(34360328193, 65537);
+f(68719083519, 131071);
+f(68719607808, 131072);
+f(68720132097, 131073);
+f(137438691327, 262143);
+f(137439215616, 262144);
+f(137439739905, 262145);
+f(274877906943, 524287);
+f(274878431232, 524288);
+f(274878955521, 524289);
+x = 1048575;
+f(1048575, 1);
+f(2097150, 2);
+f(3145725, 3);
+f(4194300, 4);
+f(5242875, 5);
+f(7340025, 7);
+f(8388600, 8);
+f(9437175, 9);
+f(15728625, 15);
+f(16777200, 16);
+f(17825775, 17);
+f(32505825, 31);
+f(33554400, 32);
+f(34602975, 33);
+f(66060225, 63);
+f(67108800, 64);
+f(68157375, 65);
+f(133169025, 127);
+f(134217600, 128);
+f(135266175, 129);
+f(267386625, 255);
+f(268435200, 256);
+f(269483775, 257);
+f(535821825, 511);
+f(536870400, 512);
+f(537918975, 513);
+f(1072692225, 1023);
+f(1073740800, 1024);
+f(1074789375, 1025);
+f(2146433025, 2047);
+f(2147481600, 2048);
+f(2148530175, 2049);
+f(4293914625, 4095);
+f(4294963200, 4096);
+f(4296011775, 4097);
+f(8588877825, 8191);
+f(8589926400, 8192);
+f(8590974975, 8193);
+f(17178804225, 16383);
+f(17179852800, 16384);
+f(17180901375, 16385);
+f(34358657025, 32767);
+f(34359705600, 32768);
+f(34360754175, 32769);
+f(68718362625, 65535);
+f(68719411200, 65536);
+f(68720459775, 65537);
+f(137437773825, 131071);
+f(137438822400, 131072);
+f(137439870975, 131073);
+f(274876596225, 262143);
+f(274877644800, 262144);
+f(274878693375, 262145);
+f(549754241025, 524287);
+f(549755289600, 524288);
+f(549756338175, 524289);
+f(1099509530625, 1048575);
+x = 1048576;
+f(1048576, 1);
+f(2097152, 2);
+f(3145728, 3);
+f(4194304, 4);
+f(5242880, 5);
+f(7340032, 7);
+f(8388608, 8);
+f(9437184, 9);
+f(15728640, 15);
+f(16777216, 16);
+f(17825792, 17);
+f(32505856, 31);
+f(33554432, 32);
+f(34603008, 33);
+f(66060288, 63);
+f(67108864, 64);
+f(68157440, 65);
+f(133169152, 127);
+f(134217728, 128);
+f(135266304, 129);
+f(267386880, 255);
+f(268435456, 256);
+f(269484032, 257);
+f(535822336, 511);
+f(536870912, 512);
+f(537919488, 513);
+f(1072693248, 1023);
+f(1073741824, 1024);
+f(1074790400, 1025);
+f(2146435072, 2047);
+f(2147483648, 2048);
+f(2148532224, 2049);
+f(4293918720, 4095);
+f(4294967296, 4096);
+f(4296015872, 4097);
+f(8588886016, 8191);
+f(8589934592, 8192);
+f(8590983168, 8193);
+f(17178820608, 16383);
+f(17179869184, 16384);
+f(17180917760, 16385);
+f(34358689792, 32767);
+f(34359738368, 32768);
+f(34360786944, 32769);
+f(68718428160, 65535);
+f(68719476736, 65536);
+f(68720525312, 65537);
+f(137437904896, 131071);
+f(137438953472, 131072);
+f(137440002048, 131073);
+f(274876858368, 262143);
+f(274877906944, 262144);
+f(274878955520, 262145);
+f(549754765312, 524287);
+f(549755813888, 524288);
+f(549756862464, 524289);
+f(1099510579200, 1048575);
+f(1099511627776, 1048576);
+x = 1048577;
+f(1048577, 1);
+f(2097154, 2);
+f(3145731, 3);
+f(4194308, 4);
+f(5242885, 5);
+f(7340039, 7);
+f(8388616, 8);
+f(9437193, 9);
+f(15728655, 15);
+f(16777232, 16);
+f(17825809, 17);
+f(32505887, 31);
+f(33554464, 32);
+f(34603041, 33);
+f(66060351, 63);
+f(67108928, 64);
+f(68157505, 65);
+f(133169279, 127);
+f(134217856, 128);
+f(135266433, 129);
+f(267387135, 255);
+f(268435712, 256);
+f(269484289, 257);
+f(535822847, 511);
+f(536871424, 512);
+f(537920001, 513);
+f(1072694271, 1023);
+f(1073742848, 1024);
+f(1074791425, 1025);
+f(2146437119, 2047);
+f(2147485696, 2048);
+f(2148534273, 2049);
+f(4293922815, 4095);
+f(4294971392, 4096);
+f(4296019969, 4097);
+f(8588894207, 8191);
+f(8589942784, 8192);
+f(8590991361, 8193);
+f(17178836991, 16383);
+f(17179885568, 16384);
+f(17180934145, 16385);
+f(34358722559, 32767);
+f(34359771136, 32768);
+f(34360819713, 32769);
+f(68718493695, 65535);
+f(68719542272, 65536);
+f(68720590849, 65537);
+f(137438035967, 131071);
+f(137439084544, 131072);
+f(137440133121, 131073);
+f(274877120511, 262143);
+f(274878169088, 262144);
+f(274879217665, 262145);
+f(549755289599, 524287);
+f(549756338176, 524288);
+f(549757386753, 524289);
+f(1099511627775, 1048575);
+f(1099512676352, 1048576);
+f(1099513724929, 1048577);
+x = 2097151;
+f(2097151, 1);
+f(4194302, 2);
+f(6291453, 3);
+f(8388604, 4);
+f(10485755, 5);
+f(14680057, 7);
+f(16777208, 8);
+f(18874359, 9);
+f(31457265, 15);
+f(33554416, 16);
+f(35651567, 17);
+f(65011681, 31);
+f(67108832, 32);
+f(69205983, 33);
+f(132120513, 63);
+f(134217664, 64);
+f(136314815, 65);
+f(266338177, 127);
+f(268435328, 128);
+f(270532479, 129);
+f(534773505, 255);
+f(536870656, 256);
+f(538967807, 257);
+f(1071644161, 511);
+f(1073741312, 512);
+f(1075838463, 513);
+f(2145385473, 1023);
+f(2147482624, 1024);
+f(2149579775, 1025);
+f(4292868097, 2047);
+f(4294965248, 2048);
+f(4297062399, 2049);
+f(8587833345, 4095);
+f(8589930496, 4096);
+f(8592027647, 4097);
+f(17177763841, 8191);
+f(17179860992, 8192);
+f(17181958143, 8193);
+f(34357624833, 16383);
+f(34359721984, 16384);
+f(34361819135, 16385);
+f(68717346817, 32767);
+f(68719443968, 32768);
+f(68721541119, 32769);
+f(137436790785, 65535);
+f(137438887936, 65536);
+f(137440985087, 65537);
+f(274875678721, 131071);
+f(274877775872, 131072);
+f(274879873023, 131073);
+f(549753454593, 262143);
+f(549755551744, 262144);
+f(549757648895, 262145);
+f(1099509006337, 524287);
+f(1099511103488, 524288);
+f(1099513200639, 524289);
+f(2199020109825, 1048575);
+f(2199022206976, 1048576);
+f(2199024304127, 1048577);
+f(4398042316801, 2097151);
+x = 2097152;
+f(2097152, 1);
+f(4194304, 2);
+f(6291456, 3);
+f(8388608, 4);
+f(10485760, 5);
+f(14680064, 7);
+f(16777216, 8);
+f(18874368, 9);
+f(31457280, 15);
+f(33554432, 16);
+f(35651584, 17);
+f(65011712, 31);
+f(67108864, 32);
+f(69206016, 33);
+f(132120576, 63);
+f(134217728, 64);
+f(136314880, 65);
+f(266338304, 127);
+f(268435456, 128);
+f(270532608, 129);
+f(534773760, 255);
+f(536870912, 256);
+f(538968064, 257);
+f(1071644672, 511);
+f(1073741824, 512);
+f(1075838976, 513);
+f(2145386496, 1023);
+f(2147483648, 1024);
+f(2149580800, 1025);
+f(4292870144, 2047);
+f(4294967296, 2048);
+f(4297064448, 2049);
+f(8587837440, 4095);
+f(8589934592, 4096);
+f(8592031744, 4097);
+f(17177772032, 8191);
+f(17179869184, 8192);
+f(17181966336, 8193);
+f(34357641216, 16383);
+f(34359738368, 16384);
+f(34361835520, 16385);
+f(68717379584, 32767);
+f(68719476736, 32768);
+f(68721573888, 32769);
+f(137436856320, 65535);
+f(137438953472, 65536);
+f(137441050624, 65537);
+f(274875809792, 131071);
+f(274877906944, 131072);
+f(274880004096, 131073);
+f(549753716736, 262143);
+f(549755813888, 262144);
+f(549757911040, 262145);
+f(1099509530624, 524287);
+f(1099511627776, 524288);
+f(1099513724928, 524289);
+f(2199021158400, 1048575);
+f(2199023255552, 1048576);
+f(2199025352704, 1048577);
+f(4398044413952, 2097151);
+f(4398046511104, 2097152);
+x = 2097153;
+f(2097153, 1);
+f(4194306, 2);
+f(6291459, 3);
+f(8388612, 4);
+f(10485765, 5);
+f(14680071, 7);
+f(16777224, 8);
+f(18874377, 9);
+f(31457295, 15);
+f(33554448, 16);
+f(35651601, 17);
+f(65011743, 31);
+f(67108896, 32);
+f(69206049, 33);
+f(132120639, 63);
+f(134217792, 64);
+f(136314945, 65);
+f(266338431, 127);
+f(268435584, 128);
+f(270532737, 129);
+f(534774015, 255);
+f(536871168, 256);
+f(538968321, 257);
+f(1071645183, 511);
+f(1073742336, 512);
+f(1075839489, 513);
+f(2145387519, 1023);
+f(2147484672, 1024);
+f(2149581825, 1025);
+f(4292872191, 2047);
+f(4294969344, 2048);
+f(4297066497, 2049);
+f(8587841535, 4095);
+f(8589938688, 4096);
+f(8592035841, 4097);
+f(17177780223, 8191);
+f(17179877376, 8192);
+f(17181974529, 8193);
+f(34357657599, 16383);
+f(34359754752, 16384);
+f(34361851905, 16385);
+f(68717412351, 32767);
+f(68719509504, 32768);
+f(68721606657, 32769);
+f(137436921855, 65535);
+f(137439019008, 65536);
+f(137441116161, 65537);
+f(274875940863, 131071);
+f(274878038016, 131072);
+f(274880135169, 131073);
+f(549753978879, 262143);
+f(549756076032, 262144);
+f(549758173185, 262145);
+f(1099510054911, 524287);
+f(1099512152064, 524288);
+f(1099514249217, 524289);
+f(2199022206975, 1048575);
+f(2199024304128, 1048576);
+f(2199026401281, 1048577);
+f(4398046511103, 2097151);
+f(4398048608256, 2097152);
+f(4398050705409, 2097153);
+x = 4194303;
+f(4194303, 1);
+f(8388606, 2);
+f(12582909, 3);
+f(16777212, 4);
+f(20971515, 5);
+f(29360121, 7);
+f(33554424, 8);
+f(37748727, 9);
+f(62914545, 15);
+f(67108848, 16);
+f(71303151, 17);
+f(130023393, 31);
+f(134217696, 32);
+f(138411999, 33);
+f(264241089, 63);
+f(268435392, 64);
+f(272629695, 65);
+f(532676481, 127);
+f(536870784, 128);
+f(541065087, 129);
+f(1069547265, 255);
+f(1073741568, 256);
+f(1077935871, 257);
+f(2143288833, 511);
+f(2147483136, 512);
+f(2151677439, 513);
+f(4290771969, 1023);
+f(4294966272, 1024);
+f(4299160575, 1025);
+f(8585738241, 2047);
+f(8589932544, 2048);
+f(8594126847, 2049);
+f(17175670785, 4095);
+f(17179865088, 4096);
+f(17184059391, 4097);
+f(34355535873, 8191);
+f(34359730176, 8192);
+f(34363924479, 8193);
+f(68715266049, 16383);
+f(68719460352, 16384);
+f(68723654655, 16385);
+f(137434726401, 32767);
+f(137438920704, 32768);
+f(137443115007, 32769);
+f(274873647105, 65535);
+f(274877841408, 65536);
+f(274882035711, 65537);
+f(549751488513, 131071);
+f(549755682816, 131072);
+f(549759877119, 131073);
+f(1099507171329, 262143);
+f(1099511365632, 262144);
+f(1099515559935, 262145);
+f(2199018536961, 524287);
+f(2199022731264, 524288);
+f(2199026925567, 524289);
+f(4398041268225, 1048575);
+f(4398045462528, 1048576);
+f(4398049656831, 1048577);
+f(8796086730753, 2097151);
+f(8796090925056, 2097152);
+f(8796095119359, 2097153);
+f(17592177655809, 4194303);
+x = 4194304;
+f(4194304, 1);
+f(8388608, 2);
+f(12582912, 3);
+f(16777216, 4);
+f(20971520, 5);
+f(29360128, 7);
+f(33554432, 8);
+f(37748736, 9);
+f(62914560, 15);
+f(67108864, 16);
+f(71303168, 17);
+f(130023424, 31);
+f(134217728, 32);
+f(138412032, 33);
+f(264241152, 63);
+f(268435456, 64);
+f(272629760, 65);
+f(532676608, 127);
+f(536870912, 128);
+f(541065216, 129);
+f(1069547520, 255);
+f(1073741824, 256);
+f(1077936128, 257);
+f(2143289344, 511);
+f(2147483648, 512);
+f(2151677952, 513);
+f(4290772992, 1023);
+f(4294967296, 1024);
+f(4299161600, 1025);
+f(8585740288, 2047);
+f(8589934592, 2048);
+f(8594128896, 2049);
+f(17175674880, 4095);
+f(17179869184, 4096);
+f(17184063488, 4097);
+f(34355544064, 8191);
+f(34359738368, 8192);
+f(34363932672, 8193);
+f(68715282432, 16383);
+f(68719476736, 16384);
+f(68723671040, 16385);
+f(137434759168, 32767);
+f(137438953472, 32768);
+f(137443147776, 32769);
+f(274873712640, 65535);
+f(274877906944, 65536);
+f(274882101248, 65537);
+f(549751619584, 131071);
+f(549755813888, 131072);
+f(549760008192, 131073);
+f(1099507433472, 262143);
+f(1099511627776, 262144);
+f(1099515822080, 262145);
+f(2199019061248, 524287);
+f(2199023255552, 524288);
+f(2199027449856, 524289);
+f(4398042316800, 1048575);
+f(4398046511104, 1048576);
+f(4398050705408, 1048577);
+f(8796088827904, 2097151);
+f(8796093022208, 2097152);
+f(8796097216512, 2097153);
+f(17592181850112, 4194303);
+f(17592186044416, 4194304);
+x = 4194305;
+f(4194305, 1);
+f(8388610, 2);
+f(12582915, 3);
+f(16777220, 4);
+f(20971525, 5);
+f(29360135, 7);
+f(33554440, 8);
+f(37748745, 9);
+f(62914575, 15);
+f(67108880, 16);
+f(71303185, 17);
+f(130023455, 31);
+f(134217760, 32);
+f(138412065, 33);
+f(264241215, 63);
+f(268435520, 64);
+f(272629825, 65);
+f(532676735, 127);
+f(536871040, 128);
+f(541065345, 129);
+f(1069547775, 255);
+f(1073742080, 256);
+f(1077936385, 257);
+f(2143289855, 511);
+f(2147484160, 512);
+f(2151678465, 513);
+f(4290774015, 1023);
+f(4294968320, 1024);
+f(4299162625, 1025);
+f(8585742335, 2047);
+f(8589936640, 2048);
+f(8594130945, 2049);
+f(17175678975, 4095);
+f(17179873280, 4096);
+f(17184067585, 4097);
+f(34355552255, 8191);
+f(34359746560, 8192);
+f(34363940865, 8193);
+f(68715298815, 16383);
+f(68719493120, 16384);
+f(68723687425, 16385);
+f(137434791935, 32767);
+f(137438986240, 32768);
+f(137443180545, 32769);
+f(274873778175, 65535);
+f(274877972480, 65536);
+f(274882166785, 65537);
+f(549751750655, 131071);
+f(549755944960, 131072);
+f(549760139265, 131073);
+f(1099507695615, 262143);
+f(1099511889920, 262144);
+f(1099516084225, 262145);
+f(2199019585535, 524287);
+f(2199023779840, 524288);
+f(2199027974145, 524289);
+f(4398043365375, 1048575);
+f(4398047559680, 1048576);
+f(4398051753985, 1048577);
+f(8796090925055, 2097151);
+f(8796095119360, 2097152);
+f(8796099313665, 2097153);
+f(17592186044415, 4194303);
+f(17592190238720, 4194304);
+f(17592194433025, 4194305);
+x = 8388607;
+f(8388607, 1);
+f(16777214, 2);
+f(25165821, 3);
+f(33554428, 4);
+f(41943035, 5);
+f(58720249, 7);
+f(67108856, 8);
+f(75497463, 9);
+f(125829105, 15);
+f(134217712, 16);
+f(142606319, 17);
+f(260046817, 31);
+f(268435424, 32);
+f(276824031, 33);
+f(528482241, 63);
+f(536870848, 64);
+f(545259455, 65);
+f(1065353089, 127);
+f(1073741696, 128);
+f(1082130303, 129);
+f(2139094785, 255);
+f(2147483392, 256);
+f(2155871999, 257);
+f(4286578177, 511);
+f(4294966784, 512);
+f(4303355391, 513);
+f(8581544961, 1023);
+f(8589933568, 1024);
+f(8598322175, 1025);
+f(17171478529, 2047);
+f(17179867136, 2048);
+f(17188255743, 2049);
+f(34351345665, 4095);
+f(34359734272, 4096);
+f(34368122879, 4097);
+f(68711079937, 8191);
+f(68719468544, 8192);
+f(68727857151, 8193);
+f(137430548481, 16383);
+f(137438937088, 16384);
+f(137447325695, 16385);
+f(274869485569, 32767);
+f(274877874176, 32768);
+f(274886262783, 32769);
+f(549747359745, 65535);
+f(549755748352, 65536);
+f(549764136959, 65537);
+f(1099503108097, 131071);
+f(1099511496704, 131072);
+f(1099519885311, 131073);
+f(2199014604801, 262143);
+f(2199022993408, 262144);
+f(2199031382015, 262145);
+f(4398037598209, 524287);
+f(4398045986816, 524288);
+f(4398054375423, 524289);
+f(8796083585025, 1048575);
+f(8796091973632, 1048576);
+f(8796100362239, 1048577);
+f(17592175558657, 2097151);
+f(17592183947264, 2097152);
+f(17592192335871, 2097153);
+f(35184359505921, 4194303);
+f(35184367894528, 4194304);
+f(35184376283135, 4194305);
+f(70368727400449, 8388607);
+x = 8388608;
+f(8388608, 1);
+f(16777216, 2);
+f(25165824, 3);
+f(33554432, 4);
+f(41943040, 5);
+f(58720256, 7);
+f(67108864, 8);
+f(75497472, 9);
+f(125829120, 15);
+f(134217728, 16);
+f(142606336, 17);
+f(260046848, 31);
+f(268435456, 32);
+f(276824064, 33);
+f(528482304, 63);
+f(536870912, 64);
+f(545259520, 65);
+f(1065353216, 127);
+f(1073741824, 128);
+f(1082130432, 129);
+f(2139095040, 255);
+f(2147483648, 256);
+f(2155872256, 257);
+f(4286578688, 511);
+f(4294967296, 512);
+f(4303355904, 513);
+f(8581545984, 1023);
+f(8589934592, 1024);
+f(8598323200, 1025);
+f(17171480576, 2047);
+f(17179869184, 2048);
+f(17188257792, 2049);
+f(34351349760, 4095);
+f(34359738368, 4096);
+f(34368126976, 4097);
+f(68711088128, 8191);
+f(68719476736, 8192);
+f(68727865344, 8193);
+f(137430564864, 16383);
+f(137438953472, 16384);
+f(137447342080, 16385);
+f(274869518336, 32767);
+f(274877906944, 32768);
+f(274886295552, 32769);
+f(549747425280, 65535);
+f(549755813888, 65536);
+f(549764202496, 65537);
+f(1099503239168, 131071);
+f(1099511627776, 131072);
+f(1099520016384, 131073);
+f(2199014866944, 262143);
+f(2199023255552, 262144);
+f(2199031644160, 262145);
+f(4398038122496, 524287);
+f(4398046511104, 524288);
+f(4398054899712, 524289);
+f(8796084633600, 1048575);
+f(8796093022208, 1048576);
+f(8796101410816, 1048577);
+f(17592177655808, 2097151);
+f(17592186044416, 2097152);
+f(17592194433024, 2097153);
+f(35184363700224, 4194303);
+f(35184372088832, 4194304);
+f(35184380477440, 4194305);
+f(70368735789056, 8388607);
+f(70368744177664, 8388608);
+x = 8388609;
+f(8388609, 1);
+f(16777218, 2);
+f(25165827, 3);
+f(33554436, 4);
+f(41943045, 5);
+f(58720263, 7);
+f(67108872, 8);
+f(75497481, 9);
+f(125829135, 15);
+f(134217744, 16);
+f(142606353, 17);
+f(260046879, 31);
+f(268435488, 32);
+f(276824097, 33);
+f(528482367, 63);
+f(536870976, 64);
+f(545259585, 65);
+f(1065353343, 127);
+f(1073741952, 128);
+f(1082130561, 129);
+f(2139095295, 255);
+f(2147483904, 256);
+f(2155872513, 257);
+f(4286579199, 511);
+f(4294967808, 512);
+f(4303356417, 513);
+f(8581547007, 1023);
+f(8589935616, 1024);
+f(8598324225, 1025);
+f(17171482623, 2047);
+f(17179871232, 2048);
+f(17188259841, 2049);
+f(34351353855, 4095);
+f(34359742464, 4096);
+f(34368131073, 4097);
+f(68711096319, 8191);
+f(68719484928, 8192);
+f(68727873537, 8193);
+f(137430581247, 16383);
+f(137438969856, 16384);
+f(137447358465, 16385);
+f(274869551103, 32767);
+f(274877939712, 32768);
+f(274886328321, 32769);
+f(549747490815, 65535);
+f(549755879424, 65536);
+f(549764268033, 65537);
+f(1099503370239, 131071);
+f(1099511758848, 131072);
+f(1099520147457, 131073);
+f(2199015129087, 262143);
+f(2199023517696, 262144);
+f(2199031906305, 262145);
+f(4398038646783, 524287);
+f(4398047035392, 524288);
+f(4398055424001, 524289);
+f(8796085682175, 1048575);
+f(8796094070784, 1048576);
+f(8796102459393, 1048577);
+f(17592179752959, 2097151);
+f(17592188141568, 2097152);
+f(17592196530177, 2097153);
+f(35184367894527, 4194303);
+f(35184376283136, 4194304);
+f(35184384671745, 4194305);
+f(70368744177663, 8388607);
+f(70368752566272, 8388608);
+f(70368760954881, 8388609);
+x = 16777215;
+f(16777215, 1);
+f(33554430, 2);
+f(50331645, 3);
+f(67108860, 4);
+f(83886075, 5);
+f(117440505, 7);
+f(134217720, 8);
+f(150994935, 9);
+f(251658225, 15);
+f(268435440, 16);
+f(285212655, 17);
+f(520093665, 31);
+f(536870880, 32);
+f(553648095, 33);
+f(1056964545, 63);
+f(1073741760, 64);
+f(1090518975, 65);
+f(2130706305, 127);
+f(2147483520, 128);
+f(2164260735, 129);
+f(4278189825, 255);
+f(4294967040, 256);
+f(4311744255, 257);
+f(8573156865, 511);
+f(8589934080, 512);
+f(8606711295, 513);
+f(17163090945, 1023);
+f(17179868160, 1024);
+f(17196645375, 1025);
+f(34342959105, 2047);
+f(34359736320, 2048);
+f(34376513535, 2049);
+f(68702695425, 4095);
+f(68719472640, 4096);
+f(68736249855, 4097);
+f(137422168065, 8191);
+f(137438945280, 8192);
+f(137455722495, 8193);
+f(274861113345, 16383);
+f(274877890560, 16384);
+f(274894667775, 16385);
+f(549739003905, 32767);
+f(549755781120, 32768);
+f(549772558335, 32769);
+f(1099494785025, 65535);
+f(1099511562240, 65536);
+f(1099528339455, 65537);
+f(2199006347265, 131071);
+f(2199023124480, 131072);
+f(2199039901695, 131073);
+f(4398029471745, 262143);
+f(4398046248960, 262144);
+f(4398063026175, 262145);
+f(8796075720705, 524287);
+f(8796092497920, 524288);
+f(8796109275135, 524289);
+f(17592168218625, 1048575);
+f(17592184995840, 1048576);
+f(17592201773055, 1048577);
+f(35184353214465, 2097151);
+f(35184369991680, 2097152);
+f(35184386768895, 2097153);
+f(70368723206145, 4194303);
+f(70368739983360, 4194304);
+f(70368756760575, 4194305);
+f(140737463189505, 8388607);
+f(140737479966720, 8388608);
+f(140737496743935, 8388609);
+f(281474943156225, 16777215);
+x = 16777216;
+f(16777216, 1);
+f(33554432, 2);
+f(50331648, 3);
+f(67108864, 4);
+f(83886080, 5);
+f(117440512, 7);
+f(134217728, 8);
+f(150994944, 9);
+f(251658240, 15);
+f(268435456, 16);
+f(285212672, 17);
+f(520093696, 31);
+f(536870912, 32);
+f(553648128, 33);
+f(1056964608, 63);
+f(1073741824, 64);
+f(1090519040, 65);
+f(2130706432, 127);
+f(2147483648, 128);
+f(2164260864, 129);
+f(4278190080, 255);
+f(4294967296, 256);
+f(4311744512, 257);
+f(8573157376, 511);
+f(8589934592, 512);
+f(8606711808, 513);
+f(17163091968, 1023);
+f(17179869184, 1024);
+f(17196646400, 1025);
+f(34342961152, 2047);
+f(34359738368, 2048);
+f(34376515584, 2049);
+f(68702699520, 4095);
+f(68719476736, 4096);
+f(68736253952, 4097);
+f(137422176256, 8191);
+f(137438953472, 8192);
+f(137455730688, 8193);
+f(274861129728, 16383);
+f(274877906944, 16384);
+f(274894684160, 16385);
+f(549739036672, 32767);
+f(549755813888, 32768);
+f(549772591104, 32769);
+f(1099494850560, 65535);
+f(1099511627776, 65536);
+f(1099528404992, 65537);
+f(2199006478336, 131071);
+f(2199023255552, 131072);
+f(2199040032768, 131073);
+f(4398029733888, 262143);
+f(4398046511104, 262144);
+f(4398063288320, 262145);
+f(8796076244992, 524287);
+f(8796093022208, 524288);
+f(8796109799424, 524289);
+f(17592169267200, 1048575);
+f(17592186044416, 1048576);
+f(17592202821632, 1048577);
+f(35184355311616, 2097151);
+f(35184372088832, 2097152);
+f(35184388866048, 2097153);
+f(70368727400448, 4194303);
+f(70368744177664, 4194304);
+f(70368760954880, 4194305);
+f(140737471578112, 8388607);
+f(140737488355328, 8388608);
+f(140737505132544, 8388609);
+f(281474959933440, 16777215);
+f(281474976710656, 16777216);
+x = 16777217;
+f(16777217, 1);
+f(33554434, 2);
+f(50331651, 3);
+f(67108868, 4);
+f(83886085, 5);
+f(117440519, 7);
+f(134217736, 8);
+f(150994953, 9);
+f(251658255, 15);
+f(268435472, 16);
+f(285212689, 17);
+f(520093727, 31);
+f(536870944, 32);
+f(553648161, 33);
+f(1056964671, 63);
+f(1073741888, 64);
+f(1090519105, 65);
+f(2130706559, 127);
+f(2147483776, 128);
+f(2164260993, 129);
+f(4278190335, 255);
+f(4294967552, 256);
+f(4311744769, 257);
+f(8573157887, 511);
+f(8589935104, 512);
+f(8606712321, 513);
+f(17163092991, 1023);
+f(17179870208, 1024);
+f(17196647425, 1025);
+f(34342963199, 2047);
+f(34359740416, 2048);
+f(34376517633, 2049);
+f(68702703615, 4095);
+f(68719480832, 4096);
+f(68736258049, 4097);
+f(137422184447, 8191);
+f(137438961664, 8192);
+f(137455738881, 8193);
+f(274861146111, 16383);
+f(274877923328, 16384);
+f(274894700545, 16385);
+f(549739069439, 32767);
+f(549755846656, 32768);
+f(549772623873, 32769);
+f(1099494916095, 65535);
+f(1099511693312, 65536);
+f(1099528470529, 65537);
+f(2199006609407, 131071);
+f(2199023386624, 131072);
+f(2199040163841, 131073);
+f(4398029996031, 262143);
+f(4398046773248, 262144);
+f(4398063550465, 262145);
+f(8796076769279, 524287);
+f(8796093546496, 524288);
+f(8796110323713, 524289);
+f(17592170315775, 1048575);
+f(17592187092992, 1048576);
+f(17592203870209, 1048577);
+f(35184357408767, 2097151);
+f(35184374185984, 2097152);
+f(35184390963201, 2097153);
+f(70368731594751, 4194303);
+f(70368748371968, 4194304);
+f(70368765149185, 4194305);
+f(140737479966719, 8388607);
+f(140737496743936, 8388608);
+f(140737513521153, 8388609);
+f(281474976710655, 16777215);
+f(281474993487872, 16777216);
+f(281475010265089, 16777217);
+x = 33554431;
+f(33554431, 1);
+f(67108862, 2);
+f(100663293, 3);
+f(134217724, 4);
+f(167772155, 5);
+f(234881017, 7);
+f(268435448, 8);
+f(301989879, 9);
+f(503316465, 15);
+f(536870896, 16);
+f(570425327, 17);
+f(1040187361, 31);
+f(1073741792, 32);
+f(1107296223, 33);
+f(2113929153, 63);
+f(2147483584, 64);
+f(2181038015, 65);
+f(4261412737, 127);
+f(4294967168, 128);
+f(4328521599, 129);
+f(8556379905, 255);
+f(8589934336, 256);
+f(8623488767, 257);
+f(17146314241, 511);
+f(17179868672, 512);
+f(17213423103, 513);
+f(34326182913, 1023);
+f(34359737344, 1024);
+f(34393291775, 1025);
+f(68685920257, 2047);
+f(68719474688, 2048);
+f(68753029119, 2049);
+f(137405394945, 4095);
+f(137438949376, 4096);
+f(137472503807, 4097);
+f(274844344321, 8191);
+f(274877898752, 8192);
+f(274911453183, 8193);
+f(549722243073, 16383);
+f(549755797504, 16384);
+f(549789351935, 16385);
+f(1099478040577, 32767);
+f(1099511595008, 32768);
+f(1099545149439, 32769);
+f(2198989635585, 65535);
+f(2199023190016, 65536);
+f(2199056744447, 65537);
+f(4398012825601, 131071);
+f(4398046380032, 131072);
+f(4398079934463, 131073);
+f(8796059205633, 262143);
+f(8796092760064, 262144);
+f(8796126314495, 262145);
+f(17592151965697, 524287);
+f(17592185520128, 524288);
+f(17592219074559, 524289);
+f(35184337485825, 1048575);
+f(35184371040256, 1048576);
+f(35184404594687, 1048577);
+f(70368708526081, 2097151);
+f(70368742080512, 2097152);
+f(70368775634943, 2097153);
+f(140737450606593, 4194303);
+f(140737484161024, 4194304);
+f(140737517715455, 4194305);
+f(281474934767617, 8388607);
+f(281474968322048, 8388608);
+f(281475001876479, 8388609);
+f(562949903089665, 16777215);
+f(562949936644096, 16777216);
+f(562949970198527, 16777217);
+f(1125899839733761, 33554431);
+x = 33554432;
+f(33554432, 1);
+f(67108864, 2);
+f(100663296, 3);
+f(134217728, 4);
+f(167772160, 5);
+f(234881024, 7);
+f(268435456, 8);
+f(301989888, 9);
+f(503316480, 15);
+f(536870912, 16);
+f(570425344, 17);
+f(1040187392, 31);
+f(1073741824, 32);
+f(1107296256, 33);
+f(2113929216, 63);
+f(2147483648, 64);
+f(2181038080, 65);
+f(4261412864, 127);
+f(4294967296, 128);
+f(4328521728, 129);
+f(8556380160, 255);
+f(8589934592, 256);
+f(8623489024, 257);
+f(17146314752, 511);
+f(17179869184, 512);
+f(17213423616, 513);
+f(34326183936, 1023);
+f(34359738368, 1024);
+f(34393292800, 1025);
+f(68685922304, 2047);
+f(68719476736, 2048);
+f(68753031168, 2049);
+f(137405399040, 4095);
+f(137438953472, 4096);
+f(137472507904, 4097);
+f(274844352512, 8191);
+f(274877906944, 8192);
+f(274911461376, 8193);
+f(549722259456, 16383);
+f(549755813888, 16384);
+f(549789368320, 16385);
+f(1099478073344, 32767);
+f(1099511627776, 32768);
+f(1099545182208, 32769);
+f(2198989701120, 65535);
+f(2199023255552, 65536);
+f(2199056809984, 65537);
+f(4398012956672, 131071);
+f(4398046511104, 131072);
+f(4398080065536, 131073);
+f(8796059467776, 262143);
+f(8796093022208, 262144);
+f(8796126576640, 262145);
+f(17592152489984, 524287);
+f(17592186044416, 524288);
+f(17592219598848, 524289);
+f(35184338534400, 1048575);
+f(35184372088832, 1048576);
+f(35184405643264, 1048577);
+f(70368710623232, 2097151);
+f(70368744177664, 2097152);
+f(70368777732096, 2097153);
+f(140737454800896, 4194303);
+f(140737488355328, 4194304);
+f(140737521909760, 4194305);
+f(281474943156224, 8388607);
+f(281474976710656, 8388608);
+f(281475010265088, 8388609);
+f(562949919866880, 16777215);
+f(562949953421312, 16777216);
+f(562949986975744, 16777217);
+f(1125899873288192, 33554431);
+f(1125899906842624, 33554432);
+x = 33554433;
+f(33554433, 1);
+f(67108866, 2);
+f(100663299, 3);
+f(134217732, 4);
+f(167772165, 5);
+f(234881031, 7);
+f(268435464, 8);
+f(301989897, 9);
+f(503316495, 15);
+f(536870928, 16);
+f(570425361, 17);
+f(1040187423, 31);
+f(1073741856, 32);
+f(1107296289, 33);
+f(2113929279, 63);
+f(2147483712, 64);
+f(2181038145, 65);
+f(4261412991, 127);
+f(4294967424, 128);
+f(4328521857, 129);
+f(8556380415, 255);
+f(8589934848, 256);
+f(8623489281, 257);
+f(17146315263, 511);
+f(17179869696, 512);
+f(17213424129, 513);
+f(34326184959, 1023);
+f(34359739392, 1024);
+f(34393293825, 1025);
+f(68685924351, 2047);
+f(68719478784, 2048);
+f(68753033217, 2049);
+f(137405403135, 4095);
+f(137438957568, 4096);
+f(137472512001, 4097);
+f(274844360703, 8191);
+f(274877915136, 8192);
+f(274911469569, 8193);
+f(549722275839, 16383);
+f(549755830272, 16384);
+f(549789384705, 16385);
+f(1099478106111, 32767);
+f(1099511660544, 32768);
+f(1099545214977, 32769);
+f(2198989766655, 65535);
+f(2199023321088, 65536);
+f(2199056875521, 65537);
+f(4398013087743, 131071);
+f(4398046642176, 131072);
+f(4398080196609, 131073);
+f(8796059729919, 262143);
+f(8796093284352, 262144);
+f(8796126838785, 262145);
+f(17592153014271, 524287);
+f(17592186568704, 524288);
+f(17592220123137, 524289);
+f(35184339582975, 1048575);
+f(35184373137408, 1048576);
+f(35184406691841, 1048577);
+f(70368712720383, 2097151);
+f(70368746274816, 2097152);
+f(70368779829249, 2097153);
+f(140737458995199, 4194303);
+f(140737492549632, 4194304);
+f(140737526104065, 4194305);
+f(281474951544831, 8388607);
+f(281474985099264, 8388608);
+f(281475018653697, 8388609);
+f(562949936644095, 16777215);
+f(562949970198528, 16777216);
+f(562950003752961, 16777217);
+f(1125899906842623, 33554431);
+f(1125899940397056, 33554432);
+f(1125899973951489, 33554433);
+x = 67108863;
+f(67108863, 1);
+f(134217726, 2);
+f(201326589, 3);
+f(268435452, 4);
+f(335544315, 5);
+f(469762041, 7);
+f(536870904, 8);
+f(603979767, 9);
+f(1006632945, 15);
+f(1073741808, 16);
+f(1140850671, 17);
+f(2080374753, 31);
+f(2147483616, 32);
+f(2214592479, 33);
+f(4227858369, 63);
+f(4294967232, 64);
+f(4362076095, 65);
+f(8522825601, 127);
+f(8589934464, 128);
+f(8657043327, 129);
+f(17112760065, 255);
+f(17179868928, 256);
+f(17246977791, 257);
+f(34292628993, 511);
+f(34359737856, 512);
+f(34426846719, 513);
+f(68652366849, 1023);
+f(68719475712, 1024);
+f(68786584575, 1025);
+f(137371842561, 2047);
+f(137438951424, 2048);
+f(137506060287, 2049);
+f(274810793985, 4095);
+f(274877902848, 4096);
+f(274945011711, 4097);
+f(549688696833, 8191);
+f(549755805696, 8192);
+f(549822914559, 8193);
+f(1099444502529, 16383);
+f(1099511611392, 16384);
+f(1099578720255, 16385);
+f(2198956113921, 32767);
+f(2199023222784, 32768);
+f(2199090331647, 32769);
+f(4397979336705, 65535);
+f(4398046445568, 65536);
+f(4398113554431, 65537);
+f(8796025782273, 131071);
+f(8796092891136, 131072);
+f(8796159999999, 131073);
+f(17592118673409, 262143);
+f(17592185782272, 262144);
+f(17592252891135, 262145);
+f(35184304455681, 524287);
+f(35184371564544, 524288);
+f(35184438673407, 524289);
+f(70368676020225, 1048575);
+f(70368743129088, 1048576);
+f(70368810237951, 1048577);
+f(140737419149313, 2097151);
+f(140737486258176, 2097152);
+f(140737553367039, 2097153);
+f(281474905407489, 4194303);
+f(281474972516352, 4194304);
+f(281475039625215, 4194305);
+f(562949877923841, 8388607);
+f(562949945032704, 8388608);
+f(562950012141567, 8388609);
+f(1125899822956545, 16777215);
+f(1125899890065408, 16777216);
+f(1125899957174271, 16777217);
+x = 67108864;
+f(67108864, 1);
+f(134217728, 2);
+f(201326592, 3);
+f(268435456, 4);
+f(335544320, 5);
+f(469762048, 7);
+f(536870912, 8);
+f(603979776, 9);
+f(1006632960, 15);
+f(1073741824, 16);
+f(1140850688, 17);
+f(2080374784, 31);
+f(2147483648, 32);
+f(2214592512, 33);
+f(4227858432, 63);
+f(4294967296, 64);
+f(4362076160, 65);
+f(8522825728, 127);
+f(8589934592, 128);
+f(8657043456, 129);
+f(17112760320, 255);
+f(17179869184, 256);
+f(17246978048, 257);
+f(34292629504, 511);
+f(34359738368, 512);
+f(34426847232, 513);
+f(68652367872, 1023);
+f(68719476736, 1024);
+f(68786585600, 1025);
+f(137371844608, 2047);
+f(137438953472, 2048);
+f(137506062336, 2049);
+f(274810798080, 4095);
+f(274877906944, 4096);
+f(274945015808, 4097);
+f(549688705024, 8191);
+f(549755813888, 8192);
+f(549822922752, 8193);
+f(1099444518912, 16383);
+f(1099511627776, 16384);
+f(1099578736640, 16385);
+f(2198956146688, 32767);
+f(2199023255552, 32768);
+f(2199090364416, 32769);
+f(4397979402240, 65535);
+f(4398046511104, 65536);
+f(4398113619968, 65537);
+f(8796025913344, 131071);
+f(8796093022208, 131072);
+f(8796160131072, 131073);
+f(17592118935552, 262143);
+f(17592186044416, 262144);
+f(17592253153280, 262145);
+f(35184304979968, 524287);
+f(35184372088832, 524288);
+f(35184439197696, 524289);
+f(70368677068800, 1048575);
+f(70368744177664, 1048576);
+f(70368811286528, 1048577);
+f(140737421246464, 2097151);
+f(140737488355328, 2097152);
+f(140737555464192, 2097153);
+f(281474909601792, 4194303);
+f(281474976710656, 4194304);
+f(281475043819520, 4194305);
+f(562949886312448, 8388607);
+f(562949953421312, 8388608);
+f(562950020530176, 8388609);
+f(1125899839733760, 16777215);
+f(1125899906842624, 16777216);
+f(1125899973951488, 16777217);
+x = 67108865;
+f(67108865, 1);
+f(134217730, 2);
+f(201326595, 3);
+f(268435460, 4);
+f(335544325, 5);
+f(469762055, 7);
+f(536870920, 8);
+f(603979785, 9);
+f(1006632975, 15);
+f(1073741840, 16);
+f(1140850705, 17);
+f(2080374815, 31);
+f(2147483680, 32);
+f(2214592545, 33);
+f(4227858495, 63);
+f(4294967360, 64);
+f(4362076225, 65);
+f(8522825855, 127);
+f(8589934720, 128);
+f(8657043585, 129);
+f(17112760575, 255);
+f(17179869440, 256);
+f(17246978305, 257);
+f(34292630015, 511);
+f(34359738880, 512);
+f(34426847745, 513);
+f(68652368895, 1023);
+f(68719477760, 1024);
+f(68786586625, 1025);
+f(137371846655, 2047);
+f(137438955520, 2048);
+f(137506064385, 2049);
+f(274810802175, 4095);
+f(274877911040, 4096);
+f(274945019905, 4097);
+f(549688713215, 8191);
+f(549755822080, 8192);
+f(549822930945, 8193);
+f(1099444535295, 16383);
+f(1099511644160, 16384);
+f(1099578753025, 16385);
+f(2198956179455, 32767);
+f(2199023288320, 32768);
+f(2199090397185, 32769);
+f(4397979467775, 65535);
+f(4398046576640, 65536);
+f(4398113685505, 65537);
+f(8796026044415, 131071);
+f(8796093153280, 131072);
+f(8796160262145, 131073);
+f(17592119197695, 262143);
+f(17592186306560, 262144);
+f(17592253415425, 262145);
+f(35184305504255, 524287);
+f(35184372613120, 524288);
+f(35184439721985, 524289);
+f(70368678117375, 1048575);
+f(70368745226240, 1048576);
+f(70368812335105, 1048577);
+f(140737423343615, 2097151);
+f(140737490452480, 2097152);
+f(140737557561345, 2097153);
+f(281474913796095, 4194303);
+f(281474980904960, 4194304);
+f(281475048013825, 4194305);
+f(562949894701055, 8388607);
+f(562949961809920, 8388608);
+f(562950028918785, 8388609);
+f(1125899856510975, 16777215);
+f(1125899923619840, 16777216);
+f(1125899990728705, 16777217);
+x = 134217727;
+f(134217727, 1);
+f(268435454, 2);
+f(402653181, 3);
+f(536870908, 4);
+f(671088635, 5);
+f(939524089, 7);
+f(1073741816, 8);
+f(1207959543, 9);
+f(2013265905, 15);
+f(2147483632, 16);
+f(2281701359, 17);
+f(4160749537, 31);
+f(4294967264, 32);
+f(4429184991, 33);
+f(8455716801, 63);
+f(8589934528, 64);
+f(8724152255, 65);
+f(17045651329, 127);
+f(17179869056, 128);
+f(17314086783, 129);
+f(34225520385, 255);
+f(34359738112, 256);
+f(34493955839, 257);
+f(68585258497, 511);
+f(68719476224, 512);
+f(68853693951, 513);
+f(137304734721, 1023);
+f(137438952448, 1024);
+f(137573170175, 1025);
+f(274743687169, 2047);
+f(274877904896, 2048);
+f(275012122623, 2049);
+f(549621592065, 4095);
+f(549755809792, 4096);
+f(549890027519, 4097);
+f(1099377401857, 8191);
+f(1099511619584, 8192);
+f(1099645837311, 8193);
+f(2198889021441, 16383);
+f(2199023239168, 16384);
+f(2199157456895, 16385);
+f(4397912260609, 32767);
+f(4398046478336, 32768);
+f(4398180696063, 32769);
+f(8795958738945, 65535);
+f(8796092956672, 65536);
+f(8796227174399, 65537);
+f(17592051695617, 131071);
+f(17592185913344, 131072);
+f(17592320131071, 131073);
+f(35184237608961, 262143);
+f(35184371826688, 262144);
+f(35184506044415, 262145);
+f(70368609435649, 524287);
+f(70368743653376, 524288);
+f(70368877871103, 524289);
+f(140737353089025, 1048575);
+f(140737487306752, 1048576);
+f(140737621524479, 1048577);
+f(281474840395777, 2097151);
+f(281474974613504, 2097152);
+f(281475108831231, 2097153);
+f(562949815009281, 4194303);
+f(562949949227008, 4194304);
+f(562950083444735, 4194305);
+f(1125899764236289, 8388607);
+f(1125899898454016, 8388608);
+f(1125900032671743, 8388609);
+x = 134217728;
+f(134217728, 1);
+f(268435456, 2);
+f(402653184, 3);
+f(536870912, 4);
+f(671088640, 5);
+f(939524096, 7);
+f(1073741824, 8);
+f(1207959552, 9);
+f(2013265920, 15);
+f(2147483648, 16);
+f(2281701376, 17);
+f(4160749568, 31);
+f(4294967296, 32);
+f(4429185024, 33);
+f(8455716864, 63);
+f(8589934592, 64);
+f(8724152320, 65);
+f(17045651456, 127);
+f(17179869184, 128);
+f(17314086912, 129);
+f(34225520640, 255);
+f(34359738368, 256);
+f(34493956096, 257);
+f(68585259008, 511);
+f(68719476736, 512);
+f(68853694464, 513);
+f(137304735744, 1023);
+f(137438953472, 1024);
+f(137573171200, 1025);
+f(274743689216, 2047);
+f(274877906944, 2048);
+f(275012124672, 2049);
+f(549621596160, 4095);
+f(549755813888, 4096);
+f(549890031616, 4097);
+f(1099377410048, 8191);
+f(1099511627776, 8192);
+f(1099645845504, 8193);
+f(2198889037824, 16383);
+f(2199023255552, 16384);
+f(2199157473280, 16385);
+f(4397912293376, 32767);
+f(4398046511104, 32768);
+f(4398180728832, 32769);
+f(8795958804480, 65535);
+f(8796093022208, 65536);
+f(8796227239936, 65537);
+f(17592051826688, 131071);
+f(17592186044416, 131072);
+f(17592320262144, 131073);
+f(35184237871104, 262143);
+f(35184372088832, 262144);
+f(35184506306560, 262145);
+f(70368609959936, 524287);
+f(70368744177664, 524288);
+f(70368878395392, 524289);
+f(140737354137600, 1048575);
+f(140737488355328, 1048576);
+f(140737622573056, 1048577);
+f(281474842492928, 2097151);
+f(281474976710656, 2097152);
+f(281475110928384, 2097153);
+f(562949819203584, 4194303);
+f(562949953421312, 4194304);
+f(562950087639040, 4194305);
+f(1125899772624896, 8388607);
+f(1125899906842624, 8388608);
+f(1125900041060352, 8388609);
+x = 134217729;
+f(134217729, 1);
+f(268435458, 2);
+f(402653187, 3);
+f(536870916, 4);
+f(671088645, 5);
+f(939524103, 7);
+f(1073741832, 8);
+f(1207959561, 9);
+f(2013265935, 15);
+f(2147483664, 16);
+f(2281701393, 17);
+f(4160749599, 31);
+f(4294967328, 32);
+f(4429185057, 33);
+f(8455716927, 63);
+f(8589934656, 64);
+f(8724152385, 65);
+f(17045651583, 127);
+f(17179869312, 128);
+f(17314087041, 129);
+f(34225520895, 255);
+f(34359738624, 256);
+f(34493956353, 257);
+f(68585259519, 511);
+f(68719477248, 512);
+f(68853694977, 513);
+f(137304736767, 1023);
+f(137438954496, 1024);
+f(137573172225, 1025);
+f(274743691263, 2047);
+f(274877908992, 2048);
+f(275012126721, 2049);
+f(549621600255, 4095);
+f(549755817984, 4096);
+f(549890035713, 4097);
+f(1099377418239, 8191);
+f(1099511635968, 8192);
+f(1099645853697, 8193);
+f(2198889054207, 16383);
+f(2199023271936, 16384);
+f(2199157489665, 16385);
+f(4397912326143, 32767);
+f(4398046543872, 32768);
+f(4398180761601, 32769);
+f(8795958870015, 65535);
+f(8796093087744, 65536);
+f(8796227305473, 65537);
+f(17592051957759, 131071);
+f(17592186175488, 131072);
+f(17592320393217, 131073);
+f(35184238133247, 262143);
+f(35184372350976, 262144);
+f(35184506568705, 262145);
+f(70368610484223, 524287);
+f(70368744701952, 524288);
+f(70368878919681, 524289);
+f(140737355186175, 1048575);
+f(140737489403904, 1048576);
+f(140737623621633, 1048577);
+f(281474844590079, 2097151);
+f(281474978807808, 2097152);
+f(281475113025537, 2097153);
+f(562949823397887, 4194303);
+f(562949957615616, 4194304);
+f(562950091833345, 4194305);
+f(1125899781013503, 8388607);
+f(1125899915231232, 8388608);
+f(1125900049448961, 8388609);
+x = 268435455;
+f(268435455, 1);
+f(536870910, 2);
+f(805306365, 3);
+f(1073741820, 4);
+f(1342177275, 5);
+f(1879048185, 7);
+f(2147483640, 8);
+f(2415919095, 9);
+f(4026531825, 15);
+f(4294967280, 16);
+f(4563402735, 17);
+f(8321499105, 31);
+f(8589934560, 32);
+f(8858370015, 33);
+f(16911433665, 63);
+f(17179869120, 64);
+f(17448304575, 65);
+f(34091302785, 127);
+f(34359738240, 128);
+f(34628173695, 129);
+f(68451041025, 255);
+f(68719476480, 256);
+f(68987911935, 257);
+f(137170517505, 511);
+f(137438952960, 512);
+f(137707388415, 513);
+f(274609470465, 1023);
+f(274877905920, 1024);
+f(275146341375, 1025);
+f(549487376385, 2047);
+f(549755811840, 2048);
+f(550024247295, 2049);
+f(1099243188225, 4095);
+f(1099511623680, 4096);
+f(1099780059135, 4097);
+f(2198754811905, 8191);
+f(2199023247360, 8192);
+f(2199291682815, 8193);
+f(4397778059265, 16383);
+f(4398046494720, 16384);
+f(4398314930175, 16385);
+f(8795824553985, 32767);
+f(8796092989440, 32768);
+f(8796361424895, 32769);
+f(17591917543425, 65535);
+f(17592185978880, 65536);
+f(17592454414335, 65537);
+f(35184103522305, 131071);
+f(35184371957760, 131072);
+f(35184640393215, 131073);
+f(70368475480065, 262143);
+f(70368743915520, 262144);
+f(70369012350975, 262145);
+f(140737219395585, 524287);
+f(140737487831040, 524288);
+f(140737756266495, 524289);
+f(281474707226625, 1048575);
+f(281474975662080, 1048576);
+f(281475244097535, 1048577);
+f(562949682888705, 2097151);
+f(562949951324160, 2097152);
+f(562950219759615, 2097153);
+f(1125899634212865, 4194303);
+f(1125899902648320, 4194304);
+f(1125900171083775, 4194305);
+x = 268435456;
+f(268435456, 1);
+f(536870912, 2);
+f(805306368, 3);
+f(1073741824, 4);
+f(1342177280, 5);
+f(1879048192, 7);
+f(2147483648, 8);
+f(2415919104, 9);
+f(4026531840, 15);
+f(4294967296, 16);
+f(4563402752, 17);
+f(8321499136, 31);
+f(8589934592, 32);
+f(8858370048, 33);
+f(16911433728, 63);
+f(17179869184, 64);
+f(17448304640, 65);
+f(34091302912, 127);
+f(34359738368, 128);
+f(34628173824, 129);
+f(68451041280, 255);
+f(68719476736, 256);
+f(68987912192, 257);
+f(137170518016, 511);
+f(137438953472, 512);
+f(137707388928, 513);
+f(274609471488, 1023);
+f(274877906944, 1024);
+f(275146342400, 1025);
+f(549487378432, 2047);
+f(549755813888, 2048);
+f(550024249344, 2049);
+f(1099243192320, 4095);
+f(1099511627776, 4096);
+f(1099780063232, 4097);
+f(2198754820096, 8191);
+f(2199023255552, 8192);
+f(2199291691008, 8193);
+f(4397778075648, 16383);
+f(4398046511104, 16384);
+f(4398314946560, 16385);
+f(8795824586752, 32767);
+f(8796093022208, 32768);
+f(8796361457664, 32769);
+f(17591917608960, 65535);
+f(17592186044416, 65536);
+f(17592454479872, 65537);
+f(35184103653376, 131071);
+f(35184372088832, 131072);
+f(35184640524288, 131073);
+f(70368475742208, 262143);
+f(70368744177664, 262144);
+f(70369012613120, 262145);
+f(140737219919872, 524287);
+f(140737488355328, 524288);
+f(140737756790784, 524289);
+f(281474708275200, 1048575);
+f(281474976710656, 1048576);
+f(281475245146112, 1048577);
+f(562949684985856, 2097151);
+f(562949953421312, 2097152);
+f(562950221856768, 2097153);
+f(1125899638407168, 4194303);
+f(1125899906842624, 4194304);
+f(1125900175278080, 4194305);
+x = 268435457;
+f(268435457, 1);
+f(536870914, 2);
+f(805306371, 3);
+f(1073741828, 4);
+f(1342177285, 5);
+f(1879048199, 7);
+f(2147483656, 8);
+f(2415919113, 9);
+f(4026531855, 15);
+f(4294967312, 16);
+f(4563402769, 17);
+f(8321499167, 31);
+f(8589934624, 32);
+f(8858370081, 33);
+f(16911433791, 63);
+f(17179869248, 64);
+f(17448304705, 65);
+f(34091303039, 127);
+f(34359738496, 128);
+f(34628173953, 129);
+f(68451041535, 255);
+f(68719476992, 256);
+f(68987912449, 257);
+f(137170518527, 511);
+f(137438953984, 512);
+f(137707389441, 513);
+f(274609472511, 1023);
+f(274877907968, 1024);
+f(275146343425, 1025);
+f(549487380479, 2047);
+f(549755815936, 2048);
+f(550024251393, 2049);
+f(1099243196415, 4095);
+f(1099511631872, 4096);
+f(1099780067329, 4097);
+f(2198754828287, 8191);
+f(2199023263744, 8192);
+f(2199291699201, 8193);
+f(4397778092031, 16383);
+f(4398046527488, 16384);
+f(4398314962945, 16385);
+f(8795824619519, 32767);
+f(8796093054976, 32768);
+f(8796361490433, 32769);
+f(17591917674495, 65535);
+f(17592186109952, 65536);
+f(17592454545409, 65537);
+f(35184103784447, 131071);
+f(35184372219904, 131072);
+f(35184640655361, 131073);
+f(70368476004351, 262143);
+f(70368744439808, 262144);
+f(70369012875265, 262145);
+f(140737220444159, 524287);
+f(140737488879616, 524288);
+f(140737757315073, 524289);
+f(281474709323775, 1048575);
+f(281474977759232, 1048576);
+f(281475246194689, 1048577);
+f(562949687083007, 2097151);
+f(562949955518464, 2097152);
+f(562950223953921, 2097153);
+f(1125899642601471, 4194303);
+f(1125899911036928, 4194304);
+f(1125900179472385, 4194305);
+x = 536870911;
+f(536870911, 1);
+f(1073741822, 2);
+f(1610612733, 3);
+f(2147483644, 4);
+f(2684354555, 5);
+f(3758096377, 7);
+f(4294967288, 8);
+f(4831838199, 9);
+f(8053063665, 15);
+f(8589934576, 16);
+f(9126805487, 17);
+f(16642998241, 31);
+f(17179869152, 32);
+f(17716740063, 33);
+f(33822867393, 63);
+f(34359738304, 64);
+f(34896609215, 65);
+f(68182605697, 127);
+f(68719476608, 128);
+f(69256347519, 129);
+f(136902082305, 255);
+f(137438953216, 256);
+f(137975824127, 257);
+f(274341035521, 511);
+f(274877906432, 512);
+f(275414777343, 513);
+f(549218941953, 1023);
+f(549755812864, 1024);
+f(550292683775, 1025);
+f(1098974754817, 2047);
+f(1099511625728, 2048);
+f(1100048496639, 2049);
+f(2198486380545, 4095);
+f(2199023251456, 4096);
+f(2199560122367, 4097);
+f(4397509632001, 8191);
+f(4398046502912, 8192);
+f(4398583373823, 8193);
+f(8795556134913, 16383);
+f(8796093005824, 16384);
+f(8796629876735, 16385);
+f(17591649140737, 32767);
+f(17592186011648, 32768);
+f(17592722882559, 32769);
+f(35183835152385, 65535);
+f(35184372023296, 65536);
+f(35184908894207, 65537);
+f(70368207175681, 131071);
+f(70368744046592, 131072);
+f(70369280917503, 131073);
+f(140736951222273, 262143);
+f(140737488093184, 262144);
+f(140738024964095, 262145);
+f(281474439315457, 524287);
+f(281474976186368, 524288);
+f(281475513057279, 524289);
+f(562949415501825, 1048575);
+f(562949952372736, 1048576);
+f(562950489243647, 1048577);
+f(1125899367874561, 2097151);
+f(1125899904745472, 2097152);
+f(1125900441616383, 2097153);
+x = 536870912;
+f(536870912, 1);
+f(1073741824, 2);
+f(1610612736, 3);
+f(2147483648, 4);
+f(2684354560, 5);
+f(3758096384, 7);
+f(4294967296, 8);
+f(4831838208, 9);
+f(8053063680, 15);
+f(8589934592, 16);
+f(9126805504, 17);
+f(16642998272, 31);
+f(17179869184, 32);
+f(17716740096, 33);
+f(33822867456, 63);
+f(34359738368, 64);
+f(34896609280, 65);
+f(68182605824, 127);
+f(68719476736, 128);
+f(69256347648, 129);
+f(136902082560, 255);
+f(137438953472, 256);
+f(137975824384, 257);
+f(274341036032, 511);
+f(274877906944, 512);
+f(275414777856, 513);
+f(549218942976, 1023);
+f(549755813888, 1024);
+f(550292684800, 1025);
+f(1098974756864, 2047);
+f(1099511627776, 2048);
+f(1100048498688, 2049);
+f(2198486384640, 4095);
+f(2199023255552, 4096);
+f(2199560126464, 4097);
+f(4397509640192, 8191);
+f(4398046511104, 8192);
+f(4398583382016, 8193);
+f(8795556151296, 16383);
+f(8796093022208, 16384);
+f(8796629893120, 16385);
+f(17591649173504, 32767);
+f(17592186044416, 32768);
+f(17592722915328, 32769);
+f(35183835217920, 65535);
+f(35184372088832, 65536);
+f(35184908959744, 65537);
+f(70368207306752, 131071);
+f(70368744177664, 131072);
+f(70369281048576, 131073);
+f(140736951484416, 262143);
+f(140737488355328, 262144);
+f(140738025226240, 262145);
+f(281474439839744, 524287);
+f(281474976710656, 524288);
+f(281475513581568, 524289);
+f(562949416550400, 1048575);
+f(562949953421312, 1048576);
+f(562950490292224, 1048577);
+f(1125899369971712, 2097151);
+f(1125899906842624, 2097152);
+f(1125900443713536, 2097153);
+x = 536870913;
+f(536870913, 1);
+f(1073741826, 2);
+f(1610612739, 3);
+f(2147483652, 4);
+f(2684354565, 5);
+f(3758096391, 7);
+f(4294967304, 8);
+f(4831838217, 9);
+f(8053063695, 15);
+f(8589934608, 16);
+f(9126805521, 17);
+f(16642998303, 31);
+f(17179869216, 32);
+f(17716740129, 33);
+f(33822867519, 63);
+f(34359738432, 64);
+f(34896609345, 65);
+f(68182605951, 127);
+f(68719476864, 128);
+f(69256347777, 129);
+f(136902082815, 255);
+f(137438953728, 256);
+f(137975824641, 257);
+f(274341036543, 511);
+f(274877907456, 512);
+f(275414778369, 513);
+f(549218943999, 1023);
+f(549755814912, 1024);
+f(550292685825, 1025);
+f(1098974758911, 2047);
+f(1099511629824, 2048);
+f(1100048500737, 2049);
+f(2198486388735, 4095);
+f(2199023259648, 4096);
+f(2199560130561, 4097);
+f(4397509648383, 8191);
+f(4398046519296, 8192);
+f(4398583390209, 8193);
+f(8795556167679, 16383);
+f(8796093038592, 16384);
+f(8796629909505, 16385);
+f(17591649206271, 32767);
+f(17592186077184, 32768);
+f(17592722948097, 32769);
+f(35183835283455, 65535);
+f(35184372154368, 65536);
+f(35184909025281, 65537);
+f(70368207437823, 131071);
+f(70368744308736, 131072);
+f(70369281179649, 131073);
+f(140736951746559, 262143);
+f(140737488617472, 262144);
+f(140738025488385, 262145);
+f(281474440364031, 524287);
+f(281474977234944, 524288);
+f(281475514105857, 524289);
+f(562949417598975, 1048575);
+f(562949954469888, 1048576);
+f(562950491340801, 1048577);
+f(1125899372068863, 2097151);
+f(1125899908939776, 2097152);
+f(1125900445810689, 2097153);
+x = 1073741823;
+f(1073741823, 1);
+f(2147483646, 2);
+f(3221225469, 3);
+f(4294967292, 4);
+f(5368709115, 5);
+f(7516192761, 7);
+f(8589934584, 8);
+f(9663676407, 9);
+f(16106127345, 15);
+f(17179869168, 16);
+f(18253610991, 17);
+f(33285996513, 31);
+f(34359738336, 32);
+f(35433480159, 33);
+f(67645734849, 63);
+f(68719476672, 64);
+f(69793218495, 65);
+f(136365211521, 127);
+f(137438953344, 128);
+f(138512695167, 129);
+f(273804164865, 255);
+f(274877906688, 256);
+f(275951648511, 257);
+f(548682071553, 511);
+f(549755813376, 512);
+f(550829555199, 513);
+f(1098437884929, 1023);
+f(1099511626752, 1024);
+f(1100585368575, 1025);
+f(2197949511681, 2047);
+f(2199023253504, 2048);
+f(2200096995327, 2049);
+f(4396972765185, 4095);
+f(4398046507008, 4096);
+f(4399120248831, 4097);
+f(8795019272193, 8191);
+f(8796093014016, 8192);
+f(8797166755839, 8193);
+f(17591112286209, 16383);
+f(17592186028032, 16384);
+f(17593259769855, 16385);
+f(35183298314241, 32767);
+f(35184372056064, 32768);
+f(35185445797887, 32769);
+f(70367670370305, 65535);
+f(70368744112128, 65536);
+f(70369817853951, 65537);
+f(140736414482433, 131071);
+f(140737488224256, 131072);
+f(140738561966079, 131073);
+f(281473902706689, 262143);
+f(281474976448512, 262144);
+f(281476050190335, 262145);
+f(562948879155201, 524287);
+f(562949952897024, 524288);
+f(562951026638847, 524289);
+f(1125898832052225, 1048575);
+f(1125899905794048, 1048576);
+f(1125900979535871, 1048577);
+x = 1073741824;
+f(1073741824, 1);
+f(2147483648, 2);
+f(3221225472, 3);
+f(4294967296, 4);
+f(5368709120, 5);
+f(7516192768, 7);
+f(8589934592, 8);
+f(9663676416, 9);
+f(16106127360, 15);
+f(17179869184, 16);
+f(18253611008, 17);
+f(33285996544, 31);
+f(34359738368, 32);
+f(35433480192, 33);
+f(67645734912, 63);
+f(68719476736, 64);
+f(69793218560, 65);
+f(136365211648, 127);
+f(137438953472, 128);
+f(138512695296, 129);
+f(273804165120, 255);
+f(274877906944, 256);
+f(275951648768, 257);
+f(548682072064, 511);
+f(549755813888, 512);
+f(550829555712, 513);
+f(1098437885952, 1023);
+f(1099511627776, 1024);
+f(1100585369600, 1025);
+f(2197949513728, 2047);
+f(2199023255552, 2048);
+f(2200096997376, 2049);
+f(4396972769280, 4095);
+f(4398046511104, 4096);
+f(4399120252928, 4097);
+f(8795019280384, 8191);
+f(8796093022208, 8192);
+f(8797166764032, 8193);
+f(17591112302592, 16383);
+f(17592186044416, 16384);
+f(17593259786240, 16385);
+f(35183298347008, 32767);
+f(35184372088832, 32768);
+f(35185445830656, 32769);
+f(70367670435840, 65535);
+f(70368744177664, 65536);
+f(70369817919488, 65537);
+f(140736414613504, 131071);
+f(140737488355328, 131072);
+f(140738562097152, 131073);
+f(281473902968832, 262143);
+f(281474976710656, 262144);
+f(281476050452480, 262145);
+f(562948879679488, 524287);
+f(562949953421312, 524288);
+f(562951027163136, 524289);
+f(1125898833100800, 1048575);
+f(1125899906842624, 1048576);
+f(1125900980584448, 1048577);
+x = 1073741825;
+f(1073741825, 1);
+f(2147483650, 2);
+f(3221225475, 3);
+f(4294967300, 4);
+f(5368709125, 5);
+f(7516192775, 7);
+f(8589934600, 8);
+f(9663676425, 9);
+f(16106127375, 15);
+f(17179869200, 16);
+f(18253611025, 17);
+f(33285996575, 31);
+f(34359738400, 32);
+f(35433480225, 33);
+f(67645734975, 63);
+f(68719476800, 64);
+f(69793218625, 65);
+f(136365211775, 127);
+f(137438953600, 128);
+f(138512695425, 129);
+f(273804165375, 255);
+f(274877907200, 256);
+f(275951649025, 257);
+f(548682072575, 511);
+f(549755814400, 512);
+f(550829556225, 513);
+f(1098437886975, 1023);
+f(1099511628800, 1024);
+f(1100585370625, 1025);
+f(2197949515775, 2047);
+f(2199023257600, 2048);
+f(2200096999425, 2049);
+f(4396972773375, 4095);
+f(4398046515200, 4096);
+f(4399120257025, 4097);
+f(8795019288575, 8191);
+f(8796093030400, 8192);
+f(8797166772225, 8193);
+f(17591112318975, 16383);
+f(17592186060800, 16384);
+f(17593259802625, 16385);
+f(35183298379775, 32767);
+f(35184372121600, 32768);
+f(35185445863425, 32769);
+f(70367670501375, 65535);
+f(70368744243200, 65536);
+f(70369817985025, 65537);
+f(140736414744575, 131071);
+f(140737488486400, 131072);
+f(140738562228225, 131073);
+f(281473903230975, 262143);
+f(281474976972800, 262144);
+f(281476050714625, 262145);
+f(562948880203775, 524287);
+f(562949953945600, 524288);
+f(562951027687425, 524289);
+f(1125898834149375, 1048575);
+f(1125899907891200, 1048576);
+f(1125900981633025, 1048577);
+x = 2147483647;
+f(2147483647, 1);
+f(4294967294, 2);
+f(6442450941, 3);
+f(8589934588, 4);
+f(10737418235, 5);
+f(15032385529, 7);
+f(17179869176, 8);
+f(19327352823, 9);
+f(32212254705, 15);
+f(34359738352, 16);
+f(36507221999, 17);
+f(66571993057, 31);
+f(68719476704, 32);
+f(70866960351, 33);
+f(135291469761, 63);
+f(137438953408, 64);
+f(139586437055, 65);
+f(272730423169, 127);
+f(274877906816, 128);
+f(277025390463, 129);
+f(547608329985, 255);
+f(549755813632, 256);
+f(551903297279, 257);
+f(1097364143617, 511);
+f(1099511627264, 512);
+f(1101659110911, 513);
+f(2196875770881, 1023);
+f(2199023254528, 1024);
+f(2201170738175, 1025);
+f(4395899025409, 2047);
+f(4398046509056, 2048);
+f(4400193992703, 2049);
+f(8793945534465, 4095);
+f(8796093018112, 4096);
+f(8798240501759, 4097);
+f(17590038552577, 8191);
+f(17592186036224, 8192);
+f(17594333519871, 8193);
+f(35182224588801, 16383);
+f(35184372072448, 16384);
+f(35186519556095, 16385);
+f(70366596661249, 32767);
+f(70368744144896, 32768);
+f(70370891628543, 32769);
+f(140735340806145, 65535);
+f(140737488289792, 65536);
+f(140739635773439, 65537);
+f(281472829095937, 131071);
+f(281474976579584, 131072);
+f(281477124063231, 131073);
+f(562947805675521, 262143);
+f(562949953159168, 262144);
+f(562952100642815, 262145);
+f(1125897758834689, 524287);
+f(1125899906318336, 524288);
+f(1125902053801983, 524289);
+x = 2147483648;
+f(2147483648, 1);
+f(4294967296, 2);
+f(6442450944, 3);
+f(8589934592, 4);
+f(10737418240, 5);
+f(15032385536, 7);
+f(17179869184, 8);
+f(19327352832, 9);
+f(32212254720, 15);
+f(34359738368, 16);
+f(36507222016, 17);
+f(66571993088, 31);
+f(68719476736, 32);
+f(70866960384, 33);
+f(135291469824, 63);
+f(137438953472, 64);
+f(139586437120, 65);
+f(272730423296, 127);
+f(274877906944, 128);
+f(277025390592, 129);
+f(547608330240, 255);
+f(549755813888, 256);
+f(551903297536, 257);
+f(1097364144128, 511);
+f(1099511627776, 512);
+f(1101659111424, 513);
+f(2196875771904, 1023);
+f(2199023255552, 1024);
+f(2201170739200, 1025);
+f(4395899027456, 2047);
+f(4398046511104, 2048);
+f(4400193994752, 2049);
+f(8793945538560, 4095);
+f(8796093022208, 4096);
+f(8798240505856, 4097);
+f(17590038560768, 8191);
+f(17592186044416, 8192);
+f(17594333528064, 8193);
+f(35182224605184, 16383);
+f(35184372088832, 16384);
+f(35186519572480, 16385);
+f(70366596694016, 32767);
+f(70368744177664, 32768);
+f(70370891661312, 32769);
+f(140735340871680, 65535);
+f(140737488355328, 65536);
+f(140739635838976, 65537);
+f(281472829227008, 131071);
+f(281474976710656, 131072);
+f(281477124194304, 131073);
+f(562947805937664, 262143);
+f(562949953421312, 262144);
+f(562952100904960, 262145);
+f(1125897759358976, 524287);
+f(1125899906842624, 524288);
+f(1125902054326272, 524289);
+x = 2147483649;
+f(2147483649, 1);
+f(4294967298, 2);
+f(6442450947, 3);
+f(8589934596, 4);
+f(10737418245, 5);
+f(15032385543, 7);
+f(17179869192, 8);
+f(19327352841, 9);
+f(32212254735, 15);
+f(34359738384, 16);
+f(36507222033, 17);
+f(66571993119, 31);
+f(68719476768, 32);
+f(70866960417, 33);
+f(135291469887, 63);
+f(137438953536, 64);
+f(139586437185, 65);
+f(272730423423, 127);
+f(274877907072, 128);
+f(277025390721, 129);
+f(547608330495, 255);
+f(549755814144, 256);
+f(551903297793, 257);
+f(1097364144639, 511);
+f(1099511628288, 512);
+f(1101659111937, 513);
+f(2196875772927, 1023);
+f(2199023256576, 1024);
+f(2201170740225, 1025);
+f(4395899029503, 2047);
+f(4398046513152, 2048);
+f(4400193996801, 2049);
+f(8793945542655, 4095);
+f(8796093026304, 4096);
+f(8798240509953, 4097);
+f(17590038568959, 8191);
+f(17592186052608, 8192);
+f(17594333536257, 8193);
+f(35182224621567, 16383);
+f(35184372105216, 16384);
+f(35186519588865, 16385);
+f(70366596726783, 32767);
+f(70368744210432, 32768);
+f(70370891694081, 32769);
+f(140735340937215, 65535);
+f(140737488420864, 65536);
+f(140739635904513, 65537);
+f(281472829358079, 131071);
+f(281474976841728, 131072);
+f(281477124325377, 131073);
+f(562947806199807, 262143);
+f(562949953683456, 262144);
+f(562952101167105, 262145);
+f(1125897759883263, 524287);
+f(1125899907366912, 524288);
+f(1125902054850561, 524289);
+x = 4294967295;
+f(4294967295, 1);
+f(8589934590, 2);
+f(12884901885, 3);
+f(17179869180, 4);
+f(21474836475, 5);
+f(30064771065, 7);
+f(34359738360, 8);
+f(38654705655, 9);
+f(64424509425, 15);
+f(68719476720, 16);
+f(73014444015, 17);
+f(133143986145, 31);
+f(137438953440, 32);
+f(141733920735, 33);
+f(270582939585, 63);
+f(274877906880, 64);
+f(279172874175, 65);
+f(545460846465, 127);
+f(549755813760, 128);
+f(554050781055, 129);
+f(1095216660225, 255);
+f(1099511627520, 256);
+f(1103806594815, 257);
+f(2194728287745, 511);
+f(2199023255040, 512);
+f(2203318222335, 513);
+f(4393751542785, 1023);
+f(4398046510080, 1024);
+f(4402341477375, 1025);
+f(8791798052865, 2047);
+f(8796093020160, 2048);
+f(8800387987455, 2049);
+f(17587891073025, 4095);
+f(17592186040320, 4096);
+f(17596481007615, 4097);
+f(35180077113345, 8191);
+f(35184372080640, 8192);
+f(35188667047935, 8193);
+f(70364449193985, 16383);
+f(70368744161280, 16384);
+f(70373039128575, 16385);
+f(140733193355265, 32767);
+f(140737488322560, 32768);
+f(140741783289855, 32769);
+f(281470681677825, 65535);
+f(281474976645120, 65536);
+f(281479271612415, 65537);
+f(562945658322945, 131071);
+f(562949953290240, 131072);
+f(562954248257535, 131073);
+f(1125895611613185, 262143);
+f(1125899906580480, 262144);
+f(1125904201547775, 262145);
+x = 4294967296;
+f(4294967296, 1);
+f(8589934592, 2);
+f(12884901888, 3);
+f(17179869184, 4);
+f(21474836480, 5);
+f(30064771072, 7);
+f(34359738368, 8);
+f(38654705664, 9);
+f(64424509440, 15);
+f(68719476736, 16);
+f(73014444032, 17);
+f(133143986176, 31);
+f(137438953472, 32);
+f(141733920768, 33);
+f(270582939648, 63);
+f(274877906944, 64);
+f(279172874240, 65);
+f(545460846592, 127);
+f(549755813888, 128);
+f(554050781184, 129);
+f(1095216660480, 255);
+f(1099511627776, 256);
+f(1103806595072, 257);
+f(2194728288256, 511);
+f(2199023255552, 512);
+f(2203318222848, 513);
+f(4393751543808, 1023);
+f(4398046511104, 1024);
+f(4402341478400, 1025);
+f(8791798054912, 2047);
+f(8796093022208, 2048);
+f(8800387989504, 2049);
+f(17587891077120, 4095);
+f(17592186044416, 4096);
+f(17596481011712, 4097);
+f(35180077121536, 8191);
+f(35184372088832, 8192);
+f(35188667056128, 8193);
+f(70364449210368, 16383);
+f(70368744177664, 16384);
+f(70373039144960, 16385);
+f(140733193388032, 32767);
+f(140737488355328, 32768);
+f(140741783322624, 32769);
+f(281470681743360, 65535);
+f(281474976710656, 65536);
+f(281479271677952, 65537);
+f(562945658454016, 131071);
+f(562949953421312, 131072);
+f(562954248388608, 131073);
+f(1125895611875328, 262143);
+f(1125899906842624, 262144);
+f(1125904201809920, 262145);
+x = 4294967297;
+f(4294967297, 1);
+f(8589934594, 2);
+f(12884901891, 3);
+f(17179869188, 4);
+f(21474836485, 5);
+f(30064771079, 7);
+f(34359738376, 8);
+f(38654705673, 9);
+f(64424509455, 15);
+f(68719476752, 16);
+f(73014444049, 17);
+f(133143986207, 31);
+f(137438953504, 32);
+f(141733920801, 33);
+f(270582939711, 63);
+f(274877907008, 64);
+f(279172874305, 65);
+f(545460846719, 127);
+f(549755814016, 128);
+f(554050781313, 129);
+f(1095216660735, 255);
+f(1099511628032, 256);
+f(1103806595329, 257);
+f(2194728288767, 511);
+f(2199023256064, 512);
+f(2203318223361, 513);
+f(4393751544831, 1023);
+f(4398046512128, 1024);
+f(4402341479425, 1025);
+f(8791798056959, 2047);
+f(8796093024256, 2048);
+f(8800387991553, 2049);
+f(17587891081215, 4095);
+f(17592186048512, 4096);
+f(17596481015809, 4097);
+f(35180077129727, 8191);
+f(35184372097024, 8192);
+f(35188667064321, 8193);
+f(70364449226751, 16383);
+f(70368744194048, 16384);
+f(70373039161345, 16385);
+f(140733193420799, 32767);
+f(140737488388096, 32768);
+f(140741783355393, 32769);
+f(281470681808895, 65535);
+f(281474976776192, 65536);
+f(281479271743489, 65537);
+f(562945658585087, 131071);
+f(562949953552384, 131072);
+f(562954248519681, 131073);
+f(1125895612137471, 262143);
+f(1125899907104768, 262144);
+f(1125904202072065, 262145);
+x = 8589934591;
+f(8589934591, 1);
+f(17179869182, 2);
+f(25769803773, 3);
+f(34359738364, 4);
+f(42949672955, 5);
+f(60129542137, 7);
+f(68719476728, 8);
+f(77309411319, 9);
+f(128849018865, 15);
+f(137438953456, 16);
+f(146028888047, 17);
+f(266287972321, 31);
+f(274877906912, 32);
+f(283467841503, 33);
+f(541165879233, 63);
+f(549755813824, 64);
+f(558345748415, 65);
+f(1090921693057, 127);
+f(1099511627648, 128);
+f(1108101562239, 129);
+f(2190433320705, 255);
+f(2199023255296, 256);
+f(2207613189887, 257);
+f(4389456576001, 511);
+f(4398046510592, 512);
+f(4406636445183, 513);
+f(8787503086593, 1023);
+f(8796093021184, 1024);
+f(8804682955775, 1025);
+f(17583596107777, 2047);
+f(17592186042368, 2048);
+f(17600775976959, 2049);
+f(35175782150145, 4095);
+f(35184372084736, 4096);
+f(35192962019327, 4097);
+f(70360154234881, 8191);
+f(70368744169472, 8192);
+f(70377334104063, 8193);
+f(140728898404353, 16383);
+f(140737488338944, 16384);
+f(140746078273535, 16385);
+f(281466386743297, 32767);
+f(281474976677888, 32768);
+f(281483566612479, 32769);
+f(562941363421185, 65535);
+f(562949953355776, 65536);
+f(562958543290367, 65537);
+f(1125891316776961, 131071);
+f(1125899906711552, 131072);
+f(1125908496646143, 131073);
+x = 8589934592;
+f(8589934592, 1);
+f(17179869184, 2);
+f(25769803776, 3);
+f(34359738368, 4);
+f(42949672960, 5);
+f(60129542144, 7);
+f(68719476736, 8);
+f(77309411328, 9);
+f(128849018880, 15);
+f(137438953472, 16);
+f(146028888064, 17);
+f(266287972352, 31);
+f(274877906944, 32);
+f(283467841536, 33);
+f(541165879296, 63);
+f(549755813888, 64);
+f(558345748480, 65);
+f(1090921693184, 127);
+f(1099511627776, 128);
+f(1108101562368, 129);
+f(2190433320960, 255);
+f(2199023255552, 256);
+f(2207613190144, 257);
+f(4389456576512, 511);
+f(4398046511104, 512);
+f(4406636445696, 513);
+f(8787503087616, 1023);
+f(8796093022208, 1024);
+f(8804682956800, 1025);
+f(17583596109824, 2047);
+f(17592186044416, 2048);
+f(17600775979008, 2049);
+f(35175782154240, 4095);
+f(35184372088832, 4096);
+f(35192962023424, 4097);
+f(70360154243072, 8191);
+f(70368744177664, 8192);
+f(70377334112256, 8193);
+f(140728898420736, 16383);
+f(140737488355328, 16384);
+f(140746078289920, 16385);
+f(281466386776064, 32767);
+f(281474976710656, 32768);
+f(281483566645248, 32769);
+f(562941363486720, 65535);
+f(562949953421312, 65536);
+f(562958543355904, 65537);
+f(1125891316908032, 131071);
+f(1125899906842624, 131072);
+f(1125908496777216, 131073);
+x = 8589934593;
+f(8589934593, 1);
+f(17179869186, 2);
+f(25769803779, 3);
+f(34359738372, 4);
+f(42949672965, 5);
+f(60129542151, 7);
+f(68719476744, 8);
+f(77309411337, 9);
+f(128849018895, 15);
+f(137438953488, 16);
+f(146028888081, 17);
+f(266287972383, 31);
+f(274877906976, 32);
+f(283467841569, 33);
+f(541165879359, 63);
+f(549755813952, 64);
+f(558345748545, 65);
+f(1090921693311, 127);
+f(1099511627904, 128);
+f(1108101562497, 129);
+f(2190433321215, 255);
+f(2199023255808, 256);
+f(2207613190401, 257);
+f(4389456577023, 511);
+f(4398046511616, 512);
+f(4406636446209, 513);
+f(8787503088639, 1023);
+f(8796093023232, 1024);
+f(8804682957825, 1025);
+f(17583596111871, 2047);
+f(17592186046464, 2048);
+f(17600775981057, 2049);
+f(35175782158335, 4095);
+f(35184372092928, 4096);
+f(35192962027521, 4097);
+f(70360154251263, 8191);
+f(70368744185856, 8192);
+f(70377334120449, 8193);
+f(140728898437119, 16383);
+f(140737488371712, 16384);
+f(140746078306305, 16385);
+f(281466386808831, 32767);
+f(281474976743424, 32768);
+f(281483566678017, 32769);
+f(562941363552255, 65535);
+f(562949953486848, 65536);
+f(562958543421441, 65537);
+f(1125891317039103, 131071);
+f(1125899906973696, 131072);
+f(1125908496908289, 131073);
+x = 17179869183;
+f(17179869183, 1);
+f(34359738366, 2);
+f(51539607549, 3);
+f(68719476732, 4);
+f(85899345915, 5);
+f(120259084281, 7);
+f(137438953464, 8);
+f(154618822647, 9);
+f(257698037745, 15);
+f(274877906928, 16);
+f(292057776111, 17);
+f(532575944673, 31);
+f(549755813856, 32);
+f(566935683039, 33);
+f(1082331758529, 63);
+f(1099511627712, 64);
+f(1116691496895, 65);
+f(2181843386241, 127);
+f(2199023255424, 128);
+f(2216203124607, 129);
+f(4380866641665, 255);
+f(4398046510848, 256);
+f(4415226380031, 257);
+f(8778913152513, 511);
+f(8796093021696, 512);
+f(8813272890879, 513);
+f(17575006174209, 1023);
+f(17592186043392, 1024);
+f(17609365912575, 1025);
+f(35167192217601, 2047);
+f(35184372086784, 2048);
+f(35201551955967, 2049);
+f(70351564304385, 4095);
+f(70368744173568, 4096);
+f(70385924042751, 4097);
+f(140720308477953, 8191);
+f(140737488347136, 8192);
+f(140754668216319, 8193);
+f(281457796825089, 16383);
+f(281474976694272, 16384);
+f(281492156563455, 16385);
+f(562932773519361, 32767);
+f(562949953388544, 32768);
+f(562967133257727, 32769);
+f(1125882726907905, 65535);
+f(1125899906777088, 65536);
+f(1125917086646271, 65537);
+x = 17179869184;
+f(17179869184, 1);
+f(34359738368, 2);
+f(51539607552, 3);
+f(68719476736, 4);
+f(85899345920, 5);
+f(120259084288, 7);
+f(137438953472, 8);
+f(154618822656, 9);
+f(257698037760, 15);
+f(274877906944, 16);
+f(292057776128, 17);
+f(532575944704, 31);
+f(549755813888, 32);
+f(566935683072, 33);
+f(1082331758592, 63);
+f(1099511627776, 64);
+f(1116691496960, 65);
+f(2181843386368, 127);
+f(2199023255552, 128);
+f(2216203124736, 129);
+f(4380866641920, 255);
+f(4398046511104, 256);
+f(4415226380288, 257);
+f(8778913153024, 511);
+f(8796093022208, 512);
+f(8813272891392, 513);
+f(17575006175232, 1023);
+f(17592186044416, 1024);
+f(17609365913600, 1025);
+f(35167192219648, 2047);
+f(35184372088832, 2048);
+f(35201551958016, 2049);
+f(70351564308480, 4095);
+f(70368744177664, 4096);
+f(70385924046848, 4097);
+f(140720308486144, 8191);
+f(140737488355328, 8192);
+f(140754668224512, 8193);
+f(281457796841472, 16383);
+f(281474976710656, 16384);
+f(281492156579840, 16385);
+f(562932773552128, 32767);
+f(562949953421312, 32768);
+f(562967133290496, 32769);
+f(1125882726973440, 65535);
+f(1125899906842624, 65536);
+f(1125917086711808, 65537);
+x = 17179869185;
+f(17179869185, 1);
+f(34359738370, 2);
+f(51539607555, 3);
+f(68719476740, 4);
+f(85899345925, 5);
+f(120259084295, 7);
+f(137438953480, 8);
+f(154618822665, 9);
+f(257698037775, 15);
+f(274877906960, 16);
+f(292057776145, 17);
+f(532575944735, 31);
+f(549755813920, 32);
+f(566935683105, 33);
+f(1082331758655, 63);
+f(1099511627840, 64);
+f(1116691497025, 65);
+f(2181843386495, 127);
+f(2199023255680, 128);
+f(2216203124865, 129);
+f(4380866642175, 255);
+f(4398046511360, 256);
+f(4415226380545, 257);
+f(8778913153535, 511);
+f(8796093022720, 512);
+f(8813272891905, 513);
+f(17575006176255, 1023);
+f(17592186045440, 1024);
+f(17609365914625, 1025);
+f(35167192221695, 2047);
+f(35184372090880, 2048);
+f(35201551960065, 2049);
+f(70351564312575, 4095);
+f(70368744181760, 4096);
+f(70385924050945, 4097);
+f(140720308494335, 8191);
+f(140737488363520, 8192);
+f(140754668232705, 8193);
+f(281457796857855, 16383);
+f(281474976727040, 16384);
+f(281492156596225, 16385);
+f(562932773584895, 32767);
+f(562949953454080, 32768);
+f(562967133323265, 32769);
+f(1125882727038975, 65535);
+f(1125899906908160, 65536);
+f(1125917086777345, 65537);
diff --git a/deps/v8/test/mjsunit/multiple-return.js b/deps/v8/test/mjsunit/multiple-return.js
new file mode 100644
index 0000000..610a367
--- /dev/null
+++ b/deps/v8/test/mjsunit/multiple-return.js
@@ -0,0 +1,62 @@
+// 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.
+
+function F() {
+  for (var x in [1,2,3]) {
+    return 42;
+  }
+  return 87;
+}
+
+
+function G() {
+  for (var x in [1,2,3]) {
+    try {
+      return 42;
+    } finally {
+      // Do nothing.
+    }
+  }
+  return 87;
+}
+
+
+function H() {
+  for (var x in [1,2,3]) {
+    try {
+      return 42;
+    } catch (e) {
+      // Do nothing.
+    }
+  }
+  return 87;
+}
+
+
+assertEquals(42, F());
+assertEquals(42, G());
+assertEquals(42, H());
diff --git a/deps/v8/test/mjsunit/negate-zero.js b/deps/v8/test/mjsunit/negate-zero.js
new file mode 100644
index 0000000..31d460a
--- /dev/null
+++ b/deps/v8/test/mjsunit/negate-zero.js
@@ -0,0 +1,42 @@
+// Copyright 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.
+
+function IsNegativeZero(x) {
+  assertEquals(0, x);
+  var y = 1 / x;
+  assertFalse(isFinite(y));
+  return y < 0;
+}
+
+var pz = 0;
+var nz = -0;
+
+assertTrue(IsNegativeZero(nz), "-0");
+assertFalse(IsNegativeZero(-nz), "-(-0)");
+
+assertFalse(IsNegativeZero(pz), "0");
+assertTrue(IsNegativeZero(-pz), "-(0)");
diff --git a/deps/v8/test/mjsunit/negate.js b/deps/v8/test/mjsunit/negate.js
new file mode 100644
index 0000000..3bf4111
--- /dev/null
+++ b/deps/v8/test/mjsunit/negate.js
@@ -0,0 +1,59 @@
+// Copyright 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.
+
+const SMI_MAX = (1 << 30) - 1;
+const SMI_MIN = -(1 << 30);
+
+function testmulneg(a, b) {
+  var base = a * b;
+  assertEquals(-base, a * -b);
+  assertEquals(-base, -a * b);
+  assertEquals(base, -a * -b);
+}
+
+testmulneg(2, 3);
+testmulneg(SMI_MAX, 3);
+testmulneg(SMI_MIN, 3);
+testmulneg(3.2, 2.3);
+
+var x = { valueOf: function() { return 2; } };
+var y = { valueOf: function() { return 3; } };
+
+testmulneg(x, y);
+
+// The test below depends on the correct evaluation order, which is not
+// implemented by any of the known JS engines.
+var z;
+var v = { valueOf: function() { z+=2; return z; } };
+var w = { valueOf: function() { z+=3; return z; } };
+
+z = 0;
+var base = v * w;
+z = 0;
+assertEquals(-base, -v * w);
+z = 0;
+assertEquals(base, -v * -w);
diff --git a/deps/v8/test/mjsunit/new.js b/deps/v8/test/mjsunit/new.js
new file mode 100644
index 0000000..1062628
--- /dev/null
+++ b/deps/v8/test/mjsunit/new.js
@@ -0,0 +1,56 @@
+// Copyright 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.
+
+function Construct(x) { return x; }
+
+assertFalse(null == new Construct(null));
+assertFalse(void 0 == new Construct(void 0));
+assertFalse(0 == new Construct(0));
+assertFalse(1 == new Construct(1));
+assertFalse(4.2 == new Construct(4.2));
+assertFalse('foo' == new Construct('foo'));
+assertFalse(true == new Construct(true));
+
+x = {};
+assertTrue(x === new Construct(x));
+assertFalse(x === new Construct(null));
+assertFalse(x === new Construct(void 0));
+assertFalse(x === new Construct(1));
+assertFalse(x === new Construct(3.2));
+assertFalse(x === new Construct(false));
+assertFalse(x === new Construct('bar'));
+x = [];
+assertTrue(x === new Construct(x));
+x = new Boolean(true);
+assertTrue(x === new Construct(x));
+x = new Number(42);
+assertTrue(x === new Construct(x));
+x = new String('foo');
+assertTrue(x === new Construct(x));
+x = function() { };
+assertTrue(x === new Construct(x));
+
diff --git a/deps/v8/test/mjsunit/newline-in-string.js b/deps/v8/test/mjsunit/newline-in-string.js
new file mode 100644
index 0000000..8c3ff86
--- /dev/null
+++ b/deps/v8/test/mjsunit/newline-in-string.js
@@ -0,0 +1,46 @@
+// Copyright 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.
+
+// Test multiline string literal.
+var str = 'asdf\
+\nasdf\
+\rasdf\
+\tasdf\
+\\\
+\
+';
+assertEquals('asdf\nasdf\rasdf\tasdf\\', str);
+
+// Allow CR+LF in multiline string literals.
+var code = "'asdf\\" + String.fromCharCode(0xD) + String.fromCharCode(0xA) + "asdf'";
+assertEquals('asdfasdf', eval(code));
+
+// Allow LF+CR in multiline string literals.
+code = "'asdf\\" + String.fromCharCode(0xA) + String.fromCharCode(0xD) + "asdf'";
+assertEquals('asdfasdf', eval(code));
+
+
diff --git a/deps/v8/test/mjsunit/no-branch-elimination.js b/deps/v8/test/mjsunit/no-branch-elimination.js
new file mode 100644
index 0000000..538039b
--- /dev/null
+++ b/deps/v8/test/mjsunit/no-branch-elimination.js
@@ -0,0 +1,36 @@
+// Copyright 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.
+
+// Branch elimination on ARM build eliminate bl branches. It was wrong.
+
+if (1 & true) { }
+
+try {
+  throw "error";
+} catch (e) {
+  assertEquals("error", e);
+}
diff --git a/deps/v8/test/mjsunit/no-octal-constants-above-256.js b/deps/v8/test/mjsunit/no-octal-constants-above-256.js
new file mode 100644
index 0000000..1525d6a
--- /dev/null
+++ b/deps/v8/test/mjsunit/no-octal-constants-above-256.js
@@ -0,0 +1,32 @@
+// Copyright 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.
+
+// Octal constants above \377 should not be allowed; instead they
+// should parse as two-digit octals constants followed by digits.
+assertEquals(2, "\400".length);
+assertEquals("\40".charCodeAt(0), "\400".charCodeAt(0));
+assertEquals("0", "\400".charAt(1));
diff --git a/deps/v8/test/mjsunit/no-semicolon.js b/deps/v8/test/mjsunit/no-semicolon.js
new file mode 100644
index 0000000..fa6ccba
--- /dev/null
+++ b/deps/v8/test/mjsunit/no-semicolon.js
@@ -0,0 +1,45 @@
+// Copyright 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.
+
+// Random tests to make sure you can leave out semicolons
+// in various places.
+
+function f() { return }
+
+function g() { 
+  return
+    4;
+}
+
+assertTrue(f() === void 0);
+assertTrue(g() === void 0);
+
+for (var i = 0; i < 10; i++) { break }
+assertEquals(0, i);
+
+for (var i = 0; i < 10; i++) { continue }
+assertEquals(10, i);
\ No newline at end of file
diff --git a/deps/v8/test/mjsunit/non-ascii-replace.js b/deps/v8/test/mjsunit/non-ascii-replace.js
new file mode 100644
index 0000000..2ccaed1
--- /dev/null
+++ b/deps/v8/test/mjsunit/non-ascii-replace.js
@@ -0,0 +1,30 @@
+// Copyright 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.
+
+// Regression test for bug #743664.
+assertEquals("uu", "\x60\x60".replace(/\x60/g, "u"));
+assertEquals("uu", "\xAB\xAB".replace(/\xAB/g, "u"));
diff --git a/deps/v8/test/mjsunit/nul-characters.js b/deps/v8/test/mjsunit/nul-characters.js
new file mode 100644
index 0000000..22da82d
--- /dev/null
+++ b/deps/v8/test/mjsunit/nul-characters.js
@@ -0,0 +1,38 @@
+// Copyright 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.
+
+var a = [ '\0', '\u0000', '\x00' ]
+for (var i in a) {
+  assertEquals(1, a[i].length);
+  assertEquals(0, a[i].charCodeAt(0));
+}
+
+assertEquals(7, 'foo\0bar'.length);
+assertEquals(7, 'foo\x00bar'.length);
+assertEquals(7, 'foo\u0000bar'.length);
+
+assertEquals(2, ('\0' + '\0').length);
diff --git a/deps/v8/test/mjsunit/number-limits.js b/deps/v8/test/mjsunit/number-limits.js
new file mode 100644
index 0000000..1d9a1e5
--- /dev/null
+++ b/deps/v8/test/mjsunit/number-limits.js
@@ -0,0 +1,43 @@
+// Copyright 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.
+
+// Ensure that Number.MAX_VALUE and Number.MIN_VALUE are extreme.
+function testLimits() {
+  var i; var eps;
+  for (i = 0, eps = 1; i < 1100; i++, eps /= 2) {
+    var mulAboveMax = Number.MAX_VALUE * (1 + eps);
+    var addAboveMax = Number.MAX_VALUE + 1/eps;
+    var mulBelowMin = Number.MIN_VALUE * (1 - eps);
+    var addBelowMin = Number.MIN_VALUE - eps;
+    assertTrue(mulAboveMax == Number.MAX_VALUE || mulAboveMax == Infinity);
+    assertTrue(addAboveMax == Number.MAX_VALUE || addAboveMax == Infinity);
+    assertTrue(mulBelowMin == Number.MIN_VALUE || mulBelowMin <= 0);
+    assertTrue(addBelowMin == Number.MIN_VALUE || addBelowMin <= 0);
+  }
+}
+
+testLimits();
diff --git a/deps/v8/test/mjsunit/number-string-index-call.js b/deps/v8/test/mjsunit/number-string-index-call.js
new file mode 100644
index 0000000..6f540c0
--- /dev/null
+++ b/deps/v8/test/mjsunit/number-string-index-call.js
@@ -0,0 +1,32 @@
+// Copyright 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.
+
+// Flags: --call_regexp
+var callbacks = [ function() {return 'foo'}, "nonobject", /abc/ ];
+assertEquals('foo', callbacks['0']());
+assertThrows("callbacks['1']()");
+assertEquals('abc', callbacks['2']("abcdefg"));
diff --git a/deps/v8/test/mjsunit/number-tostring-small.js b/deps/v8/test/mjsunit/number-tostring-small.js
new file mode 100644
index 0000000..dbd2b59
--- /dev/null
+++ b/deps/v8/test/mjsunit/number-tostring-small.js
@@ -0,0 +1,395 @@
+// Copyright 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.
+
+// This file is a concatenation of the number-tostring and
+// to-precision mjsunit tests where the mjsunit assert code has been
+// removed.
+
+// ----------------------------------------------------------------------
+// toString
+(NaN).toString();
+(1/0).toString();
+(-1/0).toString();
+(0).toString();
+(9).toString();
+(90).toString();
+(90.12).toString();
+(0.1).toString();
+(0.01).toString();
+(0.0123).toString();
+(111111111111111111111).toString();
+(1111111111111111111111).toString();
+(11111111111111111111111).toString();
+(0.00001).toString();
+(0.000001).toString();
+(0.0000001).toString();
+(0.00000012).toString();
+(0.000000123).toString();
+(0.00000001).toString();
+(0.000000012).toString();
+(0.0000000123).toString();
+
+(-0).toString();
+(-9).toString();
+(-90).toString();
+(-90.12).toString();
+(-0.1).toString();
+(-0.01).toString();
+(-0.0123).toString();
+(-111111111111111111111).toString();
+(-1111111111111111111111).toString();
+(-11111111111111111111111).toString();
+(-0.00001).toString();
+(-0.000001).toString();
+(-0.0000001).toString();
+(-0.00000012).toString();
+(-0.000000123).toString();
+(-0.00000001).toString();
+(-0.000000012).toString();
+(-0.0000000123).toString();
+
+(NaN).toString(16);
+(1/0).toString(16);
+(-1/0).toString(16);
+(0).toString(16);
+(9).toString(16);
+(90).toString(16);
+(90.12).toString(16);
+(0.1).toString(16);
+(0.01).toString(16);
+(0.0123).toString(16);
+(111111111111111111111).toString(16);
+(1111111111111111111111).toString(16);
+(11111111111111111111111).toString(16);
+(0.00001).toString(16);
+(0.000001).toString(16);
+(0.0000001).toString(16);
+(0.00000012).toString(16);
+(0.000000123).toString(16);
+(0.00000001).toString(16);
+(0.000000012).toString(16);
+(0.0000000123).toString(16);
+
+(-0).toString(16);
+(-9).toString(16);
+(-90).toString(16);
+(-90.12).toString(16);
+(-0.1).toString(16);
+(-0.01).toString(16);
+(-0.0123).toString(16);
+(-111111111111111111111).toString(16);
+(-1111111111111111111111).toString(16);
+(-11111111111111111111111).toString(16);
+(-0.00001).toString(16);
+(-0.000001).toString(16);
+(-0.0000001).toString(16);
+(-0.00000012).toString(16);
+(-0.000000123).toString(16);
+(-0.00000001).toString(16);
+(-0.000000012).toString(16);
+(-0.0000000123).toString(16);
+
+(2,32).toString();
+(Math.pow(2,32)-1).toString(16);
+(Math.pow(2,32)-1).toString(2);
+(10000007).toString(36);
+(0).toString(36);
+(0).toString(16);
+(0).toString(10);
+(0).toString(8);
+(0).toString(2);
+(2,32).toString(2);
+(Math.pow(2,32) + 1).toString(2);
+(0x100000000000081).toString(16);
+(-(-'0x1000000000000081')).toString(16);
+(0x100000000000081).toString(2);
+(-(Math.pow(2,32)-1)).toString(2);
+(-10000007).toString(36);
+(-Math.pow(2,32)).toString(2);
+(-(Math.pow(2,32) + 1)).toString(2);
+(-0x100000000000081).toString(16);
+(-0x100000000000081).toString(2);
+(1000).toString();
+(0.00001).toString();
+(1000000000000000128).toString();
+(1000000000000000012800).toString();
+(-1000000000000000012800).toString();
+(0.0000001).toString();
+(-0.0000001).toString();
+(1000000000000000128000).toString();
+(0.000001).toString();
+(0.0000001).toString();
+(8.5).toString(16);
+(-8.5).toString(16);
+
+// ----------------------------------------------------------------------
+// toFixed
+(NaN).toFixed(2);
+(1/0).toFixed(2);
+(-1/0).toFixed(2);
+
+(1111111111111111111111).toFixed(8);
+(0.1).toFixed(1);
+(0.1).toFixed(2);
+(0.1).toFixed(3);
+(0.01).toFixed(2);
+(0.01).toFixed(3);
+(0.01).toFixed(4);
+(0.001).toFixed(2);
+(0.001).toFixed(3);
+(0.001).toFixed(4);
+(1).toFixed(4);
+(1).toFixed(1);
+(1).toFixed(0);
+(12).toFixed(0);
+(1.1).toFixed(0);
+(12.1).toFixed(0);
+(1.12).toFixed(0);
+(12.12).toFixed(0);
+(0.0000006).toFixed(7);
+(0.00000006).toFixed(8);
+(0.00000006).toFixed(9);
+(0.00000006).toFixed(10);
+(0).toFixed(0);
+(0).toFixed(1);
+(0).toFixed(2);
+
+(-1111111111111111111111).toFixed(8);
+(-0.1).toFixed(1);
+(-0.1).toFixed(2);
+(-0.1).toFixed(3);
+(-0.01).toFixed(2);
+(-0.01).toFixed(3);
+(-0.01).toFixed(4);
+(-0.001).toFixed(2);
+(-0.001).toFixed(3);
+(-0.001).toFixed(4);
+(-1).toFixed(4);
+(-1).toFixed(1);
+(-1).toFixed(0);
+(-1.1).toFixed(0);
+(-12.1).toFixed(0);
+(-1.12).toFixed(0);
+(-12.12).toFixed(0);
+(-0.0000006).toFixed(7);
+(-0.00000006).toFixed(8);
+(-0.00000006).toFixed(9);
+(-0.00000006).toFixed(10);
+(-0).toFixed(0);
+(-0).toFixed(1);
+(-0).toFixed(2);
+
+(1000).toFixed();
+(0.00001).toFixed();
+(0.00001).toFixed(5);
+(0.0000000000000000001).toFixed(20);
+(0.00001).toFixed(17);
+(1).toFixed(17);
+(1000000000000000128).toFixed();
+(100000000000000128).toFixed(1);
+(10000000000000128).toFixed(2);
+(10000000000000128).toFixed(20);
+(0).toFixed();
+((-42).toFixed(3));
+(-1000000000000000128).toFixed();
+(-0.0000000000000000001).toFixed(20);
+(0.123123123123123).toFixed(20);
+// Test that we round up even when the last digit generated is even.
+// dtoa does not do this in its original form.
+(0.5).toFixed(0);
+(-0.5).toFixed(0);
+(1.25).toFixed(1);
+// This is bizare, but Spidermonkey and KJS behave the same.
+(234.20405).toFixed(4);
+(234.2040506).toFixed(4);
+
+// ----------------------------------------------------------------------
+// toExponential
+(1).toExponential();
+(11).toExponential();
+(112).toExponential();
+(1).toExponential(0);
+(11).toExponential(0);
+(112).toExponential(0);
+(1).toExponential(1);
+(11).toExponential(1);
+(112).toExponential(1);
+(1).toExponential(2);
+(11).toExponential(2);
+(112).toExponential(2);
+(1).toExponential(3);
+(11).toExponential(3);
+(112).toExponential(3);
+(0.1).toExponential();
+(0.11).toExponential();
+(0.112).toExponential();
+(0.1).toExponential(0);
+(0.11).toExponential(0);
+(0.112).toExponential(0);
+(0.1).toExponential(1);
+(0.11).toExponential(1);
+(0.112).toExponential(1);
+(0.1).toExponential(2);
+(0.11).toExponential(2);
+(0.112).toExponential(2);
+(0.1).toExponential(3);
+(0.11).toExponential(3);
+(0.112).toExponential(3);
+
+(-1).toExponential();
+(-11).toExponential();
+(-112).toExponential();
+(-1).toExponential(0);
+(-11).toExponential(0);
+(-112).toExponential(0);
+(-1).toExponential(1);
+(-11).toExponential(1);
+(-112).toExponential(1);
+(-1).toExponential(2);
+(-11).toExponential(2);
+(-112).toExponential(2);
+(-1).toExponential(3);
+(-11).toExponential(3);
+(-112).toExponential(3);
+(-0.1).toExponential();
+(-0.11).toExponential();
+(-0.112).toExponential();
+(-0.1).toExponential(0);
+(-0.11).toExponential(0);
+(-0.112).toExponential(0);
+(-0.1).toExponential(1);
+(-0.11).toExponential(1);
+(-0.112).toExponential(1);
+(-0.1).toExponential(2);
+(-0.11).toExponential(2);
+(-0.112).toExponential(2);
+(-0.1).toExponential(3);
+(-0.11).toExponential(3);
+(-0.112).toExponential(3);
+
+(NaN).toExponential(2);
+(Infinity).toExponential(2);
+(-Infinity).toExponential(2);
+(1).toExponential(0);
+(0).toExponential();
+(0).toExponential(2);
+(11.2356).toExponential(0);
+(11.2356).toExponential(4);
+(0.000112356).toExponential(4);
+(-0.000112356).toExponential(4);
+(0.000112356).toExponential();
+(-0.000112356).toExponential();
+
+// ----------------------------------------------------------------------
+// toPrecision
+(NaN).toPrecision(1);
+(Infinity).toPrecision(2);
+(-Infinity).toPrecision(2);
+(0.000555).toPrecision(15);
+(0.000000555).toPrecision(15);
+(-0.000000555).toPrecision(15);
+(123456789).toPrecision(1);
+(123456789).toPrecision(9);
+(123456789).toPrecision(8);
+(123456789).toPrecision(7);
+(-123456789).toPrecision(7);
+(-.0000000012345).toPrecision(2);
+(-.000000012345).toPrecision(2);
+(-.00000012345).toPrecision(2);
+(-.0000012345).toPrecision(2);
+(-.000012345).toPrecision(2);
+(-.00012345).toPrecision(2);
+(-.0012345).toPrecision(2);
+(-.012345).toPrecision(2);
+(-.12345).toPrecision(2);
+(-1.2345).toPrecision(2);
+(-12.345).toPrecision(2);
+(-123.45).toPrecision(2);
+(-1234.5).toPrecision(2);
+(-12345).toPrecision(2);
+(-12345.67).toPrecision(4);
+Number(-12344.67).toPrecision(4);
+// Test that we round up even when the last digit generated is even.
+// dtoa does not do this in its original form.
+(1.25).toPrecision(2);
+(1.35).toPrecision(2);
+
+// Test the exponential notation output.
+(1.2345e+27).toPrecision(1);
+(1.2345e+27).toPrecision(2);
+(1.2345e+27).toPrecision(3);
+(1.2345e+27).toPrecision(4);
+(1.2345e+27).toPrecision(5);
+(1.2345e+27).toPrecision(6);
+(1.2345e+27).toPrecision(7);
+
+(-1.2345e+27).toPrecision(1);
+(-1.2345e+27).toPrecision(2);
+(-1.2345e+27).toPrecision(3);
+(-1.2345e+27).toPrecision(4);
+(-1.2345e+27).toPrecision(5);
+(-1.2345e+27).toPrecision(6);
+(-1.2345e+27).toPrecision(7);
+
+
+// Test the fixed notation output.
+(7).toPrecision(1);
+(7).toPrecision(2);
+(7).toPrecision(3);
+
+(-7).toPrecision(1);
+(-7).toPrecision(2);
+(-7).toPrecision(3);
+
+(91).toPrecision(1);
+(91).toPrecision(2);
+(91).toPrecision(3);
+(91).toPrecision(4);
+
+(-91).toPrecision(1);
+(-91).toPrecision(2);
+(-91).toPrecision(3);
+(-91).toPrecision(4);
+
+(91.1234).toPrecision(1);
+(91.1234).toPrecision(2);
+(91.1234).toPrecision(3);
+(91.1234).toPrecision(4);
+(91.1234).toPrecision(5);
+(91.1234).toPrecision(6);
+(91.1234).toPrecision(7);
+(91.1234).toPrecision(8);
+
+(-91.1234).toPrecision(1);
+(-91.1234).toPrecision(2);
+(-91.1234).toPrecision(3);
+(-91.1234).toPrecision(4);
+(-91.1234).toPrecision(5);
+(-91.1234).toPrecision(6);
+(-91.1234).toPrecision(7);
+(-91.1234).toPrecision(8);
+
diff --git a/deps/v8/test/mjsunit/number-tostring.js b/deps/v8/test/mjsunit/number-tostring.js
new file mode 100644
index 0000000..04d027f
--- /dev/null
+++ b/deps/v8/test/mjsunit/number-tostring.js
@@ -0,0 +1,338 @@
+// Copyright 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.
+
+// ----------------------------------------------------------------------
+// toString
+assertEquals("NaN", (NaN).toString());
+assertEquals("Infinity", (1/0).toString());
+assertEquals("-Infinity", (-1/0).toString());
+assertEquals("0", (0).toString());
+assertEquals("9", (9).toString());
+assertEquals("90", (90).toString());
+assertEquals("90.12", (90.12).toString());
+assertEquals("0.1", (0.1).toString());
+assertEquals("0.01", (0.01).toString());
+assertEquals("0.0123", (0.0123).toString());
+assertEquals("111111111111111110000", (111111111111111111111).toString());
+assertEquals("1.1111111111111111e+21", (1111111111111111111111).toString());
+assertEquals("1.1111111111111111e+22", (11111111111111111111111).toString());
+assertEquals("0.00001", (0.00001).toString());
+assertEquals("0.000001", (0.000001).toString());
+assertEquals("1e-7", (0.0000001).toString());
+assertEquals("1.2e-7", (0.00000012).toString());
+assertEquals("1.23e-7", (0.000000123).toString());
+assertEquals("1e-8", (0.00000001).toString());
+assertEquals("1.2e-8", (0.000000012).toString());
+assertEquals("1.23e-8", (0.0000000123).toString());
+
+assertEquals("0", (-0).toString());
+assertEquals("-9", (-9).toString());
+assertEquals("-90", (-90).toString());
+assertEquals("-90.12", (-90.12).toString());
+assertEquals("-0.1", (-0.1).toString());
+assertEquals("-0.01", (-0.01).toString());
+assertEquals("-0.0123", (-0.0123).toString())
+assertEquals("-111111111111111110000", (-111111111111111111111).toString());
+assertEquals("-1.1111111111111111e+21", (-1111111111111111111111).toString());
+assertEquals("-1.1111111111111111e+22", (-11111111111111111111111).toString());
+assertEquals("-0.00001", (-0.00001).toString());
+assertEquals("-0.000001", (-0.000001).toString());
+assertEquals("-1e-7", (-0.0000001).toString());
+assertEquals("-1.2e-7", (-0.00000012).toString());
+assertEquals("-1.23e-7", (-0.000000123).toString());
+assertEquals("-1e-8", (-0.00000001).toString());
+assertEquals("-1.2e-8", (-0.000000012).toString());
+assertEquals("-1.23e-8", (-0.0000000123).toString());
+
+assertEquals("NaN", (NaN).toString(16));
+assertEquals("Infinity", (1/0).toString(16));
+assertEquals("-Infinity", (-1/0).toString(16));
+assertEquals("0", (0).toString(16));
+assertEquals("9", (9).toString(16));
+assertEquals("5a", (90).toString(16));
+assertEquals("5a.1eb851eb852", (90.12).toString(16));
+assertEquals("0.1999999999999a", (0.1).toString(16));
+assertEquals("0.028f5c28f5c28f6", (0.01).toString(16));
+assertEquals("0.032617c1bda511a", (0.0123).toString(16));
+assertEquals("605f9f6dd18bc8000", (111111111111111111111).toString(16));
+assertEquals("3c3bc3a4a2f75c0000", (1111111111111111111111).toString(16));
+assertEquals("25a55a46e5da9a00000", (11111111111111111111111).toString(16));
+assertEquals("0.0000a7c5ac471b4788", (0.00001).toString(16));
+assertEquals("0.000010c6f7a0b5ed8d", (0.000001).toString(16));
+assertEquals("0.000001ad7f29abcaf48", (0.0000001).toString(16));
+assertEquals("0.000002036565348d256", (0.00000012).toString(16));
+assertEquals("0.0000021047ee22aa466", (0.000000123).toString(16));
+assertEquals("0.0000002af31dc4611874", (0.00000001).toString(16));
+assertEquals("0.000000338a23b87483be", (0.000000012).toString(16));
+assertEquals("0.00000034d3fe36aaa0a2", (0.0000000123).toString(16));
+
+assertEquals("0", (-0).toString(16));
+assertEquals("-9", (-9).toString(16));
+assertEquals("-5a", (-90).toString(16));
+assertEquals("-5a.1eb851eb852", (-90.12).toString(16));
+assertEquals("-0.1999999999999a", (-0.1).toString(16));
+assertEquals("-0.028f5c28f5c28f6", (-0.01).toString(16));
+assertEquals("-0.032617c1bda511a", (-0.0123).toString(16));
+assertEquals("-605f9f6dd18bc8000", (-111111111111111111111).toString(16));
+assertEquals("-3c3bc3a4a2f75c0000", (-1111111111111111111111).toString(16));
+assertEquals("-25a55a46e5da9a00000", (-11111111111111111111111).toString(16));
+assertEquals("-0.0000a7c5ac471b4788", (-0.00001).toString(16));
+assertEquals("-0.000010c6f7a0b5ed8d", (-0.000001).toString(16));
+assertEquals("-0.000001ad7f29abcaf48", (-0.0000001).toString(16));
+assertEquals("-0.000002036565348d256", (-0.00000012).toString(16));
+assertEquals("-0.0000021047ee22aa466", (-0.000000123).toString(16));
+assertEquals("-0.0000002af31dc4611874", (-0.00000001).toString(16));
+assertEquals("-0.000000338a23b87483be", (-0.000000012).toString(16));
+assertEquals("-0.00000034d3fe36aaa0a2", (-0.0000000123).toString(16));
+
+assertEquals("4294967296", Math.pow(2,32).toString());
+assertEquals("ffffffff", (Math.pow(2,32)-1).toString(16));
+assertEquals("11111111111111111111111111111111", (Math.pow(2,32)-1).toString(2));
+assertEquals("5yc1z", (10000007).toString(36));
+assertEquals("0", (0).toString(36));
+assertEquals("0", (0).toString(16));
+assertEquals("0", (0).toString(10));
+assertEquals("0", (0).toString(8));
+assertEquals("0", (0).toString(2));
+assertEquals("100000000000000000000000000000000", Math.pow(2,32).toString(2));
+assertEquals("100000000000000000000000000000001", (Math.pow(2,32) + 1).toString(2));
+assertEquals("100000000000080", (0x100000000000081).toString(16));
+assertEquals("1000000000000100", (-(-'0x1000000000000081')).toString(16));
+assertEquals("100000000000000000000000000000000000000000000000010000000", (0x100000000000081).toString(2));
+assertEquals("-11111111111111111111111111111111", (-(Math.pow(2,32)-1)).toString(2));
+assertEquals("-5yc1z", (-10000007).toString(36));
+assertEquals("-100000000000000000000000000000000", (-Math.pow(2,32)).toString(2));
+assertEquals("-100000000000000000000000000000001", (-(Math.pow(2,32) + 1)).toString(2));
+assertEquals("-100000000000080", (-0x100000000000081).toString(16));
+assertEquals("-100000000000000000000000000000000000000000000000010000000", (-0x100000000000081).toString(2));
+assertEquals("1000", (1000).toString());
+assertEquals("0.00001", (0.00001).toString());
+assertEquals("1000000000000000100", (1000000000000000128).toString());
+assertEquals("1e+21", (1000000000000000012800).toString());
+assertEquals("-1e+21", (-1000000000000000012800).toString());
+assertEquals("1e-7", (0.0000001).toString());
+assertEquals("-1e-7", (-0.0000001).toString());
+assertEquals("1.0000000000000001e+21", (1000000000000000128000).toString());
+assertEquals("0.000001", (0.000001).toString());
+assertEquals("1e-7", (0.0000001).toString());
+assertEquals("8.8", (8.5).toString(16));
+assertEquals("-8.8", (-8.5).toString(16));
+
+// ----------------------------------------------------------------------
+// toFixed
+assertEquals("NaN", (NaN).toFixed(2));
+assertEquals("Infinity", (1/0).toFixed(2));
+assertEquals("-Infinity", (-1/0).toFixed(2));
+
+assertEquals("1.1111111111111111e+21", (1111111111111111111111).toFixed(8));
+assertEquals("0.1", (0.1).toFixed(1));
+assertEquals("0.10", (0.1).toFixed(2));
+assertEquals("0.100", (0.1).toFixed(3));
+assertEquals("0.01", (0.01).toFixed(2));
+assertEquals("0.010", (0.01).toFixed(3));
+assertEquals("0.0100", (0.01).toFixed(4));
+assertEquals("0.00", (0.001).toFixed(2));
+assertEquals("0.001", (0.001).toFixed(3));
+assertEquals("0.0010", (0.001).toFixed(4));
+assertEquals("1.0000", (1).toFixed(4));
+assertEquals("1.0", (1).toFixed(1));
+assertEquals("1", (1).toFixed(0));
+assertEquals("12", (12).toFixed(0));
+assertEquals("1", (1.1).toFixed(0));
+assertEquals("12", (12.1).toFixed(0));
+assertEquals("1", (1.12).toFixed(0));
+assertEquals("12", (12.12).toFixed(0));
+assertEquals("0.0000006", (0.0000006).toFixed(7));
+assertEquals("0.00000006", (0.00000006).toFixed(8));
+assertEquals("0.000000060", (0.00000006).toFixed(9));
+assertEquals("0.0000000600", (0.00000006).toFixed(10));
+assertEquals("0", (0).toFixed(0));
+assertEquals("0.0", (0).toFixed(1));
+assertEquals("0.00", (0).toFixed(2));
+
+assertEquals("-1.1111111111111111e+21", (-1111111111111111111111).toFixed(8));
+assertEquals("-0.1", (-0.1).toFixed(1));
+assertEquals("-0.10", (-0.1).toFixed(2));
+assertEquals("-0.100", (-0.1).toFixed(3));
+assertEquals("-0.01", (-0.01).toFixed(2));
+assertEquals("-0.010", (-0.01).toFixed(3));
+assertEquals("-0.0100", (-0.01).toFixed(4));
+assertEquals("-0.00", (-0.001).toFixed(2));
+assertEquals("-0.001", (-0.001).toFixed(3));
+assertEquals("-0.0010", (-0.001).toFixed(4));
+assertEquals("-1.0000", (-1).toFixed(4));
+assertEquals("-1.0", (-1).toFixed(1));
+assertEquals("-1", (-1).toFixed(0));
+assertEquals("-1", (-1.1).toFixed(0));
+assertEquals("-12", (-12.1).toFixed(0));
+assertEquals("-1", (-1.12).toFixed(0));
+assertEquals("-12", (-12.12).toFixed(0));
+assertEquals("-0.0000006", (-0.0000006).toFixed(7));
+assertEquals("-0.00000006", (-0.00000006).toFixed(8));
+assertEquals("-0.000000060", (-0.00000006).toFixed(9));
+assertEquals("-0.0000000600", (-0.00000006).toFixed(10));
+assertEquals("0", (-0).toFixed(0));
+assertEquals("0.0", (-0).toFixed(1));
+assertEquals("0.00", (-0).toFixed(2));
+
+assertEquals("1000", (1000).toFixed());
+assertEquals("0", (0.00001).toFixed());
+assertEquals("0.00001", (0.00001).toFixed(5));
+assertEquals("0.00000000000000000010", (0.0000000000000000001).toFixed(20));
+assertEquals("0.00001000000000000", (0.00001).toFixed(17));
+assertEquals("1.00000000000000000", (1).toFixed(17));
+assertEquals("1000000000000000128", (1000000000000000128).toFixed());
+assertEquals("100000000000000128.0", (100000000000000128).toFixed(1));
+assertEquals("10000000000000128.00", (10000000000000128).toFixed(2));
+assertEquals("10000000000000128.00000000000000000000", (10000000000000128).toFixed(20));
+assertEquals("0", (0).toFixed());
+assertEquals("-42.000", ((-42).toFixed(3)));
+assertEquals("-1000000000000000128", (-1000000000000000128).toFixed());
+assertEquals("-0.00000000000000000010", (-0.0000000000000000001).toFixed(20));
+assertEquals("0.12312312312312299889", (0.123123123123123).toFixed(20));
+// Test that we round up even when the last digit generated is even.
+// dtoa does not do this in its original form.
+assertEquals("1", 0.5.toFixed(0), "0.5.toFixed(0)");
+assertEquals("-1", -0.5.toFixed(0), "-0.5.toFixed(0)");
+assertEquals("1.3", 1.25.toFixed(1), "1.25.toFixed(1)");
+// This is bizare, but Spidermonkey and KJS behave the same.
+assertEquals("234.2040", (234.20405).toFixed(4), "234.2040.toFixed(4)");
+assertEquals("234.2041", (234.2040506).toFixed(4));
+
+// ----------------------------------------------------------------------
+// toExponential
+assertEquals("1e+0", (1).toExponential());
+assertEquals("1.1e+1", (11).toExponential());
+assertEquals("1.12e+2", (112).toExponential());
+assertEquals("1e+0", (1).toExponential(0));
+assertEquals("1e+1", (11).toExponential(0));
+assertEquals("1e+2", (112).toExponential(0));
+assertEquals("1.0e+0", (1).toExponential(1));
+assertEquals("1.1e+1", (11).toExponential(1));
+assertEquals("1.1e+2", (112).toExponential(1));
+assertEquals("1.00e+0", (1).toExponential(2));
+assertEquals("1.10e+1", (11).toExponential(2));
+assertEquals("1.12e+2", (112).toExponential(2));
+assertEquals("1.000e+0", (1).toExponential(3));
+assertEquals("1.100e+1", (11).toExponential(3));
+assertEquals("1.120e+2", (112).toExponential(3));
+assertEquals("1e-1", (0.1).toExponential());
+assertEquals("1.1e-1", (0.11).toExponential());
+assertEquals("1.12e-1", (0.112).toExponential());
+assertEquals("1e-1", (0.1).toExponential(0));
+assertEquals("1e-1", (0.11).toExponential(0));
+assertEquals("1e-1", (0.112).toExponential(0));
+assertEquals("1.0e-1", (0.1).toExponential(1));
+assertEquals("1.1e-1", (0.11).toExponential(1));
+assertEquals("1.1e-1", (0.112).toExponential(1));
+assertEquals("1.00e-1", (0.1).toExponential(2));
+assertEquals("1.10e-1", (0.11).toExponential(2));
+assertEquals("1.12e-1", (0.112).toExponential(2));
+assertEquals("1.000e-1", (0.1).toExponential(3));
+assertEquals("1.100e-1", (0.11).toExponential(3));
+assertEquals("1.120e-1", (0.112).toExponential(3));
+
+assertEquals("-1e+0", (-1).toExponential());
+assertEquals("-1.1e+1", (-11).toExponential());
+assertEquals("-1.12e+2", (-112).toExponential());
+assertEquals("-1e+0", (-1).toExponential(0));
+assertEquals("-1e+1", (-11).toExponential(0));
+assertEquals("-1e+2", (-112).toExponential(0));
+assertEquals("-1.0e+0", (-1).toExponential(1));
+assertEquals("-1.1e+1", (-11).toExponential(1));
+assertEquals("-1.1e+2", (-112).toExponential(1));
+assertEquals("-1.00e+0", (-1).toExponential(2));
+assertEquals("-1.10e+1", (-11).toExponential(2));
+assertEquals("-1.12e+2", (-112).toExponential(2));
+assertEquals("-1.000e+0", (-1).toExponential(3));
+assertEquals("-1.100e+1", (-11).toExponential(3));
+assertEquals("-1.120e+2", (-112).toExponential(3));
+assertEquals("-1e-1", (-0.1).toExponential());
+assertEquals("-1.1e-1", (-0.11).toExponential());
+assertEquals("-1.12e-1", (-0.112).toExponential());
+assertEquals("-1e-1", (-0.1).toExponential(0));
+assertEquals("-1e-1", (-0.11).toExponential(0));
+assertEquals("-1e-1", (-0.112).toExponential(0));
+assertEquals("-1.0e-1", (-0.1).toExponential(1));
+assertEquals("-1.1e-1", (-0.11).toExponential(1));
+assertEquals("-1.1e-1", (-0.112).toExponential(1));
+assertEquals("-1.00e-1", (-0.1).toExponential(2));
+assertEquals("-1.10e-1", (-0.11).toExponential(2));
+assertEquals("-1.12e-1", (-0.112).toExponential(2));
+assertEquals("-1.000e-1", (-0.1).toExponential(3));
+assertEquals("-1.100e-1", (-0.11).toExponential(3));
+assertEquals("-1.120e-1", (-0.112).toExponential(3));
+
+assertEquals("NaN", (NaN).toExponential(2));
+assertEquals("Infinity", (Infinity).toExponential(2));
+assertEquals("-Infinity", (-Infinity).toExponential(2));
+assertEquals("1e+0", (1).toExponential(0));
+assertEquals("0e+0", (0).toExponential());
+assertEquals("0.00e+0", (0).toExponential(2));
+assertEquals("1e+1", (11.2356).toExponential(0));
+assertEquals("1.1236e+1", (11.2356).toExponential(4));
+assertEquals("1.1236e-4", (0.000112356).toExponential(4));
+assertEquals("-1.1236e-4", (-0.000112356).toExponential(4));
+assertEquals("1.12356e-4", (0.000112356).toExponential());
+assertEquals("-1.12356e-4", (-0.000112356).toExponential());
+
+// ----------------------------------------------------------------------
+// toPrecision
+assertEquals("NaN", (NaN).toPrecision(1));
+assertEquals("Infinity", (Infinity).toPrecision(2));
+assertEquals("-Infinity", (-Infinity).toPrecision(2));
+assertEquals("0.000555000000000000", (0.000555).toPrecision(15));
+assertEquals("5.55000000000000e-7", (0.000000555).toPrecision(15));
+assertEquals("-5.55000000000000e-7", (-0.000000555).toPrecision(15));
+assertEquals("1e+8", (123456789).toPrecision(1));
+assertEquals("123456789", (123456789).toPrecision(9));
+assertEquals("1.2345679e+8", (123456789).toPrecision(8));
+assertEquals("1.234568e+8", (123456789).toPrecision(7));
+assertEquals("-1.234568e+8", (-123456789).toPrecision(7));
+assertEquals("-1.2e-9", Number(-.0000000012345).toPrecision(2));
+assertEquals("-1.2e-8", Number(-.000000012345).toPrecision(2));
+assertEquals("-1.2e-7", Number(-.00000012345).toPrecision(2));
+assertEquals("-0.0000012", Number(-.0000012345).toPrecision(2));
+assertEquals("-0.000012", Number(-.000012345).toPrecision(2));
+assertEquals("-0.00012", Number(-.00012345).toPrecision(2));
+assertEquals("-0.0012", Number(-.0012345).toPrecision(2));
+assertEquals("-0.012", Number(-.012345).toPrecision(2));
+assertEquals("-0.12", Number(-.12345).toPrecision(2));
+assertEquals("-1.2", Number(-1.2345).toPrecision(2));
+assertEquals("-12", Number(-12.345).toPrecision(2));
+assertEquals("-1.2e+2", Number(-123.45).toPrecision(2));
+assertEquals("-1.2e+3", Number(-1234.5).toPrecision(2));
+assertEquals("-1.2e+4", Number(-12345).toPrecision(2));
+assertEquals("-1.235e+4", Number(-12345.67).toPrecision(4));
+assertEquals("-1.234e+4", Number(-12344.67).toPrecision(4));
+// Test that we round up even when the last digit generated is even.
+// dtoa does not do this in its original form.
+assertEquals("1.3", 1.25.toPrecision(2), "1.25.toPrecision(2)");
+assertEquals("1.4", 1.35.toPrecision(2), "1.35.toPrecision(2)");
+
+
+
diff --git a/deps/v8/test/mjsunit/obj-construct.js b/deps/v8/test/mjsunit/obj-construct.js
new file mode 100644
index 0000000..98e09b2
--- /dev/null
+++ b/deps/v8/test/mjsunit/obj-construct.js
@@ -0,0 +1,46 @@
+// Copyright 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.
+
+var consCalled = false;
+
+function Object() {
+  consCalled = true;
+}
+
+function Array() {
+  consCalled = true;
+}
+
+assertFalse(consCalled);
+var x1 = { };
+assertFalse(consCalled);
+var x2 = { a: 3, b: 4 };
+assertFalse(consCalled);
+var x3 = [ ];
+assertFalse(consCalled);
+var x4 = [ 1, 2, 3 ];
+assertFalse(consCalled);
diff --git a/deps/v8/test/mjsunit/object-literal-gc.js b/deps/v8/test/mjsunit/object-literal-gc.js
new file mode 100644
index 0000000..b9d6285
--- /dev/null
+++ b/deps/v8/test/mjsunit/object-literal-gc.js
@@ -0,0 +1,66 @@
+// 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.
+
+// Flags: --expose-gc
+
+// Test that the clearing of object literal when normalizing objects
+// works.  In particular, test that the garbage collector handles the
+// normalized object literals correctly.
+function testLiteral(size) {
+
+  // Build object-literal string.
+  var literal = "var o = { ";
+
+  for (var i = 0; i < size; i++) {
+    if (i > 0) literal += ",";
+    literal += ("a" + i + ":" + i);
+  }
+  literal += "}";
+
+  // Create the object literal.
+  eval(literal);
+
+  // Force normalization of the properties.
+  delete o["a" + (size - 1)];
+
+  // Perform GC.
+  gc();
+
+  // Check that the properties have the expected values.
+  for (var i = 0; i < size - 1; i++) {
+    assertEquals(i, o["a"+i]);
+  }
+}
+
+// The sizes to test.
+var sizes = [0, 1, 2, 100, 200, 400, 1000];
+
+// Run the test.
+for (var i = 0; i < sizes.length; i++) {
+  testLiteral(sizes[i]);
+}
+
diff --git a/deps/v8/test/mjsunit/object-literal.js b/deps/v8/test/mjsunit/object-literal.js
new file mode 100644
index 0000000..cc6f59d
--- /dev/null
+++ b/deps/v8/test/mjsunit/object-literal.js
@@ -0,0 +1,105 @@
+// 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.
+
+var obj = {
+    a: 7,
+    b: { x: 12, y: 24 },
+    c: 'Zebra'
+}
+
+assertEquals(7, obj.a);
+assertEquals(12, obj.b.x);
+assertEquals(24, obj.b.y);
+assertEquals('Zebra', obj.c);
+
+var z = 24;
+
+var obj2 = {
+    a: 7,
+    b: { x: 12, y: z },
+    c: 'Zebra'
+}
+
+assertEquals(7, obj2.a);
+assertEquals(12, obj2.b.x);
+assertEquals(24, obj2.b.y);
+assertEquals('Zebra', obj2.c);
+
+var arr = [];
+for (var i = 0; i < 2; i++) {
+  arr[i] = {
+      a: 7,
+      b: { x: 12, y: 24 },
+      c: 'Zebra'
+  }
+}
+
+arr[0].b.x = 2;
+assertEquals(2, arr[0].b.x);
+assertEquals(12, arr[1].b.x);
+
+
+function makeSparseArray() {
+  return {
+    '0': { x: 12, y: 24 },
+    '1000000': { x: 0, y: 0 }
+  };
+}
+
+var sa1 = makeSparseArray();
+sa1[0].x = 0;
+var sa2 = makeSparseArray();
+assertEquals(12, sa2[0].x);
+
+// Test that non-constant literals work.
+var n = new Object();
+
+function makeNonConstantArray() { return [ [ n ] ]; }
+
+var a = makeNonConstantArray();
+a[0][0].foo = "bar";
+assertEquals("bar", n.foo);
+
+function makeNonConstantObject() { return { a: { b: n } }; }
+
+a = makeNonConstantObject();
+a.a.b.bar = "foo";
+assertEquals("foo", n.bar);
+
+// Test that exceptions for regexps still hold.
+function makeRegexpInArray() { return [ [ /a*/, {} ] ]; }
+
+a = makeRegexpInArray();
+var b = makeRegexpInArray();
+assertTrue(a[0][0] === b[0][0]);
+assertFalse(a[0][1] === b[0][1]);
+
+function makeRegexpInObject() { return { a: { b: /b*/, c: {} } }; }
+a = makeRegexpInObject();
+b = makeRegexpInObject();
+assertTrue(a.a.b === b.a.b);
+assertFalse(a.a.c === b.a.c);
diff --git a/deps/v8/test/mjsunit/override-read-only-property.js b/deps/v8/test/mjsunit/override-read-only-property.js
new file mode 100644
index 0000000..b8fa501
--- /dev/null
+++ b/deps/v8/test/mjsunit/override-read-only-property.js
@@ -0,0 +1,64 @@
+// 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.
+
+// According to ECMA-262, sections 8.6.2.2 and 8.6.2.3 you're not
+// allowed to override read-only properties, not even if the read-only
+// property is in the prototype chain.
+//
+// However, for compatibility with WebKit/JSC, we allow the overriding
+// of read-only properties in prototype chains.
+
+function F() {};
+F.prototype = Number;
+
+var original_number_max = Number.MAX_VALUE;
+
+// Assignment to a property which does not exist on the object itself,
+// but is read-only in a prototype takes effect.
+var f = new F();
+assertEquals(original_number_max, f.MAX_VALUE);
+f.MAX_VALUE = 42;
+assertEquals(42, f.MAX_VALUE);
+
+// Assignment to a property which does not exist on the object itself,
+// but is read-only in a prototype takes effect.
+f = new F();
+with (f) {
+  MAX_VALUE = 42;
+}
+assertEquals(42, f.MAX_VALUE);
+
+// Assignment to read-only property on the object itself is ignored.
+Number.MAX_VALUE = 42;
+assertEquals(original_number_max, Number.MAX_VALUE);
+
+// G should be read-only on the global object and the assignment is
+// ignored.
+(function G() {
+  eval("G = 42;");
+  assertTrue(typeof G === 'function');
+})();
diff --git a/deps/v8/test/mjsunit/parse-int-float.js b/deps/v8/test/mjsunit/parse-int-float.js
new file mode 100644
index 0000000..ad2275e
--- /dev/null
+++ b/deps/v8/test/mjsunit/parse-int-float.js
@@ -0,0 +1,82 @@
+// Copyright 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.
+
+assertEquals(0, parseInt('0'));
+assertEquals(0, parseInt(' 0'));
+assertEquals(0, parseInt(' 0 '));
+
+assertEquals(63, parseInt('077'));
+assertEquals(63, parseInt('  077'));
+assertEquals(63, parseInt('  077   '));
+assertEquals(-63, parseInt('  -077'));
+
+assertEquals(3, parseInt('11', 2));
+assertEquals(4, parseInt('11', 3));
+
+assertEquals(0x12, parseInt('0x12'));
+assertEquals(0x12, parseInt('0x12', 16));
+
+assertEquals(12, parseInt('12aaa'));
+
+assertEquals(0.1, parseFloat('0.1'));
+assertEquals(0.1, parseFloat('0.1aaa'));
+assertEquals(0, parseFloat('0x12'));
+assertEquals(77, parseFloat('077'));
+
+
+var i;
+var y = 10;
+
+for (i = 1; i < 21; i++) {
+  var x = eval("1.2e" + i);
+  assertEquals(Math.floor(x), parseInt(x));
+  x = eval("1e" + i);
+  assertEquals(x, y);
+  y *= 10;
+  assertEquals(Math.floor(x), parseInt(x));
+  x = eval("-1e" + i);
+  assertEquals(Math.ceil(x), parseInt(x));
+  x = eval("-1.2e" + i);
+  assertEquals(Math.ceil(x), parseInt(x));
+}
+
+for (i = 21; i < 53; i++) {
+  var x = eval("1e" + i);
+  assertEquals(1, parseInt(x));
+  x = eval("-1e" + i);
+  assertEquals(-1, parseInt(x));
+}
+
+assertTrue(isNaN(parseInt(0/0)));
+assertTrue(isNaN(parseInt(1/0)), "parseInt Infinity");
+assertTrue(isNaN(parseInt(-1/0)), "parseInt -Infinity");
+
+assertTrue(isNaN(parseFloat(0/0)));
+assertEquals(Infinity, parseFloat(1/0), "parseFloat Infinity");
+assertEquals(-Infinity, parseFloat(-1/0), "parseFloat -Infinity");
+
+
diff --git a/deps/v8/test/mjsunit/property-load-across-eval.js b/deps/v8/test/mjsunit/property-load-across-eval.js
new file mode 100644
index 0000000..8271f4c
--- /dev/null
+++ b/deps/v8/test/mjsunit/property-load-across-eval.js
@@ -0,0 +1,85 @@
+// 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.
+
+// Tests loading of properties across eval calls.
+
+var x = 1;
+
+// Test loading across an eval call that does not shadow variables.
+function testNoShadowing() {
+  var y = 2;
+  function f() {
+    eval('1');
+    assertEquals(1, x);
+    assertEquals(2, y);
+    function g() {
+      assertEquals(1, x);
+      assertEquals(2, y);
+    }
+    g();
+  }
+  f();
+}
+
+testNoShadowing();
+
+// Test loading across eval calls that do not shadow variables.
+function testNoShadowing2() {
+  var y = 2;
+  eval('1');
+  function f() {
+    eval('1');
+    assertEquals(1, x);
+    assertEquals(2, y);
+    function g() {
+      assertEquals(1, x);
+      assertEquals(2, y);
+    }
+    g();
+  }
+  f();
+}
+
+testNoShadowing2();
+
+// Test loading across an eval call that shadows variables.
+function testShadowing() {
+  var y = 2;
+  function f() {
+    eval('var x = 3; var y = 4;');
+    assertEquals(3, x);
+    assertEquals(4, y);
+    function g() {
+      assertEquals(3, x);
+      assertEquals(4, y);
+    }
+    g();
+  }
+  f();
+}
+
+testShadowing();
diff --git a/deps/v8/test/mjsunit/property-object-key.js b/deps/v8/test/mjsunit/property-object-key.js
new file mode 100644
index 0000000..5eb1e1b
--- /dev/null
+++ b/deps/v8/test/mjsunit/property-object-key.js
@@ -0,0 +1,36 @@
+// Copyright 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.
+
+var key = { toString: function() { return 'baz'; } }
+var object = { baz: 42 };
+
+assertEquals(42, object[key]);
+object[key] = 87;
+assertEquals(87, object[key]);
+object[key]++;
+assertEquals(88, object[key]);
+
diff --git a/deps/v8/test/mjsunit/proto.js b/deps/v8/test/mjsunit/proto.js
new file mode 100644
index 0000000..faf98b2
--- /dev/null
+++ b/deps/v8/test/mjsunit/proto.js
@@ -0,0 +1,33 @@
+// Copyright 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.
+
+var o1 = { x: 12 };
+
+var o2 = { x: 12, y: 13 };
+delete o2.x;  // normalize
+
+assertTrue(o1.__proto__ === o2.__proto__);
diff --git a/deps/v8/test/mjsunit/prototype.js b/deps/v8/test/mjsunit/prototype.js
new file mode 100644
index 0000000..bfc1a79
--- /dev/null
+++ b/deps/v8/test/mjsunit/prototype.js
@@ -0,0 +1,93 @@
+// Copyright 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.
+
+function A() { }
+function B() { }
+function C() { }
+
+function NewC() {
+  A.prototype = {};
+  B.prototype = new A();
+  C.prototype = new B();
+  var result = new C();
+  result.A = A.prototype;
+  result.B = B.prototype;
+  result.C = C.prototype;
+  return result;
+}
+
+// Check that we can read properties defined in prototypes.
+var c = NewC();
+c.A.x = 1;
+c.B.y = 2;
+c.C.z = 3;
+assertEquals(1, c.x);
+assertEquals(2, c.y);
+assertEquals(3, c.z);
+
+var c = NewC();
+c.A.x = 0;
+for (var i = 0; i < 2; i++) {
+  assertEquals(i, c.x);
+  c.B.x = 1;
+}
+
+
+// Regression test:
+// Make sure we preserve the prototype of an object in the face of map transitions.
+
+function D() {
+  this.d = 1;
+}
+var p = new Object();
+p.y = 1;
+new D();
+
+D.prototype = p
+assertEquals(1, (new D).y);
+
+
+// Regression test:
+// Make sure that arrays and functions in the prototype chain works;
+// check length.
+function X() { }
+function Y() { }
+
+X.prototype = function(a,b) { };
+Y.prototype = [1,2,3];
+
+assertEquals(2, (new X).length);
+assertEquals(3, (new Y).length);
+
+
+// Test setting the length of an object where the prototype is from an array.
+var test = new Object;
+test.__proto__ = (new Array()).__proto__;
+test.length = 14;
+assertEquals(14, test.length);
+
+
diff --git a/deps/v8/test/mjsunit/regexp-UC16.js b/deps/v8/test/mjsunit/regexp-UC16.js
new file mode 100644
index 0000000..f609e17
--- /dev/null
+++ b/deps/v8/test/mjsunit/regexp-UC16.js
@@ -0,0 +1,47 @@
+// Copyright 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.
+
+// UC16
+// Characters used:
+// "\u03a3\u03c2\u03c3\u039b\u03bb" - Sigma, final sigma, sigma, Lambda, lamda
+assertEquals("x\u03a3\u03c3x,\u03a3",
+              String(/x(.)\1x/i.exec("x\u03a3\u03c3x")), "backref-UC16");
+assertFalse(/x(...)\1/i.test("x\u03a3\u03c2\u03c3\u03c2\u03c3"),
+            "\\1 ASCII, string short");
+assertTrue(/\u03a3((?:))\1\1x/i.test("\u03c2x"), "backref-UC16-empty");
+assertTrue(/x(?:...|(...))\1x/i.test("x\u03a3\u03c2\u03c3x"),
+           "backref-UC16-uncaptured");
+assertTrue(/x(?:...|(...))\1x/i.test("x\u03c2\u03c3\u039b\u03a3\u03c2\u03bbx"),
+           "backref-UC16-backtrack");
+var longUC16String = "x\u03a3\u03c2\u039b\u03c2\u03c3\u03bb\u03c3\u03a3\u03bb";
+assertEquals(longUC16String + "," + longUC16String.substring(1,4),
+             String(/x(...)\1\1/i.exec(longUC16String)),
+             "backref-UC16-twice");
+
+assertFalse(/\xc1/i.test('fooA'), "quickcheck-uc16-pattern-ascii-subject");
+assertFalse(/[\xe9]/.test('i'), "charclass-uc16-pattern-ascii-subject");
+assertFalse(/\u5e74|\u6708/.test('t'), "alternation-uc16-pattern-ascii-subject");
diff --git a/deps/v8/test/mjsunit/regexp-capture.js b/deps/v8/test/mjsunit/regexp-capture.js
new file mode 100755
index 0000000..d4433d8
--- /dev/null
+++ b/deps/v8/test/mjsunit/regexp-capture.js
@@ -0,0 +1,57 @@
+// 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.
+
+// Tests from http://blog.stevenlevithan.com/archives/npcg-javascript
+
+assertEquals(true, /(x)?\1y/.test("y"));
+assertEquals(["y", undefined], /(x)?\1y/.exec("y"));
+assertEquals(["y", undefined], /(x)?y/.exec("y"));
+assertEquals(["y", undefined], "y".match(/(x)?\1y/));
+assertEquals(["y", undefined], "y".match(/(x)?y/));
+assertEquals(["y"], "y".match(/(x)?\1y/g));
+assertEquals(["", undefined, ""], "y".split(/(x)?\1y/));
+assertEquals(["", undefined, ""], "y".split(/(x)?y/));
+assertEquals(0, "y".search(/(x)?\1y/));
+assertEquals("z", "y".replace(/(x)?\1y/, "z"));
+assertEquals("", "y".replace(/(x)?y/, "$1"));
+assertEquals("undefined", "y".replace(/(x)?\1y/,
+    function($0, $1){ 
+        return String($1); 
+    }));
+assertEquals("undefined", "y".replace(/(x)?y/, 
+    function($0, $1){ 
+        return String($1); 
+    }));
+assertEquals("undefined", "y".replace(/(x)?y/, 
+    function($0, $1){ 
+        return $1; 
+    }));
+
+// See https://bugzilla.mozilla.org/show_bug.cgi?id=476146
+assertEquals("bbc,b", /^(b+|a){1,2}?bc/.exec("bbc"));
+assertEquals("bbaa,a,,a", /((\3|b)\2(a)){2,}/.exec("bbaababbabaaaaabbaaaabba"));
+
diff --git a/deps/v8/test/mjsunit/regexp-indexof.js b/deps/v8/test/mjsunit/regexp-indexof.js
new file mode 100644
index 0000000..a504dd8
--- /dev/null
+++ b/deps/v8/test/mjsunit/regexp-indexof.js
@@ -0,0 +1,77 @@
+// Copyright 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.
+
+function CheckMatch(re, str, matches) {
+  assertEquals(matches.length > 0, re.test(str));
+  var result = str.match(re);
+  if (matches.length > 0) {
+    assertEquals(matches.length, result.length);
+    var lastExpected;
+    var lastFrom;
+    var lastLength;
+    for (var idx = 0; idx < matches.length; idx++) {
+      var from = matches[idx][0];
+      var length = matches[idx][1];
+      var expected = str.substr(from, length);
+      var name = str + "[" + from + ".." + (from+length) + "]";
+      assertEquals(expected, result[idx], name);
+      if (re.global || idx == 0) {
+        lastExpected = expected;
+        lastFrom = from;
+        lastLength = length;
+      }
+    }
+    assertEquals(lastExpected, RegExp.lastMatch, "lastMatch");
+    assertEquals(str.substr(0, lastFrom), RegExp.leftContext, "leftContext");
+    assertEquals(
+        str.substr(lastFrom + lastLength), RegExp.rightContext, "rightContext");
+  } else {
+    assertTrue(result === null);
+  }
+}
+
+CheckMatch(/abc/, "xxxabcxxxabcxxx", [[3, 3]]);
+CheckMatch(/abc/g, "xxxabcxxxabcxxx", [[3, 3], [9, 3]]);
+CheckMatch(/abc/, "xxxabababcxxxabcxxx", [[7, 3]]);
+CheckMatch(/abc/g, "abcabcabc", [[0, 3], [3, 3], [6, 3]]);
+CheckMatch(/aba/g, "ababababa", [[0, 3], [4, 3]]);
+CheckMatch(/foo/g, "ofooofoooofofooofo", [[1, 3], [5, 3], [12, 3]]);
+CheckMatch(/foobarbaz/, "xx", []);
+CheckMatch(new RegExp(""), "xxx", [[0, 0]]);
+CheckMatch(/abc/, "abababa", []);
+
+assertEquals("xxxdefxxxdefxxx", "xxxabcxxxabcxxx".replace(/abc/g, "def"));
+assertEquals("o-o-oofo-ofo", "ofooofoooofofooofo".replace(/foo/g, "-"));
+assertEquals("deded", "deded".replace(/x/g, "-"));
+assertEquals("-a-b-c-d-e-f-", "abcdef".replace(new RegExp("", "g"), "-"));
+
+CheckMatch(/a(.)/, "xyzzyabxyzzzyacxyzzy", [[5, 2], [6, 1]]);
+CheckMatch(/a(.)/g, "xyzzyabxyzzyacxyzzy", [[5, 2], [12, 2]]);
+
+CheckMatch(/a|(?:)/g, "aba", [[0, 1], [1, 0], [2, 1], [3, 0]]);
+CheckMatch(/a|(?:)/g, "baba", [[0, 0], [1, 1], [2, 0], [3, 1], [4, 0]]);
+CheckMatch(/a|(?:)/g, "bab", [[0, 0], [1, 1], [2, 0], [3, 0]]);
\ No newline at end of file
diff --git a/deps/v8/test/mjsunit/regexp-lookahead.js b/deps/v8/test/mjsunit/regexp-lookahead.js
new file mode 100644
index 0000000..1188b56
--- /dev/null
+++ b/deps/v8/test/mjsunit/regexp-lookahead.js
@@ -0,0 +1,166 @@
+// 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.
+
+// Tests captures in positive and negative look-ahead in regular expressions.
+
+function stringEscape(string) {
+  // Converts string to source literal.
+  return '"' + string.replace(/["\\]/g, "\\$1") + '"';
+}
+
+function testRE(re, input, expected_result) {
+  var testName = re + ".test(" + stringEscape(input) +")";
+  if (expected_result) {
+    assertTrue(re.test(input), testName);
+  } else {
+    assertFalse(re.test(input), testName);
+  }
+}
+
+function execRE(re, input, expected_result) {
+  var testName = re + ".exec('" + stringEscape(input) +"')";
+  assertEquals(expected_result, re.exec(input), testName);
+}
+
+// Test of simple positive lookahead.
+
+var re = /^(?=a)/;
+testRE(re, "a", true);
+testRE(re, "b", false);
+execRE(re, "a", [""]);
+
+re = /^(?=\woo)f\w/;
+testRE(re, "foo", true);
+testRE(re, "boo", false);
+testRE(re, "fao", false);
+testRE(re, "foa", false);
+execRE(re, "foo", ["fo"]);
+
+re = /(?=\w).(?=\W)/;
+testRE(re, ".a! ", true);
+testRE(re, ".! ", false);
+testRE(re, ".ab! ", true);
+execRE(re, ".ab! ", ["b"]);
+
+re = /(?=f(?=[^f]o))../;
+testRE(re, ", foo!", true);
+testRE(re, ", fo!", false);
+testRE(re, ", ffo", false);
+execRE(re, ", foo!", ["fo"]);
+
+// Positive lookahead with captures.
+re = /^[^\'\"]*(?=([\'\"])).*\1(\w+)\1/;
+testRE(re, "  'foo' ", true);
+testRE(re, '  "foo" ', true);
+testRE(re, " \" 'foo' ", false);
+testRE(re, " ' \"foo\" ", false);
+testRE(re, "  'foo\" ", false);
+testRE(re, "  \"foo' ", false);
+execRE(re, "  'foo' ", ["  'foo'", "'", "foo"]);
+execRE(re, '  "foo" ', ['  "foo"', '"', 'foo']);
+
+// Captures are cleared on backtrack past the look-ahead.
+re = /^(?:(?=(.))a|b)\1$/;
+testRE(re, "aa", true);
+testRE(re, "b", true);
+testRE(re, "bb", false);
+testRE(re, "a", false);
+execRE(re, "aa", ["aa", "a"]);
+execRE(re, "b", ["b", undefined]);
+
+re = /^(?=(.)(?=(.)\1\2)\2\1)\1\2/;
+testRE(re, "abab", true);
+testRE(re, "ababxxxxxxxx", true);
+testRE(re, "aba", false);
+execRE(re, "abab", ["ab", "a", "b"]);
+
+re = /^(?:(?=(.))a|b|c)$/;
+testRE(re, "a", true);
+testRE(re, "b", true);
+testRE(re, "c", true);
+testRE(re, "d", false);
+execRE(re, "a", ["a", "a"]);
+execRE(re, "b", ["b", undefined]);
+execRE(re, "c", ["c", undefined]);
+
+execRE(/^(?=(b))b/, "b", ["b", "b"]);
+execRE(/^(?:(?=(b))|a)b/, "ab", ["ab", undefined]);
+execRE(/^(?:(?=(b)(?:(?=(c))|d))|)bd/, "bd", ["bd", "b", undefined]);
+
+
+
+// Test of Negative Look-Ahead.
+
+re = /(?!x)./;
+testRE(re, "y", true);
+testRE(re, "x", false);
+execRE(re, "y", ["y"]);
+
+re = /(?!(\d))|\d/;
+testRE(re, "4", true);
+execRE(re, "4", ["4", undefined]);
+execRE(re, "x", ["", undefined]);
+
+
+// Test mixed nested look-ahead with captures.
+
+re = /^(?=(x)(?=(y)))/;
+testRE(re, "xy", true);
+testRE(re, "xz", false);
+execRE(re, "xy", ["", "x", "y"]);
+
+re = /^(?!(x)(?!(y)))/;
+testRE(re, "xy", true);
+testRE(re, "xz", false);
+execRE(re, "xy", ["", undefined, undefined]);
+
+re = /^(?=(x)(?!(y)))/;
+testRE(re, "xz", true);
+testRE(re, "xy", false)
+execRE(re, "xz", ["", "x", undefined]);
+
+re = /^(?!(x)(?=(y)))/;
+testRE(re, "xz", true);
+testRE(re, "xy", false);
+execRE(re, "xz", ["", undefined, undefined]);
+
+re = /^(?=(x)(?!(y)(?=(z))))/;
+testRE(re, "xaz", true);
+testRE(re, "xya", true);
+testRE(re, "xyz", false);
+testRE(re, "a", false);
+execRE(re, "xaz", ["", "x", undefined, undefined]);
+execRE(re, "xya", ["", "x", undefined, undefined]);
+
+re = /^(?!(x)(?=(y)(?!(z))))/;
+testRE(re, "a", true);
+testRE(re, "xa", true);
+testRE(re, "xyz", true);
+testRE(re, "xya", false);
+execRE(re, "a", ["", undefined, undefined, undefined]);
+execRE(re, "xa", ["", undefined, undefined, undefined]);
+execRE(re, "xyz", ["", undefined, undefined, undefined]);
diff --git a/deps/v8/test/mjsunit/regexp-loop-capture.js b/deps/v8/test/mjsunit/regexp-loop-capture.js
new file mode 100644
index 0000000..9a0c99c
--- /dev/null
+++ b/deps/v8/test/mjsunit/regexp-loop-capture.js
@@ -0,0 +1,29 @@
+// 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.
+
+assertEquals(["abc",undefined,undefined,"c"], /(?:(a)|(b)|(c))+/.exec("abc"));
+assertEquals(["ab",undefined], /(?:(a)|b)*/.exec("ab"));
diff --git a/deps/v8/test/mjsunit/regexp-multiline-stack-trace.js b/deps/v8/test/mjsunit/regexp-multiline-stack-trace.js
new file mode 100644
index 0000000..aa2de88
--- /dev/null
+++ b/deps/v8/test/mjsunit/regexp-multiline-stack-trace.js
@@ -0,0 +1,114 @@
+// Copyright 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.
+
+// Flags: --trace-calls --preallocate-message-memory
+
+/**
+ * @fileoverview Check that various regexp constructs work as intended.
+ * Particularly those regexps that use ^ and $.
+ */
+
+assertTrue(/^bar/.test("bar"));
+assertTrue(/^bar/.test("bar\nfoo"));
+assertFalse(/^bar/.test("foo\nbar"));
+assertTrue(/^bar/m.test("bar"));
+assertTrue(/^bar/m.test("bar\nfoo"));
+assertTrue(/^bar/m.test("foo\nbar"));
+
+assertTrue(/bar$/.test("bar"));
+assertFalse(/bar$/.test("bar\nfoo"));
+assertTrue(/bar$/.test("foo\nbar"));
+assertTrue(/bar$/m.test("bar"));
+assertTrue(/bar$/m.test("bar\nfoo"));
+assertTrue(/bar$/m.test("foo\nbar"));
+
+assertFalse(/^bxr/.test("bar"));
+assertFalse(/^bxr/.test("bar\nfoo"));
+assertFalse(/^bxr/m.test("bar"));
+assertFalse(/^bxr/m.test("bar\nfoo"));
+assertFalse(/^bxr/m.test("foo\nbar"));
+
+assertFalse(/bxr$/.test("bar"));
+assertFalse(/bxr$/.test("foo\nbar"));
+assertFalse(/bxr$/m.test("bar"));
+assertFalse(/bxr$/m.test("bar\nfoo"));
+assertFalse(/bxr$/m.test("foo\nbar"));
+
+
+assertTrue(/^.*$/.test(""));
+assertTrue(/^.*$/.test("foo"));
+assertFalse(/^.*$/.test("\n"));
+assertTrue(/^.*$/m.test("\n"));
+
+assertTrue(/^[\s]*$/.test(" "));
+assertTrue(/^[\s]*$/.test("\n"));
+
+assertTrue(/^[^]*$/.test(""));
+assertTrue(/^[^]*$/.test("foo"));
+assertTrue(/^[^]*$/.test("\n"));
+
+assertTrue(/^([()\s]|.)*$/.test("()\n()"));
+assertTrue(/^([()\n]|.)*$/.test("()\n()"));
+assertFalse(/^([()]|.)*$/.test("()\n()"));
+assertTrue(/^([()]|.)*$/m.test("()\n()"));
+assertTrue(/^([()]|.)*$/m.test("()\n"));
+assertTrue(/^[()]*$/m.test("()\n."));
+
+assertTrue(/^[\].]*$/.test("...]..."));
+
+
+function check_case(lc, uc) {
+  var a = new RegExp("^" + lc + "$");
+  assertFalse(a.test(uc));
+  a = new RegExp("^" + lc + "$", "i");
+  assertTrue(a.test(uc));
+
+  var A = new RegExp("^" + uc + "$");
+  assertFalse(A.test(lc));
+  A = new RegExp("^" + uc + "$", "i");
+  assertTrue(A.test(lc));
+
+  a = new RegExp("^[" + lc + "]$");
+  assertFalse(a.test(uc));
+  a = new RegExp("^[" + lc + "]$", "i");
+  assertTrue(a.test(uc));
+
+  A = new RegExp("^[" + uc + "]$");
+  assertFalse(A.test(lc));
+  A = new RegExp("^[" + uc + "]$", "i");
+  assertTrue(A.test(lc));
+}
+
+
+check_case("a", "A");
+// Aring
+check_case(String.fromCharCode(229), String.fromCharCode(197));
+// Russian G
+check_case(String.fromCharCode(0x413), String.fromCharCode(0x433));
+
+
+assertThrows("a = new RegExp('[z-a]');");
diff --git a/deps/v8/test/mjsunit/regexp-multiline.js b/deps/v8/test/mjsunit/regexp-multiline.js
new file mode 100644
index 0000000..32edf25
--- /dev/null
+++ b/deps/v8/test/mjsunit/regexp-multiline.js
@@ -0,0 +1,112 @@
+// Copyright 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.
+
+/**
+ * @fileoverview Check that various regexp constructs work as intended.
+ * Particularly those regexps that use ^ and $.
+ */
+
+assertTrue(/^bar/.test("bar"));
+assertTrue(/^bar/.test("bar\nfoo"));
+assertFalse(/^bar/.test("foo\nbar"));
+assertTrue(/^bar/m.test("bar"));
+assertTrue(/^bar/m.test("bar\nfoo"));
+assertTrue(/^bar/m.test("foo\nbar"));
+
+assertTrue(/bar$/.test("bar"));
+assertFalse(/bar$/.test("bar\nfoo"));
+assertTrue(/bar$/.test("foo\nbar"));
+assertTrue(/bar$/m.test("bar"));
+assertTrue(/bar$/m.test("bar\nfoo"));
+assertTrue(/bar$/m.test("foo\nbar"));
+
+assertFalse(/^bxr/.test("bar"));
+assertFalse(/^bxr/.test("bar\nfoo"));
+assertFalse(/^bxr/m.test("bar"));
+assertFalse(/^bxr/m.test("bar\nfoo"));
+assertFalse(/^bxr/m.test("foo\nbar"));
+
+assertFalse(/bxr$/.test("bar"));
+assertFalse(/bxr$/.test("foo\nbar"));
+assertFalse(/bxr$/m.test("bar"));
+assertFalse(/bxr$/m.test("bar\nfoo"));
+assertFalse(/bxr$/m.test("foo\nbar"));
+
+
+assertTrue(/^.*$/.test(""));
+assertTrue(/^.*$/.test("foo"));
+assertFalse(/^.*$/.test("\n"));
+assertTrue(/^.*$/m.test("\n"));
+
+assertTrue(/^[\s]*$/.test(" "));
+assertTrue(/^[\s]*$/.test("\n"));
+
+assertTrue(/^[^]*$/.test(""));
+assertTrue(/^[^]*$/.test("foo"));
+assertTrue(/^[^]*$/.test("\n"));
+
+assertTrue(/^([()\s]|.)*$/.test("()\n()"));
+assertTrue(/^([()\n]|.)*$/.test("()\n()"));
+assertFalse(/^([()]|.)*$/.test("()\n()"));
+assertTrue(/^([()]|.)*$/m.test("()\n()"));
+assertTrue(/^([()]|.)*$/m.test("()\n"));
+assertTrue(/^[()]*$/m.test("()\n."));
+
+assertTrue(/^[\].]*$/.test("...]..."));
+
+
+function check_case(lc, uc) {
+  var a = new RegExp("^" + lc + "$");
+  assertFalse(a.test(uc));
+  a = new RegExp("^" + lc + "$", "i");
+  assertTrue(a.test(uc));
+
+  var A = new RegExp("^" + uc + "$");
+  assertFalse(A.test(lc));
+  A = new RegExp("^" + uc + "$", "i");
+  assertTrue(A.test(lc));
+
+  a = new RegExp("^[" + lc + "]$");
+  assertFalse(a.test(uc));
+  a = new RegExp("^[" + lc + "]$", "i");
+  assertTrue(a.test(uc));
+
+  A = new RegExp("^[" + uc + "]$");
+  assertFalse(A.test(lc));
+  A = new RegExp("^[" + uc + "]$", "i");
+  assertTrue(A.test(lc));
+}
+
+
+check_case("a", "A");
+// Aring
+check_case(String.fromCharCode(229), String.fromCharCode(197));
+// Russian G
+check_case(String.fromCharCode(0x413), String.fromCharCode(0x433));
+
+
+assertThrows("a = new RegExp('[z-a]');");
diff --git a/deps/v8/test/mjsunit/regexp-pcre.js b/deps/v8/test/mjsunit/regexp-pcre.js
new file mode 100644
index 0000000..dcb1b32
--- /dev/null
+++ b/deps/v8/test/mjsunit/regexp-pcre.js
@@ -0,0 +1,6603 @@
+// Autogenerated from the PCRE test suite Mon Feb  2 15:14:04 CET 2009
+
+// Note that some regexps in the PCRE test suite use features not present
+// in JavaScript.  These don't work in JS, but they fail to work in a
+// predictable way, and the expected results reflect this.
+
+// PCRE comes with the following license
+
+// PCRE LICENCE
+// ------------
+//
+// PCRE is a library of functions to support regular expressions whose syntax
+// and semantics are as close as possible to those of the Perl 5 language.
+//
+// Release 7 of PCRE is distributed under the terms of the "BSD" licence, as
+// specified below. The documentation for PCRE, supplied in the "doc"
+// directory, is distributed under the same terms as the software itself.
+//
+// The basic library functions are written in C and are freestanding. Also
+// included in the distribution is a set of C++ wrapper functions.
+//
+//
+// THE BASIC LIBRARY FUNCTIONS
+// ---------------------------
+//
+// Written by:       Philip Hazel
+// Email local part: ph10
+// Email domain:     cam.ac.uk
+//
+// University of Cambridge Computing Service,
+// Cambridge, England.
+//
+// Copyright (c) 1997-2007 University of Cambridge
+// All rights reserved.
+//
+//
+// THE C++ WRAPPER FUNCTIONS
+// -------------------------
+//
+// Contributed by:   Google Inc.
+//
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+//
+// THE "BSD" LICENCE
+// -----------------
+//
+// 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 the University of Cambridge nor the name of Google
+//       Inc. nor the names of their 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.
+//
+// End
+
+var res = new Array();
+res[0] = /(a)b|/i;
+res[1] = /abc/i;
+res[2] = /^abc/i;
+res[3] = /a+bc/i;
+res[4] = /a*bc/i;
+res[5] = /a{3}bc/i;
+res[6] = /(abc|a+z)/i;
+res[7] = /^abc$/i;
+res[8] = /ab\idef/;
+res[9] = /.*b/i;
+res[10] = /.*?b/i;
+res[11] = /cat|dog|elephant/i;
+res[12] = /cat|dog|elephant/i;
+res[13] = /cat|dog|elephant/i;
+res[14] = /a|[bcd]/i;
+res[15] = /(a|[^\dZ])/i;
+res[16] = /(a|b)*[\s]/i;
+res[17] = /(ab\2)/;
+res[18] = /(a)(b)(c)\2/i;
+res[19] = /(a)bc|(a)(b)\2/i;
+res[20] = /abc$/i;
+res[21] = /(a)(b)(c)(d)(e)\6/;
+res[22] = /the quick brown fox/i;
+res[23] = /^abc|def/i;
+res[24] = /.*((abc)$|(def))/i;
+res[25] = /abc/i;
+res[26] = /^abc|def/i;
+res[27] = /.*((abc)$|(def))/i;
+res[28] = /the quick brown fox/i;
+res[29] = /the quick brown fox/i;
+res[30] = /abc.def/i;
+res[31] = /abc$/i;
+res[32] = /(abc)\2/i;
+res[33] = /(abc\1)/i;
+res[34] = /a[]b/;
+res[35] = /[^aeiou ]{3,}/i;
+res[36] = /<.*>/i;
+res[37] = /<.*?>/i;
+res[38] = /[abcd]/i;
+res[39] = /(^a|^b)/im;
+res[40] = /a$/i;
+res[41] = /a$/im;
+res[42] = /\Aabc/im;
+res[43] = /^abc/im;
+res[44] = /(?!alphabet)[ab]/i;
+res[45] = /The next three are in testinput2 because they have variable length branches/;
+res[46] = /This one is here because Perl 5.005_02 doesn't fail it/i;
+res[47] = /This one is here because I think Perl 5.005_02 gets the setting of $1 wrong/i;
+res[48] = /^(a\1?){4}$/i;
+res[49] = /These are syntax tests from Perl 5.005/i;
+res[50] = /a[]b/;
+res[51] = /\1/;
+res[52] = /\2/;
+res[53] = /(a)|\2/;
+res[54] = /a[]b/i;
+res[55] = /abc/;
+res[56] = /abc/;
+res[57] = /abc/i;
+res[58] = /(a)bc(d)/i;
+res[59] = /(.{20})/i;
+res[60] = /(.{15})/i;
+res[61] = /(.{16})/i;
+res[62] = /^(a|(bc))de(f)/i;
+res[63] = /^abc\00def/i;
+res[64] = /word ((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+\n)((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+\n)?)?)?)?)?)?)?)?)?otherword/i;
+res[65] = /.*X/i;
+res[66] = /.*X/i;
+res[67] = /(.*X|^B)/i;
+res[68] = /(.*X|^B)/i;
+res[69] = /\Biss\B/i;
+res[70] = /\Biss\B/i;
+res[71] = /iss/ig;
+res[72] = /\Biss\B/ig;
+res[73] = /\Biss\B/ig;
+res[74] = /^iss/ig;
+res[75] = /.*iss/ig;
+res[76] = /.i./ig;
+res[77] = /^.is/ig;
+res[78] = /^ab\n/ig;
+res[79] = /^ab\n/img;
+res[80] = /abc/i;
+res[81] = /abc|bac/i;
+res[82] = /(abc|bac)/i;
+res[83] = /(abc|(c|dc))/i;
+res[84] = /(abc|(d|de)c)/i;
+res[85] = /a*/i;
+res[86] = /a+/i;
+res[87] = /(baa|a+)/i;
+res[88] = /a{0,3}/i;
+res[89] = /baa{3,}/i;
+res[90] = /"([^\\"]+|\\.)*"/i;
+res[91] = /(abc|ab[cd])/i;
+res[92] = /(a|.)/i;
+res[93] = /a|ba|\w/i;
+res[94] = /abc(?=pqr)/i;
+res[95] = /abc(?!pqr)/i;
+res[96] = /ab./i;
+res[97] = /ab[xyz]/i;
+res[98] = /abc*/i;
+res[99] = /ab.c*/i;
+res[100] = /a.c*/i;
+res[101] = /.c*/i;
+res[102] = /ac*/i;
+res[103] = /(a.c*|b.c*)/i;
+res[104] = /a.c*|aba/i;
+res[105] = /.+a/i;
+res[106] = /(?=abcda)a.*/i;
+res[107] = /(?=a)a.*/i;
+res[108] = /a(b)*/i;
+res[109] = /a\d*/i;
+res[110] = /ab\d*/i;
+res[111] = /a(\d)*/i;
+res[112] = /abcde{0,0}/i;
+res[113] = /ab\d+/i;
+res[114] = /ab\d{0}e/i;
+res[115] = /a?b?/i;
+res[116] = /|-/i;
+res[117] = /a*(b+)(z)(z)/i;
+res[118] = /^.?abcd/i;
+res[119] = /^[[:alnum:]]/;
+res[120] = /^[[:^alnum:]]/;
+res[121] = /^[[:alpha:]]/;
+res[122] = /^[[:^alpha:]]/;
+res[123] = /[_[:alpha:]]/i;
+res[124] = /^[[:ascii:]]/;
+res[125] = /^[[:^ascii:]]/;
+res[126] = /^[[:blank:]]/;
+res[127] = /^[[:^blank:]]/;
+res[128] = /[\n\x0b\x0c\x0d[:blank:]]/i;
+res[129] = /^[[:cntrl:]]/;
+res[130] = /^[[:digit:]]/;
+res[131] = /^[[:graph:]]/;
+res[132] = /^[[:lower:]]/;
+res[133] = /^[[:print:]]/;
+res[134] = /^[[:punct:]]/;
+res[135] = /^[[:space:]]/;
+res[136] = /^[[:upper:]]/;
+res[137] = /^[[:xdigit:]]/;
+res[138] = /^[[:word:]]/;
+res[139] = /^[[:^cntrl:]]/;
+res[140] = /^[12[:^digit:]]/;
+res[141] = /^[[:^blank:]]/;
+res[142] = /[01[:alpha:]%]/;
+res[143] = /[[.ch.]]/i;
+res[144] = /[[=ch=]]/i;
+res[145] = /[[:rhubarb:]]/i;
+res[146] = /[[:upper:]]/i;
+res[147] = /[[:lower:]]/i;
+res[148] = /This one's here because of the large output vector needed/i;
+res[149] = /(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\w+)\s+(\270)/i;
+res[150] = /This one's here because Perl does this differently and PCRE can't at present/i;
+res[151] = /(main(O)?)+/i;
+res[152] = /These are all cases where Perl does it differently (nested captures)/i;
+res[153] = /^(a(b)?)+$/i;
+res[154] = /^(aa(bb)?)+$/i;
+res[155] = /^(aa|aa(bb))+$/i;
+res[156] = /^(aa(bb)??)+$/i;
+res[157] = /^(?:aa(bb)?)+$/i;
+res[158] = /^(aa(b(b))?)+$/i;
+res[159] = /^(?:aa(b(b))?)+$/i;
+res[160] = /^(?:aa(b(?:b))?)+$/i;
+res[161] = /^(?:aa(bb(?:b))?)+$/i;
+res[162] = /^(?:aa(b(?:bb))?)+$/i;
+res[163] = /^(?:aa(?:b(b))?)+$/i;
+res[164] = /^(?:aa(?:b(bb))?)+$/i;
+res[165] = /^(aa(b(bb))?)+$/i;
+res[166] = /^(aa(bb(bb))?)+$/i;
+res[167] = /a/i;
+res[168] = /[\s]/;
+res[169] = /[\S]/;
+res[170] = /123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890/;
+res[171] = /\Q123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890/;
+res[172] = /\Q\E/;
+res[173] = /\Q\Ex/;
+res[174] = / \Q\E/;
+res[175] = /a\Q\E/;
+res[176] = /a\Q\Eb/;
+res[177] = /\Q\Eabc/;
+res[178] = /[.x.]/i;
+res[179] = /[=x=]/i;
+res[180] = /[:x:]/i;
+res[181] = /\l/i;
+res[182] = /\L/i;
+res[183] = /\N{name}/i;
+res[184] = /\u/i;
+res[185] = /\U/i;
+res[186] = /[[:space:]/i;
+res[187] = /[\s]/i;
+res[188] = /[[:space:]]/i;
+res[189] = /[[:space:]abcde]/i;
+res[190] = /(.*)\d+\1/i;
+res[191] = /(.*)\d+/i;
+res[192] = /(.*)\d+\1/i;
+res[193] = /(.*)\d+/i;
+res[194] = /(.*(xyz))\d+\2/i;
+res[195] = /((.*))\d+\1/i;
+res[196] = /a[b]/i;
+res[197] = /(?=a).*/i;
+res[198] = /(?=abc).xyz/i;
+res[199] = /(?=a)(?=b)/i;
+res[200] = /(?=.)a/i;
+res[201] = /((?=abcda)a)/i;
+res[202] = /((?=abcda)ab)/i;
+res[203] = /()a/i;
+res[204] = /(a)+/i;
+res[205] = /(a){2,3}/i;
+res[206] = /(a)*/i;
+res[207] = /[a]/i;
+res[208] = /[ab]/i;
+res[209] = /[ab]/i;
+res[210] = /[^a]/i;
+res[211] = /\d456/i;
+res[212] = /\d456/i;
+res[213] = /a^b/i;
+res[214] = /^a/im;
+res[215] = /c|abc/i;
+res[216] = /(.*)a/i;
+res[217] = /(.*)a\1/i;
+res[218] = /(.*)a(b)\2/i;
+res[219] = /((.*)a|(.*)b)z/i;
+res[220] = /((.*)a|(.*)b)z\1/i;
+res[221] = /((.*)a|(.*)b)z\2/i;
+res[222] = /((.*)a|(.*)b)z\3/i;
+res[223] = /((.*)a|^(.*)b)z\3/i;
+res[224] = /(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)a/i;
+res[225] = /(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)a\31/i;
+res[226] = /(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)a\32/i;
+res[227] = /(a)(bc)/i;
+res[228] = /(a+)*zz/i;
+res[229] = /((w\/|-|with)*(free|immediate)*.*?shipping\s*[!.-]*)/i;
+res[230] = /((w\/|-|with)*(free|immediate)*.*?shipping\s*[!.-]*)/i;
+res[231] = /a*.*b/i;
+res[232] = /(a|b)*.?c/i;
+res[233] = /abcde/i;
+res[234] = /a*b/i;
+res[235] = /a+b/i;
+res[236] = /(abc|def)x/i;
+res[237] = /(ab|cd){3,4}/i;
+res[238] = /([ab]{,4}c|xy)/i;
+res[239] = /([ab]{1,4}c|xy){4,5}?123/i;
+res[240] = /\b.*/i;
+res[241] = /\b.*/i;
+res[242] = /(?!.bcd).*/i;
+res[243] = /abcde/i;
+res[244] = /0{0,2}ABC/i;
+res[245] = /\d{3,}ABC/i;
+res[246] = /\d*ABC/i;
+res[247] = /[abc]+DE/i;
+res[248] = /[abc]?123/i;
+res[249] = /^(?:\d){3,5}X/i;
+res[250] = /^a/i;
+res[251] = /line\nbreak/i;
+res[252] = /line\nbreak/i;
+res[253] = /line\nbreak/im;
+res[254] = /ab.cd/i;
+res[255] = /ab.cd/i;
+res[256] = /a(b)c/i;
+res[257] = /Inthisnexttest,Jisnotsetattheouterlevel;consequentlyitisn'tsetinthepattern'soptions;consequentlypcre_get_named_substring()producesarandomvalue./i;
+res[258] = /\777/i;
+res[259] = /\s*,\s*/i;
+res[260] = /^abc/im;
+res[261] = /abc$/im;
+res[262] = /^abc/im;
+res[263] = /^abc/im;
+res[264] = /^abc/im;
+res[265] = /^abc/im;
+res[266] = /abc/i;
+res[267] = /.*/i;
+res[268] = /\w+(.)(.)?def/i;
+res[269] = /()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()(.(.))/i;
+res[270] = /()[ab]xyz/i;
+res[271] = /(|)[ab]xyz/i;
+res[272] = /(|c)[ab]xyz/i;
+res[273] = /(|c?)[ab]xyz/i;
+res[274] = /(d?|c?)[ab]xyz/i;
+res[275] = /(d?|c)[ab]xyz/i;
+res[276] = /^a*b\d/;
+res[277] = /^a*?b\d/;
+res[278] = /^a+A\d/;
+res[279] = /^a*A\d/i;
+res[280] = /(a*|b*)[cd]/i;
+res[281] = /(a+|b*)[cd]/i;
+res[282] = /(a*|b+)[cd]/i;
+res[283] = /(a+|b+)[cd]/i;
+res[284] = /(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((a)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))/i;
+res[285] = /a*\d/;
+res[286] = /a*\D/;
+res[287] = /0*\d/;
+res[288] = /0*\D/;
+res[289] = /a*\s/;
+res[290] = /a*\S/;
+res[291] = / *\s/;
+res[292] = / *\S/;
+res[293] = /a*\w/;
+res[294] = /a*\W/;
+res[295] = /=*\w/;
+res[296] = /=*\W/;
+res[297] = /\d*a/;
+res[298] = /\d*2/;
+res[299] = /\d*\d/;
+res[300] = /\d*\D/;
+res[301] = /\d*\s/;
+res[302] = /\d*\S/;
+res[303] = /\d*\w/;
+res[304] = /\d*\W/;
+res[305] = /\D*a/;
+res[306] = /\D*2/;
+res[307] = /\D*\d/;
+res[308] = /\D*\D/;
+res[309] = /\D*\s/;
+res[310] = /\D*\S/;
+res[311] = /\D*\w/;
+res[312] = /\D*\W/;
+res[313] = /\s*a/;
+res[314] = /\s*2/;
+res[315] = /\s*\d/;
+res[316] = /\s*\D/;
+res[317] = /\s*\s/;
+res[318] = /\s*\S/;
+res[319] = /\s*\w/;
+res[320] = /\s*\W/;
+res[321] = /\S*a/;
+res[322] = /\S*2/;
+res[323] = /\S*\d/;
+res[324] = /\S*\D/;
+res[325] = /\S*\s/;
+res[326] = /\S*\S/;
+res[327] = /\S*\w/;
+res[328] = /\S*\W/;
+res[329] = /\w*a/;
+res[330] = /\w*2/;
+res[331] = /\w*\d/;
+res[332] = /\w*\D/;
+res[333] = /\w*\s/;
+res[334] = /\w*\S/;
+res[335] = /\w*\w/;
+res[336] = /\w*\W/;
+res[337] = /\W*a/;
+res[338] = /\W*2/;
+res[339] = /\W*\d/;
+res[340] = /\W*\D/;
+res[341] = /\W*\s/;
+res[342] = /\W*\S/;
+res[343] = /\W*\w/;
+res[344] = /\W*\W/;
+res[345] = /[^a]+a/;
+res[346] = /[^a]+a/i;
+res[347] = /[^a]+A/i;
+res[348] = /[^a]+b/;
+res[349] = /[^a]+\d/;
+res[350] = /a*[^a]/;
+res[351] = /^(?:(?:\1|X)(a|b))+/;
+res[352] = /^[\E\Qa\E-\Qz\E]+/;
+res[353] = /^[a\Q]bc\E]/;
+res[354] = /(?=(\w+))\1:/i;
+res[355] = /(a|)*\d/;
+res[356] = /^a.b/;
+res[357] = /^abc./mg;
+res[358] = /abc.$/mg;
+res[359] = /a/;
+res[360] = /a/;
+res[361] = /^a\Rb/i;
+res[362] = /^a\R*b/i;
+res[363] = /^a\R+b/i;
+res[364] = /^a\R{1,3}b/i;
+res[365] = /^a[\R]b/i;
+res[366] = /^(a(b))\1\g1\g{1}\g-1\g{-1}\g{-02}Z/;
+res[367] = /^(a)\g-2/;
+res[368] = /^(a)\g/;
+res[369] = /^(a)\g{0}/;
+res[370] = /^(a)\g{3/;
+res[371] = /^(a)\g{4a}/;
+res[372] = /^a.b/;
+res[373] = /.+foo/;
+res[374] = /.+foo/;
+res[375] = /.+foo/;
+res[376] = /.+foo/;
+res[377] = /^$/mg;
+res[378] = /abc.$/mg;
+res[379] = /^X/m;
+res[380] = /(foo)\Kbar/;
+res[381] = /(foo)(\Kbar|baz)/;
+res[382] = /(foo\Kbar)baz/;
+res[383] = /\g{A/;
+res[384] = /\H\h\V\v/;
+res[385] = /\H*\h+\V?\v{3,4}/;
+res[386] = /\H{3,4}/;
+res[387] = /.\h{3,4}./;
+res[388] = /\h*X\h?\H+Y\H?Z/;
+res[389] = /\v*X\v?Y\v+Z\V*\x0a\V+\x0b\V{2,3}\x0c/;
+res[390] = /[\h]/;
+res[391] = /[\h]+/;
+res[392] = /[\v]/;
+res[393] = /[\H]/;
+res[394] = /[^\h]/;
+res[395] = /[\V]/;
+res[396] = /[\x0a\V]/;
+res[397] = /\H+\hY/;
+res[398] = /\H+ Y/;
+res[399] = /\h+A/;
+res[400] = /\v*B/;
+res[401] = /\V+\x0a/;
+res[402] = /A+\h/;
+res[403] = / *\H/;
+res[404] = /A*\v/;
+res[405] = /\x0b*\V/;
+res[406] = /\d+\h/;
+res[407] = /\d*\v/;
+res[408] = /S+\h\S+\v/;
+res[409] = /\w{3,}\h\w+\v/;
+res[410] = /\h+\d\h+\w\h+\S\h+\H/;
+res[411] = /\v+\d\v+\w\v+\S\v+\V/;
+res[412] = /\H+\h\H+\d/;
+res[413] = /\V+\v\V+\w/;
+res[414] = /[\E]AAA/;
+res[415] = /[\Q\E]AAA/;
+res[416] = /[^\E]AAA/;
+res[417] = /[^\Q\E]AAA/;
+res[418] = /[\E^]AAA/;
+res[419] = /[\Q\E^]AAA/;
+res[420] = /\g6666666666/;
+res[421] = /[\g6666666666]/;
+res[422] = /.+A/;
+res[423] = /\nA/;
+res[424] = /[\r\n]A/;
+res[425] = /(\r|\n)A/;
+res[426] = /a\Rb/i;
+res[427] = /a\Rb/i;
+res[428] = /a\R?b/i;
+res[429] = /a\R?b/i;
+res[430] = /a\R{2,4}b/i;
+res[431] = /a\R{2,4}b/i;
+res[432] = /\k''/;
+res[433] = /\k<>/;
+res[434] = /\k{}/;
+res[435] = /[[:foo:]]/;
+res[436] = /[[:1234:]]/;
+res[437] = /[[:f\oo:]]/;
+res[438] = /[[: :]]/;
+res[439] = /[[:...:]]/;
+res[440] = /[[:l\ower:]]/;
+res[441] = /[[:abc\:]]/;
+res[442] = /[abc[:x\]pqr:]]/;
+res[443] = /[[:a\dz:]]/;
+res[444] = /^(a|b\g<1>c)/;
+res[445] = /^(a|b\g'1'c)/;
+res[446] = /^(a|b\g'-1'c)/;
+res[447] = /(^(a|b\g<-1>c))/;
+res[448] = /(^(a|b\g<-1'c))/;
+res[449] = /(^(a|b\g{-1}))/;
+res[450] = /(\3)(\1)(a)/;
+res[451] = /(\3)(\1)(a)/;
+res[452] = /TA]/;
+res[453] = /TA]/;
+res[454] = /a[]b/;
+res[455] = /a[^]b/;
+res[456] = /a[]b/;
+res[457] = /a[]+b/;
+res[458] = /a[^]b/;
+res[459] = /a[^]+b/;
+res[460] = /a(?!)+b/;
+res[461] = /(abc|pqr|123){0}[xyz]/i;
+res[462] = / End of testinput2 /;
+res[463] = /a.b/;
+res[464] = /a(.{3})b/;
+res[465] = /a(.*?)(.)/;
+res[466] = /a(.*?)(.)/;
+res[467] = /a(.*)(.)/;
+res[468] = /a(.*)(.)/;
+res[469] = /a(.)(.)/;
+res[470] = /a(.)(.)/;
+res[471] = /a(.?)(.)/;
+res[472] = /a(.?)(.)/;
+res[473] = /a(.??)(.)/;
+res[474] = /a(.??)(.)/;
+res[475] = /a(.{3})b/;
+res[476] = /a(.{3,})b/;
+res[477] = /a(.{3,}?)b/;
+res[478] = /a(.{3,5})b/;
+res[479] = /a(.{3,5}?)b/;
+res[480] = /X(\C{3})/;
+res[481] = /X(\C{4})/;
+res[482] = /X\C*/;
+res[483] = /X\C*?/;
+res[484] = /X\C{3,5}/;
+res[485] = /X\C{3,5}?/;
+res[486] = /[^a]+/g;
+res[487] = /^[^a]{2}/;
+res[488] = /^[^a]{2,}/;
+res[489] = /^[^a]{2,}?/;
+res[490] = /[^a]+/ig;
+res[491] = /^[^a]{2}/i;
+res[492] = /^[^a]{2,}/i;
+res[493] = /^[^a]{2,}?/i;
+res[494] = /\D*/;
+res[495] = /\D*/;
+res[496] = /\D/;
+res[497] = />\S/;
+res[498] = /\d/;
+res[499] = /\s/;
+res[500] = /\D+/;
+res[501] = /\D{2,3}/;
+res[502] = /\D{2,3}?/;
+res[503] = /\d+/;
+res[504] = /\d{2,3}/;
+res[505] = /\d{2,3}?/;
+res[506] = /\S+/;
+res[507] = /\S{2,3}/;
+res[508] = /\S{2,3}?/;
+res[509] = />\s+</;
+res[510] = />\s{2,3}</;
+res[511] = />\s{2,3}?</;
+res[512] = /\w+/;
+res[513] = /\w{2,3}/;
+res[514] = /\w{2,3}?/;
+res[515] = /\W+/;
+res[516] = /\W{2,3}/;
+res[517] = /\W{2,3}?/;
+res[518] = /a\Cb/;
+res[519] = /a\Cb/;
+res[520] = /[\xFF]/;
+res[521] = /[\xff]/;
+res[522] = /[^\xFF]/;
+res[523] = /[^\xff]/;
+res[524] = /^[ac]*b/;
+res[525] = /^[^x]*b/i;
+res[526] = /^[^x]*b/;
+res[527] = /^\d*b/;
+res[528] = /(|a)/g;
+res[529] = /\S\S/g;
+res[530] = /\S{2}/g;
+res[531] = /\W\W/g;
+res[532] = /\W{2}/g;
+res[533] = /\S/g;
+res[534] = /[\S]/g;
+res[535] = /\D/g;
+res[536] = /[\D]/g;
+res[537] = /\W/g;
+res[538] = /[\W]/g;
+res[539] = /[\S\s]*/;
+res[540] = /.[^\S]./g;
+res[541] = /.[^\S\n]./g;
+res[542] = /[[:^alnum:]]/g;
+res[543] = /[[:^alpha:]]/g;
+res[544] = /[[:^ascii:]]/g;
+res[545] = /[[:^blank:]]/g;
+res[546] = /[[:^cntrl:]]/g;
+res[547] = /[[:^digit:]]/g;
+res[548] = /[[:^graph:]]/g;
+res[549] = /[[:^lower:]]/g;
+res[550] = /[[:^print:]]/g;
+res[551] = /[[:^punct:]]/g;
+res[552] = /[[:^space:]]/g;
+res[553] = /[[:^upper:]]/g;
+res[554] = /[[:^word:]]/g;
+res[555] = /[[:^xdigit:]]/g;
+res[556] = /^[^d]*?$/;
+res[557] = /^[^d]*?$/;
+res[558] = /^[^d]*?$/i;
+res[559] = /^[^d]*?$/i;
+res[560] = / End of testinput4 /;
+res[561] = /\x80/;
+res[562] = /\xff/;
+res[563] = /.{3,5}X/;
+res[564] = /.{3,5}?/;
+res[565] = /X(\C)(.*)/;
+res[566] = /^[ab]/;
+res[567] = /^[^ab]/;
+res[568] = /[^ab\xC0-\xF0]/;
+res[569] = /[\xFF]/;
+res[570] = /[\xff]/;
+res[571] = /[^\xFF]/;
+res[572] = /[^\xff]/;
+res[573] = /anything/;
+res[574] = /\W/;
+res[575] = /\w/;
+res[576] = /\777/i;
+res[577] = /\777/i;
+res[578] = /^abc./mg;
+res[579] = /abc.$/mg;
+res[580] = /^a\Rb/i;
+res[581] = /^a\R*b/i;
+res[582] = /^a\R+b/i;
+res[583] = /^a\R{1,3}b/i;
+res[584] = /\H\h\V\v/;
+res[585] = /\H*\h+\V?\v{3,4}/;
+res[586] = /\H\h\V\v/;
+res[587] = /\H*\h+\V?\v{3,4}/;
+res[588] = /[\h]/;
+res[589] = /[\h]{3,}/;
+res[590] = /[\v]/;
+res[591] = /[\H]/;
+res[592] = /[\V]/;
+res[593] = /.*$/;
+res[594] = /X/;
+res[595] = /a\Rb/i;
+res[596] = /a\Rb/i;
+res[597] = /a\R?b/i;
+res[598] = /a\R?b/i;
+res[599] = /.*a.*=.b.*/;
+res[600] = /a[^]b/;
+res[601] = /a[^]+b/;
+res[602] = /X/;
+res[603] = / End of testinput5 /;
+res[604] = /^\pC\pL\pM\pN\pP\pS\pZ</;
+res[605] = /^\PC/;
+res[606] = /^\PL/;
+res[607] = /^\PM/;
+res[608] = /^\PN/;
+res[609] = /^\PP/;
+res[610] = /^\PS/;
+res[611] = /^\PZ/;
+res[612] = /^\p{Cc}/;
+res[613] = /^\p{Cf}/;
+res[614] = /^\p{Cn}/;
+res[615] = /^\p{Co}/;
+res[616] = /^\p{Cs}/;
+res[617] = /^\p{Ll}/;
+res[618] = /^\p{Lm}/;
+res[619] = /^\p{Lo}/;
+res[620] = /^\p{Lt}/;
+res[621] = /^\p{Lu}/;
+res[622] = /^\p{Mc}/;
+res[623] = /^\p{Me}/;
+res[624] = /^\p{Mn}/;
+res[625] = /^\p{Nl}/;
+res[626] = /^\p{No}/;
+res[627] = /^\p{Pc}/;
+res[628] = /^\p{Pd}/;
+res[629] = /^\p{Pe}/;
+res[630] = /^\p{Pf}/;
+res[631] = /^\p{Pi}/;
+res[632] = /^\p{Po}/;
+res[633] = /^\p{Ps}/;
+res[634] = /^\p{Sk}/;
+res[635] = /^\p{So}/;
+res[636] = /^\p{Zl}/;
+res[637] = /^\p{Zp}/;
+res[638] = /^\p{Zs}/;
+res[639] = /\p{Nd}{2,}(..)/;
+res[640] = /\p{Nd}{2,}?(..)/;
+res[641] = /\p{Nd}*(..)/;
+res[642] = /\p{Nd}*?(..)/;
+res[643] = /\p{Nd}{2}(..)/;
+res[644] = /\p{Nd}{2,3}(..)/;
+res[645] = /\p{Nd}{2,3}?(..)/;
+res[646] = /\p{Nd}?(..)/;
+res[647] = /\p{Nd}??(..)/;
+res[648] = /\p{Lu}/i;
+res[649] = /\p{^Lu}/i;
+res[650] = /\P{Lu}/i;
+res[651] = /[\p{L}]/;
+res[652] = /[\p{^L}]/;
+res[653] = /[\P{L}]/;
+res[654] = /[\P{^L}]/;
+res[655] = /[\p{Nd}]/;
+res[656] = /[\P{Nd}]+/;
+res[657] = /\D+/;
+res[658] = /[\D]+/;
+res[659] = /[\P{Nd}]+/;
+res[660] = /[\D\P{Nd}]+/;
+res[661] = /\pL/;
+res[662] = /\pL/i;
+res[663] = /\p{Lu}/;
+res[664] = /\p{Lu}/i;
+res[665] = /\p{Ll}/;
+res[666] = /\p{Ll}/i;
+res[667] = /^\X/;
+res[668] = /^[\X]/;
+res[669] = /^(\X*)C/;
+res[670] = /^(\X*?)C/;
+res[671] = /^(\X*)(.)/;
+res[672] = /^(\X*?)(.)/;
+res[673] = /^\X(.)/;
+res[674] = /^\X{2,3}(.)/;
+res[675] = /^\X{2,3}?(.)/;
+res[676] = /^[\p{Arabic}]/;
+res[677] = /^[\P{Yi}]/;
+res[678] = /^\p{Any}X/;
+res[679] = /^\P{Any}X/;
+res[680] = /^\p{Any}?X/;
+res[681] = /^\P{Any}?X/;
+res[682] = /^\p{Any}*X/;
+res[683] = /^\P{Any}*X/;
+res[684] = /^[\p{Any}]X/;
+res[685] = /^[\P{Any}]X/;
+res[686] = /^[\p{Any}]?X/;
+res[687] = /^[\P{Any}]?X/;
+res[688] = /^[\p{Any}]+X/;
+res[689] = /^[\P{Any}]+X/;
+res[690] = /^[\p{Any}]*X/;
+res[691] = /^[\P{Any}]*X/;
+res[692] = /^\p{Any}{3,5}?/;
+res[693] = /^\p{Any}{3,5}/;
+res[694] = /^\P{Any}{3,5}?/;
+res[695] = /^\p{L&}X/;
+res[696] = /^[\p{L&}]X/;
+res[697] = /^[\p{L&}]+X/;
+res[698] = /^[\p{L&}]+?X/;
+res[699] = /^\P{L&}X/;
+res[700] = /^[\P{L&}]X/;
+res[701] = /^(\p{Z}[^\p{C}\p{Z}]+)*$/;
+res[702] = /([\pL]=(abc))*X/;
+res[703] = /^\p{Balinese}\p{Cuneiform}\p{Nko}\p{Phags_Pa}\p{Phoenician}/;
+res[704] = /The next two are special cases where the lengths of the different cases of the \nsame character differ. The first went wrong with heap frame storage; the 2nd\nwas broken in all cases./;
+res[705] = /Check property support in non-UTF-8 mode/;
+res[706] = /\p{L}{4}/;
+res[707] = /\X{1,3}\d/;
+res[708] = /\X?\d/;
+res[709] = /\P{L}?\d/;
+res[710] = /[\PPP\x8a]{1,}\x80/;
+res[711] = /(?:[\PPa*]*){8,}/;
+res[712] = /[\P{Any}]/;
+res[713] = /[\P{Any}\E]/;
+res[714] = /(\P{Yi}{2}\277)?/;
+res[715] = /[\P{Yi}A]/;
+res[716] = /[\P{Yi}\P{Yi}\P{Yi}A]/;
+res[717] = /[^\P{Yi}A]/;
+res[718] = /[^\P{Yi}\P{Yi}\P{Yi}A]/;
+res[719] = /(\P{Yi}*\277)*/;
+res[720] = /(\P{Yi}*?\277)*/;
+res[721] = /(\P{Yi}?\277)*/;
+res[722] = /(\P{Yi}??\277)*/;
+res[723] = /(\P{Yi}{0,3}\277)*/;
+res[724] = /(\P{Yi}{0,3}?\277)*/;
+res[725] = /^[\p{Arabic}]/;
+res[726] = /^\p{Cyrillic}/;
+res[727] = /^\p{Common}/;
+res[728] = /^\p{Inherited}/;
+res[729] = /^\p{Shavian}/;
+res[730] = /^\p{Deseret}/;
+res[731] = /^\p{Osmanya}/;
+res[732] = /\p{Zl}/;
+res[733] = /\p{Carian}\p{Cham}\p{Kayah_Li}\p{Lepcha}\p{Lycian}\p{Lydian}\p{Ol_Chiki}\p{Rejang}\p{Saurashtra}\p{Sundanese}\p{Vai}/;
+res[734] = /(A)\1/i;
+res[735] = / End of testinput6 /;
+res[736] = /abc/;
+res[737] = /ab*c/;
+res[738] = /ab+c/;
+res[739] = /a*/;
+res[740] = /(a|abcd|african)/;
+res[741] = /^abc/;
+res[742] = /^abc/m;
+res[743] = /\Aabc/;
+res[744] = /\Aabc/m;
+res[745] = /\Gabc/;
+res[746] = /x\dy\Dz/;
+res[747] = /x\sy\Sz/;
+res[748] = /x\wy\Wz/;
+res[749] = /x.y/;
+res[750] = /x.y/;
+res[751] = /a\d\z/;
+res[752] = /a\d\z/m;
+res[753] = /a\d\Z/;
+res[754] = /a\d\Z/m;
+res[755] = /a\d$/;
+res[756] = /a\d$/m;
+res[757] = /abc/i;
+res[758] = /[^a]/;
+res[759] = /ab?\w/;
+res[760] = /x{0,3}yz/;
+res[761] = /x{3}yz/;
+res[762] = /x{2,3}yz/;
+res[763] = /[^a]+/;
+res[764] = /[^a]*/;
+res[765] = /[^a]{3,5}/;
+res[766] = /\d*/;
+res[767] = /\D*/;
+res[768] = /\d+/;
+res[769] = /\D+/;
+res[770] = /\d?A/;
+res[771] = /\D?A/;
+res[772] = /a+/;
+res[773] = /^.*xyz/;
+res[774] = /^.+xyz/;
+res[775] = /^.?xyz/;
+res[776] = /^\d{2,3}X/;
+res[777] = /^[abcd]\d/;
+res[778] = /^[abcd]*\d/;
+res[779] = /^[abcd]+\d/;
+res[780] = /^a+X/;
+res[781] = /^[abcd]?\d/;
+res[782] = /^[abcd]{2,3}\d/;
+res[783] = /^(abc)*\d/;
+res[784] = /^(abc)+\d/;
+res[785] = /^(abc)?\d/;
+res[786] = /^(abc){2,3}\d/;
+res[787] = /^(a*\w|ab)=(a*\w|ab)/;
+res[788] = /^(?=abc)\w{5}:$/;
+res[789] = /^(?!abc)\d\d$/;
+res[790] = /(ab|cd){3,4}/;
+res[791] = /^abc/;
+res[792] = /^(a*|xyz)/;
+res[793] = /xyz$/;
+res[794] = /xyz$/m;
+res[795] = /\Gabc/;
+res[796] = /^abcdef/;
+res[797] = /^a{2,4}\d+z/;
+res[798] = /^abcdef/;
+res[799] = /(ab*(cd|ef))+X/;
+res[800] = /the quick brown fox/;
+res[801] = /The quick brown fox/i;
+res[802] = /abcd\t\n\r\f\a\e\071\x3b\$\\\?caxyz/;
+res[803] = /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/;
+res[804] = /^(abc){1,2}zz/;
+res[805] = /^(b+?|a){1,2}?c/;
+res[806] = /^(b+|a){1,2}c/;
+res[807] = /^(b*|ba){1,2}?bc/;
+res[808] = /^(ba|b*){1,2}?bc/;
+res[809] = /^[ab\]cde]/;
+res[810] = /^[]cde]/;
+res[811] = /^[^ab\]cde]/;
+res[812] = /^[^]cde]/;
+res[813] = /^[0-9]+$/;
+res[814] = /^.*nter/;
+res[815] = /^xxx[0-9]+$/;
+res[816] = /^.+[0-9][0-9][0-9]$/;
+res[817] = /^.+?[0-9][0-9][0-9]$/;
+res[818] = /^([^!]+)!(.+)=apquxz\.ixr\.zzz\.ac\.uk$/;
+res[819] = /:/;
+res[820] = /([\da-f:]+)$/i;
+res[821] = /^.*\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
+res[822] = /^(\d+)\s+IN\s+SOA\s+(\S+)\s+(\S+)\s*\(\s*$/;
+res[823] = /^[a-zA-Z\d][a-zA-Z\d\-]*(\.[a-zA-Z\d][a-zA-z\d\-]*)*\.$/;
+res[824] = /^\*\.[a-z]([a-z\-\d]*[a-z\d]+)?(\.[a-z]([a-z\-\d]*[a-z\d]+)?)*$/;
+res[825] = /^(?=ab(de))(abd)(e)/;
+res[826] = /^(?!(ab)de|x)(abd)(f)/;
+res[827] = /^(?=(ab(cd)))(ab)/;
+res[828] = /^[\da-f](\.[\da-f])*$/i;
+res[829] = /^\".*\"\s*(;.*)?$/;
+res[830] = /^$/;
+res[831] = /^ab\sc$/;
+res[832] = /^a\ b[c]d$/;
+res[833] = /^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$/;
+res[834] = /^(?:a(b(c)))(?:d(e(f)))(?:h(i(j)))(?:k(l(m)))$/;
+res[835] = /^[\w][\W][\s][\S][\d][\D][\b][\n][\c]][\022]/;
+res[836] = /^a*\w/;
+res[837] = /^a*?\w/;
+res[838] = /^a+\w/;
+res[839] = /^a+?\w/;
+res[840] = /^\d{8}\w{2,}/;
+res[841] = /^[aeiou\d]{4,5}$/;
+res[842] = /^[aeiou\d]{4,5}?/;
+res[843] = /^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]/;
+res[844] = /^From\s+\S+\s+([a-zA-Z]{3}\s+){2}\d{1,2}\s+\d\d:\d\d/;
+res[845] = /^12.34/;
+res[846] = /\w+(?=\t)/;
+res[847] = /foo(?!bar)(.*)/;
+res[848] = /(?:(?!foo)...|^.{0,2})bar(.*)/;
+res[849] = /^(\D*)(?=\d)(?!123)/;
+res[850] = /^1234/;
+res[851] = /^1234/;
+res[852] = /abcd/;
+res[853] = /^abcd/;
+res[854] = /(?!^)abc/;
+res[855] = /(?=^)abc/;
+res[856] = /^[ab]{1,3}(ab*|b)/;
+res[857] = /^[ab]{1,3}?(ab*|b)/;
+res[858] = /^[ab]{1,3}?(ab*?|b)/;
+res[859] = /^[ab]{1,3}(ab*?|b)/;
+res[860] = /(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*(?:(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"(?:[^\\\x80-\xff\n\015"]|\\[^\x80-\xff])*")(?:(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*\.(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"(?:[^\\\x80-\xff\n\015"]|\\[^\x80-\xff])*"))*(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*@(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])(?:(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*\.(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\]))*|(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"(?:[^\\\x80-\xff\n\015"]|\\[^\x80-\xff])*")(?:[^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\)|"(?:[^\\\x80-\xff\n\015"]|\\[^\x80-\xff])*")*<(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*(?:@(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])(?:(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*\.(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\]))*(?:(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*,(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*@(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])(?:(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*\.(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\]))*)*:(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*)?(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"(?:[^\\\x80-\xff\n\015"]|\\[^\x80-\xff])*")(?:(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*\.(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"(?:[^\\\x80-\xff\n\015"]|\\[^\x80-\xff])*"))*(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*@(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])(?:(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*\.(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\]))*(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*>)(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*/;
+res[861] = /[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*@[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*|(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037]*(?:(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037]*)*<[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:@[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*(?:,[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*@[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*)*:[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)?(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*@[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*>)/;
+res[862] = /abc\x0def\x00pqr\x000xyz\x0000AB/;
+res[863] = /^[\000-\037]/;
+res[864] = /\0*/;
+res[865] = /A\x0{2,3}Z/;
+res[866] = /^\s/;
+res[867] = /^abc/;
+res[868] = /ab{1,3}bc/;
+res[869] = /([^.]*)\.([^:]*):[T ]+(.*)/;
+res[870] = /([^.]*)\.([^:]*):[T ]+(.*)/i;
+res[871] = /([^.]*)\.([^:]*):[t ]+(.*)/i;
+res[872] = /^[W-c]+$/;
+res[873] = /^[W-c]+$/i;
+res[874] = /^[\x3f-\x5F]+$/i;
+res[875] = /^abc$/m;
+res[876] = /^abc$/;
+res[877] = /\Aabc\Z/m;
+res[878] = /\A(.)*\Z/;
+res[879] = /\A(.)*\Z/m;
+res[880] = /(?:b)|(?::+)/;
+res[881] = /[-az]+/;
+res[882] = /[az-]+/;
+res[883] = /[a\-z]+/;
+res[884] = /[a-z]+/;
+res[885] = /[\d-]+/;
+res[886] = /[\d-z]+/;
+res[887] = /\x5c/;
+res[888] = /\x20Z/;
+res[889] = /ab{3cd/;
+res[890] = /ab{3,cd/;
+res[891] = /ab{3,4a}cd/;
+res[892] = /{4,5a}bc/;
+res[893] = /^a.b/;
+res[894] = /abc$/;
+res[895] = /(abc)\123/;
+res[896] = /(abc)\223/;
+res[897] = /(abc)\323/;
+res[898] = /(abc)\100/;
+res[899] = /abc\81/;
+res[900] = /abc\91/;
+res[901] = /(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\12\123/;
+res[902] = /ab\idef/;
+res[903] = /a{0}bc/;
+res[904] = /(a|(bc)){0,0}?xyz/;
+res[905] = /abc[\10]de/;
+res[906] = /abc[\1]de/;
+res[907] = /(abc)[\1]de/;
+res[908] = /^([^a])([^\b])([^c]*)([^d]{3,4})/;
+res[909] = /[^a]/;
+res[910] = /[^a]/i;
+res[911] = /[^a]+/;
+res[912] = /[^a]+/i;
+res[913] = /[^a]+/;
+res[914] = /[^k]$/;
+res[915] = /[^k]{2,3}$/;
+res[916] = /^\d{8,}\@.+[^k]$/;
+res[917] = /[^a]/;
+res[918] = /[^a]/i;
+res[919] = /[^az]/;
+res[920] = /[^az]/i;
+res[921] = /\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377/;
+res[922] = /P[^*]TAIRE[^*]{1,6}?LL/;
+res[923] = /P[^*]TAIRE[^*]{1,}?LL/;
+res[924] = /(\.\d\d[1-9]?)\d+/;
+res[925] = /(\.\d\d((?=0)|\d(?=\d)))/;
+res[926] = /\b(foo)\s+(\w+)/i;
+res[927] = /foo(.*)bar/;
+res[928] = /foo(.*?)bar/;
+res[929] = /(.*)(\d*)/;
+res[930] = /(.*)(\d+)/;
+res[931] = /(.*?)(\d*)/;
+res[932] = /(.*?)(\d+)/;
+res[933] = /(.*)(\d+)$/;
+res[934] = /(.*?)(\d+)$/;
+res[935] = /(.*)\b(\d+)$/;
+res[936] = /(.*\D)(\d+)$/;
+res[937] = /^\D*(?!123)/;
+res[938] = /^(\D*)(?=\d)(?!123)/;
+res[939] = /^[W-]46]/;
+res[940] = /^[W-\]46]/;
+res[941] = /\d\d\/\d\d\/\d\d\d\d/;
+res[942] = /word (?:[a-zA-Z0-9]+ ){0,10}otherword/;
+res[943] = /word (?:[a-zA-Z0-9]+ ){0,300}otherword/;
+res[944] = /^(a){0,0}/;
+res[945] = /^(a){0,1}/;
+res[946] = /^(a){0,2}/;
+res[947] = /^(a){0,3}/;
+res[948] = /^(a){0,}/;
+res[949] = /^(a){1,1}/;
+res[950] = /^(a){1,2}/;
+res[951] = /^(a){1,3}/;
+res[952] = /^(a){1,}/;
+res[953] = /.*\.gif/;
+res[954] = /.{0,}\.gif/;
+res[955] = /.*\.gif/m;
+res[956] = /.*\.gif/;
+res[957] = /.*\.gif/m;
+res[958] = /.*$/;
+res[959] = /.*$/m;
+res[960] = /.*$/;
+res[961] = /.*$/m;
+res[962] = /.*$/;
+res[963] = /.*$/m;
+res[964] = /.*$/;
+res[965] = /.*$/m;
+res[966] = /(.*X|^B)/;
+res[967] = /(.*X|^B)/m;
+res[968] = /(.*X|^B)/;
+res[969] = /(.*X|^B)/m;
+res[970] = /^.*B/;
+res[971] = /^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/;
+res[972] = /^\d\d\d\d\d\d\d\d\d\d\d\d/;
+res[973] = /^[\d][\d][\d][\d][\d][\d][\d][\d][\d][\d][\d][\d]/;
+res[974] = /^[abc]{12}/;
+res[975] = /^[a-c]{12}/;
+res[976] = /^(a|b|c){12}/;
+res[977] = /^[abcdefghijklmnopqrstuvwxy0123456789]/;
+res[978] = /abcde{0,0}/;
+res[979] = /ab[cd]{0,0}e/;
+res[980] = /ab(c){0,0}d/;
+res[981] = /a(b*)/;
+res[982] = /ab\d{0}e/;
+res[983] = /"([^\\"]+|\\.)*"/;
+res[984] = /.*?/g;
+res[985] = /\b/g;
+res[986] = /\b/g;
+res[987] = /<tr([\w\W\s\d][^<>]{0,})><TD([\w\W\s\d][^<>]{0,})>([\d]{0,}\.)(.*)((<BR>([\w\W\s\d][^<>]{0,})|[\s]{0,}))<\/a><\/TD><TD([\w\W\s\d][^<>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD><TD([\w\W\s\d][^<>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD><\/TR>/i;
+res[988] = /a[^a]b/;
+res[989] = /a.b/;
+res[990] = /a[^a]b/;
+res[991] = /a.b/;
+res[992] = /^(b+?|a){1,2}?c/;
+res[993] = /^(b+|a){1,2}?c/;
+res[994] = /(?!\A)x/m;
+res[995] = /\x0{ab}/;
+res[996] = /(A|B)*?CD/;
+res[997] = /(A|B)*CD/;
+res[998] = /\Aabc\z/m;
+res[999] = /(\d+)(\w)/;
+res[1000] = /(a+|b+|c+)*c/;
+res[1001] = /(abc|)+/;
+res[1002] = /([a]*)*/;
+res[1003] = /([ab]*)*/;
+res[1004] = /([^a]*)*/;
+res[1005] = /([^ab]*)*/;
+res[1006] = /([a]*?)*/;
+res[1007] = /([ab]*?)*/;
+res[1008] = /([^a]*?)*/;
+res[1009] = /([^ab]*?)*/;
+res[1010] = /The following tests are taken from the Perl 5.005 test suite; some of them/;
+res[1011] = /are compatible with 5.004, but I'd rather not have to sort them out./;
+res[1012] = /abc/;
+res[1013] = /ab*c/;
+res[1014] = /ab*bc/;
+res[1015] = /.{1}/;
+res[1016] = /.{3,4}/;
+res[1017] = /ab{0,}bc/;
+res[1018] = /ab+bc/;
+res[1019] = /ab{1,}bc/;
+res[1020] = /ab+bc/;
+res[1021] = /ab{1,}bc/;
+res[1022] = /ab{1,3}bc/;
+res[1023] = /ab{3,4}bc/;
+res[1024] = /ab{4,5}bc/;
+res[1025] = /ab?bc/;
+res[1026] = /ab{0,1}bc/;
+res[1027] = /ab?bc/;
+res[1028] = /ab?c/;
+res[1029] = /ab{0,1}c/;
+res[1030] = /^abc$/;
+res[1031] = /^abc/;
+res[1032] = /^abc$/;
+res[1033] = /abc$/;
+res[1034] = /^/;
+res[1035] = /$/;
+res[1036] = /a.c/;
+res[1037] = /a.*c/;
+res[1038] = /a[bc]d/;
+res[1039] = /a[b-d]e/;
+res[1040] = /a[b-d]/;
+res[1041] = /a[-b]/;
+res[1042] = /a[b-]/;
+res[1043] = /a]/;
+res[1044] = /a[]]b/;
+res[1045] = /a[^bc]d/;
+res[1046] = /a[^-b]c/;
+res[1047] = /a[^]b]c/;
+res[1048] = /\ba\b/;
+res[1049] = /\by\b/;
+res[1050] = /\Ba\B/;
+res[1051] = /\By\b/;
+res[1052] = /\by\B/;
+res[1053] = /\By\B/;
+res[1054] = /\w/;
+res[1055] = /\W/;
+res[1056] = /a\sb/;
+res[1057] = /a\Sb/;
+res[1058] = /\d/;
+res[1059] = /\D/;
+res[1060] = /[\w]/;
+res[1061] = /[\W]/;
+res[1062] = /a[\s]b/;
+res[1063] = /a[\S]b/;
+res[1064] = /[\d]/;
+res[1065] = /[\D]/;
+res[1066] = /ab|cd/;
+res[1067] = /()ef/;
+res[1068] = /$b/;
+res[1069] = /a\(b/;
+res[1070] = /a\\b/;
+res[1071] = /((a))/;
+res[1072] = /(a)b(c)/;
+res[1073] = /a+b+c/;
+res[1074] = /a{1,}b{1,}c/;
+res[1075] = /a.+?c/;
+res[1076] = /(a+|b)*/;
+res[1077] = /(a+|b){0,}/;
+res[1078] = /(a+|b)+/;
+res[1079] = /(a+|b){1,}/;
+res[1080] = /(a+|b)?/;
+res[1081] = /(a+|b){0,1}/;
+res[1082] = /[^ab]*/;
+res[1083] = /abc/;
+res[1084] = /a*/;
+res[1085] = /([abc])*d/;
+res[1086] = /([abc])*bcd/;
+res[1087] = /a|b|c|d|e/;
+res[1088] = /(a|b|c|d|e)f/;
+res[1089] = /abcd*efg/;
+res[1090] = /ab*/;
+res[1091] = /(ab|cd)e/;
+res[1092] = /[abhgefdc]ij/;
+res[1093] = /^(ab|cd)e/;
+res[1094] = /(abc|)ef/;
+res[1095] = /(a|b)c*d/;
+res[1096] = /(ab|ab*)bc/;
+res[1097] = /a([bc]*)c*/;
+res[1098] = /a([bc]*)(c*d)/;
+res[1099] = /a([bc]+)(c*d)/;
+res[1100] = /a([bc]*)(c+d)/;
+res[1101] = /a[bcd]*dcdcde/;
+res[1102] = /a[bcd]+dcdcde/;
+res[1103] = /(ab|a)b*c/;
+res[1104] = /((a)(b)c)(d)/;
+res[1105] = /[a-zA-Z_][a-zA-Z0-9_]*/;
+res[1106] = /^a(bc+|b[eh])g|.h$/;
+res[1107] = /(bc+d$|ef*g.|h?i(j|k))/;
+res[1108] = /((((((((((a))))))))))/;
+res[1109] = /(((((((((a)))))))))/;
+res[1110] = /multiple words of text/;
+res[1111] = /multiple words/;
+res[1112] = /(.*)c(.*)/;
+res[1113] = /\((.*), (.*)\)/;
+res[1114] = /[k]/;
+res[1115] = /abcd/;
+res[1116] = /a(bc)d/;
+res[1117] = /a[-]?c/;
+res[1118] = /abc/i;
+res[1119] = /ab*c/i;
+res[1120] = /ab*bc/i;
+res[1121] = /ab*?bc/i;
+res[1122] = /ab{0,}?bc/i;
+res[1123] = /ab+?bc/i;
+res[1124] = /ab+bc/i;
+res[1125] = /ab{1,}bc/i;
+res[1126] = /ab+bc/i;
+res[1127] = /ab{1,}?bc/i;
+res[1128] = /ab{1,3}?bc/i;
+res[1129] = /ab{3,4}?bc/i;
+res[1130] = /ab{4,5}?bc/i;
+res[1131] = /ab??bc/i;
+res[1132] = /ab{0,1}?bc/i;
+res[1133] = /ab??bc/i;
+res[1134] = /ab??c/i;
+res[1135] = /ab{0,1}?c/i;
+res[1136] = /^abc$/i;
+res[1137] = /^abc/i;
+res[1138] = /^abc$/i;
+res[1139] = /abc$/i;
+res[1140] = /^/i;
+res[1141] = /$/i;
+res[1142] = /a.c/i;
+res[1143] = /a.*?c/i;
+res[1144] = /a.*c/i;
+res[1145] = /a[bc]d/i;
+res[1146] = /a[b-d]e/i;
+res[1147] = /a[b-d]/i;
+res[1148] = /a[-b]/i;
+res[1149] = /a[b-]/i;
+res[1150] = /a]/i;
+res[1151] = /a[]]b/i;
+res[1152] = /a[^bc]d/i;
+res[1153] = /a[^-b]c/i;
+res[1154] = /a[^]b]c/i;
+res[1155] = /ab|cd/i;
+res[1156] = /()ef/i;
+res[1157] = /$b/i;
+res[1158] = /a\(b/i;
+res[1159] = /a\\b/i;
+res[1160] = /((a))/i;
+res[1161] = /(a)b(c)/i;
+res[1162] = /a+b+c/i;
+res[1163] = /a{1,}b{1,}c/i;
+res[1164] = /a.+?c/i;
+res[1165] = /a.*?c/i;
+res[1166] = /a.{0,5}?c/i;
+res[1167] = /(a+|b)*/i;
+res[1168] = /(a+|b){0,}/i;
+res[1169] = /(a+|b)+/i;
+res[1170] = /(a+|b){1,}/i;
+res[1171] = /(a+|b)?/i;
+res[1172] = /(a+|b){0,1}/i;
+res[1173] = /(a+|b){0,1}?/i;
+res[1174] = /[^ab]*/i;
+res[1175] = /abc/i;
+res[1176] = /a*/i;
+res[1177] = /([abc])*d/i;
+res[1178] = /([abc])*bcd/i;
+res[1179] = /a|b|c|d|e/i;
+res[1180] = /(a|b|c|d|e)f/i;
+res[1181] = /abcd*efg/i;
+res[1182] = /ab*/i;
+res[1183] = /(ab|cd)e/i;
+res[1184] = /[abhgefdc]ij/i;
+res[1185] = /^(ab|cd)e/i;
+res[1186] = /(abc|)ef/i;
+res[1187] = /(a|b)c*d/i;
+res[1188] = /(ab|ab*)bc/i;
+res[1189] = /a([bc]*)c*/i;
+res[1190] = /a([bc]*)(c*d)/i;
+res[1191] = /a([bc]+)(c*d)/i;
+res[1192] = /a([bc]*)(c+d)/i;
+res[1193] = /a[bcd]*dcdcde/i;
+res[1194] = /a[bcd]+dcdcde/i;
+res[1195] = /(ab|a)b*c/i;
+res[1196] = /((a)(b)c)(d)/i;
+res[1197] = /[a-zA-Z_][a-zA-Z0-9_]*/i;
+res[1198] = /^a(bc+|b[eh])g|.h$/i;
+res[1199] = /(bc+d$|ef*g.|h?i(j|k))/i;
+res[1200] = /((((((((((a))))))))))/i;
+res[1201] = /(((((((((a)))))))))/i;
+res[1202] = /(?:(?:(?:(?:(?:(?:(?:(?:(?:(a))))))))))/i;
+res[1203] = /(?:(?:(?:(?:(?:(?:(?:(?:(?:(a|b|c))))))))))/i;
+res[1204] = /multiple words of text/i;
+res[1205] = /multiple words/i;
+res[1206] = /(.*)c(.*)/i;
+res[1207] = /\((.*), (.*)\)/i;
+res[1208] = /[k]/i;
+res[1209] = /abcd/i;
+res[1210] = /a(bc)d/i;
+res[1211] = /a[-]?c/i;
+res[1212] = /a(?!b)./;
+res[1213] = /a(?=d)./;
+res[1214] = /a(?=c|d)./;
+res[1215] = /a(?:b|c|d)(.)/;
+res[1216] = /a(?:b|c|d)*(.)/;
+res[1217] = /a(?:b|c|d)+?(.)/;
+res[1218] = /a(?:b|c|d)+(.)/;
+res[1219] = /a(?:b|c|d){2}(.)/;
+res[1220] = /a(?:b|c|d){4,5}(.)/;
+res[1221] = /a(?:b|c|d){4,5}?(.)/;
+res[1222] = /((foo)|(bar))*/;
+res[1223] = /a(?:b|c|d){6,7}(.)/;
+res[1224] = /a(?:b|c|d){6,7}?(.)/;
+res[1225] = /a(?:b|c|d){5,6}(.)/;
+res[1226] = /a(?:b|c|d){5,6}?(.)/;
+res[1227] = /a(?:b|c|d){5,7}(.)/;
+res[1228] = /a(?:b|c|d){5,7}?(.)/;
+res[1229] = /a(?:b|(c|e){1,2}?|d)+?(.)/;
+res[1230] = /^(.+)?B/;
+res[1231] = /^([^a-z])|(\^)$/;
+res[1232] = /^[<>]&/;
+res[1233] = /(?:(f)(o)(o)|(b)(a)(r))*/;
+res[1234] = /(?:..)*a/;
+res[1235] = /(?:..)*?a/;
+res[1236] = /^(){3,5}/;
+res[1237] = /^(a+)*ax/;
+res[1238] = /^((a|b)+)*ax/;
+res[1239] = /^((a|bc)+)*ax/;
+res[1240] = /(a|x)*ab/;
+res[1241] = /(a)*ab/;
+res[1242] = /(?:c|d)(?:)(?:a(?:)(?:b)(?:b(?:))(?:b(?:)(?:b)))/;
+res[1243] = /(?:c|d)(?:)(?:aaaaaaaa(?:)(?:bbbbbbbb)(?:bbbbbbbb(?:))(?:bbbbbbbb(?:)(?:bbbbbbbb)))/;
+res[1244] = /foo\w*\d{4}baz/;
+res[1245] = /x(~~)*(?:(?:F)?)?/;
+res[1246] = /^a{3}c/;
+res[1247] = /^a{3}c/;
+res[1248] = /^(?:a?b?)*$/;
+res[1249] = /^b/;
+res[1250] = /()^b/;
+res[1251] = /(\w+:)+/;
+res[1252] = /([\w:]+::)?(\w+)$/;
+res[1253] = /^[^bcd]*(c+)/;
+res[1254] = /(a*)b+/;
+res[1255] = /([\w:]+::)?(\w+)$/;
+res[1256] = /^[^bcd]*(c+)/;
+res[1257] = /(>a+)ab/;
+res[1258] = /([[:]+)/;
+res[1259] = /([[=]+)/;
+res[1260] = /([[.]+)/;
+res[1261] = /a\Z/;
+res[1262] = /b\Z/;
+res[1263] = /b\z/;
+res[1264] = /b\Z/;
+res[1265] = /b\z/;
+res[1266] = /((Z)+|A)*/;
+res[1267] = /(Z()|A)*/;
+res[1268] = /(Z(())|A)*/;
+res[1269] = /a*/g;
+res[1270] = /^[\d-a]/;
+res[1271] = /[[:space:]]+/;
+res[1272] = /[[:blank:]]+/;
+res[1273] = /[\s]+/;
+res[1274] = /\s+/;
+res[1275] = /ab/;
+res[1276] = /(?!\A)x/m;
+res[1277] = /(?!^)x/m;
+res[1278] = /abc\Qabc\Eabc/;
+res[1279] = /abc\Qabc\Eabc/;
+res[1280] = /abc\Qliteral\E/;
+res[1281] = /abc\Qliteral/;
+res[1282] = /abc\Qliteral\E/;
+res[1283] = /abc\Qliteral\E/;
+res[1284] = /\Qabc\$xyz\E/;
+res[1285] = /\Qabc\E\$\Qxyz\E/;
+res[1286] = /\Gabc/;
+res[1287] = /\Gabc./g;
+res[1288] = /abc./g;
+res[1289] = /[z\Qa-d]\E]/;
+res[1290] = /[\z\C]/;
+res[1291] = /\M/;
+res[1292] = /(a+)*b/;
+res[1293] = /line\nbreak/;
+res[1294] = /line\nbreak/;
+res[1295] = /line\nbreak/m;
+res[1296] = /1234/;
+res[1297] = /1234/;
+res[1298] = /^/mg;
+res[1299] = /Content-Type\x3A[^\r\n]{6,}/;
+res[1300] = /Content-Type\x3A[^\r\n]{6,}z/;
+res[1301] = /Content-Type\x3A[^a]{6,}/;
+res[1302] = /Content-Type\x3A[^a]{6,}z/;
+res[1303] = /^abc/m;
+res[1304] = /abc$/m;
+res[1305] = /^abc/m;
+res[1306] = /^abc/m;
+res[1307] = /^abc/m;
+res[1308] = /.*/;
+res[1309] = /\w+(.)(.)?def/;
+res[1310] = /^\w+=.*(\\\n.*)*/;
+res[1311] = /^(a()*)*/;
+res[1312] = /^(?:a(?:(?:))*)*/;
+res[1313] = /^(a()+)+/;
+res[1314] = /^(?:a(?:(?:))+)+/;
+res[1315] = /(a|)*\d/;
+res[1316] = /(?:a|)*\d/;
+res[1317] = /^a.b/;
+res[1318] = /^abc./mg;
+res[1319] = /abc.$/mg;
+res[1320] = /^a\Rb/i;
+res[1321] = /^a\R*b/i;
+res[1322] = /^a\R+b/i;
+res[1323] = /^a\R{1,3}b/i;
+res[1324] = /^a[\R]b/i;
+res[1325] = /.+foo/;
+res[1326] = /.+foo/;
+res[1327] = /.+foo/;
+res[1328] = /.+foo/;
+res[1329] = /^$/mg;
+res[1330] = /^X/m;
+res[1331] = /\H\h\V\v/;
+res[1332] = /\H*\h+\V?\v{3,4}/;
+res[1333] = /\H{3,4}/;
+res[1334] = /.\h{3,4}./;
+res[1335] = /\h*X\h?\H+Y\H?Z/;
+res[1336] = /\v*X\v?Y\v+Z\V*\x0a\V+\x0b\V{2,3}\x0c/;
+res[1337] = /.+A/;
+res[1338] = /\nA/;
+res[1339] = /[\r\n]A/;
+res[1340] = /(\r|\n)A/;
+res[1341] = /a\Rb/i;
+res[1342] = /a\Rb/i;
+res[1343] = /a\R?b/i;
+res[1344] = /a\R?b/i;
+res[1345] = /a\R{2,4}b/i;
+res[1346] = /a\R{2,4}b/i;
+res[1347] = /a(?!)|\wbc/;
+res[1348] = /a[]b/;
+res[1349] = /a[]+b/;
+res[1350] = /a[^]b/;
+res[1351] = /a[^]+b/;
+res[1352] = / End of testinput7 /;
+res[1353] = /\bX/;
+res[1354] = /\BX/;
+res[1355] = /X\b/;
+res[1356] = /X\B/;
+res[1357] = /[^a]/;
+res[1358] = /abc/;
+res[1359] = /a.b/;
+res[1360] = /a(.{3})b/;
+res[1361] = /a(.*?)(.)/;
+res[1362] = /a(.*?)(.)/;
+res[1363] = /a(.*)(.)/;
+res[1364] = /a(.*)(.)/;
+res[1365] = /a(.)(.)/;
+res[1366] = /a(.)(.)/;
+res[1367] = /a(.?)(.)/;
+res[1368] = /a(.?)(.)/;
+res[1369] = /a(.??)(.)/;
+res[1370] = /a(.??)(.)/;
+res[1371] = /a(.{3})b/;
+res[1372] = /a(.{3,})b/;
+res[1373] = /a(.{3,}?)b/;
+res[1374] = /a(.{3,5})b/;
+res[1375] = /a(.{3,5}?)b/;
+res[1376] = /[^a]+/g;
+res[1377] = /^[^a]{2}/;
+res[1378] = /^[^a]{2,}/;
+res[1379] = /^[^a]{2,}?/;
+res[1380] = /[^a]+/ig;
+res[1381] = /^[^a]{2}/i;
+res[1382] = /^[^a]{2,}/i;
+res[1383] = /^[^a]{2,}?/i;
+res[1384] = /\D*/;
+res[1385] = /\D*/;
+res[1386] = /\D/;
+res[1387] = />\S/;
+res[1388] = /\d/;
+res[1389] = /\s/;
+res[1390] = /\D+/;
+res[1391] = /\D{2,3}/;
+res[1392] = /\D{2,3}?/;
+res[1393] = /\d+/;
+res[1394] = /\d{2,3}/;
+res[1395] = /\d{2,3}?/;
+res[1396] = /\S+/;
+res[1397] = /\S{2,3}/;
+res[1398] = /\S{2,3}?/;
+res[1399] = />\s+</;
+res[1400] = />\s{2,3}</;
+res[1401] = />\s{2,3}?</;
+res[1402] = /\w+/;
+res[1403] = /\w{2,3}/;
+res[1404] = /\w{2,3}?/;
+res[1405] = /\W+/;
+res[1406] = /\W{2,3}/;
+res[1407] = /\W{2,3}?/;
+res[1408] = /[\xFF]/;
+res[1409] = /[\xff]/;
+res[1410] = /[^\xFF]/;
+res[1411] = /[^\xff]/;
+res[1412] = /^[ac]*b/;
+res[1413] = /^[^x]*b/i;
+res[1414] = /^[^x]*b/;
+res[1415] = /^\d*b/;
+res[1416] = /(|a)/g;
+res[1417] = /^abc./mg;
+res[1418] = /abc.$/mg;
+res[1419] = /^a\Rb/i;
+res[1420] = /^a\R*b/i;
+res[1421] = /^a\R+b/i;
+res[1422] = /^a\R{1,3}b/i;
+res[1423] = /\h+\V?\v{3,4}/;
+res[1424] = /\V?\v{3,4}/;
+res[1425] = /\h+\V?\v{3,4}/;
+res[1426] = /\V?\v{3,4}/;
+res[1427] = /\H\h\V\v/;
+res[1428] = /\H*\h+\V?\v{3,4}/;
+res[1429] = /\H\h\V\v/;
+res[1430] = /\H*\h+\V?\v{3,4}/;
+res[1431] = /a\Rb/i;
+res[1432] = /a\Rb/i;
+res[1433] = /a\R?b/i;
+res[1434] = /a\R?b/i;
+res[1435] = /X/;
+res[1436] = / End of testinput 8 /;
+res[1437] = /\pL\P{Nd}/;
+res[1438] = /\X./;
+res[1439] = /\X\X/;
+res[1440] = /^\pL+/;
+res[1441] = /^\PL+/;
+res[1442] = /^\X+/;
+res[1443] = /\X?abc/;
+res[1444] = /^\X?abc/;
+res[1445] = /\X*abc/;
+res[1446] = /^\X*abc/;
+res[1447] = /^\pL?=./;
+res[1448] = /^\pL*=./;
+res[1449] = /^\X{2,3}X/;
+res[1450] = /^\pC\pL\pM\pN\pP\pS\pZ</;
+res[1451] = /^\PC/;
+res[1452] = /^\PL/;
+res[1453] = /^\PM/;
+res[1454] = /^\PN/;
+res[1455] = /^\PP/;
+res[1456] = /^\PS/;
+res[1457] = /^\PZ/;
+res[1458] = /^\p{Cc}/;
+res[1459] = /^\p{Cf}/;
+res[1460] = /^\p{Cn}/;
+res[1461] = /^\p{Co}/;
+res[1462] = /^\p{Cs}/;
+res[1463] = /^\p{Ll}/;
+res[1464] = /^\p{Lm}/;
+res[1465] = /^\p{Lo}/;
+res[1466] = /^\p{Lt}/;
+res[1467] = /^\p{Lu}/;
+res[1468] = /^\p{Mc}/;
+res[1469] = /^\p{Me}/;
+res[1470] = /^\p{Mn}/;
+res[1471] = /^\p{Nl}/;
+res[1472] = /^\p{No}/;
+res[1473] = /^\p{Pc}/;
+res[1474] = /^\p{Pd}/;
+res[1475] = /^\p{Pe}/;
+res[1476] = /^\p{Pf}/;
+res[1477] = /^\p{Pi}/;
+res[1478] = /^\p{Po}/;
+res[1479] = /^\p{Ps}/;
+res[1480] = /^\p{Sk}/;
+res[1481] = /^\p{So}/;
+res[1482] = /^\p{Zl}/;
+res[1483] = /^\p{Zp}/;
+res[1484] = /^\p{Zs}/;
+res[1485] = /\p{Nd}{2,}(..)/;
+res[1486] = /\p{Nd}{2,}?(..)/;
+res[1487] = /\p{Nd}*(..)/;
+res[1488] = /\p{Nd}*?(..)/;
+res[1489] = /\p{Nd}{2}(..)/;
+res[1490] = /\p{Nd}{2,3}(..)/;
+res[1491] = /\p{Nd}{2,3}?(..)/;
+res[1492] = /\p{Nd}?(..)/;
+res[1493] = /\p{Nd}??(..)/;
+res[1494] = /\p{Lu}/i;
+res[1495] = /\p{^Lu}/i;
+res[1496] = /\P{Lu}/i;
+res[1497] = /[\p{Nd}]/;
+res[1498] = /[\P{Nd}]+/;
+res[1499] = /\D+/;
+res[1500] = /[\D]+/;
+res[1501] = /[\P{Nd}]+/;
+res[1502] = /[\D\P{Nd}]+/;
+res[1503] = /\pL/;
+res[1504] = /\pL/i;
+res[1505] = /\p{Lu}/;
+res[1506] = /\p{Lu}/i;
+res[1507] = /\p{Ll}/;
+res[1508] = /\p{Ll}/i;
+res[1509] = /^\X/;
+res[1510] = /^[\X]/;
+res[1511] = /^(\X*)C/;
+res[1512] = /^(\X*?)C/;
+res[1513] = /^(\X*)(.)/;
+res[1514] = /^(\X*?)(.)/;
+res[1515] = /^\X(.)/;
+res[1516] = /^\X{2,3}(.)/;
+res[1517] = /^\X{2,3}?(.)/;
+res[1518] = /^\pN{2,3}X/;
+res[1519] = /^[\p{Arabic}]/;
+res[1520] = /^[\P{Yi}]/;
+res[1521] = /^\p{Any}X/;
+res[1522] = /^\P{Any}X/;
+res[1523] = /^\p{Any}?X/;
+res[1524] = /^\P{Any}?X/;
+res[1525] = /^\p{Any}*X/;
+res[1526] = /^\P{Any}*X/;
+res[1527] = /^[\p{Any}]X/;
+res[1528] = /^[\P{Any}]X/;
+res[1529] = /^[\p{Any}]?X/;
+res[1530] = /^[\P{Any}]?X/;
+res[1531] = /^[\p{Any}]+X/;
+res[1532] = /^[\P{Any}]+X/;
+res[1533] = /^[\p{Any}]*X/;
+res[1534] = /^[\P{Any}]*X/;
+res[1535] = /^\p{Any}{3,5}?/;
+res[1536] = /^\p{Any}{3,5}/;
+res[1537] = /^\P{Any}{3,5}?/;
+res[1538] = /^\p{L&}X/;
+res[1539] = /^[\p{L&}]X/;
+res[1540] = /^[\p{L&}]+X/;
+res[1541] = /^[\p{L&}]+?X/;
+res[1542] = /^\P{L&}X/;
+res[1543] = /^[\P{L&}]X/;
+res[1544] = /Check property support in non-UTF-8 mode/;
+res[1545] = /\p{L}{4}/;
+res[1546] = /\p{Carian}\p{Cham}\p{Kayah_Li}\p{Lepcha}\p{Lycian}\p{Lydian}\p{Ol_Chiki}\p{Rejang}\p{Saurashtra}\p{Sundanese}\p{Vai}/;
+res[1547] = / End /;
+res[1548] = /^[[:alnum:]]/m;
+res[1549] = /a/im;
+res[1550] = /abcde/m;
+res[1551] = /\x80/m;
+res[1552] = /\xff/m;
+res[1553] = /[\p{L}]/m;
+res[1554] = /[\p{^L}]/m;
+res[1555] = /[\P{L}]/m;
+res[1556] = /[\P{^L}]/m;
+res[1557] = /[\p{Nd}]/m;
+res[1558] = /[a]/m;
+res[1559] = /[a]/m;
+res[1560] = /[\xaa]/m;
+res[1561] = /[\xaa]/m;
+res[1562] = /[^a]/m;
+res[1563] = /[^a]/m;
+res[1564] = /[^\xaa]/m;
+res[1565] = /[^\xaa]/m;
+res[1566] = / End of testinput10 /;
+assertEquals("abc", res[1].exec("abc"), 0);
+assertEquals("abc", res[1].exec("defabc"), 1);
+assertEquals("abc", res[1].exec("Aabc"), 2);
+assertEquals(null, res[1].exec("*** Failers", 3));
+assertEquals("abc", res[1].exec("Adefabc"), 4);
+assertEquals("ABC", res[1].exec("ABC"), 5);
+assertEquals("abc", res[2].exec("abc"), 6);
+assertEquals(null, res[2].exec("Aabc", 7));
+assertEquals(null, res[2].exec("*** Failers", 8));
+assertEquals(null, res[2].exec("defabc", 9));
+assertEquals(null, res[2].exec("Adefabc", 10));
+assertEquals("abc", res[7].exec("abc"), 11);
+assertEquals(null, res[7].exec("*** Failers", 12));
+assertEquals(null, res[7].exec("def\nabc", 13));
+assertThrows("var re = /x{5,4}/;", 14);
+assertThrows("var re = /[abcd/;", 15);
+assertThrows("var re = /[z-a]/;", 16);
+assertThrows("var re = /^*/;", 17);
+assertThrows("var re = /(abc/;", 18);
+assertThrows("var re = /(?# abc/;", 19);
+assertEquals("cat", res[11].exec("this sentence eventually mentions a cat"), 20);
+assertEquals("elephant", res[11].exec("this sentences rambles on and on for a while and then reaches elephant"), 21);
+assertEquals("cat", res[12].exec("this sentence eventually mentions a cat"), 22);
+assertEquals("elephant", res[12].exec("this sentences rambles on and on for a while and then reaches elephant"), 23);
+assertEquals("CAT", res[13].exec("this sentence eventually mentions a CAT cat"), 24);
+assertEquals("elephant", res[13].exec("this sentences rambles on and on for a while to elephant ElePhant"), 25);
+assertThrows("var re = /{4,5}abc/;", 26);
+assertEquals("abcb,a,b,c", res[18].exec("abcb"), 27);
+assertEquals("abcb,a,b,c", res[18].exec("O0abcb"), 28);
+assertEquals("abcb,a,b,c", res[18].exec("O3abcb"), 29);
+assertEquals("abcb,a,b,c", res[18].exec("O6abcb"), 30);
+assertEquals("abcb,a,b,c", res[18].exec("O9abcb"), 31);
+assertEquals("abcb,a,b,c", res[18].exec("O12abcb"), 32);
+assertEquals("abc,a,,", res[19].exec("abc"), 33);
+assertEquals("abc,a,,", res[19].exec("O0abc"), 34);
+assertEquals("abc,a,,", res[19].exec("O3abc"), 35);
+assertEquals("abc,a,,", res[19].exec("O6abc"), 36);
+assertEquals("aba,,a,b", res[19].exec("aba"), 37);
+assertEquals("aba,,a,b", res[19].exec("O0aba"), 38);
+assertEquals("aba,,a,b", res[19].exec("O3aba"), 39);
+assertEquals("aba,,a,b", res[19].exec("O6aba"), 40);
+assertEquals("aba,,a,b", res[19].exec("O9aba"), 41);
+assertEquals("aba,,a,b", res[19].exec("O12aba"), 42);
+assertEquals("abc", res[20].exec("abc"), 43);
+assertEquals(null, res[20].exec("*** Failers", 44));
+assertEquals(null, res[20].exec("abc\n", 45));
+assertEquals(null, res[20].exec("abc\ndef", 46));
+assertEquals("the quick brown fox", res[22].exec("the quick brown fox"), 47);
+assertEquals("the quick brown fox", res[22].exec("this is a line with the quick brown fox"), 48);
+assertEquals("abc", res[23].exec("abcdef"), 49);
+assertEquals("abc", res[23].exec("abcdefB"), 50);
+assertEquals("defabc,abc,abc,", res[24].exec("defabc"), 51);
+assertEquals("Zdefabc,abc,abc,", res[24].exec("Zdefabc"), 52);
+assertEquals("abc", res[25].exec("abc"), 53);
+assertEquals(null, res[25].exec("*** Failers", 54));
+assertEquals("abc", res[26].exec("abcdef"), 55);
+assertEquals("abc", res[26].exec("abcdefB"), 56);
+assertEquals("defabc,abc,abc,", res[27].exec("defabc"), 57);
+assertEquals("Zdefabc,abc,abc,", res[27].exec("Zdefabc"), 58);
+assertEquals("the quick brown fox", res[28].exec("the quick brown fox"), 59);
+assertEquals(null, res[28].exec("*** Failers", 60));
+assertEquals("The Quick Brown Fox", res[28].exec("The Quick Brown Fox"), 61);
+assertEquals("the quick brown fox", res[29].exec("the quick brown fox"), 62);
+assertEquals("The Quick Brown Fox", res[29].exec("The Quick Brown Fox"), 63);
+assertEquals(null, res[30].exec("*** Failers", 64));
+assertEquals(null, res[30].exec("abc\ndef", 65));
+assertEquals("abc", res[31].exec("abc"), 66);
+assertEquals(null, res[31].exec("abc\n", 67));
+assertEquals("abc,abc", res[33].exec("abc"), 68);
+assertThrows("var re = /)/;", 69);
+assertEquals("-pr", res[35].exec("co-processors, and for"), 70);
+assertEquals("<def>ghi<klm>", res[36].exec("abc<def>ghi<klm>nop"), 71);
+assertEquals("<def>", res[37].exec("abc<def>ghi<klm>nop"), 72);
+assertEquals("<def>", res[37].exec("abc<def>ghi<klm>nop"), 73);
+assertEquals(null, res[37].exec("abc========def", 74));
+assertEquals(null, res[37].exec("foo", 75));
+assertEquals(null, res[37].exec("catfoo", 76));
+assertEquals(null, res[37].exec("*** Failers", 77));
+assertEquals(null, res[37].exec("the barfoo", 78));
+assertEquals(null, res[37].exec("and cattlefoo", 79));
+assertEquals("a", res[40].exec("a"), 80);
+assertEquals(null, res[40].exec("a\n", 81));
+assertEquals(null, res[40].exec("*** Failers", 82));
+assertEquals("a", res[40].exec("Za"), 83);
+assertEquals(null, res[40].exec("Za\n", 84));
+assertEquals("a", res[41].exec("a"), 85);
+assertEquals("a", res[41].exec("a\n"), 86);
+assertEquals("a", res[41].exec("Za\n"), 87);
+assertEquals(null, res[41].exec("*** Failers", 88));
+assertEquals("a", res[41].exec("Za"), 89);
+assertEquals("b", res[44].exec("foo\nbarbar"), 90);
+assertEquals("a", res[44].exec("***Failers"), 91);
+assertEquals("b", res[44].exec("rhubarb"), 92);
+assertEquals("b", res[44].exec("barbell"), 93);
+assertEquals("a", res[44].exec("abc\nbarton"), 94);
+assertEquals("b", res[44].exec("foo\nbarbar"), 95);
+assertEquals("a", res[44].exec("***Failers"), 96);
+assertEquals("b", res[44].exec("rhubarb"), 97);
+assertEquals("b", res[44].exec("barbell"), 98);
+assertEquals("a", res[44].exec("abc\nbarton"), 99);
+assertEquals("a", res[44].exec("abc"), 100);
+assertEquals("a", res[44].exec("def\nabc"), 101);
+assertEquals("a", res[44].exec("*** Failers"), 102);
+assertEquals("a", res[44].exec("defabc"), 103);
+assertEquals(null, res[45].exec("the bullock-cart", 104));
+assertEquals(null, res[45].exec("a donkey-cart race", 105));
+assertEquals(null, res[45].exec("*** Failers", 106));
+assertEquals(null, res[45].exec("cart", 107));
+assertEquals(null, res[45].exec("horse-and-cart", 108));
+assertEquals(null, res[45].exec("alphabetabcd", 109));
+assertEquals(null, res[45].exec("endingxyz", 110));
+assertEquals(null, res[45].exec("abxyZZ", 111));
+assertEquals(null, res[45].exec("abXyZZ", 112));
+assertEquals(null, res[45].exec("ZZZ", 113));
+assertEquals(null, res[45].exec("zZZ", 114));
+assertEquals(null, res[45].exec("bZZ", 115));
+assertEquals(null, res[45].exec("BZZ", 116));
+assertEquals(null, res[45].exec("*** Failers", 117));
+assertEquals(null, res[45].exec("ZZ", 118));
+assertEquals(null, res[45].exec("abXYZZ", 119));
+assertEquals(null, res[45].exec("zzz", 120));
+assertEquals(null, res[45].exec("bzz", 121));
+assertEquals(null, res[45].exec("bar", 122));
+assertEquals(null, res[45].exec("foobbar", 123));
+assertEquals(null, res[45].exec("*** Failers", 124));
+assertEquals(null, res[45].exec("fooabar", 125));
+assertEquals(null, res[46].exec("*** Failers", 126));
+assertEquals(null, res[46].exec("a", 127));
+assertEquals(null, res[48].exec("aaaaaa", 128));
+assertThrows("var re = /a[b-a]/;", 129);
+assertThrows("var re = /a[/;", 130);
+assertThrows("var re = /*a/;", 131);
+assertThrows("var re = /abc)/;", 132);
+assertThrows("var re = /(abc/;", 133);
+assertThrows("var re = /a**/;", 134);
+assertThrows("var re = /)(/;", 135);
+assertThrows("var re = /a[b-a]/;", 136);
+assertThrows("var re = /a[/;", 137);
+assertThrows("var re = /*a/;", 138);
+assertThrows("var re = /abc)/;", 139);
+assertThrows("var re = /(abc/;", 140);
+assertThrows("var re = /a**/;", 141);
+assertThrows("var re = /)(/;", 142);
+assertThrows("var re = /:(?:/;", 143);
+assertThrows("var re = /a(?{)b/;", 144);
+assertThrows("var re = /a(?{{})b/;", 145);
+assertThrows("var re = /a(?{}})b/;", 146);
+assertThrows("var re = /a(?{\"{\"})b/;", 147);
+assertThrows("var re = /a(?{\"{\"}})b/;", 148);
+assertThrows("var re = /[a[:xyz:/;", 149);
+assertThrows("var re = /a{37,17}/;", 150);
+assertEquals("abcd,a,d", res[58].exec("abcd"), 151);
+assertEquals("abcd,a,d", res[58].exec("abcdC2"), 152);
+assertEquals("abcd,a,d", res[58].exec("abcdC5"), 153);
+assertEquals("abcdefghijklmnopqrst,abcdefghijklmnopqrst", res[59].exec("abcdefghijklmnopqrstuvwxyz"), 154);
+assertEquals("abcdefghijklmnopqrst,abcdefghijklmnopqrst", res[59].exec("abcdefghijklmnopqrstuvwxyzC1"), 155);
+assertEquals("abcdefghijklmnopqrst,abcdefghijklmnopqrst", res[59].exec("abcdefghijklmnopqrstuvwxyzG1"), 156);
+assertEquals("abcdefghijklmno,abcdefghijklmno", res[60].exec("abcdefghijklmnopqrstuvwxyz"), 157);
+assertEquals("abcdefghijklmno,abcdefghijklmno", res[60].exec("abcdefghijklmnopqrstuvwxyzC1G1"), 158);
+assertEquals("abcdefghijklmnop,abcdefghijklmnop", res[61].exec("abcdefghijklmnopqrstuvwxyz"), 159);
+assertEquals("abcdefghijklmnop,abcdefghijklmnop", res[61].exec("abcdefghijklmnopqrstuvwxyzC1G1L"), 160);
+assertEquals("adef,a,,f", res[62].exec("adefG1G2G3G4L"), 161);
+assertEquals("bcdef,bc,bc,f", res[62].exec("bcdefG1G2G3G4L"), 162);
+assertEquals("adef,a,,f", res[62].exec("adefghijkC0"), 163);
+assertEquals("abc\x00def", res[63].exec("abc\x00defLC0"), 164);
+assertEquals("iss", res[69].exec("Mississippi"), 165);
+assertEquals("iss", res[70].exec("Mississippi"), 166);
+assertEquals("iss", res[71].exec("Mississippi"), 167);
+assertEquals("iss", res[72].exec("Mississippi"), 168);
+assertEquals("iss", res[73].exec("Mississippi"), 169);
+assertEquals(null, res[73].exec("*** Failers", 170));
+assertEquals("iss", res[73].exec("MississippiA"), 171);
+assertEquals("iss", res[73].exec("Mississippi"), 172);
+assertEquals(null, res[73].exec("Mississippi", 173));
+assertEquals("iss", res[74].exec("ississippi"), 174);
+assertEquals("abciss", res[75].exec("abciss\nxyzisspqr"), 175);
+assertEquals("Mis", res[76].exec("Mississippi"), 176);
+assertEquals("sis", res[76].exec("MississippiA"), 177);
+assertEquals("ri ", res[76].exec("Missouri river"), 178);
+assertEquals("riv", res[76].exec("Missouri riverA"), 179);
+assertEquals("Mis", res[77].exec("Mississippi"), 180);
+assertEquals("ab\n", res[78].exec("ab\nab\ncd"), 181);
+assertEquals("ab\n", res[79].exec("ab\nab\ncd"), 182);
+assertEquals("a", res[115].exec("a"), 183);
+assertEquals("b", res[115].exec("b"), 184);
+assertEquals("ab", res[115].exec("ab"), 185);
+assertEquals("", res[115].exec("\\"), 186);
+assertEquals("", res[115].exec("*** Failers"), 187);
+assertEquals("", res[115].exec("N"), 188);
+assertEquals("", res[116].exec("abcd"), 189);
+assertEquals("", res[116].exec("-abc"), 190);
+assertEquals("", res[116].exec("Nab-c"), 191);
+assertEquals("", res[116].exec("*** Failers"), 192);
+assertEquals("", res[116].exec("Nabc"), 193);
+assertEquals("aaaabbbbzz,bbbb,z,z", res[117].exec("aaaabbbbzzzz"), 194);
+assertEquals("aaaabbbbzz,bbbb,z,z", res[117].exec("aaaabbbbzzzzO0"), 195);
+assertEquals("aaaabbbbzz,bbbb,z,z", res[117].exec("aaaabbbbzzzzO1"), 196);
+assertEquals("aaaabbbbzz,bbbb,z,z", res[117].exec("aaaabbbbzzzzO2"), 197);
+assertEquals("aaaabbbbzz,bbbb,z,z", res[117].exec("aaaabbbbzzzzO3"), 198);
+assertEquals("aaaabbbbzz,bbbb,z,z", res[117].exec("aaaabbbbzzzzO4"), 199);
+assertEquals("aaaabbbbzz,bbbb,z,z", res[117].exec("aaaabbbbzzzzO5"), 200);
+assertEquals("(abcd", res[118].exec("(abcd)"), 201);
+assertEquals("(abcd", res[118].exec("(abcd)xyz"), 202);
+assertEquals(null, res[118].exec("xyz(abcd)", 203));
+assertEquals(null, res[118].exec("(ab(xy)cd)pqr", 204));
+assertEquals(null, res[118].exec("(ab(xycd)pqr", 205));
+assertEquals(null, res[118].exec("() abc ()", 206));
+assertEquals(null, res[118].exec("12(abcde(fsh)xyz(foo(bar))lmno)89", 207));
+assertEquals(null, res[118].exec("*** Failers", 208));
+assertEquals("abcd", res[118].exec("abcd"), 209);
+assertEquals("abcd", res[118].exec("abcd)"), 210);
+assertEquals("(abcd", res[118].exec("(abcd"), 211);
+assertEquals(null, res[118].exec("(ab(xy)cd)pqr", 212));
+assertEquals(null, res[118].exec("1(abcd)(x(y)z)pqr", 213));
+assertEquals("(abcd", res[118].exec("(abcd)"), 214);
+assertEquals(null, res[118].exec("(ab(xy)cd)", 215));
+assertEquals(null, res[118].exec("(a(b(c)d)e)", 216));
+assertEquals(null, res[118].exec("((ab))", 217));
+assertEquals(null, res[118].exec("*** Failers", 218));
+assertEquals(null, res[118].exec("()", 219));
+assertEquals(null, res[118].exec("()", 220));
+assertEquals(null, res[118].exec("12(abcde(fsh)xyz(foo(bar))lmno)89", 221));
+assertEquals(null, res[118].exec("(ab(xy)cd)", 222));
+assertEquals(null, res[118].exec("(ab(xy)cd)", 223));
+assertEquals(null, res[118].exec("(ab(xy)cd)", 224));
+assertEquals(null, res[118].exec("(123ab(xy)cd)", 225));
+assertEquals(null, res[118].exec("(ab(xy)cd)", 226));
+assertEquals(null, res[118].exec("(123ab(xy)cd)", 227));
+assertEquals(null, res[118].exec("(ab(xy)cd)", 228));
+assertEquals("(abcd", res[118].exec("(abcd(xyz<p>qrs)123)"), 229);
+assertEquals(null, res[118].exec("(ab(cd)ef)", 230));
+assertEquals(null, res[118].exec("(ab(cd(ef)gh)ij)", 231));
+assertEquals(null, res[146].exec("A", 232));
+assertEquals(null, res[146].exec("a", 233));
+assertEquals(null, res[147].exec("A", 234));
+assertEquals(null, res[147].exec("a", 235));
+assertEquals(null, res[147].exec("ab", 236));
+assertEquals(null, res[147].exec("aB", 237));
+assertEquals(null, res[147].exec("*** Failers", 238));
+assertEquals(null, res[147].exec("Ab", 239));
+assertEquals(null, res[147].exec("AB", 240));
+assertThrows("var re = /[\\200-\\110]/;", 241);
+assertEquals("1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 ABC ABC,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 ,17 ,18 ,19 ,20 ,21 ,22 ,23 ,24 ,25 ,26 ,27 ,28 ,29 ,30 ,31 ,32 ,33 ,34 ,35 ,36 ,37 ,38 ,39 ,40 ,41 ,42 ,43 ,44 ,45 ,46 ,47 ,48 ,49 ,50 ,51 ,52 ,53 ,54 ,55 ,56 ,57 ,58 ,59 ,60 ,61 ,62 ,63 ,64 ,65 ,66 ,67 ,68 ,69 ,70 ,71 ,72 ,73 ,74 ,75 ,76 ,77 ,78 ,79 ,80 ,81 ,82 ,83 ,84 ,85 ,86 ,87 ,88 ,89 ,90 ,91 ,92 ,93 ,94 ,95 ,96 ,97 ,98 ,99 ,100 ,101 ,102 ,103 ,104 ,105 ,106 ,107 ,108 ,109 ,110 ,111 ,112 ,113 ,114 ,115 ,116 ,117 ,118 ,119 ,120 ,121 ,122 ,123 ,124 ,125 ,126 ,127 ,128 ,129 ,130 ,131 ,132 ,133 ,134 ,135 ,136 ,137 ,138 ,139 ,140 ,141 ,142 ,143 ,144 ,145 ,146 ,147 ,148 ,149 ,150 ,151 ,152 ,153 ,154 ,155 ,156 ,157 ,158 ,159 ,160 ,161 ,162 ,163 ,164 ,165 ,166 ,167 ,168 ,169 ,170 ,171 ,172 ,173 ,174 ,175 ,176 ,177 ,178 ,179 ,180 ,181 ,182 ,183 ,184 ,185 ,186 ,187 ,188 ,189 ,190 ,191 ,192 ,193 ,194 ,195 ,196 ,197 ,198 ,199 ,200 ,201 ,202 ,203 ,204 ,205 ,206 ,207 ,208 ,209 ,210 ,211 ,212 ,213 ,214 ,215 ,216 ,217 ,218 ,219 ,220 ,221 ,222 ,223 ,224 ,225 ,226 ,227 ,228 ,229 ,230 ,231 ,232 ,233 ,234 ,235 ,236 ,237 ,238 ,239 ,240 ,241 ,242 ,243 ,244 ,245 ,246 ,247 ,248 ,249 ,250 ,251 ,252 ,253 ,254 ,255 ,256 ,257 ,258 ,259 ,260 ,261 ,262 ,263 ,264 ,265 ,266 ,267 ,268 ,269 ,ABC,ABC", res[149].exec("O900 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 ABC ABC"), 242);
+assertEquals("mainmain,main,", res[151].exec("mainmain"), 243);
+assertEquals("mainOmain,main,", res[151].exec("mainOmain"), 244);
+assertEquals("aba,a,", res[153].exec("aba"), 245);
+assertEquals("aabbaa,aa,", res[154].exec("aabbaa"), 246);
+assertEquals("aabbaa,aa,", res[155].exec("aabbaa"), 247);
+assertEquals("aabbaa,aa,", res[156].exec("aabbaa"), 248);
+assertEquals("aabbaa,", res[157].exec("aabbaa"), 249);
+assertEquals("aabbaa,aa,,", res[158].exec("aabbaa"), 250);
+assertEquals("aabbaa,,", res[159].exec("aabbaa"), 251);
+assertEquals("aabbaa,", res[160].exec("aabbaa"), 252);
+assertEquals("aabbbaa,", res[161].exec("aabbbaa"), 253);
+assertEquals("aabbbaa,", res[162].exec("aabbbaa"), 254);
+assertEquals("aabbaa,", res[163].exec("aabbaa"), 255);
+assertEquals("aabbbaa,", res[164].exec("aabbbaa"), 256);
+assertEquals("aabbbaa,aa,,", res[165].exec("aabbbaa"), 257);
+assertEquals("aabbbbaa,aa,,", res[166].exec("aabbbbaa"), 258);
+assertThrows("var re = //;", 259);
+assertEquals("a", res[169].exec("ab"), 260);
+assertEquals("a", res[169].exec("aB"), 261);
+assertEquals("*", res[169].exec("*** Failers"), 262);
+assertEquals("A", res[169].exec("AB"), 263);
+assertEquals("a", res[169].exec("ab"), 264);
+assertEquals("a", res[169].exec("aB"), 265);
+assertEquals("*", res[169].exec("*** Failers"), 266);
+assertEquals("A", res[169].exec("AB"), 267);
+assertEquals(null, res[172].exec("\\", 268));
+assertEquals(null, res[177].exec("*** Failers", 269));
+assertEquals(null, res[177].exec("xxxxx", 270));
+assertEquals(null, res[177].exec("now is the time for all good men to come to the aid of the party", 271));
+assertEquals(null, res[177].exec("*** Failers", 272));
+assertEquals(null, res[177].exec("this is not a line with only words and spaces!", 273));
+assertEquals(null, res[177].exec("12345a", 274));
+assertEquals(null, res[177].exec("*** Failers", 275));
+assertEquals(null, res[177].exec("12345+", 276));
+assertEquals(null, res[177].exec("aaab", 277));
+assertEquals(null, res[177].exec("aaab", 278));
+assertEquals(null, res[177].exec("aaab", 279));
+assertEquals(null, res[177].exec("((abc(ade)ufh()()x", 280));
+assertEquals(null, res[177].exec("(abc)", 281));
+assertEquals(null, res[177].exec("(abc(def)xyz)", 282));
+assertEquals(null, res[177].exec("*** Failers", 283));
+assertEquals(null, res[177].exec("((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 284));
+assertEquals(null, res[177].exec("xaaaab", 285));
+assertEquals(null, res[177].exec("xaaaab", 286));
+assertThrows("var re = /[/;", 287);
+assertThrows("var re = /[a-/;", 288);
+assertEquals(null, res[189].exec("<>", 289));
+assertEquals(null, res[189].exec("<abcd>", 290));
+assertEquals(null, res[189].exec("<abc <123> hij>", 291));
+assertEquals(null, res[189].exec("<abc <def> hij>", 292));
+assertEquals(null, res[189].exec("<abc<>def>", 293));
+assertEquals(null, res[189].exec("<abc<>", 294));
+assertEquals(null, res[189].exec("*** Failers", 295));
+assertEquals(null, res[189].exec("<abc", 296));
+assertEquals("bc123bc,bc,bc", res[195].exec("abc123bc"), 297);
+assertEquals("abc", res[215].exec("abcdef"), 298);
+assertEquals("abc", res[215].exec("1234abcdef"), 299);
+assertEquals(null, res[215].exec("*** Failers", 300));
+assertEquals("abc", res[215].exec("abcxyz"), 301);
+assertEquals("abc", res[215].exec("abcxyzf"), 302);
+assertEquals("abc", res[215].exec("123abcdef"), 303);
+assertEquals("abc", res[215].exec("1234abcdef"), 304);
+assertEquals(null, res[215].exec("*** Failers", 305));
+assertEquals("abc", res[215].exec("abcdef"), 306);
+assertEquals(null, res[215].exec("*** Failers", 307));
+assertEquals("abc", res[215].exec("\x83x0abcdef"), 308);
+assertEquals("abc", res[215].exec("123abcdef"), 309);
+assertEquals("abc", res[215].exec("123abcdefC+"), 310);
+assertEquals("abc", res[215].exec("123abcdefC-"), 311);
+assertEquals(null, res[215].exec("*** Failers", 312));
+assertEquals("abc", res[215].exec("123abcdefC!1"), 313);
+assertEquals("abc", res[215].exec("abcabcabc"), 314);
+assertEquals("abc", res[215].exec("abcabcC!1!3"), 315);
+assertEquals(null, res[215].exec("*** Failers", 316));
+assertEquals("abc", res[215].exec("abcabcabcC!1!3"), 317);
+assertEquals("C", res[215].exec("123C+"), 318);
+assertEquals("C", res[215].exec("123456C+"), 319);
+assertEquals("C", res[215].exec("123456789C+"), 320);
+assertEquals("abc", res[215].exec("xyzabcC+"), 321);
+assertEquals("abc", res[215].exec("XxyzabcC+"), 322);
+assertEquals("abc", res[215].exec("abcdefC+"), 323);
+assertEquals("abc", res[215].exec("abcxyzC+"), 324);
+assertEquals("c", res[215].exec("abbbbbcccC*1"), 325);
+assertEquals("c", res[215].exec("abbbbbcccC*1"), 326);
+assertEquals(null, res[215].exec("xab", 327));
+assertEquals("c", res[215].exec("xbc"), 328);
+assertEquals(null, res[215].exec("xde", 329));
+assertEquals(null, res[215].exec("xxab", 330));
+assertEquals(null, res[215].exec("xxxab", 331));
+assertEquals(null, res[215].exec("*** Failers", 332));
+assertEquals(null, res[215].exec("xyab", 333));
+assertEquals("abc", res[215].exec("abc"), 334);
+assertEquals("c", res[215].exec("a(b)c"), 335);
+assertEquals("c", res[215].exec("a(b(c))d"), 336);
+assertEquals(null, res[215].exec("*** Failers)", 337));
+assertEquals("c", res[215].exec("a(b(c)d"), 338);
+assertEquals(null, res[215].exec("1221", 339));
+assertEquals("c", res[215].exec("Satan, oscillate my metallic sonatas!"), 340);
+assertEquals("c", res[215].exec("A man, a plan, a canal: Panama!"), 341);
+assertEquals(null, res[215].exec("Able was I ere I saw Elba.", 342));
+assertEquals(null, res[215].exec("*** Failers", 343));
+assertEquals("c", res[215].exec("The quick brown fox"), 344);
+assertEquals(null, res[215].exec("12", 345));
+assertEquals(null, res[215].exec("(((2+2)*-3)-7)", 346));
+assertEquals(null, res[215].exec("-12", 347));
+assertEquals(null, res[215].exec("*** Failers", 348));
+assertEquals(null, res[215].exec("((2+2)*-3)-7)", 349));
+assertEquals(null, res[215].exec("xyz", 350));
+assertEquals(null, res[215].exec("xxyzxyzz", 351));
+assertEquals(null, res[215].exec("*** Failers", 352));
+assertEquals(null, res[215].exec("xxyzz", 353));
+assertEquals(null, res[215].exec("xxyzxyzxyzz", 354));
+assertEquals(null, res[215].exec("<>", 355));
+assertEquals("abc", res[215].exec("<abcd>"), 356);
+assertEquals("abc", res[215].exec("<abc <123> hij>"), 357);
+assertEquals("abc", res[215].exec("<abc <def> hij>"), 358);
+assertEquals("abc", res[215].exec("<abc<>def>"), 359);
+assertEquals("abc", res[215].exec("<abc<>"), 360);
+assertEquals(null, res[215].exec("*** Failers", 361));
+assertEquals("abc", res[215].exec("<abc"), 362);
+assertEquals("abc", res[215].exec("abcdefabc"), 363);
+assertEquals(null, res[215].exec("a=a", 364));
+assertEquals(null, res[215].exec("a=b", 365));
+assertEquals("c", res[215].exec("a=bc"), 366);
+assertEquals(null, res[215].exec("a=a", 367));
+assertEquals(null, res[215].exec("a=b", 368));
+assertEquals("c", res[215].exec("a=bc"), 369);
+assertEquals(null, res[215].exec("abde", 370));
+assertEquals("c", res[215].exec("acde"), 371);
+assertEquals(null, res[215].exec("1221", 372));
+assertEquals("c", res[215].exec("Satan, oscillate my metallic sonatas!"), 373);
+assertEquals("c", res[215].exec("A man, a plan, a canal: Panama!"), 374);
+assertEquals(null, res[215].exec("Able was I ere I saw Elba.", 375));
+assertEquals(null, res[215].exec("*** Failers", 376));
+assertEquals("c", res[215].exec("The quick brown fox"), 377);
+assertEquals(null, res[228].exec("abcdefgh", 378));
+assertEquals(null, res[228].exec("abcdefghC1Gtwo", 379));
+assertEquals(null, res[228].exec("abcdefghConeCtwo", 380));
+assertEquals(null, res[228].exec("abcdefghCthree", 381));
+assertEquals("zz,", res[228].exec("zzaaCZ"), 382);
+assertEquals("zz,", res[228].exec("zzaaCA"), 383);
+assertEquals(null, res[228].exec("[10,20,30,5,5,4,4,2,43,23,4234]", 384));
+assertEquals(null, res[228].exec("*** Failers", 385));
+assertEquals(null, res[228].exec("[]", 386));
+assertEquals(null, res[228].exec("[10,20,30,5,5,4,4,2,43,23,4234]", 387));
+assertEquals(null, res[228].exec("[]", 388));
+assertEquals(" Baby Bjorn Active Carrier - With free SHIPPING!!, Baby Bjorn Active Carrier - With free SHIPPING!!,,", res[229].exec(" Baby Bjorn Active Carrier - With free SHIPPING!!"), 389);
+assertEquals(" Baby Bjorn Active Carrier - With free SHIPPING!!, Baby Bjorn Active Carrier - With free SHIPPING!!,,", res[230].exec(" Baby Bjorn Active Carrier - With free SHIPPING!!"), 390);
+assertEquals(null, res[238].exec("Note: that { does NOT introduce a quantifier", 391));
+assertEquals("aacaacaacaacaac123,aac", res[239].exec("aacaacaacaacaac123"), 392);
+assertEquals(null, res[243].exec("abP", 393));
+assertEquals(null, res[243].exec("abcP", 394));
+assertEquals(null, res[243].exec("abcdP", 395));
+assertEquals("abcde", res[243].exec("abcdeP"), 396);
+assertEquals(null, res[243].exec("the quick brown abcP", 397));
+assertEquals(null, res[243].exec("** FailersP", 398));
+assertEquals(null, res[243].exec("the quick brown abxyz foxP", 399));
+assertEquals(null, res[243].exec("13/05/04P", 400));
+assertEquals(null, res[243].exec("13/5/2004P", 401));
+assertEquals(null, res[243].exec("02/05/09P", 402));
+assertEquals(null, res[243].exec("1P", 403));
+assertEquals(null, res[243].exec("1/2P", 404));
+assertEquals(null, res[243].exec("1/2/0P", 405));
+assertEquals(null, res[243].exec("1/2/04P", 406));
+assertEquals(null, res[243].exec("0P", 407));
+assertEquals(null, res[243].exec("02/P", 408));
+assertEquals(null, res[243].exec("02/0P", 409));
+assertEquals(null, res[243].exec("02/1P", 410));
+assertEquals(null, res[243].exec("** FailersP", 411));
+assertEquals(null, res[243].exec("P", 412));
+assertEquals(null, res[243].exec("123P", 413));
+assertEquals(null, res[243].exec("33/4/04P", 414));
+assertEquals(null, res[243].exec("3/13/04P", 415));
+assertEquals(null, res[243].exec("0/1/2003P", 416));
+assertEquals(null, res[243].exec("0/P", 417));
+assertEquals(null, res[243].exec("02/0/P", 418));
+assertEquals(null, res[243].exec("02/13P", 419));
+assertEquals("123", res[248].exec("123P"), 420);
+assertEquals(null, res[248].exec("aP", 421));
+assertEquals(null, res[248].exec("bP", 422));
+assertEquals(null, res[248].exec("cP", 423));
+assertEquals(null, res[248].exec("c12P", 424));
+assertEquals("c123", res[248].exec("c123P"), 425);
+assertEquals(null, res[249].exec("1P", 426));
+assertEquals(null, res[249].exec("123P", 427));
+assertEquals("123X", res[249].exec("123X"), 428);
+assertEquals(null, res[249].exec("1234P", 429));
+assertEquals("1234X", res[249].exec("1234X"), 430);
+assertEquals(null, res[249].exec("12345P", 431));
+assertEquals("12345X", res[249].exec("12345X"), 432);
+assertEquals(null, res[249].exec("*** Failers", 433));
+assertEquals(null, res[249].exec("1X", 434));
+assertEquals(null, res[249].exec("123456P", 435));
+assertEquals(null, res[249].exec("abc", 436));
+assertEquals(null, res[249].exec("** Failers", 437));
+assertEquals(null, res[249].exec("bca", 438));
+assertEquals(null, res[249].exec("abc", 439));
+assertEquals(null, res[249].exec("** Failers", 440));
+assertEquals(null, res[249].exec("bca", 441));
+assertEquals(null, res[249].exec("abc", 442));
+assertEquals(null, res[249].exec("** Failers", 443));
+assertEquals(null, res[249].exec("def", 444));
+assertEquals(null, res[249].exec("abc", 445));
+assertEquals(null, res[249].exec("** Failers", 446));
+assertEquals(null, res[249].exec("def", 447));
+assertEquals(null, res[249].exec("<!DOCTYPE seite SYSTEM \"http://www.lco.lineas.de/xmlCms.dtd\">\n<seite>\n<dokumenteninformation>\n<seitentitel>Partner der LCO</seitentitel>\n<sprache>de</sprache>\n<seitenbeschreibung>Partner der LINEAS Consulting\nGmbH</seitenbeschreibung>\n<schluesselworte>LINEAS Consulting GmbH Hamburg\nPartnerfirmen</schluesselworte>\n<revisit>30 days</revisit>\n<robots>index,follow</robots>\n<menueinformation>\n<aktiv>ja</aktiv>\n<menueposition>3</menueposition>\n<menuetext>Partner</menuetext>\n</menueinformation>\n<lastedited>\n<autor>LCO</autor>\n<firma>LINEAS Consulting</firma>\n<datum>15.10.2003</datum>\n</lastedited>\n</dokumenteninformation>\n<inhalt>\n\n<absatzueberschrift>Die Partnerfirmen der LINEAS Consulting\nGmbH</absatzueberschrift>\n\n<absatz><link ziel=\"http://www.ca.com/\" zielfenster=\"_blank\">\n<bild name=\"logo_ca.gif\" rahmen=\"no\"/></link> <link\nziel=\"http://www.ey.com/\" zielfenster=\"_blank\"><bild\nname=\"logo_euy.gif\" rahmen=\"no\"/></link>\n</absatz>\n\n<absatz><link ziel=\"http://www.cisco.de/\" zielfenster=\"_blank\">\n<bild name=\"logo_cisco.gif\" rahmen=\"ja\"/></link></absatz>\n\n<absatz><link ziel=\"http://www.atelion.de/\"\nzielfenster=\"_blank\"><bild\nname=\"logo_atelion.gif\" rahmen=\"no\"/></link>\n</absatz>\n\n<absatz><link ziel=\"http://www.line-information.de/\"\nzielfenster=\"_blank\">\n<bild name=\"logo_line_information.gif\" rahmen=\"no\"/></link>\n</absatz>\n\n<absatz><bild name=\"logo_aw.gif\" rahmen=\"no\"/></absatz>\n\n<absatz><link ziel=\"http://www.incognis.de/\"\nzielfenster=\"_blank\"><bild\nname=\"logo_incognis.gif\" rahmen=\"no\"/></link></absatz>\n\n<absatz><link ziel=\"http://www.addcraft.com/\"\nzielfenster=\"_blank\"><bild\nname=\"logo_addcraft.gif\" rahmen=\"no\"/></link></absatz>\n\n<absatz><link ziel=\"http://www.comendo.com/\"\nzielfenster=\"_blank\"><bild\nname=\"logo_comendo.gif\" rahmen=\"no\"/></link></absatz>\n\n</inhalt>\n</seite>", 448));
+assertEquals("line\nbreak", res[251].exec("this is a line\nbreak"), 449);
+assertEquals("line\nbreak", res[251].exec("line one\nthis is a line\nbreak in the second line"), 450);
+assertEquals("line\nbreak", res[252].exec("this is a line\nbreak"), 451);
+assertEquals(null, res[252].exec("** Failers", 452));
+assertEquals("line\nbreak", res[252].exec("line one\nthis is a line\nbreak in the second line"), 453);
+assertEquals("line\nbreak", res[253].exec("this is a line\nbreak"), 454);
+assertEquals(null, res[253].exec("** Failers", 455));
+assertEquals("line\nbreak", res[253].exec("line one\nthis is a line\nbreak in the second line"), 456);
+assertEquals("ab-cd", res[254].exec("ab-cd"), 457);
+assertEquals("ab=cd", res[254].exec("ab=cd"), 458);
+assertEquals(null, res[254].exec("** Failers", 459));
+assertEquals(null, res[254].exec("ab\ncd", 460));
+assertEquals("ab-cd", res[255].exec("ab-cd"), 461);
+assertEquals("ab=cd", res[255].exec("ab=cd"), 462);
+assertEquals(null, res[255].exec("ab\ncd", 463));
+assertEquals(null, res[255].exec("AbCd", 464));
+assertEquals(null, res[255].exec("** Failers", 465));
+assertEquals(null, res[255].exec("abcd", 466));
+// We are compatible with JSC, and don't throw an exception in this case.
+// assertThrows("var re = /(){2,4294967295}/;", 467);
+assertEquals(null, res[255].exec("abcdefghijklAkB", 468));
+assertEquals(null, res[255].exec("abcdefghijklAkB", 469));
+assertEquals(null, res[255].exec("abcdefghijklAkB", 470));
+assertEquals(null, res[255].exec("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 471));
+assertEquals(null, res[255].exec("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 472));
+assertEquals(null, res[255].exec("(this(and)that", 473));
+assertEquals(null, res[255].exec("(this(and)that)", 474));
+assertEquals(null, res[255].exec("(this(and)that)stuff", 475));
+assertEquals(null, res[255].exec("(this(and)that", 476));
+assertEquals(null, res[255].exec("(this(and)that)", 477));
+assertEquals(null, res[255].exec("(this(and)that", 478));
+assertEquals(null, res[255].exec("(this(and)that)", 479));
+assertEquals(null, res[255].exec("(this(and)that", 480));
+assertEquals(null, res[255].exec("(this(and)that)", 481));
+assertEquals(null, res[255].exec("((this))", 482));
+assertEquals(null, res[255].exec("(this(and)that", 483));
+assertEquals(null, res[255].exec("(this(and)that)", 484));
+assertEquals(null, res[255].exec("(this)", 485));
+assertEquals(null, res[255].exec("((this))", 486));
+assertEquals("abc,b", res[256].exec("abc"), 487);
+assertEquals("abc,b", res[256].exec("abc"), 488);
+assertEquals(null, res[256].exec("a1bCA", 489));
+assertEquals(null, res[256].exec("a2bCA", 490));
+assertEquals(null, res[257].exec("a bc dCACBCC", 491));
+assertEquals(null, res[257].exec("aabc", 492));
+assertEquals(null, res[257].exec("bc", 493));
+assertEquals(null, res[257].exec("** Failers", 494));
+assertEquals(null, res[257].exec("abc", 495));
+assertEquals(null, res[257].exec("bXaX", 496));
+assertEquals(null, res[257].exec("bbXaaX", 497));
+assertEquals(null, res[257].exec("(b)\\Xa\\X", 498));
+assertEquals(null, res[257].exec("bXXaYYaY", 499));
+assertEquals(null, res[257].exec("bXYaXXaX", 500));
+assertEquals(null, res[257].exec("bXXaYYaY", 501));
+assertEquals("\x0b,\x0b", res[259].exec("\x0b,\x0b"), 502);
+assertEquals("\x0c,\x0d", res[259].exec("\x0c,\x0d"), 503);
+assertEquals("abc", res[260].exec("xyz\nabc"), 504);
+assertEquals("abc", res[260].exec("xyz\nabc<lf>"), 505);
+assertEquals("abc", res[260].exec("xyz\x0d\nabc<lf>"), 506);
+assertEquals("abc", res[260].exec("xyz\x0dabc<cr>"), 507);
+assertEquals("abc", res[260].exec("xyz\x0d\nabc<crlf>"), 508);
+assertEquals(null, res[260].exec("** Failers", 509));
+assertEquals("abc", res[260].exec("xyz\nabc<cr>"), 510);
+assertEquals("abc", res[260].exec("xyz\x0d\nabc<cr>"), 511);
+assertEquals("abc", res[260].exec("xyz\nabc<crlf>"), 512);
+assertEquals("abc", res[260].exec("xyz\x0dabc<crlf>"), 513);
+assertEquals("abc", res[260].exec("xyz\x0dabc<lf>"), 514);
+assertEquals("abc", res[261].exec("xyzabc"), 515);
+assertEquals("abc", res[261].exec("xyzabc\n"), 516);
+assertEquals("abc", res[261].exec("xyzabc\npqr"), 517);
+assertEquals("abc", res[261].exec("xyzabc\x0d<cr>"), 518);
+assertEquals("abc", res[261].exec("xyzabc\x0dpqr<cr>"), 519);
+assertEquals("abc", res[261].exec("xyzabc\x0d\n<crlf>"), 520);
+assertEquals("abc", res[261].exec("xyzabc\x0d\npqr<crlf>"), 521);
+assertEquals(null, res[261].exec("** Failers", 522));
+assertEquals("abc", res[261].exec("xyzabc\x0d"), 523);
+assertEquals("abc", res[261].exec("xyzabc\x0dpqr"), 524);
+assertEquals("abc", res[261].exec("xyzabc\x0d\n"), 525);
+assertEquals("abc", res[261].exec("xyzabc\x0d\npqr"), 526);
+assertEquals("abc", res[262].exec("xyz\x0dabcdef"), 527);
+assertEquals("abc", res[262].exec("xyz\nabcdef<lf>"), 528);
+assertEquals(null, res[262].exec("** Failers", 529));
+assertEquals("abc", res[262].exec("xyz\nabcdef"), 530);
+assertEquals("abc", res[263].exec("xyz\nabcdef"), 531);
+assertEquals("abc", res[263].exec("xyz\x0dabcdef<cr>"), 532);
+assertEquals(null, res[263].exec("** Failers", 533));
+assertEquals("abc", res[263].exec("xyz\x0dabcdef"), 534);
+assertEquals("abc", res[264].exec("xyz\x0d\nabcdef"), 535);
+assertEquals("abc", res[264].exec("xyz\x0dabcdef<cr>"), 536);
+assertEquals(null, res[264].exec("** Failers", 537));
+assertEquals("abc", res[264].exec("xyz\x0dabcdef"), 538);
+assertEquals("abc", res[266].exec("xyz\x0dabc<bad>"), 539);
+assertEquals("abc", res[266].exec("abc"), 540);
+assertEquals("abc", res[267].exec("abc\ndef"), 541);
+assertEquals("abc", res[267].exec("abc\x0ddef"), 542);
+assertEquals("abc", res[267].exec("abc\x0d\ndef"), 543);
+assertEquals("<cr>abc", res[267].exec("<cr>abc\ndef"), 544);
+assertEquals("<cr>abc", res[267].exec("<cr>abc\x0ddef"), 545);
+assertEquals("<cr>abc", res[267].exec("<cr>abc\x0d\ndef"), 546);
+assertEquals("<crlf>abc", res[267].exec("<crlf>abc\ndef"), 547);
+assertEquals("<crlf>abc", res[267].exec("<crlf>abc\x0ddef"), 548);
+assertEquals("<crlf>abc", res[267].exec("<crlf>abc\x0d\ndef"), 549);
+assertEquals(null, res[268].exec("abc\ndef", 550));
+assertEquals(null, res[268].exec("abc\x0ddef", 551));
+assertEquals(null, res[268].exec("abc\x0d\ndef", 552));
+assertEquals("XY,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,XY,Y", res[269].exec("XYO400"), 553);
+assertEquals("aaaA5", res[278].exec("aaaA5"), 554);
+assertEquals(null, res[278].exec("** Failers", 555));
+assertEquals(null, res[278].exec("aaaa5", 556));
+assertEquals("aaaA5", res[279].exec("aaaA5"), 557);
+assertEquals("aaaa5", res[279].exec("aaaa5"), 558);
+assertEquals("x", res[350].exec("xyCabcCxyz"), 559);
+assertEquals("x", res[350].exec("xyCabcCxyz"), 560);
+assertEquals("b", res[350].exec("bXaX"), 561);
+assertEquals("b", res[350].exec("bXbX"), 562);
+assertEquals("*", res[350].exec("** Failers"), 563);
+assertEquals("aX", res[350].exec("aXaX"), 564);
+assertEquals("aX", res[350].exec("aXbX"), 565);
+assertEquals("x", res[350].exec("xx"), 566);
+assertEquals("x", res[350].exec("xy"), 567);
+assertEquals("y", res[350].exec("yy"), 568);
+assertEquals("y", res[350].exec("yx"), 569);
+assertEquals("x", res[350].exec("xx"), 570);
+assertEquals("x", res[350].exec("xy"), 571);
+assertEquals("y", res[350].exec("yy"), 572);
+assertEquals("y", res[350].exec("yx"), 573);
+assertEquals("b", res[350].exec("bxay"), 574);
+assertEquals("b", res[350].exec("bxby"), 575);
+assertEquals("*", res[350].exec("** Failers"), 576);
+assertEquals("ax", res[350].exec("axby"), 577);
+assertEquals("X", res[350].exec("XxXxxx"), 578);
+assertEquals("X", res[350].exec("XxXyyx"), 579);
+assertEquals("X", res[350].exec("XxXyxx"), 580);
+assertEquals("*", res[350].exec("** Failers"), 581);
+assertEquals("x", res[350].exec("x"), 582);
+assertEquals("ab", res[350].exec("abcabc"), 583);
+assertEquals("Xaaa,a", res[351].exec("Xaaa"), 584);
+assertEquals("Xaba,a", res[351].exec("Xaba"), 585);
+assertThrows("var re = /^[a-\\Q\\E]/;", 586);
+assertEquals(null, res[353].exec("(xy)x", 587));
+assertEquals(null, res[353].exec("1221", 588));
+assertEquals(null, res[353].exec("Satan, oscillate my metallic sonatas!", 589));
+assertEquals(null, res[353].exec("A man, a plan, a canal: Panama!", 590));
+assertEquals(null, res[353].exec("Able was I ere I saw Elba.", 591));
+assertEquals(null, res[353].exec("*** Failers", 592));
+assertEquals(null, res[353].exec("The quick brown fox", 593));
+assertEquals("abcd:,abcd", res[354].exec("abcd:"), 594);
+assertEquals("abcd:,abcd", res[354].exec("abcd:"), 595);
+assertEquals("a:,a", res[354].exec("a:aaxyz"), 596);
+assertEquals("ab:,ab", res[354].exec("ab:ababxyz"), 597);
+assertEquals(null, res[354].exec("** Failers", 598));
+assertEquals("a:,a", res[354].exec("a:axyz"), 599);
+assertEquals("ab:,ab", res[354].exec("ab:abxyz"), 600);
+assertEquals(null, res[354].exec("abd", 601));
+assertEquals(null, res[354].exec("ce", 602));
+assertEquals(null, res[354].exec("abcabc1Xabc2XabcXabcabc", 603));
+assertEquals(null, res[354].exec("abcabc1Xabc2XabcXabcabc", 604));
+assertEquals(null, res[354].exec("abcabc1Xabc2XabcXabcabc", 605));
+assertEquals(null, res[354].exec("abcd", 606));
+assertEquals(null, res[354].exec("metcalfe 33", 607));
+assertEquals(null, res[356].exec("a\x0db", 608));
+assertEquals(null, res[356].exec("a\nb<cr>", 609));
+assertEquals("a\x85b", res[356].exec("a\x85b<anycrlf> "), 610);
+assertEquals(null, res[356].exec("** Failers", 611));
+assertEquals(null, res[356].exec("a\nb", 612));
+assertEquals(null, res[356].exec("a\nb<any>", 613));
+assertEquals(null, res[356].exec("a\x0db<cr>", 614));
+assertEquals(null, res[356].exec("a\x0db<any>", 615));
+assertEquals("a\x85b", res[356].exec("a\x85b<any> "), 616);
+assertEquals(null, res[356].exec("a\x0db<anycrlf>", 617));
+assertEquals("abc1", res[357].exec("abc1 \nabc2 \x0babc3xx \x0cabc4 \x0dabc5xx \x0d\nabc6 \x85abc7 JUNK"), 618);
+assertEquals("abc1", res[358].exec("abc1\n abc2\x0b abc3\x0c abc4\x0d abc5\x0d\n abc6\x85 abc7 abc9"), 619);
+assertEquals(null, res[361].exec("a\nb", 620));
+assertEquals(null, res[361].exec("a\x0db", 621));
+assertEquals(null, res[361].exec("a\x0d\nb", 622));
+assertEquals(null, res[361].exec("a\x0bb", 623));
+assertEquals(null, res[361].exec("a\x0cb", 624));
+assertEquals(null, res[361].exec("a\x85b", 625));
+assertEquals(null, res[361].exec("** Failers", 626));
+assertEquals(null, res[361].exec("a\n\x0db", 627));
+assertEquals("ab", res[362].exec("ab"), 628);
+assertEquals(null, res[362].exec("a\nb", 629));
+assertEquals(null, res[362].exec("a\x0db", 630));
+assertEquals(null, res[362].exec("a\x0d\nb", 631));
+assertEquals(null, res[362].exec("a\x0bb", 632));
+assertEquals(null, res[362].exec("a\x0cb", 633));
+assertEquals(null, res[362].exec("a\x85b", 634));
+assertEquals(null, res[362].exec("a\n\x0db", 635));
+assertEquals(null, res[362].exec("a\n\x0d\x85\x0cb", 636));
+assertEquals(null, res[363].exec("a\nb", 637));
+assertEquals(null, res[363].exec("a\x0db", 638));
+assertEquals(null, res[363].exec("a\x0d\nb", 639));
+assertEquals(null, res[363].exec("a\x0bb", 640));
+assertEquals(null, res[363].exec("a\x0cb", 641));
+assertEquals(null, res[363].exec("a\x85b", 642));
+assertEquals(null, res[363].exec("a\n\x0db", 643));
+assertEquals(null, res[363].exec("a\n\x0d\x85\x0cb", 644));
+assertEquals(null, res[363].exec("** Failers", 645));
+assertEquals(null, res[363].exec("ab", 646));
+assertEquals(null, res[364].exec("a\nb", 647));
+assertEquals(null, res[364].exec("a\n\x0db", 648));
+assertEquals(null, res[364].exec("a\n\x0d\x85b", 649));
+assertEquals(null, res[364].exec("a\x0d\n\x0d\nb", 650));
+assertEquals(null, res[364].exec("a\x0d\n\x0d\n\x0d\nb", 651));
+assertEquals(null, res[364].exec("a\n\x0d\n\x0db", 652));
+assertEquals(null, res[364].exec("a\n\n\x0d\nb", 653));
+assertEquals(null, res[364].exec("** Failers", 654));
+assertEquals(null, res[364].exec("a\n\n\n\x0db", 655));
+assertEquals(null, res[364].exec("a\x0d", 656));
+assertEquals("aRb", res[365].exec("aRb"), 657);
+assertEquals(null, res[365].exec("** Failers", 658));
+assertEquals(null, res[365].exec("a\nb", 659));
+assertEquals(null, res[365].exec("abcPXP123", 660));
+assertEquals(null, res[365].exec("abcPXP123", 661));
+assertEquals(null, res[365].exec("1.2.3.4", 662));
+assertEquals(null, res[365].exec("131.111.10.206", 663));
+assertEquals(null, res[365].exec("10.0.0.0", 664));
+assertEquals(null, res[365].exec("** Failers", 665));
+assertEquals(null, res[365].exec("10.6", 666));
+assertEquals(null, res[365].exec("455.3.4.5", 667));
+assertEquals(null, res[365].exec("1.2.3.4", 668));
+assertEquals(null, res[365].exec("131.111.10.206", 669));
+assertEquals(null, res[365].exec("10.0.0.0", 670));
+assertEquals(null, res[365].exec("** Failers", 671));
+assertEquals(null, res[365].exec("10.6", 672));
+assertEquals(null, res[365].exec("455.3.4.5", 673));
+assertEquals(null, res[365].exec("123axbaxbaxbx456", 674));
+assertEquals(null, res[365].exec("123axbaxbaxb456", 675));
+assertEquals(null, res[365].exec("123axbaxbaxbx456", 676));
+assertEquals(null, res[365].exec("123axbaxbaxbx456", 677));
+assertEquals(null, res[365].exec("123axbaxbaxbx456", 678));
+assertEquals(null, res[366].exec("ababababbbabZXXXX", 679));
+assertEquals(null, res[372].exec("a\x0db", 680));
+assertEquals(null, res[372].exec("*** Failers", 681));
+assertEquals(null, res[372].exec("a\nb", 682));
+assertEquals("afoo", res[373].exec("afoo"), 683);
+assertEquals(null, res[373].exec("** Failers", 684));
+assertEquals(null, res[373].exec("\x0d\nfoo", 685));
+assertEquals(null, res[373].exec("\nfoo", 686));
+assertEquals("afoo", res[374].exec("afoo"), 687);
+assertEquals(null, res[374].exec("\nfoo", 688));
+assertEquals(null, res[374].exec("** Failers", 689));
+assertEquals(null, res[374].exec("\x0d\nfoo", 690));
+assertEquals("afoo", res[375].exec("afoo"), 691);
+assertEquals(null, res[375].exec("** Failers", 692));
+assertEquals(null, res[375].exec("\nfoo", 693));
+assertEquals(null, res[375].exec("\x0d\nfoo", 694));
+assertEquals("afoo", res[376].exec("afoo"), 695);
+assertEquals(null, res[376].exec("\x0d\nfoo", 696));
+assertEquals(null, res[376].exec("\nfoo", 697));
+assertEquals("", res[377].exec("abc\x0d\x0dxyz"), 698);
+assertEquals("", res[377].exec("abc\n\x0dxyz  "), 699);
+assertEquals(null, res[377].exec("** Failers ", 700));
+assertEquals("", res[377].exec("abc\x0d\nxyz"), 701);
+assertEquals("", res[377].exec("abc\x0d\n\x0d\n"), 702);
+assertEquals("", res[377].exec("abc\x0d\n\x0d\n"), 703);
+assertEquals("", res[377].exec("abc\x0d\n\x0d\n"), 704);
+assertEquals("abc1", res[378].exec("abc1\n abc2\x0b abc3\x0c abc4\x0d abc5\x0d\n abc6\x85 abc9"), 705);
+assertEquals("X", res[379].exec("XABC"), 706);
+assertEquals(null, res[379].exec("** Failers ", 707));
+assertEquals("X", res[379].exec("XABCB"), 708);
+assertThrows("var re = /(ab|c)(?-1)/;", 709);
+assertEquals(null, res[379].exec("abc", 710));
+assertEquals(null, res[379].exec("xyabcabc", 711));
+assertEquals(null, res[379].exec("** Failers", 712));
+assertEquals(null, res[379].exec("xyabc  ", 713));
+assertThrows("var re = /x(?-0)y/;", 714);
+assertThrows("var re = /x(?-1)y/;", 715);
+assertEquals(null, res[379].exec("abcX", 716));
+assertEquals(null, res[379].exec("Y", 717));
+assertEquals(null, res[379].exec("** Failers", 718));
+assertEquals(null, res[379].exec("abcY   ", 719));
+assertEquals(null, res[379].exec("YabcXabc", 720));
+assertEquals(null, res[379].exec("YabcXabcXabc", 721));
+assertEquals(null, res[379].exec("** Failers", 722));
+assertEquals("X", res[379].exec("XabcXabc  "), 723);
+assertEquals(null, res[379].exec("Y!", 724));
+assertEquals(null, res[380].exec("foobar", 725));
+assertEquals(null, res[381].exec("foobar", 726));
+assertEquals("foobaz,foo,baz", res[381].exec("foobaz "), 727);
+assertEquals(null, res[382].exec("foobarbaz", 728));
+assertEquals(null, res[382].exec("tom-tom", 729));
+assertEquals(null, res[382].exec("bon-bon ", 730));
+assertEquals(null, res[382].exec("** Failers", 731));
+assertEquals(null, res[382].exec("tom-bon  ", 732));
+assertEquals(null, res[382].exec("tom-tom", 733));
+assertEquals(null, res[382].exec("bon-bon ", 734));
+assertThrows("var re = /(?|(abc)|(xyz))/;", 735);
+assertThrows("var re = /(x)(?|(abc)|(xyz))(x)/;", 736);
+assertEquals(null, res[383].exec("xabcx", 737));
+assertEquals(null, res[383].exec("xxyzx ", 738));
+assertThrows("var re = /(x)(?|(abc)(pqr)|(xyz))(x)/;", 739);
+assertEquals(null, res[383].exec("xabcpqrx", 740));
+assertEquals(null, res[383].exec("xxyzx ", 741));
+assertThrows("var re = /(?|(abc)|(xyz))\\1/;", 742);
+assertEquals(null, res[383].exec("abcabc", 743));
+assertEquals(null, res[383].exec("xyzxyz ", 744));
+assertEquals(null, res[383].exec("** Failers", 745));
+assertEquals(null, res[383].exec("abcxyz", 746));
+assertEquals(null, res[383].exec("xyzabc   ", 747));
+assertEquals(null, res[383].exec("abcabc", 748));
+assertEquals(null, res[383].exec("xyzabc ", 749));
+assertEquals(null, res[383].exec("** Failers ", 750));
+assertEquals(null, res[383].exec("xyzxyz ", 751));
+assertEquals(null, res[384].exec("X X\n", 752));
+assertEquals(null, res[384].exec("X\x09X\x0b", 753));
+assertEquals(null, res[384].exec("** Failers", 754));
+assertEquals(null, res[384].exec("\xa0 X\n   ", 755));
+assertEquals(null, res[385].exec("\x09 \xa0X\n\x0b\x0c\x0d\n", 756));
+assertEquals(null, res[385].exec("\x09 \xa0\n\x0b\x0c\x0d\n", 757));
+assertEquals(null, res[385].exec("\x09 \xa0\n\x0b\x0c", 758));
+assertEquals(null, res[385].exec("** Failers ", 759));
+assertEquals(null, res[385].exec("\x09 \xa0\n\x0b", 760));
+assertEquals(null, res[385].exec(" ", 761));
+assertEquals(null, res[386].exec("XY  ABCDE", 762));
+assertEquals(null, res[386].exec("XY  PQR ST ", 763));
+assertEquals(null, res[387].exec("XY  AB    PQRS", 764));
+assertEquals(null, res[388].exec(">XNNNYZ", 765));
+assertEquals(null, res[388].exec(">  X NYQZ", 766));
+assertEquals(null, res[388].exec("** Failers", 767));
+assertEquals(null, res[388].exec(">XYZ   ", 768));
+assertEquals(null, res[388].exec(">  X NY Z", 769));
+assertEquals(null, res[389].exec(">XY\nZ\nA\x0bNN\x0c", 770));
+assertEquals(null, res[389].exec(">\n\x0dX\nY\n\x0bZZZ\nAAA\x0bNNN\x0c", 771));
+assertEquals(null, res[390].exec(">\x09<", 772));
+assertEquals(null, res[391].exec(">\x09 \xa0<", 773));
+assertEquals(null, res[396].exec("** Failers", 774));
+assertEquals(null, res[396].exec("XXXX", 775));
+assertEquals(null, res[397].exec("XXXX Y ", 776));
+assertEquals(null, res[419].exec("aaaaaa", 777));
+assertEquals(null, res[419].exec("aaabccc", 778));
+assertEquals(null, res[419].exec("aaabccc", 779));
+assertEquals(null, res[419].exec("aaabccc", 780));
+assertEquals(null, res[419].exec("aaabcccaaabccc", 781));
+assertEquals(null, res[419].exec("aaaxxxxxx", 782));
+assertEquals(null, res[419].exec("aaa++++++ ", 783));
+assertEquals(null, res[419].exec("bbbxxxxx", 784));
+assertEquals(null, res[419].exec("bbb+++++ ", 785));
+assertEquals(null, res[419].exec("cccxxxx", 786));
+assertEquals(null, res[419].exec("ccc++++ ", 787));
+assertEquals(null, res[419].exec("dddddddd   ", 788));
+assertEquals(null, res[419].exec("aaaxxxxxx", 789));
+assertEquals(null, res[419].exec("aaa++++++ ", 790));
+assertEquals(null, res[419].exec("bbbxxxxx", 791));
+assertEquals(null, res[419].exec("bbb+++++ ", 792));
+assertEquals(null, res[419].exec("cccxxxx", 793));
+assertEquals(null, res[419].exec("ccc++++ ", 794));
+assertEquals(null, res[419].exec("dddddddd   ", 795));
+assertEquals(null, res[419].exec("aaabccc", 796));
+assertEquals(null, res[419].exec("ABX", 797));
+assertEquals(null, res[419].exec("AADE", 798));
+assertEquals(null, res[419].exec("ACDE", 799));
+assertEquals(null, res[419].exec("** Failers", 800));
+assertEquals(null, res[419].exec("AD ", 801));
+assertEquals(null, res[419].exec("    ", 802));
+assertEquals(null, res[419].exec("aaaaaa", 803));
+assertEquals(null, res[419].exec("aaabccc", 804));
+assertEquals(null, res[419].exec("aaabccc", 805));
+assertEquals(null, res[419].exec("aaabccc", 806));
+assertEquals(null, res[419].exec("aaabcccaaabccc", 807));
+assertEquals(null, res[419].exec("aaabccc", 808));
+assertEquals(null, res[422].exec("\x0d\nA", 809));
+assertEquals("\nA", res[423].exec("\x0d\nA "), 810);
+assertEquals("\nA", res[424].exec("\x0d\nA "), 811);
+assertEquals("\nA,\n", res[425].exec("\x0d\nA "), 812);
+assertEquals(null, res[425].exec("a\nb", 813));
+assertEquals(null, res[425].exec("** Failers", 814));
+assertEquals(null, res[425].exec("a\x0db  ", 815));
+assertEquals(null, res[425].exec("a\nb", 816));
+assertEquals(null, res[425].exec("** Failers", 817));
+assertEquals(null, res[425].exec("a\x0db  ", 818));
+assertEquals(null, res[425].exec("a\x0db", 819));
+assertEquals(null, res[425].exec("** Failers", 820));
+assertEquals(null, res[425].exec("a\nb  ", 821));
+assertEquals(null, res[425].exec("a\x0db", 822));
+assertEquals(null, res[425].exec("a\nb  ", 823));
+assertEquals(null, res[425].exec("** Failers", 824));
+assertEquals(null, res[425].exec("a\x0d\nb  ", 825));
+assertEquals(null, res[425].exec("** Failers", 826));
+assertEquals(null, res[425].exec("a\x0db", 827));
+assertEquals(null, res[425].exec("a\nb  ", 828));
+assertEquals(null, res[425].exec("a\x0d\nb  ", 829));
+assertEquals(null, res[425].exec("** Failers", 830));
+assertEquals(null, res[425].exec("a\x0db", 831));
+assertEquals(null, res[425].exec("a\nb  ", 832));
+assertEquals(null, res[425].exec("a\x0d\nb  ", 833));
+assertEquals(null, res[425].exec("a\x85b ", 834));
+assertEquals(null, res[426].exec("a\x0db", 835));
+assertEquals(null, res[426].exec("a\nb", 836));
+assertEquals(null, res[426].exec("a\x0d\nb", 837));
+assertEquals(null, res[426].exec("** Failers", 838));
+assertEquals(null, res[426].exec("a\x85b", 839));
+assertEquals(null, res[426].exec("a\x0bb     ", 840));
+assertEquals(null, res[427].exec("a\x0db", 841));
+assertEquals(null, res[427].exec("a\nb", 842));
+assertEquals(null, res[427].exec("a\x0d\nb", 843));
+assertEquals(null, res[427].exec("a\x85b", 844));
+assertEquals(null, res[427].exec("a\x0bb     ", 845));
+assertEquals(null, res[427].exec("** Failers ", 846));
+assertEquals(null, res[427].exec("a\x85b<bsr_anycrlf>", 847));
+assertEquals(null, res[427].exec("a\x0bb<bsr_anycrlf>", 848));
+assertEquals(null, res[428].exec("a\x0db", 849));
+assertEquals(null, res[428].exec("a\nb", 850));
+assertEquals(null, res[428].exec("a\x0d\nb", 851));
+assertEquals(null, res[428].exec("** Failers", 852));
+assertEquals(null, res[428].exec("a\x85b", 853));
+assertEquals(null, res[428].exec("a\x0bb     ", 854));
+assertEquals(null, res[429].exec("a\x0db", 855));
+assertEquals(null, res[429].exec("a\nb", 856));
+assertEquals(null, res[429].exec("a\x0d\nb", 857));
+assertEquals(null, res[429].exec("a\x85b", 858));
+assertEquals(null, res[429].exec("a\x0bb     ", 859));
+assertEquals(null, res[429].exec("** Failers ", 860));
+assertEquals(null, res[429].exec("a\x85b<bsr_anycrlf>", 861));
+assertEquals(null, res[429].exec("a\x0bb<bsr_anycrlf>", 862));
+assertEquals(null, res[430].exec("a\x0d\n\nb", 863));
+assertEquals(null, res[430].exec("a\n\x0d\x0db", 864));
+assertEquals(null, res[430].exec("a\x0d\n\x0d\n\x0d\n\x0d\nb", 865));
+assertEquals(null, res[430].exec("** Failers", 866));
+assertEquals(null, res[430].exec("a\x8585b", 867));
+assertEquals(null, res[430].exec("a\x0b\x00bb     ", 868));
+assertEquals(null, res[431].exec("a\x0d\x0db", 869));
+assertEquals(null, res[431].exec("a\n\n\nb", 870));
+assertEquals(null, res[431].exec("a\x0d\n\n\x0d\x0db", 871));
+assertEquals(null, res[431].exec("a\x8585b", 872));
+assertEquals(null, res[431].exec("a\x0b\x00bb     ", 873));
+assertEquals(null, res[431].exec("** Failers ", 874));
+assertEquals(null, res[431].exec("a\x0d\x0d\x0d\x0d\x0db ", 875));
+assertEquals(null, res[431].exec("a\x8585b<bsr_anycrlf>", 876));
+assertEquals(null, res[431].exec("a\x0b\x00bb<bsr_anycrlf>", 877));
+assertEquals(null, res[431].exec("a\nb", 878));
+assertEquals(null, res[431].exec("a\x0db ", 879));
+assertEquals(null, res[431].exec("a\x85b", 880));
+assertEquals(null, res[431].exec("a\nb", 881));
+assertEquals(null, res[431].exec("a\x0db ", 882));
+assertEquals(null, res[431].exec("a\x85b", 883));
+assertThrows("var re = /(?-+a)/;", 884);
+assertEquals(null, res[443].exec("aaaa", 885));
+assertEquals(null, res[443].exec("bacxxx", 886));
+assertEquals(null, res[443].exec("bbaccxxx ", 887));
+assertEquals(null, res[443].exec("bbbacccxx", 888));
+assertEquals(null, res[443].exec("aaaa", 889));
+assertEquals(null, res[443].exec("bacxxx", 890));
+assertEquals(null, res[443].exec("bbaccxxx ", 891));
+assertEquals(null, res[443].exec("bbbacccxx", 892));
+assertEquals("a,a", res[444].exec("aaaa"), 893);
+assertEquals(null, res[444].exec("bacxxx", 894));
+assertEquals(null, res[444].exec("bbaccxxx ", 895));
+assertEquals(null, res[444].exec("bbbacccxx", 896));
+assertEquals("a,a", res[445].exec("aaaa"), 897);
+assertEquals(null, res[445].exec("bacxxx", 898));
+assertEquals(null, res[445].exec("bbaccxxx ", 899));
+assertEquals(null, res[445].exec("bbbacccxx", 900));
+assertEquals("a,a", res[446].exec("aaaa"), 901);
+assertEquals(null, res[446].exec("bacxxx", 902));
+assertEquals(null, res[446].exec("bbaccxxx ", 903));
+assertEquals(null, res[446].exec("bbbacccxx", 904));
+assertEquals("a,a,a", res[447].exec("aaaa"), 905);
+assertEquals(null, res[447].exec("bacxxx", 906));
+assertEquals(null, res[447].exec("bbaccxxx ", 907));
+assertEquals(null, res[447].exec("bbbacccxx", 908));
+assertEquals(null, res[449].exec("bacxxx", 909));
+assertEquals(null, res[449].exec("XaaX", 910));
+assertEquals(null, res[449].exec("XAAX ", 911));
+assertEquals(null, res[449].exec("XaaX", 912));
+assertEquals(null, res[449].exec("** Failers ", 913));
+assertEquals(null, res[449].exec("XAAX ", 914));
+assertEquals(null, res[449].exec("XaaX", 915));
+assertEquals(null, res[449].exec("XAAX ", 916));
+assertEquals(null, res[449].exec("xzxx", 917));
+assertEquals(null, res[449].exec("yzyy ", 918));
+assertEquals(null, res[449].exec("** Failers", 919));
+assertEquals(null, res[449].exec("xxz  ", 920));
+assertEquals("a,,,a", res[450].exec("cat"), 921);
+assertEquals("a,,,a", res[451].exec("cat"), 922);
+assertEquals("TA]", res[452].exec("The ACTA] comes "), 923);
+assertEquals("TA]", res[453].exec("The ACTA] comes "), 924);
+assertEquals(null, res[453].exec("abcbabc", 925));
+assertEquals(null, res[453].exec("abcbabc", 926));
+assertEquals(null, res[453].exec("abcbabc", 927));
+assertEquals(null, res[453].exec("** Failers ", 928));
+assertEquals(null, res[453].exec("abcXabc", 929));
+assertEquals(null, res[453].exec("abcXabc", 930));
+assertEquals(null, res[453].exec("** Failers ", 931));
+assertEquals(null, res[453].exec("abcbabc", 932));
+assertEquals(null, res[453].exec("xyzbabcxyz", 933));
+assertEquals(null, res[456].exec("** Failers", 934));
+assertEquals(null, res[456].exec("ab", 935));
+assertEquals(null, res[457].exec("** Failers", 936));
+assertEquals(null, res[457].exec("ab ", 937));
+assertEquals(null, res[457].exec("** Failers", 938));
+assertEquals(null, res[457].exec("ab ", 939));
+assertEquals("aXb", res[458].exec("aXb"), 940);
+assertEquals("a\nb", res[458].exec("a\nb "), 941);
+assertEquals(null, res[458].exec("** Failers", 942));
+assertEquals(null, res[458].exec("ab  ", 943));
+assertEquals("aXb", res[459].exec("aXb"), 944);
+assertEquals("a\nX\nXb", res[459].exec("a\nX\nXb "), 945);
+assertEquals(null, res[459].exec("** Failers", 946));
+assertEquals(null, res[459].exec("ab  ", 947));
+assertEquals("acb", res[463].exec("acb"), 948);
+assertEquals("ab", res[463].exec("ab"), 949);
+assertEquals(null, res[463].exec("ax{100}b ", 950));
+assertEquals(null, res[463].exec("*** Failers", 951));
+assertEquals(null, res[463].exec("a\nb  ", 952));
+assertEquals(null, res[464].exec("ax{4000}xyb ", 953));
+assertEquals(null, res[464].exec("ax{4000}yb ", 954));
+assertEquals(null, res[464].exec("ax{4000}x{100}yb ", 955));
+assertEquals(null, res[464].exec("*** Failers", 956));
+assertEquals(null, res[464].exec("ax{4000}b ", 957));
+assertEquals(null, res[464].exec("ac\ncb ", 958));
+assertEquals("a\xc0,,\xc0", res[465].exec("a\xc0\x88b"), 959);
+assertEquals("ax,,x", res[466].exec("ax{100}b"), 960);
+assertEquals("a\xc0\x88b,\xc0\x88,b", res[467].exec("a\xc0\x88b"), 961);
+assertEquals("ax{100}b,x{100},b", res[468].exec("ax{100}b"), 962);
+assertEquals("a\xc0\x92,\xc0,\x92", res[469].exec("a\xc0\x92bcd"), 963);
+assertEquals("ax{,x,{", res[470].exec("ax{240}bcd"), 964);
+assertEquals("a\xc0\x92,\xc0,\x92", res[471].exec("a\xc0\x92bcd"), 965);
+assertEquals("ax{,x,{", res[472].exec("ax{240}bcd"), 966);
+assertEquals("a\xc0,,\xc0", res[473].exec("a\xc0\x92bcd"), 967);
+assertEquals("ax,,x", res[474].exec("ax{240}bcd"), 968);
+assertEquals(null, res[475].exec("ax{1234}xyb ", 969));
+assertEquals(null, res[475].exec("ax{1234}x{4321}yb ", 970));
+assertEquals(null, res[475].exec("ax{1234}x{4321}x{3412}b ", 971));
+assertEquals(null, res[475].exec("*** Failers", 972));
+assertEquals(null, res[475].exec("ax{1234}b ", 973));
+assertEquals(null, res[475].exec("ac\ncb ", 974));
+assertEquals("ax{1234}xyb,x{1234}xy", res[476].exec("ax{1234}xyb "), 975);
+assertEquals("ax{1234}x{4321}yb,x{1234}x{4321}y", res[476].exec("ax{1234}x{4321}yb "), 976);
+assertEquals("ax{1234}x{4321}x{3412}b,x{1234}x{4321}x{3412}", res[476].exec("ax{1234}x{4321}x{3412}b "), 977);
+assertEquals("axxxxbcdefghijb,xxxxbcdefghij", res[476].exec("axxxxbcdefghijb "), 978);
+assertEquals("ax{1234}x{4321}x{3412}x{3421}b,x{1234}x{4321}x{3412}x{3421}", res[476].exec("ax{1234}x{4321}x{3412}x{3421}b "), 979);
+assertEquals(null, res[476].exec("*** Failers", 980));
+assertEquals("ax{1234}b,x{1234}", res[476].exec("ax{1234}b "), 981);
+assertEquals("ax{1234}xyb,x{1234}xy", res[477].exec("ax{1234}xyb "), 982);
+assertEquals("ax{1234}x{4321}yb,x{1234}x{4321}y", res[477].exec("ax{1234}x{4321}yb "), 983);
+assertEquals("ax{1234}x{4321}x{3412}b,x{1234}x{4321}x{3412}", res[477].exec("ax{1234}x{4321}x{3412}b "), 984);
+assertEquals("axxxxb,xxxx", res[477].exec("axxxxbcdefghijb "), 985);
+assertEquals("ax{1234}x{4321}x{3412}x{3421}b,x{1234}x{4321}x{3412}x{3421}", res[477].exec("ax{1234}x{4321}x{3412}x{3421}b "), 986);
+assertEquals(null, res[477].exec("*** Failers", 987));
+assertEquals("ax{1234}b,x{1234}", res[477].exec("ax{1234}b "), 988);
+assertEquals(null, res[478].exec("ax{1234}xyb ", 989));
+assertEquals(null, res[478].exec("ax{1234}x{4321}yb ", 990));
+assertEquals(null, res[478].exec("ax{1234}x{4321}x{3412}b ", 991));
+assertEquals("axxxxb,xxxx", res[478].exec("axxxxbcdefghijb "), 992);
+assertEquals(null, res[478].exec("ax{1234}x{4321}x{3412}x{3421}b ", 993));
+assertEquals("axbxxb,xbxx", res[478].exec("axbxxbcdefghijb "), 994);
+assertEquals("axxxxxb,xxxxx", res[478].exec("axxxxxbcdefghijb "), 995);
+assertEquals(null, res[478].exec("*** Failers", 996));
+assertEquals(null, res[478].exec("ax{1234}b ", 997));
+assertEquals(null, res[478].exec("axxxxxxbcdefghijb ", 998));
+assertEquals(null, res[479].exec("ax{1234}xyb ", 999));
+assertEquals(null, res[479].exec("ax{1234}x{4321}yb ", 1000));
+assertEquals(null, res[479].exec("ax{1234}x{4321}x{3412}b ", 1001));
+assertEquals("axxxxb,xxxx", res[479].exec("axxxxbcdefghijb "), 1002);
+assertEquals(null, res[479].exec("ax{1234}x{4321}x{3412}x{3421}b ", 1003));
+assertEquals("axbxxb,xbxx", res[479].exec("axbxxbcdefghijb "), 1004);
+assertEquals("axxxxxb,xxxxx", res[479].exec("axxxxxbcdefghijb "), 1005);
+assertEquals(null, res[479].exec("*** Failers", 1006));
+assertEquals(null, res[479].exec("ax{1234}b ", 1007));
+assertEquals(null, res[479].exec("axxxxxxbcdefghijb ", 1008));
+assertEquals(null, res[479].exec("*** Failers", 1009));
+assertEquals(null, res[479].exec("x{100}", 1010));
+assertEquals(null, res[479].exec("aXbcd", 1011));
+assertEquals(null, res[479].exec("ax{100}bcd", 1012));
+assertEquals(null, res[479].exec("ax{100000}bcd", 1013));
+assertEquals(null, res[479].exec("x{100}x{100}x{100}b", 1014));
+assertEquals(null, res[479].exec("*** Failers ", 1015));
+assertEquals(null, res[479].exec("x{100}x{100}b", 1016));
+assertEquals(null, res[479].exec("x{ab} ", 1017));
+assertEquals(null, res[479].exec("\xc2\xab", 1018));
+assertEquals(null, res[479].exec("*** Failers ", 1019));
+assertEquals(null, res[479].exec("\x00{ab}", 1020));
+assertEquals(null, res[479].exec("WXYZ", 1021));
+assertEquals(null, res[479].exec("x{256}XYZ ", 1022));
+assertEquals(null, res[479].exec("*** Failers", 1023));
+assertEquals(null, res[479].exec("XYZ ", 1024));
+assertEquals(null, res[480].exec("Xx{1234}", 1025));
+assertEquals(null, res[481].exec("Xx{1234}YZ", 1026));
+assertEquals("X", res[482].exec("XYZabcdce"), 1027);
+assertEquals("X", res[483].exec("XYZabcde"), 1028);
+assertEquals(null, res[484].exec("Xabcdefg   ", 1029));
+assertEquals(null, res[484].exec("Xx{1234} ", 1030));
+assertEquals(null, res[484].exec("Xx{1234}YZ", 1031));
+assertEquals(null, res[484].exec("Xx{1234}x{512}  ", 1032));
+assertEquals(null, res[484].exec("Xx{1234}x{512}YZ", 1033));
+assertEquals(null, res[485].exec("Xabcdefg   ", 1034));
+assertEquals(null, res[485].exec("Xx{1234} ", 1035));
+assertEquals(null, res[485].exec("Xx{1234}YZ", 1036));
+assertEquals(null, res[485].exec("Xx{1234}x{512}  ", 1037));
+assertEquals("bcd", res[486].exec("bcd"), 1038);
+assertEquals("00}", res[486].exec("x{100}aYx{256}Z "), 1039);
+assertEquals("x{", res[487].exec("x{100}bc"), 1040);
+assertEquals("x{100}bcA", res[488].exec("x{100}bcAa"), 1041);
+assertEquals("x{", res[489].exec("x{100}bca"), 1042);
+assertEquals("bcd", res[490].exec("bcd"), 1043);
+assertEquals("00}", res[490].exec("x{100}aYx{256}Z "), 1044);
+assertEquals("x{", res[491].exec("x{100}bc"), 1045);
+assertEquals("x{100}bc", res[492].exec("x{100}bcAa"), 1046);
+assertEquals("x{", res[493].exec("x{100}bca"), 1047);
+assertEquals(null, res[493].exec("abcd", 1048));
+assertEquals(null, res[493].exec("abcd", 1049));
+assertEquals("x{", res[493].exec("x{100}x{100} "), 1050);
+assertEquals("x{", res[493].exec("x{100}x{100} "), 1051);
+assertEquals("x{", res[493].exec("x{100}x{100}x{100}x{100} "), 1052);
+assertEquals(null, res[493].exec("abce", 1053));
+assertEquals("x{", res[493].exec("x{100}x{100}x{100}x{100} "), 1054);
+assertEquals(null, res[493].exec("abcdx{100}x{100}x{100}x{100} ", 1055));
+assertEquals(null, res[493].exec("abcdx{100}x{100}x{100}x{100} ", 1056));
+assertEquals(null, res[493].exec("abcdx{100}x{100}x{100}x{100} ", 1057));
+assertEquals(null, res[493].exec("abcdx{100}x{100}x{100}XX", 1058));
+assertEquals(null, res[493].exec("abcdx{100}x{100}x{100}x{100}x{100}x{100}x{100}XX", 1059));
+assertEquals(null, res[493].exec("abcdx{100}x{100}x{100}x{100}x{100}x{100}x{100}XX", 1060));
+assertEquals("Xy", res[493].exec("Xyyyax{100}x{100}bXzzz"), 1061);
+assertEquals("X", res[496].exec("1X2"), 1062);
+assertEquals("x", res[496].exec("1x{100}2 "), 1063);
+assertEquals(">X", res[497].exec("> >X Y"), 1064);
+assertEquals(">x", res[497].exec("> >x{100} Y"), 1065);
+assertEquals("1", res[498].exec("x{100}3"), 1066);
+assertEquals(" ", res[499].exec("x{100} X"), 1067);
+assertEquals("abcd", res[500].exec("12abcd34"), 1068);
+assertEquals("*** Failers", res[500].exec("*** Failers"), 1069);
+assertEquals("  ", res[500].exec("1234  "), 1070);
+assertEquals("abc", res[501].exec("12abcd34"), 1071);
+assertEquals("ab", res[501].exec("12ab34"), 1072);
+assertEquals("***", res[501].exec("*** Failers  "), 1073);
+assertEquals(null, res[501].exec("1234", 1074));
+assertEquals("  ", res[501].exec("12a34  "), 1075);
+assertEquals("ab", res[502].exec("12abcd34"), 1076);
+assertEquals("ab", res[502].exec("12ab34"), 1077);
+assertEquals("**", res[502].exec("*** Failers  "), 1078);
+assertEquals(null, res[502].exec("1234", 1079));
+assertEquals("  ", res[502].exec("12a34  "), 1080);
+assertEquals("12", res[503].exec("12abcd34"), 1081);
+assertEquals(null, res[503].exec("*** Failers", 1082));
+assertEquals("12", res[504].exec("12abcd34"), 1083);
+assertEquals("123", res[504].exec("1234abcd"), 1084);
+assertEquals(null, res[504].exec("*** Failers  ", 1085));
+assertEquals(null, res[504].exec("1.4 ", 1086));
+assertEquals("12", res[505].exec("12abcd34"), 1087);
+assertEquals("12", res[505].exec("1234abcd"), 1088);
+assertEquals(null, res[505].exec("*** Failers  ", 1089));
+assertEquals(null, res[505].exec("1.4 ", 1090));
+assertEquals("12abcd34", res[506].exec("12abcd34"), 1091);
+assertEquals("***", res[506].exec("*** Failers"), 1092);
+assertEquals(null, res[506].exec("     ", 1093));
+assertEquals("12a", res[507].exec("12abcd34"), 1094);
+assertEquals("123", res[507].exec("1234abcd"), 1095);
+assertEquals("***", res[507].exec("*** Failers"), 1096);
+assertEquals(null, res[507].exec("       ", 1097));
+assertEquals("12", res[508].exec("12abcd34"), 1098);
+assertEquals("12", res[508].exec("1234abcd"), 1099);
+assertEquals("**", res[508].exec("*** Failers"), 1100);
+assertEquals(null, res[508].exec("       ", 1101));
+assertEquals(">      <", res[509].exec("12>      <34"), 1102);
+assertEquals(null, res[509].exec("*** Failers", 1103));
+assertEquals(">  <", res[510].exec("ab>  <cd"), 1104);
+assertEquals(">   <", res[510].exec("ab>   <ce"), 1105);
+assertEquals(null, res[510].exec("*** Failers", 1106));
+assertEquals(null, res[510].exec("ab>    <cd ", 1107));
+assertEquals(">  <", res[511].exec("ab>  <cd"), 1108);
+assertEquals(">   <", res[511].exec("ab>   <ce"), 1109);
+assertEquals(null, res[511].exec("*** Failers", 1110));
+assertEquals(null, res[511].exec("ab>    <cd ", 1111));
+assertEquals("12", res[512].exec("12      34"), 1112);
+assertEquals("Failers", res[512].exec("*** Failers"), 1113);
+assertEquals(null, res[512].exec("+++=*! ", 1114));
+assertEquals("ab", res[513].exec("ab  cd"), 1115);
+assertEquals("abc", res[513].exec("abcd ce"), 1116);
+assertEquals("Fai", res[513].exec("*** Failers"), 1117);
+assertEquals(null, res[513].exec("a.b.c", 1118));
+assertEquals("ab", res[514].exec("ab  cd"), 1119);
+assertEquals("ab", res[514].exec("abcd ce"), 1120);
+assertEquals("Fa", res[514].exec("*** Failers"), 1121);
+assertEquals(null, res[514].exec("a.b.c", 1122));
+assertEquals("====", res[515].exec("12====34"), 1123);
+assertEquals("*** ", res[515].exec("*** Failers"), 1124);
+assertEquals(" ", res[515].exec("abcd "), 1125);
+assertEquals("===", res[516].exec("ab====cd"), 1126);
+assertEquals("==", res[516].exec("ab==cd"), 1127);
+assertEquals("***", res[516].exec("*** Failers"), 1128);
+assertEquals(null, res[516].exec("a.b.c", 1129));
+assertEquals("==", res[517].exec("ab====cd"), 1130);
+assertEquals("==", res[517].exec("ab==cd"), 1131);
+assertEquals("**", res[517].exec("*** Failers"), 1132);
+assertEquals(null, res[517].exec("a.b.c", 1133));
+assertEquals(null, res[517].exec("x{100}", 1134));
+assertEquals(null, res[517].exec("Zx{100}", 1135));
+assertEquals(null, res[517].exec("x{100}Z", 1136));
+assertEquals("**", res[517].exec("*** Failers "), 1137);
+assertEquals(null, res[517].exec("Zx{100}", 1138));
+assertEquals(null, res[517].exec("x{100}", 1139));
+assertEquals(null, res[517].exec("x{100}Z", 1140));
+assertEquals("**", res[517].exec("*** Failers "), 1141);
+assertEquals(null, res[517].exec("abcx{200}X", 1142));
+assertEquals(null, res[517].exec("abcx{100}X ", 1143));
+assertEquals("**", res[517].exec("*** Failers"), 1144);
+assertEquals("  ", res[517].exec("X  "), 1145);
+assertEquals(null, res[517].exec("abcx{200}X", 1146));
+assertEquals(null, res[517].exec("abcx{100}X ", 1147));
+assertEquals(null, res[517].exec("abQX ", 1148));
+assertEquals("**", res[517].exec("*** Failers"), 1149);
+assertEquals("  ", res[517].exec("X  "), 1150);
+assertEquals(null, res[517].exec("abcx{100}x{200}x{100}X", 1151));
+assertEquals("**", res[517].exec("*** Failers"), 1152);
+assertEquals(null, res[517].exec("abcx{200}X", 1153));
+assertEquals("  ", res[517].exec("X  "), 1154);
+assertEquals(null, res[517].exec("AX", 1155));
+assertEquals(null, res[517].exec("x{150}X", 1156));
+assertEquals(null, res[517].exec("x{500}X ", 1157));
+assertEquals("**", res[517].exec("*** Failers"), 1158);
+assertEquals(null, res[517].exec("x{100}X", 1159));
+assertEquals("  ", res[517].exec("x{200}X   "), 1160);
+assertEquals(null, res[517].exec("AX", 1161));
+assertEquals(null, res[517].exec("x{150}X", 1162));
+assertEquals(null, res[517].exec("x{500}X ", 1163));
+assertEquals("**", res[517].exec("*** Failers"), 1164);
+assertEquals(null, res[517].exec("x{100}X", 1165));
+assertEquals("  ", res[517].exec("x{200}X   "), 1166);
+assertEquals(null, res[517].exec("QX ", 1167));
+assertEquals(null, res[517].exec("AX", 1168));
+assertEquals(null, res[517].exec("x{500}X ", 1169));
+assertEquals("**", res[517].exec("*** Failers"), 1170);
+assertEquals(null, res[517].exec("x{100}X", 1171));
+assertEquals(null, res[517].exec("x{150}X", 1172));
+assertEquals("  ", res[517].exec("x{200}X   "), 1173);
+assertEquals(null, res[518].exec("aXb", 1174));
+assertEquals(null, res[518].exec("a\nb", 1175));
+assertEquals(null, res[519].exec("aXb", 1176));
+assertEquals(null, res[519].exec("a\nb", 1177));
+assertEquals(null, res[519].exec("*** Failers ", 1178));
+assertEquals(null, res[519].exec("ax{100}b ", 1179));
+assertEquals(null, res[519].exec("z", 1180));
+assertEquals(null, res[519].exec("Z ", 1181));
+assertEquals(null, res[519].exec("x{100}", 1182));
+assertEquals(null, res[519].exec("*** Failers", 1183));
+assertEquals(null, res[519].exec("x{102}", 1184));
+assertEquals(null, res[519].exec("y    ", 1185));
+assertEquals("\xff", res[520].exec(">\xff<"), 1186);
+assertEquals(null, res[521].exec(">x{ff}<", 1187));
+assertEquals("X", res[522].exec("XYZ"), 1188);
+assertEquals("X", res[523].exec("XYZ"), 1189);
+assertEquals("x", res[523].exec("x{123} "), 1190);
+assertEquals(",", res[528].exec("catac"), 1191);
+assertEquals(",", res[528].exec("ax{256}a "), 1192);
+assertEquals(",", res[528].exec("x{85}"), 1193);
+assertEquals(",", res[528].exec("\u1234 "), 1194);
+assertEquals(",", res[528].exec("\u1234 "), 1195);
+assertEquals(",", res[528].exec("abcdefg"), 1196);
+assertEquals(",", res[528].exec("ab"), 1197);
+assertEquals(",", res[528].exec("a "), 1198);
+assertEquals("Ax", res[529].exec("Ax{a3}BC"), 1199);
+assertEquals("Ax", res[530].exec("Ax{a3}BC"), 1200);
+assertEquals("}=", res[531].exec("+x{a3}== "), 1201);
+assertEquals("}=", res[532].exec("+x{a3}== "), 1202);
+assertEquals("x", res[533].exec("x{442}x{435}x{441}x{442}"), 1203);
+assertEquals("x", res[534].exec("x{442}x{435}x{441}x{442}"), 1204);
+assertEquals("x", res[535].exec("x{442}x{435}x{441}x{442}"), 1205);
+assertEquals("x", res[536].exec("x{442}x{435}x{441}x{442}"), 1206);
+assertEquals("{", res[537].exec("x{2442}x{2435}x{2441}x{2442}"), 1207);
+assertEquals("{", res[538].exec("x{2442}x{2435}x{2441}x{2442}"), 1208);
+assertEquals("abc\n\x0dx{442}x{435}x{441}x{442}xyz ", res[539].exec("abc\n\x0dx{442}x{435}x{441}x{442}xyz "), 1209);
+assertEquals("x{442}x{435}x{441}x{442}", res[539].exec("x{442}x{435}x{441}x{442}"), 1210);
+assertEquals("c d", res[540].exec("abc defx{442}x{443}xyz\npqr"), 1211);
+assertEquals("c d", res[541].exec("abc defx{442}x{443}xyz\npqr"), 1212);
+assertEquals(null, res[542].exec("+x{2442}", 1213));
+assertEquals(null, res[543].exec("+x{2442}", 1214));
+assertEquals(null, res[544].exec("Ax{442}", 1215));
+assertEquals(null, res[545].exec("Ax{442}", 1216));
+assertEquals(null, res[546].exec("Ax{442}", 1217));
+assertEquals(null, res[547].exec("Ax{442}", 1218));
+assertEquals(null, res[548].exec("\x19x{e01ff}", 1219));
+assertEquals(null, res[549].exec("Ax{422}", 1220));
+assertEquals(null, res[550].exec("x{19}x{e01ff}", 1221));
+assertEquals(null, res[551].exec("Ax{442}", 1222));
+assertEquals(null, res[552].exec("Ax{442}", 1223));
+assertEquals(null, res[553].exec("ax{442}", 1224));
+assertEquals(null, res[554].exec("+x{2442}", 1225));
+assertEquals(null, res[555].exec("Mx{442}", 1226));
+assertEquals("abc", res[556].exec("abc"), 1227);
+assertEquals("abc", res[557].exec("abc"), 1228);
+assertEquals("abc", res[558].exec("abc"), 1229);
+assertEquals("abc", res[559].exec("abc"), 1230);
+assertEquals(null, res[560].exec("x{100}ax{1234}bcd", 1231));
+assertEquals(null, res[562].exec("x{0041}x{2262}x{0391}x{002e}", 1232));
+assertEquals(null, res[562].exec("x{D55c}x{ad6d}x{C5B4} ", 1233));
+assertEquals(null, res[562].exec("x{65e5}x{672c}x{8a9e}", 1234));
+assertEquals("{861}X", res[563].exec("x{212ab}x{212ab}x{212ab}x{861}X"), 1235);
+assertEquals("x{2", res[564].exec("x{212ab}x{212ab}x{212ab}x{861}"), 1236);
+assertEquals("x{c", res[564].exec("x{c0}b"), 1237);
+assertEquals("ax{", res[564].exec("ax{c0}aaaa/ "), 1238);
+assertEquals("ax{", res[564].exec("ax{c0}aaaa/ "), 1239);
+assertEquals("ax{", res[564].exec("ax{c0}ax{c0}aaa/ "), 1240);
+assertEquals("ax{", res[564].exec("ax{c0}aaaa/ "), 1241);
+assertEquals("ax{", res[564].exec("ax{c0}ax{c0}aaa/ "), 1242);
+assertEquals("ax{", res[564].exec("ax{c0}aaaa/ "), 1243);
+assertEquals("ax{", res[564].exec("ax{c0}ax{c0}aaa/ "), 1244);
+assertEquals("Sho", res[564].exec("Should produce an error diagnostic"), 1245);
+assertEquals(null, res[565].exec("Xx{1234}", 1246));
+assertEquals(null, res[565].exec("X\nabc ", 1247));
+assertEquals("b", res[566].exec("bar"), 1248);
+assertEquals(null, res[566].exec("*** Failers", 1249));
+assertEquals(null, res[566].exec("c", 1250));
+assertEquals(null, res[566].exec("x{ff}", 1251));
+assertEquals(null, res[566].exec("x{100}  ", 1252));
+assertEquals("c", res[567].exec("c"), 1253);
+assertEquals("x", res[567].exec("x{ff}"), 1254);
+assertEquals("x", res[567].exec("x{100}  "), 1255);
+assertEquals("*", res[567].exec("*** Failers "), 1256);
+assertEquals(null, res[567].exec("aaa", 1257));
+assertEquals("x", res[568].exec("x{f1}"), 1258);
+assertEquals("x", res[568].exec("x{bf}"), 1259);
+assertEquals("x", res[568].exec("x{100}"), 1260);
+assertEquals("x", res[568].exec("x{1000}   "), 1261);
+assertEquals("*", res[568].exec("*** Failers"), 1262);
+assertEquals("x", res[568].exec("x{c0} "), 1263);
+assertEquals("x", res[568].exec("x{f0} "), 1264);
+assertEquals("1", res[568].exec("1234"), 1265);
+assertEquals("\"", res[568].exec("\"1234\" "), 1266);
+assertEquals("x", res[568].exec("x{100}1234"), 1267);
+assertEquals("\"", res[568].exec("\"x{100}1234\"  "), 1268);
+assertEquals("x", res[568].exec("x{100}x{100}12ab "), 1269);
+assertEquals("x", res[568].exec("x{100}x{100}\"12\" "), 1270);
+assertEquals("*", res[568].exec("*** Failers "), 1271);
+assertEquals("x", res[568].exec("x{100}x{100}abcd"), 1272);
+assertEquals("A", res[568].exec("A"), 1273);
+assertEquals("x", res[568].exec("x{100}"), 1274);
+assertEquals("Z", res[568].exec("Zx{100}"), 1275);
+assertEquals("x", res[568].exec("x{100}Z"), 1276);
+assertEquals("*", res[568].exec("*** Failers "), 1277);
+assertEquals("Z", res[568].exec("Zx{100}"), 1278);
+assertEquals("x", res[568].exec("x{100}"), 1279);
+assertEquals("x", res[568].exec("x{100}Z"), 1280);
+assertEquals("*", res[568].exec("*** Failers "), 1281);
+assertEquals("x", res[568].exec("x{100}"), 1282);
+assertEquals("x", res[568].exec("x{104}"), 1283);
+assertEquals("*", res[568].exec("*** Failers"), 1284);
+assertEquals("x", res[568].exec("x{105}"), 1285);
+assertEquals("x", res[568].exec("x{ff}    "), 1286);
+assertEquals("x", res[568].exec("x{100}"), 1287);
+assertEquals("\u0100", res[568].exec("\u0100 "), 1288);
+assertEquals("\xff", res[569].exec(">\xff<"), 1289);
+assertEquals(null, res[570].exec(">x{ff}<", 1290));
+assertEquals("\xd6", res[572].exec("\xd6 # Matches without Study"), 1291);
+assertEquals("x", res[572].exec("x{d6}"), 1292);
+assertEquals("\xd6", res[572].exec("\xd6 <-- Same with Study"), 1293);
+assertEquals("x", res[572].exec("x{d6}"), 1294);
+assertEquals("\xd6", res[572].exec("\xd6 # Matches without Study"), 1295);
+assertEquals("x", res[572].exec("x{d6} "), 1296);
+assertEquals("\xd6", res[572].exec("\xd6 <-- Same with Study"), 1297);
+assertEquals("x", res[572].exec("x{d6} "), 1298);
+assertEquals("\ufffd", res[572].exec("\ufffd]"), 1299);
+assertEquals("\ufffd", res[572].exec("\ufffd"), 1300);
+assertEquals("\ufffd", res[572].exec("\ufffd\ufffd\ufffd"), 1301);
+assertEquals("\ufffd", res[572].exec("\ufffd\ufffd\ufffd?"), 1302);
+assertEquals(null, res[573].exec("\xc0\x80", 1303));
+assertEquals(null, res[573].exec("\xc1\x8f ", 1304));
+assertEquals(null, res[573].exec("\xe0\x9f\x80", 1305));
+assertEquals(null, res[573].exec("\xf0\x8f\x80\x80 ", 1306));
+assertEquals(null, res[573].exec("\xf8\x87\x80\x80\x80  ", 1307));
+assertEquals(null, res[573].exec("\xfc\x83\x80\x80\x80\x80", 1308));
+assertEquals(null, res[573].exec("\xfe\x80\x80\x80\x80\x80  ", 1309));
+assertEquals(null, res[573].exec("\xff\x80\x80\x80\x80\x80  ", 1310));
+assertEquals(null, res[573].exec("\xc3\x8f", 1311));
+assertEquals(null, res[573].exec("\xe0\xaf\x80", 1312));
+assertEquals(null, res[573].exec("\xe1\x80\x80", 1313));
+assertEquals(null, res[573].exec("\xf0\x9f\x80\x80 ", 1314));
+assertEquals(null, res[573].exec("\xf1\x8f\x80\x80 ", 1315));
+assertEquals(null, res[573].exec("\xf8\x88\x80\x80\x80  ", 1316));
+assertEquals(null, res[573].exec("\xf9\x87\x80\x80\x80  ", 1317));
+assertEquals(null, res[573].exec("\xfc\x84\x80\x80\x80\x80", 1318));
+assertEquals(null, res[573].exec("\xfd\x83\x80\x80\x80\x80", 1319));
+assertEquals(null, res[573].exec("?\xf8\x88\x80\x80\x80  ", 1320));
+assertEquals(null, res[573].exec("?\xf9\x87\x80\x80\x80  ", 1321));
+assertEquals(null, res[573].exec("?\xfc\x84\x80\x80\x80\x80", 1322));
+assertEquals(null, res[573].exec("?\xfd\x83\x80\x80\x80\x80", 1323));
+assertEquals(".", res[574].exec("A.B"), 1324);
+assertEquals("{", res[574].exec("Ax{100}B "), 1325);
+assertEquals("x", res[575].exec("x{100}X   "), 1326);
+assertEquals("a", res[575].exec("ax{1234}b"), 1327);
+assertEquals(null, res[577].exec("AxxB     ", 1328));
+assertEquals("abc1", res[578].exec("abc1 \nabc2 \x0babc3xx \x0cabc4 \x0dabc5xx \x0d\nabc6 x{0085}abc7 x{2028}abc8 x{2029}abc9 JUNK"), 1329);
+assertEquals("abc1", res[579].exec("abc1\n abc2\x0b abc3\x0c abc4\x0d abc5\x0d\n abc6x{0085} abc7x{2028} abc8x{2029} abc9"), 1330);
+assertEquals(null, res[580].exec("a\nb", 1331));
+assertEquals(null, res[580].exec("a\x0db", 1332));
+assertEquals(null, res[580].exec("a\x0d\nb", 1333));
+assertEquals(null, res[580].exec("a\x0bb", 1334));
+assertEquals(null, res[580].exec("a\x0cb", 1335));
+assertEquals(null, res[580].exec("ax{85}b   ", 1336));
+assertEquals(null, res[580].exec("ax{2028}b ", 1337));
+assertEquals(null, res[580].exec("ax{2029}b ", 1338));
+assertEquals(null, res[580].exec("** Failers", 1339));
+assertEquals(null, res[580].exec("a\n\x0db    ", 1340));
+assertEquals("ab", res[581].exec("ab"), 1341);
+assertEquals(null, res[581].exec("a\nb", 1342));
+assertEquals(null, res[581].exec("a\x0db", 1343));
+assertEquals(null, res[581].exec("a\x0d\nb", 1344));
+assertEquals(null, res[581].exec("a\x0bb", 1345));
+assertEquals(null, res[581].exec("a\x0cx{2028}x{2029}b", 1346));
+assertEquals(null, res[581].exec("ax{85}b   ", 1347));
+assertEquals(null, res[581].exec("a\n\x0db    ", 1348));
+assertEquals(null, res[581].exec("a\n\x0dx{85}\x0cb ", 1349));
+assertEquals(null, res[582].exec("a\nb", 1350));
+assertEquals(null, res[582].exec("a\x0db", 1351));
+assertEquals(null, res[582].exec("a\x0d\nb", 1352));
+assertEquals(null, res[582].exec("a\x0bb", 1353));
+assertEquals(null, res[582].exec("a\x0cx{2028}x{2029}b", 1354));
+assertEquals(null, res[582].exec("ax{85}b   ", 1355));
+assertEquals(null, res[582].exec("a\n\x0db    ", 1356));
+assertEquals(null, res[582].exec("a\n\x0dx{85}\x0cb ", 1357));
+assertEquals(null, res[582].exec("** Failers", 1358));
+assertEquals(null, res[582].exec("ab  ", 1359));
+assertEquals(null, res[583].exec("a\nb", 1360));
+assertEquals(null, res[583].exec("a\n\x0db", 1361));
+assertEquals(null, res[583].exec("a\n\x0dx{85}b", 1362));
+assertEquals(null, res[583].exec("a\x0d\n\x0d\nb ", 1363));
+assertEquals(null, res[583].exec("a\x0d\n\x0d\n\x0d\nb ", 1364));
+assertEquals(null, res[583].exec("a\n\x0d\n\x0db", 1365));
+assertEquals(null, res[583].exec("a\n\n\x0d\nb ", 1366));
+assertEquals(null, res[583].exec("** Failers", 1367));
+assertEquals(null, res[583].exec("a\n\n\n\x0db", 1368));
+assertEquals(null, res[583].exec("a\x0d", 1369));
+assertEquals(null, res[584].exec("X X\n", 1370));
+assertEquals(null, res[584].exec("X\x09X\x0b", 1371));
+assertEquals(null, res[584].exec("** Failers", 1372));
+assertEquals(null, res[584].exec("x{a0} X\n   ", 1373));
+assertEquals(null, res[585].exec("\x09 x{a0}X\n\x0b\x0c\x0d\n", 1374));
+assertEquals(null, res[585].exec("\x09 x{a0}\n\x0b\x0c\x0d\n", 1375));
+assertEquals(null, res[585].exec("\x09 x{a0}\n\x0b\x0c", 1376));
+assertEquals(null, res[585].exec("** Failers ", 1377));
+assertEquals(null, res[585].exec("\x09 x{a0}\n\x0b", 1378));
+assertEquals(null, res[585].exec(" ", 1379));
+assertEquals(null, res[586].exec("x{3001}x{3000}x{2030}x{2028}", 1380));
+assertEquals(null, res[586].exec("Xx{180e}Xx{85}", 1381));
+assertEquals(null, res[586].exec("** Failers", 1382));
+assertEquals(null, res[586].exec("x{2009} X\n   ", 1383));
+assertEquals(null, res[587].exec("x{1680}x{180e}x{2007}Xx{2028}x{2029}\x0c\x0d\n", 1384));
+assertEquals(null, res[587].exec("\x09x{205f}x{a0}\nx{2029}\x0cx{2028}\n", 1385));
+assertEquals(null, res[587].exec("\x09 x{202f}\n\x0b\x0c", 1386));
+assertEquals(null, res[587].exec("** Failers ", 1387));
+assertEquals(null, res[587].exec("\x09x{200a}x{a0}x{2028}\x0b", 1388));
+assertEquals(null, res[587].exec(" ", 1389));
+assertEquals(null, res[588].exec(">x{1680}", 1390));
+assertEquals(null, res[589].exec(">x{1680}x{180e}x{2000}x{2003}x{200a}x{202f}x{205f}x{3000}<", 1391));
+assertEquals("x{1ec5} ", res[593].exec("x{1ec5} "), 1392);
+assertEquals(null, res[594].exec("x{0}x{d7ff}x{e000}x{10ffff}", 1393));
+assertEquals(null, res[594].exec("x{d800}", 1394));
+assertEquals(null, res[594].exec("x{d800}?", 1395));
+assertEquals(null, res[594].exec("x{da00}", 1396));
+assertEquals(null, res[594].exec("x{da00}?", 1397));
+assertEquals(null, res[594].exec("x{dfff}", 1398));
+assertEquals(null, res[594].exec("x{dfff}?", 1399));
+assertEquals(null, res[594].exec("x{110000}    ", 1400));
+assertEquals(null, res[594].exec("x{110000}?    ", 1401));
+assertEquals(null, res[594].exec("x{2000000} ", 1402));
+assertEquals(null, res[594].exec("x{2000000}? ", 1403));
+assertEquals(null, res[594].exec("x{7fffffff} ", 1404));
+assertEquals(null, res[594].exec("x{7fffffff}? ", 1405));
+assertEquals(null, res[595].exec("a\x0db", 1406));
+assertEquals(null, res[595].exec("a\nb", 1407));
+assertEquals(null, res[595].exec("a\x0d\nb", 1408));
+assertEquals(null, res[595].exec("** Failers", 1409));
+assertEquals(null, res[595].exec("ax{85}b", 1410));
+assertEquals(null, res[595].exec("a\x0bb     ", 1411));
+assertEquals(null, res[596].exec("a\x0db", 1412));
+assertEquals(null, res[596].exec("a\nb", 1413));
+assertEquals(null, res[596].exec("a\x0d\nb", 1414));
+assertEquals(null, res[596].exec("ax{85}b", 1415));
+assertEquals(null, res[596].exec("a\x0bb     ", 1416));
+assertEquals(null, res[596].exec("** Failers ", 1417));
+assertEquals(null, res[596].exec("ax{85}b<bsr_anycrlf>", 1418));
+assertEquals(null, res[596].exec("a\x0bb<bsr_anycrlf>", 1419));
+assertEquals(null, res[597].exec("a\x0db", 1420));
+assertEquals(null, res[597].exec("a\nb", 1421));
+assertEquals(null, res[597].exec("a\x0d\nb", 1422));
+assertEquals(null, res[597].exec("** Failers", 1423));
+assertEquals(null, res[597].exec("ax{85}b", 1424));
+assertEquals(null, res[597].exec("a\x0bb     ", 1425));
+assertEquals(null, res[598].exec("a\x0db", 1426));
+assertEquals(null, res[598].exec("a\nb", 1427));
+assertEquals(null, res[598].exec("a\x0d\nb", 1428));
+assertEquals(null, res[598].exec("ax{85}b", 1429));
+assertEquals(null, res[598].exec("a\x0bb     ", 1430));
+assertEquals(null, res[598].exec("** Failers ", 1431));
+assertEquals(null, res[598].exec("ax{85}b<bsr_anycrlf>", 1432));
+assertEquals(null, res[598].exec("a\x0bb<bsr_anycrlf>", 1433));
+assertEquals("QQQx{2029}ABCaXYZ=!bPQR", res[599].exec("QQQx{2029}ABCaXYZ=!bPQR"), 1434);
+assertEquals(null, res[599].exec("** Failers", 1435));
+assertEquals(null, res[599].exec("ax{2029}b", 1436));
+assertEquals(null, res[599].exec("a\xe2\x80\xa9b ", 1437));
+assertEquals(null, res[600].exec("ax{1234}b", 1438));
+assertEquals("a\nb", res[600].exec("a\nb "), 1439);
+assertEquals(null, res[600].exec("** Failers", 1440));
+assertEquals(null, res[600].exec("ab  ", 1441));
+assertEquals("aXb", res[601].exec("aXb"), 1442);
+assertEquals("a\nX\nXx{1234}b", res[601].exec("a\nX\nXx{1234}b "), 1443);
+assertEquals(null, res[601].exec("** Failers", 1444));
+assertEquals(null, res[601].exec("ab  ", 1445));
+assertEquals(null, res[601].exec("x{de}x{de}", 1446));
+assertEquals(null, res[601].exec("x{123} ", 1447));
+assertEquals("X", res[602].exec("Ax{1ec5}ABCXYZ"), 1448);
+assertEquals(null, res[604].exec("x{c0}x{30f}x{660}x{66c}x{f01}x{1680}<", 1449));
+assertEquals(null, res[604].exec("\npx{300}9!$ < ", 1450));
+assertEquals(null, res[604].exec("** Failers ", 1451));
+assertEquals(null, res[604].exec("apx{300}9!$ < ", 1452));
+assertEquals(null, res[605].exec("X", 1453));
+assertEquals(null, res[605].exec("** Failers ", 1454));
+assertEquals(null, res[605].exec("", 1455));
+assertEquals(null, res[606].exec("9", 1456));
+assertEquals(null, res[606].exec("** Failers ", 1457));
+assertEquals(null, res[606].exec("x{c0}", 1458));
+assertEquals(null, res[607].exec("X", 1459));
+assertEquals(null, res[607].exec("** Failers ", 1460));
+assertEquals(null, res[607].exec("x{30f}", 1461));
+assertEquals(null, res[608].exec("X", 1462));
+assertEquals(null, res[608].exec("** Failers ", 1463));
+assertEquals(null, res[608].exec("x{660}", 1464));
+assertEquals(null, res[609].exec("X", 1465));
+assertEquals(null, res[609].exec("** Failers ", 1466));
+assertEquals(null, res[609].exec("x{66c}", 1467));
+assertEquals(null, res[610].exec("X", 1468));
+assertEquals(null, res[610].exec("** Failers ", 1469));
+assertEquals(null, res[610].exec("x{f01}", 1470));
+assertEquals(null, res[611].exec("X", 1471));
+assertEquals(null, res[611].exec("** Failers ", 1472));
+assertEquals(null, res[611].exec("x{1680}", 1473));
+assertEquals(null, res[612].exec("x{017}", 1474));
+assertEquals(null, res[612].exec("x{09f} ", 1475));
+assertEquals(null, res[612].exec("** Failers", 1476));
+assertEquals(null, res[612].exec("x{0600} ", 1477));
+assertEquals(null, res[613].exec("x{601}", 1478));
+assertEquals(null, res[613].exec("** Failers", 1479));
+assertEquals(null, res[613].exec("x{09f} ", 1480));
+assertEquals(null, res[614].exec("x{e0000}", 1481));
+assertEquals(null, res[614].exec("** Failers", 1482));
+assertEquals(null, res[614].exec("x{09f} ", 1483));
+assertEquals(null, res[615].exec("x{f8ff}", 1484));
+assertEquals(null, res[615].exec("** Failers", 1485));
+assertEquals(null, res[615].exec("x{09f} ", 1486));
+assertEquals(null, res[616].exec("?x{dfff}", 1487));
+assertEquals(null, res[616].exec("** Failers", 1488));
+assertEquals(null, res[616].exec("x{09f} ", 1489));
+assertEquals(null, res[617].exec("a", 1490));
+assertEquals(null, res[617].exec("** Failers ", 1491));
+assertEquals(null, res[617].exec("Z", 1492));
+assertEquals(null, res[617].exec("x{e000}  ", 1493));
+assertEquals(null, res[618].exec("x{2b0}", 1494));
+assertEquals(null, res[618].exec("** Failers", 1495));
+assertEquals(null, res[618].exec("a ", 1496));
+assertEquals(null, res[619].exec("x{1bb}", 1497));
+assertEquals(null, res[619].exec("x{3400}", 1498));
+assertEquals(null, res[619].exec("x{3401}", 1499));
+assertEquals(null, res[619].exec("x{4d00}", 1500));
+assertEquals(null, res[619].exec("x{4db4}", 1501));
+assertEquals(null, res[619].exec("x{4db5}     ", 1502));
+assertEquals(null, res[619].exec("** Failers", 1503));
+assertEquals(null, res[619].exec("a ", 1504));
+assertEquals(null, res[619].exec("x{2b0}", 1505));
+assertEquals(null, res[619].exec("x{4db6} ", 1506));
+assertEquals(null, res[620].exec("x{1c5}", 1507));
+assertEquals(null, res[620].exec("** Failers", 1508));
+assertEquals(null, res[620].exec("a ", 1509));
+assertEquals(null, res[620].exec("x{2b0}", 1510));
+assertEquals(null, res[621].exec("A", 1511));
+assertEquals(null, res[621].exec("** Failers", 1512));
+assertEquals(null, res[621].exec("x{2b0}", 1513));
+assertEquals(null, res[622].exec("x{903}", 1514));
+assertEquals(null, res[622].exec("** Failers", 1515));
+assertEquals(null, res[622].exec("X", 1516));
+assertEquals(null, res[622].exec("x{300}", 1517));
+assertEquals(null, res[622].exec("   ", 1518));
+assertEquals(null, res[623].exec("x{488}", 1519));
+assertEquals(null, res[623].exec("** Failers", 1520));
+assertEquals(null, res[623].exec("X", 1521));
+assertEquals(null, res[623].exec("x{903}", 1522));
+assertEquals(null, res[623].exec("x{300}", 1523));
+assertEquals(null, res[624].exec("x{300}", 1524));
+assertEquals(null, res[624].exec("** Failers", 1525));
+assertEquals(null, res[624].exec("X", 1526));
+assertEquals(null, res[624].exec("x{903}", 1527));
+assertEquals(null, res[624].exec("0123456789x{660}x{661}x{662}x{663}x{664}x{665}x{666}x{667}x{668}x{669}x{66a}", 1528));
+assertEquals(null, res[624].exec("x{6f0}x{6f1}x{6f2}x{6f3}x{6f4}x{6f5}x{6f6}x{6f7}x{6f8}x{6f9}x{6fa}", 1529));
+assertEquals(null, res[624].exec("x{966}x{967}x{968}x{969}x{96a}x{96b}x{96c}x{96d}x{96e}x{96f}x{970}", 1530));
+assertEquals(null, res[624].exec("** Failers", 1531));
+assertEquals(null, res[624].exec("X", 1532));
+assertEquals(null, res[625].exec("x{16ee}", 1533));
+assertEquals(null, res[625].exec("** Failers", 1534));
+assertEquals(null, res[625].exec("X", 1535));
+assertEquals(null, res[625].exec("x{966}", 1536));
+assertEquals(null, res[626].exec("x{b2}", 1537));
+assertEquals(null, res[626].exec("x{b3}", 1538));
+assertEquals(null, res[626].exec("** Failers", 1539));
+assertEquals(null, res[626].exec("X", 1540));
+assertEquals(null, res[626].exec("x{16ee}", 1541));
+assertEquals(null, res[627].exec("_", 1542));
+assertEquals(null, res[627].exec("x{203f}", 1543));
+assertEquals(null, res[627].exec("** Failers", 1544));
+assertEquals(null, res[627].exec("X", 1545));
+assertEquals(null, res[627].exec("-", 1546));
+assertEquals(null, res[627].exec("x{58a}", 1547));
+assertEquals(null, res[628].exec("-", 1548));
+assertEquals(null, res[628].exec("x{58a}", 1549));
+assertEquals(null, res[628].exec("** Failers", 1550));
+assertEquals(null, res[628].exec("X", 1551));
+assertEquals(null, res[628].exec("x{203f}", 1552));
+assertEquals(null, res[629].exec(")", 1553));
+assertEquals(null, res[629].exec("]", 1554));
+assertEquals(null, res[629].exec("}", 1555));
+assertEquals(null, res[629].exec("x{f3b}", 1556));
+assertEquals(null, res[629].exec("** Failers", 1557));
+assertEquals(null, res[629].exec("X", 1558));
+assertEquals(null, res[629].exec("x{203f}", 1559));
+assertEquals(null, res[629].exec("(", 1560));
+assertEquals(null, res[629].exec("[", 1561));
+assertEquals(null, res[629].exec("{", 1562));
+assertEquals(null, res[629].exec("x{f3c}", 1563));
+assertEquals(null, res[630].exec("x{bb}", 1564));
+assertEquals(null, res[630].exec("x{2019}", 1565));
+assertEquals(null, res[630].exec("** Failers", 1566));
+assertEquals(null, res[630].exec("X", 1567));
+assertEquals(null, res[630].exec("x{203f}", 1568));
+assertEquals(null, res[631].exec("x{ab}", 1569));
+assertEquals(null, res[631].exec("x{2018}", 1570));
+assertEquals(null, res[631].exec("** Failers", 1571));
+assertEquals(null, res[631].exec("X", 1572));
+assertEquals(null, res[631].exec("x{203f}", 1573));
+assertEquals(null, res[632].exec("!", 1574));
+assertEquals(null, res[632].exec("x{37e}", 1575));
+assertEquals(null, res[632].exec("** Failers", 1576));
+assertEquals(null, res[632].exec("X", 1577));
+assertEquals(null, res[632].exec("x{203f}", 1578));
+assertEquals(null, res[633].exec("(", 1579));
+assertEquals(null, res[633].exec("[", 1580));
+assertEquals(null, res[633].exec("{", 1581));
+assertEquals(null, res[633].exec("x{f3c}", 1582));
+assertEquals(null, res[633].exec("** Failers", 1583));
+assertEquals(null, res[633].exec("X", 1584));
+assertEquals(null, res[633].exec(")", 1585));
+assertEquals(null, res[633].exec("]", 1586));
+assertEquals(null, res[633].exec("}", 1587));
+assertEquals(null, res[633].exec("x{f3b}", 1588));
+assertEquals(null, res[633].exec("$x{a2}x{a3}x{a4}x{a5}x{a6}", 1589));
+assertEquals(null, res[633].exec("x{9f2}", 1590));
+assertEquals(null, res[633].exec("** Failers", 1591));
+assertEquals(null, res[633].exec("X", 1592));
+assertEquals(null, res[633].exec("x{2c2}", 1593));
+assertEquals(null, res[634].exec("x{2c2}", 1594));
+assertEquals(null, res[634].exec("** Failers", 1595));
+assertEquals(null, res[634].exec("X", 1596));
+assertEquals(null, res[634].exec("x{9f2}", 1597));
+assertEquals(null, res[634].exec("+<|~x{ac}x{2044}", 1598));
+assertEquals(null, res[634].exec("** Failers", 1599));
+assertEquals(null, res[634].exec("X", 1600));
+assertEquals(null, res[634].exec("x{9f2}", 1601));
+assertEquals(null, res[635].exec("x{a6}", 1602));
+assertEquals(null, res[635].exec("x{482} ", 1603));
+assertEquals(null, res[635].exec("** Failers", 1604));
+assertEquals(null, res[635].exec("X", 1605));
+assertEquals(null, res[635].exec("x{9f2}", 1606));
+assertEquals(null, res[636].exec("x{2028}", 1607));
+assertEquals(null, res[636].exec("** Failers", 1608));
+assertEquals(null, res[636].exec("X", 1609));
+assertEquals(null, res[636].exec("x{2029}", 1610));
+assertEquals(null, res[637].exec("x{2029}", 1611));
+assertEquals(null, res[637].exec("** Failers", 1612));
+assertEquals(null, res[637].exec("X", 1613));
+assertEquals(null, res[637].exec("x{2028}", 1614));
+assertEquals(null, res[638].exec("\\ \\", 1615));
+assertEquals(null, res[638].exec("x{a0}", 1616));
+assertEquals(null, res[638].exec("x{1680}", 1617));
+assertEquals(null, res[638].exec("x{180e}", 1618));
+assertEquals(null, res[638].exec("x{2000}", 1619));
+assertEquals(null, res[638].exec("x{2001}     ", 1620));
+assertEquals(null, res[638].exec("** Failers", 1621));
+assertEquals(null, res[638].exec("x{2028}", 1622));
+assertEquals(null, res[638].exec("x{200d} ", 1623));
+assertEquals(null, res[638].exec("  x{660}x{661}x{662}ABC", 1624));
+assertEquals(null, res[638].exec("  x{660}x{661}x{662}ABC", 1625));
+assertEquals(null, res[639].exec("  x{660}x{661}x{662}ABC", 1626));
+assertEquals(null, res[640].exec("  x{660}x{661}x{662}ABC", 1627));
+assertEquals(null, res[641].exec("  x{660}x{661}x{662}ABC", 1628));
+assertEquals(null, res[642].exec("  x{660}x{661}x{662}ABC", 1629));
+assertEquals(null, res[643].exec("  x{660}x{661}x{662}ABC", 1630));
+assertEquals(null, res[644].exec("  x{660}x{661}x{662}ABC", 1631));
+assertEquals(null, res[645].exec("  x{660}x{661}x{662}ABC", 1632));
+assertEquals(null, res[646].exec("  x{660}x{661}x{662}ABC", 1633));
+assertEquals(null, res[647].exec("  x{660}x{661}x{662}ABC", 1634));
+assertEquals(null, res[647].exec("  x{660}x{661}x{662}ABC", 1635));
+assertEquals(null, res[647].exec("  x{660}x{661}x{662}ABC", 1636));
+assertEquals(null, res[647].exec("  ** Failers", 1637));
+assertEquals(null, res[647].exec("  x{660}x{661}x{662}ABC", 1638));
+assertEquals(null, res[648].exec("A", 1639));
+assertEquals(null, res[648].exec("ax{10a0}B ", 1640));
+assertEquals(null, res[648].exec("** Failers ", 1641));
+assertEquals(null, res[648].exec("a", 1642));
+assertEquals(null, res[648].exec("x{1d00}  ", 1643));
+assertEquals(null, res[649].exec("1234", 1644));
+assertEquals(null, res[649].exec("** Failers", 1645));
+assertEquals(null, res[649].exec("ABC ", 1646));
+assertEquals(null, res[650].exec("1234", 1647));
+assertEquals(null, res[650].exec("** Failers", 1648));
+assertEquals(null, res[650].exec("ABC ", 1649));
+assertEquals(null, res[650].exec("A2XYZ", 1650));
+assertEquals(null, res[650].exec("123A5XYZPQR", 1651));
+assertEquals(null, res[650].exec("ABAx{660}XYZpqr", 1652));
+assertEquals(null, res[650].exec("** Failers", 1653));
+assertEquals(null, res[650].exec("AXYZ", 1654));
+assertEquals(null, res[650].exec("XYZ     ", 1655));
+assertEquals(null, res[650].exec("1XYZ", 1656));
+assertEquals(null, res[650].exec("AB=XYZ.. ", 1657));
+assertEquals(null, res[650].exec("XYZ ", 1658));
+assertEquals(null, res[650].exec("** Failers", 1659));
+assertEquals(null, res[650].exec("WXYZ ", 1660));
+assertEquals(null, res[655].exec("1234", 1661));
+assertEquals(null, res[655].exec("1234", 1662));
+assertEquals(null, res[655].exec("12-34", 1663));
+assertEquals("{", res[655].exec("12+x{661}-34  "), 1664);
+assertEquals(null, res[655].exec("** Failers", 1665));
+assertEquals("d", res[655].exec("abcd  "), 1666);
+assertEquals("d", res[656].exec("abcd"), 1667);
+assertEquals(null, res[656].exec("** Failers", 1668));
+assertEquals(null, res[656].exec("1234", 1669));
+assertEquals(null, res[657].exec("11111111111111111111111111111111111111111111111111111111111111111111111", 1670));
+assertEquals("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", res[657].exec("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), 1671);
+assertEquals(" ", res[657].exec(" "), 1672);
+assertEquals(null, res[657].exec("11111111111111111111111111111111111111111111111111111111111111111111111", 1673));
+assertEquals("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", res[657].exec("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), 1674);
+assertEquals(null, res[658].exec("11111111111111111111111111111111111111111111111111111111111111111111111", 1675));
+assertEquals("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", res[658].exec("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), 1676);
+assertEquals(null, res[659].exec("11111111111111111111111111111111111111111111111111111111111111111111111", 1677));
+assertEquals(null, res[659].exec("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 1678));
+assertEquals(null, res[660].exec("11111111111111111111111111111111111111111111111111111111111111111111111", 1679));
+assertEquals("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", res[660].exec("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), 1680);
+assertEquals(null, res[661].exec("a", 1681));
+assertEquals(null, res[661].exec("A ", 1682));
+assertEquals(null, res[662].exec("a", 1683));
+assertEquals(null, res[662].exec("A ", 1684));
+assertEquals(null, res[663].exec("A", 1685));
+assertEquals(null, res[663].exec("aZ", 1686));
+assertEquals(null, res[663].exec("** Failers", 1687));
+assertEquals(null, res[663].exec("abc   ", 1688));
+assertEquals(null, res[664].exec("A", 1689));
+assertEquals(null, res[664].exec("aZ", 1690));
+assertEquals(null, res[664].exec("** Failers", 1691));
+assertEquals(null, res[664].exec("abc   ", 1692));
+assertEquals(null, res[665].exec("a", 1693));
+assertEquals(null, res[665].exec("Az", 1694));
+assertEquals(null, res[665].exec("** Failers", 1695));
+assertEquals(null, res[665].exec("ABC   ", 1696));
+assertEquals(null, res[666].exec("a", 1697));
+assertEquals(null, res[666].exec("Az", 1698));
+assertEquals(null, res[666].exec("** Failers", 1699));
+assertEquals(null, res[666].exec("ABC   ", 1700));
+assertEquals(null, res[666].exec("x{c0}", 1701));
+assertEquals(null, res[666].exec("x{e0} ", 1702));
+assertEquals(null, res[666].exec("x{c0}", 1703));
+assertEquals(null, res[666].exec("x{e0} ", 1704));
+assertEquals(null, res[666].exec("Ax{391}x{10427}x{ff3a}x{1fb0}", 1705));
+assertEquals(null, res[666].exec("** Failers", 1706));
+assertEquals(null, res[666].exec("ax{391}x{10427}x{ff3a}x{1fb0}   ", 1707));
+assertEquals(null, res[666].exec("Ax{3b1}x{10427}x{ff3a}x{1fb0}", 1708));
+assertEquals(null, res[666].exec("Ax{391}x{1044F}x{ff3a}x{1fb0}", 1709));
+assertEquals(null, res[666].exec("Ax{391}x{10427}x{ff5a}x{1fb0}", 1710));
+assertEquals(null, res[666].exec("Ax{391}x{10427}x{ff3a}x{1fb8}", 1711));
+assertEquals(null, res[666].exec("Ax{391}x{10427}x{ff3a}x{1fb0}", 1712));
+assertEquals(null, res[666].exec("ax{391}x{10427}x{ff3a}x{1fb0}   ", 1713));
+assertEquals(null, res[666].exec("Ax{3b1}x{10427}x{ff3a}x{1fb0}", 1714));
+assertEquals(null, res[666].exec("Ax{391}x{1044F}x{ff3a}x{1fb0}", 1715));
+assertEquals(null, res[666].exec("Ax{391}x{10427}x{ff5a}x{1fb0}", 1716));
+assertEquals(null, res[666].exec("Ax{391}x{10427}x{ff3a}x{1fb8}", 1717));
+assertEquals(null, res[666].exec("x{391}x{3b1}x{3b1}x{3b1}x{391}", 1718));
+assertEquals(null, res[666].exec("x{391}x{3b1}x{3b1}x{3b1}x{391}X", 1719));
+assertEquals(null, res[666].exec("x{391}x{3b1}x{3b1}x{3b1}x{391}X", 1720));
+assertEquals(null, res[666].exec("x{391}", 1721));
+assertEquals(null, res[666].exec("x{ff3a}", 1722));
+assertEquals(null, res[666].exec("x{3b1}", 1723));
+assertEquals(null, res[666].exec("x{ff5a}   ", 1724));
+assertEquals(null, res[666].exec("x{c0}", 1725));
+assertEquals(null, res[666].exec("x{e0} ", 1726));
+assertEquals(null, res[666].exec("x{104}", 1727));
+assertEquals(null, res[666].exec("x{105}", 1728));
+assertEquals(null, res[666].exec("x{109}  ", 1729));
+assertEquals(null, res[666].exec("** Failers", 1730));
+assertEquals(null, res[666].exec("x{100}", 1731));
+assertEquals(null, res[666].exec("x{10a} ", 1732));
+assertEquals(null, res[666].exec("Z", 1733));
+assertEquals(null, res[666].exec("z", 1734));
+assertEquals(null, res[666].exec("x{39c}", 1735));
+assertEquals(null, res[666].exec("x{178}", 1736));
+assertEquals(null, res[666].exec("|", 1737));
+assertEquals(null, res[666].exec("x{80}", 1738));
+assertEquals(null, res[666].exec("x{ff}", 1739));
+assertEquals(null, res[666].exec("x{100}", 1740));
+assertEquals(null, res[666].exec("x{101} ", 1741));
+assertEquals(null, res[666].exec("** Failers", 1742));
+assertEquals(null, res[666].exec("x{102}", 1743));
+assertEquals(null, res[666].exec("Y", 1744));
+assertEquals(null, res[666].exec("y           ", 1745));
+assertEquals(null, res[667].exec("A", 1746));
+assertEquals(null, res[667].exec("Ax{300}BC ", 1747));
+assertEquals(null, res[667].exec("Ax{300}x{301}x{302}BC ", 1748));
+assertEquals(null, res[667].exec("*** Failers", 1749));
+assertEquals(null, res[667].exec("x{300}  ", 1750));
+assertEquals("X", res[668].exec("X123"), 1751);
+assertEquals(null, res[668].exec("*** Failers", 1752));
+assertEquals(null, res[668].exec("AXYZ", 1753));
+assertEquals(null, res[669].exec("Ax{300}x{301}x{302}BCAx{300}x{301} ", 1754));
+assertEquals(null, res[669].exec("Ax{300}x{301}x{302}BCAx{300}x{301}C ", 1755));
+assertEquals(null, res[670].exec("Ax{300}x{301}x{302}BCAx{300}x{301} ", 1756));
+assertEquals(null, res[670].exec("Ax{300}x{301}x{302}BCAx{300}x{301}C ", 1757));
+assertEquals("A,,A", res[671].exec("Ax{300}x{301}x{302}BCAx{300}x{301} "), 1758);
+assertEquals("A,,A", res[671].exec("Ax{300}x{301}x{302}BCAx{300}x{301}C "), 1759);
+assertEquals("A,,A", res[672].exec("Ax{300}x{301}x{302}BCAx{300}x{301} "), 1760);
+assertEquals("A,,A", res[672].exec("Ax{300}x{301}x{302}BCAx{300}x{301}C "), 1761);
+assertEquals(null, res[673].exec("*** Failers", 1762));
+assertEquals(null, res[673].exec("Ax{300}x{301}x{302}", 1763));
+assertEquals(null, res[674].exec("Ax{300}x{301}Bx{300}X", 1764));
+assertEquals(null, res[674].exec("Ax{300}x{301}Bx{300}Cx{300}x{301}", 1765));
+assertEquals(null, res[674].exec("Ax{300}x{301}Bx{300}Cx{300}x{301}X", 1766));
+assertEquals(null, res[674].exec("Ax{300}x{301}Bx{300}Cx{300}x{301}DAx{300}X", 1767));
+assertEquals(null, res[675].exec("Ax{300}x{301}Bx{300}X", 1768));
+assertEquals(null, res[675].exec("Ax{300}x{301}Bx{300}Cx{300}x{301}", 1769));
+assertEquals(null, res[675].exec("Ax{300}x{301}Bx{300}Cx{300}x{301}X", 1770));
+assertEquals(null, res[675].exec("Ax{300}x{301}Bx{300}Cx{300}x{301}DAx{300}X", 1771));
+assertEquals(null, res[675].exec("x{2e81}x{3007}x{2f804}x{31a0}", 1772));
+assertEquals(null, res[675].exec("** Failers", 1773));
+assertEquals(null, res[675].exec("x{2e7f}  ", 1774));
+assertEquals(null, res[675].exec("x{3105}", 1775));
+assertEquals(null, res[675].exec("** Failers", 1776));
+assertEquals(null, res[675].exec("x{30ff}  ", 1777));
+assertEquals(null, res[676].exec("x{06e9}", 1778));
+assertEquals(null, res[676].exec("x{060b}", 1779));
+assertEquals(null, res[676].exec("** Failers", 1780));
+assertEquals(null, res[676].exec("Xx{06e9}   ", 1781));
+assertEquals(null, res[677].exec("x{2f800}", 1782));
+assertEquals(null, res[677].exec("** Failers", 1783));
+assertEquals(null, res[677].exec("x{a014}", 1784));
+assertEquals(null, res[677].exec("x{a4c6}   ", 1785));
+assertEquals(null, res[678].exec("AXYZ", 1786));
+assertEquals(null, res[678].exec("x{1234}XYZ ", 1787));
+assertEquals(null, res[678].exec("** Failers", 1788));
+assertEquals(null, res[678].exec("X  ", 1789));
+assertEquals(null, res[679].exec("** Failers", 1790));
+assertEquals(null, res[679].exec("AX", 1791));
+assertEquals(null, res[680].exec("XYZ", 1792));
+assertEquals(null, res[680].exec("AXYZ", 1793));
+assertEquals(null, res[680].exec("x{1234}XYZ ", 1794));
+assertEquals(null, res[680].exec("** Failers", 1795));
+assertEquals(null, res[680].exec("ABXYZ   ", 1796));
+assertEquals(null, res[681].exec("XYZ", 1797));
+assertEquals(null, res[681].exec("** Failers", 1798));
+assertEquals(null, res[681].exec("AXYZ", 1799));
+assertEquals(null, res[681].exec("x{1234}XYZ ", 1800));
+assertEquals(null, res[681].exec("ABXYZ   ", 1801));
+assertEquals(null, res[681].exec("AXYZ", 1802));
+assertEquals(null, res[681].exec("x{1234}XYZ", 1803));
+assertEquals(null, res[681].exec("Ax{1234}XYZ", 1804));
+assertEquals(null, res[681].exec("** Failers", 1805));
+assertEquals(null, res[681].exec("XYZ", 1806));
+assertEquals(null, res[681].exec("** Failers", 1807));
+assertEquals(null, res[681].exec("AXYZ", 1808));
+assertEquals(null, res[681].exec("x{1234}XYZ", 1809));
+assertEquals(null, res[681].exec("Ax{1234}XYZ", 1810));
+assertEquals(null, res[681].exec("XYZ", 1811));
+assertEquals(null, res[682].exec("XYZ", 1812));
+assertEquals(null, res[682].exec("AXYZ", 1813));
+assertEquals(null, res[682].exec("x{1234}XYZ", 1814));
+assertEquals(null, res[682].exec("Ax{1234}XYZ", 1815));
+assertEquals(null, res[682].exec("** Failers", 1816));
+assertEquals(null, res[683].exec("XYZ", 1817));
+assertEquals(null, res[683].exec("** Failers", 1818));
+assertEquals(null, res[683].exec("AXYZ", 1819));
+assertEquals(null, res[683].exec("x{1234}XYZ", 1820));
+assertEquals(null, res[683].exec("Ax{1234}XYZ", 1821));
+assertEquals("AX", res[684].exec("AXYZ"), 1822);
+assertEquals(null, res[684].exec("x{1234}XYZ ", 1823));
+assertEquals(null, res[684].exec("** Failers", 1824));
+assertEquals(null, res[684].exec("X  ", 1825));
+assertEquals(null, res[685].exec("** Failers", 1826));
+assertEquals("AX", res[685].exec("AX"), 1827);
+assertEquals("X", res[686].exec("XYZ"), 1828);
+assertEquals("AX", res[686].exec("AXYZ"), 1829);
+assertEquals(null, res[686].exec("x{1234}XYZ ", 1830));
+assertEquals(null, res[686].exec("** Failers", 1831));
+assertEquals(null, res[686].exec("ABXYZ   ", 1832));
+assertEquals("X", res[687].exec("XYZ"), 1833);
+assertEquals(null, res[687].exec("** Failers", 1834));
+assertEquals("AX", res[687].exec("AXYZ"), 1835);
+assertEquals(null, res[687].exec("x{1234}XYZ ", 1836));
+assertEquals(null, res[687].exec("ABXYZ   ", 1837));
+assertEquals("AX", res[688].exec("AXYZ"), 1838);
+assertEquals(null, res[688].exec("x{1234}XYZ", 1839));
+assertEquals(null, res[688].exec("Ax{1234}XYZ", 1840));
+assertEquals(null, res[688].exec("** Failers", 1841));
+assertEquals(null, res[688].exec("XYZ", 1842));
+assertEquals(null, res[689].exec("** Failers", 1843));
+assertEquals("AX", res[689].exec("AXYZ"), 1844);
+assertEquals(null, res[689].exec("x{1234}XYZ", 1845));
+assertEquals(null, res[689].exec("Ax{1234}XYZ", 1846));
+assertEquals(null, res[689].exec("XYZ", 1847));
+assertEquals("X", res[690].exec("XYZ"), 1848);
+assertEquals("AX", res[690].exec("AXYZ"), 1849);
+assertEquals(null, res[690].exec("x{1234}XYZ", 1850));
+assertEquals(null, res[690].exec("Ax{1234}XYZ", 1851));
+assertEquals(null, res[690].exec("** Failers", 1852));
+assertEquals("X", res[691].exec("XYZ"), 1853);
+assertEquals(null, res[691].exec("** Failers", 1854));
+assertEquals("AX", res[691].exec("AXYZ"), 1855);
+assertEquals(null, res[691].exec("x{1234}XYZ", 1856));
+assertEquals(null, res[691].exec("Ax{1234}XYZ", 1857));
+assertEquals(null, res[692].exec("abcdefgh", 1858));
+assertEquals(null, res[692].exec("x{1234}\n\x0dx{3456}xyz ", 1859));
+assertEquals(null, res[693].exec("abcdefgh", 1860));
+assertEquals(null, res[693].exec("x{1234}\n\x0dx{3456}xyz ", 1861));
+assertEquals(null, res[694].exec("** Failers", 1862));
+assertEquals(null, res[694].exec("abcdefgh", 1863));
+assertEquals(null, res[694].exec("x{1234}\n\x0dx{3456}xyz ", 1864));
+assertEquals(null, res[695].exec(" AXY", 1865));
+assertEquals(null, res[695].exec(" aXY", 1866));
+assertEquals(null, res[695].exec(" x{1c5}XY", 1867));
+assertEquals(null, res[695].exec(" ** Failers", 1868));
+assertEquals(null, res[695].exec(" x{1bb}XY", 1869));
+assertEquals(null, res[695].exec(" x{2b0}XY", 1870));
+assertEquals(null, res[695].exec(" !XY      ", 1871));
+assertEquals(null, res[696].exec(" AXY", 1872));
+assertEquals(null, res[696].exec(" aXY", 1873));
+assertEquals(null, res[696].exec(" x{1c5}XY", 1874));
+assertEquals(null, res[696].exec(" ** Failers", 1875));
+assertEquals(null, res[696].exec(" x{1bb}XY", 1876));
+assertEquals(null, res[696].exec(" x{2b0}XY", 1877));
+assertEquals(null, res[696].exec(" !XY      ", 1878));
+assertEquals(null, res[696].exec(" AXY", 1879));
+assertEquals(null, res[696].exec(" aXY", 1880));
+assertEquals(null, res[696].exec(" AbcdeXyz ", 1881));
+assertEquals(null, res[696].exec(" x{1c5}AbXY", 1882));
+assertEquals(null, res[696].exec(" abcDEXypqreXlmn ", 1883));
+assertEquals(null, res[696].exec(" ** Failers", 1884));
+assertEquals(null, res[696].exec(" x{1bb}XY", 1885));
+assertEquals(null, res[696].exec(" x{2b0}XY", 1886));
+assertEquals(null, res[696].exec(" !XY      ", 1887));
+assertEquals(null, res[697].exec(" AXY", 1888));
+assertEquals(null, res[697].exec(" aXY", 1889));
+assertEquals(null, res[697].exec(" AbcdeXyz ", 1890));
+assertEquals(null, res[697].exec(" x{1c5}AbXY", 1891));
+assertEquals(null, res[697].exec(" abcDEXypqreXlmn ", 1892));
+assertEquals(null, res[697].exec(" ** Failers", 1893));
+assertEquals(null, res[697].exec(" x{1bb}XY", 1894));
+assertEquals(null, res[697].exec(" x{2b0}XY", 1895));
+assertEquals(null, res[697].exec(" !XY      ", 1896));
+assertEquals(null, res[697].exec(" AXY", 1897));
+assertEquals(null, res[697].exec(" aXY", 1898));
+assertEquals(null, res[697].exec(" AbcdeXyz ", 1899));
+assertEquals(null, res[697].exec(" x{1c5}AbXY", 1900));
+assertEquals(null, res[697].exec(" abcDEXypqreXlmn ", 1901));
+assertEquals(null, res[697].exec(" ** Failers", 1902));
+assertEquals(null, res[697].exec(" x{1bb}XY", 1903));
+assertEquals(null, res[697].exec(" x{2b0}XY", 1904));
+assertEquals(null, res[697].exec(" !XY      ", 1905));
+assertEquals(null, res[698].exec(" AXY", 1906));
+assertEquals(null, res[698].exec(" aXY", 1907));
+assertEquals(null, res[698].exec(" AbcdeXyz ", 1908));
+assertEquals(null, res[698].exec(" x{1c5}AbXY", 1909));
+assertEquals(null, res[698].exec(" abcDEXypqreXlmn ", 1910));
+assertEquals(null, res[698].exec(" ** Failers", 1911));
+assertEquals(null, res[698].exec(" x{1bb}XY", 1912));
+assertEquals(null, res[698].exec(" x{2b0}XY", 1913));
+assertEquals(null, res[698].exec(" !XY      ", 1914));
+assertEquals(null, res[699].exec(" !XY", 1915));
+assertEquals(null, res[699].exec(" x{1bb}XY", 1916));
+assertEquals(null, res[699].exec(" x{2b0}XY", 1917));
+assertEquals(null, res[699].exec(" ** Failers", 1918));
+assertEquals(null, res[699].exec(" x{1c5}XY", 1919));
+assertEquals(null, res[699].exec(" AXY      ", 1920));
+assertEquals(null, res[700].exec(" !XY", 1921));
+assertEquals(null, res[700].exec(" x{1bb}XY", 1922));
+assertEquals(null, res[700].exec(" x{2b0}XY", 1923));
+assertEquals(null, res[700].exec(" ** Failers", 1924));
+assertEquals(null, res[700].exec(" x{1c5}XY", 1925));
+assertEquals(null, res[700].exec(" AXY      ", 1926));
+assertEquals(null, res[701].exec("\xa0!", 1927));
+assertEquals(null, res[701].exec("AabcabcYZ    ", 1928));
+assertEquals("L=abcX,L=abc,abc", res[702].exec("L=abcX"), 1929);
+assertEquals(null, res[702].exec("x{c0}", 1930));
+assertEquals(null, res[702].exec("x{e0} ", 1931));
+assertEquals(null, res[702].exec("x{c0}", 1932));
+assertEquals(null, res[702].exec("x{e0} ", 1933));
+assertEquals(null, res[703].exec("x{1b00}x{12000}x{7c0}x{a840}x{10900}", 1934));
+assertEquals(null, res[706].exec("123abcdefg", 1935));
+assertEquals(null, res[706].exec("123abc\xc4\xc5zz", 1936));
+assertEquals(null, res[710].exec("A\x80", 1937));
+assertEquals(null, res[725].exec("x{60e} ", 1938));
+assertEquals(null, res[725].exec("x{656} ", 1939));
+assertEquals(null, res[725].exec("x{657} ", 1940));
+assertEquals(null, res[725].exec("x{658} ", 1941));
+assertEquals(null, res[725].exec("x{659} ", 1942));
+assertEquals(null, res[725].exec("x{65a} ", 1943));
+assertEquals(null, res[725].exec("x{65b} ", 1944));
+assertEquals(null, res[725].exec("x{65c} ", 1945));
+assertEquals(null, res[725].exec("x{65d} ", 1946));
+assertEquals(null, res[725].exec("x{65e} ", 1947));
+assertEquals(null, res[725].exec("x{66a} ", 1948));
+assertEquals(null, res[725].exec("x{6e9} ", 1949));
+assertEquals(null, res[725].exec("x{6ef}", 1950));
+assertEquals(null, res[725].exec("x{6fa}  ", 1951));
+assertEquals(null, res[725].exec("** Failers", 1952));
+assertEquals(null, res[725].exec("x{600}", 1953));
+assertEquals(null, res[725].exec("x{650}", 1954));
+assertEquals(null, res[725].exec("x{651}  ", 1955));
+assertEquals(null, res[725].exec("x{652}  ", 1956));
+assertEquals(null, res[725].exec("x{653}  ", 1957));
+assertEquals(null, res[725].exec("x{654} ", 1958));
+assertEquals(null, res[725].exec("x{655} ", 1959));
+assertEquals(null, res[725].exec("x{65f}  ", 1960));
+assertEquals(null, res[726].exec("x{1d2b} ", 1961));
+assertEquals(null, res[727].exec("x{589}", 1962));
+assertEquals(null, res[727].exec("x{60c}", 1963));
+assertEquals(null, res[727].exec("x{61f}  ", 1964));
+assertEquals(null, res[727].exec("x{964}", 1965));
+assertEquals(null, res[727].exec("x{965}  ", 1966));
+assertEquals(null, res[727].exec("x{970}  ", 1967));
+assertEquals(null, res[728].exec("x{64b}", 1968));
+assertEquals(null, res[728].exec("x{654}", 1969));
+assertEquals(null, res[728].exec("x{655}", 1970));
+assertEquals(null, res[728].exec("x{200c} ", 1971));
+assertEquals(null, res[728].exec("** Failers", 1972));
+assertEquals(null, res[728].exec("x{64a}", 1973));
+assertEquals(null, res[728].exec("x{656}     ", 1974));
+assertEquals(null, res[729].exec("x{10450}", 1975));
+assertEquals(null, res[729].exec("x{1047f}", 1976));
+assertEquals(null, res[730].exec("x{10400}", 1977));
+assertEquals(null, res[730].exec("x{1044f}", 1978));
+assertEquals(null, res[731].exec("x{10480}", 1979));
+assertEquals(null, res[731].exec("x{1049d}", 1980));
+assertEquals(null, res[731].exec("x{104a0}", 1981));
+assertEquals(null, res[731].exec("x{104a9}", 1982));
+assertEquals(null, res[731].exec("** Failers", 1983));
+assertEquals(null, res[731].exec("x{1049e}", 1984));
+assertEquals(null, res[731].exec("x{1049f}", 1985));
+assertEquals(null, res[731].exec("x{104aa}           ", 1986));
+assertEquals(null, res[731].exec("\xe2\x80\xa8\xe2\x80\xa8", 1987));
+assertEquals(null, res[731].exec("x{2028}x{2028}x{2028}", 1988));
+assertEquals(null, res[732].exec("x{c0}x{e0}x{116}x{117}", 1989));
+assertEquals(null, res[732].exec("x{c0}x{e0}x{116}x{117}", 1990));
+assertEquals(null, res[733].exec("x{102A4}x{AA52}x{A91D}x{1C46}x{10283}x{1092E}x{1C6B}x{A93B}x{A8BF}x{1BA0}x{A50A}====", 1991));
+assertEquals(null, res[733].exec("x{a77d}x{1d79}", 1992));
+assertEquals(null, res[733].exec("x{1d79}x{a77d} ", 1993));
+assertEquals(null, res[733].exec("x{a77d}x{1d79}", 1994));
+assertEquals(null, res[733].exec("** Failers ", 1995));
+assertEquals(null, res[733].exec("x{1d79}x{a77d} ", 1996));
+assertEquals("AA,A", res[734].exec("AA"), 1997);
+assertEquals("Aa,A", res[734].exec("Aa"), 1998);
+assertEquals("aa,a", res[734].exec("aa"), 1999);
+assertEquals("aA,a", res[734].exec("aA"), 2000);
+assertEquals(null, res[734].exec("x{de}x{de}", 2001));
+assertEquals(null, res[734].exec("x{de}x{fe}", 2002));
+assertEquals(null, res[734].exec("x{fe}x{fe}", 2003));
+assertEquals(null, res[734].exec("x{fe}x{de}", 2004));
+assertEquals(null, res[734].exec("x{10a}x{10a}", 2005));
+assertEquals(null, res[734].exec("x{10a}x{10b}", 2006));
+assertEquals(null, res[734].exec("x{10b}x{10b}", 2007));
+assertEquals(null, res[734].exec("x{10b}x{10a}", 2008));
+assertEquals("abc", res[736].exec("abc"), 2009);
+assertEquals("abc", res[737].exec("abc"), 2010);
+assertEquals("abbbbc", res[737].exec("abbbbc"), 2011);
+assertEquals("ac", res[737].exec("ac"), 2012);
+assertEquals("abc", res[738].exec("abc"), 2013);
+assertEquals("abbbbbbc", res[738].exec("abbbbbbc"), 2014);
+assertEquals(null, res[738].exec("*** Failers ", 2015));
+assertEquals(null, res[738].exec("ac", 2016));
+assertEquals(null, res[738].exec("ab", 2017));
+assertEquals("a", res[739].exec("a"), 2018);
+assertEquals("aaaaaaaaaaaaaaaaa", res[739].exec("aaaaaaaaaaaaaaaaa"), 2019);
+assertEquals("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", res[739].exec("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa "), 2020);
+assertEquals("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", res[739].exec("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaF "), 2021);
+assertEquals("a,a", res[740].exec("a"), 2022);
+assertEquals("a,a", res[740].exec("abcd"), 2023);
+assertEquals("a,a", res[740].exec("african"), 2024);
+assertEquals("abc", res[741].exec("abcdef"), 2025);
+assertEquals(null, res[741].exec("*** Failers", 2026));
+assertEquals(null, res[741].exec("xyzabc", 2027));
+assertEquals(null, res[741].exec("xyz\nabc    ", 2028));
+assertEquals("abc", res[742].exec("abcdef"), 2029);
+assertEquals("abc", res[742].exec("xyz\nabc    "), 2030);
+assertEquals(null, res[742].exec("*** Failers", 2031));
+assertEquals(null, res[742].exec("xyzabc", 2032));
+assertEquals(null, res[743].exec("abcdef", 2033));
+assertEquals(null, res[743].exec("*** Failers", 2034));
+assertEquals(null, res[743].exec("xyzabc", 2035));
+assertEquals(null, res[743].exec("xyz\nabc    ", 2036));
+assertEquals(null, res[744].exec("abcdef", 2037));
+assertEquals(null, res[744].exec("*** Failers", 2038));
+assertEquals(null, res[744].exec("xyzabc", 2039));
+assertEquals(null, res[744].exec("xyz\nabc    ", 2040));
+assertEquals(null, res[745].exec("abcdef", 2041));
+assertEquals(null, res[745].exec("xyzabc>3", 2042));
+assertEquals(null, res[745].exec("*** Failers", 2043));
+assertEquals(null, res[745].exec("xyzabc    ", 2044));
+assertEquals(null, res[745].exec("xyzabc>2 ", 2045));
+assertEquals("x9yzz", res[746].exec("x9yzz"), 2046);
+assertEquals("x0y+z", res[746].exec("x0y+z"), 2047);
+assertEquals(null, res[746].exec("*** Failers", 2048));
+assertEquals(null, res[746].exec("xyz", 2049));
+assertEquals(null, res[746].exec("xxy0z     ", 2050));
+assertEquals("x yzz", res[747].exec("x yzz"), 2051);
+assertEquals("x y+z", res[747].exec("x y+z"), 2052);
+assertEquals(null, res[747].exec("*** Failers", 2053));
+assertEquals(null, res[747].exec("xyz", 2054));
+assertEquals(null, res[747].exec("xxyyz", 2055));
+assertEquals("xxy+z", res[748].exec("xxy+z"), 2056);
+assertEquals(null, res[748].exec("*** Failers", 2057));
+assertEquals(null, res[748].exec("xxy0z", 2058));
+assertEquals(null, res[748].exec("x+y+z         ", 2059));
+assertEquals("x+y", res[749].exec("x+y"), 2060);
+assertEquals("x-y", res[749].exec("x-y"), 2061);
+assertEquals(null, res[749].exec("*** Failers", 2062));
+assertEquals(null, res[749].exec("x\ny", 2063));
+assertEquals("x+y", res[750].exec("x+y"), 2064);
+assertEquals("x-y", res[750].exec("x-y"), 2065);
+assertEquals(null, res[750].exec("x\ny", 2066));
+assertEquals(null, res[750].exec("a+bc+dp+q", 2067));
+assertEquals(null, res[750].exec("a+bc\ndp+q", 2068));
+assertEquals(null, res[750].exec("x\nyp+q ", 2069));
+assertEquals(null, res[750].exec("*** Failers ", 2070));
+assertEquals(null, res[750].exec("a\nbc\ndp+q", 2071));
+assertEquals(null, res[750].exec("a+bc\ndp\nq", 2072));
+assertEquals(null, res[750].exec("x\nyp\nq ", 2073));
+assertEquals(null, res[751].exec("ba0", 2074));
+assertEquals(null, res[751].exec("*** Failers", 2075));
+assertEquals(null, res[751].exec("ba0\n", 2076));
+assertEquals(null, res[751].exec("ba0\ncd   ", 2077));
+assertEquals(null, res[752].exec("ba0", 2078));
+assertEquals(null, res[752].exec("*** Failers", 2079));
+assertEquals(null, res[752].exec("ba0\n", 2080));
+assertEquals(null, res[752].exec("ba0\ncd   ", 2081));
+assertEquals(null, res[753].exec("ba0", 2082));
+assertEquals(null, res[753].exec("ba0\n", 2083));
+assertEquals(null, res[753].exec("*** Failers", 2084));
+assertEquals(null, res[753].exec("ba0\ncd   ", 2085));
+assertEquals(null, res[754].exec("ba0", 2086));
+assertEquals(null, res[754].exec("ba0\n", 2087));
+assertEquals(null, res[754].exec("*** Failers", 2088));
+assertEquals(null, res[754].exec("ba0\ncd   ", 2089));
+assertEquals("a0", res[755].exec("ba0"), 2090);
+assertEquals(null, res[755].exec("ba0\n", 2091));
+assertEquals(null, res[755].exec("*** Failers", 2092));
+assertEquals(null, res[755].exec("ba0\ncd   ", 2093));
+assertEquals("a0", res[756].exec("ba0"), 2094);
+assertEquals("a0", res[756].exec("ba0\n"), 2095);
+assertEquals("a0", res[756].exec("ba0\ncd   "), 2096);
+assertEquals(null, res[756].exec("*** Failers", 2097));
+assertEquals("abc", res[757].exec("abc"), 2098);
+assertEquals("aBc", res[757].exec("aBc"), 2099);
+assertEquals("ABC", res[757].exec("ABC"), 2100);
+assertEquals("b", res[758].exec("abcd"), 2101);
+assertEquals("abz", res[759].exec("abz"), 2102);
+assertEquals("abb", res[759].exec("abbz"), 2103);
+assertEquals("az", res[759].exec("azz  "), 2104);
+assertEquals("yz", res[760].exec("ayzq"), 2105);
+assertEquals("xyz", res[760].exec("axyzq"), 2106);
+assertEquals("xxyz", res[760].exec("axxyz"), 2107);
+assertEquals("xxxyz", res[760].exec("axxxyzq"), 2108);
+assertEquals("xxxyz", res[760].exec("axxxxyzq"), 2109);
+assertEquals(null, res[760].exec("*** Failers", 2110));
+assertEquals(null, res[760].exec("ax", 2111));
+assertEquals(null, res[760].exec("axx     ", 2112));
+assertEquals(null, res[760].exec("  ", 2113));
+assertEquals("xxxyz", res[761].exec("axxxyzq"), 2114);
+assertEquals("xxxyz", res[761].exec("axxxxyzq"), 2115);
+assertEquals(null, res[761].exec("*** Failers", 2116));
+assertEquals(null, res[761].exec("ax", 2117));
+assertEquals(null, res[761].exec("axx     ", 2118));
+assertEquals(null, res[761].exec("ayzq", 2119));
+assertEquals(null, res[761].exec("axyzq", 2120));
+assertEquals(null, res[761].exec("axxyz", 2121));
+assertEquals(null, res[761].exec("  ", 2122));
+assertEquals("xxyz", res[762].exec("axxyz"), 2123);
+assertEquals("xxxyz", res[762].exec("axxxyzq"), 2124);
+assertEquals("xxxyz", res[762].exec("axxxxyzq"), 2125);
+assertEquals(null, res[762].exec("*** Failers", 2126));
+assertEquals(null, res[762].exec("ax", 2127));
+assertEquals(null, res[762].exec("axx     ", 2128));
+assertEquals(null, res[762].exec("ayzq", 2129));
+assertEquals(null, res[762].exec("axyzq", 2130));
+assertEquals(null, res[762].exec("  ", 2131));
+assertEquals("b", res[763].exec("bac"), 2132);
+assertEquals("bcdef", res[763].exec("bcdefax"), 2133);
+assertEquals("*** F", res[763].exec("*** Failers"), 2134);
+assertEquals("   ", res[763].exec("aaaaa   "), 2135);
+assertEquals("b", res[764].exec("bac"), 2136);
+assertEquals("bcdef", res[764].exec("bcdefax"), 2137);
+assertEquals("*** F", res[764].exec("*** Failers"), 2138);
+assertEquals("", res[764].exec("aaaaa   "), 2139);
+assertEquals("xyz", res[765].exec("xyz"), 2140);
+assertEquals("wxyz", res[765].exec("awxyza"), 2141);
+assertEquals("bcdef", res[765].exec("abcdefa"), 2142);
+assertEquals("bcdef", res[765].exec("abcdefghijk"), 2143);
+assertEquals("*** F", res[765].exec("*** Failers"), 2144);
+assertEquals(null, res[765].exec("axya", 2145));
+assertEquals(null, res[765].exec("axa", 2146));
+assertEquals("     ", res[765].exec("aaaaa         "), 2147);
+assertEquals("1234", res[766].exec("1234b567"), 2148);
+assertEquals("", res[766].exec("xyz"), 2149);
+assertEquals("a", res[767].exec("a1234b567"), 2150);
+assertEquals("xyz", res[767].exec("xyz"), 2151);
+assertEquals(" ", res[767].exec(" "), 2152);
+assertEquals("1234", res[768].exec("ab1234c56"), 2153);
+assertEquals(null, res[768].exec("*** Failers", 2154));
+assertEquals(null, res[768].exec("xyz", 2155));
+assertEquals("ab", res[769].exec("ab123c56"), 2156);
+assertEquals("*** Failers", res[769].exec("*** Failers"), 2157);
+assertEquals(null, res[769].exec("789", 2158));
+assertEquals("5A", res[770].exec("045ABC"), 2159);
+assertEquals("A", res[770].exec("ABC"), 2160);
+assertEquals(null, res[770].exec("*** Failers", 2161));
+assertEquals(null, res[770].exec("XYZ", 2162));
+assertEquals("A", res[771].exec("ABC"), 2163);
+assertEquals("BA", res[771].exec("BAC"), 2164);
+assertEquals("A", res[771].exec("9ABC             "), 2165);
+assertEquals(null, res[771].exec("*** Failers", 2166));
+assertEquals("aaaa", res[772].exec("aaaa"), 2167);
+assertEquals("xyz", res[773].exec("xyz"), 2168);
+assertEquals("ggggggggxyz", res[773].exec("ggggggggxyz"), 2169);
+assertEquals("abcdxyz", res[774].exec("abcdxyz"), 2170);
+assertEquals("axyz", res[774].exec("axyz"), 2171);
+assertEquals(null, res[774].exec("*** Failers", 2172));
+assertEquals(null, res[774].exec("xyz", 2173));
+assertEquals("xyz", res[775].exec("xyz"), 2174);
+assertEquals("cxyz", res[775].exec("cxyz       "), 2175);
+assertEquals("12X", res[776].exec("12X"), 2176);
+assertEquals("123X", res[776].exec("123X"), 2177);
+assertEquals(null, res[776].exec("*** Failers", 2178));
+assertEquals(null, res[776].exec("X", 2179));
+assertEquals(null, res[776].exec("1X", 2180));
+assertEquals(null, res[776].exec("1234X     ", 2181));
+assertEquals("a4", res[777].exec("a45"), 2182);
+assertEquals("b9", res[777].exec("b93"), 2183);
+assertEquals("c9", res[777].exec("c99z"), 2184);
+assertEquals("d0", res[777].exec("d04"), 2185);
+assertEquals(null, res[777].exec("*** Failers", 2186));
+assertEquals(null, res[777].exec("e45", 2187));
+assertEquals(null, res[777].exec("abcd      ", 2188));
+assertEquals(null, res[777].exec("abcd1234", 2189));
+assertEquals(null, res[777].exec("1234  ", 2190));
+assertEquals("a4", res[778].exec("a45"), 2191);
+assertEquals("b9", res[778].exec("b93"), 2192);
+assertEquals("c9", res[778].exec("c99z"), 2193);
+assertEquals("d0", res[778].exec("d04"), 2194);
+assertEquals("abcd1", res[778].exec("abcd1234"), 2195);
+assertEquals("1", res[778].exec("1234  "), 2196);
+assertEquals(null, res[778].exec("*** Failers", 2197));
+assertEquals(null, res[778].exec("e45", 2198));
+assertEquals(null, res[778].exec("abcd      ", 2199));
+assertEquals("a4", res[779].exec("a45"), 2200);
+assertEquals("b9", res[779].exec("b93"), 2201);
+assertEquals("c9", res[779].exec("c99z"), 2202);
+assertEquals("d0", res[779].exec("d04"), 2203);
+assertEquals("abcd1", res[779].exec("abcd1234"), 2204);
+assertEquals(null, res[779].exec("*** Failers", 2205));
+assertEquals(null, res[779].exec("1234  ", 2206));
+assertEquals(null, res[779].exec("e45", 2207));
+assertEquals(null, res[779].exec("abcd      ", 2208));
+assertEquals("aX", res[780].exec("aX"), 2209);
+assertEquals("aaX", res[780].exec("aaX "), 2210);
+assertEquals("a4", res[781].exec("a45"), 2211);
+assertEquals("b9", res[781].exec("b93"), 2212);
+assertEquals("c9", res[781].exec("c99z"), 2213);
+assertEquals("d0", res[781].exec("d04"), 2214);
+assertEquals("1", res[781].exec("1234  "), 2215);
+assertEquals(null, res[781].exec("*** Failers", 2216));
+assertEquals(null, res[781].exec("abcd1234", 2217));
+assertEquals(null, res[781].exec("e45", 2218));
+assertEquals("ab4", res[782].exec("ab45"), 2219);
+assertEquals("bcd9", res[782].exec("bcd93"), 2220);
+assertEquals(null, res[782].exec("*** Failers", 2221));
+assertEquals(null, res[782].exec("1234 ", 2222));
+assertEquals(null, res[782].exec("a36 ", 2223));
+assertEquals(null, res[782].exec("abcd1234", 2224));
+assertEquals(null, res[782].exec("ee45", 2225));
+assertEquals("abc4,abc", res[783].exec("abc45"), 2226);
+assertEquals("abcabcabc4,abc", res[783].exec("abcabcabc45"), 2227);
+assertEquals("4,", res[783].exec("42xyz "), 2228);
+assertEquals(null, res[783].exec("*** Failers", 2229));
+assertEquals("abc4,abc", res[784].exec("abc45"), 2230);
+assertEquals("abcabcabc4,abc", res[784].exec("abcabcabc45"), 2231);
+assertEquals(null, res[784].exec("*** Failers", 2232));
+assertEquals(null, res[784].exec("42xyz ", 2233));
+assertEquals("abc4,abc", res[785].exec("abc45"), 2234);
+assertEquals("4,", res[785].exec("42xyz "), 2235);
+assertEquals(null, res[785].exec("*** Failers", 2236));
+assertEquals(null, res[785].exec("abcabcabc45", 2237));
+assertEquals("abcabc4,abc", res[786].exec("abcabc45"), 2238);
+assertEquals("abcabcabc4,abc", res[786].exec("abcabcabc45"), 2239);
+assertEquals(null, res[786].exec("*** Failers", 2240));
+assertEquals(null, res[786].exec("abcabcabcabc45", 2241));
+assertEquals(null, res[786].exec("abc45", 2242));
+assertEquals(null, res[786].exec("42xyz ", 2243));
+assertEquals(null, res[786].exec("1abc2abc3456", 2244));
+assertEquals(null, res[786].exec("1abc2xyz3456 ", 2245));
+assertEquals("ab=ab,ab,ab", res[787].exec("ab=ab"), 2246);
+assertEquals("ab=ab,ab,ab", res[787].exec("ab=ab"), 2247);
+assertEquals(null, res[787].exec("abc", 2248));
+assertEquals(null, res[787].exec("a(b)c", 2249));
+assertEquals(null, res[787].exec("a(b(c))d  ", 2250));
+assertEquals(null, res[787].exec("*** Failers)", 2251));
+assertEquals(null, res[787].exec("a(b(c)d  ", 2252));
+assertEquals(null, res[787].exec(">abc>123<xyz<", 2253));
+assertEquals(null, res[787].exec(">abc>1(2)3<xyz<", 2254));
+assertEquals(null, res[787].exec(">abc>(1(2)3)<xyz<", 2255));
+assertEquals(null, res[787].exec("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9876", 2256));
+assertEquals(null, res[787].exec("*** Failers ", 2257));
+assertEquals(null, res[787].exec("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 2258));
+assertEquals(null, res[787].exec("<>", 2259));
+assertEquals(null, res[787].exec("<abcd>", 2260));
+assertEquals(null, res[787].exec("<abc <123> hij>", 2261));
+assertEquals(null, res[787].exec("<abc <def> hij>", 2262));
+assertEquals(null, res[787].exec("<abc<>def> ", 2263));
+assertEquals(null, res[787].exec("<abc<>      ", 2264));
+assertEquals(null, res[787].exec("*** Failers", 2265));
+assertEquals(null, res[787].exec("<abc", 2266));
+assertEquals(null, res[787].exec("abc:                          ", 2267));
+assertEquals(null, res[787].exec("12                             ", 2268));
+assertEquals(null, res[787].exec("*** Failers                     ", 2269));
+assertEquals(null, res[787].exec("123                       ", 2270));
+assertEquals(null, res[787].exec("xyz                        ", 2271));
+assertEquals(null, res[787].exec("                            ", 2272));
+assertEquals(null, res[787].exec("abc:                        ", 2273));
+assertEquals(null, res[787].exec("12         ", 2274));
+assertEquals(null, res[787].exec("*** Failers", 2275));
+assertEquals(null, res[787].exec("123", 2276));
+assertEquals(null, res[787].exec("xyz    ", 2277));
+assertEquals(null, res[788].exec("abcde:                          ", 2278));
+assertEquals(null, res[788].exec("*** Failers                     ", 2279));
+assertEquals(null, res[788].exec("abc.. ", 2280));
+assertEquals(null, res[788].exec("123                       ", 2281));
+assertEquals(null, res[788].exec("vwxyz                        ", 2282));
+assertEquals(null, res[788].exec("                            ", 2283));
+assertEquals(null, res[789].exec("12         ", 2284));
+assertEquals(null, res[789].exec("*** Failers", 2285));
+assertEquals(null, res[789].exec("abcde:", 2286));
+assertEquals(null, res[789].exec("abc..  ", 2287));
+assertEquals(null, res[789].exec("123", 2288));
+assertEquals(null, res[789].exec("vwxyz    ", 2289));
+assertEquals(null, res[789].exec("abc12345", 2290));
+assertEquals(null, res[789].exec("wxy123z", 2291));
+assertEquals(null, res[789].exec("*** Failers", 2292));
+assertEquals(null, res[789].exec("123abc", 2293));
+assertEquals(null, res[789].exec("123abc", 2294));
+assertEquals(null, res[789].exec("mno123456 ", 2295));
+assertEquals(null, res[789].exec("*** Failers", 2296));
+assertEquals(null, res[789].exec("abc12345", 2297));
+assertEquals(null, res[789].exec("wxy123z", 2298));
+assertEquals(null, res[789].exec("abcxyz", 2299));
+assertEquals(null, res[789].exec("123abcxyz999 ", 2300));
+assertEquals("abc", res[791].exec("abcdef"), 2301);
+assertEquals(null, res[791].exec("*** Failers", 2302));
+assertEquals("abc", res[791].exec("abcdefB  "), 2303);
+assertEquals(",", res[792].exec("bcd"), 2304);
+assertEquals("aaa,aaa", res[792].exec("aaabcd"), 2305);
+assertEquals(",", res[792].exec("xyz"), 2306);
+assertEquals(",", res[792].exec("xyzN  "), 2307);
+assertEquals(",", res[792].exec("*** Failers"), 2308);
+assertEquals(",", res[792].exec("bcdN   "), 2309);
+assertEquals("xyz", res[793].exec("xyz"), 2310);
+assertEquals(null, res[793].exec("xyz\n", 2311));
+assertEquals(null, res[793].exec("*** Failers", 2312));
+assertEquals(null, res[793].exec("xyzZ", 2313));
+assertEquals(null, res[793].exec("xyz\nZ    ", 2314));
+assertEquals("xyz", res[794].exec("xyz"), 2315);
+assertEquals("xyz", res[794].exec("xyz\n "), 2316);
+assertEquals("xyz", res[794].exec("abcxyz\npqr "), 2317);
+assertEquals("xyz", res[794].exec("abcxyz\npqrZ "), 2318);
+assertEquals("xyz", res[794].exec("xyz\nZ    "), 2319);
+assertEquals(null, res[794].exec("*** Failers", 2320));
+assertEquals(null, res[794].exec("xyzZ", 2321));
+assertEquals(null, res[795].exec("abcdef", 2322));
+assertEquals(null, res[795].exec("defabcxyz>3 ", 2323));
+assertEquals(null, res[795].exec("*** Failers ", 2324));
+assertEquals(null, res[795].exec("defabcxyz", 2325));
+assertEquals(null, res[796].exec("abP", 2326));
+assertEquals(null, res[796].exec("abcdeP", 2327));
+assertEquals("abcdef", res[796].exec("abcdefP"), 2328);
+assertEquals(null, res[796].exec("*** Failers", 2329));
+assertEquals(null, res[796].exec("abxP    ", 2330));
+assertEquals(null, res[797].exec("aP", 2331));
+assertEquals(null, res[797].exec("aaP", 2332));
+assertEquals(null, res[797].exec("aa2P ", 2333));
+assertEquals(null, res[797].exec("aaaP", 2334));
+assertEquals(null, res[797].exec("aaa23P ", 2335));
+assertEquals(null, res[797].exec("aaaa12345P", 2336));
+assertEquals("aa0z", res[797].exec("aa0zP"), 2337);
+assertEquals("aaaa4444444444444z", res[797].exec("aaaa4444444444444zP "), 2338);
+assertEquals(null, res[797].exec("*** Failers", 2339));
+assertEquals(null, res[797].exec("azP ", 2340));
+assertEquals(null, res[797].exec("aaaaaP ", 2341));
+assertEquals(null, res[797].exec("a56P ", 2342));
+assertEquals(null, res[799].exec("adfadadaklhlkalkajhlkjahdfasdfasdfladsfjkjPZ", 2343));
+assertEquals(null, res[799].exec("lkjhlkjhlkjhlkjhabbbbbbcdaefabbbbbbbefaPBZ", 2344));
+assertEquals(null, res[799].exec("cdabbbbbbbbPRBZ", 2345));
+assertEquals(null, res[799].exec("efabbbbbbbbbbbbbbbbPRBZ", 2346));
+assertEquals(null, res[799].exec("bbbbbbbbbbbbcdXyasdfadfPRBZ    ", 2347));
+assertEquals(null, res[799].exec("abc", 2348));
+assertEquals(null, res[799].exec("** Failers", 2349));
+assertEquals(null, res[799].exec("def  ", 2350));
+assertEquals("the quick brown fox", res[800].exec("the quick brown fox"), 2351);
+assertEquals(null, res[800].exec("The quick brown FOX", 2352));
+assertEquals("the quick brown fox", res[800].exec("What do you know about the quick brown fox?"), 2353);
+assertEquals(null, res[800].exec("What do you know about THE QUICK BROWN FOX?", 2354));
+assertEquals("the quick brown fox", res[801].exec("the quick brown fox"), 2355);
+assertEquals("The quick brown FOX", res[801].exec("The quick brown FOX"), 2356);
+assertEquals("the quick brown fox", res[801].exec("What do you know about the quick brown fox?"), 2357);
+assertEquals("THE QUICK BROWN FOX", res[801].exec("What do you know about THE QUICK BROWN FOX?"), 2358);
+assertEquals("abcd\x09\n\x0d\x0cae9;$\\?caxyz", res[802].exec("abcd\x09\n\x0d\x0cae9;$\\?caxyz"), 2359);
+assertEquals("abxyzpqrrrabbxyyyypqAzz", res[803].exec("abxyzpqrrrabbxyyyypqAzz"), 2360);
+assertEquals("abxyzpqrrrabbxyyyypqAzz", res[803].exec("abxyzpqrrrabbxyyyypqAzz"), 2361);
+assertEquals("aabxyzpqrrrabbxyyyypqAzz", res[803].exec("aabxyzpqrrrabbxyyyypqAzz"), 2362);
+assertEquals("aaabxyzpqrrrabbxyyyypqAzz", res[803].exec("aaabxyzpqrrrabbxyyyypqAzz"), 2363);
+assertEquals("aaaabxyzpqrrrabbxyyyypqAzz", res[803].exec("aaaabxyzpqrrrabbxyyyypqAzz"), 2364);
+assertEquals("abcxyzpqrrrabbxyyyypqAzz", res[803].exec("abcxyzpqrrrabbxyyyypqAzz"), 2365);
+assertEquals("aabcxyzpqrrrabbxyyyypqAzz", res[803].exec("aabcxyzpqrrrabbxyyyypqAzz"), 2366);
+assertEquals("aaabcxyzpqrrrabbxyyyypAzz", res[803].exec("aaabcxyzpqrrrabbxyyyypAzz"), 2367);
+assertEquals("aaabcxyzpqrrrabbxyyyypqAzz", res[803].exec("aaabcxyzpqrrrabbxyyyypqAzz"), 2368);
+assertEquals("aaabcxyzpqrrrabbxyyyypqqAzz", res[803].exec("aaabcxyzpqrrrabbxyyyypqqAzz"), 2369);
+assertEquals("aaabcxyzpqrrrabbxyyyypqqqAzz", res[803].exec("aaabcxyzpqrrrabbxyyyypqqqAzz"), 2370);
+assertEquals("aaabcxyzpqrrrabbxyyyypqqqqAzz", res[803].exec("aaabcxyzpqrrrabbxyyyypqqqqAzz"), 2371);
+assertEquals("aaabcxyzpqrrrabbxyyyypqqqqqAzz", res[803].exec("aaabcxyzpqrrrabbxyyyypqqqqqAzz"), 2372);
+assertEquals("aaabcxyzpqrrrabbxyyyypqqqqqqAzz", res[803].exec("aaabcxyzpqrrrabbxyyyypqqqqqqAzz"), 2373);
+assertEquals("aaaabcxyzpqrrrabbxyyyypqAzz", res[803].exec("aaaabcxyzpqrrrabbxyyyypqAzz"), 2374);
+assertEquals("abxyzzpqrrrabbxyyyypqAzz", res[803].exec("abxyzzpqrrrabbxyyyypqAzz"), 2375);
+assertEquals("aabxyzzzpqrrrabbxyyyypqAzz", res[803].exec("aabxyzzzpqrrrabbxyyyypqAzz"), 2376);
+assertEquals("aaabxyzzzzpqrrrabbxyyyypqAzz", res[803].exec("aaabxyzzzzpqrrrabbxyyyypqAzz"), 2377);
+assertEquals("aaaabxyzzzzpqrrrabbxyyyypqAzz", res[803].exec("aaaabxyzzzzpqrrrabbxyyyypqAzz"), 2378);
+assertEquals("abcxyzzpqrrrabbxyyyypqAzz", res[803].exec("abcxyzzpqrrrabbxyyyypqAzz"), 2379);
+assertEquals("aabcxyzzzpqrrrabbxyyyypqAzz", res[803].exec("aabcxyzzzpqrrrabbxyyyypqAzz"), 2380);
+assertEquals("aaabcxyzzzzpqrrrabbxyyyypqAzz", res[803].exec("aaabcxyzzzzpqrrrabbxyyyypqAzz"), 2381);
+assertEquals("aaaabcxyzzzzpqrrrabbxyyyypqAzz", res[803].exec("aaaabcxyzzzzpqrrrabbxyyyypqAzz"), 2382);
+assertEquals("aaaabcxyzzzzpqrrrabbbxyyyypqAzz", res[803].exec("aaaabcxyzzzzpqrrrabbbxyyyypqAzz"), 2383);
+assertEquals("aaaabcxyzzzzpqrrrabbbxyyyyypqAzz", res[803].exec("aaaabcxyzzzzpqrrrabbbxyyyyypqAzz"), 2384);
+assertEquals("aaabcxyzpqrrrabbxyyyypABzz", res[803].exec("aaabcxyzpqrrrabbxyyyypABzz"), 2385);
+assertEquals("aaabcxyzpqrrrabbxyyyypABBzz", res[803].exec("aaabcxyzpqrrrabbxyyyypABBzz"), 2386);
+assertEquals("aaabxyzpqrrrabbxyyyypqAzz", res[803].exec(">>>aaabxyzpqrrrabbxyyyypqAzz"), 2387);
+assertEquals("aaaabxyzpqrrrabbxyyyypqAzz", res[803].exec(">aaaabxyzpqrrrabbxyyyypqAzz"), 2388);
+assertEquals("abcxyzpqrrrabbxyyyypqAzz", res[803].exec(">>>>abcxyzpqrrrabbxyyyypqAzz"), 2389);
+assertEquals(null, res[803].exec("*** Failers", 2390));
+assertEquals(null, res[803].exec("abxyzpqrrabbxyyyypqAzz", 2391));
+assertEquals(null, res[803].exec("abxyzpqrrrrabbxyyyypqAzz", 2392));
+assertEquals(null, res[803].exec("abxyzpqrrrabxyyyypqAzz", 2393));
+assertEquals(null, res[803].exec("aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz", 2394));
+assertEquals(null, res[803].exec("aaaabcxyzzzzpqrrrabbbxyyypqAzz", 2395));
+assertEquals(null, res[803].exec("aaabcxyzpqrrrabbxyyyypqqqqqqqAzz", 2396));
+assertEquals("abczz,abc", res[804].exec("abczz"), 2397);
+assertEquals("abcabczz,abc", res[804].exec("abcabczz"), 2398);
+assertEquals(null, res[804].exec("*** Failers", 2399));
+assertEquals(null, res[804].exec("zz", 2400));
+assertEquals(null, res[804].exec("abcabcabczz", 2401));
+assertEquals(null, res[804].exec(">>abczz", 2402));
+assertEquals("bc,b", res[805].exec("bc"), 2403);
+assertEquals("bbc,b", res[805].exec("bbc"), 2404);
+assertEquals("bbbc,bb", res[805].exec("bbbc"), 2405);
+assertEquals("bac,a", res[805].exec("bac"), 2406);
+assertEquals("bbac,a", res[805].exec("bbac"), 2407);
+assertEquals("aac,a", res[805].exec("aac"), 2408);
+assertEquals("abbbbbbbbbbbc,bbbbbbbbbbb", res[805].exec("abbbbbbbbbbbc"), 2409);
+assertEquals("bbbbbbbbbbbac,a", res[805].exec("bbbbbbbbbbbac"), 2410);
+assertEquals(null, res[805].exec("*** Failers", 2411));
+assertEquals(null, res[805].exec("aaac", 2412));
+assertEquals(null, res[805].exec("abbbbbbbbbbbac", 2413));
+assertEquals("bc,b", res[806].exec("bc"), 2414);
+assertEquals("bbc,bb", res[806].exec("bbc"), 2415);
+assertEquals("bbbc,bbb", res[806].exec("bbbc"), 2416);
+assertEquals("bac,a", res[806].exec("bac"), 2417);
+assertEquals("bbac,a", res[806].exec("bbac"), 2418);
+assertEquals("aac,a", res[806].exec("aac"), 2419);
+assertEquals("abbbbbbbbbbbc,bbbbbbbbbbb", res[806].exec("abbbbbbbbbbbc"), 2420);
+assertEquals("bbbbbbbbbbbac,a", res[806].exec("bbbbbbbbbbbac"), 2421);
+assertEquals(null, res[806].exec("*** Failers", 2422));
+assertEquals(null, res[806].exec("aaac", 2423));
+assertEquals(null, res[806].exec("abbbbbbbbbbbac", 2424));
+assertEquals("bbc,bb", res[806].exec("bbc"), 2425);
+assertEquals("babc,ba", res[807].exec("babc"), 2426);
+assertEquals("bbabc,ba", res[807].exec("bbabc"), 2427);
+assertEquals("bababc,ba", res[807].exec("bababc"), 2428);
+assertEquals(null, res[807].exec("*** Failers", 2429));
+assertEquals(null, res[807].exec("bababbc", 2430));
+assertEquals(null, res[807].exec("babababc", 2431));
+assertEquals("babc,ba", res[808].exec("babc"), 2432);
+assertEquals("bbabc,ba", res[808].exec("bbabc"), 2433);
+assertEquals("bababc,ba", res[808].exec("bababc"), 2434);
+assertEquals(null, res[808].exec("*** Failers", 2435));
+assertEquals(null, res[808].exec("bababbc", 2436));
+assertEquals(null, res[808].exec("babababc", 2437));
+assertThrows("var re = /^\\ca\\cA\\c[\\c{\\c:/;", 2438);
+assertEquals(null, res[808].exec("\x01\x01e;z", 2439));
+assertEquals("a", res[809].exec("athing"), 2440);
+assertEquals("b", res[809].exec("bthing"), 2441);
+assertEquals("]", res[809].exec("]thing"), 2442);
+assertEquals("c", res[809].exec("cthing"), 2443);
+assertEquals("d", res[809].exec("dthing"), 2444);
+assertEquals("e", res[809].exec("ething"), 2445);
+assertEquals(null, res[809].exec("*** Failers", 2446));
+assertEquals(null, res[809].exec("fthing", 2447));
+assertEquals(null, res[809].exec("[thing", 2448));
+assertEquals(null, res[809].exec("\\thing", 2449));
+assertEquals(null, res[810].exec("]thing", 2450));
+assertEquals(null, res[810].exec("cthing", 2451));
+assertEquals(null, res[810].exec("dthing", 2452));
+assertEquals(null, res[810].exec("ething", 2453));
+assertEquals(null, res[810].exec("*** Failers", 2454));
+assertEquals(null, res[810].exec("athing", 2455));
+assertEquals(null, res[810].exec("fthing", 2456));
+assertEquals("f", res[811].exec("fthing"), 2457);
+assertEquals("[", res[811].exec("[thing"), 2458);
+assertEquals("\\", res[811].exec("\\thing"), 2459);
+assertEquals("*", res[811].exec("*** Failers"), 2460);
+assertEquals(null, res[811].exec("athing", 2461));
+assertEquals(null, res[811].exec("bthing", 2462));
+assertEquals(null, res[811].exec("]thing", 2463));
+assertEquals(null, res[811].exec("cthing", 2464));
+assertEquals(null, res[811].exec("dthing", 2465));
+assertEquals(null, res[811].exec("ething", 2466));
+assertEquals(null, res[812].exec("athing", 2467));
+assertEquals(null, res[812].exec("fthing", 2468));
+assertEquals(null, res[812].exec("*** Failers", 2469));
+assertEquals(null, res[812].exec("]thing", 2470));
+assertEquals(null, res[812].exec("cthing", 2471));
+assertEquals(null, res[812].exec("dthing", 2472));
+assertEquals(null, res[812].exec("ething", 2473));
+assertEquals(null, res[812].exec("\ufffd", 2474));
+assertEquals(null, res[812].exec("\ufffd", 2475));
+assertEquals("0", res[813].exec("0"), 2476);
+assertEquals("1", res[813].exec("1"), 2477);
+assertEquals("2", res[813].exec("2"), 2478);
+assertEquals("3", res[813].exec("3"), 2479);
+assertEquals("4", res[813].exec("4"), 2480);
+assertEquals("5", res[813].exec("5"), 2481);
+assertEquals("6", res[813].exec("6"), 2482);
+assertEquals("7", res[813].exec("7"), 2483);
+assertEquals("8", res[813].exec("8"), 2484);
+assertEquals("9", res[813].exec("9"), 2485);
+assertEquals("10", res[813].exec("10"), 2486);
+assertEquals("100", res[813].exec("100"), 2487);
+assertEquals(null, res[813].exec("*** Failers", 2488));
+assertEquals(null, res[813].exec("abc", 2489));
+assertEquals("enter", res[814].exec("enter"), 2490);
+assertEquals("inter", res[814].exec("inter"), 2491);
+assertEquals("uponter", res[814].exec("uponter"), 2492);
+assertEquals("xxx0", res[815].exec("xxx0"), 2493);
+assertEquals("xxx1234", res[815].exec("xxx1234"), 2494);
+assertEquals(null, res[815].exec("*** Failers", 2495));
+assertEquals(null, res[815].exec("xxx", 2496));
+assertEquals("x123", res[816].exec("x123"), 2497);
+assertEquals("xx123", res[816].exec("xx123"), 2498);
+assertEquals("123456", res[816].exec("123456"), 2499);
+assertEquals(null, res[816].exec("*** Failers", 2500));
+assertEquals(null, res[816].exec("123", 2501));
+assertEquals("x1234", res[816].exec("x1234"), 2502);
+assertEquals("x123", res[817].exec("x123"), 2503);
+assertEquals("xx123", res[817].exec("xx123"), 2504);
+assertEquals("123456", res[817].exec("123456"), 2505);
+assertEquals(null, res[817].exec("*** Failers", 2506));
+assertEquals(null, res[817].exec("123", 2507));
+assertEquals("x1234", res[817].exec("x1234"), 2508);
+assertEquals("abc!pqr=apquxz.ixr.zzz.ac.uk,abc,pqr", res[818].exec("abc!pqr=apquxz.ixr.zzz.ac.uk"), 2509);
+assertEquals(null, res[818].exec("*** Failers", 2510));
+assertEquals(null, res[818].exec("!pqr=apquxz.ixr.zzz.ac.uk", 2511));
+assertEquals(null, res[818].exec("abc!=apquxz.ixr.zzz.ac.uk", 2512));
+assertEquals(null, res[818].exec("abc!pqr=apquxz:ixr.zzz.ac.uk", 2513));
+assertEquals(null, res[818].exec("abc!pqr=apquxz.ixr.zzz.ac.ukk", 2514));
+assertEquals(":", res[819].exec("Well, we need a colon: somewhere"), 2515);
+assertEquals(null, res[819].exec("*** Fail if we don't", 2516));
+assertEquals("0abc,0abc", res[820].exec("0abc"), 2517);
+assertEquals("abc,abc", res[820].exec("abc"), 2518);
+assertEquals("fed,fed", res[820].exec("fed"), 2519);
+assertEquals("E,E", res[820].exec("E"), 2520);
+assertEquals("::,::", res[820].exec("::"), 2521);
+assertEquals("5f03:12C0::932e,5f03:12C0::932e", res[820].exec("5f03:12C0::932e"), 2522);
+assertEquals("def,def", res[820].exec("fed def"), 2523);
+assertEquals("ff,ff", res[820].exec("Any old stuff"), 2524);
+assertEquals(null, res[820].exec("*** Failers", 2525));
+assertEquals(null, res[820].exec("0zzz", 2526));
+assertEquals(null, res[820].exec("gzzz", 2527));
+assertEquals(null, res[820].exec("fed ", 2528));
+assertEquals(null, res[820].exec("Any old rubbish", 2529));
+assertEquals(".1.2.3,1,2,3", res[821].exec(".1.2.3"), 2530);
+assertEquals("A.12.123.0,12,123,0", res[821].exec("A.12.123.0"), 2531);
+assertEquals(null, res[821].exec("*** Failers", 2532));
+assertEquals(null, res[821].exec(".1.2.3333", 2533));
+assertEquals(null, res[821].exec("1.2.3", 2534));
+assertEquals(null, res[821].exec("1234.2.3", 2535));
+assertEquals("1 IN SOA non-sp1 non-sp2(,1,non-sp1,non-sp2", res[822].exec("1 IN SOA non-sp1 non-sp2("), 2536);
+assertEquals("1    IN    SOA    non-sp1    non-sp2   (,1,non-sp1,non-sp2", res[822].exec("1    IN    SOA    non-sp1    non-sp2   ("), 2537);
+assertEquals(null, res[822].exec("*** Failers", 2538));
+assertEquals(null, res[822].exec("1IN SOA non-sp1 non-sp2(", 2539));
+assertEquals("a.,", res[823].exec("a."), 2540);
+assertEquals("Z.,", res[823].exec("Z."), 2541);
+assertEquals("2.,", res[823].exec("2."), 2542);
+assertEquals("ab-c.pq-r.,.pq-r", res[823].exec("ab-c.pq-r."), 2543);
+assertEquals("sxk.zzz.ac.uk.,.uk", res[823].exec("sxk.zzz.ac.uk."), 2544);
+assertEquals("x-.y-.,.y-", res[823].exec("x-.y-."), 2545);
+assertEquals(null, res[823].exec("*** Failers", 2546));
+assertEquals(null, res[823].exec("-abc.peq.", 2547));
+assertEquals("*.a,,,", res[824].exec("*.a"), 2548);
+assertEquals("*.b0-a,0-a,,", res[824].exec("*.b0-a"), 2549);
+assertEquals("*.c3-b.c,3-b,.c,", res[824].exec("*.c3-b.c"), 2550);
+assertEquals("*.c-a.b-c,-a,.b-c,-c", res[824].exec("*.c-a.b-c"), 2551);
+assertEquals(null, res[824].exec("*** Failers", 2552));
+assertEquals(null, res[824].exec("*.0", 2553));
+assertEquals(null, res[824].exec("*.a-", 2554));
+assertEquals(null, res[824].exec("*.a-b.c-", 2555));
+assertEquals(null, res[824].exec("*.c-a.0-c", 2556));
+assertEquals("abde,de,abd,e", res[825].exec("abde"), 2557);
+assertEquals("abdf,,abd,f", res[826].exec("abdf"), 2558);
+assertEquals("ab,abcd,cd,ab", res[827].exec("abcd"), 2559);
+assertEquals("a.b.c.d,.d", res[828].exec("a.b.c.d"), 2560);
+assertEquals("A.B.C.D,.D", res[828].exec("A.B.C.D"), 2561);
+assertEquals("a.b.c.1.2.3.C,.C", res[828].exec("a.b.c.1.2.3.C"), 2562);
+assertEquals("\"1234\",", res[829].exec("\"1234\""), 2563);
+assertEquals("\"abcd\" ;,;", res[829].exec("\"abcd\" ;"), 2564);
+assertEquals("\"\" ; rhubarb,; rhubarb", res[829].exec("\"\" ; rhubarb"), 2565);
+assertEquals(null, res[829].exec("*** Failers", 2566));
+assertEquals(null, res[829].exec("\"1234\" : things", 2567));
+assertEquals(null, res[830].exec("\\", 2568));
+assertEquals(null, res[830].exec("*** Failers", 2569));
+assertEquals("ab c", res[831].exec("ab c"), 2570);
+assertEquals(null, res[831].exec("*** Failers", 2571));
+assertEquals(null, res[831].exec("abc", 2572));
+assertEquals(null, res[831].exec("ab cde", 2573));
+assertEquals("ab c", res[831].exec("ab c"), 2574);
+assertEquals(null, res[831].exec("*** Failers", 2575));
+assertEquals(null, res[831].exec("abc", 2576));
+assertEquals(null, res[831].exec("ab cde", 2577));
+assertEquals("a bcd", res[832].exec("a bcd"), 2578);
+assertEquals(null, res[832].exec("a b d", 2579));
+assertEquals(null, res[832].exec("*** Failers", 2580));
+assertEquals(null, res[832].exec("abcd", 2581));
+assertEquals(null, res[832].exec("ab d", 2582));
+assertEquals("abcdefhijklm,abc,bc,c,def,ef,f,hij,ij,j,klm,lm,m", res[833].exec("abcdefhijklm"), 2583);
+assertEquals("abcdefhijklm,bc,c,ef,f,ij,j,lm,m", res[834].exec("abcdefhijklm"), 2584);
+assertEquals(null, res[835].exec("a+ Z0+\x08\n\x1d\x12", 2585));
+assertEquals(null, res[835].exec(".^$(*+)|{?,?}", 2586));
+assertEquals("z", res[836].exec("z"), 2587);
+assertEquals("az", res[836].exec("az"), 2588);
+assertEquals("aaaz", res[836].exec("aaaz"), 2589);
+assertEquals("a", res[836].exec("a"), 2590);
+assertEquals("aa", res[836].exec("aa"), 2591);
+assertEquals("aaaa", res[836].exec("aaaa"), 2592);
+assertEquals("a", res[836].exec("a+"), 2593);
+assertEquals("aa", res[836].exec("aa+"), 2594);
+assertEquals("z", res[837].exec("z"), 2595);
+assertEquals("a", res[837].exec("az"), 2596);
+assertEquals("a", res[837].exec("aaaz"), 2597);
+assertEquals("a", res[837].exec("a"), 2598);
+assertEquals("a", res[837].exec("aa"), 2599);
+assertEquals("a", res[837].exec("aaaa"), 2600);
+assertEquals("a", res[837].exec("a+"), 2601);
+assertEquals("a", res[837].exec("aa+"), 2602);
+assertEquals("az", res[838].exec("az"), 2603);
+assertEquals("aaaz", res[838].exec("aaaz"), 2604);
+assertEquals("aa", res[838].exec("aa"), 2605);
+assertEquals("aaaa", res[838].exec("aaaa"), 2606);
+assertEquals("aa", res[838].exec("aa+"), 2607);
+assertEquals("az", res[839].exec("az"), 2608);
+assertEquals("aa", res[839].exec("aaaz"), 2609);
+assertEquals("aa", res[839].exec("aa"), 2610);
+assertEquals("aa", res[839].exec("aaaa"), 2611);
+assertEquals("aa", res[839].exec("aa+"), 2612);
+assertEquals("1234567890", res[840].exec("1234567890"), 2613);
+assertEquals("12345678ab", res[840].exec("12345678ab"), 2614);
+assertEquals("12345678__", res[840].exec("12345678__"), 2615);
+assertEquals(null, res[840].exec("*** Failers", 2616));
+assertEquals(null, res[840].exec("1234567", 2617));
+assertEquals("uoie", res[841].exec("uoie"), 2618);
+assertEquals("1234", res[841].exec("1234"), 2619);
+assertEquals("12345", res[841].exec("12345"), 2620);
+assertEquals("aaaaa", res[841].exec("aaaaa"), 2621);
+assertEquals(null, res[841].exec("*** Failers", 2622));
+assertEquals(null, res[841].exec("123456", 2623));
+assertEquals("uoie", res[842].exec("uoie"), 2624);
+assertEquals("1234", res[842].exec("1234"), 2625);
+assertEquals("1234", res[842].exec("12345"), 2626);
+assertEquals("aaaa", res[842].exec("aaaaa"), 2627);
+assertEquals("1234", res[842].exec("123456"), 2628);
+assertEquals("From abcd  Mon Sep 01 12:33,abcd", res[843].exec("From abcd  Mon Sep 01 12:33:02 1997"), 2629);
+assertEquals("From abcd  Mon Sep 01 12:33,Sep ", res[844].exec("From abcd  Mon Sep 01 12:33:02 1997"), 2630);
+assertEquals("From abcd  Mon Sep  1 12:33,Sep  ", res[844].exec("From abcd  Mon Sep  1 12:33:02 1997"), 2631);
+assertEquals(null, res[844].exec("*** Failers", 2632));
+assertEquals(null, res[844].exec("From abcd  Sep 01 12:33:02 1997", 2633));
+assertEquals(null, res[845].exec("12\n34", 2634));
+assertEquals(null, res[845].exec("12\x0d34", 2635));
+assertEquals("brown", res[846].exec("the quick brown\x09 fox"), 2636);
+assertEquals("foolish see?,lish see?", res[847].exec("foobar is foolish see?"), 2637);
+assertEquals("rowbar etc, etc", res[848].exec("foobar crowbar etc"), 2638);
+assertEquals("barrel,rel", res[848].exec("barrel"), 2639);
+assertEquals("2barrel,rel", res[848].exec("2barrel"), 2640);
+assertEquals("A barrel,rel", res[848].exec("A barrel"), 2641);
+assertEquals("abc,abc", res[849].exec("abc456"), 2642);
+assertEquals(null, res[849].exec("*** Failers", 2643));
+assertEquals(null, res[849].exec("abc123", 2644));
+assertEquals("1234", res[850].exec("1234"), 2645);
+assertEquals("1234", res[851].exec("1234"), 2646);
+assertEquals("abcd", res[852].exec("abcd"), 2647);
+assertEquals("abcd", res[853].exec("abcd"), 2648);
+assertEquals("abc", res[854].exec("the abc"), 2649);
+assertEquals(null, res[854].exec("*** Failers", 2650));
+assertEquals(null, res[854].exec("abc", 2651));
+assertEquals("abc", res[855].exec("abc"), 2652);
+assertEquals(null, res[855].exec("*** Failers", 2653));
+assertEquals(null, res[855].exec("the abc", 2654));
+assertEquals("aabb,b", res[856].exec("aabbbbb"), 2655);
+assertEquals("aabbbbb,abbbbb", res[857].exec("aabbbbb"), 2656);
+assertEquals("aa,a", res[858].exec("aabbbbb"), 2657);
+assertEquals("aabb,b", res[859].exec("aabbbbb"), 2658);
+assertEquals("Alan Other <user@dom.ain>", res[860].exec("Alan Other <user@dom.ain>"), 2659);
+assertEquals("user@dom.ain", res[860].exec("<user@dom.ain>"), 2660);
+assertEquals("user@dom.ain", res[860].exec("user@dom.ain"), 2661);
+assertEquals("\"A. Other\" <user.1234@dom.ain> (a comment)", res[860].exec("\"A. Other\" <user.1234@dom.ain> (a comment)"), 2662);
+assertEquals(" Other <user.1234@dom.ain> (a comment)", res[860].exec("A. Other <user.1234@dom.ain> (a comment)"), 2663);
+assertEquals("\"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"@x400-re.lay", res[860].exec("\"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"@x400-re.lay"), 2664);
+assertEquals("user@some.where", res[860].exec("A missing angle <user@some.where"), 2665);
+assertEquals(null, res[860].exec("*** Failers", 2666));
+assertEquals(null, res[860].exec("The quick brown fox", 2667));
+assertEquals("Alan Other <user@dom.ain>", res[861].exec("Alan Other <user@dom.ain>"), 2668);
+assertEquals("user@dom.ain", res[861].exec("<user@dom.ain>"), 2669);
+assertEquals("user@dom.ain", res[861].exec("user@dom.ain"), 2670);
+assertEquals("\"A. Other\" <user.1234@dom.ain>", res[861].exec("\"A. Other\" <user.1234@dom.ain> (a comment)"), 2671);
+assertEquals(" Other <user.1234@dom.ain>", res[861].exec("A. Other <user.1234@dom.ain> (a comment)"), 2672);
+assertEquals("\"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"@x400-re.lay", res[861].exec("\"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"@x400-re.lay"), 2673);
+assertEquals("user@some.where", res[861].exec("A missing angle <user@some.where"), 2674);
+assertEquals(null, res[861].exec("*** Failers", 2675));
+assertEquals(null, res[861].exec("The quick brown fox", 2676));
+assertEquals(null, res[861].exec("abc\x00def\x00pqr\x00xyz\x000AB", 2677));
+assertEquals(null, res[861].exec("abc456 abc\x00def\x00pqr\x00xyz\x000ABCDE", 2678));
+assertEquals("abc\x0def\x00pqr\x000xyz\x0000AB", res[862].exec("abc\x0def\x00pqr\x000xyz\x0000AB"), 2679);
+assertEquals("abc\x0def\x00pqr\x000xyz\x0000AB", res[862].exec("abc456 abc\x0def\x00pqr\x000xyz\x0000ABCDE"), 2680);
+assertEquals("\x00", res[863].exec("\x00A"), 2681);
+assertEquals("\x01", res[863].exec("\x01B"), 2682);
+assertEquals("\x1f", res[863].exec("\x1fC"), 2683);
+assertEquals("\x00\x00\x00\x00", res[864].exec("\x00\x00\x00\x00"), 2684);
+assertEquals(null, res[865].exec("The Ax0x0Z", 2685));
+assertEquals(null, res[865].exec("An A\x00x0\x00Z", 2686));
+assertEquals(null, res[865].exec("*** Failers", 2687));
+assertEquals(null, res[865].exec("A\x00Z", 2688));
+assertEquals(null, res[865].exec("A\x00x0\x00x0Z", 2689));
+assertEquals(" ", res[866].exec(" abc"), 2690);
+assertEquals("\x0c", res[866].exec("\x0cabc"), 2691);
+assertEquals("\n", res[866].exec("\nabc"), 2692);
+assertEquals("\x0d", res[866].exec("\x0dabc"), 2693);
+assertEquals("\x09", res[866].exec("\x09abc"), 2694);
+assertEquals(null, res[866].exec("*** Failers", 2695));
+assertEquals(null, res[866].exec("abc", 2696));
+assertEquals("abc", res[867].exec("abc"), 2697);
+assertEquals("abbbbc", res[868].exec("abbbbc"), 2698);
+assertEquals("abbbc", res[868].exec("abbbc"), 2699);
+assertEquals("abbc", res[868].exec("abbc"), 2700);
+assertEquals(null, res[868].exec("*** Failers", 2701));
+assertEquals(null, res[868].exec("abc", 2702));
+assertEquals(null, res[868].exec("abbbbbc", 2703));
+assertEquals("track1.title:TBlah blah blah,track1,title,Blah blah blah", res[869].exec("track1.title:TBlah blah blah"), 2704);
+assertEquals("track1.title:TBlah blah blah,track1,title,Blah blah blah", res[870].exec("track1.title:TBlah blah blah"), 2705);
+assertEquals("track1.title:TBlah blah blah,track1,title,Blah blah blah", res[871].exec("track1.title:TBlah blah blah"), 2706);
+assertEquals("WXY_^abc", res[872].exec("WXY_^abc"), 2707);
+assertEquals(null, res[872].exec("*** Failers", 2708));
+assertEquals(null, res[872].exec("wxy", 2709));
+assertEquals("WXY_^abc", res[873].exec("WXY_^abc"), 2710);
+assertEquals("wxy_^ABC", res[873].exec("wxy_^ABC"), 2711);
+assertEquals("WXY_^abc", res[874].exec("WXY_^abc"), 2712);
+assertEquals("wxy_^ABC", res[874].exec("wxy_^ABC"), 2713);
+assertEquals("abc", res[875].exec("abc"), 2714);
+assertEquals("abc", res[875].exec("qqq\nabc"), 2715);
+assertEquals("abc", res[875].exec("abc\nzzz"), 2716);
+assertEquals("abc", res[875].exec("qqq\nabc\nzzz"), 2717);
+assertEquals("abc", res[876].exec("abc"), 2718);
+assertEquals(null, res[876].exec("*** Failers", 2719));
+assertEquals(null, res[876].exec("qqq\nabc", 2720));
+assertEquals(null, res[876].exec("abc\nzzz", 2721));
+assertEquals(null, res[876].exec("qqq\nabc\nzzz", 2722));
+assertEquals(null, res[877].exec("abc", 2723));
+assertEquals(null, res[877].exec("abc\n ", 2724));
+assertEquals(null, res[877].exec("*** Failers", 2725));
+assertEquals(null, res[877].exec("qqq\nabc", 2726));
+assertEquals(null, res[877].exec("abc\nzzz", 2727));
+assertEquals(null, res[877].exec("qqq\nabc\nzzz", 2728));
+assertEquals(null, res[878].exec("abc\ndef", 2729));
+assertEquals(null, res[879].exec("*** Failers", 2730));
+assertEquals(null, res[879].exec("abc\ndef", 2731));
+assertEquals("b", res[880].exec("b::c"), 2732);
+assertEquals("::", res[880].exec("c::b"), 2733);
+assertEquals("az-", res[881].exec("az-"), 2734);
+assertEquals("a", res[881].exec("*** Failers"), 2735);
+assertEquals(null, res[881].exec("b", 2736));
+assertEquals("za-", res[882].exec("za-"), 2737);
+assertEquals("a", res[882].exec("*** Failers"), 2738);
+assertEquals(null, res[882].exec("b", 2739));
+assertEquals("a-z", res[883].exec("a-z"), 2740);
+assertEquals("a", res[883].exec("*** Failers"), 2741);
+assertEquals(null, res[883].exec("b", 2742));
+assertEquals("abcdxyz", res[884].exec("abcdxyz"), 2743);
+assertEquals("12-34", res[885].exec("12-34"), 2744);
+assertEquals(null, res[885].exec("*** Failers", 2745));
+assertEquals(null, res[885].exec("aaa", 2746));
+assertEquals("12-34z", res[886].exec("12-34z"), 2747);
+assertEquals(null, res[886].exec("*** Failers", 2748));
+assertEquals(null, res[886].exec("aaa", 2749));
+assertEquals("\\", res[887].exec("\\\\"), 2750);
+assertEquals(" Z", res[888].exec("the Zoo"), 2751);
+assertEquals(null, res[888].exec("*** Failers", 2752));
+assertEquals(null, res[888].exec("Zulu", 2753));
+assertEquals("ab{3cd", res[889].exec("ab{3cd"), 2754);
+assertEquals("ab{3,cd", res[890].exec("ab{3,cd"), 2755);
+assertEquals("ab{3,4a}cd", res[891].exec("ab{3,4a}cd"), 2756);
+assertEquals("{4,5a}bc", res[892].exec("{4,5a}bc"), 2757);
+assertEquals(null, res[893].exec("a\x0db", 2758));
+assertEquals(null, res[893].exec("*** Failers", 2759));
+assertEquals(null, res[893].exec("a\nb", 2760));
+assertEquals("abc", res[894].exec("abc"), 2761);
+assertEquals(null, res[894].exec("abc\n", 2762));
+assertEquals(null, res[894].exec("*** Failers", 2763));
+assertEquals(null, res[894].exec("abc\ndef", 2764));
+assertEquals("abcS,abc", res[895].exec("abcS"), 2765);
+assertEquals("abc\x93,abc", res[896].exec("abc\x93"), 2766);
+assertEquals("abc\xd3,abc", res[897].exec("abc\xd3"), 2767);
+assertEquals("abc@,abc", res[898].exec("abc@"), 2768);
+assertEquals("abc@,abc", res[898].exec("abc@"), 2769);
+assertEquals("abc@,abc", res[898].exec("abc@0"), 2770);
+assertEquals("abc@,abc", res[898].exec("abc@0"), 2771);
+assertEquals("abc@,abc", res[898].exec("abc@0"), 2772);
+assertEquals("abc@,abc", res[898].exec("abc@0"), 2773);
+assertEquals("abc@,abc", res[898].exec("abc@0"), 2774);
+assertEquals("abc@,abc", res[898].exec("abc@0"), 2775);
+assertEquals(null, res[899].exec("abc\x0081", 2776));
+assertEquals(null, res[899].exec("abc\x0081", 2777));
+assertEquals(null, res[900].exec("abc\x0091", 2778));
+assertEquals(null, res[900].exec("abc\x0091", 2779));
+assertEquals("abcdefghijk\nS,a,b,c,d,e,f,g,h,i,j,k", res[901].exec("abcdefghijk\nS"), 2780);
+assertEquals("abidef", res[902].exec("abidef"), 2781);
+assertEquals("bc", res[903].exec("bc"), 2782);
+assertEquals("xyz,,", res[904].exec("xyz"), 2783);
+assertEquals("abc\x08de", res[905].exec("abc\x08de"), 2784);
+assertEquals("abc\x01de", res[906].exec("abc\x01de"), 2785);
+assertEquals("abc\x01de,abc", res[907].exec("abc\x01de"), 2786);
+assertEquals(null, res[907].exec("a\nb", 2787));
+assertEquals("baNOTcccc,b,a,NOT,cccc", res[908].exec("baNOTccccd"), 2788);
+assertEquals("baNOTccc,b,a,NOT,ccc", res[908].exec("baNOTcccd"), 2789);
+assertEquals("baNOTcc,b,a,NO,Tcc", res[908].exec("baNOTccd"), 2790);
+assertEquals("baccc,b,a,,ccc", res[908].exec("bacccd"), 2791);
+assertEquals("*** Failers,*,*,* Fail,ers", res[908].exec("*** Failers"), 2792);
+assertEquals(null, res[908].exec("anything", 2793));
+assertEquals(null, res[908].exec("b\x08c   ", 2794));
+assertEquals(null, res[908].exec("baccd", 2795));
+assertEquals("A", res[909].exec("Abc"), 2796);
+assertEquals("b", res[910].exec("Abc "), 2797);
+assertEquals("AAA", res[911].exec("AAAaAbc"), 2798);
+assertEquals("bc ", res[912].exec("AAAaAbc "), 2799);
+assertEquals("bbb\nccc", res[913].exec("bbb\nccc"), 2800);
+assertEquals("c", res[914].exec("abc"), 2801);
+assertEquals("s", res[914].exec("*** Failers"), 2802);
+assertEquals(" ", res[914].exec("abk   "), 2803);
+assertEquals("abc", res[915].exec("abc"), 2804);
+assertEquals("bc", res[915].exec("kbc"), 2805);
+assertEquals("bc ", res[915].exec("kabc "), 2806);
+assertEquals("ers", res[915].exec("*** Failers"), 2807);
+assertEquals(null, res[915].exec("abk", 2808));
+assertEquals(null, res[915].exec("akb", 2809));
+assertEquals(null, res[915].exec("akk ", 2810));
+assertEquals("12345678@a.b.c.d", res[916].exec("12345678@a.b.c.d"), 2811);
+assertEquals("123456789@x.y.z", res[916].exec("123456789@x.y.z"), 2812);
+assertEquals(null, res[916].exec("*** Failers", 2813));
+assertEquals(null, res[916].exec("12345678@x.y.uk", 2814));
+assertEquals(null, res[916].exec("1234567@a.b.c.d       ", 2815));
+assertEquals("b", res[917].exec("aaaabcd"), 2816);
+assertEquals("A", res[917].exec("aaAabcd "), 2817);
+assertEquals("b", res[918].exec("aaaabcd"), 2818);
+assertEquals("b", res[918].exec("aaAabcd "), 2819);
+assertEquals("b", res[919].exec("aaaabcd"), 2820);
+assertEquals("A", res[919].exec("aaAabcd "), 2821);
+assertEquals("b", res[920].exec("aaaabcd"), 2822);
+assertEquals("b", res[920].exec("aaAabcd "), 2823);
+assertEquals("PSTAIREISLL", res[922].exec("xxxxxxxxxxxPSTAIREISLLxxxxxxxxx"), 2824);
+assertEquals("PSTAIREISLL", res[923].exec("xxxxxxxxxxxPSTAIREISLLxxxxxxxxx"), 2825);
+assertEquals(".230003938,.23", res[924].exec("1.230003938"), 2826);
+assertEquals(".875000282,.875", res[924].exec("1.875000282   "), 2827);
+assertEquals(".235,.23", res[924].exec("1.235  "), 2828);
+assertEquals(null, res[924].exec("              ", 2829));
+assertEquals(".23,.23,", res[925].exec("1.230003938      "), 2830);
+assertEquals(".875,.875,5", res[925].exec("1.875000282"), 2831);
+assertEquals(null, res[925].exec("*** Failers ", 2832));
+assertEquals(null, res[925].exec("1.235 ", 2833));
+assertThrows("var re = /a(?)b/;", 2834);
+assertEquals(null, res[925].exec("ab ", 2835));
+assertEquals("foo table,foo,table", res[926].exec("Food is on the foo table"), 2836);
+assertEquals("food is under the bar in the bar,d is under the bar in the ", res[927].exec("The food is under the bar in the barn."), 2837);
+assertEquals("food is under the bar,d is under the ", res[928].exec("The food is under the bar in the barn."), 2838);
+assertEquals("I have 2 numbers: 53147,I have 2 numbers: 53147,", res[929].exec("I have 2 numbers: 53147"), 2839);
+assertEquals("I have 2 numbers: 53147,I have 2 numbers: 5314,7", res[930].exec("I have 2 numbers: 53147"), 2840);
+assertEquals(",,", res[931].exec("I have 2 numbers: 53147"), 2841);
+assertEquals("I have 2,I have ,2", res[932].exec("I have 2 numbers: 53147"), 2842);
+assertEquals("I have 2 numbers: 53147,I have 2 numbers: 5314,7", res[933].exec("I have 2 numbers: 53147"), 2843);
+assertEquals("I have 2 numbers: 53147,I have 2 numbers: ,53147", res[934].exec("I have 2 numbers: 53147"), 2844);
+assertEquals("I have 2 numbers: 53147,I have 2 numbers: ,53147", res[935].exec("I have 2 numbers: 53147"), 2845);
+assertEquals("I have 2 numbers: 53147,I have 2 numbers: ,53147", res[936].exec("I have 2 numbers: 53147"), 2846);
+assertEquals("AB", res[937].exec("ABC123"), 2847);
+assertEquals(" ", res[937].exec(" "), 2848);
+assertEquals("ABC,ABC", res[938].exec("ABC445"), 2849);
+assertEquals(null, res[938].exec("*** Failers", 2850));
+assertEquals(null, res[938].exec("ABC123", 2851));
+assertEquals("W46]", res[939].exec("W46]789 "), 2852);
+assertEquals("-46]", res[939].exec("-46]789"), 2853);
+assertEquals(null, res[939].exec("*** Failers", 2854));
+assertEquals(null, res[939].exec("Wall", 2855));
+assertEquals(null, res[939].exec("Zebra", 2856));
+assertEquals(null, res[939].exec("42", 2857));
+assertEquals(null, res[939].exec("[abcd] ", 2858));
+assertEquals(null, res[939].exec("]abcd[", 2859));
+assertEquals(null, res[939].exec("   ", 2860));
+assertEquals("W", res[940].exec("W46]789 "), 2861);
+assertEquals("W", res[940].exec("Wall"), 2862);
+assertEquals("Z", res[940].exec("Zebra"), 2863);
+assertEquals("X", res[940].exec("Xylophone  "), 2864);
+assertEquals("4", res[940].exec("42"), 2865);
+assertEquals("[", res[940].exec("[abcd] "), 2866);
+assertEquals("]", res[940].exec("]abcd["), 2867);
+assertEquals("\\", res[940].exec("\\backslash "), 2868);
+assertEquals(null, res[940].exec("*** Failers", 2869));
+assertEquals(null, res[940].exec("-46]789", 2870));
+assertEquals(null, res[940].exec("well", 2871));
+assertEquals("01/01/2000", res[941].exec("01/01/2000"), 2872);
+assertEquals(",", res[944].exec("bcd"), 2873);
+assertEquals(",", res[944].exec("abc"), 2874);
+assertEquals(",", res[944].exec("aab     "), 2875);
+assertEquals(",", res[945].exec("bcd"), 2876);
+assertEquals("a,a", res[945].exec("abc"), 2877);
+assertEquals("a,a", res[945].exec("aab  "), 2878);
+assertEquals(",", res[946].exec("bcd"), 2879);
+assertEquals("a,a", res[946].exec("abc"), 2880);
+assertEquals("aa,a", res[946].exec("aab  "), 2881);
+assertEquals(",", res[947].exec("bcd"), 2882);
+assertEquals("a,a", res[947].exec("abc"), 2883);
+assertEquals("aa,a", res[947].exec("aab"), 2884);
+assertEquals("aaa,a", res[947].exec("aaa   "), 2885);
+assertEquals(",", res[948].exec("bcd"), 2886);
+assertEquals("a,a", res[948].exec("abc"), 2887);
+assertEquals("aa,a", res[948].exec("aab"), 2888);
+assertEquals("aaa,a", res[948].exec("aaa"), 2889);
+assertEquals("aaaaaaaa,a", res[948].exec("aaaaaaaa    "), 2890);
+assertEquals(null, res[949].exec("bcd", 2891));
+assertEquals("a,a", res[949].exec("abc"), 2892);
+assertEquals("a,a", res[949].exec("aab  "), 2893);
+assertEquals(null, res[950].exec("bcd", 2894));
+assertEquals("a,a", res[950].exec("abc"), 2895);
+assertEquals("aa,a", res[950].exec("aab  "), 2896);
+assertEquals(null, res[951].exec("bcd", 2897));
+assertEquals("a,a", res[951].exec("abc"), 2898);
+assertEquals("aa,a", res[951].exec("aab"), 2899);
+assertEquals("aaa,a", res[951].exec("aaa   "), 2900);
+assertEquals(null, res[952].exec("bcd", 2901));
+assertEquals("a,a", res[952].exec("abc"), 2902);
+assertEquals("aa,a", res[952].exec("aab"), 2903);
+assertEquals("aaa,a", res[952].exec("aaa"), 2904);
+assertEquals("aaaaaaaa,a", res[952].exec("aaaaaaaa    "), 2905);
+assertEquals("bib.gif", res[953].exec("borfle\nbib.gif\nno"), 2906);
+assertEquals("bib.gif", res[954].exec("borfle\nbib.gif\nno"), 2907);
+assertEquals("bib.gif", res[955].exec("borfle\nbib.gif\nno"), 2908);
+assertEquals("bib.gif", res[956].exec("borfle\nbib.gif\nno"), 2909);
+assertEquals("bib.gif", res[957].exec("borfle\nbib.gif\nno"), 2910);
+assertEquals("no", res[958].exec("borfle\nbib.gif\nno"), 2911);
+assertEquals("borfle", res[959].exec("borfle\nbib.gif\nno"), 2912);
+assertEquals("no", res[960].exec("borfle\nbib.gif\nno"), 2913);
+assertEquals("borfle", res[961].exec("borfle\nbib.gif\nno"), 2914);
+assertEquals("", res[962].exec("borfle\nbib.gif\nno\n"), 2915);
+assertEquals("borfle", res[963].exec("borfle\nbib.gif\nno\n"), 2916);
+assertEquals("", res[964].exec("borfle\nbib.gif\nno\n"), 2917);
+assertEquals("borfle", res[965].exec("borfle\nbib.gif\nno\n"), 2918);
+assertEquals("1234X,1234X", res[966].exec("abcde\n1234Xyz"), 2919);
+assertEquals("B,B", res[966].exec("BarFoo "), 2920);
+assertEquals(null, res[966].exec("*** Failers", 2921));
+assertEquals(null, res[966].exec("abcde\nBar  ", 2922));
+assertEquals("1234X,1234X", res[967].exec("abcde\n1234Xyz"), 2923);
+assertEquals("B,B", res[967].exec("BarFoo "), 2924);
+assertEquals("B,B", res[967].exec("abcde\nBar  "), 2925);
+assertEquals("1234X,1234X", res[968].exec("abcde\n1234Xyz"), 2926);
+assertEquals("B,B", res[968].exec("BarFoo "), 2927);
+assertEquals(null, res[968].exec("*** Failers", 2928));
+assertEquals(null, res[968].exec("abcde\nBar  ", 2929));
+assertEquals("1234X,1234X", res[969].exec("abcde\n1234Xyz"), 2930);
+assertEquals("B,B", res[969].exec("BarFoo "), 2931);
+assertEquals("B,B", res[969].exec("abcde\nBar  "), 2932);
+assertEquals("1234X,1234X", res[969].exec("abcde\n1234Xyz"), 2933);
+assertEquals("B,B", res[969].exec("BarFoo "), 2934);
+assertEquals(null, res[969].exec("*** Failers ", 2935));
+assertEquals("B,B", res[969].exec("abcde\nBar  "), 2936);
+assertEquals("1234X,1234X", res[969].exec("abcde\n1234Xyz"), 2937);
+assertEquals("B,B", res[969].exec("BarFoo "), 2938);
+assertEquals(null, res[969].exec("*** Failers ", 2939));
+assertEquals("B,B", res[969].exec("abcde\nBar  "), 2940);
+assertEquals(null, res[970].exec("**** Failers", 2941));
+assertEquals(null, res[970].exec("abc\nB", 2942));
+assertEquals(null, res[970].exec(" ", 2943));
+assertEquals(null, res[970].exec("abc\nB", 2944));
+assertEquals(null, res[970].exec("abc\nB", 2945));
+assertEquals(null, res[970].exec(" ", 2946));
+assertEquals(null, res[970].exec("abc\nB", 2947));
+assertEquals(null, res[970].exec("abc\nB", 2948));
+assertEquals("B", res[970].exec("B\n"), 2949);
+assertEquals("123456654321", res[971].exec("123456654321"), 2950);
+assertEquals("123456654321", res[972].exec("123456654321 "), 2951);
+assertEquals("123456654321", res[973].exec("123456654321"), 2952);
+assertEquals("abcabcabcabc", res[974].exec("abcabcabcabc"), 2953);
+assertEquals("abcabcabcabc", res[975].exec("abcabcabcabc"), 2954);
+assertEquals("abcabcabcabc,c", res[976].exec("abcabcabcabc "), 2955);
+assertEquals("n", res[977].exec("n"), 2956);
+assertEquals(null, res[977].exec("*** Failers ", 2957));
+assertEquals(null, res[977].exec("z ", 2958));
+assertEquals("abcd", res[978].exec("abcd"), 2959);
+assertEquals(null, res[978].exec("*** Failers", 2960));
+assertEquals(null, res[978].exec("abce  ", 2961));
+assertEquals("abe", res[979].exec("abe"), 2962);
+assertEquals(null, res[979].exec("*** Failers", 2963));
+assertEquals(null, res[979].exec("abcde ", 2964));
+assertEquals("abd,", res[980].exec("abd"), 2965);
+assertEquals(null, res[980].exec("*** Failers", 2966));
+assertEquals(null, res[980].exec("abcd   ", 2967));
+assertEquals("a,", res[981].exec("a"), 2968);
+assertEquals("ab,b", res[981].exec("ab"), 2969);
+assertEquals("abbbb,bbbb", res[981].exec("abbbb"), 2970);
+assertEquals("a,", res[981].exec("*** Failers"), 2971);
+assertEquals(null, res[981].exec("bbbbb    ", 2972));
+assertEquals("abe", res[982].exec("abe"), 2973);
+assertEquals(null, res[982].exec("*** Failers", 2974));
+assertEquals(null, res[982].exec("ab1e   ", 2975));
+assertEquals("\"quick\",quick", res[983].exec("the \"quick\" brown fox"), 2976);
+assertEquals("\"the \\\"quick\\\" brown fox\", brown fox", res[983].exec("\"the \\\"quick\\\" brown fox\" "), 2977);
+assertEquals("", res[984].exec("abc"), 2978);
+assertEquals("", res[985].exec("abc "), 2979);
+assertEquals("", res[986].exec("abc "), 2980);
+assertThrows("var re = //;", 2981);
+assertEquals("", res[986].exec("abc"), 2982);
+assertEquals("acb", res[988].exec("acb"), 2983);
+assertEquals("a\nb", res[988].exec("a\nb"), 2984);
+assertEquals("acb", res[989].exec("acb"), 2985);
+assertEquals(null, res[989].exec("*** Failers ", 2986));
+assertEquals(null, res[989].exec("a\nb   ", 2987));
+assertEquals("acb", res[990].exec("acb"), 2988);
+assertEquals("a\nb", res[990].exec("a\nb  "), 2989);
+assertEquals("acb", res[991].exec("acb"), 2990);
+assertEquals(null, res[991].exec("a\nb  ", 2991));
+assertEquals("bac,a", res[992].exec("bac"), 2992);
+assertEquals("bbac,a", res[992].exec("bbac"), 2993);
+assertEquals("bbbac,a", res[992].exec("bbbac"), 2994);
+assertEquals("bbbbac,a", res[992].exec("bbbbac"), 2995);
+assertEquals("bbbbbac,a", res[992].exec("bbbbbac "), 2996);
+assertEquals("bac,a", res[993].exec("bac"), 2997);
+assertEquals("bbac,a", res[993].exec("bbac"), 2998);
+assertEquals("bbbac,a", res[993].exec("bbbac"), 2999);
+assertEquals("bbbbac,a", res[993].exec("bbbbac"), 3000);
+assertEquals("bbbbbac,a", res[993].exec("bbbbbac "), 3001);
+assertEquals("x", res[994].exec("x\nb\n"), 3002);
+assertEquals("x", res[994].exec("a\x08x\n  "), 3003);
+assertEquals(null, res[995].exec("\x00{ab} ", 3004));
+assertEquals("CD,", res[996].exec("CD "), 3005);
+assertEquals("CD,", res[997].exec("CD "), 3006);
+assertEquals(null, res[997].exec("foo", 3007));
+assertEquals(null, res[997].exec("catfood", 3008));
+assertEquals(null, res[997].exec("arfootle", 3009));
+assertEquals(null, res[997].exec("rfoosh", 3010));
+assertEquals(null, res[997].exec("*** Failers", 3011));
+assertEquals(null, res[997].exec("barfoo", 3012));
+assertEquals(null, res[997].exec("towbarfoo", 3013));
+assertEquals(null, res[997].exec("catfood", 3014));
+assertEquals(null, res[997].exec("*** Failers", 3015));
+assertEquals(null, res[997].exec("foo", 3016));
+assertEquals(null, res[997].exec("barfoo", 3017));
+assertEquals(null, res[997].exec("towbarfoo", 3018));
+assertEquals(null, res[997].exec("fooabar", 3019));
+assertEquals(null, res[997].exec("*** Failers", 3020));
+assertEquals(null, res[997].exec("bar", 3021));
+assertEquals(null, res[997].exec("foobbar", 3022));
+assertEquals(null, res[997].exec("  ", 3023));
+assertEquals(null, res[998].exec("abc", 3024));
+assertEquals(null, res[998].exec("*** Failers", 3025));
+assertEquals(null, res[998].exec("abc\n   ", 3026));
+assertEquals(null, res[998].exec("qqq\nabc", 3027));
+assertEquals(null, res[998].exec("abc\nzzz", 3028));
+assertEquals(null, res[998].exec("qqq\nabc\nzzz", 3029));
+assertEquals(null, res[998].exec("/this/is/a/very/long/line/in/deed/with/very/many/slashes/in/it/you/see/", 3030));
+assertEquals(null, res[998].exec("/this/is/a/very/long/line/in/deed/with/very/many/slashes/in/and/foo", 3031));
+assertEquals(null, res[998].exec("1.230003938", 3032));
+assertEquals(null, res[998].exec("1.875000282", 3033));
+assertEquals(null, res[998].exec("*** Failers ", 3034));
+assertEquals(null, res[998].exec("1.235 ", 3035));
+assertEquals(null, res[998].exec("now is the time for all good men to come to the aid of the party", 3036));
+assertEquals(null, res[998].exec("*** Failers", 3037));
+assertEquals(null, res[998].exec("this is not a line with only words and spaces!", 3038));
+assertEquals("12345a,12345,a", res[999].exec("12345a"), 3039);
+assertEquals("12345,1234,5", res[999].exec("12345+ "), 3040);
+assertEquals("12345a,12345,a", res[999].exec("12345a"), 3041);
+assertEquals(null, res[999].exec("*** Failers", 3042));
+assertEquals("12345,1234,5", res[999].exec("12345+ "), 3043);
+assertEquals(null, res[999].exec("aaab", 3044));
+assertEquals(null, res[999].exec("aaab", 3045));
+assertEquals(null, res[999].exec("aaab", 3046));
+assertEquals(null, res[999].exec("aaabbbccc", 3047));
+assertEquals(null, res[999].exec("aaabbbbccccd", 3048));
+assertEquals("aaabbbbcccc,ccc", res[1000].exec("aaabbbbccccd"), 3049);
+assertEquals("abc,b", res[1000].exec("((abc(ade)ufh()()x"), 3050);
+assertEquals(null, res[1000].exec("", 3051));
+assertEquals("abc,b", res[1000].exec("(abc)"), 3052);
+assertEquals("abc,b", res[1000].exec("(abc(def)xyz)"), 3053);
+assertEquals(null, res[1000].exec("*** Failers", 3054));
+assertEquals(null, res[1000].exec("ab", 3055));
+assertEquals(null, res[1000].exec("Ab", 3056));
+assertEquals(null, res[1000].exec("*** Failers ", 3057));
+assertEquals(null, res[1000].exec("aB", 3058));
+assertEquals(null, res[1000].exec("AB", 3059));
+assertEquals(null, res[1000].exec("    ", 3060));
+assertEquals("bc,b", res[1000].exec("a bcd e"), 3061);
+assertEquals(null, res[1000].exec("*** Failers", 3062));
+assertEquals("c,", res[1000].exec("a b cd e"), 3063);
+assertEquals("abc,b", res[1000].exec("abcd e   "), 3064);
+assertEquals("bc,b", res[1000].exec("a bcde "), 3065);
+assertEquals("bc,b", res[1000].exec("a bcde f"), 3066);
+assertEquals(null, res[1000].exec("*** Failers", 3067));
+assertEquals("abc,b", res[1000].exec("abcdef  "), 3068);
+assertEquals("abc,b", res[1000].exec("abc"), 3069);
+assertEquals("c,", res[1000].exec("aBc"), 3070);
+assertEquals(null, res[1000].exec("*** Failers", 3071));
+assertEquals(null, res[1000].exec("abC", 3072));
+assertEquals(null, res[1000].exec("aBC  ", 3073));
+assertEquals("bc,b", res[1000].exec("Abc"), 3074);
+assertEquals("c,", res[1000].exec("ABc"), 3075);
+assertEquals(null, res[1000].exec("ABC", 3076));
+assertEquals(null, res[1000].exec("AbC", 3077));
+assertEquals(null, res[1000].exec("", 3078));
+assertEquals("abc,b", res[1000].exec("abc"), 3079);
+assertEquals("c,", res[1000].exec("aBc"), 3080);
+assertEquals(null, res[1000].exec("*** Failers ", 3081));
+assertEquals(null, res[1000].exec("ABC", 3082));
+assertEquals(null, res[1000].exec("abC", 3083));
+assertEquals(null, res[1000].exec("aBC", 3084));
+assertEquals(null, res[1000].exec("", 3085));
+assertEquals("c,", res[1000].exec("aBc"), 3086);
+assertEquals("c,", res[1000].exec("aBBc"), 3087);
+assertEquals(null, res[1000].exec("*** Failers ", 3088));
+assertEquals(null, res[1000].exec("aBC", 3089));
+assertEquals(null, res[1000].exec("aBBC", 3090));
+assertEquals(null, res[1000].exec("", 3091));
+assertEquals("abc,b", res[1000].exec("abcd"), 3092);
+assertEquals(null, res[1000].exec("abCd", 3093));
+assertEquals(null, res[1000].exec("*** Failers", 3094));
+assertEquals(null, res[1000].exec("aBCd", 3095));
+assertEquals("abc,b", res[1000].exec("abcD     "), 3096);
+assertEquals(null, res[1000].exec("", 3097));
+assertEquals(null, res[1000].exec("more than million", 3098));
+assertEquals(null, res[1000].exec("more than MILLION", 3099));
+assertEquals(null, res[1000].exec("more \n than Million ", 3100));
+assertEquals(null, res[1000].exec("*** Failers", 3101));
+assertEquals(null, res[1000].exec("MORE THAN MILLION    ", 3102));
+assertEquals(null, res[1000].exec("more \n than \n million ", 3103));
+assertEquals(null, res[1000].exec("more than million", 3104));
+assertEquals(null, res[1000].exec("more than MILLION", 3105));
+assertEquals(null, res[1000].exec("more \n than Million ", 3106));
+assertEquals(null, res[1000].exec("*** Failers", 3107));
+assertEquals(null, res[1000].exec("MORE THAN MILLION    ", 3108));
+assertEquals(null, res[1000].exec("more \n than \n million ", 3109));
+assertEquals(null, res[1000].exec("", 3110));
+assertEquals("abc,b", res[1000].exec("abc"), 3111);
+assertEquals("bc,b", res[1000].exec("aBbc"), 3112);
+assertEquals("c,", res[1000].exec("aBBc "), 3113);
+assertEquals(null, res[1000].exec("*** Failers", 3114));
+assertEquals("bc,b", res[1000].exec("Abc"), 3115);
+assertEquals(null, res[1000].exec("abAb    ", 3116));
+assertEquals(null, res[1000].exec("abbC ", 3117));
+assertEquals(null, res[1000].exec("", 3118));
+assertEquals("abc,b", res[1000].exec("abc"), 3119);
+assertEquals("c,", res[1000].exec("aBc"), 3120);
+assertEquals(null, res[1000].exec("*** Failers", 3121));
+assertEquals(null, res[1000].exec("Ab ", 3122));
+assertEquals(null, res[1000].exec("abC", 3123));
+assertEquals(null, res[1000].exec("aBC     ", 3124));
+assertEquals(null, res[1000].exec("", 3125));
+assertEquals("c,", res[1000].exec("abxxc"), 3126);
+assertEquals("c,", res[1000].exec("aBxxc"), 3127);
+assertEquals(null, res[1000].exec("*** Failers", 3128));
+assertEquals("c,", res[1000].exec("Abxxc"), 3129);
+assertEquals("c,", res[1000].exec("ABxxc"), 3130);
+assertEquals(null, res[1000].exec("abxxC      ", 3131));
+assertEquals("abc,b", res[1000].exec("abc:"), 3132);
+assertEquals(null, res[1000].exec("12", 3133));
+assertEquals(null, res[1000].exec("*** Failers", 3134));
+assertEquals(null, res[1000].exec("123", 3135));
+assertEquals(null, res[1000].exec("xyz    ", 3136));
+assertEquals("abc,b", res[1000].exec("abc:"), 3137);
+assertEquals(null, res[1000].exec("12", 3138));
+assertEquals(null, res[1000].exec("*** Failers", 3139));
+assertEquals(null, res[1000].exec("123", 3140));
+assertEquals(null, res[1000].exec("xyz    ", 3141));
+assertEquals(null, res[1000].exec("", 3142));
+assertEquals(null, res[1000].exec("foobar", 3143));
+assertEquals("c,", res[1000].exec("cat"), 3144);
+assertEquals("c,", res[1000].exec("fcat"), 3145);
+assertEquals("c,", res[1000].exec("focat   "), 3146);
+assertEquals(null, res[1000].exec("*** Failers", 3147));
+assertEquals("c,", res[1000].exec("foocat  "), 3148);
+assertEquals(null, res[1000].exec("foobar", 3149));
+assertEquals("c,", res[1000].exec("cat"), 3150);
+assertEquals("c,", res[1000].exec("fcat"), 3151);
+assertEquals("c,", res[1000].exec("focat   "), 3152);
+assertEquals(null, res[1000].exec("*** Failers", 3153));
+assertEquals("c,", res[1000].exec("foocat  "), 3154);
+assertEquals(null, res[1000].exec("a", 3155));
+assertEquals(null, res[1000].exec("aa", 3156));
+assertEquals(null, res[1000].exec("aaaa", 3157));
+assertEquals(null, res[1000].exec("", 3158));
+assertEquals("abc,abc", res[1001].exec("abc"), 3159);
+assertEquals("abcabc,abc", res[1001].exec("abcabc"), 3160);
+assertEquals("abcabcabc,abc", res[1001].exec("abcabcabc"), 3161);
+assertEquals(",", res[1001].exec("xyz      "), 3162);
+assertEquals("a,a", res[1002].exec("a"), 3163);
+assertEquals("aaaaa,aaaaa", res[1002].exec("aaaaa "), 3164);
+assertEquals("a,a", res[1003].exec("a"), 3165);
+assertEquals("b,b", res[1003].exec("b"), 3166);
+assertEquals("ababab,ababab", res[1003].exec("ababab"), 3167);
+assertEquals("aaaab,aaaab", res[1003].exec("aaaabcde"), 3168);
+assertEquals("bbbb,bbbb", res[1003].exec("bbbb    "), 3169);
+assertEquals("b,b", res[1004].exec("b"), 3170);
+assertEquals("bbbb,bbbb", res[1004].exec("bbbb"), 3171);
+assertEquals(",", res[1004].exec("aaa   "), 3172);
+assertEquals("cccc,cccc", res[1005].exec("cccc"), 3173);
+assertEquals(",", res[1005].exec("abab  "), 3174);
+assertEquals("a,a", res[1006].exec("a"), 3175);
+assertEquals("aaaa,a", res[1006].exec("aaaa "), 3176);
+assertEquals("a,a", res[1007].exec("a"), 3177);
+assertEquals("b,b", res[1007].exec("b"), 3178);
+assertEquals("abab,b", res[1007].exec("abab"), 3179);
+assertEquals("baba,a", res[1007].exec("baba   "), 3180);
+assertEquals("b,b", res[1008].exec("b"), 3181);
+assertEquals("bbbb,b", res[1008].exec("bbbb"), 3182);
+assertEquals(",", res[1008].exec("aaa   "), 3183);
+assertEquals("c,c", res[1009].exec("c"), 3184);
+assertEquals("cccc,c", res[1009].exec("cccc"), 3185);
+assertEquals(",", res[1009].exec("baba   "), 3186);
+assertEquals(",", res[1009].exec("a"), 3187);
+assertEquals(",", res[1009].exec("aaabcde "), 3188);
+assertEquals(",", res[1009].exec("aaaaa"), 3189);
+assertEquals(",", res[1009].exec("aabbaa "), 3190);
+assertEquals(",", res[1009].exec("aaaaa"), 3191);
+assertEquals(",", res[1009].exec("aabbaa "), 3192);
+assertEquals("12-sep-98,8", res[1009].exec("12-sep-98"), 3193);
+assertEquals("12-09-98,8", res[1009].exec("12-09-98"), 3194);
+assertEquals("*** F,F", res[1009].exec("*** Failers"), 3195);
+assertEquals("sep-12-98,8", res[1009].exec("sep-12-98"), 3196);
+assertEquals("    , ", res[1009].exec("    "), 3197);
+assertEquals("s,s", res[1009].exec("saturday"), 3198);
+assertEquals("sund,d", res[1009].exec("sunday"), 3199);
+assertEquals("S,S", res[1009].exec("Saturday"), 3200);
+assertEquals("Sund,d", res[1009].exec("Sunday"), 3201);
+assertEquals("SATURDAY,Y", res[1009].exec("SATURDAY"), 3202);
+assertEquals("SUNDAY,Y", res[1009].exec("SUNDAY"), 3203);
+assertEquals("SunD,D", res[1009].exec("SunDay"), 3204);
+assertEquals(",", res[1009].exec("abcx"), 3205);
+assertEquals(",", res[1009].exec("aBCx"), 3206);
+assertEquals(",", res[1009].exec("bbx"), 3207);
+assertEquals("BBx,x", res[1009].exec("BBx"), 3208);
+assertEquals("*** F,F", res[1009].exec("*** Failers"), 3209);
+assertEquals(",", res[1009].exec("abcX"), 3210);
+assertEquals(",", res[1009].exec("aBCX"), 3211);
+assertEquals(",", res[1009].exec("bbX"), 3212);
+assertEquals("BBX               , ", res[1009].exec("BBX               "), 3213);
+assertEquals(",", res[1009].exec("ac"), 3214);
+assertEquals(",", res[1009].exec("aC"), 3215);
+assertEquals(",", res[1009].exec("bD"), 3216);
+assertEquals("eleph,h", res[1009].exec("elephant"), 3217);
+assertEquals("Europe , ", res[1009].exec("Europe "), 3218);
+assertEquals("frog,g", res[1009].exec("frog"), 3219);
+assertEquals("Fr,r", res[1009].exec("France"), 3220);
+assertEquals("*** F,F", res[1009].exec("*** Failers"), 3221);
+assertEquals("Afric,c", res[1009].exec("Africa     "), 3222);
+assertEquals(",", res[1009].exec("ab"), 3223);
+assertEquals(",", res[1009].exec("aBd"), 3224);
+assertEquals("xy,y", res[1009].exec("xy"), 3225);
+assertEquals("xY,Y", res[1009].exec("xY"), 3226);
+assertEquals("ze,e", res[1009].exec("zebra"), 3227);
+assertEquals("Z,Z", res[1009].exec("Zambesi"), 3228);
+assertEquals("*** F,F", res[1009].exec("*** Failers"), 3229);
+assertEquals(",", res[1009].exec("aCD  "), 3230);
+assertEquals("XY  , ", res[1009].exec("XY  "), 3231);
+assertEquals("foo\n,\n", res[1009].exec("foo\nbar"), 3232);
+assertEquals("*** F,F", res[1009].exec("*** Failers"), 3233);
+assertEquals(",", res[1009].exec("bar"), 3234);
+assertEquals(",", res[1009].exec("baz\nbar   "), 3235);
+assertEquals(",", res[1009].exec("barbaz"), 3236);
+assertEquals(",", res[1009].exec("barbarbaz "), 3237);
+assertEquals("koo,o", res[1009].exec("koobarbaz "), 3238);
+assertEquals("*** F,F", res[1009].exec("*** Failers"), 3239);
+assertEquals(",", res[1009].exec("baz"), 3240);
+assertEquals("foo,o", res[1009].exec("foobarbaz "), 3241);
+assertEquals("abc", res[1012].exec("abc"), 3242);
+assertEquals("abc", res[1012].exec("xabcy"), 3243);
+assertEquals("abc", res[1012].exec("ababc"), 3244);
+assertEquals(null, res[1012].exec("*** Failers", 3245));
+assertEquals(null, res[1012].exec("xbc", 3246));
+assertEquals(null, res[1012].exec("axc", 3247));
+assertEquals(null, res[1012].exec("abx", 3248));
+assertEquals("abc", res[1013].exec("abc"), 3249);
+assertEquals("abc", res[1014].exec("abc"), 3250);
+assertEquals("abbc", res[1014].exec("abbc"), 3251);
+assertEquals("abbbbc", res[1014].exec("abbbbc"), 3252);
+assertEquals("a", res[1015].exec("abbbbc"), 3253);
+assertEquals("abbb", res[1016].exec("abbbbc"), 3254);
+assertEquals("abbbbc", res[1017].exec("abbbbc"), 3255);
+assertEquals("abbc", res[1018].exec("abbc"), 3256);
+assertEquals(null, res[1018].exec("*** Failers", 3257));
+assertEquals(null, res[1018].exec("abc", 3258));
+assertEquals(null, res[1018].exec("abq", 3259));
+assertEquals("abbbbc", res[1020].exec("abbbbc"), 3260);
+assertEquals("abbbbc", res[1021].exec("abbbbc"), 3261);
+assertEquals("abbbbc", res[1022].exec("abbbbc"), 3262);
+assertEquals("abbbbc", res[1023].exec("abbbbc"), 3263);
+assertEquals(null, res[1024].exec("*** Failers", 3264));
+assertEquals(null, res[1024].exec("abq", 3265));
+assertEquals(null, res[1024].exec("abbbbc", 3266));
+assertEquals("abbc", res[1025].exec("abbc"), 3267);
+assertEquals("abc", res[1025].exec("abc"), 3268);
+assertEquals("abc", res[1026].exec("abc"), 3269);
+assertEquals("abc", res[1028].exec("abc"), 3270);
+assertEquals("abc", res[1029].exec("abc"), 3271);
+assertEquals("abc", res[1030].exec("abc"), 3272);
+assertEquals(null, res[1030].exec("*** Failers", 3273));
+assertEquals(null, res[1030].exec("abbbbc", 3274));
+assertEquals(null, res[1030].exec("abcc", 3275));
+assertEquals("abc", res[1031].exec("abcc"), 3276);
+assertEquals("abc", res[1033].exec("aabc"), 3277);
+assertEquals(null, res[1033].exec("*** Failers", 3278));
+assertEquals("abc", res[1033].exec("aabc"), 3279);
+assertEquals(null, res[1033].exec("aabcd", 3280));
+assertEquals("", res[1034].exec("abc"), 3281);
+assertEquals("", res[1035].exec("abc"), 3282);
+assertEquals("abc", res[1036].exec("abc"), 3283);
+assertEquals("axc", res[1036].exec("axc"), 3284);
+assertEquals("axyzc", res[1037].exec("axyzc"), 3285);
+assertEquals("abd", res[1038].exec("abd"), 3286);
+assertEquals(null, res[1038].exec("*** Failers", 3287));
+assertEquals(null, res[1038].exec("axyzd", 3288));
+assertEquals(null, res[1038].exec("abc", 3289));
+assertEquals("ace", res[1039].exec("ace"), 3290);
+assertEquals("ac", res[1040].exec("aac"), 3291);
+assertEquals("a-", res[1041].exec("a-"), 3292);
+assertEquals("a-", res[1042].exec("a-"), 3293);
+assertEquals("a]", res[1043].exec("a]"), 3294);
+assertEquals(null, res[1044].exec("a]b", 3295));
+assertEquals("aed", res[1045].exec("aed"), 3296);
+assertEquals(null, res[1045].exec("*** Failers", 3297));
+assertEquals(null, res[1045].exec("abd", 3298));
+assertEquals(null, res[1045].exec("abd", 3299));
+assertEquals("adc", res[1046].exec("adc"), 3300);
+assertEquals(null, res[1047].exec("adc", 3301));
+assertEquals(null, res[1047].exec("*** Failers", 3302));
+assertEquals(null, res[1047].exec("a-c", 3303));
+assertEquals(null, res[1047].exec("a]c", 3304));
+assertEquals("a", res[1048].exec("a-"), 3305);
+assertEquals("a", res[1048].exec("-a"), 3306);
+assertEquals("a", res[1048].exec("-a-"), 3307);
+assertEquals(null, res[1049].exec("*** Failers", 3308));
+assertEquals(null, res[1049].exec("xy", 3309));
+assertEquals(null, res[1049].exec("yz", 3310));
+assertEquals(null, res[1049].exec("xyz", 3311));
+assertEquals("a", res[1050].exec("*** Failers"), 3312);
+assertEquals(null, res[1050].exec("a-", 3313));
+assertEquals(null, res[1050].exec("-a", 3314));
+assertEquals(null, res[1050].exec("-a-", 3315));
+assertEquals("y", res[1051].exec("xy"), 3316);
+assertEquals("y", res[1052].exec("yz"), 3317);
+assertEquals("y", res[1053].exec("xyz"), 3318);
+assertEquals("a", res[1054].exec("a"), 3319);
+assertEquals("-", res[1055].exec("-"), 3320);
+assertEquals("*", res[1055].exec("*** Failers"), 3321);
+assertEquals("-", res[1055].exec("-"), 3322);
+assertEquals(null, res[1055].exec("a", 3323));
+assertEquals("a b", res[1056].exec("a b"), 3324);
+assertEquals("a-b", res[1057].exec("a-b"), 3325);
+assertEquals(null, res[1057].exec("*** Failers", 3326));
+assertEquals("a-b", res[1057].exec("a-b"), 3327);
+assertEquals(null, res[1057].exec("a b", 3328));
+assertEquals("1", res[1058].exec("1"), 3329);
+assertEquals("-", res[1059].exec("-"), 3330);
+assertEquals("*", res[1059].exec("*** Failers"), 3331);
+assertEquals("-", res[1059].exec("-"), 3332);
+assertEquals(null, res[1059].exec("1", 3333));
+assertEquals("a", res[1060].exec("a"), 3334);
+assertEquals("-", res[1061].exec("-"), 3335);
+assertEquals("*", res[1061].exec("*** Failers"), 3336);
+assertEquals("-", res[1061].exec("-"), 3337);
+assertEquals(null, res[1061].exec("a", 3338));
+assertEquals("a b", res[1062].exec("a b"), 3339);
+assertEquals("a-b", res[1063].exec("a-b"), 3340);
+assertEquals(null, res[1063].exec("*** Failers", 3341));
+assertEquals("a-b", res[1063].exec("a-b"), 3342);
+assertEquals(null, res[1063].exec("a b", 3343));
+assertEquals("1", res[1064].exec("1"), 3344);
+assertEquals("-", res[1065].exec("-"), 3345);
+assertEquals("*", res[1065].exec("*** Failers"), 3346);
+assertEquals("-", res[1065].exec("-"), 3347);
+assertEquals(null, res[1065].exec("1", 3348));
+assertEquals("ab", res[1066].exec("abc"), 3349);
+assertEquals("ab", res[1066].exec("abcd"), 3350);
+assertEquals("ef,", res[1067].exec("def"), 3351);
+assertEquals("a(b", res[1069].exec("a(b"), 3352);
+assertEquals(null, res[1069].exec("ab", 3353));
+assertEquals(null, res[1069].exec("a((b", 3354));
+assertEquals(null, res[1070].exec("a\x08", 3355));
+assertEquals("a,a,a", res[1071].exec("abc"), 3356);
+assertEquals("abc,a,c", res[1072].exec("abc"), 3357);
+assertEquals("abc", res[1073].exec("aabbabc"), 3358);
+assertEquals("abc", res[1074].exec("aabbabc"), 3359);
+assertEquals("abc", res[1075].exec("abcabc"), 3360);
+assertEquals("ab,b", res[1076].exec("ab"), 3361);
+assertEquals("ab,b", res[1077].exec("ab"), 3362);
+assertEquals("ab,b", res[1078].exec("ab"), 3363);
+assertEquals("ab,b", res[1079].exec("ab"), 3364);
+assertEquals("a,a", res[1080].exec("ab"), 3365);
+assertEquals("a,a", res[1081].exec("ab"), 3366);
+assertEquals("cde", res[1082].exec("cde"), 3367);
+assertEquals(null, res[1083].exec("*** Failers", 3368));
+assertEquals(null, res[1083].exec("b", 3369));
+assertEquals("abbbcd,c", res[1085].exec("abbbcd"), 3370);
+assertEquals("abcd,a", res[1086].exec("abcd"), 3371);
+assertEquals("e", res[1087].exec("e"), 3372);
+assertEquals("ef,e", res[1088].exec("ef"), 3373);
+assertEquals("abcdefg", res[1089].exec("abcdefg"), 3374);
+assertEquals("ab", res[1090].exec("xabyabbbz"), 3375);
+assertEquals("a", res[1090].exec("xayabbbz"), 3376);
+assertEquals("cde,cd", res[1091].exec("abcde"), 3377);
+assertEquals("hij", res[1092].exec("hij"), 3378);
+assertEquals("ef,", res[1094].exec("abcdef"), 3379);
+assertEquals("bcd,b", res[1095].exec("abcd"), 3380);
+assertEquals("abc,a", res[1096].exec("abc"), 3381);
+assertEquals("abc,bc", res[1097].exec("abc"), 3382);
+assertEquals("abcd,bc,d", res[1098].exec("abcd"), 3383);
+assertEquals("abcd,bc,d", res[1099].exec("abcd"), 3384);
+assertEquals("abcd,b,cd", res[1100].exec("abcd"), 3385);
+assertEquals("adcdcde", res[1101].exec("adcdcde"), 3386);
+assertEquals(null, res[1102].exec("*** Failers", 3387));
+assertEquals(null, res[1102].exec("abcde", 3388));
+assertEquals(null, res[1102].exec("adcdcde", 3389));
+assertEquals("abc,ab", res[1103].exec("abc"), 3390);
+assertEquals("abcd,abc,a,b,d", res[1104].exec("abcd"), 3391);
+assertEquals("alpha", res[1105].exec("alpha"), 3392);
+assertEquals("bh,", res[1106].exec("abh"), 3393);
+assertEquals("effgz,effgz,", res[1107].exec("effgz"), 3394);
+assertEquals("ij,ij,j", res[1107].exec("ij"), 3395);
+assertEquals("effgz,effgz,", res[1107].exec("reffgz"), 3396);
+assertEquals(null, res[1107].exec("*** Failers", 3397));
+assertEquals(null, res[1107].exec("effg", 3398));
+assertEquals(null, res[1107].exec("bcdd", 3399));
+assertEquals("a,a,a,a,a,a,a,a,a,a,a", res[1108].exec("a"), 3400);
+assertEquals("a,a,a,a,a,a,a,a,a,a", res[1109].exec("a"), 3401);
+assertEquals(null, res[1110].exec("*** Failers", 3402));
+assertEquals(null, res[1110].exec("aa", 3403));
+assertEquals(null, res[1110].exec("uh-uh", 3404));
+assertEquals("multiple words", res[1111].exec("multiple words, yeah"), 3405);
+assertEquals("abcde,ab,de", res[1112].exec("abcde"), 3406);
+assertEquals("(a, b),a,b", res[1113].exec("(a, b)"), 3407);
+assertEquals("abcd", res[1115].exec("abcd"), 3408);
+assertEquals("abcd,bc", res[1116].exec("abcd"), 3409);
+assertEquals("ac", res[1117].exec("ac"), 3410);
+assertEquals("ABC", res[1118].exec("ABC"), 3411);
+assertEquals("ABC", res[1118].exec("XABCY"), 3412);
+assertEquals("ABC", res[1118].exec("ABABC"), 3413);
+assertEquals(null, res[1118].exec("*** Failers", 3414));
+assertEquals(null, res[1118].exec("aaxabxbaxbbx", 3415));
+assertEquals(null, res[1118].exec("XBC", 3416));
+assertEquals(null, res[1118].exec("AXC", 3417));
+assertEquals(null, res[1118].exec("ABX", 3418));
+assertEquals("ABC", res[1119].exec("ABC"), 3419);
+assertEquals("ABC", res[1120].exec("ABC"), 3420);
+assertEquals("ABBC", res[1120].exec("ABBC"), 3421);
+assertEquals("ABBBBC", res[1121].exec("ABBBBC"), 3422);
+assertEquals("ABBBBC", res[1122].exec("ABBBBC"), 3423);
+assertEquals("ABBC", res[1123].exec("ABBC"), 3424);
+assertEquals(null, res[1124].exec("*** Failers", 3425));
+assertEquals(null, res[1124].exec("ABC", 3426));
+assertEquals(null, res[1124].exec("ABQ", 3427));
+assertEquals("ABBBBC", res[1126].exec("ABBBBC"), 3428);
+assertEquals("ABBBBC", res[1127].exec("ABBBBC"), 3429);
+assertEquals("ABBBBC", res[1128].exec("ABBBBC"), 3430);
+assertEquals("ABBBBC", res[1129].exec("ABBBBC"), 3431);
+assertEquals(null, res[1130].exec("*** Failers", 3432));
+assertEquals(null, res[1130].exec("ABQ", 3433));
+assertEquals(null, res[1130].exec("ABBBBC", 3434));
+assertEquals("ABBC", res[1131].exec("ABBC"), 3435);
+assertEquals("ABC", res[1131].exec("ABC"), 3436);
+assertEquals("ABC", res[1132].exec("ABC"), 3437);
+assertEquals("ABC", res[1134].exec("ABC"), 3438);
+assertEquals("ABC", res[1135].exec("ABC"), 3439);
+assertEquals("ABC", res[1136].exec("ABC"), 3440);
+assertEquals(null, res[1136].exec("*** Failers", 3441));
+assertEquals(null, res[1136].exec("ABBBBC", 3442));
+assertEquals(null, res[1136].exec("ABCC", 3443));
+assertEquals("ABC", res[1137].exec("ABCC"), 3444);
+assertEquals("ABC", res[1139].exec("AABC"), 3445);
+assertEquals("", res[1140].exec("ABC"), 3446);
+assertEquals("", res[1141].exec("ABC"), 3447);
+assertEquals("ABC", res[1142].exec("ABC"), 3448);
+assertEquals("AXC", res[1142].exec("AXC"), 3449);
+assertEquals("AXYZC", res[1143].exec("AXYZC"), 3450);
+assertEquals(null, res[1144].exec("*** Failers", 3451));
+assertEquals("AABC", res[1144].exec("AABC"), 3452);
+assertEquals(null, res[1144].exec("AXYZD", 3453));
+assertEquals("ABD", res[1145].exec("ABD"), 3454);
+assertEquals("ACE", res[1146].exec("ACE"), 3455);
+assertEquals(null, res[1146].exec("*** Failers", 3456));
+assertEquals(null, res[1146].exec("ABC", 3457));
+assertEquals(null, res[1146].exec("ABD", 3458));
+assertEquals("AC", res[1147].exec("AAC"), 3459);
+assertEquals("A-", res[1148].exec("A-"), 3460);
+assertEquals("A-", res[1149].exec("A-"), 3461);
+assertEquals("A]", res[1150].exec("A]"), 3462);
+assertEquals(null, res[1151].exec("A]B", 3463));
+assertEquals("AED", res[1152].exec("AED"), 3464);
+assertEquals("ADC", res[1153].exec("ADC"), 3465);
+assertEquals(null, res[1153].exec("*** Failers", 3466));
+assertEquals(null, res[1153].exec("ABD", 3467));
+assertEquals(null, res[1153].exec("A-C", 3468));
+assertEquals(null, res[1154].exec("ADC", 3469));
+assertEquals("AB", res[1155].exec("ABC"), 3470);
+assertEquals("AB", res[1155].exec("ABCD"), 3471);
+assertEquals("EF,", res[1156].exec("DEF"), 3472);
+assertEquals(null, res[1157].exec("*** Failers", 3473));
+assertEquals(null, res[1157].exec("A]C", 3474));
+assertEquals(null, res[1157].exec("B", 3475));
+assertEquals("A(B", res[1158].exec("A(B"), 3476);
+assertEquals(null, res[1158].exec("AB", 3477));
+assertEquals(null, res[1158].exec("A((B", 3478));
+assertEquals(null, res[1159].exec("AB", 3479));
+assertEquals("A,A,A", res[1160].exec("ABC"), 3480);
+assertEquals("ABC,A,C", res[1161].exec("ABC"), 3481);
+assertEquals("ABC", res[1162].exec("AABBABC"), 3482);
+assertEquals("ABC", res[1163].exec("AABBABC"), 3483);
+assertEquals("ABC", res[1164].exec("ABCABC"), 3484);
+assertEquals("ABC", res[1165].exec("ABCABC"), 3485);
+assertEquals("ABC", res[1166].exec("ABCABC"), 3486);
+assertEquals("AB,B", res[1167].exec("AB"), 3487);
+assertEquals("AB,B", res[1168].exec("AB"), 3488);
+assertEquals("AB,B", res[1169].exec("AB"), 3489);
+assertEquals("AB,B", res[1170].exec("AB"), 3490);
+assertEquals("A,A", res[1171].exec("AB"), 3491);
+assertEquals("A,A", res[1172].exec("AB"), 3492);
+assertEquals(",", res[1173].exec("AB"), 3493);
+assertEquals("CDE", res[1174].exec("CDE"), 3494);
+assertEquals("ABBBCD,C", res[1177].exec("ABBBCD"), 3495);
+assertEquals("ABCD,A", res[1178].exec("ABCD"), 3496);
+assertEquals("E", res[1179].exec("E"), 3497);
+assertEquals("EF,E", res[1180].exec("EF"), 3498);
+assertEquals("ABCDEFG", res[1181].exec("ABCDEFG"), 3499);
+assertEquals("AB", res[1182].exec("XABYABBBZ"), 3500);
+assertEquals("A", res[1182].exec("XAYABBBZ"), 3501);
+assertEquals("CDE,CD", res[1183].exec("ABCDE"), 3502);
+assertEquals("HIJ", res[1184].exec("HIJ"), 3503);
+assertEquals(null, res[1185].exec("ABCDE", 3504));
+assertEquals("EF,", res[1186].exec("ABCDEF"), 3505);
+assertEquals("BCD,B", res[1187].exec("ABCD"), 3506);
+assertEquals("ABC,A", res[1188].exec("ABC"), 3507);
+assertEquals("ABC,BC", res[1189].exec("ABC"), 3508);
+assertEquals("ABCD,BC,D", res[1190].exec("ABCD"), 3509);
+assertEquals("ABCD,BC,D", res[1191].exec("ABCD"), 3510);
+assertEquals("ABCD,B,CD", res[1192].exec("ABCD"), 3511);
+assertEquals("ADCDCDE", res[1193].exec("ADCDCDE"), 3512);
+assertEquals("ABC,AB", res[1195].exec("ABC"), 3513);
+assertEquals("ABCD,ABC,A,B,D", res[1196].exec("ABCD"), 3514);
+assertEquals("ALPHA", res[1197].exec("ALPHA"), 3515);
+assertEquals("BH,", res[1198].exec("ABH"), 3516);
+assertEquals("EFFGZ,EFFGZ,", res[1199].exec("EFFGZ"), 3517);
+assertEquals("IJ,IJ,J", res[1199].exec("IJ"), 3518);
+assertEquals("EFFGZ,EFFGZ,", res[1199].exec("REFFGZ"), 3519);
+assertEquals(null, res[1199].exec("*** Failers", 3520));
+assertEquals(null, res[1199].exec("ADCDCDE", 3521));
+assertEquals(null, res[1199].exec("EFFG", 3522));
+assertEquals(null, res[1199].exec("BCDD", 3523));
+assertEquals("A,A,A,A,A,A,A,A,A,A,A", res[1200].exec("A"), 3524);
+assertEquals("A,A,A,A,A,A,A,A,A,A", res[1201].exec("A"), 3525);
+assertEquals("A,A", res[1202].exec("A"), 3526);
+assertEquals("C,C", res[1203].exec("C"), 3527);
+assertEquals(null, res[1204].exec("*** Failers", 3528));
+assertEquals(null, res[1204].exec("AA", 3529));
+assertEquals(null, res[1204].exec("UH-UH", 3530));
+assertEquals("MULTIPLE WORDS", res[1205].exec("MULTIPLE WORDS, YEAH"), 3531);
+assertEquals("ABCDE,AB,DE", res[1206].exec("ABCDE"), 3532);
+assertEquals("(A, B),A,B", res[1207].exec("(A, B)"), 3533);
+assertEquals("ABCD", res[1209].exec("ABCD"), 3534);
+assertEquals("ABCD,BC", res[1210].exec("ABCD"), 3535);
+assertEquals("AC", res[1211].exec("AC"), 3536);
+assertEquals("ad", res[1212].exec("abad"), 3537);
+assertEquals("ad", res[1213].exec("abad"), 3538);
+assertEquals("ad", res[1214].exec("abad"), 3539);
+assertEquals("ace,e", res[1215].exec("ace"), 3540);
+assertEquals("ace,e", res[1216].exec("ace"), 3541);
+assertEquals("ace,e", res[1217].exec("ace"), 3542);
+assertEquals("acd,d", res[1217].exec("acdbcdbe"), 3543);
+assertEquals("acdbcdbe,e", res[1218].exec("acdbcdbe"), 3544);
+assertEquals("acdb,b", res[1219].exec("acdbcdbe"), 3545);
+assertEquals("acdbcdb,b", res[1220].exec("acdbcdbe"), 3546);
+assertEquals("acdbcd,d", res[1221].exec("acdbcdbe"), 3547);
+assertEquals("foobar,bar,,bar", res[1222].exec("foobar"), 3548);
+assertEquals("acdbcdbe,e", res[1223].exec("acdbcdbe"), 3549);
+assertEquals("acdbcdbe,e", res[1224].exec("acdbcdbe"), 3550);
+assertEquals("acdbcdbe,e", res[1225].exec("acdbcdbe"), 3551);
+assertEquals("acdbcdb,b", res[1226].exec("acdbcdbe"), 3552);
+assertEquals("acdbcdbe,e", res[1227].exec("acdbcdbe"), 3553);
+assertEquals("acdbcdb,b", res[1228].exec("acdbcdbe"), 3554);
+assertEquals("ace,c,e", res[1229].exec("ace"), 3555);
+assertEquals("AB,A", res[1230].exec("AB"), 3556);
+assertEquals(".,.,", res[1231].exec("."), 3557);
+assertEquals("<&", res[1232].exec("<&OUT"), 3558);
+assertEquals("foobar,,,,b,a,r", res[1233].exec("foobar"), 3559);
+assertEquals(",,,,,,", res[1233].exec("ab"), 3560);
+assertEquals(",,,,,,", res[1233].exec("*** Failers"), 3561);
+assertEquals(",,,,,,", res[1233].exec("cb"), 3562);
+assertEquals(",,,,,,", res[1233].exec("b"), 3563);
+assertEquals(",,,,,,", res[1233].exec("ab"), 3564);
+assertEquals(",,,,,,", res[1233].exec("b"), 3565);
+assertEquals(",,,,,,", res[1233].exec("b"), 3566);
+assertEquals("aba", res[1234].exec("aba"), 3567);
+assertEquals("a", res[1235].exec("aba"), 3568);
+assertEquals(",", res[1236].exec("abc"), 3569);
+assertEquals("aax,a", res[1237].exec("aax"), 3570);
+assertEquals("aax,a,a", res[1238].exec("aax"), 3571);
+assertEquals("aax,a,a", res[1239].exec("aax"), 3572);
+assertEquals("ab,", res[1240].exec("cab"), 3573);
+assertEquals("ab,", res[1241].exec("cab"), 3574);
+assertEquals("ab,", res[1241].exec("ab"), 3575);
+assertEquals("ab,", res[1241].exec("ab"), 3576);
+assertEquals(null, res[1241].exec("Ab", 3577));
+assertEquals(null, res[1241].exec("Ab", 3578));
+assertEquals(null, res[1241].exec("*** Failers", 3579));
+assertEquals(null, res[1241].exec("cb", 3580));
+assertEquals(null, res[1241].exec("aB", 3581));
+assertEquals("ab,", res[1241].exec("ab"), 3582);
+assertEquals("ab,", res[1241].exec("ab"), 3583);
+assertEquals(null, res[1241].exec("Ab", 3584));
+assertEquals(null, res[1241].exec("Ab", 3585));
+assertEquals(null, res[1241].exec("*** Failers", 3586));
+assertEquals(null, res[1241].exec("aB", 3587));
+assertEquals(null, res[1241].exec("aB", 3588));
+assertEquals("ab,", res[1241].exec("ab"), 3589);
+assertEquals("ab,", res[1241].exec("ab"), 3590);
+assertEquals(null, res[1241].exec("aB", 3591));
+assertEquals(null, res[1241].exec("aB", 3592));
+assertEquals(null, res[1241].exec("*** Failers", 3593));
+assertEquals(null, res[1241].exec("aB", 3594));
+assertEquals(null, res[1241].exec("Ab", 3595));
+assertEquals(null, res[1241].exec("aB", 3596));
+assertEquals(null, res[1241].exec("aB", 3597));
+assertEquals(null, res[1241].exec("*** Failers", 3598));
+assertEquals(null, res[1241].exec("Ab", 3599));
+assertEquals(null, res[1241].exec("AB", 3600));
+assertEquals("ab,", res[1241].exec("ab"), 3601);
+assertEquals("ab,", res[1241].exec("ab"), 3602);
+assertEquals(null, res[1241].exec("aB", 3603));
+assertEquals(null, res[1241].exec("aB", 3604));
+assertEquals(null, res[1241].exec("*** Failers", 3605));
+assertEquals(null, res[1241].exec("AB", 3606));
+assertEquals(null, res[1241].exec("Ab", 3607));
+assertEquals(null, res[1241].exec("aB", 3608));
+assertEquals(null, res[1241].exec("aB", 3609));
+assertEquals(null, res[1241].exec("*** Failers", 3610));
+assertEquals(null, res[1241].exec("Ab", 3611));
+assertEquals(null, res[1241].exec("AB", 3612));
+assertEquals(null, res[1241].exec("*** Failers", 3613));
+assertEquals(null, res[1241].exec("AB", 3614));
+assertEquals(null, res[1241].exec("a\nB", 3615));
+assertEquals(null, res[1241].exec("a\nB", 3616));
+assertEquals("cabbbb", res[1242].exec("cabbbb"), 3617);
+assertEquals("caaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", res[1243].exec("caaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"), 3618);
+assertEquals("foobar1234baz", res[1244].exec("foobar1234baz"), 3619);
+assertEquals("x~~,~~", res[1245].exec("x~~"), 3620);
+assertEquals("aaac", res[1246].exec("aaac"), 3621);
+assertEquals("aaac", res[1247].exec("aaac"), 3622);
+assertEquals(null, res[1247].exec("*** Failers", 3623));
+assertEquals(null, res[1247].exec("B\nB", 3624));
+assertEquals(null, res[1247].exec("dbcb", 3625));
+assertEquals(null, res[1247].exec("dbaacb", 3626));
+assertEquals(null, res[1247].exec("dbaacb", 3627));
+assertEquals(null, res[1247].exec("cdaccb", 3628));
+assertEquals(null, res[1248].exec("*** Failers", 3629));
+assertEquals(null, res[1248].exec("dbcb", 3630));
+assertEquals(null, res[1248].exec("a--", 3631));
+assertEquals(null, res[1248].exec("a\nb\nc\n", 3632));
+assertEquals(null, res[1248].exec("a\nb\nc\n", 3633));
+assertEquals(null, res[1248].exec("a\nb\n", 3634));
+assertEquals(null, res[1248].exec("a\nb\n", 3635));
+assertEquals(null, res[1248].exec("a\nb\n", 3636));
+assertEquals(null, res[1248].exec("a\nb\n", 3637));
+assertEquals(null, res[1248].exec("a\nb\nc\n", 3638));
+assertEquals(null, res[1248].exec("a\nb\nc\n", 3639));
+assertEquals(null, res[1248].exec("a\nb\nc\n", 3640));
+assertEquals(null, res[1248].exec("a\nb\nc\n", 3641));
+assertEquals(null, res[1250].exec("*** Failers", 3642));
+assertEquals(null, res[1250].exec("a\nb\nc\n", 3643));
+assertEquals(null, res[1250].exec("a\nb\nc\n", 3644));
+assertEquals(null, res[1250].exec("a\nb\nc\n", 3645));
+assertEquals(null, res[1250].exec("a", 3646));
+assertEquals(null, res[1250].exec("*** Failers", 3647));
+assertEquals(null, res[1250].exec("a", 3648));
+assertEquals(null, res[1250].exec("a", 3649));
+assertEquals(null, res[1250].exec("a", 3650));
+assertEquals("one:,one:", res[1251].exec("one:"), 3651);
+assertEquals(null, res[1251].exec("a", 3652));
+assertEquals("abcd,,abcd", res[1252].exec("abcd"), 3653);
+assertEquals("xy:z:::abcd,xy:z:::,abcd", res[1252].exec("xy:z:::abcd"), 3654);
+assertEquals("aexyc,c", res[1253].exec("aexycd"), 3655);
+assertEquals("aab,aa", res[1254].exec("caab"), 3656);
+assertEquals("abcd,,abcd", res[1255].exec("abcd"), 3657);
+assertEquals("xy:z:::abcd,xy:z:::,abcd", res[1255].exec("xy:z:::abcd"), 3658);
+assertEquals("Failers,,Failers", res[1255].exec("*** Failers"), 3659);
+assertEquals(null, res[1255].exec("abcd:", 3660));
+assertEquals(null, res[1255].exec("abcd:", 3661));
+assertEquals("aexyc,c", res[1256].exec("aexycd"), 3662);
+assertEquals(null, res[1257].exec("aaab", 3663));
+assertEquals(":[,:[", res[1258].exec("a:[b]:"), 3664);
+assertEquals("=[,=[", res[1259].exec("a=[b]="), 3665);
+assertEquals(".[,.[", res[1260].exec("a.[b]."), 3666);
+assertEquals(null, res[1260].exec("aaab", 3667));
+assertEquals(null, res[1260].exec("aaab", 3668));
+assertEquals(null, res[1260].exec("((abc(ade)ufh()()x", 3669));
+assertEquals(null, res[1261].exec("*** Failers", 3670));
+assertEquals(null, res[1261].exec("aaab", 3671));
+assertEquals(null, res[1261].exec("a\nb\n", 3672));
+assertEquals(null, res[1262].exec("a\nb\n", 3673));
+assertEquals(null, res[1264].exec("a\nb", 3674));
+assertEquals(null, res[1265].exec("a\nb", 3675));
+assertEquals(null, res[1265].exec("*** Failers", 3676));
+assertEquals(null, res[1265].exec("alphabetabcd", 3677));
+assertEquals(null, res[1265].exec("endingwxyz", 3678));
+assertEquals(null, res[1265].exec("*** Failers", 3679));
+assertEquals(null, res[1265].exec("a rather long string that doesn't end with one of them", 3680));
+assertEquals(null, res[1265].exec("word cat dog elephant mussel cow horse canary baboon snake shark otherword", 3681));
+assertEquals(null, res[1265].exec("word cat dog elephant mussel cow horse canary baboon snake shark", 3682));
+assertEquals(null, res[1265].exec("word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope", 3683));
+assertEquals(null, res[1265].exec("999foo", 3684));
+assertEquals(null, res[1265].exec("123999foo ", 3685));
+assertEquals(null, res[1265].exec("*** Failers", 3686));
+assertEquals(null, res[1265].exec("123abcfoo", 3687));
+assertEquals(null, res[1265].exec("999foo", 3688));
+assertEquals(null, res[1265].exec("123999foo ", 3689));
+assertEquals(null, res[1265].exec("*** Failers", 3690));
+assertEquals(null, res[1265].exec("123abcfoo", 3691));
+assertEquals(null, res[1265].exec("123abcfoo", 3692));
+assertEquals(null, res[1265].exec("123456foo ", 3693));
+assertEquals(null, res[1265].exec("*** Failers", 3694));
+assertEquals(null, res[1265].exec("123999foo  ", 3695));
+assertEquals(null, res[1265].exec("123abcfoo   ", 3696));
+assertEquals(null, res[1265].exec("123456foo ", 3697));
+assertEquals(null, res[1265].exec("*** Failers", 3698));
+assertEquals(null, res[1265].exec("123999foo  ", 3699));
+assertEquals("ZA,A,", res[1266].exec("ZABCDEFG"), 3700);
+assertEquals("ZA,A,", res[1267].exec("ZABCDEFG"), 3701);
+assertEquals("ZA,A,,", res[1268].exec("ZABCDEFG"), 3702);
+assertEquals("ZA,A,,", res[1268].exec("ZABCDEFG"), 3703);
+assertEquals("ZA,A,,", res[1268].exec("ZABCDEFG"), 3704);
+assertEquals("a", res[1269].exec("abbab"), 3705);
+assertEquals("", res[1269].exec("abcde"), 3706);
+assertEquals("", res[1269].exec("-things"), 3707);
+assertEquals("", res[1269].exec("0digit"), 3708);
+assertEquals("", res[1269].exec("*** Failers"), 3709);
+assertEquals("", res[1269].exec("bcdef    "), 3710);
+assertEquals("a", res[1270].exec("abcde"), 3711);
+assertEquals("-", res[1270].exec("-things"), 3712);
+assertEquals("0", res[1270].exec("0digit"), 3713);
+assertEquals(null, res[1270].exec("*** Failers", 3714));
+assertEquals(null, res[1270].exec("bcdef    ", 3715));
+assertEquals(null, res[1271].exec("> \x09\n\x0c\x0d\x0b<", 3716));
+assertEquals(null, res[1271].exec(" ", 3717));
+assertEquals(null, res[1272].exec("> \x09\n\x0c\x0d\x0b<", 3718));
+assertEquals(null, res[1272].exec(" ", 3719));
+assertEquals(" \x09\n\x0c\x0d\x0b", res[1273].exec("> \x09\n\x0c\x0d\x0b<"), 3720);
+assertEquals(" ", res[1273].exec(" "), 3721);
+assertEquals(" \x09\n\x0c\x0d\x0b", res[1274].exec("> \x09\n\x0c\x0d\x0b<"), 3722);
+assertEquals(" ", res[1274].exec(" "), 3723);
+assertEquals(null, res[1275].exec("ab", 3724));
+assertEquals(null, res[1278].exec("abcabcabc", 3725));
+assertEquals(null, res[1278].exec("abc(*+|abc ", 3726));
+assertEquals(null, res[1279].exec("abc abcabc", 3727));
+assertEquals(null, res[1279].exec("*** Failers", 3728));
+assertEquals(null, res[1279].exec("abcabcabc  ", 3729));
+assertEquals(null, res[1280].exec("abc#not comment\n    literal     ", 3730));
+assertEquals(null, res[1281].exec("abc#not comment\n    literal     ", 3731));
+assertEquals(null, res[1282].exec("abc#not comment\n    literal     ", 3732));
+assertEquals(null, res[1283].exec("abc#not comment\n    literal     ", 3733));
+assertEquals(null, res[1284].exec("abc\\$xyz", 3734));
+assertEquals(null, res[1285].exec("abc$xyz", 3735));
+assertEquals(null, res[1286].exec("abc", 3736));
+assertEquals(null, res[1286].exec("*** Failers", 3737));
+assertEquals(null, res[1286].exec("xyzabc  ", 3738));
+assertEquals(null, res[1287].exec("abc1abc2xyzabc3", 3739));
+assertEquals("abc1", res[1288].exec("abc1abc2xyzabc3 "), 3740);
+assertEquals(null, res[1288].exec("XabcdY", 3741));
+assertEquals(null, res[1288].exec("*** Failers ", 3742));
+assertEquals(null, res[1288].exec("Xa b c d Y ", 3743));
+assertEquals("abcY", res[1288].exec("XabcY"), 3744);
+assertEquals(null, res[1288].exec("AxyzB ", 3745));
+assertEquals(null, res[1288].exec("XabCY", 3746));
+assertEquals(null, res[1288].exec("*** Failers", 3747));
+assertEquals("abcY", res[1288].exec("XabcY  "), 3748);
+assertEquals(null, res[1288].exec("abCE", 3749));
+assertEquals(null, res[1288].exec("DE", 3750));
+assertEquals(null, res[1288].exec("*** Failers", 3751));
+assertEquals("abcE", res[1288].exec("abcE"), 3752);
+assertEquals(null, res[1288].exec("abCe  ", 3753));
+assertEquals(null, res[1288].exec("dE", 3754));
+assertEquals(null, res[1288].exec("De    ", 3755));
+assertEquals(null, res[1289].exec("z", 3756));
+assertEquals(null, res[1289].exec("a", 3757));
+assertEquals(null, res[1289].exec("-", 3758));
+assertEquals(null, res[1289].exec("d", 3759));
+assertEquals(null, res[1289].exec("] ", 3760));
+assertEquals(null, res[1289].exec("*** Failers", 3761));
+assertEquals(null, res[1289].exec("b     ", 3762));
+assertEquals("z", res[1290].exec("z"), 3763);
+assertEquals("C", res[1290].exec("C "), 3764);
+assertEquals("M", res[1291].exec("M "), 3765);
+assertEquals(null, res[1292].exec("", 3766));
+assertEquals(null, res[1292].exec("REGular", 3767));
+assertEquals(null, res[1292].exec("regulaer", 3768));
+assertEquals(null, res[1292].exec("Regex  ", 3769));
+assertEquals(null, res[1292].exec("regul\ufffdr ", 3770));
+assertEquals(null, res[1292].exec("\ufffd\ufffd\ufffd\ufffd\ufffd", 3771));
+assertEquals(null, res[1292].exec("\ufffd\ufffd\ufffd\ufffd\ufffd", 3772));
+assertEquals(null, res[1292].exec("\ufffd\ufffd\ufffd\ufffd\ufffd", 3773));
+assertEquals(null, res[1292].exec("\ufffd\ufffd\ufffd\ufffd\ufffd", 3774));
+assertEquals(null, res[1292].exec("\x84XAZXB", 3775));
+assertEquals(null, res[1292].exec("123a", 3776));
+assertEquals(null, res[1292].exec("ac", 3777));
+assertEquals("b,", res[1292].exec("bbbbc"), 3778);
+assertEquals("ab,a", res[1292].exec("abc"), 3779);
+assertEquals(null, res[1292].exec("*** Failers", 3780));
+assertEquals("b,", res[1292].exec("bca"), 3781);
+assertEquals(null, res[1292].exec("", 3782));
+assertEquals("ab,a", res[1292].exec("abc"), 3783);
+assertEquals(null, res[1292].exec("*** Failers", 3784));
+assertEquals("b,", res[1292].exec("bca"), 3785);
+assertEquals("ab,a", res[1292].exec("abc"), 3786);
+assertEquals(null, res[1292].exec("*** Failers", 3787));
+assertEquals(null, res[1292].exec("def  ", 3788));
+assertEquals(null, res[1292].exec("", 3789));
+assertEquals("ab,a", res[1292].exec("abc"), 3790);
+assertEquals(null, res[1292].exec("*** Failers", 3791));
+assertEquals(null, res[1292].exec("def  ", 3792));
+assertEquals(null, res[1292].exec("", 3793));
+assertEquals("line\nbreak", res[1293].exec("this is a line\nbreak"), 3794);
+assertEquals("line\nbreak", res[1293].exec("line one\nthis is a line\nbreak in the second line "), 3795);
+assertEquals("line\nbreak", res[1294].exec("this is a line\nbreak"), 3796);
+assertEquals(null, res[1294].exec("** Failers ", 3797));
+assertEquals("line\nbreak", res[1294].exec("line one\nthis is a line\nbreak in the second line "), 3798);
+assertEquals("line\nbreak", res[1295].exec("this is a line\nbreak"), 3799);
+assertEquals(null, res[1295].exec("** Failers ", 3800));
+assertEquals("line\nbreak", res[1295].exec("line one\nthis is a line\nbreak in the second line "), 3801);
+assertEquals(null, res[1296].exec("123P", 3802));
+assertEquals(null, res[1296].exec("a4PR", 3803));
+assertEquals(null, res[1297].exec("123P", 3804));
+assertEquals(null, res[1297].exec("4PR", 3805));
+assertEquals("", res[1298].exec("a\nb\nc\n"), 3806);
+assertEquals("", res[1298].exec(" "), 3807);
+assertEquals("", res[1298].exec("A\nC\nC\n "), 3808);
+assertEquals("", res[1298].exec("AB"), 3809);
+assertEquals("", res[1298].exec("aB  "), 3810);
+assertEquals("", res[1298].exec("AB"), 3811);
+assertEquals("", res[1298].exec("aB  "), 3812);
+assertEquals("", res[1298].exec("AB"), 3813);
+assertEquals("", res[1298].exec("aB  "), 3814);
+assertEquals("", res[1298].exec("AB"), 3815);
+assertEquals("", res[1298].exec("aB  "), 3816);
+assertEquals("Content-Type:xxxxxyyy ", res[1299].exec("Content-Type:xxxxxyyy "), 3817);
+assertEquals("Content-Type:xxxxxyyyz", res[1300].exec("Content-Type:xxxxxyyyz"), 3818);
+assertEquals("Content-Type:xxxyyy ", res[1301].exec("Content-Type:xxxyyy "), 3819);
+assertEquals("Content-Type:xxxyyyz", res[1302].exec("Content-Type:xxxyyyz"), 3820);
+assertEquals("abc", res[1303].exec("xyz\nabc"), 3821);
+assertEquals("abc", res[1303].exec("xyz\nabc<lf>"), 3822);
+assertEquals("abc", res[1303].exec("xyz\x0d\nabc<lf>"), 3823);
+assertEquals("abc", res[1303].exec("xyz\x0dabc<cr>"), 3824);
+assertEquals("abc", res[1303].exec("xyz\x0d\nabc<crlf>"), 3825);
+assertEquals(null, res[1303].exec("** Failers ", 3826));
+assertEquals("abc", res[1303].exec("xyz\nabc<cr>"), 3827);
+assertEquals("abc", res[1303].exec("xyz\x0d\nabc<cr>"), 3828);
+assertEquals("abc", res[1303].exec("xyz\nabc<crlf>"), 3829);
+assertEquals("abc", res[1303].exec("xyz\x0dabc<crlf>"), 3830);
+assertEquals("abc", res[1303].exec("xyz\x0dabc<lf>"), 3831);
+assertEquals("abc", res[1304].exec("xyzabc"), 3832);
+assertEquals("abc", res[1304].exec("xyzabc\n "), 3833);
+assertEquals("abc", res[1304].exec("xyzabc\npqr "), 3834);
+assertEquals("abc", res[1304].exec("xyzabc\x0d<cr> "), 3835);
+assertEquals("abc", res[1304].exec("xyzabc\x0dpqr<cr> "), 3836);
+assertEquals("abc", res[1304].exec("xyzabc\x0d\n<crlf> "), 3837);
+assertEquals("abc", res[1304].exec("xyzabc\x0d\npqr<crlf> "), 3838);
+assertEquals(null, res[1304].exec("** Failers", 3839));
+assertEquals("abc", res[1304].exec("xyzabc\x0d "), 3840);
+assertEquals("abc", res[1304].exec("xyzabc\x0dpqr "), 3841);
+assertEquals("abc", res[1304].exec("xyzabc\x0d\n "), 3842);
+assertEquals("abc", res[1304].exec("xyzabc\x0d\npqr "), 3843);
+assertEquals("abc", res[1305].exec("xyz\x0dabcdef"), 3844);
+assertEquals("abc", res[1305].exec("xyz\nabcdef<lf>"), 3845);
+assertEquals(null, res[1305].exec("** Failers  ", 3846));
+assertEquals("abc", res[1305].exec("xyz\nabcdef"), 3847);
+assertEquals(null, res[1305].exec("   ", 3848));
+assertEquals("abc", res[1306].exec("xyz\nabcdef"), 3849);
+assertEquals("abc", res[1306].exec("xyz\x0dabcdef<cr>"), 3850);
+assertEquals(null, res[1306].exec("** Failers  ", 3851));
+assertEquals("abc", res[1306].exec("xyz\x0dabcdef"), 3852);
+assertEquals(null, res[1306].exec("   ", 3853));
+assertEquals("abc", res[1307].exec("xyz\x0d\nabcdef"), 3854);
+assertEquals("abc", res[1307].exec("xyz\x0dabcdef<cr>"), 3855);
+assertEquals(null, res[1307].exec("** Failers  ", 3856));
+assertEquals("abc", res[1307].exec("xyz\x0dabcdef"), 3857);
+assertEquals("abc", res[1308].exec("abc\ndef"), 3858);
+assertEquals("abc", res[1308].exec("abc\x0ddef"), 3859);
+assertEquals("abc", res[1308].exec("abc\x0d\ndef"), 3860);
+assertEquals("<cr>abc", res[1308].exec("<cr>abc\ndef"), 3861);
+assertEquals("<cr>abc", res[1308].exec("<cr>abc\x0ddef"), 3862);
+assertEquals("<cr>abc", res[1308].exec("<cr>abc\x0d\ndef"), 3863);
+assertEquals("<crlf>abc", res[1308].exec("<crlf>abc\ndef"), 3864);
+assertEquals("<crlf>abc", res[1308].exec("<crlf>abc\x0ddef"), 3865);
+assertEquals("<crlf>abc", res[1308].exec("<crlf>abc\x0d\ndef"), 3866);
+assertEquals(null, res[1309].exec("abc\ndef", 3867));
+assertEquals(null, res[1309].exec("abc\x0ddef", 3868));
+assertEquals(null, res[1309].exec("abc\x0d\ndef", 3869));
+assertEquals("abc=xyz\\,", res[1310].exec("abc=xyz\\\npqr"), 3870);
+assertEquals("aaaa,a,", res[1311].exec("aaaa"), 3871);
+assertEquals("aaaa", res[1312].exec("aaaa"), 3872);
+assertEquals("aaaa,a,", res[1313].exec("aaaa"), 3873);
+assertEquals("aaaa", res[1314].exec("aaaa"), 3874);
+assertEquals(null, res[1317].exec("a\x0db", 3875));
+assertEquals(null, res[1317].exec("a\nb<cr> ", 3876));
+assertEquals(null, res[1317].exec("** Failers", 3877));
+assertEquals(null, res[1317].exec("a\nb", 3878));
+assertEquals(null, res[1317].exec("a\nb<any>", 3879));
+assertEquals(null, res[1317].exec("a\x0db<cr>   ", 3880));
+assertEquals(null, res[1317].exec("a\x0db<any>   ", 3881));
+assertEquals("abc1", res[1318].exec("abc1 \nabc2 \x0babc3xx \x0cabc4 \x0dabc5xx \x0d\nabc6 \x85abc7 JUNK"), 3882);
+assertEquals("abc1", res[1319].exec("abc1\n abc2\x0b abc3\x0c abc4\x0d abc5\x0d\n abc6\x85 abc9"), 3883);
+assertEquals(null, res[1320].exec("a\nb", 3884));
+assertEquals(null, res[1320].exec("a\x0db", 3885));
+assertEquals(null, res[1320].exec("a\x0d\nb", 3886));
+assertEquals(null, res[1320].exec("a\x0bb", 3887));
+assertEquals(null, res[1320].exec("a\x0cb", 3888));
+assertEquals(null, res[1320].exec("a\x85b   ", 3889));
+assertEquals(null, res[1320].exec("** Failers", 3890));
+assertEquals(null, res[1320].exec("a\n\x0db    ", 3891));
+assertEquals("ab", res[1321].exec("ab"), 3892);
+assertEquals(null, res[1321].exec("a\nb", 3893));
+assertEquals(null, res[1321].exec("a\x0db", 3894));
+assertEquals(null, res[1321].exec("a\x0d\nb", 3895));
+assertEquals(null, res[1321].exec("a\x0bb", 3896));
+assertEquals(null, res[1321].exec("a\x0cb", 3897));
+assertEquals(null, res[1321].exec("a\x85b   ", 3898));
+assertEquals(null, res[1321].exec("a\n\x0db    ", 3899));
+assertEquals(null, res[1321].exec("a\n\x0d\x85\x0cb ", 3900));
+assertEquals(null, res[1322].exec("a\nb", 3901));
+assertEquals(null, res[1322].exec("a\x0db", 3902));
+assertEquals(null, res[1322].exec("a\x0d\nb", 3903));
+assertEquals(null, res[1322].exec("a\x0bb", 3904));
+assertEquals(null, res[1322].exec("a\x0cb", 3905));
+assertEquals(null, res[1322].exec("a\x85b   ", 3906));
+assertEquals(null, res[1322].exec("a\n\x0db    ", 3907));
+assertEquals(null, res[1322].exec("a\n\x0d\x85\x0cb ", 3908));
+assertEquals(null, res[1322].exec("** Failers", 3909));
+assertEquals(null, res[1322].exec("ab  ", 3910));
+assertEquals(null, res[1323].exec("a\nb", 3911));
+assertEquals(null, res[1323].exec("a\n\x0db", 3912));
+assertEquals(null, res[1323].exec("a\n\x0d\x85b", 3913));
+assertEquals(null, res[1323].exec("a\x0d\n\x0d\nb ", 3914));
+assertEquals(null, res[1323].exec("a\x0d\n\x0d\n\x0d\nb ", 3915));
+assertEquals(null, res[1323].exec("a\n\x0d\n\x0db", 3916));
+assertEquals(null, res[1323].exec("a\n\n\x0d\nb ", 3917));
+assertEquals(null, res[1323].exec("** Failers", 3918));
+assertEquals(null, res[1323].exec("a\n\n\n\x0db", 3919));
+assertEquals(null, res[1323].exec("a\x0d", 3920));
+assertEquals("aRb", res[1324].exec("aRb"), 3921);
+assertEquals(null, res[1324].exec("** Failers", 3922));
+assertEquals(null, res[1324].exec("a\nb  ", 3923));
+assertEquals("afoo", res[1325].exec("afoo"), 3924);
+assertEquals(null, res[1325].exec("** Failers ", 3925));
+assertEquals(null, res[1325].exec("\x0d\nfoo ", 3926));
+assertEquals(null, res[1325].exec("\nfoo ", 3927));
+assertEquals("afoo", res[1326].exec("afoo"), 3928);
+assertEquals(null, res[1326].exec("\nfoo ", 3929));
+assertEquals(null, res[1326].exec("** Failers ", 3930));
+assertEquals(null, res[1326].exec("\x0d\nfoo ", 3931));
+assertEquals("afoo", res[1327].exec("afoo"), 3932);
+assertEquals(null, res[1327].exec("** Failers ", 3933));
+assertEquals(null, res[1327].exec("\nfoo ", 3934));
+assertEquals(null, res[1327].exec("\x0d\nfoo ", 3935));
+assertEquals("afoo", res[1328].exec("afoo"), 3936);
+assertEquals(null, res[1328].exec("\x0d\nfoo ", 3937));
+assertEquals(null, res[1328].exec("\nfoo ", 3938));
+assertEquals("", res[1329].exec("abc\x0d\x0dxyz"), 3939);
+assertEquals("", res[1329].exec("abc\n\x0dxyz  "), 3940);
+assertEquals(null, res[1329].exec("** Failers ", 3941));
+assertEquals("", res[1329].exec("abc\x0d\nxyz"), 3942);
+assertEquals("X", res[1330].exec("XABC"), 3943);
+assertEquals(null, res[1330].exec("** Failers ", 3944));
+assertEquals("X", res[1330].exec("XABCB"), 3945);
+assertEquals(null, res[1330].exec("abc\x0d\n\x0d\n", 3946));
+assertEquals(null, res[1330].exec("abc\x0d\n\x0d\n", 3947));
+assertEquals(null, res[1330].exec("abc\x0d\n\x0d\n", 3948));
+assertThrows("var re = /(?|(abc)|(xyz))/;", 3949);
+assertThrows("var re = /(x)(?|(abc)|(xyz))(x)/;", 3950);
+assertEquals(null, res[1330].exec("xabcx", 3951));
+assertEquals(null, res[1330].exec("xxyzx ", 3952));
+assertThrows("var re = /(x)(?|(abc)(pqr)|(xyz))(x)/;", 3953);
+assertEquals(null, res[1330].exec("xabcpqrx", 3954));
+assertEquals(null, res[1330].exec("xxyzx ", 3955));
+assertEquals(null, res[1330].exec("abcabc", 3956));
+assertEquals(null, res[1330].exec("xyzabc ", 3957));
+assertEquals(null, res[1330].exec("** Failers ", 3958));
+assertEquals(null, res[1330].exec("xyzxyz ", 3959));
+assertEquals(null, res[1331].exec("X X\n", 3960));
+assertEquals(null, res[1331].exec("X\x09X\x0b", 3961));
+assertEquals(null, res[1331].exec("** Failers", 3962));
+assertEquals(null, res[1331].exec("\xa0 X\n   ", 3963));
+assertEquals(null, res[1332].exec("\x09 \xa0X\n\x0b\x0c\x0d\n", 3964));
+assertEquals(null, res[1332].exec("\x09 \xa0\n\x0b\x0c\x0d\n", 3965));
+assertEquals(null, res[1332].exec("\x09 \xa0\n\x0b\x0c", 3966));
+assertEquals(null, res[1332].exec("** Failers ", 3967));
+assertEquals(null, res[1332].exec("\x09 \xa0\n\x0b", 3968));
+assertEquals(null, res[1332].exec(" ", 3969));
+assertEquals(null, res[1333].exec("XY  ABCDE", 3970));
+assertEquals(null, res[1333].exec("XY  PQR ST ", 3971));
+assertEquals(null, res[1334].exec("XY  AB    PQRS", 3972));
+assertEquals(null, res[1335].exec(">XNNNYZ", 3973));
+assertEquals(null, res[1335].exec(">  X NYQZ", 3974));
+assertEquals(null, res[1335].exec("** Failers", 3975));
+assertEquals(null, res[1335].exec(">XYZ   ", 3976));
+assertEquals(null, res[1335].exec(">  X NY Z", 3977));
+assertEquals(null, res[1336].exec(">XY\nZ\nA\x0bNN\x0c", 3978));
+assertEquals(null, res[1336].exec(">\n\x0dX\nY\n\x0bZZZ\nAAA\x0bNNN\x0c", 3979));
+assertEquals(null, res[1337].exec("\x0d\nA", 3980));
+assertEquals("\nA", res[1338].exec("\x0d\nA "), 3981);
+assertEquals("\nA", res[1339].exec("\x0d\nA "), 3982);
+assertEquals("\nA,\n", res[1340].exec("\x0d\nA "), 3983);
+assertEquals(null, res[1341].exec("a\x0db", 3984));
+assertEquals(null, res[1341].exec("a\nb", 3985));
+assertEquals(null, res[1341].exec("a\x0d\nb", 3986));
+assertEquals(null, res[1341].exec("** Failers", 3987));
+assertEquals(null, res[1341].exec("a\x85b", 3988));
+assertEquals(null, res[1341].exec("a\x0bb     ", 3989));
+assertEquals(null, res[1342].exec("a\x0db", 3990));
+assertEquals(null, res[1342].exec("a\nb", 3991));
+assertEquals(null, res[1342].exec("a\x0d\nb", 3992));
+assertEquals(null, res[1342].exec("a\x85b", 3993));
+assertEquals(null, res[1342].exec("a\x0bb     ", 3994));
+assertEquals(null, res[1342].exec("** Failers ", 3995));
+assertEquals(null, res[1342].exec("a\x85b<bsr_anycrlf>", 3996));
+assertEquals(null, res[1342].exec("a\x0bb<bsr_anycrlf>", 3997));
+assertEquals(null, res[1343].exec("a\x0db", 3998));
+assertEquals(null, res[1343].exec("a\nb", 3999));
+assertEquals(null, res[1343].exec("a\x0d\nb", 4000));
+assertEquals(null, res[1343].exec("** Failers", 4001));
+assertEquals(null, res[1343].exec("a\x85b", 4002));
+assertEquals(null, res[1343].exec("a\x0bb     ", 4003));
+assertEquals(null, res[1344].exec("a\x0db", 4004));
+assertEquals(null, res[1344].exec("a\nb", 4005));
+assertEquals(null, res[1344].exec("a\x0d\nb", 4006));
+assertEquals(null, res[1344].exec("a\x85b", 4007));
+assertEquals(null, res[1344].exec("a\x0bb     ", 4008));
+assertEquals(null, res[1344].exec("** Failers ", 4009));
+assertEquals(null, res[1344].exec("a\x85b<bsr_anycrlf>", 4010));
+assertEquals(null, res[1344].exec("a\x0bb<bsr_anycrlf>", 4011));
+assertEquals(null, res[1345].exec("a\x0d\n\nb", 4012));
+assertEquals(null, res[1345].exec("a\n\x0d\x0db", 4013));
+assertEquals(null, res[1345].exec("a\x0d\n\x0d\n\x0d\n\x0d\nb", 4014));
+assertEquals(null, res[1345].exec("** Failers", 4015));
+assertEquals(null, res[1345].exec("a\x8585b", 4016));
+assertEquals(null, res[1345].exec("a\x0b\x00bb     ", 4017));
+assertEquals(null, res[1346].exec("a\x0d\x0db", 4018));
+assertEquals(null, res[1346].exec("a\n\n\nb", 4019));
+assertEquals(null, res[1346].exec("a\x0d\n\n\x0d\x0db", 4020));
+assertEquals(null, res[1346].exec("a\x8585b", 4021));
+assertEquals(null, res[1346].exec("a\x0b\x00bb     ", 4022));
+assertEquals(null, res[1346].exec("** Failers ", 4023));
+assertEquals(null, res[1346].exec("a\x0d\x0d\x0d\x0d\x0db ", 4024));
+assertEquals(null, res[1346].exec("a\x8585b<bsr_anycrlf>", 4025));
+assertEquals(null, res[1346].exec("a\x0b\x00bb<bsr_anycrlf>", 4026));
+assertEquals("abc", res[1347].exec("abc "), 4027);
+assertEquals(null, res[1348].exec("** Failers", 4028));
+assertEquals(null, res[1348].exec("ab", 4029));
+assertEquals(null, res[1349].exec("** Failers", 4030));
+assertEquals(null, res[1349].exec("ab ", 4031));
+assertEquals(null, res[1349].exec("** Failers", 4032));
+assertEquals(null, res[1349].exec("ab ", 4033));
+assertEquals("aXb", res[1350].exec("aXb"), 4034);
+assertEquals("a\nb", res[1350].exec("a\nb "), 4035);
+assertEquals(null, res[1350].exec("** Failers", 4036));
+assertEquals(null, res[1350].exec("ab  ", 4037));
+assertEquals("aXb", res[1351].exec("aXb"), 4038);
+assertEquals("a\nX\nXb", res[1351].exec("a\nX\nXb "), 4039);
+assertEquals(null, res[1351].exec("** Failers", 4040));
+assertEquals(null, res[1351].exec("ab  ", 4041));
+assertEquals(null, res[1352].exec("ab", 4042));
+assertEquals(null, res[1352].exec("ax{100}b  ", 4043));
+assertEquals(null, res[1352].exec("ax{100}x{100}b  ", 4044));
+assertEquals(null, res[1352].exec("ax{100}b  ", 4045));
+assertEquals(null, res[1352].exec("ax{100}x{100}b  ", 4046));
+assertEquals(null, res[1352].exec("*** Failers ", 4047));
+assertEquals(null, res[1352].exec("ab", 4048));
+assertEquals(null, res[1352].exec(" ", 4049));
+assertEquals("X", res[1353].exec("Xoanon"), 4050);
+assertEquals("X", res[1353].exec("+Xoanon"), 4051);
+assertEquals("X", res[1353].exec("x{300}Xoanon "), 4052);
+assertEquals(null, res[1353].exec("*** Failers ", 4053));
+assertEquals(null, res[1353].exec("YXoanon  ", 4054));
+assertEquals("X", res[1354].exec("YXoanon"), 4055);
+assertEquals(null, res[1354].exec("*** Failers", 4056));
+assertEquals(null, res[1354].exec("Xoanon", 4057));
+assertEquals(null, res[1354].exec("+Xoanon    ", 4058));
+assertEquals(null, res[1354].exec("x{300}Xoanon ", 4059));
+assertEquals("X", res[1355].exec("X+oanon"), 4060);
+assertEquals(null, res[1355].exec("ZXx{300}oanon ", 4061));
+assertEquals("X", res[1355].exec("FAX "), 4062);
+assertEquals(null, res[1355].exec("*** Failers ", 4063));
+assertEquals(null, res[1355].exec("Xoanon  ", 4064));
+assertEquals("X", res[1356].exec("Xoanon  "), 4065);
+assertEquals(null, res[1356].exec("*** Failers", 4066));
+assertEquals(null, res[1356].exec("X+oanon", 4067));
+assertEquals("X", res[1356].exec("ZXx{300}oanon "), 4068);
+assertEquals(null, res[1356].exec("FAX ", 4069));
+assertEquals("b", res[1357].exec("abcd"), 4070);
+assertEquals("x", res[1357].exec("ax{100}   "), 4071);
+assertEquals("b", res[1357].exec("ab99"), 4072);
+assertEquals("x", res[1357].exec("x{123}x{123}45"), 4073);
+assertEquals("x", res[1357].exec("x{400}x{401}x{402}6  "), 4074);
+assertEquals("*", res[1357].exec("*** Failers"), 4075);
+assertEquals("d", res[1357].exec("d99"), 4076);
+assertEquals("x", res[1357].exec("x{123}x{122}4   "), 4077);
+assertEquals("x", res[1357].exec("x{400}x{403}6  "), 4078);
+assertEquals("x", res[1357].exec("x{400}x{401}x{402}x{402}6  "), 4079);
+assertEquals(null, res[1358].exec("\ufffd]", 4080));
+assertEquals(null, res[1358].exec("\ufffd", 4081));
+assertEquals(null, res[1358].exec("\ufffd\ufffd\ufffd", 4082));
+assertEquals(null, res[1358].exec("\ufffd\ufffd\ufffd?", 4083));
+assertEquals("acb", res[1359].exec("acb"), 4084);
+assertEquals("ab", res[1359].exec("ab"), 4085);
+assertEquals(null, res[1359].exec("ax{100}b ", 4086));
+assertEquals(null, res[1359].exec("*** Failers", 4087));
+assertEquals(null, res[1359].exec("a\nb  ", 4088));
+assertEquals(null, res[1360].exec("ax{4000}xyb ", 4089));
+assertEquals(null, res[1360].exec("ax{4000}yb ", 4090));
+assertEquals(null, res[1360].exec("ax{4000}x{100}yb ", 4091));
+assertEquals(null, res[1360].exec("*** Failers", 4092));
+assertEquals(null, res[1360].exec("ax{4000}b ", 4093));
+assertEquals(null, res[1360].exec("ac\ncb ", 4094));
+assertEquals("a\xc0,,\xc0", res[1361].exec("a\xc0\x88b"), 4095);
+assertEquals("ax,,x", res[1362].exec("ax{100}b"), 4096);
+assertEquals("a\xc0\x88b,\xc0\x88,b", res[1363].exec("a\xc0\x88b"), 4097);
+assertEquals("ax{100}b,x{100},b", res[1364].exec("ax{100}b"), 4098);
+assertEquals("a\xc0\x92,\xc0,\x92", res[1365].exec("a\xc0\x92bcd"), 4099);
+assertEquals("ax{,x,{", res[1366].exec("ax{240}bcd"), 4100);
+assertEquals("a\xc0\x92,\xc0,\x92", res[1367].exec("a\xc0\x92bcd"), 4101);
+assertEquals("ax{,x,{", res[1368].exec("ax{240}bcd"), 4102);
+assertEquals("a\xc0,,\xc0", res[1369].exec("a\xc0\x92bcd"), 4103);
+assertEquals("ax,,x", res[1370].exec("ax{240}bcd"), 4104);
+assertEquals(null, res[1371].exec("ax{1234}xyb ", 4105));
+assertEquals(null, res[1371].exec("ax{1234}x{4321}yb ", 4106));
+assertEquals(null, res[1371].exec("ax{1234}x{4321}x{3412}b ", 4107));
+assertEquals(null, res[1371].exec("*** Failers", 4108));
+assertEquals(null, res[1371].exec("ax{1234}b ", 4109));
+assertEquals(null, res[1371].exec("ac\ncb ", 4110));
+assertEquals("ax{1234}xyb,x{1234}xy", res[1372].exec("ax{1234}xyb "), 4111);
+assertEquals("ax{1234}x{4321}yb,x{1234}x{4321}y", res[1372].exec("ax{1234}x{4321}yb "), 4112);
+assertEquals("ax{1234}x{4321}x{3412}b,x{1234}x{4321}x{3412}", res[1372].exec("ax{1234}x{4321}x{3412}b "), 4113);
+assertEquals("axxxxbcdefghijb,xxxxbcdefghij", res[1372].exec("axxxxbcdefghijb "), 4114);
+assertEquals("ax{1234}x{4321}x{3412}x{3421}b,x{1234}x{4321}x{3412}x{3421}", res[1372].exec("ax{1234}x{4321}x{3412}x{3421}b "), 4115);
+assertEquals(null, res[1372].exec("*** Failers", 4116));
+assertEquals("ax{1234}b,x{1234}", res[1372].exec("ax{1234}b "), 4117);
+assertEquals("ax{1234}xyb,x{1234}xy", res[1373].exec("ax{1234}xyb "), 4118);
+assertEquals("ax{1234}x{4321}yb,x{1234}x{4321}y", res[1373].exec("ax{1234}x{4321}yb "), 4119);
+assertEquals("ax{1234}x{4321}x{3412}b,x{1234}x{4321}x{3412}", res[1373].exec("ax{1234}x{4321}x{3412}b "), 4120);
+assertEquals("axxxxb,xxxx", res[1373].exec("axxxxbcdefghijb "), 4121);
+assertEquals("ax{1234}x{4321}x{3412}x{3421}b,x{1234}x{4321}x{3412}x{3421}", res[1373].exec("ax{1234}x{4321}x{3412}x{3421}b "), 4122);
+assertEquals(null, res[1373].exec("*** Failers", 4123));
+assertEquals("ax{1234}b,x{1234}", res[1373].exec("ax{1234}b "), 4124);
+assertEquals(null, res[1374].exec("ax{1234}xyb ", 4125));
+assertEquals(null, res[1374].exec("ax{1234}x{4321}yb ", 4126));
+assertEquals(null, res[1374].exec("ax{1234}x{4321}x{3412}b ", 4127));
+assertEquals("axxxxb,xxxx", res[1374].exec("axxxxbcdefghijb "), 4128);
+assertEquals(null, res[1374].exec("ax{1234}x{4321}x{3412}x{3421}b ", 4129));
+assertEquals("axbxxb,xbxx", res[1374].exec("axbxxbcdefghijb "), 4130);
+assertEquals("axxxxxb,xxxxx", res[1374].exec("axxxxxbcdefghijb "), 4131);
+assertEquals(null, res[1374].exec("*** Failers", 4132));
+assertEquals(null, res[1374].exec("ax{1234}b ", 4133));
+assertEquals(null, res[1374].exec("axxxxxxbcdefghijb ", 4134));
+assertEquals(null, res[1375].exec("ax{1234}xyb ", 4135));
+assertEquals(null, res[1375].exec("ax{1234}x{4321}yb ", 4136));
+assertEquals(null, res[1375].exec("ax{1234}x{4321}x{3412}b ", 4137));
+assertEquals("axxxxb,xxxx", res[1375].exec("axxxxbcdefghijb "), 4138);
+assertEquals(null, res[1375].exec("ax{1234}x{4321}x{3412}x{3421}b ", 4139));
+assertEquals("axbxxb,xbxx", res[1375].exec("axbxxbcdefghijb "), 4140);
+assertEquals("axxxxxb,xxxxx", res[1375].exec("axxxxxbcdefghijb "), 4141);
+assertEquals(null, res[1375].exec("*** Failers", 4142));
+assertEquals(null, res[1375].exec("ax{1234}b ", 4143));
+assertEquals(null, res[1375].exec("axxxxxxbcdefghijb ", 4144));
+assertEquals(null, res[1375].exec("*** Failers", 4145));
+assertEquals(null, res[1375].exec("x{100}", 4146));
+assertEquals(null, res[1375].exec("aXbcd", 4147));
+assertEquals(null, res[1375].exec("ax{100}bcd", 4148));
+assertEquals(null, res[1375].exec("ax{100000}bcd", 4149));
+assertEquals(null, res[1375].exec("x{100}x{100}x{100}b", 4150));
+assertEquals(null, res[1375].exec("*** Failers ", 4151));
+assertEquals(null, res[1375].exec("x{100}x{100}b", 4152));
+assertEquals(null, res[1375].exec("x{ab} ", 4153));
+assertEquals(null, res[1375].exec("\xc2\xab", 4154));
+assertEquals(null, res[1375].exec("*** Failers ", 4155));
+assertEquals(null, res[1375].exec("\x00{ab}", 4156));
+assertEquals(null, res[1375].exec("WXYZ", 4157));
+assertEquals(null, res[1375].exec("x{256}XYZ ", 4158));
+assertEquals(null, res[1375].exec("*** Failers", 4159));
+assertEquals(null, res[1375].exec("XYZ ", 4160));
+assertEquals("bcd", res[1376].exec("bcd"), 4161);
+assertEquals("00}", res[1376].exec("x{100}aYx{256}Z "), 4162);
+assertEquals("x{", res[1377].exec("x{100}bc"), 4163);
+assertEquals("x{100}bcA", res[1378].exec("x{100}bcAa"), 4164);
+assertEquals("x{", res[1379].exec("x{100}bca"), 4165);
+assertEquals("bcd", res[1380].exec("bcd"), 4166);
+assertEquals("00}", res[1380].exec("x{100}aYx{256}Z "), 4167);
+assertEquals("x{", res[1381].exec("x{100}bc"), 4168);
+assertEquals("x{100}bc", res[1382].exec("x{100}bcAa"), 4169);
+assertEquals("x{", res[1383].exec("x{100}bca"), 4170);
+assertEquals(null, res[1383].exec("abcd", 4171));
+assertEquals(null, res[1383].exec("abcd", 4172));
+assertEquals("x{", res[1383].exec("x{100}x{100} "), 4173);
+assertEquals("x{", res[1383].exec("x{100}x{100} "), 4174);
+assertEquals("x{", res[1383].exec("x{100}x{100}x{100}x{100} "), 4175);
+assertEquals(null, res[1383].exec("abce", 4176));
+assertEquals("x{", res[1383].exec("x{100}x{100}x{100}x{100} "), 4177);
+assertEquals(null, res[1383].exec("abcdx{100}x{100}x{100}x{100} ", 4178));
+assertEquals(null, res[1383].exec("abcdx{100}x{100}x{100}x{100} ", 4179));
+assertEquals(null, res[1383].exec("abcdx{100}x{100}x{100}x{100} ", 4180));
+assertEquals(null, res[1383].exec("abcdx{100}x{100}x{100}XX", 4181));
+assertEquals(null, res[1383].exec("abcdx{100}x{100}x{100}x{100}x{100}x{100}x{100}XX", 4182));
+assertEquals(null, res[1383].exec("abcdx{100}x{100}x{100}x{100}x{100}x{100}x{100}XX", 4183));
+assertEquals("Xy", res[1383].exec("Xyyyax{100}x{100}bXzzz"), 4184);
+assertEquals("X", res[1386].exec("1X2"), 4185);
+assertEquals("x", res[1386].exec("1x{100}2 "), 4186);
+assertEquals(">X", res[1387].exec("> >X Y"), 4187);
+assertEquals(">x", res[1387].exec("> >x{100} Y"), 4188);
+assertEquals("1", res[1388].exec("x{100}3"), 4189);
+assertEquals(" ", res[1389].exec("x{100} X"), 4190);
+assertEquals("abcd", res[1390].exec("12abcd34"), 4191);
+assertEquals("*** Failers", res[1390].exec("*** Failers"), 4192);
+assertEquals("  ", res[1390].exec("1234  "), 4193);
+assertEquals("abc", res[1391].exec("12abcd34"), 4194);
+assertEquals("ab", res[1391].exec("12ab34"), 4195);
+assertEquals("***", res[1391].exec("*** Failers  "), 4196);
+assertEquals(null, res[1391].exec("1234", 4197));
+assertEquals("  ", res[1391].exec("12a34  "), 4198);
+assertEquals("ab", res[1392].exec("12abcd34"), 4199);
+assertEquals("ab", res[1392].exec("12ab34"), 4200);
+assertEquals("**", res[1392].exec("*** Failers  "), 4201);
+assertEquals(null, res[1392].exec("1234", 4202));
+assertEquals("  ", res[1392].exec("12a34  "), 4203);
+assertEquals("12", res[1393].exec("12abcd34"), 4204);
+assertEquals(null, res[1393].exec("*** Failers", 4205));
+assertEquals("12", res[1394].exec("12abcd34"), 4206);
+assertEquals("123", res[1394].exec("1234abcd"), 4207);
+assertEquals(null, res[1394].exec("*** Failers  ", 4208));
+assertEquals(null, res[1394].exec("1.4 ", 4209));
+assertEquals("12", res[1395].exec("12abcd34"), 4210);
+assertEquals("12", res[1395].exec("1234abcd"), 4211);
+assertEquals(null, res[1395].exec("*** Failers  ", 4212));
+assertEquals(null, res[1395].exec("1.4 ", 4213));
+assertEquals("12abcd34", res[1396].exec("12abcd34"), 4214);
+assertEquals("***", res[1396].exec("*** Failers"), 4215);
+assertEquals(null, res[1396].exec("     ", 4216));
+assertEquals("12a", res[1397].exec("12abcd34"), 4217);
+assertEquals("123", res[1397].exec("1234abcd"), 4218);
+assertEquals("***", res[1397].exec("*** Failers"), 4219);
+assertEquals(null, res[1397].exec("       ", 4220));
+assertEquals("12", res[1398].exec("12abcd34"), 4221);
+assertEquals("12", res[1398].exec("1234abcd"), 4222);
+assertEquals("**", res[1398].exec("*** Failers"), 4223);
+assertEquals(null, res[1398].exec("       ", 4224));
+assertEquals(">      <", res[1399].exec("12>      <34"), 4225);
+assertEquals(null, res[1399].exec("*** Failers", 4226));
+assertEquals(">  <", res[1400].exec("ab>  <cd"), 4227);
+assertEquals(">   <", res[1400].exec("ab>   <ce"), 4228);
+assertEquals(null, res[1400].exec("*** Failers", 4229));
+assertEquals(null, res[1400].exec("ab>    <cd ", 4230));
+assertEquals(">  <", res[1401].exec("ab>  <cd"), 4231);
+assertEquals(">   <", res[1401].exec("ab>   <ce"), 4232);
+assertEquals(null, res[1401].exec("*** Failers", 4233));
+assertEquals(null, res[1401].exec("ab>    <cd ", 4234));
+assertEquals("12", res[1402].exec("12      34"), 4235);
+assertEquals("Failers", res[1402].exec("*** Failers"), 4236);
+assertEquals(null, res[1402].exec("+++=*! ", 4237));
+assertEquals("ab", res[1403].exec("ab  cd"), 4238);
+assertEquals("abc", res[1403].exec("abcd ce"), 4239);
+assertEquals("Fai", res[1403].exec("*** Failers"), 4240);
+assertEquals(null, res[1403].exec("a.b.c", 4241));
+assertEquals("ab", res[1404].exec("ab  cd"), 4242);
+assertEquals("ab", res[1404].exec("abcd ce"), 4243);
+assertEquals("Fa", res[1404].exec("*** Failers"), 4244);
+assertEquals(null, res[1404].exec("a.b.c", 4245));
+assertEquals("====", res[1405].exec("12====34"), 4246);
+assertEquals("*** ", res[1405].exec("*** Failers"), 4247);
+assertEquals(" ", res[1405].exec("abcd "), 4248);
+assertEquals("===", res[1406].exec("ab====cd"), 4249);
+assertEquals("==", res[1406].exec("ab==cd"), 4250);
+assertEquals("***", res[1406].exec("*** Failers"), 4251);
+assertEquals(null, res[1406].exec("a.b.c", 4252));
+assertEquals("==", res[1407].exec("ab====cd"), 4253);
+assertEquals("==", res[1407].exec("ab==cd"), 4254);
+assertEquals("**", res[1407].exec("*** Failers"), 4255);
+assertEquals(null, res[1407].exec("a.b.c", 4256));
+assertEquals(null, res[1407].exec("x{100}", 4257));
+assertEquals(null, res[1407].exec("Zx{100}", 4258));
+assertEquals(null, res[1407].exec("x{100}Z", 4259));
+assertEquals("**", res[1407].exec("*** Failers "), 4260);
+assertEquals(null, res[1407].exec("Zx{100}", 4261));
+assertEquals(null, res[1407].exec("x{100}", 4262));
+assertEquals(null, res[1407].exec("x{100}Z", 4263));
+assertEquals("**", res[1407].exec("*** Failers "), 4264);
+assertEquals(null, res[1407].exec("abcx{200}X", 4265));
+assertEquals(null, res[1407].exec("abcx{100}X ", 4266));
+assertEquals("**", res[1407].exec("*** Failers"), 4267);
+assertEquals("  ", res[1407].exec("X  "), 4268);
+assertEquals(null, res[1407].exec("abcx{200}X", 4269));
+assertEquals(null, res[1407].exec("abcx{100}X ", 4270));
+assertEquals(null, res[1407].exec("abQX ", 4271));
+assertEquals("**", res[1407].exec("*** Failers"), 4272);
+assertEquals("  ", res[1407].exec("X  "), 4273);
+assertEquals(null, res[1407].exec("abcx{100}x{200}x{100}X", 4274));
+assertEquals("**", res[1407].exec("*** Failers"), 4275);
+assertEquals(null, res[1407].exec("abcx{200}X", 4276));
+assertEquals("  ", res[1407].exec("X  "), 4277);
+assertEquals(null, res[1407].exec("AX", 4278));
+assertEquals(null, res[1407].exec("x{150}X", 4279));
+assertEquals(null, res[1407].exec("x{500}X ", 4280));
+assertEquals("**", res[1407].exec("*** Failers"), 4281);
+assertEquals(null, res[1407].exec("x{100}X", 4282));
+assertEquals("  ", res[1407].exec("x{200}X   "), 4283);
+assertEquals(null, res[1407].exec("AX", 4284));
+assertEquals(null, res[1407].exec("x{150}X", 4285));
+assertEquals(null, res[1407].exec("x{500}X ", 4286));
+assertEquals("**", res[1407].exec("*** Failers"), 4287);
+assertEquals(null, res[1407].exec("x{100}X", 4288));
+assertEquals("  ", res[1407].exec("x{200}X   "), 4289);
+assertEquals(null, res[1407].exec("QX ", 4290));
+assertEquals(null, res[1407].exec("AX", 4291));
+assertEquals(null, res[1407].exec("x{500}X ", 4292));
+assertEquals("**", res[1407].exec("*** Failers"), 4293);
+assertEquals(null, res[1407].exec("x{100}X", 4294));
+assertEquals(null, res[1407].exec("x{150}X", 4295));
+assertEquals("  ", res[1407].exec("x{200}X   "), 4296);
+assertEquals(null, res[1407].exec("z", 4297));
+assertEquals(null, res[1407].exec("Z ", 4298));
+assertEquals(null, res[1407].exec("x{100}", 4299));
+assertEquals("**", res[1407].exec("*** Failers"), 4300);
+assertEquals(null, res[1407].exec("x{102}", 4301));
+assertEquals("  ", res[1407].exec("y    "), 4302);
+assertEquals("\xff", res[1408].exec(">\xff<"), 4303);
+assertEquals(null, res[1409].exec(">x{ff}<", 4304));
+assertEquals("X", res[1410].exec("XYZ"), 4305);
+assertEquals("X", res[1411].exec("XYZ"), 4306);
+assertEquals("x", res[1411].exec("x{123} "), 4307);
+assertEquals(",", res[1416].exec("catac"), 4308);
+assertEquals(",", res[1416].exec("ax{256}a "), 4309);
+assertEquals(",", res[1416].exec("x{85}"), 4310);
+assertEquals("abc1", res[1417].exec("abc1 \nabc2 \x0babc3xx \x0cabc4 \x0dabc5xx \x0d\nabc6 x{0085}abc7 x{2028}abc8 x{2029}abc9 JUNK"), 4311);
+assertEquals("abc1", res[1418].exec("abc1\n abc2\x0b abc3\x0c abc4\x0d abc5\x0d\n abc6x{0085} abc7x{2028} abc8x{2029} abc9"), 4312);
+assertEquals(null, res[1419].exec("a\nb", 4313));
+assertEquals(null, res[1419].exec("a\x0db", 4314));
+assertEquals(null, res[1419].exec("a\x0d\nb", 4315));
+assertEquals(null, res[1419].exec("a\x0bb", 4316));
+assertEquals(null, res[1419].exec("a\x0cb", 4317));
+assertEquals(null, res[1419].exec("ax{85}b   ", 4318));
+assertEquals(null, res[1419].exec("ax{2028}b ", 4319));
+assertEquals(null, res[1419].exec("ax{2029}b ", 4320));
+assertEquals(null, res[1419].exec("** Failers", 4321));
+assertEquals(null, res[1419].exec("a\n\x0db    ", 4322));
+assertEquals("ab", res[1420].exec("ab"), 4323);
+assertEquals(null, res[1420].exec("a\nb", 4324));
+assertEquals(null, res[1420].exec("a\x0db", 4325));
+assertEquals(null, res[1420].exec("a\x0d\nb", 4326));
+assertEquals(null, res[1420].exec("a\x0bb", 4327));
+assertEquals(null, res[1420].exec("a\x0cx{2028}x{2029}b", 4328));
+assertEquals(null, res[1420].exec("ax{85}b   ", 4329));
+assertEquals(null, res[1420].exec("a\n\x0db    ", 4330));
+assertEquals(null, res[1420].exec("a\n\x0dx{85}\x0cb ", 4331));
+assertEquals(null, res[1421].exec("a\nb", 4332));
+assertEquals(null, res[1421].exec("a\x0db", 4333));
+assertEquals(null, res[1421].exec("a\x0d\nb", 4334));
+assertEquals(null, res[1421].exec("a\x0bb", 4335));
+assertEquals(null, res[1421].exec("a\x0cx{2028}x{2029}b", 4336));
+assertEquals(null, res[1421].exec("ax{85}b   ", 4337));
+assertEquals(null, res[1421].exec("a\n\x0db    ", 4338));
+assertEquals(null, res[1421].exec("a\n\x0dx{85}\x0cb ", 4339));
+assertEquals(null, res[1421].exec("** Failers", 4340));
+assertEquals(null, res[1421].exec("ab  ", 4341));
+assertEquals(null, res[1422].exec("a\nb", 4342));
+assertEquals(null, res[1422].exec("a\n\x0db", 4343));
+assertEquals(null, res[1422].exec("a\n\x0dx{85}b", 4344));
+assertEquals(null, res[1422].exec("a\x0d\n\x0d\nb ", 4345));
+assertEquals(null, res[1422].exec("a\x0d\n\x0d\n\x0d\nb ", 4346));
+assertEquals(null, res[1422].exec("a\n\x0d\n\x0db", 4347));
+assertEquals(null, res[1422].exec("a\n\n\x0d\nb ", 4348));
+assertEquals(null, res[1422].exec("** Failers", 4349));
+assertEquals(null, res[1422].exec("a\n\n\n\x0db", 4350));
+assertEquals(null, res[1422].exec("a\x0d", 4351));
+assertEquals(null, res[1423].exec("\x09 x{a0}X\n\x0b\x0c\x0d\n", 4352));
+assertEquals(null, res[1424].exec(" x{a0}X\n\x0b\x0c\x0d\n", 4353));
+assertEquals(null, res[1425].exec(">\x09 x{a0}X\n\n\n<", 4354));
+assertEquals(null, res[1426].exec(">\x09 x{a0}X\n\n\n<", 4355));
+assertEquals(null, res[1427].exec("X X\n", 4356));
+assertEquals(null, res[1427].exec("X\x09X\x0b", 4357));
+assertEquals(null, res[1427].exec("** Failers", 4358));
+assertEquals(null, res[1427].exec("x{a0} X\n   ", 4359));
+assertEquals(null, res[1428].exec("\x09 x{a0}X\n\x0b\x0c\x0d\n", 4360));
+assertEquals(null, res[1428].exec("\x09 x{a0}\n\x0b\x0c\x0d\n", 4361));
+assertEquals(null, res[1428].exec("\x09 x{a0}\n\x0b\x0c", 4362));
+assertEquals(null, res[1428].exec("** Failers ", 4363));
+assertEquals(null, res[1428].exec("\x09 x{a0}\n\x0b", 4364));
+assertEquals(null, res[1428].exec(" ", 4365));
+assertEquals(null, res[1429].exec("x{3001}x{3000}x{2030}x{2028}", 4366));
+assertEquals(null, res[1429].exec("Xx{180e}Xx{85}", 4367));
+assertEquals(null, res[1429].exec("** Failers", 4368));
+assertEquals(null, res[1429].exec("x{2009} X\n   ", 4369));
+assertEquals(null, res[1430].exec("x{1680}x{180e}x{2007}Xx{2028}x{2029}\x0c\x0d\n", 4370));
+assertEquals(null, res[1430].exec("\x09x{205f}x{a0}\nx{2029}\x0cx{2028}\n", 4371));
+assertEquals(null, res[1430].exec("\x09 x{202f}\n\x0b\x0c", 4372));
+assertEquals(null, res[1430].exec("** Failers ", 4373));
+assertEquals(null, res[1430].exec("\x09x{200a}x{a0}x{2028}\x0b", 4374));
+assertEquals(null, res[1430].exec(" ", 4375));
+assertEquals(null, res[1431].exec("a\x0db", 4376));
+assertEquals(null, res[1431].exec("a\nb", 4377));
+assertEquals(null, res[1431].exec("a\x0d\nb", 4378));
+assertEquals(null, res[1431].exec("** Failers", 4379));
+assertEquals(null, res[1431].exec("ax{85}b", 4380));
+assertEquals(null, res[1431].exec("a\x0bb     ", 4381));
+assertEquals(null, res[1432].exec("a\x0db", 4382));
+assertEquals(null, res[1432].exec("a\nb", 4383));
+assertEquals(null, res[1432].exec("a\x0d\nb", 4384));
+assertEquals(null, res[1432].exec("ax{85}b", 4385));
+assertEquals(null, res[1432].exec("a\x0bb     ", 4386));
+assertEquals(null, res[1432].exec("** Failers ", 4387));
+assertEquals(null, res[1432].exec("ax{85}b<bsr_anycrlf>", 4388));
+assertEquals(null, res[1432].exec("a\x0bb<bsr_anycrlf>", 4389));
+assertEquals(null, res[1433].exec("a\x0db", 4390));
+assertEquals(null, res[1433].exec("a\nb", 4391));
+assertEquals(null, res[1433].exec("a\x0d\nb", 4392));
+assertEquals(null, res[1433].exec("** Failers", 4393));
+assertEquals(null, res[1433].exec("ax{85}b", 4394));
+assertEquals(null, res[1433].exec("a\x0bb     ", 4395));
+assertEquals(null, res[1434].exec("a\x0db", 4396));
+assertEquals(null, res[1434].exec("a\nb", 4397));
+assertEquals(null, res[1434].exec("a\x0d\nb", 4398));
+assertEquals(null, res[1434].exec("ax{85}b", 4399));
+assertEquals(null, res[1434].exec("a\x0bb     ", 4400));
+assertEquals(null, res[1434].exec("** Failers ", 4401));
+assertEquals(null, res[1434].exec("ax{85}b<bsr_anycrlf>", 4402));
+assertEquals(null, res[1434].exec("a\x0bb<bsr_anycrlf>", 4403));
+assertEquals("X", res[1435].exec("Ax{1ec5}ABCXYZ"), 4404);
+assertEquals(null, res[1437].exec("AB", 4405));
+assertEquals(null, res[1437].exec("*** Failers", 4406));
+assertEquals(null, res[1437].exec("A0", 4407));
+assertEquals(null, res[1437].exec("00   ", 4408));
+assertEquals(null, res[1438].exec("AB", 4409));
+assertEquals(null, res[1438].exec("Ax{300}BC ", 4410));
+assertEquals(null, res[1438].exec("Ax{300}x{301}x{302}BC ", 4411));
+assertEquals(null, res[1438].exec("*** Failers", 4412));
+assertEquals(null, res[1438].exec("x{300}  ", 4413));
+assertEquals(null, res[1439].exec("ABC", 4414));
+assertEquals(null, res[1439].exec("Ax{300}Bx{300}x{301}C ", 4415));
+assertEquals(null, res[1439].exec("Ax{300}x{301}x{302}BC ", 4416));
+assertEquals(null, res[1439].exec("*** Failers", 4417));
+assertEquals(null, res[1439].exec("x{300}  ", 4418));
+assertEquals(null, res[1440].exec("abcd", 4419));
+assertEquals(null, res[1440].exec("a ", 4420));
+assertEquals(null, res[1440].exec("*** Failers ", 4421));
+assertEquals(null, res[1441].exec("1234", 4422));
+assertEquals(null, res[1441].exec("= ", 4423));
+assertEquals(null, res[1441].exec("*** Failers ", 4424));
+assertEquals(null, res[1441].exec("abcd ", 4425));
+assertEquals(null, res[1442].exec("abcdAx{300}x{301}x{302}", 4426));
+assertEquals(null, res[1442].exec("Ax{300}x{301}x{302}", 4427));
+assertEquals(null, res[1442].exec("Ax{300}x{301}x{302}Ax{300}x{301}x{302}", 4428));
+assertEquals(null, res[1442].exec("a ", 4429));
+assertEquals(null, res[1442].exec("*** Failers ", 4430));
+assertEquals(null, res[1442].exec("x{300}x{301}x{302}", 4431));
+assertEquals("abc", res[1443].exec("abc"), 4432);
+assertEquals("abc", res[1443].exec("Ax{300}abc"), 4433);
+assertEquals("abc", res[1443].exec("Ax{300}x{301}x{302}Ax{300}Ax{300}Ax{300}abcxyz"), 4434);
+assertEquals("abc", res[1443].exec("x{300}abc  "), 4435);
+assertEquals(null, res[1443].exec("*** Failers", 4436));
+assertEquals("abc", res[1444].exec("abc"), 4437);
+assertEquals(null, res[1444].exec("Ax{300}abc", 4438));
+assertEquals(null, res[1444].exec("*** Failers", 4439));
+assertEquals(null, res[1444].exec("Ax{300}x{301}x{302}Ax{300}Ax{300}Ax{300}abcxyz", 4440));
+assertEquals(null, res[1444].exec("x{300}abc  ", 4441));
+assertEquals("abc", res[1445].exec("abc"), 4442);
+assertEquals("abc", res[1445].exec("Ax{300}abc"), 4443);
+assertEquals("abc", res[1445].exec("Ax{300}x{301}x{302}Ax{300}Ax{300}Ax{300}abcxyz"), 4444);
+assertEquals("abc", res[1445].exec("x{300}abc  "), 4445);
+assertEquals(null, res[1445].exec("*** Failers", 4446));
+assertEquals("abc", res[1446].exec("abc"), 4447);
+assertEquals(null, res[1446].exec("Ax{300}abc", 4448));
+assertEquals(null, res[1446].exec("Ax{300}x{301}x{302}Ax{300}Ax{300}Ax{300}abcxyz", 4449));
+assertEquals(null, res[1446].exec("*** Failers", 4450));
+assertEquals(null, res[1446].exec("x{300}abc  ", 4451));
+assertEquals(null, res[1447].exec("A=b", 4452));
+assertEquals(null, res[1447].exec("=c ", 4453));
+assertEquals(null, res[1447].exec("*** Failers", 4454));
+assertEquals(null, res[1447].exec("1=2 ", 4455));
+assertEquals(null, res[1447].exec("AAAA=b  ", 4456));
+assertEquals(null, res[1448].exec("AAAA=b", 4457));
+assertEquals(null, res[1448].exec("=c ", 4458));
+assertEquals(null, res[1448].exec("*** Failers", 4459));
+assertEquals(null, res[1448].exec("1=2  ", 4460));
+assertEquals(null, res[1449].exec("Ax{300}x{301}x{302}Ax{300}x{301}x{302}X", 4461));
+assertEquals(null, res[1449].exec("Ax{300}x{301}x{302}Ax{300}x{301}x{302}Ax{300}x{301}x{302}X ", 4462));
+assertEquals(null, res[1449].exec("*** Failers", 4463));
+assertEquals(null, res[1449].exec("X", 4464));
+assertEquals(null, res[1449].exec("Ax{300}x{301}x{302}X", 4465));
+assertEquals(null, res[1449].exec("Ax{300}x{301}x{302}Ax{300}x{301}x{302}Ax{300}x{301}x{302}Ax{300}x{301}x{302}X", 4466));
+assertEquals(null, res[1450].exec("x{c0}x{30f}x{660}x{66c}x{f01}x{1680}<", 4467));
+assertEquals(null, res[1450].exec("\npx{300}9!$ < ", 4468));
+assertEquals(null, res[1450].exec("** Failers ", 4469));
+assertEquals(null, res[1450].exec("apx{300}9!$ < ", 4470));
+assertEquals(null, res[1451].exec("X", 4471));
+assertEquals(null, res[1451].exec("** Failers ", 4472));
+assertEquals(null, res[1451].exec("", 4473));
+assertEquals(null, res[1452].exec("9", 4474));
+assertEquals(null, res[1452].exec("** Failers ", 4475));
+assertEquals(null, res[1452].exec("x{c0}", 4476));
+assertEquals(null, res[1453].exec("X", 4477));
+assertEquals(null, res[1453].exec("** Failers ", 4478));
+assertEquals(null, res[1453].exec("x{30f}", 4479));
+assertEquals(null, res[1454].exec("X", 4480));
+assertEquals(null, res[1454].exec("** Failers ", 4481));
+assertEquals(null, res[1454].exec("x{660}", 4482));
+assertEquals(null, res[1455].exec("X", 4483));
+assertEquals(null, res[1455].exec("** Failers ", 4484));
+assertEquals(null, res[1455].exec("x{66c}", 4485));
+assertEquals(null, res[1456].exec("X", 4486));
+assertEquals(null, res[1456].exec("** Failers ", 4487));
+assertEquals(null, res[1456].exec("x{f01}", 4488));
+assertEquals(null, res[1457].exec("X", 4489));
+assertEquals(null, res[1457].exec("** Failers ", 4490));
+assertEquals(null, res[1457].exec("x{1680}", 4491));
+assertEquals(null, res[1458].exec("x{017}", 4492));
+assertEquals(null, res[1458].exec("x{09f} ", 4493));
+assertEquals(null, res[1458].exec("** Failers", 4494));
+assertEquals(null, res[1458].exec("x{0600} ", 4495));
+assertEquals(null, res[1459].exec("x{601}", 4496));
+assertEquals(null, res[1459].exec("** Failers", 4497));
+assertEquals(null, res[1459].exec("x{09f} ", 4498));
+assertEquals(null, res[1460].exec("** Failers", 4499));
+assertEquals(null, res[1460].exec("x{09f} ", 4500));
+assertEquals(null, res[1461].exec("x{f8ff}", 4501));
+assertEquals(null, res[1461].exec("** Failers", 4502));
+assertEquals(null, res[1461].exec("x{09f} ", 4503));
+assertEquals(null, res[1462].exec("?x{dfff}", 4504));
+assertEquals(null, res[1462].exec("** Failers", 4505));
+assertEquals(null, res[1462].exec("x{09f} ", 4506));
+assertEquals(null, res[1463].exec("a", 4507));
+assertEquals(null, res[1463].exec("** Failers ", 4508));
+assertEquals(null, res[1463].exec("Z", 4509));
+assertEquals(null, res[1463].exec("x{e000}  ", 4510));
+assertEquals(null, res[1464].exec("x{2b0}", 4511));
+assertEquals(null, res[1464].exec("** Failers", 4512));
+assertEquals(null, res[1464].exec("a ", 4513));
+assertEquals(null, res[1465].exec("x{1bb}", 4514));
+assertEquals(null, res[1465].exec("** Failers", 4515));
+assertEquals(null, res[1465].exec("a ", 4516));
+assertEquals(null, res[1465].exec("x{2b0}", 4517));
+assertEquals(null, res[1466].exec("x{1c5}", 4518));
+assertEquals(null, res[1466].exec("** Failers", 4519));
+assertEquals(null, res[1466].exec("a ", 4520));
+assertEquals(null, res[1466].exec("x{2b0}", 4521));
+assertEquals(null, res[1467].exec("A", 4522));
+assertEquals(null, res[1467].exec("** Failers", 4523));
+assertEquals(null, res[1467].exec("x{2b0}", 4524));
+assertEquals(null, res[1468].exec("x{903}", 4525));
+assertEquals(null, res[1468].exec("** Failers", 4526));
+assertEquals(null, res[1468].exec("X", 4527));
+assertEquals(null, res[1468].exec("x{300}", 4528));
+assertEquals(null, res[1468].exec("   ", 4529));
+assertEquals(null, res[1469].exec("x{488}", 4530));
+assertEquals(null, res[1469].exec("** Failers", 4531));
+assertEquals(null, res[1469].exec("X", 4532));
+assertEquals(null, res[1469].exec("x{903}", 4533));
+assertEquals(null, res[1469].exec("x{300}", 4534));
+assertEquals(null, res[1470].exec("x{300}", 4535));
+assertEquals(null, res[1470].exec("** Failers", 4536));
+assertEquals(null, res[1470].exec("X", 4537));
+assertEquals(null, res[1470].exec("x{903}", 4538));
+assertEquals(null, res[1470].exec("0123456789x{660}x{661}x{662}x{663}x{664}x{665}x{666}x{667}x{668}x{669}x{66a}", 4539));
+assertEquals(null, res[1470].exec("x{6f0}x{6f1}x{6f2}x{6f3}x{6f4}x{6f5}x{6f6}x{6f7}x{6f8}x{6f9}x{6fa}", 4540));
+assertEquals(null, res[1470].exec("x{966}x{967}x{968}x{969}x{96a}x{96b}x{96c}x{96d}x{96e}x{96f}x{970}", 4541));
+assertEquals(null, res[1470].exec("** Failers", 4542));
+assertEquals(null, res[1470].exec("X", 4543));
+assertEquals(null, res[1471].exec("x{16ee}", 4544));
+assertEquals(null, res[1471].exec("** Failers", 4545));
+assertEquals(null, res[1471].exec("X", 4546));
+assertEquals(null, res[1471].exec("x{966}", 4547));
+assertEquals(null, res[1472].exec("x{b2}", 4548));
+assertEquals(null, res[1472].exec("x{b3}", 4549));
+assertEquals(null, res[1472].exec("** Failers", 4550));
+assertEquals(null, res[1472].exec("X", 4551));
+assertEquals(null, res[1472].exec("x{16ee}", 4552));
+assertEquals(null, res[1473].exec("_", 4553));
+assertEquals(null, res[1473].exec("x{203f}", 4554));
+assertEquals(null, res[1473].exec("** Failers", 4555));
+assertEquals(null, res[1473].exec("X", 4556));
+assertEquals(null, res[1473].exec("-", 4557));
+assertEquals(null, res[1473].exec("x{58a}", 4558));
+assertEquals(null, res[1474].exec("-", 4559));
+assertEquals(null, res[1474].exec("x{58a}", 4560));
+assertEquals(null, res[1474].exec("** Failers", 4561));
+assertEquals(null, res[1474].exec("X", 4562));
+assertEquals(null, res[1474].exec("x{203f}", 4563));
+assertEquals(null, res[1475].exec(")", 4564));
+assertEquals(null, res[1475].exec("]", 4565));
+assertEquals(null, res[1475].exec("}", 4566));
+assertEquals(null, res[1475].exec("x{f3b}", 4567));
+assertEquals(null, res[1475].exec("** Failers", 4568));
+assertEquals(null, res[1475].exec("X", 4569));
+assertEquals(null, res[1475].exec("x{203f}", 4570));
+assertEquals(null, res[1475].exec("(", 4571));
+assertEquals(null, res[1475].exec("[", 4572));
+assertEquals(null, res[1475].exec("{", 4573));
+assertEquals(null, res[1475].exec("x{f3c}", 4574));
+assertEquals(null, res[1476].exec("x{bb}", 4575));
+assertEquals(null, res[1476].exec("x{2019}", 4576));
+assertEquals(null, res[1476].exec("** Failers", 4577));
+assertEquals(null, res[1476].exec("X", 4578));
+assertEquals(null, res[1476].exec("x{203f}", 4579));
+assertEquals(null, res[1477].exec("x{ab}", 4580));
+assertEquals(null, res[1477].exec("x{2018}", 4581));
+assertEquals(null, res[1477].exec("** Failers", 4582));
+assertEquals(null, res[1477].exec("X", 4583));
+assertEquals(null, res[1477].exec("x{203f}", 4584));
+assertEquals(null, res[1478].exec("!", 4585));
+assertEquals(null, res[1478].exec("x{37e}", 4586));
+assertEquals(null, res[1478].exec("** Failers", 4587));
+assertEquals(null, res[1478].exec("X", 4588));
+assertEquals(null, res[1478].exec("x{203f}", 4589));
+assertEquals(null, res[1479].exec("(", 4590));
+assertEquals(null, res[1479].exec("[", 4591));
+assertEquals(null, res[1479].exec("{", 4592));
+assertEquals(null, res[1479].exec("x{f3c}", 4593));
+assertEquals(null, res[1479].exec("** Failers", 4594));
+assertEquals(null, res[1479].exec("X", 4595));
+assertEquals(null, res[1479].exec(")", 4596));
+assertEquals(null, res[1479].exec("]", 4597));
+assertEquals(null, res[1479].exec("}", 4598));
+assertEquals(null, res[1479].exec("x{f3b}", 4599));
+assertEquals(null, res[1479].exec("$x{a2}x{a3}x{a4}x{a5}x{a6}", 4600));
+assertEquals(null, res[1479].exec("x{9f2}", 4601));
+assertEquals(null, res[1479].exec("** Failers", 4602));
+assertEquals(null, res[1479].exec("X", 4603));
+assertEquals(null, res[1479].exec("x{2c2}", 4604));
+assertEquals(null, res[1480].exec("x{2c2}", 4605));
+assertEquals(null, res[1480].exec("** Failers", 4606));
+assertEquals(null, res[1480].exec("X", 4607));
+assertEquals(null, res[1480].exec("x{9f2}", 4608));
+assertEquals(null, res[1480].exec("+<|~x{ac}x{2044}", 4609));
+assertEquals(null, res[1480].exec("** Failers", 4610));
+assertEquals(null, res[1480].exec("X", 4611));
+assertEquals(null, res[1480].exec("x{9f2}", 4612));
+assertEquals(null, res[1481].exec("x{a6}", 4613));
+assertEquals(null, res[1481].exec("x{482} ", 4614));
+assertEquals(null, res[1481].exec("** Failers", 4615));
+assertEquals(null, res[1481].exec("X", 4616));
+assertEquals(null, res[1481].exec("x{9f2}", 4617));
+assertEquals(null, res[1482].exec("x{2028}", 4618));
+assertEquals(null, res[1482].exec("** Failers", 4619));
+assertEquals(null, res[1482].exec("X", 4620));
+assertEquals(null, res[1482].exec("x{2029}", 4621));
+assertEquals(null, res[1483].exec("x{2029}", 4622));
+assertEquals(null, res[1483].exec("** Failers", 4623));
+assertEquals(null, res[1483].exec("X", 4624));
+assertEquals(null, res[1483].exec("x{2028}", 4625));
+assertEquals(null, res[1484].exec("\\ \\", 4626));
+assertEquals(null, res[1484].exec("x{a0}", 4627));
+assertEquals(null, res[1484].exec("x{1680}", 4628));
+assertEquals(null, res[1484].exec("x{180e}", 4629));
+assertEquals(null, res[1484].exec("x{2000}", 4630));
+assertEquals(null, res[1484].exec("x{2001}     ", 4631));
+assertEquals(null, res[1484].exec("** Failers", 4632));
+assertEquals(null, res[1484].exec("x{2028}", 4633));
+assertEquals(null, res[1484].exec("x{200d} ", 4634));
+assertEquals(null, res[1484].exec("  x{660}x{661}x{662}ABC", 4635));
+assertEquals(null, res[1484].exec("  x{660}x{661}x{662}ABC", 4636));
+assertEquals(null, res[1485].exec("  x{660}x{661}x{662}ABC", 4637));
+assertEquals(null, res[1486].exec("  x{660}x{661}x{662}ABC", 4638));
+assertEquals(null, res[1487].exec("  x{660}x{661}x{662}ABC", 4639));
+assertEquals(null, res[1488].exec("  x{660}x{661}x{662}ABC", 4640));
+assertEquals(null, res[1489].exec("  x{660}x{661}x{662}ABC", 4641));
+assertEquals(null, res[1490].exec("  x{660}x{661}x{662}ABC", 4642));
+assertEquals(null, res[1491].exec("  x{660}x{661}x{662}ABC", 4643));
+assertEquals(null, res[1492].exec("  x{660}x{661}x{662}ABC", 4644));
+assertEquals(null, res[1493].exec("  x{660}x{661}x{662}ABC", 4645));
+assertEquals(null, res[1493].exec("  x{660}x{661}x{662}ABC", 4646));
+assertEquals(null, res[1493].exec("  x{660}x{661}x{662}ABC", 4647));
+assertEquals(null, res[1493].exec("  ** Failers", 4648));
+assertEquals(null, res[1493].exec("  x{660}x{661}x{662}ABC", 4649));
+assertEquals(null, res[1494].exec("A", 4650));
+assertEquals(null, res[1494].exec("ax{10a0}B ", 4651));
+assertEquals(null, res[1494].exec("** Failers ", 4652));
+assertEquals(null, res[1494].exec("a", 4653));
+assertEquals(null, res[1494].exec("x{1d00}  ", 4654));
+assertEquals(null, res[1495].exec("1234", 4655));
+assertEquals(null, res[1495].exec("** Failers", 4656));
+assertEquals(null, res[1495].exec("ABC ", 4657));
+assertEquals(null, res[1496].exec("1234", 4658));
+assertEquals(null, res[1496].exec("** Failers", 4659));
+assertEquals(null, res[1496].exec("ABC ", 4660));
+assertEquals(null, res[1496].exec("A2XYZ", 4661));
+assertEquals(null, res[1496].exec("123A5XYZPQR", 4662));
+assertEquals(null, res[1496].exec("ABAx{660}XYZpqr", 4663));
+assertEquals(null, res[1496].exec("** Failers", 4664));
+assertEquals(null, res[1496].exec("AXYZ", 4665));
+assertEquals(null, res[1496].exec("XYZ     ", 4666));
+assertEquals(null, res[1496].exec("1XYZ", 4667));
+assertEquals(null, res[1496].exec("AB=XYZ.. ", 4668));
+assertEquals(null, res[1496].exec("XYZ ", 4669));
+assertEquals(null, res[1496].exec("** Failers", 4670));
+assertEquals(null, res[1496].exec("WXYZ ", 4671));
+assertEquals(null, res[1497].exec("1234", 4672));
+assertEquals(null, res[1497].exec("1234", 4673));
+assertEquals(null, res[1497].exec("12-34", 4674));
+assertEquals("{", res[1497].exec("12+x{661}-34  "), 4675);
+assertEquals(null, res[1497].exec("** Failers", 4676));
+assertEquals("d", res[1497].exec("abcd  "), 4677);
+assertEquals("d", res[1498].exec("abcd"), 4678);
+assertEquals(null, res[1498].exec("** Failers", 4679));
+assertEquals(null, res[1498].exec("1234", 4680));
+assertEquals(null, res[1499].exec("11111111111111111111111111111111111111111111111111111111111111111111111", 4681));
+assertEquals("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", res[1499].exec("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), 4682);
+assertEquals(" ", res[1499].exec(" "), 4683);
+assertEquals(null, res[1499].exec("11111111111111111111111111111111111111111111111111111111111111111111111", 4684));
+assertEquals("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", res[1499].exec("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), 4685);
+assertEquals(null, res[1500].exec("11111111111111111111111111111111111111111111111111111111111111111111111", 4686));
+assertEquals("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", res[1500].exec("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), 4687);
+assertEquals(null, res[1501].exec("11111111111111111111111111111111111111111111111111111111111111111111111", 4688));
+assertEquals(null, res[1501].exec("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 4689));
+assertEquals(null, res[1502].exec("11111111111111111111111111111111111111111111111111111111111111111111111", 4690));
+assertEquals("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", res[1502].exec("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), 4691);
+assertEquals(null, res[1503].exec("a", 4692));
+assertEquals(null, res[1503].exec("A ", 4693));
+assertEquals(null, res[1504].exec("a", 4694));
+assertEquals(null, res[1504].exec("A ", 4695));
+assertEquals(null, res[1505].exec("A", 4696));
+assertEquals(null, res[1505].exec("aZ", 4697));
+assertEquals(null, res[1505].exec("** Failers", 4698));
+assertEquals(null, res[1505].exec("abc   ", 4699));
+assertEquals(null, res[1506].exec("A", 4700));
+assertEquals(null, res[1506].exec("aZ", 4701));
+assertEquals(null, res[1506].exec("** Failers", 4702));
+assertEquals(null, res[1506].exec("abc   ", 4703));
+assertEquals(null, res[1507].exec("a", 4704));
+assertEquals(null, res[1507].exec("Az", 4705));
+assertEquals(null, res[1507].exec("** Failers", 4706));
+assertEquals(null, res[1507].exec("ABC   ", 4707));
+assertEquals(null, res[1508].exec("a", 4708));
+assertEquals(null, res[1508].exec("Az", 4709));
+assertEquals(null, res[1508].exec("** Failers", 4710));
+assertEquals(null, res[1508].exec("ABC   ", 4711));
+assertEquals(null, res[1508].exec("x{c0}", 4712));
+assertEquals(null, res[1508].exec("x{e0} ", 4713));
+assertEquals(null, res[1508].exec("x{c0}", 4714));
+assertEquals(null, res[1508].exec("x{e0} ", 4715));
+assertEquals(null, res[1508].exec("Ax{391}x{10427}x{ff3a}x{1fb0}", 4716));
+assertEquals(null, res[1508].exec("** Failers", 4717));
+assertEquals(null, res[1508].exec("ax{391}x{10427}x{ff3a}x{1fb0}   ", 4718));
+assertEquals(null, res[1508].exec("Ax{3b1}x{10427}x{ff3a}x{1fb0}", 4719));
+assertEquals(null, res[1508].exec("Ax{391}x{1044F}x{ff3a}x{1fb0}", 4720));
+assertEquals(null, res[1508].exec("Ax{391}x{10427}x{ff5a}x{1fb0}", 4721));
+assertEquals(null, res[1508].exec("Ax{391}x{10427}x{ff3a}x{1fb8}", 4722));
+assertEquals(null, res[1508].exec("Ax{391}x{10427}x{ff3a}x{1fb0}", 4723));
+assertEquals(null, res[1508].exec("ax{391}x{10427}x{ff3a}x{1fb0}   ", 4724));
+assertEquals(null, res[1508].exec("Ax{3b1}x{10427}x{ff3a}x{1fb0}", 4725));
+assertEquals(null, res[1508].exec("Ax{391}x{1044F}x{ff3a}x{1fb0}", 4726));
+assertEquals(null, res[1508].exec("Ax{391}x{10427}x{ff5a}x{1fb0}", 4727));
+assertEquals(null, res[1508].exec("Ax{391}x{10427}x{ff3a}x{1fb8}", 4728));
+assertEquals(null, res[1508].exec("x{391}x{3b1}x{3b1}x{3b1}x{391}", 4729));
+assertEquals(null, res[1508].exec("x{391}x{3b1}x{3b1}x{3b1}x{391}X", 4730));
+assertEquals(null, res[1508].exec("x{391}x{3b1}x{3b1}x{3b1}x{391}X", 4731));
+assertEquals(null, res[1508].exec("x{391}", 4732));
+assertEquals(null, res[1508].exec("x{ff3a}", 4733));
+assertEquals(null, res[1508].exec("x{3b1}", 4734));
+assertEquals(null, res[1508].exec("x{ff5a}   ", 4735));
+assertEquals(null, res[1508].exec("x{c0}", 4736));
+assertEquals(null, res[1508].exec("x{e0} ", 4737));
+assertEquals(null, res[1508].exec("x{104}", 4738));
+assertEquals(null, res[1508].exec("x{105}", 4739));
+assertEquals(null, res[1508].exec("x{109}  ", 4740));
+assertEquals(null, res[1508].exec("** Failers", 4741));
+assertEquals(null, res[1508].exec("x{100}", 4742));
+assertEquals(null, res[1508].exec("x{10a} ", 4743));
+assertEquals(null, res[1508].exec("Z", 4744));
+assertEquals(null, res[1508].exec("z", 4745));
+assertEquals(null, res[1508].exec("x{39c}", 4746));
+assertEquals(null, res[1508].exec("x{178}", 4747));
+assertEquals(null, res[1508].exec("|", 4748));
+assertEquals(null, res[1508].exec("x{80}", 4749));
+assertEquals(null, res[1508].exec("x{ff}", 4750));
+assertEquals(null, res[1508].exec("x{100}", 4751));
+assertEquals(null, res[1508].exec("x{101} ", 4752));
+assertEquals(null, res[1508].exec("** Failers", 4753));
+assertEquals(null, res[1508].exec("x{102}", 4754));
+assertEquals(null, res[1508].exec("Y", 4755));
+assertEquals(null, res[1508].exec("y           ", 4756));
+assertEquals(null, res[1509].exec("A", 4757));
+assertEquals(null, res[1509].exec("Ax{300}BC ", 4758));
+assertEquals(null, res[1509].exec("Ax{300}x{301}x{302}BC ", 4759));
+assertEquals(null, res[1509].exec("*** Failers", 4760));
+assertEquals(null, res[1509].exec("x{300}  ", 4761));
+assertEquals("X", res[1510].exec("X123"), 4762);
+assertEquals(null, res[1510].exec("*** Failers", 4763));
+assertEquals(null, res[1510].exec("AXYZ", 4764));
+assertEquals(null, res[1511].exec("Ax{300}x{301}x{302}BCAx{300}x{301} ", 4765));
+assertEquals(null, res[1511].exec("Ax{300}x{301}x{302}BCAx{300}x{301}C ", 4766));
+assertEquals(null, res[1512].exec("Ax{300}x{301}x{302}BCAx{300}x{301} ", 4767));
+assertEquals(null, res[1512].exec("Ax{300}x{301}x{302}BCAx{300}x{301}C ", 4768));
+assertEquals("A,,A", res[1513].exec("Ax{300}x{301}x{302}BCAx{300}x{301} "), 4769);
+assertEquals("A,,A", res[1513].exec("Ax{300}x{301}x{302}BCAx{300}x{301}C "), 4770);
+assertEquals("A,,A", res[1514].exec("Ax{300}x{301}x{302}BCAx{300}x{301} "), 4771);
+assertEquals("A,,A", res[1514].exec("Ax{300}x{301}x{302}BCAx{300}x{301}C "), 4772);
+assertEquals(null, res[1515].exec("*** Failers", 4773));
+assertEquals(null, res[1515].exec("Ax{300}x{301}x{302}", 4774));
+assertEquals(null, res[1516].exec("Ax{300}x{301}Bx{300}X", 4775));
+assertEquals(null, res[1516].exec("Ax{300}x{301}Bx{300}Cx{300}x{301}", 4776));
+assertEquals(null, res[1516].exec("Ax{300}x{301}Bx{300}Cx{300}x{301}X", 4777));
+assertEquals(null, res[1516].exec("Ax{300}x{301}Bx{300}Cx{300}x{301}DAx{300}X", 4778));
+assertEquals(null, res[1517].exec("Ax{300}x{301}Bx{300}X", 4779));
+assertEquals(null, res[1517].exec("Ax{300}x{301}Bx{300}Cx{300}x{301}", 4780));
+assertEquals(null, res[1517].exec("Ax{300}x{301}Bx{300}Cx{300}x{301}X", 4781));
+assertEquals(null, res[1517].exec("Ax{300}x{301}Bx{300}Cx{300}x{301}DAx{300}X", 4782));
+assertEquals(null, res[1518].exec("12X", 4783));
+assertEquals(null, res[1518].exec("123X", 4784));
+assertEquals(null, res[1518].exec("*** Failers", 4785));
+assertEquals(null, res[1518].exec("X", 4786));
+assertEquals(null, res[1518].exec("1X", 4787));
+assertEquals(null, res[1518].exec("1234X     ", 4788));
+assertEquals(null, res[1518].exec("x{100}   ", 4789));
+assertEquals(null, res[1518].exec("x{101} ", 4790));
+assertEquals(null, res[1518].exec("x{2e81}x{3007}x{2f804}x{31a0}", 4791));
+assertEquals(null, res[1518].exec("** Failers", 4792));
+assertEquals(null, res[1518].exec("x{2e7f}  ", 4793));
+assertEquals(null, res[1518].exec("x{3105}", 4794));
+assertEquals(null, res[1518].exec("** Failers", 4795));
+assertEquals(null, res[1518].exec("x{30ff}  ", 4796));
+assertEquals(null, res[1519].exec("x{06e9}", 4797));
+assertEquals(null, res[1519].exec("x{060b}", 4798));
+assertEquals(null, res[1519].exec("** Failers", 4799));
+assertEquals(null, res[1519].exec("Xx{06e9}   ", 4800));
+assertEquals(null, res[1520].exec("x{2f800}", 4801));
+assertEquals(null, res[1520].exec("** Failers", 4802));
+assertEquals(null, res[1520].exec("x{a014}", 4803));
+assertEquals(null, res[1520].exec("x{a4c6}   ", 4804));
+assertEquals(null, res[1521].exec("AXYZ", 4805));
+assertEquals(null, res[1521].exec("x{1234}XYZ ", 4806));
+assertEquals(null, res[1521].exec("** Failers", 4807));
+assertEquals(null, res[1521].exec("X  ", 4808));
+assertEquals(null, res[1522].exec("** Failers", 4809));
+assertEquals(null, res[1522].exec("AX", 4810));
+assertEquals(null, res[1523].exec("XYZ", 4811));
+assertEquals(null, res[1523].exec("AXYZ", 4812));
+assertEquals(null, res[1523].exec("x{1234}XYZ ", 4813));
+assertEquals(null, res[1523].exec("** Failers", 4814));
+assertEquals(null, res[1523].exec("ABXYZ   ", 4815));
+assertEquals(null, res[1524].exec("XYZ", 4816));
+assertEquals(null, res[1524].exec("** Failers", 4817));
+assertEquals(null, res[1524].exec("AXYZ", 4818));
+assertEquals(null, res[1524].exec("x{1234}XYZ ", 4819));
+assertEquals(null, res[1524].exec("ABXYZ   ", 4820));
+assertEquals(null, res[1524].exec("AXYZ", 4821));
+assertEquals(null, res[1524].exec("x{1234}XYZ", 4822));
+assertEquals(null, res[1524].exec("Ax{1234}XYZ", 4823));
+assertEquals(null, res[1524].exec("** Failers", 4824));
+assertEquals(null, res[1524].exec("XYZ", 4825));
+assertEquals(null, res[1524].exec("** Failers", 4826));
+assertEquals(null, res[1524].exec("AXYZ", 4827));
+assertEquals(null, res[1524].exec("x{1234}XYZ", 4828));
+assertEquals(null, res[1524].exec("Ax{1234}XYZ", 4829));
+assertEquals(null, res[1524].exec("XYZ", 4830));
+assertEquals(null, res[1525].exec("XYZ", 4831));
+assertEquals(null, res[1525].exec("AXYZ", 4832));
+assertEquals(null, res[1525].exec("x{1234}XYZ", 4833));
+assertEquals(null, res[1525].exec("Ax{1234}XYZ", 4834));
+assertEquals(null, res[1525].exec("** Failers", 4835));
+assertEquals(null, res[1526].exec("XYZ", 4836));
+assertEquals(null, res[1526].exec("** Failers", 4837));
+assertEquals(null, res[1526].exec("AXYZ", 4838));
+assertEquals(null, res[1526].exec("x{1234}XYZ", 4839));
+assertEquals(null, res[1526].exec("Ax{1234}XYZ", 4840));
+assertEquals("AX", res[1527].exec("AXYZ"), 4841);
+assertEquals(null, res[1527].exec("x{1234}XYZ ", 4842));
+assertEquals(null, res[1527].exec("** Failers", 4843));
+assertEquals(null, res[1527].exec("X  ", 4844));
+assertEquals(null, res[1528].exec("** Failers", 4845));
+assertEquals("AX", res[1528].exec("AX"), 4846);
+assertEquals("X", res[1529].exec("XYZ"), 4847);
+assertEquals("AX", res[1529].exec("AXYZ"), 4848);
+assertEquals(null, res[1529].exec("x{1234}XYZ ", 4849));
+assertEquals(null, res[1529].exec("** Failers", 4850));
+assertEquals(null, res[1529].exec("ABXYZ   ", 4851));
+assertEquals("X", res[1530].exec("XYZ"), 4852);
+assertEquals(null, res[1530].exec("** Failers", 4853));
+assertEquals("AX", res[1530].exec("AXYZ"), 4854);
+assertEquals(null, res[1530].exec("x{1234}XYZ ", 4855));
+assertEquals(null, res[1530].exec("ABXYZ   ", 4856));
+assertEquals("AX", res[1531].exec("AXYZ"), 4857);
+assertEquals(null, res[1531].exec("x{1234}XYZ", 4858));
+assertEquals(null, res[1531].exec("Ax{1234}XYZ", 4859));
+assertEquals(null, res[1531].exec("** Failers", 4860));
+assertEquals(null, res[1531].exec("XYZ", 4861));
+assertEquals(null, res[1532].exec("** Failers", 4862));
+assertEquals("AX", res[1532].exec("AXYZ"), 4863);
+assertEquals(null, res[1532].exec("x{1234}XYZ", 4864));
+assertEquals(null, res[1532].exec("Ax{1234}XYZ", 4865));
+assertEquals(null, res[1532].exec("XYZ", 4866));
+assertEquals("X", res[1533].exec("XYZ"), 4867);
+assertEquals("AX", res[1533].exec("AXYZ"), 4868);
+assertEquals(null, res[1533].exec("x{1234}XYZ", 4869));
+assertEquals(null, res[1533].exec("Ax{1234}XYZ", 4870));
+assertEquals(null, res[1533].exec("** Failers", 4871));
+assertEquals("X", res[1534].exec("XYZ"), 4872);
+assertEquals(null, res[1534].exec("** Failers", 4873));
+assertEquals("AX", res[1534].exec("AXYZ"), 4874);
+assertEquals(null, res[1534].exec("x{1234}XYZ", 4875));
+assertEquals(null, res[1534].exec("Ax{1234}XYZ", 4876));
+assertEquals(null, res[1535].exec("abcdefgh", 4877));
+assertEquals(null, res[1535].exec("x{1234}\n\x0dx{3456}xyz ", 4878));
+assertEquals(null, res[1536].exec("abcdefgh", 4879));
+assertEquals(null, res[1536].exec("x{1234}\n\x0dx{3456}xyz ", 4880));
+assertEquals(null, res[1537].exec("** Failers", 4881));
+assertEquals(null, res[1537].exec("abcdefgh", 4882));
+assertEquals(null, res[1537].exec("x{1234}\n\x0dx{3456}xyz ", 4883));
+assertEquals(null, res[1538].exec(" AXY", 4884));
+assertEquals(null, res[1538].exec(" aXY", 4885));
+assertEquals(null, res[1538].exec(" x{1c5}XY", 4886));
+assertEquals(null, res[1538].exec(" ** Failers", 4887));
+assertEquals(null, res[1538].exec(" x{1bb}XY", 4888));
+assertEquals(null, res[1538].exec(" x{2b0}XY", 4889));
+assertEquals(null, res[1538].exec(" !XY      ", 4890));
+assertEquals(null, res[1539].exec(" AXY", 4891));
+assertEquals(null, res[1539].exec(" aXY", 4892));
+assertEquals(null, res[1539].exec(" x{1c5}XY", 4893));
+assertEquals(null, res[1539].exec(" ** Failers", 4894));
+assertEquals(null, res[1539].exec(" x{1bb}XY", 4895));
+assertEquals(null, res[1539].exec(" x{2b0}XY", 4896));
+assertEquals(null, res[1539].exec(" !XY      ", 4897));
+assertEquals(null, res[1539].exec(" AXY", 4898));
+assertEquals(null, res[1539].exec(" aXY", 4899));
+assertEquals(null, res[1539].exec(" AbcdeXyz ", 4900));
+assertEquals(null, res[1539].exec(" x{1c5}AbXY", 4901));
+assertEquals(null, res[1539].exec(" abcDEXypqreXlmn ", 4902));
+assertEquals(null, res[1539].exec(" ** Failers", 4903));
+assertEquals(null, res[1539].exec(" x{1bb}XY", 4904));
+assertEquals(null, res[1539].exec(" x{2b0}XY", 4905));
+assertEquals(null, res[1539].exec(" !XY      ", 4906));
+assertEquals(null, res[1540].exec(" AXY", 4907));
+assertEquals(null, res[1540].exec(" aXY", 4908));
+assertEquals(null, res[1540].exec(" AbcdeXyz ", 4909));
+assertEquals(null, res[1540].exec(" x{1c5}AbXY", 4910));
+assertEquals(null, res[1540].exec(" abcDEXypqreXlmn ", 4911));
+assertEquals(null, res[1540].exec(" ** Failers", 4912));
+assertEquals(null, res[1540].exec(" x{1bb}XY", 4913));
+assertEquals(null, res[1540].exec(" x{2b0}XY", 4914));
+assertEquals(null, res[1540].exec(" !XY      ", 4915));
+assertEquals(null, res[1540].exec(" AXY", 4916));
+assertEquals(null, res[1540].exec(" aXY", 4917));
+assertEquals(null, res[1540].exec(" AbcdeXyz ", 4918));
+assertEquals(null, res[1540].exec(" x{1c5}AbXY", 4919));
+assertEquals(null, res[1540].exec(" abcDEXypqreXlmn ", 4920));
+assertEquals(null, res[1540].exec(" ** Failers", 4921));
+assertEquals(null, res[1540].exec(" x{1bb}XY", 4922));
+assertEquals(null, res[1540].exec(" x{2b0}XY", 4923));
+assertEquals(null, res[1540].exec(" !XY      ", 4924));
+assertEquals(null, res[1541].exec(" AXY", 4925));
+assertEquals(null, res[1541].exec(" aXY", 4926));
+assertEquals(null, res[1541].exec(" AbcdeXyz ", 4927));
+assertEquals(null, res[1541].exec(" x{1c5}AbXY", 4928));
+assertEquals(null, res[1541].exec(" abcDEXypqreXlmn ", 4929));
+assertEquals(null, res[1541].exec(" ** Failers", 4930));
+assertEquals(null, res[1541].exec(" x{1bb}XY", 4931));
+assertEquals(null, res[1541].exec(" x{2b0}XY", 4932));
+assertEquals(null, res[1541].exec(" !XY      ", 4933));
+assertEquals(null, res[1542].exec(" !XY", 4934));
+assertEquals(null, res[1542].exec(" x{1bb}XY", 4935));
+assertEquals(null, res[1542].exec(" x{2b0}XY", 4936));
+assertEquals(null, res[1542].exec(" ** Failers", 4937));
+assertEquals(null, res[1542].exec(" x{1c5}XY", 4938));
+assertEquals(null, res[1542].exec(" AXY      ", 4939));
+assertEquals(null, res[1543].exec(" !XY", 4940));
+assertEquals(null, res[1543].exec(" x{1bb}XY", 4941));
+assertEquals(null, res[1543].exec(" x{2b0}XY", 4942));
+assertEquals(null, res[1543].exec(" ** Failers", 4943));
+assertEquals(null, res[1543].exec(" x{1c5}XY", 4944));
+assertEquals(null, res[1543].exec(" AXY      ", 4945));
+assertEquals(null, res[1543].exec("x{c0}x{e0}x{116}x{117}", 4946));
+assertEquals(null, res[1543].exec("x{c0}x{e0}x{116}x{117}", 4947));
+assertEquals(null, res[1545].exec("123abcdefg", 4948));
+assertEquals(null, res[1545].exec("123abc\xc4\xc5zz", 4949));
+assertEquals(null, res[1546].exec("x{102A4}x{AA52}x{A91D}x{1C46}x{10283}x{1092E}x{1C6B}x{A93B}x{A8BF}x{1BA0}x{A50A}====", 4950));
+assertEquals(null, res[1546].exec("x{a77d}x{1d79}", 4951));
+assertEquals(null, res[1546].exec("x{1d79}x{a77d} ", 4952));
+assertEquals(null, res[1546].exec("x{a77d}x{1d79}", 4953));
+assertEquals(null, res[1546].exec("** Failers ", 4954));
+assertEquals(null, res[1546].exec("x{1d79}x{a77d} ", 4955));
+assertThrows("var re = //;", 4956);
diff --git a/deps/v8/test/mjsunit/regexp-standalones.js b/deps/v8/test/mjsunit/regexp-standalones.js
new file mode 100644
index 0000000..4699754
--- /dev/null
+++ b/deps/v8/test/mjsunit/regexp-standalones.js
@@ -0,0 +1,78 @@
+// Copyright 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.
+
+/* Many of the Mozilla regexp tests used 'toSource' to test their
+ * results.  Since we don't currently support toSource, those tests
+ * are disabled and standalone versions are included here.
+ */
+
+// Tests from ecma_3/RegExp/regress-78156.js
+var string = 'aaa\n789\r\nccc\r\n345';
+var pattern = /^\d/gm;
+var result = string.match(pattern);
+assertEquals(2, result.length, "1");
+assertEquals('7', result[0], "2");
+assertEquals('3', result[1], "3");
+
+pattern = /\d$/gm;
+result = string.match(pattern);
+assertEquals(2, result.length, "4");
+assertEquals('9', result[0], "5");
+assertEquals('5', result[1], "6");
+
+string = 'aaa\n789\r\nccc\r\nddd';
+pattern = /^\d/gm;
+result = string.match(pattern);
+assertEquals(1, result.length, "7");
+assertEquals('7', result[0], "8");
+
+pattern = /\d$/gm;
+result = string.match(pattern);
+assertEquals(1, result.length, "9");
+assertEquals('9', result[0], "10");
+
+// Tests from ecma_3/RegExp/regress-72964.js
+pattern = /[\S]+/;
+string = '\u00BF\u00CD\u00BB\u00A7';
+result = string.match(pattern);
+assertEquals(1, result.length, "11");
+assertEquals(string, result[0], "12");
+
+string = '\u00BF\u00CD \u00BB\u00A7';
+result = string.match(pattern);
+assertEquals(1, result.length, "13");
+assertEquals('\u00BF\u00CD', result[0], "14");
+
+string = '\u4e00\uac00\u4e03\u4e00';
+result = string.match(pattern);
+assertEquals(1, result.length, "15");
+assertEquals(string, result[0], "16");
+
+string = '\u4e00\uac00 \u4e03\u4e00';
+result = string.match(pattern);
+assertEquals(1, result.length, "17");
+assertEquals('\u4e00\uac00', result[0], "18");
diff --git a/deps/v8/test/mjsunit/regexp-static.js b/deps/v8/test/mjsunit/regexp-static.js
new file mode 100644
index 0000000..9e73f3d
--- /dev/null
+++ b/deps/v8/test/mjsunit/regexp-static.js
@@ -0,0 +1,167 @@
+// Copyright 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.
+
+// Test that we throw exceptions when calling test and exec with no
+// input.  This is not part of the spec, but we do it for
+// compatibility with JSC.
+assertThrows("/a/.test()");
+assertThrows("/a/.exec()");
+
+// Test that we do not throw exceptions once the static RegExp.input
+// field has been set.
+RegExp.input = "a";
+assertDoesNotThrow("/a/.test()");
+assertDoesNotThrow("/a/.exec()");
+
+// Test the (deprecated as of JS 1.5) properties of the RegExp function.
+var re = /((\d+)\.(\d+))/;
+var s = 'abc123.456def';
+
+re.exec(s);
+
+assertEquals(s, RegExp.input);
+assertEquals('123.456', RegExp.lastMatch);
+assertEquals('456', RegExp.lastParen);
+assertEquals('abc', RegExp.leftContext);
+assertEquals('def', RegExp.rightContext);
+
+assertEquals(s, RegExp['$_']);
+assertEquals('123.456', RegExp['$&']);
+assertEquals('456', RegExp['$+']);
+assertEquals('abc', RegExp['$`']);
+assertEquals('def', RegExp["$'"]);
+
+assertEquals('123.456', RegExp['$1']);
+assertEquals('123', RegExp['$2']);
+assertEquals('456', RegExp['$3']);
+for (var i = 4; i < 10; ++i) {
+  assertEquals('', RegExp['$' + i]);
+}
+
+// They should be read only.
+RegExp['$1'] = 'fisk';
+assertEquals('123.456', RegExp['$1']);
+
+// String.prototype.match and String.prototype.replace (when given a
+// regexp) and also RegExp.prototype.test should all behave as if
+// RegExp.prototype.exec were called.
+s = 'ghi789.012jkl';
+s.match(re);
+assertEquals(s, RegExp.input);
+assertEquals('789.012', RegExp.lastMatch);
+assertEquals('012', RegExp.lastParen);
+assertEquals('ghi', RegExp.leftContext);
+assertEquals('jkl', RegExp.rightContext);
+assertEquals(s, RegExp['$_']);
+assertEquals('789.012', RegExp['$&']);
+assertEquals('012', RegExp['$+']);
+assertEquals('ghi', RegExp['$`']);
+assertEquals('jkl', RegExp["$'"]);
+assertEquals('789.012', RegExp['$1']);
+assertEquals('789', RegExp['$2']);
+assertEquals('012', RegExp['$3']);
+for (var i = 4; i < 10; ++i) {
+  assertEquals('', RegExp['$' + i]);
+}
+
+s = 'abc123.456def';
+s.replace(re, 'whocares');
+assertEquals(s, RegExp.input);
+assertEquals('123.456', RegExp.lastMatch);
+assertEquals('456', RegExp.lastParen);
+assertEquals('abc', RegExp.leftContext);
+assertEquals('def', RegExp.rightContext);
+assertEquals(s, RegExp['$_']);
+assertEquals('123.456', RegExp['$&']);
+assertEquals('456', RegExp['$+']);
+assertEquals('abc', RegExp['$`']);
+assertEquals('def', RegExp["$'"]);
+assertEquals('123.456', RegExp['$1']);
+assertEquals('123', RegExp['$2']);
+assertEquals('456', RegExp['$3']);
+for (var i = 4; i < 10; ++i) {
+  assertEquals('', RegExp['$' + i]);
+}
+
+s = 'ghi789.012jkl';
+re.test(s);
+assertEquals(s, RegExp.input);
+assertEquals('789.012', RegExp.lastMatch);
+assertEquals('012', RegExp.lastParen);
+assertEquals('ghi', RegExp.leftContext);
+assertEquals('jkl', RegExp.rightContext);
+assertEquals(s, RegExp['$_']);
+assertEquals('789.012', RegExp['$&']);
+assertEquals('012', RegExp['$+']);
+assertEquals('ghi', RegExp['$`']);
+assertEquals('jkl', RegExp["$'"]);
+assertEquals('789.012', RegExp['$1']);
+assertEquals('789', RegExp['$2']);
+assertEquals('012', RegExp['$3']);
+for (var i = 4; i < 10; ++i) {
+  assertEquals('', RegExp['$' + i]);
+}
+
+// String.prototype.replace must interleave matching and replacing when a
+// global regexp is matched and replaced with the result of a function, in
+// case the function uses the static properties of the regexp constructor.
+re = /(.)/g;
+function f() { return RegExp.$1; };
+assertEquals('abcd', 'abcd'.replace(re, f));
+
+// lastParen where the last parenthesis didn't match.
+assertEquals("foo,", /foo(?:a(x))?/.exec("foobx"), "lastParen setup");
+assertEquals("", RegExp.lastParen, "lastParen");
+
+// The same test for $1 to $9.
+for (var i = 1; i <= 9; i++) {
+  var haystack = "foo";
+  var re_text = "^foo";
+  for (var j = 0; j < i - 1; j++) {
+    haystack += "x";
+    re_text += "(x)";
+  }
+  re_text += "(?:a(x))?";
+  haystack += "bx";
+  var re = new RegExp(re_text);
+  assertTrue(re.test(haystack), "$" + i + " setup");
+  for (var j = 1; j < i - 1; j++) {
+    assertEquals("x", RegExp['$' + j], "$" + j + " in $" + i + " setup");
+  }
+  assertEquals("", RegExp['$' + (i)], "$" + i);
+}
+
+RegExp.multiline = "foo";
+assertTrue(typeof RegExp.multiline == typeof Boolean(), "RegExp.multiline coerces values to booleans");
+RegExp.input = Number();
+assertTrue(typeof RegExp.input == typeof String(), "RegExp.input coerces values to booleans");
+
+// Ensure that we save the correct string as the last subject when
+// we do a match on a sliced string (the top one not the underlying).
+var foo = "lsdfj sldkfj sdklfj læsdfjl sdkfjlsdk fjsdl fjsdljskdj flsj flsdkj flskd regexp: /foobar/\nldkfj sdlkfj sdkl";
+assertTrue(/^([a-z]+): (.*)/.test(foo.substring(foo.indexOf("regexp:"))), "regexp: setup");
+assertEquals("regexp", RegExp.$1, "RegExp.$1");
diff --git a/deps/v8/test/mjsunit/regexp-string-methods.js b/deps/v8/test/mjsunit/regexp-string-methods.js
new file mode 100644
index 0000000..ef3bf6e
--- /dev/null
+++ b/deps/v8/test/mjsunit/regexp-string-methods.js
@@ -0,0 +1,51 @@
+// 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.
+
+// Regexp shouldn't use String.prototype.slice()
+var s = new String("foo");
+assertEquals("f", s.slice(0,1));
+String.prototype.slice = function() { return "x"; }
+assertEquals("x", s.slice(0,1));
+assertEquals("g", /g/.exec("gg"));
+
+// Regexp shouldn't use String.prototype.charAt()
+var f1 = new RegExp("f", "i");
+assertEquals("F", f1.exec("F"));
+assertEquals("f", "foo".charAt(0));
+String.prototype.charAt = function(idx) { return 'g'; };
+assertEquals("g", "foo".charAt(0));
+var f2 = new RegExp("[g]", "i");
+assertEquals("G", f2.exec("G"));
+assertTrue(f2.ignoreCase);
+
+// On the other hand test is defined in a semi-coherent way as a call to exec.
+// 15.10.6.3
+// We match other browsers in using the original value of RegExp.prototype.exec.
+// I.e., RegExp.prototype.test shouldn't use the current value of
+// RegExp.prototype.exec.
+RegExp.prototype.exec = function(string) { return 'x'; }
+assertFalse(/f/.test('x'));
diff --git a/deps/v8/test/mjsunit/regexp.js b/deps/v8/test/mjsunit/regexp.js
new file mode 100644
index 0000000..e562df0
--- /dev/null
+++ b/deps/v8/test/mjsunit/regexp.js
@@ -0,0 +1,377 @@
+// Copyright 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.
+
+function testEscape(str, regex) {
+  assertEquals("foo:bar:baz", str.split(regex).join(":"));
+}
+
+testEscape("foo\nbar\nbaz", /\n/);
+testEscape("foo bar baz", /\s/);
+testEscape("foo\tbar\tbaz", /\s/);
+testEscape("foo-bar-baz", /\u002D/);
+
+// Test containing null char in regexp.
+var s = '[' + String.fromCharCode(0) + ']';
+var re = new RegExp(s);
+assertEquals(s.match(re).length, 1);
+assertEquals(s.match(re)[0], String.fromCharCode(0));
+
+// Test strings containing all line separators
+s = 'aA\nbB\rcC\r\ndD\u2028eE\u2029fF';
+re = /^./gm; // any non-newline character at the beginning of a line
+var result = s.match(re);
+assertEquals(result.length, 6);
+assertEquals(result[0], 'a');
+assertEquals(result[1], 'b');
+assertEquals(result[2], 'c');
+assertEquals(result[3], 'd');
+assertEquals(result[4], 'e');
+assertEquals(result[5], 'f');
+
+re = /.$/gm; // any non-newline character at the end of a line
+result = s.match(re);
+assertEquals(result.length, 6);
+assertEquals(result[0], 'A');
+assertEquals(result[1], 'B');
+assertEquals(result[2], 'C');
+assertEquals(result[3], 'D');
+assertEquals(result[4], 'E');
+assertEquals(result[5], 'F');
+
+re = /^[^]/gm; // *any* character at the beginning of a line
+result = s.match(re);
+assertEquals(result.length, 7);
+assertEquals(result[0], 'a');
+assertEquals(result[1], 'b');
+assertEquals(result[2], 'c');
+assertEquals(result[3], '\n');
+assertEquals(result[4], 'd');
+assertEquals(result[5], 'e');
+assertEquals(result[6], 'f');
+
+re = /[^]$/gm; // *any* character at the end of a line
+result = s.match(re);
+assertEquals(result.length, 7);
+assertEquals(result[0], 'A');
+assertEquals(result[1], 'B');
+assertEquals(result[2], 'C');
+assertEquals(result[3], '\r');
+assertEquals(result[4], 'D');
+assertEquals(result[5], 'E');
+assertEquals(result[6], 'F');
+
+// Some tests from the Mozilla tests, where our behavior differs from
+// SpiderMonkey.
+// From ecma_3/RegExp/regress-334158.js
+assertTrue(/\ca/.test( "\x01" ));
+assertFalse(/\ca/.test( "\\ca" ));
+// Passes in KJS, fails in IrregularExpressions.
+// See http://code.google.com/p/v8/issues/detail?id=152
+//assertTrue(/\c[a/]/.test( "\x1ba/]" ));
+
+
+// Test \c in character class
+re = /^[\cM]$/;
+assertTrue(re.test("\r"));
+assertFalse(re.test("M"));
+assertFalse(re.test("c"));
+assertFalse(re.test("\\"));
+assertFalse(re.test("\x03"));  // I.e., read as \cc
+
+re = /^[\c]]$/;
+assertTrue(re.test("c]"));
+assertFalse(re.test("\\]"));
+assertFalse(re.test("\x1d"));  // ']' & 0x1f
+assertFalse(re.test("\\]"));
+assertFalse(re.test("\x03]"));  // I.e., read as \cc
+
+
+// Test that we handle \s and \S correctly inside some bizarre
+// character classes.
+re = /[\s-:]/;
+assertTrue(re.test('-'));
+assertTrue(re.test(':'));
+assertTrue(re.test(' '));
+assertTrue(re.test('\t'));
+assertTrue(re.test('\n'));
+assertFalse(re.test('a'));
+assertFalse(re.test('Z'));
+
+re = /[\S-:]/;
+assertTrue(re.test('-'));
+assertTrue(re.test(':'));
+assertFalse(re.test(' '));
+assertFalse(re.test('\t'));
+assertFalse(re.test('\n'));
+assertTrue(re.test('a'));
+assertTrue(re.test('Z'));
+
+re = /[^\s-:]/;
+assertFalse(re.test('-'));
+assertFalse(re.test(':'));
+assertFalse(re.test(' '));
+assertFalse(re.test('\t'));
+assertFalse(re.test('\n'));
+assertTrue(re.test('a'));
+assertTrue(re.test('Z'));
+
+re = /[^\S-:]/;
+assertFalse(re.test('-'));
+assertFalse(re.test(':'));
+assertTrue(re.test(' '));
+assertTrue(re.test('\t'));
+assertTrue(re.test('\n'));
+assertFalse(re.test('a'));
+assertFalse(re.test('Z'));
+
+re = /[\s]/;
+assertFalse(re.test('-'));
+assertFalse(re.test(':'));
+assertTrue(re.test(' '));
+assertTrue(re.test('\t'));
+assertTrue(re.test('\n'));
+assertFalse(re.test('a'));
+assertFalse(re.test('Z'));
+
+re = /[^\s]/;
+assertTrue(re.test('-'));
+assertTrue(re.test(':'));
+assertFalse(re.test(' '));
+assertFalse(re.test('\t'));
+assertFalse(re.test('\n'));
+assertTrue(re.test('a'));
+assertTrue(re.test('Z'));
+
+re = /[\S]/;
+assertTrue(re.test('-'));
+assertTrue(re.test(':'));
+assertFalse(re.test(' '));
+assertFalse(re.test('\t'));
+assertFalse(re.test('\n'));
+assertTrue(re.test('a'));
+assertTrue(re.test('Z'));
+
+re = /[^\S]/;
+assertFalse(re.test('-'));
+assertFalse(re.test(':'));
+assertTrue(re.test(' '));
+assertTrue(re.test('\t'));
+assertTrue(re.test('\n'));
+assertFalse(re.test('a'));
+assertFalse(re.test('Z'));
+
+re = /[\s\S]/;
+assertTrue(re.test('-'));
+assertTrue(re.test(':'));
+assertTrue(re.test(' '));
+assertTrue(re.test('\t'));
+assertTrue(re.test('\n'));
+assertTrue(re.test('a'));
+assertTrue(re.test('Z'));
+
+re = /[^\s\S]/;
+assertFalse(re.test('-'));
+assertFalse(re.test(':'));
+assertFalse(re.test(' '));
+assertFalse(re.test('\t'));
+assertFalse(re.test('\n'));
+assertFalse(re.test('a'));
+assertFalse(re.test('Z'));
+
+// Test beginning and end of line assertions with or without the
+// multiline flag.
+re = /^\d+/;
+assertFalse(re.test("asdf\n123"));
+re = /^\d+/m;
+assertTrue(re.test("asdf\n123"));
+
+re = /\d+$/;
+assertFalse(re.test("123\nasdf"));
+re = /\d+$/m;
+assertTrue(re.test("123\nasdf"));
+
+// Test that empty matches are handled correctly for multiline global
+// regexps.
+re = /^(.*)/mg;
+assertEquals(3, "a\n\rb".match(re).length);
+assertEquals("*a\n*b\r*c\n*\r*d\r*\n*e", "a\nb\rc\n\rd\r\ne".replace(re, "*$1"));
+
+// Test that empty matches advance one character
+re = new RegExp("", "g");
+assertEquals("xAx", "A".replace(re, "x"));
+assertEquals(3, String.fromCharCode(161).replace(re, "x").length);
+
+// Test that we match the KJS behavior with regard to undefined constructor
+// arguments:
+re = new RegExp();
+// KJS actually shows this as '//'.  Here we match the Firefox behavior (ie,
+// giving a syntactically legal regexp literal).
+assertEquals('/(?:)/', re.toString());
+re = new RegExp(void 0);
+assertEquals('/(?:)/', re.toString());
+re.compile();
+assertEquals('/(?:)/', re.toString());
+re.compile(void 0);
+assertEquals('/undefined/', re.toString());
+
+
+// Check for lazy RegExp literal creation
+function lazyLiteral(doit) {
+  if (doit) return "".replace(/foo(/gi, "");
+  return true;
+}
+
+assertTrue(lazyLiteral(false));
+assertThrows("lazyLiteral(true)");
+
+// Check $01 and $10
+re = new RegExp("(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)");
+assertEquals("t", "123456789t".replace(re, "$10"), "$10");
+assertEquals("15", "123456789t".replace(re, "$15"), "$10");
+assertEquals("1", "123456789t".replace(re, "$01"), "$01");
+assertEquals("$001", "123456789t".replace(re, "$001"), "$001");
+re = new RegExp("foo(.)");
+assertEquals("bar$0", "foox".replace(re, "bar$0"), "$0");
+assertEquals("bar$00", "foox".replace(re, "bar$00"), "$00");
+assertEquals("bar$000", "foox".replace(re, "bar$000"), "$000");
+assertEquals("barx", "foox".replace(re, "bar$01"), "$01 2");
+assertEquals("barx5", "foox".replace(re, "bar$15"), "$15");
+
+assertFalse(/()foo$\1/.test("football"), "football1");
+assertFalse(/foo$(?=ball)/.test("football"), "football2");
+assertFalse(/foo$(?!bar)/.test("football"), "football3");
+assertTrue(/()foo$\1/.test("foo"), "football4");
+assertTrue(/foo$(?=(ball)?)/.test("foo"), "football5");
+assertTrue(/()foo$(?!bar)/.test("foo"), "football6");
+assertFalse(/(x?)foo$\1/.test("football"), "football7");
+assertFalse(/foo$(?=ball)/.test("football"), "football8");
+assertFalse(/foo$(?!bar)/.test("football"), "football9");
+assertTrue(/(x?)foo$\1/.test("foo"), "football10");
+assertTrue(/foo$(?=(ball)?)/.test("foo"), "football11");
+assertTrue(/foo$(?!bar)/.test("foo"), "football12");
+
+// Check that the back reference has two successors.  See
+// BackReferenceNode::PropagateForward.
+assertFalse(/f(o)\b\1/.test('foo'));
+assertTrue(/f(o)\B\1/.test('foo'));
+
+// Back-reference, ignore case:
+// ASCII
+assertEquals("xaAx,a", String(/x(a)\1x/i.exec("xaAx")), "backref-ASCII");
+assertFalse(/x(...)\1/i.test("xaaaaa"), "backref-ASCII-short");
+assertTrue(/x((?:))\1\1x/i.test("xx"), "backref-ASCII-empty");
+assertTrue(/x(?:...|(...))\1x/i.test("xabcx"), "backref-ASCII-uncaptured");
+assertTrue(/x(?:...|(...))\1x/i.test("xabcABCx"), "backref-ASCII-backtrack");
+assertEquals("xaBcAbCABCx,aBc",
+             String(/x(...)\1\1x/i.exec("xaBcAbCABCx")),
+             "backref-ASCII-twice");
+
+for (var i = 0; i < 128; i++) {
+  var testName = "backref-ASCII-char-" + i + "," + (i^0x20);
+  var test = /^(.)\1$/i.test(String.fromCharCode(i, i ^ 0x20))
+  var c = String.fromCharCode(i);
+  if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')) {
+    assertTrue(test, testName);
+  } else {
+    assertFalse(test, testName);
+  }
+}
+
+assertFalse(/f(o)$\1/.test('foo'), "backref detects at_end");
+
+// Check decimal escapes doesn't overflow.
+// (Note: \214 is interpreted as octal).
+assertEquals(/\2147483648/.exec("\x8c7483648"),
+             ["\x8c7483648"],
+             "Overflow decimal escape");
+
+
+// Check numbers in quantifiers doesn't overflow and doesn't throw on
+// too large numbers.
+assertFalse(/a{111111111111111111111111111111111111111111111}/.test('b'),
+            "overlarge1");
+assertFalse(/a{999999999999999999999999999999999999999999999}/.test('b'),
+            "overlarge2");
+assertFalse(/a{1,111111111111111111111111111111111111111111111}/.test('b'),
+            "overlarge3");
+assertFalse(/a{1,999999999999999999999999999999999999999999999}/.test('b'),
+            "overlarge4");
+assertFalse(/a{2147483648}/.test('b'),
+            "overlarge5");
+assertFalse(/a{21474836471}/.test('b'),
+            "overlarge6");
+assertFalse(/a{1,2147483648}/.test('b'),
+            "overlarge7");
+assertFalse(/a{1,21474836471}/.test('b'),
+            "overlarge8");
+assertFalse(/a{2147483648,2147483648}/.test('b'),
+            "overlarge9");
+assertFalse(/a{21474836471,21474836471}/.test('b'),
+            "overlarge10");
+assertFalse(/a{2147483647}/.test('b'),
+            "overlarge11");
+assertFalse(/a{1,2147483647}/.test('b'),
+            "overlarge12");
+assertTrue(/a{1,2147483647}/.test('a'),
+            "overlarge13");
+assertFalse(/a{2147483647,2147483647}/.test('a'),
+            "overlarge14");
+
+
+// Check that we don't read past the end of the string.
+assertFalse(/f/.test('b'));
+assertFalse(/[abc]f/.test('x'));
+assertFalse(/[abc]f/.test('xa'));
+assertFalse(/[abc]</.test('x'));
+assertFalse(/[abc]</.test('xa'));
+assertFalse(/f/i.test('b'));
+assertFalse(/[abc]f/i.test('x'));
+assertFalse(/[abc]f/i.test('xa'));
+assertFalse(/[abc]</i.test('x'));
+assertFalse(/[abc]</i.test('xa'));
+assertFalse(/f[abc]/.test('x'));
+assertFalse(/f[abc]/.test('xa'));
+assertFalse(/<[abc]/.test('x'));
+assertFalse(/<[abc]/.test('xa'));
+assertFalse(/f[abc]/i.test('x'));
+assertFalse(/f[abc]/i.test('xa'));
+assertFalse(/<[abc]/i.test('x'));
+assertFalse(/<[abc]/i.test('xa'));
+
+// Test that merging of quick test masks gets it right.
+assertFalse(/x([0-7]%%x|[0-6]%%y)/.test('x7%%y'), 'qt');
+assertFalse(/()x\1(y([0-7]%%%x|[0-6]%%%y)|dkjasldkas)/.test('xy7%%%y'), 'qt2');
+assertFalse(/()x\1(y([0-7]%%%x|[0-6]%%%y)|dkjasldkas)/.test('xy%%%y'), 'qt3');
+assertFalse(/()x\1y([0-7]%%%x|[0-6]%%%y)/.test('xy7%%%y'), 'qt4');
+assertFalse(/()x\1(y([0-7]%%%x|[0-6]%%%y)|dkjasldkas)/.test('xy%%%y'), 'qt5');
+assertFalse(/()x\1y([0-7]%%%x|[0-6]%%%y)/.test('xy7%%%y'), 'qt6');
+assertFalse(/xy([0-7]%%%x|[0-6]%%%y)/.test('xy7%%%y'), 'qt7');
+assertFalse(/x([0-7]%%%x|[0-6]%%%y)/.test('x7%%%y'), 'qt8');
+
+
+// Don't hang on this one.
+/[^\xfe-\xff]*/.test("");
diff --git a/deps/v8/test/mjsunit/regress/regress-1030466.js b/deps/v8/test/mjsunit/regress/regress-1030466.js
new file mode 100644
index 0000000..8427ba0
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1030466.js
@@ -0,0 +1,45 @@
+// Copyright 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.
+
+// Whenever we enter a with-scope, we copy the context. This in itself is fine
+// (contexts may escape), but when leaving a with-scope, we currently also copy
+// the context instead of reverting to the original. This does not work because
+// inner functions may already have been created using the original context. In
+// the failing test case below, the inner function is run in the original context
+// (where x is undefined), but the assignment to x after the with-statement is
+// run in the copied context:
+
+var result = (function outer() {
+ with ({}) { }
+ var x = 10;
+ function inner() {
+   return x;
+ };
+ return inner();
+})();
+
+assertEquals(10, result);
diff --git a/deps/v8/test/mjsunit/regress/regress-1036894.js b/deps/v8/test/mjsunit/regress/regress-1036894.js
new file mode 100644
index 0000000..d89ceda
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1036894.js
@@ -0,0 +1,38 @@
+// Copyright 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.
+
+xeval = function(s) { eval(s); }
+xeval("$=function anonymous() { /*noex*/do {} while(({ get x(x) { break ; }, set x() { (undefined);} })); }");
+
+foo = function() { eval("$=function anonymous() { /*noex*/do {} while(({ get x(x) { break ; }, set x() { (undefined);} })); }"); }
+foo();
+
+xeval = function(s) { eval(s); }
+eval("$=function anonymous() { /*noex*/do {} while(({ get x(x) { break ; }, set x() { (undefined);} })); }");
+
+xeval = function(s) { eval(s); }
+xeval('$=function(){L: {break L;break L;}};');
diff --git a/deps/v8/test/mjsunit/regress/regress-1039610.js b/deps/v8/test/mjsunit/regress/regress-1039610.js
new file mode 100644
index 0000000..fd5c549
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1039610.js
@@ -0,0 +1,29 @@
+// Copyright 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.
+
+// Make sure that the Debug object does not return to the global object
+assertTrue(typeof(Debug) === 'undefined');
\ No newline at end of file
diff --git a/deps/v8/test/mjsunit/regress/regress-1050043.js b/deps/v8/test/mjsunit/regress/regress-1050043.js
new file mode 100644
index 0000000..e42728f
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1050043.js
@@ -0,0 +1,51 @@
+// Copyright 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.
+
+function unsignedShiftRight(val, shift) {
+  return val >>> shift;
+}
+
+assertEquals(        15, unsignedShiftRight(15, 0), "15 >>> 0");
+assertEquals(         7, unsignedShiftRight(15, 1), "15 >>> 1");
+assertEquals(         3, unsignedShiftRight(15, 2), "15 >>> 2");
+
+assertEquals(4294967288, unsignedShiftRight(-8, 0), "-8 >>> 0");
+assertEquals(2147483644, unsignedShiftRight(-8, 1), "-8 >>> 1");
+assertEquals(1073741822, unsignedShiftRight(-8, 2), "-8 >>> 2");
+
+assertEquals(         1, unsignedShiftRight(-8, 31), "-8 >>> 31");
+assertEquals(4294967288, unsignedShiftRight(-8, 32), "-8 >>> 32");
+assertEquals(2147483644, unsignedShiftRight(-8, 33), "-8 >>> 33");
+assertEquals(1073741822, unsignedShiftRight(-8, 34), "-8 >>> 34");
+
+assertEquals(2147483648, unsignedShiftRight(0x80000000, 0), "0x80000000 >>> 0");
+assertEquals(1073741824, unsignedShiftRight(0x80000000, 1), "0x80000000 >>> 1");
+assertEquals( 536870912, unsignedShiftRight(0x80000000, 2), "0x80000000 >>> 2");
+
+assertEquals(1073741824, unsignedShiftRight(0x40000000, 0), "0x40000000 >>> 0");
+assertEquals( 536870912, unsignedShiftRight(0x40000000, 1), "0x40000000 >>> 1");
+assertEquals( 268435456, unsignedShiftRight(0x40000000, 2), "0x40000000 >>> 2");
diff --git a/deps/v8/test/mjsunit/regress/regress-1062422.js b/deps/v8/test/mjsunit/regress/regress-1062422.js
new file mode 100644
index 0000000..1e2c798
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1062422.js
@@ -0,0 +1,30 @@
+// Copyright 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.
+
+// 1062422 Ensure that accessors can handle unexpected receivers.
+Number.prototype.__proto__ = String.prototype;
+assertEquals((123).length, 0)
diff --git a/deps/v8/test/mjsunit/regress/regress-1066899.js b/deps/v8/test/mjsunit/regress/regress-1066899.js
new file mode 100644
index 0000000..37fd554
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1066899.js
@@ -0,0 +1,37 @@
+// Copyright 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.
+
+// This test case segfaults in generated code. See
+// issue #1066899.
+function Crash() {
+  for (var key in [0]) {
+    try { } finally { continue; }
+  }
+}
+
+Crash();
+
diff --git a/deps/v8/test/mjsunit/regress/regress-1081309.js b/deps/v8/test/mjsunit/regress/regress-1081309.js
new file mode 100644
index 0000000..a771ac0
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1081309.js
@@ -0,0 +1,110 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// Make sure that the backtrace command can be processed when the receiver is
+// undefined.
+listenerCalled = false;
+exception = false;
+
+function ParsedResponse(json) {
+  this.response_ = eval('(' + json + ')');
+  this.refs_ = [];
+  if (this.response_.refs) {
+    for (var i = 0; i < this.response_.refs.length; i++) {
+      this.refs_[this.response_.refs[i].handle] = this.response_.refs[i];
+    }
+  }
+}
+
+
+ParsedResponse.prototype.response = function() {
+  return this.response_;
+}
+
+
+ParsedResponse.prototype.body = function() {
+  return this.response_.body;
+}
+
+
+ParsedResponse.prototype.lookup = function(handle) {
+  return this.refs_[handle];
+}
+
+
+function listener(event, exec_state, event_data, data) {
+  try {
+  if (event == Debug.DebugEvent.Exception)
+  {
+    // The expected backtrace is
+    // 1: g
+    // 0: [anonymous]
+    
+    // Get the debug command processor.
+    var dcp = exec_state.debugCommandProcessor();
+
+    // Get the backtrace.
+    var json;
+    json = '{"seq":0,"type":"request","command":"backtrace"}'
+    var response = new ParsedResponse(dcp.processDebugJSONRequest(json));
+    var backtrace = response.body();
+    assertEquals(2, backtrace.totalFrames);
+    assertEquals(2, backtrace.frames.length);
+
+    assertEquals("g", response.lookup(backtrace.frames[0].func.ref).name);
+    assertEquals("", response.lookup(backtrace.frames[1].func.ref).name);
+
+    listenerCalled = true;
+  }
+  } catch (e) {
+    exception = e
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Call method on undefined.
+function g() {
+  (void 0).f();
+};
+
+// Break on the exception to do a backtrace with undefined as receiver.
+Debug.setBreakOnException(true);
+try {
+  g();
+} catch(e) {
+  // Ignore the exception "Cannot call method 'x' of undefined"
+}
+
+// Make sure that the debug event listener vas invoked.
+assertTrue(listenerCalled, "listener not called");
+assertFalse(exception, "exception in listener", exception)
diff --git a/deps/v8/test/mjsunit/regress/regress-1102760.js b/deps/v8/test/mjsunit/regress/regress-1102760.js
new file mode 100644
index 0000000..890ecab
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1102760.js
@@ -0,0 +1,35 @@
+// Copyright 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.
+
+function F() {
+  return arguments.length;
+}
+
+assertEquals(0, F.apply(), "no receiver or args");
+assertEquals(0, F.apply(this), "no args");
+assertEquals(0, F.apply(this, []), "empty args");
+assertEquals(0, F.apply(this, [], 0), "empty args, extra argument");
diff --git a/deps/v8/test/mjsunit/regress/regress-1110164.js b/deps/v8/test/mjsunit/regress/regress-1110164.js
new file mode 100644
index 0000000..33f96af
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1110164.js
@@ -0,0 +1,46 @@
+// Copyright 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.
+
+var o = { x: 0, f: function() { return 42; } };
+delete o.x;  // go dictionary
+
+function CallF(o) {
+  return o.f();
+}
+
+// Make sure the call IC in CallF is initialized.
+for (var i = 0; i < 10; i++) assertEquals(42, CallF(o));
+
+var caught = false;
+o.f = 87;
+try {
+  CallF(o);
+} catch (e) {
+  caught = true;
+  assertTrue(e instanceof TypeError);
+}
+assertTrue(caught);
diff --git a/deps/v8/test/mjsunit/regress/regress-1112051.js b/deps/v8/test/mjsunit/regress/regress-1112051.js
new file mode 100644
index 0000000..0af6bb4
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1112051.js
@@ -0,0 +1,33 @@
+// Copyright 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.
+
+// Regression test for issue #1112051.
+function f() { }
+assertThrows("f.call.apply()");
+assertThrows("f.call.apply(null)");
+assertThrows("f.call.apply(null, [], 0)");
+assertThrows("f.call.apply(null, [1,2,3,4,5,6,7,8,9], 0)");
diff --git a/deps/v8/test/mjsunit/regress/regress-1114040.js b/deps/v8/test/mjsunit/regress/regress-1114040.js
new file mode 100644
index 0000000..9d1b320
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1114040.js
@@ -0,0 +1,58 @@
+// Copyright 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.
+
+function TestBreak() {
+  var sequence = "";
+  for (var a in [0,1]) {
+    L: {
+      for (var b in [2,3,4]) {
+        break L;
+      }
+    }
+    sequence += a;
+  }
+  return sequence;
+}
+
+
+function TestContinue() {
+  var sequence = "";
+  for (var a in [0,1]) {
+    L: do {
+      for (var b in [2,3,4]) {
+        continue L;
+      }
+    } while (false);
+    sequence += a;
+  }
+  return sequence;
+}
+
+
+assertEquals("01", TestBreak());
+assertEquals("01", TestContinue());
+
diff --git a/deps/v8/test/mjsunit/regress/regress-1134697.js b/deps/v8/test/mjsunit/regress/regress-1134697.js
new file mode 100644
index 0000000..3d851ae
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1134697.js
@@ -0,0 +1,31 @@
+// Copyright 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.
+
+// Regression test case for issue 1134697.
+// Must run using valgrind.
+
+(-90).toPrecision(6);
diff --git a/deps/v8/test/mjsunit/regress/regress-114.js b/deps/v8/test/mjsunit/regress/regress-114.js
new file mode 100644
index 0000000..6c1a6a3
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-114.js
@@ -0,0 +1,43 @@
+// Copyright 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.
+
+// German eszett
+assertEquals("FRIEDRICHSTRASSE 14", "friedrichstra\xDFe 14".toUpperCase());
+assertEquals("XXSSSSSSXX", "xx\xDF\xDF\xDFxx".toUpperCase());
+assertEquals("(SS)", "(\xDF)".toUpperCase());
+assertEquals("SS", "\xDF".toUpperCase());
+
+// Turkish dotted upper-case I lower-case converts to two characters
+assertEquals("i\u0307", "\u0130".toLowerCase());
+assertEquals("(i\u0307)", "(\u0130)".toLowerCase());
+assertEquals("xxi\u0307xx", "XX\u0130XX".toLowerCase());
+
+// Greek small upsilon with dialytika and tonos upper-case converts to three
+// characters
+assertEquals("\u03A5\u0308\u0301", "\u03B0".toUpperCase());
+assertEquals("(\u03A5\u0308\u0301)", "(\u03B0)".toUpperCase());
+assertEquals("XX\u03A5\u0308\u0301XX", "xx\u03B0xx".toUpperCase());
diff --git a/deps/v8/test/mjsunit/regress/regress-116.js b/deps/v8/test/mjsunit/regress/regress-116.js
new file mode 100644
index 0000000..7b4620c
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-116.js
@@ -0,0 +1,40 @@
+// Copyright 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.
+
+var testCache = {};
+var doLookup = function(id) {
+  return testCache[id] = 'foo';
+};
+
+var r2 = doLookup(0);
+var r1 = doLookup([0]);
+
+assertFalse(r1 === testCache);
+assertEquals('foo', r1);
+assertEquals('f', r1[0]);
+assertEquals('foo', r2);
+assertEquals('f', r2[0]);
diff --git a/deps/v8/test/mjsunit/regress/regress-1170187.js b/deps/v8/test/mjsunit/regress/regress-1170187.js
new file mode 100644
index 0000000..5e82f8a
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1170187.js
@@ -0,0 +1,80 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Make sure that the retreival of local variables are performed correctly even
+// when an adapter frame is present.
+
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+listenerCalled = false;
+exception = false;
+
+
+function checkName(name) {
+  assertTrue(name == 'a' || name == 'b' || name == 'c');
+}
+
+
+function checkValue(value) {
+  assertEquals(void 0, value);
+}
+
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      var local0Name = exec_state.frame(0).localName(0);
+      var local1Name = exec_state.frame(0).localName(1);
+      var local2Name = exec_state.frame(0).localName(2);
+      checkName(local0Name);
+      checkName(local1Name);
+      checkName(local2Name);
+      var local0Value = exec_state.frame(0).localValue(0).value();
+      var local1Value = exec_state.frame(0).localValue(1).value();
+      var local2Value = exec_state.frame(0).localValue(2).value();
+      checkValue(local0Value);
+      checkValue(local1Value);
+      checkValue(local2Value);
+      listenerCalled = true;
+    }
+  } catch (e) {
+    exception = e;
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Call a function with local variables passing a different number parameters
+// that the number of arguments.
+(function(x,y){var a,b,c; debugger; return 3})()
+
+// Make sure that the debug event listener vas invoked (again).
+assertTrue(listenerCalled);
+assertFalse(exception, "exception in listener")
diff --git a/deps/v8/test/mjsunit/regress/regress-1173979.js b/deps/v8/test/mjsunit/regress/regress-1173979.js
new file mode 100644
index 0000000..42649d0
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1173979.js
@@ -0,0 +1,48 @@
+// Copyright 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.
+
+// Ensure that null only equals null and undefined, also for variables.
+
+var null_var = null;
+var undef_var = [][0];
+var boolean_var = false;
+var number_var = 0;
+var string_var = "";
+var object_var = { foo : 0 };
+
+assertTrue(null_var == null_var);
+assertTrue(null_var == undef_var);
+assertTrue(null_var != boolean_var);
+assertTrue(null_var != number_var);
+assertTrue(null_var != string_var);
+assertTrue(null_var != object_var);
+
+assertTrue(undef_var == null_var);
+assertTrue(boolean_var != null_var);
+assertTrue(number_var != null_var);
+assertTrue(string_var != null_var);
+assertTrue(object_var != null_var);
diff --git a/deps/v8/test/mjsunit/regress/regress-1175390.js b/deps/v8/test/mjsunit/regress/regress-1175390.js
new file mode 100644
index 0000000..7b1a7e0
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1175390.js
@@ -0,0 +1,30 @@
+// Copyright 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.
+
+// Flags: --print-code --debug-code
+// Simply ensure that we can generate comments without crashing.
+a = 0;
diff --git a/deps/v8/test/mjsunit/regress/regress-1177518.js b/deps/v8/test/mjsunit/regress/regress-1177518.js
new file mode 100644
index 0000000..2ba3c11
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1177518.js
@@ -0,0 +1,39 @@
+// Copyright 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.
+
+// Make sure that natives and delayed natives don't use methods from the global
+// scope that could have been modified by input javascript.
+
+isFinite = 0;
+Math.floor = 0;
+Math.abs = 0;
+
+// uses Math.floor
+assertEquals(4, parseInt(4.5));
+
+// uses Math.abs, Math.floor and isFinite
+assertEquals('string', typeof (new Date(9999)).toString());
diff --git a/deps/v8/test/mjsunit/regress/regress-1177809.js b/deps/v8/test/mjsunit/regress/regress-1177809.js
new file mode 100644
index 0000000..703e607
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1177809.js
@@ -0,0 +1,31 @@
+// Copyright 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.
+
+// The encoding of large pc jumps caused code to be overwritten with
+// relocation information.  We pass this test if it does not crash.
+
+String.fromCharCode(48,48,48,59,32,102,111,110,116,45,119,101,105,103,104,116,58,98,111,108,100,59,102,111,110,116,45,102,97,109,105,108,121,58,65,114,105,97,108,44,32,72,101,108,118,101,116,105,99,97,44,32,115,97,110,115,45,115,101,114,105,102,44,86,101,114,100,97,110,97,34,32,99,111,108,111,114,61,34,35,70,70,48,48,48,48,34,62,70,79,82,69,88,47,80,65,82,38,35,51,48,52,59,60,119,98,114,32,47,62,84,69,32,38,35,51,48,52,59,38,35,51,53,48,59,76,69,77,76,69,82,38,35,51,48,52,59,60,47,102,111,110,116,62,60,47,115,112,97,110,62,60,47,116,100,62,10,60,47,116,114,62,60,116,114,62,10,60,116,100,32,97,108,105,103,110,61,34,108,101,102,116,34,62,60,115,112,97,110,32,105,100,61,34,97,99,95,100,101,115,99,34,62,60,102,111,110,116,32,115,116,121,108,101,61,34,102,111,110,116,45,115,105,122,101,58,49,49,112,120,59,32,99,111,108,111,114,58,35,48,48,48,48,48,48,59,32,102,111,110,116,45,102,97,109,105,108,121,58,65,114,105,97,108,44,32,72,101,108,118,101,116,105,99,97,44,32,115,97,110,115,45,115,101,114,105,102,44,86,101,114,100,97,110,97,34,62,38,112,111,117,110,100,59,47,36,32,50,32,112,105,112,44,32,89,84,76,32,49,50,32,112,105,112,44,65,108,116,38,35,51,48,53,59,110,32,51,32,99,101,110,116,46,32,83,97,98,105,116,32,83,112,114,101,97,100,45,84,38,117,117,109,108,59,114,60,119,98,114,32,47,62,107,32,66,97,110,107,97,115,38,35,51,48,53,59,32,65,86,65,78,84,65,74,73,60,47,102,111,110,116,62,60,47,115,112,97,110,62,60,47,116,100,62,10,60,47,116,114,62,60,116,114,62,10,60,116,100,32,97,108,105,103,110,61,34,108,101,102,116,34,62,60,100,105,118,32,105,100,61,34,97,99,95,117,114,108,34,62,60,102,111,110,116,32,115,116,121,108,101,61,34,102,111,110,116,45,115,105,122,101,58,49,48,112,120,59,32,99,111,108,111,114,58,35,70,70,54,54,57,57,59,32,102,111,110,116,45,102,97,109,105,108,121,58,65,114,105,97,108,44,32,72,101,108,118,101,116,105,99,97,44,32,115,97,110,115,45,115,101,114,105,102,44,86,101,114,100,97,110,97,34,62,119,119,119,46,104,101,100,101,102,111,60,119,98,114,32,47,62,110,108,105,110,101,46,99,111,109,60,47,102,111,110,116,62,60,47,100,105,118,62,60,47,116,100,62,60,47,116,114,62,60,47,116,97,98,108,101,62,60,47,116,100,62,60,47,116,114,62,60,116,114,62,10,60,116,100,32,99,108,97,115,115,61,34,97,99,95,107,97,114,105,109,34,32,104,101,105,103,104,116,61,34,50,48,37,34,32,98,103,99,111,108,111,114,61,34,35,70,70,70,70,70,70,34,32,105,100,61,34,116,97,119,52,34,32,97,108,105,103,110,61,34,108,101,102,116,34,32,118,97,108,105,103,110,61,34,109,105,100,100,108,101,34,32,111,110,70,111,99,117,115,61,34,115,115,40,39,103,111,32,116,111,32,119,119,119,46,107,97,108,101,100,101,60,119,98,114,32,47,62,46,99,111,109,39,44,39,97,119,52,39,41,34,32,111,110,77,111,117,115,101,79,118,101,114,61,34,115,115,40,39,103,111,32,116,111,32,119,119,119,46,107,97,108,101,100,101,60,119,98,114,32,47,62,46,99,111,109,39,44,39,97,119,52,39,41,34,32,32,111,110,77,111,117,115,101,79,117,116,61,34,99,115,40,41,34,32,111,110,67,108,105,99,107,61,34,103,97,40,39,104,116,116,112,58,47,47,97,100,115,101,114,118,101,114,46,109,121,110,101,116,46,99,111,109,47,65,100,83,101,114,118,101,114,47,99,108,105,99,107,46,106,115,112,63,117,114,108,61,56,56,49,48,48,50,53,49,50,49,55,54,51,57,52,54,50,51,49,56,52,52,48,51,57,54,48,48,54,51,49,51,54,54,52,52,56,50,56,54,50,48,49,49,49,52,55,51,55,54,52,51,50,57,50,52,50,56,51,53,56,51,54,53,48,48,48,48,53,56,49,55,50,56,57,53,48,48,52,49,57,48,54,56,56,55,50,56,49,55,48,55,53,48,57,50,55,53,55,57,57,51,54,53,50,52,54,49,51,56,49,57,53,55,52,53,50,49,52,50,55,54,48,57,53,57,56,52,55,50,55,48,56,52,51,49,54,52,49,54,57,53,48,56,57,50,54,54,54,48,57,49,54,53,55,57,48,57,49,55,57,52,55,52,55,57,50,48,55,50,55,51,51,53,51,50,55,53,50,54,55,50,56,48,51,57,49,56,54,50,56,55,49,51,55,48,52,51,49,51,52,55,56,51,54,51,52,53,50,54,55,53,57,48,57,48,56,54,57,49,52,53,49,49,52,55,53,50,120,49,57,50,88,49,54,56,88,51,56,88,52,49,88,56,48,56,48,88,65,39,41,34,32,115,116,121,108,101,61,34,99,117,114,115,111,114,58,112,111,105,110,116,101,114,34,62,10,60,116,97,98,108,101,32,119,105,100,116,104,61,34,49,53,54,34,32,98,111,114,100,101,114,61,34,48,34,32,99,101,108,108,115,112,97,99,105,110,103,61,34,49,34,32,99,101,108,108,112,97,100,100,105,110,103,61,34,49,34,62,10,60,116,114,62,10,32,32,60,116,100,32,97,108,105,103,110,61,34,108,101,102,116,34,32,62,60,115,112,97,110,32,105,100,61,34,97,99,95,116,105,116,108,101,34,62,60,102,111,110,116,32,115,116,121,108,101,61,34,102,111,110,116,45,115,105,122,101,58,49,50,112,120,59,32,99,111,108,111,114,58,35,70,70,48,48,48,48,59,32,102,111,110,116,45,119,101,105,103,104,116,58,98,111,108,100,59,102,111,110,116,45,102,97,109,105,108,121,58,65,114,105,97,108,44,32,72,101,108,118,101,116,105,99,97,44,32,115,97,110,115,45,115,101,114,105,102,44,86,101,114,100,97,110,97,34,32,99,111,108,111,114,61,34,35,70,70,48,48,48,48,34,62,66,108,117,101,32,72,111,117,115,101,32,77,105,107,115,101,114,39,100,101,32,38,35,51,53,48,59,111,107,33,60,47,102,111,110,116,62,60,47,115,112,97,110,62,60,47,116,100,62,10,60,47,116,114,62,60,116,114,62,10,60,116,100,32,97,108,105,103,110,61,34,108,101,102,116,34,62,60,115,112,97,110,32,105,100,61,34,97,99,95,100,101,115,99,34,62,60,102,111,110,116,32,115,116,121,108,101,61,34,102,111,110,116,45,115,105,122,101,58,49,49,112,120,59,32,99,111,108,111,114,58,35,48,48,48,48,48,48,59,32,102,111,110,116,45,102,97,109,105,108,121,58,65,114,105,97,108,44,32,72,101,108,118,101,116,105,99,97,44,32,115,97,110,115,45,115,101,114,105,102,44,86,101,114,100,97,110,97,34,62,66,108,117,101,32,72,111,117,115,101,32,77,105,107,115,101,114,39,100,101,32,65,110,110,101,108,101,114,101,32,38,79,117,109,108,59,122,101,108,32,70,105,121,97,116,32,83,65,68,69,67,69,32,50,57,44,57,54,32,89,84,76,33,60,47,102,111,110,116,62,60,47,115,112,97,110,62,60,47,116,100,62,10,60,47,116,114,62,60,116,114,62,10,60,116,100,32,97,108,105,103,110,61,34,108,101,102,116,34,62,60,100,105,118,32,105,100,61,34,97,99,95,117,114,108,34,62,60,102,111,110,116,32,115,116,121,108,101,61,34,102,111,110,116,45,115,105,122,101,58,49,48,112,120,59,32,99,111,108,111,114,58,35,70,70,54,54,57,57,59,32,102,111,110,116,45,102,97,109,105,108,121,58,65,114,105,97,108,44,32,72,101,108,118,101,116,105,99,97,44,32,115,97,110,115,45,115,101,114,105,102,44,86,101,114,100,97,110,97,34,62,119,119,119,46,107,97,108,101,100,101,60,119,98,114,32,47,62,46,99,111,109,60,47,102,111,110,116,62,60,47,100,105,118,62,60,47,116,100,62,60,47,116,114,62,60,47,116,97,98,108,101,62,60,47,116,100,62,60,47,116,114,62,60,116,114,62,10,60,116,100,32,99,108,97,115,115,61,34,97,99,95,107,97,114,105,109,34,32,104,101,105,103,104,116,61,34,50,48,37,34,32,98,103,99,111,108,111,114,61,34,35,70,70,70,70,70,70,34,32,105,100,61,34,116,97,119,53,34,32,97,108,105,103,110,61,34,108,101,102,116,34,32,118,97,108,105,103,110,61,34,109,105,100,100,108,101,34,32,111,110,70,111,99,117,115,61,34,115,115,40,39,103,111,32,116,111,32,119,119,119,46,98,105,116,109,101,100,60,119,98,114,32,47,62,101,110,46,99,111,109,39,44,39,97,119,53,39,41,34,32,111,110,77,111,117,115,101,79,118,101,114,61,34,115,115,40,39,103,111,32,116,111,32,119,119,119,46,98,105,116,109,101,100,60,119,98,114,32,47,62,101,110,46,99,111,109,39,44,39,97,119,53,39,41,34,32,32,111,110,77,111,117,115,101,79,117,116,61,34,99,115,40,41,34,32,111,110,67,108,105,99,107,61,34,103,97,40,39,104,116,116,112,58,47,47,97,100,115,101,114,118,101,114,46,109,121,110,101,116,46,99,111,109,47,65,100,83,101,114,118,101,114,47,99,108,105,99,107,46,106,115,112,63,117,114,108,61,51,51,54,49,55,53,56,50,56,51,56,50,53,52,57,55,54,49,48)
diff --git a/deps/v8/test/mjsunit/regress/regress-1178598.js b/deps/v8/test/mjsunit/regress/regress-1178598.js
new file mode 100644
index 0000000..9caaec2
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1178598.js
@@ -0,0 +1,90 @@
+// Copyright 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.
+
+// Regression test cases for issue 1178598.
+
+// Make sure const-initialization doesn't conflict
+// with heap-allocated locals for catch variables.
+var value = (function(){
+  try { } catch(e) {
+    // Force the 'e' variable to be heap-allocated
+    // by capturing it in a function closure.
+    (function() { e; });
+  }
+  // Make sure the two definitions of 'e' do
+  // not conflict in any way.
+  eval("const e=1");
+  return e;
+})();
+
+assertEquals(1, value);
+
+
+
+// Make sure that catch variables can be accessed using eval.
+var value = (function() {
+  var result;
+  try {
+    throw 42;
+  } catch (e) {
+    result = eval("e");
+  }
+  return result;
+})();
+
+assertEquals(42, value);
+
+
+
+// Make sure that heap-allocated locals for catch variables aren't
+// visible outside the catch scope and that they are visible from
+// within.
+var value = (function() {
+  var result;
+  try {
+    throw 87;
+  } catch(e) {
+    // Force the 'e' variable to be heap-allocated
+    // by capturing it in a function closure.
+    (function() { e; });
+    result = eval("e");
+  }
+
+  // Expect accessing 'e' to yield an exception because
+  // it is not defined in the current scope.
+  try {
+    eval("e");
+    assertTrue(false);  // should throw exception
+  } catch(exception) {
+    assertTrue(exception instanceof ReferenceError);
+    return result;
+  }
+})();
+
+assertEquals(87, value);
+
+
diff --git a/deps/v8/test/mjsunit/regress/regress-1182832.js b/deps/v8/test/mjsunit/regress/regress-1182832.js
new file mode 100644
index 0000000..6c4fcb4
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1182832.js
@@ -0,0 +1,38 @@
+// Copyright 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.
+
+var caught = false;
+try {
+  (function () {
+    var e = 0;
+    eval("const e = 1;");
+  })();
+} catch (e) {
+  caught = true;
+  assertTrue(e instanceof TypeError);
+}
+assertTrue(caught);
diff --git a/deps/v8/test/mjsunit/regress/regress-1187524.js b/deps/v8/test/mjsunit/regress/regress-1187524.js
new file mode 100644
index 0000000..2aeb1c5
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1187524.js
@@ -0,0 +1,34 @@
+// Copyright 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.
+
+// Make sure we don't die on conversion to Smi in string indexing
+
+assertEquals(undefined, ""[0x40000000]);
+assertEquals(undefined, ""[0x80000000]);
+assertEquals(undefined, ""[-1]);
+assertEquals(undefined, ""[-0x40000001]);
+assertEquals(undefined, ""[-0x80000000]);
diff --git a/deps/v8/test/mjsunit/regress/regress-1199401.js b/deps/v8/test/mjsunit/regress/regress-1199401.js
new file mode 100644
index 0000000..792faea
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1199401.js
@@ -0,0 +1,61 @@
+// Copyright 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.
+
+// Ensure that we can correctly change the sign of the most negative smi.
+
+assertEquals(1073741824, -1073741824 * -1);
+assertEquals(1073741824, -1073741824 / -1);
+assertEquals(1073741824, -(-1073741824));
+assertEquals(1073741824, 0 - (-1073741824));
+
+var min_smi = -1073741824;
+
+assertEquals(1073741824, min_smi * -1);
+assertEquals(1073741824, min_smi / -1);
+assertEquals(1073741824, -min_smi);
+assertEquals(1073741824, 0 - min_smi);
+
+var zero = 0;
+var minus_one = -1;
+
+assertEquals(1073741824, min_smi * minus_one);
+assertEquals(1073741824, min_smi / minus_one);
+assertEquals(1073741824, -min_smi);
+assertEquals(1073741824, zero - min_smi);
+
+assertEquals(1073741824, -1073741824 * minus_one);
+assertEquals(1073741824, -1073741824 / minus_one);
+assertEquals(1073741824, -(-1073741824));
+assertEquals(1073741824, zero - (-1073741824));
+
+var half_min_smi = -(1<<15);
+var half_max_smi = (1<<15);
+
+assertEquals(1073741824, -half_min_smi * half_max_smi);
+assertEquals(1073741824, half_min_smi * -half_max_smi);
+assertEquals(1073741824, half_max_smi * -half_min_smi);
+assertEquals(1073741824, -half_max_smi * half_min_smi);
diff --git a/deps/v8/test/mjsunit/regress/regress-1199637.js b/deps/v8/test/mjsunit/regress/regress-1199637.js
new file mode 100644
index 0000000..d9116c1
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1199637.js
@@ -0,0 +1,78 @@
+// Copyright 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.
+
+// Flags: --allow-natives-syntax
+
+// Make sure that we can introduce global variables (using
+// both var and const) that shadow even READ_ONLY variables
+// in the prototype chain.
+const NONE = 0;
+const READ_ONLY = 1;
+
+// Use DeclareGlobal...
+%SetProperty(this.__proto__, "a", "1234", NONE);
+assertEquals(1234, a);
+eval("var a = 5678;");
+assertEquals(5678, a);
+
+%SetProperty(this.__proto__, "b", "1234", NONE);
+assertEquals(1234, b);
+eval("const b = 5678;");
+assertEquals(5678, b);
+
+%SetProperty(this.__proto__, "c", "1234", READ_ONLY);
+assertEquals(1234, c);
+eval("var c = 5678;");
+assertEquals(5678, c);
+
+%SetProperty(this.__proto__, "d", "1234", READ_ONLY);
+assertEquals(1234, d);
+eval("const d = 5678;");
+assertEquals(5678, d);
+
+// Use DeclareContextSlot...
+%SetProperty(this.__proto__, "x", "1234", NONE);
+assertEquals(1234, x);
+eval("with({}) { var x = 5678; }");
+assertEquals(5678, x);
+
+%SetProperty(this.__proto__, "y", "1234", NONE);
+assertEquals(1234, y);
+eval("with({}) { const y = 5678; }");
+assertEquals(5678, y);
+
+%SetProperty(this.__proto__, "z", "1234", READ_ONLY);
+assertEquals(1234, z);
+eval("with({}) { var z = 5678; }");
+assertEquals(5678, z);
+
+%SetProperty(this.__proto__, "w", "1234", READ_ONLY);
+assertEquals(1234, w);
+eval("with({}) { const w = 5678; }");
+assertEquals(5678, w);
+
+
diff --git a/deps/v8/test/mjsunit/regress/regress-1200351.js b/deps/v8/test/mjsunit/regress/regress-1200351.js
new file mode 100644
index 0000000..f752a1e
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1200351.js
@@ -0,0 +1,2032 @@
+// Copyright 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.
+
+// Make sure the 'constructor' property isn't enumerable.
+var enums = "";
+for (var k in this) enums += (k + '|');
+assertEquals(-1, enums.split('|').indexOf("constructor"));
+
+// Make sure this doesn't crash.
+new this.constructor;
+new this.constructor();
+new this.constructor(1,2,3,4,5,6);
+
+var x = 0;
+try {
+  eval("SetValueOf(typeof(break.prototype.name), Math.max(typeof(break)))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export Join((void), false.className(), null instanceof continue, return 'a', 0.__defineGetter__(x,function(){native}))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ void&&null.push(goto NaN) : Math.max(undef).toText }) { {-1/null,1.isNull} }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new break>>>=native.charCodeAt(-1.valueOf())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Number(this > native)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new {native,0.2}?continue+undef:IsSmi(0.2)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = break.toString()&&return continue")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (-1==continue.toJSONProtocol, GetFunctionFor(break.call(NaN)), (!new RegExp).prototype.new Object()<<void) { debugger.__defineSetter__(null,function(){continue})>>>=GetFunctionFor(-1) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (parseFloat(NaN).splice() in null.add(1).className()) { true[0.2]<<x.splice() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("let (debugger.constructor.valueOf()) { this.sort().true.splice() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("unescape(break.toObject()).prototype.new RegExp.continue.__lookupGetter__(x.slice(1, NaN)) = typeof(null.push(0.2))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Date(Iterator(continue.pop()))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return new RegExp.shift().concat({debugger,continue}) }; X(return goto 0)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate(0.add(break)&&x > null)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ eval(Array(x)) : 1.call('a').superConstructor }) { debugger.lastIndex.toLocaleString() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = return true.__defineGetter__(this,function(){0.2})")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new typeof(0)&this.lastIndex")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("String(new RegExp.call(1)).prototype.unescape(parseFloat(-1)) = false<<true.x.lastIndexOf(1)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ 1+debugger.valueOf() : continue.join().name() }) { parseInt(true)==undef.sort() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new RegExp>>0.2.superConstructor.prototype.eval(void).className() = false.join().prototype.name")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export (new Object()?undef:native)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new null.isNull.slice(x.prototype.value, Iterator(undef))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export function () { 0.2 }.unshift()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Math.max(continue.valueOf())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = return debugger.toObject()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("switch (-1.length+new Object().prototype.name) { case (debugger.constructor.sort()): IsPrimitive(undef.__defineSetter__(undef,function(){native})); break; }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("delete (!new Object().toLocaleString())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Date(0<<'a'>>>=new RegExp['a'])")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("native {unescape(true),new RegExp.isNull}")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = -1.lastIndexOf(false)?parseFloat(void):Join(null, continue, new Object(), x, break)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("label null/void-break.__lookupGetter__(native)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Function(0.2.join().constructor)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("label function () { false }.__lookupGetter__(this==1)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate(-1.prototype.0.2.unshift())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = new return goto -1")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new {Number(debugger)}")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("if (parseInt(break) instanceof 0.length) { this.(!0.2) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf(break.superConstructor[throw new false(true)], this.~x)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf(function () { IsSmi(-1) }, unescape(IsPrimitive(void)))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (new RegExp.join().className() in new Object().length()>>true.toObject()) { parseFloat(escape(debugger)) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = new String(debugger).toJSONProtocol")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf(1.indexOf('a')<<break.__lookupGetter__('a'), new Object().null.prototype.new RegExp.charCodeAt(-1))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = new {parseInt(0)}")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Date(void.join().add(escape(undef)))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("native parseFloat(false.charAt(new RegExp))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Date(~Iterator(void))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Function(NaN.shift().toJSONProtocol)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Date(native-debugger<<continue.slice(x, new RegExp))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = parseFloat(~new Object())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (null.size/true.add(void) in 0+continue&true.null) { continue.toObject()/throw new true(debugger) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (Iterator(native+break) in debugger.superConstructor.constructor) { Math.max(0.add(undef)) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new {-1.add(native),true.sort()}")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new {IsSmi(break),throw new 'a'(null)}")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("switch (parseInt(0).length()) { case ('a'.toObject().__defineSetter__(GetFunctionFor(null),function(){(!x)})): IsSmi(void).constructor; break; }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new 0.lastIndexOf(NaN).shift()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ 0>>>=this.lastIndex : new Object().lastIndexOf(true).toObject() }) { x.lastIndex > 1.__defineSetter__(false,function(){this}) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ throw new false(0.2).prototype.name : parseFloat(false)+(!debugger) }) { escape(undef.lastIndex) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Math.pow(0.2).toJSONProtocol.prototype.break.superConstructor.slice(NaN.exec(undef), -1.lastIndexOf(NaN)) = true.splice().length")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("native continue.className().constructor")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("let (0.2.isNull&undef.toString()) { continue/void+parseInt(null) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = new Math.pow(break==this)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf(continue.__lookupGetter__(null).constructor, debugger.filter(0.2)>>>=this.'a')")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ 0.2.unshift() > true.size : return Math.max(new RegExp) }) { void.splice().toString() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new unescape(false).unshift()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return this.true?'a'==this:0.2.__lookupGetter__(void) }; X(Iterator(false).length)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = function () { null }.__defineSetter__(0.charCodeAt(new Object()),function(){null>>>=new Object()})")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("import goto 'a'.charAt(native.className())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("import 0.2.isNull.__lookupGetter__(debugger.size)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (~new Object().push(Array(null)) in new RegExp>>>=void.prototype.name) { goto break.lastIndex }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("delete String(x).slice(String('a'), parseFloat(false))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new parseInt(continue.__defineGetter__(0.2,function(){1}))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate(true.concat(undef)==0.2.new RegExp)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return NaN['a']?-1.exec(0):NaN.prototype.this }; X(native.prototype.name.toLocaleString())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (debugger==continue.toObject(), Array(NaN.className()), Math.max(new RegExp).prototype.value) { GetFunctionFor('a').prototype.value }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = new parseInt(break)==Array(x)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (parseInt(0.2.charCodeAt(this)), this.continue.prototype.name, native.superConstructor.superConstructor) { Join(0.__defineGetter__(continue,function(){undef}), {1}, parseFloat(0), undef.__defineSetter__(break,function(){null}), x?-1:-1) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export Join(debugger.splice(), parseInt(NaN), new RegExp.pop(), this.false, x.-1)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = Math.max(native).charCodeAt(continue==break)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (void==NaN.sort(), new Object()==new RegExp.toObject(), -1/NaN.unshift()) { GetFunctionFor(true).name() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for ((!'a'.join()), ~NaN.__defineGetter__(undef,function(){this}), Math.pow(NaN).__lookupGetter__(typeof(false))) { throw new debugger.toObject()(Math.max(-1)) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (NaN.shift()&&undef&&continue in throw new x(NaN).prototype.-1&x) { return native.toJSONProtocol }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new (0).charAt(this.charCodeAt(new Object()))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return x.valueOf().size }; X(0.2.unshift().unshift())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("if (eval(new Object().valueOf())) { break.prototype.name.__defineGetter__(eval(NaN),function(){Math.max(native)}) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (Math.pow(1).isNull in Iterator(continue.length())) { Join(true, 0.2, null, x, new Object()).length }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf(0>>>=void.unshift(), void.exec('a').undef.length())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("delete throw new this(0.2).pop()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Iterator(unescape(continue))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return unescape(goto debugger) }; X(new RegExp.push(break).name())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = undef/'a'.indexOf(-1.exec(false))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (continue.isNull.filter(this.toText), function () { throw new 'a'(0.2) }, native?break:undef.prototype.return continue) { Array(void.toText) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = new this.slice(new Object(), 1).isNull")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (0.2.className().call((!debugger)), native.__defineGetter__(0,function(){x}).name(), null.splice().splice()) { NaN.charCodeAt(new Object()) > true.toString() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("native false.length?new RegExp instanceof this:Array(undef)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new ~0.2.call(typeof(false))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Number(0.2.sort())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new x.join().shift()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("switch (~new Object().toText) { case (new RegExp.unshift().exec(new RegExp<<debugger)): -1.length.exec(this.isNull); break; }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new parseInt(~true)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new unescape(debugger.call(null))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = new GetFunctionFor(0.2).toObject()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("delete IsPrimitive(null.join())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (eval(0.2) instanceof debugger.splice() in null.superConstructor==new Object()&void) { Number(0+x) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("let ('a'-continue?null.length():escape(continue)) { return undef.push(false.shift()) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (Array(x.length) in 'a'.length().sort()) { goto (new Object()) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("let (NaN==true.length) { IsPrimitive(0.2).prototype.value }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf(return true&&void, new RegExp.toObject().length())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Math.pow(void).length")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Function(void.add(continue).charCodeAt(this.toObject()))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export Join(break.toObject(), 0.2.isNull, false.call(0), break.filter(break), 1.length())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("if (1/NaN.__lookupGetter__(undef.prototype.value)) { escape(eval(this)) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Function(Join(unescape(x), new RegExp.__defineGetter__(debugger,function(){NaN}), 'a'.indexOf(0.2), false.prototype.name, (this)))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = new Math.pow(native).indexOf(1>>>=-1)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new RegExp?native:continue.join().prototype.Math.max(x.__defineSetter__(1,function(){continue})) = parseFloat(parseInt(null))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("native function () { new RegExp }.new RegExp.pop()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("import typeof(new RegExp.valueOf())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("switch (0.2.size>>NaN-continue) { case ('a'.push(true).indexOf(NaN.lastIndexOf(-1))): {0.2,x}.toObject(); break; }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("if (IsSmi(new Object())/false.filter('a')) { function () { Iterator(debugger) } }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = break.lastIndex.size")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Function(new Object() > 0.length())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("native IsPrimitive(continue)==break.charCodeAt(new Object())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new break.true<<'a'-NaN")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Number(-1?'a':-1)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (parseFloat('a'.exec(continue)) in (!new RegExp)&&0.2.toObject()) { {true,x}.add(void.prototype.NaN) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("let (-1.prototype.value.join()) { (!1.prototype.name) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new GetFunctionFor(continue).toJSONProtocol")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (Math.pow(continue.slice(null, native)), goto (!0), native?1:this.charAt(String(debugger))) { parseFloat(~this) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf(debugger.pop().length, new RegExp.isNull.toText)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (typeof(new RegExp.slice(new RegExp, 0)) in native.toLocaleString().lastIndexOf(0.2.length())) { native>>>=new RegExp.length() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("native x.join().className()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new 0?0:true.toLocaleString()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = IsPrimitive(0).concat(new Object().name())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new parseFloat(x)?this.valueOf():IsSmi(x)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new 'a'.slice(null, -1).shift()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("label 'a'+void.concat('a'>>>=-1)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Function(escape(0.length))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = parseInt(0.lastIndexOf(NaN))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf(null&debugger.valueOf(), 0[false].push(false.add(debugger)))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = parseInt(new RegExp.__lookupGetter__(break))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf(~false&&break>>0, new RegExp.lastIndex.add({this}))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = Join(break, continue, 0, debugger, NaN).toLocaleString()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("import new Object().sort().superConstructor")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = new IsSmi(goto -1)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return Iterator(null).toObject() }; X(-1==new Object()==0.__lookupGetter__(native))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("native void.join().add(parseFloat(continue))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("let (function () { -1 }.shift()) { escape(1.unshift()) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Function(new RegExp.indexOf(1).filter(continue instanceof break))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("if (NaN?continue:NaN.shift()) { native.push(null).add(new Object().superConstructor) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return new Object().length().toText }; X(debugger.indexOf(this).toText)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = new Object().call('a').charCodeAt(native.size)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new function () { continue }.add(true.slice(continue, new RegExp))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x[native] instanceof -1.join().prototype.this.null.size = 0.2.prototype.x+0.2.indexOf(false)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (this instanceof new RegExp.splice() in null>>>=new RegExp.valueOf()) { function () { unescape(1) } }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (true.shift()/native.null in undef.call(NaN).isNull) { native+this-x.size }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return false.pop()<<Join(continue, false, break, NaN, -1) }; X(IsSmi(debugger>>x))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("if ({parseFloat(null),Math.max(native)}) { 0.2-new Object().__lookupGetter__(eval(new Object())) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf(Array(1).toLocaleString(), null.name().exec(undef.filter(false)))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Function(true.filter(this).pop())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("let (break.lastIndex.superConstructor) { new Object().toString().length() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("label (!0.2/debugger)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ NaN.concat(new RegExp)+Join(1, false, new Object(), new Object(), x) : unescape(x).concat(Iterator(-1)) }) { 'a'.isNull.__lookupGetter__(this+native) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export break.name()/IsPrimitive(this)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new {null}.prototype.value")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new true+false.__lookupGetter__(null&continue)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("if (-1.push(new RegExp)[void.valueOf()]) { new RegExp.className().__lookupGetter__(Array(0)) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export NaN.__lookupGetter__(undef).__lookupGetter__(void.isNull)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ ~new RegExp.filter(undef&&this) : String(continue)<<NaN.toText }) { this.exec(this).length }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (true&void.exec(void.exec(continue)) in Join('a', undef, new Object(), continue, x) instanceof {undef}) { unescape(-1.prototype.name) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("import void.push(true).join()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf({break}&x.name(), 1.charAt(false).slice(continue.superConstructor, this&&break))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("let (this.call(this) > Iterator(continue)) { new Object().prototype.value.slice(1.slice(native, -1), (!false)) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export parseInt(new RegExp>>>=x)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (escape(x==debugger), NaN.shift()&debugger?false:0.2, (!new RegExp)&goto break) { unescape(x.toText) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Date(throw new NaN.toObject()(this?break:true))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new (typeof(this))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (unescape('a'/0) in ~new Object().lastIndex) { IsSmi(0).push(0.concat(0.2)) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("(!new RegExp)[0.2 > new Object()].prototype.Number(debugger.join()) = native&-1.size")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new false.toJSONProtocol&&0.2.constructor")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (~0?0.2:undef in new RegExp.charCodeAt(0).prototype.name) { NaN.toLocaleString().splice() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (~IsPrimitive(new RegExp), true.toString().size, null.charCodeAt('a') > null.concat(0)) { break.toJSONProtocol/IsPrimitive(break) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new parseInt(new Object()).lastIndexOf(NaN > void)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export break.splice()&&-1.prototype.new Object()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("{{true,0}}.prototype.break.length.splice() = 'a'.toText.superConstructor")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("let (debugger>>>=continue > break.exec(1)) { Math.pow(new RegExp)==NaN>>>=0.2 }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ 0.2==0.2/goto true : IsSmi(native).isNull }) { throw new {x,null}(false.className()) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = {false.concat(null),Math.pow(NaN)}")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export Array(null).add(NaN.valueOf())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (parseFloat(new Object()==true) in GetFunctionFor('a'&false)) { native&undef.toJSONProtocol }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new {eval(null),(debugger)}")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("import {this.0,debugger.filter(NaN)}")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("import break.charAt(-1)<<false.__defineSetter__(0,function(){x})")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = goto false > new Object()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("null.superConstructor[debugger.isNull].prototype.Math.max('a').shift() = parseInt(0).size")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("native eval(void.add(break))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Date(x > void.join())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ {this.toObject()} : Number(NaN).toJSONProtocol }) { 0.2.className().prototype.name }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("if (false.__defineGetter__(undef,function(){undef}).exec(NaN.splice())) { typeof(Join(void, new RegExp, break, -1, -1)) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (false.splice().toObject(), continue.name().size, Join(void?debugger:this, new RegExp.__defineSetter__(NaN,function(){NaN}), x.unshift(), this.true, parseInt(break))) { undef<<continue.toText }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("let (this.0.indexOf(break)) { break.charAt(this).unshift() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("import Join(new Object().splice(), this instanceof 1, parseFloat(NaN), undef.concat(x), void.className())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Function(goto NaN.toString())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("label 'a'<<break.shift()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = Iterator(continue)[new Object()>>NaN]")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = Join(new RegExp, 'a', this, void, true)>>>=continue>>native")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("import new Object().toJSONProtocol.splice()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return undef.__defineSetter__(native,function(){void}).toJSONProtocol }; X(eval(x).charCodeAt('a'.concat(true)))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate(throw new 0.2.__defineGetter__(NaN,function(){-1})(void&&new RegExp))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = 0.unshift() > IsSmi(NaN)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("label x.call(null).lastIndex")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf(IsSmi(0.2.add(0)), x.add(break).this.__defineGetter__(undef,function(){new RegExp}))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("native Number(this).toObject()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new NaN.shift().add(String(new Object()))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new null.name().splice()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = 1.undef.push(new Object().call(null))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Function(parseInt(1).size)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = this.x.sort()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate(continue.valueOf().prototype.new RegExp.splice())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate(this.charAt(continue)?undef+'a':unescape(1))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf({throw new 'a'(0.2),void.lastIndexOf(NaN)}, Math.pow(new Object().className()))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("if (1.slice(new Object(), this).valueOf()) { parseInt(true).pop() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ 0.2.superConstructor.lastIndex : goto debugger<<Join(undef, 1, true, undef, debugger) }) { function () { NaN }.prototype.name }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("-1.exec(debugger).length.prototype.debugger > null.slice(Iterator(void), continue.concat(0)) = parseInt(throw new 1(1))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Date(new Object().constructor.call(Number(1)))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = new null.unshift().call(escape(x))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("switch (Math.pow(native).toLocaleString()) { case (false instanceof native.join()): Math.pow(NaN).size; break; }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("label function () { new Object() }.prototype.true.size")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = Join('a', 0.2, false, new Object(), void).continue.className()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = IsPrimitive(break.__lookupGetter__(-1))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new Object()>>0.2.prototype.name")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = new IsPrimitive(new Object()).shift()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("if (Array(parseInt(break))) { 'a'.toString().unshift() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = return 0.2>>>=-1?undef:undef")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Object().splice().unshift().prototype.null&&native.__lookupGetter__(undef>>>=NaN) = (1<<break)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("delete NaN.charAt(1).concat(NaN.0.2)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate(new RegExp.sort().toJSONProtocol)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return GetFunctionFor(false).lastIndexOf(1.shift()) }; X(this.0.2.charCodeAt(0.2))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (goto NaN.toObject(), ~true.'a', parseInt(debugger)+eval(false)) { eval(0.2.constructor) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("switch (parseInt(debugger).pop()) { case (this.push(true).valueOf()): Join(continue, debugger, native, native, debugger).filter(Array(continue)); break; }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new debugger.sort() instanceof this>>1")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ parseFloat(false).prototype.(!new Object()) : {unescape(-1)} }) { Math.max(new RegExp.superConstructor) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate({Math.pow(break)})")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("import typeof(break.valueOf())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate(Math.pow(-1[new RegExp]))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("native IsPrimitive(1).concat({x,null})")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("NaN.length.prototype.value.prototype.function () { null==new Object() } = break.name()&IsPrimitive(0)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("delete NaN.prototype.-1.toString()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new continue.unshift()+parseFloat(undef)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = new NaN-break.call(false.pop())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("native new RegExp.exec(break).pop()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf({'a',null}.prototype.value, 1.shift() instanceof {'a',0})")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (debugger.valueOf().size, function () { x.unshift() }, IsSmi(1)&&true==native) { new Object().__defineGetter__(this,function(){'a'})&&eval(native) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export 'a'.pop().charCodeAt(x.className())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export String(IsSmi(debugger))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("typeof(debugger).valueOf().prototype.(1).lastIndexOf(this.break) = x.prototype.name.toLocaleString()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("native Array(typeof(false))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Function(1.__defineGetter__(1,function(){1}).null.constructor)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = 1.charAt(0).toObject()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Date(Math.max('a'.filter(new Object())))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Date(void.prototype.name.unshift())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (-1.toJSONProtocol.call(-1.size) in ~x.sort()) { eval(0&debugger) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for ('a'==undef.join() in Math.pow(IsSmi(false))) { undef > this>>goto x }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate('a'.constructor.isNull)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (GetFunctionFor(this.slice(0.2, this)), this.prototype.void?null.unshift():native.className(), Number(new Object().call(-1))) { 0.splice() > debugger&&this }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ {goto new RegExp,Join(new Object(), native, continue, -1, x)} : NaN&x/{0,break} }) { this.lastIndexOf(new RegExp).join() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("let (typeof(break.length())) { native&&false.sort() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new parseFloat(-1 instanceof break)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("label throw new continue.unshift()(null.shift())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("import Math.max(0.2.toLocaleString())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return false.unshift().className() }; X(escape(NaN&NaN))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Date(Join(native.toText, goto x, 0.2.splice(), Join('a', 0, void, NaN, 1), eval(native)))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("if (GetFunctionFor(true.prototype.name)) { parseInt(NaN).toLocaleString() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new escape(native).__defineSetter__(return native,function(){undef > native})")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = new typeof(true > 'a')")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("switch (debugger.prototype.0.2<<new RegExp+false) { case (native.splice().filter({x})): false&true.indexOf(1.__defineGetter__(native,function(){continue})); break; }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("label true-NaN.prototype.native.shift()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new typeof(new RegExp.splice())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("switch (function () { this.NaN }) { case (this.continue.prototype.parseFloat(false)): IsPrimitive(new Object()-'a'); break; }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export break.__lookupGetter__(debugger).indexOf(native.pop())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("switch (GetFunctionFor(NaN.lastIndex)) { case (new RegExp.lastIndex.toLocaleString()): NaN.join().indexOf(eval(-1)); break; }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("native {void.charAt(true)}")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new new Object()==NaN.join()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Date(typeof(Array(new Object())))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("label throw new (false)(eval(x))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new new RegExp.size.charAt(true > -1)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = debugger.toObject().charAt(this<<undef)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ 'a'.valueOf()+parseInt(undef) : IsPrimitive(null).lastIndex }) { NaN.toObject().isNull }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new new Object()&&void.lastIndexOf(0.2.splice())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ 1+1.name() : Join(Math.pow(debugger), new RegExp-1, x > 1, x<<-1, new RegExp.size) }) { undef[undef].size }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("delete native.call(-1).isNull")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("if (new Object()>>>=break==Math.pow(debugger)) { IsPrimitive(this).lastIndex }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for ((!x&&new RegExp) in undef.toLocaleString().slice(new RegExp.indexOf(NaN), IsPrimitive(-1))) { false.size+debugger[x] }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("import 0.length.__defineGetter__(0.2.shift(),function(){'a'.className()})")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate(goto new Object().push(void))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ Array(this.0) : parseFloat(void).pop() }) { escape(true).slice(continue.lastIndex, false.toObject()) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new native==true.filter({NaN,-1})")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for ('a'.__defineSetter__(continue,function(){-1}).unshift(), Array(undef).toLocaleString(), undef.__lookupGetter__(void).toLocaleString()) { parseInt(false/native) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("this.x<<false.prototype.true.toLocaleString()==NaN.pop() = this.superConstructor>>Math.max(true)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return this.prototype.name.splice() }; X(unescape(x).__lookupGetter__(Number(debugger)))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new (!NaN).unshift()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Function(escape(Iterator(this)))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return Number(new RegExp)<<this?true:-1 }; X(Number(null).lastIndex)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export this.void.splice()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (this.prototype.null.sort() in -1.className()&void.filter(new Object())) { GetFunctionFor(new Object()).pop() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("label 0[break].sort()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (null.length().toString(), eval(-1).toObject(), (!continue.concat(continue))) { true.name()/native<<new RegExp }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (unescape(null).sort(), Number(undef).charCodeAt(IsPrimitive(NaN)), null>>true/null.join()) { 0.2.toObject() > IsPrimitive(new RegExp) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Date({NaN,native}&&1+undef)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate(IsPrimitive(undef>>>=1))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (Join(true, 'a', true, 1, NaN).add({1}), GetFunctionFor(new Object().push(new Object())), goto 1.length) { Math.pow(GetFunctionFor(native)) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return break.isNull > parseInt(continue) }; X((new RegExp instanceof 1))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ Number(false).indexOf(x instanceof new Object()) : function () { x.toString() } }) { false.name().indexOf(GetFunctionFor(null)) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Date('a'.constructor.prototype.name)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("GetFunctionFor(void&new Object()).prototype.debugger.add(null)[void.unshift()] = new RegExp.isNull.Iterator(this)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("delete false?break:undef.constructor")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ (native.filter(1)) : eval(this&&0.2) }) { undef.length instanceof new Object().toText }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export String(break.lastIndexOf(null))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("label (!Iterator(new RegExp))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf(String(null==-1), {1&0})")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Date(parseInt('a' > 0))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf(debugger.toJSONProtocol.indexOf(escape(0)), this.filter(null).__defineSetter__(continue.break,function(){debugger>>null}))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("this.name().length().prototype.goto false.exec(true.charCodeAt(continue)) = Join(-1-false, undef.superConstructor, 'a'.shift(), (!x), NaN.this)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Function(typeof(new RegExp).sort())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new 0.2.concat(x).splice()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (goto void.indexOf(throw new x(1)), typeof(return new RegExp), IsPrimitive(-1).add(void.lastIndexOf(debugger))) { null.indexOf(void).toText }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("return new RegExp.pop().prototype.String(x.toObject()) = 1.superConstructor.charCodeAt(new RegExp.charCodeAt(null))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new null&true.prototype.name")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = -1>>>=NaN.indexOf((debugger))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = new parseFloat(null).splice()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("import -1.lastIndexOf(new RegExp) instanceof throw new void(0.2)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("if ((0.shift())) { Join(IsPrimitive(-1), break.__defineSetter__(true,function(){break}), parseInt(null), parseFloat(break), true/null) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new escape(1 > continue)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("switch (parseInt(undef)>>false.filter(continue)) { case (this.undef/new Object()): 'a'.toJSONProtocol.__defineGetter__(new RegExp-undef,function(){parseFloat(new RegExp)}); break; }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("{void}.shift().prototype.this.Array(new Object()) = {0.2,new RegExp}.lastIndexOf(break.splice())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new continue&&new Object().lastIndexOf(new Object() instanceof 1)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (throw new 'a'.exec(x)(return false), native/void.constructor, {native}==true.toLocaleString()) { goto 1 instanceof 1.isNull }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (break.concat(break) > native>>>=-1, (debugger.x), Join(x, void, void, new RegExp, null).name()) { void.charCodeAt(true).valueOf() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = new 'a'>>0 instanceof new Object().push(new RegExp)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("if (return ~break) { break.__defineGetter__(break,function(){-1}).shift() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate(Join(null, -1, undef, null, 0).toString())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("let ({new RegExp,void}.slice(break.isNull, false.shift())) { eval(debugger.slice(this, 1)) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return {GetFunctionFor(0)} }; X('a'.prototype.debugger.concat(void.constructor))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("let (~true instanceof continue) { escape(new RegExp.toObject()) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("escape(0[native]).prototype.debugger.add(1).unshift() = (true.join())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (unescape(void).length, undef.toObject() instanceof x.toObject(), 0.2+true.concat(true.__lookupGetter__(this))) { (x).toJSONProtocol }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate(escape(null).__lookupGetter__(undef.size))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("label Array(continue[false])")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return Number(this&&false) }; X(NaN.toJSONProtocol.toJSONProtocol)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("null.toString().shift().prototype.Array(x).__lookupGetter__('a'.prototype.x) = {1.length,break.join()}")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new 1.charCodeAt(break)+IsSmi(false)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf(String(this) > 0.2.toText, new RegExp.length.lastIndexOf(1<<0.2))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("switch (new RegExp.pop().charAt(IsSmi(new RegExp))) { case (native.indexOf(this)/native.lastIndex): this.debugger.indexOf(debugger); break; }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Date(Number(x)[debugger.prototype.break])")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return new RegExp>>>=x.unshift() }; X(Math.max(continue.name()))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate(IsSmi(null.size))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = native?0.2:1+GetFunctionFor(void)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (IsPrimitive(-1)>>>=break.valueOf() in String(0 > 0.2)) { Math.max(true.length()) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("switch (escape(unescape(NaN))) { case (Math.pow(eval(undef))): true.charAt(null)&new RegExp.pop(); break; }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("delete Join(new RegExp, 1, false, new Object(), this).toLocaleString()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("label return x.filter(x.join())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new new RegExp.pop().shift()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new (!debugger.size)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("label Math.max(debugger.__lookupGetter__(NaN))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate(eval(debugger[debugger]))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new 0.2.filter(true)&throw new true(debugger)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Date(continue.exec(debugger) > Math.pow(0.2))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("void.prototype.value.name().prototype.Number(undef&NaN) = false.__lookupGetter__(-1).name()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate(null.__defineGetter__(native,function(){continue}).valueOf())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ {new Object()[continue],native.length()} : undef.name().superConstructor }) { Math.pow(break).indexOf(0.toJSONProtocol) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("switch (Iterator(native.call(new RegExp))) { case (String(new RegExp).isNull): goto new RegExp.pop(); break; }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = new x.constructor instanceof undef.indexOf(-1)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf(this.~null, continue.pop()&0&'a')")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("switch (GetFunctionFor(~0)) { case ('a'.'a'<<undef.__defineGetter__(false,function(){true})): (!1).lastIndex; break; }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return debugger.unshift().0.toString() }; X(Number(break).0.2>>>=false)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Date(Iterator(x)/undef.pop())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf(undef.join().toLocaleString(), null.add(false).valueOf())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("IsSmi(x).toString().prototype.0>>continue.indexOf(NaN.__lookupGetter__(new Object())) = ~-1&typeof(0)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (continue.__lookupGetter__(new RegExp).toObject(), false-0.toString(), return native.sort()) { new RegExp.name().className() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("switch (escape(new RegExp).toString()) { case (goto eval(1)): this.filter(new Object()).call(new RegExp.slice(null, this)); break; }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = debugger-false.toText")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = Number(null>>new RegExp)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("delete this&native.indexOf('a'.splice())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf(~Math.max(break), 0.2.valueOf().length)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate(Number(native.charCodeAt(x)))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = new goto continue.add(0)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("delete typeof(debugger).name()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("'a'<<false.toText.prototype.throw new true(1).lastIndex = 'a'.name().length")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("native 'a'.indexOf(debugger).charAt(NaN.add(new Object()))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf(break>>false.toString(), (false.indexOf(this)))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("delete goto NaN==(!debugger)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Date(0.2.join().superConstructor)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = new this.void.toLocaleString()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("SetValueOf(x.exec(debugger)[GetFunctionFor(0)], native.toObject().exec(new RegExp.sort()))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate(0.2.valueOf().toLocaleString())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Function(-1.toJSONProtocol.prototype.name)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Date(Array(-1.shift()))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export break.concat(undef).unshift()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("native parseFloat(-1)?NaN.toText:debugger.toString()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (void-continue/continue.prototype.undef in String(break.toText)) { parseInt(false).isNull }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate(true.isNull.toObject())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ typeof(debugger).toObject() : x.constructor>>>=null.__defineGetter__(native,function(){debugger}) }) { unescape(undef.lastIndexOf(false)) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export unescape(continue)<<native[0]")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("if (String(0).unescape(debugger)) { {break.pop(),0.2.constructor} }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("String({true}).prototype.break.length.call(false > 0.2) = GetFunctionFor(0.prototype.new RegExp)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ false.push(0.2).indexOf(Math.max(debugger)) : x&x.prototype.name }) { goto 1.lastIndex }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Function(0.2.lastIndex&0.2?break:NaN)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = -1.prototype.value.toText")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("import native.toLocaleString()-1.prototype.0")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export debugger[-1].indexOf(Join(new Object(), 0, x, new Object(), 0.2))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return (!true).lastIndexOf(true.splice()) }; X(NaN.toString().prototype.value)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return continue.slice(-1, 1).prototype.true.name() }; X('a'.push(void).prototype.value)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (goto new RegExp.length(), x.sort().className(), Math.max(new RegExp.toJSONProtocol)) { (IsSmi(-1)) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = 0.splice()&&-1.sort()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("let (Math.max(-1>>1)) { break.toLocaleString().toJSONProtocol }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new {void.prototype.break,new RegExp.toString()}")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new IsSmi(debugger).name()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new 'a'.concat(undef).sort()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new {debugger.toObject(),'a' > false}")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("if (goto 1.concat(Join(x, undef, native, x, new Object()))) { new RegExp.prototype.name==new RegExp.superConstructor }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return new Object().__defineGetter__(0.2,function(){0.2}).length() }; X(void.isNull<<parseFloat(NaN))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("delete continue.toJSONProtocol.toLocaleString()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (continue.constructor.toObject() in true&&undef.toJSONProtocol) { String(0+break) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("import true.call(continue)>>break.toString()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("label escape(this) > Math.pow(new RegExp)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new {void}/IsSmi(new Object())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("switch (native==null?debugger.prototype.name:null.toLocaleString()) { case (NaN.push(this).join()): (break instanceof continue); break; }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new Math.pow(x.push(0))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new (Array(NaN))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("label IsSmi(new RegExp).toLocaleString()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("label NaN.push(1).shift()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("{escape(undef),debugger.filter(0.2)}.prototype.-1 > new RegExp[0.2.valueOf()] = new RegExp.prototype.value.splice()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new Join(0.2, x, continue, debugger, new Object()).size")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("with ({ Number(null).name() : Math.pow(true).__defineGetter__(debugger.toString(),function(){false+0.2}) }) { this.{x,break} }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Math.pow(goto debugger)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = IsPrimitive(void.pop())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new Object().toString().toJSONProtocol")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate(this.String(0.2))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("let ({-1.call(new RegExp)}) { break.length().splice() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("import null.size.__defineGetter__(void.filter(x),function(){null.pop()})")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = new IsPrimitive(null.superConstructor)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new eval(-1.prototype.continue)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("switch (typeof(Iterator('a'))) { case (0.constructor>>~1): void.__defineGetter__(void,function(){1})/GetFunctionFor(0); break; }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for (false instanceof x.add(true.charAt(new RegExp)) in Join(undef.lastIndexOf(break), 0.2.add(new Object()), Iterator(1), {'a',x}, Array(new Object()))) { function () { null }/1&&-1 }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new escape('a'.concat(undef))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Function(Math.pow(NaN).toText)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new throw new 0(NaN).className()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("delete String(GetFunctionFor(new Object()))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = Iterator(new Object()).charAt((0.2))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Number(undef.charAt(1)).prototype.undef.lastIndexOf(true).slice(1.className(), undef.filter(-1)) = null<<null.push(parseInt('a'))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = {Math.max(1),IsSmi(new Object())}")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("switch (new Object().exec(0).isNull) { case (escape(IsSmi(false))): false.toObject()-null.size; break; }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new 'a'.__defineSetter__(debugger,function(){false}).name()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = debugger?-1:0+true.prototype.1")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new {false instanceof continue,native.size}")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("GetFunctionFor(continue.__lookupGetter__(0.2)).prototype.Math.max(1.splice()) = true.__defineGetter__(undef,function(){NaN}).filter(String(new RegExp))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("null.size-1.toLocaleString().prototype.(this).shift() = GetFunctionFor(native.charAt(break))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate((!null.indexOf(-1)))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = {break.sort()}")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new throw new debugger.splice()(this.__lookupGetter__(undef))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("unescape(x[native]).prototype.0.splice().-1.prototype.true = x.prototype.value.className()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export x+true.length")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export debugger.indexOf(-1).indexOf(true.constructor)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("for ({break}.exec(new Object().continue) in eval(0.2.charAt(new Object()))) { throw new null.length(null?break:-1) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = NaN.toLocaleString().toObject()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return Math.pow(break+false) }; X(Join(true.add(new Object()), null[-1], new RegExp[true], NaN&&debugger, x.charAt(undef)))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("switch ((break).add(true.sort())) { case (undef.charAt(native).__defineGetter__(IsPrimitive(1),function(){NaN<<new RegExp})): -1.__defineSetter__(null,function(){-1}) > this.charCodeAt(this); break; }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("import return 0.2.length")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("continue.join().toText.prototype.Number(debugger).slice(new RegExp.-1, (NaN)) = function () { (!null) }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export Number(break.__lookupGetter__(false))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Date(return null/x)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export Number(undef).shift()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = 1[native]/this&true")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("delete typeof(debugger.unshift())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("import x.charAt(false)&-1>>x")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("if (null.toText.superConstructor) { typeof(-1).toString() }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("let (parseFloat(continue.superConstructor)) { 0.2.toText.prototype.value }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("label parseInt(IsSmi(null))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("delete new Object().valueOf().indexOf(true-x)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new unescape(1.__defineGetter__(new Object(),function(){x}))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("let (undef.size.splice()) { 1.constructor.charCodeAt(0+'a') }")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("this.new RegExp.pop().prototype.eval(debugger).toJSONProtocol = unescape(continue).valueOf()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("const x = new this.new RegExp.indexOf(unescape(new Object()))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = new break instanceof false instanceof native.length()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate(parseFloat(x).valueOf())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("label {escape(true),Math.max(null)}")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("'a'>>>=void.prototype.value.prototype.break.prototype.break.indexOf(0.className()) = (!this&native)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("import Number(NaN).push(IsSmi(break))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("export true.exec(void).toObject()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Function({'a',true}/eval(new Object()))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("label null.concat(null).toObject()")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("native {0.2.length,new RegExp.lastIndexOf(-1)}")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("function X(x) { return Math.max({0.2}) }; X(true.charCodeAt(null).add(new RegExp.name()))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("delete -1.lastIndex.length")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("new Function(0.2[1].call(true > break))")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("Instantiate('a'.toLocaleString().splice())")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
+
+try {
+  eval("x = typeof(void&&void)")
+} catch (e) { if (e.message.length > 0) { print (e.message); } };
diff --git a/deps/v8/test/mjsunit/regress/regress-1201933.js b/deps/v8/test/mjsunit/regress/regress-1201933.js
new file mode 100644
index 0000000..d4827e4
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1201933.js
@@ -0,0 +1,40 @@
+// Copyright 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.
+
+// Make sure this doesn't fail with an assertion
+// failure during lazy compilation.
+
+var caught = false;
+try {
+  (function() {
+    const a;
+    var a;
+  })();
+} catch (e) {
+  caught = true;
+}
+assertTrue(caught);
diff --git a/deps/v8/test/mjsunit/regress/regress-1203459.js b/deps/v8/test/mjsunit/regress/regress-1203459.js
new file mode 100644
index 0000000..da1e0ed
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1203459.js
@@ -0,0 +1,29 @@
+// Copyright 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.
+
+// Ensure that we allow non-index number properties in object literals.
+var obj = { 0.2 : 'a' }
diff --git a/deps/v8/test/mjsunit/regress/regress-1207276.js b/deps/v8/test/mjsunit/regress/regress-1207276.js
new file mode 100644
index 0000000..ce7efe9
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1207276.js
@@ -0,0 +1,36 @@
+// Copyright 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.
+
+try {
+  const x=n,Glo0al;
+} catch(e){}
+
+delete Date;
+function X(){String(Glo0al)}
+X();
+X();
+X();
diff --git a/deps/v8/test/mjsunit/regress/regress-1213516.js b/deps/v8/test/mjsunit/regress/regress-1213516.js
new file mode 100644
index 0000000..6703f32
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1213516.js
@@ -0,0 +1,40 @@
+// Copyright 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.
+
+function run() {
+ var a = 0;
+ L: try {
+   throw "x";
+ } catch(x) {
+   break L;
+ } finally {
+   a = 1;
+ }
+ assertEquals(1, a);
+}
+
+run();
diff --git a/deps/v8/test/mjsunit/regress/regress-1213575.js b/deps/v8/test/mjsunit/regress/regress-1213575.js
new file mode 100644
index 0000000..0c3dcc2
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1213575.js
@@ -0,0 +1,41 @@
+// Copyright 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.
+
+// Make sure that a const definition always
+// conflicts with a defined setter. This avoid
+// trying to pass 'the hole' to the setter.
+
+this.__defineSetter__('x', function(value) { assertTrue(false); });
+
+var caught = false;
+try {
+  eval('const x'); 
+} catch(e) {
+  assertTrue(e instanceof TypeError);
+  caught = true;
+}
+assertTrue(caught);
diff --git a/deps/v8/test/mjsunit/regress/regress-1215653.js b/deps/v8/test/mjsunit/regress/regress-1215653.js
new file mode 100644
index 0000000..881e22c
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1215653.js
@@ -0,0 +1,365 @@
+// Copyright 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.
+
+// Make sure this doesn't crash the VM.
+
+var caught = false;
+try {
+  OverflowParserStack();
+  assertTrue(false);
+} catch (e) {
+  assertTrue(e instanceof RangeError);
+  caught = true;
+}
+assertTrue(caught);
+
+
+function OverflowParserStack() {
+  var s =
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" +
+      "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((";
+  eval(s);
+}
diff --git a/deps/v8/test/mjsunit/regress/regress-124.js b/deps/v8/test/mjsunit/regress/regress-124.js
new file mode 100644
index 0000000..81526b0
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-124.js
@@ -0,0 +1,57 @@
+// Copyright 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.
+
+assertEquals("[object global]", this.toString());
+assertEquals("[object global]", toString());
+
+assertEquals("[object global]", eval("this.toString()"));
+assertEquals("[object global]", eval("toString()"));
+
+assertEquals("[object global]", eval("var f; this.toString()"));
+assertEquals("[object global]", eval("var f; toString()"));
+
+
+function F(f) {
+  assertEquals("[object global]", this.toString());
+  assertEquals("[object global]", toString());
+
+  assertEquals("[object global]", eval("this.toString()"));
+  assertEquals("[object global]", eval("toString()"));
+
+  assertEquals("[object global]", eval("var f; this.toString()"));
+  assertEquals("[object global]", eval("var f; toString()"));
+
+  assertEquals("[object global]", eval("f()"));
+
+  // Receiver should be the arguments object here.
+  assertEquals("[object Object]", eval("arguments[0]()"));
+  with (arguments) {
+    assertEquals("[object Object]", toString());
+  }
+}
+
+F(Object.prototype.toString);
diff --git a/deps/v8/test/mjsunit/regress/regress-1254366.js b/deps/v8/test/mjsunit/regress/regress-1254366.js
new file mode 100644
index 0000000..2f9e011
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1254366.js
@@ -0,0 +1,38 @@
+// Copyright 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.
+
+function gee() {};
+
+Object.prototype.findOrStore = function() {
+  var z = this.vvv = gee;
+  return z;
+};
+
+var a =  new Object();
+assertEquals(gee, a.findOrStore());
+assertEquals(gee, a.findOrStore());
+
diff --git a/deps/v8/test/mjsunit/regress/regress-1327557.js b/deps/v8/test/mjsunit/regress/regress-1327557.js
new file mode 100644
index 0000000..bdf4277
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1327557.js
@@ -0,0 +1,36 @@
+// Copyright 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.
+
+var x = { valueOf: function() { throw "x"; } };
+var y = { valueOf: function() { throw "y"; } };
+
+try {
+  x * -y;
+  assertUnreachable("Didn't throw an exception");
+} catch (e) {
+  assertEquals("y", e);
+}
diff --git a/deps/v8/test/mjsunit/regress/regress-1341167.js b/deps/v8/test/mjsunit/regress/regress-1341167.js
new file mode 100644
index 0000000..194a7b8
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1341167.js
@@ -0,0 +1,33 @@
+// Copyright 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.
+
+// Make sure that 'this' is bound to the global object when using
+// execScript.
+
+var result;
+execScript("result = this");
+assertTrue(result === this);
diff --git a/deps/v8/test/mjsunit/regress/regress-1346700.js b/deps/v8/test/mjsunit/regress/regress-1346700.js
new file mode 100644
index 0000000..fe2d6fa
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1346700.js
@@ -0,0 +1,29 @@
+// 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.
+
+var o = {"\u59cb\u53d1\u7ad9": 1};
+assertEquals(1, o.\u59cb\u53d1\u7ad9);
diff --git a/deps/v8/test/mjsunit/regress/regress-137.js b/deps/v8/test/mjsunit/regress/regress-137.js
new file mode 100644
index 0000000..cc7b68c
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-137.js
@@ -0,0 +1,46 @@
+// Copyright 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.
+
+// See <URL:http://code.google.com/p/v8/issues/detail?id=137>
+
+(function () {
+  var strNum = 170;
+  var base = strNum / 16;
+  var rem = strNum % 16;
+  var base = base - (rem / 16);  // base is now HeapNumber with valid Smi value.
+
+  switch(base) {
+    case 10: return "A";  // Expected result.
+    case 11: return "B";
+    case 12: return "C";
+    case 13: return "D";
+    case 14: return "E";
+    case 15: return "F";  // Enough cases to trigger fast-case Smi switch.
+  };
+  fail("case 10", "Default case", "Heap number not recognized as Smi value");
+})();
+
diff --git a/deps/v8/test/mjsunit/regress/regress-1439135.js b/deps/v8/test/mjsunit/regress/regress-1439135.js
new file mode 100644
index 0000000..737a7ba
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1439135.js
@@ -0,0 +1,40 @@
+// Copyright 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.
+
+
+function Test() {
+  var left  = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
+  var right = "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY";
+  for (var i = 0; i < 100000; i++) {
+    var cons = left + right;
+    var substring = cons.substring(20, 80);
+    var index = substring.indexOf('Y');
+    assertEquals(34, index);
+  }
+}
+
+Test();
diff --git a/deps/v8/test/mjsunit/regress/regress-149.js b/deps/v8/test/mjsunit/regress/regress-149.js
new file mode 100644
index 0000000..6377a5b
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-149.js
@@ -0,0 +1,28 @@
+// Copyright 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.
+
+assertEquals(String.fromCharCode(0x26B), String.fromCharCode(0x2C62).toLowerCase());
diff --git a/deps/v8/test/mjsunit/regress/regress-1493017.js b/deps/v8/test/mjsunit/regress/regress-1493017.js
new file mode 100644
index 0000000..99a1dad
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1493017.js
@@ -0,0 +1,52 @@
+// 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.
+
+// Test collection of abandoned maps.  Tests that deleted map
+// transitions do not show up as properties in for in.
+
+// Flags: --expose-gc --collect-maps
+
+function C() {}
+
+
+// Create an instance of C.  Add a property to the instance and then
+// remove all references to instances of C.
+var o = new C();
+o.x = 42;
+o = null;
+
+// Force a global GC. This will collect the maps starting from C and
+// delete map transitions.
+gc();
+
+// Create a new instance of C.
+o = new C();
+
+// Test that the deleted map transitions do not show up in for in.
+for (var p in o) {
+  assertTrue(false);
+}
diff --git a/deps/v8/test/mjsunit/regress/regress-171.js b/deps/v8/test/mjsunit/regress/regress-171.js
new file mode 100644
index 0000000..fe981da
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-171.js
@@ -0,0 +1,41 @@
+// 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.
+
+function f(s) { return s.length; }
+function g(s, key) { return s[key]; }
+
+assertEquals(f(new String("a")), 1);
+assertEquals(f(new String("a")), 1);
+assertEquals(f(new String("a")), 1);
+assertEquals(f("a"), 1);
+assertEquals(f(new String("a")), 1);
+
+assertEquals(g(new String("a"), "length"), 1);
+assertEquals(g(new String("a"), "length"), 1);
+assertEquals(g(new String("a"), "length"), 1);
+assertEquals(g("a", "length"), 1);
+assertEquals(g(new String("a"), "length"), 1);
diff --git a/deps/v8/test/mjsunit/regress/regress-176.js b/deps/v8/test/mjsunit/regress/regress-176.js
new file mode 100644
index 0000000..b204812
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-176.js
@@ -0,0 +1,50 @@
+// Copyright 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.
+
+// See http://code.google.com/p/v8/issues/detail?id=176
+
+assertEquals("f,",
+             "foo".match(/(?:(?=(f)o))?f/).toString(),
+             "zero length match in (?:) with capture in lookahead");
+assertEquals("f,",
+             "foo".match(/(?=(f)o)?f/).toString(),
+             "zero length match in (?=) with capture in lookahead");
+assertEquals("fo,f",
+             "foo".match(/(?:(?=(f)o)f)?o/),
+             "non-zero length match with capture in lookahead");
+assertEquals("fo,f",
+             "foo".match(/(?:(?=(f)o)f?)?o/),
+             "non-zero length match with greedy ? in (?:)");
+assertEquals("fo,f",
+             "foo".match(/(?:(?=(f)o)f??)?o/),
+             "non-zero length match with non-greedy ? in (?:), o forces backtrack");
+assertEquals("fo,f",
+             "foo".match(/(?:(?=(f)o)f??)?./),
+             "non-zero length match with non-greedy ? in (?:), zero length match causes backtrack");
+assertEquals("f,",
+             "foo".match(/(?:(?=(f)o)fx)?./),
+             "x causes backtrack inside (?:)");
diff --git a/deps/v8/test/mjsunit/regress/regress-186.js b/deps/v8/test/mjsunit/regress/regress-186.js
new file mode 100644
index 0000000..335869d
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-186.js
@@ -0,0 +1,72 @@
+// 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.
+
+// Make sure that eval can introduce a local variable called __proto__.
+// See http://code.google.com/p/v8/issues/detail?id=186
+
+var setterCalled = false;
+
+var o = {};
+o.__defineSetter__("x", function() { setterCalled = true; });
+
+function runTest(test) {
+  setterCalled = false;
+  test();
+}
+
+function testLocal() {
+  // Add property called __proto__ to the extension object.
+  eval("var __proto__ = o");
+  // Check that the extension object's prototype did not change.
+  eval("var x = 27");
+  assertFalse(setterCalled, "prototype of extension object changed");
+  assertEquals(o, eval("__proto__"));
+}
+
+function testConstLocal() {
+  // Add const property called __proto__ to the extension object.
+  eval("const __proto__ = o");
+  // Check that the extension object's prototype did not change.
+  eval("var x = 27");
+  assertFalse(setterCalled, "prototype of extension object changed");
+  assertEquals(o, eval("__proto__"));
+}
+
+function testGlobal() {
+  // Assign to the global __proto__ property.
+  eval("__proto__ = o");
+  // Check that the prototype of the global object changed.
+  eval("x = 27");
+  assertTrue(setterCalled, "prototype of global object did not change");
+  setterCalled = false;
+  assertEquals(o, eval("__proto__"));
+}
+
+runTest(testLocal);
+runTest(testConstLocal);
+runTest(testGlobal);
+
diff --git a/deps/v8/test/mjsunit/regress/regress-187.js b/deps/v8/test/mjsunit/regress/regress-187.js
new file mode 100644
index 0000000..44d8d7a
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-187.js
@@ -0,0 +1,30 @@
+// Copyright 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.
+
+// See http://code.google.com/p/v8/issues/detail?id=187
+
+assertEquals("f,", "foo".match(/(?:(?=(f)o)fx|)./));
diff --git a/deps/v8/test/mjsunit/regress/regress-189.js b/deps/v8/test/mjsunit/regress/regress-189.js
new file mode 100644
index 0000000..a84b620
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-189.js
@@ -0,0 +1,36 @@
+// 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.
+
+// Test that we can handle initialization of a deleted const variable.
+
+// See http://code.google.com/p/v8/issues/detail?id=189.
+
+function f() {
+  eval("delete x; const x = 32");
+}
+
+f();
diff --git a/deps/v8/test/mjsunit/regress/regress-191.js b/deps/v8/test/mjsunit/regress/regress-191.js
new file mode 100644
index 0000000..ca513c9
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-191.js
@@ -0,0 +1,42 @@
+// 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.
+
+// Make sure that accessor setters are ignored on context extension
+// objects.
+// See http://code.google.com/p/v8/issues/detail?id=191
+
+var setterCalled = false;
+
+Object.prototype.__defineSetter__("x", function() { setterCalled = true; });
+
+function test() {
+  eval("var x = 42");
+  assertFalse(setterCalled, "accessor setter call on context object");
+  assertEquals(42, eval("x"));
+}
+
+test();
diff --git a/deps/v8/test/mjsunit/regress/regress-192.js b/deps/v8/test/mjsunit/regress/regress-192.js
new file mode 100644
index 0000000..8f0978f
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-192.js
@@ -0,0 +1,38 @@
+// 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.
+
+// Test that exceptions are correctly propagated when creating object
+// literals.
+
+// See http://code.google.com/p/v8/issues/detail?id=192
+
+Object.prototype.__defineGetter__("x", function() {});
+
+// Creating this object literal will throw an exception because we are
+// assigning to a property that has only a getter.
+assertThrows("({ x: 42 })");
+
diff --git a/deps/v8/test/mjsunit/regress/regress-193.js b/deps/v8/test/mjsunit/regress/regress-193.js
new file mode 100644
index 0000000..f803483
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-193.js
@@ -0,0 +1,44 @@
+// 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.
+
+// Test that context extension objects do not have a constructor
+// property.
+
+// See http://code.google.com/p/v8/issues/detail?id=193.
+
+function f() {
+  return eval("var x; constructor");
+}
+
+// It should be ok to call the constructor function returned by f.
+f()();
+
+// The call to f should get the constructor of the receiver which is
+// the constructor of the global object.
+assertEquals(constructor, f());
+
+
diff --git a/deps/v8/test/mjsunit/regress/regress-20070207.js b/deps/v8/test/mjsunit/regress/regress-20070207.js
new file mode 100644
index 0000000..e90b2ec
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-20070207.js
@@ -0,0 +1,42 @@
+// Copyright 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.
+
+// The following regression test illustrates a problem in using the
+// value of setting a property in the arguments object. 
+
+function f(s) {
+  arguments.length;
+  return (s += 10) < 0;
+}
+
+assertTrue(f(-100));
+assertTrue(f(-20));
+assertFalse(f(-10));
+assertFalse(f(-5));
+assertFalse(f(0));
+assertFalse(f(10));
+
diff --git a/deps/v8/test/mjsunit/regress/regress-201.js b/deps/v8/test/mjsunit/regress/regress-201.js
new file mode 100644
index 0000000..8847fc0
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-201.js
@@ -0,0 +1,37 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// See http://code.google.com/p/v8/issues/detail?id=201.
+
+function testsort(n) {
+  n=1*n;
+  var numbers=new Array(n);
+  for (var i=0;i<n;i++) numbers[i]=i;
+  numbers.sort();
+}
+
+testsort("5001")
diff --git a/deps/v8/test/mjsunit/regress/regress-219.js b/deps/v8/test/mjsunit/regress/regress-219.js
new file mode 100644
index 0000000..4bfabdc
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-219.js
@@ -0,0 +1,176 @@
+// Copyright 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.
+
+// Tests handling of flags for regexps.
+
+// We should now allow duplicates of flags.
+// (See http://code.google.com/p/v8/issues/detail?id=219)
+
+// Base tests: we recognize the basic flags
+
+function assertFlags(re, global, multiline, ignoreCase) {
+  var name = re + " flag: ";
+  (global ? assertTrue : assertFalse)(re.global, name + "g");
+  (multiline ? assertTrue : assertFalse)(re.multiline, name + "m");
+  (ignoreCase ? assertTrue : assertFalse)(re.ignoreCase, name + "i");
+}
+
+var re = /a/;
+assertFlags(re, false, false, false)
+
+re = /a/gim;
+assertFlags(re, true, true, true)
+
+re = RegExp("a","");
+assertFlags(re, false, false, false)
+
+re = RegExp("a", "gim");
+assertFlags(re, true, true, true)
+
+// Double i's
+
+re = /a/ii;
+assertFlags(re, false, false, true)
+
+re = /a/gii;
+assertFlags(re, true, false, true)
+
+re = /a/igi;
+assertFlags(re, true, false, true)
+
+re = /a/iig;
+assertFlags(re, true, false, true)
+
+re = /a/gimi;
+assertFlags(re, true, true, true)
+
+re = /a/giim;
+assertFlags(re, true, true, true)
+
+re = /a/igim;
+assertFlags(re, true, true, true)
+
+
+re = RegExp("a", "ii");
+assertFlags(re, false, false, true)
+
+re = RegExp("a", "gii");
+assertFlags(re, true, false, true)
+
+re = RegExp("a", "igi");
+assertFlags(re, true, false, true)
+
+re = RegExp("a", "iig");
+assertFlags(re, true, false, true)
+
+re = RegExp("a", "gimi");
+assertFlags(re, true, true, true)
+
+re = RegExp("a", "giim");
+assertFlags(re, true, true, true)
+
+re = RegExp("a", "igim");
+assertFlags(re, true, true, true)
+
+// Tripple i's
+
+re = /a/iii;
+assertFlags(re, false, false, true)
+
+re = /a/giii;
+assertFlags(re, true, false, true)
+
+re = /a/igii;
+assertFlags(re, true, false, true)
+
+re = /a/iigi;
+assertFlags(re, true, false, true)
+
+re = /a/iiig;
+assertFlags(re, true, false, true)
+
+re = /a/miiig;
+assertFlags(re, true, true, true)
+
+
+re = RegExp("a", "iii");
+assertFlags(re, false, false, true)
+
+re = RegExp("a", "giii");
+assertFlags(re, true, false, true)
+
+re = RegExp("a", "igii");
+assertFlags(re, true, false, true)
+
+re = RegExp("a", "iigi");
+assertFlags(re, true, false, true)
+
+re = RegExp("a", "iiig");
+assertFlags(re, true, false, true)
+
+re = RegExp("a", "miiig");
+assertFlags(re, true, true, true)
+
+// Illegal flags - flags late in string.
+
+re = /a/arglebargleglopglyf;
+assertFlags(re, true, false, false)
+
+re = /a/arglebargleglopglif;
+assertFlags(re, true, false, true)
+
+re = /a/arglebargleglopglym;
+assertFlags(re, true, true, false)
+
+re = /a/arglebargleglopglim;
+assertFlags(re, true, true, true)
+
+// Case of flags still matters.
+
+re = /a/gmi;
+assertFlags(re, true, true, true)
+
+re = /a/Gmi;
+assertFlags(re, false, true, true)
+
+re = /a/gMi;
+assertFlags(re, true, false, true)
+
+re = /a/gmI;
+assertFlags(re, true, true, false)
+
+re = /a/GMi;
+assertFlags(re, false, false, true)
+
+re = /a/GmI;
+assertFlags(re, false, true, false)
+
+re = /a/gMI;
+assertFlags(re, true, false, false)
+
+re = /a/GMI;
+assertFlags(re, false, false, false)
diff --git a/deps/v8/test/mjsunit/regress/regress-220.js b/deps/v8/test/mjsunit/regress/regress-220.js
new file mode 100644
index 0000000..416aa41
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-220.js
@@ -0,0 +1,31 @@
+// 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.
+
+function foo(f) { eval(f); }
+
+// Ensure that compiling a declaration of a function does not crash.
+foo("function (x) { with ({x: []}) function x(){} }");
diff --git a/deps/v8/test/mjsunit/regress/regress-221.js b/deps/v8/test/mjsunit/regress/regress-221.js
new file mode 100644
index 0000000..d3f2e35
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-221.js
@@ -0,0 +1,34 @@
+// 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.
+
+// Test that direct eval calls handle the case where eval has been
+// deleted correctly.
+
+// See http://code.google.com/p/v8/issues/detail?id=221
+
+assertThrows('eval(delete eval)');
+
diff --git a/deps/v8/test/mjsunit/regress/regress-225.js b/deps/v8/test/mjsunit/regress/regress-225.js
new file mode 100644
index 0000000..e101ca0
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-225.js
@@ -0,0 +1,32 @@
+// 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=225
+
+assertEquals("foo", "foo".replace(/(?:)/g, function() { return ""; }));
+
+assertEquals("foo", "foo".replace(/(?:)/g, ""));
diff --git a/deps/v8/test/mjsunit/regress/regress-227.js b/deps/v8/test/mjsunit/regress/regress-227.js
new file mode 100644
index 0000000..ebb4627
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-227.js
@@ -0,0 +1,33 @@
+// 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.
+
+var re = /\u23a1|x/;
+var res = re.exec("!");
+assertEquals(null, res, "Throwing away high bits on ASCII string");
+
+res = re.exec("!x");
+assertEquals(["x"], res, "Throwing away high bits on ASCII string");
diff --git a/deps/v8/test/mjsunit/regress/regress-231.js b/deps/v8/test/mjsunit/regress/regress-231.js
new file mode 100644
index 0000000..0c6e5b3
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-231.js
@@ -0,0 +1,92 @@
+// 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 issue 231 <URL: http://code.google.com/p/v8/issues/detail?id=231 >
+// A stack growth during a look-ahead could restore a pointer to the old stack.
+// (Test derived from crash at ibs.blumex.com).
+
+var re = /Ggcy\b[^D]*D((?:(?=([^G]+))\2|G(?!gcy\b[^D]*D))*?)GIgcyD/;
+
+var str = 'GgcyDGgcy.saaaa.aDGaaa.aynaaaaaaaaacaaaaagcaaaaaaaancaDGgnayr' +
+    '.aryycnaaaataaaa.aryyacnaaataaaa.aaaaraaaaa.aaagaaaaaaaaDGgaaaaDGga' +
+    '.aaagaaaaaaaaDGga.nyataaaaragraa.anyataaagaca.agayraaarataga.aaacaa' +
+    '.aaagaa.aaacaaaDGaaa.aynaaaaaaaaacaaaaagcaaaaaacaagaa.agayraaaGgaaa' +
+    '.trgaaaaaagaatGanyara.caagaaGaD.araaaa_aat_aayDDaaDGaaa.aynaaaaaaaa' +
+    'acaaaaagcaaaaaacaaaaa.agayraaaGgaaa.trgaaaaaaatGanyaraDDaaDGacna.ay' +
+    'naaaaaaaaacaaaaagcaaaaaacaaaraGgaaa.naaaaagaaaaaaraynaaGanyaraDDaaD' +
+    'aGgaaa.saaangaaaaraaaGgaaa.trgaaaragaaaarGanyaraDDDaGIacnaDGIaaaDGI' +
+    'aaaDGIgaDGga.anyataaagaca.agayraaaaagaa.aaaaa.cnaaaata.aca.aca.aca.' +
+    'acaaaDGgnayr.aaaaraaaaa.aaagaaaaaaaaDGgaaaaDGgaDGga.aayacnaaaaa.ayn' +
+    'aaaaaaaaacaaaaagcaaaaaanaraDGaDacaaaaag_anaraGIaDGIgaDGIgaDGgaDGga.' +
+    'aayacnaaaaa.aaagaaaaaaaaDGaa.aaagaaaaaaaa.aaaraaaa.aaaanaraaaa.IDGI' +
+    'gaDGIgaDGgaDGga.aynaaaaaaaaacaaaaagcaaaaaaaraaaa.anyataaagacaDaGgaa' +
+    'a.trgGragaaaacgGaaaaaaaG_aaaaa_Gaaaaaaaaa,.aGanar.anaraDDaaGIgaDGga' +
+    '.aynaaaaaaaaacaaaaagcaaaaaaanyara.anyataaagacaDGaDaaaaag_caaaaag_an' +
+    'araGIaDGIgaDGIgaDGgaDGga.aynaaaaaaaaacaaaaagcaaaaaaaraaaa.anyataaag' +
+    'acaDaGgaaa.trgGragaaaacgGaaaaaaaG_aaaaa_aaaaaa,.aaaaacaDDaaGIgaDGga' +
+    '.aynaaaaaaaaacaaaaagcaaaaaaanyara.anyataaagacaDGaDataaac_araaaaGIaD' +
+    'GIgaDGIgaDaagcyaaGgaDGga.aayacnaaaaa.aaagaaaaaaaaDGaa.aaagaaaaaaaa.' +
+    'aaaraaaa.aaaanaraaaa.IDGIgaDGIgaDGgcy.asaadanyaga.aa.aaaDGgaDGga.ay' +
+    'naaaaaaaaacaaaaagcaaaaaaaraaaa.anyataaagacaDaGgaaa.trgGragaaaacgGaa' +
+    'aaaaaG_aaaaa_DaaaaGaa,.aDanyagaaDDaaGIgaDGga.aynaaaaaaaaacaaaaagcaa' +
+    'aaaaanyara.anyataaagacaDGaDadanyagaaGIaDGIgaDGIgaDGIgcyDGgcy.asaaga' +
+    'cras.agra_yratga.aa.aaaarsaaraa.aa.agra_yratga.aa.aaaDGgaDGga.aynaa' +
+    'aaaaaaacaaaaagcaaaaaaaraaaa.anyataaagacaDaGgaaa.trgGragaaaacgGaaaaa' +
+    'aaG_aaaaa_aGaaaaaaGaa,.aaratgaaDDaaGIgaDGga.aynaaaaaaaaacaaaaagcaaa' +
+    'aaaanyara.anyataaagacaDGaDaagra_yratgaaGIaDGIgaDGIgaDGIgcyDGgcy.asa' +
+    'agacras.aratag.aa.aaaarsaaraa.aa.aratag.aa.aaaDGgaDGga.aynaaaaaaaaa' +
+    'caaaaagcaaaaaaaraaaa.anyataaagacaDaGgaaa.trgGragaaaacgGaaaaaaaG_aaa' +
+    'aa_aaaaaGa,.aaratagaDDaaGIgaDGga.aynaaaaaaaaacaaaaagcaaaaaaanyara.a' +
+    'nyataaagacaDGaDaaratagaGIaDGIgaDGIgaDGIgcyDGgcy.asaagacras.gaaax_ar' +
+    'atag.aa.aaaarsaaraa.aa.gaaax_aratag.aa.aaaDGgaDGga.aynaaaaaaaaacaaa' +
+    'aagcaaaaaaaraaaa.anyataaagacaDaGgaaa.trgGragaaaacgGaaaaaaaG_aaaaa_G' +
+    'aaaaaaaaaGa,.aaratagaDDaaGIgaDGga.aynaaaaaaaaacaaaaagcaaaaaaanyara.' +
+    'anyataaagacaDGaDagaaax_aratagaGIaDGIgaDGIgaDGIgcyDGgcy.asaagacras.c' +
+    'ag_aaar.aa.aaaarsaaraa.aa.cag_aaar.aa.aaaDGgaDGga.aynaaaaaaaaacaaaa' +
+    'agcaaaaaaaraaaa.anyataaagacaDaGgaaa.trgGragaaaacgGaaaaaaaG_aaaaa_aa' +
+    'Gaaaaa,.aaagaaaraDDaaGIgaDGga.aynaaaaaaaaacaaaaagcaaaaaaanyara.anya' +
+    'taaagacaDGaDacag_aaaraGIaDGIgaDGIgaDGIgcyDGgcy.asaagacras.aaggaata_' +
+    'aa_cynaga_cc.aa.aaaarsaaraa.aa.aaggaata_aa_cynaga_cc.aa.aaaDGgaDGga' +
+    '.aynaaaaaaaaacaaaaagcaaaaaaaraaaa.anyataaagacaDaGgaaa.trgGragaaaacg' +
+    'GaaaaaaaG_aaaaa_aaGGaaaa_aa_aaaaGa_aaa,.aaynagaIcagaDDaaGIgaDGga.ay' +
+    'naaaaaaaaacaaaaagcaaaaaaanyara.anyataaagacaDGaDaaaggaata_aa_cynaga_' +
+    'ccaGIaDGIgaDGIgaDGIgcyDGgcy.asaagacras.syaara_aanargra.aa.aaaarsaar' +
+    'aa.aa.syaara_aanargra.aa.aaaDGgaDGga.aynaaaaaaaaacaaaaagcaaaaaaaraa' +
+    'aa.anyataaagacaDaGgaaa.trgGragaaaacgGaaaaaaaG_aaaaa_aaaaaaaaaaaGaaa' +
+    ',.aaanargraaDDaaGIgaDGga.aynaaaaaaaaacaaaaagcaaaaaaanyara.anyataaag' +
+    'acaDGaDasyaara_aanargraaGIaDGIgaDGIgaDGIgcyDGgcy.asaagacras.cynag_a' +
+    'anargra.aa.aaaarsaaraa.aa.cynag_aanargra.aa.aaaDGgaDGga.aynaaaaaaaa' +
+    'acaaaaagcaaaaaaaraaaa.anyataaagacaDaGgaaa.trgGragaaaacgGaaaaaaaG_aa' +
+    'aaa_aaaaGaaaaaGaaa,.aaanargraaDDaaGIgaDGga.aynaaaaaaaaacaaaaagcaaaa' +
+    'aaanyara.anyataaagacaDGaDacynag_aanargraaGIaDGIgaDGIgaDGIgcyDGgaDGg' +
+    'a.aynaaaaaaaaacaaaaagcaaaaaaaraaaa.anyataaagacaDaGgaaa.trgGragaaaac' +
+    'gGaaaaaaaG';
+
+//Shouldn't crash.
+
+var res = re.test(str);
+assertTrue(res);
\ No newline at end of file
diff --git a/deps/v8/test/mjsunit/regress/regress-233.js b/deps/v8/test/mjsunit/regress/regress-233.js
new file mode 100644
index 0000000..8723679
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-233.js
@@ -0,0 +1,39 @@
+// 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 issue 233 <URL: http://code.google.com/p/v8/issues/detail?id=233 >
+// A stack overflow detected by a global regexp match wasn't handled correctly.
+
+// This code shouldn't segmentation fault.
+function loop(s) {
+  loop(s.replace(/\s/g, ""));
+}
+try {
+  loop("No");
+} catch(e) {
+  // Stack overflow caught.
+}
diff --git a/deps/v8/test/mjsunit/regress/regress-244.js b/deps/v8/test/mjsunit/regress/regress-244.js
new file mode 100644
index 0000000..ffddcf8
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-244.js
@@ -0,0 +1,67 @@
+// 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.
+
+var kLegalPairs = [
+  [0x00, '%00'],
+  [0x01, '%01'],
+  [0x7f, '%7F'],
+  [0x80, '%C2%80'],
+  [0x81, '%C2%81'],
+  [0x7ff, '%DF%BF'],
+  [0x800, '%E0%A0%80'],
+  [0x801, '%E0%A0%81'],
+  [0xd7ff, '%ED%9F%BF'],
+  [0xffff, '%EF%BF%BF']
+];
+
+var kIllegalEncoded = [
+  '%80', '%BF', '%80%BF', '%80%BF%80', '%C0%22', '%DF',
+  '%EF%BF', '%F7BFBF', '%FE', '%FF', '%FE%FE%FF%FF',
+  '%C0%AF', '%E0%9F%BF', '%F0%8F%BF%BF', '%C0%80',
+  '%E0%80%80'
+];
+
+function run() {
+  for (var i = 0; i < kLegalPairs.length; i++) {
+    var decoded = String.fromCharCode(kLegalPairs[i][0]);
+    var encoded = kLegalPairs[i][1];
+    assertEquals(decodeURI(encoded), decoded);
+    assertEquals(encodeURI(decoded), encoded);
+  }
+  for (var i = 0; i < kIllegalEncoded.length; i++) {
+    var value = kIllegalEncoded[i];
+    var threw = false;
+    try {
+      decodeURI(value);
+      fail(value);
+    } catch (e) {
+      assertInstanceof(e, URIError);
+    }
+  }
+}
+
+run();
diff --git a/deps/v8/test/mjsunit/regress/regress-246.js b/deps/v8/test/mjsunit/regress/regress-246.js
new file mode 100755
index 0000000..4324b54
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-246.js
@@ -0,0 +1,31 @@
+// Copyright 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.
+
+// See: http://code.google.com/p/v8/issues/detail?id=246
+
+assertTrue(/(?:text)/.test("text"));
+assertEquals(["text"], /(?:text)/.exec("text"));
\ No newline at end of file
diff --git a/deps/v8/test/mjsunit/regress/regress-253.js b/deps/v8/test/mjsunit/regress/regress-253.js
new file mode 100644
index 0000000..72c5dc1
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-253.js
@@ -0,0 +1,31 @@
+// 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.
+
+var x = 0;
+x[0] = 0;
+x[0] = 1;
+x[0] = 2;
diff --git a/deps/v8/test/mjsunit/regress/regress-254.js b/deps/v8/test/mjsunit/regress/regress-254.js
new file mode 100755
index 0000000..ec4b40a
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-254.js
@@ -0,0 +1,58 @@
+// 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=254
+
+// RegExp with global flag: exec and test updates lastIndex.
+var re = /x/g;
+
+assertEquals(0, re.lastIndex, "Global, initial lastIndex");
+
+assertTrue(re.test("x"), "Global, test 1");
+assertEquals(1, re.lastIndex, "Global, lastIndex after test 1");
+assertFalse(re.test("x"), "Global, test 2");
+assertEquals(0, re.lastIndex, "Global, lastIndex after test 2");
+
+assertEquals(["x"], re.exec("x"), "Global, exec 1");
+assertEquals(1, re.lastIndex, "Global, lastIndex after exec 1");
+assertEquals(null, re.exec("x"), "Global, exec 2");
+assertEquals(0, re.lastIndex, "Global, lastIndex after exec 2");
+
+// RegExp without global flag: exec and test leavs lastIndex at zero.
+var re2 = /x/;
+
+assertEquals(0, re2.lastIndex, "Non-global, initial lastIndex");
+
+assertTrue(re2.test("x"), "Non-global, test 1");
+assertEquals(0, re2.lastIndex, "Non-global, lastIndex after test 1");
+assertTrue(re2.test("x"), "Non-global, test 2");
+assertEquals(0, re2.lastIndex, "Non-global, lastIndex after test 2");
+
+assertEquals(["x"], re2.exec("x"), "Non-global, exec 1");
+assertEquals(0, re2.lastIndex, "Non-global, lastIndex after exec 1");
+assertEquals(["x"], re2.exec("x"), "Non-global, exec 2");
+assertEquals(0, re2.lastIndex, "Non-global, lastIndex after exec 2");
diff --git a/deps/v8/test/mjsunit/regress/regress-259.js b/deps/v8/test/mjsunit/regress/regress-259.js
new file mode 100644
index 0000000..f0476ff
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-259.js
@@ -0,0 +1,33 @@
+// 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.
+
+// Test that we do not crash when compiling a try/finally with an
+// infinite loop (with no normal exits) in the try block.
+
+// See http://code.google.com/p/v8/issues/detail?id=259
+
+assertThrows("try { while (true) { throw 0; }} finally {}");
diff --git a/deps/v8/test/mjsunit/regress/regress-260.js b/deps/v8/test/mjsunit/regress/regress-260.js
new file mode 100644
index 0000000..65242bc
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-260.js
@@ -0,0 +1,33 @@
+// 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.
+
+// We should not compile the bodies of function literals in loop
+// conditions twice, even in cases where the loop condition is
+// compiled twice.
+
+function test() { eval("while(!function () { var x; });"); }
+test();
diff --git a/deps/v8/test/mjsunit/regress/regress-263.js b/deps/v8/test/mjsunit/regress/regress-263.js
new file mode 100644
index 0000000..123bde6
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-263.js
@@ -0,0 +1,38 @@
+// 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.
+
+// Exits via return, break, or continue from within try/finally or
+// for/in should not crash or trigger a debug assert.
+
+// See http://code.google.com/p/v8/issues/detail?id=263
+
+function test0() { with({}) for(var x in {}) return; }
+test0();
+
+
+function test1() { with({}) try { } finally { with({}) return; } }
+test1();
diff --git a/deps/v8/test/mjsunit/regress/regress-265.js b/deps/v8/test/mjsunit/regress/regress-265.js
new file mode 100644
index 0000000..21ac1a6
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-265.js
@@ -0,0 +1,64 @@
+// 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.
+
+// When returning or breaking out of a deeply nested try/finally, we
+// should not crash.
+
+// See http://code.google.com/p/v8/issues/detail?id=263
+
+function test0() {
+  try {
+    try {
+      return 0;
+    } finally {
+      try {
+        return 0;
+      } finally {
+      }
+    }
+  } finally {
+  }
+}
+
+test0();
+
+function test1() {
+L0:
+  try {
+    try {
+      break L0;
+    } finally {
+      try {
+        break L0;
+      } finally {
+      }
+    }
+  } finally {
+  }
+}
+
+test1();
diff --git a/deps/v8/test/mjsunit/regress/regress-267.js b/deps/v8/test/mjsunit/regress/regress-267.js
new file mode 100644
index 0000000..bb61606
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-267.js
@@ -0,0 +1,35 @@
+// 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=267
+
+var global = (function(){ return this; })();
+function taint(fn){var v = fn(); eval("taint"); return v; }
+function getThis(){ return this; }
+var obj = taint(getThis);
+
+assertEquals(global, obj, "Should be the global object.");
diff --git a/deps/v8/test/mjsunit/regress/regress-269.js b/deps/v8/test/mjsunit/regress/regress-269.js
new file mode 100644
index 0000000..49b24c0
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-269.js
@@ -0,0 +1,49 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function g() {
+}
+ 
+function f() {
+  debugger;
+  g.apply(null, ['']);
+}
+
+f()
\ No newline at end of file
diff --git a/deps/v8/test/mjsunit/regress/regress-279.js b/deps/v8/test/mjsunit/regress/regress-279.js
new file mode 100644
index 0000000..e500dd6
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-279.js
@@ -0,0 +1,62 @@
+// 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.
+
+function makeArrayInObject() {
+  return { foo: [] };
+}
+
+var a = makeArrayInObject();
+a.foo.push(5);
+var b = makeArrayInObject();
+assertEquals(0, b.foo.length, "Array in object");
+
+function makeObjectInObject() {
+  return { foo: {} };
+}
+
+a = makeObjectInObject();
+a.foo.bar = 1;
+b = makeObjectInObject();
+assertEquals('undefined', typeof(b.foo.bar), "Object in object");
+
+function makeObjectInArray() {
+  return [ {} ];
+}
+
+a = makeObjectInArray();
+a[0].bar = 1;
+b = makeObjectInArray();
+assertEquals('undefined', typeof(b[0].bar), "Object in array");
+
+function makeArrayInArray() {
+  return [ [] ];
+}
+
+a = makeArrayInArray();
+a[0].push(5);
+b = makeArrayInArray();
+assertEquals(0, b[0].length, "Array in array");
diff --git a/deps/v8/test/mjsunit/regress/regress-284.js b/deps/v8/test/mjsunit/regress/regress-284.js
new file mode 100644
index 0000000..ecfdeea
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-284.js
@@ -0,0 +1,50 @@
+// 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=284
+
+function continueWithinLoop() {
+  var result;
+  for (var key in [0]) {
+    result = "hopla";
+    continue;
+  }
+  return result;
+};
+
+assertEquals("hopla", continueWithinLoop());
+
+function breakWithinLoop() {
+  var result;
+  for (var key in [0]) {
+    result = "hopla";
+    break;
+  }
+  return result;
+};
+
+assertEquals("hopla", continueWithinLoop());
diff --git a/deps/v8/test/mjsunit/regress/regress-286.js b/deps/v8/test/mjsunit/regress/regress-286.js
new file mode 100644
index 0000000..361b726
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-286.js
@@ -0,0 +1,36 @@
+// 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=286
+
+function test() {
+  var o = [1];
+  var a = o[o ^= 1];
+  return a;
+};
+
+assertEquals(1, test());
diff --git a/deps/v8/test/mjsunit/regress/regress-294.js b/deps/v8/test/mjsunit/regress/regress-294.js
new file mode 100644
index 0000000..285b447
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-294.js
@@ -0,0 +1,43 @@
+// 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.
+
+// Should not crash.
+// See http://code.google.com/p/v8/issues/detail?id=294
+
+function f() { return false; }
+
+function test(x) {
+  var y = x;
+  if (x == "kat") x = "kat";
+  else {
+    x = "hund";
+    var z = f();
+    if (!z) x = "kat";
+  }
+}
+
+test("hund");
diff --git a/deps/v8/test/mjsunit/regress/regress-312.js b/deps/v8/test/mjsunit/regress/regress-312.js
new file mode 100644
index 0000000..0fb8c21
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-312.js
@@ -0,0 +1,31 @@
+// 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.
+
+// Should not trigger debug ASSERT.
+// See http://code.google.com/p/v8/issues/detail?id=312
+
+var o = { f: "x" ? function () {} : function () {} };
diff --git a/deps/v8/test/mjsunit/regress/regress-317.js b/deps/v8/test/mjsunit/regress/regress-317.js
new file mode 100644
index 0000000..b742fa1
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-317.js
@@ -0,0 +1,31 @@
+// 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.
+
+// Ensure replacement with string allows $ in replacement string.
+
+assertEquals("a$ec", "abc".replace("b", "$e"), "$e isn't meaningful");
+
diff --git a/deps/v8/test/mjsunit/regress/regress-318.js b/deps/v8/test/mjsunit/regress/regress-318.js
new file mode 100644
index 0000000..9e00b5f
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-318.js
@@ -0,0 +1,35 @@
+// 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.
+
+// Should not raise an exception.
+
+function test(value) {
+  if (typeof(value) == 'boolean') value = value + '';
+  if (typeof(value) == 'number') value = value + '';
+}
+
+assertDoesNotThrow(test(0));
diff --git a/deps/v8/test/mjsunit/regress/regress-35.js b/deps/v8/test/mjsunit/regress/regress-35.js
new file mode 100644
index 0000000..2fcdbe7
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-35.js
@@ -0,0 +1,33 @@
+// Copyright 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.
+
+var result;
+eval("result = 42; while(true)break");
+assertEquals(42, result);
+
+eval("result = 87; while(false)continue");
+assertEquals(87, result);
diff --git a/deps/v8/test/mjsunit/regress/regress-57.js b/deps/v8/test/mjsunit/regress/regress-57.js
new file mode 100644
index 0000000..1d410b9
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-57.js
@@ -0,0 +1,32 @@
+// Copyright 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.
+
+try {
+  delete (void 0).x;
+} catch (e) {
+  print(e.toString());
+}
diff --git a/deps/v8/test/mjsunit/regress/regress-588599.js b/deps/v8/test/mjsunit/regress/regress-588599.js
new file mode 100644
index 0000000..a1c16e2
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-588599.js
@@ -0,0 +1,31 @@
+// Copyright 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.
+
+assertFalse(Infinity == -Infinity);
+assertEquals(Infinity, 1 / 1e-9999);
+assertEquals(-Infinity, 1 / -1e-9999);
+
diff --git a/deps/v8/test/mjsunit/regress/regress-662254.js b/deps/v8/test/mjsunit/regress/regress-662254.js
new file mode 100644
index 0000000..daf5e17
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-662254.js
@@ -0,0 +1,40 @@
+// Copyright 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.
+
+function f() {
+  for (var c in []) { }
+}
+
+f();
+
+
+function g() {
+  var c;
+  for (c in []) { }
+}
+
+g();
diff --git a/deps/v8/test/mjsunit/regress/regress-666721.js b/deps/v8/test/mjsunit/regress/regress-666721.js
new file mode 100644
index 0000000..e2c632f
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-666721.js
@@ -0,0 +1,53 @@
+// Copyright 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.
+
+function len0(a) { return a.length; }
+function len1(a) { return a.length; }
+function len2(a) { return a.length; }
+function len3(a) { return a.length; }
+
+assertEquals(0, len0([]));
+assertEquals(1, len0({length:1}));
+assertEquals(2, len0([1,2]));
+assertEquals(3, len0('123'));
+
+assertEquals(0, len1(''));
+assertEquals(1, len1({length:1}));
+assertEquals(2, len1('12'));
+assertEquals(3, len1([1,2,3]));
+
+assertEquals(0, len2({length:0}));
+assertEquals(1, len2([1]));
+assertEquals(2, len2({length:2}));
+assertEquals(3, len2([1,2,3]));
+assertEquals(4, len2('1234'));
+
+assertEquals(0, len3({length:0}));
+assertEquals(1, len3('1'));
+assertEquals(2, len3({length:2}));
+assertEquals(3, len3('123'));
+assertEquals(4, len3([1,2,3,4]));
diff --git a/deps/v8/test/mjsunit/regress/regress-667061.js b/deps/v8/test/mjsunit/regress/regress-667061.js
new file mode 100644
index 0000000..4d29a1a
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-667061.js
@@ -0,0 +1,90 @@
+// Copyright 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.
+
+// Test non-ICC case.
+var caught = false;
+try {
+  (('foo'))();
+} catch (o) {
+  assertTrue(o instanceof TypeError);
+  caught = true;
+}
+assertTrue(caught);
+
+
+// Test uninitialized case.
+function h(o) {
+  return o.x();
+}
+
+var caught = false;
+try {
+  h({ x: 1 });
+} catch (o) {
+  assertTrue(o instanceof TypeError);
+  caught = true;
+}
+assertTrue(caught);
+
+
+// Test monomorphic case.
+function g(o) {
+  return o.x();
+}
+
+function O(x) { this.x = x; };
+var o = new O(function() { return 1; });
+assertEquals(1, g(o));  // go monomorphic
+assertEquals(1, g(o));  // stay monomorphic
+
+var caught = false;
+try {
+  g(new O(3));
+} catch (o) {
+  assertTrue(o instanceof TypeError);
+  caught = true;
+}
+assertTrue(caught);
+
+
+// Test megamorphic case.
+function f(o) {
+  return o.x();
+}
+
+assertEquals(1, f({ x: function () { return 1; }}));  // go monomorphic
+assertEquals(2, f({ x: function () { return 2; }}));  // go megamorphic
+assertEquals(3, f({ x: function () { return 3; }}));  // stay megamorphic
+
+var caught = false;
+try {
+  f({ x: 4 });
+} catch (o) {
+  assertTrue(o instanceof TypeError);
+  caught = true;
+}
+assertTrue(caught);
diff --git a/deps/v8/test/mjsunit/regress/regress-670147.js b/deps/v8/test/mjsunit/regress/regress-670147.js
new file mode 100644
index 0000000..b5b00d0
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-670147.js
@@ -0,0 +1,34 @@
+// Copyright 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.
+
+function XXX(x) {
+  var k = delete x;
+  return k;
+}
+
+assertFalse(XXX('Hello'));
+
diff --git a/deps/v8/test/mjsunit/regress/regress-674753.js b/deps/v8/test/mjsunit/regress/regress-674753.js
new file mode 100644
index 0000000..361b457
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-674753.js
@@ -0,0 +1,87 @@
+// Copyright 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.
+
+// Number
+assertTrue(typeof 0 == 'number');
+assertTrue(typeof 0 === 'number');
+assertTrue(typeof 1.2 == 'number');
+assertTrue(typeof 1.2 === 'number');
+assertFalse(typeof 'x' == 'number');
+assertFalse(typeof 'x' === 'number');
+
+// String
+assertTrue(typeof 'x' == 'string');
+assertTrue(typeof 'x' === 'string');
+assertTrue(typeof ('x' + 'x') == 'string');
+assertTrue(typeof ('x' + 'x') === 'string');
+assertFalse(typeof 1 == 'string');
+assertFalse(typeof 1 === 'string');
+assertFalse(typeof Object() == 'string');
+assertFalse(typeof Object() === 'string');
+
+// Boolean
+assertTrue(typeof true == 'boolean');
+assertTrue(typeof true === 'boolean');
+assertTrue(typeof false == 'boolean');
+assertTrue(typeof false === 'boolean');
+assertFalse(typeof 1 == 'boolean');
+assertFalse(typeof 1 === 'boolean');
+assertFalse(typeof Object() == 'boolean');
+assertFalse(typeof Object() === 'boolean');
+
+// Undefined
+assertTrue(typeof void 0 == 'undefined');
+assertTrue(typeof void 0 === 'undefined');
+assertFalse(typeof 1 == 'undefined');
+assertFalse(typeof 1 === 'undefined');
+assertFalse(typeof Object() == 'undefined');
+assertFalse(typeof Object() === 'undefined');
+
+// Function
+assertTrue(typeof Object == 'function');
+assertTrue(typeof Object === 'function');
+assertFalse(typeof 1 == 'function');
+assertFalse(typeof 1 === 'function');
+assertFalse(typeof Object() == 'function');
+assertFalse(typeof Object() === 'function');
+
+// Object
+assertTrue(typeof Object() == 'object');
+assertTrue(typeof Object() === 'object');
+assertTrue(typeof new String('x') == 'object');
+assertTrue(typeof new String('x') === 'object');
+assertTrue(typeof ['x'] == 'object');
+assertTrue(typeof ['x'] === 'object');
+assertTrue(typeof null == 'object');
+assertTrue(typeof null === 'object');
+assertFalse(typeof 1 == 'object');
+assertFalse(typeof 1 === 'object');
+assertFalse(typeof 'x' == 'object');  // bug #674753
+assertFalse(typeof 'x' === 'object');
+assertFalse(typeof Object == 'object');
+assertFalse(typeof Object === 'object');
+
diff --git a/deps/v8/test/mjsunit/regress/regress-676025.js b/deps/v8/test/mjsunit/regress/regress-676025.js
new file mode 100644
index 0000000..15157f2
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-676025.js
@@ -0,0 +1,31 @@
+// Copyright 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.
+
+var result;
+try { eval('a=/(/'); } catch (e) { result = e; }
+assertEquals('object', typeof result);
+assertTrue(result instanceof SyntaxError);
diff --git a/deps/v8/test/mjsunit/regress/regress-678525.js b/deps/v8/test/mjsunit/regress/regress-678525.js
new file mode 100644
index 0000000..5ff9c3d
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-678525.js
@@ -0,0 +1,59 @@
+// Copyright 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.
+
+assertEquals(0,  '\0'.charCodeAt(0));
+assertEquals(1,  '\1'.charCodeAt(0));
+assertEquals(2,  '\2'.charCodeAt(0));
+assertEquals(3,  '\3'.charCodeAt(0));
+assertEquals(4,  '\4'.charCodeAt(0));
+assertEquals(5,  '\5'.charCodeAt(0));
+assertEquals(6,  '\6'.charCodeAt(0));
+assertEquals(7,  '\7'.charCodeAt(0));
+assertEquals(56, '\8'.charCodeAt(0));
+
+assertEquals('\010', '\10');
+assertEquals('\011', '\11');    
+assertEquals('\012', '\12');
+assertEquals('\013', '\13');
+assertEquals('\014', '\14');
+assertEquals('\015', '\15');
+assertEquals('\016', '\16');
+assertEquals('\017', '\17');
+    
+assertEquals('\020', '\20');
+assertEquals('\021', '\21');    
+assertEquals('\022', '\22');
+assertEquals('\023', '\23');
+assertEquals('\024', '\24');
+assertEquals('\025', '\25');
+assertEquals('\026', '\26');
+assertEquals('\027', '\27');
+
+assertEquals(73,  '\111'.charCodeAt(0));
+assertEquals(105, '\151'.charCodeAt(0));
+
+    
diff --git a/deps/v8/test/mjsunit/regress/regress-682649.js b/deps/v8/test/mjsunit/regress/regress-682649.js
new file mode 100644
index 0000000..f23aed5
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-682649.js
@@ -0,0 +1,30 @@
+// Copyright 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.
+
+// Should return [object global], v8 returns [object Object]
+
+assertEquals(this.toString(), eval("this.toString()"));
diff --git a/deps/v8/test/mjsunit/regress/regress-69.js b/deps/v8/test/mjsunit/regress/regress-69.js
new file mode 100644
index 0000000..3fb1f76
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-69.js
@@ -0,0 +1,43 @@
+// Copyright 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.
+
+// This tests a switch statement with only default clause leaves
+// balanced stack. It should not trigger the break point when --debug_code
+// flag is turned on.
+// See issue: http://code.google.com/p/v8/issues/detail?id=69
+
+// Flags: --debug-code --expose-gc
+function unbalanced_switch(a) {
+  try {
+    switch (a) {
+      default: break;
+    }
+  } catch (e) {}
+  gc();
+}
+
+unbalanced_switch(1);
diff --git a/deps/v8/test/mjsunit/regress/regress-734862.js b/deps/v8/test/mjsunit/regress/regress-734862.js
new file mode 100644
index 0000000..6239047
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-734862.js
@@ -0,0 +1,37 @@
+// Copyright 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.
+
+function catcher(o, p) {
+  try { o[p]; } catch (e) { return e; }
+  throw p;
+}
+
+assertTrue(catcher(null, 'foo') instanceof TypeError);
+assertTrue(catcher(void 0, 'foo') instanceof TypeError);
+assertTrue(catcher(null, 123) instanceof TypeError);
+assertTrue(catcher(void 0, 123) instanceof TypeError);
+
diff --git a/deps/v8/test/mjsunit/regress/regress-737588.js b/deps/v8/test/mjsunit/regress/regress-737588.js
new file mode 100644
index 0000000..0f71dfc
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-737588.js
@@ -0,0 +1,34 @@
+// Copyright 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.
+
+var goog = goog || {} ;
+goog.global = this;
+goog.globalEval = function(script) {
+  return goog.global.eval(script);
+};
+
+assertEquals(125, goog.globalEval('var foofoofoo = 125; foofoofoo'));
diff --git a/deps/v8/test/mjsunit/regress/regress-74.js b/deps/v8/test/mjsunit/regress/regress-74.js
new file mode 100644
index 0000000..f22b33c
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-74.js
@@ -0,0 +1,41 @@
+// 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.
+
+// Test that the variable introduced by catch blocks is DontDelete.
+// See http://code.google.com/p/v8/issues/detail?id=74
+
+function test() {
+  try {
+    throw 42;
+  } catch(e) {
+    assertFalse(delete e, "deleting catch variable");
+    assertEquals(42, e);
+  }
+}
+
+test();
+
diff --git a/deps/v8/test/mjsunit/regress/regress-780423.js b/deps/v8/test/mjsunit/regress/regress-780423.js
new file mode 100644
index 0000000..862db32
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-780423.js
@@ -0,0 +1,39 @@
+// Copyright 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.
+
+var Class = {
+ create: function() {
+   return function kurt() {
+   }
+ }
+};
+
+var o1 = Class.create();
+var o2 = Class.create();
+
+assertTrue(o1 !== o2, "different functions");
+assertTrue(o1.prototype !== o2.prototype, "different protos");
diff --git a/deps/v8/test/mjsunit/regress/regress-799761.js b/deps/v8/test/mjsunit/regress/regress-799761.js
new file mode 100644
index 0000000..d3be1bd
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-799761.js
@@ -0,0 +1,92 @@
+// Copyright 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.
+
+// const variables should be read-only
+const c = 42;
+c = 87;
+assertEquals(42, c);
+
+
+// const variables are not behaving like other JS variables when it comes
+// to scoping - in fact they behave more sanely. Inside a 'with' they do
+// not interfere with the 'with' scopes.
+
+(function () {
+  with ({ x: 42 }) {
+    const x = 7;
+  }
+  x = 5;
+  assertEquals(7, x);
+})();
+
+
+// const variables may be declared but never initialized, in which case
+// their value is undefined.
+
+(function (sel) {
+  if (sel == 0)
+    with ({ x: 42 }) {
+    const x;
+    }
+  else
+    x = 3;
+  x = 5;
+  assertTrue(typeof x == 'undefined');
+})(1);
+
+
+// const variables may be initialized to undefined.
+(function () {
+  with ({ x: 42 }) {
+    const x = undefined;
+  }
+  x = 5;
+  assertTrue(typeof x == 'undefined');
+})();
+
+
+// const variables may be accessed in inner scopes like any other variable.
+(function () {
+  function bar() {
+    assertEquals(7, x);
+  }
+  with ({ x: 42 }) {
+    const x = 7;
+  }
+  x = 5
+  bar();
+})();
+
+
+// const variables may be declared via 'eval'
+(function () {
+  with ({ x: 42 }) {
+    eval('const x = 7');
+  }
+  x = 5;
+  assertEquals(7, x);
+})();
diff --git a/deps/v8/test/mjsunit/regress/regress-806473.js b/deps/v8/test/mjsunit/regress/regress-806473.js
new file mode 100644
index 0000000..6d6485d
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-806473.js
@@ -0,0 +1,60 @@
+// Copyright 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.
+
+// Flags: --expose-gc
+
+function catchThese() {
+  L: {
+    try {
+      break L;
+    } catch (e) {}
+  }
+}
+
+function finallyThese() {
+  L: {
+    try {
+      break L;
+    } finally {}
+  }
+}
+
+
+for (var i = 0; i < 10; i++) {
+  catchThese();
+  gc();
+}
+
+for (var j = 0; j < 10; j++) {
+  finallyThese();
+  gc();
+}
+
+assertEquals(10, i);
+assertEquals(10, j);
+
+
diff --git a/deps/v8/test/mjsunit/regress/regress-842017.js b/deps/v8/test/mjsunit/regress/regress-842017.js
new file mode 100644
index 0000000..3a367bb
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-842017.js
@@ -0,0 +1,60 @@
+// Copyright 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.
+
+// Flags: --expose-gc
+
+function break_from_for_in() {
+  L: {
+    try {
+      for (var x in [1,2,3]) {
+        break L;
+      }
+    } finally {}
+  }
+}
+
+function break_from_finally() {
+  L: {
+    try {
+    } finally {
+      break L;
+    }
+  }
+}
+
+for (var i = 0; i < 10; i++) {
+  break_from_for_in();
+  gc();
+}
+
+for (var j = 0; j < 10; j++) {
+  break_from_finally();
+  gc();
+}
+
+assertEquals(10, i);
+assertEquals(10, j);
diff --git a/deps/v8/test/mjsunit/regress/regress-86.js b/deps/v8/test/mjsunit/regress/regress-86.js
new file mode 100644
index 0000000..a33b60b
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-86.js
@@ -0,0 +1,46 @@
+// Copyright 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.
+
+var aList = [1, 2, 3];
+var loopCount = 0;
+var leftThroughFinally = false;
+var enteredFinally = false;
+for (x in aList) {
+  leftThroughFinally = true;
+  try {
+    throw "ex1";
+  } catch(er1) {
+    loopCount += 1;
+  } finally {
+    enteredFinally = true;
+    continue;
+  }
+  leftThroughFinally = false;
+}
+assertEquals(3, loopCount);
+assertTrue(enteredFinally);
+assertTrue(leftThroughFinally);
diff --git a/deps/v8/test/mjsunit/regress/regress-87.js b/deps/v8/test/mjsunit/regress/regress-87.js
new file mode 100644
index 0000000..131cb58
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-87.js
@@ -0,0 +1,58 @@
+// 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.
+
+function testFlags(flagstring, global, ignoreCase, multiline) {
+  var text = "/x/"+flagstring;
+  var re = eval(text);
+  assertEquals(global, re.global, text + ".global");
+  assertEquals(ignoreCase, re.ignoreCase, text + ".ignoreCase");
+  assertEquals(multiline, re.multiline, text + ".multiline");
+}
+
+testFlags("", false, false, false);
+
+testFlags("\u0067", true, false, false);
+
+testFlags("\u0069", false, true, false)
+
+testFlags("\u006d", false, false, true);
+
+testFlags("\u0068", false, false, false);
+
+testFlags("\u0020", false, false, false);
+
+
+testFlags("\u0067g", true, false, false);
+
+testFlags("g\u0067", true, false, false);
+
+testFlags("abc\u0067efg", true, false, false);
+
+testFlags("i\u0067", true, true, false);
+
+testFlags("\u0067i", true, true, false);
+
diff --git a/deps/v8/test/mjsunit/regress/regress-874178.js b/deps/v8/test/mjsunit/regress/regress-874178.js
new file mode 100644
index 0000000..0ed5434
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-874178.js
@@ -0,0 +1,32 @@
+// Copyright 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.
+
+function foo(){}
+assertTrue(Function.prototype.isPrototypeOf(foo));
+
+foo.bar = 'hello';
+assertTrue(foo.propertyIsEnumerable('bar'));
diff --git a/deps/v8/test/mjsunit/regress/regress-875031.js b/deps/v8/test/mjsunit/regress/regress-875031.js
new file mode 100644
index 0000000..f18b084
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-875031.js
@@ -0,0 +1,37 @@
+// Copyright 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.
+
+// Regression test for issue 875031.
+
+var caught = false;
+try {
+  eval("return;");
+  assertTrue(false);  // should not reach here
+} catch (e) {
+  caught = true;
+}
+assertTrue(caught);
diff --git a/deps/v8/test/mjsunit/regress/regress-877615.js b/deps/v8/test/mjsunit/regress/regress-877615.js
new file mode 100644
index 0000000..d35aba6
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-877615.js
@@ -0,0 +1,37 @@
+// Copyright 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.
+
+Number.prototype.toLocaleString = function() { return 'invalid'};
+assertEquals([1].toLocaleString(), 'invalid');  // invalid
+
+Number.prototype.toLocaleString = 'invalid';
+assertEquals([1].toLocaleString(), '1');  // 1
+
+Number.prototype.toString = function() { return 'invalid' };
+assertEquals([1].toLocaleString(), '1');  // 1
+assertEquals([1].toString(), '1');        // 1
+
diff --git a/deps/v8/test/mjsunit/regress/regress-892742.js b/deps/v8/test/mjsunit/regress/regress-892742.js
new file mode 100644
index 0000000..a60395e
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-892742.js
@@ -0,0 +1,50 @@
+// Copyright 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.
+
+function f() {
+  return/* useless*/1;
+};
+
+
+// According to ECMA-262, this comment should actually be parsed as a
+// line terminator making g() return undefined, but this is not the
+// way it's handled by Spidermonkey or KJS.
+function g() {
+  return/* useless
+         */2;
+};
+
+function h() {
+  return// meaningful
+      3;
+};
+
+
+assertEquals(1, f());
+assertEquals(2, g());
+assertTrue(typeof h() == 'undefined', 'h');
+
diff --git a/deps/v8/test/mjsunit/regress/regress-900055.js b/deps/v8/test/mjsunit/regress/regress-900055.js
new file mode 100644
index 0000000..9a02f22
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-900055.js
@@ -0,0 +1,42 @@
+// Copyright 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.
+
+var alias = eval;
+function e(s) { return alias(s); }
+
+assertEquals(42, e("42"));
+assertEquals(Object, e("Object"));
+assertEquals(e, e("e"));
+
+var caught = false;
+try {
+  e('s');  // should throw exception since aliased eval is global
+} catch (e) {
+  caught = true;
+  assertTrue(e instanceof ReferenceError);
+}
+assertTrue(caught);
diff --git a/deps/v8/test/mjsunit/regress/regress-900966.js b/deps/v8/test/mjsunit/regress/regress-900966.js
new file mode 100644
index 0000000..b95d10e
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-900966.js
@@ -0,0 +1,38 @@
+// Copyright 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.
+
+assertTrue('abc'[10] === undefined);
+String.prototype[10] = 'x';
+assertEquals('abc'[10], 'x');
+
+assertTrue(2[11] === undefined);
+Number.prototype[11] = 'y';
+assertEquals(2[11], 'y');
+
+assertTrue(true[12] === undefined);
+Boolean.prototype[12] = 'z';
+assertEquals(true[12], 'z');
diff --git a/deps/v8/test/mjsunit/regress/regress-91.js b/deps/v8/test/mjsunit/regress/regress-91.js
new file mode 100644
index 0000000..7f6263d
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-91.js
@@ -0,0 +1,38 @@
+// 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.
+
+var date = new Date();
+var year = date.getYear();
+date.setMilliseconds(Number.NaN);
+date.setYear(1900 + year);
+assertEquals(year, date.getYear());
+assertEquals(0, date.getMonth());
+assertEquals(1, date.getDate());
+assertEquals(0, date.getHours());
+assertEquals(0, date.getMinutes());
+assertEquals(0, date.getSeconds());
+assertEquals(0, date.getMilliseconds());
diff --git a/deps/v8/test/mjsunit/regress/regress-925537.js b/deps/v8/test/mjsunit/regress/regress-925537.js
new file mode 100644
index 0000000..11582ea
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-925537.js
@@ -0,0 +1,42 @@
+// Copyright 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.
+
+function assertClose(expected, actual) {
+  var delta = 0.00001;
+  if (Math.abs(expected - actual) > delta) {
+    print('Failure: Expected <' + actual + '> to be close to <' + 
+          expected + '>');    
+  }
+}
+
+assertEquals(1, Math.pow(NaN, 0));
+var pinf = Number.POSITIVE_INFINITY, ninf = Number.NEGATIVE_INFINITY;
+assertClose( Math.PI / 4, Math.atan2(pinf, pinf));
+assertClose(-Math.PI / 4, Math.atan2(ninf, pinf));
+assertClose( 3 * Math.PI / 4, Math.atan2(pinf, ninf));
+assertClose(-3 * Math.PI / 4, Math.atan2(ninf, ninf));
+
diff --git a/deps/v8/test/mjsunit/regress/regress-937896.js b/deps/v8/test/mjsunit/regress/regress-937896.js
new file mode 100644
index 0000000..e8e5ef2
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-937896.js
@@ -0,0 +1,50 @@
+// Copyright 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.
+
+// This used to crash because the label collector in the parser didn't
+// discard duplicates which caused the outer-most continue statement
+// to try to unlink the inner try-handler that wasn't on the stack.
+
+function f() {
+  try {
+    for (var i = 0; i < 2; i++) {
+      continue;
+      try {
+        continue;
+        continue;
+      } catch (ex) {
+        // Empty.
+      }
+    }
+  } catch (e) {
+    // Empty. 
+  }
+  return 42;
+}
+
+
+assertEquals(42, f());
diff --git a/deps/v8/test/mjsunit/regress/regress-990205.js b/deps/v8/test/mjsunit/regress/regress-990205.js
new file mode 100644
index 0000000..1ab5bf8
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-990205.js
@@ -0,0 +1,35 @@
+// Copyright 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.
+
+function f() {
+  // Force eager compilation of x through the use of eval. The break
+  // in function x should not try to break out of the enclosing while.
+  return eval("while(0) function x() { break; }; 42");
+};
+
+assertEquals(42, f());
+
diff --git a/deps/v8/test/mjsunit/regress/regress-992733.js b/deps/v8/test/mjsunit/regress/regress-992733.js
new file mode 100644
index 0000000..d0f7511
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-992733.js
@@ -0,0 +1,35 @@
+// Copyright 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.
+
+assertEquals("object", typeof this);
+var threw = false;
+try {
+  this();
+} catch (e) {
+  threw = true;
+}
+assertTrue(threw);
diff --git a/deps/v8/test/mjsunit/regress/regress-996542.js b/deps/v8/test/mjsunit/regress/regress-996542.js
new file mode 100644
index 0000000..8fc704e
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-996542.js
@@ -0,0 +1,40 @@
+// Copyright 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.
+
+var zero = 0;
+var one = 1;
+var minus_one = -1;
+
+assertEquals(-Infinity, 1 / (0 / -1));
+assertEquals(-Infinity, one / (zero / minus_one));
+assertEquals(Infinity, 1 / (0 / 1));
+assertEquals(Infinity, one / (zero / one));
+
+assertEquals(-Infinity, 1 / (-1 % 1));
+assertEquals(-Infinity, one / (minus_one % one))
+assertEquals(Infinity, 1 / (1 % 1));
+assertEquals(Infinity, one / (one % one));
diff --git a/deps/v8/test/mjsunit/regress/regress-998565.js b/deps/v8/test/mjsunit/regress/regress-998565.js
new file mode 100644
index 0000000..260b791
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-998565.js
@@ -0,0 +1,51 @@
+// Copyright 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.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+listenerCalled = false;
+
+function listener(event, exec_state, event_data, data) {
+ listenerCalled = true;
+ throw 1;
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function f() {
+ a=1
+};
+
+// Set a break point and call to invoke the debug event listener.
+Debug.setBreakPoint(f, 0, 0);
+f();
+
+// Make sure that the debug event listener vas invoked.
+assertTrue(listenerCalled);
\ No newline at end of file
diff --git a/deps/v8/test/mjsunit/scanner.js b/deps/v8/test/mjsunit/scanner.js
new file mode 100644
index 0000000..516a4e8
--- /dev/null
+++ b/deps/v8/test/mjsunit/scanner.js
@@ -0,0 +1,30 @@
+// Copyright 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.
+
+// Tests that we check if escaped characters are valid indentifier
+// start characters.
+assertThrows('var \\u0030')
diff --git a/deps/v8/test/mjsunit/short-circuit-boolean.js b/deps/v8/test/mjsunit/short-circuit-boolean.js
new file mode 100644
index 0000000..df40c22
--- /dev/null
+++ b/deps/v8/test/mjsunit/short-circuit-boolean.js
@@ -0,0 +1,46 @@
+// 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.
+
+// Test some code paths through the compiler for short-circuited
+// boolean expressions.
+
+function andTest0() {
+  var a = 0;
+  // Left subexpression is known false at compile time.
+  return a != 0 && "failure";
+}
+
+assertFalse(andTest0());
+
+
+function orTest0() {
+  var a = 0;
+  // Left subexpression is known true at compile time.
+  return a == 0 || "failure";
+}
+
+assertTrue(orTest0());
diff --git a/deps/v8/test/mjsunit/smi-negative-zero.js b/deps/v8/test/mjsunit/smi-negative-zero.js
new file mode 100644
index 0000000..99ddc97
--- /dev/null
+++ b/deps/v8/test/mjsunit/smi-negative-zero.js
@@ -0,0 +1,100 @@
+// Copyright 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.
+
+// Ensure that operations on small integers handle -0.
+
+var zero = 0;
+var one = 1;
+var minus_one = -1;
+var two = 2;
+var four = 4;
+var minus_two = -2;
+var minus_four = -4;
+
+// variable op variable
+
+assertEquals(one / (-zero), -Infinity);
+
+assertEquals(one / (zero * minus_one), -Infinity);
+assertEquals(one / (minus_one * zero), -Infinity);
+assertEquals(one / (zero * zero), Infinity);
+assertEquals(one / (minus_one * minus_one), 1);
+
+assertEquals(one / (zero / minus_one), -Infinity);
+assertEquals(one / (zero / one), Infinity);
+
+assertEquals(one / (minus_four % two), -Infinity);
+assertEquals(one / (minus_four % minus_two), -Infinity);
+assertEquals(one / (four % two), Infinity);
+assertEquals(one / (four % minus_two), Infinity);
+
+// literal op variable
+
+assertEquals(one / (0 * minus_one), -Infinity);
+assertEquals(one / (-1 * zero), -Infinity);
+assertEquals(one / (0 * zero), Infinity);
+assertEquals(one / (-1 * minus_one), 1);
+
+assertEquals(one / (0 / minus_one), -Infinity);
+assertEquals(one / (0 / one), Infinity);
+
+assertEquals(one / (-4 % two), -Infinity);
+assertEquals(one / (-4 % minus_two), -Infinity);
+assertEquals(one / (4 % two), Infinity);
+assertEquals(one / (4 % minus_two), Infinity);
+
+// variable op literal
+
+assertEquals(one / (zero * -1), -Infinity);
+assertEquals(one / (minus_one * 0), -Infinity);
+assertEquals(one / (zero * 0), Infinity);
+assertEquals(one / (minus_one * -1), 1);
+
+assertEquals(one / (zero / -1), -Infinity);
+assertEquals(one / (zero / 1), Infinity);
+
+assertEquals(one / (minus_four % 2), -Infinity);
+assertEquals(one / (minus_four % -2), -Infinity);
+assertEquals(one / (four % 2), Infinity);
+assertEquals(one / (four % -2), Infinity);
+
+// literal op literal
+
+assertEquals(one / (-0), -Infinity);
+
+assertEquals(one / (0 * -1), -Infinity);
+assertEquals(one / (-1 * 0), -Infinity);
+assertEquals(one / (0 * 0), Infinity);
+assertEquals(one / (-1 * -1), 1);
+
+assertEquals(one / (0 / -1), -Infinity);
+assertEquals(one / (0 / 1), Infinity);
+
+assertEquals(one / (-4 % 2), -Infinity);
+assertEquals(one / (-4 % -2), -Infinity);
+assertEquals(one / (4 % 2), Infinity);
+assertEquals(one / (4 % -2), Infinity);
diff --git a/deps/v8/test/mjsunit/smi-ops.js b/deps/v8/test/mjsunit/smi-ops.js
new file mode 100644
index 0000000..bdd7509
--- /dev/null
+++ b/deps/v8/test/mjsunit/smi-ops.js
@@ -0,0 +1,102 @@
+// Copyright 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.
+
+const SMI_MAX = (1 << 30) - 1;
+const SMI_MIN = -(1 << 30);
+const ONE = 1;
+const ONE_HUNDRED = 100;
+
+const OBJ_42 = new (function() {
+  this.valueOf = function() { return 42; };
+})();
+
+assertEquals(42, OBJ_42.valueOf()); 
+
+
+function Add1(x) {
+  return x + 1;
+}
+
+function Add100(x) {
+  return x + 100;
+}
+
+function Add1Reversed(x) {
+  return 1 + x;
+}
+
+function Add100Reversed(x) {
+  return 100 + x;
+}
+
+
+assertEquals(1, Add1(0));  // fast case
+assertEquals(1, Add1Reversed(0));  // fast case
+assertEquals(SMI_MAX + ONE, Add1(SMI_MAX));  // overflow
+assertEquals(SMI_MAX + ONE, Add1Reversed(SMI_MAX));  // overflow
+assertEquals(42 + ONE, Add1(OBJ_42));  // non-smi
+assertEquals(42 + ONE, Add1Reversed(OBJ_42));  // non-smi
+
+assertEquals(100, Add100(0));  // fast case
+assertEquals(100, Add100Reversed(0));  // fast case
+assertEquals(SMI_MAX + ONE_HUNDRED, Add100(SMI_MAX));  // overflow
+assertEquals(SMI_MAX + ONE_HUNDRED, Add100Reversed(SMI_MAX));  // overflow
+assertEquals(42 + ONE_HUNDRED, Add100(OBJ_42));  // non-smi
+assertEquals(42 + ONE_HUNDRED, Add100Reversed(OBJ_42));  // non-smi
+
+
+
+function Sub1(x) {
+  return x - 1;
+}
+
+function Sub100(x) {
+  return x - 100;
+}
+
+function Sub1Reversed(x) {
+  return 1 - x;
+}
+
+function Sub100Reversed(x) {
+  return 100 - x;
+}
+
+
+assertEquals(0, Sub1(1));  // fast case
+assertEquals(-1, Sub1Reversed(2));  // fast case
+assertEquals(SMI_MIN - ONE, Sub1(SMI_MIN));  // overflow
+assertEquals(ONE - SMI_MIN, Sub1Reversed(SMI_MIN));  // overflow
+assertEquals(42 - ONE, Sub1(OBJ_42));  // non-smi
+assertEquals(ONE - 42, Sub1Reversed(OBJ_42));  // non-smi
+
+assertEquals(0, Sub100(100));  // fast case
+assertEquals(1, Sub100Reversed(99));  // fast case
+assertEquals(SMI_MIN - ONE_HUNDRED, Sub100(SMI_MIN));  // overflow
+assertEquals(ONE_HUNDRED - SMI_MIN, Sub100Reversed(SMI_MIN));  // overflow
+assertEquals(42 - ONE_HUNDRED, Sub100(OBJ_42));  // non-smi
+assertEquals(ONE_HUNDRED - 42, Sub100Reversed(OBJ_42));  // non-smi
diff --git a/deps/v8/test/mjsunit/sparse-array-reverse.js b/deps/v8/test/mjsunit/sparse-array-reverse.js
new file mode 100644
index 0000000..45a6da4
--- /dev/null
+++ b/deps/v8/test/mjsunit/sparse-array-reverse.js
@@ -0,0 +1,131 @@
+// Copyright 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.
+
+/**
+ * @fileoverview Test reverse on small * and large arrays.
+ */
+
+var VERYLARGE = 4000000000;
+
+// Nicer for firefox 1.5.  Unless you uncomment the following line,
+// smjs will appear to hang on this file.
+//var VERYLARGE = 40000;
+
+
+// Simple test of reverse on sparse array.
+var a = [];
+a.length = 2000;
+a[15] = 'a';
+a[30] = 'b';
+Array.prototype[30] = 'B';  // Should be hidden by a[30].
+a[40] = 'c';
+a[50] = 'deleted';
+delete a[50]; // Should leave no trace once deleted.
+a[1959] = 'd'; // Swapped with a[40] when reversing.
+a[1999] = 'e';
+assertEquals("abcde", a.join(''));
+a.reverse();
+delete Array.prototype[30];
+assertEquals("edcba", a.join(''));
+
+
+
+var seed = 43;
+
+// CONG pseudo random number generator.  Used for fuzzing the sparse array
+// reverse code.
+function DoOrDont() {
+  seed = (69069 * seed + 1234567) % 0x100000000;
+  return (seed & 0x100000) != 0;
+}
+
+var sizes = [140, 40000, VERYLARGE];
+var poses = [0, 10, 50, 69];
+
+
+// Fuzzing test of reverse on sparse array.
+for (var iterations = 0; iterations < 20; iterations++) {
+  for (var size_pos = 0; size_pos < sizes.length; size_pos++) {
+    var size = sizes[size_pos];
+
+    var to_delete = [];
+
+    var a;
+    // Make sure we test both array-backed and hash-table backed
+    // arrays.
+    if (size < 1000) {
+      a = new Array(size);
+    } else {
+      a = new Array();
+      a.length = size;
+    }
+
+    var expected = '';
+    var expected_reversed = '';
+
+    for (var pos_pos = 0; pos_pos < poses.length; pos_pos++) {
+      var pos = poses[pos_pos];
+      var letter = String.fromCharCode(97 + pos_pos);
+      if (DoOrDont()) {
+        a[pos] = letter;
+        expected += letter;
+        expected_reversed = letter + expected_reversed;
+      } else if (DoOrDont()) {
+        Array.prototype[pos] = letter;
+        expected += letter;
+        expected_reversed = letter + expected_reversed;
+        to_delete.push(pos);
+      }
+    }
+    var expected2 = '';
+    var expected_reversed2 = '';
+    for (var pos_pos = poses.length - 1; pos_pos >= 0; pos_pos--) {
+      var letter = String.fromCharCode(110 + pos_pos);
+      var pos = size - poses[pos_pos] - 1;
+      if (DoOrDont()) {
+        a[pos] = letter;
+        expected2 += letter;
+        expected_reversed2 = letter + expected_reversed2;
+      } else if (DoOrDont()) {
+        Array.prototype[pos] = letter;
+        expected2 += letter;
+        expected_reversed2 = letter + expected_reversed2;
+        to_delete.push(pos);
+      }
+    }
+
+    assertEquals(expected + expected2, a.join(''), 'join' + size);
+    a.reverse();
+
+    while (to_delete.length != 0) {
+      var pos = to_delete.pop();
+      delete(Array.prototype[pos]);
+    }
+
+    assertEquals(expected_reversed2 + expected_reversed, a.join(''), 'reverse then join' + size);
+  }
+}
diff --git a/deps/v8/test/mjsunit/sparse-array.js b/deps/v8/test/mjsunit/sparse-array.js
new file mode 100644
index 0000000..0952f2c
--- /dev/null
+++ b/deps/v8/test/mjsunit/sparse-array.js
@@ -0,0 +1,41 @@
+// Copyright 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.
+
+// Because of a bug in the heuristics used to figure out when to
+// convert a slow-case elements backing storage to fast case, the
+// following took a very long time.
+//
+// This test passes if it finishes almost immediately.
+for (var repetitions = 0; repetitions < 20; repetitions++) {
+  var stride = 500;
+  var array = [];
+  for (var i = 0; i < 1000; i++) {
+    array[i * stride] = i;
+  }
+}
+
+
diff --git a/deps/v8/test/mjsunit/str-to-num.js b/deps/v8/test/mjsunit/str-to-num.js
new file mode 100644
index 0000000..12a3716
--- /dev/null
+++ b/deps/v8/test/mjsunit/str-to-num.js
@@ -0,0 +1,158 @@
+// Copyright 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.
+
+function toNumber(val) {
+  return Number(val);
+}
+
+// assertEquals(, toNumber());
+
+
+assertEquals(123, toNumber(" 123"));
+assertEquals(123, toNumber("\n123"));
+assertEquals(123, toNumber("\r123"));
+assertEquals(123, toNumber("\t123"));
+assertEquals(123, toNumber("\f123"));
+
+assertEquals(123, toNumber("123 "));
+assertEquals(123, toNumber("123\n"));
+assertEquals(123, toNumber("123\r"));
+assertEquals(123, toNumber("123\t"));
+assertEquals(123, toNumber("123\f"));
+
+assertEquals(123, toNumber(" 123 "));
+assertEquals(123, toNumber("\n123\n"));
+assertEquals(123, toNumber("\r123\r"));
+assertEquals(123, toNumber("\t123\t"));
+assertEquals(123, toNumber("\f123\f"));
+
+assertTrue(isNaN(toNumber(" NaN ")));
+assertEquals(Infinity,  toNumber(" Infinity ") ," Infinity");
+assertEquals(-Infinity, toNumber(" -Infinity "));
+assertEquals(Infinity,  toNumber(" +Infinity "), " +Infinity");
+assertEquals(Infinity,  toNumber("Infinity ") ,"Infinity");
+assertEquals(-Infinity, toNumber("-Infinity "));
+assertEquals(Infinity,  toNumber("+Infinity "), "+Infinity");
+
+assertEquals(0,  toNumber("0"));
+assertEquals(0,  toNumber("+0"));
+assertEquals(-0, toNumber("-0"));
+
+assertEquals(1,  toNumber("1"));
+assertEquals(1,  toNumber("+1"));
+assertEquals(-1, toNumber("-1"));
+
+assertEquals(2,  toNumber("2"));
+assertEquals(2,  toNumber("+2"));
+assertEquals(-2, toNumber("-2"));
+
+assertEquals(3.1415926,  toNumber("3.1415926"));
+assertEquals(3.1415926,  toNumber("+3.1415926"));
+assertEquals(-3.1415926, toNumber("-3.1415926"));
+
+assertEquals(5,  toNumber("5."));
+assertEquals(5,  toNumber("+5."));
+assertEquals(-5, toNumber("-5."));
+
+assertEquals(500,   toNumber("5e2"));
+assertEquals(500,   toNumber("+5e2"));
+assertEquals(-500,  toNumber("-5e2"));
+assertEquals(500,   toNumber("5e+2"));
+assertEquals(500,   toNumber("+5e+2"));
+assertEquals(-500,  toNumber("-5e+2"));
+assertEquals(0.05,  toNumber("5e-2"));
+assertEquals(0.05,  toNumber("+5e-2"));
+assertEquals(-0.05, toNumber("-5e-2"));
+
+assertEquals(0.00001,   toNumber(".00001"));
+assertEquals(0.00001,   toNumber("+.00001"));
+assertEquals(-0.00001,  toNumber("-.00001"));
+assertEquals(1,         toNumber(".00001e5"));
+assertEquals(1,         toNumber("+.00001e5"));
+assertEquals(-1,        toNumber("-.00001e5"));
+assertEquals(1,         toNumber(".00001e+5"));
+assertEquals(1,         toNumber("+.00001e+5"));
+assertEquals(-1,        toNumber("-.00001e+5"));
+assertEquals(0.00001,   toNumber(".001e-2"));
+assertEquals(0.00001,   toNumber("+.001e-2"));
+assertEquals(-0.00001,  toNumber("-.001e-2"));
+
+assertEquals(12340000,   toNumber("1234e4"));
+assertEquals(12340000,   toNumber("+1234e4"));
+assertEquals(-12340000,  toNumber("-1234e4"));
+assertEquals(12340000,   toNumber("1234e+4"));
+assertEquals(12340000,   toNumber("+1234e+4"));
+assertEquals(-12340000,  toNumber("-1234e+4"));
+assertEquals(0.1234,     toNumber("1234e-4"));
+assertEquals(0.1234,     toNumber("+1234e-4"));
+assertEquals(-0.1234,    toNumber("-1234e-4"));
+
+assertEquals(0,  toNumber("0x0"));
+assertEquals(1,  toNumber("0x1"));
+assertEquals(2,  toNumber("0x2"));
+assertEquals(9,  toNumber("0x9"));
+assertEquals(10, toNumber("0xa"));
+assertEquals(11, toNumber("0xb"));
+assertEquals(15, toNumber("0xf"));
+assertEquals(10, toNumber("0xA"));
+assertEquals(11, toNumber("0xB"));
+assertEquals(15, toNumber("0xF"));
+
+assertEquals(0,  toNumber("0X0"));
+assertEquals(9,  toNumber("0X9"));
+assertEquals(10, toNumber("0Xa"));
+assertEquals(10, toNumber("0XA"));
+assertEquals(15, toNumber("0Xf"));
+assertEquals(15, toNumber("0XF"));
+
+assertEquals(0,  toNumber("0x000"));
+assertEquals(9,  toNumber("0x009"));
+assertEquals(10, toNumber("0x00a"));
+assertEquals(10, toNumber("0x00A"));
+assertEquals(15, toNumber("0x00f"));
+assertEquals(15, toNumber("0x00F"));
+
+assertEquals(0, toNumber("00"));
+assertEquals(1, toNumber("01"));
+assertEquals(2, toNumber("02"));
+assertEquals(10, toNumber("010"));
+assertEquals(100, toNumber("0100"));
+assertEquals(100, toNumber("000100"));
+
+assertEquals(Infinity,  toNumber("1e999"), "1e999");
+assertEquals(-Infinity, toNumber("-1e999"));
+assertEquals(0,         toNumber("1e-999"));
+assertEquals(0,         toNumber("-1e-999"));
+assertEquals(Infinity,  1 / toNumber("1e-999"), "1e-999");
+assertEquals(-Infinity, 1 / toNumber("-1e-999"));
+
+assertTrue(isNaN(toNumber("junk")), "junk");
+assertTrue(isNaN(toNumber("100 junk")), "100 junk");
+assertTrue(isNaN(toNumber("0x100 junk")), "0x100 junk");
+assertTrue(isNaN(toNumber("100.0 junk")), "100.0 junk");
+assertTrue(isNaN(toNumber(".1e4 junk")), ".1e4 junk");
+assertTrue(isNaN(toNumber("Infinity junk")), "Infinity junk");
diff --git a/deps/v8/test/mjsunit/stress-array-push.js b/deps/v8/test/mjsunit/stress-array-push.js
new file mode 100644
index 0000000..1db2e2a
--- /dev/null
+++ b/deps/v8/test/mjsunit/stress-array-push.js
@@ -0,0 +1,34 @@
+// Copyright 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.
+
+// Rewrite of mozilla_js_tests/js1_5/GC/regress-278725
+// to stress test pushing elements to an array.
+var results = [];
+for (var k = 0; k < 60000; k++) {
+  if ((k%10000) == 0) results.length = 0;
+  results.push({});
+}
diff --git a/deps/v8/test/mjsunit/strict-equals.js b/deps/v8/test/mjsunit/strict-equals.js
new file mode 100644
index 0000000..d080ce8
--- /dev/null
+++ b/deps/v8/test/mjsunit/strict-equals.js
@@ -0,0 +1,90 @@
+// Copyright 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.
+
+var n = null;
+var u = void 0;
+assertTrue(null === null);
+assertTrue(null === n);
+assertTrue(n === null);
+assertTrue(n === n);
+assertFalse(null === void 0);
+assertFalse(void 0 === null);
+assertFalse(u === null);
+assertFalse(null === u);
+assertFalse(n === u);
+assertFalse(u === n);
+assertTrue(void 0 === void 0);
+assertTrue(u === u);
+assertTrue(u === void 0);
+assertTrue(void 0 === u);
+
+assertTrue('foo' === 'foo');
+assertFalse('bar' === 'foo');
+assertFalse('foo' === new String('foo'));
+assertFalse(new String('foo') === new String('foo'));
+var s = new String('foo');
+assertTrue(s === s);
+assertFalse(s === null);
+assertFalse(s === void 0);
+assertFalse('foo' === null);
+assertFalse('foo' === 7);
+assertFalse('foo' === true);
+assertFalse('foo' === void 0);
+assertFalse('foo' === {});
+
+assertFalse({} === {});
+var x = {};
+assertTrue(x === x);
+assertFalse(x === null);
+assertFalse(x === 7);
+assertFalse(x === true);
+assertFalse(x === void 0);
+assertFalse(x === {});
+
+assertTrue(true === true);
+assertTrue(false === false);
+assertFalse(false === true);
+assertFalse(true === false);
+assertFalse(true === new Boolean(true));
+assertFalse(true === new Boolean(false));
+assertFalse(false === new Boolean(true));
+assertFalse(false === new Boolean(false));
+assertFalse(true === 0);
+assertFalse(true === 1);
+
+assertTrue(0 === 0);
+assertTrue(-0 === -0);
+assertTrue(-0 === 0);
+assertTrue(0 === -0);
+assertFalse(0 === new Number(0));
+assertFalse(1 === new Number(1));
+assertTrue(4.2 === 4.2);
+assertTrue(4.2 === Number(4.2));
+
+
+
+
diff --git a/deps/v8/test/mjsunit/string-add.js b/deps/v8/test/mjsunit/string-add.js
new file mode 100644
index 0000000..c42cf79
--- /dev/null
+++ b/deps/v8/test/mjsunit/string-add.js
@@ -0,0 +1,175 @@
+// 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.
+
+assertEquals("ab", "a" + "b", "ll");
+
+assertEquals("12", "1" + "2", "dd");
+assertEquals("123", "1" + "2" + "3", "ddd");
+assertEquals("123", 1 + "2" + "3", "ndd");
+assertEquals("123", "1" + 2 + "3", "dnd");
+assertEquals("123", "1" + "2" + 3, "ddn");
+
+assertEquals("123", "1" + 2 + 3, "dnn");
+assertEquals("123", 1 + "2" + 3, "ndn");
+assertEquals("33", 1 + 2 + "3", "nnd");
+
+var x = "1";
+assertEquals("12", x + 2, "vn");
+assertEquals("12", x + "2", "vd");
+assertEquals("21", 2 + x, "nv");
+assertEquals("21", "2" + x, "dv");
+
+var y = "2";
+assertEquals("12", x + y, "vdvd");
+
+x = 1;
+assertEquals("12", x + y, "vnvd");
+
+y = 2;
+assertEquals(3, x + y, "vnvn");
+
+x = "1";
+assertEquals("12", x + y, "vdvn");
+
+y = "2";
+assertEquals("12", x + y, "vdvd2");
+
+(function(x, y) {
+  var z = "3";
+  var w = "4";
+
+  assertEquals("11", x + x, "xx");
+  assertEquals("12", x + y, "xy");
+  assertEquals("13", x + z, "xz");
+  assertEquals("14", x + w, "xw");
+
+  assertEquals("21", y + x, "yx");
+  assertEquals("22", y + y, "yy");
+  assertEquals("23", y + z, "yz");
+  assertEquals("24", y + w, "yw");
+
+  assertEquals("31", z + x, "zx");
+  assertEquals("32", z + y, "zy");
+  assertEquals("33", z + z, "zz");
+  assertEquals("34", z + w, "zw");
+
+  assertEquals("41", w + x, "wx");
+  assertEquals("42", w + y, "wy");
+  assertEquals("43", w + z, "wz");
+  assertEquals("44", w + w, "ww");
+
+  (function(){x = 1; z = 3;})();
+
+  assertEquals(2, x + x, "x'x");
+  assertEquals("12", x + y, "x'y");
+  assertEquals(4, x + z, "x'z'");
+  assertEquals("14", x + w, "x'w");
+
+  assertEquals("21", y + x, "yx'");
+  assertEquals("22", y + y, "yy");
+  assertEquals("23", y + z, "yz'");
+  assertEquals("24", y + w, "yw");
+
+  assertEquals(4, z + x, "z'x'");
+  assertEquals("32", z + y, "z'y");
+  assertEquals(6, z + z, "z'z'");
+  assertEquals("34", z + w, "z'w");
+
+  assertEquals("41", w + x, "wx'");
+  assertEquals("42", w + y, "wy");
+  assertEquals("43", w + z, "wz'");
+  assertEquals("44", w + w, "ww");
+})("1", "2");
+
+assertEquals("142", "1" + new Number(42), "sN");
+assertEquals("421", new Number(42) + "1", "Ns");
+assertEquals(84, new Number(42) + new Number(42), "NN");
+
+assertEquals("142", "1" + new String("42"), "sS");
+assertEquals("421", new String("42") + "1", "Ss");
+assertEquals("142", "1" + new String("42"), "sS");
+assertEquals("4242", new String("42") + new String("42"), "SS");
+
+assertEquals("1true", "1" + true, "sb");
+assertEquals("true1", true + "1", "bs");
+assertEquals(2, true + true, "bs");
+
+assertEquals("1true", "1" + new Boolean(true), "sB");
+assertEquals("true1", new Boolean(true) + "1", "Bs");
+assertEquals(2, new Boolean(true) + new Boolean(true), "Bs");
+
+assertEquals("1undefined", "1" + void 0, "sv");
+assertEquals("undefined1", (void 0)  + "1", "vs");
+assertTrue(isNaN(void 0 + void 0), "vv");
+
+assertEquals("1null", "1" + null, "su");
+assertEquals("null1", null + "1", "us");
+assertEquals(0, null + null, "uu");
+
+(function (i) {
+  // Check that incoming frames are merged correctly.
+  var x;
+  var y;
+  var z;
+  var w;
+  switch (i) {
+  case 1: x = 42; y = "stry"; z = "strz"; w = 42; break;
+  default: x = "strx", y = 42; z = "strz"; w = 42; break;
+  }
+  var resxx = x + x;
+  var resxy = x + y;
+  var resxz = x + z;
+  var resxw = x + w;
+  var resyx = y + x;
+  var resyy = y + y;
+  var resyz = y + z;
+  var resyw = y + w;
+  var reszx = z + x;
+  var reszy = z + y;
+  var reszz = z + z;
+  var reszw = z + w;
+  var reswx = w + x;
+  var reswy = w + y;
+  var reswz = w + z;
+  var resww = w + w;
+  assertEquals(84, resxx, "swxx");
+  assertEquals("42stry", resxy, "swxy");
+  assertEquals("42strz", resxz, "swxz");
+  assertEquals(84, resxw, "swxw");
+  assertEquals("stry42", resyx, "swyx");
+  assertEquals("strystry", resyy, "swyy");
+  assertEquals("strystrz", resyz, "swyz");
+  assertEquals("stry42", resyw, "swyw");
+  assertEquals("strz42", reszx, "swzx");
+  assertEquals("strzstry", reszy, "swzy");
+  assertEquals("strzstrz", reszz, "swzz");
+  assertEquals("strz42", reszw, "swzw");
+  assertEquals(84, reswx, "swwx");
+  assertEquals("42stry", reswy, "swwy");
+  assertEquals("42strz", reswz, "swwz");
+  assertEquals(84, resww, "swww");
+})(1);
diff --git a/deps/v8/test/mjsunit/string-case.js b/deps/v8/test/mjsunit/string-case.js
new file mode 100644
index 0000000..13dcd3e
--- /dev/null
+++ b/deps/v8/test/mjsunit/string-case.js
@@ -0,0 +1,28 @@
+// Copyright 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.
+
+assertEquals("ΚΟΣΜΟΣ ΚΟΣΜΟΣ".toLowerCase(), "κοσμος κοσμος");
diff --git a/deps/v8/test/mjsunit/string-charat.js b/deps/v8/test/mjsunit/string-charat.js
new file mode 100644
index 0000000..8ec8f1e
--- /dev/null
+++ b/deps/v8/test/mjsunit/string-charat.js
@@ -0,0 +1,53 @@
+// Copyright 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.
+
+var s = "test";
+
+assertEquals("t", s.charAt());
+assertEquals("t", s.charAt("string"));
+assertEquals("t", s.charAt(null));
+assertEquals("t", s.charAt(void 0));
+assertEquals("t", s.charAt(false));
+assertEquals("e", s.charAt(true));
+assertEquals("", s.charAt(-1));
+assertEquals("", s.charAt(4));
+assertEquals("t", s.charAt(0));
+assertEquals("t", s.charAt(3));
+assertEquals("t", s.charAt(NaN));
+
+assertEquals(116, s.charCodeAt());
+assertEquals(116, s.charCodeAt("string"));
+assertEquals(116, s.charCodeAt(null));
+assertEquals(116, s.charCodeAt(void 0));
+assertEquals(116, s.charCodeAt(false));
+assertEquals(101, s.charCodeAt(true));
+assertEquals(116, s.charCodeAt(0));
+assertEquals(116, s.charCodeAt(3));
+assertEquals(116, s.charCodeAt(NaN));
+assertTrue(isNaN(s.charCodeAt(-1)));
+assertTrue(isNaN(s.charCodeAt(4)));
+
diff --git a/deps/v8/test/mjsunit/string-charcodeat.js b/deps/v8/test/mjsunit/string-charcodeat.js
new file mode 100644
index 0000000..f66dd3e
--- /dev/null
+++ b/deps/v8/test/mjsunit/string-charcodeat.js
@@ -0,0 +1,189 @@
+// Copyright 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.
+
+/**
+ * @fileoverview Check all sorts of borderline cases for charCodeAt.
+ */
+
+function Cons() {
+  return "Te" + "st";
+}
+
+
+function Deep() {
+  var a = "T";
+  a += "e";
+  a += "s";
+  a += "t";
+  return a;
+}
+
+
+function Slice() {
+  return "testing Testing".substring(8, 12);
+}
+
+
+function Flat() {
+  return "Test";
+}
+
+function Cons16() {
+  return "Te" + "\u1234t";
+}
+
+
+function Deep16() {
+  var a = "T";
+  a += "e";
+  a += "\u1234";
+  a += "t";
+  return a;
+}
+
+
+function Slice16Beginning() {
+  return "Te\u1234t test".substring(0, 4);
+}
+
+
+function Slice16Middle() {
+  return "test Te\u1234t test".substring(5, 9);
+}
+
+
+function Slice16End() {
+  return "test Te\u1234t".substring(5, 9);
+}
+
+
+function Flat16() {
+  return "Te\u1234t";
+}
+
+
+function Thing() {
+}
+
+
+function NotAString() {
+  var n = new Thing();
+  n.toString = function() { return "Test"; };
+  n.charCodeAt = String.prototype.charCodeAt;
+  return n;
+}
+
+
+function NotAString16() {
+  var n = new Thing();
+  n.toString = function() { return "Te\u1234t"; };
+  n.charCodeAt = String.prototype.charCodeAt;
+  return n;
+}
+
+
+function TestStringType(generator, sixteen) {
+  var g = generator;
+  assertTrue(isNaN(g().charCodeAt(-1e19)));
+  assertTrue(isNaN(g().charCodeAt(-0x80000001)));
+  assertTrue(isNaN(g().charCodeAt(-0x80000000)));
+  assertTrue(isNaN(g().charCodeAt(-0x40000000)));
+  assertTrue(isNaN(g().charCodeAt(-1)));
+  assertTrue(isNaN(g().charCodeAt(4)));
+  assertTrue(isNaN(g().charCodeAt(5)));
+  assertTrue(isNaN(g().charCodeAt(0x3fffffff)));
+  assertTrue(isNaN(g().charCodeAt(0x7fffffff)));
+  assertTrue(isNaN(g().charCodeAt(0x80000000)));
+  assertTrue(isNaN(g().charCodeAt(1e9)));
+  assertEquals(84, g().charCodeAt(0));
+  assertEquals(84, g().charCodeAt("test"));
+  assertEquals(84, g().charCodeAt(""));
+  assertEquals(84, g().charCodeAt(null));
+  assertEquals(84, g().charCodeAt(undefined));
+  assertEquals(84, g().charCodeAt());
+  assertEquals(84, g().charCodeAt(void 0));
+  assertEquals(84, g().charCodeAt(false));
+  assertEquals(101, g().charCodeAt(true));
+  assertEquals(101, g().charCodeAt(1));
+  assertEquals(sixteen ? 0x1234 : 115, g().charCodeAt(2));
+  assertEquals(116, g().charCodeAt(3));
+  assertEquals(101, g().charCodeAt(1.1));
+  assertEquals(sixteen ? 0x1234 : 115, g().charCodeAt(2.1718));
+  assertEquals(116, g().charCodeAt(3.14159));
+}
+
+
+TestStringType(Cons, false);
+TestStringType(Deep, false);
+TestStringType(Slice, false);
+TestStringType(Flat, false);
+TestStringType(NotAString, false);
+TestStringType(Cons16, true);
+TestStringType(Deep16, true);
+TestStringType(Slice16Beginning, true);
+TestStringType(Slice16Middle, true);
+TestStringType(Slice16End, true);
+TestStringType(Flat16, true);
+TestStringType(NotAString16, true);
+
+
+function StupidThing() {
+  // Doesn't return a string from toString!
+  this.toString = function() { return 42; }
+  this.charCodeAt = String.prototype.charCodeAt;
+}
+
+assertEquals(52, new StupidThing().charCodeAt(0));
+assertEquals(50, new StupidThing().charCodeAt(1));
+assertTrue(isNaN(new StupidThing().charCodeAt(2)));
+assertTrue(isNaN(new StupidThing().charCodeAt(-1)));
+
+
+// Medium (>255) and long (>65535) strings.
+
+var medium = "12345678";
+medium += medium; // 16.
+medium += medium; // 32.
+medium += medium; // 64.
+medium += medium; // 128.
+medium += medium; // 256.
+
+var long = medium;
+long += long + long + long;     // 1024.
+long += long + long + long;     // 4096.
+long += long + long + long;     // 16384.
+long += long + long + long;     // 65536.
+
+assertTrue(isNaN(medium.charCodeAt(-1)));
+assertEquals(49, medium.charCodeAt(0));
+assertEquals(56, medium.charCodeAt(255));
+assertTrue(isNaN(medium.charCodeAt(256)));
+
+assertTrue(isNaN(long.charCodeAt(-1)));
+assertEquals(49, long.charCodeAt(0));
+assertEquals(56, long.charCodeAt(65535));
+assertTrue(isNaN(long.charCodeAt(65536)));
diff --git a/deps/v8/test/mjsunit/string-compare-alignment.js b/deps/v8/test/mjsunit/string-compare-alignment.js
new file mode 100644
index 0000000..a291417
--- /dev/null
+++ b/deps/v8/test/mjsunit/string-compare-alignment.js
@@ -0,0 +1,47 @@
+// Copyright 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.
+
+// Test that we can compare two strings that are not 4-byte aligned.
+// This situation can arise with sliced strings.  This tests for an ARM bug
+// that was fixed in r554.
+
+var base = "Now is the time for all good men to come to the aid of the party. " + 
+           "Now is the time for all good men to come to the aid of the party."
+var s1 = base.substring(0, 64);
+var s2 = base.substring(66, 130);
+
+var o = new Object();
+o[s1] = 1;
+o[s2] = 2;
+
+var first_time = true;
+
+for (var x in o) {
+  assertTrue(o[x] == 2, "expect 2");
+  assertTrue(first_time, "once only");
+  first_time = false;
+}
diff --git a/deps/v8/test/mjsunit/string-flatten.js b/deps/v8/test/mjsunit/string-flatten.js
new file mode 100644
index 0000000..91877b2
--- /dev/null
+++ b/deps/v8/test/mjsunit/string-flatten.js
@@ -0,0 +1,37 @@
+// Copyright 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.
+
+// Check for regression of bug 1011505 (out of memory when flattening strings).
+var i;
+var s = "";
+
+for (i = 0; i < 1024; i++) {
+  s = s + (i + (i+1));
+  s = s.substring(1);
+}
+// Flatten the string.
+assertEquals(57, s.charCodeAt(0));
diff --git a/deps/v8/test/mjsunit/string-index.js b/deps/v8/test/mjsunit/string-index.js
new file mode 100644
index 0000000..2256286
--- /dev/null
+++ b/deps/v8/test/mjsunit/string-index.js
@@ -0,0 +1,154 @@
+// Copyright 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.
+
+/**
+ * @fileoverview Test indexing on strings with [].
+ */
+
+var foo = "Foo";
+assertEquals("Foo", foo);
+assertEquals("F", foo[0]);
+assertEquals("o", foo[1]);
+assertEquals("o", foo[2]);
+
+assertEquals("F", foo["0" + ""], "string index");
+assertEquals("o", foo["1"], "string index");
+assertEquals("o", foo["2"], "string index");
+
+assertEquals("undefined", typeof(foo[3]), "out of range");
+// SpiderMonkey 1.5 fails this next one.  So does FF 2.0.6.
+assertEquals("undefined", typeof(foo[-1]), "known failure in SpiderMonkey 1.5");
+assertEquals("undefined", typeof(foo[-2]), "negative index");
+
+foo[0] = "f";
+assertEquals("Foo", foo);
+
+foo[3] = "t";
+assertEquals("Foo", foo);
+assertEquals("undefined", typeof(foo[3]), "out of range");
+assertEquals("undefined", typeof(foo[-2]), "negative index");
+
+var S = new String("foo");
+assertEquals("foo", S);
+assertEquals("f", S[0], "string object");
+assertEquals("f", S["0"], "string object");
+S[0] = 'bente';
+assertEquals("f", S[0], "string object");
+assertEquals("f", S["0"], "string object");
+S[-2] = 'spider';
+assertEquals('spider', S[-2]);
+S[3] = 'monkey';
+assertEquals('monkey', S[3]);
+S['foo'] = 'Fu';
+assertEquals("Fu", S.foo);
+
+// In FF this is ignored I think.  In V8 it puts a property on the String object
+// but you won't ever see it because it is hidden by the 0th character in the
+// string.  The net effect is pretty much the same.
+S["0"] = 'bente';
+assertEquals("f", S[0], "string object");
+assertEquals("f", S["0"], "string object");
+
+assertEquals(true, 0 in S, "0 in");
+assertEquals(false, -1 in S, "-1 in");
+assertEquals(true, 2 in S, "2 in");
+assertEquals(true, 3 in S, "3 in");
+assertEquals(false, 4 in S, "3 in");
+
+assertEquals(true, "0" in S, '"0" in');
+assertEquals(false, "-1" in S, '"-1" in');
+assertEquals(true, "2" in S, '"2" in');
+assertEquals(true, "3" in S, '"3" in');
+assertEquals(false, "4" in S, '"3" in');
+
+assertEquals(true, S.hasOwnProperty(0), "0 hasOwnProperty");
+assertEquals(false, S.hasOwnProperty(-1), "-1 hasOwnProperty");
+assertEquals(true, S.hasOwnProperty(2), "2 hasOwnProperty");
+assertEquals(true, S.hasOwnProperty(3), "3 hasOwnProperty");
+assertEquals(false, S.hasOwnProperty(4), "3 hasOwnProperty");
+
+assertEquals(true, S.hasOwnProperty("0"), '"0" hasOwnProperty');
+assertEquals(false, S.hasOwnProperty("-1"), '"-1" hasOwnProperty');
+assertEquals(true, S.hasOwnProperty("2"), '"2" hasOwnProperty');
+assertEquals(true, S.hasOwnProperty("3"), '"3" hasOwnProperty');
+assertEquals(false, S.hasOwnProperty("4"), '"3" hasOwnProperty');
+
+assertEquals(true, "foo".hasOwnProperty(0), "foo 0 hasOwnProperty");
+assertEquals(false, "foo".hasOwnProperty(-1), "foo -1 hasOwnProperty");
+assertEquals(true, "foo".hasOwnProperty(2), "foo 2 hasOwnProperty");
+assertEquals(false, "foo".hasOwnProperty(4), "foo 3 hasOwnProperty");
+
+assertEquals(true, "foo".hasOwnProperty("0"), 'foo "0" hasOwnProperty');
+assertEquals(false, "foo".hasOwnProperty("-1"), 'foo "-1" hasOwnProperty');
+assertEquals(true, "foo".hasOwnProperty("2"), 'foo "2" hasOwnProperty');
+assertEquals(false, "foo".hasOwnProperty("4"), 'foo "3" hasOwnProperty');
+
+//assertEquals(true, 0 in "foo", "0 in");
+//assertEquals(false, -1 in "foo", "-1 in");
+//assertEquals(true, 2 in "foo", "2 in");
+//assertEquals(false, 3 in "foo", "3 in");
+//
+//assertEquals(true, "0" in "foo", '"0" in');
+//assertEquals(false, "-1" in "foo", '"-1" in');
+//assertEquals(true, "2" in "foo", '"2" in');
+//assertEquals(false, "3" in "foo", '"3" in');
+
+delete S[3];
+assertEquals("undefined", typeof(S[3]));
+assertEquals(false, 3 in S);
+assertEquals(false, "3" in S);
+
+var N = new Number(43);
+assertEquals(43, N);
+N[-2] = "Alpha";
+assertEquals("Alpha", N[-2]);
+N[0] = "Zappa";
+assertEquals("Zappa", N[0]);
+assertEquals("Zappa", N["0"]);
+
+var A = ["V", "e", "t", "t", "e", "r"];
+var A2 = (A[0] = "v");
+assertEquals('v', A[0]);
+assertEquals('v', A2);
+
+var S = new String("Onkel");
+var S2 = (S[0] = 'o');
+assertEquals('O', S[0]);
+assertEquals('o', S2);
+
+var s = "Tante";
+var s2 = (s[0] = 't');
+assertEquals('T', s[0]);
+assertEquals('t', s2);
+
+var S2 = (S[-2] = 'o');
+assertEquals('o', S[-2]);
+assertEquals('o', S2);
+
+var s2 = (s[-2] = 't');
+assertEquals('undefined', typeof(s[-2]));
+assertEquals('t', s2);
diff --git a/deps/v8/test/mjsunit/string-indexof.js b/deps/v8/test/mjsunit/string-indexof.js
new file mode 100644
index 0000000..2018da7
--- /dev/null
+++ b/deps/v8/test/mjsunit/string-indexof.js
@@ -0,0 +1,142 @@
+// Copyright 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.
+
+var s = "test test test";
+
+assertEquals(0, s.indexOf("t"));
+assertEquals(3, s.indexOf("t", 1));
+assertEquals(5, s.indexOf("t", 4));
+assertEquals(1, s.indexOf("e"));
+assertEquals(2, s.indexOf("s"));
+
+assertEquals(5, s.indexOf("test", 4));
+assertEquals(5, s.indexOf("test", 5));
+assertEquals(10, s.indexOf("test", 6));
+assertEquals(0, s.indexOf("test", 0));
+assertEquals(0, s.indexOf("test", -1));
+assertEquals(0, s.indexOf("test"));
+assertEquals(-1, s.indexOf("notpresent"));
+assertEquals(-1, s.indexOf());
+
+for (var i = 0; i < s.length+10; i++) {
+  var expected = i < s.length ? i : s.length;
+  assertEquals(expected, s.indexOf("", i));
+}
+
+var reString = "asdf[a-z]+(asdf)?";
+
+assertEquals(4, reString.indexOf("[a-z]+"));
+assertEquals(10, reString.indexOf("(asdf)?"));
+
+assertEquals(1, String.prototype.indexOf.length);
+
+// Random greek letters
+var twoByteString = "\u039a\u0391\u03a3\u03a3\u0395";
+
+// Test single char pattern
+assertEquals(0, twoByteString.indexOf("\u039a"), "Lamda");
+assertEquals(1, twoByteString.indexOf("\u0391"), "Alpha");
+assertEquals(2, twoByteString.indexOf("\u03a3"), "First Sigma");
+assertEquals(3, twoByteString.indexOf("\u03a3",3), "Second Sigma");
+assertEquals(4, twoByteString.indexOf("\u0395"), "Epsilon");
+assertEquals(-1, twoByteString.indexOf("\u0392"), "Not beta");  
+
+// Test multi-char pattern
+assertEquals(0, twoByteString.indexOf("\u039a\u0391"), "lambda Alpha");
+assertEquals(1, twoByteString.indexOf("\u0391\u03a3"), "Alpha Sigma");
+assertEquals(2, twoByteString.indexOf("\u03a3\u03a3"), "Sigma Sigma");
+assertEquals(3, twoByteString.indexOf("\u03a3\u0395"), "Sigma Epsilon");
+
+assertEquals(-1, twoByteString.indexOf("\u0391\u03a3\u0395"), 
+    "Not Alpha Sigma Epsilon");
+
+//single char pattern
+assertEquals(4, twoByteString.indexOf("\u0395"));
+
+// Test complex string indexOf algorithms. Only trigger for long strings.
+
+// Long string that isn't a simple repeat of a shorter string.
+var long = "A";
+for(var i = 66; i < 76; i++) {  // from 'B' to 'K'
+  long =  long + String.fromCharCode(i) + long;
+}
+
+// pattern of 15 chars, repeated every 16 chars in long
+var pattern = "ABACABADABACABA";
+for(var i = 0; i < long.length - pattern.length; i+= 7) {
+  var index = long.indexOf(pattern, i);
+  assertEquals((i + 15) & ~0xf, index, "Long ABACABA...-string at index " + i);
+}
+assertEquals(510, long.indexOf("AJABACA"), "Long AJABACA, First J");
+assertEquals(1534, long.indexOf("AJABACA", 511), "Long AJABACA, Second J");
+
+pattern = "JABACABADABACABA";
+assertEquals(511, long.indexOf(pattern), "Long JABACABA..., First J");
+assertEquals(1535, long.indexOf(pattern, 512), "Long JABACABA..., Second J");
+
+
+var lipsum = "lorem ipsum per se esse fugiendum. itaque aiunt hanc quasi "
+    + "naturalem atque insitam in animis nostris inesse notionem, ut "
+    + "alterum esse appetendum, alterum aspernandum sentiamus. Alii autem,"
+    + " quibus ego assentior, cum a philosophis compluribus permulta "
+    + "dicantur, cur nec voluptas in bonis sit numeranda nec in malis "
+    + "dolor, non existimant oportere nimium nos causae confidere, sed et"
+    + " argumentandum et accurate disserendum et rationibus conquisitis de"
+    + " voluptate et dolore disputandum putant.\n"
+    + "Sed ut perspiciatis, unde omnis iste natus error sit voluptatem "
+    + "accusantium doloremque laudantium, totam rem aperiam eaque ipsa,"
+    + "quae ab illo inventore veritatis et quasi architecto beatae vitae "
+    + "dicta sunt, explicabo. nemo enim ipsam voluptatem, quia voluptas"
+    + "sit, aspernatur aut odit aut fugit, sed quia consequuntur magni"
+    + " dolores eos, qui ratione voluptatem sequi nesciunt, neque porro"
+    + " quisquam est, qui dolorem ipsum, quia dolor sit, amet, "
+    + "consectetur, adipisci velit, sed quia non numquam eius modi"
+    + " tempora incidunt, ut labore et dolore magnam aliquam quaerat "
+    + "voluptatem. ut enim ad minima veniam, quis nostrum exercitationem "
+    + "ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi "
+    + "consequatur? quis autem vel eum iure reprehenderit, qui in ea "
+    + "voluptate velit esse, quam nihil molestiae consequatur, vel illum, "
+    + "qui dolorem eum fugiat, quo voluptas nulla pariatur?\n";
+
+assertEquals(893, lipsum.indexOf("lorem ipsum, quia dolor sit, amet"),
+        "Lipsum");
+// test a lot of substrings of differing length and start-position.
+for(var i = 0; i < lipsum.length; i += 3) {
+  for(var len = 1; i + len < lipsum.length; len += 7) {
+    var substring = lipsum.substring(i, i + len);
+    var index = -1;
+    do {
+      index = lipsum.indexOf(substring, index + 1);
+      assertTrue(index != -1, 
+                 "Lipsum substring " + i + ".." + (i + len-1) + " not found");
+      assertEquals(lipsum.substring(index, index + len), substring, 
+          "Wrong lipsum substring found: " + i + ".." + (i + len - 1) + "/" + 
+              index + ".." + (index + len - 1));
+    } while (index >= 0 && index < i);
+    assertEquals(i, index, "Lipsum match at " + i + ".." + (i + len - 1));
+  }
+}
diff --git a/deps/v8/test/mjsunit/string-lastindexof.js b/deps/v8/test/mjsunit/string-lastindexof.js
new file mode 100644
index 0000000..bf46666
--- /dev/null
+++ b/deps/v8/test/mjsunit/string-lastindexof.js
@@ -0,0 +1,51 @@
+// Copyright 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.
+
+var s = "test test test";
+
+assertEquals(5, s.lastIndexOf("test", 5));
+assertEquals(5, s.lastIndexOf("test", 6));
+assertEquals(0, s.lastIndexOf("test", 4));
+assertEquals(0, s.lastIndexOf("test", 0));
+assertEquals(-1, s.lastIndexOf("test", -1));
+assertEquals(10, s.lastIndexOf("test"));
+assertEquals(-1, s.lastIndexOf("notpresent"));
+assertEquals(-1, s.lastIndexOf());
+assertEquals(10, s.lastIndexOf("test", "not a number"));
+
+for (var i = s.length + 10; i >= 0; i--) {
+  var expected = i < s.length ? i : s.length;
+  assertEquals(expected, s.lastIndexOf("", i));
+}
+
+
+var reString = "asdf[a-z]+(asdf)?";
+
+assertEquals(4, reString.lastIndexOf("[a-z]+"));
+assertEquals(10, reString.lastIndexOf("(asdf)?"));
+
+assertEquals(1, String.prototype.lastIndexOf.length);
diff --git a/deps/v8/test/mjsunit/string-localecompare.js b/deps/v8/test/mjsunit/string-localecompare.js
new file mode 100644
index 0000000..90a1813
--- /dev/null
+++ b/deps/v8/test/mjsunit/string-localecompare.js
@@ -0,0 +1,40 @@
+// Copyright 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.
+
+// String.prototype.localeCompare.
+//
+// Implementation dependent function.  For now, we do not do anything
+// locale specific.
+
+// Equal prefix.
+assertTrue("asdf".localeCompare("asdf") == 0);
+assertTrue("asd".localeCompare("asdf") < 0);
+assertTrue("asdff".localeCompare("asdf") > 0);
+
+// Chars differ.
+assertTrue("asdf".localeCompare("asdq") < 0);
+assertTrue("asdq".localeCompare("asdf") > 0);
diff --git a/deps/v8/test/mjsunit/string-match.js b/deps/v8/test/mjsunit/string-match.js
new file mode 100644
index 0000000..202396d
--- /dev/null
+++ b/deps/v8/test/mjsunit/string-match.js
@@ -0,0 +1,149 @@
+// 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.
+
+/**
+ * @fileoverview Test String.prototype.match
+ */
+
+
+function testMatch(name, input, regexp, result, captures, from, to) {
+  var matchResult = input.match(regexp);
+  assertEquals(result, matchResult, name + "-match");
+
+  var match = input.substring(from, to);
+  var preMatch = input.substring(0, from);
+  var postMatch = input.substring(to);
+  var lastParen = captures.length > 0 ? captures[captures.length - 1] : "";
+
+  if (regexp.global) {
+    // Returns array of matched strings.
+    var lastMatch = matchResult[matchResult.length - 1];
+    assertEquals(match, lastMatch, name + "-match-string_g");
+  } else {
+    // Returns array of match and captures.
+    assertEquals(match, matchResult[0], name + "-match-string");
+    assertEquals(captures.length + 1, matchResult.length, name + "-cap-return");
+    for (var i = 1; i < matchResult.length; i++) {
+      assertEquals(captures[i - 1], matchResult[i], name + "-cap-return-" + i);
+    }
+  }
+
+  assertEquals(match, RegExp["$&"], name + "-$&");
+  assertEquals(match, RegExp.lastMatch, name + "-lastMatch");
+
+  assertEquals(undefined, RegExp.$0, name + "-nocapture-10");
+  for (var i = 1; i <= 9; i++) {
+    if (i <= captures.length) {
+      assertEquals(captures[i - 1], RegExp["$" + i], name + "-capture-" + i);
+    } else {
+      assertEquals("", RegExp["$" + i], name + "-nocapture-" + i);
+    }
+  }
+  assertEquals(undefined, RegExp.$10, name + "-nocapture-10");
+
+  assertEquals(input, RegExp.input, name + "-input");
+  assertEquals(input, RegExp.$input, name + "-$input");
+  assertEquals(input, RegExp.$_, name + "-$_");
+
+  assertEquals(preMatch, RegExp["$`"], name + "-$`");
+  assertEquals(preMatch, RegExp.leftContext, name + "-leftContex");
+
+  assertEquals(postMatch, RegExp["$'"], name + "-$'");
+  assertEquals(postMatch, RegExp.rightContext, name + "-rightContex");
+
+  assertEquals(lastParen, RegExp["$+"], name + "-$+");
+  assertEquals(lastParen, RegExp.lastParen, name + "-lastParen");
+
+}
+
+
+var stringSample = "A man, a plan, a canal: Panama";
+var stringSample2 = "Argle bargle glop glyf!";
+var stringSample3 = "abcdefghijxxxxxxxxxx";
+
+
+// Non-capturing, non-global regexp.
+
+var re_nog = /\w+/;
+
+testMatch("Nonglobal", stringSample, re_nog,
+          ["A"],
+          [], 0, 1);
+
+
+re_nog.lastIndex = 2;
+
+testMatch("Nonglobal-ignore-lastIndex", stringSample, re_nog,
+          ["A"],
+          [], 0, 1);
+
+
+// Capturing non-global regexp.
+
+var re_multicap = /(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)/;
+testMatch("Capture-Nonglobal", stringSample3, re_multicap,
+          ["abcdefghij", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j"],
+          ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"], 0, 10);
+
+
+// Global regexp (also check that capture from before are cleared)
+
+var re = /\w+/g;
+testMatch("Global", stringSample2, re,
+          ["Argle", "bargle", "glop", "glyf"], [], 18, 22);
+
+re.lastIndex = 10;
+
+testMatch("Global-ignore-lastIndex", stringSample2, re,
+          ["Argle", "bargle", "glop", "glyf"], [], 18, 22);
+
+
+// Capturing global regexp
+
+var re_cap = /\w(\w*)/g;
+
+testMatch("Capture-Global", stringSample, re_cap,
+          ["A", "man", "a", "plan", "a", "canal", "Panama"],
+          ["anama"], 24, 30);
+
+
+// Atom, non-global
+
+var re_atom = /an/;
+
+testMatch("Atom", stringSample, re_atom,
+          ["an"],
+          [], 3, 5);
+
+
+// Atom, global
+
+var re_atomg = /an/g;
+
+testMatch("Global-Atom", stringSample, re_atomg,
+          ["an", "an", "an", "an"],
+          [], 25, 27);
diff --git a/deps/v8/test/mjsunit/string-replace-gc.js b/deps/v8/test/mjsunit/string-replace-gc.js
new file mode 100644
index 0000000..26fba10
--- /dev/null
+++ b/deps/v8/test/mjsunit/string-replace-gc.js
@@ -0,0 +1,57 @@
+// 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.
+
+// Flags: --always-compact
+//
+// Regression test for the r1512 fix.
+
+var foo = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+
+foo = foo + foo;
+foo = foo + foo;
+foo = foo + foo;
+foo = foo + foo;
+foo = foo + foo;
+foo = foo + foo;
+foo = foo + foo;
+foo = foo + foo;
+foo = foo + foo;
+foo = foo + foo;
+foo = foo + foo;
+foo = foo + foo;
+foo = foo + foo;
+foo = foo + foo;
+foo = foo + foo;
+
+foo.replace(/[b]/, "c");  // Flatten foo.
+
+var moving_string = "b" + "c";
+
+var bar = foo.replace(/[a]/g, moving_string);
+
+print(bar.length);
+
diff --git a/deps/v8/test/mjsunit/string-replace.js b/deps/v8/test/mjsunit/string-replace.js
new file mode 100644
index 0000000..d72f73b
--- /dev/null
+++ b/deps/v8/test/mjsunit/string-replace.js
@@ -0,0 +1,182 @@
+// 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.
+
+/**
+ * @fileoverview Test String.prototype.replace
+ */
+
+function replaceTest(result, subject, pattern, replacement) {
+  var name = 
+    "\"" + subject + "\".replace(" + pattern + ", " + replacement + ")";
+  assertEquals(result, subject.replace(pattern, replacement), name);
+}
+
+
+var short = "xaxbxcx";
+
+replaceTest("axbxcx", short, "x", "");
+replaceTest("axbxcx", short, /x/, "");
+replaceTest("abc", short, /x/g, "");
+
+replaceTest("xaxxcx", short, "b", "");
+replaceTest("xaxxcx", short, /b/, "");
+replaceTest("xaxxcx", short, /b/g, "");
+
+
+replaceTest("[]axbxcx", short, "x", "[]");
+replaceTest("[]axbxcx", short, /x/, "[]");
+replaceTest("[]a[]b[]c[]", short, /x/g, "[]");
+
+replaceTest("xax[]xcx", short, "b", "[]");
+replaceTest("xax[]xcx", short, /b/, "[]");
+replaceTest("xax[]xcx", short, /b/g, "[]");
+
+
+replaceTest("[$]axbxcx", short, "x", "[$$]");
+replaceTest("[$]axbxcx", short, /x/, "[$$]");
+replaceTest("[$]a[$]b[$]c[$]", short, /x/g, "[$$]");
+
+replaceTest("xax[$]xcx", short, "b", "[$$]");
+replaceTest("xax[$]xcx", short, /b/, "[$$]");
+replaceTest("xax[$]xcx", short, /b/g, "[$$]");
+
+
+replaceTest("[]axbxcx", short, "x", "[$`]");
+replaceTest("[]axbxcx", short, /x/, "[$`]");
+replaceTest("[]a[xa]b[xaxb]c[xaxbxc]", short, /x/g, "[$`]");
+
+replaceTest("xax[xax]xcx", short, "b", "[$`]");
+replaceTest("xax[xax]xcx", short, /b/, "[$`]");
+replaceTest("xax[xax]xcx", short, /b/g, "[$`]");
+
+
+replaceTest("[x]axbxcx", short, "x", "[$&]");
+replaceTest("[x]axbxcx", short, /x/, "[$&]");
+replaceTest("[x]a[x]b[x]c[x]", short, /x/g, "[$&]");
+
+replaceTest("xax[b]xcx", short, "b", "[$&]");
+replaceTest("xax[b]xcx", short, /b/, "[$&]");
+replaceTest("xax[b]xcx", short, /b/g, "[$&]");
+
+
+replaceTest("[axbxcx]axbxcx", short, "x", "[$']");
+replaceTest("[axbxcx]axbxcx", short, /x/, "[$']");
+replaceTest("[axbxcx]a[bxcx]b[cx]c[]", short, /x/g, "[$']");
+
+replaceTest("xax[xcx]xcx", short, "b", "[$']");
+replaceTest("xax[xcx]xcx", short, /b/, "[$']");
+replaceTest("xax[xcx]xcx", short, /b/g, "[$']");
+
+
+replaceTest("[$1]axbxcx", short, "x", "[$1]");
+replaceTest("[$1]axbxcx", short, /x/, "[$1]");
+replaceTest("[]axbxcx", short, /x()/, "[$1]");
+replaceTest("[$1]a[$1]b[$1]c[$1]", short, /x/g, "[$1]");
+replaceTest("[]a[]b[]c[]", short, /x()/g, "[$1]");
+
+replaceTest("xax[$1]xcx", short, "b", "[$1]");
+replaceTest("xax[$1]xcx", short, /b/, "[$1]");
+replaceTest("xax[]xcx", short, /b()/, "[$1]");
+replaceTest("xax[$1]xcx", short, /b/g, "[$1]");
+replaceTest("xax[]xcx", short, /b()/g, "[$1]");
+
+// Bug 317 look-alikes. If "$e" has no meaning, the "$" must be retained.
+replaceTest("xax$excx", short, "b", "$e");
+replaceTest("xax$excx", short, /b/, "$e");
+replaceTest("xax$excx", short, /b/g, "$e");
+
+replaceTest("xaxe$xcx", short, "b", "e$");
+replaceTest("xaxe$xcx", short, /b/, "e$");
+replaceTest("xaxe$xcx", short, /b/g, "e$");
+
+
+replaceTest("[$$$1$$a1abb1bb0$002$3$03][$$$1$$b1bcc1cc0$002$3$03]c", 
+            "abc", /(.)(?=(.))/g, "[$$$$$$1$$$$$11$01$2$21$02$020$002$3$03]"); 
+
+// Replace with functions.
+
+
+var ctr = 0;
+replaceTest("0axbxcx", short, "x", function r(m, i, s) {
+  assertEquals(3, arguments.length, "replace('x',func) func-args");
+  assertEquals("x", m, "replace('x',func(m,..))");
+  assertEquals(0, i, "replace('x',func(..,i,..))");
+  assertEquals(short, s, "replace('x',func(..,s))");
+  return String(ctr++);
+});
+assertEquals(1, ctr, "replace('x',func) num-match");
+
+ctr = 0;
+replaceTest("0axbxcx", short, /x/, function r(m, i, s) {
+  assertEquals(3, arguments.length, "replace(/x/,func) func-args");
+  assertEquals("x", m, "replace(/x/,func(m,..))");
+  assertEquals(0, i, "replace(/x/,func(..,i,..))");
+  assertEquals(short, s, "replace(/x/,func(..,s))");
+  return String(ctr++);
+});
+assertEquals(1, ctr, "replace(/x/,func) num-match");
+
+ctr = 0;
+replaceTest("0a1b2c3", short, /x/g, function r(m, i, s) {
+  assertEquals(3, arguments.length, "replace(/x/g,func) func-args");
+  assertEquals("x", m, "replace(/x/g,func(m,..))");
+  assertEquals(ctr * 2, i, "replace(/x/g,func(..,i,.))");
+  assertEquals(short, s, "replace(/x/g,func(..,s))");
+  return String(ctr++);
+});
+assertEquals(4, ctr, "replace(/x/g,func) num-match");
+
+ctr = 0;
+replaceTest("0a1b2cx", short, /(x)(?=(.))/g, function r(m, c1, c2, i, s) {
+  assertEquals(5, arguments.length, "replace(/(x)(?=(.))/g,func) func-args");
+  assertEquals("x", m, "replace(/(x)(?=(.))/g,func(m,..))");
+  assertEquals("x", c1, "replace(/(x)(?=(.))/g,func(..,c1,..))");
+  assertEquals(["a","b","c"][ctr], c2, "replace(/(x)(?=(.))/g,func(..,c2,..))");
+  assertEquals(ctr * 2, i, "replace(/(x)(?=(.))/g,func(..,i,..))");
+  assertEquals(short, s, "replace(/(x)(?=(.))/g,func(..,s))");
+  return String(ctr++);
+});
+assertEquals(3, ctr, "replace(/x/g,func) num-match");
+
+
+// Test special cases of replacement parts longer than 1<<11.
+var longstring = "xyzzy";
+longstring = longstring + longstring;
+longstring = longstring + longstring;
+longstring = longstring + longstring;
+longstring = longstring + longstring;
+longstring = longstring + longstring;
+longstring = longstring + longstring;
+longstring = longstring + longstring;
+longstring = longstring + longstring;
+longstring = longstring + longstring;
+longstring = longstring + longstring;
+longstring = longstring + longstring;
+// longstring.length == 5 << 11
+
+replaceTest(longstring + longstring, 
+            "<" + longstring + ">", /<(.*)>/g, "$1$1");
diff --git a/deps/v8/test/mjsunit/string-search.js b/deps/v8/test/mjsunit/string-search.js
new file mode 100644
index 0000000..36891c2
--- /dev/null
+++ b/deps/v8/test/mjsunit/string-search.js
@@ -0,0 +1,30 @@
+// Copyright 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.
+
+var str="ABC abc";
+var r = str.search('a');
+assertEquals(r, 4);
diff --git a/deps/v8/test/mjsunit/string-split.js b/deps/v8/test/mjsunit/string-split.js
new file mode 100644
index 0000000..59d3ad3
--- /dev/null
+++ b/deps/v8/test/mjsunit/string-split.js
@@ -0,0 +1,126 @@
+// Copyright 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.
+
+expected = ["A", undefined, "B", "bold", "/", "B", "and", undefined, "CODE", "coded", "/", "CODE", ""];
+result = "A<B>bold</B>and<CODE>coded</CODE>".split(/<(\/)?([^<>]+)>/);
+assertArrayEquals(expected, result, 1);
+
+expected = ["a", "b"];
+result = "ab".split(/a*?/);
+assertArrayEquals(expected, result, 2);
+
+expected = ["", "b"];
+result = "ab".split(/a*/);
+assertArrayEquals(expected, result, 3);
+
+expected = ["a"];
+result = "ab".split(/a*?/, 1);
+assertArrayEquals(expected, result, 4);
+
+expected = [""];
+result = "ab".split(/a*/, 1);
+assertArrayEquals(expected, result, 5);
+
+expected = ["as","fas","fas","f"];
+result = "asdfasdfasdf".split("d");
+assertArrayEquals(expected, result, 6);
+
+expected = ["as","fas","fas","f"];
+result = "asdfasdfasdf".split("d", -1);
+assertArrayEquals(expected, result, 7);
+
+expected = ["as", "fas"];
+result = "asdfasdfasdf".split("d", 2);
+assertArrayEquals(expected, result, 8);
+
+expected = [];
+result = "asdfasdfasdf".split("d", 0);
+assertArrayEquals(expected, result, 9);
+
+expected = ["as","fas","fas",""];
+result = "asdfasdfasd".split("d");
+assertArrayEquals(expected, result, 10);
+
+expected = [];
+result = "".split("");
+assertArrayEquals(expected, result, 11);
+
+expected = [""]
+result = "".split("a");
+assertArrayEquals(expected, result, 12);
+
+expected = ["a","b"]
+result = "axxb".split(/x*/);
+assertArrayEquals(expected, result, 13);
+
+expected = ["a","b"]
+result = "axxb".split(/x+/);
+assertArrayEquals(expected, result, 14);
+
+expected = ["a","","b"]
+result = "axxb".split(/x/);
+assertArrayEquals(expected, result, 15);
+
+// This was http://b/issue?id=1151354
+expected = ["div", "#id", ".class"]
+result = "div#id.class".split(/(?=[#.])/);
+assertArrayEquals(expected, result, 16);
+
+expected = ["div", "#i", "d", ".class"]
+result = "div#id.class".split(/(?=[d#.])/);
+assertArrayEquals(expected, result, 17);
+
+expected = ["a", "b", "c"]
+result = "abc".split(/(?=.)/);
+assertArrayEquals(expected, result, 18);
+
+/* "ab".split(/((?=.))/)
+ * 
+ * KJS:   ,a,,b
+ * SM:    a,,b,
+ * IE:    a,b
+ * Opera: a,,b
+ * V8:    a,,b
+ * 
+ * Opera seems to have this right.  The others make no sense.
+ */
+expected = ["a", "", "b"]
+result = "ab".split(/((?=.))/);
+assertArrayEquals(expected, result, 19);
+
+/* "ab".split(/(?=)/)
+ *
+ * KJS:   a,b
+ * SM:    ab
+ * IE:    a,b
+ * Opera: a,b
+ * V8:    a,b
+ */
+expected = ["a", "b"]
+result = "ab".split(/(?=)/);
+assertArrayEquals(expected, result, 20);
+
diff --git a/deps/v8/test/mjsunit/substr.js b/deps/v8/test/mjsunit/substr.js
new file mode 100644
index 0000000..8c276f9
--- /dev/null
+++ b/deps/v8/test/mjsunit/substr.js
@@ -0,0 +1,65 @@
+// Copyright 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.
+
+var s = 'abcdefghijklmn';
+assertEquals(s, s.substr());
+assertEquals(s, s.substr(0));
+assertEquals(s, s.substr('0'));
+assertEquals(s, s.substr(void 0));
+assertEquals(s, s.substr(null));
+assertEquals(s, s.substr(false));
+assertEquals(s, s.substr(0.9));
+assertEquals(s, s.substr({ valueOf: function() { return 0; } }));
+assertEquals(s, s.substr({ toString: function() { return '0'; } }));
+
+var s1 = s.substring(1);
+assertEquals(s1, s.substr(1));
+assertEquals(s1, s.substr('1'));
+assertEquals(s1, s.substr(true));
+assertEquals(s1, s.substr(1.1));
+assertEquals(s1, s.substr({ valueOf: function() { return 1; } }));
+assertEquals(s1, s.substr({ toString: function() { return '1'; } }));
+
+for (var i = 0; i < s.length; i++)
+  for (var j = i; j < s.length + 5; j++)
+    assertEquals(s.substring(i, j), s.substr(i, j - i));
+
+assertEquals(s.substring(s.length - 1), s.substr(-1));
+assertEquals(s.substring(s.length - 1), s.substr(-1.2));
+assertEquals(s.substring(s.length - 1), s.substr(-1.7));
+assertEquals(s.substring(s.length - 2), s.substr(-2));
+assertEquals(s.substring(s.length - 2), s.substr(-2.3));
+assertEquals(s.substring(s.length - 2, s.length - 1), s.substr(-2, 1));
+assertEquals(s, s.substr(-100));
+assertEquals('abc', s.substr(-100, 3));
+assertEquals(s1, s.substr(-s.length + 1));
+
+// assertEquals('', s.substr(0, void 0)); // smjs and rhino 
+assertEquals('abcdefghijklmn', s.substr(0, void 0));  // kjs and v8
+assertEquals('', s.substr(0, null));
+assertEquals(s, s.substr(0, String(s.length)));
+assertEquals('a', s.substr(0, true));
diff --git a/deps/v8/test/mjsunit/switch.js b/deps/v8/test/mjsunit/switch.js
new file mode 100644
index 0000000..4044490
--- /dev/null
+++ b/deps/v8/test/mjsunit/switch.js
@@ -0,0 +1,289 @@
+// Copyright 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.
+
+function f0() {
+  switch (0) {
+    // switch deliberately left empty
+  }
+}
+
+f0();  // no errors
+
+function f1(x) {
+  switch (x) {
+    default:      return "f1";
+  }
+  return "foo";
+}
+
+assertEquals("f1", f1(0), "default-switch.0");
+assertEquals("f1", f1(1), "default-switch.1");
+
+function f2(x) {
+  var r;
+  switch (x) {
+    case 0:
+      r = "zero";
+      break;
+    case 1:
+      r = "one";
+      break;
+    case 2:
+      r = "two";
+      break;
+    case 3:
+      r = "three";
+      break;
+    default:
+      r = "default";
+  }
+  return r;
+}
+
+assertEquals("zero", f2(0), "0-1-switch.0");
+assertEquals("one", f2(1), "0-1-switch.1");
+assertEquals("default", f2(7), "0-1-switch.2");
+assertEquals("default", f2(-1), "0-1-switch.-1");
+assertEquals("default", f2(NaN), "0-1-switch.NaN");
+assertEquals("default", f2(Math.pow(2,34)), "0-1-switch.largeNum");
+assertEquals("default", f2("0"), "0-1-switch.string");
+assertEquals("default", f2(false), "0-1-switch.bool");
+assertEquals("default", f2(null), "0-1-switch.null");
+assertEquals("default", f2(undefined), "0-1-switch.undef");
+assertEquals("default", f2(new Number(2)), "0-1-switch.undef");
+assertEquals("default", f2({valueOf: function(){return 2; }}), "0-1-switch.obj");
+
+
+function f3(x, c) {
+  var r = 0;
+  switch (x) {
+    default:
+      r = "default";
+      break;
+    case  c:
+      r = "value is c = " + c;
+      break;
+    case  2:
+      r = "two";
+      break;
+    case -5:
+      r = "minus 5";
+      break;
+    case  9:
+      r = "nine";
+      break;
+  }
+  return r;
+}
+
+assertEquals("two", f3(2,0), "value-switch.2-0");
+assertEquals("minus 5", f3(-5,0), "value-switch.-5-0");
+assertEquals("nine", f3(9,0), "value-switch.9-0");
+assertEquals("value is c = 0", f3(0,0), "value-switch.0-0");
+assertEquals("value is c = 2", f3(2,2), "value-switch.2-2");
+assertEquals("default", f3(7,0), "value-switch.7-0");
+
+
+function f4(x) {
+  switch(x) {
+    case 0:
+      x++;
+    default:
+      x++;
+    case 2:
+      x++;
+  }
+  return x;
+}
+
+
+assertEquals(3, f4(0), "fallthrough-switch.0");
+assertEquals(3, f4(1), "fallthrough-switch.1");
+assertEquals(3, f4(2), "fallthrough-switch.2");
+assertEquals(5, f4(3), "fallthrough-switch.3");
+
+
+function f5(x) {
+  switch(x) {
+     case -2: return true;
+     case -1: return false;
+     case 0: return true;
+     case 2: return false;
+     default: return 42;
+  }
+}
+
+assertTrue(f5(-2), "negcase.-2");
+assertFalse(f5(-1), "negcase.-1");
+assertTrue(f5(0), "negcase.-0");
+assertEquals(42, f5(1), "negcase.1");
+assertFalse(f5(2), "negcase.2");
+
+function f6(N) {
+  // long enough case that code buffer grows during code-generation
+  var res = 0;
+  for(var i = 0; i < N; i++) {
+    switch(i & 0x3f) {
+    case 0: res += 0; break;
+    case 1: res += 1; break;
+    case 2: res += 2; break;
+    case 3: res += 3; break;
+    case 4: res += 4; break;
+    case 5: res += 5; break;
+    case 6: res += 6; break;
+    case 7: res += 7; break;
+    case 8: res += 8; break;
+    case 9: res += 9; break;
+    case 10: res += 10; break;
+    case 11: res += 11; break;
+    case 12: res += 12; break;
+    case 13: res += 13; break;
+    case 14: res += 14; break;
+    case 15: res += 15; break;
+    case 16: res += 16; break;
+    case 17: res += 17; break;
+    case 18: res += 18; break;
+    case 19: res += 19; break;
+    case 20: res += 20; break;
+    case 21: res += 21; break;
+    case 22: res += 22; break;
+    case 23: res += 23; break;
+    case 24: res += 24; break;
+    case 25: res += 25; break;
+    case 26: res += 26; break;
+    case 27: res += 27; break;
+    case 28: res += 28; break;
+    case 29: res += 29; break;
+    case 30: res += 30; break;
+    case 31: res += 31; break;
+    case 32: res += 32; break;
+    case 33: res += 33; break;
+    case 34: res += 34; break;
+    case 35: res += 35; break;
+    case 36: res += 36; break;
+    case 37: res += 37; break;
+    case 38: res += 38; break;
+    case 39: res += 39; break;
+    case 40: res += 40; break;
+    case 41: res += 41; break;
+    case 42: res += 42; break;
+    case 43: res += 43; break;
+    case 44: res += 44; break;
+    case 45: res += 45; break;
+    case 46: res += 46; break;
+    case 47: res += 47; break;
+    case 48: res += 48; break;
+    case 49: res += 49; break;
+    case 50: res += 50; break;
+    case 51: res += 51; break;
+    case 52: res += 52; break;
+    case 53: res += 53; break;
+    case 54: res += 54; break;
+    case 55: res += 55; break;
+    case 56: res += 56; break;
+    case 57: res += 57; break;
+    case 58: res += 58; break;
+    case 59: res += 59; break;
+    case 60: res += 60; break;
+    case 61: res += 61; break;
+    case 62: res += 62; break;
+    case 63: res += 63; break;
+    case 64: break;
+    default: break;
+    }
+  }
+  return res;
+}
+
+assertEquals(190, f6(20), "largeSwitch.20");
+assertEquals(2016, f6(64), "largeSwitch.64");
+assertEquals(4032, f6(128), "largeSwitch.128");
+assertEquals(4222, f6(148), "largeSwitch.148");
+
+
+function f7(value) {
+  switch (value) {
+  case 0: return "0";
+  case -0: return "-0";
+  case 1: case 2: case 3: case 4:  // Dummy fillers.
+  }
+  switch (value) {
+  case 0x3fffffff: return "MaxSmi";
+  case 0x3ffffffe:
+  case 0x3ffffffd:
+  case 0x3ffffffc:
+  case 0x3ffffffb:
+  case 0x3ffffffa:  // Dummy fillers
+  }
+  switch (value) {
+  case -0x40000000: return "MinSmi";
+  case -0x3fffffff:
+  case -0x3ffffffe:
+  case -0x3ffffffd:
+  case -0x3ffffffc:
+  case -0x3ffffffb:  // Dummy fillers
+  }
+  switch (value) {
+  case 10: return "A";
+  case 11:
+  case 12:
+  case 13:
+  case 14:
+  case 15:  // Dummy fillers
+  }
+  return "default";
+}
+
+
+assertEquals("default", f7(0.1), "0-1-switch.double-0.1");
+assertEquals("0", f7(-0), "0-1-switch.double-neg0");
+assertEquals("MaxSmi", f7((1<<30)-1), "0-1-switch.maxsmi");
+assertEquals("MinSmi", f7(-(1<<30)), "0-1-switch.minsmi");
+assertEquals("default", f7(1<<30), "0-1-switch.maxsmi++");
+assertEquals("default", f7(-(1<<30)-1), "0-1-switch.minsmi--");
+assertEquals("A", f7((170/16)-(170%16/16)), "0-1-switch.heapnum");
+
+
+function makeVeryLong(length) {
+  var res = "function() {\n" +
+            "  var res = 0;\n" +
+            "  for (var i = 0; i <= " + length + "; i++) {\n" +
+            "    switch(i) {\n";
+  for (var i = 0; i < length; i++) {
+    res += "    case " + i + ": res += 2; break;\n";
+  }
+  res += "    default: res += 1;\n" +
+         "    }\n" +
+         "  }\n" +
+         "  return res;\n" +
+         "}";
+  return eval(res);
+}
+var verylong_size = 1000;
+var verylong = makeVeryLong(verylong_size);
+
+assertEquals(verylong_size * 2 + 1, verylong());
diff --git a/deps/v8/test/mjsunit/testcfg.py b/deps/v8/test/mjsunit/testcfg.py
new file mode 100644
index 0000000..9c7e028
--- /dev/null
+++ b/deps/v8/test/mjsunit/testcfg.py
@@ -0,0 +1,106 @@
+# Copyright 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.
+
+import test
+import os
+from os.path import join, dirname, exists
+import re
+
+
+FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)")
+FILES_PATTERN = re.compile(r"//\s+Files:(.*)")
+
+
+class MjsunitTestCase(test.TestCase):
+
+  def __init__(self, path, file, mode, context, config):
+    super(MjsunitTestCase, self).__init__(context, path)
+    self.file = file
+    self.config = config
+    self.mode = mode
+
+  def GetLabel(self):
+    return "%s %s" % (self.mode, self.GetName())
+
+  def GetName(self):
+    return self.path[-1]
+
+  def GetCommand(self):
+    result = [self.config.context.GetVm(self.mode)]
+    source = open(self.file).read()
+    flags_match = FLAGS_PATTERN.search(source)
+    if flags_match:
+      result += flags_match.group(1).strip().split()
+    files_match = FILES_PATTERN.search(source);
+    additional_files = []
+    if files_match:
+      additional_files += files_match.group(1).strip().split()
+    for a_file in additional_files:
+      result.append(join(dirname(self.config.root), '..', a_file))
+    framework = join(dirname(self.config.root), 'mjsunit', 'mjsunit.js')
+    result += [framework, self.file]
+    return result
+
+  def GetSource(self):
+    return open(self.file).read()
+
+
+class MjsunitTestConfiguration(test.TestConfiguration):
+
+  def __init__(self, context, root):
+    super(MjsunitTestConfiguration, self).__init__(context, root)
+
+  def Ls(self, path):
+    def SelectTest(name):
+      return name.endswith('.js') and name != 'mjsunit.js'
+    return [f[:-3] for f in os.listdir(path) if SelectTest(f)]
+
+  def ListTests(self, current_path, path, mode):
+    mjsunit = [current_path + [t] for t in self.Ls(self.root)]
+    regress = [current_path + ['regress', t] for t in self.Ls(join(self.root, 'regress'))]
+    bugs = [current_path + ['bugs', t] for t in self.Ls(join(self.root, 'bugs'))]
+    tools = [current_path + ['tools', t] for t in self.Ls(join(self.root, 'tools'))]
+    all_tests = mjsunit + regress + bugs + tools
+    result = []
+    for test in all_tests:
+      if self.Contains(path, test):
+        file_path = join(self.root, reduce(join, test[1:], "") + ".js")
+        result.append(MjsunitTestCase(test, file_path, mode, self.context, self))
+    return result
+
+  def GetBuildRequirements(self):
+    return ['sample', 'sample=shell']
+
+  def GetTestStatus(self, sections, defs):
+    status_file = join(self.root, 'mjsunit.status')
+    if exists(status_file):
+      test.ReadConfigurationInto(status_file, sections, defs)
+
+
+
+def GetConfiguration(context, root):
+  return MjsunitTestConfiguration(context, root)
diff --git a/deps/v8/test/mjsunit/this-in-callbacks.js b/deps/v8/test/mjsunit/this-in-callbacks.js
new file mode 100644
index 0000000..d50be6c
--- /dev/null
+++ b/deps/v8/test/mjsunit/this-in-callbacks.js
@@ -0,0 +1,47 @@
+// Copyright 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.
+
+// Test 'this' is the right global object of callback functions passed to
+// builtin functions.
+// See bug 1231592
+
+var my_identity = 'id';
+// test Array.sort
+function cp(x, y) {
+  assertEquals('id', this.my_identity);
+  return 0;
+}
+
+[1, 2].sort(cp);
+
+// test String.replace
+function r(x) {
+  return this.my_identity;
+}
+
+assertEquals('id', 'hello'.replace('hello', r));
+assertEquals('id', 'hello'.replace(/hello/, r));
diff --git a/deps/v8/test/mjsunit/this.js b/deps/v8/test/mjsunit/this.js
new file mode 100644
index 0000000..890dea4
--- /dev/null
+++ b/deps/v8/test/mjsunit/this.js
@@ -0,0 +1,46 @@
+// Copyright 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.
+
+function f() { return this; }
+
+assertFalse(this == null);  // the global object shouldn't be null or undefined
+assertEquals('[object global]', String(this));
+
+assertTrue(this === this);
+assertTrue(this === (function() { return this; })());
+assertTrue(this === f());
+
+var x = {}, y = {};
+x.f = y.f = f;
+assertFalse(x === f());
+assertFalse(y === f());
+assertTrue(x === x.f());
+assertTrue(x === x[new String('f')]());
+assertTrue(y === y.f(), "y.f()");
+assertTrue(y === y[new String('f')]());
+assertFalse(x === y.f());
+assertFalse(y === x.f());
diff --git a/deps/v8/test/mjsunit/throw-and-catch-function.js b/deps/v8/test/mjsunit/throw-and-catch-function.js
new file mode 100644
index 0000000..fd24f6e
--- /dev/null
+++ b/deps/v8/test/mjsunit/throw-and-catch-function.js
@@ -0,0 +1,50 @@
+// Copyright 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.
+
+var g = this;
+var x = new Object();
+x.e = function() { return this; };
+try {
+  throw x.e;
+} catch (e) {
+  assertTrue(e() === g);
+}
+try {
+  throw x.e;
+} catch (e) {
+  with(x) { assertTrue(e() === x); }
+}
+with(x) {
+  try { throw e; } catch (e) { assertTrue(e() === g); }
+}
+var e = 0;
+try {
+  throw x.e;
+} catch (e) {
+  var e = 7;
+}
+assertEquals(0, e);
diff --git a/deps/v8/test/mjsunit/throw-exception-for-null-access.js b/deps/v8/test/mjsunit/throw-exception-for-null-access.js
new file mode 100644
index 0000000..018cfef
--- /dev/null
+++ b/deps/v8/test/mjsunit/throw-exception-for-null-access.js
@@ -0,0 +1,37 @@
+// Copyright 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.
+
+// Must throw TypeError when accessing properties of null.
+var caught = false
+try {
+  null[0];
+  assertTrue(false);
+} catch (e) {
+  caught = true;
+  assertTrue(e instanceof TypeError);
+}
+assertTrue(caught);
diff --git a/deps/v8/test/mjsunit/to-precision.js b/deps/v8/test/mjsunit/to-precision.js
new file mode 100644
index 0000000..04c7d76
--- /dev/null
+++ b/deps/v8/test/mjsunit/to-precision.js
@@ -0,0 +1,82 @@
+// Copyright 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.
+
+// Test the exponential notation output.
+assertEquals("1e+27", (1.2345e+27).toPrecision(1));
+assertEquals("1.2e+27", (1.2345e+27).toPrecision(2));
+assertEquals("1.23e+27", (1.2345e+27).toPrecision(3));
+assertEquals("1.234e+27", (1.2345e+27).toPrecision(4));
+assertEquals("1.2345e+27", (1.2345e+27).toPrecision(5));
+assertEquals("1.23450e+27", (1.2345e+27).toPrecision(6));
+assertEquals("1.234500e+27", (1.2345e+27).toPrecision(7));
+
+assertEquals("-1e+27", (-1.2345e+27).toPrecision(1));
+assertEquals("-1.2e+27", (-1.2345e+27).toPrecision(2));
+assertEquals("-1.23e+27", (-1.2345e+27).toPrecision(3));
+assertEquals("-1.234e+27", (-1.2345e+27).toPrecision(4));
+assertEquals("-1.2345e+27", (-1.2345e+27).toPrecision(5));
+assertEquals("-1.23450e+27", (-1.2345e+27).toPrecision(6));
+assertEquals("-1.234500e+27", (-1.2345e+27).toPrecision(7));
+
+
+// Test the fixed notation output.
+assertEquals("7", (7).toPrecision(1));
+assertEquals("7.0", (7).toPrecision(2));
+assertEquals("7.00", (7).toPrecision(3));
+
+assertEquals("-7", (-7).toPrecision(1));
+assertEquals("-7.0", (-7).toPrecision(2));
+assertEquals("-7.00", (-7).toPrecision(3));
+
+assertEquals("9e+1", (91).toPrecision(1));
+assertEquals("91", (91).toPrecision(2));
+assertEquals("91.0", (91).toPrecision(3));
+assertEquals("91.00", (91).toPrecision(4));
+
+assertEquals("-9e+1", (-91).toPrecision(1));
+assertEquals("-91", (-91).toPrecision(2));
+assertEquals("-91.0", (-91).toPrecision(3));
+assertEquals("-91.00", (-91).toPrecision(4));
+
+assertEquals("9e+1", (91.1234).toPrecision(1));
+assertEquals("91", (91.1234).toPrecision(2));
+assertEquals("91.1", (91.1234).toPrecision(3));
+assertEquals("91.12", (91.1234).toPrecision(4));
+assertEquals("91.123", (91.1234).toPrecision(5));
+assertEquals("91.1234", (91.1234).toPrecision(6));
+assertEquals("91.12340", (91.1234).toPrecision(7));
+assertEquals("91.123400", (91.1234).toPrecision(8));
+
+assertEquals("-9e+1", (-91.1234).toPrecision(1));
+assertEquals("-91", (-91.1234).toPrecision(2));
+assertEquals("-91.1", (-91.1234).toPrecision(3));
+assertEquals("-91.12", (-91.1234).toPrecision(4));
+assertEquals("-91.123", (-91.1234).toPrecision(5));
+assertEquals("-91.1234", (-91.1234).toPrecision(6));
+assertEquals("-91.12340", (-91.1234).toPrecision(7));
+assertEquals("-91.123400", (-91.1234).toPrecision(8));
+
diff --git a/deps/v8/test/mjsunit/tobool.js b/deps/v8/test/mjsunit/tobool.js
new file mode 100644
index 0000000..65bffb6
--- /dev/null
+++ b/deps/v8/test/mjsunit/tobool.js
@@ -0,0 +1,36 @@
+// Copyright 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.
+
+// All objects, including wrappers, must convert to true.
+assertTrue(!!new Boolean(true), "new Boolean(true)");
+assertTrue(!!new Boolean(false), "new Boolean(false)");
+
+assertTrue(!!new Number(-1), "new Number(-1)");
+assertTrue(!!new Number(0), "new Number(0)");
+assertTrue(!!new Number(1), "new Number(1)");
+
+
diff --git a/deps/v8/test/mjsunit/toint32.js b/deps/v8/test/mjsunit/toint32.js
new file mode 100644
index 0000000..a558295
--- /dev/null
+++ b/deps/v8/test/mjsunit/toint32.js
@@ -0,0 +1,129 @@
+// Copyright 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.
+
+function toInt32(x) {
+  return x | 0;
+}
+
+assertEquals(0, toInt32(Infinity));
+assertEquals(0, toInt32(-Infinity));
+assertEquals(0, toInt32(NaN));
+assertEquals(0, toInt32(0.0));
+assertEquals(0, toInt32(-0.0));
+
+assertEquals(0, toInt32(Number.MIN_VALUE));
+assertEquals(0, toInt32(-Number.MIN_VALUE));
+assertEquals(0, toInt32(0.1));
+assertEquals(0, toInt32(-0.1));
+assertEquals(1, toInt32(1));
+assertEquals(1, toInt32(1.1));
+assertEquals(-1, toInt32(-1));
+assertEquals(0, toInt32(0.6), "truncate positive (0.6)");
+assertEquals(1, toInt32(1.6), "truncate positive (1.6)");
+assertEquals(0, toInt32(-0.6), "truncate negative (-0.6)");
+assertEquals(-1, toInt32(-1.6), "truncate negative (-1.6)");
+
+assertEquals(2147483647, toInt32(2147483647));
+assertEquals(-2147483648, toInt32(2147483648));
+assertEquals(-2147483647, toInt32(2147483649));
+
+assertEquals(-1, toInt32(4294967295));
+assertEquals(0, toInt32(4294967296));
+assertEquals(1, toInt32(4294967297));
+
+assertEquals(-2147483647, toInt32(-2147483647));
+assertEquals(-2147483648, toInt32(-2147483648));
+assertEquals(2147483647, toInt32(-2147483649));
+
+assertEquals(1, toInt32(-4294967295));
+assertEquals(0, toInt32(-4294967296));
+assertEquals(-1, toInt32(-4294967297));
+
+assertEquals(-2147483648, toInt32(2147483648.25));
+assertEquals(-2147483648, toInt32(2147483648.5));
+assertEquals(-2147483648, toInt32(2147483648.75));
+assertEquals(-1, toInt32(4294967295.25));
+assertEquals(-1, toInt32(4294967295.5));
+assertEquals(-1, toInt32(4294967295.75));
+assertEquals(-1294967296, toInt32(3000000000.25));
+assertEquals(-1294967296, toInt32(3000000000.5));
+assertEquals(-1294967296, toInt32(3000000000.75));
+
+assertEquals(-2147483648, toInt32(-2147483648.25));
+assertEquals(-2147483648, toInt32(-2147483648.5));
+assertEquals(-2147483648, toInt32(-2147483648.75));
+assertEquals(1, toInt32(-4294967295.25));
+assertEquals(1, toInt32(-4294967295.5));
+assertEquals(1, toInt32(-4294967295.75));
+assertEquals(1294967296, toInt32(-3000000000.25));
+assertEquals(1294967296, toInt32(-3000000000.5));
+assertEquals(1294967296, toInt32(-3000000000.75));
+
+var base = Math.pow(2, 64);
+assertEquals(0, toInt32(base + 0));
+assertEquals(0, toInt32(base + 1117));
+assertEquals(4096, toInt32(base + 2234));
+assertEquals(4096, toInt32(base + 3351));
+assertEquals(4096, toInt32(base + 4468));
+assertEquals(4096, toInt32(base + 5585));
+assertEquals(8192, toInt32(base + 6702));
+assertEquals(8192, toInt32(base + 7819));
+assertEquals(8192, toInt32(base + 8936));
+assertEquals(8192, toInt32(base + 10053));
+assertEquals(12288, toInt32(base + 11170));
+assertEquals(12288, toInt32(base + 12287));
+assertEquals(12288, toInt32(base + 13404));
+assertEquals(16384, toInt32(base + 14521));
+assertEquals(16384, toInt32(base + 15638));
+assertEquals(16384, toInt32(base + 16755));
+assertEquals(16384, toInt32(base + 17872));
+assertEquals(20480, toInt32(base + 18989));
+assertEquals(20480, toInt32(base + 20106));
+assertEquals(20480, toInt32(base + 21223));
+assertEquals(20480, toInt32(base + 22340));
+assertEquals(24576, toInt32(base + 23457));
+assertEquals(24576, toInt32(base + 24574));
+assertEquals(24576, toInt32(base + 25691));
+assertEquals(28672, toInt32(base + 26808));
+assertEquals(28672, toInt32(base + 27925));
+assertEquals(28672, toInt32(base + 29042));
+assertEquals(28672, toInt32(base + 30159));
+assertEquals(32768, toInt32(base + 31276));
+
+// bignum is (2^53 - 1) * 2^31 - highest number with bit 31 set.
+var bignum = Math.pow(2, 84) - Math.pow(2, 31);
+assertEquals(-Math.pow(2,31), toInt32(bignum));
+assertEquals(-Math.pow(2,31), toInt32(-bignum));
+assertEquals(0, toInt32(2 * bignum));
+assertEquals(0, toInt32(-(2 * bignum)));
+assertEquals(0, toInt32(bignum - Math.pow(2,31)));
+assertEquals(0, toInt32(-(bignum - Math.pow(2,31))));
+
+// max_fraction is largest number below 1.
+var max_fraction = (1 - Math.pow(2,-53));
+assertEquals(0, toInt32(max_fraction));
+assertEquals(0, toInt32(-max_fraction));
diff --git a/deps/v8/test/mjsunit/tools/splaytree.js b/deps/v8/test/mjsunit/tools/splaytree.js
new file mode 100644
index 0000000..3beba0b
--- /dev/null
+++ b/deps/v8/test/mjsunit/tools/splaytree.js
@@ -0,0 +1,166 @@
+// 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.
+
+// Load the Splay tree implementation from <project root>/tools.
+// Files: tools/splaytree.js
+
+
+(function testIsEmpty() {
+  var tree = new goog.structs.SplayTree();
+  assertTrue(tree.isEmpty());
+  tree.insert(0, 'value');
+  assertFalse(tree.isEmpty());
+})();
+
+
+(function testExportValues() {
+  var tree = new goog.structs.SplayTree();
+  assertArrayEquals([], tree.exportValues());
+  tree.insert(0, 'value');
+  assertArrayEquals(['value'], tree.exportValues());
+  tree.insert(0, 'value');
+  assertArrayEquals(['value'], tree.exportValues());
+})();
+
+
+function createSampleTree() {
+  // Creates the following tree:
+  //           50
+  //          /  \
+  //         30  60
+  //        /  \   \
+  //       10  40  90
+  //         \    /  \
+  //         20  70 100
+  //        /      \
+  //       15      80
+  //
+  // We can't use the 'insert' method because it also uses 'splay_'.
+  return { key: 50, value: 50,
+      left: { key: 30, value: 30,
+              left: { key: 10, value: 10, left: null,
+                      right: { key: 20, value: 20,
+                               left: { key: 15, value: 15,
+                                       left: null, right: null },
+                               right: null } },
+              right: { key: 40, value: 40, left: null, right: null } },
+      right: { key: 60, value: 60, left: null,
+               right: { key: 90, value: 90,
+                        left: { key: 70, value: 70, left: null,
+                                right: { key: 80, value: 80,
+                                         left: null, right: null } },
+                        right: { key: 100, value: 100,
+                                 left: null, right: null } } } };
+};
+
+
+(function testSplay() {
+  var tree = new goog.structs.SplayTree();
+  tree.root_ = createSampleTree();
+  assertArrayEquals(['50', '30', '60', '10', '40', '90', '20', '70', '100', '15', '80'],
+                    tree.exportValues());
+  tree.splay_(50);
+  assertArrayEquals(['50', '30', '60', '10', '40', '90', '20', '70', '100', '15', '80'],
+                    tree.exportValues());
+  tree.splay_(80);
+  assertArrayEquals(['80', '60', '90', '50', '70', '100', '30', '10', '40', '20', '15'],
+                    tree.exportValues());
+})();
+
+
+(function testInsert() {
+  var tree = new goog.structs.SplayTree();
+  tree.insert(5, 'root');
+  tree.insert(3, 'left');
+  assertArrayEquals(['left', 'root'], tree.exportValues());
+  tree.insert(7, 'right');
+  assertArrayEquals(['right', 'root', 'left'], tree.exportValues());
+})();
+
+
+(function testFind() {
+  var tree = new goog.structs.SplayTree();
+  tree.insert(5, 'root');
+  tree.insert(3, 'left');
+  tree.insert(7, 'right');
+  assertEquals('root', tree.find(5).value);
+  assertEquals('left', tree.find(3).value);
+  assertEquals('right', tree.find(7).value);
+  assertEquals(null, tree.find(0));
+  assertEquals(null, tree.find(100));
+  assertEquals(null, tree.find(-100));
+})();
+
+
+(function testFindMin() {
+  var tree = new goog.structs.SplayTree();
+  assertEquals(null, tree.findMin());
+  tree.insert(5, 'root');
+  tree.insert(3, 'left');
+  tree.insert(7, 'right');
+  assertEquals('left', tree.findMin().value);
+})();
+
+
+(function testFindMax() {
+  var tree = new goog.structs.SplayTree();
+  assertEquals(null, tree.findMax());
+  tree.insert(5, 'root');
+  tree.insert(3, 'left');
+  tree.insert(7, 'right');
+  assertEquals('right', tree.findMax().value);
+})();
+
+
+(function testFindGreatestLessThan() {
+  var tree = new goog.structs.SplayTree();
+  assertEquals(null, tree.findGreatestLessThan(10));
+  tree.insert(5, 'root');
+  tree.insert(3, 'left');
+  tree.insert(7, 'right');
+  assertEquals('right', tree.findGreatestLessThan(10).value);
+  assertEquals('right', tree.findGreatestLessThan(7).value);
+  assertEquals('root', tree.findGreatestLessThan(6).value);
+  assertEquals('left', tree.findGreatestLessThan(4).value);
+  assertEquals(null, tree.findGreatestLessThan(2));
+})();
+
+
+(function testRemove() {
+  var tree = new goog.structs.SplayTree();
+  assertThrows('tree.remove(5)');
+  tree.insert(5, 'root');
+  tree.insert(3, 'left');
+  tree.insert(7, 'right');
+  assertThrows('tree.remove(1)');
+  assertThrows('tree.remove(6)');
+  assertThrows('tree.remove(10)');
+  assertEquals('root', tree.remove(5).value);
+  assertEquals('left', tree.remove(3).value);
+  assertEquals('right', tree.remove(7).value);
+  assertArrayEquals([], tree.exportValues());
+})();
diff --git a/deps/v8/test/mjsunit/top-level-assignments.js b/deps/v8/test/mjsunit/top-level-assignments.js
new file mode 100644
index 0000000..7acc9c1
--- /dev/null
+++ b/deps/v8/test/mjsunit/top-level-assignments.js
@@ -0,0 +1,107 @@
+// 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.
+
+// Testing that optimization of top-level object initialization doesn't
+// break V8.
+
+var x = new Object();
+x.a = 7;
+x.b = function() { return 42; };
+x.c = 88;
+x.d = "A Man Called Horse";
+
+assertEquals(7, x.a);
+assertEquals(42, x.b());
+assertEquals(88, x.c);
+assertEquals("A Man Called Horse", x.d);
+
+var y = new Object();
+y.a = 7;
+y.b = function() { return 42; };
+y.c = 12 * y.a;
+y.d = "A Man Called Horse";
+
+assertEquals(84, y.c);
+
+var z = new Object();
+z.a = 3;
+function forty_two() { return 42; };
+z.a += 4;
+z.b = forty_two;
+z.c = 12;
+z.c *= z.a;
+z.d = "A Man Called Horse";
+
+assertEquals(84, z.c);
+
+var x1 = new Object();
+var x2 = new Object();
+x1.a = 7;
+x1.b = function() { return 42; };
+x2.a = 7;
+x2.b = function() { return 42; };
+x1.c = 88;
+x1.d = "A Man Called Horse";
+x2.c = 88;
+x2.d = "A Man Called Horse";
+
+assertEquals(7, x1.a);
+assertEquals(42, x1.b());
+assertEquals(88, x1.c);
+assertEquals("A Man Called Horse", x1.d);
+
+assertEquals(7, x2.a);
+assertEquals(42, x2.b());
+assertEquals(88, x2.c);
+assertEquals("A Man Called Horse", x2.d);
+
+function Calculator(x, y) {
+  this.x = x;
+  this.y = y;
+}
+
+Calculator.prototype.sum = function() { return this.x + this.y; };
+Calculator.prototype.difference = function() { return this.x - this.y; };
+Calculator.prototype.product = function() { return this.x * this.y; };
+Calculator.prototype.quotient = function() { return this.x / this.y; };
+
+var calc = new Calculator(20, 10);
+assertEquals(30, calc.sum());
+assertEquals(10, calc.difference());
+assertEquals(200, calc.product());
+assertEquals(2, calc.quotient());
+
+var x = new Object();
+x.__defineGetter__('a', function() { return 7 });
+x.b = function() { return 42; };
+x.c = 88;
+x.d = "A Man Called Horse";
+
+assertEquals(7, x.a);
+assertEquals(42, x.b());
+assertEquals(88, x.c);
+assertEquals("A Man Called Horse", x.d);
diff --git a/deps/v8/test/mjsunit/touint32.js b/deps/v8/test/mjsunit/touint32.js
new file mode 100644
index 0000000..f06bddf
--- /dev/null
+++ b/deps/v8/test/mjsunit/touint32.js
@@ -0,0 +1,72 @@
+// Copyright 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.
+
+function ToUInt32(x) {
+  return x >>> 0;
+}
+
+assertEquals(0, ToUInt32(0),         "0");
+assertEquals(0, ToUInt32(-0),        "-0");
+assertEquals(0, ToUInt32(Infinity),  "Infinity");
+assertEquals(0, ToUInt32(-Infinity), "-Infinity");
+assertEquals(0, ToUInt32(NaN),       "NaN");
+
+assertEquals(0, ToUInt32(Number.MIN_VALUE),  "MIN");
+assertEquals(0, ToUInt32(-Number.MIN_VALUE), "-MIN");
+assertEquals(0, ToUInt32(0.1),               "0.1");
+assertEquals(0, ToUInt32(-0.1),              "-0.1");
+assertEquals(1, ToUInt32(1),                 "1");
+assertEquals(1, ToUInt32(1.1),               "1.1");
+
+assertEquals(4294967295, ToUInt32(-1),   "-1");
+assertEquals(4294967295, ToUInt32(-1.1), "-1.1");
+
+assertEquals(2147483647, ToUInt32(2147483647), "2147483647");
+assertEquals(2147483648, ToUInt32(2147483648), "2147483648");
+assertEquals(2147483649, ToUInt32(2147483649), "2147483649");
+
+assertEquals(4294967295, ToUInt32(4294967295), "4294967295");
+assertEquals(0,          ToUInt32(4294967296), "4294967296");
+assertEquals(1,          ToUInt32(4294967297), "4294967297");
+
+assertEquals(2147483649, ToUInt32(-2147483647), "-2147483647");
+assertEquals(2147483648, ToUInt32(-2147483648), "-2147483648");
+assertEquals(2147483647, ToUInt32(-2147483649), "-2147483649");
+
+assertEquals(1,          ToUInt32(-4294967295), "-4294967295");
+assertEquals(0,          ToUInt32(-4294967296), "-4294967296");
+assertEquals(4294967295, ToUInt32(-4294967297), "-4294967297");
+
+assertEquals(2147483647, ToUInt32('2147483647'), "'2147483647'");
+assertEquals(2147483648, ToUInt32('2147483648'), "'2147483648'");
+assertEquals(2147483649, ToUInt32('2147483649'), "'2147483649'");
+
+assertEquals(4294967295, ToUInt32('4294967295'), "'4294967295'");
+assertEquals(0,          ToUInt32('4294967296'), "'4294967296'");
+assertEquals(1,          ToUInt32('4294967297'), "'4294967297'");
+
+
diff --git a/deps/v8/test/mjsunit/try-catch-extension-object.js b/deps/v8/test/mjsunit/try-catch-extension-object.js
new file mode 100644
index 0000000..efab821
--- /dev/null
+++ b/deps/v8/test/mjsunit/try-catch-extension-object.js
@@ -0,0 +1,58 @@
+// 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.
+
+// Try catch scopes should be implemented with special extension
+// objects so that __proto__ accessors and accessor setters in the
+// Object prototype have no effect.
+
+var setterCalled = false;
+Object.prototype.__defineSetter__("x", function() { setterCalled = true; });
+
+function runTest(test) {
+  setterCalled = false;
+  test();
+}
+
+function testProto() {
+  try {
+    throw 42;
+  } catch(__proto__) {
+    assertEquals(42, __proto__);
+  }
+}
+
+function testAccessorSetter() {
+  try {
+    throw 42;
+  } catch(x) {
+    assertFalse(setterCalled);
+    assertEquals(42, x);
+  }
+}
+
+runTest(testProto);
+runTest(testAccessorSetter);
diff --git a/deps/v8/test/mjsunit/try-catch-scopes.js b/deps/v8/test/mjsunit/try-catch-scopes.js
new file mode 100644
index 0000000..c5bada2
--- /dev/null
+++ b/deps/v8/test/mjsunit/try-catch-scopes.js
@@ -0,0 +1,42 @@
+// Copyright 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.
+
+// Exception variables used in try-catch should be scoped, e.g. only
+// visible inside the catch block. They should *not* just be treated
+// as local variables and they should be allowed to nest.
+var e = 0;
+try {
+  throw e + 1;
+} catch(e) {
+  try {
+    throw e + 1;
+  } catch (e) {
+    assertEquals(2, e);
+  }
+  assertEquals(1, e);
+}
+assertEquals(0, e);
diff --git a/deps/v8/test/mjsunit/try-finally-nested.js b/deps/v8/test/mjsunit/try-finally-nested.js
new file mode 100644
index 0000000..c05f96a
--- /dev/null
+++ b/deps/v8/test/mjsunit/try-finally-nested.js
@@ -0,0 +1,46 @@
+// Copyright 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.
+
+function f() {
+  try {
+    return 42;
+  } finally {
+    var executed = false;
+    while (!executed) {
+      try {
+        break;
+      } finally {
+        executed = true;
+      }
+      assertTrue(false, "should not reach here");
+    }
+    assertTrue(executed, "finally block executed");
+  }
+  return 87;
+};
+
+assertEquals(42, f());
diff --git a/deps/v8/test/mjsunit/try.js b/deps/v8/test/mjsunit/try.js
new file mode 100644
index 0000000..0bd78b4
--- /dev/null
+++ b/deps/v8/test/mjsunit/try.js
@@ -0,0 +1,349 @@
+// Copyright 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.
+
+// Flags: --expose-gc
+
+function Catch(f, g) {
+  var r;
+  try { r = f(); } catch (o) { return g(o); }
+  return r;
+}
+
+function CatchReturn(f, g) {
+  try { return f(); } catch (o) { return g(o); }
+}
+
+
+var a = [Catch, CatchReturn]
+for (var n in a) {
+  var c = a[n];
+  assertEquals(1, c(function() { return 1; }));
+  assertEquals('bar', c(function() { return 'bar'; }));
+  assertEquals(1, c(function () { throw 1; }, function (x) { return x; }));
+  assertEquals('bar', c(function () { throw 'bar'; }, function (x) { return x; }));
+}
+
+
+assertEquals(1, (function() { try { return 1; } finally { } })());
+assertEquals(1, (function() { try { return 1; } finally { var x = 12; } })());
+assertEquals(2, (function() { try { } finally { return 2; } })());
+assertEquals(4, (function() { try { return 3; } finally { return 4; } })());
+
+function f(x, n, v) { try { return x; } finally { x[n] = v; } }
+assertEquals(2, f({}, 'foo', 2).foo);
+assertEquals(5, f({}, 'bar', 5).bar);
+
+function guard(f) { try { f(); } catch (o) { return o; } }
+assertEquals('baz', guard(function() { throw 'baz'; }));
+assertEquals(2, (function() { try { throw {}; } catch(e) {} finally { return 2; } })());
+assertEquals(1, guard(function() { try { throw 1; } finally { } }));
+assertEquals(2, guard(function() { try { throw 2; } finally { var x = 12; } }));
+assertEquals(4, guard(function() { try { throw 3; } finally { throw 4; } }));
+
+(function () {
+  var iter = 1000000;
+  for (var i = 1; i <= iter; i++) {
+    try {
+      if (i == iter) gc();
+    } finally {
+      if (i == iter) gc();
+    }
+  }
+})();
+
+function trycatch(a) {
+  var o;
+  try {
+    throw 1;
+  } catch (o) {
+    a.push(o);
+    try {
+      throw 2;
+    } catch (o) {
+      a.push(o);
+    }
+    a.push(o);
+  }
+  a.push(o);
+}
+var a = [];
+trycatch(a);
+assertEquals(4, a.length);
+assertEquals(1, a[0], "a[0]");
+assertEquals(2, a[1], "a[1]");
+
+assertEquals(1, a[2], "a[2]");
+assertTrue(typeof a[3] === 'undefined', "a[3]");
+
+assertTrue(typeof o === 'undefined', "global.o");
+
+
+function return_from_nested_catch(x) {
+  try {
+    try {
+      return x;
+    } catch (o) {
+      return -1;
+    }
+  } catch (o) {
+    return -2;
+  }
+}
+
+assertEquals(0, return_from_nested_catch(0));
+assertEquals(1, return_from_nested_catch(1));
+
+
+function return_from_nested_finally(x) {
+  var a = [x-2];
+  try {
+    try {
+      return a;
+    } finally {
+      a[0]++;
+    }
+  } finally {
+    a[0]++;
+  }
+}
+
+assertEquals(0, return_from_nested_finally(0)[0]);
+assertEquals(1, return_from_nested_finally(1)[0]);
+
+
+function break_from_catch(x) {
+  x--;
+ L:
+  {
+    try {
+      x++;
+      if (false) return -1;
+      break L;
+    } catch (o) {
+      x--;
+    }
+  }
+  return x;
+}
+
+assertEquals(0, break_from_catch(0));
+assertEquals(1, break_from_catch(1));
+
+
+function break_from_finally(x) {
+ L:
+  {
+    try {
+      x++;
+      if (false) return -1;
+      break L;
+    } finally {
+      x--;
+    }
+    x--;
+  }
+  return x;
+}
+
+assertEquals(0, break_from_finally(0), "break from finally");
+assertEquals(1, break_from_finally(1), "break from finally");
+
+
+function continue_from_catch(x) {
+  x--;
+  var cont = true;
+  while (cont) {
+    try {
+      x++;
+      if (false) return -1;
+      cont = false;
+      continue;
+    } catch (o) {
+      x--;
+    }
+  }
+  return x;
+}
+
+assertEquals(0, continue_from_catch(0));
+assertEquals(1, continue_from_catch(1));
+
+
+function continue_from_finally(x) {
+  var cont = true;
+  while (cont) {
+    try {
+      x++;
+      if (false) return -1;
+      cont = false;
+      continue;
+    } finally {
+      x--;
+    }
+    x--;
+  }
+  return x;
+}
+
+assertEquals(0, continue_from_finally(0));
+assertEquals(1, continue_from_finally(1));
+
+
+function continue_alot_from_finally(x) {
+  var j = 0;
+  for (var i = 0; i < x;) {
+    try {
+      j++;
+      continue;
+      j++;  // should not happen
+    } finally {
+      i++; // must happen
+    }
+    j++; // should not happen
+  }
+  return j;
+}
+
+
+assertEquals(100, continue_alot_from_finally(100));
+assertEquals(200, continue_alot_from_finally(200));
+
+
+
+function break_from_nested_catch(x) {
+  x -= 2;
+ L:
+  {
+    try {
+      x++;
+      try {
+        x++;
+        if (false) return -1;
+        break L;
+      } catch (o) {
+        x--;
+      }
+    } catch (o) {
+      x--;
+    }
+  } 
+  return x;
+}
+
+assertEquals(0, break_from_nested_catch(0));
+assertEquals(1, break_from_nested_catch(1));
+
+
+function break_from_nested_finally(x) {
+ L:
+  {
+    try {
+      x++;
+      try {
+        x++;
+        if (false) return -1;
+        break L;
+      } finally {
+        x--;
+      }
+    } finally {
+      x--;
+    }
+    x--; // should not happen
+  } 
+  return x;
+}
+
+assertEquals(0, break_from_nested_finally(0));
+assertEquals(1, break_from_nested_finally(1));
+
+
+function continue_from_nested_catch(x) {
+  x -= 2;
+  var cont = true;
+  while (cont) {
+    try {
+      x++;
+      try {
+        x++;
+        if (false) return -1;
+        cont = false;
+        continue;
+      } catch (o) {
+        x--;
+      }
+    } catch (o) {
+      x--;
+    }
+  }
+  return x;
+}
+
+assertEquals(0, continue_from_nested_catch(0));
+assertEquals(1, continue_from_nested_catch(1));
+
+
+function continue_from_nested_finally(x) {
+  var cont = true;
+  while (cont) {
+    try {
+      x++;
+      try {
+        x++;
+        if (false) return -1;
+        cont = false;
+        continue;
+      } finally {
+        x--;
+      }
+    } finally {
+      x--;
+    }
+    x--;  // should not happen
+  }
+  return x;
+}
+
+assertEquals(0, continue_from_nested_finally(0));
+assertEquals(1, continue_from_nested_finally(1));
+
+
+var caught = false;
+var finalized = false;
+var broke = true;
+L: try {
+  break L;
+  broke = false;
+} catch (o) {
+  caught = true;
+} finally {
+  finalized = true;
+}
+assertTrue(broke);
+assertFalse(caught);
+assertTrue(finalized);
+
diff --git a/deps/v8/test/mjsunit/unicode-string-to-number.js b/deps/v8/test/mjsunit/unicode-string-to-number.js
new file mode 100644
index 0000000..13a7acf
--- /dev/null
+++ b/deps/v8/test/mjsunit/unicode-string-to-number.js
@@ -0,0 +1,46 @@
+// Copyright 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.
+
+// Make sure not to treat 16-bit unicode characters as ASCII
+// characters when converting to numbers.
+assertEquals(272, Number('2\u00372'));
+assertTrue(isNaN(Number('2\u11372')), "short-string");
+
+// Check that long string can convert to proper numbers.
+var s = '\u0031';
+for (var i = 0; i < 7; i++) {
+  s += s;
+}
+assertTrue(isFinite(Number(s)));
+
+// Check that long strings with non-ASCII characters cannot convert.
+var s = '\u1131';
+for (var i = 0; i < 7; i++) {
+  s += s;
+}
+assertTrue(isNaN(Number(s)), "long-string");
+
diff --git a/deps/v8/test/mjsunit/unicode-test.js b/deps/v8/test/mjsunit/unicode-test.js
new file mode 100644
index 0000000..59a684e
--- /dev/null
+++ b/deps/v8/test/mjsunit/unicode-test.js
@@ -0,0 +1,9169 @@
+// Copyright 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.
+
+// Texts are from the Unibrow test suite.
+
+// Note that this file is in UTF-8.  smjs and testkjs do not read their
+// source files as UTF-8, so they will fail on this test.  If you want
+// to run the test on them you can do so after filtering it with the
+// following piece of perl-based line noise:
+
+// perl -CIO -ne '$_ =~ s/([^\n -~])/"\\u" . sprintf("%04x", ord($1))/ge; print $_;' < unicode-test.js > unicode-test-ascii.js
+
+// The result is predictably illegible even for those fluent in Hindi.
+
+var chinese =
+"中国历史\n" +
+"[编辑首段]维基百科，自由的百科全书\n" +
+"跳转到： 导航, 搜索\n" +
+"中國歷史\n" +
+"中国历史系列条目\n" +
+"史前时期\n" +
+"传说时期\n" +
+"(另见三皇五帝)\n" +
+"夏\n" +
+"商\n" +
+"西周 	周\n" +
+"春秋 	东周\n" +
+"战国\n" +
+"秦\n" +
+"西汉 	汉\n" +
+"新朝\n" +
+"东汉\n" +
+"魏 	蜀 	吴 	三\n" +
+"国\n" +
+"西晋 	晋\n" +
+"东晋 	十六国\n" +
+"宋 	南\n" +
+"朝 	北魏 	北\n" +
+"朝 	南\n" +
+"北\n" +
+"朝\n" +
+"齐\n" +
+"梁 	东\n" +
+"魏 	西\n" +
+"魏\n" +
+"陈 	北\n" +
+"齐 	北\n" +
+"周\n" +
+"隋\n" +
+"唐\n" +
+"（另见武周）\n" +
+"五代十国\n" +
+"辽\n" +
+"(西辽) 	西\n" +
+"夏 	北宋 	宋\n" +
+"金 	南宋\n" +
+"元\n" +
+"明\n" +
+"清\n" +
+"中华民国\n" +
+"中华人民\n" +
+"共和国 	中华\n" +
+"民国\n" +
+"（见台湾问题）\n" +
+"\n" +
+"    * 中国历史年表\n" +
+"    * 中国军事史\n" +
+"    * 中国美术史\n" +
+"    * 中国科学技术史\n" +
+"    * 中国教育史\n" +
+"\n" +
+"中国\n" +
+"天坛\n" +
+"文化\n" +
+"中文 - 文学 - 哲学 - 教育\n" +
+"艺术 - 国画 - 戏曲 - 音乐\n" +
+"神话 - 宗教 - 术数 - 建筑\n" +
+"文物 - 电影 - 服饰 - 饮食\n" +
+"武术 - 书法 - 节日 - 姓名\n" +
+"地理\n" +
+"疆域 - 行政区划 - 城市\n" +
+"地图 - 旅游 - 环境 - 生物\n" +
+"人口 - 民族 - 交通 - 时区\n" +
+"历史\n" +
+"年表 - 传说时代 - 朝代\n" +
+"民国史 - 共和国史\n" +
+"文化史 - 科技史 - 教育史\n" +
+"人口史 - 经济史 - 政治史\n" +
+"政治\n" +
+"中华人民共和国政治 - 中华民国政治\n" +
+"宪法 - 外交 - 军事 - 国旗\n" +
+"两岸问题 - 两岸关系\n" +
+"一个中国 - 中国统一\n" +
+"经济\n" +
+"金融 - 农业 - 工业 - 商业\n" +
+"中国各省经济 - 五年计划\n" +
+"其他\n" +
+"列表 - 体育 - 人权 - 媒体\n" +
+"\n" +
+"中国历史自商朝起算约有3600年，自黄帝时代起算约有4000多年。有历史学者认为，在人类文明史中，“历史时代”的定义是指从有文字发明时起算，那之前则称为“史前”；中国历史中传说伏羲做八卦，黄帝时代仓颉造文字；近代考古发现了3600多年前（公元前1600年）商朝的甲骨文、约4000年前至7000年前的陶文、约7000年前至10000年前具有文字性貭的龟骨契刻符号。另外，目前在中国发现最早的史前人类遗址距今约200万年。\n" +
+"\n" +
+"从政治形态区分中国历史，可见夏朝以前长达3000年以上的三皇五帝是母系氏族社会到父系氏族社会的过渡时代，而夏朝开始君王世袭，周朝建立完备的封建制度至东周逐渐解构，秦朝首度一统各国政治和许多民间分歧的文字和丈量制度，并建立中央集权政治，汉朝起则以文官主治国家直至清朝，清末以降，民主政治、马克思主义等各种政治思潮流传，先促成中华民国的建立，并于其后四、五十年再出现中华人民共和国，而由于内战失败，中华民国政府退守台湾。\n" +
+"\n" +
+"由经济形态观察，中国古代人口主要由自由民构成，私有制、商业活动发达。周朝时商业主要由封建领主阶层控制的官商贸易和庶民的自由贸易构成。秦汉以后实行中央集权，人口由士、农、工、商等构成，其中以从事农业的自由民为主体，是一个君权官僚制下的以土地为主要生产资本的较为自由的商业经济社会，一些重要的行业由官商垄断。除了农业，手工业以及商业贸易也有很大的发展。早在汉朝丝路的开通，促进了东亚与中亚至欧洲的陆上交通时，国际贸易早已起步；隋唐时大运河的开通促进了南北贸易；唐朝的盛世及外交的开放、交通的建设，更使各国文化、物资得以交流；宋代时出现了纸币；元代时与中亚的商业交流十分繁荣；明清两代受到西方国家海上发展的影响，海上国际贸易发展迅猛。自中华民国成立起试图建立民主国家，实行自由经济，直到1990年代台湾落实民主制度，1950年代以后30多年迅速实现了向工业化社会的转型；而中国大陆则在1949年后采用一党制统治，起先为公有制的计划经济社会，改革开放后逐步向私有制的市场经济社会転型，同时，1980年代以来工业化发展迅猛，数亿人口在短短20多年内从农民转为产业工人（目前仅仅被称为“农民工”的产业工人就达到约2亿）。伴随经济的迅速国际化，中国经济成为全球经济中越来越重要的组成部分。\n" +
+"目录\n" +
+"[隐藏]\n" +
+"\n" +
+"    * 1 史前时代\n" +
+"    * 2 传说时代\n" +
+"    * 3 先秦时期\n" +
+"          o 3.1 三代\n" +
+"          o 3.2 春秋战国\n" +
+"    * 4 秦汉时期\n" +
+"    * 5 魏晋南北朝时期\n" +
+"    * 6 隋唐五代时期\n" +
+"    * 7 宋元时期\n" +
+"    * 8 明清时期\n" +
+"          o 8.1 清末的内忧外患\n" +
+"    * 9 20世纪至今\n" +
+"    * 10 参见\n" +
+"    * 11 其他特定主题中国史\n" +
+"    * 12 注解\n" +
+"    * 13 参考文献\n" +
+"    * 14 相关著作\n" +
+"    * 15 外部链接\n" +
+"\n" +
+"[编辑] 史前时代\n" +
+"大汶口文化的陶鬹，山東莒县大朱村出土\n" +
+"大汶口文化的陶鬹，山东莒县大朱村出土\n" +
+"\n" +
+"迄今为止发现的最早的高等灵长类中华曙猿在4500万年前生活在中国江南一带。考古证据显示224万年至25万年前，中国就有直立人居住，目前考古发现的有巫山人、元谋人、蓝田人、南京直立人、北京直立人等。这些都是目前所知较早的原始人类踪迹。\n" +
+"\n" +
+"中国史前时代的各种文化是经过了以下几个阶段：以直立猿\n" +
+"人为主的旧石器时代早中期（距今约50至40多万年前），接着进入了旧石器时代中晚期，以山顶洞人为代表，距今约在20至10余万年前。新石器时代早期的代表性文化是裴李岗文化，紧接着是以仰韶文化为代表的新石器时代中期。而以龙山文化为代表的新石器时代晚期，大约出现在公元前2500年到公元前1300年间。\n" +
+"\n" +
+"根据现在的考古学研究，中国的新石器时代呈现多元并立的情形：约西元前5000年到3000年前在河南省、河北省南部、甘肃省南部和山西省南部出现的仰韶文化便具备使用红陶、彩陶以及食用粟和畜养家畜的特质。而大约在同一时间，尚有在浙江省北边出现的河姆渡文化、山东省的大汶口文化。而之后发现的如二里头遗址和三星堆遗址则为青铜器时代的代表。\n" +
+"\n" +
+"[编辑] 传说时代\n" +
+"\n" +
+"    主条目：三皇五帝\n" +
+"\n" +
+"後人所繪的黄帝像\n" +
+"后人所绘的黄帝像\n" +
+"\n" +
+"华夏文明形成于黄河流域中原地区。早期的历史，口口相传。神话中有盘古开天地、女娲造人的说法。传说中的三皇五帝，是夏朝以前数千年杰出首领的代表，具体而言有不同的说法。一般认为，三皇是燧人、伏羲、神农以及女娲、祝融中的三人，五帝一般指黄帝、颛顼、帝喾、尧、舜。自三皇至五帝，历年无确数，最少当不下数千年。\n" +
+"\n" +
+"据现今整理出来的传说，黄帝原系炎帝部落的一个分支的首领，强大之后在阪泉之战中击败炎帝，成为新部落联盟首领，之后又与东南方的蚩尤部落发生冲突，在涿鹿之战中彻底击败对手，树立了自己的霸主地位。\n" +
+"\n" +
+"后来黄帝的孙子颛顼和玄孙帝喾继续担任部落联盟的首领。帝喾的儿子尧继位，他是一名贤君，创立了禅让制，传位给了舜。在舜时期，洪水泛滥，鲧采用堵塞的方法，结果洪水更厉害了，鲧被处决，他的儿子禹采用疏导的方法，成功治理了洪水，因此被推举为首领。然而他的儿子启破坏了禅让制方式，自立为王(但据《史记》及香港中学课本所述，启是被推举为领袖)，建立了第一个世袭王朝——夏朝，夏朝持续了400多年，在最后一个夏朝君主——桀末期，东方诸侯国商首领成汤夺取了政权，建立了商朝。\n" +
+"\n" +
+"[编辑] 先秦时期\n" +
+"\n" +
+"[编辑] 三代\n" +
+"\n" +
+"    主条目：夏朝、商朝、周朝和西周\n" +
+"\n" +
+"甲骨文\n" +
+"甲骨文\n" +
+"\n" +
+"最早的世袭朝代夏朝约在前21世纪到前16世纪，由于这段历史目前没有发现文字性文物做印证，所以只能靠后世的记录和出土文物互相对照考证，中国学者一般认为河南洛阳二里头遗址是夏朝首都遗址，有学者对此持有疑问。根据文字记载，夏朝有了中国最早的历法--夏小正。不过之后的商朝是目前所发现的最早有文字文物的历史时期，存在于前16世纪到约前1046年。据说夏朝最后一个君主——桀，由于荒淫无道而被汤推翻。而商代时文明已经十分发达，有历法、青铜器以及成熟的文字——甲骨文等。商王朝时已经有一个完整的国家组织，并且具有了封建王朝的规模。当时的主要生产部门是农业，不过手工业，特别是青铜器的冶铸水平也已经十分高超。并且已经出现了原始的瓷器。商朝自盘庚之后，定都于殷（今河南安阳），因此也称为殷朝。商朝的王位继承制度是传子或传弟，多按年龄的长幼继承。\n" +
+"\n" +
+"与此同时，黄河上游的另一个部落周正在逐步兴起，到了大约前1046年，周武王伐纣，在牧野之战中取得决定性胜利，商朝灭亡。周朝正式建立，建都渭河流域的镐京（今陕西西安附近）。之后周朝的势力又慢慢渗透到黄河下游和淮河一带。周王朝依然是封建贵族统治，有许多贵族的封国（诸侯）。到鼎盛时，周朝的影响力已经在南方跨过长江，东北到今天的辽宁，西至甘肃，东到山东。周朝时的宗法制度已经建立，政权机构也较完善。自唐尧、虞舜至周朝皆封建时代，帝王与诸侯分而治之[1]。中国最早有确切时间的历史事件是发生于公元前841年西周的国人暴动。\n" +
+"\n" +
+"[编辑] 春秋战国\n" +
+"\n" +
+"    主条目：周朝、东周、春秋时期和战国 (中国)\n" +
+"\n" +
+"先師孔子行教像，為唐朝画家吳道子所画\n" +
+"先师孔子行教像，为唐朝画家吴道子所画\n" +
+"\n" +
+"前770年，由于遭到北方游牧部落犬戎的侵袭，周平王东迁黄河中游的洛邑（今河南洛阳），东周开始。此后，周王朝的影响力逐渐减弱，取而代之的是大大小小一百多个小国（诸侯国和附属国），史称春秋时期。春秋时期的大国共有十几个，其中包括了晋、秦、郑、齐及楚等。这一时期社会动荡，战争不断，先后有五个国家称霸，即齐、宋、晋、楚、秦(又有一说是齐、晋、楚、吴、越)，合称春秋五霸。到了前546年左右，黄河流域的争霸基本结束，晋、楚两国平分了霸权。前403年，晋国被分成韩、赵、魏三个诸侯国，史称“三家分晋”。再加上被田氏夺去了政权的齐国，和秦、楚及燕，并称战国七雄，战国时期正式开始。大部分马克思主义史学家将战国开始划为封建社会，然而大部分西方及台湾学者却又将之划为封建社会的崩溃。前356年秦国商鞅变法开始后，秦国国力大大增强，最后终于在前221年消灭六国最后的齐国，完成统一，中国历史也进入了新时代。\n" +
+"\n" +
+"春秋战国时期学术思想比较自由，史称百家争鸣。出现了多位对之后中国有深远影响的思想家（诸子百家），例如老子、孔子、墨子、庄子、孟子、荀子、韩非等人。出现了很多学术流派，较出名的有十大家，即道家（自然）、儒家（伦理）、阴阳家（星象占卜）、法家（法治）、名家（修辞辩论）、墨家（科技）、众、杂、农家（农业）、小说家（小说）等。文化上则出现了第一个以个人名字出现在中国文学史上的诗人屈原，他著有楚辞、离骚等文学作品。孔子编成了诗经。战争史上出现了杰出的兵法家孙武、孙膑、吴起等等。科技史上出现了墨子，建筑史上有鲁班，首次发明了瓦当，奠定了中国建筑技术的基础。能制造精良的战车与骑兵，同时此时中国的冶金也十分发达，能制造精良的铁器，在农业上出现了各种灌溉机械，大大提高了生产率，从而为以后人口大大膨胀奠定了基础。历史上出现了春秋（左传），国语，战国策。中华文化的源头基本上都可以在这一时期找到。\n" +
+"\n" +
+"这一时期科技方面也取得了很大进步。夏朝发明了干支纪年，出现了十进位制。西周人用圭表测日影来确定季节；春秋时期确定了二十八宿；后期则产生了古四分历。\n" +
+"\n" +
+"[编辑] 秦汉时期\n" +
+"\n" +
+"    主条目：秦朝、汉朝、西汉、新朝和东汉\n" +
+"\n" +
+"北京八達嶺長城\n" +
+"北京八达岭长城\n" +
+"\n" +
+"前221年，秦并其他六国后统一了中国主体部分，成为了中国历史上第一个统一的中央集权君主统治国家，定都咸阳（今西安附近）。由于秦王嬴政自认“功盖三皇，德过五帝”，于是改用皇帝称号，自封始皇帝，人称秦始皇，传位后的皇帝称二世，直至千世万世。他对国家进行了许多项改革，包括了中央集权的确立，取代了周朝的诸侯分封制；统一了文字，方便官方行文；统一度量衡，便于工程上的计算。秦始皇还大力修筑驰道，并连接了战国时赵国、燕国和秦国的北面围城，筑成了西起临洮、东至辽东的万里长城以抵御北方来自匈奴，东胡等游牧民族的侵袭。秦始皇推崇法治，重用法家的李斯作为丞相，并听其意见，下令焚书坑儒，收缴天下兵器，役使七十万人修筑阿房宫以及自己的陵墓——包括兵马俑等。部分史学家对以上事件存有怀疑，认为由于秦始皇的一系列激进改革得罪了贵族，平民无法适应，才在史书上留此一笔。[来源请求]\n" +
+"\n" +
+"前210年，秦始皇病死于出巡途中，胡亥（即秦二世）杀害太子扶苏即位。但十个月后，陈胜、吴广在大泽乡揭竿而起，包括六国遗臣等野心家乘势作乱，前206年刘邦围攻咸阳，秦王子婴自缚出城投降，秦亡。此后，汉王刘邦与西楚霸王项羽展开了争夺天下的楚汉战争。 前202年十二月，项羽被汉军围困于垓下（今安徽灵壁），四面楚歌。项羽在乌江自刎而死。楚汉之争至此结束。汉高祖刘邦登基，定都长安（今陕西西安），西汉开始。到了汉武帝时，西汉到达鼎盛。并与罗马，安息(帕提亚），贵霜并称为四大帝国。武帝实行推恩令，彻底削弱了封国势力，强化监察制度，实现中央集权；他派遣卫青、霍去病、李广等大将北伐，成功地击溃了匈奴，控制了西域，还派遣张骞出使西域，开拓了著名的丝绸之路，发展了对外贸易，使中国真正了解了外面的世界，促进中西文化交流。儒家学说也被确立为官方的主流意识形态，成为了占统治地位的思想。其他艺术与文化也蒸蒸日上。同时期还出现了第一部通史性质的巨著——《史记》，同时这时的中国出现造纸术，大大推动了文化发展。\n" +
+"\n" +
+"西汉发展到了一世纪左右开始逐渐衰败。公元9年，外戚王莽夺权，宣布进行一系列的改革，改国号为新。然而这些改革却往往不切实际，最终导致农民纷纷起义。公元25年刘秀复辟了汉朝，定都洛阳，史称东汉，而他就是汉光武帝。东汉的发展延续了西汉的传统，此时出现了天文学家张衡。汉的文化吸取了秦的教训，显得相当开明，当时佛教通过西域到达中国，在河南洛阳修建了中国的第一座佛教寺庙——白马寺，佛教正式传入中国。\n" +
+"\n" +
+"[编辑] 魏晋南北朝时期\n" +
+"\n" +
+"    主条目：魏晋南北朝、三国、晋朝、十六国和南北朝\n" +
+"\n" +
+"赤壁\n" +
+"赤壁\n" +
+"\n" +
+"东汉中后期，宦官和外戚长期争权，在黄巾起义的打击下，到了公元二世纪左右时再度衰败，196年曹操控制了东汉朝廷，把汉献帝迎至许都，“挟天子以令诸侯”，220年，曹操死后，长子曹丕废汉献帝自立，建立魏国，同时尚有刘氏的汉和孙氏的吴，历史进入了三国时期。\n" +
+"\n" +
+"265年，魏权臣司马炎称帝，建立晋朝。280年三国归晋，再度统一。晋朝的文化也有一定发展，当时由于战乱纷纷，很多学士选择归隐，不问世事，典型的代表人物是陶渊明（陶潜），当时的书法艺术也十分兴盛。290年晋武帝死后不到一年，十六年的朝廷权利斗争开始，史称“八王之乱”。与此同时，中原周边的五个游牧民族（匈奴、鲜卑、羌、氐、羯）与各地流民起来反晋，史称五胡乱华。这些游牧民族纷纷建立自己的国家，从304年到409年，北部中国陆陆续续有多个国家建立，包括了汉、前赵、后赵、前燕、前凉、前秦、后秦、后燕、西秦、后凉、北凉、南凉、南燕、西凉、夏和北燕, 史称十六国。\n" +
+"\n" +
+"自东汉后期开始，为躲避战乱，北方的汉族人民大量迁居南方，造成经济重心南移；晋朝南迁，建都建康（今江苏南京），历史上称此前为西晋，南迁后为东晋。最后，拓跋鲜卑统一北方，建立北朝的第一个王朝——北魏，形成了南北朝的对立。南朝经历了宋、齐、梁、陈的更替，而北朝则有北魏、东魏、西魏、北齐和北周。南北朝时期是佛教十分盛行的时期，西方的佛教大师络绎不绝地来到中国，许多佛经被翻译成汉文。\n" +
+"\n" +
+"[编辑] 隋唐五代时期\n" +
+"\n" +
+"    主条目：隋朝、唐朝和五代十国\n" +
+"\n" +
+"唐代画家张萱作《捣练图》。\n" +
+"唐代画家张萱作《捣练图》。\n" +
+"\n" +
+"581年，杨坚取代北周建立了隋朝，并于589年灭掉南朝最后一个政权——陈，中国历经了三百多年的分裂之后再度实现了统一。不过隋朝也是一个短命的王朝，在修筑了巨大工程——京杭大运河后就灭亡了，只经历了两代37年。\n" +
+"\n" +
+"618年，唐高祖李渊推翻隋朝建立了唐朝，它是中国历史上延续时间最长的朝代之一。626年，唐太宗李世民即位，唐朝开始进入鼎盛时期，史称贞观之治。长安（今陕西西安）是当时世界上最大的城市，唐王朝也是当时最发达的文明。高宗李治之妻武则天迁都洛阳，并称帝，成为中国史上唯一的女皇帝，改国号周，并定佛教为国教，广修佛寺，大兴土木。隋唐时期开创的科举制是当时比较科学与公平的人材选拔制度。唐王朝与许多邻国发展了良好的关系，文成公主嫁到吐蕃，带去了大批丝织品和手工艺品。日本则不断派遣使节、学问僧和留学生到中国。唐朝的文化也处于鼎盛，特别是诗文得到较大的发展，还编撰了许多纪传体史书。唐代涌现出许多伟大的文学家，例如诗人李白、杜甫、白居易、杜牧，以及散文家韩愈、柳宗元。唐代的佛教是最兴盛的宗教，玄奘曾赴天竺取经，回国后译成1335卷的经文，并于西安修建了大雁塔以存放佛经。唐朝前期对宗教采取宽容政策，佛教外，道教、摩尼教(Manicheism)、景教和伊斯兰教等也得到了广泛传播。这一切都在李世民的曾孙唐玄宗李隆基统治时期达到顶峰，史称开元盛世。然而在755年，爆发了安史之乱，唐朝由此开始走向衰落。\n" +
+"\n" +
+"875年，黄巢起义爆发，唐朝再度分裂，并于907年灭亡，形成了五代十国的混乱局面。\n" +
+"\n" +
+"[编辑] 宋元时期\n" +
+"\n" +
+"    主条目：辽朝、金朝、西夏、宋朝和元朝\n" +
+"\n" +
+"清明上河圖局部，描繪了清明時節，北宋京城汴梁及汴河兩岸的繁華和熱鬧的景象和優美的自然風光。\n" +
+"清明上河图局部，描绘了清明时节，北宋京城汴梁及汴河两岸的繁华和热闹的景象和优美的自然风光。\n" +
+"\n" +
+"经过了五十多年的纷争后，960年北宋控制了中国大部分地区，但是燕云十六州在北方契丹族建立的辽朝手中(五代中的后晋太祖“儿皇帝”石敬瑭所献)，河西走廊被党项族建立的西夏趁中原内乱占据，北宋初期虽然曾出兵讨还(宋太宗)但是以失败告终，木以成舟,无可奈何,不得不向日益坐大的辽和西夏交纳岁币。北宋晚期发生了分别以王安石、司马光为首的党派斗争，增加了社会的不安。到了1125年松花江流域女真族，也就是后来的满族，建立的金国势力逐渐强大，1125年，金国灭辽。金国随即开始进攻积弱的北宋，1127年(靖康元年)金国攻破北宋首都汴京（今河南开封），俘虏三千多皇族，其中包括了当时的皇帝宋钦宗和太上皇宋徽宗，因为钦宗其时的年号为靖康，史称靖康之难，北宋灭亡。同年宋钦宗的弟弟赵构在南京应天府（今河南商丘）即皇位，定都临安（今浙江杭州），史称南宋，偏安江南。\n" +
+"\n" +
+"此后金与南宋多次交战，英雄人物层出不穷(如名将岳飞)。直到1234年，蒙古南宋联合灭金。随即蒙古与南宋对抗，经历了空前绝后的大规模血腥战争(如襄樊之战, 钓鱼城之战)。1271年忽必烈建立元朝，定都大都（今北京）。元军于1279年与南宋进行了崖山海战，8岁的小皇帝赵昺被民族英雄陆秀夫背着以身殉国惨烈地跳海而死。崖山海战以元朝的胜利告终，南宋随之灭亡。另有一说, 原华夏文明至此夭折.[来源请求]\n" +
+"\n" +
+"北宋时期中国出现印刷术和火药。当时中国经济发达，中国海上贸易十分兴盛，福建泉州一带成为繁华的港口，中国当时的经济总量占世界的一半，财政收入超过一亿两白银，首都开封和杭州人口达到400到500万人口，相对当时佛罗伦萨和巴黎十几万人口来讲确实是十分繁华，各国商人云集，文化也极盛，出现了程颐、朱熹等理学家，提倡三从四德。与唐诗并驾齐驱的宋词，有苏轼等词文优秀的词人，出现了中国历史上最著名的女词人李清照，社会文化发达，出现了白蛇传，梁祝等浪漫爱情传说，以至于宋朝被西方学者称为中国的“文艺复兴”。\n" +
+"\n" +
+"元朝建立后，一方面吸收了许多中原、汉族文化，以中原的统治机构和方式来统治人民，并大力宣扬朱熹一派的理论（即程朱理学），使得程朱理学成为元朝（以及其后朝代）的官方思想，另一方面却实行了民族等级制度，第一等是蒙古人；第二等是“色目人”，包括原西夏统治区以及来自西域、中亚等地的人口；第三等是“汉人”，包括原金统治区的汉族和契丹、女真等族人；第四等是“南人”，包括原南宋统治区的汉族和其他族人。这种民族制度导致汉族的不满，许多汉族人将元朝视为外来政权，并发动多次反抗。元朝政府除了传统的农业外，也比较重视商业。元朝首都大都十分繁华，来自世界各国的商人云集。在文化上，则出现了与唐诗、宋词并称的元曲，涌现出诸如关汉卿、马致远、王实甫等著名作曲家。\n" +
+"\n" +
+"[编辑] 明清时期\n" +
+"紫禁城太和殿\n" +
+"紫禁城太和殿\n" +
+"\n" +
+"    主条目：明朝、南明、清朝和中国近代史\n" +
+"\n" +
+"1368年，农民起义军领袖朱元璋推翻元朝并建立了明朝。明朝前期建都南京，1405年曾帮助明成祖篡位的太监郑和奉命七次下西洋，曾经到达印度洋、东南亚及非洲等地，但后来明朝逐渐走向闭关锁国。1421年，明朝迁都北京。明朝文化上则出现了王阳明、李贽等思想家，以及《三国演义》、《水浒传》、《西游记》和《金瓶梅》等长篇小说。由于明朝末年行政混乱及严重自然灾害，1627年，明末农民大起义爆发，1644年，起义首领李自成攻克北京，明思宗自缢。南方大臣先后拥护福王朱由崧（弘光）、唐王朱聿键（隆武）、桂王朱由榔（永历）为帝，史称南明，最终因实力不足及政治内斗，仍为当时强盛的清朝所灭。\n" +
+"\n" +
+"明朝晚期，居住在东北地区的满族开始兴盛起来，终于在1644年李自成攻克北京后不久，驱逐李自成，进入北京，建立了清朝，当时明朝旧臣郑成功南撤到台湾岛，并驱逐了那里的荷兰殖民者，后来被清朝军队攻下。清朝在之后的半个世纪还成功地征服了许多地区，例如新疆、西藏、蒙古以及台湾。康熙年间，清廷还与沙俄在黑龙江地区发生战争，最终于1689年签订停战条约——《中俄尼布楚条约》。清朝由于取消了丁税（人头税），导致人口增加，到19世纪已达当时世界总人口的三分之一，人口的增多促进当时农业的兴盛，为当时世界上第一强国，到1820年时中国的经济总量占世界的三分之一。\n" +
+"\n" +
+"然而到了19世纪初，清朝已经走向衰落，在嘉庆年间先后爆发白莲教、天理教的大规模起义。与此同时海上强国英国、荷兰与葡萄牙等纷纷开始强制与中国进行贸易。1787年，英国商人开始向华输入鸦片，导致中国的国际贸易由顺差变为巨额逆差。清廷于1815年颁布搜查洋船鸦片章程，然而英商无视禁令依然走私大量鸦片，道光皇帝不得不于1838年派林则徐赴广州禁烟。1839年6月，将237万多斤鸦片在虎门销毁，史称虎门销烟。英国政府因此于1840年6月发动鸦片战争。一般中国大陆史学界认为这是中国近代史的开始。\n" +
+"\n" +
+"[编辑] 清末的内忧外患\n" +
+"一幅描繪列強瓜分中國情形的漫畫\n" +
+"一幅描绘列强瓜分中国情形的漫画\n" +
+"\n" +
+"鸦片战争持续了一年多，1841年8月英军到达南京，清廷恐惧英军会进逼北京，于是求和，1842年8月29日，《南京条约》签署。香港岛被割让；上海、广州、厦门、福州和宁波开放作为通商口岸，还赔偿款银（西班牙银圆）2100万元。1844年，美国与法国也与清廷分别签订了《望厦条约》和《黄埔条约》，中国的主权受到破坏。\n" +
+"\n" +
+"与此同时中国国内反抗清朝的斗争再度兴起。1851年至1864年间，受到基督教影响的秀才洪秀全建立拜上帝会，发动金田起义并创建了太平天国。太平天国曾经一度占领南方部分省份，并定都南京（改名“天京”），建立政教合一的中央政权。同一时期其它的运动还有天地会、捻军、上海小刀会起义、甘肃回民起义等。这些反抗清朝的斗争直到1860年代才基本平息下来。\n" +
+"\n" +
+"19世纪后期，英、美、法、俄、日等国多次侵入中国，强迫中国与之签定不平等条约。1858年中俄签定《瑷珲条约》，俄国割去黑龙江以北、外兴安岭以南60多万平方公里的中国领土。1860年，英法联军发动第二次鸦片战争，侵入北京，掠夺并烧毁皇家园林圆明园，并于1860年与清廷签定《北京条约》，各赔英法800万两白银，开放更多通商口岸。同年中俄《北京条约》将乌苏里江以东，包括库页岛（萨哈林岛）、海参崴（符拉迪沃斯托克）约40万平方公里的中国领土，划归俄国。1864年，《中俄勘分西北界约记》将巴尔喀什湖以东、以南和斋桑卓尔南北44万平方公里的中国领土，割给俄国。\n" +
+"\n" +
+"为了增强国力并巩固国防，清朝自1860年代开始推行洋务运动，国力有所恢复，并一度出现了同治中兴的局面。1877年清军收复新疆，1881年通过《伊犁条约》清军收复被沙俄占据多年的伊犁。中法战争后清朝还建立了当时号称亚洲第一、世界第六的近代海军舰队—北洋水师。然而在1894年爆发的中日甲午战争中，中国战败，次年被迫与日本签定《马关条约》，赔偿日本2亿两白银，并割让台湾、澎湖列岛给日本。甲午战争的失败，对当时的中国产生了很大的影响。1898年，光绪帝在亲政后同意康有为、梁启超等人提出的变法主张，从6月11日到9月21日的被称为百日维新的103天中进行了多项改革，但最终在慈禧太后发动政变后失败落幕，康有为、梁启超逃亡国外，谭嗣同、刘光第等六人被杀，史称“戊戌六君子”。\n" +
+"\n" +
+"1899年，义和团运动爆发，以“扶清灭洋”为宗旨并在慈禧太后默许下开始围攻外国驻北京使馆。于是，各国以解救驻京使馆人员的名义侵入中国，史称八国联军。1901年，清政府被迫与各国签定辛丑条约，赔款4.5亿两白银，分39年还清（本息合计9.8亿两），同时从北京到山海关铁路沿线由各国派兵驻扎，开北京东交民巷为使馆区，国人不得入内等。\n" +
+"\n" +
+"[编辑] 20世纪至今\n" +
+"\n" +
+"    主条目：中华民国历史和中华人民共和国史\n" +
+"\n" +
+"1901年，革命党开始兴起，孙中山等人在海外积极筹款，指挥国内的多次起义运动。经过十次失败的起义后，与革命党互不沟通的湖北新军在武昌起义获得成功。1912年元月，中华民国宣告成立。孙中山就任临时大总统。以清帝退位为条件，孙中山辞去总统位置，由袁世凯接任。但袁世凯妄图恢复帝制。此后，孙中山发起护法运动与护国运动讨伐袁世凯。1916年，袁世凯在称帝83天之后死去，中华民国进入北洋军阀控制中央政府统治时期，地方政府分别由各个军阀派系占据。\n" +
+"\n" +
+"孙中山之后多次试图联合南方地方军阀北伐北京中央政府未果。1921年，在共产国际的指导下中国共产党成立，并成为共产国际中国支部。1924年，孙中山提出新三民主义并确定联俄联共扶助农工的政策，国民党在共产国际帮助下改组，共产党员以个人身份加入国民党，国共两党进行第一次合作。孙中山自建立广州军政府（1923年改称大元帅府）以后，曾经三次进行北伐，均因条件不具备而未果。1925年春，孙中山病逝于北京。同年，广州国民政府为统一与巩固广东革命根据地，先后举行第一次东征第二次东征与南征，肃清广东境内的军阀势力和反革命武装，并将广东境内倾向革命的军队统一改编为国民革命军，下辖第1至第6军。不久又将广西部队改编为第7军。为北伐战争作了重要准备。1926年6月5日，国民党中央执行委员会正式通过国民革命军出师北伐案，并任命蒋介石为国民革命军总司令正式开始北伐。然而随着北伐和国民革命的深入，国民党不能容忍共产党激进的工人运动，国共两党分裂，大量共产党员及其支持者被清出国民党，有的被拘捕和杀害。1927年8月1日，以周恩来、贺龙、叶挺为首的共产党员在江西南昌发动南昌叛乱，共产党从此有自己独立的军队（中华人民共和国成立后，8月1日被定为建军节）。并于江西瑞金建立了第一个红色苏维埃地方割据政权。此后南京国民政府先后对中央苏区进行五次围剿，红军逃过了前四次围剿，在第五次战争失败，不得不离开红区。1934年开始，红军进行战略转移，在贵州遵义确立了毛泽东对红军的领导和指挥权，四渡赤水河，终于摆脱了追击，途经江西，贵州，四川，甘肃，陕西，经过二万五千里长征，最后在陕西北部与陕北红军刘志丹部会师，建立陕甘宁共产党临时政府。\n" +
+"毛泽東在天安门城楼上宣布中华人民共和國的成立\n" +
+"毛泽东在天安门城楼上宣布中华人民共和国的成立\n" +
+"\n" +
+"1931年9月18日，日本开始侵华，占领了东北全境。1936年12月12日，西安事变后国共第二次合作抗日。1937年7月7日，抗日战争全面爆发，蒋中正在庐山发表著名的“最后关头”的演说，号召全国人民一致抗日。在日军进行南京大屠杀前夕，中华民国首都从南京迁至武汉，后来迁至重庆，在八年间蒋中正为统帅的抗日力量共进行了22次大会战，和成千上万次大小战斗。1945年，二战结束后，当时的中国国民政府从日本手里获得了台湾及澎湖列岛以及其他一些领土，但也在1946年与苏联签订的条约中承认了外蒙古的独立（1951年，迁往台湾的国民党国民政府以苏联未履约为由，不承认该条约及依据该条约而独立的外蒙古的独立地位；但是，蒙古独立已为既成事实）。1946年6月，国共两党又进行了内战。中国共产党最终于1949年获得决定性胜利，中华民国中央政府迁往战后的台湾。中华人民共和国在北平成立，并将北平改名为北京，毛泽东宣布中华人民共和国政府为包括台湾在内的全中国的唯一合法政府。与此同时，蒋介石宣布台北为中华民国临时首都，宣誓三年内反攻大陆。（请参看台湾问题）\n" +
+"\n" +
+"中共执政之初，采取“土地革命”“公私合营”等手段，国内纷乱的局势暂时得到了稳定。按照中共的史观，自1956年“三大改造”完成后，中国正式进入社会主义阶段。并制订第一个五年计划，大力发展重工业，国家经济一度好转。但是1958年，毛泽东发动“大跃进”运动与人民公社话运动，各地浮夸风“放卫星”等谎报数据的情况盛行。自1959年到1961年，国家经济又陷入濒临崩溃的境地，中共称其为“三年自然灾害”。毛泽东因此退居幕后，以刘少奇为首的一批官僚着手恢复经济，国家形式得到了回稳。1966年，文化大革命爆发，刘少奇、贺龙等人被打倒，毛泽东再度成为政治领导，林彪一度成为内定接班人。在林彪阴谋败露后，四人帮成为新的重要政治势力。1976年，周恩来朱德先后去世；9月9日，毛泽东去世。华国锋接替了毛的领导地位，四人帮被打倒。但是华提出了“两个凡是”的路线，国家实质上仍然没有完全脱离文化大革命阶段。 1978年，邓小平复出，中共十一届三中全会召开，改革开放时代正式到来。中国的经济开始步入正轨。但是，由于通货膨胀与政治腐败，民间不满情绪开始酝酿。胡耀邦的去世成为愤怒爆发的导火索，终致爆发了六四事件。从此以后，改革的步伐一度停滞，直到1992年邓小平南巡后才得以改变。1997年，中国收复香港的主权，江泽民也接替邓成为了新的中国领导人。2002 年后，胡锦涛成为新的国家领导人，上海帮淡出政治中心。中共政府近几年渐渐放弃“韬光养晦”的外交方针，在外交舞台上动作频繁，并加强对台湾的攻势。经济改革依然得到了持续，但政治改革的话题仍然是禁忌。而由于贫富差距的拉大与政治腐败不见好转，民间对中共的评价与看法也日益两极。\n" +
+"\n" +
+"至于中华民国，在国府迁台后，国民党始终保持对政治与言论自由的强力控制。1986年，中华民国第一个反对党民主进步党成立，威权时代的戒严体制开始松动。1987年，中华民国政府正式宣告台湾省解严，进入了一个新的时代。之后，1996年实现了第一次民选总统；2000年更实现第一次政党和平轮替。2005年，末代国民大会召开，中华民国宪法出现了重大修改。今后，民主化的中华民国仍然充满变量。\n" +
+"\n" +
+"[编辑] 参见\n" +
+"\n" +
+"    * 中国\n" +
+"    * 中国历史年表\n" +
+"    * 中国历史事件列表\n" +
+"    * 诸侯会盟\n" +
+"    * 中国历史地图\n" +
+"\n" +
+"	\n" +
+"\n" +
+"    * 中华人民共和国历史年表\n" +
+"    * 中华人民共和国史\n" +
+"    * 汉学\n" +
+"    * 中华文明\n" +
+"    * 中国历史大事年表\n" +
+"\n" +
+"	\n" +
+"\n" +
+"    * 中国文化\n" +
+"    * 中国行政区划\n" +
+"    * 中国朝代\n" +
+"    * 夏商周断代工程\n" +
+"    * 中国古都\n" +
+"\n" +
+"	\n" +
+"\n" +
+"    * 中国战争列表\n" +
+"    * 中国国旗\n" +
+"    * 中国皇帝\n" +
+"    * 中国历代王朝君主世系表\n" +
+"    * 中国君王诸子女列表\n" +
+"    * 中华民国历史\n" +
+"\n" +
+"[编辑] 其他特定主题中国史\n" +
+"\n" +
+"    * 中国军事史\n" +
+"    * 中国科学技术史\n" +
+"    * 中国文化史\n" +
+"    * 中国文学史\n" +
+"    * 中国艺术史\n" +
+"    * 中国经济史\n" +
+"    * 中国体育史\n" +
+"    * 中国人口史\n" +
+"    * 中国疆域史\n" +
+"    * 中国盗墓史\n" +
+"    * 中国酷刑史\n" +
+"    * 中国食人史\n" +
+"    * 中国盐业史\n" +
+"\n" +
+"[编辑] 注解\n" +
+"\n" +
+"   1. ↑ 柳翼谋：《中国文化史》\n" +
+"\n" +
+"[编辑] 参考文献\n" +
+"\n" +
+"   1. 白寿彝主编：中国通史纲要，1993年上海：人民出版社，ISBN 7208001367\n" +
+"   2. 周谷城著：中国通史，1995年上海：人民出版社，ISBN 7208003300\n" +
+"   3. 李敖著：独白下的传统，2000年香港：三联书店（香港）有限公司，ISBN 9620418913\n" +
+"   4. 范文澜著：中国近代史，1962年北京：人民出版社，统一书号 11001241\n" +
+"   5. 徐中约著：中国近代史(上册)，香港2001 中文大学出版社，ISBN 9622019870\n" +
+"   6. Korotayev A., Malkov A., Khaltourina D. Introduction to Social Macrodynamics: Secular Cycles and Millennial Trends. Moscow: URSS, 2006. ISBN 5-484-00559-0 [1] (Chapter 2: Historical Population Dynamics in China).\n" +
+"\n" +
+"[编辑] 相关著作\n" +
+"\n" +
+"    * 《二十四史》 （正史）\n" +
+"    * 《国史要义》 柳诒徵\n" +
+"    * 《国史大纲》 钱穆\n" +
+"    * 《中华五千年史》 张其昀\n" +
+"\n" +
+"[编辑] 外部链接\n" +
+"维基共享资源中相关的多媒体资源：\n" +
+"中国历史\n" +
+"\n" +
+"    * 中华万年网\n" +
+"    * 一个全面专门研究中华历史的论坛：中华历史网论坛\n" +
+"    * （正体中文 - 台湾）《中国大百科全书》：中国历史概述\n";
+
+var cyrillic =
+"История Китая\n" +
+"[править]\n" +
+"Материал из Википедии — свободной энциклопедии\n" +
+"Перейти к: навигация, поиск\n" +
+"История Китая\n" +
+"История Китая\n" +
+"Три властителя и пять императоров\n" +
+"Династия Ся\n" +
+"Династия Шан\n" +
+"Династия Чжоу 	\n" +
+"Западное Чжоу\n" +
+"Восточное Чжоу 	Чуньцю\n" +
+"Чжаньго\n" +
+"Династия Цинь\n" +
+"(Династия Чу) - смутное время\n" +
+"Династия Хань 	Западная Хань\n" +
+"Синь, Ван Ман\n" +
+"Восточная Хань\n" +
+"Эпоха Троецарствия 	Вэй 	Шу 	У\n" +
+"Цзинь\n" +
+"	Западная Цзинь\n" +
+"Шестнадцать варварских государств 	Восточная Цзинь\n" +
+"Северные и Южные Династии\n" +
+"Династия Суй\n" +
+"Династия Тан\n" +
+"Ляо\n" +
+"	\n" +
+"5 династий и 10 царств\n" +
+"Северная Сун\n" +
+"	\n" +
+"Сун\n" +
+"Цзинь\n" +
+"	\n" +
+"Западная Ся\n" +
+"	\n" +
+"Южная Сун\n" +
+"Династия Юань\n" +
+"Династия Мин\n" +
+"Династия Цин\n" +
+"Китайская республика\n" +
+"Китайская Народная Республика\n" +
+"	Китайская республика (Тайвань)\n" +
+"\n" +
+"Китайская цивилизация — одна из старейших в мире. По утверждениям китайских учёных, её возраст может составлять пять тысяч лет, при этом имеющиеся письменные источники покрывают период не менее 3500 лет. Наличие систем административного управления, которые совершенствовались сменявшими друг друга династиями, ранняя освоенность крупнейших аграрных очагов в бассейнах рек Хуанхэ и Янцзы создавало преимущества для китайского государства, экономика которого основывалась на развитом земледелии, по сравнению с соседями-кочевниками и горцами. Ещё более укрепило китайскую цивилизацию введение конфуцианства в качестве государственной идеологии (I век до н. э.) и единой системы письма (II век до н. э.).\n" +
+"Содержание\n" +
+"[убрать]\n" +
+"\n" +
+"    * 1 Древний Китай\n" +
+"    * 2 Государство Шан-Инь\n" +
+"    * 3 Государство Чжоу (XI—III вв. до н. э.)\n" +
+"    * 4 Империя Цинь\n" +
+"    * 5 Империя Хань\n" +
+"    * 6 Государство Цзинь и период Нань-бэй чао (IV—VI вв.)\n" +
+"    * 7 Государство Суй (581—618)\n" +
+"    * 8 Государство Тан\n" +
+"    * 9 Государство Сун\n" +
+"    * 10 Монголы и государство Юань (1280—1368)\n" +
+"    * 11 Государство Мин (1368—1644)\n" +
+"    * 12 Государство Цин\n" +
+"          o 12.1 Внешняя экспансия Цин\n" +
+"          o 12.2 Цинский Китай и Россия\n" +
+"          o 12.3 Опиумные войны\n" +
+"          o 12.4 Японо-китайская война 1894—1895 годов\n" +
+"          o 12.5 Тройственная интервенция\n" +
+"          o 12.6 Успехи русской политики в Китае\n" +
+"          o 12.7 Захват Цзяочжоу Германией\n" +
+"          o 12.8 Сто дней реформ\n" +
+"    * 13 XX век\n" +
+"          o 13.1 Боксерское восстание\n" +
+"          o 13.2 Русско-японская война\n" +
+"          o 13.3 Смерть Цыси\n" +
+"          o 13.4 Аннексия Кореи\n" +
+"          o 13.5 Революция 1911 года и создание Китайской Республики\n" +
+"          o 13.6 Первая мировая война\n" +
+"          o 13.7 Эра милитаристов\n" +
+"          o 13.8 Победа Гоминьдана\n" +
+"          o 13.9 Японская оккупация и Вторая мировая война\n" +
+"          o 13.10 Создание Китайской Народной Республики\n" +
+"          o 13.11 Культурная революция\n" +
+"          o 13.12 Экономическая либерализация\n" +
+"    * 14 См. также\n" +
+"    * 15 Литература\n" +
+"\n" +
+"[править] Древний Китай\n" +
+"\n" +
+"Китайская цивилизация (предков государствообразующего этноса хань) — группа культур (Баньпо 1, Шицзя, Баньпо 2, Мяодигоу, Чжуншаньчжай 2, Хоуган 1 и др.) среднего неолита (ок. 4500-2500 до н.э.) в бассейне реки Хуанхэ, которые традиционно объединяются общим названием Яншао. Представители этих культур выращивали зерновые (чумиза и др.) и занимались разведением скота (свиньи). Позднее в этом районе появились ближневосточные виды злаков (пшеница и ячмень) и породы домашнего скота (коровы, овцы, козы).\n" +
+"\n" +
+"[править] Государство Шан-Инь\n" +
+"\n" +
+"Первым известным государством бронзового века на территории Китая было государство Шан-Инь, сформировавшееся в XIV веке до н. э. в среднем течении реки Хуанхэ, в районе Аньяна.\n" +
+"\n" +
+"В результате войн с соседними племенами его территория расширилась и к XI веку до н. э. охватывала территории современных провинций Хэнань и Шаньси, а также часть территории провинций Шэньси и Хэбэй. Уже тогда появились зачатки лунного календаря и возникла письменность — прообраз современного иероглифического китайского письма. Иньцы значительно превосходили окружающие их племена и с военной точки зрения — у них было профессиональное войско, использовавшее бронзовое оружие, луки, копья и боевые колесницы. Иньцы практиковали человеческие жертвоприношения — чаще всего в жертву приносились пленные.\n" +
+"\n" +
+"В XI веке до н. э. государство Инь было завоёвано немногочисленным западным племенем Чжоу, которое до этого находилось в вассальных отношениях с иньцами, но постепенно укрепилось и создало коалицию племён.\n" +
+"\n" +
+"[править] Государство Чжоу (XI—III вв. до н. э.)\n" +
+"Китайская медная монета в виде мотыги. Провинция Лоян, V-III в. до н.э.\n" +
+"Китайская медная монета в виде мотыги. Провинция Лоян, V-III в. до н.э.\n" +
+"\n" +
+"Обширная территория государства Чжоу, охватывавшая практически весь бассейн Хуанхэ, со временем распалась на множество соперничающих между собой самостоятельных государственных образований — изначально, наследственных уделов на территориях, заселённых различными племенами и расположенных на удалении от столиц — Цзунчжоу (западной - около г. Сиань) и Чэнчжоу (восточной - Лои, Лоян). Эти уделы предоставлялись во владение родственникам и приближённым верховного правителя — обычно чжоусцам. В междоусобной борьбе число первоначальных уделов постепенно сокращалось, а сами уделы укреплялись и становились более самостоятельными.\n" +
+"\n" +
+"Население Чжоу было разнородным, причём наиболее крупную и развитую его часть составляли иньцы. В государстве Чжоу значительная часть иньцев была расселена на новых землях на востоке, где была построена новая столица — Чэнчжоу (современная провинция Хэнань).\n" +
+"\n" +
+"Для периода Чжоу в целом характерно активное освоение новых земель, расселение и этническое смешивание выходцев из различных районов, уделов (впоследствии — царств), что способствовало созданию фундамента будущей китайской общности.\n" +
+"\n" +
+"Период Чжоу (XI—III вв. до н. э.) делится на так называемые Западное и Восточное Чжоу, что связано с переездом правителя Чжоу в 770 до н. э. под угрозой нашествия варварских племён из Цзунчжоу — первоначальной столицы государства — в Чэнчжоу. Земли в районе старой столицы были отданы одному из союзников правителя государства, который создал здесь новый удел Цинь. Впоследствии именно этот удел станет центром единой китайской империи.\n" +
+"\n" +
+"Период Восточное Чжоу, в свою очередь, разделяется на два периода:\n" +
+"\n" +
+"    * Чуньцю ( «Период Весны и Осени» VIII—V вв. до н. э.);\n" +
+"    * Чжаньго («Период Сражающихся царств», V—III вв. до н. э.).\n" +
+"\n" +
+"В период Восточного Чжоу власть центрального правителя — вана, сына Неба (тянь-цзы), правящего Поднебесной по Мандату Неба (тянь-мин), — постепенно ослабла, а ведущую политическую роль стали играть сильные уделы, превращавшиеся в крупные царства. Большинство из них (за исключением окраинных) именовали себя «срединными государствами» (чжун-го), ведущими своё происхождение от раннечжоуских уделов.\n" +
+"\n" +
+"В период Восточного Чжоу формируются основные философские школы древнего Китая — конфуцианство (VI—V вв. до н. э.), моизм (V в. до н. э.), даосизм (IV в. до н. э.), легизм.\n" +
+"\n" +
+"В V—III вв. до н.э. (период Чжаньго) Китай вступает в железный век. Расширяются сельскохозяйственные площади, увеличиваются ирригационные системы, развиваются ремёсла, революционные изменения происходят в военном деле.\n" +
+"\n" +
+"В период Чжаньго на территории Китая сосуществовало семь крупнейших царств — Вэй, Чжао и Хань (ранее все три входили в царство Цзинь), Цинь, Ци, Янь и Чу. Постепенно в результате ожесточённого соперничества верх стало одерживать самое западное — Цинь. Присоединив одно за другим соседние царства, в 221 до н. э. правитель Цинь — будущий император Цинь Ши Хуан — объединил весь Китай под своей властью.\n" +
+"\n" +
+"Так в середине III века до н. э. завершился период Восточного Чжоу.\n" +
+"\n" +
+"[править] Империя Цинь\n" +
+"\n" +
+"Объединив древнекитайские царства, император Цинь Ши Хуан конфисковал всё оружие у населения, переселил десятки тысяч семей наследственной знати из различных царств в новую столицу — Сяньян и разделил огромную страну на 36 новых областей, которые возглавили назначаемые губернаторы.\n" +
+"\n" +
+"При Цинь Шихуанди были соединены оборонительные стены (валы) северных чжоуских царств и создана Великая китайская стена. Было сооружено несколько стратегических дорог из столицы на окраины империи. В результате успешных войн на севере гунны (сюнну) были оттеснены за Великую стену. На юге к империи были присоединены значительные территории племён юэ, в том числе северная часть современного Вьетнама.\n" +
+"Строительство Великой китайской стены, протянувшейся на более чем 6700 км, было начато в III веке до н. э. для защиты северных районов Китая от набегов кочевников.\n" +
+"Строительство Великой китайской стены, протянувшейся на более чем 6700 км, было начато в III веке до н. э. для защиты северных районов Китая от набегов кочевников.\n" +
+"\n" +
+"Цинь Шихуанди, строивший все свои реформы на основах легизма с казарменной дисциплиной и жестокими наказаниями провинившихся, преследовал конфуцианцев, предавая их казни (погребение заживо) и сжигая их сочинения — за то, что они смели выступать против установившегося в стране жесточайшего гнёта.\n" +
+"\n" +
+"Империя Цинь прекратила существование вскоре после смерти Цинь Шихуанди.\n" +
+"\n" +
+"[править] Империя Хань\n" +
+"\n" +
+"Вторую в истории Китая империю, получившую название Хань (206 до н. э.—220 н. э.) основал выходец из среднего чиновничества Лю Бан (Гао-цзу), один из военачальников возрожденного царства Чу, воевавших против Цинь после смерти императора Цинь Шихуана в 210 г. до н.э.\n" +
+"\n" +
+"Китай в это время переживал экономический и социальный кризис, вызванный потерей управляемости и войнами военачальников циньских армий с элитами уничтоженных раннее царств, пытавшихся восстановить свою государственность. Из-за переселений и войн значительно сократилась численность сельского населения в основных аграрных районах.\n" +
+"\n" +
+"Важная особенность смены династий в Китае состояла в том, что каждая новая династия приходила на смену предыдущей в обстановке социально-экономического кризиса, ослабления центральной власти и войн между военачальниками. Основателем нового государства становился тот из них, кто мог захватить столицу и насильственно отстранить правившего императора от власти.\n" +
+"\n" +
+"С правления Гао-цзу (206–195 до н.э.) начинается новый период китайской истории, который получил название Западная Хань.\n" +
+"\n" +
+"При императоре У-ди (140—87 до н. э.) была взята на вооружение иная философия — восстановленное и реформированное конфуцианство, которое стало господствующей официальной идеологией вместо дискредитировавшего себя легизма с его жёсткими нормами и бесчеловечной практикой. Именно с этого времени берёт своё начало китайская конфуцианская империя.\n" +
+"\n" +
+"При нем территория ханьской империи значительно расширяется. Были уничтожены вьетское государство Намвьет (территория современной провинции Гуандун, Гуанси-Чжуанского автономного района и север Индокитайского полуострова), вьетские государства в южных частях современных провинций Чжэцзян и Фуцзянь, корейское государство Чосон, присоеденены земли на юго-западе, сюнну оттеснены далее на севере.\n" +
+"\n" +
+"Китайский путешественник Чжан Цянь проникает далеко на запад и описывает многие страны Средней Азии (Фергана, Бактрия, Парфия и др.). Вдоль пройденного им маршрута прокладывается торговый путь через Джунгарию и Восточный Туркестан в страны Средней Азии и Ближнего Востока — так называемый «Великий шёлковый путь». Империя на некоторое время подчиняет себе оазисы-протогосударства вдоль Шёлкового пути и распространяет своё влияние до Памира.\n" +
+"\n" +
+"В I в. н. э. в Китай из Индии начинает проникать буддизм.\n" +
+"\n" +
+"В период с 8 по 23 гг. н. э. власть захватывает Ван Ман, провозглашающий себя императором и основателем государства Синь. Начинается ряд преобразований, который прерывается экологической катастрофой - река Хуанхэ изменила русло. Из-за трехлетнего голода центральная власть ослабла. В этих условиях началось движение представителей рода Лю за возвращение престола. Ван Ман был убит, столица взята, власть возвратилась династии Лю.\n" +
+"\n" +
+"Новый период получил название Восточная Хань, он продлился до 220 г. н. э.\n" +
+"\n" +
+"[править] Государство Цзинь и период Нань-бэй чао (IV—VI вв.)\n" +
+"\n" +
+"Восточную Хань сменил период Троецарствия (Вэй, Шу и У). В ходе борьбы за власть между военачальниками было основано новое государство Цзинь (265—420).\n" +
+"\n" +
+"В начале IV века Китай подвергается нашествию кочевников — сюнну (гуннов), сяньбийцев, цянов, цзе и др. Весь Северный Китай был захвачен кочевниками, которые создали здесь свои царства, так называемые 16 варварских государств Китая. Значительная часть китайской знати бежала на юг и юго-восток, основанное там государство получило название Восточная Цзинь.\n" +
+"\n" +
+"Кочевники приходят волнами, одна за другой, и после каждой из этих волн в Северном Китае возникают новые царства и правящие династии, которые, однако, принимают классические китайские названия (Чжао, Янь, Лян, Цинь, Вэй и др.).\n" +
+"\n" +
+"В это время, с одной стороны, происходит варваризация образа жизни оседлых китайцев — разгул жестокости, произвола, массовых убийств, нестабильности, казней и бесконечных переворотов. А с другой стороны, пришельцы-кочевники активно стремятся использовыть китайский опыт управления и китайскую культуру для стабилизации и упрочения своей власти — мощь китайской конфуцианской цивилизации в конечном счёте гасит волны нашествий варварских племён, которые подвергаются китаизации. К концу VI века потомки кочевников практически полностью ассимилируются с китайцами.\n" +
+"\n" +
+"На севере Китая верх в столетней борьбе между некитайскими царствами берёт сяньбийское государство Тоба Вэй (Северная Вэй), объединившее под своей властью весь Северный Китай (бассейн Хуанхэ) и к концу V века в борьбе против южнокитайского государства Сун распространившее своё влияние до берегов Янцзы. При этом уже в VI веке, как было сказано, захватчики-сяньбийцы ассимилировались с подавляющим большинством местного населения.\n" +
+"\n" +
+"С началом варварских вторжений на север Китая, сопровождавшихся массовым уничтожением и порабощением местного населения, до миллиона местных жителей — в первую очередь знатных, богатых и образованных, включая императорский двор, — перебрались на юг, в районы, сравнительно недавно присоединённые к империи. Пришельцы с севера, заселив речные долины, активно занялись выращиванием риса и постепенно превратили Южный Китай в основной земледельческий район империи. Уже в V веке здесь стали собирать по два урожая риса в год. Резко ускорилась китаизация и ассимиляция местного населения, колонизация новых земель, строительство новых городов и развитие старых. На юге сосредоточился центр китайской культуры.\n" +
+"\n" +
+"Одновременно здесь укрепляет свои позиции буддизм — на севере и юге построено уже несколько десятков тысяч монастырей с более чем 2 млн. монахов. В немалой степени распространению буддизма способствует ослабление официальной религии — конфуцианства — в связи с варварскими вторжениями и междоусобицами. Первыми китайскими буддистами, способствовавшими популяризации новой религии, были приверженцы даосизма — именно с их помощью переводились с санскрита на китайский древние буддийские тексты. Буддизм постепенно стал процветающей религией.\n" +
+"\n" +
+"[править] Государство Суй (581—618)\n" +
+"\n" +
+"Процесс китаизации варваризованного севера и колонизованного юга создаёт предпосылки для нового объединения страны. В 581 севернокитайский полководец Чжоу Ян Цзянь объединяет под своей властью весь Северный Китай и провозглашает новую династию Суй (581—618), а после уничтожения южнокитайского государства Чэнь возглавляет объединённый Китай. В начале VII века его сын Ян Ди ведёт войны против корейского государства Когурё (611 - 614) и вьетнамского государства Вансуан, строит Великий канал между Хуанхэ и Янцзы для транспортировки риса с юга в столицу, создаёт роскошные дворцы в столице Лоян, восстанавливает и строит новые участки Великой китайской стены, пришедшей в упадок за тысячу лет.\n" +
+"\n" +
+"Подданные не выдерживают тягот и лишений и восстают. Ян Ди убивают, а династию Суй сменяет династия Тан (618—907), основатель — шансийский феодал Ли Юань.\n" +
+"\n" +
+"[править] Государство Тан\n" +
+"\n" +
+"Правители из династии Лю покончили с выступлениями знати и провели ряд успешных преобразований. Происходит разделение страны на 10 провинций, была восстановлена \"надельная система\", усовершенствовано административное законодательство, укреплена вертикаль власти, оживились торговля и городская жизнь. Значительно увеличились размеры многих городов и численность городского населения.\n" +
+"\n" +
+"К концу VII века усилившееся военное могущество Танской империи приводит к расширению территории Китая за счёт Восточно-Тюркского и Западно-Тюркского каганатов. Государства, расположенные в Джунгарии и Восточном Туркестане, на некоторое время становятся данниками Китая. Корейское государство Когурё покорено и становится Аньдунским наместничеством Китая. Вновь открыт Великий шёлковый путь.\n" +
+"\n" +
+"В VIII—X вв. в Китае получают распространение новые сельскохозяйственные культуры — в частности, чай, хлопок.\n" +
+"\n" +
+"Развивается морская торговля, главным образом через Гуанчжоу (Кантон), с Индией и Ираном, Арабским Халифатом, корейским государством Силла и Японией.\n" +
+"\n" +
+"В VIII веке империю Тан ослабляют конфликты между центральной властью и военными наместниками на периферии. Окончательно господство династии Лю подрывает война Хуан Чао за престол 874—901.\n" +
+"\n" +
+"В течение долгого времени (907—960) в стране не удаётся восстановить единую государственную власть, что связано с междоусобными войнами, особенно на севере страны.\n" +
+"\n" +
+"[править] Государство Сун\n" +
+"\n" +
+"В 960 военачальник Чжао Куан-инь основывает династию Сун (960—1279). Все три столетия Сун прошли под знаком успешного давления на Китай со стороны северных степных народов.\n" +
+"\n" +
+"Ещё в начале X века усилилось развитие и консолидация протомонгольской этнической общности киданей, соседствовавшей с Китаем на северо-востоке. Государство киданей, основанное в 916 и существовавшее по 1125, получило название Ляо. Активно укрепляясь на северных рубежах, кидани отторгли часть китайских территорий (часть современных провинций Хэбэй и Шаньси). Основы управления в государстве Ляо были созданы китайцами и корейцами, на основе китайских иероглифов и из китайских элементов письма была создана письменность, развивались города, ремёсла, торговля. Не сумев справиться с соседями и вернуть утраченные территории, Сунская империя была вынуждена пойти на подписание в 1004 мирного договора и согласиться на выплату дани. В 1042 дань была увеличена, а в 1075 Китай отдал киданям ещё часть своей территории.\n" +
+"\n" +
+"В то же время на северо-западных окраинах Сунской империи, к западу от киданей, на рубеже X—XI вв. складывается сильное государство тангутов — Западное Ся. Тангуты отторгли от Китая часть современной провинции Шэньси, целиком территорию современной провинции Ганьсу и Нинся-Хуэйского автономного района. С 1047 Сунской империи пришлось и тангутам платить дань серебром и шёлком.\n" +
+"\n" +
+"Несмотря на вынужденные территориальные уступки соседям период Сун считается эпохой экономического и культурного расцвета Китая. Растёт число городов, продолжается рост численности городского населения, китайские ремесленники достигают высот в изготовлении изделий из фарфора, шёлка, лака, дерева, слоновой кости и др. Изобретены порох и компас, распространяется книгопечатание, выводятся новые высокоурожайные сорта зерновых, увеличиваются посевы хлопка. Одной из наиболее впечатляющих и эффективных из данных инноваций было вполне сознательное, систематическое и хорошо организованное внедрение и распространение новых сортов скороспелого риса из Южного Вьетнама (Чампы).\n" +
+"Чжан Цзэдуань. «По реке в День поминовения усопших» (XII век).\n" +
+"Чжан Цзэдуань. «По реке в День поминовения усопших» (XII век).\n" +
+"\n" +
+"В XII веке Китаю приходится отдать ещё большую территорию новым захватчикам — южноманьчжурским чжурчжэням, создавшим (на базе уничтоженной ими в 1125 империи киданей Ляо) государство (впоследствии — империю) Цзинь (1115—1234), границы которой проходили по р. Хуайхэ. При этом часть разбитых киданей ушла на запад, где в районе рек Талас и Чу сложилось небольшое государство кара-китаев — Западное Ляо (1124—1211).\n" +
+"\n" +
+"В 1127 чжурчжэни захватывают столицу империи Сун — Кайфын и берут в плен императорскую семью. Один из сыновей императора бежит на юг, в Ханчжоу, который впоследствии становится столицей новой — южносунской империи (1127—1280). Продвижение армии чжурчжэней на юг сдерживает лишь река Янцзы. Граница между Цзинь и южносунской империей устанавливается по междуречью Хуанхэ и Янцзы. Северный Китай вновь на длительное время оказывается под господством иноземных завоевателей.\n" +
+"\n" +
+"В 1141 подписан мирный договор, согласно которому Сунская империя признаёт себя вассалом империи Цзинь и обязуется платить ей дань.\n" +
+"\n" +
+"[править] Монголы и государство Юань (1280—1368)\n" +
+"\n" +
+"В начале XIII века в Китай вторгаются монголы. До XIII века монголы являлись частью большой степной общности, которую китайцы называли \"татарами\". Их предшественники — протомонгольские и раннемонгольские группы и народы, одним из которых были кидани, представляли собой степных кочевников, разводивших лошадей и рогатый скот, кочевавших от пастбища к пастбищу и организованных в небольшие родоплеменные коллективы, связанные общностью происхождения, языка, культуры и т. п.\n" +
+"\n" +
+"Соседство развитой китайской цивилизации способствовало ускорению процесса создания племён, а затем и мощных племенных союзов во главе с влиятельными вождями. В 1206 на всемонгольском курултае вождём всех монголов был провозглашён победивший в жестокой междоусобной борьбе Темучин, принявший имя и титул Чингисхана.\n" +
+"\n" +
+"Чингисхан создал организованную и боеспособную армию, которая и стала решающим фактором в последующих успехах сравнительно немногочисленного монгольского этноса.\n" +
+"\n" +
+"Покорив соседние народы Южной Сибири, Чингисхан в 1210 пошёл войной на чжурчжэней и в 1215 взял Пекин.\n" +
+"\n" +
+"В 1219—1221 была разорена Средняя Азия и разбито государство Хорезмшахов. В 1223 — разбиты русские князья, в 1226—1227 — уничтожено государство тангутов. В 1231 основные силы монголов вернулись в Северный Китай и к 1234 завершили разгром чжурчжэньского государства Цзинь.\n" +
+"\n" +
+"Завоевания в Южном Китае были продолжены уже в 1250-х, после походов в Европу и на Ближний и Средний Восток. Вначале монголы захватили страны, окружавшие Южно-Сунскую империю — государство Дали (1252—1253), Тибет (1253). В 1258 монгольские войска под предводительством хана Хубилая с разных сторон вторглись в Южный Китай, но осуществлению их планов помешала неожиданная смерть Великого хана Мункэ (1259). Хан Хубилай, захватив ханский престол, в 1260 перенёс столицу из Каракорума на территорию Китая (сначала в Кайпин, а в 1264 в Чжунду — современный Пекин). Столицу южносунского государства Ханчжоу монголам удалось взять лишь в 1276. К 1280 весь Китай был завоёван, а Сунская империя — уничтожена.\n" +
+"\n" +
+"После покорения Китая хан Хубилай основывает новую династию Юань (1271—1368), на службу новой власти привлекаются кидани, чжурчжэни, тюрки и даже европейцы — в частности, в это время Китай посещает венецианский купец Марко Поло.\n" +
+"\n" +
+"Тяжёлый экономический, политический и национальный гнёт, установленный монгольскими феодалами, сдерживает развитие страны. Множество китайцев было обращено в рабство. Земледелие и торговля были подорваны. Не выполнялись необходимые работы по поддержанию ирригационных сооружений (дамб и каналов), что привело в 1334 к чудовищному наводнению и гибели нескольких сот тысяч человек. Великтий Китайский канал был построен во время монгольского господства.\n" +
+"\n" +
+"Народное недовольство новыми правителями вылилось в мощное патриотическое движение и восстания, которые возглавили руководители тайного общества «Белый лотос» (Байляньцзяо).\n" +
+"\n" +
+"[править] Государство Мин (1368—1644)\n" +
+"\n" +
+"В результате длительной борьбы в середине XIV века монголы были изгнаны. К власти пришёл один из руководителей восстания — сын крестьянина Чжу Юаньчжан, основавший государствоМин (1368—1644).\n" +
+"\n" +
+"Монголы, оттеснённые на север, приступают к активному освоению степей современной Монголии. Империя Мин подчиняет себе часть чжурчжэньских племён, государство Наньчжао (современные провинции Юньнань и Гуйчжоу), часть современных провинций Цинхай и Сычуань.\n" +
+"\n" +
+"Китайский флот под командой Чжэн Хэ, состоящий из нескольких десятков многопалубных фрегатов, за период с 1405 по 1433 совершает несколько морских экспедиций в Юго-Восточную Азию, Индию и к восточному побережью Африки. Не принеся Китаю никакой экономической выгоды, экспедиции были прекращены, а корабли — разобраны.\n" +
+"\n" +
+"В XVI веке происходит первая попытка усилившейся Японии вторгнуться в Китай и Корею. В это же время в Китай проникают европейцы — португальцы, испанцы, голландцы. В 1557 Португалия овладела на правах «аренды» китайской территорией Аомынь (Макао). В Китае появляются и христианские миссионеры — иезуиты. Они привезли в Китай новые инструменты и механизмы — часы, астрономические приборы, наладили здесь производство огнестрельного оружия. В то же время они занимаются доскональным изучением Китая.\n" +
+"\n" +
+"[править] Государство Цин\n" +
+"\n" +
+"К концу XVI века северные соседи империи Мин — потомки чжурчжэньских племён, разбитых в своё время Чингисханом, — объединяются вокруг владения Маньчжоу под предводительством вождя Нурхаци (1559—1626). В 1609 Нурхаци прекращает платить дань Китаю, а затем провозглашает собственную династию Цзинь. С 1618 маньчжуры усиливают вооружённое давление на Китай. За восемь лет они выходят практически к Великой китайской стене (на крайнем востоке).\n" +
+"\n" +
+"Преемник Нурхаци Абахай провозглашает себя императором и меняет название династии на Цин. В начале XVII века маньчжуры завоевали Южную (Внутреннюю) Монголию. На всей территории Южной Маньчжурии и захваченных ханств Южной Монголии устанавливается централизованная администрация.\n" +
+"\n" +
+"Маньчжурская конница, поддержанная внутренними монголами, начинает совершать регулярные набеги на Китай, грабя и обращая в рабство сотни тысяч китайцев. Императору Мин приходится направить на северные рубежи свою лучшую армию под командованием У Саньгуя. Тем временем в Китае разгорается очередное крестьянское восстание. В 1644 крестьянские отряды под предводительством Ли Цзычэна, разгромив все остальные армии, занимают Пекин, а сам Ли Цзычэн провозглашает себя императором. У Саньгуй пропускает маньчжурскую конницу на Пекин. 6 июня 1644 маньчжуры захватывают столицу. Ли Цзычэн вскоре гибнет, а маньчжуры объявляют своего малолетнего императора Шуньчжи правителем всего Китая. У Саньгуй вместе со всей армией переходит на службу к завоевателям.\n" +
+"\n" +
+"Борьба против маньчжурских захватчиков продолжается ещё долго, но ослабленный Китай не в силах противостоять хорошо вооружённому и организованному войску. Последний оплот сопротивления — Тайвань захвачен маньчжурами в 1683.\n" +
+"\n" +
+"Маньчжурская династия в государстве Цин правила с 1644 по 1911 год. В руках маньчжурской знати находились высшие органы власти и руководство армией. Смешанные браки были запрещены, и тем не менее маньчжуры быстро китаизировались, тем более что, в отличие от монголов, они не противопоставляли себя китайской культуре.\n" +
+"\n" +
+"Начиная с Канси (годы правления 1662—1723), маньчжурские императоры были ревностными конфуцианцами, управляя страной по древним законам. Китай под властью династии Цин в XVII—XVIII вв. развивался достаточно интенсивно. К началу XIX века в Китае насчитывалось уже около 300 млн. человек — примерно в пять раз больше, чем в среднем на протяжении предыдущих двух тысяч лет. Демографическое давление привело к необходимости интенсификации сельского хозяйственного производства при активном участии государства. Маньчжуры обеспечили покорность китайского населения, но при этом заботились о процветании экономики страны и благосостоянии народа.\n" +
+"\n" +
+"[править] Внешняя экспансия Цин\n" +
+"\n" +
+"Правители государства Цин проводили политику изоляции Китая от внешнего мира. Европейская колонизация почти не затронула Китай. Католические миссионеры играли заметную роль при императорском дворе до конца XVII века, после чего христианские церкви были постепенно закрыты, а миссионеры — высланы из страны. В середине XVIII века была ликвидирована торговля с европейцами, за исключением одного порта в Кантоне (Гуанчжоу). Опорным пунктом иностранной торговли оставался остров Макао, находившийся под контролем португальцев.\n" +
+"\n" +
+"В первые два столетия цинской династии Китай, закрытый от повседневных контактов с внешним миром, проявлял себя как сильное независимое государство, осуществляющее экспансию во всех направлениях.\n" +
+"\n" +
+"Вассалом Китая была Корея. В середине XVIII века в империю вошла Северная (Внешняя) Монголия. В 1757 было уничтожено Джунгарское ханство, и территория его вместе с покорённым к 1760 Восточным Туркестаном была включена в состав Цинской империи под названием Синьцзян («Новая граница»). После ряда походов маньчжуро-китайской армии против Тибета этот район был в конце XVIII века присоединён к Цинской империи. Войны Цинской империи против Бирмы (1765—1769) и Вьетнама (1788—1789) оказались неудачными и закончились поражением цинских войск.\n" +
+"\n" +
+"Одновременно осуществлялась экспансия на север и северо-восток, что неминуемо привело к конфликту с Россией в Приамурье. В течение двух веков территория Китая увеличилась практически вдвое. Цинская империя обзавелась своего рода буферными зонами — Маньчжурией, Монголией, Тибетом, Синьцзяном — которые охраняли китайские земли.\n" +
+"\n" +
+"В цинском Китае любые официальные представители иностранных государств рассматривались исключительно как представители вассальных государств — реальных или потенциальных.\n" +
+"\n" +
+"[править] Цинский Китай и Россия\n" +
+"\n" +
+"    Основная статья: Российско-китайские отношения\n" +
+"\n" +
+"Первые шаги по установлению русско-китайских отношений были предприняты Россией в конце периода Мин (миссия И. Петлина в 1618—1619), но основные миссии (Фёдора Байкова в 1654—1657, Николая Спафария в 1675—1678 и др.) последовали уже в цинский период. Параллельно с миссиями шло продвижение на восток русских казаков — походы первопроходцев Василия Пояркова (1643—1646) и Ерофея Хабарова (1649—1653) положили начало освоению русскими людьми Приамурья и привели к присоединению его к России, в то время как маньчжуры считали эти районы своей вотчиной.\n" +
+"\n" +
+"В середине XVII века на обоих берегах Амура уже существовали русские крепости-остроги (Албазинский, Кумарский и др.), крестьянские слободы и пашни. В 1656 было образовано Даурское (позднее — Албазинское) воеводство, в которое входила долина Верхнего и Среднего Амура по обоим берегам.\n" +
+"\n" +
+"Хотя граница империи Цин тогда проходила чуть севернее Ляодунского полуострова («Ивовый палисад»), в 1650-е годы и позднее Цинская империя попыталась военной силой захватить русские владения в бассейне Амура и предотвратить принятие местными племенами российского подданства. Маньчжурское войско на какое-то время вытеснило казаков из крепости Албазин. Вслед за миссиями Фёдора Байкова и Николая Спафария Россия направила в 1686 к пограничным властям на Амуре полномочное посольство Фёдора Головина для мирного урегулирования конфликта.\n" +
+"\n" +
+"Переговоры велись в окружении многотысячной маньчжурской армии. С китайской стороны в переговорах участвовали миссионеры-иезуиты, противившиеся соглашению Китая с Россией, что ещё более осложняло обстановку. Китай отказался определить русско-китайскую границу по Амуру, потребовав себе всё Албазинское воеводство, всё Забайкалье, а впоследствии — вообще все земли к востоку от Лены.\n" +
+"\n" +
+"Угрожая захватить Нерчинск штурмом, цинские представители вынудили Головина согласиться на уход русских с Верхнего и Среднего Амура. По Нерчинскому договору Россия была вынуждена уступить Цинской империи свои владения по правому берегу р. Аргунь и на части левого и правого берегов Амура. Казаки были обязаны разрушить и оставить Албазин. Вследствие разночтений в текстах договора, составленных каждой из сторон, однако, большая территория оказалась неразграниченной и фактически превратилась в буферную зону между двумя государствами. Разграничение между Россией и Китаем в пределах этой зоны завершилось в XIX веке. Окончательно граница России с Китаем на Дальнем Востоке была определена Айгуньским (1858) и Пекинским (1860) договорами; она прошла по рекам Амур и Уссури через озеро Ханка и горные хребты до р. Туманьцзян; русско-китайское территориальное разграничение в Центральной Азии было завершено к середине 1890-х.\n" +
+"\n" +
+"[править] Опиумные войны\n" +
+"Территория собственно Китая в 1875\n" +
+"Территория собственно Китая в 1875\n" +
+"\n" +
+"К концу XVIII века торговля Китая с внешним миром вновь начала расширяться. Китайский шёлк, фарфор, чай и другие товары пользовались большим спросом в Европе, но китайцы отказывались что-либо покупать у европейцев, так что тем приходилось платить серебром за китайские товары. Тогда англичане начали ввозить в Китай опиум — в основном контрабандой из Индии — и вскоре приобщили к курению опиума местное население, особенно в приморских районах. Ввоз опиума постоянно возрастал и стал подлинным бедствием для страны, что привело к серии Опиумных войн в середине XIX века. Поражение в этих войнах привело к постепенному превращению Китая в фактическую полуколонию европейских держав.\n" +
+"\n" +
+"[править] Японо-китайская война 1894—1895 годов\n" +
+"\n" +
+"В 1874 году Япония захватила Формозу, однако вынуждена была покинуть её по требованию Англии. Тогда Япония обратила свои усилия на Корею, находившуюся в вассальной зависимости от Китая и Манчжурию. В июне 1894 по просьбе корейского правительства Китай направил войска в Корею для подавления крестьянского восстания. Воспользовавшись этим предлогом, Япония также направила сюда свои войска, после чего потребовала от корейского короля проведения «реформ», означавших фактически установление в Корее японского контроля.\n" +
+"\n" +
+"В ночь на 23 июля при поддержке японских войск в Сеуле был организован правительственный переворот. Новое правительство 27 июля обратилось к Японии с «просьбой» об изгнании китайских войск из Кореи. Однако ещё 25 июля японский флот уже без объявления войны начал военные действия против Китая; официальное объявление войны последовало только 1 августа 1894. Началась Японо-китайская война\n" +
+"\n" +
+"В ходе войны превосходство японской армии и флота привело к крупным поражениям Китая на суше и на море (под Асаном, июль 1894; под Пхеньяном, сентябрь 1894; при Цзюляне, октябрь 1894).\n" +
+"\n" +
+"С 24 октября 1894 военные действия перешли на территорию Северо-Восточного Китая. К марту 1895 японские войска захватили Ляодунский полуостров, Вэйхайвэй, Инкоу, под угрозой находился Мукден.\n" +
+"\n" +
+"17 апреля 1895 в Симоносеки представители Японии и Китая подписали унизительный для Китая Симоносекский договор.\n" +
+"\n" +
+"[править] Тройственная интервенция\n" +
+"\n" +
+"Условия, навязанные Японией Китаю, привели к так называемой \"тройственной интервенции\" России, Германии и Франции - держав, которые к этому времени уже поддерживали обширные контакты с Китаем и поэтому восприняли подписанный договор как наносящий ущерб их интересам. 23 апреля 1895 Россия, Германия и Франция одновременно, но по отдельности обратились к японскому правительству с требованием отказа от аннексии Ляодунского полуострова, которая могла бы привести к установлению японского контроля над Порт-Артуром, в то время как Николай II, поддерживаемый западными союзниками, имел собственные виды на Порт-Артур как незамерзающий порт для России. Германская нота была наиболее жесткой, даже оскорбительной для Японии.\n" +
+"\n" +
+"Японии пришлось уступить. 10 мая 1895 года японское правительство заявило о возвращении Китаю Ляодунского полуострова, правда, добившись увеличения суммы китайской контрибуции на 30 миллионов таэлей.\n" +
+"\n" +
+"[править] Успехи русской политики в Китае\n" +
+"\n" +
+"В 1895 году Россия предоставила Китаю заём в 150 миллионов рублей под 4% годовых. Договор содержал обязательство Китая не соглашаться на иностранный контроль над своими финансами, если в нём не будет участвовать Россия. В конце 1895 года по инициативе Витте был основан Русско-Китайский банк. 3 июня 1896 года в Москве был подписан русско-китайский договор об оборонительном союзе против Японии. 8 сентября 1896 года между китайским правительством и Русско-Китайским банком был подписан концессионный договор о сроительстве Китайской Восточной железной дороги. Общество КВЖД получало полосу земли вдоль дороги, которая переходила под его юрисдикцию. В марте 1898 года был подписан русско-китайский договор об аренде Россией Порт-Артура и Ляодунского полуострова.\n" +
+"\n" +
+"[править] Захват Цзяочжоу Германией\n" +
+"\n" +
+"В августе 1897 года Вильгельм II посетил Николая II в Петергофе и добился согласия на устройство немецкой военно-морской базы в Цзяочжоу (в тогдашнем варианте транскрипции - \"Киао-Чао\"), на южном побережье Шаньдуна. В начале ноября в Шаньдуне китайцами были убиты германские миссионеры. 14 ноября 1897 года немцы высадили десант на побережье Цзяочжоу и захватили его. 6 марта 1898 года было подписано германо-китайское соглашение, по которому Китай арендовал Германии Цзяочжоу сроком на 99 лет. Одновременно китайское правительство предоставило Германии концессию на постройку двух железных дорог в Шаньдуне и ряд горных концессий в этой провинции.\n" +
+"\n" +
+"[править] Сто дней реформ\n" +
+"\n" +
+"Непродолжительный период реформ начался 11 июня 1898 с издания маньчжурским императором Цзай Тянем (название годов правления — Гуансюй) указа «Об установлении основной линии государственной политики». Цзай Тянь привлек группу молодых реформаторов — учеников и единомышленников Кан Ювэя для разработки серии указов о реформах. В общей сложности было издано свыше 60 указов, которые касались системы образования, строительства железных дорог, заводов и фабрик, модернизации сельского хозяйства, развития внутренней и внешней торговли, реорганизации вооружённых сил, чистки государственного аппарата и т.д. Период радикальных реформ окончился 21 сентября того же года, когда вдовствующая Императрица Цыси произвела дворцовый переворот и отменила реформы.\n" +
+"\n" +
+"[править] XX век\n" +
+"\n" +
+"[править] Боксерское восстание\n" +
+"\n" +
+"В мае 1900 года в Китае началось большое восстание, получившее название боксерского или Ихэтуаньского восстания. 20 июня в Пекине был убит германский посланник Кеттелер. Вслед за этим восставшими были осаждены дипломатические миссии, находившиеся в особом квартале Пекина. Было осаждено также здание католического кафедрального собора Петанг (Бейтанг). Начались массовые убийства \"ихэтуанями\" китайцев-христиан, в том числе было убито 222 православных китайца. 21 июня 1900 года Императрица Цыси объявила войну Великобритании, Германии, Австро-Венгрии, Франции, Италии, Японии, США и России. Великие державы согласились о совместных действиях против восставших. Главнокомандующим экспедиционными силами был назначен германский генерал Вальдерзее. Однако, когда он прибыл в Китай, Пекин был уже освобожден небольшим передовым отрядом под командованием русского генерала Линевича. Русская армия заняла Манчжурию.\n" +
+"\n" +
+"[править] Русско-японская война\n" +
+"\n" +
+"8 февраля 1904 года началась Русско-японская война за контроль над Манчжурией и Кореей. Война, шедшая на территории Китая была для России неудачной, по её результатам, Россия была вынуждена уступить Японии Порт-Артур и Ляодунский полуостров с частью построенной к тому времени КВЖД.\n" +
+"\n" +
+"[править] Смерть Цыси\n" +
+"\n" +
+"14 декабря 1908 года в один день умерли Императрица Цыси и Император Гуансюй, которого Цыси ранее отстранила от власти. Возможно, Гуансюй был отравлен, так как Цыси не хотела, чтобы он её пережил. На престол взошёл Император Пу И, которому было два года. Регентом назначен его отец князь Чунь, однако вскоре власть перешла к его брату.\n" +
+"\n" +
+"[править] Аннексия Кореи\n" +
+"\n" +
+"В 1910 году Япония аннексировала Корею, хотя японские войска там находились с начала Русско-японской войны.\n" +
+"\n" +
+"[править] Революция 1911 года и создание Китайской Республики\n" +
+"\n" +
+"В 1911 году в Китае началось Учанское восстание. Оно стало началом Синьхайской революции (1911—1913) в Китае, в результате которой было свергнута маньчжурская династия Цин и провозглашено создание Китайской республики.\n" +
+"\n" +
+"После падения монархии правитель Монголии отказался повиноваться республике и отделился от Китая. 3 ноября им было заключено соглашение с Россией. Англия воспользовалась внутренней борьбой в Китае для превращения Тибета в свою зону влияния. Тибет поднялся на борьбу и заставил китайский гарнизон покинуть страну. Все последующие попытки китайцев восстановить там свою власть пресекались Британией. Россия согласилась считать Тибет английской сферой влияния, а Англия признала русские интересы в независимой (внешней) Монголии.\n" +
+"\n" +
+"12 февраля 1912 года Император Пу И отрекся от престола. К власти пришел генерал Юань Шикай премьер-министр и главнокомандующий армией. Вскоре он был провозглашен президентом Китая.\n" +
+"\n" +
+"В 1913 году произошла \"Вторая революция\". Юань Шикай подавил разрозненные выступления в центральных и южных провинциях. В стране устанавливается военная диктатура Юань Шикая, основателя группировки бэйянских (северных) милитаристов. Сунь Ятсен вынужден эмигрировать за границу.\n" +
+"\n" +
+"[править] Первая мировая война\n" +
+"\n" +
+"После начала первой мировой войны китайское правительство объявляет о своем нейтралитете и просит воюющие державы не переносить военные действия на территорию Китая, в том числе и на \"арендованные\" державами китайские земли. Однако 22 августа 1914 года Япония объявила о своем состоянии войны с Германией и высадила 30-тысячную армию севернее Циндао - центра немецкой колонии в провинции Шаньдун. После двухмесячной военной кампании Япония захватила германские владения в Шаньдуне, а также распространила свой контроль на всю территорию провинции.\n" +
+"\n" +
+"В 1915 году китайские принцы голосуют за установленче в Китае монархии с Юанем Шикаем на императорском троне. Распускается парламент. Объявляется монархия. Это вызывает ряд восстаний в провинциях Китая. Независимость от Пекина объявляют провинции Юньнань, Гуйчжоу и Гуанси. Потом отделяются Гуандун, Чжэцзян, Сычуань и Хунань.\n" +
+"\n" +
+"22 марта 1916 года умирает Юань Шикай.\n" +
+"\n" +
+"[править] Эра милитаристов\n" +
+"\n" +
+"После смерти Юань Шикая в Китае начали оформляться многочисленные военно-феодальные вотчины различных милитаристских группировок. Наиболее крупной была бэйянская (северная), делившаяся на фэнтяньскую (маньчжурскую) во главе с бывшим главарем шайки хунхузов Чжан Цзолинем, чжилийскую во главе с генералом Фэн Гочжаном, и аньхойскую во главе с генералом Дуань Цижуем. В провинции Шаньси господствовал милитарист Янь Сишань, заигрывавший с бэйянской группировкой, а в провинции Шэньси - генерал Чэнь Шуфань. Лагерь юго-западных милитаристов состоял из двух крупных группировок: юньнаньской во главе с генералом Тан Цзияо, и гуансийской во главе с генералом Лу Жунтином.\n" +
+"\n" +
+"Под контролем фэнтяньской группировки находились провинции Хэйлунцзян, Гирин и Фэнтянь, под контролем чжилийской - Шаньдун, Цзянсу, Чжэцзян, Фуцзянь, Цзянси, Хунань, Хубэй и часть Чжили. Фэнтяньская и аньхойская клики финансировались Японией, чжилийская - Англией и США. Ли Юаньхун был ставленником юго-западных милитаристов. Вице-президент генерал Фэн Гочжан ориентировался на Англию и США, а премьер-министр генерал Дуань Цижуй держался прояпонского направления. В 1917 году Япония начала предоставлять Дуань Цижую крупные займы, получая за них все новые и новые уступки, в том числе концессии в Маньчжурии.\n" +
+"\n" +
+"[править] Победа Гоминьдана\n" +
+"\n" +
+"Партия Гоминьдан была создана в 1912 году в провинции Гуанчжоу. Примерно в тоже время, в 1921 г., была создана и Китайская коммунистическая партия, малочисленная и не пользовавшаяся в тот период особой популярностью. 8 сентября 1923 в Китай по просьбе Сунь Ятсена, который просил прислать ему человека с которым он мог бы говорить по-английски без переводчика, прибыл агент коминтерна М.М.Бородин, ставший политическим советником ЦИК Гоминьдана и советником Сунь Ятсена. Он организовал сотрудничество между Гоминьданом и КПК. 20 января 1924 г. проходит I Всекитайский съезд Гоминьдана в Гуанчжоу. На съезде был принят курс на союз с китайскими коммунистами и СССР. 16 июня учреждена Военная академия Вампу под руководством Чан Кайши. В первый набор было зачислено 400, во второй - 500, в третий - 800 и четвертый - около 2600 слушателей; при школе было создано два учебных полка. В академию Вампу прибыла большая группа советских военных советников. В октябре 1924 г. в Гуанчжоу на должность главного военного советника прибыл Василий Константинович Блюхер.\n" +
+"В марте 1926 Чан Кайши осуществил в Кантоне военный переворот, изгнал из города коммунистов, а спустя три месяца был избран председателем Гоминьдана и главнокомандующим вооруженными войсками. Добившись высокой власти, Чан Кайши пригласил немецких советников во главе бывшим генералом рейхсвера фон Сектом.\n" +
+"В качестве советников у Чан Кайши действовали офицеры Германии:\n" +
+"\n" +
+"    * полковник В.Бауэр (друг Гитлера и ученик Людендорфа)\n" +
+"    * нацист подполковник Крибель\n" +
+"    * генерал-лейтенант Ветцель\n" +
+"    * генерал Фалькенхаузен\n" +
+"\n" +
+"Гоминьдановцы старательно перенимали опыт нацистов по наведению порядка в стране. Китайские офицеры в организованном порядке направлялись на обучение в Германию.\n" +
+"В 1926 Национально-революционная армия Китая Чан Кайши предприняла так называемый Великий Северный поход. В течение шести месяцев непрерывных боев от власти местных военных правителей были освобождены центральные районы Китая.\n" +
+"В начале 1927 Чан Кайши пошел на открытый развал единого фронта ГМД и КПК: его войска начали разоружение шанхайских рабочих отрядов и дружин, начались массовые аресты и казни профсоюзных деятелей и коммунистов. В ответ на это коммунисты организовали 1 августа в городе Наньчан восстание части гоминьдановских войск, вошедшее в историю Китая как \"Наньчанское восстание\".\n" +
+"В декабре 1927 было поднято коммунистическое восстание в Кантоне, которое гоминьдановцы жесточайшим образом подавили после четырех дней кровопролитных боев.\n" +
+"После нескольких военных операций к 1927 году войска Гоминьдана контролировали большую часть территории Китая.\n" +
+"\n" +
+"[править] Японская оккупация и Вторая мировая война\n" +
+"\n" +
+"Осенью 1931 Япония напала на Китай. 18 сентября после серии провокаций японцы перешли в наступление, за короткое оккупировав всю Манчжурию. В марте 1932 здесь было провозглашено прояпонское марионеточное государство Маньчжоу-Го, которое возглавил Пу И – последний отпрыск маньчжурской династии Цин, свергнутой в годы Синьхайской революции.\n" +
+"\n" +
+"В этих сложных условиях Чан Кайши был вынужден бороться одновременно с тремя врагами: внешней японской агрессией, спорадическими бунтами отдельных милитаристов на местах, и вооружёнными силами КПК, претендовавшими на захват власти в стране. Он выбрал политику компромисса с японцами, с милитаристами вёл дела в зависимости от конкретных обстоятельств, с коммунистами же никакой компромисс был невозможен. В 1934 году основные силы КПК были блокированы в провинции Цзянси. В этих сложных условиях руководство КПК сумело организовать прорыв, и после многомесячного марша привело войска на Северо-Запад страны в т.н. \"особый район\" с центром в городе Яньань; эти события вошли в историю КПК как \"Великий поход\". Чан Кайши планировал продолжать борьбу с коммунистами и там, но тут взбунтовался ряд его генералов, считавших более приоритетной задачей примирение с коммунистами и совместную борьбу с японской агрессией. В результате \"Сианьского инцидента\" было подписано соглашение о создании единого фронта между КПК и Гоминьданом.\n" +
+"\n" +
+"7 июля 1937 конфликтом у моста Лугоуцяо недалеко от Пекина началась «большая» война. С этого момента, по мнению китайских историков, начинается Вторая мировая война.\n" +
+"\n" +
+"\n" +
+"   Этот раздел не завершён. Вы можете помочь проекту, исправив и дополнив его.\n" +
+"Японская оккупация (1940)\n" +
+"Японская оккупация (1940)\n" +
+"\n" +
+"[править] Создание Китайской Народной Республики\n" +
+"\n" +
+"Разгром милитаристской Японии в августе-сентябре 1945 завершил Вторую мировую войну, освободив от порабощения страны Азиатско-Тихоокеанского региона. В Китае шла ожесточенная гражданская война.\n" +
+"Советская Красная Армия полностью оккупировала Манчжурию, приняв капитуляцию фактически у всей японской Квантунской армии. К тому времени на территории Манчжурии действовали лишь разрозненные партизанские отряды и разведгруппы китайских партизан.\n" +
+"В сентябре 1945 начала осуществляться массовая переброска вооруженных сил КПК из северного и Восточного Китая на северо-восток страны. К ноябрю туда перешли около 100 тысяч бойцов 8-ой и 4-ой армий. Из этих частей, партизанских формирований и местных жителей была сформирована Объединенная демократическая армия (ОДА) Северо-Востока, которая стала костяком Народно-освободительной армии Китая.\n" +
+"Советская армия находилась в Манчжурии вплоть до мая 1946. За это время советская сторона помогла китайским коммунистам организовать, обучить и вооружить новые китайские войска. В результате, когда гоминьдановские войска начали в апреле 1946 входить в Манчжурию, они, к своему удивлению, обнаружили там не разрозненные партизанские отряды, а современную дисциплинированную армию коммунистов, вовсе не намеревавшуюся самораспускаться.\n" +
+"Ситуация в Манчжурии стала шоком и для Белого дома. Первый отряд вооруженных сил США в составе двух дивизий морской пехоты высадился в Китае в районе Тяньцзиня еще 30 сентября 1945. К осени в Китае находилось уже свыше 100 тысяч американских военнослужащих.\n" +
+"Американские экспедиционные войска, главным образом части морской пехоты, старались не вмешиваться в отношения между КПК и ГМД. Однако они активно взаимодействовали с вооруженными силами легитимного китайского правительства - войсками Гоминьдана, прежде всего в приеме капитуляции японских войск в Северном и Центральном Китае, а также в поддержании порядка и охране различных важных объектов в китайских городах.\n" +
+"С самого начала командование войск ГМД допустило стратегическую ошибку: несмотря на успехи первых столкновений с ОДА в Манчжурии, военные действия в Северо-Восточном Китае не были доведены до конца, ГМД направил свои усилия не на борьбу с регулярными войсками КПК, а на уничтожение партизанского движения и партизанских баз в Центральном, Восточном и Северном Китае.\n" +
+"Укрепившись с помощью советской стороны, при поддержке местного населения, войска Мао Цзэдуна к осени 1948 достигли численности в 600 тысяч человек. С 1 ноября ОДА стала именоваться 4-й Полевой армией. возглавили ее Линь Бяо.\n" +
+"В ноябре 1948 4-я полевая армия перешла к решительным боевым действиям против гоминьдановцев. За короткие сроки было разбито 52 дивизии Чан Кайши, еще 26 дивизий, обученных военными инструкторами США, перешли на сторону КПК. В начале 1949 армия вошла в Северный Китай, где объединилась с войсками 8-й армии КПК. 15 января был взят Тяньцзинь, 22 января - Пекин.\n" +
+"К весне 1949 вооруженные силы КПК освободили от гоминьдановцев весь Китай севернее реки Янцзы и восточнее провинции Ганьсу. К концу гражданской войны Народно-освободительная армия представляла собой мощную 4-миллионую армию, крупнейшую в Азии.\n" +
+"24 апреля 1949 войска КПК под командованием маршала Лю Бочэна вступили в столицу гоминьдановского Китая - город Нанкин. Само гоминьдановское правительство еще в феврале переехало на юг страны, в Кантон, а затем вместе с остатками верных ему войск - бежало на остров Тайвань.\n" +
+"В конце года Народно-освободительная армия Китая уничтожила все основные группировки Гоминьдана на континенте, победоносно завершив тем самым третью гражданскую войну в Китае.\n" +
+"1 октября 1949 г. в Пекине была провозглашена Китайская Народная Республика.\n" +
+"На следующий же день Советский Союз первым признал КНР и заключил с ней Договор о дружбе, союзе и взаимной помощи. Таким образом, в конце 1949 года родился советско-китайский «монолит» - тот самый, который на многие годы стал кошмаром для Запада.\n" +
+"\n" +
+"[править] Культурная революция\n" +
+"\n" +
+"В 1966 году председателем КПК Мао Цзэдуном была начата культурная революция для утверждения маоизма в качестве единственной государственной идеологии и уничтожения политической оппозиции. Было организовано массовое ополчение молодёжи, называвшееся «красногвардейцы». Красногвардейцы занялись преследованием «контререволюционеров» из числа аппарата КПК, интеллигенции и вообще всех, кто мог им не понравиться.\n" +
+"\n" +
+"[править] Экономическая либерализация\n" +
+"\n" +
+"После падения \"банды четырех\" власть в стране взяли реформаторы Дэн Сяопин и Ху Яобан, которые в конце 1978 года провозгласили на 3-м пленуме ЦК КПК 11-го созыва политику \"реформ и открытости\". Реальный старт \"Экономической реформе\" был дан на XII съезде КПК (1982 г.). На XIII съезде КПК (1987 г.) было дано подробное толкование теории начального этапа социализма, согласно которой социалистический строй и социалистическая экономическая система - разные вещи, т.е. социалистический политический режим не подразумевает безусловной плановой централизации всей экономики, а позволяет использовать и рыночные механизмы, особенно в паре \"государство-предприятие\". На XIV съезде КПК (1992 г.) был провозглашен курс на построение социалистической рыночной экономической системы с китайской спецификой. Данное изменение идеологии хорошо иллюстрирует высказываение Д.Сяопина: \"Неважно какого цвета кошка - главное, чтобы ловила мышей\".\n" +
+"\n" +
+"Фактически введение \"Экономической реформы\" означало настоящую \"революцию сверху\", заключавшуюся в постепенном и частичном сворачивании тоталитарной сталинско-маоистской модели жестко централизованной экономики и переводе части отраслей народного хозяйства на рыночные рельсы, но при полностью неизменной политической надстройке в лице монопольно управляющей страной КПК. К концу 70-х исторически слабая экономика Китая \"лежала\" из-за негативных последствий авантюристических кампаний Мао Цзедуна - \"большого скачка\" и \"культурной революции\". От систематического голода в Китае ежегодно страдали практически все 800 млн. крестьян (из миллиардного населения), страна занимала последние места в мире по уровню производства товаров и продовольствия на душу населения. Для решения проблемы голода необходимо было обеспечить стабильный валовый сбор зерна в объеме не менее 400 млн. т в год. Аграрные преобразования были связаны с отменой народной коммуны и заменой ее семейным подрядом и единой коллективной собственностью. Практически все 800 млн. крестьян получили право на свободное сельскохозяйственное производство. В основном была отменена система госзаготовок, освобождены цены на большинство видов сельскохозяйственной продукции. Результатом этих мер стал выход аграрного сектора из застоя, вступление крестьянских хозяйств на путь специализации и повышения товарности. Организованные в деревне по инициативе крестьян волостно-поселковые предприятия позволили обеспечить рост занятости (120 млн. чел.) и повысить жизненный уровень крестьян.Задача обеспечения страны зерном была в основном решена в 80-х. Постепенно в деревне сформировалась двухслойная хозяйственная система на основе сочетания коллективной собственности и семейного подряда.\n" +
+"\n" +
+"В области промышленной политики правительство Китая, начиная с 1984 года сделало упор концепцию плановой товарной экономики. На практике это означало перевод части отдельных городских предприятий на самоокупаемость. Позже правительство разрешило и подразделениям армии Китая (НОАК) перейти на самообеспечение и заниматься свободным предпринимательством. В соответствии с принципом \"Чжуа Да Фан Сяо\" (\"держать в руках большие предприятия, отпустить маленькие\") многие мелкие госпредприятия получили право изменить не только механизм хозяйствования, но и форму собственности. Это позволило государству сосредоточить силы на улучшении положения крупных предприятий. Четыре города - Шэньчжэнь, Чжухай, Сямынь, Шаньтоу - были объявлены специальными экономическими зонами. Вслед за ними 14 приморских городов, четыре региона в устьях рек Янцзы и Чжуцзян, юго-восточная часть провинции Фуцзянь и регион в районе Бахайского залива стали открытыми экономическими зонами. На острове Хайнань была создана одноименная новая провинция, а сам он стал специальной экономической зоной. Все эти города и районы получили различные инвестиционные и налоговые льготы для привлечения иностранного капитала и технологий, заимствования у иностранных партнеров эффективных методов управления. Быстрое развитие их экономики способствовало эффективному росту в масштабе страны. Характерно, что значительную долю ввозимого капитала на начальном этапе обеспечила китайская диаспора (хуацяо), проживающая преимущественно в странах тихоокеанского бассейна (основные зоны компактного проживания: Гонконг, Макао, Сингапур, Малайзия, США). Успешное проведение политики либерализации в сочетании с жестко проводимой политикой ограничения рождаемости (снижение рождаемости за 20 лет составило не менее 200 млн. человек) позволило создать многоукладную экономику, в которой госпредприятия дают 48% промышленной продукции, коллективные - 38%, частные, в том числе с иностранным участием, - 13,5%. На долю государственной торговли приходится свыше 41% общего розничного оборота, коллективной - почти 28% и частной - 31%. Доля рыночных цен по потребительским товарам достигла 90%, средствам производства - 80%, по сельскохозяйственным продуктам - 85%. Доля видов промышленной продукции, производство которых регулируется государственными директивными планами, снизилась с 95% в 1978 г. до 5% в настоящее время. Удельный вес товаров, ценами которых непосредственно управляет государство, в розничном товарообороте упал с 95 до 6%. Помимо рынка товаров начали создаваться рынки капиталов, машин и оборудования, рабочей силы, других необходимых для производства элементов. ВВП Китая рос в течение 20 лет, начиная с 1985 года в среднем на 9,5% ежегодно. Страна вышла на 1-е место в мире по производству цемента, цветных металлов, хлопчатобумажных тканей, велосипедов (свыше 80 млн.), мотоциклов (21,3 млн.), телевизоров (35 млн.), угля, зерна, хлопка, рапсовых семян, мяса, яиц, на 2-е - химических удобрений, 3-е - сахара, автомобилей (7,3 млн., вкл. 4,6 млн. легковых), 4-е - электроэнергии, 5-е - сырой нефти. По объему ВВП Китай находится на 4-м месте в мире (при расчете по паритетному покупательскому курсу - на 2-м). На его долю приходится 5,4% мирового валового продукта (2006 г.). Золотовалютные резервы страны превысили в 2006 г. триллион долларов США. Положительное сальдо торгового баланса составляет 180 млрд. долларов. Правда, несмотря на такой рекордно длительный и масштабный экономический рост, среднедушевые показатели ВВП Китая остаются еще на относительно низком уровне, ВВП на душу населения в 2005 году составил 7600 долларов (109-110 место в мире рядом с Украиной). В тоже время средний доход горожанина в открытых городах на конец 2006 г. превысил 10000 юаней в месяц. В китайской деревне от 100 до 150 млн. человек не могут найти работу, еще несколько сотен миллионов заняты частично. Официальный уровень безработицы в городах 4,2% (2005 г.).\n" +
+"\n" +
+"В начале 21-го века Китай превратился в \"мировую фабрику\" куда переводится ряд производств из развитых стран Европы, Северной Америки и Японии. Бурный экономический рост во многом связан с дешевизной рабочей силы, слабым уровнем техники безопасности и низким контролем за экологией. В результате Китай уже стал вторым загрязнителем мировой атмосферы и гидросферы, после гораздо более мощной экономики США, а также вышел в \"лидеры\" по эррозии почвы (особенно в северных областях). Возросший из-за роста авто- и мотопарка уровень импорта Китаем нефти (3,2 млн. баррелей/сут. в 2005-м, 2-е место в мире) приводит в последние годы к росту ее среднемировой цены.\n" +
+"\n" +
+"В тоже время экономическое и политическое влияние страны в мире в последние годы постоянно возрастает. Так Китаю в 1997-м и 1999-и годах были возращены \"арендованные\" еще у Поднебесной империи территории Гонконг (Сянган) и Макао (Аомынь). Постоянно возрастает уровень обороноспособности страны и техническое оснащение НОАК, чему в немалой степени способствует и РФ, поставляющая в Китай самые современные виды вооружения.\n" +
+"\n" +
+"Либерализация экономики КНР пока не сопровождается смягчением политического режима. В стране продолжаются политические репрессии против оппозиции, особенно масштабно реализованные во время \"событий на площади Тяньаньмэнь\" в мае 1989-го, жестко контролируются СМИ, включая Интернет. В тоже время в последние годы предпринят ряд важных изменений устава КПК, например, в партию разрешено вступать представителям предпринимательских кругов, введена ротация высших кадров руководства Партии. Во внутренней политике сняты все ограничения на рост личных состояний и разрешено владение личными автомобилями. В тоже время страна лидирует в мире по количеству смертных казней (более 7000 в год). Несмотря на такую суровую практику, уровень преступности и коррупции постоянно возрастает.\n" +
+"\n" +
+"Политика либерализации дала сенсационно высокие результаты, перевела экономику Китая на иной качественный уровень. При этом развитие экономики идет неравномерно по регионам, накапливаются социальные диспропорции, а экологическим аспектам уделяется недостаточное внимание, что уже затрагивает не только территорию Китая, но и интересы сопредельных с ним стран.\n" +
+"\n" +
+"[править] См. также\n" +
+"\n" +
+"    * Китай (цивилизация)\n" +
+"    * События на площади Тяньаньмэнь 1989 года\n" +
+"\n" +
+"[править] Литература\n" +
+"\n" +
+"    * Васильев Л.С. Древний Китай: в 3 т. Т. 3. Период Чжаньго (V–III вв. до н.э.). М.: Восточная литература, 2006. ISBN 502018103X\n" +
+"    * Непомнин О.Е. История Китая: Эпоха Цин. XVII – начало XX века. М.: Восточная литература, 2005. ISBN 5020184004\n";
+
+var devanagari = 
+"भारत\n" +
+"विकिपीडिया, एक मुक्त ज्ञानकोष से\n" +
+"Jump to: navigation, search\n" +
+"	यह लेख एक निर्वाचित लेख उम्मीदवार है। अधिक जानकारी के लिए और इस लेख को निर्वाचित लेख बनने के लिए क्या आवश्यकताएँ हैं यह जानने के लिए कृपया यहाँ देखें।\n" +
+"भारत गणराज्य\n" +
+"Flag of भारत 	Coat of arms of भारत\n" +
+"ध्वज 	कुलचिह्न\n" +
+"राष्ट्रवाक्य: \"सत्यमेव जयते\" (संस्कृत)\n" +
+"\n" +
+"सत्य ही विजयी होता है\n" +
+"राष्ट्रगान: जन गण मन\n" +
+"भारत की स्थिति\n" +
+"राजधानी 	नई दिल्ली\n" +
+"८७, ५९०) 28°34′ N 77°12′ E\n" +
+"सबसे बड़ा शहर 	मुम्बई\n" +
+"राजभाषा(एँ) 	हिन्दी, अंग्रेज़ी तथा अन्य भारतीय भाषाएं\n" +
+"सरकार\n" +
+"राष्ट्रपति\n" +
+"प्रधानमंत्री\n" +
+"	गणराज्य\n" +
+"प्रतिभा पाटिल\n" +
+"डॉ मनमोहन सिंह\n" +
+"ब्रिटिश राज से स्वतंत्रता\n" +
+"	१५ अगस्त, १९४७\n" +
+"क्षेत्रफल\n" +
+" - कुल\n" +
+" \n" +
+" - जलीय (%) 	 \n" +
+"३२, ८७, ५९० km² (सातवां)\n" +
+"१२,२२,५५९ sq mi \n" +
+"९.५६\n" +
+"जनसंख्या\n" +
+" - २००५ अनुमान\n" +
+" - २००१ जनगणना\n" +
+" - जनसंख्या का घनत्व 	 \n" +
+"१,१०,३३,७१,००० (द्वितीय)\n" +
+"१,०२,७०,१५,२४८\n" +
+"३२९/km² (३१ वीं)\n" +
+"८५२/sq mi \n" +
+"सकल घरेलू उत्पाद (जीडीपी) (पीपीपी)\n" +
+" - कुल\n" +
+" - प्रतिव्यत्ति 	२००५ estimate\n" +
+"$३.६३३ महासंख (चौथी GDP_PPP_per_capita = $३,३२०)\n" +
+"{{{GDP_PPP_per_capita}}} (१२२ वीं)\n" +
+"मानव विकास संकेतांक (एइचडीआइ) 	०.६११ (१२६ वीं) – medium\n" +
+"मुद्रा 	भारतीय रुपया (आइएनआर)\n" +
+"समय मण्डल\n" +
+" - ग्रीष्म ऋतु (डेलाइट सेविंग टाइम) 	आइएसटी (UTC+५:३०)\n" +
+"अब्सर्व्ड नहीं है (UTC+५:३०)\n" +
+"इंटरनेट टॉप लेवेल डोमेन 	.आइएन\n" +
+"दूरभाष कोड 	+९१\n" +
+"\n" +
+"भारत गणराज्य, पौराणिक जम्बुद्वीप, दक्षिण एशिया में स्थित एक देश है। यह भारतीय उपमहाद्वीप का सबसे बड़ा देश है। भारत का भौगोलिक फैलाव 8० 4' से 37० 6' उत्तरी अक्षांश तक तथा 68० 7' से 97० 25'पूर्वी देशान्तर तक है । भारत का क्षेत्रफल ३२,८७,२६३ वर्ग कि. मी. हैं | भारत का विस्तार उत्तर से दक्षिण तक ३,२१४ कि. मी. और पूर्व से पश्चिम तक २,९३३ कि. मी. हैं । भारत की समुद्र तट रेखा ७५१६.६ किलोमीटर लम्बी है। भारत, भौगोलिक दृष्टि से विश्व का सातवाँ सबसे बड़ा और जनसँख्या के दृष्टिकोण से दूसरा बड़ा देश है | भारत के पश्चिम में पाकिस्तान , उत्तर-पूर्व मे चीन, नेपाल, और भूटान और पूर्व में बांग्लादेश और म्यांमार देश स्थित हैं। हिन्द महासागर में इसके दक्षिण पश्चिम में मालदीव, दक्षिण में श्रीलंका और दक्षिण-पूर्व में इंडोनेशिया है। भारत उत्तर-पश्चिम में अफ़्ग़ानिस्तान के साथ सीमा का दावा करता है। इसके उत्तर में हिमालय पर्वत है। दक्षिण में हिन्द महासागर है। पूर्व में बंगाल की खाड़ी है। पश्चिम में अरब सागर है। भारत में कई बड़ी नदियाँ है। गंगा नदी भारतीय सभ्यता मै बहुत पवित्र मानी जाती है। अन्य बड़ी नदियाँ ब्रह्मपुत्र, यमुना, गोदावरी, कावेरी, कृष्णा, चम्बल, सतलज, बियास हैं ।\n" +
+"\n" +
+"भारत की १०० करोड़ (१ अरब) से अधिक जनसंख्या, चीन के बाद विश्व में सबसे अधिक है। यह विश्व का सबसे बड़ा लोकतंत्र है। यहाँ ३०० से अधिक भाषाएँ बोली जाती है (साइटेसन चाहिए)। यह एक बहुत प्राचीन सभ्यता की भूमि है।\n" +
+"\n" +
+"भारत विश्व की दसवीं सबसे बड़ी अर्थव्यवस्था है, किन्तु हाल में भारत ने काफी प्रगति की है, और ताज़ा स्थिति में भारत विश्व में तीसरे, चौथे स्थान पर होने का दावा करता है (साइटेसन चाहिए)। भारत भौगोलिक क्षेत्रफल के आधार पर विश्व का सातवाँ सबसे बड़ा राष्ट्र है। यह विश्व की कुछ प्राचीनतम सभ्यताओं का पालना रहा है जैसे - सिन्धु घाटी सभ्यता , और महत्वपूर्ण ऐतिहासिक व्यापार पथों का अभिन्न अंग है। विश्व के चार प्रमुख धर्म : हिन्दू , बौध , जैन तथा सिख भारत में प्रतिपादित हुए | १९४७ में स्वतंत्रता प्राप्ति से पूर्व ब्रिटिश भारत के रूप में ब्रिटिश साम्राज्य के प्रमुख अंग भारत ने विगत २० वर्ष में सार्थक प्रगति की है, विशेष रूप से आर्थिक और सैन्य | भारतीय सेना एक क्षेत्रिय शक्ति और विश्वव्यापक शक्ति है।\n" +
+"\n" +
+"भारत की राजधानी नई दिल्ली है। भारत के अन्य बड़े महानगर मुम्बई (बम्बई), कोलकाता (कलकत्ता) और चेन्नई (मद्रास) हैं।\n" +
+"\n" +
+"\n" +
+"अनुक्रम\n" +
+"[छुपाएं]\n" +
+"\n" +
+"    * १ नाम\n" +
+"    * २ इतिहास\n" +
+"    * ३ सरकार\n" +
+"    * ४ राजनीति\n" +
+"    * ५ राज्य और केन्द्रशासित प्रदेश\n" +
+"    * ६ भूगोल और मौसम\n" +
+"    * ७ अर्थव्यवस्था\n" +
+"    * ८ जनवृत्त\n" +
+"    * ९ संस्कृति\n" +
+"    * १० यह भी देखें\n" +
+"    * ११ बाहरी कड़ियाँ\n" +
+"\n" +
+"[संपादित करें] नाम\n" +
+"मुख्य लेख: भारत नाम की उत्पत्ति\n" +
+"\n" +
+"भारत के दो आधिकारिक नाम है हिन्दी में भारत और अंग्रेज़ी में इन्डिया (India)। इन्डिया नाम की उत्पत्ति सिन्धु नदी के फारसी नाम से हुई। भारत नाम एक प्राचीन हिन्दू राजा भरत, जिनकी कथा महाभारत में है, के नाम से लिया गया है। एक तीसरा नाम हिन्दुस्तान (उत्पत्ति फारसी) या हिन्दुओं की भूमि मुगल काल से प्रयोग होता है यद्यपि इसका समकालीन उपयोग कम है।\n" +
+"\n" +
+"[संपादित करें] इतिहास\n" +
+"मुख्य लेख: भारतीय इतिहास\n" +
+"\n" +
+"पाषाण युग भीमबेटका मध्य प्रदेश की गुफाएं भारत में मानव जीवन का प्राचीनतम प्रमाण है। प्रथम स्थाई बस्तियों ने ९००० वर्ष पूर्व स्वरुप लिया। यही आगे चल कर सिन्धु घाटी सभ्यता में विकसित हुई , जो २६०० ईसवी और १९०० ईसवी के मध्य अपने चरम पर थी। लगभग १६०० ईसापूर्व आर्य भारत आए और उत्तर भारतीय क्षेत्रों में वैदिक सभ्यता का सूत्रपात किया । इस सभ्यता के स्रोत वेद और पुराण हैं। यह परम्परा कई सहस्र वर्ष पुरानी है। इसी समय दक्षिण बारत में द्रविड़ सभ्यता का विकास होता रहा। दोनो जातियों ने एक दूसरे की खूबियों को अपनाते हुए भारत में एक मिश्रित संस्कृति का निर्माण किया।\n" +
+"\n" +
+"५०० ईसवी पूर्व कॆ बाद, कई स्वतंत्र राज्य बन गए। उत्तर में मौर्य राजवंश, जिसमें बौद्ध महाराजा अशोक सम्मिलित थे, ने भारत के सांस्कृतिक पटल पर उल्लेखनीय छाप छोड़ी। १८० ईसवी के आरम्भ से, मध्य एशिया से कई आक्रमण हुए, जिनके परिणामस्वरूप उत्तरी भारतीय उपमहाद्वीप में यूनानी, शक, पार्थी और अंततः कुषाण राजवंश स्थापित हुए | तीसरी शताब्दी के आगे का समय जब भारत पर गुप्त वंश का शासन था, भारत का \"स्वर्णिम काल\" कहलाया।\n" +
+"तीसरी शताब्दी में सम्राट अशोक द्वारा बनाया गया मध्य प्रदेश में साँची का स्तूप\n" +
+"तीसरी शताब्दी में सम्राट अशोक द्वारा बनाया गया मध्य प्रदेश में साँची का स्तूप\n" +
+"\n" +
+"दक्षिण भारत में भिन्न-भिन्न समयकाल में कई राजवंश चालुक्य, चेर, चोल, पल्लव तथा पांड्य चले | विज्ञान, कला, साहित्य, गणित, खगोल शास्त्र, प्राचीन प्रौद्योगिकी, धर्म, तथा दर्शन इन्हीं राजाओं के शासनकाल में फ़ले-फ़ूले |\n" +
+"\n" +
+"१२वीं शताब्दी के प्रारंभ में, भारत पर इस्लामी आक्रमणों के पश्चात, उत्तरी व केन्द्रीय भारत का अधिकांश भाग दिल्ली सल्तनत के शासनाधीन हो गया; और बाद में, अधिकांश उपमहाद्वीप मुगल वंश के अधीन । दक्षिण भारत में विजयनगर साम्राज्य शक्तिशाली निकला। हालांकि, विशेषतः तुलनात्मक रूप से, संरक्षित दक्षिण में अनेक राज्य शेष रहे अथवा अस्तित्व में आये।\n" +
+"\n" +
+"१७वीं शताब्दी के मध्यकाल में पुर्तगाल, डच, फ्रांस, ब्रिटेन सहित अनेकों यूरोपीय देशों, जो भारत से व्यापार करने के इच्छुक थे, उन्होनें देश की शासकीय अराजकता का लाभ प्राप्त किया। अंग्रेज दूसरे देशों से व्यापार के इच्छुक लोगों को रोकने में सफल रहे और १८४० तक लगभग संपूर्ण देश पर शासन करने में सफल हुए। १८५७ में ब्रिटिश इस्ट इंडिया कम्पनी के विरुद्ध असफल विद्रोह, जो कि भारतीय स्वतन्त्रता के प्रथम संग्राम से जाना जाता है, के बाद भारत का अधिकांश भाग सीधे अंग्रेजी शासन के प्रशासनिक नियंत्रण में आ गया।\n" +
+"कोणार्क चक्र - १३वीं शताब्दी में बने उड़ीसा के सूर्य मन्दिर में स्थित, यह दुनिया के सब से प्रसिद्घ ऐतिहासिक स्थानों में से एक है।\n" +
+"कोणार्क चक्र - १३वीं शताब्दी में बने उड़ीसा के सूर्य मन्दिर में स्थित, यह दुनिया के सब से प्रसिद्घ ऐतिहासिक स्थानों में से एक है।\n" +
+"\n" +
+"बीसवीं शताब्दी के प्रारंभ में एक लम्बे समय तक स्वतंत्रता प्राप्ति के लिये विशाल अहिंसावादी संघर्ष चला, जिसका नेतृत्‍व महात्मा गांधी, जो कि आधिकारिक रुप से आधुनिक भारत के राष्ट्रपिता से संबोधित किये जाते हैं, ने किया। ईसके साथ - साथ चंद्रशेखर आजाद, सरदार भगत सिंह, सुख देव, राजगुरू, नेताजी सुभाष चन्द्र बोस आदि के नेतृत्‍व मे चले क्रांतिकारी संघर्ष के फलस्वरुप 15 अगस्त, 1947 भारत ने अंग्रेजी शासन से पूर्णतः स्वतंत्रता प्राप्त की। तदुपरान्त 26 जनवरी, 1950 को भारत एक गणराज्य बना।\n" +
+"\n" +
+"एक बहुजातीय तथा बहुधर्मिक राष्ट्र होने के कारण भारत को समय-समय पर साम्प्रदायिक तथा जातीय विद्वेष का शिकार होना पङा है। क्षेत्रीय असंतोष तथा विद्रोह भी हालाँकि देश के अलग-अलग हिस्सों में होते रहे हैं, पर इसकी धर्मनिरपेक्षता तथा जनतांत्रिकता, केवल १९७५-७७ को छोड़, जब तत्कालीन प्रधानमंत्री इंदिरा गांधी ने आपातकाल की घोषणा कर दी थी, अक्षुण्य रही है।\n" +
+"\n" +
+"भारत के पड़ोसी राष्ट्रों के साथ अनसुलझे सीमा विवाद हैं। इसके कारण इसे छोटे पैमानों पर युद्ध का भी सामना करना पड़ा है। १९६२ में चीन के साथ, तथा १९४७, १९६५, १९७१ एवम् १९९९ में पाकिस्तान के साथ लड़ाइयाँ हो चुकी हैं।\n" +
+"\n" +
+"भारत गुटनिरपेक्ष आन्दोलन तथा संयुक्त राष्ट्र संघ के संस्थापक सदस्य देशों में से एक है।\n" +
+"\n" +
+"१९७४ में भारत ने अपना पहला परमाणु परीक्षण किया था जिसके बाद १९९८ में 5 और परीक्षण किये गये। १९९० के दशक में किये गये आर्थिक सुधारीकरण की बदौलत आज देश सबसे तेजी से विकासशील राष्ट्रों की सूची में आ गया है।\n" +
+"\n" +
+"[संपादित करें] सरकार\n" +
+"मुख्य लेख: भारत सरकार\n" +
+"\n" +
+"भारत का संविधान भारत को एक सार्वभौमिक, समाजवादी, धर्मनिरपेक्ष, लोकतान्त्रिक गणराज्य की उपाधि देता है। भारत एक लोकतांत्रिक गणराज्य है, जिसका द्विसदनात्मक संसद वेस्टमिन्स्टर शैली के संसदीय प्रणाली द्वारा संचालित है। इसके शासन में तीन मुख्य अंग हैं: न्यायपालिका, कार्यपालिका और व्यवस्थापिका।\n" +
+"\n" +
+"राष्ट्रपति,जो कि राष्ट्र का प्रमुख है, has a largely ceremonial role. उसके कार्यों में संविधान का अभिव्यक्तिकरण, प्रस्तावित कानूनों (विधेयक) पर अपनी सहमति देना, और अध्यादेश जारी करना। वह भारतीय सेनाओं का मुख्य सेनापति भी है। राष्ट्रपति और उपराष्ट्रपति को एक अप्रत्यक्ष मतदान विधि द्वारा ५ वर्षों के लिये चुना जाता है। प्रधानमन्त्री सरकार का प्रमुख है और कार्यपालिका की सारी शक्तियाँ उसी के पास होती हैं। इसका चुनाव राजनैतिक पार्टियों या गठबन्धन के द्वारा प्रत्यक्ष विधि से संसद में बहुमत प्राप्त करने पर होता है। बहुमत बने रहने की स्थिति में इसका कार्यकाल ५ वर्षों का होता है। संविधान में किसी उप-प्रधानमंत्री का प्रावधान नहीं है पर समय-समय पर इसमें फेरबदल होता रहा है।\n" +
+"\n" +
+"व्यवस्थापिका संसद को कहते हैं जिसके दो सदन हैं - उच्चसदन राज्यसभा, or Council of States,और निम्नसदन लोकसभा. राज्यसभा में २४५ सदस्य होते हैं जबकि लोकसभा में ५५२। राज्यसभा के सदस्यों का चुनाव, अप्रत्यक्ष विधि से ६ वर्षों के लिये होता है, जबकि लोकसभा के सदस्यों का चुनाव प्रत्यक्ष विधि से, ५ वर्षों की अवधि के लिये। १८ वर्ष से अधिक उम्र के सभी भारतीय नागरिक मतदान कर सकते हैं।\n" +
+"\n" +
+"कार्यपालिका के तीन अंग हैं - राष्ट्रपति, उपराष्ट्रपति और मंत्रीमंडल। मंत्रीमंडल का प्रमुख प्रधानमंत्री होता है। मंत्रीमंडल के प्रत्येक मंत्री को संसद का सदस्य होना अनिवार्य है। कार्यपालिका, व्यवस्थापिका से नीचे होता है।\n" +
+"\n" +
+"भारत की स्वतंत्र न्यायपालिका का शीर्ष सर्वोच्च न्यायालय है, जिसका प्रधान प्रधान न्यायाधीश होता है। सर्वोच्च न्यायालय को अपने नये मामलों तथा उच्च न्यायालयों के विवादों, दोनो को देखने का अधिकार है। भारत में 21 उच्च न्यायालय हैं, जिनके अधिकार और उत्तरदायित्व सर्वोच्च न्यायालय की अपेक्षा सीमित हैं। न्यायपालिका और व्यवस्थापिका के परस्पर मतभेद या विवाद का सुलह राष्ट्रपति करता है।\n" +
+"\n" +
+"[संपादित करें] राजनीति\n" +
+"मुख्य लेख: भारत की राजनीति\n" +
+"भारत का मानचित्र\n" +
+"भारत का मानचित्र\n" +
+"\n" +
+"स्वतंत्र भारत के इतिहास में उसकी सरकार मुख्य रूप से भारतीय राष्ट्रीय कान्ग्रेस पार्टी के हाथ में रही है। स्वतन्त्रतापूर्व भारत में सबसे बडे़ राजनीतिक संगठन होने के कारण काँग्रेस की, जिसका नेता मूल रूप से नेहरू - गाँधी परिवार का कोई न कोई सदस्य होता है, चालीस वर्षों तक राष्ट्रीय राजनीति में प्रमुख भूमिका रही। १९७७ में, पूर्व काँग्रेस शासन की इंदिरा गाँधी के आपातकाल लगाने के बाद एक संगठित विपक्ष जनता पार्टी ने चुनाव जीता और उसने अत्यधिक छोटी अवधि के लिये एक गैर-काँग्रेसी सरकार बनाई।\n" +
+"\n" +
+"१९९६ में, भारतीय जनता पार्टी (भाजपा), सबसे बड़े राजनीतिक संगठन के रूप में उभरी और उसने काँग्रेस के आगे इतिहास में पहली बार एक ठोस विपक्ष प्रस्तुत किया। परन्तु आगे चलकर सत्ता वास्तविक रूप से दो गठबन्धन सरकारों के हाथ में रही जिन्हें काँग्रेस का सम्पूर्ण समर्थन था। १९९९ में, भाजपा ने छोटे दलों को साथ लेकर राष्ट्रीय जनतान्त्रिक गठबन्धन (राजग) बनाया और ५ वर्षों तक कार्यकाल पूरा करने वाली वह पहली गैर-काँग्रेसी सरकार बनी। १९९९ से पूर्व का दशक अल्पावधि सरकारों का था, इन वर्षों में सात भिन्न सरकारें बनी। परन्तु १९९१ मे बनी काँग्रेस सरकार ने अपना ५ वर्ष का कार्यकाल पूरा किया और कई आर्थिक सुधार लाई।\n" +
+"\n" +
+"भारतीय आम चुनाव २००४ के फ़लस्वरूप काँग्रेस दल ने सर्वाधिक सीटें जीतीं और वह बड़े ही कम बहुमत से सत्ता में वापिस आई। काँग्रेस ने गठजोड़ द्वारा भारतीय कम्युनिस्ट पार्टी (मार्क्सवादी) और बहुत सी राज्य स्तरीय पार्टियों को साथ लेकर यूनाईटेड प्रोग्रेसिव अलायन्स (यूपीए) नामक सरकार बनाई। आज बीजेपी और उसके सहयोगी विपक्ष में मुख्य भूमिका निभाते हैं। राष्ट्रीय स्तर पर किसी विशेष पार्टी का दबदबा न होने और राज्य स्तर की कई पार्टियों के राष्ट्रीय स्तर पर उभरने के कारण १९९६ से बनी सभी सरकारों को राजनीतिक गठबन्धनों की आवश्यक्ता पड़ी है।\n" +
+"\n" +
+"[संपादित करें] राज्य और केन्द्रशासित प्रदेश\n" +
+"मुख्य लेख: भारत के राज्य\n" +
+"\n" +
+"वर्तमान में भारत २८ राज्यों, ६ केन्द्रशासित प्रदेशों और राजधानी दिल्ली मे बँटा हुआ है। राज्यों की चुनी हुई स्वतंत्र सरकारें हैं जबकि केन्द्रशासित प्रदेशों पर केन्द्र द्वारा नियुक्त प्रबंधन शासन करता है, हालाँकि कुछ की लोकतांत्रिक सरकार भी है।\n" +
+"\n" +
+"अन्टार्कटिका और दक्षिण गंगोत्री और मैत्री पर भी भारत के वैज्ञानिक स्थल हैं यद्यपि अभी तक कोई वास्तविक आधिपत्य स्थापित नहीं किया गया है।\n" +
+"\n" +
+"[संपादित करें] भूगोल और मौसम\n" +
+"मुख्य लेख: भारत का भूगोल\n" +
+"हिमालय उत्तर में जम्मू और काश्मीर से लेकर पूर्व में अरुणाचल प्रदेश तक भारत की अधिकतर पूर्वी सीमा बनाता है\n" +
+"हिमालय उत्तर में जम्मू और काश्मीर से लेकर पूर्व में अरुणाचल प्रदेश तक भारत की अधिकतर पूर्वी सीमा बनाता है\n" +
+"\n" +
+"भारत के अधिकतर उत्तरी और उत्तरपश्चिमीय प्रांत हिमालय की पहाङियों में स्थित हैं। शेष का उत्तरी, मध्य और पूर्वी भारत गंगा के उपजाऊ मैदानों से बना है। उत्तरी-पूर्वी पाकिस्तान से सटा हुआ, भारत के पश्चिम में थार का मरुस्थल है। दक्षिण भारत लगभग संपूर्ण ही दक्खन के पठार से निर्मित है। यह पठार पूर्वी और पश्चिमी घाटों के बीच स्थित है।\n" +
+"\n" +
+"कई महत्वपूर्ण और बड़ी नदियाँ जैसे गंगा, ब्रह्मपुत्र, यमुना, गोदावरी और कृष्णा भारत से होकर बहती हैं। इन नदियों के कारण उत्तर भारत की भूमि कृषि के लिए उपजाऊ है।\n" +
+"\n" +
+"भारत के विस्तार के साथ ही इसके मौसम में भी बहुत भिन्नता है। दक्षिण में जहाँ तटीय और गर्म वातावरण रहता है वहीं उत्तर में कड़ी सर्दी, पूर्व में जहाँ अधिक बरसात है वहीं पश्चिम में रेगिस्तान की शुष्कता। भारत में वर्षा मुख्यतया मानसून हवाओं से होती है।\n" +
+"\n" +
+"भारत के मुख्य शहर है - दिल्ली, मुम्बई, कोलकाता, चेन्नई, बंगलोर ( बेंगलुरु ) | ये भी देंखे - भारत के शहर\n" +
+"\n" +
+"[संपादित करें] अर्थव्यवस्था\n" +
+"मुख्य लेख: भारत की अर्थव्यवस्था\n" +
+"सूचना प्रोद्योगिकी (आईटी) भारत के सबसे अधिक विकासशील उद्योगों में से एक है, वार्षिक आय $२८५० करोड़ डालर, इन्फ़ोसिस, भारत की सबसे बडी आईटी कम्पनियों में से एक\n" +
+"सूचना प्रोद्योगिकी (आईटी) भारत के सबसे अधिक विकासशील उद्योगों में से एक है, वार्षिक आय $२८५० करोड़ डालर, इन्फ़ोसिस, भारत की सबसे बडी आईटी कम्पनियों में से एक\n" +
+"\n" +
+"मुद्रा स्थानांतरण की दर से भारत की अर्थव्यवस्था विश्व में दसवें और क्रयशक्ति के अनुसार चौथे स्थान पर है। वर्ष २००३ में भारत में लगभग ८% की दर से आर्थिक वृद्धि हुई है जो कि विश्व की सबसे तीव्र बढती हुई अर्थव्यवस्थओं में से एक है। परंतु भारत की अत्यधिक जनसंख्या के कारण प्रतिव्यक्ति आय क्रयशक्ति की दर से मात्र ३२६२ अमेरिकन डॉलर है जो कि विश्व बैंक के अनुसार १२५वें स्थान पर है। भारत का विदेशी मुद्रा भंडार १४३ अरब अमेरिकन डॉलर है। मुम्बई भारत की आर्थिक राजधानी है और भारतीय रिजर्व बैंक और बॉम्बे स्टॉक एक्सचेंज का मुख्यालय भी। यद्यपि एक चौथाई भारतीय अभी भी निर्धनता रेखा से नीचे हैं, तीव्रता से बढ़ती हुई सूचना प्रोद्योगिकी कंपनियों के कारण मध्यमवर्गीय लोगों में वृद्धि हुई है। १९९१ के बाद भारत मे आर्थिक सुधार की नीति ने भारत के सर्वंगीण विकास मे बडी भूमिका निभाआयी।\n" +
+"\n" +
+"१९९१ के बाद भारत मे हुए [आर्थिक सुधार। आर्थिक सुधारोँ]] ने भारत के सर्वांगीण विकास मे बड़ी भूमिका निभाई। भारतीय अर्थव्यवस्था ने कृषि पर अपनी ऐतिहासिक निर्भरता कम की है और कृषि अब भारतीय सकल घरेलू उत्पाद (जीडीपी) का केवल २५% है। दूसरे प्रमुख उद्योग हैं उत्खनन, पेट्रोलियम, बहुमूल्य रत्न, चलचित्र, टेक्स्टाईल, सूचना प्रोद्योगिकी सेवाएं, तथा सजावटी वस्तुऐं। भारत के अधिकतर औद्योगिक क्षेत्र उसके प्रमुख महानगरों के आसपास स्थित हैं। हाल ही के वर्षों में $१७२० करोड़ अमरीकी डालर वार्षिक आय २००४-२००५ के साथ भारत सॉफ़्टवेयर और बीपीओ सेवाओं का सबसे बडा केन्द्र बनकर उभरा है। इसके साथ ही कई लघु स्तर के उद्योग भी हैं जोकि छोटे भारतीय गाँव और भारतीय नगरों के कई नागरिकों को जीविका प्रदान करते हैं। पिछले वषों मंे भारत में वित्तीय संस्थानो ने विकास में बड़ी भूमिका निभाई है।\n" +
+"\n" +
+"केवल तीस लाख विदेशी पर्यटकों के प्रतिवर्ष आने के बाद भी भार्तीय पर्यटन राष्ट्रीय आय का एक अति आवश्यक परन्तु कम विकसित स्त्रोत है। पर्यटन उद्योग भारत के जीडीपी का कुल ५.३% है। पर्यटन १०% भारतीय कामगारों को आजीविका देता है। वास्तविक संख्या ४.२ करोड है। आर्थिक रूप से देखा जाए तो पर्यटन भारतीय अर्थव्यवस्था को लगभग $४०० करोड डालर प्रदान करता है। भारत के प्रमुख व्यापार सहयोगी हैं अमरीका, जापान, चीन और संयुक्त अरब अमीरात।\n" +
+"\n" +
+"भारत के निर्यातों में कृषि उत्पाद, चाय, कपड़ा, बहुमूल्य रत्न व ज्वैलरी, साफ़्टवेयर सेवायें, इंजीनियरिंग सामान, रसायन तथा चमड़ा उत्पाद प्रमुख हैं जबकि उसके आयातों में कच्चा तेल, मशीनरी, बहुमूल्य रत्न, फ़र्टिलाइज़र तथा रसायन प्रमुख हैं। वर्ष २००४ के लिये भारत के कुल निर्यात $६९१८ करोड़ डालर के थे जबकि उसके आयात $८९३३ करोड डालर के थे।\n" +
+"\n" +
+"[संपादित करें] जनवृत्त\n" +
+"मुख्य लेख: भारत के लोग\n" +
+"\n" +
+"भारत चीन के बाद विश्व का दूसरा सबसे बड़ी जनसंख्या वाला देश है। भारत की विभिन्नताओं से भरी जनता में भाषा, जाति और धर्म, सामाजिक और राजनीतिक संगठन के मुख्य शत्रु हैं।\n" +
+"हिन्दुत्व भारत का सबसे बङा धर्म है - इस चित्र मे गोआ का एक मंदिर दर्शाया गया है\n" +
+"हिन्दुत्व भारत का सबसे बङा धर्म है - इस चित्र मे गोआ का एक मंदिर दर्शाया गया है\n" +
+"\n" +
+"भारत में ६४.८ प्रतिशत साक्षरता है जिसमे से ७५.३ % पुरुष और ५३.७% स्त्रियाँ साक्षर है। लिंग अनुपात की दृष्टि से भारत में प्रत्येक १००० पुरुषों के पीछे मात्र ९३३ महिलायें हैं। कार्य भागीदारी दर (कुल जनसंख्या मे कार्य करने वालों का भाग) ३९.१% है। पुरुषों के लिये यह दर ५१.७% और स्त्रियों के लिये २५.६% है। भारत की १००० जनसंख्या में २२.३२ जन्मों के साथ बढती जनसंख्या के आधे लोग २२.६६ वर्ष से कम आयु के हैं।\n" +
+"\n" +
+"यद्यपि भारत की ८०.५ प्रतिशत जनसंख्या हिन्दू है, १३.४ प्रतिशत जनसंख्या के साथ भारत विश्व में मुसलमानों की संख्या में भी इंडोनेशिया के बाद दूसरे स्थान पर है। अन्य धर्मावलम्बियों में ईसाई (२.३३ %), सिख (१.८४ %), बौद्ध (०.७६ %), जैन (०.४० %), अय्यावलि (०.१२ %), यहूदी, पारसी, अहमदी और बहाई आदि सम्मिलित हैं।\n" +
+"\n" +
+"भारत दो मुख्य भाषा सूत्रों, आर्यन् और द्रविङियन्, का भी स्त्रोत है (साइटेसन चाहिए)। भारत का संविधान कुल २३ भाषाओं को मान्यता देता है। हिन्दी और अंग्रेजी केन्द्रीय सरकार द्वारा सरकारी कामकाज के लिये उपयोग की जाती है। संस्कृत और तमिल जैसी अति प्राचीन भाषाएं भारत में ही जन्मी हैं। कुल मिलाकर भारत में १६५२ से भी अधिक भाषाएं एवं बोलियाँ बोली जातीं हैं।\n" +
+"\n" +
+"[संपादित करें] संस्कृति\n" +
+"मुख्य लेख: भारतीय संस्कृति\n" +
+"ताजमहल विश्व के सबसे प्रसिद्ध पर्यटक स्थलों में गिना जाता है।\n" +
+"ताजमहल विश्व के सबसे प्रसिद्ध पर्यटक स्थलों में गिना जाता है।\n" +
+"\n" +
+"भारत की सांस्कृतिक धरोहर बहुत संपन्न है। यहां की संस्कृति अनोखी है, और वर्षों से इसके कई अवयव अबतक अक्षुण्य हैं। आक्रमणकारियों तथा प्रवासियों से विभिन्न चीजों को समेटकर यह एक मिश्रित संस्कृति बन गई है। आधुनिक भारत का समाज, भाषाएं, रीति-रिवाज इत्यादि इसका प्रमाण हैं। ताजमहल और अन्य उदाहरण, इस्लाम प्रभावित स्थापत्य कला के अतिसुन्दर नमूने हैं।\n" +
+"गुम्पा नृत्य एक तिब्बती बौद्ध समाज का सिक्किम में छिपा नृत्य है। यह बौद्ध नव बर्ष में है।\n" +
+"गुम्पा नृत्य एक तिब्बती बौद्ध समाज का सिक्किम में छिपा नृत्य है। यह बौद्ध नव बर्ष में है।\n" +
+"\n" +
+"भारतीय समाज बहुधर्मिक, बहुभाषी तथा मिश्र-सांस्कृतिक है। पारंपरिक भारतीय पारिवारिक मूल्यों को काफी आदर की दृष्टि से देखा जाता है।\n" +
+"\n" +
+"विभिन्न धर्मों के इस भूभाग पर कई मनभावन पर्व त्यौहार मनाए जाते हैं - दिवाली, होली, दशहरा. पोंगल तथा ओणम . ईद-उल-फितर, मुहर्रम, क्रिसमस, ईस्टर आदि भी काफ़ी लोकप्रिय हैं।\n" +
+"\n" +
+"हालाँकि हॉकी देश का राष्ट्रीय खेल है, क्रिकेट सबसे अधिक लोकप्रिय है। वर्तमान में फुटबॉल, हॉकी तथा टेनिस में भी बहुत भारतीयों की अभिरुचि है। देश की राष्ट्रीय क्रिकेट टीम में 1983 में एक बार विश्व कप भी जीता है। इसके अतिरिक्त वर्ष 2003 में वह विश्व कप के फाइनल तक पहुँचा था। 1930 तथा 40 के दशक में हाकी में भारत अपने चरम पर था। मेजर ध्यानचंद ने हॉकी में भारत को बहुत प्रसिद्धि दिलाई और एक समय भारत ने अमरीका को 24-0 से हराया था जो अब तर विश्व कीर्तिमान है। शतरंज के जनक देश भारत के खिलाड़ी शतरंज में भी अच्छा प्रदर्शन करते आए हैं।\n" +
+"\n" +
+"भारतीय खानपान बहुत ही समृद्ध है। शाकाहारी तथा मांसाहारी दोनो तरह का खाना पसन्द किया जाता है। भारतीय व्यंजन विदेशों में भी बहुत पसन्द किए जाते है।\n" +
+"\n" +
+"भारत में संगीत तथा नृत्य की अपनी शैलियां भी विकसित हुईं जो बहुत ही लोकप्रिय हैं। भरतनाट्यम, ओडिसी, कत्थक प्रसिद्ध भारतीय नृत्य शैली है। हिन्दुस्तानी संगीत तथा कर्नाटक संगीत भारतीय परंपरागत संगीत की दो मुख्य धाराएं हैं।\n" +
+"\n" +
+"वैश्वीकरण के इस युग में शेष विश्व की तरह भारतीय समाज पर भी अंग्रेजी तथा यूरोपीय प्रभाव पड़ रहा है। बाहरी लोगों की खूबियों को अपनाने की भारतीय परंपरा का नया दौर कई भारतीयों की दृष्टि में अनुचित है। एक खुले समाज के जीवन का यत्न कर रहे लोगों को मध्यमवर्गीय तथा वरिष्ठ नागरिकों की उपेक्षा का शिकार होना पड़ता है। कुछ लोग इसे भारतीय पारंपरिक मूल्यों का हनन मानते हैं। विज्ञान तथा साहित्य में अधिक प्रगति ना कर पाने की वजह से भारतीय समाज यूरोपीय लोगों पर निर्भर होता जा रहा है। ऐसे समय में लोग विदेशी अविष्कारों का भारत में प्रयोग अनुचित भी समझते हैं। हालाँकि ऐसे कई लोग है जो ऐसा विचार नहीं रखते।\n" +
+"\n" +
+"[संपादित करें] यह भी देखें\n" +
+"\n" +
+"    * दक्षिण भारत\n" +
+"    * उत्तर पूर्वी भारत\n" +
+"    * भारत की भाषाएँ\n" +
+"\n" +
+"\n" +
+"[संपादित करें] बाहरी कड़ियाँ\n" +
+"\n" +
+"सरकार (हिन्दी)\n" +
+"\n" +
+"    * भारत का राष्ट्रीय पोर्टल\n" +
+"\n" +
+"सरकार (अंग्रेज़ी)\n" +
+"\n" +
+"    * भारतीय सरकार का सरकारी वैबसाइट\n" +
+"    * भारतीय सरकार का वेबसाइट का सरकारी निर्देशिका\n" +
+"\n" +
+"सेनापति निर्देश (अंग्रेज़ी)\n" +
+"\n" +
+"    * सीआईए में भारत निबन्ध\n" +
+"    * एन्साक्लोपीडिया ब्रिटैनिका का भारत निबन्ध\n" +
+"    * बीबीसी का भारत निबन्ध\n" +
+"\n" +
+"भारत का देश नक्शा\n" +
+"\n" +
+"सैटेलाइट चित्र (अंग्रेज़ी)\n" +
+"\n" +
+"    * गूगल मानचित्र से भारत का सैटेलाइट चित्र\n" +
+"\n" +
+"अन्य (अंग्रेज़ी)\n" +
+"\n" +
+"    * विकिभ्रमण का भारत निबन्ध\n" +
+"    * भारत ओपेन डायरैक्टरी प्रॉजेक्ट में\n" +
+"    * भारत यात्रा - सामूहिक यात्रा ब्लॉग\n";
+
+var english =
+"English language\n" +
+"From Wikipedia, the free encyclopedia\n" +
+"• Learn more about citing Wikipedia •\n" +
+"Jump to: navigation, search\n" +
+"	Editing of this article by unregistered or newly registered users is currently disabled.\n" +
+"If you cannot edit this article and you wish to make a change, you can discuss changes on the talk page, request unprotection, log in, or create an account.\n" +
+"English  \n" +
+"Pronunciation: 	/ˈɪŋɡlɪʃ/[37]\n" +
+"Spoken in: 	Listed in the article\n" +
+"Total speakers: 	First language: 309[38] – 380 million[3]\n" +
+"Second language: 199[39] – 600 million[40]\n" +
+"Overall: 1.8 billion[41] \n" +
+"Ranking: 	3 (native speakers)[9][10]\n" +
+"Total: 1 or 2 [11]\n" +
+"Language family: 	Indo-European\n" +
+" Germanic\n" +
+"  West Germanic\n" +
+"   Anglo–Frisian\n" +
+"    Anglic\n" +
+"     English \n" +
+"Writing system: 	Latin (English variant) \n" +
+"Official status\n" +
+"Official language of: 	53 countries\n" +
+"Flag of the United Nations United Nations\n" +
+"Regulated by: 	no official regulation\n" +
+"Language codes\n" +
+"ISO 639-1: 	en\n" +
+"ISO 639-2: 	eng\n" +
+"ISO 639-3: 	eng \n" +
+"World countries, states, and provinces where English is a primary language are dark blue; countries, states and provinces where it is an official but not a primary language are light blue. English is also one of the official languages of the European Union.\n" +
+"Note: This page may contain IPA phonetic symbols in Unicode. See IPA chart for English for an English-​based pronunciation key.\n" +
+"\n" +
+"English is a West Germanic language originating in England, and the first language for most people in Australia, Canada, the Commonwealth Caribbean, Ireland, New Zealand, the United Kingdom and the United States of America (also commonly known as the Anglosphere). It is used extensively as a second language and as an official language throughout the world, especially in Commonwealth countries such as India, Sri Lanka, Pakistan and South Africa, and in many international organisations.\n" +
+"\n" +
+"Modern English is sometimes described as the global lingua franca.[1][2] English is the dominant international language in communications, science, business, aviation, entertainment, radio and diplomacy.[3] The influence of the British Empire is the primary reason for the initial spread of the language far beyond the British Isles.[4] Following World War II, the growing economic and cultural influence of the United States has significantly accelerated the spread of the language.\n" +
+"\n" +
+"A working knowledge of English is required in certain fields, professions, and occupations. As a result over a billion people speak English at least at a basic level (see English language learning and teaching). English is one of six official languages of the United Nations.\n" +
+"Contents\n" +
+"[hide]\n" +
+"\n" +
+"    * 1 History\n" +
+"    * 2 Classification and related languages\n" +
+"    * 3 Geographical distribution\n" +
+"          o 3.1 English as a global language\n" +
+"          o 3.2 Dialects and regional varieties\n" +
+"          o 3.3 Constructed varieties of English\n" +
+"    * 4 Phonology\n" +
+"          o 4.1 Vowels\n" +
+"                + 4.1.1 See also\n" +
+"          o 4.2 Consonants\n" +
+"                + 4.2.1 Voicing and aspiration\n" +
+"          o 4.3 Supra-segmental features\n" +
+"                + 4.3.1 Tone groups\n" +
+"                + 4.3.2 Characteristics of intonation\n" +
+"    * 5 Grammar\n" +
+"    * 6 Vocabulary\n" +
+"          o 6.1 Number of words in English\n" +
+"          o 6.2 Word origins\n" +
+"                + 6.2.1 Dutch origins\n" +
+"                + 6.2.2 French origins\n" +
+"    * 7 Writing system\n" +
+"          o 7.1 Basic sound-letter correspondence\n" +
+"          o 7.2 Written accents\n" +
+"    * 8 Formal written English\n" +
+"    * 9 Basic and simplified versions\n" +
+"    * 10 Notes\n" +
+"    * 11 References\n" +
+"    * 12 See also\n" +
+"    * 13 External links\n" +
+"          o 13.1 Dictionaries\n" +
+"\n" +
+"History\n" +
+"\n" +
+"    Main article: History of the English language\n" +
+"\n" +
+"English is an Anglo-Frisian language. Germanic-speaking peoples from northwest Germany (Saxons and Angles) and Jutland (Jutes) invaded what is now known as Eastern England around the fifth century AD. It is a matter of debate whether the Old English language spread by displacement of the original population, or the native Celts gradually adopted the language and culture of a new ruling class, or a combination of both of these processes (see Sub-Roman Britain).\n" +
+"\n" +
+"Whatever their origin, these Germanic dialects eventually coalesced to a degree (there remained geographical variation) and formed what is today called Old English. Old English loosely resembles some coastal dialects in what are now northwest Germany and the Netherlands (i.e., Frisia). Throughout the history of written Old English, it retained a synthetic structure closer to that of Proto-Indo-European, largely adopting West Saxon scribal conventions, while spoken Old English became increasingly analytic in nature, losing the more complex noun case system, relying more heavily on prepositions and fixed word order to convey meaning. This is evident in the Middle English period, when literature was to an increasing extent recorded with spoken dialectal variation intact, after written Old English lost its status as the literary language of the nobility. It is postulated that the early development of the language was influenced by a Celtic substratum.[5][6] Later, it was influenced by the related North Germanic language Old Norse, spoken by the Vikings who settled mainly in the north and the east coast down to London, the area known as the Danelaw.\n" +
+"\n" +
+"The Norman Conquest of England in 1066 profoundly influenced the evolution of the language. For about 300 years after this, the Normans used Anglo-Norman, which was close to Old French, as the language of the court, law and administration. By the fourteenth century, Anglo-Norman borrowings had contributed roughly 10,000 words to English, of which 75% remain in use. These include many words pertaining to the legal and administrative fields, but also include common words for food, such as mutton[7] and beef[8]. The Norman influence gave rise to what is now referred to as Middle English. Later, during the English Renaissance, many words were borrowed directly from Latin (giving rise to a number of doublets) and Greek, leaving a parallel vocabulary that persists into modern times. By the seventeenth century there was a reaction in some circles against so-called inkhorn terms.\n" +
+"\n" +
+"During the fifteenth century, Middle English was transformed by the Great Vowel Shift, the spread of a prestigious South Eastern-based dialect in the court, administration and academic life, and the standardising effect of printing. Early Modern English can be traced back to around the Elizabethan period.\n" +
+"\n" +
+"Classification and related languages\n" +
+"\n" +
+"The English language belongs to the western sub-branch of the Germanic branch of the Indo-European family of languages.\n" +
+"\n" +
+"The question as to which is the nearest living relative of English is a matter of discussion. Apart from such English-lexified creole languages such as Tok Pisin, Scots (spoken primarily in Scotland and parts of Northern Ireland) is not a Gaelic language, but is part of the English family of languages: both Scots and modern English are descended from Old English, also known as Anglo-Saxon. The closest relative to English after Scots is Frisian, which is spoken in the Northern Netherlands and Northwest Germany. Other less closely related living West Germanic languages include German, Low Saxon, Dutch, and Afrikaans. The North Germanic languages of Scandinavia are less closely related to English than the West Germanic languages.\n" +
+"\n" +
+"Many French words are also intelligible to an English speaker (though pronunciations are often quite different) because English absorbed a large vocabulary from Norman and French, via Anglo-Norman after the Norman Conquest and directly from French in subsequent centuries. As a result, a large portion of English vocabulary is derived from French, with some minor spelling differences (word endings, use of old French spellings, etc.), as well as occasional divergences in meaning, in so-called \"faux amis\", or false friends.\n" +
+"\n" +
+"Geographical distribution\n" +
+"\n" +
+"    See also: List of countries by English-speaking population\n" +
+"\n" +
+"Over 380 million people speak English as their first language. English today is probably the third largest language by number of native speakers, after Mandarin Chinese and Spanish.[9][10] However, when combining native and non-native speakers it is probably the most commonly spoken language in the world, though possibly second to a combination of the Chinese Languages, depending on whether or not distinctions in the latter are classified as \"languages\" or \"dialects.\"[11][12] Estimates that include second language speakers vary greatly from 470 million to over a billion depending on how literacy or mastery is defined.[13][14] There are some who claim that non-native speakers now outnumber native speakers by a ratio of 3 to 1.[15]\n" +
+"\n" +
+"The countries with the highest populations of native English speakers are, in descending order: United States (215 million),[16] United Kingdom (58 million),[17] Canada (17.7 million),[18] Australia (15 million),[19] Ireland (3.8 million),[17] South Africa (3.7 million),[20] and New Zealand (3.0-3.7 million).[21] Countries such as Jamaica and Nigeria also have millions of native speakers of dialect continuums ranging from an English-based creole to a more standard version of English. Of those nations where English is spoken as a second language, India has the most such speakers ('Indian English') and linguistics professor David Crystal claims that, combining native and non-native speakers, India now has more people who speak or understand English than any other country in the world.[22] Following India is the People's Republic of China.[23]\n" +
+"Distribution of native English speakers by country (Crystal 1997)\n" +
+"Distribution of native English speakers by country (Crystal 1997)\n" +
+"	Country 	Native speakers\n" +
+"1 	USA 	214,809,000[16]\n" +
+"2 	UK 	58,200,000[17]\n" +
+"3 	Canada 	17,694,830[18]\n" +
+"4 	Australia 	15,013,965[19]\n" +
+"5 	Ireland 	4,200,000+ (Approx)[17]\n" +
+"6 	South Africa 	3,673,203[20]\n" +
+"7 	New Zealand 	3,500,000+ (Approx)[21]\n" +
+"8 	Singapore 	665,087[24]\n" +
+"\n" +
+"English is the primary language in Anguilla, Antigua and Barbuda, Australia (Australian English), the Bahamas, Barbados, Bermuda, Belize, the British Indian Ocean Territory, the British Virgin Islands, Canada (Canadian English), the Cayman Islands, Dominica, the Falkland Islands, Gibraltar, Grenada, Guernsey (Guernsey English), Guyana, Ireland (Hiberno-English), Isle of Man (Manx English), Jamaica (Jamaican English), Jersey, Montserrat, Nauru, New Zealand (New Zealand English), Pitcairn Islands, Saint Helena, Saint Lucia, Saint Kitts and Nevis, Saint Vincent and the Grenadines, Singapore, South Georgia and the South Sandwich Islands, Trinidad and Tobago, the Turks and Caicos Islands, the United Kingdom, the U.S. Virgin Islands, and the United States (various forms of American English).\n" +
+"\n" +
+"In many other countries, where English is not the most spoken language, it is an official language; these countries include Botswana, Cameroon, Fiji, the Federated States of Micronesia, Ghana, Gambia, Hong Kong, India, Kiribati, Lesotho, Liberia, Kenya, Madagascar, Malta, the Marshall Islands, Namibia, Nigeria, Pakistan, Papua New Guinea, the Philippines, Puerto Rico, Rwanda, the Solomon Islands, Samoa, Sierra Leone, Singapore, Sri Lanka, Swaziland, Tanzania, Uganda, Zambia, and Zimbabwe. It is also one of the 11 official languages that are given equal status in South Africa (\"South African English\"). English is also an important language in several former colonies or current dependent territories of the United Kingdom and the United States, such as in Hong Kong and Mauritius.\n" +
+"\n" +
+"English is not an official language in either the United States or the United Kingdom.[25][26] Although the United States federal government has no official languages, English has been given official status by 30 of the 50 state governments.[27]\n" +
+"\n" +
+"English as a global language\n" +
+"\n" +
+"    See also: English on the Internet and global language\n" +
+"\n" +
+"Because English is so widely spoken, it has often been referred to as a \"global language\", the lingua franca of the modern era.[2] While English is not an official language in many countries, it is currently the language most often taught as a second language around the world. Some linguists believe that it is no longer the exclusive cultural sign of \"native English speakers\", but is rather a language that is absorbing aspects of cultures worldwide as it continues to grow. It is, by international treaty, the official language for aerial and maritime communications, as well as one of the official languages of the European Union, the United Nations, and most international athletic organisations, including the International Olympic Committee.\n" +
+"\n" +
+"English is the language most often studied as a foreign language in the European Union (by 89% of schoolchildren), followed by French (32%), German (18%), and Spanish (8%).[28] In the EU, a large fraction of the population reports being able to converse to some extent in English. Among non-English speaking countries, a large percentage of the population claimed to be able to converse in English in the Netherlands (87%), Sweden (85%), Denmark (83%), Luxembourg (66%), Finland (60%), Slovenia (56%), Austria (53%), Belgium (52%), and Germany (51%). [29] Norway and Iceland also have a large majority of competent English-speakers.\n" +
+"\n" +
+"Books, magazines, and newspapers written in English are available in many countries around the world. English is also the most commonly used language in the sciences.[2] In 1997, the Science Citation Index reported that 95% of its articles were written in English, even though only half of them came from authors in English-speaking countries.\n" +
+"\n" +
+"Dialects and regional varieties\n" +
+"\n" +
+"    Main article: List of dialects of the English language\n" +
+"\n" +
+"The expansion of the British Empire and—since WWII—the primacy of the United States have spread English throughout the globe.[2] Because of that global spread, English has developed a host of English dialects and English-based creole languages and pidgins.\n" +
+"\n" +
+"The major varieties of English include, in most cases, several subvarieties, such as Cockney slang within British English; Newfoundland English within Canadian English; and African American Vernacular English (\"Ebonics\") and Southern American English within American English. English is a pluricentric language, without a central language authority like France's Académie française; and, although no variety is clearly considered the only standard, there are a number of accents considered to be more prestigious, such as Received Pronunciation in Britain.\n" +
+"\n" +
+"Scots developed — largely independently — from the same origins, but following the Acts of Union 1707 a process of language attrition began, whereby successive generations adopted more and more features from English causing dialectalisation. Whether it is now a separate language or a dialect of English better described as Scottish English is in dispute. The pronunciation, grammar and lexis of the traditional forms differ, sometimes substantially, from other varieties of English.\n" +
+"\n" +
+"Because of the wide use of English as a second language, English speakers have many different accents, which often signal the speaker's native dialect or language. For the more distinctive characteristics of regional accents, see Regional accents of English speakers, and for the more distinctive characteristics of regional dialects, see List of dialects of the English language.\n" +
+"\n" +
+"Just as English itself has borrowed words from many different languages over its history, English loanwords now appear in a great many languages around the world, indicative of the technological and cultural influence of its speakers. Several pidgins and creole languages have formed using an English base, such as Jamaican Creole, Nigerian Pidgin, and Tok Pisin. There are many words in English coined to describe forms of particular non-English languages that contain a very high proportion of English words. Franglais, for example, is used to describe French with a very high English word content; it is found on the Channel Islands. Another variant, spoken in the border bilingual regions of Québec in Canada, is called FrEnglish.\n" +
+"\n" +
+"Constructed varieties of English\n" +
+"\n" +
+"    * Basic English is simplified for easy international use. It is used by manufacturers and other international businesses to write manuals and communicate. Some English schools in Asia teach it as a practical subset of English for use by beginners.\n" +
+"    * Special English is a simplified version of English used by the Voice of America. It uses a vocabulary of only 1500 words.\n" +
+"    * English reform is an attempt to improve collectively upon the English language.\n" +
+"    * Seaspeak and the related Airspeak and Policespeak, all based on restricted vocabularies, were designed by Edward Johnson in the 1980s to aid international cooperation and communication in specific areas. There is also a tunnelspeak for use in the Channel Tunnel.\n" +
+"    * English as a lingua franca for Europe and Euro-English are concepts of standardising English for use as a second language in continental Europe.\n" +
+"    * Manually Coded English — a variety of systems have been developed to represent the English language with hand signals, designed primarily for use in deaf education. These should not be confused with true sign languages such as British Sign Language and American Sign Language used in Anglophone countries, which are independent and not based on English.\n" +
+"    * E-Prime excludes forms of the verb to be.\n" +
+"\n" +
+"Euro-English (also EuroEnglish or Euro-English) terms are English translations of European concepts that are not native to English-speaking countries. Due to the United Kingdom's (and even the Republic of Ireland's) involvement in the European Union, the usage focuses on non-British concepts. This kind of Euro-English was parodied when English was \"made\" one of the constituent languages of Europanto.\n" +
+"\n" +
+"Phonology\n" +
+"\n" +
+"    Main article: English phonology\n" +
+"\n" +
+"Vowels\n" +
+"IPA 	Description 	word\n" +
+"monophthongs\n" +
+"i/iː 	Close front unrounded vowel 	bead\n" +
+"ɪ 	Near-close near-front unrounded vowel 	bid\n" +
+"ɛ 	Open-mid front unrounded vowel 	bed\n" +
+"æ 	Near-open front unrounded vowel 	bad\n" +
+"ɒ 	Open back rounded vowel 	bod 1\n" +
+"ɔ 	Open-mid back rounded vowel 	pawed 2\n" +
+"ɑ/ɑː 	Open back unrounded vowel 	bra\n" +
+"ʊ 	Near-close near-back rounded vowel 	good\n" +
+"u/uː 	Close back rounded vowel 	booed\n" +
+"ʌ/ɐ 	Open-mid back unrounded vowel, Near-open central vowel 	bud\n" +
+"ɝ/ɜː 	Open-mid central unrounded vowel 	bird 3\n" +
+"ə 	Schwa 	Rosa's 4\n" +
+"ɨ 	Close central unrounded vowel 	roses 5\n" +
+"diphthongs\n" +
+"e(ɪ)/eɪ 	Close-mid front unrounded vowel\n" +
+"Close front unrounded vowel 	bayed 6\n" +
+"o(ʊ)/əʊ 	Close-mid back rounded vowel\n" +
+"Near-close near-back rounded vowel 	bode 6\n" +
+"aɪ 	Open front unrounded vowel\n" +
+"Near-close near-front unrounded vowel 	cry\n" +
+"aʊ 	Open front unrounded vowel\n" +
+"Near-close near-back rounded vowel 	bough\n" +
+"ɔɪ 	Open-mid back rounded vowel\n" +
+"Close front unrounded vowel 	boy\n" +
+"ʊɝ/ʊə 	Near-close near-back rounded vowel\n" +
+"Schwa 	boor 9\n" +
+"ɛɝ/ɛə 	Open-mid front unrounded vowel\n" +
+"Schwa 	fair 10\n" +
+"\n" +
+"Notes:\n" +
+"\n" +
+"It is the vowels that differ most from region to region.\n" +
+"\n" +
+"Where symbols appear in pairs, the first corresponds to American English, General American accent; the second corresponds to British English, Received Pronunciation.\n" +
+"\n" +
+"   1. American English lacks this sound; words with this sound are pronounced with /ɑ/ or /ɔ/.\n" +
+"   2. Many dialects of North American English do not have this vowel. See Cot-caught merger.\n" +
+"   3. The North American variation of this sound is a rhotic vowel.\n" +
+"   4. Many speakers of North American English do not distinguish between these two unstressed vowels. For them, roses and Rosa's are pronounced the same, and the symbol usually used is schwa /ə/.\n" +
+"   5. This sound is often transcribed with /i/ or with /ɪ/.\n" +
+"   6. The diphthongs /eɪ/ and /oʊ/ are monophthongal for many General American speakers, as /eː/ and /oː/.\n" +
+"   7. The letter <U> can represent either /u/ or the iotated vowel /ju/. In BRP, if this iotated vowel /ju/ occurs after /t/, /d/, /s/ or /z/, it often triggers palatalization of the preceding consonant, turning it to /ʨ/, /ʥ/, /ɕ/ and /ʑ/ respectively, as in tune, during, sugar, and azure. In American English, palatalization does not generally happen unless the /ju/ is followed by r, with the result that /(t, d,s, z)jur/ turn to /tʃɚ/, /dʒɚ/, /ʃɚ/ and /ʒɚ/ respectively, as in nature, verdure, sure, and treasure.\n" +
+"   8. Vowel length plays a phonetic role in the majority of English dialects, and is said to be phonemic in a few dialects, such as Australian English and New Zealand English. In certain dialects of the modern English language, for instance General American, there is allophonic vowel length: vowel phonemes are realized as long vowel allophones before voiced consonant phonemes in the coda of a syllable. Before the Great Vowel Shift, vowel length was phonemically contrastive.\n" +
+"   9. This sound only occurs in non-rhotic accents. In some accents, this sound may be, instead of /ʊə/, /ɔ:/. See pour-poor merger.\n" +
+"  10. This sound only occurs in non-rhotic accents. In some accents, the schwa offglide of /ɛə/ may be dropped, monophthising and lengthening the sound to /ɛ:/.\n" +
+"\n" +
+"See also\n" +
+"\n" +
+"    * International Phonetic Alphabet for English for more vowel charts.\n" +
+"\n" +
+"Consonants\n" +
+"\n" +
+"This is the English Consonantal System using symbols from the International Phonetic Alphabet (IPA).\n" +
+"  	bilabial 	labio-\n" +
+"dental 	dental 	alveolar 	post-\n" +
+"alveolar 	palatal 	velar 	glottal\n" +
+"plosive 	p  b 	  	  	t  d 	  	  	k  ɡ 	 \n" +
+"nasal 	m 	  	  	n 	  	  	ŋ 1 	 \n" +
+"flap 	  	  	  	ɾ 2 	  	  	  	 \n" +
+"fricative 	  	f  v 	θ  ð 3 	s  z 	ʃ  ʒ 4 	ç 5 	x 6 	h\n" +
+"affricate 	  	  	  	  	tʃ  dʒ 4 	  	  	 \n" +
+"approximant 	  	  	  	ɹ 4 	  	j 	  	 \n" +
+"lateral approximant 	  	  	  	l 	  	  	  	 \n" +
+"  	labial-velar\n" +
+"approximant 	ʍ  w 7\n" +
+"\n" +
+"   1. The velar nasal [ŋ] is a non-phonemic allophone of /n/ in some northerly British accents, appearing only before /k/ and /g/. In all other dialects it is a separate phoneme, although it only occurs in syllable codas.\n" +
+"   2. The alveolar flap [ɾ] is an allophone of /t/ and /d/ in unstressed syllables in North American English and Australian English.[30] This is the sound of tt or dd in the words latter and ladder, which are homophones for many speakers of North American English. In some accents such as Scottish English and Indian English it replaces /ɹ/. This is the same sound represented by single r in most varieties of Spanish.\n" +
+"   3. In some dialects, such as Cockney, the interdentals /θ/ and /ð/ are usually merged with /f/ and /v/, and in others, like African American Vernacular English, /ð/ is merged with dental /d/. In some Irish varieties, /θ/ and /ð/ become the corresponding dental plosives, which then contrast with the usual alveolar plosives.\n" +
+"   4. The sounds /ʃ/, /ʒ/, and /ɹ/ are labialised in some dialects. Labialisation is never contrastive in initial position and therefore is sometimes not transcribed. Most speakers of General American realize <r> (always rhoticized) as the retroflex approximant /ɻ/, whereas the same is realized in Scottish English, etc. as the alveolar trill.\n" +
+"   5. The voiceless palatal fricative /ç/ is in most accents just an allophone of /h/ before /j/; for instance human /çjuːmən/. However, in some accents (see this), the /j/ is dropped, but the initial consonant is the same.\n" +
+"   6. The voiceless velar fricative /x/ is used only by Scottish or Welsh speakers of English for Scots/Gaelic words such as loch /lɒx/ or by some speakers for loanwords from German and Hebrew like Bach /bax/ or Chanukah /xanuka/. In some dialects such as Scouse (Liverpool) either [x] or the affricate [kx] may be used as an allophone of /k/ in words such as docker [dɒkxə]. Most native speakers have a great deal of trouble pronouncing it correctly when learning a foreign language. Most speakers use the sounds [k] and [h] instead.\n" +
+"   7. Voiceless w [ʍ] is found in Scottish and Irish English, as well as in some varieties of American, New Zealand, and English English. In most other dialects it is merged with /w/, in some dialects of Scots it is merged with /f/.\n" +
+"\n" +
+"Voicing and aspiration\n" +
+"\n" +
+"Voicing and aspiration of stop consonants in English depend on dialect and context, but a few general rules can be given:\n" +
+"\n" +
+"    * Voiceless plosives and affricates (/ p/, / t/, / k/, and / tʃ/) are aspirated when they are word-initial or begin a stressed syllable — compare pin [pʰɪn] and spin [spɪn], crap [kʰɹ̥æp] and scrap [skɹæp].\n" +
+"          o In some dialects, aspiration extends to unstressed syllables as well.\n" +
+"          o In other dialects, such as Indo-Pakistani English, all voiceless stops remain unaspirated.\n" +
+"    * Word-initial voiced plosives may be devoiced in some dialects.\n" +
+"    * Word-terminal voiceless plosives may be unreleased or accompanied by a glottal stop in some dialects (e.g. many varieties of American English) — examples: tap [tʰæp̚], sack [sæk̚].\n" +
+"    * Word-terminal voiced plosives may be devoiced in some dialects (e.g. some varieties of American English) — examples: sad [sæd̥], bag [bæɡ̊]. In other dialects they are fully voiced in final position, but only partially voiced in initial position.\n" +
+"\n" +
+"Supra-segmental features\n" +
+"\n" +
+"Tone groups\n" +
+"\n" +
+"English is an intonation language. This means that the pitch of the voice is used syntactically, for example, to convey surprise and irony, or to change a statement into a question.\n" +
+"\n" +
+"In English, intonation patterns are on groups of words, which are called tone groups, tone units, intonation groups or sense groups. Tone groups are said on a single breath and, as a consequence, are of limited length, more often being on average five words long or lasting roughly two seconds. For example:\n" +
+"\n" +
+"    - /duː juː niːd ˈɛnɪˌθɪŋ/ Do you need anything?\n" +
+"    - /aɪ dəʊnt | nəʊ/ I don't, no\n" +
+"    - /aɪ dəʊnt nəʊ/ I don't know (contracted to, for example, - /aɪ dəʊnəʊ/ or /aɪ dənəʊ/ I dunno in fast or colloquial speech that de-emphasises the pause between don't and know even further)\n" +
+"\n" +
+"Characteristics of intonation\n" +
+"\n" +
+"English is a strongly stressed language, in that certain syllables, both within words and within phrases, get a relative prominence/loudness during pronunciation while the others do not. The former kind of syllables are said to be accentuated/stressed and the latter are unaccentuated/unstressed. All good dictionaries of English mark the accentuated syllable(s) by either placing an apostrophe-like ( ˈ ) sign either before (as in IPA, Oxford English Dictionary, or Merriam-Webster dictionaries) or after (as in many other dictionaries) the syllable where the stress accent falls. In general, for a two-syllable word in English, it can be broadly said that if it is a noun or an adjective, the first syllable is accentuated; but if it is a verb, the second syllable is accentuated.\n" +
+"\n" +
+"Hence in a sentence, each tone group can be subdivided into syllables, which can either be stressed (strong) or unstressed (weak). The stressed syllable is called the nuclear syllable. For example:\n" +
+"\n" +
+"    That | was | the | best | thing | you | could | have | done!\n" +
+"\n" +
+"Here, all syllables are unstressed, except the syllables/words best and done, which are stressed. Best is stressed harder and, therefore, is the nuclear syllable.\n" +
+"\n" +
+"The nuclear syllable carries the main point the speaker wishes to make. For example:\n" +
+"\n" +
+"    John hadn't stolen that money. (... Someone else had.)\n" +
+"    John hadn't stolen that money. (... You said he had. or ... Not at that time, but later he did.)\n" +
+"    John hadn't stolen that money. (... He acquired the money by some other means.)\n" +
+"    John hadn't stolen that money. (... He had stolen some other money.)\n" +
+"    John hadn't stolen that money. (... He stole something else.)\n" +
+"\n" +
+"Also\n" +
+"\n" +
+"    I didn't tell her that. (... Someone else told her.)\n" +
+"    I didn't tell her that. (... You said I did. or ... But now I will!)\n" +
+"    I didn't tell her that. (... I didn't say it; she could have inferred it, etc.)\n" +
+"    I didn't tell her that. (... I told someone else.)\n" +
+"    I didn't tell her that. (... I told her something else.)\n" +
+"\n" +
+"This can also be used to express emotion:\n" +
+"\n" +
+"    Oh really? (...I didn't know that)\n" +
+"    Oh really? (...I disbelieve you)\n" +
+"\n" +
+"The nuclear syllable is spoken more loudly than the others and has a characteristic change of pitch. The changes of pitch most commonly encountered in English are the rising pitch and the falling pitch, although the fall-rising pitch and/or the rise-falling pitch are sometimes used. In this opposition between falling and rising pitch, which plays a larger role in English than in most other languages, falling pitch conveys certainty and rising pitch uncertainty. This can have a crucial impact on meaning, specifically in relation to polarity, the positive–negative opposition; thus, falling pitch means \"polarity known\", while rising pitch means \"polarity unknown\". This underlies the rising pitch of yes/no questions. For example:\n" +
+"\n" +
+"    When do you want to be paid?\n" +
+"    Now? (Rising pitch. In this case, it denotes a question: \"Can I be paid now?\" or \"Do you desire to be paid now?\")\n" +
+"    Now. (Falling pitch. In this case, it denotes a statement: \"I choose to be paid now.\")\n" +
+"\n" +
+"Grammar\n" +
+"\n" +
+"    Main article: English grammar\n" +
+"\n" +
+"English grammar has minimal inflection compared with most other Indo-European languages. For example, Modern English, unlike Modern German or Dutch and the Romance languages, lacks grammatical gender and adjectival agreement. Case marking has almost disappeared from the language and mainly survives in pronouns. The patterning of strong (e.g. speak/spoke/spoken) versus weak verbs inherited from its Germanic origins has declined in importance in modern English, and the remnants of inflection (such as plural marking) have become more regular.\n" +
+"\n" +
+"At the same time, the language has become more analytic, and has developed features such as modal verbs and word order as rich resources for conveying meaning. Auxiliary verbs mark constructions such as questions, negative polarity, the passive voice and progressive tenses.\n" +
+"\n" +
+"Vocabulary\n" +
+"\n" +
+"The English vocabulary has changed considerably over the centuries.[31]\n" +
+"\n" +
+"Germanic words (generally words of Old English or to a lesser extent Norse origin) which include all the basics such as pronouns (I, my, you, it) and conjunctions (and, or, but) tend to be shorter than the Latinate words of English, and more common in ordinary speech. The longer Latinate words are often regarded as more elegant or educated. However, the excessive or superfluous use of Latinate words is considered at times to be either pretentious (as in the stereotypical policeman's talk of \"apprehending the suspect\") or an attempt to obfuscate an issue. George Orwell's essay \"Politics and the English Language\" is critical of this, as well as other perceived abuses of the language.\n" +
+"\n" +
+"An English speaker is in many cases able to choose between Germanic and Latinate synonyms: come or arrive; sight or vision; freedom or liberty. In some cases there is a choice between a Germanic derived word (oversee), a Latin derived word (supervise), and a French word derived from the same Latin word (survey). The richness of the language arises from the variety of different meanings and nuances such synonyms harbour, enabling the speaker to express fine variations or shades of thought. Familiarity with the etymology of groups of synonyms can give English speakers greater control over their linguistic register. See: List of Germanic and Latinate equivalents.\n" +
+"\n" +
+"An exception to this and a peculiarity perhaps unique to English is that the nouns for meats are commonly different from, and unrelated to, those for the animals from which they are produced, the animal commonly having a Germanic name and the meat having a French-derived one. Examples include: deer and venison; cow and beef; swine/pig and pork, or sheep and mutton. This is assumed to be a result of the aftermath of the Norman invasion, where a French-speaking elite were the consumers of the meat, produced by English-speaking lower classes.\n" +
+"\n" +
+"In everyday speech, the majority of words will normally be Germanic. If a speaker wishes to make a forceful point in an argument in a very blunt way, Germanic words will usually be chosen. A majority of Latinate words (or at least a majority of content words) will normally be used in more formal speech and writing, such as a courtroom or an encyclopedia article. However, there are other Latinate words that are used normally in everyday speech and do not sound formal; these are mainly words for concepts that no longer have Germanic words, and are generally assimilated better and in many cases do not appear Latinate. For instance, the words mountain, valley, river, aunt, uncle, move, use, push and stay are all Latinate.\n" +
+"\n" +
+"English is noted for the vast size of its active vocabulary and its fluidity.[citation needed][weasel words] English easily accepts technical terms into common usage and imports new words and phrases that often come into common usage. Examples of this phenomenon include: cookie, Internet and URL (technical terms), as well as genre, über, lingua franca and amigo (imported words/phrases from French, German, modern Latin, and Spanish, respectively). In addition, slang often provides new meanings for old words and phrases. In fact, this fluidity is so pronounced that a distinction often needs to be made between formal forms of English and contemporary usage. See also: sociolinguistics.\n" +
+"\n" +
+"Number of words in English\n" +
+"\n" +
+"English has an extraordinarily rich vocabulary and willingness to absorb new words. As the General Explanations at the beginning of the Oxford English Dictionary states:\n" +
+"\n" +
+"    The Vocabulary of a widely diffused and highly cultivated living language is not a fixed quantity circumscribed by definite limits... there is absolutely no defining line in any direction: the circle of the English language has a well-defined centre but no discernible circumference.\n" +
+"\n" +
+"The vocabulary of English is undoubtedly vast, but assigning a specific number to its size is more a matter of definition than of calculation. Unlike other languages, there is no Academy to define officially accepted words. Neologisms are coined regularly in medicine, science and technology and other fields, and new slang is constantly developed. Some of these new words enter wide usage; others remain restricted to small circles. Foreign words used in immigrant communities often make their way into wider English usage. Archaic, dialectal, and regional words might or might not be widely considered as \"English\".\n" +
+"\n" +
+"The Oxford English Dictionary, 2nd edition (OED2) includes over 600,000 definitions, following a rather inclusive policy:\n" +
+"\n" +
+"    It embraces not only the standard language of literature and conversation, whether current at the moment, or obsolete, or archaic, but also the main technical vocabulary, and a large measure of dialectal usage and slang (Supplement to the OED, 1933).[32]\n" +
+"\n" +
+"The editors of Webster's Third New International Dictionary, Unabridged (475,000 main headwords) in their preface, estimate the number to be much higher. It is estimated that about 25,000 words are added to the language each year.[33]\n" +
+"\n" +
+"Word origins\n" +
+"Influences in English vocabulary\n" +
+"Influences in English vocabulary\n" +
+"\n" +
+"    Main article: Lists of English words of international origin\n" +
+"\n" +
+"One of the consequences of the French influence is that the vocabulary of English is, to a certain extent, divided between those words which are Germanic (mostly Old English) and those which are \"Latinate\" (Latin-derived, either directly from Norman French or other Romance languages).\n" +
+"\n" +
+"Numerous sets of statistics have been proposed to demonstrate the various origins of English vocabulary. None, as yet, are considered definitive by a majority of linguists.\n" +
+"\n" +
+"A computerised survey of about 80,000 words in the old Shorter Oxford Dictionary (3rd ed.) was published in Ordered Profusion by Thomas Finkenstaedt and Dieter Wolff (1973)[34] that estimated the origin of English words as follows:\n" +
+"\n" +
+"    * Langue d'oïl, including French and Old Norman: 28.3%\n" +
+"    * Latin, including modern scientific and technical Latin: 28.24%\n" +
+"    * Other Germanic languages (including words directly inherited from Old English): 25%\n" +
+"    * Greek: 5.32%\n" +
+"    * No etymology given: 4.03%\n" +
+"    * Derived from proper names: 3.28%\n" +
+"    * All other languages contributed less than 1% (e.g. Arabic-English loanwords)\n" +
+"\n" +
+"A survey by Joseph M. Williams in Origins of the English Language of 10,000 words taken from several thousand business letters[35] gave this set of statistics:\n" +
+"\n" +
+"    * French (langue d'oïl), 41%\n" +
+"    * \"Native\" English, 33%\n" +
+"    * Latin, 15%\n" +
+"    * Danish, 2%\n" +
+"    * Dutch, 1%\n" +
+"    * Other, 10%\n" +
+"\n" +
+"However, 83% of the 1,000 most-common English words are Anglo-Saxon in origin. [36]\n" +
+"\n" +
+"Dutch origins\n" +
+"\n" +
+"    Main article: List of English words of Dutch origin\n" +
+"\n" +
+"Words describing the navy, types of ships, and other objects or activities on the water are often from Dutch origin. Yacht (Jacht) and cruiser (kruiser) are examples.\n" +
+"\n" +
+"French origins\n" +
+"\n" +
+"    Main article: List of French phrases used by English speakers\n" +
+"\n" +
+"There are many words of French origin in English, such as competition, art, table, publicity, police, role, routine, machine, force, and many others that have been and are being anglicised; they are now pronounced according to English rules of phonology, rather than French. A large portion of English vocabulary is of French or Oïl language origin, most derived from, or transmitted via, the Anglo-Norman spoken by the upper classes in England for several hundred years after the Norman Conquest.\n";
+
+
+var greek = 
+"Ελλάδα\n" +
+"Από τη Βικιπαίδεια, την ελεύθερη εγκυκλοπαίδεια\n" +
+"Ελληνική Δημοκρατία\n" +
+"	\n" +
+"Σημαία	Εθνόσημο\n" +
+"Εθνικό σύνθημα: Ελευθερία ή Θάνατος\n" +
+"Εθνικός ύμνος: Ὕμνος εἰς τὴν Ἐλευθερίαν\n" +
+"\n" +
+"Πρωτεύουσα	Αθήνα \n" +
+"38.01.36N 23.44.00E\n" +
+"\n" +
+"Μεγαλύτερη πόλη	Αθήνα\n" +
+"Επίσημες γλώσσες	Ελληνική\n" +
+"Πολίτευμα\n" +
+"\n" +
+"Πρόεδρος της Δημοκρατίας\n" +
+"Πρωθυπουργός	Προεδρευόμενη\n" +
+"Κοινοβουλευτική Δημοκρατία\n" +
+"Κάρολος Παπούλιας\n" +
+"Κωνσταντίνος Καραμανλής\n" +
+"Ανεξαρτησία\n" +
+"- Κηρύχθηκε\n" +
+"- Αναγνωρίστηκε\n" +
+"\n" +
+"25 Μαρτίου, 1821\n" +
+"1828\n" +
+"Έκταση\n" +
+" - Σύνολο\n" +
+" - Νερό (%)	 \n" +
+"131.940 km² (94ηη)\n" +
+"%0.86\n" +
+"Πληθυσμός\n" +
+" - Εκτίμηση 2006\n" +
+" - Απογραφή 2001\n" +
+" - Πυκνότητα	 \n" +
+"11.120.000 [1] (72ηη)\n" +
+"10.964.020\n" +
+"83.1 κάτ./km² (87ηη)\n" +
+"Α.Ε.Π.\n" +
+" - Ολικό\n" +
+" - Κατά κεφαλή	Εκτίμηση 2007\n" +
+"$305,595 δισ. (37η)\n" +
+"$27,360 (27η)\n" +
+"Νόμισμα	Ευρώ\n" +
+"(€)\n" +
+"Ζώνη ώρας\n" +
+" - Θερινή ώρα	(UTC+2)\n" +
+"(UTC+3)\n" +
+"Internet TLD	.gr\n" +
+"Κωδικός κλήσης	+30\n" +
+"Η Ελλάδα (αρχαΐζουσα: Ἑλλάς, επίσημα: Ελληνική Δημοκρατία), είναι χώρα στην νοτιοανατολική Ευρώπη, στο νοτιότερο άκρο της Βαλκανικής χερσονήσου, στην Ανατολική Μεσόγειο. Συνορεύει στην ξηρά, βόρεια με την Πρώην Γιουγκοσλαβική Δημοκρατία της Μακεδονίας και την Βουλγαρία, στα βορειοδυτικά με την Αλβανία και στα βορειοανατολικά με την Τουρκία. Βρέχεται ανατολικά από το Αιγαίο Πέλαγος, στα δυτικά και νότια από το Ιόνιο και από την Μεσόγειο Θάλασσα. Είναι το λίκνο του Δυτικού πολιτισμού. Η Ελλάδα έχει μια μακρά και πλούσια ιστορία κατά την οποία άσκησε μεγάλη πολιτισμική επίδραση σε τρεις ηπείρους.\n" +
+"Πίνακας περιεχομένων [Απόκρυψη]\n" +
+"1 Ιστορία\n" +
+"2 Πολιτικά\n" +
+"2.1 Κόμματα\n" +
+"2.2 Κυβέρνηση\n" +
+"3 Περιφέρειες\n" +
+"3.1 Βουνά της Ελλάδας\n" +
+"3.2 Λίμνες της Ελλάδας\n" +
+"3.3 Ποτάμια της Ελλάδας\n" +
+"3.4 Κλίμα\n" +
+"4 Οικονομία\n" +
+"5 Δημογραφία\n" +
+"6 Ένοπλες δυνάμεις και Σώματα ασφαλείας\n" +
+"6.1 Υποχρεωτική στράτευση\n" +
+"7 Πολιτισμός\n" +
+"7.1 Αργίες\n" +
+"8 Σημειώσεις\n" +
+"9 Δείτε επίσης\n" +
+"10 Εξωτερικές συνδέσεις\n" +
+"[Επεξεργασία]\n" +
+"Ιστορία\n" +
+"\n" +
+"Κύριο άρθρο: Ελληνική ιστορία\n" +
+"Στις ακτές του Αιγαίου Πελάγους εμφανίστηκαν οι πρώτοι πολιτισμοί της Ευρώπης, ο Μινωικός και ο Μυκηναϊκός. Την εποχή των πολιτισμών αυτών, ακολούθησε μία σκοτεινή περίοδος περίπου μέχρι το 800 π.Χ., οπότε εμφανίζεται ένας καινούριος Ελληνικός πολιτισμός, βασισμένος στο μοντέλο της πόλης-κράτους. Είναι ο πολιτισμός που θα διαδοθεί με τον αποικισμό των ακτών της Μεσογείου, θα αντισταθεί στην Περσική εισβολή με τους δύο επιφανέστερους εκπροσώπους του, την κοσμοπολίτικη και δημοκρατική Αθήνα και την μιλιταριστική και ολιγαρχική Σπάρτη, θα αποτελέσει τη βάση του Ελληνιστικού πολιτισμού που δημιούργησαν οι κατακτήσεις του Μεγάλου Αλεξάνδρου, θα επηρεάσει ως ένα βαθμό την πολιτισμική φυσιογνωμία της Βυζαντινής Αυτοκρατορίας και αργότερα θα πυροδοτήσει την Αναγέννηση στην Ευρώπη.\n" +
+"Στρατιωτικά έχανε δύναμη σε σύγκριση με τη Ρωμαϊκή αυτοκρατορία μέχρι που κατακτήθηκε τελικά από τους Ρωμαίους το 146 π.Χ., αν και ο Ελληνικός πολιτισμός τελικά κατέκτησε το Ρωμαϊκό τρόπο ζωής. Οι Ρωμαίοι αναγνώρισαν και θαύμασαν τον πλούτο του Ελληνικού πολιτισμού, τον μελέτησαν βαθιά και έγιναv συνειδητά συνεχιστές του. Διέσωσαν επίσης και μεγάλο μέρος της αρχαιοελληνικής γραμματείας. Αν και ήταν μόνο ένα μέρος της Ρωμαϊκής αυτοκρατορίας, ο ελληνικός πολιτισμός θα συνέχιζε να δεσπόζει στην Ανατολική Μεσόγειο, και όταν τελικά η Αυτοκρατορία χωρίστηκε στα δύο, η ανατολική ή Βυζαντινή Αυτοκρατορία με πρωτεύουσα την Κωνσταντινούπολη, θα είχε κυρίως λόγω γλώσσας έντονο τον ελληνικό χαρακτήρα. Από τον 4ο μέχρι τον 15ο αιώνα, η Ανατολική Ρωμαϊκή Αυτοκρατορία επέζησε επιθέσεις 11 αιώνων από δυτικά και ανατολικά, μέχρι που η Κωνσταντινούπολη έπεσε στις 29 Μαΐου του 1453 στα χέρια της Οθωμανικής Αυτοκρατορίας. Σταδιακά το Βυζάντιο κατακτήθηκε ολόκληρο μέσα στον 15ο αιώνα.\n" +
+"Η Οθωμανική κυριαρχία συνεχίστηκε μέχρι το 1821 που οι Έλληνες κήρυξαν την ανεξαρτησία τους. Η Ελληνική Επανάσταση του 1821 έληξε το 1828. Το 1830 αναγνωρίζεται η ανεξαρτησία του νέου ελληνικού κράτους. Εγκαθιδρύθηκε μοναρχία το 1833. Μέσα στον 19ο και τον πρώιμο 20ό αιώνα, η Ελλάδα προσπάθησε να προσαρτήσει στα εδάφη της όλες τις περιοχές που ακόμη ανήκαν στην Οθωμανική Αυτοκρατορία και είχαν Ελληνόφωνο πληθυσμό, πράγμα που κατάφερε εν μέρει, επεκτείνοντας σταδιακά την έκτασή της, μέχρι να φτάσει το σημερινό της μέγεθος το 1947.\n" +
+"Μετά τον Δεύτερο Παγκόσμιο Πόλεμο στην Ελλάδα ξέσπασε εμφύλιος πόλεμος μέχρι το 1949. Αργότερα, το 1952, η Ελλάδα έγινε μέλος του ΝΑΤΟ. Στις 21 Απριλίου του 1967 ο στρατός, υποβοηθούμενος από την κυβέρνηση των ΗΠΑ, πήρε την εξουσία με πραξικόπημα. Οι δικτατορες στη συνεχεια διαχωριστηκαν και απο τον βασιλια, τον εκδίωξαν απο την χώρα και κατήργησαν τη μοναρχία. Η στρατιωτική Χούντα υπήρξε η αιτία δημιουργίας, μετά από λανθασμένους χειρισμούς που εκμεταλλεύτηκε η Τουρκική πλευρά, του Κυπριακού ζητήματος, το οποίο οδήγησε στην κατάρρευσή της το 1974. Έπειτα από δημοψήφισμα για την κατάργηση της μοναρχίας στις 8 Δεκεμβρίου 1974 το πολίτευμα της Ελλάδας μετατράπηκε ξανά σε αβασίλευτη Δημοκρατία και συντάχθηκε νέο σύνταγμα από την πέμπτη Αναθεωρητική Βουλή που τέθηκε σε ισχύ στις 11 Ιουνίου 1975, το οποίο ισχύει σήμερα όπως αναθεωρήθηκε το 1986 και το 2001. Η Ελλάδα έγινε μέλος της Ευρωπαϊκής Ένωσης το 1981 και μέλος της Ευρωπαϊκής Οικονομικής και Νομισματικής Ένωσης (ΟΝΕ) γνωστής και ως ζώνης ευρώ, το 2001.\n" +
+"Ελληνική ιστορία \n" +
+"Κυκλαδικός πολιτισμός	(3η χιλιετία π.Χ.)\n" +
+"Μινωικός πολιτισμός	(3000-1450 π.Χ.)\n" +
+"Μυκηναϊκός πολιτισμός	(1600-1100 π.Χ.)\n" +
+"Γεωμετρική εποχή	(1100-800 π.Χ.)\n" +
+"Αρχαϊκή εποχή	(800-500 π.Χ.)\n" +
+"Κλασική εποχή	(500 π.Χ.- 323 π.Χ.)\n" +
+"Ελληνιστική εποχή	(323-146 π.Χ.)\n" +
+"Ρωμαϊκή περίοδος	(146 π.Χ.-330 μ.Χ.)\n" +
+"Βυζαντινή περίοδος	(330-1453)\n" +
+"Οθωμανική περίοδος	(1453-1821)\n" +
+"Νεότερη Ελλάδα	(1821 έως σήμερα)\n" +
+"Σχετικά\n" +
+"Αρχαία ελληνική γραμματεία\n" +
+"Ελληνική γλώσσα\n" +
+"Ονομασίες Ελλήνων\n" +
+"\n" +
+"[Επεξεργασία]\n" +
+"Πολιτικά\n" +
+"\n" +
+"Το Σύνταγμα του 1975 περιέχει εκτενείς εγγυήσεις των ελευθεριών και των δικαιωμάτων του πολίτη, ελευθερίες και δικαιώματα που ενισχύθηκαν περαιτέρω με την αναθεώρηση του 2001. Είναι χαρακτηριστικό ότι κατά την αναθεώρηση αυτή κατοχυρώθηκαν, για πρώτη φορά συνταγματικά, πέντε ανεξάρτητες αρχές, οι τρεις εκ των οποίων (Συνήγορος του Πολίτη, Αρχή Διασφάλισης Ατομικών Δικαιωμάτων και Αρχή Προστασίας Προσωπικών Δεδομένων) είναι ταγμένες στην προστασία και διασφάλιση των ατομικών δικαιωμάτων. Η Ελλάδα είναι επίσης μέλος της Ευρωπαϊκής Σύμβασης για τα Δικαιώματα του Ανθρώπου.\n" +
+"Σε πολιτειακό και οργανωτικό επίπεδο, το Σύνταγμα διακρίνει τρεις εξουσίες: τη νομοθετική, την εκτελεστική και τη δικαστική. Στη νομοθετική μετέχουν ο Πρόεδρος της Δημοκρατίας και η Βουλή· στην εκτελεστική ο Πρόεδρος της Δημοκρατίας και η Κυβέρνηση, ενώ η δικαστική εξουσία ασκείται από τα δικαστήρια στο όνομα του ελληνικού λαού.\n" +
+"Ο Πρόεδρος της Δημοκρατίας, ιεραρχικά, βρίσκεται στην κορυφή της εκτελεστικής εξουσίας, μετέχει στη νομοθετική με τη δημοσίευση των νόμων και τη δυνατότητα αναπομπής ψηφισμένου νομοσχεδίου, ενώ ορίζεται από το Σύνταγμα ως ρυθμιστής του πολιτεύματος [2] . Εκλέγεται έμμεσα από τη Βουλή με διαδοχικές ψηφοφορίες των μελών της, στις οποίες επιδιώκεται η εξασφάλιση πλειοψηφίας 2/3, σε πρώτη φάση, και 3/5, σε δεύτερη, του συνόλου των μελών της. Σε περίπτωση αποτυχίας συγκέντρωσης των ανωτέρω πλειοψηφιών, διαλύεται η Βουλή, προκηρύσσονται εκλογές και η νέα Βουλή εκλέγει τον Πρόεδρο της Δημοκρατίας με την απόλυτη πλειοψηφία των μελών της, ή και με σχετική αν δεν συγκεντρωθεί η απόλυτη πλειοψηφία. Οι εξουσίες του Προέδρου είναι περιορισμένες καθώς ασκεί, κυρίως, τελετουργικά καθήκοντα. Όλες, σχεδόν, οι πράξεις του, χρήζουν προσυπογραφής από τον Πρωθυπουργό ή άλλο μέλος της Κυβέρνησης (υπουργό), όπως, π.χ., τα προεδρικά διατάγματα. Από την υποχρέωση προσυπογραφής εξαιρούνται ρητά ελάχιστες πράξεις του Προέδρου που προβλέπονται από το Σύνταγμα, όπως ο διορισμός των υπαλλήλων της Προεδρίας της Δημοκρατίας. Η θητεία του είναι πενταετής με δικαίωμα επανεκλογής για μία ακόμη φορά.\n" +
+"Η νομοθετική εξουσία ασκείται από τη Βουλή, τα μέλη της οποίας εκλέγονται με καθολική μυστική ψηφοφορία για τετραετή θητεία. Εκλογές μπορεί να κηρυχθούν νωρίτερα για έκτακτους λόγους, όπως αυτοί ορίζονται στο Σύνταγμα. Μετά, πάντως, το 1975 η προκήρυξη πρόωρων εκλογών αποτελεί τον κανόνα, με την επίκληση, συνήθως, από τις απερχόμενες κυβερνήσεις ιδιαζούσης σημασίας εθνικού θέματος. Η Ελληνική Δημοκρατία χρησιμοποιεί για την ανάδειξη των βουλευτών ένα σύνθετο ενδυναμωμένο εκλογικό σύστημα αναλογικής εκπροσώπησης (ενισχυμένη αναλογική), που αποθαρρύνει τη δημιουργία πολυκομματικών Κυβερνήσεων συνεργασίας και επιτρέπει ισχυρή κυβέρνηση πλειοψηφίας, ακόμα και αν το πρώτο κόμμα υστερεί της πλειοψηφίας των ψήφων. Για να μπορεί να καταλάβει μία από τις 300 βουλευτικές έδρες ένα κόμμα, πρέπει να έχει λάβει τουλάχιστον το 3% του συνόλου των ψήφων, ενώ με τον εκλογικό νόμο, που θα εφαρμοστεί, για πρώτη φορά, στις μετά το 2004 βουλευτικές εκλογές, το πρώτο κόμμα εξασφαλίζει απόλυτη πλειοψηφία στη Βουλή με ποσοστό 41%.\n" +
+"Η εκτελεστική εξουσία ασκείται από την Κυβέρνηση, κεφαλή της οποίας είναι ο Πρωθυπουργός, το ισχυρότερο πρόσωπο του ελληνικού πολιτικού συστήματος. Η Κυβέρνηση καθορίζει και κατευθύνει τη γενική πολιτική της Χώρας [3], εφαρμόζει την πολιτική, που εγκρίνει μέσω των νομοθετικών πράξεων η Βουλή, αλλά ταυτόχρονα μετέχει στη νομοπαρασκευαστική διαδικασία, μέσω της σύνταξης και της προώθησης προς ψήφιση των νομοσχεδίων. Η Κυβέρνηση με βάση την αρχή της δεδηλωμένης οφείλει να απολαύει της εμπιστοσύνης της Βουλής, να έχει λάβει δηλαδή ψήφο εμπιστοσύνης από την πλειοψηφία των Βουλευτών. Στα πλαίσια δε της σύγχρονης κομματικής δημοκρατίας, η Κυβέρνηση κυριαρχεί και στη νομοθετική λειτουργία, καθώς προέρχεται από το Κόμμα που ελέγχει την πλειοψηφία του Κοινοβουλίου, καθιστώντας, έτσι, την ψήφιση των νόμων μια τυπική, κατά κανόνα, διαδικασία. Λόγω δε της συχνής έως καταχρηστικής επίκλησης της κομματικής πειθαρχίας, η δυνατότητα διαφωνίας κυβερνητικού βουλευτή με την Κυβέρνηση που στηρίζει θεωρείται σπάνιο φαινόμενο. Σε έκτακτες περιπτώσεις μπορεί η Κυβέρνηση να εκδίδει Πράξεις Νομοθετικού Περιεχομένου. Οι Π.Ν.Π. έχουν ισχύ νόμου και οφείλουν να εγκριθούν εντός 40 ημερών από τη Βουλή.\n" +
+"Ο Πρωθυπουργός αποτελεί την κεφαλή της κυβέρνησης και, με βάση το Σύνταγμα, είναι, συνήθως (αν και όχι απαραίτητα), ο αρχηγός του έχοντος την απόλυτη πλειοψηφία στη Βουλή κυβερνώντος κόμματος. Βάσει του άρθρου 82 του Συντάγματος, \"ο Πρωθυπουργός εξασφαλίζει την ενότητα της Κυβέρνησης και κατευθύνει τις ενέργειές της, καθώς και των δημοσίων γενικά υπηρεσιών για την εφαρμογή της κυβερνητικής πολιτικής μέσα στο πλαίσιο των νόμων\" [3]. Οι βασικότερες εξουσίες του είναι οι εξής:\n" +
+"Προεδρεύει του Υπουργικού Συμβουλίου, στο οποίο μετέχει μαζί με τους Υπουργούς.\n" +
+"Με δέσμια πρόταση του διορίζονται και παύονται από τον Πρόεδρο της Δημοκρατίας οι υπουργοί και οι υφυπουργοί της Κυβέρνησης.\n" +
+"Καθορίζει με τον οικείο Υπουργό τις αρμοδιότητες των υφυπουργών.\n" +
+"Προΐσταται τεσσάρων αυτοτελών υπηρεσιών και γραμματειών: του Πολιτικού Γραφείου του Πρωθυπουργού, της Γραμματείας της Κυβερνήσεως, της Κεντρικής Νομοπαρασκευαστικής Επιτροπής και της Γενικής Γραμματείας Τύπου.\n" +
+"Δίνει άδεια για τη δημοσίευση στην Εφημερίδα της Κυβερνήσεως οποιουδήποτε κειμένου πρέπει, κατά το νόμο, να καταχωρισθεί σε αυτήν.\n" +
+"[Επεξεργασία]\n" +
+"Κόμματα\n" +
+"Περισσότερα: Κατάλογος ελληνικών πολιτικών κομμάτων\n" +
+"Μετά την αποκατάσταση της Δημοκρατίας το 1974 (μεταπολίτευση) το πολιτικό σύστημα κυριαρχείται από το φιλελεύθερο κόμμα της Νέας Δημοκρατίας και το σοσιαλιστικό ΠΑΣΟΚ (Πανελλλήνιο Σοσιαλιστικό Κίνημα). Άλλα κόμματα είναι το Κομμουνιστικό Κόμμα Ελλάδας, ο Συνασπισμός της Αριστεράς και ο ΛΑ.Ο.Σ..\n" +
+"[Επεξεργασία]\n" +
+"Κυβέρνηση\n" +
+"Περισσότερα: Κυβέρνηση της Ελλάδας\n" +
+"Στις εκλογές της 7 Μαρτίου 2004, πρωθυπουργός εκλέχθηκε ο Κωνσταντίνος Α. Καραμανλής, πρόεδρος της Νέας Δημοκρατίας. Ήταν η πρώτη εκλογική νίκη του κόμματος μετά από 11 χρόνια. Ο Καραμανλής αντικατέστησε τον Κωνσταντίνο Σημίτη και σχημάτισε δική του κυβέρνηση. Οι επόμενες βουλευτικές εκλογές προβλέπονταν από το Σύνταγμα για το 2008, όμως διεξήχθησαν πρόωρα στις 16 Σεπτεμβρίου 2007. Τις εκλογές της 16ης κέρδισε ξανά η ΝΔ. Η Νέα βουλή είναι η πρώτη πεντακομματική Βουλή τα τελευταία χρόνια και σε αυτή συμμετέχουν η ΝΔ το ΠΑΣΟΚ, το ΚΚΕ, ο ΣΥ.ΡΙ.ΖΑ και το ΛΑ.Ο.Σ. Συγκεκριμένα η ΝΔ εξασφάλισε το 41.83% και 152 από τις 300 Έδρες. Το ΠΑΣΟΚ εξασφάλισε το 38.10 % και 102 Έδρες. Το Κ.Κ.Ε εξασφάλισε το 8.15% και 22 έδρες. Ο ΣΥ.ΡΙ.ΖΑ εξασφάλισε το 5.04% και 14 έδρες και τέλος το ΛΑ.Ο.Σ εξασφάλισε το 3.80% κερδίζοντας 10 έδρες.\n" +
+"[Επεξεργασία]\n" +
+"Περιφέρειες\n" +
+"\n" +
+"Κύριο άρθρο: Περιφέρειες της Ελλάδας\n" +
+"Η Ελλάδα χωρίζεται σε 13 διοικητικές περιοχές γνωστές σαν Περιφέρειες, που διαχωρίζονται περαιτέρω σε 51 Νομούς:\n" +
+"Αττική\n" +
+"Αττική\n" +
+"Στερεά Ελλάδα\n" +
+"Εύβοια\n" +
+"Ευρυτανία\n" +
+"Φωκίδα\n" +
+"Φθιώτιδα\n" +
+"Βοιωτία\n" +
+"Κεντρική Μακεδονία\n" +
+"Χαλκιδική\n" +
+"Ημαθία\n" +
+"Κιλκίς\n" +
+"Πέλλα\n" +
+"Πιερία\n" +
+"Σέρρες\n" +
+"Θεσσαλονίκη\n" +
+"Κρήτη\n" +
+"Χανιά\n" +
+"Ηράκλειο\n" +
+"Λασίθι\n" +
+"Ρέθυμνο\n" +
+"Ανατολική Μακεδονία και Θράκη\n" +
+"Καβάλα\n" +
+"Δράμα\n" +
+"Ξάνθη\n" +
+"Ροδόπη\n" +
+"Έβρος\n" +
+"Ήπειρος\n" +
+"Άρτα\n" +
+"Ιωάννινα\n" +
+"Πρέβεζα\n" +
+"Θεσπρωτία\n" +
+"Ιόνια νησιά\n" +
+"Κέρκυρα\n" +
+"Κεφαλονιά\n" +
+"Λευκάδα\n" +
+"Ζάκυνθος\n" +
+"Βόρειο Αιγαίο\n" +
+"Χίος\n" +
+"Λέσβος\n" +
+"Σάμος - Ικαρία\n" +
+"Πελοπόννησος\n" +
+"Αρκαδία\n" +
+"Αργολίδα\n" +
+"Κορινθία\n" +
+"Λακωνία\n" +
+"Μεσσηνία\n" +
+"Νότιο Αιγαίο\n" +
+"Κυκλάδες\n" +
+"Δωδεκάνησα\n" +
+"Θεσσαλία\n" +
+"Καρδίτσα\n" +
+"Λάρισα\n" +
+"Μαγνησία\n" +
+"Τρίκαλα\n" +
+"Δυτική Ελλάδα\n" +
+"Αχαΐα\n" +
+"Αιτωλοακαρνανία\n" +
+"Ηλεία\n" +
+"Δυτική Μακεδονία\n" +
+"Φλώρινα\n" +
+"Γρεβενά\n" +
+"Καστοριά\n" +
+"Κοζάνη\n" +
+"Επιπλέον, στη Μακεδονία υπάρχει μία αυτόνομη περιοχή, το Άγιο Όρος, μία μοναστική πολιτεία υπό Ελληνική κυριαρχία. Οι νομοί χωρίζονται σε 147 επαρχίες, που διαιρούνται σε 900 δήμους και 133 κοινότητες. Πριν το 1999, υπήρχαν 5.775 οργανισμοί τοπικής αυτοδιοίκησης: 361 δήμοι και 5.560 κοινότητες, υποδιαιρούμενες σε 12.817 οικισμούς\n" +
+"\n" +
+"\n" +
+"\n" +
+"Αλβανία\n" +
+"\n" +
+"П.Γ.Δ.Μ.\n" +
+"\n" +
+"Βουλγαρία\n" +
+"'\n" +
+"\n" +
+"Τουρκία\n" +
+"\n" +
+"EΛΛAΣ\n" +
+"AΘHNA\n" +
+"Θεσσαλονίκη\n" +
+"Καβάλα\n" +
+"Αλεξανδρούπολη\n" +
+"Κέρκυρα\n" +
+"Ηγουμενίτσα\n" +
+"Λάρισα\n" +
+"Βόλος\n" +
+"Ιωάννινα\n" +
+"Χαλκίδα\n" +
+"Πάτρα\n" +
+"Πειραιάς\n" +
+"Ελευσίνα\n" +
+"Λαύριο\n" +
+"Ηράκλειο\n" +
+"Μ α κ ε δ ο ν ί α\n" +
+"Θράκη\n" +
+"Ήπειρος\n" +
+"Θεσσαλία\n" +
+"Στερεά Ελλάδα\n" +
+"Πελοπόννησος\n" +
+"Όλυμπος (2917m)\n" +
+"Λευκάδα\n" +
+"Κεφαλονιά\n" +
+"Λήμνος\n" +
+"Λέσβος\n" +
+"Χίος\n" +
+"Σάμος\n" +
+"Τήνος\n" +
+"Ικαρία\n" +
+"Νάξος\n" +
+"Σαντορίνη\n" +
+"Κως\n" +
+"Ρόδος\n" +
+"Κάρπαθος\n" +
+"Κύθηρα\n" +
+"Γαύδος\n" +
+"Αιγαίον\n" +
+"Πέλαγος\n" +
+"Μυρτώον\n" +
+"Πέλαγος\n" +
+"Κρητικόν Πέλαγος\n" +
+"Ιόνιον\n" +
+"Πέλαγος\n" +
+"Μεσόγειος\n" +
+"Θάλασσα\n" +
+"Κρήτη\n" +
+"[Επεξεργασία]\n" +
+"Βουνά της Ελλάδας\n" +
+"Κύριο άρθρο: Κατάλογος βουνών της Ελλάδας\n" +
+"Περίπου το 80% του εδάφους της χώρας είναι ορεινό ή λοφώδες. Μεγάλο μέρος του είναι ξηρό και βραχώδες, μόνο 28% του εδάφους είναι καλλιεργήσιμο.\n" +
+"Όλυμπος 2917 μ. Θεσσαλία, Κεντρική Μακεδονία (Λάρισα, Πιερία)\n" +
+"Σμόλικας 2637 μ. Βόρεια Πίνδος (Ιωάννινα)\n" +
+"Βόρας 2524 μ. Κεντρική Μακεδονία (Πέλλα, Φλώρινα, Π.Γ.Δ.Μ.)\n" +
+"Γράμος 2520 μ. Δυτική Μακεδονία (Καστοριά, Ιωάννινα, Αλβανία)\n" +
+"Γκιώνα 2510 μ. Στερεά (Φωκίδα)\n" +
+"Τύμφη 2497 μ. Βόρεια Πίνδος (Ιωάννινα)\n" +
+"Βαρδούσια 2495 μ. Στερεά (Φωκίδα)\n" +
+"Αθαμανικά όρη 2469 μ. Νότια Πίνδος (Άρτα)\n" +
+"Παρνασσός 2457 μ. Στερεά (Φωκίδα, Φθιώτιδα)\n" +
+"Ψηλορείτης 2456 μ. Κρήτη (Ηράκλειο)\n" +
+"\n" +
+"\n" +
+"\n" +
+"\n" +
+"Η χώρα αποτελείται από ένα μεγάλο ηπειρωτικό τμήμα, το νότιο άκρο των Βαλκανίων, ενωμένο με την πρώην ηπειρωτική Πελοπόννησο, από τον Ισθμό της Κορίνθου, και το Ιόνιο και Αιγαίο πέλαγος. Η Πελοπόννησος πλέον μετά την κατασκευή της διώρυγας της Κορίνθου είναι στην πραγματικότητα νησί. Το Αιγαίο περιέχει πολυάριθμα νησιά, ανάμεσά τους τη Ρόδο, την Εύβοια, τη Λέσβο και τα συμπλέγματα των Κυκλάδων και Δωδεκανήσων. 180 χιλιόμετρα νότια των ακτών δεσπόζει η Κρήτη, το πέμπτο μεγαλύτερο νησί της Μεσογείου. Η Ελλάδα έχει μήκος ακτών 15.021 χιλιόμετρα, που θεωρείται εξαιρετικά μεγάλο, και οφείλεται στον πλούσιο οριζόντιο εδαφικό διαμελισμό, καθώς και στο πλήθος των αναρίθμητων νησιών, τα οποία είναι πάνω από 1500. Έχει μήκος συνόρων που πλησιάζει τα 1.181 χιλιόμετρα.\n" +
+"\n" +
+"\n" +
+"Δορυφορική εικόνα της Ελλάδας\n" +
+"Κύριο άρθρο: Γεωγραφία της Ελλάδας\n" +
+"[Επεξεργασία]\n" +
+"Λίμνες της Ελλάδας\n" +
+"Κύριο άρθρο: Κατάλογος λιμνών της Ελλάδας\n" +
+"Η Ελλάδα έχει αρκετές λίμνες, οι περισσότερες των οποίων βρίσκονται στο ηπειρωτικό της τμήμα. Οι μεγαλύτερες λίμνες στην ελληνική επικράτεια είναι:\n" +
+"Τριχωνίδα 96.513 τ.χλμ.\n" +
+"Βόλβη 75.600 τ.χλμ\n" +
+"Λίμνη Βεγορίτιδα 72.488 τ.χλμ\n" +
+"Λίμνη Βιστονίδα 45.625 τ.χλμ\n" +
+"Λίμνη Κορώνεια 42.823 τ.χλμ\n" +
+"Μικρή Πρέσπα (ελληνικό τμήμα) 43.122 τ.χλμ\n" +
+"Μεγάλη Πρέσπα (ελληνικό τμήμα) 38.325 τ.χλμ\n" +
+"Κερκίνη 37.688 τ.χλμ\n" +
+"Υπάρχουν επίσης και αρκετές τεχνητές λίμνες κυρίως για παραγωγή ηλεκτρικού ρεύματος, όπως η Λίμνη Κρεμαστών (68.531 τ.χλμ) και η Λίμνη Πολυφύτου (56.793 τ.χλμ).\n" +
+"\n" +
+"[Επεξεργασία]\n" +
+"Ποτάμια της Ελλάδας\n" +
+"Αρκετά ποτάμια διαρρέουν την Ελλάδα, από τα οποίο κανένα δεν είναι πλεύσιμο. Μερικά από τα μεγαλύτερα, τα Δέλτα που σχηματίζουν στην εκροή τους προς την θάλασσα αποτελούν σημαντικούς υγροβιότοπους, όπως αυτοί του Αλιάκμονα και του Έβρου. Ποταμοί όπως ο Πηνειός στην Θεσσαλία, υδροδοτούν μεγάλες γεωργικές εκτάσεις με την βοήθεια καναλιών, ενώ σε άλλα έχουν δημιουργηθεί τεχνητές λίμνες για την λειτουργία υδροηλεκτρικών εργοστασίων. Ένα αμφιλεγόμενο για οικολογικούς λόγους σχέδιο των τελευταίων δεκαετιών, είναι η εκτροπή του Αχελώου από τη νότια Πίνδο για την αντιμετώπιση του υδατικού προβλήματος της Θεσσαλίας.\n" +
+"Ακολουθεί κατάλογος των μεγαλύτερων σε μήκος ποταμών της Ελλάδας. Το μήκος που αναγράφεται είναι αυτό που διατρέχει την ελληνική επικράτεια.\n" +
+"Αλιάκμονας 297 χλμ.\n" +
+"Αχελώος 220 χλμ.\n" +
+"Πηνειός (Θεσσαλίας) 205 χλμ.\n" +
+"Έβρος [4] 204 χλμ.\n" +
+"Νέστος [4] 130 χλμ.\n" +
+"Στρυμόνας [4] 118 χλμ.\n" +
+"Θύαμις (Καλαμάς) 115 χλμ.\n" +
+"Αλφειός 110 χλμ.\n" +
+"Άραχθος 110 χλμ.\n" +
+"[Επεξεργασία]\n" +
+"Κλίμα\n" +
+"Η Ελλάδα χαρακτηρίζεται από τον μεσογειακό τύπο του εύκρατου κλίματος και έχει ήπιους υγρούς χειμώνες και ζεστά ξηρά καλοκαίρια. Το κλίμα της χώρας μπορεί να διαιρεθεί σε τέσσερις βασικές κατηγορίες:\n" +
+"- υγρό μεσογειακό (δυτική Ελλάδα, δυτική Πελοπόννησος, πεδινά και ημιορεινά της Ηπείρου) - ξηρό μεσογειακό (Κυκλάδες, παραλιακή Κρήτη, Δωδεκάνησα, ανατολική Πελοπόννησος, Αττική, πεδινές περιοχές Ανατολικής Στερεάς) - ηπειρωτικό (δυτική Μακεδονία, εσωτερικά υψίπεδα ηπειρωτικής Ελλάδας, βόρειος Έβρος) - ορεινό (ορεινές περιοχές με υψόμετρο περίπου >1500μ στη βόρεια Ελλάδα, >1800μ στην κεντρική Ελλάδα και >2000μ στην Κρήτη).\n" +
+"Οι θερμοκρασίες είναι σπάνια υπερβολικές στις παραθαλάσσιες περιοχές. Στις κλειστές εσωτερικές πεδιάδες και στα υψίπεδα της χώρας παρατηρούνται τα μεγαλύτερα θερμοκρασιακά εύρη -τόσο ετήσια όσο και ημερήσια. Οι χιονοπτώσεις είναι κοινές στα ορεινά από τα τέλη Σεπτεμβρίου (στη βόρεια Ελλάδα, τέλη Οκτωβρίου κατά μέσο όρο στην υπόλοιπη χώρα), ενώ στις πεδινές περιοχές χιονίζει κυρίως από τον Δεκέμβριο μέχρι τα μέσα Μαρτίου. Έχει χιονίσει, πάντως, ακόμα και κατά μήνα Μάιο στη Φλώρινα. Στις παραθαλάσσιες περιοχές των νησιωτικών περιοχών, οι χιονοπτώσεις συμβαίνουν σπανιότερα και δεν αποτελούν βασικό χαρακτηριστικό του κλίματος. Η πόλη της Ρόδου έχει μέσο όρο 0,0 μέρες χιονόπτωσης το χρόνο. Οι καύσωνες επηρεάζουν κυρίως τις πεδινές περιοχές και είναι κοινότεροι τον Ιούλιο και τον Αύγουστο. Σπάνια, πάντως, διαρκούν περισσότερες από 3 μέρες.\n" +
+"Η Ελλάδα βρίσκεται μεταξύ των παραλλήλων 34ου και 42oυ του βορείου ημισφαιρίου και έχει μεγάλη ηλιοφάνεια όλο σχεδόν το χρόνο. Λεπτομερέστερα στις διάφορες περιοχές της Ελλάδας παρουσιάζεται μια μεγάλη ποικιλία κλιματικών τύπων, πάντα βέβαια μέσα στα πλαίσια του μεσογειακού κλίματος. Αυτό οφείλεται στην τοπογραφική διαμόρφωση της χώρας που έχει μεγάλες διαφορές υψομέτρου (υπάρχουν μεγάλες οροσειρές κατά μήκος της κεντρικής χώρας και άλλοι ορεινοί όγκοι) και εναλλαγή ξηράς και θάλασσας. Έτσι από το ξηρό κλίμα της Αττικής και γενικά της ανατολικής Ελλάδας μεταπίπτουμε στο υγρό της βόρειας και δυτικής Ελλάδας. Τέτοιες κλιματικές διαφορές συναντώνται ακόμη και σε τόπους που βρίσκονται σε μικρή απόσταση μεταξύ τους, πράγμα που παρουσιάζεται σε λίγες μόνο χώρες σε όλο τον κόσμο.\n" +
+"Από κλιματολογικής πλευράς το έτος μπορεί να χωριστεί κυρίως σε δύο εποχές: Την ψυχρή και βροχερή χειμερινή περίοδο που διαρκεί από τα μέσα του Οκτωβρίου και μέχρι το τέλος Μαρτίου και τη θερμή και άνομβρη εποχή που διαρκεί από τον Απρίλιο έως τον Οκτώβριο.\n" +
+"Κατά την πρώτη περίοδο οι ψυχρότεροι μήνες είναι ο Ιανουάριος και ο Φεβρουάριος, όπου κατά μέσον όρο η μέση ελάχιστη θερμοκρασία κυμαίνεται από 5-10 °C στις παραθαλάσσιες περιοχές, από 0-5 °C στις ηπειρωτικές περιοχές και σε χαμηλότερες τιμές κάτω από το μηδέν στις βόρειες περιοχές.\n" +
+"Οι βροχές ακόμη και τη χειμερινή περίοδο δεν διαρκούν για πολλές ημέρες και ο ουρανός της Ελλάδας δεν μένει συννεφιασμένος για αρκετές συνεχόμενες ημέρες, όπως συμβαίνει σε άλλες περιοχές της γης. Οι χειμερινές κακοκαιρίες διακόπτονται συχνά κατά τον Ιανουάριο και το πρώτο δεκαπενθήμερο του Φεβρουαρίου από ηλιόλουστες ημέρες, τις γνωστές από την αρχαιότητα Αλκυονίδες ημέρες.\n" +
+"Η χειμερινή εποχή είναι γλυκύτερη στα νησιά του Αιγαίου και του Ιονίου από ό,τι στη Βόρεια και Ανατολική ηπειρωτική Ελλάδα. Κατά τη θερμή και άνομβρη εποχή ο καιρός είναι σταθερός, ο ουρανός σχεδόν αίθριος, ο ήλιος λαμπερός και δεν βρέχει εκτός από σπάνια διαστήματα με ραγδαίες βροχές ή καταιγίδες μικρής γενικά διάρκειας.\n" +
+"Η θερμότερη περίοδος είναι το τελευταίο δεκαήμερο του Ιουλίου και το πρώτο του Αυγούστου οπότε η μέση μεγίστη θερμοκρασία κυμαίνεται από 29 °C μέχρι 35 °C. Κατά τη θερμή εποχή οι υψηλές θερμοκρασίες μετριάζονται από τη δροσερή θαλάσσια αύρα στις παράκτιες περιοχές της χώρας και από τους βόρειους ανέμους (ετησίες) που φυσούν κυρίως στο Αιγαίο.\n" +
+"Η άνοιξη έχει μικρή διάρκεια, διότι ο μεν χειμώνας είναι όψιμος, το δε καλοκαίρι αρχίζει πρώιμα. Το φθινόπωρο είναι μακρύ και θερμό και πολλές φορές παρατείνεται στη νότια Ελλάδα μέχρι τα μισά του Δεκεμβρίου.\n" +
+"[Επεξεργασία]\n" +
+"Οικονομία\n" +
+"\n" +
+"Κύριο άρθρο: Οικονομία της Ελλάδας\n" +
+"Η Ελλάδα έχει μικτή καπιταλιστική οικονομία, με τον δημόσιο τομέα να συνεισφέρει περίπου στο μισό του Α.Ε.Π.. Ο Τουρισμός αποτελεί μία πολύ σημαντική βιομηχανία, που συνεισφέρει κι αυτή σε μεγάλο ποσοστό του Α.Ε.Π., και επίσης αποτελεί πηγή συναλλάγματος. Το 2004 η μεγαλύτερη βιομηχανία στην Ελλάδα με έσοδα γύρω στα 12 δισ. ευρώ ήταν η συνήθως σχετικά αφανής ναυτιλία.\n" +
+"Η οικονομία βελτιώνεται σταθερά τα τελευταία χρόνια, καθώς η κυβέρνηση εφάρμοσε αποτελεσματική οικονομική πολιτική, στην προσπάθεια της ένταξης της Ελλάδας στην ζώνη του ευρώ, την 1 Ιανουαρίου 2001. Παράγων που σίγουρα βοήθησε σε αυτήν την πορεία είναι ότι η Ελλάδα είναι αποδέκτης οικονομικής βοήθειας από την Ευρωπαϊκή Ένωση, ίσης περίπου με το 3,3% του Α.Ε.Π. Η συνέχιση τόσο γενναιόδωρων ενισχύσεων από την Ε.Ε. όμως είναι υπό αμφισβήτηση. Η διεύρυνση της Ευρωπαϊκής Ένωσης με την είσοδο χωρών πολύ φτωχότερων από την Ελλάδα σε συνδυασμό με την ανοδική πορεία της ελληνικής οικονομίας θα βγάλει πιθανότατα πολλές περιοχές από τον λεγόμενο Στόχο 1 του Κοινοτικού Πλαισίου Στήριξης στον οποίο κατευθύνονται και οι περισσότερες επιδοτήσεις και στον οποίο ανήκουν περιοχές με Α.Ε.Π. κατά κεφαλήν μικρότερο του 75% του ευρωπαϊκού μέσου όρου. Με τα στοιχεία του 2003 από τον Στόχο 1 έχουν βγει οι εξής περιοχές: Αττική, Νότιο Αιγαίο, Στερεά Ελλάδα, Κεντρική Μακεδονία, Βόρειο Αιγαίο και οριακά η Πελοπόννησος.\n" +
+"Μεγάλες προκλήσεις παραμένουν, η μείωση της ανεργίας και η περαιτέρω ανοικοδόμηση της οικονομίας μέσω και της ιδιωτικοποίησης διαφόρων μεγάλων κρατικών εταιρειών, η αναμόρφωση της κοινωνικής ασφάλισης, διόρθωση του φορολογικού συστήματος, και η ελαχιστοποίηση των γραφειοκρατικών αδυναμιών. Η ανάπτυξη υπολογίζεται σε 3,9% για το 2004.\n" +
+"Η εθνική κεντρική τράπεζα του κράτους της Ελλάδας είναι η Τράπεζα της Ελλάδος (ΤτΕ), η οποία όμως έχει παραχωρήσει τις περισσότερες αρμοδιότητές της στην Ευρωπαϊκή Κεντρική Τράπεζα (Ε.Κ.Τ.), μετά την είσοδό της στην ζώνη του ευρώ το 2001.\n" +
+"[Επεξεργασία]\n" +
+"Δημογραφία\n" +
+"\n" +
+"Κύριο άρθρο: Δημογραφία της Ελλάδας\n" +
+"Άρθρο βασικών αποτελεσμάτων απογραφής: Απογραφή 2001\n" +
+"Σύμφωνα με την τελευταία απογραφή (2001)[5] ο μόνιμος πληθυσμός της χώρας είναι 10.934.097 κ. Την ημέρα της απογραφής, στη χώρα βρέθηκαν και απογράφηκαν (πραγματικός πληθυσμός) 10.964.020 κ.\n" +
+"Η Διεθνής Έκθεση για τις Θρησκευτικές Ελευθερίες που συντάσσει κάθε έτος το Υπουργείο Εξωτερικών των Ηνωμένων Πολιτειών, αναφέρει το 2005: «Περίπου 97% των πολιτών αυτοπροσδιορίζονται, τουλάχιστον κατ’ όνομα, ως Ελληνoρθόδοξοι. Υπάρχουν περίπου 500.000-800.000 παλαιοημερολογίτες σε ολόκληρη τη χώρα – υπερ-συντηρητικοί Ορθόδοξοι, οι οποίοι χρησιμοποιούν το Ιουλιανό ημερολόγιο και είναι αφοσιωμένοι στις παραδοσιακές Ελληνορθόδοξες πρακτικές. Η κυβέρνηση δεν τηρεί στατιστικά στοιχεία για τις θρησκευτικές ομάδες. Κατά τη διάρκεια των απογραφών πληθυσμού, οι κάτοικοι δεν ερωτώνται για το θρησκευτικό τους πιστεύω. Οι αρχές υπολογίζουν ότι η Τουρκόφωνη Μουσουλμανική κοινότητα αριθμεί 98.000 άτομα, αλλά, άλλοι υπολογίζουν ότι ο αριθμός αυτός ανέρχεται σε 140.000 άτομα. Τα περισσότερα χριστιανικά μη Ορθόδοξα δόγματα συναπαρτίζονται κατά κύριο λόγο από γηγενείς Έλληνες. Οι Μάρτυρες του Ιεχωβά αναφέρουν ότι έχουν 30.000 περίπου ενεργά μέλη και 50.000 άτομα που έχουν προσχωρήσει στην πίστη. Οι Καθολικοί υπολογίζονται σε 50.000. Οι Προτεστάντες, συμπεριλαμβανόμενων των Ευαγγελιστών, είναι 30.000, και οι οπαδοί της Εκκλησίας του Ιησού Χριστού των Αγίων των Τελευταίων Ημερών (Μορμόνοι) 300. Οι Σαϊεντολόγοι ισχυρίζονται ότι έχουν 500 ενεργά εγγεγραμμένα μέλη. Η από αιώνων υπάρχουσα Εβραϊκή κοινότητα αριθμεί περίπου 5.000 πιστούς, από τους οποίους 2.000 υπολογίζεται ότι διαμένουν στη Θεσσαλονίκη. Περίπου 250 μέλη της κοινότητας των Μπαχάι είναι διασκορπισμένα στην χώρα, τα περισσότερα των οποίων δεν είναι πολίτες ελληνικής καταγωγής. Η αρχαία Ελληνική Θρησκεία του Δωδεκαθέου έχει περίπου 2.000 μέλη. Υπάρχουν ακόμα μικρές ομάδες Αγγλικανών, Βαπτιστών, καθώς και άλλοι Χριστιανοί που δεν ανήκουν σε κάποιο συγκεκριμένο δόγμα. Δεν υπάρχει επίσημη ή ανεπίσημη εκτίμηση ως προς τον αριθμό των αθέων. Η πλειοψηφία των κατοίκων μη ελληνικής υπηκοότητας δεν είναι Ορθόδοξοι. Η μεγαλύτερη από αυτές τις ομάδες είναι Αλβανοί[5], συμπεριλαμβανόμενων των νομίμων και παρανόμων μεταναστών. Αν και οι περισσότεροι Αλβανοί δεν ανήκουν σε κάποια θρησκεία, παραδοσιακά συνδέονται με τη Μουσουλμανική, την Ορθόδοξη, ή τη Ρωμαιοκαθολική πίστη. Εκτός της εντόπιας Μουσουλμανικής μειονότητας στη Θράκη, οι Μουσουλμάνοι μετανάστες που βρίσκονται στην υπόλοιπη χώρα υπολογίζεται ότι ανέρχονται σε 200.000-300.000.» [6]\n" +
+"Τις τελευταίες δεκαετίες η Ελλάδα έχει δεχτεί ένα μεγάλο κύμα μετανάστευσης. Ο συνολικός αριθμός των μεταναστών υπολογίζεται περίπου στο 10% του συνολικού πληθυσμού ή στις 950.000 ανθρώπους. Νόμιμοι κάτοικοι της χώρας είναι περίπου οι μισοί αν και οι αριθμοί έχουν μεγάλη διακύμανση λόγω της έλλειψης επίσημης μεταναστευτικής πολιτικής και της αστάθειας στις γειτονικές χώρες πηγές μεταναστών. Οι μεγαλύτερες πληθυσμιακές ομάδες σύμφωνα με την απογραφή του 2001 φαίνεται να είναι οι προερχόμενοι από Αλβανία, Ρουμανία, Βουλγαρία, Πακιστάν, Ουκρανία, Πολωνία, Αίγυπτο.\n" +
+"Πέρα από τους αλλοδαπούς μετανάστες έχουν έρθει μετά την πτώση του Τείχους και αρκετοί ομογενείς από περιοχές της πρώην Ε.Σ.Σ.Δ. και από τα Βαλκάνια. Οι μεγαλύτερες ομάδες παλιννοστούντων είναι από την Αλβανία, την Ρωσία και την Γεωργία.\n" +
+"[Επεξεργασία]\n" +
+"Ένοπλες δυνάμεις και Σώματα ασφαλείας\n" +
+"\n" +
+"Ελληνικές Ένοπλες Δυνάμεις:\n" +
+"Ελληνικός Στρατός\n" +
+"Ελληνικό Πολεμικό Ναυτικό\n" +
+"Ελληνική Πολεμική Αεροπορία\n" +
+"Σώματα ασφαλείας:\n" +
+"Ελληνική Αστυνομία\n" +
+"Πυροσβεστικό Σώμα\n" +
+"Λιμενικό Σώμα\n" +
+"[Επεξεργασία]\n" +
+"Υποχρεωτική στράτευση\n" +
+"Κύριο άρθρο: Η θητεία στην Ελλάδα\n" +
+"Μέχρι το 2004, η Ελλάδα είχε νομοθετήσει υποχρεωτική θητεία 12 μηνών, για όλους τους άνδρες άνω των 18 ετών. Ωστόσο, κινείται προς την ανάπτυξη ενός πλήρως επαγγελματικού στρατού, με στόχο την πλήρη κατάργηση της θητείας. Το Υπουργείο Εθνικής Άμυνας έχει αναγγείλει τη σταδιακή μείωση στους 6 μήνες το 2008 και πιθανολογείται ότι μπορεί και να καταργηθεί τελείως. Παρότι γίνονται δεκτές αιτήσεις γυναικών που θέλουν να υπηρετήσουν, δεν είναι υποχρεωτικό. Η κίνηση αυτή δημιουργεί αντιρρήσεις από τους κύκλους που αντιτίθενται στην υποχρεωτική στράτευση, γιατί ενώ το Άρθρο 2 του Ελληνικού Συντάγματος θέτει υπόχρεους όλους τους Έλληνες πολίτες να υπερασπιστούν την Ελλάδα, ο φόρτος έγκειται ολοκληρωτικά στον ανδρικό πληθυσμό.\n" +
+"Οι κληρωτοί δεν λαμβάνουν ιατρική ασφάλιση κατά τη διάρκεια της θητείας τους, ούτε ο χρόνος της θητείας συνυπολογίζεται στα χρόνια εργασίας τους που θεμελιώνουν το συνταξιοδοτικό δικαίωμα. Λαμβάνουν, όμως, πλήρη ιατρική και νοσοκομειακή περίθαλψη από τα κατά τόπους στρατιωτικά νοσοκομεία, εφ' όσον αυτά υπάρχουν στον τόπο που υπηρετούν, αλλιώς αναγκάζονται να μεταφερθούν στην Αθήνα. Ο μισθός του κληρωτού είναι συμβολικός (9 ευρώ το μήνα για τους οπλίτες, σμηνίτες, κληρωτούς, 11 ευρώ για τους στρατεύσιμους δεκανείς, υποσμηνίες, υποκελευστές και τους στρατεύσιμους λοχίες, σμηνίες, κελευστές και 600 ευρώ για τους δόκιμους και των τριών σωμάτων). Οι δόκιμοι υπηρετούν 5 μήνες παραπάνω από τους υπόλοιπους συναδέλφους τους. Ο μισθός δεν αρκεί για να καλύψει τα έξοδα των κληρωτών, ιδιαίτερα όταν ένας κληρωτός υπηρετεί μακριά από τον τόπο διαμονής του, με αποτέλεσμα πρακτικά οι κληρωτοί να ζούνε από την οικονομική στήριξη των γονέων τους κατά την διάρκεια της θητείας τους.\n" +
+"[Επεξεργασία]\n" +
+"Πολιτισμός\n" +
+"\n" +
+"Κατάλογος διάσημων Ελλήνων\n" +
+"Ελληνική μυθολογία\n" +
+"Αρχαία ελληνική λογοτεχνία\n" +
+"Ελληνική Αρχιτεκτονική\n" +
+"Ελληνική κουζίνα\n" +
+"Ελληνική Γλώσσα\n" +
+"Ελληνική Μουσική\n" +
+"Ελληνικά Μουσεία\n" +
+"Μέσα Ενημέρωσης\n" +
+"[Επεξεργασία]\n" +
+"Αργίες\n" +
+"Ημερομηνία	Ονομασία	Σχόλια\n" +
+"1 Ιανουαρίου	Πρωτοχρονιά	 \n" +
+"6 Ιανουαρίου	Θεοφάνεια	 \n" +
+"κινητή	Καθαρά Δευτέρα	έναρξη της Μεγάλης Τεσσαρακοστής\n" +
+"25η Μαρτίου	Ευαγγελισμός της Θεοτόκου και Εθνική Εορτή	Εθνική Εορτή για την Επανάσταση του 1821\n" +
+"κινητή	Μεγάλη Παρασκευή	 \n" +
+"κινητή	Πάσχα	Ανάσταση του Χριστού\n" +
+"κινητή	Δευτέρα Διακαινησίμου (Δευτέρα του Πάσχα)	Δευτέρα μετά την Ανάσταση\n" +
+"1 Μαΐου	Πρωτομαγιά	 \n" +
+"κινητή	Αγίου Πνεύματος	 \n" +
+"15 Αυγούστου	Κοίμηση της Θεοτόκου	 \n" +
+"28η Οκτωβρίου	Επέτειος του Όχι	Εθνική Εορτή (1940)\n" +
+"25 Δεκεμβρίου	Χριστούγεννα	 \n" +
+"26 Δεκεμβρίου	Σύναξις Θεοτόκου	 \n" +
+"[Επεξεργασία]\n" +
+"Σημειώσεις\n" +
+"\n" +
+"↑ www.destatis.de εκτίμηση πληθυσμού χώρας, 2006\n" +
+"↑ Σύνταγμα της Ελλάδας, άρθρο 30\n" +
+"↑ 3,0 3,1 Σύνταγμα της Ελλάδας, άρθρο 82\n" +
+"↑ 4,0 4,1 4,2 Πηγάζει στη Βουλγαρία\n" +
+"↑ 5,0 5,1 απογραφή 2001\n" +
+"↑ Πηγή: Διεθνής Έκθεση Θρησκευτικής Ελευθερίας του 2005 στην ελληνική και στην αγγλική, Υπουργείο Εξωτερικών των Η.Π.Α.\n" +
+"[Επεξεργασία]\n" +
+"Δείτε επίσης\n" +
+"\n" +
+"Σημαία της Ελλάδας\n" +
+"Κατάλογος γλωσσών της Ελλάδας\n" +
+"Τράπεζα της Ελλάδος\n" +
+"Ονομασίες της Ελλάδας σε διάφορες γλώσσες\n" +
+"Άτλας της Ελλάδας: συλλογή διαφόρων χαρτών της Ελλάδας στα Κοινά (Commons).\n" +
+"Κατάλογος νοσοκομείων της Ελλάδας\n" +
+"[Επεξεργασία]\n" +
+"Εξωτερικές συνδέσεις\n" +
+"\n" +
+"Πρωθυπουργός της Ελλάδας (Γραφείο Πρωθυπουργού)\n" +
+"Βουλή των Ελλήνων\n" +
+"Παράθυρο στην Ελλάδα (χρήσιμες πληροφορίες και σύνδεσμοι για την Ελλάδα)\n" +
+"Παράθυρο στην Ελλάδα (παλαιότερη «έκδοση»)\n" +
+"Ελληνικός Οργανισμός Τουρισμού\n" +
+"Υπουργείο Εξωτερικών\n";
+
+
+var hebrew =
+"היסטוריה של סין\n" +
+"מתוך ויקיפדיה, האנציקלופדיה החופשית\n" +
+"קפיצה אל: ניווט, חפש\n" +
+"\n" +
+"    ערך זה עוסק בההיסטוריה של הישות התרבותית והגאוגרפית במזרח אסיה. אם התכוונתם לההיסטוריה של מדינה המוכרת היום בשם \"סין\", ראו היסטוריה של הרפובליקה העממית של סין.\n" +
+"\n" +
+"בערך זה מופיע גופן מזרח אסייתי\n" +
+"\n" +
+"כדי שתוכלו לראות את הכתוב בערך זה בצורה תקינה, תצטרכו להתקין גופן מזרח אסייתי במחשבכם. אם אינכם יודעים כיצד לעשות זאת, לחצו כאן לקבלת עזרה\n" +
+"\n" +
+"סין הנה התרבות המפותחת והרציפה העתיקה ביותר בעולם, תיעודים כתובים של התרבות נמצאים כבר מלפני 3,500 שנים והסינים עצמם נוקבים במספר 5,000 כמספר שנות קיומה של תרבותם. שושלות השלטון בסין פיתחו לאורך השנים שיטות בירוקרטיה שלטונית שהעניקו לסינים יתרון משמעותי על העמים השבטיים שחיו מסביבם. פיתוח אידאולוגיה למדינה, המבוססת על משנתו הפילוסופית של קונפוציוס (המאה ה-1 לפנה\"ס), יחד עם פיתוח מערכת כתב זמינה לכל (המאה ה-2 לפנה\"ס) חיזקו עוד יותר את התרבות הסינית. מבחינה פוליטית, סין נעה בתנועה מתמדת בין איחוד ופירוד ולעתים גם נכבשה על ידי כוחות זרים אשר מרביתם התמזגו לתוך תרבותה והפכו לחלק בלתי נפרד ממנה. השפעות תרבותיות ופוליטיות אלו שהגיעו מכל קצוות אסיה כמו גם גלי הגירה אל ומחוץ למדינה יצרו יחד את דמותם של התרבות והעם הסיני כפי שהם מוכרים לנו היום.\n" +
+"היסטוריה של סין\n" +
+"\n" +
+"    * התקופה הקדומה\n" +
+"\n" +
+"    שלושת המלכים וחמשת הקיסרים\n" +
+"    שושלת שיה\n" +
+"    שושלת שאנג\n" +
+"    שושלת ג'ואו\n" +
+"    תקופת האביב והסתיו\n" +
+"    תקופת המדינות הלוחמות\n" +
+"\n" +
+"    * סין הקיסרית\n" +
+"\n" +
+"    שושלת צ'ין\n" +
+"    שושלת האן המערבית\n" +
+"    שושלת שין\n" +
+"    שושלת האן המזרחית\n" +
+"    שלושת הממלכות\n" +
+"    שושלת ג'ין\n" +
+"    השושלת הצפונית והדרומית\n" +
+"    שושלת סוי\n" +
+"    שושלת טאנג\n" +
+"    שושלת סונג\n" +
+"    שושלת יו'אן\n" +
+"    שושלת מינג\n" +
+"    שושלת צ'ינג\n" +
+"\n" +
+"    * התפוררות הקיסרות\n" +
+"\n" +
+"    מלחמת האופיום הראשונה\n" +
+"    מרד טאיפינג\n" +
+"    מלחמת האופיום השנייה\n" +
+"    מלחמת סין-צרפת\n" +
+"    מלחמת סין-יפן הראשונה\n" +
+"    רפורמת מאה הימים\n" +
+"    מרד הבוקסרים\n" +
+"\n" +
+"    * סין המודרנית\n" +
+"\n" +
+"    מהפכת שינהאי\n" +
+"    הקמתה של המפלגה הקומניסטית של סין\n" +
+"    המצעד הארוך\n" +
+"    תקרית שיאן\n" +
+"    מלחמת סין-יפן השנייה\n" +
+"    מלחמת האזרחים הסינית\n" +
+"\n" +
+"    * העת החדשה\n" +
+"\n" +
+"    הקמת הרפובליקה העממית של סין\n" +
+"    מערכת מאה הפרחים\n" +
+"    הזינוק הגדול קדימה\n" +
+"    הפיצול הסיני-סובייטי\n" +
+"    מלחמת הודו-סין\n" +
+"    מהפכת התרבות בסין\n" +
+"    תקרית טיאנאנמן\n" +
+"\n" +
+"ראו גם\n" +
+"\n" +
+"    * הרפובליקה הסינית\n" +
+"    * לוח זמנים של ההיסטוריה של סין\n" +
+"\n" +
+"פורטל סין\n" +
+"קטגוריה ראשית\n" +
+"\n" +
+"\n" +
+"תוכן עניינים\n" +
+"[הסתר]\n" +
+"\n" +
+"    * 1 פרה-היסטוריה\n" +
+"          o 1.1 שלושת המלכים וחמשת הקיסרים\n" +
+"    * 2 היסטוריה קדומה\n" +
+"          o 2.1 שושלת שְׂיָה\n" +
+"          o 2.2 שושלת שָׁאנְג\n" +
+"          o 2.3 שושלת ג'וֹאוּ\n" +
+"          o 2.4 תקופת האביב והסתיו\n" +
+"          o 2.5 תקופת המדינות הלוחמות\n" +
+"    * 3 שושלת צ'ין: האימפריה הסינית הראשונה\n" +
+"    * 4 שושלת האן: תקופה של שגשוג\n" +
+"    * 5 ג'ין, שש עשרה הממלכות והשושלות הדרומית והצפונית: התקופה האפלה של סין\n" +
+"    * 6 שושלת טאנג: חזרה לשיגשוג\n" +
+"    * 7 שושלת סונג ושכנותיה הצפוניות, ליאו וג'ין\n" +
+"    * 8 המונגולים\n" +
+"    * 9 תחייתה מחדש של התרבות הסינית\n" +
+"    * 10 תקופת מינג: מהתפתחות לבידוד\n" +
+"    * 11 שושלת צ'ינג\n" +
+"    * 12 הרפובליקה הסינית\n" +
+"    * 13 הרפובליקה העממית של סין\n" +
+"    * 14 ראו גם\n" +
+"    * 15 לקריאה נוספת\n" +
+"    * 16 קישורים חיצוניים\n" +
+"    * 17 הערות שוליים\n" +
+"\n" +
+"[עריכה] פרה-היסטוריה\n" +
+"\n" +
+"העדויות הארכאולוגיות הקדומות ביותר לנוכחות אנושית בסין של ימינו הן של הומו ארקטוס. מחקרים חדשים מגלים כי עמודי האבן שנמצאו באתר שיאוצ'אנגליאנג מתאורכים מבחינה סטרטיגרפית מלפני 1.36 מיליוני שנים. באתר הארכאולוגי שִׂיהוֹאוּדוּ שבמחוז שאנסי נמצאות העדויות הראשונות בעולם לשימוש באש על ידי ההומו ארקטוס, ומתאורכות ללפני 1.27 מיליוני שנים. עם זאת תושביו הנוכחיים של האזור אינם צאצאי אותו הומו ארקטוס, אלא צאצאי הומו סאפיינס שהגיע לאזור מאזור אפריקה רק לפני 65,000 שנים.\n" +
+"\n" +
+"עדויות מוקדמות לחקלאות סינית טיפוסית – גידולי אורז בברכות – מתוארכות לשנת 6,000 לפנה\"ס. בדומה לתרבויות קדומות בכל העולם, הביאה החקלאות לגידול מהיר באוכלוסייה, כיוון שהתבססות על גידולים חקלאיים הבטיחה יכולת שימור המזון ואגירתו לזמן ממושך יותר, וזו הביאה בהדרגה לגידול האוכלוסייה, להתפתחותה התרבותית ולריבוד חברתי.\n" +
+"\n" +
+"בשלהי התקופה הניאוליטית החל עמק הנהר הצהוב בסין לפתח את מעמדו כמרכז תרבותי, כאשר ראשוני הכפרים באזור הופיעו שם. מרבית העדויות למרכז חשוב זה נמצאות באזור העיר שי-אן בסין.\n" +
+"\n" +
+"[עריכה] שלושת המלכים וחמשת הקיסרים\n" +
+"\n" +
+"    ערך מורחב – שלושת המלכים וחמשת הקיסרים\n" +
+"\n" +
+"ספרי ההיסטוריה הקדומים, רשומות ההיסטוריון, שנכתבו על ידי ההיסטורוגרף הסיני סְה-מָה צְ'ייֵן במאה השנייה לפנה\"ס, וספר תולדות החיזרן, שנכתבו במאה הרביעית לפנה\"ס מתארכים את תחילת ההיסטוריה הסינית לתקופת שלושת המלכים וחמשת הקיסרים - 2800 לפנה\"ס. לתקופה זו מאפיינים מיתולוגיים מובהקים. למלכים ולקיסרים תכונות מיסטיות והם מתוארים כשליטים נבונים ובעלי מוסר למופת. אחד מהם, הקיסר הצהוב נחשב לאבי בני ההאן.\n" +
+"\n" +
+"סה-מה צ'יאן כותב כי תחילת ביסוס מערכת ממשלתית נעשה בימי שושלת שיה, וסגנון המערכת הונצח על ידי שושלות שאנג וג'ואו. בתקופת שלושת השושלות האלו, החלה סין לפצוע על שחר ההיסטוריה. מכאן ואילך, עד למאה העשרים, מתוארות תולדות סין לפי השושלות שמשלו בה.\n" +
+"\n" +
+"[עריכה] היסטוריה קדומה\n" +
+"\n" +
+"[עריכה] שושלת שְׂיָה\n" +
+"\n" +
+"    ערך מורחב – שושלת שיה\n" +
+"\n" +
+"שושלת שְׂיָה (סינית: 夏, פיניין: Xià), היא השושלת הראשונה בתולדות סין. שושלת זו התקיימה לפני המצאת הכתב בסין, כך שהעדויות לקיומה מסתמכות על מסמכים מאוחרים יותר ועל ארכאולוגיה. סְה-מָה צְ'ייֵן וספר תולדות החיזרן מתארכים את ימי השושלת לכלפני 4,200 שנה, אולם אין בידינו לאמת את הדברים. 17 מלכים ו-14 דורות מנתה השושלת, שהתחילה בימיו של יוּ'‏ הגדול והסתיימה בימיו של גְ'יֵה איש שְׂיָה, כך על-פי סְה-מָה צְ'ייֵן ומקורות אחרים מתקופת שושלת צ'ין.\n" +
+"\n" +
+"שושלות שאנג וג'ואו התקיימו במקביל לשושלת שיה כבר מתחילתה, אך היו כפופות לה. אורך ימיה של השושלת לא ברור, אך 431 או 471 שנים הן שתי החלופות הסבירות ביותר.\n" +
+"\n" +
+"ארכאולוגים רבים מזהים את שושלת שְׂיָה עם אתר אָרלִיטוֹאוּ שבמרכז מחוז הנאן[1]. באתר זה נתגלה כור היתוך מברונזה משנת 2000 לפנה\"ס לערך. נטען גם כי סימונים על-גבי חרס וקונכיות מתקופה זו הן גילגול קדום של הכתב הסיני[2]. בהיעדר עדויות כתובות בכתב המוכר מעצמות הניחוש של שושלת שאנג ומכלי הברונזה של שושלת ג'ואו, נותר טיבה של שושלת שיה לוט בערפל.\n" +
+"\n" +
+"[עריכה] שושלת שָׁאנְג\n" +
+"\n" +
+"    ערך מורחב – שושלת שאנג\n" +
+"\n" +
+"הרישומים הכתובים העתיקים ביותר בסין נחרטו לצורך הגדת עתידות על עצמות או קונכיות. כתבים אלה, המכונים עצמות ניחוש, מתוארכים למאה ה-13 לפנה\"ס לערך, תקופת שושלת שָׁאנְג (סינית: 商, פיניין: Shāng). ממצאים ארכאולוגיים, המעידים על קיומה של השושלת בשנים 1600-1046 לפנה\"ס בקירוב, מחולקים לשתי קבוצות. הקבוצה המוקדמת, עד ל-1300 בקירוב, מגיעה מאתרים שונים במחוז הנאן. הקבוצה המאוחרת, מתקופת יִין (殷), מורכבת מאסופה רחבה של עצמות ניחוש, גם הן ממחוז הנאן. אָנְיָאנְג שבמחוז הנאן הייתה הבירה התשיעית והאחרונה של שושלת שאנג. לשושלת היו 31 מלכים, והיא הייתה הארוכה שבשושלות סין.\n" +
+"\n" +
+"על פי רשומות ההיסטוריון העבירה שושלת שאנג את בירתה שש פעמים, כשהמעבר השישי והאחרון לעיר יִין ב-1350 לפנה\"ס סימן את תחילת תור הזהב של השושלת. ההיסטוריה התמטית של סין מתארת בדרך-כלל קיום של שושלת אחת אחרי השנייה, אך המצב לאשורו באותה עת היה מורכב יותר. חוקרים טוענים כי ייתכן ושושלות שיה ושאנג התקיימו במקביל, כשם ששושלת ג'ואו (שֶׁירשה את שושלת שאנג), התקיימה אף היא בזמן שושלת שאנג. עדויות כתובות מאתר אניאנג מאששים אמנם את קיומה של שושלת שאנג, אך חוקרים מערביים אינם נוטים לזהות יישובים בני אותה תקופה עם שושלת שאנג דווקא. כך למשל, ממצאים ארכאולוגיים מאותה עת באתר סָאנְשִׂינְגְדְווֵי מצביעים על חברה מתקדמת, השונה בתרבותה מזו שנתגלתה בְּאָנְיָאנְג. אין עדויות מכריעות במוגע לתחום שליטתה של שושלת שאנג. ההנחה המקובלת היא כי שושלת שאנג שבהיסטוריה הרשמית אכן שלטה בעיר אניאנג, תוך שהיא מקיימת קשרי מסחר עם יישובים שונים בסביבתה, שהיו שונים זה מזה מבחינה תרבותית.\n" +
+"\n" +
+"[עריכה] שושלת ג'וֹאוּ\n" +
+"\n" +
+"    ערך מורחב – שושלת ג'ואו\n" +
+"\n" +
+"שושלת ג'וֹאוּ (סינית: 周, פיניין: Zhōu), הייתה השושלת ששלטה את הזמן הארוך ביותר בסין, מ-1122 לפנה\"ס ועד 256 לפנה\"ס - 866 שנה. השושלת התחילה להתגלות בנהר הצהוב והתפשטה אל תוך גבולותיה של השאנג. השושלת התחילה את שליטתה כפיאודליזם. הג'ואו חיו מערבית לשאנג, ושליטם היה מכונה בפיהם של שאנג כ\"מגן המערבי\". שליט ג'ואו המלך ווּ, בעזרת דודו הדוכס של ג'ואו, הצליחו להכניע את אחרון קיסרי שאנג בקרב שקבל את השם הקרב של מויה. היה זה מלכה של ג'ואו באותו הזמן, שטבע את מושג מנדט השמים, רעיון לפיו השמים הם המחליטים מי יהיה הקעסר הבא, ודרכם להביע את זה היא הצלחתו של הקיסר בניהול מלכותו, כך שמרד נתפס כלגיטימי, כל עוד זכה להצלחה. הקיסר העביר את בירתו אל עבר מערב האזור, סמוך למקום המכונה כיום שיאן, לגדות הנהר הצהוב, אולם שליטתם התפרסה אל כל עבר מושבות נהר היאנגטסה. זו הייתה ההגירה הראשונה בגודל כזה מצפון סין לדרומה.\n" +
+"\n" +
+"[עריכה] תקופת האביב והסתיו\n" +
+"\n" +
+"    ערך מורחב – תקופת האביב והסתיו\n" +
+"\n" +
+"תקופת האביב והסתיו (בסינית: 春秋時代) הוא כינויה של תקופה בין השנים 722 לפנה\"ס ל 481 לפנה\"ס. שמה של התקופה לקוח משם הספר רשומות האביב והסתיו, תיעוד היסטורי של אותה תקופה אשר נכתב בידי קונפוציוס.\n" +
+"\n" +
+"במהלך התקופה נערכו מלחמות רבות בין המדינות שהרכיבו באותה תקופה את סין מה שהביא לביזור של הכח השלטוני בסין העתיקה. בעקבות המלחמות הודחו שליטים רבים מכסאם, ושכבת האצולה בסין התפוררה למעשה. עם התפשטותם של האצילים ברחבי הארץ נפוצה איתם גם ידיעת הקרוא וכתוב אשר הייתה נחלתם הכמעט בלעדית של האצילים עד לאותה תקופה. התפשטות הקריאה והכתיבה עודדה את חופש המחשבה וההתפתחות הטכנולוגית. לאחר תקופת האביב והסתיו החלה בסין תקופת מלחמת המדינות.\n" +
+"\n" +
+"[עריכה] תקופת המדינות הלוחמות\n" +
+"\n" +
+"    ערך מורחב – תקופת המדינות הלוחמות\n" +
+"\n" +
+"תקופת המדינות הלוחמות (סינית: 戰國, פיניין: Zhàn Guó) החלה במאה החמישית לפנה\"ס והסתיימה בשנת 221 לפנה\"ס באיחודה של סין על ידי שושלת צ'ין. רשמית, בתקופת המדינות הלוחמות, כמו גם בתקופה שקדמה לה, תקופת האביב והסתיו, הייתה סין תחת שלטונה של שושלת ג'וֹאוּ המזרחית, אך שליטה זו הייתה רק להלכה, ולשושלת לא הייתה השפעה ממשית, ולמעשה חדלה להתקיים 35 שנה לפני סיומה הרשמי של התקופה. את שמה קיבלה התקופה מ\"רשומות המדינות הלוחמות\", תיעוד היסטורי של התקופה, שנכתב בתקופת שושלת האן.\n" +
+"\n" +
+"תקופת המדינות הלוחמות, שלא כמו תקופת האביב והסתיו, הייתה תקופה בה שרי צבא ואריסטוקרטים מקומיים סיפחו לאחוזותיהם כפרים, ערים ומדינות זעירות סמוכות והשליטו עליהם את שלטונם. במאה השלישית לפנה\"ס הביא מצב זה ליצירת שבע מדינות עיקריות בסין: מדינות צִ'י (齊), צ'וּ (楚), יֵן (燕), הַאן (韓), גָ'או (趙), ווֶי (魏) וצִ'ין (秦). סימן נוסף לשינוי במעמדם של הגנרלים היה שינוי תארם הרשמי מגונג (公 - המקבילה הסינית לדוכס), הכפופים כביכול למלך של ג'ואו, לוואנג (王) - מלכים, השווים במעמדם למלך של ג'ואו.\n" +
+"\n" +
+"תקופת המדינות הלוחמות היא גם תחילתו של השימוש בברזל במקום ארד בסין כמתכת עיקרית בכל תחומי החיים האזרחיים והצבאיים. במהלך תקופה זו החלו להבנות החומות, שיגנו על הממלכות מפני פלישה של שבטים ברבריים מהצפון חומות, שהיוו את היסוד לחומה הסינית המאוחרת יותר. מאפיין תרבותי נוסף של התקופה היה הפיכתן של פילוסופיות שונות כגון קונפוציזם, דאואיזם, לגאליזם, ומוהיזם למעמד של דתות במדינות השונות.\n" +
+"\n" +
+"בתום התקופה, לאחר שממלכת צ'ין הצליחה להביס ולכבוש את שאר הממלכות, הפך המלך צ'ין לקיסר הראשון של סין המאוחדת.\n" +
+"\n" +
+"[עריכה] שושלת צ'ין: האימפריה הסינית הראשונה\n" +
+"\n" +
+"    ערך מורחב – שושלת צ'ין\n" +
+"\n" +
+"סין אוחדה לראשונה בשנת 212 לפנה\"ס בידי צִ'ין שְׁה-חְוָאנג, מייסד שושלת צ'ין. קדמה לאיחוד תקופת מלחמת המדינות ותקופת האביב והסתיו, שהתאפיינו שתיהן במספר ממלכות שהתקיימו במקביל ולחמו זו בזו. בשנת 212 לפנה\"ס עלה בידו של צ'ין להשתלט סופית על כל הממלכות בסין העתיקה ולשים קץ למלחמות הפנימיות.\n" +
+"\n" +
+"למרות שהאימפריה המאוחדת של הקיסר צ'ין התקיימה רק 12 שנים, הצליח הקיסר בזמן מועט זה למסד את רוב שטחה של המדינה כפי שאנו מכירים אותה כיום ולהשליט בה משטר ריכוזי המבוסס על לגאליזם אשר מושבו היה בשיאניאנג, שיאן של ימינו. שושלת צ'ין מפורסמת גם בשל תחילת בנייתה של החומה הסינית הגדולה (החומה הוגדלה בתקופת שושלת מינג). בניו של הקיסר לא היו מוצלחים כמוהו, ועם מותו של הקיסר תמה תקופת שלטונה של שושלתו.\n" +
+"\n" +
+"מקור המילה סין בשפה העברית וכן בשפה האנגלית (China), מגיע ככל הנראה מהמילה צ'ין (秦), שמה של השושלת הראשונה.\n" +
+"\n" +
+"[עריכה] שושלת האן: תקופה של שגשוג\n" +
+"\n" +
+"    ערך מורחב – שושלת האן\n" +
+"\n" +
+"שושלת האן הופיעה בסין בשנת 202 לפנה\"ס. בתקופת שלטונה הפכה הקונפוציוניזם לדת המדינה ולפילוסופיה המנחה אותה ואשר המשיכה להנחות את המשטר הסיני עד לסוף התקופה הקיסרית בתחילת המאה ה-20. תחת שלטון ההאן עשתה התרבות הסינית התקדמות אדירה בתחומי ההיסטוריוגפיה, האומנות והמדע. הקיסר וו חיזק והרחיב את הממלכה בהודפו את ה\"שׂיוֹנג-נוּ\" (שבטים שלעתים מזוהים עם ההונים) אל תוך מונגוליה של ימינו, תוך שהוא מספח לממלכתו את השטחים בהם ישבו שבטים אלו. שטחים חדשים אלו אפשרו לסין לראשונה לפתוח קשר מסחר עם המערב: דרך המשי.\n" +
+"\n" +
+"אולם, השתלטותן של משפחות אצולה על אדמות המדינה, עירערה את בסיס המיסוי של הממלכה, גורמות בכך חוסר יציבות שלטוני. חוסר היציבות הזה נוצל על ידי וואנג מנג, שהקים את שושלת שין שהחזיקה מעמד זמן קצר מאוד. וואנג החל לבצע רפורמות ענפות בהחזקת האדמות ובכלכלה. תומכיה העיקריים של הרפורמה היו האיכרים ובני המעמדות הנמוכים, אך משפחות האצולה שהחזיקו באדמות, התנגדות להן בכל תוקף. עקב כך נוצא מצב של כאוס והתקוממויות רבות במדינה. צאצאה של שושלת האן, הקיסר גואנגוו, ייסד מחדש את שושלת האן בתמיכתם של משפחות האצילים והסוחרים בלוו-יאנג, מזרחית לשיאן, מכאן קיבל העידן החדש שהחל אז את שמו: שושלת האן המזרחית. אולם ייסודה מחדש של השושלת לא הביא את השקט הרצוי לממלכה. עימותים עם בעלי הקרקעות, יחד עם פלישות מבחוץ ומאבקים פנימיים במיעוטים החלישו שוב את השלטון. מרד הטורבן הצהוב שפרץ בשנת 184, סימן את תחילתו של עידן בו שליטים צבאיים מובילים מלחמות בתוך המדינה ומחלקים את המדינה למספר מדינות קטנות. תקופה זו ידועה כתקופת שלוש הממלכות.\n" +
+"\n" +
+"[עריכה] ג'ין, שש עשרה הממלכות והשושלות הדרומית והצפונית: התקופה האפלה של סין\n" +
+"\n" +
+"    ערך מורחב – שושלת ג'ין\n" +
+"\n" +
+"שלוש הממלכות התאחדו בשנת 280 תחת שלטונה של שושלת ג'ין. אולם איחוד זה נמשך זמן קצר מאוד. בתחילת המאה ה-4 החלו המיעוטים בסין (כיום מכונים סינים לא בני האן ) להתמרד ולבתר את המדינה, גורמים בכך להגירה עצומה של סינים בני האן אל מדרום לנהר היאנגטסה. בשנת 303 החלו אנשי מיעוט הדאי במרד שבסופו הם כבשו את צ'נגדו שבסצ'ואן. השׂיוֹנְג-נוּ, שנהדפו מסין בתחילת שלטונה של שושלת האן, חזרו להלחם בסין, כבשו חלקים ממנה והוציאו להורג את שני קיסריה האחרונים של שושלת ג'ין. יותר משש-עשרה מדינות הוקמו על ידי המיעוטים האתניים בצפונה של סין. הצפון הכאוטי אוחד לזמן קצר על ידי פו ג'יאן, אך הוא הובס בנסיון פלישתו לדרום סין וממלכתו התפוררה. נסיון נוסף לאיחוד הצפון בוצע על ידי הקיסר טאיוון, שהקים את השושלות הצפוניות, סדרה של משטרים מקומיים ששלטו בסין שמצפון לנהר היאנג צה.\n" +
+"\n" +
+"עם הפליטים שנסו לדרומה של המדינה, היה גם הקיסר יואן, נצר לשושלת ג'ין, שחידש את שלטון השושלת בדרום המדינה . שושלת זו הייתה הראשונה מבין השושלות הדרומיות שכללו את שושלות סונג, צי, ליאנג וצ'ן. בירתן של השושלות הדרומיות הייתה ג'יאנקאנג, ליד ננג'ינג של ימינו. התקופה בה התקיימו במקביל שתי מדינות הנשלטות על ידי שושלות שונות בצפונה ובדרומה של הארץ נקראה תקופת השושלות הצפונית והדרומית. שושלת סוי קצרת המועד, הצליחה לאחד את המדינה ב589 לאחר כמעט 300 שנות פירוד.\n" +
+"\n" +
+"[עריכה] שושלת טאנג: חזרה לשיגשוג\n" +
+"\n" +
+"    ערך מורחב – שושלת טאנג\n" +
+"\n" +
+"בשנת 618 נוסדה שושלת טאנג, פותחת עידן חדש של שיגשוג וחידושים בתחומי האמנות והטכנולוגיה. בתקופה זו פעלו משוררים נודעים כלי באי ודו פו. הבודהיזם, שהחל חודר לסין כבר במאה ה-1, הוכרז כדת הרשמית של המדינה ואומץ על ידי המשפחה הקיסרית. צ'אנג-אן (שיאן של ימינו), בירת השושלת הייתה באותה תקופה העיר הגדולה ביותר בעולם. תקופות טאנג והאן נחשבות לרוב כתקופות השגשוג הממושכות ביותר בהיסטוריה של סין. אולם, על אף השגשוג, כוחה של שושלת טאנג החל להחלש והמדינה החלה נקרעת בשנית בידי שליטים מקומיים. תקופה נוספת של כאוס הגיעה למדינה: תקופת חמש השושלות ועשר הממלכות.\n" +
+"\n" +
+"[עריכה] שושלת סונג ושכנותיה הצפוניות, ליאו וג'ין\n" +
+"\n" +
+"    ערך מורחב – שושלת סונג\n" +
+"\n" +
+"בשנת 960 הצליחה שושלת סונג לאסוף מספיק כח כדי לאחד את סין תחת שלטונה. תחת שלטון סונג, שבירתו הייתה קאיפנג, החלה תקופת צמיחה חדשה בסין. אולם שושלת סונג לא הייתה הכח הפוליטי הגדול היחיד באזור. במנצ'וריה ובמזרח מונגוליה התהוותה ממלכתה של שושלת ליאו החיטאנית וב1115 עלתה לשלטון במנצ'וריה שושלת ג'ין הג'ורצ'נית (הג'ורצ'נים היו אבותיהם של המנצ'ורים) שתוך 10 שנים בלעה את שושלת ליאו לתוכה. שושלת ג'ין השתלטה גם על שטחים בצפון סין, בתוכם הבירה הסינית קאיפנג, מה שאילץ את שושלת סונג הסינית להעביר את בירתה לחאנגג'ואו. שושלת סונג גם אולצה על ידי שושלת ג'ין להכריז על הכרתה בשושלת ג'ין כשליטה העליונה שלה. בתקופה שלאחר מכן הוקמו שלוש ממלכות גדולות בשטחה של סין (ממלכת סונג, ממלכת ג'ין וממלכה שלישית של מיעוטים שנקראה ממלכת שיה המערבית). בתקופה זו נעשו פיתוחים משמעותיים בטכנולוגיה, ככל הנראה עקב הלחץ הצבאי שהופעל על ממלכת סונג מצד שכנותיה הצפוניות.\n" +
+"\n" +
+"[עריכה] המונגולים\n" +
+"\n" +
+"ממלכת ג'ין הייתה הראשונה מבין הממלכות בסין שהובסה על ידי המונגולים, שהמשיכו וכבשו גם את ממלכת סונג במלחמה ארוכה ועקובה מדם שהייתה המלחמה הראשונה בהיסטוריה בה נעשה שימוש מכריע בנשק חם. לאחר תום המלחמה החל עידן של שלום כמעט בכל אסיה (שהייתה נתונה לשלטון המונגולים), עידן שנקרא \"השלום המונגולי\" (Pax Mongolica). שלום זה איפשר לנוסעים מהמערב, דוגמת מרקו פולו, להגיע לסין ולחשוף לראשונה את אוצרתיה למערב. בסין, נחלקו המונגולים בין אלו שרצו להחיל בסין את מנהגי המונגולים ובין אלו שרצו לאמץ את המנהגים הסינים לעצמם. קובלאי חאן, שנמנה עם הקבוצה השנייה, הקים בסין את שושלת יואן (מילולית: \"השושלת הראשונה\") זו הייתה הממלכה הראשונה שהשתרעה על כל שטחה של סין ושבירתה הייתה בייג'ינג (בייג'ינג הייתה בירתה של שושלת גי'ן אך השושלת לא שלטה על סין כולה).\n" +
+"\n" +
+"[עריכה] תחייתה מחדש של התרבות הסינית\n" +
+"\n" +
+"בקרב העם בסין, הייתה התמרמרות רבה ביחס לשלטון ה\"זרים\" החדש, התמרמרות שלבסוף הובילה להתקוממויות איכרים במדינה שהתפתחו למאבק בשלטון שנדחף למעשה אל מחוץ לגבולותיה של סין. את השלטון המונגולי החליף שלטונה של שושלת מינג בשנת 1368. שושלת זו פתחה תקופה של פריחה והתחדשות תרבותית: האומנות, ובעיקר תעשיית הפורצלן, נסקה לגבהים שלא נודעו קודם לכן, סחורות סיניות נעו ברחבי האוקיינוס ההודי, מגיעות עד לחופיה המזרחיים של אפריקה במסעותיו של צ'נג חה. סין בנתה צי ספינות שהגדולות מבניהן שינעו 1,500 טונות של סחורות וחיילים מהצבא בן מיליון החיילים שהיה ברשותה באותה העת. יותר מ100,000 טונות ברזל יוצרו כל שנה וספרים רבים נדפסו. יש הטוענים כי שהאומה הסינית בתקופת מינג הייתה האומה המתקדמת ביותר בעולם.\n" +
+"\n" +
+"הקיסר חונג-וו, מייסד השושלת, הניח את היסודות לנטייתה של המדינה למעט במסחר ותעשייה ולהתמקד בעיקר בהגדלת הרווחים מהמגזר החקלאי, כנראה בשל מוצאו החקלאי של הקיסר. חברות פאודליות זעירות שהתפתחו במהלך שנות שלטונם של שושלת סונג ושל המונגולים פורקו ואדמותיהם הולאמו, חולקו והושכרו לאיכרים מחדש. כמו כן, הוטל חוק האוסר החזקת עבדים במדינה. החוקים נגד מסחר נשארו בממלכה עוד מתקופת שושלת סונג, אך כעת הם חלו גם על סוחרים זרים מה שהביא במהרה לגוויעת סחר החוץ בין סין לשאר העולם.\n" +
+"\n" +
+"ככל שחלף הזמן, שלטון הקיסר נעשה חזק יותר ויותר על אף שהחצר הקיסרית עשתה שימוש נרחב בפקידים ממשלתיים שהיו אחראיים לתפקודה השוטף של המדינה.\n" +
+"\n" +
+"במהלך שלטון המונגולים פחתה האוכלוסייה בכ-40% לכ-60 מיליון נפש. שתי מאות מאוחר יותר המספר הוכפל. הערים החלו להתפתח בקצב מואץ ובעקבות כך החלה להופיע גם תעשייה זעירה. כתוצאה מהתערבות שלטונית, נמנעה בסין התפתחותו של מרכז אורבני מצומצם ובמקום זאת צמחו מספר רב של ערים שהיוו מרכזים מקומיים לאזורים המקיפים אותן.\n" +
+"\n" +
+"[עריכה] תקופת מינג: מהתפתחות לבידוד\n" +
+"\n" +
+"    ערך מורחב – שושלת מינג\n" +
+"\n" +
+"למרות הסלידה ממסחר עם מדינות אחרות, וההתרכזות הפנימית בענייני המדינה, סין תחת שלטונה של שושלת מינג לא הייתה מבודדת. הסחר עם מדינות אחרות, ובעיקר עם יפן, המשיך להתקיים והקיסר יונגלה השתדל ככל יכולתו למסד קשרים דיפלומטיים עם המדינות הסובבות את סין. צבאה של סין כבש את אנאם והצי הימי שלה הפליג במסעותיו עד לחופי אפריקה. הסינים גם הצליחו לייצר השפעה מסוימת בטורקסטן.\n" +
+"\n" +
+"אחת הדרכים המרשימות ביותר בהן התבטאה מדיניות החוץ הסינית של אותה תקופה הייתה מסעותיו הימיים של צ'אנג חֶה, סריס מוסלמי ונצר למשפחה מונגולית, אשר הוביל שבעה מסעות ימיים מפוארים בין 1405 ל1433 שעברו בכל האוקיינוס ההודי והאיים שבו והגיעו עד לכף התקווה הטובה. מסעו הראשון של הה, כלל 62 ספינות שנשאו 28,000 מלחים – ללא ספק המסע הימי הגדול ביותר בהיסטוריה האנושית.\n" +
+"\n" +
+"אולם, לקראת סופה של המאה ה-15, הוטל איסור על אזרחי המדינה לבנות ספינות בעלות כושר הפלגה באוקיינוס וכן נאסר על כלל האזרחים לעזוב את המדינה. כיום קיימת הסכמה על כך שצעד זה ננקט כדי להגן על הקיסרות מפני התקפות של שודדי ים. הגבלות אלו בוטלו לבסוף באמצע המאה ה-17.\n" +
+"\n" +
+"[עריכה] שושלת צ'ינג\n" +
+"\n" +
+"    ערך מורחב – שושלת צ'ינג\n" +
+"\n" +
+"השושלת הקיסרית האחרונה בסין, נוסדה ב1644 כאשר המנצ'ורים כבשו את המדינה, הדיחו מהשלטון את שושלת מינג המקומית והקימו את שושלת צ'ינג שבירתה בייג'ינג. במשך חצי מאה נלחמו המנצ'ורים מלחמות עקובות מדם שבמהלכן השתלטו על האזורים שהיו בשליטת שושלת מינג ובכללם מחוז יונאן המרוחקת, טיבט ומונגוליה. את ההצלחה לה זכו המנצ'ורים בתחילת תקופת שלטונם יש לזקוף לזכות כוחם הצבאי האדיר והמיומן ששולב עם מיומנויות בירוקרטיות סיניות.\n" +
+"\n" +
+"חלק מההיסטוריונים רואים בתקופה של תחילת שלטון צ'ינג המשך רציף להתדרדרות התרבותית שחלה בסוף תקופת מינג. אך יש כאלה הרואים בתחילת שלטון צ'ינג תקופה של שיגשוג יותר מאשר נסיגה. בהוראת הקיסר קנגשי נכתב המילון המקיף והמפורט ביותר לשפה הסינית שנכתב עד אז ותחת שלטונו של הקיסר קיאנלונג חובר הקטלוג המלא של כל העבודות החשובות של התרבות הסינית. שושלת צ'ינג גם המשיכה בהרחבת אוצר הספרות העממית ובפיתוח החקלאות תוך יבוא גידולים חדשים מהעולם החדש דוגמת התירס. גם צמיחת האוכלוסייה המשיכה להאיץ בתקופת צ'ינג ואוכלוסיית המדינה, שבשנת 1700 מנתה 100 מיליון נפש, הגיעה לכדי 220 מליון בשנת 1800.\n" +
+"\n" +
+"\n" +
+"בקריקטורה צרפתית מפורסמת זו, נראית חלוקתה של סין בין בריטניה, גרמניה, רוסיה, צרפת ויפן\n" +
+"בקריקטורה צרפתית מפורסמת זו, נראית חלוקתה של סין בין בריטניה, גרמניה, רוסיה, צרפת ויפן\n" +
+"\n" +
+"במהלך המאה ה-19, נחלשה שליטתה של שושלת צ'ינג במדינה והשגשוג שהיה בה התפוגג. סין סבלה מרעב קשה, התפוצצות אוכלוסין וחדירה בלתי פוסקת של מדינות המערב בנסיון להשיג לעצמן השפעה במדינה. שאיפתה של בריטניה להמשיך בסחר הבלתי חוקי באופיום, נתקל בהתנגדות עזה של המשטר הקיסרי, מה שהביא לפריצתה של מלחמת האופיום הראשונה ב1840. סין, שהפסידה במלחמה, אולצה לבצע ויתורים כואבים ולפתוח את נמליה לסחר חפשי עם מדינות המערב. ויתוריה הטריטוריאלים של סין כללו את העברת הונג קונג לידיה של בריטניה ב1842 כחלק מחוזה נאנג'ינג. בנוסף מרד טאי פינג (1864-1851) ומרד ניאן (1868-1853), יחד עם תנועות לאומיות מוסלמיות ששאפו לעצמאות וחוזקו על ידי רוסיה ייבשו את קופת המדינה וכמעט שהביאו לנפילת השלטון בה.\n" +
+"\n" +
+"המרידות בשלטון דוכאו בעיקר על ידי כוחות המערב שבאותו הזמן עשו במדינה כבשלהם וניצלו את שווקיה ואת מערכתה הכלכלית.\n" +
+"\n" +
+"לאחר שוך המהומות בשנות השישים של המאה ה-19, החלה שושלת צ'ינג לטפל בבעיות המודרניזציה במדינה על ידי ביצוע רפורמות בכל תחומי שליטתה. אבל, הקיסרית האלמנה צישי, יחד עם גורמים שמרניים במדינה, ביצעה מעין הפיכה והדיחה את הקיסר הצעיר מהשלטון, מורידה בכך לטמיון את הרפורמות שאך החלו להתבצע. הרפורמות הצבאיות, שהושארו על כנן, היו חסרות ערך עקב השחיתות האיומה שהתפשטה בצמרת השלטון. חלק מספינות הקרב החדישות של הצבא כלל לא יכלו לבצע ירי, וזאת עקב מעילות גדולות בתקציבי בנייתן שלא השאירו די כסף לרכישת אבק שריפה. כתוצאה מכך כוחות \"הצבא הסיני החדש\" נחלו תבוסות משפילות הן במלחמת סין-צרפת (1885-1883) והן במלחמת סין-יפן הראשונה (1895-1894)\n" +
+"\n" +
+"עם תחילתה של המאה ה-20, הייתה החצר הקיסרית בסין הרוסה, שחיתות הייתה בכל והאוכלוסייה גדלה בקצב בלתי ניתן לעצירה. המדינה נשלטה על ידי הקיסרית צישי, דמות שמרנית ביותר שהתנגדה לכל סוג של רפורמה. מותו של הקיסר גוואנגשו יום אחד לפני מותה של הקיסרית (יש הטוענים שהוא הורעל על ידה) הרס את הסיכוי האחרון לביסוס הנהגה אפקטיבית במדינה.\n" +
+"\n" +
+"[עריכה] הרפובליקה הסינית\n" +
+"\n" +
+"    ערך מורחב – היסטוריה של הרפובליקה הסינית\n" +
+"\n" +
+"ביאושם מאוזלת ידו של השלטון, החלו פקידי ממשל צעירים, קציני צבא וסטודנטים, שהושפעו מרעיונותיו המהפכניים של סון יאט-סן להתארגן לקראת הפיכה במדינה שתסלק את שושלת צ'ינג מהשלטון ותהפוך את המדינה לרפובליקה. התקוממות ווצ'אנג, התקוממות מהפכנית צבאית, החלה ב10 באוקטובר 1911. כחצי שנה מאוחר יותר, ב12 בפברואר 1912 הוקמה הממשלה הזמנית של הרפובליקה הסינית בנאנג'ינג כשבראשה עומד סון יאט-סן כנשיאה הזמני. אך סון נאלץ לוותר על תפקידו לטובת יואן שיקאי אשר פיקד באותו הזמן על \"הצבא החדש\" והיה ראש הממשלה תחת שלטון צ'ינג, כחלק מהסכם שנחתם להדחת הקיסר האחרון – הילד הנרי פו-יי. בשנים שלאחר הכתרתו כנשיא, ניסה יואן שיקאי לעקוף את סמכויותיהן של הוועדות הפרובינציאליות של הרפובליקה ואף הכריז על עצמו קיסר ב1915. שאיפותיו הקיסריות של יואן נתקלו בהתנגדות עזה של המהפכנים שראו כיצד מהפכתם הולכת לכינונה מחדש של קיסרות במדינה ולא של רפובליקה, והם החלו מתמרדים נגד יואן עד למותו ב1916 שהשאיר ריק שלטוני בסין. סין שלאחר מותו של יואן נחלקה בין הממשל הרפובליקני החדש, ובין מצביאים מקומיים ששלטו באזוריהם עוד מתקופת צ'ינג.\n" +
+"\n" +
+"לאירוע חסר החשיבות (בעיני המעצמות מחוץ לסין) שהתרחש ב1919 הייתה השלכה מכריעה על המשך ההיסטוריה הסינית במאה ה-20, אירוע זה הוא תנועת הארבעה במאי. התנועה, שהוציאה שם רע לפילוסופיות המערביות המקובלות והאימוץ של קוי מחשבה קיצוניים יותר שבאו לאחר מכן זרעו את הזרעים לקונפליקט בלתי ניתן לגישור בין הימין והשמאל בסין, קונפליקט שהמשיך עד לסופה של המאה.\n" +
+"\n" +
+"ב1920, הקים סון יאט-סן בסיס לתנועתו המהפכנית בדרום סין, אשר ממנו הוא יצא לאיחוד האומה השסועה. בעזרתם של הסובייטים, הוא הקים ברית עם המפלגה הקומוניסטית הסינית, ברית שלחמה בשאריות המשטר הקיסרי שהיו מפוזרות בצפון המדינה. לאחר מותו של סון ב1925 השתלט יורשו צ'יאנג קאי שק על המפלגה הלאומנית (הקוומינטנג) והצליח לאחד תחת שלטונו את מרבית דרום המדינה ומרכזה במערכה צבאית שנקראה המשלחת הצפונית. לאחר שהצליח להביס גם את תומכי הקיסר בצפון, פנה צ'יאנג למלחמה באנשי המפלגה הקומוניסטית, שעד לאותה תקופה נלחמו יחד איתו. הקומוניסטים פרשו מהקוומינטנג ב1927 וברחו להרים שבדרום סין. ב1934 יצאו הקומוניסטים מההרים שבשליטתם (שם הקימו את הרפובליקה הסינית-סובייטית) למצעד הארוך, מסע צבאי מפרך באזורים הטרשיים ביותר במדינה אל עבר צפון מערבה של המדינה לפרובינציית שאאנסי שם הקימו לעצמם בסיסי לוחמת גרילה.\n" +
+"\n" +
+"במהלך המצעד הארוך, הכירו הקומוניסטים במנהיגם החדש מאו צה דונג. המאבק בין הקוומינטנג והמפלגה הקומוניסטית הסינית נמשך לעתים בגלוי ולעתים בחשאי תוך כדי מלחמת סין-יפן השנייה (1945-1931) על אף שהכוחות יצרו לכאורה חזית מאוחדת כנגד פלישת היפנים ב1937 כחלק ממלחמת העולם השנייה. הלחימה בין שתי המפלגות המשיכה לאחר תבוסתם של היפנים ב-1945, וב-1949 שלטו הקומוניסטים ברוב שטחה של המדינה.\n" +
+"\n" +
+"[עריכה] הרפובליקה העממית של סין\n" +
+"\n" +
+"    ערך מורחב – היסטוריה של הרפובליקה העממית של סין\n" +
+"\n" +
+"פרק זה לוקה בחסר. אתם מוזמנים לתרום לוויקיפדיה ולהשלים אותו. ראו פירוט בדף השיחה.\n" +
+"\n" +
+"צ'יאנג קאי שק נמלט עם שאריות ממשלתו וצבאו לטיוואן שם הוא הכריז על טייפה כבירה הזמנית של הרפובליקה עד להשלמת הכיבוש מחדש של סין היבשתית על ידי כוחותיו. הרפובליקה הסינית ממשיכה להתקיים עד ימינו (סוף 2004) בטיוואן אך היא טרם הכריזה עצמאות והיא אינה מוכרת רשמית כמדינה על ידי שאר העולם.\n" +
+"\n" +
+"עם ההכרזה על הקמתה של הרפובליקה העממית של סין ב1 באוקטובר 1949, חולקה סין שוב לרפובליקה העממית של סין בסין היבשתית ולרפובליקה הסינית שישבה בטיוואן ובמספר איים קטנים בסביבה, כאשר לכל רפובליקה יש ממשלה הרואה בעצמה את הממשלה הסינית האמיתית והמתייחסת אל הממשלה האחרת בבוז ובביטול. מצב זה נמשך עד לשנות התשעים של המאה ה-20, כאשר שינויים פוליטים ברפובליקה הסינית הביאו אותה להפסקת הטענה הפומבית להיותה ממשלת סין היחידה.\n" +
+"\n" +
+"[עריכה] ראו גם\n" +
+"\n" +
+"    * לוח זמנים של ההיסטוריה של סין – טבלה המתארת את האירועים והאישים החשובים בתולדותיה של סין.\n" +
+"\n" +
+"[עריכה] לקריאה נוספת\n" +
+"\n" +
+"    * עמנואל צ' י' שו, צמיחתה של סין המודרנית, הוצאת שוקן, 2005.\n" +
+"\n" +
+"[עריכה] קישורים חיצוניים\n" +
+"\n" +
+"    * ירדן ניר-בוכבינדר, סין אימנו, קונפוציוס אבינו, באתר \"האייל הקורא\"\n" +
+"\n" +
+"\n" +
+"[עריכה] הערות שוליים\n" +
+"\n" +
+"   1. ^ סין של תקופת הברונזה בגלריה הלאומית לאמנות של ארצות-הברית\n" +
+"   2. ^ כתב על חרסים מאתר ארליטואו (כתוב בסינית מפושטת)\n";
+
+
+var japanese =
+"中国の歴史\n" +
+"出典: フリー百科事典『ウィキペディア（Wikipedia）』\n" +
+"移動: ナビゲーション, 検索\n" +
+"中国歴史\n" +
+"中国の歴史\n" +
+"元謀・藍田・北京原人\n" +
+"神話伝説（三皇五帝）\n" +
+"黄河・長江文明\n" +
+"夏\n" +
+"殷\n" +
+"周 	西周\n" +
+"東周 	春秋\n" +
+"戦国\n" +
+"秦\n" +
+"漢 	前漢\n" +
+"新\n" +
+"後漢\n" +
+"三国 	魏 	呉 	蜀\n" +
+"晋 	西晋\n" +
+"東晋 	十六国\n" +
+"南北朝 	宋 	北魏\n" +
+"斉\n" +
+"梁 	西魏 	東魏\n" +
+"陳 	北周 	北斉\n" +
+"隋\n" +
+"唐\n" +
+"五代十国\n" +
+"宋 	北宋 	遼 	西夏\n" +
+"南宋 	金\n" +
+"元\n" +
+"明 	北元\n" +
+"後金 	南明 	大順\n" +
+"清\n" +
+"中華民国\n" +
+"中華人民共和国 	(参考:\n" +
+"台湾問題)\n" +
+"\n" +
+"中国の歴史（ちゅうごくのれきし）、或いは中国史（ちゅうごくし）\n" +
+"\n" +
+"中国の黄河文明は古代の四大文明の一つに数えられ、また黄河文明よりも更に遡る長江文明が存在した。\n" +
+"目次\n" +
+"[非表示]\n" +
+"\n" +
+"    * 1 王朝、政権の変遷\n" +
+"    * 2 概略\n" +
+"          o 2.1 先史人類史\n" +
+"          o 2.2 文明の萌芽\n" +
+"                + 2.2.1 黄河文明\n" +
+"                + 2.2.2 長江文明\n" +
+"                + 2.2.3 その他\n" +
+"          o 2.3 先秦時代\n" +
+"                + 2.3.1 三代\n" +
+"                + 2.3.2 春秋戦国\n" +
+"          o 2.4 秦漢帝国\n" +
+"          o 2.5 魏晋南北朝時代\n" +
+"          o 2.6 隋唐帝国\n" +
+"          o 2.7 五代十国・宋\n" +
+"          o 2.8 モンゴル帝国\n" +
+"          o 2.9 明清帝国\n" +
+"          o 2.10 中国の半植民地化\n" +
+"          o 2.11 中華民国\n" +
+"                + 2.11.1 革命後の中国の政局\n" +
+"                + 2.11.2 袁世凱の台頭と帝制運動（1913年～1916年）\n" +
+"                + 2.11.3 袁世凱死後の政局（1916年～1920年）\n" +
+"                + 2.11.4 国民革命（1920年～1928年）\n" +
+"                + 2.11.5 国民政府（1928年～1931年）\n" +
+"                + 2.11.6 抗日戦争（1931年～1937年）\n" +
+"                + 2.11.7 日中戦争（1937年～1945年）\n" +
+"                + 2.11.8 漢民族以外の民族の動向\n" +
+"                      # 2.11.8.1 モンゴルとチベットでの動き\n" +
+"                      # 2.11.8.2 東トルキスタン（新疆）での動き\n" +
+"          o 2.12 中華人民共和国\n" +
+"                + 2.12.1 社会主義国化と粛清（1949年～1957年）\n" +
+"                + 2.12.2 中国共産党の対ソ自立化（1958年～1965年）\n" +
+"                + 2.12.3 文化大革命前期（1966年～1969年）\n" +
+"                + 2.12.4 文化大革命後期（1969～1976年）\n" +
+"                + 2.12.5 改革開放以後の現在（1976年～）\n" +
+"                      # 2.12.5.1 一党独裁\n" +
+"                      # 2.12.5.2 少数民族問題\n" +
+"    * 3 人口の変遷\n" +
+"    * 4 地方行政制度\n" +
+"          o 4.1 封建制度（前1600年頃～前221年）\n" +
+"          o 4.2 郡県制度（前221年～249年）\n" +
+"          o 4.3 軍府による広域行政（249年～583年）\n" +
+"          o 4.4 州県制（583年～1276年）\n" +
+"    * 5 祭祀制度\n" +
+"    * 6 外交\n" +
+"          o 6.1 漢帝国\n" +
+"          o 6.2 魏晋南北朝時代\n" +
+"          o 6.3 隋唐帝国\n" +
+"    * 7 関連項目\n" +
+"    * 8 脚注\n" +
+"\n" +
+"[編集] 王朝、政権の変遷\n" +
+"現在の中国、すなわち中華人民共和国の領域\n" +
+"現在の中国、すなわち中華人民共和国の領域\n" +
+"\n" +
+"    * 長江文明\n" +
+"    * 黄河文明\n" +
+"    * 夏（紀元前2070年頃 - 紀元前1600年頃\n" +
+"    * 殷（紀元前1600年頃 - 紀元前12世紀・紀元前11世紀ごろ）\n" +
+"\n" +
+"    * 周（紀元前12世紀・紀元前11世紀ごろ - 紀元前256年）…殷を倒し、西周建国。克殷の年代については諸説あり、はっきりしない。\n" +
+"          o 春秋時代（紀元前770年 - 紀元前403年）…紀元前453年晋が韓魏趙に分割された時点、または紀元前403年韓魏趙が諸侯に列した時点をもって春秋時代の終わり、戦国時代の始まりとする。\n" +
+"          o 戦国時代（紀元前403年 - 紀元前221年）…晋が韓・趙・魏に分裂し、戦国時代突入。\n" +
+"    * 秦（紀元前221年 - 紀元前207年）…秦王・政が6国を滅ぼし中華統一。\n" +
+"    * 漢\n" +
+"          o 前漢（紀元前206年 - 8年）…秦滅亡後、楚の項羽との楚漢戦争に勝ち、劉邦が建国。\n" +
+"          o 新（8年 - 23年）…外戚の王莽が前漢皇帝から帝位を簒奪し建国。\n" +
+"          o 後漢（25年 - 220年）…前漢の景帝の子孫の劉秀（光武帝）が王莽軍を破り、漢を再興。\n" +
+"    * 三国時代（220年 - 280年）\n" +
+"          o 魏、蜀（蜀漢・漢）、呉…曹操の子曹丕が献帝から禅譲を受け即位すると、蜀の劉備も漢皇帝を名乗り即位、さらに呉の孫権も大帝として即位し、三国時代に入る。\n" +
+"    * 晋（265年 - 420年）\n" +
+"          o 西晋（265年 - 316年）…晋王司馬炎が魏の元帝より禅譲を受け即位し建国。だが、異民族五胡の侵入により衰退。異民族の漢に滅ぼされた。\n" +
+"          o 東晋（317年 - 420年）…皇族でただ一人生き残った琅邪王・司馬睿は江南に逃れ、建康で即位(元帝)。これを中原の晋と区別して東晋という。\n" +
+"          o 五胡十六国時代（304年 - 439年）\n" +
+"    * 南北朝時代（439年 - 589年）\n" +
+"          o 北魏、東魏、西魏、北斉、北周\n" +
+"          o 宋、斉、梁、陳\n" +
+"    * 隋（581年 - 619年）\n" +
+"    * 唐（618年 - 907年）\n" +
+"          o 武周\n" +
+"    * 五代十国時代\n" +
+"          o 後梁、後唐、後晋、後漢、後周……五代（中原を中心とする国）\n" +
+"          o 呉、南唐・閩・呉越・荊南・楚・南漢・前蜀・後蜀・北漢……十国（中華東西南北に拠る勢力）\n" +
+"    * 宋\n" +
+"          o 北宋（960年 - 1127年）\n" +
+"          o 南宋（1127年 - 1279年）\n" +
+"          o 遼、西夏、金\n" +
+"    * 元（1271年 - 1368年）\n" +
+"    * 明（1368年 - 1644年）\n" +
+"          o 南明\n" +
+"    * 清（1616年 - 1912年）（1616年 - 1636年は後金、それ以前はマンジュ国）\n" +
+"          o 太平天国、満州国\n" +
+"    * 中華民国（台湾）（1912年 - 現在）\n" +
+"    * 中華人民共和国（1949年 - 現在）\n" +
+"\n" +
+"[編集] 概略\n" +
+"\n" +
+"[編集] 先史人類史\n" +
+"\n" +
+"中国に現れた最初期の人類としては、元謀原人や藍田原人、そして北京原人が知られている。\n" +
+"\n" +
+"[編集] 文明の萌芽\n" +
+"\n" +
+"中国大陸では、古くから文明が発達した。中国文明と呼ばれるものは、大きく分けて黄河文明と長江文明の2つがある。黄河文明は、畑作が中心、長江文明は稲作が中心であった。黄河文明が、歴史時代の殷（商）や周などにつながっていき、中国大陸の歴史の中軸となった。長江文明は次第に、中央集権国家を創出した黄河文明に同化吸収されていった。\n" +
+"\n" +
+"[編集] 黄河文明\n" +
+"龍山文化時代の高杯。1976年山東省出土\n" +
+"龍山文化時代の高杯。1976年山東省出土\n" +
+"\n" +
+"黄河文明は、その後の中国の歴史の主軸となる。\n" +
+"\n" +
+"    * 裴李崗文化…紀元前7000?~紀元前5000?。一般的な「新石器時代」のはじまり。定住し、農業も行われていた。河南省(黄河中流)。土器は赤褐色\n" +
+"    * 老官台文化…紀元前6000?~紀元前5000?。土器作りや粟作りが行われていた。陝西省(黄河上流)。土器は赤色。\n" +
+"    * 北辛文化…紀元前6000?~紀元前5000?。土器は黄褐色。山東省(黄河下流)\n" +
+"    * 磁山文化…紀元前6000?~紀元前5000?。土器は赤褐色。河北省(黄河下流)\n" +
+"    * 仰韶文化…紀元前4800?~紀元前2500?。前期黄河文明における最大の文化。陝西省から河南省にかけて存在。このころは母系社会で、農村の階層化も始まった。文化後期になると、社会の階層化、分業化が進み、マルクス経済学でいうところの原始共産制は仰韶文化のころに終焉したと見られる。土器は赤色。\n" +
+"    * 後岡文化…紀元前5000?~紀元前4000?。北辛文化が発展。河南省。\n" +
+"    * 大汶口文化…紀元前4300?~紀元前2400?。土器は前期は赤色(彩陶)、後期は黒色(黒陶)。なお、この区分は黄河文明全体に見られる。山東省。\n" +
+"    * 龍山文化…紀元前2500?~紀元前2000?。大汶口文化から発展。後期黄河文明最大の文化。土器は黒色。山東省。\n" +
+"    * 二里頭文化…紀元前2000?~紀元前1600?。遺跡の中心部には二つの宮殿がある。河南省。\n" +
+"\n" +
+"[編集] 長江文明\n" +
+"母なる長江\n" +
+"母なる長江\n" +
+"\n" +
+"長江文明は黄河文明が萌芽する遥か前より栄えていた。夏王朝の始祖とされる禹が南方出身であるとされるため、この長江流域に夏王朝が存在したのではないかという説[1]がある。\n" +
+"\n" +
+"    * 玉蟾岩遺跡…湖南省(長江中流)。紀元前14000年？～紀元前12000年？の稲モミが見つかっているが、栽培したものかは確定できない。\n" +
+"    * 仙人洞・呂桶環遺跡…江西省(長江中流)。紀元前12000年ごろ？の栽培した稲が見つかっており、それまで他から伝播してきたと考えられていた中国の農耕が中国独自でかつ最も古いものの一つだと確かめられた。\n" +
+"    * 彭頭山文化…湖南省(長江中流)。紀元前7000年？～紀元前5000年？。散播農法が行われており、中国における最古の水稲とされる。\n" +
+"    * 大渓文化…四川省(長江上流)。紀元前4500年？～紀元前3300年？。彩文紅陶（紋様を付けた紅い土器）が特徴で、後期には黒陶・灰陶が登場。灌漑農法が確立され、住居地が水の補給のための水辺から大規模に農耕を行う事の出来る平野部へ移動した。\n" +
+"    * 屈家嶺文化…湖北省。紀元前3000年？～紀元前2500年？大渓文化を引き継いで、ろくろを使用した黒陶が特徴。河南地方の黄河文明にも影響を与えたと考えられる。\n" +
+"    * 石家河文化…屈家嶺文化から発展し、湖北省天門県石家河に大規模な都城を作った紀元前2500年頃を境として屈家嶺と区別する。この都城は南北1.3Km、東西1.1Kmという大きさで、上述の黄河流域の部族と抗争したのはこの頃と考えられる。\n" +
+"    * 河姆渡文化 …紀元前5000年？～紀元前4000年？下流域では最古の稲作。狩猟や漁労も合わせて行われ、ブタの家畜化なども行われた。\n" +
+"    * 良渚文化… 浙江省(銭塘江流域)。紀元前5260年？～紀元前4200年？（以前は文化形態から大汶口文化中期ごろにはじまったとされていたが、1977年出土木材の年輪分析で改められた）青銅器以前の文明。多数の玉器の他に、絹が出土している。分業や階層化も行われたと見られ、殉死者を伴う墓が発見されている。黄河文明の山東竜山文化とは相互に関係があったと見られ、同時期に衰退したことは何らかの共通の原因があると見られている。\n" +
+"    * 三星堆遺跡… 紀元前2600年？～紀元前850年？。大量の青銅器が出土し、前述の他に目が飛び出た仮面・縦目の仮面・黄金の杖などがあり、また子安貝や象牙なども集められており、権力の階層があったことがうかがい知れる。青銅器については原始的な部分が無いままに高度な青銅器を作っているため他の地域、おそらくは黄河流域からの技術の流入と考えられる。長江文明と同じく文字は発見されていないが、「巴蜀文字」と呼ばれる文字らしきものがあり、一部にこれをインダス文字と結びつける説もある。\n" +
+"\n" +
+"[編集] その他\n" +
+"\n" +
+"    * 新楽遺跡…遼寧省(遼河流域)。紀元前5200年?ごろの定住集落。母系社会が定着し、農業も行われていた。\n" +
+"\n" +
+"[編集] 先秦時代\n" +
+"\n" +
+"[編集] 三代\n" +
+"\n" +
+"史記では伝説と目される三皇五帝時代に続いて夏[2]王朝について記述されている。夏については実在が確かでなくまた定説もない。\n" +
+"\n" +
+"殷[3]（商）が実在の確認されている最古の王朝である。殷では、王が占いによって政治を行っていた（神権政治）。殷は以前は山東で興ったとされたが、近年は河北付近に興ったとする見方が有力で、黄河文明で生まれた村のうち強大になり発展した都市国家の盟主であった[4]と考えられる。\n" +
+"\n" +
+"紀元前11世紀頃に殷を滅ぼした周は、各地の有力者や王族を諸侯として封建制をおこなった。しかし、周王朝は徐々に弱体化し、異民族に攻められ、紀元前770年には成周へ遷都した。その後、史記周本紀によれば犬戎の侵入により西周が滅び、洛陽に東周が再興されたされるが、同じく平勢隆郎の検討によれば幽王が殺害されたあと短期間携王が西、平王が東に並立し、紀元前759年平王が携王を滅ぼしたと考えられる。平王のもとで周は洛陽にあり、西周の故地には秦が入る。これ以降を春秋時代と呼ぶ。春秋時代には、周王朝の権威はまだ残っていたが、紀元前403年から始まるとされる戦国時代には、周王朝の権威は無視されるようになる。\n" +
+"\n" +
+"[編集] 春秋戦国\n" +
+"諸子百家の一、孔子\n" +
+"諸子百家の一、孔子\n" +
+"\n" +
+"春秋戦国時代は、諸侯が争う戦乱の時代であった。\n" +
+"\n" +
+"春秋時代は都市国家の盟主どうしの戦いだった。しかし春秋末期最強の都市国家晋が三分割されたころから様子が変わる。その当時の晋の有力な家臣六家が相争い、最初力が抜きん出ていた智氏が弱小な趙氏を攻めたものの、趙氏がよく農村を経済的ではなく封建的に支配し、それによって集めた食糧が多かったために城を守りきり、疲弊した智氏を魏氏、韓氏が攻め滅ぼしたために最終的に趙、魏、韓の三国が出来た。このこともあってそれまで人口多くてもせいぜい5万人程度だった都市国家が富国強兵に努め、商工業が発達し、貨幣も使用し始めやがて領土国家に変貌しその国都となった旧都市国家は30万人規模の都市に変貌する。また鉄器が普及したこともあいまって、農業生産も増大した。晋の分裂以後を一般に戦国時代という。\n" +
+"\n" +
+"また、このような戦乱の世をどのように過ごすべきかという思想がさまざまな人たちによって作られた。このような思想を説いた人たちを諸子百家（陰陽家、儒家、墨家、法家、名家、道家、兵家等が代表的）という。\n" +
+"\n" +
+"[編集] 秦漢帝国\n" +
+"始皇帝\n" +
+"\n" +
+"現在の陝西省あたりにあった秦は、戦国時代に着々と勢力を伸ばした。勢力を伸ばした背景には、厳格な法律で人々を統治しようとする法家の思想を採用して、富国強兵に努めたことにあった。秦王政は、他の6つの列強を次々と滅ぼし、紀元前221年には史上はじめての中国統一を成し遂げた。秦王政は、自らの偉業をたたえ、王を超える称号として皇帝を用い、自ら始皇帝と名乗った。\n" +
+"兵馬俑\n" +
+"\n" +
+"始皇帝は、法家の李斯を登用し、中央集権化を推し進めた。このとき、中央から派遣した役人が全国の各地方を支配する郡県制が施行された。また、文字・貨幣・度量衡の統一も行われた。さらに、当時モンゴル高原に勢力をもっていた遊牧民族の匈奴を防ぐために万里の長城を建設させた。さらに、軍隊を派遣して、匈奴の南下を抑えた。また、嶺南地方（現在の広東省）にも軍を派遣し、この地にいた百越諸族を制圧した。しかし、このような中央集権化や土木事業・軍事作戦は人々に多大な負担を与えた。そのため、紀元前210年に始皇帝が死ぬと、翌年には陳勝・呉広の乱という農民反乱がおきた。これに刺激され各地で反乱がおき、ついに秦は紀元前206年に滅びた。\n" +
+"漢の偉大な発明、紙\n" +
+"漢の偉大な発明、紙\n" +
+"\n" +
+"秦が滅びたあと、劉邦と項羽が覇権をめぐって争った（楚漢戦争）が、紀元前202年には、劉邦が項羽を破り、漢の皇帝となった。劉邦は、始皇帝が急速な中央集権化を推し進めて失敗したことから、一部の地域には親戚や臣下を王として治めさせ、ほかの地域を中央が直接管理できるようにした。これを郡国制という。しかし、紀元前154年には、各地の王が中央に対して呉楚七国の乱と呼ばれる反乱を起こした。この反乱は鎮圧され、結果として、中央集権化が進んだ。紀元前141年に即位した武帝は、国内の安定もあり、対外発展を推し進めた。武帝は匈奴を撃退し、シルクロードを通じた西方との貿易を直接行えるようにした。また、朝鮮半島北部、ベトナム北中部にも侵攻した。これらの地域はその後も強く中国文化の影響を受けることとなった。また、武帝は董仲舒の意見を聞いて、儒教を統治の基本とした。これ以降、中国の王朝は基本的に儒教を統治の基本としていく。一方で文帝の頃より貨幣経済が広汎に浸透しており、度重なる軍事行動と相まって、農民の生活を苦しめた。漢の宮廷では貨幣の浸透が農民に不利益であることがしばしば論じられており、農民の救済策が検討され、富商を中心に増税をおこなうなど大土地所有を抑制しようと努力した。また儒教の国教化に関連して儒教の教義論争がしばしば宮廷の重大問題とされるようになった。\n" +
+"\n" +
+"8年には、王莽が皇帝の位を奪って、一旦漢を滅ぼした。王莽は当初儒教主義的な徳治政治をおこなったが、相次ぐ貨幣の改鋳や頻繁な地名、官名の変更など理想主義的で恣意的な政策をおこなったため徐々に民心を失い、辺境異民族が頻繁に侵入し、赤眉の乱など漢の復興を求める反乱が起き、内乱状態に陥った。結局、漢の皇族の血を引く劉秀によって漢王朝が復興された。この劉秀が建てた漢を後漢という。王朝初期には雲南に進出し、また班超によって西域経営がおこなわれ、シルクロードをおさえた。初期の後漢王朝は豪族連合的な政権であったが、章帝の時代までは中央集権化につとめ安定した政治が行われた。しかし安帝時代以後外戚や宦官の権力の増大と官僚の党派対立に悩まされるようになった。\n" +
+"\n" +
+"[編集] 魏晋南北朝時代\n" +
+"三国決戦の地、赤壁\n" +
+"三国決戦の地、赤壁\n" +
+"\n" +
+"後漢末期の184年には、黄巾の乱と呼ばれる農民反乱がおきた。これ以降、隋が589年に中国を再統一するまで、一時期を除いて中国は分裂を続けた。この隋の再統一までの分裂の時代を魏晋南北朝時代という。また、この時期には日本や朝鮮など中国周辺の諸民族が独自の国家を形成し始めた時期でもある。\n" +
+"\n" +
+"さて、黄巾の乱が鎮圧されたあと、豪族が各地に独自政権を立てた。中でも有力であったのが、漢王朝の皇帝を擁していた曹操である。しかし、中国統一を目指していた曹操は、208年に赤壁の戦いで、江南の豪族孫権に敗れた。結局、曹操の死後、220年に曹操の子の曹丕が後漢の皇帝から皇帝の位を譲られ、魏を建国した。これに対して、221年には、現在の四川省に割拠していた劉備が皇帝となり、蜀を建国した。さらに、江南の孫権も229年に皇帝と称して、呉を建国した。この魏・呉・蜀の三国が並立した時代を三国時代という。\n" +
+"\n" +
+"三国の中で、もっとも有力であったのは魏であった。魏は後漢の半分以上の領土を継承したが、戦乱で荒廃した地域に積極的な屯田をおこない、支配地域の国力の回復につとめた。魏では官吏登用法として、九品官人法[5]がおこなわれた。\n" +
+"\n" +
+"三国は基本的に魏と呉・蜀同盟との争いを軸としてしばしば交戦したが、蜀がまず263年に魏に滅ぼされ、その魏も有力な臣下であった司馬炎に265年に皇帝の位を譲るという形で滅亡した。司馬炎は皇帝となって国号を晋と命名し、さらに280年に呉を滅ぼし、中国を統一した。しかし、300年から帝位をめぐって各地の皇族が戦争を起こした（八王の乱）。このとき、五胡と呼ばれる異民族を軍隊として用いたため、これらの五胡が非常に強い力を持つようになった。316年には、五胡の1つである匈奴が晋をいったん滅ぼした。これ以降、中国の北方は、五胡の建てた国々が支配し、南方は江南に避難した晋王朝（南に移ったあとの晋を東晋という）が支配した。この時期は、戦乱を憎み、宗教に頼る向きがあった。代表的な宗教が仏教と道教であり、この2つの宗教は時には激しく対立することがあった。\n" +
+"\n" +
+"さて、江南を中心とする中国の南方では、異民族を恐れて、中国の北方から人々が多く移住してきた。これらの人々によって、江南の開発が進んだ。それに伴い、貴族が大土地所有を行うということが一般的になり、貴族が国の政治を左右した。一部の貴族の権力は、しばしば皇帝権力よりも強かった。これらの貴族階層の者により散文、書画等の六朝文化と呼ばれる文化が発展した。東晋滅亡後、宋・斉・梁・陳という4つの王朝が江南地方を支配したが、貴族が強い力を握ることは変わらなかった。梁の武帝は仏教の保護に努めた。\n" +
+"\n" +
+"北方では、鮮卑族の王朝である北魏が台頭し、439年には、華北を統一した。471年に即位した孝文帝は漢化政策を推し進めた。また、土地を国家が民衆に割り振る均田制を始め、律令制の基礎付けをした。しかし、このような漢化政策に反対するものがいたこともあり、北魏は、西魏と東魏に分裂した。西魏は北周へと、東魏は北斉へと王朝が交代した。577年には北周が北斉を滅ぼしたが、581年に隋が北周にとって代わった。589年に隋は南方の陳を滅ぼし、中国を統一した。\n" +
+"\n" +
+"魏晋南北朝表も参照。\n" +
+"\n" +
+"[編集] 隋唐帝国\n" +
+"現在でも使用される世界最大の大運河\n" +
+"現在でも使用される世界最大の大運河\n" +
+"\n" +
+"中国を統一した隋の文帝は、均田制・租庸調制・府兵制などを進め、中央集権化を目指した。また同時に九品中正法を廃止し、試験によって実力を測る科挙を採用した。しかし、文帝の後を継いだ煬帝は、江南・華北を結ぶ大運河を建設したり、度重なる遠征を行ったために、民衆の負担が増大した。このため農民反乱が起き、618年に隋は滅亡した。\n" +
+"\n" +
+"隋に代わって、中国を支配したのが、唐である。唐は基本的に隋の支配システムを受け継いだ。626年に即位した太宗は、租庸調制を整備し、律令制を完成させた。唐の都の長安は、当時世界最大級の都市であり、各国の商人などが集まった。長安は、西方にはシルクロードによってイスラム帝国や東ローマ帝国などと結ばれ、ゾロアスター教・景教・マニ教をはじめとする各地の宗教が流入した。また、文化史上も唐時代の詩は最高のものとされる。\n" +
+"当時世界最大の都市だった長安のシンボルタワー・大雁塔\n" +
+"当時世界最大の都市だった長安のシンボルタワー・大雁塔\n" +
+"\n" +
+"太宗の死後着々と力を付けた太宗とその子の高宗の皇后武則天はついに690年皇帝に即位した。前にも後にも中国にはこれのほかに女帝はいない。\n" +
+"\n" +
+"712年に即位した玄宗は国内の安定を目指したが、すでに律令制は制度疲労を起こしていた。また、周辺諸民族の統治に失敗したため、辺境に強大な軍事力が置かれた。これを節度使という。節度使は、後に軍権以外にも、民政権・財政権をももつようになり、力を強めていく。763年には、節度使の安禄山たちが安史の乱と呼ばれる反乱を起こした。この反乱は郭子儀や僕固懐恩、ウイグル帝国の太子葉護らの活躍で何とか鎮圧されたが、反乱軍の投降者の勢力を無視できず、投降者を節度使に任じたことなどから各地で土地の私有（荘園）が進み、土地の国有を前提とする均田制が行えなくなっていった。結局、政府は土地の私有を認めざるを得なくなった。結果として、律令制度は崩壊した。875年から884年には黄巣の乱と呼ばれる農民反乱がおき、唐王朝の権威は失墜した。このような中、各地の節度使はますます権力を強めた。907年には、節度使の1人である朱全忠が唐を滅ぼした。\n" +
+"\n" +
+"[編集] 五代十国・宋\n" +
+"画像:Compass in a wooden frame.jpg\n" +
+"中国航海術の偉大な発明、羅針盤\n" +
+"\n" +
+"唐の滅亡後、各地で節度使があい争った。この時代を五代十国時代という。この戦乱を静めたのが、960年に皇帝となって宋を建国した趙匡胤である。ただし、完全に中国を宋が統一したのは趙匡胤の死後の976年である。\n" +
+"\n" +
+"趙匡胤は、節度使が強い権力をもっていたことで戦乱が起きていたことを考え、軍隊は文官が率いるという文治主義をとった。また、これらの文官は、科挙によって登用された。宋からは、科挙の最終試験は皇帝自らが行うものとされ、科挙で登用された官吏と皇帝の結びつきは深まった。また、多くの国家機関を皇帝直属のものとし、中央集権・皇帝権力強化を進めた。科挙を受験した人々は大体が、地主層であった。これらの地主層を士大夫と呼び、のちの清時代まで、この層が皇帝権力を支え、官吏を輩出し続けた。\n" +
+"杭州\n" +
+"杭州\n" +
+"\n" +
+"唐は、その強大な力によって、周辺諸民族を影響下においていたが、唐の衰退によってこれらの諸民族は自立し、独自文化を発達させた。また、宋は文治主義を採用していたたため、戦いに不慣れな文官が軍隊を統制したので、軍事力が弱く、周辺諸民族との戦いにも負け続けた。なかでも、契丹族の遼・タングート族の西夏・女真族の金は、中国本土にも侵入し、宋を圧迫した。これらの民族は、魏晋南北朝時代の五胡と違い、中国文化を唯一絶対なものとせず、独自文化を保持し続けた。このような王朝を征服王朝という。後代の元や清も征服王朝であり、以降、中国文化はこれらの周辺諸民族の影響を強く受けるようになった。\n" +
+"\n" +
+"1127年には、金の圧迫を受け、宋は、江南に移った。これ以前の宋を北宋、以降を南宋という。南宋時代には、江南の経済が急速に発展した。また、すでに唐代の終わりから、陸上の東西交易は衰退していたが、この時期には、ムスリム商人を中心とした海上の東西交易が発達した。当時の宋の特産品であった陶磁器から、この交易路は陶磁の道と呼ばれる。南宋の首都にして海上貿易の中心港だった杭州は経済都市として栄え、元時代に中国を訪れたマルコ・ポーロは杭州を「世界一繁栄し、世界一豊かな都市」と評している。\n" +
+"\n" +
+"文化的には、経済発展に伴って庶民文化が発達した。また、士大夫の中では新しい学問をもとめる動きが出て、儒教の一派として朱子学が生まれた。\n" +
+"\n" +
+"[編集] モンゴル帝国\n" +
+"\n" +
+"13世紀初頭にモンゴル高原で、チンギス・ハーンが、モンゴルの諸部族を統一し、ユーラシア大陸各地へと、征服運動を開始した。モンゴル人たちは、東ヨーロッパ、ロシア、小アジア、メソポタミア、ペルシャ、アフガニスタン、チベットに至る広大な領域を支配し、この帝国はモンゴル帝国と呼ばれる。中国もまた征服活動の例外ではなかった。当時、黄河が南流し、山東半島の南に流れていたため、漢民族は北方民族の攻勢を防げなかった。華北は満州系の女真族による金が、南部を南宋が支配していたが、金は1234年、南宋は1279年にモンゴルに滅ぼされた。\n" +
+"\n" +
+"モンゴル帝国は各地に王族や漢人有力者を分封した。モンゴル帝国の5代目の君主（ハーン）にクビライが即位すると、これに反発する者たちが、反乱を起こした。結局、モンゴル帝国西部に対する大ハーン直轄支配は消滅し、大ハーンの政権は中国に軸足を置くようになった。もっとも、西方が離反しても、帝国としての緩やかな連合は保たれ、ユーラシアには平和が訪れていた。1271年にクビライは元を国号として中国支配をすすめた。\n" +
+"宋代に発明された火薬は元寇の時使用され、日本の武士を驚かせた\n" +
+"宋代に発明された火薬は元寇の時使用され、日本の武士を驚かせた\n" +
+"\n" +
+"モンゴル帝国(元)は未だ征服していなかった南宋への牽制のためにも日本に対して通交を求めたが、日本側は断った。このため二度に渡り日本に侵攻したが、成功しなかった（元寇）。元は三度目の日本侵攻を計画したが、実現には至らなかった。\n" +
+"\n" +
+"中国南部を支配していた南宋を1279年に元が滅ぼしたのはすでに見たとおりである。\n" +
+"\n" +
+"元の中国支配は、伝統的な中国王朝とは大きく異なっていた。元は中国の伝統的な統治機構を採用せず、遊牧民の政治の仕組みを中国に移入したからである。元の支配階級の人々は、すでに西方の優れた文化に触れていたため、中国文化を無批判に取り入れることはなかった。それは政治においても同様だったのである。それに伴い、伝統的な統治機構を担ってきた、儒教的な教養を身に付けた士大夫層は冷遇され、政権から遠ざけられた。そのため、彼らは曲や小説などの娯楽性の強い文学作品の執筆に携わった。この時代の曲は元曲と呼ばれ、中国文学史上最高のものとされる。また、モンゴル帝国がユーラシア大陸を広く支配したために、この時期は東西交易が前代に増して盛んになった。\n" +
+"\n" +
+"元は、宮廷費用などを浪費しており、そのため塩の専売策や紙幣の濫発で収入を増やそうとした。しかし、これは経済を混乱させるだけであった。そして、庶民の生活は困窮した。こうした中、各地で反乱が発生した。中でも最大規模のものは1351年に勃発した紅巾党の乱であった。紅巾党の中から頭角をあらわした朱元璋は、1368年に南京で皇帝に即位して明を建国した。同年、朱元璋は元の都の大都を陥落させ、元の政府はモンゴル高原へと撤退した。撤退後の元のことを北元といい、明と北元はしばしば争った。明側は1388年に北元は滅んだと称しているが、実質的にはその後も両者の争いは続いた。\n" +
+"\n" +
+"[編集] 明清帝国\n" +
+"鄭和の南海大遠征の時の巨艦・「宝船」\n" +
+"鄭和の南海大遠征の時の巨艦・「宝船」\n" +
+"\n" +
+"洪武帝の死後、孫の建文帝が即位したが、洪武帝の四男である朱棣が反乱（靖難の変）を起こし、朱棣が永楽帝として皇帝になった。永楽帝は、モンゴルを攻撃するなど、積極的に対外進出を進めた。また、鄭和を南洋に派遣して、諸国に朝貢を求めた。この時の船が近年の研究によって長さ170m余、幅50m余という巨艦で、その約70年後の大航海時代の船の5倍から10倍近い船であったことが分かっている。\n" +
+"\n" +
+"また、永楽帝によって現在に至るまで世界最大の宮殿である紫禁城が北京に築かれた。\n" +
+"\n" +
+"永楽帝の死後、財政事情もあって、明は海禁政策をとり、貿易を著しく制限することとなる。このとき永楽帝を引き継いで、鄭和のようにずっと積極的に海外へ進出していれば、ヨーロッパのアジア・アフリカ支配も実現しなかっただろうと多くの歴史家は推測する。その後、モンゴルが再び勢力を強めはじめ、1449年には皇帝がモンゴルの捕虜になるという事件（土木の変）まで起きた。同じ頃、中国南部沿岸には、倭寇と呼ばれる海上の無法者たちが襲撃を重ねていた。これは、海禁政策で貿易が自由にできなくなっていたためである。倭寇とモンゴルを併称して北虜南倭というが、北虜南倭は明を強く苦しめた。\n" +
+"紫禁城の中心、太和殿\n" +
+"紫禁城の中心、太和殿\n" +
+"\n" +
+"また、皇帝による贅沢や多額の軍事費用の負担は民衆に重税となって圧し掛かってきた。これに対し、各地で反乱がおき、その中で頭角をあらわした李自成が1644年に明を滅ぼした。\n" +
+"\n" +
+"17世紀初頭には、現在の中国東北地方でヌルハチが女真族を統一した。その子のホンタイジは中国東北地方と内モンゴルを征服し、1636年にはモンゴル人から元の玉璽を譲られ、清を建国した。李自成が明を滅ぼすと清の軍隊は万里の長城を越えて、李自成の軍隊を打ち破り、中国全土を支配下に置いた。17世紀後半から18世紀にかけて、康熙帝・雍正帝・乾隆帝という3人の賢い皇帝の下で、清の支配領域は中国本土と中国東北地方・モンゴルのほかに、台湾・東トルキスタン・チベットにまで及んだ。\n" +
+"\n" +
+"この清の支配領域が大幅に広がった時期は、『四庫全書』の編纂など文化事業も盛んになった。しかし、これは学者をこのような事業に動員して、異民族支配に反抗する暇をなくそうとした面もあった。\n" +
+"\n" +
+"明代の後期には、メキシコや日本から大量の銀が中国に流入し、貨幣として基本的に銀が使われるようになった。そのため、政府も一条鞭法と呼ばれる税を銀で払わせる税法を始めた。また、清代に入ると、人頭税を廃止し土地課税のみとする地丁銀制が始まった。また明清両代ともに商品経済が盛んになり、農業生産も向上した。\n" +
+"\n" +
+"[編集] 中国の半植民地化\n" +
+"フランス人が描いた中国半植民地化の風刺画。イギリス、ドイツ、ロシア、フランス、日本が中国を分割している。\n" +
+"フランス人が描いた中国半植民地化の風刺画。イギリス、ドイツ、ロシア、フランス、日本が中国を分割している。\n" +
+"\n" +
+"18世紀が終わるまでには、清とヨーロッパとの貿易はイギリスがほぼ独占していた。しかし、当時イギリスの物産で中国に売れるものはほとんどなく、逆に中国の安いお茶はイギリスの労働者階級を中心に大きな需要があったこともあり、イギリスは貿易赤字に苦しんだ。そこで、イギリスは麻薬であるアヘンを中国に輸出し始めた。結果、イギリスは大幅な貿易黒字に転じた。しかし、中国にはアヘン中毒者が蔓延し、この事態を重く見た清朝政府は、1839年に林則徐に命じてアヘン貿易を取り締まらせた。しかし、これに反発したイギリス政府は清に対して翌1840年宣戦布告した。アヘン戦争と呼ばれるこの戦争では、工業化をとげ、近代兵器を持っていたイギリス軍が勝利した。これ以降、イギリスをはじめとするヨーロッパの列強は中国に対し、不平等条約（治外法権の承認、関税自主権の喪失、片務的最恵国待遇の承認、開港、租借といった）を締結させ、中国の半植民地化が進んだ。\n" +
+"\n" +
+"国内的には、太平天国の乱などの反乱もしばしば起きた。これに対し、同治帝（在位1861年 - 1875年）の治世の下で、ヨーロッパの技術の取り入れ（洋務運動）が行われた。\n" +
+"\n" +
+"1894年から翌1895年にかけて清と日本との間で行われた日清戦争にも清は敗退した。これは洋務運動の失敗を意味するものであった。この戦争の結果、日本と清との間で結んだ下関条約により、李氏朝鮮の独立が認められ、中国の王朝が長年続けてきた冊封体制が崩壊した。\n" +
+"\n" +
+"その後、清朝政府は改革を進めようとしたものの、沿岸地域を租借地とされるなどのイギリス・フランス・ロシア・ドイツ・アメリカ合衆国・日本による半植民地化の動きは止まらなかった。結局、1911年の武昌での軍隊蜂起をきっかけに辛亥革命が起こり、各地の省が清からの独立を宣言した。翌1912年1月1日、革命派の首領の孫文によって南京で中華民国の樹立が宣言された。北京にいた清の皇帝溥儀（宣統帝）は、清朝政府内部の実力者である袁世凱により2月12日に退位させられ、清は完全に滅亡した。\n" +
+"\n" +
+"[編集] 中華民国\n" +
+"\n" +
+"[編集] 革命後の中国の政局\n" +
+"\n" +
+"中華民国は成立したものの、清朝を打倒した時点で革命に参加した勢力どうしで利害をめぐって対立するようになり、政局は混乱した。各地の軍閥も民国政府の税金を横領したり勝手に新税を導入して独自の財源を持つようになり、自立化した。\n" +
+"\n" +
+"[編集] 袁世凱の台頭と帝制運動（1913年～1916年）\n" +
+"袁世凱\n" +
+"袁世凱\n" +
+"\n" +
+"臨時大総統であった袁世凱は大総統の権力強化を図って議会主義的な国民党の勢力削減を企てた。国民党の急進派はこれに反発、第二革命を起こしたが鎮圧された。1913年10月袁は正式な大総統となり、さらに11月には国民党を非合法化し、解散を命じた。1914年1月には国会を廃止、5月1日には立法府の権限を弱め大総統の権力を大幅に強化した中華民国約法を公布した。\n" +
+"\n" +
+"袁は列強から多額の借款を借り受けて積極的な軍備強化・経済政策に着手した。当初列強の袁政権に対する期待は高かった。しかしこのような外国依存の財政は、のちに列強による中国の半植民地化をますます進めることにもなった。第一次世界大戦が始まると、新規借款の望みがなくなったため、袁は財政的に行き詰まった。また日本が中国での権益拡大に積極的に動いた。\n" +
+"\n" +
+"1915年5月9日に、袁が大隈重信内閣の21ヶ条要求を受けたことは大きな外交的失敗と見られ、同日は国恥記念日とされ袁の外交姿勢は激しく非難された。袁は独裁を強化することでこの危機を乗り越えようとし、立憲君主制的な皇帝制度へ移行し、自身が皇帝となることを望んだ。日本も立憲君主制には当初賛成していたようだが、中国国内で帝制反対運動が激化すると反対に転じ外交圧力をかけた。1916年袁は失意のうちに没した。\n" +
+"\n" +
+"[編集] 袁世凱死後の政局（1916年～1920年）\n" +
+"\n" +
+"袁の死後、北京政府の実権を掌握したのは国務総理となった段祺瑞であった。段は当初国会[6]の国民党議員などと提携し、調整的な政策をとっていた。しかし、第一次世界戦に対独参戦しようとしたため徐々に国会と対立した。段は日本の援助の下に強硬な政策を断行した。1917年8月14日第一次世界大戦に対独参戦。軍備を拡張して国内の統一を進めた。また鉄道や通信などの業界を背景とする利権集団が段を支えた。1918年には国会議員改定選挙を強行した。国民党はこれに激しく対立し、南方の地方軍とともに孫文を首班とする広東軍政府をつくった。5月には日本と日中軍事協定[7]を結んだ。寺内正毅内閣失脚後に日本の外交方針が転回すると、段は急速に没落した。段の安徽派と対立関係にあった直隷派の馮国璋は徐世昌を大総統に推薦し、段もこれを受け入れた。親日的な安徽派は徐々に影響力を失っていった。1919年5月4日、山東半島での主権回復と反日を訴えるデモ行進が始まった。これを五・四運動という。なお山東半島は1922年に返還された。1920年7月の安直戦争で直隷派に敗れたことで段は失脚した。\n" +
+"\n" +
+"[編集] 国民革命（1920年～1928年）\n" +
+"革命家・孫文\n" +
+"革命家・孫文\n" +
+"\n" +
+"袁世凱により国民党が非合法化されたのち、孫文は1914年7月に中国革命党を東京で結成した。1919年には拠点を上海に移し、中国国民党と改称した。1921年には上海で中国共産党が成立した。これらの政党は1918年のロシア革命の影響を受けており、議会政党というよりも明確な計画性と組織性を備えた革命政党を目指した。1924年国民党は第一回全国大会をおこない、党の組織を改編するとともに共産党との合同（第一次国共合作）を打ち出した。孫文はこのころ全く機能していなかった国会に代わって国内の団体代表による国民会議を提唱し、これに呼応した馮国璋により北京に迎えられた。1925年には国民会議促成会が開かれたが、この会期中に孫文は没した。7月には広東軍政府で機構再編が進み、中華民国国民政府の成立が宣言された。一方で1924年6月には蒋介石を校長として黄埔軍官学校が設立された。1925年4月に国民革命軍が正式に発足され、国民党は蒋介石を指導者として軍事的な革命路線を推し進めることとなった。1926年に広州から北伐を開始した。1927年1月には武漢に政府を移し、武漢国民政府と呼ばれるようになった。この武漢国民政府では当初国民党左派と共産党が優位にあったが、蒋介石は同年4月12日上海クーデターを起こしてこれらを弾圧し、4月18日には反共を前面に打ち出した南京国民政府を成立させた。南京国民政府は主に上海系の資本家に支えられ、北京・武漢・南京に3つの政権が鼎立することになったが、9月ごろから武漢政府も反共に転じ、南京政府に吸収された。1928年6月南京政府の国民革命軍は北京の中華民国政府を打倒し、12月に張学良もこれを承認したことから、国民政府によって中国は再び統一された。\n" +
+"\n" +
+"[編集] 国民政府（1928年～1931年）\n" +
+"蒋介石\n" +
+"蒋介石\n" +
+"\n" +
+"国民政府においては基本的に国民党の一党独裁の立場が貫かれた。しかし一般党員の数は50万人以下であったとされており、4億をこえると考えられた中国国民のなかではかなり少数であった（国民の多くが「国民」として登録されておらず、しかも文盲のものも多かった）。そのため支配基盤は完全とは言えず、土地税を中心として地方政権の財源を確保する国地画分政策がおこなって、割拠的傾向がいまだに強い地方勢力に配慮したりした。1930年代前半には国民政府に叛旗を翻す形で地方政権が樹立される例が多くなり、軍事衝突なども起きた。1930年に閻錫山と汪兆銘が中心となった北平政府や1931年に孫科らがたてた広州政府などである。\n" +
+"\n" +
+"しかしこのような軍事的緊張は国民政府の中央軍を掌握していた蒋介石の立場を強めることにもなった。蒋介石は経済政策[8]でも手腕を発揮し影響力を増した。\n" +
+"\n" +
+"[編集] 抗日戦争（1931年～1937年）\n" +
+"満州国皇帝愛新覚羅溥儀\n" +
+"満州国皇帝愛新覚羅溥儀\n" +
+"\n" +
+"張作霖が関東軍に爆殺されたあとをついだ張学良は国民革命を支持しており、自身の支配していた中国東北地方を国民政府へ合流させた。このために反日運動が中国東北地方にも広がったが、日本は中国東北地方の権益を確保しようとしていたためにこれに大きく反発した。1931年9月、満州事変がおこり、関東軍によって日本政府の意向を無視して大規模な武力行動がおこなわれた。しかし列強はこれを傍観する姿勢をとったので、日本政府はこの行動を追認した。\n" +
+"\n" +
+"東北地方をほぼ制圧した日本軍は、1932年に上海事変を起こし、列強がそれに注目している間に傀儡政権として満州国を東北地方に樹立した。同年10月、リットン調査団が国際連盟によって派遣され、満州国を中国の主権の下に列強の共同管理による自治政府とするべきという妥協案を示したが、日本は採択に反対した。1933年5月日中間で停戦協定（塘沽協定）が結ばれた。1934年には満州国は帝制に移行し、満州帝国となった。\n" +
+"\n" +
+"1931年に瑞金に政権を樹立していた中国共産党は満州国建国時に日本に宣戦布告していたが、国民党との抗争に忙しく、中国国民で一致して日本の侵略に立ち向かうことはできなかった。1934年には瑞金は国民党により陥落し、打撃を受けた中国共産党は長征と称して西部に移動し、組織の再編をはかった。長征の結果中国共産党は延安に拠点を移した。\n" +
+"\n" +
+"[編集] 日中戦争（1937年～1945年）\n" +
+"\n" +
+"1937年には、盧溝橋事件を契機に、日本軍が中国本土に進出し、中華民国と全面戦争に入った（日中戦争）。これに対し、蒋介石は当初日本との戦いよりも中国共産党との戦いを優先していたが、西安事件により、二つの党が協力して日本と戦うことになった（第二次国共合作）。\n" +
+"カイロ会談に出席した蒋介石とアメリカのフランクリン・D・ルーズベルト大統領、イギリスのウィンストン・チャーチル首相\n" +
+"カイロ会談に出席した蒋介石とアメリカのフランクリン・D・ルーズベルト大統領、イギリスのウィンストン・チャーチル首相\n" +
+"\n" +
+"しかし日中戦争は当初日本軍優位に進み、日本軍は多くの都市を占領したが、各拠点支配はできても広大な中国において面での支配はできず、これを利用した国民党軍・共産党軍ともに各地でゲリラ戦を行い日本軍を苦しめ、戦線を膠着させた。日本は汪兆銘ら国民党左派を懐柔、南京国民政府を樹立させたが、国内外ともに支持は得られなかった。加えて1941年12月、日本はアメリカやイギリス（連合国）とも戦端を開いたが（太平洋戦争）、一方で中国で多くの戦力を釘付けにされるなど、苦しい状況に落ち込まされた。国民党政府は連合国側に所属し、アメリカやイギリスなどから豊富な援助を受けることとなった。\n" +
+"\n" +
+"結局、中国大陸戦線では終始日本側が優勢であったものの、1945年8月ポツダム宣言の受諾とともに日本が無条件降伏することで終結した。国民党政府は連合国の1国として大きな地位を占めていたこともあり、戦勝国として有利な立場を有することとなり、日本だけでなくヨーロッパ諸国も租界を返還するなど、中国の半植民地化は一応の終わりを見せた。\n" +
+"\n" +
+"しかしまもなく国民党と共産党との対立が激化して国共内戦が勃発し、結果として左派が力を持ったアメリカからの支援が減った国民党に対して、ソビエト連邦からの支援を受けていた中国共産党が勝利し、1949年10月1日に毛沢東が中華人民共和国の成立を宣言した。内戦に敗れた中国国民党率いる中華民国政府は台湾島に撤退し、現在に至るまで中国共産党率いる中華人民共和国と「中国を代表する正統な政府」の地位を争っている。\n" +
+"\n" +
+"[編集] 漢民族以外の民族の動向\n" +
+"\n" +
+"[編集] モンゴルとチベットでの動き\n" +
+"\n" +
+"辛亥革命により清国が消滅すると、その旧領をめぐって中国、モンゴル、チベットは、それぞれに自領域を主張した。\n" +
+"\n" +
+"中国は清領全域を主張した。これに対して、モンゴルとチベットは、自分たちは清朝の皇帝に服属していたのであって中国という国家に帰属するものではなく、服属先の清帝退位後は中国と対等の国家であると主張し独立を目指す動きが強まった。\n" +
+"ポタラ宮、当時のチベットの中心地\n" +
+"ポタラ宮、当時のチベットの中心地\n" +
+"\n" +
+"1913年、モンゴルではボグド・ハーンによって、チベットではダライ・ラマ13世よって中国からの独立が宣言され、両者はモンゴル・チベット相互承認条約を締結するなど国際的承認をもとめ、これを認めない中華民国とは戦火を交えた。 この状況は、モンゴル域への勢力浸透をはかるロシア、チベット域への進出をねらうイギリスの介入をゆるし、モンゴル・ロシア・中華民国はキャフタ協定に調印批准、チベット・イギリス・中華民国はシムラ協定（民国政府のみ調印、批准されなかった）が模索されたものの問題の解決には至らなかった。\n" +
+"\n" +
+"ダライ・ラマを補佐していたパンチェン・ラマは親中国的であったために、イギリスに接近するダライ・ラマに反発し、1925年に中国に亡命した。1933年、ダライ・ラマ13世が死去、中国の統治下にあったチベット東北部のアムド地方（青海省）で生まれたダライ・ラマ14世の即位式典に列席した国民政府の使節団は、式典が終了したのちも、蒙蔵委員会駐蔵弁事處を自称してラサにとどまった。1936年には長征中の中国共産党の労農紅軍が、カム地方東部（四川省西部、当時西康省）に滞留中、同地のチベット人に「チベット人人民共和国」（博巴人民共和国）[9]を組織させたが、紅軍の退出とともに、ほどなく消滅した。\n" +
+"\n" +
+"この問題は、モンゴルについては、1947年、外蒙古部分のみの独立を中華民国政府が承認することによって、チベットについては、1950年、十七ヶ条協定によってチベットの独立が否定され中華人民共和国の一地方となったことによって、一応の決着をみた。\n" +
+"\n" +
+"[編集] 東トルキスタン（新疆）での動き\n" +
+"\n" +
+"東トルキスタン（新疆)では、19世紀中に統治機構の中国化が達成されていた。すなわち、旗人の3将軍による軍政と、地元ムスリムによるベク官人制にかわり、省を頂点に府、州、県に行政区画された各地方に漢人科挙官僚が派遣されて統治する体制である。そのため、辛亥革命時、東トルキスタンでは、地元ムスリムがチベットやモンゴルと歩調をあわせて自身の独立国家を形成しようとする動きはみられず、新疆省の当局者たちは、すみやかに新共和国へ合流する姿勢を示した。この地では、楊増新が自立的な政権を維持し、またソ連と独自に難民や貿易の問題について交渉した。楊増新の暗殺後は金樹仁が実権が握ったが、彼は重税を課して腐敗した政治をおこなったため、1931年には大規模な内乱状態に陥った。その後金樹仁の部下であった盛世才が実権を握るようになり、彼はソ連にならった政策を打ち出して徐々に権力を強化した。一方で1933年には南部で東トルキスタン共和国の独立が宣言されたが、わずか6ヶ月で倒れた。\n" +
+"\n" +
+"[編集] 中華人民共和国\n" +
+"\n" +
+"[編集] 社会主義国化と粛清（1949年～1957年）\n" +
+"「建国宣言」を行なう毛沢東\n" +
+"「建国宣言」を行なう毛沢東\n" +
+"\n" +
+"1950年中ソ友好同盟相互援助条約が結ばれた。これは日本およびその同盟国との戦争を想定して締結されたものである。この条約でソ連が租借していた大連、旅順が返還され、ソ連の経済援助の下で復興を目指すこととなった。1953年より社会主義化が進み、人民政治協商会議に代わって全国人民代表大会が成立、農業生産合作社が組織された。\n" +
+"\n" +
+"1956年にソ連でフルシチョフによって「スターリン批判」がおこなわれると、東欧の社会主義国に動揺がはしった。中国共産党政府も共産圏にある国としてこの問題への対処を迫られ、この年初めて開催された党全国代表大会では、「毛沢東思想」という文言が党規約から消えた。そして全く一時的に（わずか2ヶ月）「百花斉放、百家争鳴」と称して民主党などの「ブルジョワ政党」の政治参加が試みられた。しかしブルジョワ政党が中国共産党政府による一党独裁に対して激しい批判を噴出させたため、逆に共産党による反右派闘争を惹起し、一党支配体制は強められた。一方で中ソ協定が結ばれ、軍事上の対ソ依存は強くなった。この時代の中華人民共和国をソ連のアメリカに対する緩衝国家あるいは衛星国家とみなすことも可能である。しかし徐々にデタント政策へと転回し始めていたソ連の対外政策は、中国共産党政府の中華民国に対する強硬政策と明らかに矛盾していた。\n" +
+"\n" +
+"[編集] 中国共産党の対ソ自立化（1958年～1965年）\n" +
+"\n" +
+"1958年に、毛沢東は大躍進政策を開始し、人民公社化を推進した。当初はかなりの効果をあげたかに見えた人民公社であったが、党幹部を意識した誇大報告の存在、極端な労働平均化などの問題が開始3ヶ月にしてすでに報告されていた。毛沢東はこのような報告を右派的な日和見主義であり、過渡的な問題に過ぎないと見ていたため、反対意見を封殺したが、あまりに急速な人民公社化は都市人口の異様な増大など深刻な問題を引き起こしていた。\n" +
+"\n" +
+"一方でこの年、中国共産党政府は台湾海峡で中華民国に対して大規模な軍事行動を起こし、アメリカ軍の介入を招いた。フルシチョフは中国共産党政府の強硬な姿勢を非難し、また自国がアメリカとの全面戦争に引きずり込まれないように努力した。ソ連はワルシャワ条約機構の東アジア版ともいうべき中ソの共同防衛体制を提案したが、中国共産党政府はソ連の対外政策への不信からこれを断った。その後1959年6月ソ連は中ソ協定を一方的に破棄した。1960年には経済技術援助条約も打ち切られ、この年の中国のGNPは1%も下落した。\n" +
+"\n" +
+"1959年と1960年に大規模な飢饉が中国を襲い、1500万人程度（2000万から5000万人以上とも）と言われる餓死者を出して大躍進政策も失敗に終わった。1960年代初頭には人民公社の縮小がおこなわれ、毛沢東自身が自己批判をおこなうなど、一見調整的な時期に入ったように思われた。劉少奇が第2次5ヶ年計画の失敗を人民公社による分権的傾向にあると指摘し、中央集権を目指した政治改革、個人経営を一部認めるなど官僚主義的な経済調整をおこなった。\n" +
+"\n" +
+"しかし党組織の中央集権化と個人経営に懐疑的であった毛沢東はこれを修正主義に陥るものであると見ていた。1963年に毛沢東は「社会主義教育運動」を提唱し、下部構造である「農村の基層組織の3分の1」は地主やブルジョワ分子によって簒奪されていると述べた。これは劉少奇ら「実権派」を暗に批判するものであった。またこのころ毛沢東は「文芸整風」運動と称して学術界、芸術界の刷新をはかっていたことも、のちの文化大革命の伏線となった。1964年中国は核実験に成功し、軍事的な自立化に大きな一歩を踏み出した。一方で1965年にアメリカによる北爆が始まりベトナム戦争が本格化すると、軍事的緊張も高まった。\n" +
+"\n" +
+"チベットでは独立運動が高まったが、政府はこれを運動家に対する拷問など暴力によって弾圧した。このため多数の難民がインドへ流入した。\n" +
+"\n" +
+"[編集] 文化大革命前期（1966年～1969年）\n" +
+"天安門広場は中華人民共和国時代にも多くの歴史の舞台となった\n" +
+"天安門広場は中華人民共和国時代にも多くの歴史の舞台となった\n" +
+"\n" +
+"1966年に毛沢東は文化大革命を提唱した。毛沢東の指示によって中央文化革命小組が設置され、北京の青少年によって革命に賛同する組織である紅衛兵が結成された。毛沢東は「造反有理」（反動派に対する謀反には道理がある）という言葉でこの運動を支持したので、紅衛兵は各地で組織されるようになった。\n" +
+"\n" +
+"毛沢東は文革の目的をブルジョワ的反動主義者と「実権派」であるとし、劉少奇とその支持者を攻撃対象とした。毛沢東は林彪の掌握する軍を背景として劉少奇を失脚させた。しかし文化大革命は政治だけにとどまることがなく、広く社会や文化一般にも批判の矛先が向けられ、反革命派とされた文化人をつるし上げたり、反動的とされた文物が破壊されたりした。\n" +
+"\n" +
+"1966年の末ごろから武力的な闘争が本格化し、地方では党組織と紅衛兵との間で武力を伴った激しい権力闘争がおこなわれた。毛沢東は秩序維持の目的から軍を介入させたが、軍は毛沢東の意向を汲んで紅衛兵などの中国共産党左派に加担した。中央では周恩来らと文革小組の間で権力闘争がおこなわれた。1967年の後半になると、毛沢東は内乱状態になった国内を鎮めるために軍を紅衛兵運動の基盤であった学校や工場に駐屯させた。\n" +
+"\n" +
+"この時期軍の影響力は極端に増大し、それに伴って林彪が急速に台頭した。1969年には中ソ国境の珍宝島で両国の軍事衝突があり（中ソ国境紛争）、軍事的緊張が高まったこともこれを推進した。同年採択された党規約で林彪は毛沢東の後継者であると定められた。\n" +
+"\n" +
+"[編集] 文化大革命後期（1969～1976年）\n" +
+"\n" +
+"文化大革命は後期になると国内の権力闘争や内乱状態を引き起こしたが、最終的に文化大革命は1976年の毛沢東死去で終結した。 文化大革命では各地で文化財破壊や大量の殺戮が行われ、その犠牲者の合計数は数百万人とも数千万人とも言われている。また学生たちが下放され農村で働くなど、生産現場や教育現場は混乱し、特に産業育成や高等教育などで長いブランクをもたらした。\n" +
+"\n" +
+"一方この時期、ソ連に敵対する中国共産党政府は、同じくソ連と敵対する日本やアメリカなどからの外交的承認を受け、この結果国連の常任理事国の議席も台湾島に遷都した中華民国政府（国民党政権）に変わって手にするなど、国際政治での存在感を高めつつあった。\n" +
+"\n" +
+"[編集] 改革開放以後の現在（1976年～）\n" +
+"返還された香港は中国経済の牽引都市になっている\n" +
+"返還された香港は中国経済の牽引都市になっている\n" +
+"\n" +
+"その後は一旦華国鋒が後を継いだが、1978年12月第11期三中全会で鄧小平が政権を握った。鄧小平は、政治体制は共産党一党独裁を堅持しつつ、資本主義経済導入などの改革開放政策を取り、近代化を進めた（社会主義市場経済、鄧小平理論）。この結果、香港ほか日米欧などの外資の流入が開始され、中国経済は離陸を始めた。\n" +
+"\n" +
+"[編集] 一党独裁\n" +
+"\n" +
+"冷戦崩壊後に、複数政党による選挙や言論の自由などの民主主義化を達成した中華民国と違い、いまだに中国共産党政府による一党独裁から脱却できない中華人民共和国には多数の問題が山積している。\n" +
+"\n" +
+"1989年には北京で、1980年代の改革開放政策を進めながら失脚していた胡耀邦の死を悼み、民主化を求める学生や市民の百万人規模のデモ（天安門事件）が起きたが、これは政府により武力鎮圧された。その一連の民主化運動の犠牲者数は中国共産党政府の報告と諸外国の調査との意見の違いがあるが、数百人から数万人に上るといわれている。しかし中国共産党政府はこの事件に関しては国内での正確な報道を許さず、事件後の国外からの非難についても虐殺の正当化に終始している。\n" +
+"\n" +
+"この事件以降も、中国共産党政府は情報や政策の透明化、民主化や法整備の充実などの国際市場が要求する近代化と、暴動や国家分裂につながる事態を避けるため、内外の報道機関やインターネットに統制を加え、反政府活動家に対する弾圧を加えるなどの前近代的な動きとの間で揺れている。この様な中、2003年には国内でSARSの大発生があったが、このときも政府は虚偽の発表を行なうなど問題の隠蔽を繰り返した。\n" +
+"\n" +
+"天安門事件で外資流入に急ブレーキがかかったが、1990年代には、江沢民政権のもとで、鄧小平路線に従い、経済の改革開放が進み、特に安い人件費を生かした工場誘致で「世界の工場」と呼ばれるほど経済は急成長した。なお、1997年にイギリスから香港が、1999年にポルトガルからマカオが、それぞれ中華人民共和国に返還され、植民地時代に整備された経済的、法的インフラを引き継ぎ、中華人民共和国の経済の大きな推進役となっている。また、敵対している中華民国との間にも経済的な交流が進み、両国の首都の間に直行便が就航するまでになっている。\n" +
+"\n" +
+"人口、面積ともに世界的な規模をもつことから、アメリカの証券会社であるゴールドマンサックスは、「中華人民共和国は2050年に世界最大の経済大国になる」と予想するなど、現在、中国経済の動向は良くも悪くも注目されているが、低賃金による大量生産を売り物にしてきた経済成長は賃金上昇・東南アジアやインドの追い上げなどで限界に達しており、産業の高度化や高付加価値化などの難題に迫られている。また、各種経済統計も中国共産党政府発表のそれは信憑性が乏しいと諸外国から指摘されている。各省など地方も独自の産業振興策に走り、中国共産党中央政府に対して経済統計の水増し発表や災害などの情報隠蔽を行うなど、統計や発表の信憑性不足に拍車をかけている。\n" +
+"\n" +
+"これらのことより、中国共産党の一党独裁による言論統制や貧富格差、地域格差など国内のひずみを放置し続ければ、いずれ内部崩壊を起こして再度混乱状態に陥り、ソ連同様に中華人民共和国という国家体制そのものが解体、消滅するという意見も多い。\n" +
+"\n" +
+"[編集] 少数民族問題\n" +
+"\n" +
+"なお、少数民族が住む新疆ウイグル自治区（東トルキスタン）では現在漢化政策の進展によって、漢民族が同地域へ大量に流入する、都市を中心として就職などに有利な中国語教育の充実によりウイグル語が廃れるなどの民族的なマイノリティ問題が発生している。またタクラマカン砂漠の石油資源利用や新疆南北の経済格差が広がっているなど、中国共産党政府の経済政策に対する批判も根強い。\n" +
+"\n" +
+"1997年には新疆ウイグル自治区で大規模な暴動が起きた。海外で東トルキスタン独立運動がおこなわれている一方国内でもウイグル人活動家の処刑などが行われているが、民族自治における権限拡大という現実主義的な主張もあらわれている。たとえば中国語教育を受けたウイグル人が中国共産党組織に参加する、新疆での中国共産党政府の経済政策に積極的に参加するといった事例も見られる。\n" +
+"\n" +
+"チベット自治区では歴史的なチベットの主権を主張するダライ・ラマの亡命政権が海外に存在し、中国共産党政府が不法な領土占拠をしていると訴えるとともに独立運動が継続されている。中国共産党政府はこれを武力で弾圧し続け、独立運動家への拷問などを行なったために、多数の難民が隣国のインドに流入した。\n" +
+"\n" +
+"[編集] 人口の変遷\n" +
+"\n" +
+"以下のデータは主に楊学通「計画生育是我国人口史発展的必然」（1980年）による。\n" +
+"時代 	年代 	戸数 	人口 	資料出所\n" +
+"（夏） 	禹（前2205年とされる） 		13,553,923 	『帝王世紀』\n" +
+"秦 			20,000,000? 	\n" +
+"前漢 	平帝元始2年（2年） 	12,233,062 	59,594,978 	『漢書』地理志\n" +
+"新 			20,000,000? 	\n" +
+"後漢 	順帝建康元年（144年） 	9,946,919 	49,730,550 	『冊府元亀』\n" +
+"晋 	武帝泰康元年（280年） 	2,459,804 	16,163,863 	『晋書』食貨志\n" +
+"隋 	煬帝大業2年（606年） 	8,907,536 	46,019,056 	『隋書』地理志・食貨志\n" +
+"唐 	玄宗天宝14年（755年） 	8,914,709 	52,919,309 	『通志』\n" +
+"宋 	神宗元豊3年（1080年） 	14,852,684 	33,303,889 	『宋史』地理志\n" +
+"金 	章宗明昌6年（1195年） 	7,223,400 	48,490,400 	『金史』食貨志\n" +
+"元 	世祖至元27年（1290年） 	13,196,206 	58,834,711 	『元史』地理志\n" +
+"明 	神宗万暦6年（1570年） 	10,621,436 	60,692,850 	『続文献通考』\n" +
+"清 	清初（1644年） 		45,000,000 	\n" +
+"聖祖康熙50年（1711年） 		100,000,000以上 	\n" +
+"高宗乾隆27年（1762年） 		200,000,000以上 	\n" +
+"高宗乾隆55年（1790年） 		300,000,000以上 	\n" +
+"仁宗嘉慶17年（1812年） 		333,700,560 	『東華録』\n" +
+"宣宗道光14年（1834年） 		400,000,000以上 	\n" +
+"中華民国 	民国36年（1947年） 		455,590,000 	『統計提要』\n" +
+"中華人民共和国 	1995年 		1,211,210,000 	『中国統計年鑑』\n" +
+"\n" +
+"[編集] 地方行政制度\n" +
+"\n" +
+"[編集] 封建制度（前1600年頃～前221年）\n" +
+"\n" +
+"殷・周の時代は封建制度[10]によって一定の直轄地以外は間接的に統治された。\n" +
+"\n" +
+"[編集] 郡県制度（前221年～249年）\n" +
+"\n" +
+"中国最初の統一王朝である秦は全国を郡とその下級単位である県に分ける郡県制度によって征服地を統治した。前漢初期においては、郡以上に広域な自治を認められた行政単位である国が一部の功臣や皇族のために設置された。しかし徐々に国の行政権限が回収されるとともに、推恩政策によって国の細分化が進められ、国は郡県と等しいものとなり、後漢時代には実質郡県制度そのままとなっていた。\n" +
+"\n" +
+"前漢時代に広域な監察制度としての刺史制度が始められると全国を13州[11]に分けた。これはいまだ行政的なものではない[12]と考えられている。後漢の後の魏王朝では官僚登用制度としての九品官人法が249年に司馬懿によって州単位でおこなわれるように適用されたので、行政単位として郡以上に広域な州が現実的な行政単位として確立したと考えられている。が、軍政面と官吏登用面のほかにどれほど地方行政に貢献したか[13]はあまり明確ではない。\n" +
+"\n" +
+"[編集] 軍府による広域行政（249年～583年）\n" +
+"\n" +
+"魏晋時代から都督府などの軍府の重要性が高まった。五胡十六国および南北朝時代になると、中国内部で複数の王朝が割拠し軍事的な緊張が高まったことから、とくに南朝において重要性が増した。これは本来特定の行政機関を持たなかったと思われる刺史に対して、軍事的に重要な地域の刺史に例外的に複数の州を統括できる行政権を与えたものであった。長官である府主（府の長官は一般的にさまざまな将軍号を帯び、呼称は一定ではないため便宜的に府主とする）は属僚の選定に対して大幅な裁量権が与えられており、そのため地方で自治的な支配を及ぼすことが出来た。また南朝では西晋末期から官吏登用において州は形骸化しており、吏部尚書によって官制における中央集権化が進行している。したがって中正官も単なる地方官吏に過ぎなくなり、広域行政単位としての州は官吏登用の面からは重要性が低下したが、地方行政単位としてはより実際性を帯びた。この時代州は一般に細分化傾向にあり、南北朝前期には中国全土で5,60州、南北朝末期に至ると中国全土で300州以上になり、ひとつの州がわずか2郡、ひとつの郡はわずか2,3県しか含まないという有様であった。\n" +
+"\n" +
+"[編集] 州県制（583年～1276年）\n" +
+"\n" +
+"南朝では都督制度が発達していたころ、北魏では州鎮制度が発達した。北魏では征服地にまず軍事的性格の強い鎮を置き、鎮は一般の平民と区別され軍籍に登録された鎮民を隷属させて支配した。鎮は徐々に州に改められたようであるが、北部辺境などでは鎮がずっと維持された。583年に隋の文帝が郡を廃止し、州県二級の行政制度を開始した。この際従来の軍府制度[14]にあった漢代地方制度的な旧州刺史系統の地方官は廃止され、軍府系統の地方官に統一されたと考えられている。595年には形骸化していた中正官も最終的に廃止されたという指摘もされている。またこれにより府主の属官任命権が著しく制限され、中央集権化がはかられた。唐では辺境を中心に広域な州鎮的軍府である総管府が置かれたが徐々に廃止され、刺史制度に基づいた地方軍的軍府、それに中央軍に対する吏部の人事権が強化・一元化され、軍事制度の中央集権化が完成された。特定の州に折衝府が置かれ、自営農民を中心として府兵が組織され常備地方軍[15]とされた。唐では州の上に10の道も設置されたが、これは監察区域で行政単位ではないと考えられている。\n" +
+"\n" +
+"[編集] 祭祀制度\n" +
+"\n" +
+"中国でおこなわれた国家祭祀については皇帝祭祀を参照。\n" +
+"\n" +
+"[編集] 外交\n" +
+"\n" +
+"中国大陸の諸王朝は前近代まで基本的に東アジアでの優越的な地位を主張し、外交的には大国として近隣諸国を従属的に扱う冊封体制が主流であった。\n" +
+"\n" +
+"[編集] 漢帝国\n" +
+"\n" +
+"漢代には南越、閩越、衛氏朝鮮などが漢の宗主権下にあったと考えられ、これらの国々は漢の冊封体制下にあったと考えられている。前漢武帝の時にこれらの諸国は征服され郡県に編入された。このことは漢の冊封が必ずしも永続的な冊封秩序を形成することを意図したものではなく、機会さえあれば実効支配を及ぼそうとしていたことを示す。また匈奴は基本的には冊封体制に組み込まれず、匈奴の単于と中国王朝の皇帝は原則的には対等であった。大秦（ローマ帝国のことを指すとされる）や大月氏などとの外交関係は冊封を前提とされていない。\n" +
+"\n" +
+"[編集] 魏晋南北朝時代\n" +
+"\n" +
+"魏晋南北朝時代には、中国王朝が分立する事態になったので、冊封体制は変質し実効支配を意図しない名目的な傾向が強くなったと考えられている。朝鮮半島では高句麗をはじめとして中小国家が分立する状態があらわれ、日本列島の古代国家[16] も半島の紛争に介入するようになったために、半島の紛争での外交的優位を得るため、これらの国々は積極的に中国王朝の冊封を求めた。しかし高句麗が北朝の実効支配には頑強に抵抗しているように、あくまで名目的関係にとどめようという努力がなされており、南越と閩越の紛争においておこなわれたような中国王朝の主導による紛争解決などは期待されていないという見方が主流である。\n" +
+"\n" +
+"[編集] 隋唐帝国\n" +
+"\n" +
+"再び中国大陸を統一した隋・唐の王朝の時代は東アジアの冊封体制がもっとも典型的となったという見方が主流である。隋は高句麗がみだりに突厥と通交し、辺境を侵したことからこれを討伐しようとしたが、遠征に失敗した。唐は、新羅と連合し、高句麗・百済を滅亡させ、朝鮮半島を州県支配しようとしたが、新羅に敗北し、願いは、叶わなかった。したがって隋・唐の冊封は実効支配とは無関係に形成されるようになった。唐の冊封体制の下では、律令的な政治体制・仏教的な文化が共有された。\n" +
+"\n" +
+"一方、突厥や西域諸国が服属すると、それらの地域に対する支配は直接支配としての州県、外交支配としての冊封とは異なった羈縻政策[17]がおこなわれた。\n" +
+"\n" +
+"[編集] 関連項目\n" +
+"\n" +
+"    * 中華人民共和国\n" +
+"    * 中華民国\n" +
+"    * 中国帝王一覧\n" +
+"    * 中国の首都\n" +
+"    * 中国史時代区分表\n" +
+"          o 夏商周年表\n" +
+"          o 魏晋南北朝表\n" +
+"    * 元号一覧\n" +
+"    * 二十四史（清によって公認された正史）\n" +
+"    * 中国史関係記事一覧\n" +
+"    * マカオの歴史\n" +
+"    * 香港の歴史\n" +
+"    * 台湾の歴史\n" +
+"    * 中国の通貨制度史\n" +
+"    * 中国の仏教\n" +
+"    * 中国法制史\n" +
+"    * 中国化\n" +
+"\n" +
+"Wikibooks\n" +
+"ウィキブックスに中国史関連の教科書や解説書があります。\n" +
+"[編集] 脚注\n" +
+"\n" +
+"   1. ^ 浙江省紹興市郊外にある陵墓が禹のものであるとされ、戦国時代同地を支配していた越王勾践が禹の子孫を標榜していること、夏の桀王が『史記』鄭玄注などで淮河と長江の中間にある南巣で死んだとしていることなどによる。\n" +
+"   2. ^ 河南省にある偃師二里頭遺跡が夏のものではないかとされているが、文書などが発見されていないため確定はされていない。また偃師二里頭遺跡での発掘結果から殷との連続性が確認されたが、細かい分析においては殷との非連続性も確認されているため、偃師二里頭遺跡が夏王朝のものであっても、夏が黄河流域起源の王朝であったかどうかは論争中である。\n" +
+"   3. ^ 代表的な遺跡殷墟が有名であるため日本では一般に殷と呼ばれるが、商の地が殷王朝の故郷とされており、商が自称であるという説もあるため、中国では商と呼ぶほうが一般的である。\n" +
+"   4. ^ ただし殷を北西から侵入してきた遊牧民族による征服王朝だとする説もある。これは偃師二里頭遺跡では青銅器が現地生産されているのに対し、殷時代の青銅器は主に蜀方面で生産されていたことが確認されていることによる。\n" +
+"   5. ^ 当初は漢魏革命の際に漢の官僚を魏宮廷に回収する目的で制定されたものであったが、優れたものであったために一般的な官吏登用に使用されるようになった。これは中正官を通して地方の世論を反映した人事政策をおこなうもので、地方で名望のあったものをその程度に応じて品位に分け官僚として登用するものであった。官僚は自身の品位と官職の官品に従って一定の官職を歴任した。地方の世論に基づくとはいえ、一般的に家柄が重視される傾向にあり、「上品に寒門なく、下品に勢族なし」といわれた。南北朝時代になると官職内で名誉的な清流官職と濁流官職が貴族意識によって明確に分けられ、また家柄によって官職が固定される傾向が顕著となった。このような傾向は専制支配を貫徹しようとする皇帝の意向と対立するものであったため、官品の整理をおこなって清濁の区別をなくす努力が続けられた。しかし皇帝も貴族社会の解体そのものを望んでおらず、貴族社会の上位に皇帝権力を位置づけることでヒエラルキーを維持しようとしていたから、官職制度の根幹的な改変には至らず、官職の家柄による独占傾向を抑えることは出来なかった。\n" +
+"   6. ^ 1916年8月に復活された。\n" +
+"   7. ^ これはロシア革命に対するシベリア出兵において日中両軍が協力するという秘密条約である。\n" +
+"   8. ^ 1928年～30年に各国と交渉して関税自主権を回復し、関税を引き上げ、塩税と統一消費税をさだめて財源を確保した。アメリカとイギリスの銀行資本に「法幣」という紙幣を使用させ、秤量貨幣であった銀両を廃止した。さらにアメリカ政府に銀を売ってドルを外為資金として貯蓄した。これにより国際的な銀価格の中国の国内経済に対する影響が大幅に緩和された。このような経済政策を積極的に推進したのは国民政府財政部長の宋子文で、彼は孫文の妻宋慶齢の弟で、妹はのちに蒋介石と結婚した宋美齢であった。\n" +
+"   9. ^ 博巴あるいは波巴とはチベット人の自称。日本語に訳せばチベット人の人民政府という意味である。博巴と波巴はともに「ぽぱ」と読む。\n" +
+"  10. ^ 封建制度は殷代からおこなわれているが、殷代封建制についてはあまり明確なことはわからない。殷では封建がおこなわれている地域と方国と呼ばれる、外様あるいは異民族の国家の存在が知られ、殷を方国の連盟の盟主であり、封建された国々は殷の同族国家であるとする説もあるが詳しいことはわからない。周では一定の城市を基準とした邑に基づいた封建制が広汎におこなわれたと考えられているが、この邑制国家の実態も不明である。邑をポリス的な都市国家とみる見方から、邑と周辺農地である鄙が一緒になって（これを邑土という）、貴族による大土地所有であるとする見方もある。明らかであるのは邑を支配した貴族が長子相続を根幹とした血族共同体をもっていたということで、このような共同体に基づいた支配形態を宗法制度という。宗法制度については殷代にさかのぼる見方もあるが、広汎におこなわれたのは春秋あるいは戦国時代であったとする説もある。周の封建制を宗法制度の延長にあるものと捉え、封建儀礼を宗族への加盟儀礼の延長として捉える見方もある。\n" +
+"  11. ^ 中国古来より中国世界を9つの地方に分ける考え方が漠然と存在した。中国王朝の支配領域を「九州」といい、それがすなわち「天下」であった。ただし九州の概念は後漢時代にいたるまでははっきりしたものではなく一様でない。\n" +
+"  12. ^ 前漢成帝のときに州の監察権が御史中丞へ移行され、刺史が行政官となったという見方もあるが、後漢末期に刺史に軍事権が認められると、広域行政単位としての州はにわかに現実化したとみる見方もある。\n" +
+"  13. ^ このころの州を行政単位ではなく、軍管区のような概念上の管理単位であるとする見方も強い。\n" +
+"  14. ^ 北周の宇文護が創始した二十四軍制をもっていわゆる府兵制の成立と見做す見方があるがこれについては詳しいことはわからない。\n" +
+"  15. ^ 折衝府の置かれた州と非設置州では当然差異があったのであるが、唐代はほかに募兵に基づく行軍制度もおこなわれており、大規模な対外戦争の際にはおもに折衝府非設置州を中心として兵が集められた。唐後期にはこの募兵制が常態化することで節度使制度がおこなわれるようになった。\n" +
+"  16. ^ なお、史書からうかがえる外交記録と日本国内での銅鏡など出土品に記載された年号の問題などから、日本の古代王朝は特に南朝との外交関係を重視していたという見方が主流であるが、北朝との通交事実を明らかにしようという研究は続けられている。\n" +
+"  17. ^ これは都護府を通じて服属民族を部族別に自治権を与えて間接支配するもので、羈縻政策がおこなわれた地域では現地民の国家は否定された。このことは羈縻州の住民が自発的に中国王朝の文化を受け入れることを阻害したと考えられており、羈縻政策のおこなわれた地域では冊封のおこなわれた地域とは異なり、漢字や律令などの文化の共有はおこなわれず、唐の支配が後退すると、唐の文化もこの地域では衰退することになった。冊封された国々で唐の支配が後退したあとも漢字文化が存続したことと対照的である。\n";
+
+
+var korean =
+"한국의 역사\n" +
+"위키백과 ― 우리 모두의 백과사전.\n" +
+" 이 문서는 남, 북으로 분단된 1945년 이전의 한국에 대한 역사를 주로 기술하고 있다.\n" +
+"\n" +
+"한국의 역사 (연표)\n" +
+"한국의 선사 시대 (유적)\n" +
+"환인 · 환웅 (신시)\n" +
+"　	고조선 - 단군\n" +
+"진국\n" +
+"원\n" +
+"삼\n" +
+"국\n" +
+"|\n" +
+"삼\n" +
+"국\n" +
+"|\n" +
+"남\n" +
+"북\n" +
+"국\n" +
+"|\n" +
+"후\n" +
+"삼\n" +
+"국	삼한	옥\n" +
+"저	동\n" +
+"예	부\n" +
+"여\n" +
+"진\n" +
+"한	변\n" +
+"한	마\n" +
+"한\n" +
+"　	가\n" +
+"야	　\n" +
+"　\n" +
+"백\n" +
+"제\n" +
+"　\n" +
+"　	고\n" +
+"구\n" +
+"려	　	　\n" +
+"신\n" +
+"라	　	　\n" +
+"　	　\n" +
+"후\n" +
+"백\n" +
+"제	태\n" +
+"봉	발\n" +
+"해\n" +
+"　\n" +
+"고려\n" +
+"　\n" +
+"　\n" +
+"조선\n" +
+"　\n" +
+"대한제국\n" +
+"대한민국임시정부\n" +
+"일제 강점기 (조선총독부)\n" +
+"군정기\n" +
+"대한민국	조선민주주의\n" +
+"인민공화국\n" +
+"한국의 인물\n" +
+"한국의 역사는 구석기 시대 이후의 주로 한반도와 만주, 넓게는 동아시아 지역을 배경으로 발전되어 온 한국인의 역사이다.\n" +
+"목차 [숨기기]\n" +
+"1 선사 시대\n" +
+"1.1 유적에 의한 구분\n" +
+"1.2 문헌에 의한 구분\n" +
+"2 상고 시대 (B.C. 2333년 ~ A.D. 1세기)\n" +
+"2.1 고조선 시대\n" +
+"2.2 고조선 멸망 이후 여러나라의 성장\n" +
+"3 고대 시대 (A.D. 1세기~A.D. 900)\n" +
+"3.1 삼국시대\n" +
+"3.1.1 삼국시대 경제\n" +
+"3.1.2 삼국시대 정치\n" +
+"3.2 남북국시대\n" +
+"4 중세시대 (A.D. 918년 ~ A.D. 1392년)\n" +
+"4.1 고려의 정치\n" +
+"4.2 고려의 경제\n" +
+"4.3 고려의 사회\n" +
+"4.4 고려의 문화\n" +
+"5 근세시대 (A.D. 1392년 ~ A.D. 1506년)\n" +
+"5.1 초기 조선의 정치\n" +
+"5.2 초기 조선의 경제\n" +
+"5.3 초기 조선의 사회\n" +
+"5.4 초기 조선의 문화\n" +
+"6 근대 태동기 (A.D. 1506년 ~ A.D. 1907년)\n" +
+"6.1 후기 조선의 정치\n" +
+"6.2 후기 조선의 경제\n" +
+"6.3 후기 조선의 사회\n" +
+"6.4 후기 조선의 문화\n" +
+"7 근현대시대 (A.D. 1907년 ~ )\n" +
+"7.1 개괄\n" +
+"7.2 근대시대\n" +
+"7.3 현대시대\n" +
+"8 주석\n" +
+"9 같이 보기\n" +
+"10 참고문헌 및 링크\n" +
+"10.1 역사 일반\n" +
+"10.2 재단, 기타, 정부 기관\n" +
+"[편집]\n" +
+"선사 시대\n" +
+"\n" +
+"[편집]\n" +
+"유적에 의한 구분\n" +
+"한국의 구석기 시대(20만 년 이전 ~ 약 1만 년 전)\n" +
+"한국의 신석기 시대(약 1만 년 전 ~ 약 4천 년 전)\n" +
+"참고>> 웅기 부포리와 평양 만달리 유적, 통영 상노대도의 조개더미 최하층, 거창 임불리, 홍천 화화계리 유적 등을 중석기 유적지로 보는 사학자도 있다.\n" +
+"[편집]\n" +
+"문헌에 의한 구분\n" +
+"환국시대 [1](비공식)\n" +
+"신시[2] 또는 배달국 시대 [3](비공식)\n" +
+"[편집]\n" +
+"상고 시대 (B.C. 2333년 ~ A.D. 1세기)\n" +
+"\n" +
+"농경의 발달로 잉여 생산물이 생기고 청동기가 사용되면서 사유 재산 제도와 계급이 발생하였고, 그 결과, 부와 권력을 가진 족장(군장)이 출현하였다고 추측된다. 이 시기의 대표적인 유적으로 고인돌, 비파형 동검, 미송리식 토기 등이 있다. 부족장은 세력을 키워 주변 지역을 아우르고, 마침내 국가를 이룩하였다. 이 시기에 성립된 한국 최초의 국가가 고조선이다. 기원전 4세기경 철기가 보급되었고, 이후, 고조선은 철기 문화를 수용하면서 중국과 대립할 정도로 크게 발전하였으며, 만주와 한반도 각지에는 부여, 고구려, 옥저, 동예, 삼한 등 여러 나라가 성립될 수 있는 터전이 마련되었다.\n" +
+"[편집]\n" +
+"고조선 시대\n" +
+"단군조선\n" +
+"위만조선\n" +
+"조선 시대 이전에는 은나라에서 건너온 기자가 세운 기자조선이 정식 역사로서 인정되었으나, 일제강점기를 전후로 점차 부인되어 현재에는 대한민국과 조선민주주의인민공화국의 역사학계 모두 이를 공식적으로 인정하지 않고 있으며, 사학자들도 대체적으로 이 설을 부정한다.\n" +
+"[편집]\n" +
+"고조선 멸망 이후 여러나라의 성장\n" +
+"철기문명을 받아들인 각 나라들은 철기를 이용하여 농업을 발전시키면서도 독특한 사회 풍습을 유지하였다. 많은 소국들이 경쟁하는 가운데 일부는 다른 나라를 병합되었고, 다시 연맹 왕국으로 발전하여 중앙 집권 국가를 형성할 수 있는 기반을 마련하게 되었다.\n" +
+"부여: 북부여, 동부여, 졸본부여\n" +
+"옥저\n" +
+"동예\n" +
+"삼한:\n" +
+"마한\n" +
+"변한\n" +
+"진한\n" +
+"[편집]\n" +
+"고대 시대 (A.D. 1세기~A.D. 900)\n" +
+"\n" +
+"[편집]\n" +
+"삼국시대\n" +
+"고구려\n" +
+"백제\n" +
+"신라\n" +
+"삼국시대 초반은 고구려와 백제가 주도했으나 진흥왕 이후 국력이 막강해진 신라가 삼국시대 후기를 주도 했다.\n" +
+"[편집]\n" +
+"삼국시대 경제\n" +
+"삼국의 경제는 기본적으로 물물교환 경제를 못 벗어난 체제였다고 한다.[출처 필요]\n" +
+"삼국사기에는 신라가 수도에 시전을 세웠다는 기록이 있다.\n" +
+"[편집]\n" +
+"삼국시대 정치\n" +
+"삼국의 정치는 기본적으로 중앙집권체제를 토대로 한 전제왕권 또는 귀족정치였다.\n" +
+"[편집]\n" +
+"남북국시대\n" +
+"신라\n" +
+"발해\n" +
+"[편집]\n" +
+"중세시대 (A.D. 918년 ~ A.D. 1392년)\n" +
+"\n" +
+"한국사에서는 고려시대를 중세시대로 보고 있다.\n" +
+"[편집]\n" +
+"고려의 정치\n" +
+"고려는 새로운 통일 왕조로서 커다란 역사적 의의를 지닌다. 고려의 성립은 고대 사회에서 중세 사회로 이행하는 우리 역사의 내재적 발전을 의미한다. 신라말의 득난(6두품 세력) 출신 지식인과 호족 출신을 중심으로 성립한 고려는 골품 위주의 신라 사회보다 개방적이었고, 통치 체제도 과거제를 실시하는 등 효율성과 합리성이 강화되는 방향으로 정비되었다. 특히, 사상적으로 유교 정치 이념을 수용하여 고대적 성격을 벗어날 수 있었다.\n" +
+"고려 시대는 외적의 침입이 유달리 많았던 시기였다. 그러나 고려는 줄기찬 항쟁으로 이를 극복할 수 있었다. 12세기 후반에 무신들이 일으킨 무신정변은 종전의 문신 귀족 중심의 사회를 변화 시키는 계기가 되어 신분이 낮은 사람도 정치적으로 진출할 수 있었다.\n" +
+"이후, 무신 집권기와 원나라 간섭기를 지나 고려 후기에 이르러서는 새롭게 성장한 신진 사대부를 중심으로 성리학이 수용되어 합리적이고 민본적인 정치 이념이 성립되었고, 이에 따른 사회 개혁이 진전되었다.\n" +
+"[편집]\n" +
+"고려의 경제\n" +
+"고려는 후삼국 시기의 혼란을 극복하고 전시과 제도를 만드는 등 토지 제도를 정비하여 통치 체제의 토대를 확립하였다. 또, 수취 체제를 정비하면서 토지와 인구를 파악하기 위하여 양전 사업을 실시하고 호적을 작성하였다. 아울러 국가가 주도하여 산업을 재편하면서 경작지를 확대시키고, 상업과 수공업의 체제를 확립하여 안정된 경제 기반을 확보하였다.\n" +
+"농업에서는 기술의 발달로 농업 생산력이 증대되었고, 상업은 시전을 중심으로 도시 상업이 발달하면서 점차 지방에서도 상업 활동이 증가하였다. 수공업도 관청 수공업 중심에서 점차 사원이나 농민을 중심으로한 민간 수공업을 중심으로 발전해 갔다.\n" +
+"[편집]\n" +
+"고려의 사회\n" +
+"고려의 사회 신분은 귀족, 중류층, 양민, 천민으로 구성되었다. 고려 지배층의 핵심은 귀족이었다. 신분은 세습되는 것이 원칙이었고, 각 신분에는 그에 따른 역이 부과되었다. 그러나 그렇지 않은 경우도 있었는데, 향리로부터 문반직에 오르는 경우와 군인이 군공을 쌓아 무반으로 출세하는 경우를 들 수 있다.\n" +
+"백성의 대부분을 이루는 양민은 군현에 거주하는 농민으로, 조세, 공납, 역을 부담하였다. 향, 부곡, 소 같은 특수 행정 구역에 거주하는 백성은 조세 부담에 있어서 군현민보다 차별받았으나, 고려 후기 이후 특수 행정 구역은 일반 군현으로 바뀌어 갔다. 흉년이나 재해 등으로 어려움을 겪는 백성들의 생활을 안정시키기 위하여 국가는 의창과 상평창을 설치하고, 여러 가지 사회 복지 시책을 실시 하였다.\n" +
+"[편집]\n" +
+"고려의 문화\n" +
+"고려 시대에 해당하는 중세 문화는 고대 문화의 기반 위에서 조상들의 노력과 슬기가 보태져 새로운 양상을 보였다.\n" +
+"유교가 정치 이념으로 채택, 적용됨으로써 유교에 대한 인식이 확대 되었으며, 후기에는 성리학도 전래 되었다. 불교는 그 저변이 확대되어 생활 전반에 영향을 끼쳤다. 이런 가운데 불교 사상이 심화되고, 교종과 선종의 통합운동이 꾸준히 추진되었다.\n" +
+"중세의 예술은 귀족 중심의 우아하고 세련된 특징을 드러내고 있다. 건축과 조각에서는 고대의 성격을 벗어나 중세적 양식을 창출하였으며, 청자와 인쇄술은 세계적인 수준을 자랑하고 있다. 그림과 문학에서도 중세의 품격 높은 멋을 찾아 볼 수 있다.\n" +
+"[편집]\n" +
+"근세시대 (A.D. 1392년 ~ A.D. 1506년)\n" +
+"\n" +
+"한국사에서는 초기 조선 시대를 근세시대로 보고 있다.\n" +
+"[편집]\n" +
+"초기 조선의 정치\n" +
+"조선은 왕과 양반 관료들에 의하여 통치되었다. 왕은 최고 명령권자로서 통치 체제의 중심이었다. 조선 초기에는 고려 말에 성리학을 정치 이념으로 하면서 지방에서 성장한 신진 사대부들이 지배층이 되어 정국을 이끌어 나갔다. 그러나 15세기 말부터 새롭게 성장한 사림이 16세기 후반 이후 정국을 주도해 나가면서 학파를 중심으로 사림이 분열하여 붕당을 이루었다. 이후 여러 붕당 사이에 서로 비판하며 견제하는 붕당 정치를 전개하였다.\n" +
+"정치 구조는 권력의 집중을 방지하면서 행정의 효율성을 높이는 방향으로 정비되었다. 관리 등용에 혈연이나 지연보다 능력을 중시하였고, 언로를 개방하여 독점적인 권력 행사를 견제하였다. 아울러 육조를 중심으로 행정을 분담하여 효율성을 높이면서 정책의 협의나 집행 과정에서 유기적인 연결이 가능하도록 하였다. 조선은 고려에 비하여 한 단계 발전된 모습을 보여 주면서 중세 사회에서 벗어나 근세 사회로 나아갔다.\n" +
+"[편집]\n" +
+"초기 조선의 경제\n" +
+"조선은 고려 말기의 파탄된 국가 재정과 민생 문제를 해결하고 재정 확충과 민생 안정을 위한 방안으로 농본주의 경제 정책을 내세웠다. 특히 애민사상을 주장하는 왕도 정치 사상에서 민생 안정은 가장 먼저 해결해야 할 과제였다.\n" +
+"조선 건국을 주도하였던 신진 사대부들은 중농 정책을 표방하면서 농경지를 확대하고 농업 생산력을 증가시키며, 농민의 조세 부담을 줄여 농민들의 생활을 안정시키려 하였다. 그리하여 건국 초부터 토지 개간을 장려하고 양전 사업을 실시한 결과 고려 말 50여만 결이었던 경지 면적이 15세기 중엽에는 160여만 결로 증가하였다. 또한 농업 생산력을 향상시키기 위하여 새로운 농업 기술과 농기구를 개발하여 민간에 널리 보급하였다.\n" +
+"반면 상공업자가 허가 없이 마음대로 영업 활동을 벌이는 것을 규제하였는데, 이는 당시 검약한 생활을 강조하는 유교적인 경제관을 가진 사대부들이 물화의 수량과 종류를 정부가 통제하지 않고 자유 활동에 맡겨 두면 사치와 낭비가 조장되며 농업이 피폐하여 빈부의 격차가 커지게 된다고 생각하였기 때문이다. 더욱이 당시 사회에서는 직업적인 차별이 있어 상공업자들이 제대로 대우받지 못하였다.\n" +
+"[편집]\n" +
+"초기 조선의 사회\n" +
+"조선은 사회 신분을 양인과 천민으로 구분하는 양천 제도를 법제화하였다. 양인은 과거에 응시하고 벼슬길에 오를 수 있는 자유민으로서 조세, 국역 등의 의무를 지녔다. 천민은 비(非)자유민으로서 개인이나 국가에 소속되어 천역을 담당하였다.\n" +
+"양천 제도는 갑오개혁 이전까지 조선 사회를 지탱해 온 기본적인 신분 제도였다. 그러나 실제로는 양천 제도의 원칙에만 입각하여 운영되지는 않았다. 세월이 흐를수록 관직을 가진 사람을 의미하던 양반은 하나의 신분으로 굳어져 갔고, 양반 관료들을 보좌하던 중인도 신분층으로 정착되어 갔다. 그리하여 지배층인 양반과 피지배층인 상민 간의 차별을 두는 반상 제도가 일반화되고 양반, 중인, 상민, 천민의 신분 제도가 점차 정착되었다.\n" +
+"조선 시대는 엄격한 신분제 사회였으나 신분 이동이 가능하였다. 법적으로 양인 이상이면 누구나 과거에 응시하여 관직에 오를 수 있었고, 양반도 죄를 지으면 노비가 되거나 경제적으로 몰락하여 중인이나 상민이 되기도 하였다.\n" +
+"[편집]\n" +
+"초기 조선의 문화\n" +
+"조선 초기에는 괄목할 만한 민족적이면서 실용적인 성격의 학문이 발달하여 다른 시기보다 민족 문화의 발전이 크게 이루어졌다. 당시의 집권층은 민생 안정과 부국강병을 위하여 과학 기술과 실용적 학문을 중시하여, 한글이 창제되고 역사책을 비롯한 각 분야의 서적들이 출반되는 등 민족 문화 발전의 기반이 형성되었다.\n" +
+"성리학이 정착, 발달하여 전 사회에 큰 영향을 끼쳤고, 여러 갈래의 학파가 나타났다. 15세기 문화를 주도한 관학파 계열의 관료들과 학자들은 성리학을 지도 이념으로 내세웠으나 성리학 이외의 학문과 사상이라도 좋은 점이 있으면 받아들이는 융통성을 보였다. 불교는 정부에 의하여 정비되면서 위축되었으나 민간에서는 여전히 신앙의 대상으로 자리 잡고 있었다.\n" +
+"천문학, 의학 등 과학 기술에 있어서도 큰 발전을 이룩하여 생활에 응용되었고, 농업 기술은 크게 향상되어 농업 생산력을 증대시켰다.\n" +
+"예술 분야에서도 민족적 특색이 돋보이는 발전을 나타내었고, 사대부들의 검소하고 소박한 생활이 반영된 그림과 필체 및 자기 공예가 두드러졌다.\n" +
+"[편집]\n" +
+"근대 태동기 (A.D. 1506년 ~ A.D. 1907년)\n" +
+"\n" +
+"한국사에서는 후기 조선 시대를 근대 태동기로 보고 있다.\n" +
+"[편집]\n" +
+"후기 조선의 정치\n" +
+"숙종 때에 이르러 붕당 정치가 변질되고 그 폐단이 심화되면서 특정 붕당이 정권을 독점하는 일당 전제화의 추세가 대두되었다. 붕당 정치가 변질되자 정치 집단 간의 세력 균형이 무너지고 왕권 자체도 불안하게 되었다. 이에 영조와 정조는 특정 붕당의 권력 장악을 견제하기 위하여 탕평 정치를 추진하였다. 탕평 정치는 특정 권력 집단을 억제하고 왕권을 강화하려는 방향으로 진행되어 어느 정도 성과를 거두었지만, 붕당 정치의 폐단을 일소하지는 못하였다.\n" +
+"탕평 정치로 강화된 왕권을 순조 이후의 왕들이 제대로 행사하지 못하면서 왕실의 외척을 중심으로 한 소수 가문에 권력이 집중되고 정치 기강이 문란해지는 세도 정치가 전개되었다. 이로써 부정부패가 만연해지고 정부의 백성들에 대한 수탈이 심해졌다.\n" +
+"[편집]\n" +
+"후기 조선의 경제\n" +
+"임진왜란과 병자호란을 거치면서 농촌 사회는 심각하게 파괴되었다. 수많은 농민들이 전란 중에 죽거나 피난을 가고 경작지는 황폐화되었다. 이에 정부는 수취 체제를 개편하여 농촌 사회를 안정시키고 재정 기반을 확대하려 하였다. 그것은 전세 제도, 공납 제도, 군역 제도의 개편으로 나타났다.\n" +
+"서민들은 생산력을 높이기 위하여 농기구와 시비법을 개량하는 등 새로운 영농 방법을 추구하였고, 상품 작물을 재배하여 소득을 늘리려 하였다. 상인들도 상업 활동에 적극적으로 참여하여 대자본을 가진 상인들도 출현하였다. 수공업 생산도 활발해져 민간에서 생산 활동을 주도하여 갔다. 이러한 과정에서 자본 축적이 이루어지고, 지방의 상공업 활동이 활기를 띠었으며, 상업 도시가 출현하기에 이르렀다.\n" +
+"[편집]\n" +
+"후기 조선의 사회\n" +
+"조선 후기 사회는 사회 경제적 변화로 인하여 신분 변동이 활발해져 양반 중심의 신분 체제가 크게 흔들렸다. 붕당 정치가 날이 갈수록 변질되어 가면서 양반 상호 간에 일어난 정치적 갈등은 양반층의 분화을 불러왔다. 이러한 현상은 일당 전제화가 전개되면서 더욱 두드러지고 권력을 장악한 소수의 양반을 제외한 다수의 양반들이 몰락하는 계기가 되었다. 이렇게 양반 계층의 도태 현상이 날로 심화되어 가면서도 양반의 수는 늘어나고 상민과 노비의 숫자는 줄어드는 경향을 보였다. 이는 부를 축적한 농민들이나 해방된 노비들이 자신들의 지위를 높이기 위하여 또는 역의 부담을 모면하기 위하여 양반 신분을 사는 경우가 많았기 때문이다.\n" +
+"이러한 급격한 사회 변화에 대한 집권층의 자세는 극히 보수적이고 임기응변적이었다. 이에 계층 간의 갈등은 더욱 심화되어 갔으며, 19세기에 들어와 평등 사상과 내세 신앙을 주장한 로마 가톨릭이 유포되면서 백성들의 의식이 점차 높아져서[출처 필요] 크고 작은 봉기가 전국적으로 일어나게 되었다. 정부는 로마 가톨릭이 점차 교세가 확장되자 양반 중심의 신분 질서 부정과 왕권에 대한 도전으로 받아들여[출처 필요] 사교로 규정하고 탄압을 가하기에 이르렀다.\n" +
+"[편집]\n" +
+"후기 조선의 문화\n" +
+"임진왜란과 병자호란 이후 사회 각 분야의 변화와 함께 문화에서는 새로운 기운이 나타났다. 양반층 뿐만 아니라 중인층과 서민층도 문화의 한 주역으로 등장하면서 문화의 질적 변화와 함께 문화의 폭이 확대되었다.\n" +
+"학문에서는 성리학의 교조화와 형식화를 비판하며 실천성을 강조한 양명학을 받아들였으며 민생 안정과 부국강병을 목표로 하여 비판적이면서 실증적인 논리로 사회 개혁론을 제시한 실학이 대두되어 개혁 추진을 주장하기도 하였다.\n" +
+"천문학의 의학 등 각 분야의 기술적 성과들이 농업과 상업 등 산업 발전을 촉진하였다. 서양 문물의 유입도 이러한 발전을 가속화하는 데 이바지하였다.\n" +
+"예술 분야에서는 판소리, 탈품, 서민 음악 등 서민 문화가 크게 유행하였고, 백자 등 공예도 생활 공예가 중심이 되었다. 자연 경치와 삶을 소재로 하는 문예 풍토가 진작되어 문학과 서화에 큰 영향을 끼쳤다.\n" +
+"[편집]\n" +
+"근현대시대 (A.D. 1907년 ~ )\n" +
+"\n" +
+"[편집]\n" +
+"개괄\n" +
+"조선 사회는 안에서 성장하고 있던 근대적인 요소를 충분히 발전시키지 못한 채 19C 후반 제국주의 열강에 문호를 개방하였다. 이후 정부와 각계(各界), 각당(各堂), 각단체(各單體), 각층(各層), 각파(各派)에서는 근대화하려는 노력을 하였으나, 성공하지 못하였다.\n" +
+"개항 이후 조선은 서구 문물을 수용하고 새로운 경제 정책을 펼치면서 자주적인 근대화를 모색하였다. 그러나 일본과 청을 비롯한 외세의 경제 침략이 본격화 되면서, 이러한 노력은 큰 성과를 거두지 못했다.\n" +
+"개항 이후, 사회 개혁이 진행되면서 신분 제도가 폐지되고 평등 의식도 점차 성장하였다. 또, 외국과의 교류를 통해 외래 문물과 제도 등이 수용됨에 따라 전통적인 생활 모습에도 많은 변화가 생겨났다.\n" +
+"개항 이후 서양 과학 기술에 대한 관심이 높아지자, 전기, 철도, 같은 근대 기술과 서양 의술 등 각종 근대 문물이 들어왔다. 근대 시설은 일상생활을 편리하게 해 주었으나, 열강의 침략 목적에 이용되기도 하였다.\n" +
+"일제는 강압적인 식민 통치를 통하여 우리 민족을 지배하였다. 이에 맞서 우리 민족은 국내외에서 무장 독립 투쟁, 민족 실력 양성 운동, 독립 외교 활동 등을 벌여 일제에 줄기차게 저항하였다. 이러한 우리 민족의 투쟁과 연합군의 승리로 1945년 8월에 광복을 맞이하였다.\n" +
+"일제 강점기에는 일제의 경제적 침략으로 경제 발전이 왜곡되어, 우리 민족은 고통을 겪게 되었다. 광복 이후 일제의 식민 지배를 벗어나면서부터는 새로운 경제 발전의 계기를 마련할 수 있었다. 그러나 분단과 전쟁으로 인한 경제적 어려움도 대단히 컸다.\n" +
+"일제 강점기에는 국권을 되찾으려는 독립 운동이 줄기차게 일어났고, 다른 한편에서는 근대화를 위한 각계(各界), 각당(各堂), 각단체(各單體), 각층(各層), 각파(各派)에서는 근대화하려는 노력이 펼쳐졌다. 이러한 가운데 근대 자본주의 문명이 본격적으로 유입되어 전통 사회는 점차 근대 사회로 변모해 갔는데, 식민지 현실 아래에서 근대화는 왜곡될 수밖에 없었다.\n" +
+"일제는 국권을 탈취한 후에 동화와 차별의 이중 정책을 바탕으로 황국 신민화를 강력하게 추진하였다. 특히, 우리 민족의 독립 의지를 꺾으려고 우리의 역사와 문화를 왜곡하였다. 이에 맞서 우리의 전통과 문화를 지키려는 움직임이 일어났다.\n" +
+"그런데, 미∙소의 한반도 분할 정책과 좌∙우익 세력의 갈등으로 남북이 분단되어 통일 국가를 세우지 못하였다. 특히, 6∙25 전쟁을 겪으면서 분단은 더욱 고착화되고 남북 사이의 상호 불신이 깊어 갔다.\n" +
+"대한민국 정부 수립 이후, 민주주의가 정착되는 과정에서 많은 시련을 겪었다. 그러나 4∙19혁명과 5∙18민주화 운동, 6월 민주 항쟁 등으로 민주주의가 점차 발전하였다. 이와 함께, 냉전 체제가 해체되면서 민족 통일을 위한 노력도 계속 되고 있다.\n" +
+"1960년대 이후 한국 경제는 비약적인 성장을 일구어 냈다. 한국은 이제 가난한 농업 국가가 아닌, 세계적인 경제 대국으로 변모하고 있다.\n" +
+"광복 후에 한국은 많은 어려움 속에서도 경제 발전을 이룩하였는데, 이는 커다란 사회 변화를 가져왔다. 농업 사회에서 산업 사회로, 다시 정보화 사회로 발전하면서 사람들의 생활양식과 가치관도 많이 변하였다.1980년대에 진행된 민주화 운동으로 권위주의적 정치 문화가 점차 극복되고, 사회의 민주화도 꾸준히 이루어 졌다.\n" +
+"광복 이후에는 학문 활동이 활발해지고 교육의 기회가 크게 확대되었다. 그러나 미국을 비롯한 서구 문화가 급속하게 유입되면서 가치관의 혼란과 전통문화의 위축 현상을 가져오기도 하였다.\n" +
+"민주화와 더불어 문화의 다양화가 촉진되고, 반도체 등 몇몇 과학 기술 분야는 세계적인 수준까지 도달하였다. 한편, 현대 사회의 윤리와 생명 과학 기술의 발달 사이에서 빚어지는 갈등을 해소하려는 노력도 펼쳐지고 있다.\n" +
+"[편집]\n" +
+"근대시대\n" +
+"대한 제국\n" +
+"일제강점기 : 일본의 제국주의 세력이 한반도를 강제적으로 식민지로 삼은 시기로서, 무단 통치 시기, 문화 통치 시기, 전시 체계 시기로 나뉜다.\n" +
+"무단 통치 시기 : 조선을 영구히 통치하기 위해 조선 총독부를 설치하고, 군대를 파견하여 의병 활동을 억누르고 국내의 저항 세력을 무단으로 통치한 시기이다. 언론, 집회, 출판, 결사의 자유같은 기본권을 박탈하고, 독립운동을 무자비하게 탄압하였다. 또, 헌병 경찰과 헌병 보조원을 전국에 배치하고 즉결 처분권을 부여하여 한국인을 태형에 처하기도 했다. 토지조사령을 공포하여 식민지 수탈을 시작하였고, 회사령을 공포하여 국내의 자본 세력을 억압하고 일본 자본 세력의 편의를 봐주었다. 이 시기의 한국인 노동자는 극악한 환경과 저임금, 민족적 차별까지 받으며 혹사 하였다.\n" +
+"문화 통치 시기 : 3·1 운동이 발발하자 일제는 무단통치로는 조선을 효과적으로 지배할 수 없다는 판단하에, 친일파를 육성하는 문화정책을 펼친다. 이 문화정치는 가혹한 식민 통치를 은폐하려는 술책에 불과 했다. 헌병 경찰제를 보통 경찰제로 전환하였지만, 경찰력은 오히려 증강되었다. 이 들은 교육의 기회를 늘리고 자본 운용의 기회와 참정권의 기회등을 제공하겠다고 선전 하였으나 소수의 친일 분자를 육성하고, 민족 운동가들을 회유하여 민족을 기만하고 분열을 획책하였다.\n" +
+"전시 체계 시기 : 1930년대 일제는 대륙침략을 본격적으로 시작하면서 한반도를 대륙 침략의 병참기지로 삼았다. 또한, 1941년 일제가 미국의 진주만을 불법적으로 기습하자 태평양 전쟁이 발발하였다. 조선에서는 일제의 강제 징용으로 한국인 노동력이 착취 되었고, 학도 지원병 제도, 징병 제도 등을 실시하여 수많은 젊은이를 전쟁에 동원하였다. 또, 젊은 여성을 정신대라는 이름으로 강제 동원하여 군수 공장 등에서 혹사시켰으며, 그 중 일부는 전선으로 끌고 가 일본군 위안부로 삼는 만행을 저질렀다.\n" +
+"[편집]\n" +
+"현대시대\n" +
+"군정기 : 미국과 소련의 군대가 진주하여 한반도에 정부가 세워지기 이전까지의 시기\n" +
+"대한민국\n" +
+"제1공화국\n" +
+"한국전쟁\n" +
+"제2공화국\n" +
+"제3공화국\n" +
+"제4공화국 - 유신헌법시기. 종신 대통령제 채택\n" +
+"제5공화국\n" +
+"1. 정치 : 전두환 정부(군사 쿠데타에 의한 정부 - 12.12 사태) 시기. 대통령 간접선거제도 채택. 이 시기에는 민주화에 대한 무자비한 탄압이 자행되었으나, 광범위한 대중들의 1987년 6월 혁명으로 6월29선언(대통령 직접선거제도 공약)을 이끌어 내기도 하였다.\n" +
+"2. 경제 : 1960~70년대에 닦아온 중공업, 경공업 기반을 첨단공업 수준으로 이끌어 올린 시기이다. 이 시기의 한국 경제는 세계에서 유래 없을 정도로 빠르게 성장했으며, 국내 물가가 가장 안정된 시기였다.\n" +
+"3. 문화 : 1986년 서울 아시안 게임을 개최하였고, 1988년 서울 올림픽 게임을 유치하는 데 성공했다.\n" +
+"제6공화국\n" +
+"노태우 정권\n" +
+"문민정부\n" +
+"국민의 정부\n" +
+"참여정부\n" +
+"조선민주주의인민공화국\n" +
+"조선민주주의인민공화국의 역사\n" +
+"[편집]\n" +
+"주석\n" +
+"\n" +
+"↑ 삼국유사 - 동경제국대학 1904년 판본, 환단고기 - 1979년 복원본\n" +
+"↑ 동사 - 허목 숙종조, 규원사화 - 북애자 숙종원년\n" +
+"↑ 환단고기 - 1979년 복원본\n" +
+"[편집]\n" +
+"같이 보기\n" +
+"\n" +
+"중국의 역사\n" +
+"일본의 역사\n" +
+"민족사관\n" +
+"식민사관\n" +
+"[편집]\n" +
+"참고문헌 및 링크\n" +
+"\n" +
+"[편집]\n" +
+"역사 일반\n" +
+"국사 편찬 위원회 : 한국사에 관한 정보를 수집, 정리, 편찬하는 국가 연구 기관, 소장 자료, 논문, 저서 검색, 한국사 관련 연구 기관. 소장 자료, 논문, 저서 검색, 한국사 관련 안내\n" +
+"국사 전자 교과서 : 현직 교사들이 연구.감수하고, 국사편찬위원회가 지원하였다. 2007년 개정된 국사교과서의 내용이 아직 반영되지 않았다.\n" +
+"한국 역사 정보 시스템 : 한국사 연표, 한국사 기초 사전 및 신문 자료, 문헌 자료, 문집 등을 제공\n" +
+"한국학 중앙 연구원 : 한국 문화 및 한국학 여러 분햐에 관한 연구와 교육을 수행하는 연구 기관. 디지털 한국학 개발, 정보 광장, 전자 도서관, 전통 문화 등 수록\n" +
+"역사 문제 연구소 : 순수 민간 연구 단체(역사적 중립성이 의심됨), 근현대사 자료실, 간행물 자료, 한국사 학습 자료 등 수록\n" +
+"[편집]\n" +
+"재단, 기타, 정부 기관\n" +
+"고구려 연구재단 : 고구려사를 비롯한 중국의 역사 왜곡에 학술적으로 대응하기 위하여 2004年 설립된 법인. 고구려, 발해를 비롯한 동아시아 역사 관련 자료의 조사, 수집, 정리, 정보화 자료 제공. 동북아역사재단으로 편입되어 더이상 유용하지 않다.\n" +
+"국가 기록 영상관 : 대한 뉴스, 문화 기록 영화, 대통령 기록 영상 등 멀티미디어 역사 자료 제공\n" +
+"국가 문화 유산 종합 정보 서비스 : 국보, 보물, 사적, 명승, 천연 기념물 지정 종목별, 시대별, 지역별, 유형별, 유물 정보, 검색 서비스 제공\n" +
+"국가 지식 정보 통합 검색 시스템 : 정보 통신부 제공, 과학 기술, 정보 통신, 교육, 학술, 문화, 역사 등의 포괄적이고 연동적인 학술 데이터 검색\n" +
+"국가기록유산 : 국가적 기록유산의 원본과 원문 열람 서비스 제공\n";
+
+
+var persian =
+"تاریخ ایران پیش از اسلام\n" +
+"از ویکی‌پدیا، دانشنامهٔ آزاد.\n" +
+"تمدنهای باستانی آسیای غربی\n" +
+"بین‌النهرین، سومر، اکد، آشور، بابل\n" +
+"هیتی‌ها، لیدیه\n" +
+"ایلام، اورارتو، ماننا، ماد، هخامنشی\n" +
+"امپراتوری‌ها / شهرها\n" +
+"سومر: اوروک – اور – اریدو\n" +
+"کیش – لاگاش – نیپور – اکد\n" +
+"بابل – ایسین – کلدانی\n" +
+"آشور: آسور، نینوا، نوزی، نمرود\n" +
+"ایلامیان – اموری‌ها – شوش\n" +
+"هوری‌ها – میتانی\n" +
+"کاسی‌ها – اورارتو\n" +
+"گاهشماری\n" +
+"شاهان سومر\n" +
+"شاهان ایلام\n" +
+"شاهان آشور\n" +
+"شاهان بابل\n" +
+"شاهان ماد\n" +
+"شاهان هخامنشی\n" +
+"زبان\n" +
+"خط میخی\n" +
+"سومری – اکدی\n" +
+"ایلامی – هوری\n" +
+"اساطیر بین‌النهرین\n" +
+"انوما الیش\n" +
+"گیل گمش – مردوخ\n" +
+"نیبیرو\n" +
+"اگر بخواهیم تاریخ ایران پیش از اسلام را بررسی ‌‌کنیم باید از مردمانی که در دوران نوسنگی در فلات ایران زندگی می‌‌کردند نام ببریم. پیش از مهاجرت آریائیان به فلات ایران، اقوامی با تمدن‌های متفاوت در ایران می‌زیستند که آثار زیادی از آنها در نقاط مختلف فلات ایران مانند تمدن جیرفت (در کرمانِ کنونی) و شهر سوخته در سیستان، و تمدن ساکنان تمدن تپه سیلک (در کاشان)، تمدن اورارتو و ماننا (در آذربایجان)، تپه گیان نهاوند و تمدن کاسی‌ها (در لرستان امروز) بجای مانده است. اما تمدن این اقوام کم کم با ورود آریائیان، در فرهنگ و تمدن آنها حل شد.\n" +
+"برای بررسی تاریخ ایران پیش از اسلام باید از دیگر تمدنهای باستانی آسیای غربی نیز نام ببریم. شناخت اوضاع و رابطه این مناطق ایران در رابطه با تمدن‌های دیگر نظیر سومر - اکد، کلده - بابل - آشور، و غیره نیز مهم است.\n" +
+"فهرست مندرجات [مخفی شود]\n" +
+"۱ ایلامیان\n" +
+"۲ مهاجرت آریائیان به ایران\n" +
+"۳ مادها\n" +
+"۴ هخامنشیان\n" +
+"۵ سلوکیان\n" +
+"۶ اشکانیان\n" +
+"۷ ساسانیان\n" +
+"۸ منابع\n" +
+"۹ جستارهای وابسته\n" +
+"۱۰ پیوند به بیرون\n" +
+"[ویرایش]\n" +
+"ایلامیان\n" +
+"\n" +
+"ایلامیان یا عیلامی‌ها اقوامی بودند که از هزاره سوم پ. م. تا هزاره نخست پ. م. ، بر بخش بزرگی از مناطق جنوب و غرب ایران فرمانروایی داشتند. بر حسب تقسیمات جغرافیای سیاسی امروز، ایلام باستان سرزمین‌های خوزستان، فارس، ایلام و بخش‌هایی از استان‌های بوشهر، کرمان، لرستان و کردستان را شامل می‌شد.\n" +
+"آثار كشف ‌شده تمدن ایلامیان، در شوش نمایانگر تمدن شهری قابل توجهی است. تمدن ایلامیان از راه شهر سوخته در سیستان، با تمدن پیرامون رود سند هند و از راه شوش با تمدن سومر مربوط می‌شده است. ایلامیان نخستین مخترعان خط در ایران هستند.\n" +
+"به قدرت رسیدن حكومت ایلامیان و قدرت یافتن سلسله عیلامی پادشاهی اوان در شمال دشت خوزستان مهم ‌ترین رویداد سیاسی ایران در هزاره سوم پ. م. است. پادشاهی اَوان یکی از دودمان‌های ایلامی باستان در جنوب غربی ایران بود. پادشاهی آوان پس از شکوه و قدرت کوتیک ـ این شوشینک همچون امپراتوری اکد، ناگهان فرو پاشید؛ این فروپاشی و هرج و مرج در منطقه در پی تاخت و تاز گوتیان زاگرس نشین رخ داد. تا پیش از ورود مادها و پارسها حدود یك هزار سال تاریخ سرزمین ایران منحصر به تاریخ عیلام است.\n" +
+"سرزمین اصلی عیلام در شمال دشت خوزستان بوده. فرهنگ و تمدن عیلامی از شرق رودخانه دجله تا شهر سوخته زابل و از ارتفاعات زاگرس مركزی تا بوشهر اثر گذار بوده است. عیلامیان نه سامی نژادند و نه آریایی آنان ساكنان اوليه دشت خوزستان هستند.\n" +
+"[ویرایش]\n" +
+"مهاجرت آریائیان به ایران\n" +
+"\n" +
+"آریائیان، مردمانی از نژاد هند و اروپایی بودند که در شمال فلات ایران می‌‌زیستند. دلیل اصلی مهاجرت آنها مشخص نیست اما به نظر می‌‌رسد دشوار شدن شرایط آب و هوایی و کمبود چراگاه ها، از دلایل آن باشد. مهاجرت آریائیان به فلات ایران یک مهاجرت تدریجی بوده است که در پایان دوران نوسنگی (7000 سال پیش از میلاد) آغاز شد و تا 4000 پیش از میلاد ادامه داشته است.\n" +
+"نخستین آریایی‌هایی که به ایران آمدند شامل کاسی‌ها (کانتوها ـ کاشی‌ها)، لولوبیان و گوتیان بودند. کا‌سی‌ها تمدنی را پایه گذاری کردند که امروزه ما آن را بنام تمدن تپه سیلک می‌‌شناسیم. لولوبیان و گوتیان نیز در زاگرس مرکزی اقامت گزیدند که بعدها با آمدن مادها بخشی از آنها شدند. در حدود 5000 سال پیش از میلاد، مهاجرت بزرگ آریائیان به ایران آغاز شد و سه گروه بزرگ آریایی به ایران آمدند و هر یک در قسمتی از ایران سکنی گزیدند: مادها در شمال غربی ایران، پارس‌ها در قسمت جنوبی و پارت‌ها در حدود خراسان امروزی.\n" +
+"شاخه‌های قومِ ایرانی در نیمه‌های هزاره‌ی اول قبل از مسیح عبارت بوده‌اند از: باختریان در باختریه (تاجیکستان و شمالشرق افغانستانِ کنونی)، سکاهای هوم‌کار در سگائیه (شرقِ ازبکستانِ کنونی)، سُغدیان در سغدیه (جنوب ازبکستان کنونی)، خوارزمیان در خوارزمیه (شمال ازبکستان و شمالشرق ترکمنستانِ کنونی)، مرغزیان در مرغوه یا مرو (جنوبغرب ازبکستان و شرق ترکمستان کنونی)، داهه در مرکز ترکمستان کنونی، هَرَیویان در هَرَیوَه یا هرات (غرب افغانستان کنونی)، دِرَنگِیان در درنگیانه یا سیستان (غرب افغانستان کنونی و شرق ایران کنونی)، مکائیان در مکائیه یا مَک‌کُران (بلوچستانِ ایران و پاکستان کنونی)، هیرکانیان در هیرکانیا یا گرگان (جنوبغربِ ترکمنستان کنونی و شمال ایرانِ کنونی)، پَرتُوَه‌ئیان در پارتیه (شمالشرق ایران کنونی)، تپوریان در تپوریه یا تپورستان (گیلان و مازندران کنونی)، آریازَنتا در اسپدانه در مرکزِ ایرانِ کنونی، سکاهای تیزخود در الانیه یا اران (آذربایجان مستقل کنونی)، آترپاتیگان در آذربایجان ایرانِ کنونی، مادایَه در ماد (غرب ایرانِ کنونی)، کُردوخ در کردستانِ (چهارپاره‌شده‌ی) کنونی، پارسَی در پارس و کرمانِ کنونی، انشان در لرستان و شمال خوزستان کنونی. قبایلی که در تاریخ با نامهای مانناها، لولوبیان‌ها، گوتیان‌ها، و کاسی‌ها شناسانده شده‌اند و در مناطق غربی ایران ساکن بوده‌اند تیره‌هائی از شاخه‌های قوم ایرانی بوده‌اند که زمانی برای خودشان اتحادیه‌های قبایلی و امیرنشین داشته‌اند، و سپس در پادشاهی ماد ادغام شده‌اند.\n" +
+"مادها در ایران نزدیک 150 سال (708- 550 ق.م) هخامنشی‌ها کمی بیش از دویست سال (550-330 ق.م) اسکندر و سلوکی‌ها در حدود صد سال (330 -250 ق.م) اشکانیان قریب پانصد سال (250 ق.م – 226 م) و ساسانیان قریب چهار صد و سی سال (226-651 م) فرمانروایی داشتند.\n" +
+"[ویرایش]\n" +
+"مادها\n" +
+"\n" +
+"\n" +
+"\n" +
+"ماد در 675 پیش از میلاد\n" +
+"\n" +
+"\n" +
+"ماد در 600 پیش از میلاد\n" +
+"مادها قومی ایرانی بودند از تبار آریایی که در بخش غربی فلات ایران ساکن شدند. سرزمین مادها دربرگیرنده بخش غربی فلات ایران بود. سرزمین آذربایجان در شمال غربی فلات ایران را با نام ماد کوچک و بقیهٔ ناحیه زاگرس را با نام ماد بزرگ می‌شناختند. پایتخت ماد هگمتانه است آنها توانستند در اوایل قرن هفتم قبل از میلاد اولین دولت ایرانی را تأسیس کنند\n" +
+"پس از حملات شدید و خونین آشوریان به مناطق مادنشین، گروهی از بزرگان ماد گرد رهبری به نام دیاکو جمع شدند.\n" +
+"از پادشاهان بزرگ این دودمان هووخشتره بود که با دولت بابل متحد شد و سرانجام امپراتوری آشور را منقرض کرد و پایه‌های نخستین شاهنشاهی آریایی‌تباران در ایران را بنیاد نهاد.\n" +
+"دولت ماد در ۵۵۰ پیش از میلاد به دست کوروش منقرض شد و سلطنت ایران به پارسی‌ها منتقل گشت. در زمان داریوش بزرگ، امپراتوری هخامنشی به منتهای بزرگی خود رسید: از هند تا دریای آدریاتیک و از دریای عمان تا کوه‌های قفقاز.\n" +
+"[ویرایش]\n" +
+"هخامنشیان\n" +
+"\n" +
+"\n" +
+"\n" +
+"شاهنشاهی بزرگ هخامنشی در 330 ق.م.\n" +
+"هخامنشیان نخست پادشاهان بومی پارس و سپس انشان بودند ولی با شکستی که کوروش بزرگ بزرگ بر ایشتوویگو واپسین پادشاه ماد وارد ساخت و سپس فتح لیدیه و بابل پادشاهی هخامنشیان تبدیل به شاهنشاهی بزرگی شد. از این رو کوروش بزرگ را بنیادگذار شاهنشاهی هخامنشی می‌دانند.\n" +
+"در ۵۲۹ پ.م کوروش بزرگ پایه گذار دولت هخامنشی در جنگ‌های شمال شرقی ایران با سکاها، کشته شد. لشکرکشی کمبوجیه جانشین او به مصر آخرین رمق کشاورزان و مردم مغلوب را کشید و زمینه را برای شورشی همگانی فراهم کرد. داریوش بزرگ در کتیبهً بیستون می‌‌گوید: \" بعد از رفتن او (کمبوجیه) به مصر مردم از او برگشتند...\"\n" +
+"شورش‌ها بزرگ شد و حتی پارس زادگاه شاهان هخامنشی را نیز در برگرفت. داریوش در کتیبه بیستون شمه‌ای از این قیام‌ها را در بند دوم چنین نقل می‌کند: \" زمانی که من در بابل بودم این ایالات از من برگشتند: پارس، خوزستان، ماد، آشور، مصر، پارت خراسان (مرو، گوش) افغانستان (مکائیه).\" داریوش از 9 مهر ماه 522 تا 19 اسفند 520 ق.م به سرکوبی این جنبش‌ها مشغول بود.\n" +
+"جنگ‌های ایران و یونان در زمان داریوش آغاز شد. دولت هخامنشی سر انجام در 330 ق. م به دست اسکندر مقدونی منقرض گشت و ایران به دست سپاهیان او افتاد.\n" +
+"اسکندر سلسله هخامنشیان را نابود کرد، دارا را کشت ولی در حرکت خود به شرق همه جا به مقاومت‌های سخت برخورد، از جمله سغد و باکتریا یکی از سرداران جنگی او بنام سپتامان 327- 329 ق. م در راس جنبش همگانی مردم بیش از دو سال علیه مهاجم خارجی مبارزه دلاورانه کرد. در این ناحیه مکرر مردم علیه ساتراپهای اسکندر قیام کردند. گرچه سرانجام نیروهای مجهز و ورزیده اسکندر این جنبش‌ها را سرکوب کردند ولی از این تاریخ اسکندر ناچار روش خشونت آمیز خود را به نرمش و خوشخویی بدل کرد.\n" +
+"\n" +
+"ایران\n" +
+"تاریخ ایران\n" +
+"ایران پیش از آریایی‌ها	\n" +
+"تاریخ ایران پیش از اسلام	\n" +
+"    | دودمان‌ها و حکومت‌ها\n" +
+"ایلامیان\n" +
+"ماد\n" +
+"هخامنشیان\n" +
+"سلوکیان\n" +
+"اشکانیان\n" +
+"ساسانیان\n" +
+"تاریخ ایران پس از اسلام	\n" +
+"    | دودمان‌ها و حکومت‌ها\n" +
+"خلفای راشدین\n" +
+"امویان\n" +
+"عباسیان\n" +
+"ایران در دوران حکومت‌های محلی	\n" +
+"    | دودمان‌ها و حکومت‌ها\n" +
+"طاهریان\n" +
+"صفاریان\n" +
+"سامانیان\n" +
+"آل زیار\n" +
+"آل بویه\n" +
+"غزنویان\n" +
+"سلجوقیان\n" +
+"خوارزمشاهیان\n" +
+"ایران در دوره مغول	\n" +
+"    | دودمان‌ها و حکومت‌ها\n" +
+"ایلخانیان\n" +
+"ایران در دوران ملوک‌الطوایفی	\n" +
+"    | دودمان‌ها و حکومت‌ها\n" +
+"سربداران\n" +
+"تیموریان\n" +
+"مرعشیان\n" +
+"کیائیان\n" +
+"قراقویونلو\n" +
+"آق‌قویونلو\n" +
+"ایران در دوران حکومت‌های ملی	\n" +
+"    | دودمان‌ها و حکومت‌ها\n" +
+"صفوی\n" +
+"افشاریان\n" +
+"زند\n" +
+"قاجار\n" +
+"پهلوی\n" +
+"جمهوری اسلامی\n" +
+"موضوعی\n" +
+"تاریخ معاصر ایران\n" +
+"تاریخ مذاهب ایران\n" +
+"مهرپرستی\n" +
+"زرتشتی\n" +
+"تسنن\n" +
+"تصوف\n" +
+"تشیع\n" +
+"تاریخ اسلام\n" +
+"تاریخ زبان و ادبیات ایران\n" +
+"جغرافیای ایران\n" +
+"استان‌های تاریخی ایران\n" +
+"اقتصاد ایران\n" +
+"گاهشمار تاریخ ایران\n" +
+"پروژه ایران\n" +
+"[ویرایش]\n" +
+"سلوکیان\n" +
+"\n" +
+"\n" +
+"ایران در زمان سلوکیان (330 - 150 ق.م.)\n" +
+"پس از مرگ اسکندر (323 ق. م) فتوحاتش بین سردارانش تقسیم شد و بیشتر متصرفات آسیائی او که ایران هسته آن بود به سلوکوس اول رسید. به این ترتیب ایران تحت حکومت سلوکیان (330 - 150 ق.م.) در آمد. پس از مدتی پارت‌ها نفوذ خود را گسترش دادند و سرانجام توانستند سلوکیان را نابود و امپراتوری اشکانی را ایجاد کنند.\n" +
+"[ویرایش]\n" +
+"اشکانیان\n" +
+"\n" +
+"\n" +
+"\n" +
+"امپراتوری اشکانی 250 ق.م. 224 م.\n" +
+"اشکانیان (250 ق. م 224 م) که از تیره ایرانی پرنی و شاخه‌ای از طوایف وابسته به اتحادیه داهه از عشایر سکاهای حدود باختر بودند، از ایالت پارت که مشتمل بر خراسان فعلی بود برخاستند. نام سرزمین پارت در کتیبه‌های داریوش پرثوه آمده است که به زبان پارتی پهلوه می‌شود. چون پارتیان از اهل ایالت پهله بودند، از این جهت در نسبت به آن سرزمین ایشان را پهلوی نیز می‌‌توان خواند. ایالت پارتیها از مغرب به دامغان و سواحل جنوب شرقی دریای خزر و از شمال به ترکستان و از مشرق به رود تجن و از جنوب به کویر نمک و سیستان محدود می‌‌شد. قبایل پارتی در آغاز با قوم داهه که در مشرق دریای خزر می‌‌زیستند در یک جا سکونت داشتند و سپس از آنان جدا شده در ناحیه خراسان مسکن گزیدند.\n" +
+"این امپراتوری در دوره اقتدارش از رود فرات تا هندوکش و از کوه‌های قفقاز تا خلیج فارس توسعه یافت. در عهد اشکانی جنگ‌های ایران و روم آغاز شد. سلسله اشکانی در اثر اختلافات داخلی و جنگ‌های خارجی به تدریج ضعیف شد تا سر انجام به دست اردشیر اول ساسانی منقرض گردید.\n" +
+"[ویرایش]\n" +
+"ساسانیان\n" +
+"\n" +
+"\n" +
+"\n" +
+"شاهنشاهی ساسانی در سالهای ۲۲۴ تا ۶۵۱ م.\n" +
+"ساسانیان خاندان شاهنشاهی ایرانی در سالهای ۲۲۴ تا ۶۵۱ میلادی بودند. شاهنشاهان ساسانی که اصلیتشان از استان پارس بود بر بخش بزرگی از غرب قارهٔ آسیا چیرگی یافتند. پایتخت ساسانیان شهر تیسفون در نزدیکی بغداد در عراق امروزی بود.\n" +
+"سلسله اشکانی به دست اردشیر اول ساسانی منقرض گردید. وی سلسله ساسانیان را بنا نهاد که تا 652 میلادی در ایران ادامه یافت. دولت ساسانی حکومتی ملی و متکی به دین و تمدن ایرانی بود و قدرت بسیار زیادی کسب کرد. در این دوره نیز جنگ‌های ایران و روم ادامه یافت.\n" +
+"\n" +
+"در همين دوران مانی[1] (216 - 276 میلادی) به تبلیغ مذهب خود پرداخت. مانی پس از مسافرت به هند و آشنائی با مذهب بودائی سیستم جهان مذهبی مانوی خود را که التقاطی از مذهب زردشتی، بودائی و مسیحی و اسطوره بود با دقت تنظیم کرد و در کتاب \"شاهپورگان\" اصول آن‌ها را بیان و هنگام تاجگذاری شاپوراول به شاه هدیه کرد. مانی اصول اخلاقی خود را بر پایه فلسفی مثنویت: روشنائی و تاریکی که ازلی و ابدی هستند استوار نمود. در واقع این اصول) خودداری از قتل نفس حتی در مورد حیوانات، نخوردن می، دوری از زن و جمع نکردن مال (واکنش در مقابل زندگی پر تجمل و پر از لذت طبقات حاکم و عکس العمل منفی در برابر بحران اجتماعی پایان حکومت اشکانی و آغاز حکومت ساسانی است. شاپور و هرمزد، نشر چنین مذهبی را تجویز کردند، زیرا با وجود مخالفت آن با شهوت پرستی و غارتگری و سود جوئی طبقات حاکم، از جانبی مردم را به راه \"معنویت\" و \"آشتی‌خواهی\" سوق می‌‌داد و از جانب دیگر از قدرت مذهب زردشت می‌‌کاست.\n" +
+"جنبش معنوی مانی به سرعت در جهان آن روز گسترش یافت و تبدیل به نیروئی شد که با وجود جنبه منفی آن با هدف‌های شاهان و نجبا و پیشرفت جامعه آن روزی وفق نمی‌داد. پیشوایان زردتشتی و عیسوی که با هم دائما در نبرد بودند، متحد شدند و در دوران شاهی بهرام اول که شاهی تن آسا و شهوت پرست بود در جریان محاکمه او را محکوم و مقتول نمودند ( 276 میلادی). از آن پس مانی کشی آغاز شد و مغان مردم بسیاری را به نام زندک(زندیق) کشتند. مانویان درد و جانب شرق و غرب، در آسیای میانه تا سرحد چین و در غرب تا روم پراکنده شدند.\n" +
+"\n" +
+"امپراتوری پهناور ساسانی که از رود سند تا دریای سرخ وسعت داشت، در اثر مشکلات خارجی و داخلی ضعیف شد. آخرین پادشاه این سلسله یزدگرد سوم بود. در دوره او مسلمانان عرب به ایران حمله کردند و ایرانیان را در جنگ‌های قادسیه، مدائن، جلولاء و نهاوند شکست دادند و بدین ترتیب دولت ساسانی از میان رفت.\n" +
+"در پایان سده پنجم و آغاز قرن ششم میلادی جنبش بزرگی جامعه ایران را تکان داد که به صورت قیامی واقعی سی سال ( 24-494 م.) دوام آورد و تأثیر شگرفی در تکامل جامعه آن روزایران بخشید.\n" +
+"در چنین اوضاعی مزدک[2] پسر بامدادان به تبلیغ مذهب خود که گویند موسسش زردشت خورک بابوندس بوده، پرداخت. عقاید مزدک بر دو گانگی مانوی استوار است:\n" +
+"روشنائی دانا و تاریکی نادان، به عبارت دیگر نیکی با عقل و بدی جاهل، این دو نیرو با هم در نبردند و چون روشنائی داناست سرانجام پیروز خواهد شد.\n" +
+"اساس تعلیمات اجتماعی مزدک دو چیز است: یکی برابری و دیگری دادگری.\n" +
+"مردم بسیاری به سرعت پیرو مذهب مزدک شدند. جنبش مزدکی با قتل او و پیروانش به طرز وحشیانه‌ای سرکوب شد، اما افکار او اثر خود را حتی در قیام‌ها و جنبش‌های مردم ایران در دوران اسلام، باقی گذاشت.\n" +
+"[ویرایش]\n" +
+"منابع\n" +
+"\n" +
+"تاریخ ایران - دکتر خنجی\n" +
+"تاریخ اجتماعی ایران. مرتضی راوندی. ( جلد ۱ ) 1354\n" +
+"تاریخ ماد. ایگور میخائیلوویچ دیاکونوف. ترجمه کریم کشاورز، تهران: نشر امیرکبیر.\n" +
+"تاريخ ايران باستان. دياكونوف، ميخائيل ميخائيلوويچ. روحی ارباب. انتشارات علمی و فرهنگی، چاپ دوم 1380\n" +
+"سهم ایرانیان در پیدایش و آفرینش خط در جهان ،دکتر رکن الدین همایونفرخ، انتشارات اساطیر.\n" +
+"کمرون، جرج. ایران در سپیده دم تاریخ. ترجمه حسن انوشه. تهران، مرکز نشر دانشگاهی، 1379\n" +
+"تاریخ ایران از زمان باستان تا امروز، ا. آ. گرانتوسكی - م. آ. داندامایو، مترجم، كیخسرو كشاورزی، ناشر: مرواريد 1385\n" +
+"تاریخ ایران از عهد باستان تا قرن 18، پیگولووسکایا، ترجمه کریم کشاورز، تهران، 1353.\n" +
+"[ویرایش]\n" +
+"جستارهای وابسته\n" +
+"\n" +
+"ماد\n" +
+"کاسی\n" +
+"ایلامیان\n" +
+"تپه هگمتانه\n" +
+"تاریخ ایران\n" +
+"ایران پیش از آریایی‌ها\n" +
+"تمدنهای باستانی آسیای غربی\n" +
+"[ویرایش]\n" +
+"پیوند به بیرون\n" +
+"\n" +
+"ایران قبل از آریاها\n" +
+"ايران پيش از آريایی‌ها\n" +
+"تمدنهای قبل از آریایی ایران\n" +
+"ایران ازدیدگاه باستانشناسی\n" +
+"سنگ‌نبشته‌ی داریوش بزرگ در بیستون\n" +
+"شیوه آسیائی تولید در ایران\n" +
+"نیای اساطیری ایرانیان\n" +
+"قیام‌های ایرانیان در طول تاریخ\n" +
+"خلاصهٔ تاریخ ایران\n" +
+"شهر، شهرسازی و شهرنشينی در ايران پيش از اسلام\n" +
+"\n" +
+"[3]\n" +
+"[4]\n" +
+"[5]\n" +
+"[6]\n" +
+"[7]\n" +
+"\n" +
+"\n" +
+"\n" +
+" این نوشتار خُرد است. با گسترش آن به ویکی‌پدیا کمک کنید.\n" +
+"\n" +
+"این مقاله نیازمند ویکی‌سازی است. لطفاً با توجه به راهنمای ویرایش و شیوه‌نامه آن را تغییر دهید. در پایان، پس از ویکی‌سازی این الگوی پیامی را بردارید.\n";
+
+
+var source =
+("/*\n" +
+"  This is a version (aka dlmalloc) of malloc/free/realloc written by\n" +
+"  Doug Lea and released to the public domain.  Use, modify, and\n" +
+"  redistribute this code without permission or acknowledgement in any\n" +
+"  way you wish.  Send questions, comments, complaints, performance\n" +
+"  data, etc to dl@cs.oswego.edu\n" +
+"\n" +
+"* VERSION 2.7.2 Sat Aug 17 09:07:30 2002  Doug Lea  (dl at gee)\n" +
+"\n" +
+"   Note: There may be an updated version of this malloc obtainable at\n" +
+"           ftp://gee.cs.oswego.edu/pub/misc/malloc.c\n" +
+"         Check before installing!\n" +
+"\n" +
+"* Quickstart\n" +
+"\n" +
+"  This library is all in one file to simplify the most common usage:\n" +
+"  ftp it, compile it (-O), and link it into another program. All\n" +
+"  of the compile-time options default to reasonable values for use on\n" +
+"  most unix platforms. Compile -DWIN32 for reasonable defaults on windows.\n" +
+"  You might later want to step through various compile-time and dynamic\n" +
+"  tuning options.\n" +
+"\n" +
+"  For convenience, an include file for code using this malloc is at:\n" +
+"     ftp://gee.cs.oswego.edu/pub/misc/malloc-2.7.1.h\n" +
+"  You don't really need this .h file unless you call functions not\n" +
+"  defined in your system include files.  The .h file contains only the\n" +
+"  excerpts from this file needed for using this malloc on ANSI C/C++\n" +
+"  systems, so long as you haven't changed compile-time options about\n" +
+"  naming and tuning parameters.  If you do, then you can create your\n" +
+"  own malloc.h that does include all settings by cutting at the point\n" +
+"  indicated below.\n" +
+"\n" +
+"* Why use this malloc?\n" +
+"\n" +
+"  This is not the fastest, most space-conserving, most portable, or\n" +
+"  most tunable malloc ever written. However it is among the fastest\n" +
+"  while also being among the most space-conserving, portable and tunable.\n" +
+"  Consistent balance across these factors results in a good general-purpose\n" +
+"  allocator for malloc-intensive programs.\n" +
+"\n" +
+"  The main properties of the algorithms are:\n" +
+"  * For large (>= 512 bytes) requests, it is a pure best-fit allocator,\n" +
+"    with ties normally decided via FIFO (i.e. least recently used).\n" +
+"  * For small (<= 64 bytes by default) requests, it is a caching\n" +
+"    allocator, that maintains pools of quickly recycled chunks.\n" +
+"  * In between, and for combinations of large and small requests, it does\n" +
+"    the best it can trying to meet both goals at once.\n" +
+"  * For very large requests (>= 128KB by default), it relies on system\n" +
+"    memory mapping facilities, if supported.\n" +
+"\n" +
+"  For a longer but slightly out of date high-level description, see\n" +
+"     http://gee.cs.oswego.edu/dl/html/malloc.html\n" +
+"\n" +
+"  You may already by default be using a C library containing a malloc\n" +
+"  that is  based on some version of this malloc (for example in\n" +
+"  linux). You might still want to use the one in this file in order to\n" +
+"  customize settings or to avoid overheads associated with library\n" +
+"  versions.\n" +
+"\n" +
+"* Contents, described in more detail in \"description of public routines\" below.\n" +
+"\n" +
+"  Standard (ANSI/SVID/...)  functions:\n" +
+"    malloc(size_t n);\n" +
+"    calloc(size_t n_elements, size_t element_size);\n" +
+"    free(Void_t* p);\n" +
+"    realloc(Void_t* p, size_t n);\n" +
+"    memalign(size_t alignment, size_t n);\n" +
+"    valloc(size_t n);\n" +
+"    mallinfo()\n" +
+"    mallopt(int parameter_number, int parameter_value)\n" +
+"\n" +
+"  Additional functions:\n" +
+"    independent_calloc(size_t n_elements, size_t size, Void_t* chunks[]);\n" +
+"    independent_comalloc(size_t n_elements, size_t sizes[], Void_t* chunks[]);\n" +
+"    pvalloc(size_t n);\n" +
+"    cfree(Void_t* p);\n" +
+"    malloc_trim(size_t pad);\n" +
+"    malloc_usable_size(Void_t* p);\n" +
+"    malloc_stats();\n" +
+"\n" +
+"* Vital statistics:\n" +
+"\n" +
+"  Supported pointer representation:       4 or 8 bytes\n" +
+"  Supported size_t  representation:       4 or 8 bytes\n" +
+"       Note that size_t is allowed to be 4 bytes even if pointers are 8.\n" +
+"       You can adjust this by defining INTERNAL_SIZE_T\n" +
+"\n" +
+"  Alignment:                              2 * sizeof(size_t) (default)\n" +
+"       (i.e., 8 byte alignment with 4byte size_t). This suffices for\n" +
+"       nearly all current machines and C compilers. However, you can\n" +
+"       define MALLOC_ALIGNMENT to be wider than this if necessary.\n" +
+"\n" +
+"  Minimum overhead per allocated chunk:   4 or 8 bytes\n" +
+"       Each malloced chunk has a hidden word of overhead holding size\n" +
+"       and status information.\n" +
+"\n" +
+"  Minimum allocated size: 4-byte ptrs:  16 bytes    (including 4 overhead)\n" +
+"                          8-byte ptrs:  24/32 bytes (including, 4/8 overhead)\n" +
+"\n" +
+"       When a chunk is freed, 12 (for 4byte ptrs) or 20 (for 8 byte\n" +
+"       ptrs but 4 byte size) or 24 (for 8/8) additional bytes are\n" +
+"       needed; 4 (8) for a trailing size field and 8 (16) bytes for\n" +
+"       free list pointers. Thus, the minimum allocatable size is\n" +
+"       16/24/32 bytes.\n" +
+"\n" +
+"       Even a request for zero bytes (i.e., malloc(0)) returns a\n" +
+"       pointer to something of the minimum allocatable size.\n" +
+"\n" +
+"       The maximum overhead wastage (i.e., number of extra bytes\n" +
+"       allocated than were requested in malloc) is less than or equal\n" +
+"       to the minimum size, except for requests >= mmap_threshold that\n" +
+"       are serviced via mmap(), where the worst case wastage is 2 *\n" +
+"       sizeof(size_t) bytes plus the remainder from a system page (the\n" +
+"       minimal mmap unit); typically 4096 or 8192 bytes.\n" +
+"\n" +
+"  Maximum allocated size:  4-byte size_t: 2^32 minus about two pages\n" +
+"                           8-byte size_t: 2^64 minus about two pages\n" +
+"\n" +
+"       It is assumed that (possibly signed) size_t values suffice to\n" +
+"       represent chunk sizes. `Possibly signed' is due to the fact\n" +
+"       that `size_t' may be defined on a system as either a signed or\n" +
+"       an unsigned type. The ISO C standard says that it must be\n" +
+"       unsigned, but a few systems are known not to adhere to this.\n" +
+"       Additionally, even when size_t is unsigned, sbrk (which is by\n" +
+"       default used to obtain memory from system) accepts signed\n" +
+"       arguments, and may not be able to handle size_t-wide arguments\n" +
+"       with negative sign bit.  Generally, values that would\n" +
+"       appear as negative after accounting for overhead and alignment\n" +
+"       are supported only via mmap(), which does not have this\n" +
+"       limitation.\n" +
+"\n" +
+"       Requests for sizes outside the allowed range will perform an optional\n" +
+"       failure action and then return null. (Requests may also\n" +
+"       also fail because a system is out of memory.)\n" +
+"\n" +
+"  Thread-safety: NOT thread-safe unless USE_MALLOC_LOCK defined\n" +
+"\n" +
+"       When USE_MALLOC_LOCK is defined, wrappers are created to\n" +
+"       surround every public call with either a pthread mutex or\n" +
+"       a win32 spinlock (depending on WIN32). This is not\n" +
+"       especially fast, and can be a major bottleneck.\n" +
+"       It is designed only to provide minimal protection\n" +
+"       in concurrent environments, and to provide a basis for\n" +
+"       extensions.  If you are using malloc in a concurrent program,\n" +
+"       you would be far better off obtaining ptmalloc, which is\n" +
+"       derived from a version of this malloc, and is well-tuned for\n" +
+"       concurrent programs. (See http://www.malloc.de) Note that\n" +
+"       even when USE_MALLOC_LOCK is defined, you can can guarantee\n" +
+"       full thread-safety only if no threads acquire memory through\n" +
+"       direct calls to MORECORE or other system-level allocators.\n" +
+"\n" +
+"  Compliance: I believe it is compliant with the 1997 Single Unix Specification\n" +
+"       (See http://www.opennc.org). Also SVID/XPG, ANSI C, and probably\n" +
+"       others as well.\n" +
+"\n" +
+"* Synopsis of compile-time options:\n" +
+"\n" +
+"    People have reported using previous versions of this malloc on all\n" +
+"    versions of Unix, sometimes by tweaking some of the defines\n" +
+"    below. It has been tested most extensively on Solaris and\n" +
+"    Linux. It is also reported to work on WIN32 platforms.\n" +
+"    People also report using it in stand-alone embedded systems.\n" +
+"\n" +
+"    The implementation is in straight, hand-tuned ANSI C.  It is not\n" +
+"    at all modular. (Sorry!)  It uses a lot of macros.  To be at all\n" +
+"    usable, this code should be compiled using an optimizing compiler\n" +
+"    (for example gcc -O3) that can simplify expressions and control\n" +
+"    paths. (FAQ: some macros import variables as arguments rather than\n" +
+"    declare locals because people reported that some debuggers\n" +
+"    otherwise get confused.)\n" +
+"\n" +
+"    OPTION                     DEFAULT VALUE\n" +
+"\n" +
+"    Compilation Environment options:\n" +
+"\n" +
+"    __STD_C                    derived from C compiler defines\n" +
+"    WIN32                      NOT defined\n" +
+"    HAVE_MEMCPY                defined\n" +
+"    USE_MEMCPY                 1 if HAVE_MEMCPY is defined\n" +
+"    HAVE_MMAP                  defined as 1\n" +
+"    MMAP_CLEARS                1\n" +
+"    HAVE_MREMAP                0 unless linux defined\n" +
+"    malloc_getpagesize         derived from system #includes, or 4096 if not\n" +
+"    HAVE_USR_INCLUDE_MALLOC_H  NOT defined\n" +
+"    LACKS_UNISTD_H             NOT defined unless WIN32\n" +
+"    LACKS_SYS_PARAM_H          NOT defined unless WIN32\n" +
+"    LACKS_SYS_MMAN_H           NOT defined unless WIN32\n" +
+"    LACKS_FCNTL_H              NOT defined\n" +
+"\n" +
+"    Changing default word sizes:\n" +
+"\n" +
+"    INTERNAL_SIZE_T            size_t\n" +
+"    MALLOC_ALIGNMENT           2 * sizeof(INTERNAL_SIZE_T)\n" +
+"    PTR_UINT                   unsigned long\n" +
+"    CHUNK_SIZE_T               unsigned long\n" +
+"\n" +
+"    Configuration and functionality options:\n" +
+"\n" +
+"    USE_DL_PREFIX              NOT defined\n" +
+"    USE_PUBLIC_MALLOC_WRAPPERS NOT defined\n" +
+"    USE_MALLOC_LOCK            NOT defined\n" +
+"    DEBUG                      NOT defined\n" +
+"    REALLOC_ZERO_BYTES_FREES   NOT defined\n" +
+"    MALLOC_FAILURE_ACTION      errno = ENOMEM, if __STD_C defined, else no-op\n" +
+"    TRIM_FASTBINS              0\n" +
+"    FIRST_SORTED_BIN_SIZE      512\n" +
+"\n" +
+"    Options for customizing MORECORE:\n" +
+"\n" +
+"    MORECORE                   sbrk\n" +
+"    MORECORE_CONTIGUOUS        1\n" +
+"    MORECORE_CANNOT_TRIM       NOT defined\n" +
+"    MMAP_AS_MORECORE_SIZE      (1024 * 1024)\n" +
+"\n" +
+"    Tuning options that are also dynamically changeable via mallopt:\n" +
+"\n" +
+"    DEFAULT_MXFAST             64\n" +
+"    DEFAULT_TRIM_THRESHOLD     256 * 1024\n" +
+"    DEFAULT_TOP_PAD            0\n" +
+"    DEFAULT_MMAP_THRESHOLD     256 * 1024\n" +
+"    DEFAULT_MMAP_MAX           65536\n" +
+"\n" +
+"    There are several other #defined constants and macros that you\n" +
+"    probably don't want to touch unless you are extending or adapting malloc.\n" +
+"*/\n" +
+"\n" +
+"#define MORECORE_CONTIGUOUS 0\n" +
+"#define MORECORE_CANNOT_TRIM 1\n" +
+"#define MALLOC_FAILURE_ACTION abort()\n" +
+"\n" +
+"\n" +
+"namespace khtml {\n" +
+"\n" +
+"#ifndef NDEBUG\n" +
+"\n" +
+"// In debugging builds, use the system malloc for its debugging features.\n" +
+"\n" +
+"void *main_thread_malloc(size_t n)\n" +
+"{\n" +
+"    assert(pthread_main_np());\n" +
+"    return malloc(n);\n" +
+"}\n" +
+"\n" +
+"void *main_thread_calloc(size_t n_elements, size_t element_size)\n" +
+"{\n" +
+"    assert(pthread_main_np());\n" +
+"    return calloc(n_elements, element_size);\n" +
+"}\n" +
+"\n" +
+"void main_thread_free(void* p)\n" +
+"{\n" +
+"    // it's ok to main_thread_free on a non-main thread - the actual\n" +
+"    // free will be scheduled on the main thread in that case.\n" +
+"    free(p);\n" +
+"}\n" +
+"\n" +
+"void *main_thread_realloc(void* p, size_t n)\n" +
+"{\n" +
+"    assert(pthread_main_np());\n" +
+"    return realloc(p, n);\n" +
+"}\n" +
+"\n" +
+"#else\n" +
+"\n" +
+"/*\n" +
+"  WIN32 sets up defaults for MS environment and compilers.\n" +
+"  Otherwise defaults are for unix.\n" +
+"*/\n" +
+"\n" +
+"/* #define WIN32 */\n" +
+"\n" +
+"#ifdef WIN32\n" +
+"\n" +
+"#define WIN32_LEAN_AND_MEAN\n" +
+"#include <windows.h>\n" +
+"\n" +
+"/* Win32 doesn't supply or need the following headers */\n" +
+"#define LACKS_UNISTD_H\n" +
+"#define LACKS_SYS_PARAM_H\n" +
+"#define LACKS_SYS_MMAN_H\n" +
+"\n" +
+"/* Use the supplied emulation of sbrk */\n" +
+"#define MORECORE sbrk\n" +
+"#define MORECORE_CONTIGUOUS 1\n" +
+"#define MORECORE_FAILURE    ((void*)(-1))\n" +
+"\n" +
+"/* Use the supplied emulation of mmap and munmap */\n" +
+"#define HAVE_MMAP 1\n" +
+"#define MUNMAP_FAILURE  (-1)\n" +
+"#define MMAP_CLEARS 1\n" +
+"\n" +
+"/* These values don't really matter in windows mmap emulation */\n" +
+"#define MAP_PRIVATE 1\n" +
+"#define MAP_ANONYMOUS 2\n" +
+"#define PROT_READ 1\n" +
+"#define PROT_WRITE 2\n" +
+"\n" +
+"/* Emulation functions defined at the end of this file */\n" +
+"\n" +
+"/* If USE_MALLOC_LOCK, use supplied critical-section-based lock functions */\n" +
+"#ifdef USE_MALLOC_LOCK\n") +
+("static int slwait(int *sl);\n" +
+"static int slrelease(int *sl);\n" +
+"#endif\n" +
+"\n" +
+"static long getpagesize(void);\n" +
+"static long getregionsize(void);\n" +
+"static void *sbrk(long size);\n" +
+"static void *mmap(void *ptr, long size, long prot, long type, long handle, long arg);\n" +
+"static long munmap(void *ptr, long size);\n" +
+"\n" +
+"static void vminfo (unsigned long*free, unsigned long*reserved, unsigned long*committed);\n" +
+"static int cpuinfo (int whole, unsigned long*kernel, unsigned long*user);\n" +
+"\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  __STD_C should be nonzero if using ANSI-standard C compiler, a C++\n" +
+"  compiler, or a C compiler sufficiently close to ANSI to get away\n" +
+"  with it.\n" +
+"*/\n" +
+"\n" +
+"#ifndef __STD_C\n" +
+"#if defined(__STDC__) || defined(_cplusplus)\n" +
+"#define __STD_C     1\n" +
+"#else\n" +
+"#define __STD_C     0\n" +
+"#endif\n" +
+"#endif /*__STD_C*/\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  Void_t* is the pointer type that malloc should say it returns\n" +
+"*/\n" +
+"\n" +
+"#ifndef Void_t\n" +
+"#if (__STD_C || defined(WIN32))\n" +
+"#define Void_t      void\n" +
+"#else\n" +
+"#define Void_t      char\n" +
+"#endif\n" +
+"#endif /*Void_t*/\n" +
+"\n" +
+"#if __STD_C\n" +
+"#include <stddef.h>   /* for size_t */\n" +
+"#else\n" +
+"#include <sys/types.h>\n" +
+"#endif\n" +
+"\n" +
+"/* define LACKS_UNISTD_H if your system does not have a <unistd.h>. */\n" +
+"\n" +
+"/* #define  LACKS_UNISTD_H */\n" +
+"\n" +
+"#ifndef LACKS_UNISTD_H\n" +
+"#include <unistd.h>\n" +
+"#endif\n" +
+"\n" +
+"/* define LACKS_SYS_PARAM_H if your system does not have a <sys/param.h>. */\n" +
+"\n" +
+"/* #define  LACKS_SYS_PARAM_H */\n" +
+"\n" +
+"\n" +
+"#include <stdio.h>    /* needed for malloc_stats */\n" +
+"#include <errno.h>    /* needed for optional MALLOC_FAILURE_ACTION */\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  Debugging:\n" +
+"\n" +
+"  Because freed chunks may be overwritten with bookkeeping fields, this\n" +
+"  malloc will often die when freed memory is overwritten by user\n" +
+"  programs.  This can be very effective (albeit in an annoying way)\n" +
+"  in helping track down dangling pointers.\n" +
+"\n" +
+"  If you compile with -DDEBUG, a number of assertion checks are\n" +
+"  enabled that will catch more memory errors. You probably won't be\n" +
+"  able to make much sense of the actual assertion errors, but they\n" +
+"  should help you locate incorrectly overwritten memory.  The\n" +
+"  checking is fairly extensive, and will slow down execution\n" +
+"  noticeably. Calling malloc_stats or mallinfo with DEBUG set will\n" +
+"  attempt to check every non-mmapped allocated and free chunk in the\n" +
+"  course of computing the summmaries. (By nature, mmapped regions\n" +
+"  cannot be checked very much automatically.)\n" +
+"\n" +
+"  Setting DEBUG may also be helpful if you are trying to modify\n" +
+"  this code. The assertions in the check routines spell out in more\n" +
+"  detail the assumptions and invariants underlying the algorithms.\n" +
+"\n" +
+"  Setting DEBUG does NOT provide an automated mechanism for checking\n" +
+"  that all accesses to malloced memory stay within their\n" +
+"  bounds. However, there are several add-ons and adaptations of this\n" +
+"  or other mallocs available that do this.\n" +
+"*/\n" +
+"\n" +
+"/*\n" +
+"  The unsigned integer type used for comparing any two chunk sizes.\n" +
+"  This should be at least as wide as size_t, but should not be signed.\n" +
+"*/\n" +
+"\n" +
+"#ifndef CHUNK_SIZE_T\n" +
+"#define CHUNK_SIZE_T unsigned long\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  The unsigned integer type used to hold addresses when they are are\n" +
+"  manipulated as integers. Except that it is not defined on all\n" +
+"  systems, intptr_t would suffice.\n" +
+"*/\n" +
+"#ifndef PTR_UINT\n" +
+"#define PTR_UINT unsigned long\n" +
+"#endif\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  INTERNAL_SIZE_T is the word-size used for internal bookkeeping\n" +
+"  of chunk sizes.\n" +
+"\n" +
+"  The default version is the same as size_t.\n" +
+"\n" +
+"  While not strictly necessary, it is best to define this as an\n" +
+"  unsigned type, even if size_t is a signed type. This may avoid some\n" +
+"  artificial size limitations on some systems.\n" +
+"\n" +
+"  On a 64-bit machine, you may be able to reduce malloc overhead by\n" +
+"  defining INTERNAL_SIZE_T to be a 32 bit `unsigned int' at the\n" +
+"  expense of not being able to handle more than 2^32 of malloced\n" +
+"  space. If this limitation is acceptable, you are encouraged to set\n" +
+"  this unless you are on a platform requiring 16byte alignments. In\n" +
+"  this case the alignment requirements turn out to negate any\n" +
+"  potential advantages of decreasing size_t word size.\n" +
+"\n" +
+"  Implementors: Beware of the possible combinations of:\n" +
+"     - INTERNAL_SIZE_T might be signed or unsigned, might be 32 or 64 bits,\n" +
+"       and might be the same width as int or as long\n" +
+"     - size_t might have different width and signedness as INTERNAL_SIZE_T\n" +
+"     - int and long might be 32 or 64 bits, and might be the same width\n" +
+"  To deal with this, most comparisons and difference computations\n" +
+"  among INTERNAL_SIZE_Ts should cast them to CHUNK_SIZE_T, being\n" +
+"  aware of the fact that casting an unsigned int to a wider long does\n" +
+"  not sign-extend. (This also makes checking for negative numbers\n" +
+"  awkward.) Some of these casts result in harmless compiler warnings\n" +
+"  on some systems.\n" +
+"*/\n" +
+"\n" +
+"#ifndef INTERNAL_SIZE_T\n" +
+"#define INTERNAL_SIZE_T size_t\n" +
+"#endif\n" +
+"\n" +
+"/* The corresponding word size */\n" +
+"#define SIZE_SZ                (sizeof(INTERNAL_SIZE_T))\n" +
+"\n" +
+"\n") +
+("\n" +
+"/*\n" +
+"  MALLOC_ALIGNMENT is the minimum alignment for malloc'ed chunks.\n" +
+"  It must be a power of two at least 2 * SIZE_SZ, even on machines\n" +
+"  for which smaller alignments would suffice. It may be defined as\n" +
+"  larger than this though. Note however that code and data structures\n" +
+"  are optimized for the case of 8-byte alignment.\n" +
+"*/\n" +
+"\n" +
+"\n" +
+"#ifndef MALLOC_ALIGNMENT\n" +
+"#define MALLOC_ALIGNMENT       (2 * SIZE_SZ)\n" +
+"#endif\n" +
+"\n" +
+"/* The corresponding bit mask value */\n" +
+"#define MALLOC_ALIGN_MASK      (MALLOC_ALIGNMENT - 1)\n" +
+"\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  REALLOC_ZERO_BYTES_FREES should be set if a call to\n" +
+"  realloc with zero bytes should be the same as a call to free.\n" +
+"  Some people think it should. Otherwise, since this malloc\n" +
+"  returns a unique pointer for malloc(0), so does realloc(p, 0).\n" +
+"*/\n" +
+"\n" +
+"/*   #define REALLOC_ZERO_BYTES_FREES */\n" +
+"\n" +
+"/*\n" +
+"  TRIM_FASTBINS controls whether free() of a very small chunk can\n" +
+"  immediately lead to trimming. Setting to true (1) can reduce memory\n" +
+"  footprint, but will almost always slow down programs that use a lot\n" +
+"  of small chunks.\n" +
+"\n" +
+"  Define this only if you are willing to give up some speed to more\n" +
+"  aggressively reduce system-level memory footprint when releasing\n" +
+"  memory in programs that use many small chunks.  You can get\n" +
+"  essentially the same effect by setting MXFAST to 0, but this can\n" +
+"  lead to even greater slowdowns in programs using many small chunks.\n" +
+"  TRIM_FASTBINS is an in-between compile-time option, that disables\n" +
+"  only those chunks bordering topmost memory from being placed in\n" +
+"  fastbins.\n" +
+"*/\n" +
+"\n" +
+"#ifndef TRIM_FASTBINS\n" +
+"#define TRIM_FASTBINS  0\n" +
+"#endif\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  USE_DL_PREFIX will prefix all public routines with the string 'dl'.\n" +
+"  This is necessary when you only want to use this malloc in one part\n" +
+"  of a program, using your regular system malloc elsewhere.\n" +
+"*/\n" +
+"\n" +
+"#define USE_DL_PREFIX\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  USE_MALLOC_LOCK causes wrapper functions to surround each\n" +
+"  callable routine with pthread mutex lock/unlock.\n" +
+"\n" +
+"  USE_MALLOC_LOCK forces USE_PUBLIC_MALLOC_WRAPPERS to be defined\n" +
+"*/\n" +
+"\n" +
+"\n" +
+"/* #define USE_MALLOC_LOCK */\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  If USE_PUBLIC_MALLOC_WRAPPERS is defined, every public routine is\n" +
+"  actually a wrapper function that first calls MALLOC_PREACTION, then\n" +
+"  calls the internal routine, and follows it with\n" +
+"  MALLOC_POSTACTION. This is needed for locking, but you can also use\n" +
+"  this, without USE_MALLOC_LOCK, for purposes of interception,\n" +
+"  instrumentation, etc. It is a sad fact that using wrappers often\n" +
+"  noticeably degrades performance of malloc-intensive programs.\n" +
+"*/\n" +
+"\n" +
+"#ifdef USE_MALLOC_LOCK\n" +
+"#define USE_PUBLIC_MALLOC_WRAPPERS\n" +
+"#else\n" +
+"/* #define USE_PUBLIC_MALLOC_WRAPPERS */\n" +
+"#endif\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"   Two-phase name translation.\n" +
+"   All of the actual routines are given mangled names.\n" +
+"   When wrappers are used, they become the public callable versions.\n" +
+"   When DL_PREFIX is used, the callable names are prefixed.\n" +
+"*/\n" +
+"\n" +
+"#ifndef USE_PUBLIC_MALLOC_WRAPPERS\n" +
+"#define cALLOc      public_cALLOc\n" +
+"#define fREe        public_fREe\n" +
+"#define cFREe       public_cFREe\n" +
+"#define mALLOc      public_mALLOc\n" +
+"#define mEMALIGn    public_mEMALIGn\n" +
+"#define rEALLOc     public_rEALLOc\n" +
+"#define vALLOc      public_vALLOc\n" +
+"#define pVALLOc     public_pVALLOc\n" +
+"#define mALLINFo    public_mALLINFo\n" +
+"#define mALLOPt     public_mALLOPt\n" +
+"#define mTRIm       public_mTRIm\n" +
+"#define mSTATs      public_mSTATs\n" +
+"#define mUSABLe     public_mUSABLe\n" +
+"#define iCALLOc     public_iCALLOc\n" +
+"#define iCOMALLOc   public_iCOMALLOc\n" +
+"#endif\n" +
+"\n" +
+"#ifdef USE_DL_PREFIX\n" +
+"#define public_cALLOc    main_thread_calloc\n" +
+"#define public_fREe      main_thread_free\n" +
+"#define public_cFREe     main_thread_cfree\n" +
+"#define public_mALLOc    main_thread_malloc\n" +
+"#define public_mEMALIGn  main_thread_memalign\n" +
+"#define public_rEALLOc   main_thread_realloc\n" +
+"#define public_vALLOc    main_thread_valloc\n" +
+"#define public_pVALLOc   main_thread_pvalloc\n" +
+"#define public_mALLINFo  main_thread_mallinfo\n" +
+"#define public_mALLOPt   main_thread_mallopt\n" +
+"#define public_mTRIm     main_thread_malloc_trim\n" +
+"#define public_mSTATs    main_thread_malloc_stats\n" +
+"#define public_mUSABLe   main_thread_malloc_usable_size\n" +
+"#define public_iCALLOc   main_thread_independent_calloc\n" +
+"#define public_iCOMALLOc main_thread_independent_comalloc\n" +
+"#else /* USE_DL_PREFIX */\n" +
+"#define public_cALLOc    calloc\n" +
+"#define public_fREe      free\n" +
+"#define public_cFREe     cfree\n" +
+"#define public_mALLOc    malloc\n" +
+"#define public_mEMALIGn  memalign\n" +
+"#define public_rEALLOc   realloc\n" +
+"#define public_vALLOc    valloc\n" +
+"#define public_pVALLOc   pvalloc\n" +
+"#define public_mALLINFo  mallinfo\n" +
+"#define public_mALLOPt   mallopt\n" +
+"#define public_mTRIm     malloc_trim\n" +
+"#define public_mSTATs    malloc_stats\n" +
+"#define public_mUSABLe   malloc_usable_size\n" +
+"#define public_iCALLOc   independent_calloc\n" +
+"#define public_iCOMALLOc independent_comalloc\n" +
+"#endif /* USE_DL_PREFIX */\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  HAVE_MEMCPY should be defined if you are not otherwise using\n" +
+"  ANSI STD C, but still have memcpy and memset in your C library\n" +
+"  and want to use them in calloc and realloc. Otherwise simple\n" +
+"  macro versions are defined below.\n" +
+"\n") +
+("  USE_MEMCPY should be defined as 1 if you actually want to\n" +
+"  have memset and memcpy called. People report that the macro\n" +
+"  versions are faster than libc versions on some systems.\n" +
+"\n" +
+"  Even if USE_MEMCPY is set to 1, loops to copy/clear small chunks\n" +
+"  (of <= 36 bytes) are manually unrolled in realloc and calloc.\n" +
+"*/\n" +
+"\n" +
+"#define HAVE_MEMCPY\n" +
+"\n" +
+"#ifndef USE_MEMCPY\n" +
+"#ifdef HAVE_MEMCPY\n" +
+"#define USE_MEMCPY 1\n" +
+"#else\n" +
+"#define USE_MEMCPY 0\n" +
+"#endif\n" +
+"#endif\n" +
+"\n" +
+"\n" +
+"#if (__STD_C || defined(HAVE_MEMCPY))\n" +
+"\n" +
+"#ifdef WIN32\n" +
+"/* On Win32 memset and memcpy are already declared in windows.h */\n" +
+"#else\n" +
+"#if __STD_C\n" +
+"extern \"C\" {\n" +
+"void* memset(void*, int, size_t);\n" +
+"void* memcpy(void*, const void*, size_t);\n" +
+"}\n" +
+"#else\n" +
+"extern \"C\" {\n" +
+"Void_t* memset();\n" +
+"Void_t* memcpy();\n" +
+"}\n" +
+"#endif\n" +
+"#endif\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  MALLOC_FAILURE_ACTION is the action to take before \"return 0\" when\n" +
+"  malloc fails to be able to return memory, either because memory is\n" +
+"  exhausted or because of illegal arguments.\n" +
+"\n" +
+"  By default, sets errno if running on STD_C platform, else does nothing.\n" +
+"*/\n" +
+"\n" +
+"#ifndef MALLOC_FAILURE_ACTION\n" +
+"#if __STD_C\n" +
+"#define MALLOC_FAILURE_ACTION \\n" +
+"   errno = ENOMEM;\n" +
+"\n" +
+"#else\n" +
+"#define MALLOC_FAILURE_ACTION\n" +
+"#endif\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  MORECORE-related declarations. By default, rely on sbrk\n" +
+"*/\n" +
+"\n" +
+"\n" +
+"#ifdef LACKS_UNISTD_H\n" +
+"#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)\n" +
+"#if __STD_C\n" +
+"extern Void_t*     sbrk(ptrdiff_t);\n" +
+"#else\n" +
+"extern Void_t*     sbrk();\n" +
+"#endif\n" +
+"#endif\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  MORECORE is the name of the routine to call to obtain more memory\n" +
+"  from the system.  See below for general guidance on writing\n" +
+"  alternative MORECORE functions, as well as a version for WIN32 and a\n" +
+"  sample version for pre-OSX macos.\n" +
+"*/\n" +
+"\n" +
+"#ifndef MORECORE\n" +
+"#define MORECORE sbrk\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  MORECORE_FAILURE is the value returned upon failure of MORECORE\n" +
+"  as well as mmap. Since it cannot be an otherwise valid memory address,\n" +
+"  and must reflect values of standard sys calls, you probably ought not\n" +
+"  try to redefine it.\n" +
+"*/\n" +
+"\n" +
+"#ifndef MORECORE_FAILURE\n" +
+"#define MORECORE_FAILURE (-1)\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  If MORECORE_CONTIGUOUS is true, take advantage of fact that\n" +
+"  consecutive calls to MORECORE with positive arguments always return\n" +
+"  contiguous increasing addresses.  This is true of unix sbrk.  Even\n" +
+"  if not defined, when regions happen to be contiguous, malloc will\n" +
+"  permit allocations spanning regions obtained from different\n" +
+"  calls. But defining this when applicable enables some stronger\n" +
+"  consistency checks and space efficiencies.\n" +
+"*/\n" +
+"\n" +
+"#ifndef MORECORE_CONTIGUOUS\n" +
+"#define MORECORE_CONTIGUOUS 1\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  Define MORECORE_CANNOT_TRIM if your version of MORECORE\n" +
+"  cannot release space back to the system when given negative\n" +
+"  arguments. This is generally necessary only if you are using\n" +
+"  a hand-crafted MORECORE function that cannot handle negative arguments.\n" +
+"*/\n" +
+"\n" +
+"/* #define MORECORE_CANNOT_TRIM */\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  Define HAVE_MMAP as true to optionally make malloc() use mmap() to\n" +
+"  allocate very large blocks.  These will be returned to the\n" +
+"  operating system immediately after a free(). Also, if mmap\n" +
+"  is available, it is used as a backup strategy in cases where\n" +
+"  MORECORE fails to provide space from system.\n" +
+"\n" +
+"  This malloc is best tuned to work with mmap for large requests.\n" +
+"  If you do not have mmap, operations involving very large chunks (1MB\n" +
+"  or so) may be slower than you'd like.\n" +
+"*/\n" +
+"\n" +
+"#ifndef HAVE_MMAP\n" +
+"#define HAVE_MMAP 1\n" +
+"#endif\n" +
+"\n" +
+"#if HAVE_MMAP\n" +
+"/*\n" +
+"   Standard unix mmap using /dev/zero clears memory so calloc doesn't\n" +
+"   need to.\n" +
+"*/\n" +
+"\n" +
+"#ifndef MMAP_CLEARS\n" +
+"#define MMAP_CLEARS 1\n" +
+"#endif\n" +
+"\n" +
+"#else /* no mmap */\n" +
+"#ifndef MMAP_CLEARS\n" +
+"#define MMAP_CLEARS 0\n" +
+"#endif\n" +
+"#endif\n" +
+"\n" +
+"\n" +
+"/*\n") +
+("   MMAP_AS_MORECORE_SIZE is the minimum mmap size argument to use if\n" +
+"   sbrk fails, and mmap is used as a backup (which is done only if\n" +
+"   HAVE_MMAP).  The value must be a multiple of page size.  This\n" +
+"   backup strategy generally applies only when systems have \"holes\" in\n" +
+"   address space, so sbrk cannot perform contiguous expansion, but\n" +
+"   there is still space available on system.  On systems for which\n" +
+"   this is known to be useful (i.e. most linux kernels), this occurs\n" +
+"   only when programs allocate huge amounts of memory.  Between this,\n" +
+"   and the fact that mmap regions tend to be limited, the size should\n" +
+"   be large, to avoid too many mmap calls and thus avoid running out\n" +
+"   of kernel resources.\n" +
+"*/\n" +
+"\n" +
+"#ifndef MMAP_AS_MORECORE_SIZE\n" +
+"#define MMAP_AS_MORECORE_SIZE (1024 * 1024)\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  Define HAVE_MREMAP to make realloc() use mremap() to re-allocate\n" +
+"  large blocks.  This is currently only possible on Linux with\n" +
+"  kernel versions newer than 1.3.77.\n" +
+"*/\n" +
+"\n" +
+"#ifndef HAVE_MREMAP\n" +
+"#ifdef linux\n" +
+"#define HAVE_MREMAP 1\n" +
+"#else\n" +
+"#define HAVE_MREMAP 0\n" +
+"#endif\n" +
+"\n" +
+"#endif /* HAVE_MMAP */\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  The system page size. To the extent possible, this malloc manages\n" +
+"  memory from the system in page-size units.  Note that this value is\n" +
+"  cached during initialization into a field of malloc_state. So even\n" +
+"  if malloc_getpagesize is a function, it is only called once.\n" +
+"\n" +
+"  The following mechanics for getpagesize were adapted from bsd/gnu\n" +
+"  getpagesize.h. If none of the system-probes here apply, a value of\n" +
+"  4096 is used, which should be OK: If they don't apply, then using\n" +
+"  the actual value probably doesn't impact performance.\n" +
+"*/\n" +
+"\n" +
+"\n" +
+"#ifndef malloc_getpagesize\n" +
+"\n" +
+"#ifndef LACKS_UNISTD_H\n" +
+"#  include <unistd.h>\n" +
+"#endif\n" +
+"\n" +
+"#  ifdef _SC_PAGESIZE         /* some SVR4 systems omit an underscore */\n" +
+"#    ifndef _SC_PAGE_SIZE\n" +
+"#      define _SC_PAGE_SIZE _SC_PAGESIZE\n" +
+"#    endif\n" +
+"#  endif\n" +
+"\n" +
+"#  ifdef _SC_PAGE_SIZE\n" +
+"#    define malloc_getpagesize sysconf(_SC_PAGE_SIZE)\n" +
+"#  else\n" +
+"#    if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)\n" +
+"       extern size_t getpagesize();\n" +
+"#      define malloc_getpagesize getpagesize()\n" +
+"#    else\n" +
+"#      ifdef WIN32 /* use supplied emulation of getpagesize */\n" +
+"#        define malloc_getpagesize getpagesize()\n" +
+"#      else\n" +
+"#        ifndef LACKS_SYS_PARAM_H\n" +
+"#          include <sys/param.h>\n" +
+"#        endif\n" +
+"#        ifdef EXEC_PAGESIZE\n" +
+"#          define malloc_getpagesize EXEC_PAGESIZE\n" +
+"#        else\n" +
+"#          ifdef NBPG\n" +
+"#            ifndef CLSIZE\n" +
+"#              define malloc_getpagesize NBPG\n" +
+"#            else\n" +
+"#              define malloc_getpagesize (NBPG * CLSIZE)\n" +
+"#            endif\n" +
+"#          else\n" +
+"#            ifdef NBPC\n" +
+"#              define malloc_getpagesize NBPC\n" +
+"#            else\n" +
+"#              ifdef PAGESIZE\n" +
+"#                define malloc_getpagesize PAGESIZE\n" +
+"#              else /* just guess */\n" +
+"#                define malloc_getpagesize (4096)\n" +
+"#              endif\n" +
+"#            endif\n" +
+"#          endif\n" +
+"#        endif\n" +
+"#      endif\n" +
+"#    endif\n" +
+"#  endif\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  This version of malloc supports the standard SVID/XPG mallinfo\n" +
+"  routine that returns a struct containing usage properties and\n" +
+"  statistics. It should work on any SVID/XPG compliant system that has\n" +
+"  a /usr/include/malloc.h defining struct mallinfo. (If you'd like to\n" +
+"  install such a thing yourself, cut out the preliminary declarations\n" +
+"  as described above and below and save them in a malloc.h file. But\n" +
+"  there's no compelling reason to bother to do this.)\n" +
+"\n" +
+"  The main declaration needed is the mallinfo struct that is returned\n" +
+"  (by-copy) by mallinfo().  The SVID/XPG malloinfo struct contains a\n" +
+"  bunch of fields that are not even meaningful in this version of\n" +
+"  malloc.  These fields are are instead filled by mallinfo() with\n" +
+"  other numbers that might be of interest.\n" +
+"\n" +
+"  HAVE_USR_INCLUDE_MALLOC_H should be set if you have a\n" +
+"  /usr/include/malloc.h file that includes a declaration of struct\n" +
+"  mallinfo.  If so, it is included; else an SVID2/XPG2 compliant\n" +
+"  version is declared below.  These must be precisely the same for\n" +
+"  mallinfo() to work.  The original SVID version of this struct,\n" +
+"  defined on most systems with mallinfo, declares all fields as\n" +
+"  ints. But some others define as unsigned long. If your system\n" +
+"  defines the fields using a type of different width than listed here,\n" +
+"  you must #include your system version and #define\n" +
+"  HAVE_USR_INCLUDE_MALLOC_H.\n" +
+"*/\n" +
+"\n" +
+"/* #define HAVE_USR_INCLUDE_MALLOC_H */\n" +
+"\n" +
+"#ifdef HAVE_USR_INCLUDE_MALLOC_H\n" +
+"#include \"/usr/include/malloc.h\"\n" +
+"#else\n" +
+"\n" +
+"/* SVID2/XPG mallinfo structure */\n" +
+"\n" +
+"struct mallinfo {\n" +
+"  int arena;    /* non-mmapped space allocated from system */\n" +
+"  int ordblks;  /* number of free chunks */\n" +
+"  int smblks;   /* number of fastbin blocks */\n" +
+"  int hblks;    /* number of mmapped regions */\n" +
+"  int hblkhd;   /* space in mmapped regions */\n" +
+"  int usmblks;  /* maximum total allocated space */\n" +
+"  int fsmblks;  /* space available in freed fastbin blocks */\n" +
+"  int uordblks; /* total allocated space */\n" +
+"  int fordblks; /* total free space */\n" +
+"  int keepcost; /* top-most, releasable (via malloc_trim) space */\n" +
+"};\n" +
+"\n" +
+"/*\n" +
+"  SVID/XPG defines four standard parameter numbers for mallopt,\n" +
+"  normally defined in malloc.h.  Only one of these (M_MXFAST) is used\n" +
+"  in this malloc. The others (M_NLBLKS, M_GRAIN, M_KEEP) don't apply,\n" +
+"  so setting them has no effect. But this malloc also supports other\n" +
+"  options in mallopt described below.\n" +
+"*/\n") +
+("#endif\n" +
+"\n" +
+"\n" +
+"/* ---------- description of public routines ------------ */\n" +
+"\n" +
+"/*\n" +
+"  malloc(size_t n)\n" +
+"  Returns a pointer to a newly allocated chunk of at least n bytes, or null\n" +
+"  if no space is available. Additionally, on failure, errno is\n" +
+"  set to ENOMEM on ANSI C systems.\n" +
+"\n" +
+"  If n is zero, malloc returns a minumum-sized chunk. (The minimum\n" +
+"  size is 16 bytes on most 32bit systems, and 24 or 32 bytes on 64bit\n" +
+"  systems.)  On most systems, size_t is an unsigned type, so calls\n" +
+"  with negative arguments are interpreted as requests for huge amounts\n" +
+"  of space, which will often fail. The maximum supported value of n\n" +
+"  differs across systems, but is in all cases less than the maximum\n" +
+"  representable value of a size_t.\n" +
+"*/\n" +
+"#if __STD_C\n" +
+"Void_t*  public_mALLOc(size_t);\n" +
+"#else\n" +
+"Void_t*  public_mALLOc();\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  free(Void_t* p)\n" +
+"  Releases the chunk of memory pointed to by p, that had been previously\n" +
+"  allocated using malloc or a related routine such as realloc.\n" +
+"  It has no effect if p is null. It can have arbitrary (i.e., bad!)\n" +
+"  effects if p has already been freed.\n" +
+"\n" +
+"  Unless disabled (using mallopt), freeing very large spaces will\n" +
+"  when possible, automatically trigger operations that give\n" +
+"  back unused memory to the system, thus reducing program footprint.\n" +
+"*/\n" +
+"#if __STD_C\n" +
+"void     public_fREe(Void_t*);\n" +
+"#else\n" +
+"void     public_fREe();\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  calloc(size_t n_elements, size_t element_size);\n" +
+"  Returns a pointer to n_elements * element_size bytes, with all locations\n" +
+"  set to zero.\n" +
+"*/\n" +
+"#if __STD_C\n" +
+"Void_t*  public_cALLOc(size_t, size_t);\n" +
+"#else\n" +
+"Void_t*  public_cALLOc();\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  realloc(Void_t* p, size_t n)\n" +
+"  Returns a pointer to a chunk of size n that contains the same data\n" +
+"  as does chunk p up to the minimum of (n, p's size) bytes, or null\n" +
+"  if no space is available.\n" +
+"\n" +
+"  The returned pointer may or may not be the same as p. The algorithm\n" +
+"  prefers extending p when possible, otherwise it employs the\n" +
+"  equivalent of a malloc-copy-free sequence.\n" +
+"\n" +
+"  If p is null, realloc is equivalent to malloc.\n" +
+"\n" +
+"  If space is not available, realloc returns null, errno is set (if on\n" +
+"  ANSI) and p is NOT freed.\n" +
+"\n" +
+"  if n is for fewer bytes than already held by p, the newly unused\n" +
+"  space is lopped off and freed if possible.  Unless the #define\n" +
+"  REALLOC_ZERO_BYTES_FREES is set, realloc with a size argument of\n" +
+"  zero (re)allocates a minimum-sized chunk.\n" +
+"\n" +
+"  Large chunks that were internally obtained via mmap will always\n" +
+"  be reallocated using malloc-copy-free sequences unless\n" +
+"  the system supports MREMAP (currently only linux).\n" +
+"\n" +
+"  The old unix realloc convention of allowing the last-free'd chunk\n" +
+"  to be used as an argument to realloc is not supported.\n" +
+"*/\n" +
+"#if __STD_C\n" +
+"Void_t*  public_rEALLOc(Void_t*, size_t);\n" +
+"#else\n" +
+"Void_t*  public_rEALLOc();\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  memalign(size_t alignment, size_t n);\n" +
+"  Returns a pointer to a newly allocated chunk of n bytes, aligned\n" +
+"  in accord with the alignment argument.\n" +
+"\n" +
+"  The alignment argument should be a power of two. If the argument is\n" +
+"  not a power of two, the nearest greater power is used.\n" +
+"  8-byte alignment is guaranteed by normal malloc calls, so don't\n" +
+"  bother calling memalign with an argument of 8 or less.\n" +
+"\n" +
+"  Overreliance on memalign is a sure way to fragment space.\n" +
+"*/\n" +
+"#if __STD_C\n" +
+"Void_t*  public_mEMALIGn(size_t, size_t);\n" +
+"#else\n" +
+"Void_t*  public_mEMALIGn();\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  valloc(size_t n);\n" +
+"  Equivalent to memalign(pagesize, n), where pagesize is the page\n" +
+"  size of the system. If the pagesize is unknown, 4096 is used.\n" +
+"*/\n" +
+"#if __STD_C\n" +
+"Void_t*  public_vALLOc(size_t);\n" +
+"#else\n" +
+"Void_t*  public_vALLOc();\n" +
+"#endif\n" +
+"\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  mallopt(int parameter_number, int parameter_value)\n" +
+"  Sets tunable parameters The format is to provide a\n" +
+"  (parameter-number, parameter-value) pair.  mallopt then sets the\n" +
+"  corresponding parameter to the argument value if it can (i.e., so\n" +
+"  long as the value is meaningful), and returns 1 if successful else\n" +
+"  0.  SVID/XPG/ANSI defines four standard param numbers for mallopt,\n" +
+"  normally defined in malloc.h.  Only one of these (M_MXFAST) is used\n" +
+"  in this malloc. The others (M_NLBLKS, M_GRAIN, M_KEEP) don't apply,\n" +
+"  so setting them has no effect. But this malloc also supports four\n" +
+"  other options in mallopt. See below for details.  Briefly, supported\n" +
+"  parameters are as follows (listed defaults are for \"typical\"\n" +
+"  configurations).\n" +
+"\n" +
+"  Symbol            param #   default    allowed param values\n" +
+"  M_MXFAST          1         64         0-80  (0 disables fastbins)\n" +
+"  M_TRIM_THRESHOLD -1         256*1024   any   (-1U disables trimming)\n" +
+"  M_TOP_PAD        -2         0          any\n" +
+"  M_MMAP_THRESHOLD -3         256*1024   any   (or 0 if no MMAP support)\n" +
+"  M_MMAP_MAX       -4         65536      any   (0 disables use of mmap)\n" +
+"*/\n" +
+"#if __STD_C\n" +
+"int      public_mALLOPt(int, int);\n" +
+"#else\n" +
+"int      public_mALLOPt();\n" +
+"#endif\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  mallinfo()\n" +
+"  Returns (by copy) a struct containing various summary statistics:\n" +
+"\n") +
+("  arena:     current total non-mmapped bytes allocated from system\n" +
+"  ordblks:   the number of free chunks\n" +
+"  smblks:    the number of fastbin blocks (i.e., small chunks that\n" +
+"               have been freed but not use resused or consolidated)\n" +
+"  hblks:     current number of mmapped regions\n" +
+"  hblkhd:    total bytes held in mmapped regions\n" +
+"  usmblks:   the maximum total allocated space. This will be greater\n" +
+"                than current total if trimming has occurred.\n" +
+"  fsmblks:   total bytes held in fastbin blocks\n" +
+"  uordblks:  current total allocated space (normal or mmapped)\n" +
+"  fordblks:  total free space\n" +
+"  keepcost:  the maximum number of bytes that could ideally be released\n" +
+"               back to system via malloc_trim. (\"ideally\" means that\n" +
+"               it ignores page restrictions etc.)\n" +
+"\n" +
+"  Because these fields are ints, but internal bookkeeping may\n" +
+"  be kept as longs, the reported values may wrap around zero and\n" +
+"  thus be inaccurate.\n" +
+"*/\n" +
+"#if __STD_C\n" +
+"struct mallinfo public_mALLINFo(void);\n" +
+"#else\n" +
+"struct mallinfo public_mALLINFo();\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  independent_calloc(size_t n_elements, size_t element_size, Void_t* chunks[]);\n" +
+"\n" +
+"  independent_calloc is similar to calloc, but instead of returning a\n" +
+"  single cleared space, it returns an array of pointers to n_elements\n" +
+"  independent elements that can hold contents of size elem_size, each\n" +
+"  of which starts out cleared, and can be independently freed,\n" +
+"  realloc'ed etc. The elements are guaranteed to be adjacently\n" +
+"  allocated (this is not guaranteed to occur with multiple callocs or\n" +
+"  mallocs), which may also improve cache locality in some\n" +
+"  applications.\n" +
+"\n" +
+"  The \"chunks\" argument is optional (i.e., may be null, which is\n" +
+"  probably the most typical usage). If it is null, the returned array\n" +
+"  is itself dynamically allocated and should also be freed when it is\n" +
+"  no longer needed. Otherwise, the chunks array must be of at least\n" +
+"  n_elements in length. It is filled in with the pointers to the\n" +
+"  chunks.\n" +
+"\n" +
+"  In either case, independent_calloc returns this pointer array, or\n" +
+"  null if the allocation failed.  If n_elements is zero and \"chunks\"\n" +
+"  is null, it returns a chunk representing an array with zero elements\n" +
+"  (which should be freed if not wanted).\n" +
+"\n" +
+"  Each element must be individually freed when it is no longer\n" +
+"  needed. If you'd like to instead be able to free all at once, you\n" +
+"  should instead use regular calloc and assign pointers into this\n" +
+"  space to represent elements.  (In this case though, you cannot\n" +
+"  independently free elements.)\n" +
+"\n" +
+"  independent_calloc simplifies and speeds up implementations of many\n" +
+"  kinds of pools.  It may also be useful when constructing large data\n" +
+"  structures that initially have a fixed number of fixed-sized nodes,\n" +
+"  but the number is not known at compile time, and some of the nodes\n" +
+"  may later need to be freed. For example:\n" +
+"\n" +
+"  struct Node { int item; struct Node* next; };\n" +
+"\n" +
+"  struct Node* build_list() {\n" +
+"    struct Node** pool;\n" +
+"    int n = read_number_of_nodes_needed();\n" +
+"    if (n <= 0) return 0;\n" +
+"    pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0);\n" +
+"    if (pool == 0) die();\n" +
+"    // organize into a linked list...\n" +
+"    struct Node* first = pool[0];\n" +
+"    for (i = 0; i < n-1; ++i)\n" +
+"      pool[i]->next = pool[i+1];\n" +
+"    free(pool);     // Can now free the array (or not, if it is needed later)\n" +
+"    return first;\n" +
+"  }\n" +
+"*/\n" +
+"#if __STD_C\n" +
+"Void_t** public_iCALLOc(size_t, size_t, Void_t**);\n" +
+"#else\n" +
+"Void_t** public_iCALLOc();\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  independent_comalloc(size_t n_elements, size_t sizes[], Void_t* chunks[]);\n" +
+"\n" +
+"  independent_comalloc allocates, all at once, a set of n_elements\n" +
+"  chunks with sizes indicated in the \"sizes\" array.    It returns\n" +
+"  an array of pointers to these elements, each of which can be\n" +
+"  independently freed, realloc'ed etc. The elements are guaranteed to\n" +
+"  be adjacently allocated (this is not guaranteed to occur with\n" +
+"  multiple callocs or mallocs), which may also improve cache locality\n" +
+"  in some applications.\n" +
+"\n" +
+"  The \"chunks\" argument is optional (i.e., may be null). If it is null\n" +
+"  the returned array is itself dynamically allocated and should also\n" +
+"  be freed when it is no longer needed. Otherwise, the chunks array\n" +
+"  must be of at least n_elements in length. It is filled in with the\n" +
+"  pointers to the chunks.\n" +
+"\n" +
+"  In either case, independent_comalloc returns this pointer array, or\n" +
+"  null if the allocation failed.  If n_elements is zero and chunks is\n" +
+"  null, it returns a chunk representing an array with zero elements\n" +
+"  (which should be freed if not wanted).\n" +
+"\n" +
+"  Each element must be individually freed when it is no longer\n" +
+"  needed. If you'd like to instead be able to free all at once, you\n" +
+"  should instead use a single regular malloc, and assign pointers at\n" +
+"  particular offsets in the aggregate space. (In this case though, you\n" +
+"  cannot independently free elements.)\n" +
+"\n" +
+"  independent_comallac differs from independent_calloc in that each\n" +
+"  element may have a different size, and also that it does not\n" +
+"  automatically clear elements.\n" +
+"\n" +
+"  independent_comalloc can be used to speed up allocation in cases\n" +
+"  where several structs or objects must always be allocated at the\n" +
+"  same time.  For example:\n" +
+"\n" +
+"  struct Head { ... }\n" +
+"  struct Foot { ... }\n" +
+"\n" +
+"  void send_message(char* msg) {\n" +
+"    int msglen = strlen(msg);\n" +
+"    size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) };\n" +
+"    void* chunks[3];\n" +
+"    if (independent_comalloc(3, sizes, chunks) == 0)\n" +
+"      die();\n" +
+"    struct Head* head = (struct Head*)(chunks[0]);\n" +
+"    char*        body = (char*)(chunks[1]);\n" +
+"    struct Foot* foot = (struct Foot*)(chunks[2]);\n" +
+"    // ...\n" +
+"  }\n" +
+"\n" +
+"  In general though, independent_comalloc is worth using only for\n" +
+"  larger values of n_elements. For small values, you probably won't\n" +
+"  detect enough difference from series of malloc calls to bother.\n" +
+"\n" +
+"  Overuse of independent_comalloc can increase overall memory usage,\n" +
+"  since it cannot reuse existing noncontiguous small chunks that\n" +
+"  might be available for some of the elements.\n" +
+"*/\n" +
+"#if __STD_C\n" +
+"Void_t** public_iCOMALLOc(size_t, size_t*, Void_t**);\n" +
+"#else\n" +
+"Void_t** public_iCOMALLOc();\n" +
+"#endif\n" +
+"\n" +
+"\n" +
+"/*\n") +
+("  pvalloc(size_t n);\n" +
+"  Equivalent to valloc(minimum-page-that-holds(n)), that is,\n" +
+"  round up n to nearest pagesize.\n" +
+" */\n" +
+"#if __STD_C\n" +
+"Void_t*  public_pVALLOc(size_t);\n" +
+"#else\n" +
+"Void_t*  public_pVALLOc();\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  cfree(Void_t* p);\n" +
+"  Equivalent to free(p).\n" +
+"\n" +
+"  cfree is needed/defined on some systems that pair it with calloc,\n" +
+"  for odd historical reasons (such as: cfree is used in example\n" +
+"  code in the first edition of K&R).\n" +
+"*/\n" +
+"#if __STD_C\n" +
+"void     public_cFREe(Void_t*);\n" +
+"#else\n" +
+"void     public_cFREe();\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  malloc_trim(size_t pad);\n" +
+"\n" +
+"  If possible, gives memory back to the system (via negative\n" +
+"  arguments to sbrk) if there is unused memory at the `high' end of\n" +
+"  the malloc pool. You can call this after freeing large blocks of\n" +
+"  memory to potentially reduce the system-level memory requirements\n" +
+"  of a program. However, it cannot guarantee to reduce memory. Under\n" +
+"  some allocation patterns, some large free blocks of memory will be\n" +
+"  locked between two used chunks, so they cannot be given back to\n" +
+"  the system.\n" +
+"\n" +
+"  The `pad' argument to malloc_trim represents the amount of free\n" +
+"  trailing space to leave untrimmed. If this argument is zero,\n" +
+"  only the minimum amount of memory to maintain internal data\n" +
+"  structures will be left (one page or less). Non-zero arguments\n" +
+"  can be supplied to maintain enough trailing space to service\n" +
+"  future expected allocations without having to re-obtain memory\n" +
+"  from the system.\n" +
+"\n" +
+"  Malloc_trim returns 1 if it actually released any memory, else 0.\n" +
+"  On systems that do not support \"negative sbrks\", it will always\n" +
+"  rreturn 0.\n" +
+"*/\n" +
+"#if __STD_C\n" +
+"int      public_mTRIm(size_t);\n" +
+"#else\n" +
+"int      public_mTRIm();\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  malloc_usable_size(Void_t* p);\n" +
+"\n" +
+"  Returns the number of bytes you can actually use in\n" +
+"  an allocated chunk, which may be more than you requested (although\n" +
+"  often not) due to alignment and minimum size constraints.\n" +
+"  You can use this many bytes without worrying about\n" +
+"  overwriting other allocated objects. This is not a particularly great\n" +
+"  programming practice. malloc_usable_size can be more useful in\n" +
+"  debugging and assertions, for example:\n" +
+"\n" +
+"  p = malloc(n);\n" +
+"  assert(malloc_usable_size(p) >= 256);\n" +
+"\n" +
+"*/\n" +
+"#if __STD_C\n" +
+"size_t   public_mUSABLe(Void_t*);\n" +
+"#else\n" +
+"size_t   public_mUSABLe();\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  malloc_stats();\n" +
+"  Prints on stderr the amount of space obtained from the system (both\n" +
+"  via sbrk and mmap), the maximum amount (which may be more than\n" +
+"  current if malloc_trim and/or munmap got called), and the current\n" +
+"  number of bytes allocated via malloc (or realloc, etc) but not yet\n" +
+"  freed. Note that this is the number of bytes allocated, not the\n" +
+"  number requested. It will be larger than the number requested\n" +
+"  because of alignment and bookkeeping overhead. Because it includes\n" +
+"  alignment wastage as being in use, this figure may be greater than\n" +
+"  zero even when no user-level chunks are allocated.\n" +
+"\n" +
+"  The reported current and maximum system memory can be inaccurate if\n" +
+"  a program makes other calls to system memory allocation functions\n" +
+"  (normally sbrk) outside of malloc.\n" +
+"\n" +
+"  malloc_stats prints only the most commonly interesting statistics.\n" +
+"  More information can be obtained by calling mallinfo.\n" +
+"\n" +
+"*/\n" +
+"#if __STD_C\n" +
+"void     public_mSTATs();\n" +
+"#else\n" +
+"void     public_mSTATs();\n" +
+"#endif\n" +
+"\n" +
+"/* mallopt tuning options */\n" +
+"\n" +
+"/*\n" +
+"  M_MXFAST is the maximum request size used for \"fastbins\", special bins\n" +
+"  that hold returned chunks without consolidating their spaces. This\n" +
+"  enables future requests for chunks of the same size to be handled\n" +
+"  very quickly, but can increase fragmentation, and thus increase the\n" +
+"  overall memory footprint of a program.\n" +
+"\n" +
+"  This malloc manages fastbins very conservatively yet still\n" +
+"  efficiently, so fragmentation is rarely a problem for values less\n" +
+"  than or equal to the default.  The maximum supported value of MXFAST\n" +
+"  is 80. You wouldn't want it any higher than this anyway.  Fastbins\n" +
+"  are designed especially for use with many small structs, objects or\n" +
+"  strings -- the default handles structs/objects/arrays with sizes up\n" +
+"  to 16 4byte fields, or small strings representing words, tokens,\n" +
+"  etc. Using fastbins for larger objects normally worsens\n" +
+"  fragmentation without improving speed.\n" +
+"\n" +
+"  M_MXFAST is set in REQUEST size units. It is internally used in\n" +
+"  chunksize units, which adds padding and alignment.  You can reduce\n" +
+"  M_MXFAST to 0 to disable all use of fastbins.  This causes the malloc\n" +
+"  algorithm to be a closer approximation of fifo-best-fit in all cases,\n" +
+"  not just for larger requests, but will generally cause it to be\n" +
+"  slower.\n" +
+"*/\n" +
+"\n" +
+"\n" +
+"/* M_MXFAST is a standard SVID/XPG tuning option, usually listed in malloc.h */\n" +
+"#ifndef M_MXFAST\n" +
+"#define M_MXFAST            1\n" +
+"#endif\n" +
+"\n" +
+"#ifndef DEFAULT_MXFAST\n" +
+"#define DEFAULT_MXFAST     64\n" +
+"#endif\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  M_TRIM_THRESHOLD is the maximum amount of unused top-most memory\n" +
+"  to keep before releasing via malloc_trim in free().\n" +
+"\n" +
+"  Automatic trimming is mainly useful in long-lived programs.\n" +
+"  Because trimming via sbrk can be slow on some systems, and can\n" +
+"  sometimes be wasteful (in cases where programs immediately\n" +
+"  afterward allocate more large chunks) the value should be high\n" +
+"  enough so that your overall system performance would improve by\n" +
+"  releasing this much memory.\n" +
+"\n") +
+("  The trim threshold and the mmap control parameters (see below)\n" +
+"  can be traded off with one another. Trimming and mmapping are\n" +
+"  two different ways of releasing unused memory back to the\n" +
+"  system. Between these two, it is often possible to keep\n" +
+"  system-level demands of a long-lived program down to a bare\n" +
+"  minimum. For example, in one test suite of sessions measuring\n" +
+"  the XF86 X server on Linux, using a trim threshold of 128K and a\n" +
+"  mmap threshold of 192K led to near-minimal long term resource\n" +
+"  consumption.\n" +
+"\n" +
+"  If you are using this malloc in a long-lived program, it should\n" +
+"  pay to experiment with these values.  As a rough guide, you\n" +
+"  might set to a value close to the average size of a process\n" +
+"  (program) running on your system.  Releasing this much memory\n" +
+"  would allow such a process to run in memory.  Generally, it's\n" +
+"  worth it to tune for trimming rather tham memory mapping when a\n" +
+"  program undergoes phases where several large chunks are\n" +
+"  allocated and released in ways that can reuse each other's\n" +
+"  storage, perhaps mixed with phases where there are no such\n" +
+"  chunks at all.  And in well-behaved long-lived programs,\n" +
+"  controlling release of large blocks via trimming versus mapping\n" +
+"  is usually faster.\n" +
+"\n" +
+"  However, in most programs, these parameters serve mainly as\n" +
+"  protection against the system-level effects of carrying around\n" +
+"  massive amounts of unneeded memory. Since frequent calls to\n" +
+"  sbrk, mmap, and munmap otherwise degrade performance, the default\n" +
+"  parameters are set to relatively high values that serve only as\n" +
+"  safeguards.\n" +
+"\n" +
+"  The trim value must be greater than page size to have any useful\n" +
+"  effect.  To disable trimming completely, you can set to\n" +
+"  (unsigned long)(-1)\n" +
+"\n" +
+"  Trim settings interact with fastbin (MXFAST) settings: Unless\n" +
+"  TRIM_FASTBINS is defined, automatic trimming never takes place upon\n" +
+"  freeing a chunk with size less than or equal to MXFAST. Trimming is\n" +
+"  instead delayed until subsequent freeing of larger chunks. However,\n" +
+"  you can still force an attempted trim by calling malloc_trim.\n" +
+"\n" +
+"  Also, trimming is not generally possible in cases where\n" +
+"  the main arena is obtained via mmap.\n" +
+"\n" +
+"  Note that the trick some people use of mallocing a huge space and\n" +
+"  then freeing it at program startup, in an attempt to reserve system\n" +
+"  memory, doesn't have the intended effect under automatic trimming,\n" +
+"  since that memory will immediately be returned to the system.\n" +
+"*/\n" +
+"\n" +
+"#define M_TRIM_THRESHOLD       -1\n" +
+"\n" +
+"#ifndef DEFAULT_TRIM_THRESHOLD\n" +
+"#define DEFAULT_TRIM_THRESHOLD (256 * 1024)\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  M_TOP_PAD is the amount of extra `padding' space to allocate or\n" +
+"  retain whenever sbrk is called. It is used in two ways internally:\n" +
+"\n" +
+"  * When sbrk is called to extend the top of the arena to satisfy\n" +
+"  a new malloc request, this much padding is added to the sbrk\n" +
+"  request.\n" +
+"\n" +
+"  * When malloc_trim is called automatically from free(),\n" +
+"  it is used as the `pad' argument.\n" +
+"\n" +
+"  In both cases, the actual amount of padding is rounded\n" +
+"  so that the end of the arena is always a system page boundary.\n" +
+"\n" +
+"  The main reason for using padding is to avoid calling sbrk so\n" +
+"  often. Having even a small pad greatly reduces the likelihood\n" +
+"  that nearly every malloc request during program start-up (or\n" +
+"  after trimming) will invoke sbrk, which needlessly wastes\n" +
+"  time.\n" +
+"\n" +
+"  Automatic rounding-up to page-size units is normally sufficient\n" +
+"  to avoid measurable overhead, so the default is 0.  However, in\n" +
+"  systems where sbrk is relatively slow, it can pay to increase\n" +
+"  this value, at the expense of carrying around more memory than\n" +
+"  the program needs.\n" +
+"*/\n" +
+"\n" +
+"#define M_TOP_PAD              -2\n" +
+"\n" +
+"#ifndef DEFAULT_TOP_PAD\n" +
+"#define DEFAULT_TOP_PAD        (0)\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  M_MMAP_THRESHOLD is the request size threshold for using mmap()\n" +
+"  to service a request. Requests of at least this size that cannot\n" +
+"  be allocated using already-existing space will be serviced via mmap.\n" +
+"  (If enough normal freed space already exists it is used instead.)\n" +
+"\n" +
+"  Using mmap segregates relatively large chunks of memory so that\n" +
+"  they can be individually obtained and released from the host\n" +
+"  system. A request serviced through mmap is never reused by any\n" +
+"  other request (at least not directly; the system may just so\n" +
+"  happen to remap successive requests to the same locations).\n" +
+"\n" +
+"  Segregating space in this way has the benefits that:\n" +
+"\n" +
+"   1. Mmapped space can ALWAYS be individually released back\n" +
+"      to the system, which helps keep the system level memory\n" +
+"      demands of a long-lived program low.\n" +
+"   2. Mapped memory can never become `locked' between\n" +
+"      other chunks, as can happen with normally allocated chunks, which\n" +
+"      means that even trimming via malloc_trim would not release them.\n" +
+"   3. On some systems with \"holes\" in address spaces, mmap can obtain\n" +
+"      memory that sbrk cannot.\n" +
+"\n" +
+"  However, it has the disadvantages that:\n" +
+"\n" +
+"   1. The space cannot be reclaimed, consolidated, and then\n" +
+"      used to service later requests, as happens with normal chunks.\n" +
+"   2. It can lead to more wastage because of mmap page alignment\n" +
+"      requirements\n" +
+"   3. It causes malloc performance to be more dependent on host\n" +
+"      system memory management support routines which may vary in\n" +
+"      implementation quality and may impose arbitrary\n" +
+"      limitations. Generally, servicing a request via normal\n" +
+"      malloc steps is faster than going through a system's mmap.\n" +
+"\n" +
+"  The advantages of mmap nearly always outweigh disadvantages for\n" +
+"  \"large\" chunks, but the value of \"large\" varies across systems.  The\n" +
+"  default is an empirically derived value that works well in most\n" +
+"  systems.\n" +
+"*/\n" +
+"\n" +
+"#define M_MMAP_THRESHOLD      -3\n" +
+"\n" +
+"#ifndef DEFAULT_MMAP_THRESHOLD\n" +
+"#define DEFAULT_MMAP_THRESHOLD (256 * 1024)\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  M_MMAP_MAX is the maximum number of requests to simultaneously\n" +
+"  service using mmap. This parameter exists because\n" +
+". Some systems have a limited number of internal tables for\n" +
+"  use by mmap, and using more than a few of them may degrade\n" +
+"  performance.\n" +
+"\n" +
+"  The default is set to a value that serves only as a safeguard.\n" +
+"  Setting to 0 disables use of mmap for servicing large requests.  If\n" +
+"  HAVE_MMAP is not set, the default value is 0, and attempts to set it\n" +
+"  to non-zero values in mallopt will fail.\n" +
+"*/\n" +
+"\n" +
+"#define M_MMAP_MAX             -4\n" +
+"\n") +
+("#ifndef DEFAULT_MMAP_MAX\n" +
+"#if HAVE_MMAP\n" +
+"#define DEFAULT_MMAP_MAX       (65536)\n" +
+"#else\n" +
+"#define DEFAULT_MMAP_MAX       (0)\n" +
+"#endif\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  ========================================================================\n" +
+"  To make a fully customizable malloc.h header file, cut everything\n" +
+"  above this line, put into file malloc.h, edit to suit, and #include it\n" +
+"  on the next line, as well as in programs that use this malloc.\n" +
+"  ========================================================================\n" +
+"*/\n" +
+"\n" +
+"/* #include \"malloc.h\" */\n" +
+"\n" +
+"/* --------------------- public wrappers ---------------------- */\n" +
+"\n" +
+"#ifdef USE_PUBLIC_MALLOC_WRAPPERS\n" +
+"\n" +
+"/* Declare all routines as internal */\n" +
+"#if __STD_C\n" +
+"static Void_t*  mALLOc(size_t);\n" +
+"static void     fREe(Void_t*);\n" +
+"static Void_t*  rEALLOc(Void_t*, size_t);\n" +
+"static Void_t*  mEMALIGn(size_t, size_t);\n" +
+"static Void_t*  vALLOc(size_t);\n" +
+"static Void_t*  pVALLOc(size_t);\n" +
+"static Void_t*  cALLOc(size_t, size_t);\n" +
+"static Void_t** iCALLOc(size_t, size_t, Void_t**);\n" +
+"static Void_t** iCOMALLOc(size_t, size_t*, Void_t**);\n" +
+"static void     cFREe(Void_t*);\n" +
+"static int      mTRIm(size_t);\n" +
+"static size_t   mUSABLe(Void_t*);\n" +
+"static void     mSTATs();\n" +
+"static int      mALLOPt(int, int);\n" +
+"static struct mallinfo mALLINFo(void);\n" +
+"#else\n" +
+"static Void_t*  mALLOc();\n" +
+"static void     fREe();\n" +
+"static Void_t*  rEALLOc();\n" +
+"static Void_t*  mEMALIGn();\n" +
+"static Void_t*  vALLOc();\n" +
+"static Void_t*  pVALLOc();\n" +
+"static Void_t*  cALLOc();\n" +
+"static Void_t** iCALLOc();\n" +
+"static Void_t** iCOMALLOc();\n" +
+"static void     cFREe();\n" +
+"static int      mTRIm();\n" +
+"static size_t   mUSABLe();\n" +
+"static void     mSTATs();\n" +
+"static int      mALLOPt();\n" +
+"static struct mallinfo mALLINFo();\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  MALLOC_PREACTION and MALLOC_POSTACTION should be\n" +
+"  defined to return 0 on success, and nonzero on failure.\n" +
+"  The return value of MALLOC_POSTACTION is currently ignored\n" +
+"  in wrapper functions since there is no reasonable default\n" +
+"  action to take on failure.\n" +
+"*/\n" +
+"\n" +
+"\n" +
+"#ifdef USE_MALLOC_LOCK\n" +
+"\n" +
+"#ifdef WIN32\n" +
+"\n" +
+"static int mALLOC_MUTEx;\n" +
+"#define MALLOC_PREACTION   slwait(&mALLOC_MUTEx)\n" +
+"#define MALLOC_POSTACTION  slrelease(&mALLOC_MUTEx)\n" +
+"\n" +
+"#else\n" +
+"\n" +
+"#include <pthread.h>\n" +
+"\n" +
+"static pthread_mutex_t mALLOC_MUTEx = PTHREAD_MUTEX_INITIALIZER;\n" +
+"\n" +
+"#define MALLOC_PREACTION   pthread_mutex_lock(&mALLOC_MUTEx)\n" +
+"#define MALLOC_POSTACTION  pthread_mutex_unlock(&mALLOC_MUTEx)\n" +
+"\n" +
+"#endif /* USE_MALLOC_LOCK */\n" +
+"\n" +
+"#else\n" +
+"\n" +
+"/* Substitute anything you like for these */\n" +
+"\n" +
+"#define MALLOC_PREACTION   (0)\n" +
+"#define MALLOC_POSTACTION  (0)\n" +
+"\n" +
+"#endif\n" +
+"\n" +
+"Void_t* public_mALLOc(size_t bytes) {\n" +
+"  Void_t* m;\n" +
+"  if (MALLOC_PREACTION != 0) {\n" +
+"    return 0;\n" +
+"  }\n" +
+"  m = mALLOc(bytes);\n" +
+"  if (MALLOC_POSTACTION != 0) {\n" +
+"  }\n" +
+"  return m;\n" +
+"}\n" +
+"\n" +
+"\n" +
+"static pthread_once_t free_mutex_once = PTHREAD_ONCE_INIT;\n" +
+"static pthread_mutex_t free_mutex;\n" +
+"static int scheduled_free_size;\n" +
+"static int scheduled_free_capacity;\n" +
+"static int scheduled_free_list;\n" +
+"bool free_is_scheduled;\n" +
+"\n" +
+"static void initialize_scheduled_free_list()\n" +
+"{\n" +
+"    pthread_mutex_init(&free_mutex, NULL);\n" +
+"}\n" +
+"\n" +
+"static void drain_scheduled_free_list()\n" +
+"{\n" +
+"    pthread_mutex_lock(&free_mutex);\n" +
+"    if (free_is_scheduled) {\n" +
+"        for(int i = 0; i < scheduled_free_size; i++) {\n" +
+"            main_thread_free(scheduled_free_list[i]);\n" +
+"        }\n" +
+"        free(scheduled_free_list);\n" +
+"        scheduled_free_list = NULL;\n" +
+"        scheduled_free_size = 0;\n" +
+"        scheduled_free_capacity = 0;\n" +
+"        free_is_scheduled = false;\n" +
+"    }\n" +
+"    pthread_mutex_unlock(&free_mutex);\n" +
+"}\n" +
+"\n" +
+"static void schedule_free_on_main_thread(Void_t* m)\n" +
+"{\n" +
+"    pthread_once(&free_mutex_once, initialize_scheduled_free_list);\n" +
+"\n" +
+"    pthread_mutex_lock(&free_mutex);\n" +
+"    if (scheduled_free_size == scheduled_free_capacity) {\n" +
+"        scheduled_free_capacity = scheduled_free_capacity == 0 ? 16 : scheduled_free_capacity * 1.2;\n" +
+"        scheduled_free_list = (Void_t**)realloc(scheduled_free_list, sizeof(Void_t*) * scheduled_free_capacity);\n" +
+"    }\n" +
+"    scheduled_free_list[scheduled_free_size++] = m;\n" +
+"    if (!free_is_scheduled) {\n" +
+"        QTimer::immediateSingleShotOnMainThread(0, drain_scheduled_free_list);\n" +
+"        free_is_scheduled = true;\n" +
+"    }\n" +
+"    pthread_mutex_unlock(&free_mutex);\n" +
+"}\n") +
+("\n" +
+"void public_fREe(Void_t* m) {\n" +
+"  if (!pthread_main_np()) {\n" +
+"      schedule_free_on_main_thread(m);\n" +
+"      return;\n" +
+"  }\n" +
+"\n" +
+"  if (MALLOC_PREACTION != 0) {\n" +
+"    return;\n" +
+"  }\n" +
+"  fREe(m);\n" +
+"  if (MALLOC_POSTACTION != 0) {\n" +
+"  }\n" +
+"}\n" +
+"\n" +
+"Void_t* public_rEALLOc(Void_t* m, size_t bytes) {\n" +
+"  if (MALLOC_PREACTION != 0) {\n" +
+"    return 0;\n" +
+"  }\n" +
+"  m = rEALLOc(m, bytes);\n" +
+"  if (MALLOC_POSTACTION != 0) {\n" +
+"  }\n" +
+"  return m;\n" +
+"}\n" +
+"\n" +
+"Void_t* public_mEMALIGn(size_t alignment, size_t bytes) {\n" +
+"  Void_t* m;\n" +
+"  if (MALLOC_PREACTION != 0) {\n" +
+"    return 0;\n" +
+"  }\n" +
+"  m = mEMALIGn(alignment, bytes);\n" +
+"  if (MALLOC_POSTACTION != 0) {\n" +
+"  }\n" +
+"  return m;\n" +
+"}\n" +
+"\n" +
+"Void_t* public_vALLOc(size_t bytes) {\n" +
+"  Void_t* m;\n" +
+"  if (MALLOC_PREACTION != 0) {\n" +
+"    return 0;\n" +
+"  }\n" +
+"  m = vALLOc(bytes);\n" +
+"  if (MALLOC_POSTACTION != 0) {\n" +
+"  }\n" +
+"  return m;\n" +
+"}\n" +
+"\n" +
+"Void_t* public_pVALLOc(size_t bytes) {\n" +
+"  Void_t* m;\n" +
+"  if (MALLOC_PREACTION != 0) {\n" +
+"    return 0;\n" +
+"  }\n" +
+"  m = pVALLOc(bytes);\n" +
+"  if (MALLOC_POSTACTION != 0) {\n" +
+"  }\n" +
+"  return m;\n" +
+"}\n" +
+"\n" +
+"Void_t* public_cALLOc(size_t n, size_t elem_size) {\n" +
+"  Void_t* m;\n" +
+"  if (MALLOC_PREACTION != 0) {\n" +
+"    return 0;\n" +
+"  }\n" +
+"  m = cALLOc(n, elem_size);\n" +
+"  if (MALLOC_POSTACTION != 0) {\n" +
+"  }\n" +
+"  return m;\n" +
+"}\n" +
+"\n" +
+"\n" +
+"Void_t** public_iCALLOc(size_t n, size_t elem_size, Void_t** chunks) {\n" +
+"  Void_t** m;\n" +
+"  if (MALLOC_PREACTION != 0) {\n" +
+"    return 0;\n" +
+"  }\n" +
+"  m = iCALLOc(n, elem_size, chunks);\n" +
+"  if (MALLOC_POSTACTION != 0) {\n" +
+"  }\n" +
+"  return m;\n" +
+"}\n" +
+"\n" +
+"Void_t** public_iCOMALLOc(size_t n, size_t sizes[], Void_t** chunks) {\n" +
+"  Void_t** m;\n" +
+"  if (MALLOC_PREACTION != 0) {\n" +
+"    return 0;\n" +
+"  }\n" +
+"  m = iCOMALLOc(n, sizes, chunks);\n" +
+"  if (MALLOC_POSTACTION != 0) {\n" +
+"  }\n" +
+"  return m;\n" +
+"}\n" +
+"\n" +
+"void public_cFREe(Void_t* m) {\n" +
+"  if (MALLOC_PREACTION != 0) {\n" +
+"    return;\n" +
+"  }\n" +
+"  cFREe(m);\n" +
+"  if (MALLOC_POSTACTION != 0) {\n" +
+"  }\n" +
+"}\n" +
+"\n" +
+"int public_mTRIm(size_t s) {\n" +
+"  int result;\n" +
+"  if (MALLOC_PREACTION != 0) {\n" +
+"    return 0;\n" +
+"  }\n" +
+"  result = mTRIm(s);\n" +
+"  if (MALLOC_POSTACTION != 0) {\n" +
+"  }\n" +
+"  return result;\n" +
+"}\n" +
+"\n" +
+"size_t public_mUSABLe(Void_t* m) {\n" +
+"  size_t result;\n" +
+"  if (MALLOC_PREACTION != 0) {\n" +
+"    return 0;\n" +
+"  }\n" +
+"  result = mUSABLe(m);\n" +
+"  if (MALLOC_POSTACTION != 0) {\n" +
+"  }\n" +
+"  return result;\n" +
+"}\n" +
+"\n" +
+"void public_mSTATs() {\n" +
+"  if (MALLOC_PREACTION != 0) {\n" +
+"    return;\n" +
+"  }\n" +
+"  mSTATs();\n" +
+"  if (MALLOC_POSTACTION != 0) {\n" +
+"  }\n" +
+"}\n" +
+"\n" +
+"struct mallinfo public_mALLINFo() {\n" +
+"  struct mallinfo m;\n" +
+"  if (MALLOC_PREACTION != 0) {\n" +
+"    struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };\n" +
+"    return nm;\n" +
+"  }\n" +
+"  m = mALLINFo();\n" +
+"  if (MALLOC_POSTACTION != 0) {\n" +
+"  }\n" +
+"  return m;\n" +
+"}\n" +
+"\n" +
+"int public_mALLOPt(int p, int v) {\n" +
+"  int result;\n" +
+"  if (MALLOC_PREACTION != 0) {\n" +
+"    return 0;\n" +
+"  }\n" +
+"  result = mALLOPt(p, v);\n" +
+"  if (MALLOC_POSTACTION != 0) {\n" +
+"  }\n" +
+"  return result;\n" +
+"}\n" +
+"\n") +
+("#endif\n" +
+"\n" +
+"\n" +
+"\n" +
+"/* ------------- Optional versions of memcopy ---------------- */\n" +
+"\n" +
+"\n" +
+"#if USE_MEMCPY\n" +
+"\n" +
+"/*\n" +
+"  Note: memcpy is ONLY invoked with non-overlapping regions,\n" +
+"  so the (usually slower) memmove is not needed.\n" +
+"*/\n" +
+"\n" +
+"#define MALLOC_COPY(dest, src, nbytes)  memcpy(dest, src, nbytes)\n" +
+"#define MALLOC_ZERO(dest, nbytes)       memset(dest, 0,   nbytes)\n" +
+"\n" +
+"#else /* !USE_MEMCPY */\n" +
+"\n" +
+"/* Use Duff's device for good zeroing/copying performance. */\n" +
+"\n" +
+"#define MALLOC_ZERO(charp, nbytes)                                            \\n" +
+"do {                                                                          \\n" +
+"  INTERNAL_SIZE_T* mzp = (INTERNAL_SIZE_T*)(charp);                           \\n" +
+"  CHUNK_SIZE_T  mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T);                     \\n" +
+"  long mcn;                                                                   \\n" +
+"  if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; }             \\n" +
+"  switch (mctmp) {                                                            \\n" +
+"    case 0: for(;;) { *mzp++ = 0;                                             \\n" +
+"    case 7:           *mzp++ = 0;                                             \\n" +
+"    case 6:           *mzp++ = 0;                                             \\n" +
+"    case 5:           *mzp++ = 0;                                             \\n" +
+"    case 4:           *mzp++ = 0;                                             \\n" +
+"    case 3:           *mzp++ = 0;                                             \\n" +
+"    case 2:           *mzp++ = 0;                                             \\n" +
+"    case 1:           *mzp++ = 0; if(mcn <= 0) break; mcn--; }                \\n" +
+"  }                                                                           \\n" +
+"} while(0)\n" +
+"\n" +
+"#define MALLOC_COPY(dest,src,nbytes)                                          \\n" +
+"do {                                                                          \\n" +
+"  INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) src;                            \\n" +
+"  INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) dest;                           \\n" +
+"  CHUNK_SIZE_T  mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T);                     \\n" +
+"  long mcn;                                                                   \\n" +
+"  if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; }             \\n" +
+"  switch (mctmp) {                                                            \\n" +
+"    case 0: for(;;) { *mcdst++ = *mcsrc++;                                    \\n" +
+"    case 7:           *mcdst++ = *mcsrc++;                                    \\n" +
+"    case 6:           *mcdst++ = *mcsrc++;                                    \\n" +
+"    case 5:           *mcdst++ = *mcsrc++;                                    \\n" +
+"    case 4:           *mcdst++ = *mcsrc++;                                    \\n" +
+"    case 3:           *mcdst++ = *mcsrc++;                                    \\n" +
+"    case 2:           *mcdst++ = *mcsrc++;                                    \\n" +
+"    case 1:           *mcdst++ = *mcsrc++; if(mcn <= 0) break; mcn--; }       \\n" +
+"  }                                                                           \\n" +
+"} while(0)\n" +
+"\n" +
+"#endif\n" +
+"\n" +
+"/* ------------------ MMAP support ------------------  */\n" +
+"\n" +
+"\n" +
+"#if HAVE_MMAP\n" +
+"\n" +
+"#ifndef LACKS_FCNTL_H\n" +
+"#include <fcntl.h>\n" +
+"#endif\n" +
+"\n" +
+"#ifndef LACKS_SYS_MMAN_H\n" +
+"#include <sys/mman.h>\n" +
+"#endif\n" +
+"\n" +
+"#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)\n" +
+"#define MAP_ANONYMOUS MAP_ANON\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"   Nearly all versions of mmap support MAP_ANONYMOUS,\n" +
+"   so the following is unlikely to be needed, but is\n" +
+"   supplied just in case.\n" +
+"*/\n" +
+"\n" +
+"#ifndef MAP_ANONYMOUS\n" +
+"\n" +
+"static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */\n" +
+"\n" +
+"#define MMAP(addr, size, prot, flags) ((dev_zero_fd < 0) ? \\n" +
+" (dev_zero_fd = open(\"/dev/zero\", O_RDWR), \\n" +
+"  mmap((addr), (size), (prot), (flags), dev_zero_fd, 0)) : \\n" +
+"   mmap((addr), (size), (prot), (flags), dev_zero_fd, 0))\n" +
+"\n" +
+"#else\n" +
+"\n" +
+"#define MMAP(addr, size, prot, flags) \\n" +
+" (mmap((addr), (size), (prot), (flags)|MAP_ANONYMOUS, -1, 0))\n" +
+"\n" +
+"#endif\n" +
+"\n" +
+"\n" +
+"#endif /* HAVE_MMAP */\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  -----------------------  Chunk representations -----------------------\n" +
+"*/\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  This struct declaration is misleading (but accurate and necessary).\n" +
+"  It declares a \"view\" into memory allowing access to necessary\n" +
+"  fields at known offsets from a given base. See explanation below.\n" +
+"*/\n" +
+"\n" +
+"struct malloc_chunk {\n" +
+"\n" +
+"  INTERNAL_SIZE_T      prev_size;  /* Size of previous chunk (if free).  */\n" +
+"  INTERNAL_SIZE_T      size;       /* Size in bytes, including overhead. */\n" +
+"\n" +
+"  struct malloc_chunk* fd;         /* double links -- used only if free. */\n" +
+"  struct malloc_chunk* bk;\n" +
+"};\n" +
+"\n" +
+"\n" +
+"typedef struct malloc_chunk* mchunkptr;\n" +
+"\n" +
+"/*\n" +
+"   malloc_chunk details:\n" +
+"\n" +
+"    (The following includes lightly edited explanations by Colin Plumb.)\n" +
+"\n" +
+"    Chunks of memory are maintained using a `boundary tag' method as\n" +
+"    described in e.g., Knuth or Standish.  (See the paper by Paul\n" +
+"    Wilson ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a\n" +
+"    survey of such techniques.)  Sizes of free chunks are stored both\n" +
+"    in the front of each chunk and at the end.  This makes\n" +
+"    consolidating fragmented chunks into bigger chunks very fast.  The\n" +
+"    size fields also hold bits representing whether chunks are free or\n" +
+"    in use.\n" +
+"\n" +
+"    An allocated chunk looks like this:\n" +
+"\n" +
+"\n" +
+"    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n" +
+"            |             Size of previous chunk, if allocated            | |\n" +
+"            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n" +
+"            |             Size of chunk, in bytes                         |P|\n" +
+"      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n" +
+"            |             User data starts here...                          .\n" +
+"            .                                                               .\n" +
+"            .             (malloc_usable_space() bytes)                     .\n" +
+"            .                                                               |\n" +
+"nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n" +
+"            |             Size of chunk                                     |\n" +
+"            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n" +
+"\n") +
+("\n" +
+"    Where \"chunk\" is the front of the chunk for the purpose of most of\n" +
+"    the malloc code, but \"mem\" is the pointer that is returned to the\n" +
+"    user.  \"Nextchunk\" is the beginning of the next contiguous chunk.\n" +
+"\n" +
+"    Chunks always begin on even word boundries, so the mem portion\n" +
+"    (which is returned to the user) is also on an even word boundary, and\n" +
+"    thus at least double-word aligned.\n" +
+"\n" +
+"    Free chunks are stored in circular doubly-linked lists, and look like this:\n" +
+"\n" +
+"    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n" +
+"            |             Size of previous chunk                            |\n" +
+"            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n" +
+"    `head:' |             Size of chunk, in bytes                         |P|\n" +
+"      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n" +
+"            |             Forward pointer to next chunk in list             |\n" +
+"            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n" +
+"            |             Back pointer to previous chunk in list            |\n" +
+"            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n" +
+"            |             Unused space (may be 0 bytes long)                .\n" +
+"            .                                                               .\n" +
+"            .                                                               |\n" +
+"nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n" +
+"    `foot:' |             Size of chunk, in bytes                           |\n" +
+"            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n" +
+"\n" +
+"    The P (PREV_INUSE) bit, stored in the unused low-order bit of the\n" +
+"    chunk size (which is always a multiple of two words), is an in-use\n" +
+"    bit for the *previous* chunk.  If that bit is *clear*, then the\n" +
+"    word before the current chunk size contains the previous chunk\n" +
+"    size, and can be used to find the front of the previous chunk.\n" +
+"    The very first chunk allocated always has this bit set,\n" +
+"    preventing access to non-existent (or non-owned) memory. If\n" +
+"    prev_inuse is set for any given chunk, then you CANNOT determine\n" +
+"    the size of the previous chunk, and might even get a memory\n" +
+"    addressing fault when trying to do so.\n" +
+"\n" +
+"    Note that the `foot' of the current chunk is actually represented\n" +
+"    as the prev_size of the NEXT chunk. This makes it easier to\n" +
+"    deal with alignments etc but can be very confusing when trying\n" +
+"    to extend or adapt this code.\n" +
+"\n" +
+"    The two exceptions to all this are\n" +
+"\n" +
+"     1. The special chunk `top' doesn't bother using the\n" +
+"        trailing size field since there is no next contiguous chunk\n" +
+"        that would have to index off it. After initialization, `top'\n" +
+"        is forced to always exist.  If it would become less than\n" +
+"        MINSIZE bytes long, it is replenished.\n" +
+"\n" +
+"     2. Chunks allocated via mmap, which have the second-lowest-order\n" +
+"        bit (IS_MMAPPED) set in their size fields.  Because they are\n" +
+"        allocated one-by-one, each must contain its own trailing size field.\n" +
+"\n" +
+"*/\n" +
+"\n" +
+"/*\n" +
+"  ---------- Size and alignment checks and conversions ----------\n" +
+"*/\n" +
+"\n" +
+"/* conversion from malloc headers to user pointers, and back */\n" +
+"\n" +
+"#define chunk2mem(p)   ((Void_t*)((char*)(p) + 2*SIZE_SZ))\n" +
+"#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))\n" +
+"\n" +
+"/* The smallest possible chunk */\n" +
+"#define MIN_CHUNK_SIZE        (sizeof(struct malloc_chunk))\n" +
+"\n" +
+"/* The smallest size we can malloc is an aligned minimal chunk */\n" +
+"\n" +
+"#define MINSIZE  \\n" +
+"  (CHUNK_SIZE_T)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))\n" +
+"\n" +
+"/* Check if m has acceptable alignment */\n" +
+"\n" +
+"#define aligned_OK(m)  (((PTR_UINT)((m)) & (MALLOC_ALIGN_MASK)) == 0)\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"   Check if a request is so large that it would wrap around zero when\n" +
+"   padded and aligned. To simplify some other code, the bound is made\n" +
+"   low enough so that adding MINSIZE will also not wrap around sero.\n" +
+"*/\n" +
+"\n" +
+"#define REQUEST_OUT_OF_RANGE(req)                                 \\n" +
+"  ((CHUNK_SIZE_T)(req) >=                                        \\n" +
+"   (CHUNK_SIZE_T)(INTERNAL_SIZE_T)(-2 * MINSIZE))\n" +
+"\n" +
+"/* pad request bytes into a usable size -- internal version */\n" +
+"\n" +
+"#define request2size(req)                                         \\n" +
+"  (((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE)  ?             \\n" +
+"   MINSIZE :                                                      \\n" +
+"   ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)\n" +
+"\n" +
+"/*  Same, except also perform argument check */\n" +
+"\n" +
+"#define checked_request2size(req, sz)                             \\n" +
+"  if (REQUEST_OUT_OF_RANGE(req)) {                                \\n" +
+"    MALLOC_FAILURE_ACTION;                                        \\n" +
+"    return 0;                                                     \\n" +
+"  }                                                               \\n" +
+"  (sz) = request2size(req);\n" +
+"\n" +
+"/*\n" +
+"  --------------- Physical chunk operations ---------------\n" +
+"*/\n" +
+"\n" +
+"\n" +
+"/* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */\n" +
+"#define PREV_INUSE 0x1\n" +
+"\n" +
+"/* extract inuse bit of previous chunk */\n" +
+"#define prev_inuse(p)       ((p)->size & PREV_INUSE)\n" +
+"\n" +
+"\n" +
+"/* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */\n" +
+"#define IS_MMAPPED 0x2\n" +
+"\n" +
+"/* check for mmap()'ed chunk */\n" +
+"#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)\n" +
+"\n" +
+"/*\n" +
+"  Bits to mask off when extracting size\n" +
+"\n" +
+"  Note: IS_MMAPPED is intentionally not masked off from size field in\n" +
+"  macros for which mmapped chunks should never be seen. This should\n" +
+"  cause helpful core dumps to occur if it is tried by accident by\n" +
+"  people extending or adapting this malloc.\n" +
+"*/\n" +
+"#define SIZE_BITS (PREV_INUSE|IS_MMAPPED)\n" +
+"\n" +
+"/* Get size, ignoring use bits */\n" +
+"#define chunksize(p)         ((p)->size & ~(SIZE_BITS))\n" +
+"\n" +
+"\n" +
+"/* Ptr to next physical malloc_chunk. */\n" +
+"#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) ))\n" +
+"\n" +
+"/* Ptr to previous physical malloc_chunk */\n" +
+"#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) ))\n" +
+"\n" +
+"/* Treat space at ptr + offset as a chunk */\n" +
+"#define chunk_at_offset(p, s)  ((mchunkptr)(((char*)(p)) + (s)))\n" +
+"\n" +
+"/* extract p's inuse bit */\n" +
+"#define inuse(p)\\n" +
+"((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE)\n" +
+"\n" +
+"/* set/clear chunk as being inuse without otherwise disturbing */\n" +
+"#define set_inuse(p)\\n" +
+"((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE\n" +
+"\n") +
+("#define clear_inuse(p)\\n" +
+"((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE)\n" +
+"\n" +
+"\n" +
+"/* check/set/clear inuse bits in known places */\n" +
+"#define inuse_bit_at_offset(p, s)\\n" +
+" (((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE)\n" +
+"\n" +
+"#define set_inuse_bit_at_offset(p, s)\\n" +
+" (((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE)\n" +
+"\n" +
+"#define clear_inuse_bit_at_offset(p, s)\\n" +
+" (((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE))\n" +
+"\n" +
+"\n" +
+"/* Set size at head, without disturbing its use bit */\n" +
+"#define set_head_size(p, s)  ((p)->size = (((p)->size & PREV_INUSE) | (s)))\n" +
+"\n" +
+"/* Set size/use field */\n" +
+"#define set_head(p, s)       ((p)->size = (s))\n" +
+"\n" +
+"/* Set size at footer (only when chunk is not in use) */\n" +
+"#define set_foot(p, s)       (((mchunkptr)((char*)(p) + (s)))->prev_size = (s))\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  -------------------- Internal data structures --------------------\n" +
+"\n" +
+"   All internal state is held in an instance of malloc_state defined\n" +
+"   below. There are no other static variables, except in two optional\n" +
+"   cases:\n" +
+"   * If USE_MALLOC_LOCK is defined, the mALLOC_MUTEx declared above.\n" +
+"   * If HAVE_MMAP is true, but mmap doesn't support\n" +
+"     MAP_ANONYMOUS, a dummy file descriptor for mmap.\n" +
+"\n" +
+"   Beware of lots of tricks that minimize the total bookkeeping space\n" +
+"   requirements. The result is a little over 1K bytes (for 4byte\n" +
+"   pointers and size_t.)\n" +
+"*/\n" +
+"\n" +
+"/*\n" +
+"  Bins\n" +
+"\n" +
+"    An array of bin headers for free chunks. Each bin is doubly\n" +
+"    linked.  The bins are approximately proportionally (log) spaced.\n" +
+"    There are a lot of these bins (128). This may look excessive, but\n" +
+"    works very well in practice.  Most bins hold sizes that are\n" +
+"    unusual as malloc request sizes, but are more usual for fragments\n" +
+"    and consolidated sets of chunks, which is what these bins hold, so\n" +
+"    they can be found quickly.  All procedures maintain the invariant\n" +
+"    that no consolidated chunk physically borders another one, so each\n" +
+"    chunk in a list is known to be preceeded and followed by either\n" +
+"    inuse chunks or the ends of memory.\n" +
+"\n" +
+"    Chunks in bins are kept in size order, with ties going to the\n" +
+"    approximately least recently used chunk. Ordering isn't needed\n" +
+"    for the small bins, which all contain the same-sized chunks, but\n" +
+"    facilitates best-fit allocation for larger chunks. These lists\n" +
+"    are just sequential. Keeping them in order almost never requires\n" +
+"    enough traversal to warrant using fancier ordered data\n" +
+"    structures.\n" +
+"\n" +
+"    Chunks of the same size are linked with the most\n" +
+"    recently freed at the front, and allocations are taken from the\n" +
+"    back.  This results in LRU (FIFO) allocation order, which tends\n" +
+"    to give each chunk an equal opportunity to be consolidated with\n" +
+"    adjacent freed chunks, resulting in larger free chunks and less\n" +
+"    fragmentation.\n" +
+"\n" +
+"    To simplify use in double-linked lists, each bin header acts\n" +
+"    as a malloc_chunk. This avoids special-casing for headers.\n" +
+"    But to conserve space and improve locality, we allocate\n" +
+"    only the fd/bk pointers of bins, and then use repositioning tricks\n" +
+"    to treat these as the fields of a malloc_chunk*.\n" +
+"*/\n" +
+"\n" +
+"typedef struct malloc_chunk* mbinptr;\n" +
+"\n" +
+"/* addressing -- note that bin_at(0) does not exist */\n" +
+"#define bin_at(m, i) ((mbinptr)((char*)&((m)->bins[(i)<<1]) - (SIZE_SZ<<1)))\n" +
+"\n" +
+"/* analog of ++bin */\n" +
+"#define next_bin(b)  ((mbinptr)((char*)(b) + (sizeof(mchunkptr)<<1)))\n" +
+"\n" +
+"/* Reminders about list directionality within bins */\n" +
+"#define first(b)     ((b)->fd)\n" +
+"#define last(b)      ((b)->bk)\n" +
+"\n" +
+"/* Take a chunk off a bin list */\n" +
+"#define unlink(P, BK, FD) {                                            \\n" +
+"  FD = P->fd;                                                          \\n" +
+"  BK = P->bk;                                                          \\n" +
+"  FD->bk = BK;                                                         \\n" +
+"  BK->fd = FD;                                                         \\n" +
+"}\n" +
+"\n" +
+"/*\n" +
+"  Indexing\n" +
+"\n" +
+"    Bins for sizes < 512 bytes contain chunks of all the same size, spaced\n" +
+"    8 bytes apart. Larger bins are approximately logarithmically spaced:\n" +
+"\n" +
+"    64 bins of size       8\n" +
+"    32 bins of size      64\n" +
+"    16 bins of size     512\n" +
+"     8 bins of size    4096\n" +
+"     4 bins of size   32768\n" +
+"     2 bins of size  262144\n" +
+"     1 bin  of size what's left\n" +
+"\n" +
+"    The bins top out around 1MB because we expect to service large\n" +
+"    requests via mmap.\n" +
+"*/\n" +
+"\n" +
+"#define NBINS              96\n" +
+"#define NSMALLBINS         32\n" +
+"#define SMALLBIN_WIDTH      8\n" +
+"#define MIN_LARGE_SIZE    256\n" +
+"\n" +
+"#define in_smallbin_range(sz)  \\n" +
+"  ((CHUNK_SIZE_T)(sz) < (CHUNK_SIZE_T)MIN_LARGE_SIZE)\n" +
+"\n" +
+"#define smallbin_index(sz)     (((unsigned)(sz)) >> 3)\n" +
+"\n" +
+"/*\n" +
+"  Compute index for size. We expect this to be inlined when\n" +
+"  compiled with optimization, else not, which works out well.\n" +
+"*/\n" +
+"static int largebin_index(unsigned int sz) {\n" +
+"  unsigned int  x = sz >> SMALLBIN_WIDTH;\n" +
+"  unsigned int m;            /* bit position of highest set bit of m */\n" +
+"\n" +
+"  if (x >= 0x10000) return NBINS-1;\n" +
+"\n" +
+"  /* On intel, use BSRL instruction to find highest bit */\n" +
+"#if defined(__GNUC__) && defined(i386)\n" +
+"\n" +
+"  __asm__(\"bsrl %1,%0\\n\\t\"\n" +
+"          : \"=r\" (m)\n" +
+"          : \"g\"  (x));\n" +
+"\n" +
+"#else\n" +
+"  {\n" +
+"    /*\n" +
+"      Based on branch-free nlz algorithm in chapter 5 of Henry\n" +
+"      S. Warren Jr's book \"Hacker's Delight\".\n" +
+"    */\n" +
+"\n" +
+"    unsigned int n = ((x - 0x100) >> 16) & 8;\n" +
+"    x <<= n;\n" +
+"    m = ((x - 0x1000) >> 16) & 4;\n" +
+"    n += m;\n" +
+"    x <<= m;\n" +
+"    m = ((x - 0x4000) >> 16) & 2;\n" +
+"    n += m;\n" +
+"    x = (x << m) >> 14;\n" +
+"    m = 13 - n + (x & ~(x>>1));\n" +
+"  }\n" +
+"#endif\n" +
+"\n") +
+(
+"  /* Use next 2 bits to create finer-granularity bins */\n" +
+"  return NSMALLBINS + (m << 2) + ((sz >> (m + 6)) & 3);\n" +
+"}\n" +
+"\n" +
+"#define bin_index(sz) \\n" +
+" ((in_smallbin_range(sz)) ? smallbin_index(sz) : largebin_index(sz))\n" +
+"\n" +
+"/*\n" +
+"  FIRST_SORTED_BIN_SIZE is the chunk size corresponding to the\n" +
+"  first bin that is maintained in sorted order. This must\n" +
+"  be the smallest size corresponding to a given bin.\n" +
+"\n" +
+"  Normally, this should be MIN_LARGE_SIZE. But you can weaken\n" +
+"  best fit guarantees to sometimes speed up malloc by increasing value.\n" +
+"  Doing this means that malloc may choose a chunk that is\n" +
+"  non-best-fitting by up to the width of the bin.\n" +
+"\n" +
+"  Some useful cutoff values:\n" +
+"      512 - all bins sorted\n" +
+"     2560 - leaves bins <=     64 bytes wide unsorted\n" +
+"    12288 - leaves bins <=    512 bytes wide unsorted\n" +
+"    65536 - leaves bins <=   4096 bytes wide unsorted\n" +
+"   262144 - leaves bins <=  32768 bytes wide unsorted\n" +
+"       -1 - no bins sorted (not recommended!)\n" +
+"*/\n" +
+"\n" +
+"#define FIRST_SORTED_BIN_SIZE MIN_LARGE_SIZE\n" +
+"/* #define FIRST_SORTED_BIN_SIZE 65536 */\n" +
+"\n" +
+"/*\n" +
+"  Unsorted chunks\n" +
+"\n" +
+"    All remainders from chunk splits, as well as all returned chunks,\n" +
+"    are first placed in the \"unsorted\" bin. They are then placed\n" +
+"    in regular bins after malloc gives them ONE chance to be used before\n" +
+"    binning. So, basically, the unsorted_chunks list acts as a queue,\n" +
+"    with chunks being placed on it in free (and malloc_consolidate),\n" +
+"    and taken off (to be either used or placed in bins) in malloc.\n" +
+"*/\n" +
+"\n" +
+"/* The otherwise unindexable 1-bin is used to hold unsorted chunks. */\n" +
+"#define unsorted_chunks(M)          (bin_at(M, 1))\n" +
+"\n" +
+"/*\n" +
+"  Top\n" +
+"\n" +
+"    The top-most available chunk (i.e., the one bordering the end of\n" +
+"    available memory) is treated specially. It is never included in\n" +
+"    any bin, is used only if no other chunk is available, and is\n" +
+"    released back to the system if it is very large (see\n" +
+"    M_TRIM_THRESHOLD).  Because top initially\n" +
+"    points to its own bin with initial zero size, thus forcing\n" +
+"    extension on the first malloc request, we avoid having any special\n" +
+"    code in malloc to check whether it even exists yet. But we still\n" +
+"    need to do so when getting memory from system, so we make\n" +
+"    initial_top treat the bin as a legal but unusable chunk during the\n" +
+"    interval between initialization and the first call to\n" +
+"    sYSMALLOc. (This is somewhat delicate, since it relies on\n" +
+"    the 2 preceding words to be zero during this interval as well.)\n" +
+"*/\n" +
+"\n" +
+"/* Conveniently, the unsorted bin can be used as dummy top on first call */\n" +
+"#define initial_top(M)              (unsorted_chunks(M))\n" +
+"\n" +
+"/*\n" +
+"  Binmap\n" +
+"\n" +
+"    To help compensate for the large number of bins, a one-level index\n" +
+"    structure is used for bin-by-bin searching.  `binmap' is a\n" +
+"    bitvector recording whether bins are definitely empty so they can\n" +
+"    be skipped over during during traversals.  The bits are NOT always\n" +
+"    cleared as soon as bins are empty, but instead only\n" +
+"    when they are noticed to be empty during traversal in malloc.\n" +
+"*/\n" +
+"\n" +
+"/* Conservatively use 32 bits per map word, even if on 64bit system */\n" +
+"#define BINMAPSHIFT      5\n" +
+"#define BITSPERMAP       (1U << BINMAPSHIFT)\n" +
+"#define BINMAPSIZE       (NBINS / BITSPERMAP)\n" +
+"\n" +
+"#define idx2block(i)     ((i) >> BINMAPSHIFT)\n" +
+"#define idx2bit(i)       ((1U << ((i) & ((1U << BINMAPSHIFT)-1))))\n" +
+"\n" +
+"#define mark_bin(m,i)    ((m)->binmap[idx2block(i)] |=  idx2bit(i))\n" +
+"#define unmark_bin(m,i)  ((m)->binmap[idx2block(i)] &= ~(idx2bit(i)))\n" +
+"#define get_binmap(m,i)  ((m)->binmap[idx2block(i)] &   idx2bit(i))\n" +
+"\n" +
+"/*\n" +
+"  Fastbins\n" +
+"\n" +
+"    An array of lists holding recently freed small chunks.  Fastbins\n" +
+"    are not doubly linked.  It is faster to single-link them, and\n" +
+"    since chunks are never removed from the middles of these lists,\n" +
+"    double linking is not necessary. Also, unlike regular bins, they\n" +
+"    are not even processed in FIFO order (they use faster LIFO) since\n" +
+"    ordering doesn't much matter in the transient contexts in which\n" +
+"    fastbins are normally used.\n" +
+"\n" +
+"    Chunks in fastbins keep their inuse bit set, so they cannot\n" +
+"    be consolidated with other free chunks. malloc_consolidate\n" +
+"    releases all chunks in fastbins and consolidates them with\n" +
+"    other free chunks.\n" +
+"*/\n" +
+"\n" +
+"typedef struct malloc_chunk* mfastbinptr;\n" +
+"\n" +
+"/* offset 2 to use otherwise unindexable first 2 bins */\n" +
+"#define fastbin_index(sz)        ((((unsigned int)(sz)) >> 3) - 2)\n" +
+"\n" +
+"/* The maximum fastbin request size we support */\n" +
+"#define MAX_FAST_SIZE     80\n" +
+"\n" +
+"#define NFASTBINS  (fastbin_index(request2size(MAX_FAST_SIZE))+1)\n" +
+"\n" +
+"/*\n" +
+"  FASTBIN_CONSOLIDATION_THRESHOLD is the size of a chunk in free()\n" +
+"  that triggers automatic consolidation of possibly-surrounding\n" +
+"  fastbin chunks. This is a heuristic, so the exact value should not\n" +
+"  matter too much. It is defined at half the default trim threshold as a\n" +
+"  compromise heuristic to only attempt consolidation if it is likely\n" +
+"  to lead to trimming. However, it is not dynamically tunable, since\n" +
+"  consolidation reduces fragmentation surrounding loarge chunks even\n" +
+"  if trimming is not used.\n" +
+"*/\n" +
+"\n" +
+"#define FASTBIN_CONSOLIDATION_THRESHOLD  \\n" +
+"  ((unsigned long)(DEFAULT_TRIM_THRESHOLD) >> 1)\n" +
+"\n" +
+"/*\n" +
+"  Since the lowest 2 bits in max_fast don't matter in size comparisons,\n" +
+"  they are used as flags.\n" +
+"*/\n" +
+"\n" +
+"/*\n" +
+"  ANYCHUNKS_BIT held in max_fast indicates that there may be any\n" +
+"  freed chunks at all. It is set true when entering a chunk into any\n" +
+"  bin.\n" +
+"*/\n" +
+"\n" +
+"#define ANYCHUNKS_BIT        (1U)\n" +
+"\n" +
+"#define have_anychunks(M)     (((M)->max_fast &  ANYCHUNKS_BIT))\n" +
+"#define set_anychunks(M)      ((M)->max_fast |=  ANYCHUNKS_BIT)\n" +
+"#define clear_anychunks(M)    ((M)->max_fast &= ~ANYCHUNKS_BIT)\n" +
+"\n" +
+"/*\n" +
+"  FASTCHUNKS_BIT held in max_fast indicates that there are probably\n" +
+"  some fastbin chunks. It is set true on entering a chunk into any\n" +
+"  fastbin, and cleared only in malloc_consolidate.\n" +
+"*/\n" +
+"\n") +
+(
+"#define FASTCHUNKS_BIT        (2U)\n" +
+"\n" +
+"#define have_fastchunks(M)   (((M)->max_fast &  FASTCHUNKS_BIT))\n" +
+"#define set_fastchunks(M)    ((M)->max_fast |=  (FASTCHUNKS_BIT|ANYCHUNKS_BIT))\n" +
+"#define clear_fastchunks(M)  ((M)->max_fast &= ~(FASTCHUNKS_BIT))\n" +
+"\n" +
+"/*\n" +
+"   Set value of max_fast.\n" +
+"   Use impossibly small value if 0.\n" +
+"*/\n" +
+"\n" +
+"#define set_max_fast(M, s) \\n" +
+"  (M)->max_fast = (((s) == 0)? SMALLBIN_WIDTH: request2size(s)) | \\n" +
+"  ((M)->max_fast &  (FASTCHUNKS_BIT|ANYCHUNKS_BIT))\n" +
+"\n" +
+"#define get_max_fast(M) \\n" +
+"  ((M)->max_fast & ~(FASTCHUNKS_BIT | ANYCHUNKS_BIT))\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  morecore_properties is a status word holding dynamically discovered\n" +
+"  or controlled properties of the morecore function\n" +
+"*/\n" +
+"\n" +
+"#define MORECORE_CONTIGUOUS_BIT  (1U)\n" +
+"\n" +
+"#define contiguous(M) \\n" +
+"        (((M)->morecore_properties &  MORECORE_CONTIGUOUS_BIT))\n" +
+"#define noncontiguous(M) \\n" +
+"        (((M)->morecore_properties &  MORECORE_CONTIGUOUS_BIT) == 0)\n" +
+"#define set_contiguous(M) \\n" +
+"        ((M)->morecore_properties |=  MORECORE_CONTIGUOUS_BIT)\n" +
+"#define set_noncontiguous(M) \\n" +
+"        ((M)->morecore_properties &= ~MORECORE_CONTIGUOUS_BIT)\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"   ----------- Internal state representation and initialization -----------\n" +
+"*/\n" +
+"\n" +
+"struct malloc_state {\n" +
+"\n" +
+"  /* The maximum chunk size to be eligible for fastbin */\n" +
+"  INTERNAL_SIZE_T  max_fast;   /* low 2 bits used as flags */\n" +
+"\n" +
+"  /* Fastbins */\n" +
+"  mfastbinptr      fastbins[NFASTBINS];\n" +
+"\n" +
+"  /* Base of the topmost chunk -- not otherwise kept in a bin */\n" +
+"  mchunkptr        top;\n" +
+"\n" +
+"  /* The remainder from the most recent split of a small request */\n" +
+"  mchunkptr        last_remainder;\n" +
+"\n" +
+"  /* Normal bins packed as described above */\n" +
+"  mchunkptr        bins[NBINS * 2];\n" +
+"\n" +
+"  /* Bitmap of bins. Trailing zero map handles cases of largest binned size */\n" +
+"  unsigned int     binmap[BINMAPSIZE+1];\n" +
+"\n" +
+"  /* Tunable parameters */\n" +
+"  CHUNK_SIZE_T     trim_threshold;\n" +
+"  INTERNAL_SIZE_T  top_pad;\n" +
+"  INTERNAL_SIZE_T  mmap_threshold;\n" +
+"\n" +
+"  /* Memory map support */\n" +
+"  int              n_mmaps;\n" +
+"  int              n_mmaps_max;\n" +
+"  int              max_n_mmaps;\n" +
+"\n" +
+"  /* Cache malloc_getpagesize */\n" +
+"  unsigned int     pagesize;\n" +
+"\n" +
+"  /* Track properties of MORECORE */\n" +
+"  unsigned int     morecore_properties;\n" +
+"\n" +
+"  /* Statistics */\n" +
+"  INTERNAL_SIZE_T  mmapped_mem;\n" +
+"  INTERNAL_SIZE_T  sbrked_mem;\n" +
+"  INTERNAL_SIZE_T  max_sbrked_mem;\n" +
+"  INTERNAL_SIZE_T  max_mmapped_mem;\n" +
+"  INTERNAL_SIZE_T  max_total_mem;\n" +
+"};\n" +
+"\n" +
+"typedef struct malloc_state *mstate;\n" +
+"\n" +
+"/*\n" +
+"   There is exactly one instance of this struct in this malloc.\n" +
+"   If you are adapting this malloc in a way that does NOT use a static\n" +
+"   malloc_state, you MUST explicitly zero-fill it before using. This\n" +
+"   malloc relies on the property that malloc_state is initialized to\n" +
+"   all zeroes (as is true of C statics).\n" +
+"*/\n" +
+"\n" +
+"static struct malloc_state av_;  /* never directly referenced */\n" +
+"\n" +
+"/*\n" +
+"   All uses of av_ are via get_malloc_state().\n" +
+"   At most one \"call\" to get_malloc_state is made per invocation of\n" +
+"   the public versions of malloc and free, but other routines\n" +
+"   that in turn invoke malloc and/or free may call more then once.\n" +
+"   Also, it is called in check* routines if DEBUG is set.\n" +
+"*/\n" +
+"\n" +
+"#define get_malloc_state() (&(av_))\n" +
+"\n" +
+"/*\n" +
+"  Initialize a malloc_state struct.\n" +
+"\n" +
+"  This is called only from within malloc_consolidate, which needs\n" +
+"  be called in the same contexts anyway.  It is never called directly\n" +
+"  outside of malloc_consolidate because some optimizing compilers try\n" +
+"  to inline it at all call points, which turns out not to be an\n" +
+"  optimization at all. (Inlining it in malloc_consolidate is fine though.)\n" +
+"*/\n" +
+"\n" +
+"#if __STD_C\n" +
+"static void malloc_init_state(mstate av)\n" +
+"#else\n" +
+"static void malloc_init_state(av) mstate av;\n" +
+"#endif\n" +
+"{\n" +
+"  int     i;\n" +
+"  mbinptr bin;\n" +
+"\n" +
+"  /* Establish circular links for normal bins */\n" +
+"  for (i = 1; i < NBINS; ++i) {\n" +
+"    bin = bin_at(av,i);\n" +
+"    bin->fd = bin->bk = bin;\n" +
+"  }\n" +
+"\n" +
+"  av->top_pad        = DEFAULT_TOP_PAD;\n" +
+"  av->n_mmaps_max    = DEFAULT_MMAP_MAX;\n" +
+"  av->mmap_threshold = DEFAULT_MMAP_THRESHOLD;\n" +
+"  av->trim_threshold = DEFAULT_TRIM_THRESHOLD;\n" +
+"\n" +
+"#if MORECORE_CONTIGUOUS\n" +
+"  set_contiguous(av);\n" +
+"#else\n" +
+"  set_noncontiguous(av);\n" +
+"#endif\n" +
+"\n" +
+"\n" +
+"  set_max_fast(av, DEFAULT_MXFAST);\n" +
+"\n" +
+"  av->top            = initial_top(av);\n" +
+"  av->pagesize       = malloc_getpagesize;\n" +
+"}\n" +
+"\n" +
+"/*\n" +
+"   Other internal utilities operating on mstates\n" +
+"*/\n" +
+"\n") +
+(
+"#if __STD_C\n" +
+"static Void_t*  sYSMALLOc(INTERNAL_SIZE_T, mstate);\n" +
+"#ifndef MORECORE_CANNOT_TRIM\n" +
+"static int      sYSTRIm(size_t, mstate);\n" +
+"#endif\n" +
+"static void     malloc_consolidate(mstate);\n" +
+"static Void_t** iALLOc(size_t, size_t*, int, Void_t**);\n" +
+"#else\n" +
+"static Void_t*  sYSMALLOc();\n" +
+"static int      sYSTRIm();\n" +
+"static void     malloc_consolidate();\n" +
+"static Void_t** iALLOc();\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  Debugging support\n" +
+"\n" +
+"  These routines make a number of assertions about the states\n" +
+"  of data structures that should be true at all times. If any\n" +
+"  are not true, it's very likely that a user program has somehow\n" +
+"  trashed memory. (It's also possible that there is a coding error\n" +
+"  in malloc. In which case, please report it!)\n" +
+"*/\n" +
+"\n" +
+"#if ! DEBUG\n" +
+"\n" +
+"#define check_chunk(P)\n" +
+"#define check_free_chunk(P)\n" +
+"#define check_inuse_chunk(P)\n" +
+"#define check_remalloced_chunk(P,N)\n" +
+"#define check_malloced_chunk(P,N)\n" +
+"#define check_malloc_state()\n" +
+"\n" +
+"#else\n" +
+"#define check_chunk(P)              do_check_chunk(P)\n" +
+"#define check_free_chunk(P)         do_check_free_chunk(P)\n" +
+"#define check_inuse_chunk(P)        do_check_inuse_chunk(P)\n" +
+"#define check_remalloced_chunk(P,N) do_check_remalloced_chunk(P,N)\n" +
+"#define check_malloced_chunk(P,N)   do_check_malloced_chunk(P,N)\n" +
+"#define check_malloc_state()        do_check_malloc_state()\n" +
+"\n" +
+"/*\n" +
+"  Properties of all chunks\n" +
+"*/\n" +
+"\n" +
+"#if __STD_C\n" +
+"static void do_check_chunk(mchunkptr p)\n" +
+"#else\n" +
+"static void do_check_chunk(p) mchunkptr p;\n" +
+"#endif\n" +
+"{\n" +
+"  mstate av = get_malloc_state();\n" +
+"  CHUNK_SIZE_T  sz = chunksize(p);\n" +
+"  /* min and max possible addresses assuming contiguous allocation */\n" +
+"  char* max_address = (char*)(av->top) + chunksize(av->top);\n" +
+"  char* min_address = max_address - av->sbrked_mem;\n" +
+"\n" +
+"  if (!chunk_is_mmapped(p)) {\n" +
+"\n" +
+"    /* Has legal address ... */\n" +
+"    if (p != av->top) {\n" +
+"      if (contiguous(av)) {\n" +
+"        assert(((char*)p) >= min_address);\n" +
+"        assert(((char*)p + sz) <= ((char*)(av->top)));\n" +
+"      }\n" +
+"    }\n" +
+"    else {\n" +
+"      /* top size is always at least MINSIZE */\n" +
+"      assert((CHUNK_SIZE_T)(sz) >= MINSIZE);\n" +
+"      /* top predecessor always marked inuse */\n" +
+"      assert(prev_inuse(p));\n" +
+"    }\n" +
+"\n" +
+"  }\n" +
+"  else {\n" +
+"#if HAVE_MMAP\n" +
+"    /* address is outside main heap  */\n" +
+"    if (contiguous(av) && av->top != initial_top(av)) {\n" +
+"      assert(((char*)p) < min_address || ((char*)p) > max_address);\n" +
+"    }\n" +
+"    /* chunk is page-aligned */\n" +
+"    assert(((p->prev_size + sz) & (av->pagesize-1)) == 0);\n" +
+"    /* mem is aligned */\n" +
+"    assert(aligned_OK(chunk2mem(p)));\n" +
+"#else\n" +
+"    /* force an appropriate assert violation if debug set */\n" +
+"    assert(!chunk_is_mmapped(p));\n" +
+"#endif\n" +
+"  }\n" +
+"}\n" +
+"\n" +
+"/*\n" +
+"  Properties of free chunks\n" +
+"*/\n" +
+"\n" +
+"#if __STD_C\n" +
+"static void do_check_free_chunk(mchunkptr p)\n" +
+"#else\n" +
+"static void do_check_free_chunk(p) mchunkptr p;\n" +
+"#endif\n" +
+"{\n" +
+"  mstate av = get_malloc_state();\n" +
+"\n" +
+"  INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;\n" +
+"  mchunkptr next = chunk_at_offset(p, sz);\n" +
+"\n" +
+"  do_check_chunk(p);\n" +
+"\n" +
+"  /* Chunk must claim to be free ... */\n" +
+"  assert(!inuse(p));\n" +
+"  assert (!chunk_is_mmapped(p));\n" +
+"\n" +
+"  /* Unless a special marker, must have OK fields */\n" +
+"  if ((CHUNK_SIZE_T)(sz) >= MINSIZE)\n" +
+"  {\n" +
+"    assert((sz & MALLOC_ALIGN_MASK) == 0);\n" +
+"    assert(aligned_OK(chunk2mem(p)));\n" +
+"    /* ... matching footer field */\n" +
+"    assert(next->prev_size == sz);\n" +
+"    /* ... and is fully consolidated */\n" +
+"    assert(prev_inuse(p));\n" +
+"    assert (next == av->top || inuse(next));\n" +
+"\n" +
+"    /* ... and has minimally sane links */\n" +
+"    assert(p->fd->bk == p);\n" +
+"    assert(p->bk->fd == p);\n" +
+"  }\n" +
+"  else /* markers are always of size SIZE_SZ */\n" +
+"    assert(sz == SIZE_SZ);\n" +
+"}\n" +
+"\n" +
+"/*\n" +
+"  Properties of inuse chunks\n" +
+"*/\n" +
+"\n" +
+"#if __STD_C\n" +
+"static void do_check_inuse_chunk(mchunkptr p)\n" +
+"#else\n" +
+"static void do_check_inuse_chunk(p) mchunkptr p;\n" +
+"#endif\n" +
+"{\n" +
+"  mstate av = get_malloc_state();\n" +
+"  mchunkptr next;\n" +
+"  do_check_chunk(p);\n" +
+"\n" +
+"  if (chunk_is_mmapped(p))\n" +
+"    return; /* mmapped chunks have no next/prev */\n" +
+"\n" +
+"  /* Check whether it claims to be in use ... */\n" +
+"  assert(inuse(p));\n" +
+"\n") +
+(
+"  next = next_chunk(p);\n" +
+"\n" +
+"  /* ... and is surrounded by OK chunks.\n" +
+"    Since more things can be checked with free chunks than inuse ones,\n" +
+"    if an inuse chunk borders them and debug is on, it's worth doing them.\n" +
+"  */\n" +
+"  if (!prev_inuse(p))  {\n" +
+"    /* Note that we cannot even look at prev unless it is not inuse */\n" +
+"    mchunkptr prv = prev_chunk(p);\n" +
+"    assert(next_chunk(prv) == p);\n" +
+"    do_check_free_chunk(prv);\n" +
+"  }\n" +
+"\n" +
+"  if (next == av->top) {\n" +
+"    assert(prev_inuse(next));\n" +
+"    assert(chunksize(next) >= MINSIZE);\n" +
+"  }\n" +
+"  else if (!inuse(next))\n" +
+"    do_check_free_chunk(next);\n" +
+"}\n" +
+"\n" +
+"/*\n" +
+"  Properties of chunks recycled from fastbins\n" +
+"*/\n" +
+"\n" +
+"#if __STD_C\n" +
+"static void do_check_remalloced_chunk(mchunkptr p, INTERNAL_SIZE_T s)\n" +
+"#else\n" +
+"static void do_check_remalloced_chunk(p, s) mchunkptr p; INTERNAL_SIZE_T s;\n" +
+"#endif\n" +
+"{\n" +
+"  INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;\n" +
+"\n" +
+"  do_check_inuse_chunk(p);\n" +
+"\n" +
+"  /* Legal size ... */\n" +
+"  assert((sz & MALLOC_ALIGN_MASK) == 0);\n" +
+"  assert((CHUNK_SIZE_T)(sz) >= MINSIZE);\n" +
+"  /* ... and alignment */\n" +
+"  assert(aligned_OK(chunk2mem(p)));\n" +
+"  /* chunk is less than MINSIZE more than request */\n" +
+"  assert((long)(sz) - (long)(s) >= 0);\n" +
+"  assert((long)(sz) - (long)(s + MINSIZE) < 0);\n" +
+"}\n" +
+"\n" +
+"/*\n" +
+"  Properties of nonrecycled chunks at the point they are malloced\n" +
+"*/\n" +
+"\n" +
+"#if __STD_C\n" +
+"static void do_check_malloced_chunk(mchunkptr p, INTERNAL_SIZE_T s)\n" +
+"#else\n" +
+"static void do_check_malloced_chunk(p, s) mchunkptr p; INTERNAL_SIZE_T s;\n" +
+"#endif\n" +
+"{\n" +
+"  /* same as recycled case ... */\n" +
+"  do_check_remalloced_chunk(p, s);\n" +
+"\n" +
+"  /*\n" +
+"    ... plus,  must obey implementation invariant that prev_inuse is\n" +
+"    always true of any allocated chunk; i.e., that each allocated\n" +
+"    chunk borders either a previously allocated and still in-use\n" +
+"    chunk, or the base of its memory arena. This is ensured\n" +
+"    by making all allocations from the the `lowest' part of any found\n" +
+"    chunk.  This does not necessarily hold however for chunks\n" +
+"    recycled via fastbins.\n" +
+"  */\n" +
+"\n" +
+"  assert(prev_inuse(p));\n" +
+"}\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  Properties of malloc_state.\n" +
+"\n" +
+"  This may be useful for debugging malloc, as well as detecting user\n" +
+"  programmer errors that somehow write into malloc_state.\n" +
+"\n" +
+"  If you are extending or experimenting with this malloc, you can\n" +
+"  probably figure out how to hack this routine to print out or\n" +
+"  display chunk addresses, sizes, bins, and other instrumentation.\n" +
+"*/\n" +
+"\n" +
+"static void do_check_malloc_state()\n" +
+"{\n" +
+"  mstate av = get_malloc_state();\n" +
+"  unsigned int i;\n" +
+"  mchunkptr p;\n" +
+"  mchunkptr q;\n" +
+"  mbinptr b;\n" +
+"  unsigned int binbit;\n" +
+"  int empty;\n" +
+"  unsigned int idx;\n" +
+"  INTERNAL_SIZE_T size;\n" +
+"  CHUNK_SIZE_T  total = 0;\n" +
+"  int max_fast_bin;\n" +
+"\n" +
+"  /* internal size_t must be no wider than pointer type */\n" +
+"  assert(sizeof(INTERNAL_SIZE_T) <= sizeof(char*));\n" +
+"\n" +
+"  /* alignment is a power of 2 */\n" +
+"  assert((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-1)) == 0);\n" +
+"\n" +
+"  /* cannot run remaining checks until fully initialized */\n" +
+"  if (av->top == 0 || av->top == initial_top(av))\n" +
+"    return;\n" +
+"\n" +
+"  /* pagesize is a power of 2 */\n" +
+"  assert((av->pagesize & (av->pagesize-1)) == 0);\n" +
+"\n" +
+"  /* properties of fastbins */\n" +
+"\n" +
+"  /* max_fast is in allowed range */\n" +
+"  assert(get_max_fast(av) <= request2size(MAX_FAST_SIZE));\n" +
+"\n" +
+"  max_fast_bin = fastbin_index(av->max_fast);\n" +
+"\n" +
+"  for (i = 0; i < NFASTBINS; ++i) {\n" +
+"    p = av->fastbins[i];\n" +
+"\n" +
+"    /* all bins past max_fast are empty */\n" +
+"    if (i > max_fast_bin)\n" +
+"      assert(p == 0);\n" +
+"\n" +
+"    while (p != 0) {\n" +
+"      /* each chunk claims to be inuse */\n" +
+"      do_check_inuse_chunk(p);\n" +
+"      total += chunksize(p);\n" +
+"      /* chunk belongs in this bin */\n" +
+"      assert(fastbin_index(chunksize(p)) == i);\n" +
+"      p = p->fd;\n" +
+"    }\n" +
+"  }\n" +
+"\n" +
+"  if (total != 0)\n" +
+"    assert(have_fastchunks(av));\n" +
+"  else if (!have_fastchunks(av))\n" +
+"    assert(total == 0);\n" +
+"\n" +
+"  /* check normal bins */\n" +
+"  for (i = 1; i < NBINS; ++i) {\n" +
+"    b = bin_at(av,i);\n" +
+"\n" +
+"    /* binmap is accurate (except for bin 1 == unsorted_chunks) */\n" +
+"    if (i >= 2) {\n" +
+"      binbit = get_binmap(av,i);\n" +
+"      empty = last(b) == b;\n" +
+"      if (!binbit)\n" +
+"        assert(empty);\n" +
+"      else if (!empty)\n" +
+"        assert(binbit);\n" +
+"    }\n" +
+"\n") +
+(
+"    for (p = last(b); p != b; p = p->bk) {\n" +
+"      /* each chunk claims to be free */\n" +
+"      do_check_free_chunk(p);\n" +
+"      size = chunksize(p);\n" +
+"      total += size;\n" +
+"      if (i >= 2) {\n" +
+"        /* chunk belongs in bin */\n" +
+"        idx = bin_index(size);\n" +
+"        assert(idx == i);\n" +
+"        /* lists are sorted */\n" +
+"        if ((CHUNK_SIZE_T) size >= (CHUNK_SIZE_T)(FIRST_SORTED_BIN_SIZE)) {\n" +
+"          assert(p->bk == b ||\n" +
+"                 (CHUNK_SIZE_T)chunksize(p->bk) >=\n" +
+"                 (CHUNK_SIZE_T)chunksize(p));\n" +
+"        }\n" +
+"      }\n" +
+"      /* chunk is followed by a legal chain of inuse chunks */\n" +
+"      for (q = next_chunk(p);\n" +
+"           (q != av->top && inuse(q) &&\n" +
+"             (CHUNK_SIZE_T)(chunksize(q)) >= MINSIZE);\n" +
+"           q = next_chunk(q))\n" +
+"        do_check_inuse_chunk(q);\n" +
+"    }\n" +
+"  }\n" +
+"\n" +
+"  /* top chunk is OK */\n" +
+"  check_chunk(av->top);\n" +
+"\n" +
+"  /* sanity checks for statistics */\n" +
+"\n" +
+"  assert(total <= (CHUNK_SIZE_T)(av->max_total_mem));\n" +
+"  assert(av->n_mmaps >= 0);\n" +
+"  assert(av->n_mmaps <= av->max_n_mmaps);\n" +
+"\n" +
+"  assert((CHUNK_SIZE_T)(av->sbrked_mem) <=\n" +
+"         (CHUNK_SIZE_T)(av->max_sbrked_mem));\n" +
+"\n" +
+"  assert((CHUNK_SIZE_T)(av->mmapped_mem) <=\n" +
+"         (CHUNK_SIZE_T)(av->max_mmapped_mem));\n" +
+"\n" +
+"  assert((CHUNK_SIZE_T)(av->max_total_mem) >=\n" +
+"         (CHUNK_SIZE_T)(av->mmapped_mem) + (CHUNK_SIZE_T)(av->sbrked_mem));\n" +
+"}\n" +
+"#endif\n" +
+"\n" +
+"\n" +
+"/* ----------- Routines dealing with system allocation -------------- */\n" +
+"\n" +
+"/*\n" +
+"  sysmalloc handles malloc cases requiring more memory from the system.\n" +
+"  On entry, it is assumed that av->top does not have enough\n" +
+"  space to service request for nb bytes, thus requiring that av->top\n" +
+"  be extended or replaced.\n" +
+"*/\n" +
+"\n" +
+"#if __STD_C\n" +
+"static Void_t* sYSMALLOc(INTERNAL_SIZE_T nb, mstate av)\n" +
+"#else\n" +
+"static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av;\n" +
+"#endif\n" +
+"{\n" +
+"  mchunkptr       old_top;        /* incoming value of av->top */\n" +
+"  INTERNAL_SIZE_T old_size;       /* its size */\n" +
+"  char*           old_end;        /* its end address */\n" +
+"\n" +
+"  long            size;           /* arg to first MORECORE or mmap call */\n" +
+"  char*           brk;            /* return value from MORECORE */\n" +
+"\n" +
+"  long            correction;     /* arg to 2nd MORECORE call */\n" +
+"  char*           snd_brk;        /* 2nd return val */\n" +
+"\n" +
+"  INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of new space */\n" +
+"  INTERNAL_SIZE_T end_misalign;   /* partial page left at end of new space */\n" +
+"  char*           aligned_brk;    /* aligned offset into brk */\n" +
+"\n" +
+"  mchunkptr       p;              /* the allocated/returned chunk */\n" +
+"  mchunkptr       remainder;      /* remainder from allocation */\n" +
+"  CHUNK_SIZE_T    remainder_size; /* its size */\n" +
+"\n" +
+"  CHUNK_SIZE_T    sum;            /* for updating stats */\n" +
+"\n" +
+"  size_t          pagemask  = av->pagesize - 1;\n" +
+"\n" +
+"  /*\n" +
+"    If there is space available in fastbins, consolidate and retry\n" +
+"    malloc from scratch rather than getting memory from system.  This\n" +
+"    can occur only if nb is in smallbin range so we didn't consolidate\n" +
+"    upon entry to malloc. It is much easier to handle this case here\n" +
+"    than in malloc proper.\n" +
+"  */\n" +
+"\n" +
+"  if (have_fastchunks(av)) {\n" +
+"    assert(in_smallbin_range(nb));\n" +
+"    malloc_consolidate(av);\n" +
+"    return mALLOc(nb - MALLOC_ALIGN_MASK);\n" +
+"  }\n" +
+"\n" +
+"\n" +
+"#if HAVE_MMAP\n" +
+"\n" +
+"  /*\n" +
+"    If have mmap, and the request size meets the mmap threshold, and\n" +
+"    the system supports mmap, and there are few enough currently\n" +
+"    allocated mmapped regions, try to directly map this request\n" +
+"    rather than expanding top.\n" +
+"  */\n" +
+"\n" +
+"  if ((CHUNK_SIZE_T)(nb) >= (CHUNK_SIZE_T)(av->mmap_threshold) &&\n" +
+"      (av->n_mmaps < av->n_mmaps_max)) {\n" +
+"\n" +
+"    char* mm;             /* return value from mmap call*/\n" +
+"\n" +
+"    /*\n" +
+"      Round up size to nearest page.  For mmapped chunks, the overhead\n" +
+"      is one SIZE_SZ unit larger than for normal chunks, because there\n" +
+"      is no following chunk whose prev_size field could be used.\n" +
+"    */\n" +
+"    size = (nb + SIZE_SZ + MALLOC_ALIGN_MASK + pagemask) & ~pagemask;\n" +
+"\n" +
+"    /* Don't try if size wraps around 0 */\n" +
+"    if ((CHUNK_SIZE_T)(size) > (CHUNK_SIZE_T)(nb)) {\n" +
+"\n" +
+"      mm = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE));\n" +
+"\n" +
+"      if (mm != (char*)(MORECORE_FAILURE)) {\n" +
+"\n" +
+"        /*\n" +
+"          The offset to the start of the mmapped region is stored\n" +
+"          in the prev_size field of the chunk. This allows us to adjust\n" +
+"          returned start address to meet alignment requirements here\n" +
+"          and in memalign(), and still be able to compute proper\n" +
+"          address argument for later munmap in free() and realloc().\n" +
+"        */\n" +
+"\n" +
+"        front_misalign = (INTERNAL_SIZE_T)chunk2mem(mm) & MALLOC_ALIGN_MASK;\n" +
+"        if (front_misalign > 0) {\n" +
+"          correction = MALLOC_ALIGNMENT - front_misalign;\n" +
+"          p = (mchunkptr)(mm + correction);\n" +
+"          p->prev_size = correction;\n" +
+"          set_head(p, (size - correction) |IS_MMAPPED);\n" +
+"        }\n" +
+"        else {\n" +
+"          p = (mchunkptr)mm;\n" +
+"          p->prev_size = 0;\n" +
+"          set_head(p, size|IS_MMAPPED);\n" +
+"        }\n" +
+"\n" +
+"        /* update statistics */\n" +
+"\n" +
+"        if (++av->n_mmaps > av->max_n_mmaps)\n" +
+"          av->max_n_mmaps = av->n_mmaps;\n" +
+"\n") +
+(
+"        sum = av->mmapped_mem += size;\n" +
+"        if (sum > (CHUNK_SIZE_T)(av->max_mmapped_mem))\n" +
+"          av->max_mmapped_mem = sum;\n" +
+"        sum += av->sbrked_mem;\n" +
+"        if (sum > (CHUNK_SIZE_T)(av->max_total_mem))\n" +
+"          av->max_total_mem = sum;\n" +
+"\n" +
+"        check_chunk(p);\n" +
+"\n" +
+"        return chunk2mem(p);\n" +
+"      }\n" +
+"    }\n" +
+"  }\n" +
+"#endif\n" +
+"\n" +
+"  /* Record incoming configuration of top */\n" +
+"\n" +
+"  old_top  = av->top;\n" +
+"  old_size = chunksize(old_top);\n" +
+"  old_end  = (char*)(chunk_at_offset(old_top, old_size));\n" +
+"\n" +
+"  brk = snd_brk = (char*)(MORECORE_FAILURE);\n" +
+"\n" +
+"  /*\n" +
+"     If not the first time through, we require old_size to be\n" +
+"     at least MINSIZE and to have prev_inuse set.\n" +
+"  */\n" +
+"\n" +
+"  assert((old_top == initial_top(av) && old_size == 0) ||\n" +
+"         ((CHUNK_SIZE_T) (old_size) >= MINSIZE &&\n" +
+"          prev_inuse(old_top)));\n" +
+"\n" +
+"  /* Precondition: not enough current space to satisfy nb request */\n" +
+"  assert((CHUNK_SIZE_T)(old_size) < (CHUNK_SIZE_T)(nb + MINSIZE));\n" +
+"\n" +
+"  /* Precondition: all fastbins are consolidated */\n" +
+"  assert(!have_fastchunks(av));\n" +
+"\n" +
+"\n" +
+"  /* Request enough space for nb + pad + overhead */\n" +
+"\n" +
+"  size = nb + av->top_pad + MINSIZE;\n" +
+"\n" +
+"  /*\n" +
+"    If contiguous, we can subtract out existing space that we hope to\n" +
+"    combine with new space. We add it back later only if\n" +
+"    we don't actually get contiguous space.\n" +
+"  */\n" +
+"\n" +
+"  if (contiguous(av))\n" +
+"    size -= old_size;\n" +
+"\n" +
+"  /*\n" +
+"    Round to a multiple of page size.\n" +
+"    If MORECORE is not contiguous, this ensures that we only call it\n" +
+"    with whole-page arguments.  And if MORECORE is contiguous and\n" +
+"    this is not first time through, this preserves page-alignment of\n" +
+"    previous calls. Otherwise, we correct to page-align below.\n" +
+"  */\n" +
+"\n" +
+"  size = (size + pagemask) & ~pagemask;\n" +
+"\n" +
+"  /*\n" +
+"    Don't try to call MORECORE if argument is so big as to appear\n" +
+"    negative. Note that since mmap takes size_t arg, it may succeed\n" +
+"    below even if we cannot call MORECORE.\n" +
+"  */\n" +
+"\n" +
+"  if (size > 0)\n" +
+"    brk = (char*)(MORECORE(size));\n" +
+"\n" +
+"  /*\n" +
+"    If have mmap, try using it as a backup when MORECORE fails or\n" +
+"    cannot be used. This is worth doing on systems that have \"holes\" in\n" +
+"    address space, so sbrk cannot extend to give contiguous space, but\n" +
+"    space is available elsewhere.  Note that we ignore mmap max count\n" +
+"    and threshold limits, since the space will not be used as a\n" +
+"    segregated mmap region.\n" +
+"  */\n" +
+"\n" +
+"#if HAVE_MMAP\n" +
+"  if (brk == (char*)(MORECORE_FAILURE)) {\n" +
+"\n" +
+"    /* Cannot merge with old top, so add its size back in */\n" +
+"    if (contiguous(av))\n" +
+"      size = (size + old_size + pagemask) & ~pagemask;\n" +
+"\n" +
+"    /* If we are relying on mmap as backup, then use larger units */\n" +
+"    if ((CHUNK_SIZE_T)(size) < (CHUNK_SIZE_T)(MMAP_AS_MORECORE_SIZE))\n" +
+"      size = MMAP_AS_MORECORE_SIZE;\n" +
+"\n" +
+"    /* Don't try if size wraps around 0 */\n" +
+"    if ((CHUNK_SIZE_T)(size) > (CHUNK_SIZE_T)(nb)) {\n" +
+"\n" +
+"      brk = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE));\n" +
+"\n" +
+"      if (brk != (char*)(MORECORE_FAILURE)) {\n" +
+"\n" +
+"        /* We do not need, and cannot use, another sbrk call to find end */\n" +
+"        snd_brk = brk + size;\n" +
+"\n" +
+"        /*\n" +
+"           Record that we no longer have a contiguous sbrk region.\n" +
+"           After the first time mmap is used as backup, we do not\n" +
+"           ever rely on contiguous space since this could incorrectly\n" +
+"           bridge regions.\n" +
+"        */\n" +
+"        set_noncontiguous(av);\n" +
+"      }\n" +
+"    }\n" +
+"  }\n" +
+"#endif\n" +
+"\n" +
+"  if (brk != (char*)(MORECORE_FAILURE)) {\n" +
+"    av->sbrked_mem += size;\n" +
+"\n" +
+"    /*\n" +
+"      If MORECORE extends previous space, we can likewise extend top size.\n" +
+"    */\n" +
+"\n" +
+"    if (brk == old_end && snd_brk == (char*)(MORECORE_FAILURE)) {\n" +
+"      set_head(old_top, (size + old_size) | PREV_INUSE);\n" +
+"    }\n" +
+"\n" +
+"    /*\n" +
+"      Otherwise, make adjustments:\n" +
+"\n" +
+"      * If the first time through or noncontiguous, we need to call sbrk\n" +
+"        just to find out where the end of memory lies.\n" +
+"\n" +
+"      * We need to ensure that all returned chunks from malloc will meet\n" +
+"        MALLOC_ALIGNMENT\n" +
+"\n" +
+"      * If there was an intervening foreign sbrk, we need to adjust sbrk\n" +
+"        request size to account for fact that we will not be able to\n" +
+"        combine new space with existing space in old_top.\n" +
+"\n" +
+"      * Almost all systems internally allocate whole pages at a time, in\n" +
+"        which case we might as well use the whole last page of request.\n" +
+"        So we allocate enough more memory to hit a page boundary now,\n" +
+"        which in turn causes future contiguous calls to page-align.\n" +
+"    */\n" +
+"\n" +
+"    else {\n" +
+"      front_misalign = 0;\n" +
+"      end_misalign = 0;\n" +
+"      correction = 0;\n" +
+"      aligned_brk = brk;\n" +
+"\n") +
+(
+"      /*\n" +
+"        If MORECORE returns an address lower than we have seen before,\n" +
+"        we know it isn't really contiguous.  This and some subsequent\n" +
+"        checks help cope with non-conforming MORECORE functions and\n" +
+"        the presence of \"foreign\" calls to MORECORE from outside of\n" +
+"        malloc or by other threads.  We cannot guarantee to detect\n" +
+"        these in all cases, but cope with the ones we do detect.\n" +
+"      */\n" +
+"      if (contiguous(av) && old_size != 0 && brk < old_end) {\n" +
+"        set_noncontiguous(av);\n" +
+"      }\n" +
+"\n" +
+"      /* handle contiguous cases */\n" +
+"      if (contiguous(av)) {\n" +
+"\n" +
+"        /*\n" +
+"           We can tolerate forward non-contiguities here (usually due\n" +
+"           to foreign calls) but treat them as part of our space for\n" +
+"           stats reporting.\n" +
+"        */\n" +
+"        if (old_size != 0)\n" +
+"          av->sbrked_mem += brk - old_end;\n" +
+"\n" +
+"        /* Guarantee alignment of first new chunk made from this space */\n" +
+"\n" +
+"        front_misalign = (INTERNAL_SIZE_T)chunk2mem(brk) & MALLOC_ALIGN_MASK;\n" +
+"        if (front_misalign > 0) {\n" +
+"\n" +
+"          /*\n" +
+"            Skip over some bytes to arrive at an aligned position.\n" +
+"            We don't need to specially mark these wasted front bytes.\n" +
+"            They will never be accessed anyway because\n" +
+"            prev_inuse of av->top (and any chunk created from its start)\n" +
+"            is always true after initialization.\n" +
+"          */\n" +
+"\n" +
+"          correction = MALLOC_ALIGNMENT - front_misalign;\n" +
+"          aligned_brk += correction;\n" +
+"        }\n" +
+"\n" +
+"        /*\n" +
+"          If this isn't adjacent to existing space, then we will not\n" +
+"          be able to merge with old_top space, so must add to 2nd request.\n" +
+"        */\n" +
+"\n" +
+"        correction += old_size;\n" +
+"\n" +
+"        /* Extend the end address to hit a page boundary */\n" +
+"        end_misalign = (INTERNAL_SIZE_T)(brk + size + correction);\n" +
+"        correction += ((end_misalign + pagemask) & ~pagemask) - end_misalign;\n" +
+"\n" +
+"        assert(correction >= 0);\n" +
+"        snd_brk = (char*)(MORECORE(correction));\n" +
+"\n" +
+"        if (snd_brk == (char*)(MORECORE_FAILURE)) {\n" +
+"          /*\n" +
+"            If can't allocate correction, try to at least find out current\n" +
+"            brk.  It might be enough to proceed without failing.\n" +
+"          */\n" +
+"          correction = 0;\n" +
+"          snd_brk = (char*)(MORECORE(0));\n" +
+"        }\n" +
+"        else if (snd_brk < brk) {\n" +
+"          /*\n" +
+"            If the second call gives noncontiguous space even though\n" +
+"            it says it won't, the only course of action is to ignore\n" +
+"            results of second call, and conservatively estimate where\n" +
+"            the first call left us. Also set noncontiguous, so this\n" +
+"            won't happen again, leaving at most one hole.\n" +
+"\n" +
+"            Note that this check is intrinsically incomplete.  Because\n" +
+"            MORECORE is allowed to give more space than we ask for,\n" +
+"            there is no reliable way to detect a noncontiguity\n" +
+"            producing a forward gap for the second call.\n" +
+"          */\n" +
+"          snd_brk = brk + size;\n" +
+"          correction = 0;\n" +
+"          set_noncontiguous(av);\n" +
+"        }\n" +
+"\n" +
+"      }\n" +
+"\n" +
+"      /* handle non-contiguous cases */\n" +
+"      else {\n" +
+"        /* MORECORE/mmap must correctly align */\n" +
+"        assert(aligned_OK(chunk2mem(brk)));\n" +
+"\n" +
+"        /* Find out current end of memory */\n" +
+"        if (snd_brk == (char*)(MORECORE_FAILURE)) {\n" +
+"          snd_brk = (char*)(MORECORE(0));\n" +
+"          av->sbrked_mem += snd_brk - brk - size;\n" +
+"        }\n" +
+"      }\n" +
+"\n" +
+"      /* Adjust top based on results of second sbrk */\n" +
+"      if (snd_brk != (char*)(MORECORE_FAILURE)) {\n" +
+"        av->top = (mchunkptr)aligned_brk;\n" +
+"        set_head(av->top, (snd_brk - aligned_brk + correction) | PREV_INUSE);\n" +
+"        av->sbrked_mem += correction;\n" +
+"\n" +
+"        /*\n" +
+"          If not the first time through, we either have a\n" +
+"          gap due to foreign sbrk or a non-contiguous region.  Insert a\n" +
+"          double fencepost at old_top to prevent consolidation with space\n" +
+"          we don't own. These fenceposts are artificial chunks that are\n" +
+"          marked as inuse and are in any case too small to use.  We need\n" +
+"          two to make sizes and alignments work out.\n" +
+"        */\n" +
+"\n" +
+"        if (old_size != 0) {\n" +
+"          /*\n" +
+"             Shrink old_top to insert fenceposts, keeping size a\n" +
+"             multiple of MALLOC_ALIGNMENT. We know there is at least\n" +
+"             enough space in old_top to do this.\n" +
+"          */\n" +
+"          old_size = (old_size - 3*SIZE_SZ) & ~MALLOC_ALIGN_MASK;\n" +
+"          set_head(old_top, old_size | PREV_INUSE);\n" +
+"\n" +
+"          /*\n" +
+"            Note that the following assignments completely overwrite\n" +
+"            old_top when old_size was previously MINSIZE.  This is\n" +
+"            intentional. We need the fencepost, even if old_top otherwise gets\n" +
+"            lost.\n" +
+"          */\n" +
+"          chunk_at_offset(old_top, old_size          )->size =\n" +
+"            SIZE_SZ|PREV_INUSE;\n" +
+"\n" +
+"          chunk_at_offset(old_top, old_size + SIZE_SZ)->size =\n" +
+"            SIZE_SZ|PREV_INUSE;\n" +
+"\n" +
+"          /*\n" +
+"             If possible, release the rest, suppressing trimming.\n" +
+"          */\n" +
+"          if (old_size >= MINSIZE) {\n" +
+"            INTERNAL_SIZE_T tt = av->trim_threshold;\n" +
+"            av->trim_threshold = (INTERNAL_SIZE_T)(-1);\n" +
+"            fREe(chunk2mem(old_top));\n" +
+"            av->trim_threshold = tt;\n" +
+"          }\n" +
+"        }\n" +
+"      }\n" +
+"    }\n" +
+"\n" +
+"    /* Update statistics */\n" +
+"    sum = av->sbrked_mem;\n" +
+"    if (sum > (CHUNK_SIZE_T)(av->max_sbrked_mem))\n" +
+"      av->max_sbrked_mem = sum;\n" +
+"\n") +
+(
+"    sum += av->mmapped_mem;\n" +
+"    if (sum > (CHUNK_SIZE_T)(av->max_total_mem))\n" +
+"      av->max_total_mem = sum;\n" +
+"\n" +
+"    check_malloc_state();\n" +
+"\n" +
+"    /* finally, do the allocation */\n" +
+"\n" +
+"    p = av->top;\n" +
+"    size = chunksize(p);\n" +
+"\n" +
+"    /* check that one of the above allocation paths succeeded */\n" +
+"    if ((CHUNK_SIZE_T)(size) >= (CHUNK_SIZE_T)(nb + MINSIZE)) {\n" +
+"      remainder_size = size - nb;\n" +
+"      remainder = chunk_at_offset(p, nb);\n" +
+"      av->top = remainder;\n" +
+"      set_head(p, nb | PREV_INUSE);\n" +
+"      set_head(remainder, remainder_size | PREV_INUSE);\n" +
+"      check_malloced_chunk(p, nb);\n" +
+"      return chunk2mem(p);\n" +
+"    }\n" +
+"\n" +
+"  }\n" +
+"\n" +
+"  /* catch all failure paths */\n" +
+"  MALLOC_FAILURE_ACTION;\n" +
+"  return 0;\n" +
+"}\n" +
+"\n" +
+"\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  sYSTRIm is an inverse of sorts to sYSMALLOc.  It gives memory back\n" +
+"  to the system (via negative arguments to sbrk) if there is unused\n" +
+"  memory at the `high' end of the malloc pool. It is called\n" +
+"  automatically by free() when top space exceeds the trim\n" +
+"  threshold. It is also called by the public malloc_trim routine.  It\n" +
+"  returns 1 if it actually released any memory, else 0.\n" +
+"*/\n" +
+"\n" +
+"#ifndef MORECORE_CANNOT_TRIM\n" +
+"\n" +
+"#if __STD_C\n" +
+"static int sYSTRIm(size_t pad, mstate av)\n" +
+"#else\n" +
+"static int sYSTRIm(pad, av) size_t pad; mstate av;\n" +
+"#endif\n" +
+"{\n" +
+"  long  top_size;        /* Amount of top-most memory */\n" +
+"  long  extra;           /* Amount to release */\n" +
+"  long  released;        /* Amount actually released */\n" +
+"  char* current_brk;     /* address returned by pre-check sbrk call */\n" +
+"  char* new_brk;         /* address returned by post-check sbrk call */\n" +
+"  size_t pagesz;\n" +
+"\n" +
+"  pagesz = av->pagesize;\n" +
+"  top_size = chunksize(av->top);\n" +
+"\n" +
+"  /* Release in pagesize units, keeping at least one page */\n" +
+"  extra = ((top_size - pad - MINSIZE + (pagesz-1)) / pagesz - 1) * pagesz;\n" +
+"\n" +
+"  if (extra > 0) {\n" +
+"\n" +
+"    /*\n" +
+"      Only proceed if end of memory is where we last set it.\n" +
+"      This avoids problems if there were foreign sbrk calls.\n" +
+"    */\n" +
+"    current_brk = (char*)(MORECORE(0));\n" +
+"    if (current_brk == (char*)(av->top) + top_size) {\n" +
+"\n" +
+"      /*\n" +
+"        Attempt to release memory. We ignore MORECORE return value,\n" +
+"        and instead call again to find out where new end of memory is.\n" +
+"        This avoids problems if first call releases less than we asked,\n" +
+"        of if failure somehow altered brk value. (We could still\n" +
+"        encounter problems if it altered brk in some very bad way,\n" +
+"        but the only thing we can do is adjust anyway, which will cause\n" +
+"        some downstream failure.)\n" +
+"      */\n" +
+"\n" +
+"      MORECORE(-extra);\n" +
+"      new_brk = (char*)(MORECORE(0));\n" +
+"\n" +
+"      if (new_brk != (char*)MORECORE_FAILURE) {\n" +
+"        released = (long)(current_brk - new_brk);\n" +
+"\n" +
+"        if (released != 0) {\n" +
+"          /* Success. Adjust top. */\n" +
+"          av->sbrked_mem -= released;\n" +
+"          set_head(av->top, (top_size - released) | PREV_INUSE);\n" +
+"          check_malloc_state();\n" +
+"          return 1;\n" +
+"        }\n" +
+"      }\n" +
+"    }\n" +
+"  }\n" +
+"  return 0;\n" +
+"}\n" +
+"\n" +
+"#endif\n" +
+"\n" +
+"/*\n" +
+"  ------------------------------ malloc ------------------------------\n" +
+"*/\n" +
+"\n" +
+"\n" +
+"#if __STD_C\n" +
+"Void_t* mALLOc(size_t bytes)\n" +
+"#else\n" +
+"  Void_t* mALLOc(bytes) size_t bytes;\n" +
+"#endif\n" +
+"{\n" +
+"  mstate av = get_malloc_state();\n" +
+"\n" +
+"  INTERNAL_SIZE_T nb;               /* normalized request size */\n" +
+"  unsigned int    idx;              /* associated bin index */\n" +
+"  mbinptr         bin;              /* associated bin */\n" +
+"  mfastbinptr*    fb;               /* associated fastbin */\n" +
+"\n" +
+"  mchunkptr       victim;           /* inspected/selected chunk */\n" +
+"  INTERNAL_SIZE_T size;             /* its size */\n" +
+"  int             victim_index;     /* its bin index */\n" +
+"\n" +
+"  mchunkptr       remainder;        /* remainder from a split */\n" +
+"  CHUNK_SIZE_T    remainder_size;   /* its size */\n" +
+"\n" +
+"  unsigned int    block;            /* bit map traverser */\n" +
+"  unsigned int    bit;              /* bit map traverser */\n" +
+"  unsigned int    map;              /* current word of binmap */\n" +
+"\n" +
+"  mchunkptr       fwd;              /* misc temp for linking */\n" +
+"  mchunkptr       bck;              /* misc temp for linking */\n" +
+"\n" +
+"  /*\n" +
+"    Convert request size to internal form by adding SIZE_SZ bytes\n" +
+"    overhead plus possibly more to obtain necessary alignment and/or\n" +
+"    to obtain a size of at least MINSIZE, the smallest allocatable\n" +
+"    size. Also, checked_request2size traps (returning 0) request sizes\n" +
+"    that are so large that they wrap around zero when padded and\n" +
+"    aligned.\n" +
+"  */\n" +
+"\n" +
+"  checked_request2size(bytes, nb);\n" +
+"\n" +
+"  /*\n" +
+"    Bypass search if no frees yet\n" +
+"   */\n" +
+"  if (!have_anychunks(av)) {\n" +
+"    if (av->max_fast == 0) /* initialization check */\n" +
+"      malloc_consolidate(av);\n" +
+"    goto use_top;\n" +
+"  }\n" +
+"\n") +
+(
+"  /*\n" +
+"    If the size qualifies as a fastbin, first check corresponding bin.\n" +
+"  */\n" +
+"\n" +
+"  if ((CHUNK_SIZE_T)(nb) <= (CHUNK_SIZE_T)(av->max_fast)) {\n" +
+"    fb = &(av->fastbins[(fastbin_index(nb))]);\n" +
+"    if ( (victim = *fb) != 0) {\n" +
+"      *fb = victim->fd;\n" +
+"      check_remalloced_chunk(victim, nb);\n" +
+"      return chunk2mem(victim);\n" +
+"    }\n" +
+"  }\n" +
+"\n" +
+"  /*\n" +
+"    If a small request, check regular bin.  Since these \"smallbins\"\n" +
+"    hold one size each, no searching within bins is necessary.\n" +
+"    (For a large request, we need to wait until unsorted chunks are\n" +
+"    processed to find best fit. But for small ones, fits are exact\n" +
+"    anyway, so we can check now, which is faster.)\n" +
+"  */\n" +
+"\n" +
+"  if (in_smallbin_range(nb)) {\n" +
+"    idx = smallbin_index(nb);\n" +
+"    bin = bin_at(av,idx);\n" +
+"\n" +
+"    if ( (victim = last(bin)) != bin) {\n" +
+"      bck = victim->bk;\n" +
+"      set_inuse_bit_at_offset(victim, nb);\n" +
+"      bin->bk = bck;\n" +
+"      bck->fd = bin;\n" +
+"\n" +
+"      check_malloced_chunk(victim, nb);\n" +
+"      return chunk2mem(victim);\n" +
+"    }\n" +
+"  }\n" +
+"\n" +
+"  /*\n" +
+"     If this is a large request, consolidate fastbins before continuing.\n" +
+"     While it might look excessive to kill all fastbins before\n" +
+"     even seeing if there is space available, this avoids\n" +
+"     fragmentation problems normally associated with fastbins.\n" +
+"     Also, in practice, programs tend to have runs of either small or\n" +
+"     large requests, but less often mixtures, so consolidation is not\n" +
+"     invoked all that often in most programs. And the programs that\n" +
+"     it is called frequently in otherwise tend to fragment.\n" +
+"  */\n" +
+"\n" +
+"  else {\n" +
+"    idx = largebin_index(nb);\n" +
+"    if (have_fastchunks(av))\n" +
+"      malloc_consolidate(av);\n" +
+"  }\n" +
+"\n" +
+"  /*\n" +
+"    Process recently freed or remaindered chunks, taking one only if\n" +
+"    it is exact fit, or, if this a small request, the chunk is remainder from\n" +
+"    the most recent non-exact fit.  Place other traversed chunks in\n" +
+"    bins.  Note that this step is the only place in any routine where\n" +
+"    chunks are placed in bins.\n" +
+"  */\n" +
+"\n" +
+"  while ( (victim = unsorted_chunks(av)->bk) != unsorted_chunks(av)) {\n" +
+"    bck = victim->bk;\n" +
+"    size = chunksize(victim);\n" +
+"\n" +
+"    /*\n" +
+"       If a small request, try to use last remainder if it is the\n" +
+"       only chunk in unsorted bin.  This helps promote locality for\n" +
+"       runs of consecutive small requests. This is the only\n" +
+"       exception to best-fit, and applies only when there is\n" +
+"       no exact fit for a small chunk.\n" +
+"    */\n" +
+"\n" +
+"    if (in_smallbin_range(nb) &&\n" +
+"        bck == unsorted_chunks(av) &&\n" +
+"        victim == av->last_remainder &&\n" +
+"        (CHUNK_SIZE_T)(size) > (CHUNK_SIZE_T)(nb + MINSIZE)) {\n" +
+"\n" +
+"      /* split and reattach remainder */\n" +
+"      remainder_size = size - nb;\n" +
+"      remainder = chunk_at_offset(victim, nb);\n" +
+"      unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;\n" +
+"      av->last_remainder = remainder;\n" +
+"      remainder->bk = remainder->fd = unsorted_chunks(av);\n" +
+"\n" +
+"      set_head(victim, nb | PREV_INUSE);\n" +
+"      set_head(remainder, remainder_size | PREV_INUSE);\n" +
+"      set_foot(remainder, remainder_size);\n" +
+"\n" +
+"      check_malloced_chunk(victim, nb);\n" +
+"      return chunk2mem(victim);\n" +
+"    }\n" +
+"\n" +
+"    /* remove from unsorted list */\n" +
+"    unsorted_chunks(av)->bk = bck;\n" +
+"    bck->fd = unsorted_chunks(av);\n" +
+"\n" +
+"    /* Take now instead of binning if exact fit */\n" +
+"\n" +
+"    if (size == nb) {\n" +
+"      set_inuse_bit_at_offset(victim, size);\n" +
+"      check_malloced_chunk(victim, nb);\n" +
+"      return chunk2mem(victim);\n" +
+"    }\n" +
+"\n" +
+"    /* place chunk in bin */\n" +
+"\n" +
+"    if (in_smallbin_range(size)) {\n" +
+"      victim_index = smallbin_index(size);\n" +
+"      bck = bin_at(av, victim_index);\n" +
+"      fwd = bck->fd;\n" +
+"    }\n" +
+"    else {\n" +
+"      victim_index = largebin_index(size);\n" +
+"      bck = bin_at(av, victim_index);\n" +
+"      fwd = bck->fd;\n" +
+"\n" +
+"      if (fwd != bck) {\n" +
+"        /* if smaller than smallest, place first */\n" +
+"        if ((CHUNK_SIZE_T)(size) < (CHUNK_SIZE_T)(bck->bk->size)) {\n" +
+"          fwd = bck;\n" +
+"          bck = bck->bk;\n" +
+"        }\n" +
+"        else if ((CHUNK_SIZE_T)(size) >=\n" +
+"                 (CHUNK_SIZE_T)(FIRST_SORTED_BIN_SIZE)) {\n" +
+"\n" +
+"          /* maintain large bins in sorted order */\n" +
+"          size |= PREV_INUSE; /* Or with inuse bit to speed comparisons */\n" +
+"          while ((CHUNK_SIZE_T)(size) < (CHUNK_SIZE_T)(fwd->size))\n" +
+"            fwd = fwd->fd;\n" +
+"          bck = fwd->bk;\n" +
+"        }\n" +
+"      }\n" +
+"    }\n" +
+"\n" +
+"    mark_bin(av, victim_index);\n" +
+"    victim->bk = bck;\n" +
+"    victim->fd = fwd;\n" +
+"    fwd->bk = victim;\n" +
+"    bck->fd = victim;\n" +
+"  }\n" +
+"\n" +
+"  /*\n" +
+"    If a large request, scan through the chunks of current bin to\n" +
+"    find one that fits.  (This will be the smallest that fits unless\n" +
+"    FIRST_SORTED_BIN_SIZE has been changed from default.)  This is\n" +
+"    the only step where an unbounded number of chunks might be\n" +
+"    scanned without doing anything useful with them. However the\n" +
+"    lists tend to be short.\n" +
+"  */\n" +
+"\n") +
+(
+"  if (!in_smallbin_range(nb)) {\n" +
+"    bin = bin_at(av, idx);\n" +
+"\n" +
+"    for (victim = last(bin); victim != bin; victim = victim->bk) {\n" +
+"      size = chunksize(victim);\n" +
+"\n" +
+"      if ((CHUNK_SIZE_T)(size) >= (CHUNK_SIZE_T)(nb)) {\n" +
+"        remainder_size = size - nb;\n" +
+"        unlink(victim, bck, fwd);\n" +
+"\n" +
+"        /* Exhaust */\n" +
+"        if (remainder_size < MINSIZE)  {\n" +
+"          set_inuse_bit_at_offset(victim, size);\n" +
+"          check_malloced_chunk(victim, nb);\n" +
+"          return chunk2mem(victim);\n" +
+"        }\n" +
+"        /* Split */\n" +
+"        else {\n" +
+"          remainder = chunk_at_offset(victim, nb);\n" +
+"          unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;\n" +
+"          remainder->bk = remainder->fd = unsorted_chunks(av);\n" +
+"          set_head(victim, nb | PREV_INUSE);\n" +
+"          set_head(remainder, remainder_size | PREV_INUSE);\n" +
+"          set_foot(remainder, remainder_size);\n" +
+"          check_malloced_chunk(victim, nb);\n" +
+"          return chunk2mem(victim);\n" +
+"        }\n" +
+"      }\n" +
+"    }\n" +
+"  }\n" +
+"\n" +
+"  /*\n" +
+"    Search for a chunk by scanning bins, starting with next largest\n" +
+"    bin. This search is strictly by best-fit; i.e., the smallest\n" +
+"    (with ties going to approximately the least recently used) chunk\n" +
+"    that fits is selected.\n" +
+"\n" +
+"    The bitmap avoids needing to check that most blocks are nonempty.\n" +
+"  */\n" +
+"\n" +
+"  ++idx;\n" +
+"  bin = bin_at(av,idx);\n" +
+"  block = idx2block(idx);\n" +
+"  map = av->binmap[block];\n" +
+"  bit = idx2bit(idx);\n" +
+"\n" +
+"  for (;;) {\n" +
+"\n" +
+"    /* Skip rest of block if there are no more set bits in this block.  */\n" +
+"    if (bit > map || bit == 0) {\n" +
+"      do {\n" +
+"        if (++block >= BINMAPSIZE)  /* out of bins */\n" +
+"          goto use_top;\n" +
+"      } while ( (map = av->binmap[block]) == 0);\n" +
+"\n" +
+"      bin = bin_at(av, (block << BINMAPSHIFT));\n" +
+"      bit = 1;\n" +
+"    }\n" +
+"\n" +
+"    /* Advance to bin with set bit. There must be one. */\n" +
+"    while ((bit & map) == 0) {\n" +
+"      bin = next_bin(bin);\n" +
+"      bit <<= 1;\n" +
+"      assert(bit != 0);\n" +
+"    }\n" +
+"\n" +
+"    /* Inspect the bin. It is likely to be non-empty */\n" +
+"    victim = last(bin);\n" +
+"\n" +
+"    /*  If a false alarm (empty bin), clear the bit. */\n" +
+"    if (victim == bin) {\n" +
+"      av->binmap[block] = map &= ~bit; /* Write through */\n" +
+"      bin = next_bin(bin);\n" +
+"      bit <<= 1;\n" +
+"    }\n" +
+"\n" +
+"    else {\n" +
+"      size = chunksize(victim);\n" +
+"\n" +
+"      /*  We know the first chunk in this bin is big enough to use. */\n" +
+"      assert((CHUNK_SIZE_T)(size) >= (CHUNK_SIZE_T)(nb));\n" +
+"\n" +
+"      remainder_size = size - nb;\n" +
+"\n" +
+"      /* unlink */\n" +
+"      bck = victim->bk;\n" +
+"      bin->bk = bck;\n" +
+"      bck->fd = bin;\n" +
+"\n" +
+"      /* Exhaust */\n" +
+"      if (remainder_size < MINSIZE) {\n" +
+"        set_inuse_bit_at_offset(victim, size);\n" +
+"        check_malloced_chunk(victim, nb);\n" +
+"        return chunk2mem(victim);\n" +
+"      }\n" +
+"\n" +
+"      /* Split */\n" +
+"      else {\n" +
+"        remainder = chunk_at_offset(victim, nb);\n" +
+"\n" +
+"        unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;\n" +
+"        remainder->bk = remainder->fd = unsorted_chunks(av);\n" +
+"        /* advertise as last remainder */\n" +
+"        if (in_smallbin_range(nb))\n" +
+"          av->last_remainder = remainder;\n" +
+"\n" +
+"        set_head(victim, nb | PREV_INUSE);\n" +
+"        set_head(remainder, remainder_size | PREV_INUSE);\n" +
+"        set_foot(remainder, remainder_size);\n" +
+"        check_malloced_chunk(victim, nb);\n" +
+"        return chunk2mem(victim);\n" +
+"      }\n" +
+"    }\n" +
+"  }\n" +
+"\n" +
+"  use_top:\n" +
+"  /*\n" +
+"    If large enough, split off the chunk bordering the end of memory\n" +
+"    (held in av->top). Note that this is in accord with the best-fit\n" +
+"    search rule.  In effect, av->top is treated as larger (and thus\n" +
+"    less well fitting) than any other available chunk since it can\n" +
+"    be extended to be as large as necessary (up to system\n" +
+"    limitations).\n" +
+"\n" +
+"    We require that av->top always exists (i.e., has size >=\n" +
+"    MINSIZE) after initialization, so if it would otherwise be\n" +
+"    exhuasted by current request, it is replenished. (The main\n" +
+"    reason for ensuring it exists is that we may need MINSIZE space\n" +
+"    to put in fenceposts in sysmalloc.)\n" +
+"  */\n" +
+"\n" +
+"  victim = av->top;\n" +
+"  size = chunksize(victim);\n" +
+"\n" +
+"  if ((CHUNK_SIZE_T)(size) >= (CHUNK_SIZE_T)(nb + MINSIZE)) {\n" +
+"    remainder_size = size - nb;\n" +
+"    remainder = chunk_at_offset(victim, nb);\n" +
+"    av->top = remainder;\n" +
+"    set_head(victim, nb | PREV_INUSE);\n" +
+"    set_head(remainder, remainder_size | PREV_INUSE);\n" +
+"\n" +
+"    check_malloced_chunk(victim, nb);\n" +
+"    return chunk2mem(victim);\n" +
+"  }\n" +
+"\n" +
+"  /*\n" +
+"     If no space in top, relay to handle system-dependent cases\n" +
+"  */\n" +
+"  return sYSMALLOc(nb, av);\n" +
+"}\n" +
+"\n") +
+(
+"/*\n" +
+"  ------------------------------ free ------------------------------\n" +
+"*/\n" +
+"\n" +
+"#if __STD_C\n" +
+"void fREe(Void_t* mem)\n" +
+"#else\n" +
+"void fREe(mem) Void_t* mem;\n" +
+"#endif\n" +
+"{\n" +
+"  mstate av = get_malloc_state();\n" +
+"\n" +
+"  mchunkptr       p;           /* chunk corresponding to mem */\n" +
+"  INTERNAL_SIZE_T size;        /* its size */\n" +
+"  mfastbinptr*    fb;          /* associated fastbin */\n" +
+"  mchunkptr       nextchunk;   /* next contiguous chunk */\n" +
+"  INTERNAL_SIZE_T nextsize;    /* its size */\n" +
+"  int             nextinuse;   /* true if nextchunk is used */\n" +
+"  INTERNAL_SIZE_T prevsize;    /* size of previous contiguous chunk */\n" +
+"  mchunkptr       bck;         /* misc temp for linking */\n" +
+"  mchunkptr       fwd;         /* misc temp for linking */\n" +
+"\n" +
+"  /* free(0) has no effect */\n" +
+"  if (mem != 0) {\n" +
+"    p = mem2chunk(mem);\n" +
+"    size = chunksize(p);\n" +
+"\n" +
+"    check_inuse_chunk(p);\n" +
+"\n" +
+"    /*\n" +
+"      If eligible, place chunk on a fastbin so it can be found\n" +
+"      and used quickly in malloc.\n" +
+"    */\n" +
+"\n" +
+"    if ((CHUNK_SIZE_T)(size) <= (CHUNK_SIZE_T)(av->max_fast)\n" +
+"\n" +
+"#if TRIM_FASTBINS\n" +
+"        /*\n" +
+"           If TRIM_FASTBINS set, don't place chunks\n" +
+"           bordering top into fastbins\n" +
+"        */\n" +
+"        && (chunk_at_offset(p, size) != av->top)\n" +
+"#endif\n" +
+"        ) {\n" +
+"\n" +
+"      set_fastchunks(av);\n" +
+"      fb = &(av->fastbins[fastbin_index(size)]);\n" +
+"      p->fd = *fb;\n" +
+"      *fb = p;\n" +
+"    }\n" +
+"\n" +
+"    /*\n" +
+"       Consolidate other non-mmapped chunks as they arrive.\n" +
+"    */\n" +
+"\n" +
+"    else if (!chunk_is_mmapped(p)) {\n" +
+"      set_anychunks(av);\n" +
+"\n" +
+"      nextchunk = chunk_at_offset(p, size);\n" +
+"      nextsize = chunksize(nextchunk);\n" +
+"\n" +
+"      /* consolidate backward */\n" +
+"      if (!prev_inuse(p)) {\n" +
+"        prevsize = p->prev_size;\n" +
+"        size += prevsize;\n" +
+"        p = chunk_at_offset(p, -((long) prevsize));\n" +
+"        unlink(p, bck, fwd);\n" +
+"      }\n" +
+"\n" +
+"      if (nextchunk != av->top) {\n" +
+"        /* get and clear inuse bit */\n" +
+"        nextinuse = inuse_bit_at_offset(nextchunk, nextsize);\n" +
+"        set_head(nextchunk, nextsize);\n" +
+"\n" +
+"        /* consolidate forward */\n" +
+"        if (!nextinuse) {\n" +
+"          unlink(nextchunk, bck, fwd);\n" +
+"          size += nextsize;\n" +
+"        }\n" +
+"\n" +
+"        /*\n" +
+"          Place the chunk in unsorted chunk list. Chunks are\n" +
+"          not placed into regular bins until after they have\n" +
+"          been given one chance to be used in malloc.\n" +
+"        */\n" +
+"\n" +
+"        bck = unsorted_chunks(av);\n" +
+"        fwd = bck->fd;\n" +
+"        p->bk = bck;\n" +
+"        p->fd = fwd;\n" +
+"        bck->fd = p;\n" +
+"        fwd->bk = p;\n" +
+"\n" +
+"        set_head(p, size | PREV_INUSE);\n" +
+"        set_foot(p, size);\n" +
+"\n" +
+"        check_free_chunk(p);\n" +
+"      }\n" +
+"\n" +
+"      /*\n" +
+"         If the chunk borders the current high end of memory,\n" +
+"         consolidate into top\n" +
+"      */\n" +
+"\n" +
+"      else {\n" +
+"        size += nextsize;\n" +
+"        set_head(p, size | PREV_INUSE);\n" +
+"        av->top = p;\n" +
+"        check_chunk(p);\n" +
+"      }\n" +
+"\n" +
+"      /*\n" +
+"        If freeing a large space, consolidate possibly-surrounding\n" +
+"        chunks. Then, if the total unused topmost memory exceeds trim\n" +
+"        threshold, ask malloc_trim to reduce top.\n" +
+"\n" +
+"        Unless max_fast is 0, we don't know if there are fastbins\n" +
+"        bordering top, so we cannot tell for sure whether threshold\n" +
+"        has been reached unless fastbins are consolidated.  But we\n" +
+"        don't want to consolidate on each free.  As a compromise,\n" +
+"        consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD\n" +
+"        is reached.\n" +
+"      */\n" +
+"\n" +
+"      if ((CHUNK_SIZE_T)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) {\n" +
+"        if (have_fastchunks(av))\n" +
+"          malloc_consolidate(av);\n" +
+"\n" +
+"#ifndef MORECORE_CANNOT_TRIM\n" +
+"        if ((CHUNK_SIZE_T)(chunksize(av->top)) >=\n" +
+"            (CHUNK_SIZE_T)(av->trim_threshold))\n" +
+"          sYSTRIm(av->top_pad, av);\n" +
+"#endif\n" +
+"      }\n" +
+"\n" +
+"    }\n" +
+"    /*\n" +
+"      If the chunk was allocated via mmap, release via munmap()\n" +
+"      Note that if HAVE_MMAP is false but chunk_is_mmapped is\n" +
+"      true, then user must have overwritten memory. There's nothing\n" +
+"      we can do to catch this error unless DEBUG is set, in which case\n" +
+"      check_inuse_chunk (above) will have triggered error.\n" +
+"    */\n" +
+"\n" +
+"    else {\n" +
+"#if HAVE_MMAP\n" +
+"      int ret;\n" +
+"      INTERNAL_SIZE_T offset = p->prev_size;\n" +
+"      av->n_mmaps--;\n" +
+"      av->mmapped_mem -= (size + offset);\n" +
+"      ret = munmap((char*)p - offset, size + offset);\n" +
+"      /* munmap returns non-zero on failure */\n" +
+"      assert(ret == 0);\n" +
+"#endif\n" +
+"    }\n" +
+"  }\n" +
+"}\n" +
+"\n") +
+(
+"/*\n" +
+"  ------------------------- malloc_consolidate -------------------------\n" +
+"\n" +
+"  malloc_consolidate is a specialized version of free() that tears\n" +
+"  down chunks held in fastbins.  Free itself cannot be used for this\n" +
+"  purpose since, among other things, it might place chunks back onto\n" +
+"  fastbins.  So, instead, we need to use a minor variant of the same\n" +
+"  code.\n" +
+"\n" +
+"  Also, because this routine needs to be called the first time through\n" +
+"  malloc anyway, it turns out to be the perfect place to trigger\n" +
+"  initialization code.\n" +
+"*/\n" +
+"\n" +
+"#if __STD_C\n" +
+"static void malloc_consolidate(mstate av)\n" +
+"#else\n" +
+"static void malloc_consolidate(av) mstate av;\n" +
+"#endif\n" +
+"{\n" +
+"  mfastbinptr*    fb;                 /* current fastbin being consolidated */\n" +
+"  mfastbinptr*    maxfb;              /* last fastbin (for loop control) */\n" +
+"  mchunkptr       p;                  /* current chunk being consolidated */\n" +
+"  mchunkptr       nextp;              /* next chunk to consolidate */\n" +
+"  mchunkptr       unsorted_bin;       /* bin header */\n" +
+"  mchunkptr       first_unsorted;     /* chunk to link to */\n" +
+"\n" +
+"  /* These have same use as in free() */\n" +
+"  mchunkptr       nextchunk;\n" +
+"  INTERNAL_SIZE_T size;\n" +
+"  INTERNAL_SIZE_T nextsize;\n" +
+"  INTERNAL_SIZE_T prevsize;\n" +
+"  int             nextinuse;\n" +
+"  mchunkptr       bck;\n" +
+"  mchunkptr       fwd;\n" +
+"\n" +
+"  /*\n" +
+"    If max_fast is 0, we know that av hasn't\n" +
+"    yet been initialized, in which case do so below\n" +
+"  */\n" +
+"\n" +
+"  if (av->max_fast != 0) {\n" +
+"    clear_fastchunks(av);\n" +
+"\n" +
+"    unsorted_bin = unsorted_chunks(av);\n" +
+"\n" +
+"    /*\n" +
+"      Remove each chunk from fast bin and consolidate it, placing it\n" +
+"      then in unsorted bin. Among other reasons for doing this,\n" +
+"      placing in unsorted bin avoids needing to calculate actual bins\n" +
+"      until malloc is sure that chunks aren't immediately going to be\n" +
+"      reused anyway.\n" +
+"    */\n" +
+"\n" +
+"    maxfb = &(av->fastbins[fastbin_index(av->max_fast)]);\n" +
+"    fb = &(av->fastbins[0]);\n" +
+"    do {\n" +
+"      if ( (p = *fb) != 0) {\n" +
+"        *fb = 0;\n" +
+"\n" +
+"        do {\n" +
+"          check_inuse_chunk(p);\n" +
+"          nextp = p->fd;\n" +
+"\n" +
+"          /* Slightly streamlined version of consolidation code in free() */\n" +
+"          size = p->size & ~PREV_INUSE;\n" +
+"          nextchunk = chunk_at_offset(p, size);\n" +
+"          nextsize = chunksize(nextchunk);\n" +
+"\n" +
+"          if (!prev_inuse(p)) {\n" +
+"            prevsize = p->prev_size;\n" +
+"            size += prevsize;\n" +
+"            p = chunk_at_offset(p, -((long) prevsize));\n" +
+"            unlink(p, bck, fwd);\n" +
+"          }\n" +
+"\n" +
+"          if (nextchunk != av->top) {\n" +
+"            nextinuse = inuse_bit_at_offset(nextchunk, nextsize);\n" +
+"            set_head(nextchunk, nextsize);\n" +
+"\n" +
+"            if (!nextinuse) {\n" +
+"              size += nextsize;\n" +
+"              unlink(nextchunk, bck, fwd);\n" +
+"            }\n" +
+"\n" +
+"            first_unsorted = unsorted_bin->fd;\n" +
+"            unsorted_bin->fd = p;\n" +
+"            first_unsorted->bk = p;\n" +
+"\n" +
+"            set_head(p, size | PREV_INUSE);\n" +
+"            p->bk = unsorted_bin;\n" +
+"            p->fd = first_unsorted;\n" +
+"            set_foot(p, size);\n" +
+"          }\n" +
+"\n" +
+"          else {\n" +
+"            size += nextsize;\n" +
+"            set_head(p, size | PREV_INUSE);\n" +
+"            av->top = p;\n" +
+"          }\n" +
+"\n" +
+"        } while ( (p = nextp) != 0);\n" +
+"\n" +
+"      }\n" +
+"    } while (fb++ != maxfb);\n" +
+"  }\n" +
+"  else {\n" +
+"    malloc_init_state(av);\n" +
+"    check_malloc_state();\n" +
+"  }\n" +
+"}\n" +
+"\n" +
+"/*\n" +
+"  ------------------------------ realloc ------------------------------\n" +
+"*/\n" +
+"\n" +
+"\n" +
+"#if __STD_C\n" +
+"Void_t* rEALLOc(Void_t* oldmem, size_t bytes)\n" +
+"#else\n" +
+"Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;\n" +
+"#endif\n" +
+"{\n" +
+"  mstate av = get_malloc_state();\n" +
+"\n" +
+"  INTERNAL_SIZE_T  nb;              /* padded request size */\n" +
+"\n" +
+"  mchunkptr        oldp;            /* chunk corresponding to oldmem */\n" +
+"  INTERNAL_SIZE_T  oldsize;         /* its size */\n" +
+"\n" +
+"  mchunkptr        newp;            /* chunk to return */\n" +
+"  INTERNAL_SIZE_T  newsize;         /* its size */\n" +
+"  Void_t*          newmem;          /* corresponding user mem */\n" +
+"\n" +
+"  mchunkptr        next;            /* next contiguous chunk after oldp */\n" +
+"\n" +
+"  mchunkptr        remainder;       /* extra space at end of newp */\n" +
+"  CHUNK_SIZE_T     remainder_size;  /* its size */\n" +
+"\n" +
+"  mchunkptr        bck;             /* misc temp for linking */\n" +
+"  mchunkptr        fwd;             /* misc temp for linking */\n" +
+"\n" +
+"  CHUNK_SIZE_T     copysize;        /* bytes to copy */\n" +
+"  unsigned int     ncopies;         /* INTERNAL_SIZE_T words to copy */\n" +
+"  INTERNAL_SIZE_T* s;               /* copy source */\n" +
+"  INTERNAL_SIZE_T* d;               /* copy destination */\n" +
+"\n" +
+"\n" +
+"#ifdef REALLOC_ZERO_BYTES_FREES\n" +
+"  if (bytes == 0) {\n" +
+"    fREe(oldmem);\n" +
+"    return 0;\n" +
+"  }\n" +
+"#endif\n" +
+"\n") +
+(
+"  /* realloc of null is supposed to be same as malloc */\n" +
+"  if (oldmem == 0) return mALLOc(bytes);\n" +
+"\n" +
+"  checked_request2size(bytes, nb);\n" +
+"\n" +
+"  oldp    = mem2chunk(oldmem);\n" +
+"  oldsize = chunksize(oldp);\n" +
+"\n" +
+"  check_inuse_chunk(oldp);\n" +
+"\n" +
+"  if (!chunk_is_mmapped(oldp)) {\n" +
+"\n" +
+"    if ((CHUNK_SIZE_T)(oldsize) >= (CHUNK_SIZE_T)(nb)) {\n" +
+"      /* already big enough; split below */\n" +
+"      newp = oldp;\n" +
+"      newsize = oldsize;\n" +
+"    }\n" +
+"\n" +
+"    else {\n" +
+"      next = chunk_at_offset(oldp, oldsize);\n" +
+"\n" +
+"      /* Try to expand forward into top */\n" +
+"      if (next == av->top &&\n" +
+"          (CHUNK_SIZE_T)(newsize = oldsize + chunksize(next)) >=\n" +
+"          (CHUNK_SIZE_T)(nb + MINSIZE)) {\n" +
+"        set_head_size(oldp, nb);\n" +
+"        av->top = chunk_at_offset(oldp, nb);\n" +
+"        set_head(av->top, (newsize - nb) | PREV_INUSE);\n" +
+"        return chunk2mem(oldp);\n" +
+"      }\n" +
+"\n" +
+"      /* Try to expand forward into next chunk;  split off remainder below */\n" +
+"      else if (next != av->top &&\n" +
+"               !inuse(next) &&\n" +
+"               (CHUNK_SIZE_T)(newsize = oldsize + chunksize(next)) >=\n" +
+"               (CHUNK_SIZE_T)(nb)) {\n" +
+"        newp = oldp;\n" +
+"        unlink(next, bck, fwd);\n" +
+"      }\n" +
+"\n" +
+"      /* allocate, copy, free */\n" +
+"      else {\n" +
+"        newmem = mALLOc(nb - MALLOC_ALIGN_MASK);\n" +
+"        if (newmem == 0)\n" +
+"          return 0; /* propagate failure */\n" +
+"\n" +
+"        newp = mem2chunk(newmem);\n" +
+"        newsize = chunksize(newp);\n" +
+"\n" +
+"        /*\n" +
+"          Avoid copy if newp is next chunk after oldp.\n" +
+"        */\n" +
+"        if (newp == next) {\n" +
+"          newsize += oldsize;\n" +
+"          newp = oldp;\n" +
+"        }\n" +
+"        else {\n" +
+"          /*\n" +
+"            Unroll copy of <= 36 bytes (72 if 8byte sizes)\n" +
+"            We know that contents have an odd number of\n" +
+"            INTERNAL_SIZE_T-sized words; minimally 3.\n" +
+"          */\n" +
+"\n" +
+"          copysize = oldsize - SIZE_SZ;\n" +
+"          s = (INTERNAL_SIZE_T*)(oldmem);\n" +
+"          d = (INTERNAL_SIZE_T*)(newmem);\n" +
+"          ncopies = copysize / sizeof(INTERNAL_SIZE_T);\n" +
+"          assert(ncopies >= 3);\n" +
+"\n" +
+"          if (ncopies > 9)\n" +
+"            MALLOC_COPY(d, s, copysize);\n" +
+"\n" +
+"          else {\n" +
+"            *(d+0) = *(s+0);\n" +
+"            *(d+1) = *(s+1);\n" +
+"            *(d+2) = *(s+2);\n" +
+"            if (ncopies > 4) {\n" +
+"              *(d+3) = *(s+3);\n" +
+"              *(d+4) = *(s+4);\n" +
+"              if (ncopies > 6) {\n" +
+"                *(d+5) = *(s+5);\n" +
+"                *(d+6) = *(s+6);\n" +
+"                if (ncopies > 8) {\n" +
+"                  *(d+7) = *(s+7);\n" +
+"                  *(d+8) = *(s+8);\n" +
+"                }\n" +
+"              }\n" +
+"            }\n" +
+"          }\n" +
+"\n" +
+"          fREe(oldmem);\n" +
+"          check_inuse_chunk(newp);\n" +
+"          return chunk2mem(newp);\n" +
+"        }\n" +
+"      }\n" +
+"    }\n" +
+"\n" +
+"    /* If possible, free extra space in old or extended chunk */\n" +
+"\n" +
+"    assert((CHUNK_SIZE_T)(newsize) >= (CHUNK_SIZE_T)(nb));\n" +
+"\n" +
+"    remainder_size = newsize - nb;\n" +
+"\n" +
+"    if (remainder_size < MINSIZE) { /* not enough extra to split off */\n" +
+"      set_head_size(newp, newsize);\n" +
+"      set_inuse_bit_at_offset(newp, newsize);\n" +
+"    }\n" +
+"    else { /* split remainder */\n" +
+"      remainder = chunk_at_offset(newp, nb);\n" +
+"      set_head_size(newp, nb);\n" +
+"      set_head(remainder, remainder_size | PREV_INUSE);\n" +
+"      /* Mark remainder as inuse so free() won't complain */\n" +
+"      set_inuse_bit_at_offset(remainder, remainder_size);\n" +
+"      fREe(chunk2mem(remainder));\n" +
+"    }\n" +
+"\n" +
+"    check_inuse_chunk(newp);\n" +
+"    return chunk2mem(newp);\n" +
+"  }\n" +
+"\n" +
+"  /*\n" +
+"    Handle mmap cases\n" +
+"  */\n" +
+"\n" +
+"  else {\n" +
+"#if HAVE_MMAP\n" +
+"\n" +
+"#if HAVE_MREMAP\n" +
+"    INTERNAL_SIZE_T offset = oldp->prev_size;\n" +
+"    size_t pagemask = av->pagesize - 1;\n" +
+"    char *cp;\n" +
+"    CHUNK_SIZE_T  sum;\n" +
+"\n" +
+"    /* Note the extra SIZE_SZ overhead */\n" +
+"    newsize = (nb + offset + SIZE_SZ + pagemask) & ~pagemask;\n" +
+"\n" +
+"    /* don't need to remap if still within same page */\n" +
+"    if (oldsize == newsize - offset)\n" +
+"      return oldmem;\n" +
+"\n" +
+"    cp = (char*)mremap((char*)oldp - offset, oldsize + offset, newsize, 1);\n" +
+"\n" +
+"    if (cp != (char*)MORECORE_FAILURE) {\n" +
+"\n" +
+"      newp = (mchunkptr)(cp + offset);\n" +
+"      set_head(newp, (newsize - offset)|IS_MMAPPED);\n" +
+"\n" +
+"      assert(aligned_OK(chunk2mem(newp)));\n" +
+"      assert((newp->prev_size == offset));\n" +
+"\n") +
+(
+"      /* update statistics */\n" +
+"      sum = av->mmapped_mem += newsize - oldsize;\n" +
+"      if (sum > (CHUNK_SIZE_T)(av->max_mmapped_mem))\n" +
+"        av->max_mmapped_mem = sum;\n" +
+"      sum += av->sbrked_mem;\n" +
+"      if (sum > (CHUNK_SIZE_T)(av->max_total_mem))\n" +
+"        av->max_total_mem = sum;\n" +
+"\n" +
+"      return chunk2mem(newp);\n" +
+"    }\n" +
+"#endif\n" +
+"\n" +
+"    /* Note the extra SIZE_SZ overhead. */\n" +
+"    if ((CHUNK_SIZE_T)(oldsize) >= (CHUNK_SIZE_T)(nb + SIZE_SZ))\n" +
+"      newmem = oldmem; /* do nothing */\n" +
+"    else {\n" +
+"      /* Must alloc, copy, free. */\n" +
+"      newmem = mALLOc(nb - MALLOC_ALIGN_MASK);\n" +
+"      if (newmem != 0) {\n" +
+"        MALLOC_COPY(newmem, oldmem, oldsize - 2*SIZE_SZ);\n" +
+"        fREe(oldmem);\n" +
+"      }\n" +
+"    }\n" +
+"    return newmem;\n" +
+"\n" +
+"#else\n" +
+"    /* If !HAVE_MMAP, but chunk_is_mmapped, user must have overwritten mem */\n" +
+"    check_malloc_state();\n" +
+"    MALLOC_FAILURE_ACTION;\n" +
+"    return 0;\n" +
+"#endif\n" +
+"  }\n" +
+"}\n" +
+"\n" +
+"/*\n" +
+"  ------------------------------ memalign ------------------------------\n" +
+"*/\n" +
+"\n" +
+"#if __STD_C\n" +
+"Void_t* mEMALIGn(size_t alignment, size_t bytes)\n" +
+"#else\n" +
+"Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;\n" +
+"#endif\n" +
+"{\n" +
+"  INTERNAL_SIZE_T nb;             /* padded  request size */\n" +
+"  char*           m;              /* memory returned by malloc call */\n" +
+"  mchunkptr       p;              /* corresponding chunk */\n" +
+"  char*           brk;            /* alignment point within p */\n" +
+"  mchunkptr       newp;           /* chunk to return */\n" +
+"  INTERNAL_SIZE_T newsize;        /* its size */\n" +
+"  INTERNAL_SIZE_T leadsize;       /* leading space before alignment point */\n" +
+"  mchunkptr       remainder;      /* spare room at end to split off */\n" +
+"  CHUNK_SIZE_T    remainder_size; /* its size */\n" +
+"  INTERNAL_SIZE_T size;\n" +
+"\n" +
+"  /* If need less alignment than we give anyway, just relay to malloc */\n" +
+"\n" +
+"  if (alignment <= MALLOC_ALIGNMENT) return mALLOc(bytes);\n" +
+"\n" +
+"  /* Otherwise, ensure that it is at least a minimum chunk size */\n" +
+"\n" +
+"  if (alignment <  MINSIZE) alignment = MINSIZE;\n" +
+"\n" +
+"  /* Make sure alignment is power of 2 (in case MINSIZE is not).  */\n" +
+"  if ((alignment & (alignment - 1)) != 0) {\n" +
+"    size_t a = MALLOC_ALIGNMENT * 2;\n" +
+"    while ((CHUNK_SIZE_T)a < (CHUNK_SIZE_T)alignment) a <<= 1;\n" +
+"    alignment = a;\n" +
+"  }\n" +
+"\n" +
+"  checked_request2size(bytes, nb);\n" +
+"\n" +
+"  /*\n" +
+"    Strategy: find a spot within that chunk that meets the alignment\n" +
+"    request, and then possibly free the leading and trailing space.\n" +
+"  */\n" +
+"\n" +
+"\n" +
+"  /* Call malloc with worst case padding to hit alignment. */\n" +
+"\n" +
+"  m  = (char*)(mALLOc(nb + alignment + MINSIZE));\n" +
+"\n" +
+"  if (m == 0) return 0; /* propagate failure */\n" +
+"\n" +
+"  p = mem2chunk(m);\n" +
+"\n" +
+"  if ((((PTR_UINT)(m)) % alignment) != 0) { /* misaligned */\n" +
+"\n" +
+"    /*\n" +
+"      Find an aligned spot inside chunk.  Since we need to give back\n" +
+"      leading space in a chunk of at least MINSIZE, if the first\n" +
+"      calculation places us at a spot with less than MINSIZE leader,\n" +
+"      we can move to the next aligned spot -- we've allocated enough\n" +
+"      total room so that this is always possible.\n" +
+"    */\n" +
+"\n" +
+"    brk = (char*)mem2chunk((PTR_UINT)(((PTR_UINT)(m + alignment - 1)) &\n" +
+"                           -((signed long) alignment)));\n" +
+"    if ((CHUNK_SIZE_T)(brk - (char*)(p)) < MINSIZE)\n" +
+"      brk += alignment;\n" +
+"\n" +
+"    newp = (mchunkptr)brk;\n" +
+"    leadsize = brk - (char*)(p);\n" +
+"    newsize = chunksize(p) - leadsize;\n" +
+"\n" +
+"    /* For mmapped chunks, just adjust offset */\n" +
+"    if (chunk_is_mmapped(p)) {\n" +
+"      newp->prev_size = p->prev_size + leadsize;\n" +
+"      set_head(newp, newsize|IS_MMAPPED);\n" +
+"      return chunk2mem(newp);\n" +
+"    }\n" +
+"\n" +
+"    /* Otherwise, give back leader, use the rest */\n" +
+"    set_head(newp, newsize | PREV_INUSE);\n" +
+"    set_inuse_bit_at_offset(newp, newsize);\n" +
+"    set_head_size(p, leadsize);\n" +
+"    fREe(chunk2mem(p));\n" +
+"    p = newp;\n" +
+"\n" +
+"    assert (newsize >= nb &&\n" +
+"            (((PTR_UINT)(chunk2mem(p))) % alignment) == 0);\n" +
+"  }\n" +
+"\n" +
+"  /* Also give back spare room at the end */\n" +
+"  if (!chunk_is_mmapped(p)) {\n" +
+"    size = chunksize(p);\n" +
+"    if ((CHUNK_SIZE_T)(size) > (CHUNK_SIZE_T)(nb + MINSIZE)) {\n" +
+"      remainder_size = size - nb;\n" +
+"      remainder = chunk_at_offset(p, nb);\n" +
+"      set_head(remainder, remainder_size | PREV_INUSE);\n" +
+"      set_head_size(p, nb);\n" +
+"      fREe(chunk2mem(remainder));\n" +
+"    }\n" +
+"  }\n" +
+"\n" +
+"  check_inuse_chunk(p);\n" +
+"  return chunk2mem(p);\n" +
+"}\n" +
+"\n" +
+"/*\n" +
+"  ------------------------------ calloc ------------------------------\n" +
+"*/\n" +
+"\n" +
+"#if __STD_C\n" +
+"Void_t* cALLOc(size_t n_elements, size_t elem_size)\n" +
+"#else\n" +
+"Void_t* cALLOc(n_elements, elem_size) size_t n_elements; size_t elem_size;\n" +
+"#endif\n" +
+"{\n" +
+"  mchunkptr p;\n" +
+"  CHUNK_SIZE_T  clearsize;\n" +
+"  CHUNK_SIZE_T  nclears;\n" +
+"  INTERNAL_SIZE_T* d;\n" +
+"\n") +
+(
+"  Void_t* mem = mALLOc(n_elements * elem_size);\n" +
+"\n" +
+"  if (mem != 0) {\n" +
+"    p = mem2chunk(mem);\n" +
+"\n" +
+"    if (!chunk_is_mmapped(p))\n" +
+"    {\n" +
+"      /*\n" +
+"        Unroll clear of <= 36 bytes (72 if 8byte sizes)\n" +
+"        We know that contents have an odd number of\n" +
+"        INTERNAL_SIZE_T-sized words; minimally 3.\n" +
+"      */\n" +
+"\n" +
+"      d = (INTERNAL_SIZE_T*)mem;\n" +
+"      clearsize = chunksize(p) - SIZE_SZ;\n" +
+"      nclears = clearsize / sizeof(INTERNAL_SIZE_T);\n" +
+"      assert(nclears >= 3);\n" +
+"\n" +
+"      if (nclears > 9)\n" +
+"        MALLOC_ZERO(d, clearsize);\n" +
+"\n" +
+"      else {\n" +
+"        *(d+0) = 0;\n" +
+"        *(d+1) = 0;\n" +
+"        *(d+2) = 0;\n" +
+"        if (nclears > 4) {\n" +
+"          *(d+3) = 0;\n" +
+"          *(d+4) = 0;\n" +
+"          if (nclears > 6) {\n" +
+"            *(d+5) = 0;\n" +
+"            *(d+6) = 0;\n" +
+"            if (nclears > 8) {\n" +
+"              *(d+7) = 0;\n" +
+"              *(d+8) = 0;\n" +
+"            }\n" +
+"          }\n" +
+"        }\n" +
+"      }\n" +
+"    }\n" +
+"#if ! MMAP_CLEARS\n" +
+"    else\n" +
+"    {\n" +
+"      d = (INTERNAL_SIZE_T*)mem;\n" +
+"      /*\n" +
+"        Note the additional SIZE_SZ\n" +
+"      */\n" +
+"      clearsize = chunksize(p) - 2*SIZE_SZ;\n" +
+"      MALLOC_ZERO(d, clearsize);\n" +
+"    }\n" +
+"#endif\n" +
+"  }\n" +
+"  return mem;\n" +
+"}\n" +
+"\n" +
+"/*\n" +
+"  ------------------------------ cfree ------------------------------\n" +
+"*/\n" +
+"\n" +
+"#if __STD_C\n" +
+"void cFREe(Void_t *mem)\n" +
+"#else\n" +
+"void cFREe(mem) Void_t *mem;\n" +
+"#endif\n" +
+"{\n" +
+"  fREe(mem);\n" +
+"}\n" +
+"\n" +
+"/*\n" +
+"  ------------------------- independent_calloc -------------------------\n" +
+"*/\n" +
+"\n" +
+"#if __STD_C\n" +
+"Void_t** iCALLOc(size_t n_elements, size_t elem_size, Void_t* chunks[])\n" +
+"#else\n" +
+"Void_t** iCALLOc(n_elements, elem_size, chunks) size_t n_elements; size_t elem_size; Void_t* chunks[];\n" +
+"#endif\n" +
+"{\n" +
+"  size_t sz = elem_size; /* serves as 1-element array */\n" +
+"  /* opts arg of 3 means all elements are same size, and should be cleared */\n" +
+"  return iALLOc(n_elements, &sz, 3, chunks);\n" +
+"}\n" +
+"\n" +
+"/*\n" +
+"  ------------------------- independent_comalloc -------------------------\n" +
+"*/\n" +
+"\n" +
+"#if __STD_C\n" +
+"Void_t** iCOMALLOc(size_t n_elements, size_t sizes[], Void_t* chunks[])\n" +
+"#else\n" +
+"Void_t** iCOMALLOc(n_elements, sizes, chunks) size_t n_elements; size_t sizes[]; Void_t* chunks[];\n" +
+"#endif\n" +
+"{\n" +
+"  return iALLOc(n_elements, sizes, 0, chunks);\n" +
+"}\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  ------------------------------ ialloc ------------------------------\n" +
+"  ialloc provides common support for independent_X routines, handling all of\n" +
+"  the combinations that can result.\n" +
+"\n" +
+"  The opts arg has:\n" +
+"    bit 0 set if all elements are same size (using sizes[0])\n" +
+"    bit 1 set if elements should be zeroed\n" +
+"*/\n" +
+"\n" +
+"\n" +
+"#if __STD_C\n" +
+"static Void_t** iALLOc(size_t n_elements,\n" +
+"                       size_t* sizes,\n" +
+"                       int opts,\n" +
+"                       Void_t* chunks[])\n" +
+"#else\n" +
+"static Void_t** iALLOc(n_elements, sizes, opts, chunks) size_t n_elements; size_t* sizes; int opts; Void_t* chunks[];\n" +
+"#endif\n" +
+"{\n" +
+"  mstate av = get_malloc_state();\n" +
+"  INTERNAL_SIZE_T element_size;   /* chunksize of each element, if all same */\n" +
+"  INTERNAL_SIZE_T contents_size;  /* total size of elements */\n" +
+"  INTERNAL_SIZE_T array_size;     /* request size of pointer array */\n" +
+"  Void_t*         mem;            /* malloced aggregate space */\n" +
+"  mchunkptr       p;              /* corresponding chunk */\n" +
+"  INTERNAL_SIZE_T remainder_size; /* remaining bytes while splitting */\n" +
+"  Void_t**        marray;         /* either \"chunks\" or malloced ptr array */\n" +
+"  mchunkptr       array_chunk;    /* chunk for malloced ptr array */\n" +
+"  int             mmx;            /* to disable mmap */\n" +
+"  INTERNAL_SIZE_T size;\n" +
+"  size_t          i;\n" +
+"\n" +
+"  /* Ensure initialization */\n" +
+"  if (av->max_fast == 0) malloc_consolidate(av);\n" +
+"\n" +
+"  /* compute array length, if needed */\n" +
+"  if (chunks != 0) {\n" +
+"    if (n_elements == 0)\n" +
+"      return chunks; /* nothing to do */\n" +
+"    marray = chunks;\n" +
+"    array_size = 0;\n" +
+"  }\n" +
+"  else {\n" +
+"    /* if empty req, must still return chunk representing empty array */\n" +
+"    if (n_elements == 0)\n" +
+"      return (Void_t**) mALLOc(0);\n" +
+"    marray = 0;\n" +
+"    array_size = request2size(n_elements * (sizeof(Void_t*)));\n" +
+"  }\n" +
+"\n" +
+"  /* compute total element size */\n" +
+"  if (opts & 0x1) { /* all-same-size */\n" +
+"    element_size = request2size(*sizes);\n" +
+"    contents_size = n_elements * element_size;\n" +
+"  }\n" +
+"  else { /* add up all the sizes */\n" +
+"    element_size = 0;\n" +
+"    contents_size = 0;\n" +
+"    for (i = 0; i != n_elements; ++i)\n" +
+"      contents_size += request2size(sizes[i]);\n" +
+"  }\n" +
+"\n") +
+(
+"  /* subtract out alignment bytes from total to minimize overallocation */\n" +
+"  size = contents_size + array_size - MALLOC_ALIGN_MASK;\n" +
+"\n" +
+"  /*\n" +
+"     Allocate the aggregate chunk.\n" +
+"     But first disable mmap so malloc won't use it, since\n" +
+"     we would not be able to later free/realloc space internal\n" +
+"     to a segregated mmap region.\n" +
+" */\n" +
+"  mmx = av->n_mmaps_max;   /* disable mmap */\n" +
+"  av->n_mmaps_max = 0;\n" +
+"  mem = mALLOc(size);\n" +
+"  av->n_mmaps_max = mmx;   /* reset mmap */\n" +
+"  if (mem == 0)\n" +
+"    return 0;\n" +
+"\n" +
+"  p = mem2chunk(mem);\n" +
+"  assert(!chunk_is_mmapped(p));\n" +
+"  remainder_size = chunksize(p);\n" +
+"\n" +
+"  if (opts & 0x2) {       /* optionally clear the elements */\n" +
+"    MALLOC_ZERO(mem, remainder_size - SIZE_SZ - array_size);\n" +
+"  }\n" +
+"\n" +
+"  /* If not provided, allocate the pointer array as final part of chunk */\n" +
+"  if (marray == 0) {\n" +
+"    array_chunk = chunk_at_offset(p, contents_size);\n" +
+"    marray = (Void_t**) (chunk2mem(array_chunk));\n" +
+"    set_head(array_chunk, (remainder_size - contents_size) | PREV_INUSE);\n" +
+"    remainder_size = contents_size;\n" +
+"  }\n" +
+"\n" +
+"  /* split out elements */\n" +
+"  for (i = 0; ; ++i) {\n" +
+"    marray[i] = chunk2mem(p);\n" +
+"    if (i != n_elements-1) {\n" +
+"      if (element_size != 0)\n" +
+"        size = element_size;\n" +
+"      else\n" +
+"        size = request2size(sizes[i]);\n" +
+"      remainder_size -= size;\n" +
+"      set_head(p, size | PREV_INUSE);\n" +
+"      p = chunk_at_offset(p, size);\n" +
+"    }\n" +
+"    else { /* the final element absorbs any overallocation slop */\n" +
+"      set_head(p, remainder_size | PREV_INUSE);\n" +
+"      break;\n" +
+"    }\n" +
+"  }\n" +
+"\n" +
+"#if DEBUG\n" +
+"  if (marray != chunks) {\n" +
+"    /* final element must have exactly exhausted chunk */\n" +
+"    if (element_size != 0)\n" +
+"      assert(remainder_size == element_size);\n" +
+"    else\n" +
+"      assert(remainder_size == request2size(sizes[i]));\n" +
+"    check_inuse_chunk(mem2chunk(marray));\n" +
+"  }\n" +
+"\n" +
+"  for (i = 0; i != n_elements; ++i)\n" +
+"    check_inuse_chunk(mem2chunk(marray[i]));\n" +
+"#endif\n" +
+"\n" +
+"  return marray;\n" +
+"}\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  ------------------------------ valloc ------------------------------\n" +
+"*/\n" +
+"\n" +
+"#if __STD_C\n" +
+"Void_t* vALLOc(size_t bytes)\n" +
+"#else\n" +
+"Void_t* vALLOc(bytes) size_t bytes;\n" +
+"#endif\n" +
+"{\n" +
+"  /* Ensure initialization */\n" +
+"  mstate av = get_malloc_state();\n" +
+"  if (av->max_fast == 0) malloc_consolidate(av);\n" +
+"  return mEMALIGn(av->pagesize, bytes);\n" +
+"}\n" +
+"\n" +
+"/*\n" +
+"  ------------------------------ pvalloc ------------------------------\n" +
+"*/\n" +
+"\n" +
+"\n" +
+"#if __STD_C\n" +
+"Void_t* pVALLOc(size_t bytes)\n" +
+"#else\n" +
+"Void_t* pVALLOc(bytes) size_t bytes;\n" +
+"#endif\n" +
+"{\n" +
+"  mstate av = get_malloc_state();\n" +
+"  size_t pagesz;\n" +
+"\n" +
+"  /* Ensure initialization */\n" +
+"  if (av->max_fast == 0) malloc_consolidate(av);\n" +
+"  pagesz = av->pagesize;\n" +
+"  return mEMALIGn(pagesz, (bytes + pagesz - 1) & ~(pagesz - 1));\n" +
+"}\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  ------------------------------ malloc_trim ------------------------------\n" +
+"*/\n" +
+"\n" +
+"#if __STD_C\n" +
+"int mTRIm(size_t pad)\n" +
+"#else\n" +
+"int mTRIm(pad) size_t pad;\n" +
+"#endif\n" +
+"{\n" +
+"  mstate av = get_malloc_state();\n" +
+"  /* Ensure initialization/consolidation */\n" +
+"  malloc_consolidate(av);\n" +
+"\n" +
+"#ifndef MORECORE_CANNOT_TRIM\n" +
+"  return sYSTRIm(pad, av);\n" +
+"#else\n" +
+"  return 0;\n" +
+"#endif\n" +
+"}\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  ------------------------- malloc_usable_size -------------------------\n" +
+"*/\n" +
+"\n" +
+"#if __STD_C\n" +
+"size_t mUSABLe(Void_t* mem)\n" +
+"#else\n" +
+"size_t mUSABLe(mem) Void_t* mem;\n" +
+"#endif\n" +
+"{\n" +
+"  mchunkptr p;\n" +
+"  if (mem != 0) {\n" +
+"    p = mem2chunk(mem);\n" +
+"    if (chunk_is_mmapped(p))\n" +
+"      return chunksize(p) - 2*SIZE_SZ;\n" +
+"    else if (inuse(p))\n" +
+"      return chunksize(p) - SIZE_SZ;\n" +
+"  }\n" +
+"  return 0;\n" +
+"}\n" +
+"\n" +
+"/*\n" +
+"  ------------------------------ mallinfo ------------------------------\n" +
+"*/\n" +
+"\n") +
+(
+"struct mallinfo mALLINFo()\n" +
+"{\n" +
+"  mstate av = get_malloc_state();\n" +
+"  struct mallinfo mi;\n" +
+"  unsigned int i;\n" +
+"  mbinptr b;\n" +
+"  mchunkptr p;\n" +
+"  INTERNAL_SIZE_T avail;\n" +
+"  INTERNAL_SIZE_T fastavail;\n" +
+"  int nblocks;\n" +
+"  int nfastblocks;\n" +
+"\n" +
+"  /* Ensure initialization */\n" +
+"  if (av->top == 0)  malloc_consolidate(av);\n" +
+"\n" +
+"  check_malloc_state();\n" +
+"\n" +
+"  /* Account for top */\n" +
+"  avail = chunksize(av->top);\n" +
+"  nblocks = 1;  /* top always exists */\n" +
+"\n" +
+"  /* traverse fastbins */\n" +
+"  nfastblocks = 0;\n" +
+"  fastavail = 0;\n" +
+"\n" +
+"  for (i = 0; i < NFASTBINS; ++i) {\n" +
+"    for (p = av->fastbins[i]; p != 0; p = p->fd) {\n" +
+"      ++nfastblocks;\n" +
+"      fastavail += chunksize(p);\n" +
+"    }\n" +
+"  }\n" +
+"\n" +
+"  avail += fastavail;\n" +
+"\n" +
+"  /* traverse regular bins */\n" +
+"  for (i = 1; i < NBINS; ++i) {\n" +
+"    b = bin_at(av, i);\n" +
+"    for (p = last(b); p != b; p = p->bk) {\n" +
+"      ++nblocks;\n" +
+"      avail += chunksize(p);\n" +
+"    }\n" +
+"  }\n" +
+"\n" +
+"  mi.smblks = nfastblocks;\n" +
+"  mi.ordblks = nblocks;\n" +
+"  mi.fordblks = avail;\n" +
+"  mi.uordblks = av->sbrked_mem - avail;\n" +
+"  mi.arena = av->sbrked_mem;\n" +
+"  mi.hblks = av->n_mmaps;\n" +
+"  mi.hblkhd = av->mmapped_mem;\n" +
+"  mi.fsmblks = fastavail;\n" +
+"  mi.keepcost = chunksize(av->top);\n" +
+"  mi.usmblks = av->max_total_mem;\n" +
+"  return mi;\n" +
+"}\n" +
+"\n" +
+"/*\n" +
+"  ------------------------------ malloc_stats ------------------------------\n" +
+"*/\n" +
+"\n" +
+"void mSTATs()\n" +
+"{\n" +
+"  struct mallinfo mi = mALLINFo();\n" +
+"\n" +
+"#ifdef WIN32\n" +
+"  {\n" +
+"    CHUNK_SIZE_T  free, reserved, committed;\n" +
+"    vminfo (&free, &reserved, &committed);\n" +
+"    fprintf(stderr, \"free bytes       = %10lu\\n\",\n" +
+"            free);\n" +
+"    fprintf(stderr, \"reserved bytes   = %10lu\\n\",\n" +
+"            reserved);\n" +
+"    fprintf(stderr, \"committed bytes  = %10lu\\n\",\n" +
+"            committed);\n" +
+"  }\n" +
+"#endif\n" +
+"\n" +
+"\n" +
+"  fprintf(stderr, \"max system bytes = %10lu\\n\",\n" +
+"          (CHUNK_SIZE_T)(mi.usmblks));\n" +
+"  fprintf(stderr, \"system bytes     = %10lu\\n\",\n" +
+"          (CHUNK_SIZE_T)(mi.arena + mi.hblkhd));\n" +
+"  fprintf(stderr, \"in use bytes     = %10lu\\n\",\n" +
+"          (CHUNK_SIZE_T)(mi.uordblks + mi.hblkhd));\n" +
+"\n" +
+"#ifdef WIN32\n" +
+"  {\n" +
+"    CHUNK_SIZE_T  kernel, user;\n" +
+"    if (cpuinfo (TRUE, &kernel, &user)) {\n" +
+"      fprintf(stderr, \"kernel ms        = %10lu\\n\",\n" +
+"              kernel);\n" +
+"      fprintf(stderr, \"user ms          = %10lu\\n\",\n" +
+"              user);\n" +
+"    }\n" +
+"  }\n" +
+"#endif\n" +
+"}\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  ------------------------------ mallopt ------------------------------\n" +
+"*/\n" +
+"\n" +
+"#if __STD_C\n" +
+"int mALLOPt(int param_number, int value)\n" +
+"#else\n" +
+"int mALLOPt(param_number, value) int param_number; int value;\n" +
+"#endif\n" +
+"{\n" +
+"  mstate av = get_malloc_state();\n" +
+"  /* Ensure initialization/consolidation */\n" +
+"  malloc_consolidate(av);\n" +
+"\n" +
+"  switch(param_number) {\n" +
+"  case M_MXFAST:\n" +
+"    if (value >= 0 && value <= MAX_FAST_SIZE) {\n" +
+"      set_max_fast(av, value);\n" +
+"      return 1;\n" +
+"    }\n" +
+"    else\n" +
+"      return 0;\n" +
+"\n" +
+"  case M_TRIM_THRESHOLD:\n" +
+"    av->trim_threshold = value;\n" +
+"    return 1;\n" +
+"\n" +
+"  case M_TOP_PAD:\n" +
+"    av->top_pad = value;\n" +
+"    return 1;\n" +
+"\n" +
+"  case M_MMAP_THRESHOLD:\n" +
+"    av->mmap_threshold = value;\n" +
+"    return 1;\n" +
+"\n" +
+"  case M_MMAP_MAX:\n" +
+"#if !HAVE_MMAP\n" +
+"    if (value != 0)\n" +
+"      return 0;\n" +
+"#endif\n" +
+"    av->n_mmaps_max = value;\n" +
+"    return 1;\n" +
+"\n" +
+"  default:\n" +
+"    return 0;\n" +
+"  }\n" +
+"}\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  -------------------- Alternative MORECORE functions --------------------\n" +
+"*/\n" +
+"\n") +
+(
+"\n" +
+"/*\n" +
+"  General Requirements for MORECORE.\n" +
+"\n" +
+"  The MORECORE function must have the following properties:\n" +
+"\n" +
+"  If MORECORE_CONTIGUOUS is false:\n" +
+"\n" +
+"    * MORECORE must allocate in multiples of pagesize. It will\n" +
+"      only be called with arguments that are multiples of pagesize.\n" +
+"\n" +
+"    * MORECORE(0) must return an address that is at least\n" +
+"      MALLOC_ALIGNMENT aligned. (Page-aligning always suffices.)\n" +
+"\n" +
+"  else (i.e. If MORECORE_CONTIGUOUS is true):\n" +
+"\n" +
+"    * Consecutive calls to MORECORE with positive arguments\n" +
+"      return increasing addresses, indicating that space has been\n" +
+"      contiguously extended.\n" +
+"\n" +
+"    * MORECORE need not allocate in multiples of pagesize.\n" +
+"      Calls to MORECORE need not have args of multiples of pagesize.\n" +
+"\n" +
+"    * MORECORE need not page-align.\n" +
+"\n" +
+"  In either case:\n" +
+"\n" +
+"    * MORECORE may allocate more memory than requested. (Or even less,\n" +
+"      but this will generally result in a malloc failure.)\n" +
+"\n" +
+"    * MORECORE must not allocate memory when given argument zero, but\n" +
+"      instead return one past the end address of memory from previous\n" +
+"      nonzero call. This malloc does NOT call MORECORE(0)\n" +
+"      until at least one call with positive arguments is made, so\n" +
+"      the initial value returned is not important.\n" +
+"\n" +
+"    * Even though consecutive calls to MORECORE need not return contiguous\n" +
+"      addresses, it must be OK for malloc'ed chunks to span multiple\n" +
+"      regions in those cases where they do happen to be contiguous.\n" +
+"\n" +
+"    * MORECORE need not handle negative arguments -- it may instead\n" +
+"      just return MORECORE_FAILURE when given negative arguments.\n" +
+"      Negative arguments are always multiples of pagesize. MORECORE\n" +
+"      must not misinterpret negative args as large positive unsigned\n" +
+"      args. You can suppress all such calls from even occurring by defining\n" +
+"      MORECORE_CANNOT_TRIM,\n" +
+"\n" +
+"  There is some variation across systems about the type of the\n" +
+"  argument to sbrk/MORECORE. If size_t is unsigned, then it cannot\n" +
+"  actually be size_t, because sbrk supports negative args, so it is\n" +
+"  normally the signed type of the same width as size_t (sometimes\n" +
+"  declared as \"intptr_t\", and sometimes \"ptrdiff_t\").  It doesn't much\n" +
+"  matter though. Internally, we use \"long\" as arguments, which should\n" +
+"  work across all reasonable possibilities.\n" +
+"\n" +
+"  Additionally, if MORECORE ever returns failure for a positive\n" +
+"  request, and HAVE_MMAP is true, then mmap is used as a noncontiguous\n" +
+"  system allocator. This is a useful backup strategy for systems with\n" +
+"  holes in address spaces -- in this case sbrk cannot contiguously\n" +
+"  expand the heap, but mmap may be able to map noncontiguous space.\n" +
+"\n" +
+"  If you'd like mmap to ALWAYS be used, you can define MORECORE to be\n" +
+"  a function that always returns MORECORE_FAILURE.\n" +
+"\n" +
+"  Malloc only has limited ability to detect failures of MORECORE\n" +
+"  to supply contiguous space when it says it can. In particular,\n" +
+"  multithreaded programs that do not use locks may result in\n" +
+"  rece conditions across calls to MORECORE that result in gaps\n" +
+"  that cannot be detected as such, and subsequent corruption.\n" +
+"\n" +
+"  If you are using this malloc with something other than sbrk (or its\n" +
+"  emulation) to supply memory regions, you probably want to set\n" +
+"  MORECORE_CONTIGUOUS as false.  As an example, here is a custom\n" +
+"  allocator kindly contributed for pre-OSX macOS.  It uses virtually\n" +
+"  but not necessarily physically contiguous non-paged memory (locked\n" +
+"  in, present and won't get swapped out).  You can use it by\n" +
+"  uncommenting this section, adding some #includes, and setting up the\n" +
+"  appropriate defines above:\n" +
+"\n" +
+"      #define MORECORE osMoreCore\n" +
+"      #define MORECORE_CONTIGUOUS 0\n" +
+"\n" +
+"  There is also a shutdown routine that should somehow be called for\n" +
+"  cleanup upon program exit.\n" +
+"\n" +
+"  #define MAX_POOL_ENTRIES 100\n" +
+"  #define MINIMUM_MORECORE_SIZE  (64 * 1024)\n" +
+"  static int next_os_pool;\n" +
+"  void *our_os_pools[MAX_POOL_ENTRIES];\n" +
+"\n" +
+"  void *osMoreCore(int size)\n" +
+"  {\n" +
+"    void *ptr = 0;\n" +
+"    static void *sbrk_top = 0;\n" +
+"\n" +
+"    if (size > 0)\n" +
+"    {\n" +
+"      if (size < MINIMUM_MORECORE_SIZE)\n" +
+"         size = MINIMUM_MORECORE_SIZE;\n" +
+"      if (CurrentExecutionLevel() == kTaskLevel)\n" +
+"         ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0);\n" +
+"      if (ptr == 0)\n" +
+"      {\n" +
+"        return (void *) MORECORE_FAILURE;\n" +
+"      }\n" +
+"      // save ptrs so they can be freed during cleanup\n" +
+"      our_os_pools[next_os_pool] = ptr;\n" +
+"      next_os_pool++;\n" +
+"      ptr = (void *) ((((CHUNK_SIZE_T) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK);\n" +
+"      sbrk_top = (char *) ptr + size;\n" +
+"      return ptr;\n" +
+"    }\n" +
+"    else if (size < 0)\n" +
+"    {\n" +
+"      // we don't currently support shrink behavior\n" +
+"      return (void *) MORECORE_FAILURE;\n" +
+"    }\n" +
+"    else\n" +
+"    {\n" +
+"      return sbrk_top;\n" +
+"    }\n" +
+"  }\n" +
+"\n" +
+"  // cleanup any allocated memory pools\n" +
+"  // called as last thing before shutting down driver\n" +
+"\n" +
+"  void osCleanupMem(void)\n" +
+"  {\n" +
+"    void **ptr;\n" +
+"\n" +
+"    for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++)\n" +
+"      if (*ptr)\n" +
+"      {\n" +
+"         PoolDeallocate(*ptr);\n" +
+"         *ptr = 0;\n" +
+"      }\n" +
+"  }\n" +
+"\n" +
+"*/\n" +
+"\n" +
+"\n" +
+"/*\n" +
+"  --------------------------------------------------------------\n" +
+"\n" +
+"  Emulation of sbrk for win32.\n" +
+"  Donated by J. Walter <Walter@GeNeSys-e.de>.\n" +
+"  For additional information about this code, and malloc on Win32, see\n" +
+"     http://www.genesys-e.de/jwalter/\n" +
+"*/\n" +
+"\n" +
+"\n") +
+(
+"#ifdef WIN32\n" +
+"\n" +
+"#ifdef _DEBUG\n" +
+"/* #define TRACE */\n" +
+"#endif\n" +
+"\n" +
+"/* Support for USE_MALLOC_LOCK */\n" +
+"#ifdef USE_MALLOC_LOCK\n" +
+"\n" +
+"/* Wait for spin lock */\n" +
+"static int slwait (int *sl) {\n" +
+"    while (InterlockedCompareExchange ((void **) sl, (void *) 1, (void *) 0) != 0)\n" +
+"        Sleep (0);\n" +
+"    return 0;\n" +
+"}\n" +
+"\n" +
+"/* Release spin lock */\n" +
+"static int slrelease (int *sl) {\n" +
+"    InterlockedExchange (sl, 0);\n" +
+"    return 0;\n" +
+"}\n" +
+"\n" +
+"#ifdef NEEDED\n" +
+"/* Spin lock for emulation code */\n" +
+"static int g_sl;\n" +
+"#endif\n" +
+"\n" +
+"#endif /* USE_MALLOC_LOCK */\n" +
+"\n" +
+"/* getpagesize for windows */\n" +
+"static long getpagesize (void) {\n" +
+"    static long g_pagesize = 0;\n" +
+"    if (! g_pagesize) {\n" +
+"        SYSTEM_INFO system_info;\n" +
+"        GetSystemInfo (&system_info);\n" +
+"        g_pagesize = system_info.dwPageSize;\n" +
+"    }\n" +
+"    return g_pagesize;\n" +
+"}\n" +
+"static long getregionsize (void) {\n" +
+"    static long g_regionsize = 0;\n" +
+"    if (! g_regionsize) {\n" +
+"        SYSTEM_INFO system_info;\n" +
+"        GetSystemInfo (&system_info);\n" +
+"        g_regionsize = system_info.dwAllocationGranularity;\n" +
+"    }\n" +
+"    return g_regionsize;\n" +
+"}\n" +
+"\n" +
+"/* A region list entry */\n" +
+"typedef struct _region_list_entry {\n" +
+"    void *top_allocated;\n" +
+"    void *top_committed;\n" +
+"    void *top_reserved;\n" +
+"    long reserve_size;\n" +
+"    struct _region_list_entry *previous;\n" +
+"} region_list_entry;\n" +
+"\n" +
+"/* Allocate and link a region entry in the region list */\n" +
+"static int region_list_append (region_list_entry **last, void *base_reserved, long reserve_size) {\n" +
+"    region_list_entry *next = HeapAlloc (GetProcessHeap (), 0, sizeof (region_list_entry));\n" +
+"    if (! next)\n" +
+"        return FALSE;\n" +
+"    next->top_allocated = (char *) base_reserved;\n" +
+"    next->top_committed = (char *) base_reserved;\n" +
+"    next->top_reserved = (char *) base_reserved + reserve_size;\n" +
+"    next->reserve_size = reserve_size;\n" +
+"    next->previous = *last;\n" +
+"    *last = next;\n" +
+"    return TRUE;\n" +
+"}\n" +
+"/* Free and unlink the last region entry from the region list */\n" +
+"static int region_list_remove (region_list_entry **last) {\n" +
+"    region_list_entry *previous = (*last)->previous;\n" +
+"    if (! HeapFree (GetProcessHeap (), sizeof (region_list_entry), *last))\n" +
+"        return FALSE;\n" +
+"    *last = previous;\n" +
+"    return TRUE;\n" +
+"}\n" +
+"\n" +
+"#define CEIL(size,to)   (((size)+(to)-1)&~((to)-1))\n" +
+"#define FLOOR(size,to)  ((size)&~((to)-1))\n" +
+"\n" +
+"#define SBRK_SCALE  0\n" +
+"/* #define SBRK_SCALE  1 */\n" +
+"/* #define SBRK_SCALE  2 */\n" +
+"/* #define SBRK_SCALE  4  */\n" +
+"\n" +
+"/* sbrk for windows */\n" +
+"static void *sbrk (long size) {\n" +
+"    static long g_pagesize, g_my_pagesize;\n" +
+"    static long g_regionsize, g_my_regionsize;\n" +
+"    static region_list_entry *g_last;\n" +
+"    void *result = (void *) MORECORE_FAILURE;\n" +
+"#ifdef TRACE\n" +
+"    printf (\"sbrk %d\\n\", size);\n" +
+"#endif\n" +
+"#if defined (USE_MALLOC_LOCK) && defined (NEEDED)\n" +
+"    /* Wait for spin lock */\n" +
+"    slwait (&g_sl);\n" +
+"#endif\n" +
+"    /* First time initialization */\n" +
+"    if (! g_pagesize) {\n" +
+"        g_pagesize = getpagesize ();\n" +
+"        g_my_pagesize = g_pagesize << SBRK_SCALE;\n" +
+"    }\n" +
+"    if (! g_regionsize) {\n" +
+"        g_regionsize = getregionsize ();\n" +
+"        g_my_regionsize = g_regionsize << SBRK_SCALE;\n" +
+"    }\n" +
+"    if (! g_last) {\n" +
+"        if (! region_list_append (&g_last, 0, 0))\n" +
+"           goto sbrk_exit;\n" +
+"    }\n" +
+"    /* Assert invariants */\n" +
+"    assert (g_last);\n" +
+"    assert ((char *) g_last->top_reserved - g_last->reserve_size <= (char *) g_last->top_allocated &&\n" +
+"            g_last->top_allocated <= g_last->top_committed);\n" +
+"    assert ((char *) g_last->top_reserved - g_last->reserve_size <= (char *) g_last->top_committed &&\n" +
+"            g_last->top_committed <= g_last->top_reserved &&\n" +
+"            (unsigned) g_last->top_committed % g_pagesize == 0);\n" +
+"    assert ((unsigned) g_last->top_reserved % g_regionsize == 0);\n" +
+"    assert ((unsigned) g_last->reserve_size % g_regionsize == 0);\n" +
+"    /* Allocation requested? */\n" +
+"    if (size >= 0) {\n" +
+"        /* Allocation size is the requested size */\n" +
+"        long allocate_size = size;\n" +
+"        /* Compute the size to commit */\n" +
+"        long to_commit = (char *) g_last->top_allocated + allocate_size - (char *) g_last->top_committed;\n" +
+"        /* Do we reach the commit limit? */\n" +
+"        if (to_commit > 0) {\n" +
+"            /* Round size to commit */\n" +
+"            long commit_size = CEIL (to_commit, g_my_pagesize);\n" +
+"            /* Compute the size to reserve */\n" +
+"            long to_reserve = (char *) g_last->top_committed + commit_size - (char *) g_last->top_reserved;\n" +
+"            /* Do we reach the reserve limit? */\n" +
+"            if (to_reserve > 0) {\n" +
+"                /* Compute the remaining size to commit in the current region */\n" +
+"                long remaining_commit_size = (char *) g_last->top_reserved - (char *) g_last->top_committed;\n" +
+"                if (remaining_commit_size > 0) {\n" +
+"                    /* Assert preconditions */\n" +
+"                    assert ((unsigned) g_last->top_committed % g_pagesize == 0);\n" +
+"                    assert (0 < remaining_commit_size && remaining_commit_size % g_pagesize == 0); {\n" +
+"                        /* Commit this */\n" +
+"                        void *base_committed = VirtualAlloc (g_last->top_committed, remaining_commit_size,\n" +
+"                                                             MEM_COMMIT, PAGE_READWRITE);\n" +
+"                        /* Check returned pointer for consistency */\n" +
+"                        if (base_committed != g_last->top_committed)\n" +
+"                            goto sbrk_exit;\n") +
+(
+"                        /* Assert postconditions */\n" +
+"                        assert ((unsigned) base_committed % g_pagesize == 0);\n" +
+"#ifdef TRACE\n" +
+"                        printf (\"Commit %p %d\\n\", base_committed, remaining_commit_size);\n" +
+"#endif\n" +
+"                        /* Adjust the regions commit top */\n" +
+"                        g_last->top_committed = (char *) base_committed + remaining_commit_size;\n" +
+"                    }\n" +
+"                } {\n" +
+"                    /* Now we are going to search and reserve. */\n" +
+"                    int contiguous = -1;\n" +
+"                    int found = FALSE;\n" +
+"                    MEMORY_BASIC_INFORMATION memory_info;\n" +
+"                    void *base_reserved;\n" +
+"                    long reserve_size;\n" +
+"                    do {\n" +
+"                        /* Assume contiguous memory */\n" +
+"                        contiguous = TRUE;\n" +
+"                        /* Round size to reserve */\n" +
+"                        reserve_size = CEIL (to_reserve, g_my_regionsize);\n" +
+"                        /* Start with the current region's top */\n" +
+"                        memory_info.BaseAddress = g_last->top_reserved;\n" +
+"                        /* Assert preconditions */\n" +
+"                        assert ((unsigned) memory_info.BaseAddress % g_pagesize == 0);\n" +
+"                        assert (0 < reserve_size && reserve_size % g_regionsize == 0);\n" +
+"                        while (VirtualQuery (memory_info.BaseAddress, &memory_info, sizeof (memory_info))) {\n" +
+"                            /* Assert postconditions */\n" +
+"                            assert ((unsigned) memory_info.BaseAddress % g_pagesize == 0);\n" +
+"#ifdef TRACE\n" +
+"                            printf (\"Query %p %d %s\\n\", memory_info.BaseAddress, memory_info.RegionSize,\n" +
+"                                    memory_info.State == MEM_FREE ? \"FREE\":\n" +
+"                                    (memory_info.State == MEM_RESERVE ? \"RESERVED\":\n" +
+"                                     (memory_info.State == MEM_COMMIT ? \"COMMITTED\": \"?\")));\n" +
+"#endif\n" +
+"                            /* Region is free, well aligned and big enough: we are done */\n" +
+"                            if (memory_info.State == MEM_FREE &&\n" +
+"                                (unsigned) memory_info.BaseAddress % g_regionsize == 0 &&\n" +
+"                                memory_info.RegionSize >= (unsigned) reserve_size) {\n" +
+"                                found = TRUE;\n" +
+"                                break;\n" +
+"                            }\n" +
+"                            /* From now on we can't get contiguous memory! */\n" +
+"                            contiguous = FALSE;\n" +
+"                            /* Recompute size to reserve */\n" +
+"                            reserve_size = CEIL (allocate_size, g_my_regionsize);\n" +
+"                            memory_info.BaseAddress = (char *) memory_info.BaseAddress + memory_info.RegionSize;\n" +
+"                            /* Assert preconditions */\n" +
+"                            assert ((unsigned) memory_info.BaseAddress % g_pagesize == 0);\n" +
+"                            assert (0 < reserve_size && reserve_size % g_regionsize == 0);\n" +
+"                        }\n" +
+"                        /* Search failed? */\n" +
+"                        if (! found)\n" +
+"                            goto sbrk_exit;\n" +
+"                        /* Assert preconditions */\n" +
+"                        assert ((unsigned) memory_info.BaseAddress % g_regionsize == 0);\n" +
+"                        assert (0 < reserve_size && reserve_size % g_regionsize == 0);\n" +
+"                        /* Try to reserve this */\n" +
+"                        base_reserved = VirtualAlloc (memory_info.BaseAddress, reserve_size,\n" +
+"                                                      MEM_RESERVE, PAGE_NOACCESS);\n" +
+"                        if (! base_reserved) {\n" +
+"                            int rc = GetLastError ();\n" +
+"                            if (rc != ERROR_INVALID_ADDRESS)\n" +
+"                                goto sbrk_exit;\n" +
+"                        }\n" +
+"                        /* A null pointer signals (hopefully) a race condition with another thread. */\n" +
+"                        /* In this case, we try again. */\n" +
+"                    } while (! base_reserved);\n" +
+"                    /* Check returned pointer for consistency */\n" +
+"                    if (memory_info.BaseAddress && base_reserved != memory_info.BaseAddress)\n" +
+"                        goto sbrk_exit;\n" +
+"                    /* Assert postconditions */\n" +
+"                    assert ((unsigned) base_reserved % g_regionsize == 0);\n" +
+"#ifdef TRACE\n" +
+"                    printf (\"Reserve %p %d\\n\", base_reserved, reserve_size);\n" +
+"#endif\n" +
+"                    /* Did we get contiguous memory? */\n" +
+"                    if (contiguous) {\n" +
+"                        long start_size = (char *) g_last->top_committed - (char *) g_last->top_allocated;\n" +
+"                        /* Adjust allocation size */\n" +
+"                        allocate_size -= start_size;\n" +
+"                        /* Adjust the regions allocation top */\n" +
+"                        g_last->top_allocated = g_last->top_committed;\n" +
+"                        /* Recompute the size to commit */\n" +
+"                        to_commit = (char *) g_last->top_allocated + allocate_size - (char *) g_last->top_committed;\n" +
+"                        /* Round size to commit */\n" +
+"                        commit_size = CEIL (to_commit, g_my_pagesize);\n" +
+"                    }\n" +
+"                    /* Append the new region to the list */\n" +
+"                    if (! region_list_append (&g_last, base_reserved, reserve_size))\n" +
+"                        goto sbrk_exit;\n" +
+"                    /* Didn't we get contiguous memory? */\n" +
+"                    if (! contiguous) {\n" +
+"                        /* Recompute the size to commit */\n" +
+"                        to_commit = (char *) g_last->top_allocated + allocate_size - (char *) g_last->top_committed;\n" +
+"                        /* Round size to commit */\n" +
+"                        commit_size = CEIL (to_commit, g_my_pagesize);\n" +
+"                    }\n" +
+"                }\n" +
+"            }\n" +
+"            /* Assert preconditions */\n" +
+"            assert ((unsigned) g_last->top_committed % g_pagesize == 0);\n" +
+"            assert (0 < commit_size && commit_size % g_pagesize == 0); {\n" +
+"                /* Commit this */\n" +
+"                void *base_committed = VirtualAlloc (g_last->top_committed, commit_size,\n" +
+"                                                     MEM_COMMIT, PAGE_READWRITE);\n" +
+"                /* Check returned pointer for consistency */\n" +
+"                if (base_committed != g_last->top_committed)\n" +
+"                    goto sbrk_exit;\n" +
+"                /* Assert postconditions */\n" +
+"                assert ((unsigned) base_committed % g_pagesize == 0);\n" +
+"#ifdef TRACE\n" +
+"                printf (\"Commit %p %d\\n\", base_committed, commit_size);\n" +
+"#endif\n" +
+"                /* Adjust the regions commit top */\n" +
+"                g_last->top_committed = (char *) base_committed + commit_size;\n" +
+"            }\n" +
+"        }\n" +
+"        /* Adjust the regions allocation top */\n" +
+"        g_last->top_allocated = (char *) g_last->top_allocated + allocate_size;\n" +
+"        result = (char *) g_last->top_allocated - size;\n" +
+"    /* Deallocation requested? */\n" +
+"    } else if (size < 0) {\n" +
+"        long deallocate_size = - size;\n" +
+"        /* As long as we have a region to release */\n" +
+"        while ((char *) g_last->top_allocated - deallocate_size < (char *) g_last->top_reserved - g_last->reserve_size) {\n" +
+"            /* Get the size to release */\n" +
+"            long release_size = g_last->reserve_size;\n" +
+"            /* Get the base address */\n" +
+"            void *base_reserved = (char *) g_last->top_reserved - release_size;\n" +
+"            /* Assert preconditions */\n" +
+"            assert ((unsigned) base_reserved % g_regionsize == 0);\n" +
+"            assert (0 < release_size && release_size % g_regionsize == 0); {\n" +
+"                /* Release this */\n" +
+"                int rc = VirtualFree (base_reserved, 0,\n" +
+"                                      MEM_RELEASE);\n" +
+"                /* Check returned code for consistency */\n" +
+"                if (! rc)\n" +
+"                    goto sbrk_exit;\n" +
+"#ifdef TRACE\n" +
+"                printf (\"Release %p %d\\n\", base_reserved, release_size);\n" +
+"#endif\n" +
+"            }\n" +
+"            /* Adjust deallocation size */\n" +
+"            deallocate_size -= (char *) g_last->top_allocated - (char *) base_reserved;\n" +
+"            /* Remove the old region from the list */\n" +
+"            if (! region_list_remove (&g_last))\n" +
+"                goto sbrk_exit;\n" +
+"        } {\n") +
+(
+"            /* Compute the size to decommit */\n" +
+"            long to_decommit = (char *) g_last->top_committed - ((char *) g_last->top_allocated - deallocate_size);\n" +
+"            if (to_decommit >= g_my_pagesize) {\n" +
+"                /* Compute the size to decommit */\n" +
+"                long decommit_size = FLOOR (to_decommit, g_my_pagesize);\n" +
+"                /*  Compute the base address */\n" +
+"                void *base_committed = (char *) g_last->top_committed - decommit_size;\n" +
+"                /* Assert preconditions */\n" +
+"                assert ((unsigned) base_committed % g_pagesize == 0);\n" +
+"                assert (0 < decommit_size && decommit_size % g_pagesize == 0); {\n" +
+"                    /* Decommit this */\n" +
+"                    int rc = VirtualFree ((char *) base_committed, decommit_size,\n" +
+"                                          MEM_DECOMMIT);\n" +
+"                    /* Check returned code for consistency */\n" +
+"                    if (! rc)\n" +
+"                        goto sbrk_exit;\n" +
+"#ifdef TRACE\n" +
+"                    printf (\"Decommit %p %d\\n\", base_committed, decommit_size);\n" +
+"#endif\n" +
+"                }\n" +
+"                /* Adjust deallocation size and regions commit and allocate top */\n" +
+"                deallocate_size -= (char *) g_last->top_allocated - (char *) base_committed;\n" +
+"                g_last->top_committed = base_committed;\n" +
+"                g_last->top_allocated = base_committed;\n" +
+"            }\n" +
+"        }\n" +
+"        /* Adjust regions allocate top */\n" +
+"        g_last->top_allocated = (char *) g_last->top_allocated - deallocate_size;\n" +
+"        /* Check for underflow */\n" +
+"        if ((char *) g_last->top_reserved - g_last->reserve_size > (char *) g_last->top_allocated ||\n" +
+"            g_last->top_allocated > g_last->top_committed) {\n" +
+"            /* Adjust regions allocate top */\n" +
+"            g_last->top_allocated = (char *) g_last->top_reserved - g_last->reserve_size;\n" +
+"            goto sbrk_exit;\n" +
+"        }\n" +
+"        result = g_last->top_allocated;\n" +
+"    }\n" +
+"    /* Assert invariants */\n" +
+"    assert (g_last);\n" +
+"    assert ((char *) g_last->top_reserved - g_last->reserve_size <= (char *) g_last->top_allocated &&\n" +
+"            g_last->top_allocated <= g_last->top_committed);\n" +
+"    assert ((char *) g_last->top_reserved - g_last->reserve_size <= (char *) g_last->top_committed &&\n" +
+"            g_last->top_committed <= g_last->top_reserved &&\n" +
+"            (unsigned) g_last->top_committed % g_pagesize == 0);\n" +
+"    assert ((unsigned) g_last->top_reserved % g_regionsize == 0);\n" +
+"    assert ((unsigned) g_last->reserve_size % g_regionsize == 0);\n" +
+"\n" +
+"sbrk_exit:\n" +
+"#if defined (USE_MALLOC_LOCK) && defined (NEEDED)\n" +
+"    /* Release spin lock */\n" +
+"    slrelease (&g_sl);\n" +
+"#endif\n" +
+"    return result;\n" +
+"}\n" +
+"\n" +
+"/* mmap for windows */\n" +
+"static void *mmap (void *ptr, long size, long prot, long type, long handle, long arg) {\n" +
+"    static long g_pagesize;\n" +
+"    static long g_regionsize;\n" +
+"#ifdef TRACE\n" +
+"    printf (\"mmap %d\\n\", size);\n" +
+"#endif\n" +
+"#if defined (USE_MALLOC_LOCK) && defined (NEEDED)\n" +
+"    /* Wait for spin lock */\n" +
+"    slwait (&g_sl);\n" +
+"#endif\n" +
+"    /* First time initialization */\n" +
+"    if (! g_pagesize)\n" +
+"        g_pagesize = getpagesize ();\n" +
+"    if (! g_regionsize)\n" +
+"        g_regionsize = getregionsize ();\n" +
+"    /* Assert preconditions */\n" +
+"    assert ((unsigned) ptr % g_regionsize == 0);\n" +
+"    assert (size % g_pagesize == 0);\n" +
+"    /* Allocate this */\n" +
+"    ptr = VirtualAlloc (ptr, size,\n" +
+"                        MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE);\n" +
+"    if (! ptr) {\n" +
+"        ptr = (void *) MORECORE_FAILURE;\n" +
+"        goto mmap_exit;\n" +
+"    }\n" +
+"    /* Assert postconditions */\n" +
+"    assert ((unsigned) ptr % g_regionsize == 0);\n" +
+"#ifdef TRACE\n" +
+"    printf (\"Commit %p %d\\n\", ptr, size);\n" +
+"#endif\n" +
+"mmap_exit:\n" +
+"#if defined (USE_MALLOC_LOCK) && defined (NEEDED)\n" +
+"    /* Release spin lock */\n" +
+"    slrelease (&g_sl);\n" +
+"#endif\n" +
+"    return ptr;\n" +
+"}\n" +
+"\n" +
+"/* munmap for windows */\n" +
+"static long munmap (void *ptr, long size) {\n" +
+"    static long g_pagesize;\n" +
+"    static long g_regionsize;\n" +
+"    int rc = MUNMAP_FAILURE;\n" +
+"#ifdef TRACE\n" +
+"    printf (\"munmap %p %d\\n\", ptr, size);\n" +
+"#endif\n" +
+"#if defined (USE_MALLOC_LOCK) && defined (NEEDED)\n" +
+"    /* Wait for spin lock */\n" +
+"    slwait (&g_sl);\n" +
+"#endif\n" +
+"    /* First time initialization */\n" +
+"    if (! g_pagesize)\n" +
+"        g_pagesize = getpagesize ();\n" +
+"    if (! g_regionsize)\n" +
+"        g_regionsize = getregionsize ();\n" +
+"    /* Assert preconditions */\n" +
+"    assert ((unsigned) ptr % g_regionsize == 0);\n" +
+"    assert (size % g_pagesize == 0);\n" +
+"    /* Free this */\n" +
+"    if (! VirtualFree (ptr, 0,\n" +
+"                       MEM_RELEASE))\n" +
+"        goto munmap_exit;\n" +
+"    rc = 0;\n" +
+"#ifdef TRACE\n" +
+"    printf (\"Release %p %d\\n\", ptr, size);\n" +
+"#endif\n" +
+"munmap_exit:\n" +
+"#if defined (USE_MALLOC_LOCK) && defined (NEEDED)\n" +
+"    /* Release spin lock */\n" +
+"    slrelease (&g_sl);\n" +
+"#endif\n" +
+"    return rc;\n" +
+"}\n" +
+"\n" +
+"static void vminfo (CHUNK_SIZE_T  *free, CHUNK_SIZE_T  *reserved, CHUNK_SIZE_T  *committed) {\n" +
+"    MEMORY_BASIC_INFORMATION memory_info;\n" +
+"    memory_info.BaseAddress = 0;\n" +
+"    *free = *reserved = *committed = 0;\n" +
+"    while (VirtualQuery (memory_info.BaseAddress, &memory_info, sizeof (memory_info))) {\n" +
+"        switch (memory_info.State) {\n" +
+"        case MEM_FREE:\n" +
+"            *free += memory_info.RegionSize;\n" +
+"            break;\n" +
+"        case MEM_RESERVE:\n" +
+"            *reserved += memory_info.RegionSize;\n" +
+"            break;\n" +
+"        case MEM_COMMIT:\n" +
+"            *committed += memory_info.RegionSize;\n" +
+"            break;\n" +
+"        }\n" +
+"        memory_info.BaseAddress = (char *) memory_info.BaseAddress + memory_info.RegionSize;\n" +
+"    }\n" +
+"}\n" +
+"\n") +
+(
+"static int cpuinfo (int whole, CHUNK_SIZE_T  *kernel, CHUNK_SIZE_T  *user) {\n" +
+"    if (whole) {\n" +
+"        __int64 creation64, exit64, kernel64, user64;\n" +
+"        int rc = GetProcessTimes (GetCurrentProcess (),\n" +
+"                                  (FILETIME *) &creation64,\n" +
+"                                  (FILETIME *) &exit64,\n" +
+"                                  (FILETIME *) &kernel64,\n" +
+"                                  (FILETIME *) &user64);\n" +
+"        if (! rc) {\n" +
+"            *kernel = 0;\n" +
+"            *user = 0;\n" +
+"            return FALSE;\n" +
+"        }\n" +
+"        *kernel = (CHUNK_SIZE_T) (kernel64 / 10000);\n" +
+"        *user = (CHUNK_SIZE_T) (user64 / 10000);\n" +
+"        return TRUE;\n" +
+"    } else {\n" +
+"        __int64 creation64, exit64, kernel64, user64;\n" +
+"        int rc = GetThreadTimes (GetCurrentThread (),\n" +
+"                                 (FILETIME *) &creation64,\n" +
+"                                 (FILETIME *) &exit64,\n" +
+"                                 (FILETIME *) &kernel64,\n" +
+"                                 (FILETIME *) &user64);\n" +
+"        if (! rc) {\n" +
+"            *kernel = 0;\n" +
+"            *user = 0;\n" +
+"            return FALSE;\n" +
+"        }\n" +
+"        *kernel = (CHUNK_SIZE_T) (kernel64 / 10000);\n" +
+"        *user = (CHUNK_SIZE_T) (user64 / 10000);\n" +
+"        return TRUE;\n" +
+"    }\n" +
+"}\n" +
+"\n" +
+"#endif /* WIN32 */\n" +
+"\n" +
+"#endif // NDEBUG\n" +
+"\n" +
+"};  /* end of namespace KJS */\n");
+
+
+var thai =
+"ประเทศไทย\n" +
+"จากวิกิพีเดีย สารานุกรมเสรี\n" +
+"ไปที่: ป้ายบอกทาง, ค้นหา\n" +
+"	\n" +
+"\n" +
+"เนื่องจากบทความนี้ถูกล็อกเนื่องจาก ถูกก่อกวนหลายครั้งติดต่อกัน การแก้ไขจากผู้ที่ไม่ได้ลงทะเบียน หรือผู้ใช้ใหม่ไม่สามารถทำได้ขณะนี้\n" +
+"คุณสามารถแสดงความเห็น เสนอข้อความ หรือขอให้ยกเลิกการป้องกันได้ในหน้าอภิปราย หรือลงทะเบียนโดยสร้างชื่อผู้ใช้\n" +
+"   \n" +
+"วิกิพีเดีย:บทความคัดสรร\n" +
+"\n" +
+"    \"ไทย\" เปลี่ยนทางมาที่นี่ สำหรับความหมายอื่น ดูที่ ไทย (แก้ความกำกวม)\n" +
+"\n" +
+"ราชอาณาจักรไทย\n" +
+"ธงชาติไทย 	ตราแผ่นดินของไทย\n" +
+"ธงชาติ 	ตราแผ่นดิน\n" +
+"คำขวัญ: ชาติ ศาสนา พระมหากษัตริย์\n" +
+"เพลงชาติ: เพลงชาติไทย\n" +
+"แผนที่แสดงที่ตั้งของประเทศไทย\n" +
+"เมืองหลวง 	กรุงเทพมหานคร\n" +
+"13°44′N 100°30′E\n" +
+"เมืองใหญ่สุด 	กรุงเทพมหานคร\n" +
+"ภาษาราชการ 	ภาษาไทย\n" +
+"รัฐบาล 	เผด็จการทหาร\n" +
+" - ประมุขแห่งรัฐ 	พระบาทสมเด็จพระปรมินทรมหาภูมิพลอดุลยเดช\n" +
+" - นายกรัฐมนตรี 	พลเอกสุรยุทธ์ จุลานนท์\n" +
+" - ประธานคณะมนตรีความมั่นคงแห่งชาติ 	พลอากาศเอก ชลิต พุกผาสุข (รักษาการ)\n" +
+"สถาปนาเป็น\n" +
+"• สุโขทัย\n" +
+"• กรุงศรีอยุธยา\n" +
+"• กรุงธนบุรี\n" +
+"• กรุงรัตนโกสินทร์ 	\n" +
+"พ.ศ. 1781–1911\n" +
+"1893–2310\n" +
+"2310–6 เมษายน 2325\n" +
+"6 เมษายน 2325–ปัจจุบัน\n" +
+"เนื้อที่\n" +
+" - ทั้งหมด\n" +
+" \n" +
+" - พื้นน้ำ (%) 	 \n" +
+"514,000 กม.² (อันดับที่ 49)\n" +
+"198,457 ไมล์² \n" +
+"0.4%\n" +
+"ประชากร\n" +
+" - 2548 ประมาณ\n" +
+" - 2543\n" +
+" - ความหนาแน่น 	 \n" +
+"62,418,054 (อันดับที่ 19)\n" +
+"60,916,441\n" +
+"122/กม² (อันดับที่ 59)\n" +
+"{{{population_densitymi²}}}/ไมล์² \n" +
+"GDP (PPP)\n" +
+" - รวม\n" +
+" - ต่อประชากร 	2548 ค่าประมาณ\n" +
+"$559.5 billion (อันดับที่ 21)\n" +
+"$8,542 (อันดับที่ 72)\n" +
+"HDI (2546) 	0.778 (อันดับที่ 73) – ปานกลาง\n" +
+"สกุลเงิน 	บาท (฿) (THB)\n" +
+"เขตเวลา 	(UTC+7)\n" +
+"รหัสอินเทอร์เน็ต 	.th\n" +
+"รหัสโทรศัพท์ 	+66\n" +
+"\n" +
+"ประเทศไทย หรือ ราชอาณาจักรไทย ตั้งอยู่ในเอเชียตะวันออกเฉียงใต้ มีพรมแดนทางทิศตะวันออกติดลาวและกัมพูชา ทิศใต้ติดอ่าวไทยและมาเลเซีย ทิศตะวันตกติดทะเลอันดามันและพม่า และทิศเหนือติดพม่าและลาว โดยมีแม่น้ำโขงกั้นเป็นบางช่วง\n" +
+"\n" +
+"ประเทศไทยเป็นสมาชิกของสหประชาชาติ เอเปค และ อาเซียน มีศูนย์รวมการปกครองอยู่ที่ กรุงเทพมหานคร ซึ่งเป็นเมืองหลวงของประเทศ\n" +
+"\n" +
+"พระบาทสมเด็จพระปรมินทรมหาภูมิพลอดุลยเดช ทรงเป็นพระมหากษัตริย์ที่ครองราชย์ ในฐานะประมุขแห่งรัฐ ยาวนานที่สุดในโลกถึง 60 ปี\n" +
+"\n" +
+"\n" +
+"เนื้อหา\n" +
+"[ซ่อน]\n" +
+"\n" +
+"    * 1 ประวัติศาสตร์\n" +
+"          o 1.1 ชื่อประเทศไทย\n" +
+"    * 2 การเมืองการปกครอง\n" +
+"          o 2.1 เขตการปกครอง\n" +
+"          o 2.2 เมืองใหญ่ / จังหวัดใหญ่\n" +
+"    * 3 ภูมิอากาศและภูมิประเทศ\n" +
+"          o 3.1 ภูมิประเทศ\n" +
+"          o 3.2 ภูมิอากาศ\n" +
+"    * 4 เศรษฐกิจ\n" +
+"          o 4.1 เศรษฐกิจหลักของประเทศ\n" +
+"          o 4.2 การคมนาคม\n" +
+"          o 4.3 การสื่อสาร\n" +
+"    * 5 สังคม\n" +
+"          o 5.1 ชนชาติ\n" +
+"          o 5.2 ศาสนา\n" +
+"          o 5.3 การศึกษา\n" +
+"          o 5.4 ภาษา\n" +
+"          o 5.5 ศิลปะและวัฒนธรรม\n" +
+"          o 5.6 กีฬา\n" +
+"          o 5.7 วันสำคัญ\n" +
+"    * 6 ลำดับที่สำคัญ\n" +
+"    * 7 อ้างอิง\n" +
+"    * 8 แหล่งข้อมูลอื่น\n" +
+"\n" +
+"ประวัติศาสตร์\n" +
+"\n" +
+"    ดูบทความหลักที่ ประวัติศาสตร์ไทย\n" +
+"\n" +
+"ประเทศไทยมีประวัติศาสตร์ยาวนานมากนับเริ่มแต่การล่มสลายของราชอาณาจักรขอม-จักรวรรดินครวัต นครธม เมื่อต้นๆ คริสต์ศตวรรษที่ 13 [1]โดยมีความสืบเนื่องและคาบเกี่ยวระหว่างอาณาจักรโบราณหลายแห่ง เช่น อาณาจักรทวารวดี ศรีวิชัย ละโว้ เขมร ฯลฯ โดยเริ่มมีความชัดเจนในอาณาจักรสุโขทัยตั้งแต่ปี พ.ศ. 1781 อาณาจักรล้านนาทางภาคเหนือ กระทั่งเสื่อมอำนาจลงในช่วงต้นพุทธศตวรรษที่ 19 แล้วความรุ่งเรืองได้ปรากฏขึ้นในอาณาจักรทางใต้ ณ กรุงศรีอยุธยา โดยยังมีอาณาเขตที่ไม่แน่ชัด ครั้นเมื่อเสียกรุงศรีอยุธยาเป็นครั้งที่สองในปี พ.ศ. 2310 พระเจ้าตากสินจึงได้ย้ายราชธานีมาอยู่ที่กรุงธนบุรี\n" +
+"\n" +
+"ภายหลังสิ้นสุดอำนาจและมีการสถาปนากรุงรัตนโกสินทร์เมื่อ พ.ศ. 2325 อาณาจักรสยามเริ่มมีความเป็นปึกแผ่น มีการผนวกดินแดนบางส่วนของอาณาจักรล้านช้าง ครั้นในรัชกาลที่ 5 ได้ผนวกดินแดนของเมืองเชียงใหม่ หรืออาณาจักรล้านนาส่วนล่าง (ส่วนบนอยู่บริเวณเชียงตุง) เป็นการรวบรวมดินแดนครั้งใหญ่ครั้งสุดท้าย วันที่ 24 มิถุนายน พ.ศ. 2475 ได้เปลี่ยนแปลงการปกครองมาเป็นระบอบประชาธิปไตยแต่ก็ต้องรออีกถึง 41 ปี กว่าจะได้นายกรัฐมนตรีที่มาจากการเลือกตั้งครั้งแรกเมื่อ พ.ศ. 2516 หลังจากเหตุการณ์ 14 ตุลา หลังจากนั้นมีเหตุการณ์เรียกร้องประชาธิปไตยอีกสองครั้งคือ เหตุการณ์ 6 ตุลา และ เหตุการณ์พฤษภาทมิฬ ล่าสุดได้เกิดรัฐประหารขึ้นอีกครั้งในเดือนกันยายน พ.ศ. 2549 ซึ่งเป็นการยึดอำนาจจากรัฐบาลรักษาการ หลังจากได้มีการยุบสภาผู้แทนราษฎรเมื่อเดือนกุมภาพันธ์ 2549\n" +
+"\n" +
+"ชื่อประเทศไทย\n" +
+"\n" +
+"คำว่า ไทย มีความหมายในภาษาไทยว่า อิสรภาพ เสรีภาพ หรืออีกความหมายคือ ใหญ่ ยิ่งใหญ่ เพราะการจะเป็นอิสระได้จะต้องมีกำลังที่มากกว่า แข็งแกร่งกว่า เพื่อป้องกันการรุกรานจากข้าศึก เดิมประเทศไทยใช้ชื่อ สยาม (Siam) แต่ได้เปลี่ยนมาเป็นชื่อปัจจุบัน เมื่อปี พ.ศ. 2482 ตามประกาศรัฐนิยม ฉบับที่ 1 ของรัฐบาลจอมพล ป. พิบูลสงคราม ให้ใช้ชื่อ ประเทศ ประชาชน และสัญชาติว่า \"ไทย\" โดยในช่วงต่อมาได้เปลี่ยนกลับเป็นสยามเมื่อปี พ.ศ. 2488 ในช่วงเปลี่ยนนายกรัฐมนตรี แต่ในที่สุดได้เปลี่ยนกลับมาชื่อไทยอีกครั้งในปี พ.ศ. 2491 ซึ่งเป็นช่วงที่จอมพล ป. พิบูลสงครามเป็นนายกรัฐมนตรีในสมัยต่อมา ช่วงแรกเปลี่ยนเฉพาะชื่อภาษาไทยเท่านั้น ชื่อภาษาฝรั่งเศส[2]และอังกฤษคงยังเป็น \"Siam\" อยู่จนกระทั่งเดือนเมษายน พ.ศ. 2491 จึงได้เปลี่ยนชื่อภาษาฝรั่งเศสเป็น \"Thaïlande\" และภาษาอังกฤษเป็น \"Thailand\" อย่างในปัจจุบัน อย่างไรก็ตาม ชื่อ สยาม ยังเป็นที่รู้จักแพร่หลายทั้งในและต่างประเทศ.\n" +
+"\n" +
+"การเมืองการปกครอง\n" +
+"\n" +
+"เดิมประเทศไทยมีการปกครองระบอบสมบูรณาญาสิทธิราชย์ จนกระทั่งวันที่ 24 มิถุนายน พ.ศ. 2475 คณะราษฎรได้ทำการเปลี่ยนแปลงการปกครองเป็นราชาธิปไตยภายใต้รัฐธรรมนูญ โดยแบ่งอำนาจเป็นสามฝ่าย ได้แก่ ฝ่ายบริหาร ฝ่ายนิติบัญญัติและฝ่ายตุลาการ โดยฝ่ายบริหารจะมีนายกรัฐมนตรีเป็นหัวหน้ารัฐบาลซึ่งมากจากการแต่งตั้ง ฝ่ายนิติบัญญัติ ได้แก่ สภานิติบัญญัติแห่งชาติ และฝ่ายตุลาการ คือ ศาลยุติธรรม ศาลรัฐธรรมนูญ และศาลปกครอง\n" +
+"\n" +
+"ปัจจุบัน ประเทศไทยอยู่ภายใต้การปกครองระบอบเผด็จการทหาร โดยมีรัฐบาลชั่วคราวซึ่งแต่งตั้งโดยคณะมนตรีความมั่นคงแห่งชาติ หลังเกิดเหตุการณ์รัฐประหารเมื่อคืนวันที่ 19 กันยายน พ.ศ. 2549\n" +
+"\n" +
+"เขตการปกครอง\n" +
+"\n" +
+"ประเทศไทยแบ่งเขตการบริหารออกเป็น การบริหารราชการส่วนภูมิภาค ได้แก่จังหวัด 75 จังหวัด นอกจากนั้นยังมีการปกครองส่วนท้องถิ่น ได้แก่ กรุงเทพมหานคร เมืองพัทยา องค์การบริหารส่วนจังหวัด เทศบาล และองค์การบริหารส่วนตำบล ส่วน'สุขาภิบาล'นั้นถูกยกฐานะไปเป็นเทศบาลทั้งหมดในปี พ.ศ. 2542\n" +
+"\n" +
+"    รายชื่อจังหวัดทั้งหมดดูเพิ่มเติมที่ จังหวัดในประเทศไทย\n" +
+"\n" +
+"เมืองใหญ่ / จังหวัดใหญ่\n" +
+"ประเทศไทย จังหวัดในประเทศไทย\n" +
+"ประเทศไทย จังหวัดในประเทศไทย\n" +
+"กรุงเทพมหานครริมแม่น้ำเจ้าพระยา\n" +
+"กรุงเทพมหานครริมแม่น้ำเจ้าพระยา\n" +
+"\n" +
+"นอกจากกรุงเทพมหานครแล้ว มีหลายเมืองที่มีประชากรอยู่เป็นจำนวนมาก (ข้อมูลเดือนตุลาคม พ.ศ. 2549 ของ กรมการปกครอง กระทรวงมหาดไทย ) โดยเรียงลำดับตามตารางด้านล่าง โดยดูจากจำนวนประชากรในเขตเทศบาลและกรุงเทพมหานคร ซึ่งจะแสดงประชากรในเขตเมืองได้อย่างแท้จริง\n" +
+"อันดับ 	เมือง / เทศบาล 	จำนวนประชากร 	จังหวัด\n" +
+"1 	กรุงเทพมหานคร 	6,121,672 	กรุงเทพมหานคร\n" +
+"2 	นนทบุรี 	266,941 	นนทบุรี\n" +
+"3 	ปากเกร็ด 	167,138 	นนทบุรี\n" +
+"4 	หาดใหญ่ 	157,678 	สงขลา\n" +
+"5 	เชียงใหม่ 	150,805 	เชียงใหม่\n" +
+"6 	นครราชสีมา 	149,938 	นครราชสีมา\n" +
+"7 	อุดรธานี 	142,670 	อุดรธานี\n" +
+"8 	สุราษฎร์ธานี 	124,665 	สุราษฎร์ธานี\n" +
+"9 	ขอนแก่น 	121,283 	ขอนแก่น\n" +
+"10 	นครศรีธรรมราช 	106,293 	นครศรีธรรมราช\n" +
+"\n" +
+"นอกจากนี้ยังมีการเรียงลำดับประชากรตามจังหวัดได้ดังต่อไปนี้\n" +
+"อันดับ 	จังหวัด 	จำนวนประชากร 	ภาค\n" +
+"1 	กรุงเทพมหานคร 	6,121,672 	ภาคกลาง\n" +
+"2 	นครราชสีมา 	2,546,763 	ภาคตะวันออกเฉียงเหนือ\n" +
+"3 	อุบลราชธานี 	1,774,808 	ภาคตะวันออกเฉียงเหนือ\n" +
+"4 	ขอนแก่น 	1,747,542 	ภาคตะวันออกเฉียงเหนือ\n" +
+"5 	เชียงใหม่ 	1,650,009 	ภาคเหนือ\n" +
+"6 	บุรีรัมย์ 	1,531,430 	ภาคตะวันออกเฉียงเหนือ\n" +
+"7 	อุดรธานี 	1,523,802 	ภาคตะวันออกเฉียงเหนือ\n" +
+"8 	นครศรีธรรมราช 	1,504,420 	ภาคใต้\n" +
+"9 	ศรีสะเกษ 	1,443,975 	ภาคตะวันออกเฉียงเหนือ\n" +
+"10 	สุรินทร์ 	1,374,700 	ภาคตะวันออกเฉียงเหนือ\n" +
+"\n" +
+"    ดูข้อมูลทั้งหมดที่ เมืองใหญ่ของประเทศไทยเรียงตามจำนวนประชากร และ จังหวัดในประเทศไทยเรียงตามจำนวนประชากร\n" +
+"\n" +
+"ภูมิอากาศและภูมิประเทศ\n" +
+"\n" +
+"ภูมิประเทศ\n" +
+"ประเทศไทย สภาพทางภูมิศาสตร์\n" +
+"ประเทศไทย สภาพทางภูมิศาสตร์\n" +
+"\n" +
+"ประเทศไทยมีสภาพทางภูมิศาสตร์ที่หลากหลาย ภาคเหนือประกอบด้วยเทือกเขาจำนวนมาก จุดที่สูงที่สุด คือ ดอยอินทนนท์ (2,576 เมตร) ในจังหวัดเชียงใหม่ ภาคตะวันออกเฉียงเหนือเป็นที่ราบสูงโคราชติดกับแม่น้ำโขงทางด้านตะวันออก ภาคกลางเป็นที่ราบลุ่มแม่น้ำเจ้าพระยา ซึ่งสายน้ำไหลลงสู่อ่าวไทย ภาคใต้มีจุดที่แคบลง ณ คอคอดกระแล้วขยายใหญ่เป็นคาบสมุทรมลายู\n" +
+"\n" +
+"    * เมื่อเปรียบเทียบพื้นที่ของประเทศไทย กับ ประเทศอื่น จะได้ดังนี้\n" +
+"          o ประเทศพม่า ใหญ่กว่าประเทศไทยประมาณ 1.3 เท่า\n" +
+"          o ประเทศอินโดนีเซีย ใหญ่กว่าประมาณ 3.7 เท่า\n" +
+"          o ประเทศอินเดีย ใหญ่กว่าประมาณ 6.4 เท่า\n" +
+"          o ประเทศจีน และ สหรัฐอเมริกา ใหญ่กว่าประมาณ 19 เท่า\n" +
+"          o ประเทศรัสเซีย ใหญ่กว่าประมาณ 33 เท่า\n" +
+"          o ขนาดใกล้เคียงกับ ประเทศฝรั่งเศส ประเทศสวีเดน และ ประเทศสเปน\n" +
+"\n" +
+"วันที่ 26 ธันวาคม พ.ศ. 2547 ได้มีเหตุการณ์คลื่นสึนามิเกิดขึ้นก่อความเสียหายในเขตภาคใต้ของประเทศไทย\n" +
+"\n" +
+"ภูมิอากาศ\n" +
+"\n" +
+"ภูมิอากาศของไทยเป็นแบบเขตร้อน อากาศร้อนที่สุดในเดือนเมษายน-พฤษภาคม โดยจะมีฝนตกและเมฆมากจากลมมรสุมตะวันตกเฉียงใต้ในช่วงกลางเดือนพฤษภาคม-เดือนตุลาคม ส่วนในเดือนพฤศจิกายนถึงกลางเดือนมีนาคม อากาศแห้ง และหนาวเย็นจากลมมรสุมตะวันออกเฉียงเหนือ ยกเว้นภาคใต้ที่มีอากาศร้อนชื้นตลอดทั้งปี\n" +
+"\n" +
+"เศรษฐกิจ\n" +
+"\n" +
+"เศรษฐกิจหลักของประเทศ\n" +
+"\n" +
+"เกษตรกรรม อุตสาหกรรม การท่องเที่ยว การบริการ และ ทรัพยากรธรรมชาติ ถือเป็นเศรษฐกิจหลักที่ทำรายได้ให้กับคนในประเทศ โดยภาพรวมทางเศรษฐกิจอ้างอิงเมื่อ พ.ศ. 2546 มี GDP 5,930.4 พันล้านบาท ส่งออกมูลค่า 78.1 พันล้านเหรียญสหรัฐ ในขณะที่นำเข้า 74.3 พันล้านเหรียญสหรัฐ[3]\n" +
+"ภาพพันธุ์ข้าวจากกรมวิชาการเกษตร\n" +
+"ภาพพันธุ์ข้าวจากกรมวิชาการเกษตร\n" +
+"ภาพยางพาราจากกรมวิชาการเกษตร\n" +
+"ภาพยางพาราจากกรมวิชาการเกษตร\n" +
+"\n" +
+"ในด้านเกษตรกรรม ข้าว ถือเป็นผลผลิตที่สำคัญที่สุด เป็นผู้ผลิตและส่งออกข้าว เป็นอันดับหนึ่งของโลก ด้วยสัดส่วนการส่งออก ร้อยละ 36 รองลงมาคือ เวียดนาม ร้อยละ 20 อินเดีย ร้อยละ 18 สหรัฐอเมริกา ร้อยละ14 ปากีสถาน ร้อยละ 12 ตามลำดับ [4] พืชผลทางการเกษตรอื่นๆ ได้แก่ ยางพารา ผักและผลไม้ต่างๆ มีการเพาะเลี้ยงปศุสัตว์เช่น วัว สุกร เป็ด ไก่ สัตว์น้ำทั้งปลาน้ำจืด ปลาน้ำเค็มในกระชัง นากุ้ง เลี้ยงหอย รวมถึงการประมงทางทะเล ปี 2549 ไทยมีการส่งออกกุ้งไปสหรัฐฯ 177,717.29 ตัน มูลค่า 45,434.57 ล้านบาท [5]\n" +
+"\n" +
+"อุตสาหกรรมที่สำคัญ ได้แก่ อุตสาหกรรมแปรรูปทางการเกษตร สิ่งทอ อิเล็กทรอนิกส์ รถยนต์ ส่วนทรัพยากรธรรมชาติที่สำคัญเช่น ดีบุก ก๊าซธรรมชาติ จากข้อมูลปี พ.ศ. 2547 มีการผลิตสิ่งทอมูลค่า 211.4 พันล้านบาท แผงวงจรรวม 196.4 พันล้านบาท อาหารทะเลกระป๋อง 36.5 พันล้านบาท สับปะรดกระป๋อง 11.1 พันล้านบาท รถยนต์ส่วนบุคคล 2.99 แสนคัน รถบรรทุก รถกระบะ และอื่นๆ รวม 6.28 แสนคัน จักรยานยนต์ 2.28 ล้านคัน ดีบุก 694 ตัน ก๊าซธรรมชาติ 789 พันล้านลูกบาศก์ฟุต น้ำมันดิบ]] 31.1 ล้านบาร์เรล [6]\n" +
+"เกาะพีพี สถานท่องเที่ยวที่สำคัญแห่งหนึ่งของประเทศ\n" +
+"เกาะพีพี สถานท่องเที่ยวที่สำคัญแห่งหนึ่งของประเทศ\n" +
+"\n" +
+"ส่วนด้านการท่องเที่ยว การบริการและโรงแรม ในปี พ.ศ. 2547 มีนักท่องเที่ยวรวม 11.65 ล้านคน 56.52% มาจากเอเชียตะวันออกและอาเซียน (โดยเฉพาะมาเลเซียคิดเป็น 11.97% ญี่ปุ่น 10.33%) ยุโรป 24.29% ทวีปอเมริกาเหนือและใต้รวมกัน 7.02% [7] สถานที่ท่องเที่ยวที่สำคัญได้แก่ กรุงเทพมหานคร พัทยา ภาคใต้ฝั่งทะเลอันดามัน จังหวัดเชียงใหม่\n" +
+"\n" +
+"การคมนาคม\n" +
+"\n" +
+"ดูบทความหลัก การคมนาคมในประเทศไทย\n" +
+"\n" +
+"การคมนาคมในประเทศไทย ส่วนใหญ่ประกอบด้วย การเดินทางโดยรถยนต์ และ จักรยานยนต์ ทางหลวงสายหลักในประเทศไทย ได้แก่ ถนนพหลโยธิน (ทางหลวงหมายเลข 1) ถนนมิตรภาพ (ทางหลวงหมายเลข 2) ถนนสุขุมวิท (ทางหลวงหมายเลข 3) และถนนเพชรเกษม (ทางหลวงหมายเลข 4) และยังมีทางหลวงพิเศษระหว่างเมือง (มอเตอร์เวย์) ใน 2 เส้นทางคือ มอเตอร์เวย์กรุงเทพฯ-ชลบุรี (ทางหลวงหมายเลข 7) และถนนกาญจนาภิเษก (วงแหวนรอบนอกกรุงเทพมหานคร - ทางหลวงหมายเลข 9) นอกจากนี้ระบบขนส่งมวลชนจะมีการบริการตามเมืองใหญ่ต่างๆ ได้แก่ระบบรถเมล์ และรถไฟ รวมถึงระบบที่เริ่มมีการใช้งาน รถไฟลอยฟ้า และรถไฟใต้ดิน และในหลายพื้นที่จะมีการบริการรถสองแถว รวมถึงรถรับจ้างต่างๆ ได้แก่ แท็กซี่ เมลเครื่อง มอเตอร์ไซค์รับจ้าง และ รถตุ๊กตุ๊ก ในบางพื้นที่ ที่อยู่ริมน้ำจะมีเรือรับจ้าง และแพข้ามฟาก บริการ\n" +
+"รถไฟฟ้าบีทีเอส สถานีอโศก\n" +
+"รถไฟฟ้าบีทีเอส สถานีอโศก\n" +
+"\n" +
+"สำหรับการคมนาคมทางอากาศนั้น ปัจจุบันประเทศไทยได้เปิดใช้ท่าอากาศยานสุวรรณภูมิ ซึ่งเป็นท่าอากาศยานที่มีขนาดตัวอาคารที่ใหญ่ที่สุดในโลก และมีหอบังคับการบินที่สูงที่สุดในโลก ด้วยความสูง 132.2 เมตร ซึ่งรองรับผู้โดยสารได้ 45 ล้านคนต่อปี โดยเปิดอย่างเป็นทางการตั้งแต่วันที่ 29 กันยายน พ.ศ. 2549 ทดแทนท่าอากาศยานนานาชาติกรุงเทพ (ดอนเมือง) ที่เปิดใช้งานมานานถึง 92 ปี\n" +
+"\n" +
+"ส่วนการคมนาคมทางน้ำ ประเทศไทยมีท่าเรือหลักๆ คือ ท่าเรือกรุงเทพ(คลองเตย) และท่าเรือแหลมฉบัง\n" +
+"\n" +
+"การสื่อสาร\n" +
+"\n" +
+"    * ระบบโทรศัพท์ในประเทศไทยมีโทรศัพท์พื้นฐาน 7.035 ล้านหมายเลข (2548) และโทรศัพท์มือถือ 27.4 ล้านหมายเลข (2548) [8]\n" +
+"    * สถานีวิทยุ: คลื่นเอฟเอ็ม 334 สถานี , คลื่นเอเอ็ม 204 สถานี และ คลื่นสั้น 6 สถานี (2542) โดยมีจำนวนผู้ใช้วิทยุ 13.96 ล้านคน (2540) [8]\n" +
+"    * สถานีโทรทัศน์ มี 6 ช่องสถานี (โดยทุกช่องสถานีแม่ข่ายอยู่ในกรุงเทพ) มีสถานีเครือข่ายทั้งหมด 111 สถานี และจำนวนผู้ใช้โทรทัศน์ 15.19 ล้านคน (2540) [8]\n" +
+"    * รหัสโดเมนอินเทอร์เน็ตใช้รหัส th\n" +
+"\n" +
+"สังคม\n" +
+"วัดพระศรีรัตนศาสดาราม กรุงเทพมหานคร\n" +
+"วัดพระศรีรัตนศาสดาราม กรุงเทพมหานคร\n" +
+"\n" +
+"ชนชาติ\n" +
+"\n" +
+"ในประเทศไทย ถือได้ว่า มีความหลากหลายทางเชื้อชาติ มีทั้ง ชาวไทย ชาวไทยเชื้อสายลาว ชาวไทยเชื้อสายมอญ ชาวไทยเชื้อสายเขมร รวมไปถึงกลุ่มชาวไทยเชื้อสายจีน ชาวไทยเชื้อสายมลายู ชาวชวา(แขกแพ) ชาวจาม(แขกจาม) ชาวเวียด ไปจนถึงชาวพม่า และชาวไทยภูเขาเผ่าต่างๆ เช่น ชาวกะเหรี่ยง ชาวลีซอ ชาวอ่าข่า ชาวอีก้อ ชาวม้ง ชาวเย้า รวมไปจนถึงชาวส่วย ชาวกูบ ชาวกวย ชาวจะราย ชาวระแดว์ ชาวข่า ชาวขมุ ซึ่งมีในปัจจุบันก็มีความสำคัญมาก ต่อวิถีชีวิต และวัฒนธรรมไทยในปัจจุบัน\n" +
+"\n" +
+"ประชากรชาวไทย 75% ชาวไทยเชื้อสายจีน 14% และอื่นๆ 11% [8]\n" +
+"\n" +
+"    ดูเพิ่มที่ ชาวไทย\n" +
+"\n" +
+"ศาสนา\n" +
+"พระพุทธชินราช วัดพระศรีรัตนมหาธาตุวรมหาวิหาร จังหวัดพิษณุโลก\n" +
+"พระพุทธชินราช วัดพระศรีรัตนมหาธาตุวรมหาวิหาร จังหวัดพิษณุโลก\n" +
+"\n" +
+"ประมาณร้อยละ 95 ของประชากรไทยนับถือศาสนาพุทธซึ่งเป็นศาสนาประจำชาติ(โดยพฤตินัย) นิกายเถรวาท ศาสนาอิสลามประมาณร้อยละ 4 (ส่วนใหญ่เป็นชาวไทยทางภาคใต้ตอนล่าง) ศาสนาคริสต์และศาสนาอื่นประมาณร้อยละ 1\n" +
+"\n" +
+"    ดูเพิ่มที่ พระพุทธศาสนาในประเทศไทย\n" +
+"\n" +
+"การศึกษา\n" +
+"\n" +
+"ในทางกฎหมาย รัฐบาลจะต้องจัดการศึกษาให้ขั้นพื้นฐานสิบสองปี แต่การศึกษาขั้นบังคับของประเทศไทยในปัจจุบันคือเก้าปี บุคคลทั่วไปจะเริ่มจากระดับชั้นอนุบาล เป็นการเตรียมความพร้อมก่อนการเรียนตามหลักสูตรพื้นฐาน ต่อเนื่องด้วยระดับประถมศึกษาและมัธยมศึกษาตอนต้น หลังจากจบการศึกษาระดับมัธยมต้น สามารถเลือกได้ระหว่างศึกษาต่อสายสามัญ ระดับมัธยมศึกษาตอนปลายเพื่อศึกษาต่อในระดับมหาวิทยาลัย หรือเลือกศึกษาต่อสายวิชาชีพ ในวิทยาลัยเทคนิค หรือพาณิชยการ หรือเลือกศึกษาต่อในสถาบันทางทหารหรือตำรวจ\n" +
+"\n" +
+"โรงเรียนและมหาวิทยาลัยในประเทศไทย แบ่งออกเป็น 2 ประเภทหลักได้แก่ โรงเรียนรัฐบาล และโรงเรียนเอกชน และ มหาวิทยาลัยรัฐบาล และมหาวิทยาลัยเอกชน โดยโรงเรียนรัฐบาลและมหาวิทยาลัยรัฐบาล จะเสียค่าเล่าเรียนน้อยกว่า โรงเรียนเอกชนและมหาวิทยาลัยเอกชน\n" +
+"\n" +
+"    ดูเพิ่มที่ รายชื่อสถาบันอุดมศึกษาในประเทศไทย\n" +
+"\n" +
+"ภาษา\n" +
+"\n" +
+"    ดูบทความหลักที่ ภาษาในประเทศไทย\n" +
+"\n" +
+"ภาษาไทย ประเทศไทยมีภาษาไทยเป็นภาษาราชการ ภาษาพูดของคนไทยมีมาแต่เมื่อไรยังไม่เป็นที่ทราบแน่ชัด แต่จากการสันนิฐานน่าจะมีมากว่า 4,000 ปีแล้ว ส่วนตัวอักษรนั้นเพิ่งมีการประดิษฐ์ขึ้นอย่างเป็นทางการในสมัยสุโขทัยโดย พ่อขุนรามคำแหงมหาราช ส่วนภาษาอื่นที่มีการใช้อยู่บ้าง เช่น ภาษาอังกฤษ ภาษาจีน เป็นต้น\n" +
+"\n" +
+"ศิลปะและวัฒนธรรม\n" +
+"พระที่นั่งไอศวรรย์ทิพย์อาสน์ พระราชวังบางปะอิน จังหวัดพระนครศรีอยุธยา\n" +
+"พระที่นั่งไอศวรรย์ทิพย์อาสน์ พระราชวังบางปะอิน จังหวัดพระนครศรีอยุธยา\n" +
+"\n" +
+"ศิลปะไทยมีลักษณะเฉพาะตัวค่อนข้างสูง โดยมีความกลมกลืนและคล้ายคลึงกับศิลปวัฒนธรรมเพื่อนบ้านอยู่บ้าง แต่ด้วยการสืบทอดและการสร้างสรรค์ใหม่ ทำให้ศิลปะไทยมีเอกลักษณ์สูง\n" +
+"\n" +
+"    * จิตรกรรม งานจิตรกรรมไทยนับว่าเป็นงานศิลปะชั้นสูง ได้รับการสืบทอดมาช้านาน มักปรากฏในงานจิตรกรรมฝาผนัง ตามวัดวาอาราม รวมทั้งในสมุดข่อยโบราณ งานจิตรกรรมไทยยังเกี่ยวข้องกับงานศิลปะแขนงอื่นๆ เช่น งานลงรักปิดทอง ภาพวาดพระบฏ เป็นต้น\n" +
+"    * ประติมากรรม เดิมนั้นช่างไทยทำงานประติมากรรมเฉพาะสิ่งศักดิ์สิทธิ์ เช่น พระพุทธรูป เทวรูป โดยมีสกุลช่างต่างๆ นับตั้งแต่ก่อนสมัยสุโขทัย เรียกว่า สกุลช่างเชียงแสน สกุลช่างสุโขทัย อยุธยา และกระทั่งรัตนโกสินทร์ โดยใช้ทองสำริดเป็นวัสดุหลักในงานประติมากรรม เนื่องจากสามารถแกะแบบด้วยขี้ผึ้งและตกแต่งได้ แล้วจึงนำไปหล่อโลหะ เมื่อเทียบกับประติมากรรมศิลาในยุคก่อนนั้น งานสำริดนับว่าอ่อนช้อยงดงามกว่ามาก\n" +
+"    * สถาปัตยกรรม สถาปัตยกรรมไทยมีปรากฏให้เห็นในชั้นหลัง เนื่องจากงานสถาปัตยกรรมส่วนใหญ่ชำรุดทรุดโทรมได้ง่าย โดยเฉพาะงานไม้ ไม่ปรากฏร่องรอยสมัยโบราณเลย สถาปัตยกรรมไทยมีให้เห็นอยู่ในรูปของบ้านเรือนไทย โบสถ์ วัด และปราสาทราชวัง ซึ่งล้วนแต่สร้างขึ้นให้เหมาะสมกับสภาพอากาศและการใช้สอยจริง\n" +
+"\n" +
+"    ดูเพิ่มที่ ศิลปะไทย\n" +
+"\n" +
+"กีฬา\n" +
+"ราชมังคลากีฬาสถาน การกีฬาแห่งประเทศไทย\n" +
+"ราชมังคลากีฬาสถาน การกีฬาแห่งประเทศไทย\n" +
+"\n" +
+"กีฬาที่นิยมมากที่สุดในประเทศไทยได้แก่ ฟุตบอล โดยในการแข่งขันระหว่างประเทศ ทีมชาติไทยได้เข้าเล่นและได้อันดับสูงสุดในเอเชียนคัพ ได้อันดับ 3 ใน เอเชียนคัพ 1972 กีฬาอื่นที่นิยมเล่นได้แก่ บาสเกตบอล มวย และแบดมินตัน โดยในประเทศไทยมีการจัดฟุตบอลอาชีพ โดยแบ่งแยกตามทีมประจำจังหวัด สำหรับกีฬาไทย ได้แก่ มวยไทย และ ตะกร้อ แม้จะมีความนิยมไม่เท่ากีฬาทั่วไป แต่ยังมีการเล่นโดยทั่วไปรวมถึงการเปิดสอนในโรงเรียน\n" +
+"\n" +
+"ประเทศไทยเป็นตัวแทนจัดงานเอเชียนเกมส์ 4 ครั้ง และซีเกมส์ ทั้งหมด 5 ครั้ง โดยจัดครั้งแรกที่ประเทศไทย\n" +
+"\n" +
+"นักกีฬาไทยที่มีชื่อเสียงมาก ได้แก่\n" +
+"\n" +
+"    * นักมวย - เขาทราย แกแล็คซี่, สด จิตรลดา, สามารถ พยัคฆ์อรุณ, สมรักษ์ คำสิงห์\n" +
+"    * นักเทนนิส - ภราดร ศรีชาพันธุ์, แทมมารีน ธนสุกาญจน์, ดนัย อุดมโชค\n" +
+"    * นักว่ายน้ำ - รัฐพงษ์ ศิริสานนท์(ฉลามนุ้ก), ต่อวัย เสฎฐโสธร, ต่อลาภ เสฎฐโสธร\n" +
+"    * นักฟุตบอล - ปิยะพงษ์ ผิวอ่อน, เกียรติศักดิ์ เสนาเมือง\n" +
+"    * นักสนุกเกอร์ - ต๋อง ศิษย์ฉ่อย\n" +
+"    * นักกรีฑา - เรวดี ศรีท้าว\n" +
+"    * นักเทควันโด - เยาวภา บุรพลชัย\n" +
+"    * นักยกน้ำหนัก - อุดมพร พลศักดิ์, ปวีณา ทองสุก\n" +
+"    * นักกอล์ฟ - ธงชัย ใจดี\n" +
+"\n" +
+"วันสำคัญ\n" +
+"\n" +
+"วันสำคัญในประเทศไทยจะมีจำนวนมากโดยเฉพาะวันที่ไม่ใช่วันหยุดราชการ ซึ่งจะตั้งขึ้นหลังจากมีเหตุการณ์สำคัญเกิดขึ้น โดยวันชาติของประเทศไทยตรงกับวันที่ 5 ธันวาคม เป็น ตามวันพระราชสมภพ ของพระบาทสมเด็จพระเจ้าอยู่หัว ภูมิพลอดุลยเดช\n" +
+"\n" +
+"    ดูบทความหลักที่ วันสำคัญในประเทศไทย\n" +
+"\n" +
+"ลำดับที่สำคัญ\n" +
+"\n" +
+"    * พระมหากษัตริย์ไทยพระบาทสมเด็จพระปรมินทรมหาภูมิพลอดุลยเดช เป็นพระมหากษัตริย์ที่ครองราชย์ในฐานะประมุขแห่งรัฐที่นานที่สุดในโลก\n" +
+"    * กรุงเทพฯ เป็นเมืองหลวงที่มีชื่อยาวที่สุดในโลก (169 ตัวอักษร)\n" +
+"    * ดัชนีเศรษฐกิจของประเทศไทย อยู่อันดับที่ 71 จาก 155 เขตเศรษฐกิจ ตาม Index of Economic Freedom\n" +
+"    * จังหวัดหนองคายได้รับการจัดอันดับจากนิตยสาร Modern Maturity ของสหรัฐเมื่อ พ.ศ. 2544 ว่าเป็นเมืองที่น่าอยู่สำหรับผู้สูงอายุชาวอเมริกันอันดับที่ 7 ของโลก [9]\n" +
+"    * Growth Competitiveness Index Ranking พ.ศ. 2546 อยู่อันดับที่ 34 จาก 104 [10]\n" +
+"    * ตึกใบหยก 2 เป็นตึกที่สูงที่สุดในประเทศไทย และสูงเป็นอันดับ 30 ของโลก พ.ศ. 2549\n" +
+"\n" +
+"อ้างอิง\n" +
+"\n" +
+"   1. ↑ 4th edition \"ANKOR an introduction to the temples\" Dawn Rooney ISBN: 962-217-683-6\n" +
+"   2. ↑ ในสมัยก่อนนั้น (ตั้งแต่คริสต์ศตวรรษที่ 17 ในยุโรป) ภาษาสากลในการติดต่อระหว่างประเทศ (lingua franca) คือ ภาษาฝรั่งเศส เอกสารระหว่างประเทศจะใช้ภาษาฝรั่งเศสเป็นหลัก รวมถึงหนังสือเดินทางไทยรุ่นแรกๆ ด้วย\n" +
+"   3. ↑ ดัชนีเศรษฐกิจประเทศไทย จากเว็บไซต์ธนาคารแห่งประเทศไทย\n" +
+"   4. ↑ ข้าวไทย ย่างก้าวพัฒนา สร้างไทยเป็นศูนย์กลางข้าวโลก โดย เทคโนโลยีชาวบ้าน มติชน วันที่ 01 มิถุนายน พ.ศ. 2550 ปีที่ 19 ฉบับที่ 408\n" +
+"   5. ↑ http://www.thairath.co.th/news.php?section=agriculture&content=52868\n" +
+"   6. ↑ ผลผลิตของประเทศไทย จากเว็บไซต์ธนาคารแห่งประเทศไทย\n" +
+"   7. ↑ ข้อมูลการท่องเที่ยว จากการท่องเที่ยวแห่งประเทศไทย (ข้อมูลเป็นไฟล์เอกเซล)\n" +
+"   8. ↑ 8.0 8.1 8.2 8.3 รายละเอียดประเทศไทยจากเว็บซีไอเอ\n" +
+"   9. ↑ http://207.5.46.81/tat_news/detail.asp?id=963\n" +
+"  10. ↑ ข้อมูลจาก Webforum.org พ.ศ. 2546\n" +
+"\n" +
+"แหล่งข้อมูลอื่น\n" +
+"Commons\n" +
+"คอมมอนส์ มีภาพและสื่ออื่นๆ เกี่ยวกับ:\n" +
+"ประเทศไทย\n" +
+"ฟลิคเกอร์\n" +
+"ฟลิคเกอร์ มีรูปภาพเกี่ยวกับ: ประเทศไทย\n" +
+"\n" +
+"    * รัฐบาลไทย\n" +
+"    * การท่องเที่ยวแห่งประเทศไทย\n" +
+"    * ประเทศไทยศึกษา ห้องสมุดรัฐสภา สหรัฐอเมริกา\n" +
+"    * พจนานุกรมท่องเที่ยวไทย\n" +
+"    * แผนที่ประเทศไทย Longdo Map\n";
+
+function get_most_popular(text) {
+  var i;
+  var frequencies = new Object();
+  var letter;
+  for (i = 0; i < text.length; i++) {
+    letter = text.charAt(i);
+    if (typeof(frequencies[letter]) == 'undefined')
+      frequencies[letter] = 0;
+    frequencies[letter]++;
+  }
+  var most = [];
+  for (letter in frequencies) {
+    if (frequencies[letter] > 50) {
+      most.push(letter);
+    }
+  }
+  most.sort();
+  return most;
+}
+
+
+var languages = new Array(
+    chinese,     // 1
+    cyrillic,    // 2
+    devanagari,  // 3
+    english,     // 4
+    greek,       // 5
+    hebrew,      // 6
+    japanese,    // 7
+    korean,      // 8
+    persian,     // 9
+    source,      // 10
+    thai);       // 11
+
+
+var number_re = /[0-9]/;
+var latin_lc = "[a-zA\u0631]";
+assertEquals(7, latin_lc.length);
+var latin_lc_re = new RegExp(latin_lc);
+var latin_lc_re2 = new RegExp(/[a-zA\u0631]/);
+
+assertEquals(13793, chinese.length, "chinese utf8 in source");
+assertEquals(60606, cyrillic.length, "cyrillic utf8 in source");
+assertEquals(20203, devanagari.length, "devanagari utf8 in source");
+assertEquals(37505, english.length, "english utf8 in source");
+assertEquals(30052, greek.length, "greek utf8 in source");
+assertEquals(25640, hebrew.length, "hebrew utf8 in source");
+assertEquals(31082, japanese.length, "japanese utf8 in source");
+assertEquals(12291, korean.length, "korean utf8 in source");
+assertEquals(13851, persian.length, "persian utf8 in source");
+assertEquals(177470, source.length, "source utf8 in source");
+assertEquals(18315, thai.length, "thai utf8 in source");
+
+munged_sizes = new Array(17197, 2511, 2645, 3820, 3086, 2609,
+                         27231, 12972, 2014, 24943, 2773);
+
+
+var i = 0;
+for (idx in languages) {
+  i++;
+  var text = languages[idx];
+  assertTrue(latin_lc_re.test(text), "latin_lc" + i);
+  assertTrue(latin_lc_re2.test(text), "latin_lc" + i);
+  assertTrue(number_re.test(text), "number " + i);
+  var most_popular = get_most_popular(text);
+  var idx;
+  var re = "([x";
+  var last_c = -9999;
+  for (idx in most_popular) {
+    var c = most_popular[idx];
+    if ("^]-\n\\".indexOf(c) == -1) {
+      if (c.charCodeAt(0) > last_c &&
+          c.charCodeAt(0) - 20 < last_c) {
+        re += "-" + c;
+        last_c = -9999;
+      } else {
+        re += c;
+        last_c = c.charCodeAt(0);
+      }
+    }
+  }
+  re += "]+)";
+  var char_class = new RegExp(re, "g");
+  var munged = text.replace(char_class, "foo");
+  assertEquals(munged_sizes[i - 1], munged.length, "munged size " + i);
+}
+
+
+function hex(x) {
+  x &= 15;
+  if (x < 10) {
+    return String.fromCharCode(x + 48);
+  } else {
+    return String.fromCharCode(x + 97 - 10);
+  }
+}
+
+
+function dump_re(re) {
+  var out = "";
+  for (var i = 0; i < re.length; i++) {
+    var c = re.charCodeAt(i);
+    if (c >= 32 && c <= 126) {
+      out += re[i];
+    } else if (c < 256) {
+      out += "\\x" + hex(c >> 4) + hex(c);
+    } else {
+      out += "\\u" + hex(c >> 12) + hex(c >> 8) + hex(c >> 4) + hex(c);
+    }
+  }
+  print ("re = " + out);
+}
+
+var thai_l_thingy = "\u0e44";
+var thai_l_regexp = new RegExp(thai_l_thingy);
+var thai_l_regexp2 = new RegExp("[" + thai_l_thingy + "]");
+assertTrue(thai_l_regexp.test(thai_l_thingy));
+assertTrue(thai_l_regexp2.test(thai_l_thingy));
+
+
diff --git a/deps/v8/test/mjsunit/unusual-constructor.js b/deps/v8/test/mjsunit/unusual-constructor.js
new file mode 100644
index 0000000..4e1ec2e
--- /dev/null
+++ b/deps/v8/test/mjsunit/unusual-constructor.js
@@ -0,0 +1,38 @@
+// Copyright 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.
+
+var obj = new (Function.__proto__)();
+
+
+var threw = false;
+try {
+  obj.toString();
+} catch (e) {
+  assertInstanceof(e, TypeError);
+  threw = true;
+}
+assertTrue(threw);
diff --git a/deps/v8/test/mjsunit/uri.js b/deps/v8/test/mjsunit/uri.js
new file mode 100644
index 0000000..178ff1f
--- /dev/null
+++ b/deps/v8/test/mjsunit/uri.js
@@ -0,0 +1,78 @@
+// Copyright 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.
+
+// Tests of URI encoding and decoding.
+
+assertEquals("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.!~*'();/?:@&=+$,#",
+             encodeURI("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.!~*'();/?:@&=+$,#"));
+
+var cc1 = 0x007D;
+var s1 = String.fromCharCode(cc1);
+var cc2 = 0x0000;
+var s2 = String.fromCharCode(cc2);
+var cc3 = 0x0080;
+var s3 = String.fromCharCode(cc3);
+var cc4 = 0x0555;
+var s4 = String.fromCharCode(cc4);
+var cc5 = 0x07FF;
+var s5 = String.fromCharCode(cc5);
+var cc6 = 0x0800;
+var s6 = String.fromCharCode(cc6);
+var cc7 = 0xAEEE;
+var s7 = String.fromCharCode(cc7);
+var cc8_1 = 0xD800;
+var cc8_2 = 0xDC00;
+var s8 = String.fromCharCode(cc8_1)+String.fromCharCode(cc8_2);
+var cc9_1 = 0xDBFF;
+var cc9_2 = 0xDFFF;
+var s9 = String.fromCharCode(cc9_1)+String.fromCharCode(cc9_2);
+var cc10 = 0xE000;
+var s10 = String.fromCharCode(cc10);
+
+assertEquals('%7D', encodeURI(s1));
+assertEquals('%00', encodeURI(s2));
+assertEquals('%C2%80', encodeURI(s3));
+assertEquals('%D5%95', encodeURI(s4));
+assertEquals('%DF%BF', encodeURI(s5));
+assertEquals('%E0%A0%80', encodeURI(s6));
+assertEquals('%EA%BB%AE', encodeURI(s7));
+assertEquals('%F0%90%80%80', encodeURI(s8));
+assertEquals('%F4%8F%BF%BF', encodeURI(s9));
+assertEquals('%EE%80%80', encodeURI(s10));
+
+assertEquals(cc1, decodeURI(encodeURI(s1)).charCodeAt(0));
+assertEquals(cc2, decodeURI(encodeURI(s2)).charCodeAt(0));
+assertEquals(cc3, decodeURI(encodeURI(s3)).charCodeAt(0));
+assertEquals(cc4, decodeURI(encodeURI(s4)).charCodeAt(0));
+assertEquals(cc5, decodeURI(encodeURI(s5)).charCodeAt(0));
+assertEquals(cc6, decodeURI(encodeURI(s6)).charCodeAt(0));
+assertEquals(cc7, decodeURI(encodeURI(s7)).charCodeAt(0));
+assertEquals(cc8_1, decodeURI(encodeURI(s8)).charCodeAt(0));
+assertEquals(cc8_2, decodeURI(encodeURI(s8)).charCodeAt(1));
+assertEquals(cc9_1, decodeURI(encodeURI(s9)).charCodeAt(0));
+assertEquals(cc9_2, decodeURI(encodeURI(s9)).charCodeAt(1));
+assertEquals(cc10, decodeURI(encodeURI(s10)).charCodeAt(0));
diff --git a/deps/v8/test/mjsunit/value-callic-prototype-change.js b/deps/v8/test/mjsunit/value-callic-prototype-change.js
new file mode 100644
index 0000000..52f0629
--- /dev/null
+++ b/deps/v8/test/mjsunit/value-callic-prototype-change.js
@@ -0,0 +1,94 @@
+// Copyright 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.
+
+// Test that the inline caches correctly detect that constant
+// functions on value prototypes change.
+
+function testString() {
+  function f(s, expected) {
+    var result = s.toString();
+    assertEquals(expected, result);
+  };
+
+  for (var i = 0; i < 10; i++) {
+    var s = String.fromCharCode(i);
+    f(s, s);
+  }
+
+  String.prototype.toString = function() { return "ostehaps"; };
+
+  for (var i = 0; i < 10; i++) {
+    var s = String.fromCharCode(i);
+    f(s, "ostehaps");
+  }
+}
+
+testString();
+
+
+function testNumber() {
+  Number.prototype.toString = function() { return 0; };
+
+  function f(n, expected) {
+    var result = n.toString();
+    assertEquals(expected, result);
+  };
+
+  for (var i = 0; i < 10; i++) {
+    f(i, 0);
+  }
+
+  Number.prototype.toString = function() { return 42; };
+
+  for (var i = 0; i < 10; i++) {
+    f(i, 42);
+  }
+}
+
+testNumber();
+
+
+function testBoolean() {
+  Boolean.prototype.toString = function() { return 0; };
+
+  function f(b, expected) {
+    var result = b.toString();
+    assertEquals(expected, result);
+  };
+
+  for (var i = 0; i < 10; i++) {
+    f((i % 2 == 0), 0);
+  }
+
+  Boolean.prototype.toString = function() { return 42; };
+
+  for (var i = 0; i < 10; i++) {
+    f((i % 2 == 0), 42);
+  }
+}
+
+testBoolean();
diff --git a/deps/v8/test/mjsunit/var.js b/deps/v8/test/mjsunit/var.js
new file mode 100644
index 0000000..5999d70
--- /dev/null
+++ b/deps/v8/test/mjsunit/var.js
@@ -0,0 +1,37 @@
+// Copyright 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.
+
+assertTrue(!x && typeof x == 'undefined');
+assertTrue(!y && typeof y == 'undefined');
+if (false) { var x = 42; }
+if (true)  { var y = 87; }
+assertTrue(!x && typeof x == 'undefined');
+assertEquals(87, y);
+
+assertTrue(!z && typeof z == 'undefined');
+if (false) { var z; }
+assertTrue(!z && typeof z == 'undefined');
diff --git a/deps/v8/test/mjsunit/with-function-expression.js b/deps/v8/test/mjsunit/with-function-expression.js
new file mode 100644
index 0000000..17de817
--- /dev/null
+++ b/deps/v8/test/mjsunit/with-function-expression.js
@@ -0,0 +1,36 @@
+// Copyright 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.
+
+var source = "(function x() { with({}) { return '' + x; } })()";
+
+// Don't throw exceptions.
+assertDoesNotThrow(source);
+
+// Check that the return value is a function.  Use regexp to avoid
+// depending on the exact printing of the function.
+var regexp = /function/;
+var res = assertTrue(eval(source).match(regexp) == 'function');
diff --git a/deps/v8/test/mjsunit/with-leave.js b/deps/v8/test/mjsunit/with-leave.js
new file mode 100644
index 0000000..ded62ca
--- /dev/null
+++ b/deps/v8/test/mjsunit/with-leave.js
@@ -0,0 +1,61 @@
+// Copyright 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.
+
+L: with ({x:12}) {
+  assertEquals(12, x);
+  break L;
+  assertTrue(false);
+}
+
+do {
+  with ({x:15}) {
+    assertEquals(15, x);
+    continue;
+    assertTrue(false);
+  }
+} while (false);
+
+var caught = false;
+try {
+  with ({x:18}) { throw 25; assertTrue(false); }
+} catch (e) {
+  caught = true;
+  assertEquals(25, e);
+  with ({y:19}) {
+    assertEquals(19, y);
+    try {
+      // NOTE: This checks that the object containing x has been
+      // removed from the context chain.
+      x;
+      assertTrue(false);  // should not reach here
+    } catch (e2) {
+      assertTrue(e2 instanceof ReferenceError);
+    }
+  }
+}
+assertTrue(caught);
+
diff --git a/deps/v8/test/mjsunit/with-parameter-access.js b/deps/v8/test/mjsunit/with-parameter-access.js
new file mode 100644
index 0000000..747da22
--- /dev/null
+++ b/deps/v8/test/mjsunit/with-parameter-access.js
@@ -0,0 +1,47 @@
+// Copyright 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.
+
+// Return a parameter from inside a with statement.
+function f(x) {
+  with ({}) {
+    return x;
+  }
+}
+
+assertEquals(5, f(5));
+
+
+function g(x) {
+  function h() {
+    with ({}) {
+      return x;
+    }
+  }
+  return h();
+}
+
+assertEquals(7, g(7));
diff --git a/deps/v8/test/mjsunit/with-prototype.js b/deps/v8/test/mjsunit/with-prototype.js
new file mode 100644
index 0000000..e760f4e
--- /dev/null
+++ b/deps/v8/test/mjsunit/with-prototype.js
@@ -0,0 +1,44 @@
+// 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.
+
+// Test the behavior of an assignment in a with statement where the
+// extension object contains a property with the name assigned to in
+// the prototype chain.
+
+var o = {};
+var p = { x: 42 };
+o.__proto__ = p;
+
+function f() {
+  with (o) {
+    x = 123;
+  }
+}
+f();
+
+assertEquals(42, p.x);
+assertEquals(123, o.x);
diff --git a/deps/v8/test/mjsunit/with-value.js b/deps/v8/test/mjsunit/with-value.js
new file mode 100644
index 0000000..a4da1fa
--- /dev/null
+++ b/deps/v8/test/mjsunit/with-value.js
@@ -0,0 +1,38 @@
+// Copyright 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.
+
+// Values used in 'with' statements should be wrapped in an object
+// before establishing the context.
+(function() {
+  // 7 should be converted to an number object
+  with (7) { assertTrue(typeof valueOf == 'function'); }
+})();
+
+/* This should be fairly easy again. May need some work in the
+compiler's VisitWith() function, or perhaps the runtime routine's
+PushContextForWith().
+*/
\ No newline at end of file
diff --git a/deps/v8/test/mozilla/mozilla-shell-emulation.js b/deps/v8/test/mozilla/mozilla-shell-emulation.js
new file mode 100644
index 0000000..4875236
--- /dev/null
+++ b/deps/v8/test/mozilla/mozilla-shell-emulation.js
@@ -0,0 +1,37 @@
+// 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.
+
+// Sets up fake implementations of MDC built-in objects and functions
+// necessary to run the tests in V8.
+
+// Options are generally ignored (not set, if anybody asks).
+
+function options(aOptionName) {
+  // Returns comma-separated list of options set.
+  // Toggles the option if a name is given.
+  return "";  // Default implementation is always false.
+}
diff --git a/deps/v8/test/mozilla/mozilla.status b/deps/v8/test/mozilla/mozilla.status
new file mode 100644
index 0000000..97182f3
--- /dev/null
+++ b/deps/v8/test/mozilla/mozilla.status
@@ -0,0 +1,821 @@
+# Copyright 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.
+
+# This file is up to date with respect to Mozilla's CVS repository as of
+# 2008-09-02.  If new tests are added to Mozilla's CVS it may need to be
+# updated.
+
+# To get the mozilla tests:
+# cd /path/to/checkout/test/mozilla
+# rm -rf data
+# cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co -D 2008-09-02 mozilla/js/tests
+# mv mozilla/js/tests data
+# rm -rf mozilla
+
+# --------------------------------------------------------------------
+# If you add a test case to this file, please try to provide
+# an explanation of why the test fails; this may ease future
+# debugging.
+# --------------------------------------------------------------------
+
+prefix mozilla
+def FAIL_OK = FAIL, OKAY
+
+##################### SKIPPED TESTS #####################
+
+# This test checks that we behave properly in an out-of-memory
+# situation.  The test fails in V8 with an exception and takes a long
+# time to do so.
+js1_5/Regress/regress-271716-n: SKIP
+
+
+# These tests are simply wrong (i.e., they do not test what they intend
+# to test).
+# In particular, these two compare numbers to NaN with != in the current
+# version of the Mozilla tests. This is *fixed* in a later version.
+# The tests should be re-enabled when switching to a new version.
+ecma_3/Date/15.9.3.2-1: SKIP
+js1_2/function/Number: SKIP
+
+
+##################### SLOW TESTS #####################
+
+# This takes a long time to run (~100 seconds). It should only be run
+# by the really patient.
+js1_5/GC/regress-324278: SLOW
+
+# This takes a long time to run because our indexOf operation is
+# pretty slow - it causes a lot of GCs; see issue
+# #926379. We could consider marking this SKIP because it takes a
+# while to run to completion.
+js1_5/GC/regress-338653: SLOW
+
+# This test is designed to run until it runs out of memory. This takes
+# a very long time because it builds strings character by character
+# and compiles a lot of regular expressions. We could consider marking
+# this SKIP because it takes a while to run to completion.
+js1_5/GC/regress-346794: SLOW
+
+# Runs out of memory while trying to build huge string of 'x'
+# characters. This takes a long time to run (~32 seconds).
+js1_5/GC/regress-348532: SLOW
+
+
+##################### FLAKY TESTS #####################
+
+# These tests time out in debug mode but pass in product mode
+js1_5/Regress/regress-280769-3: PASS || FAIL if $mode == debug
+js1_5/Regress/regress-203278-1: PASS || FAIL if $mode == debug
+js1_5/GC/regress-203278-2: PASS || FAIL if $mode == debug
+js1_5/Regress/regress-244470: PASS || FAIL if $mode == debug
+ecma_3/RegExp/regress-209067: PASS || FAIL if $mode == debug
+js1_5/GC/regress-278725: PASS || FAIL if $mode == debug
+js1_5/Regress/regress-360969-03: PASS || FAIL if $mode == debug
+js1_5/Regress/regress-360969-04: PASS || FAIL if $mode == debug
+js1_5/Regress/regress-360969-05: PASS || FAIL if $mode == debug
+js1_5/Regress/regress-360969-06: PASS || FAIL if $mode == debug
+js1_5/extensions/regress-365527: PASS || FAIL if $mode == debug
+# http://b/issue?id=1206983
+js1_5/Regress/regress-367561-03: PASS || FAIL if $mode == debug
+ecma/Date/15.9.5.10-2: PASS || FAIL if $mode == debug
+
+# These tests create two Date objects just after each other and
+# expects them to match.  Sometimes this happens on the border
+# between one second and the next.
+ecma/Date/15.9.2.1: PASS || FAIL
+ecma/Date/15.9.2.2-1: PASS || FAIL
+ecma/Date/15.9.2.2-2: PASS || FAIL
+ecma/Date/15.9.2.2-3: PASS || FAIL
+ecma/Date/15.9.2.2-4: PASS || FAIL
+ecma/Date/15.9.2.2-5: PASS || FAIL
+ecma/Date/15.9.2.2-6: PASS || FAIL
+
+# 1026139: These date tests fail on arm
+ecma/Date/15.9.5.29-1: PASS || ($ARM && FAIL)
+ecma/Date/15.9.5.34-1: PASS || ($ARM && FAIL)
+ecma/Date/15.9.5.28-1: PASS || ($ARM && FAIL)
+
+# 1050186: Arm vm is broken; probably unrelated to dates
+ecma/Array/15.4.4.5-3: PASS || ($ARM && FAIL)
+ecma/Date/15.9.5.22-2: PASS || ($ARM && FAIL)
+
+# Severely brain-damaged test. Access to local variables must not
+# be more than 2.5 times faster than access to global variables? WTF?
+js1_5/Regress/regress-169559: PASS || FAIL
+
+
+# Test that rely on specific timezone (not working in Denmark).
+js1_5/Regress/regress-58116: PASS || FAIL
+
+
+# Flaky random() test. Tests the distribution of calls to Math.random().
+js1_5/Regress/regress-211590: PASS || FAIL
+
+
+# Flaky tests; expect BigO-order computations to yield 1, but the code
+# cannot handle outliers. See bug #925864.
+ecma_3/RegExp/regress-311414: PASS || FAIL
+ecma_3/RegExp/regress-289669: PASS || FAIL
+js1_5/String/regress-314890: PASS || FAIL
+js1_5/String/regress-56940-01: PASS || FAIL
+js1_5/String/regress-56940-02: PASS || FAIL
+js1_5/String/regress-157334-01: PASS || FAIL
+js1_5/String/regress-322772: PASS || FAIL
+js1_5/Array/regress-99120-01: PASS || FAIL
+js1_5/Array/regress-99120-02: PASS || FAIL
+js1_5/Regress/regress-347306-01: PASS || FAIL
+js1_5/Regress/regress-416628: PASS || FAIL
+
+
+# The following two tests assume that daylight savings time starts first Sunday
+# in April. This is not true when executing the tests outside California!
+# In Denmark the adjustment starts one week earlier!.
+# Tests based on shell that use dates in this gap are flaky.
+ecma/Date/15.9.5.10-1: PASS || FAIL
+ecma/Date/15.9.5.12-1: PASS || FAIL
+ecma/Date/15.9.5.14: PASS || FAIL
+ecma/Date/15.9.5.34-1: PASS || FAIL
+
+
+# These tests sometimes pass (in particular on Windows). They build up
+# a lot of stuff on the stack, which normally causes a stack overflow,
+# but sometimes it makes it through?
+js1_5/Regress/regress-290575: PASS || FAIL
+js1_5/Regress/regress-98901: PASS || FAIL
+
+
+# Tests that sorting arrays of ints is less than 3 times as fast
+# as sorting arrays of strings.
+js1_5/extensions/regress-371636: PASS || FAIL
+
+
+# Tests depend on GC timings. Inherently flaky.
+js1_5/GC/regress-383269-01: PASS || FAIL
+js1_5/GC/regress-383269-02: PASS || FAIL
+js1_5/Regress/regress-404755: PASS || FAIL
+
+
+# Test that depends on timer resolution. Fails every now and then
+# if we're unlucky enough to get a context switch at a bad time.
+js1_5/extensions/regress-363258: PASS || FAIL
+
+
+
+##################### INCOMPATIBLE TESTS #####################
+
+# This section is for tests that fail in both V8 and JSC.  Thus they
+# have been determined to be incompatible between Mozilla and V8/JSC.
+
+# Fail because of toLowerCase and toUpperCase conversion.
+ecma/String/15.5.4.11-2: FAIL_OK
+ecma/String/15.5.4.11-5: FAIL_OK
+ecma/String/15.5.4.12-1: FAIL_OK
+ecma/String/15.5.4.12-4: FAIL_OK
+
+# This test uses an older version of the unicode standard that fails
+# us because we correctly convert the armenian small ligature ech-yiwn
+# to the two upper-case characters ECH and YIWN, whereas the older
+# unicode version converts it to itself.
+ecma/String/15.5.4.12-5: FAIL_OK
+
+# Creates a linked list of arrays until we run out of memory or timeout.
+js1_5/Regress/regress-312588: FAIL_OK
+
+
+# Runs out of memory because it compiles huge functions.
+js1_5/Function/regress-338001: FAIL_OK
+js1_5/Function/regress-338121-01: FAIL_OK
+js1_5/Function/regress-338121-02: FAIL_OK
+js1_5/Function/regress-338121-03: FAIL_OK
+
+
+# Length of objects whose prototype chain includes a function
+ecma_3/Function/regress-313570: FAIL_OK
+
+# toPrecision argument restricted to range 1..21 in JSC/V8
+js1_5/Regress/regress-452346: FAIL_OK
+
+# Array.prototype.slice with zero arguments return undefined in JSC/V8, 
+# empty array in Spider/TraceMonkey.
+js1_5/Array/regress-451483: FAIL_OK
+
+
+#:=== RegExp:=== 
+# To be compatible with JSC we silently ignore flags that do not make
+# sense.  This test expects us to throw exceptions.  
+ecma_3/RegExp/regress-57631: FAIL_OK
+
+# PCRE doesn't allow subpattern nesting deeper than 200, this tests
+# depth 500.  JSC detects the case, and return null from the match,
+# and passes this test (the test doesn't check for a correct return
+# value).
+ecma_3/RegExp/regress-119909: PASS || FAIL_OK
+
+
+# Difference in the way capturing subpatterns work.  In JS, when the
+# 'minimum repeat count' is reached, the empty string must not match.
+# In this case, we are similar but not identical to JSC.  Hard to
+# support the JS behavior with PCRE, so maybe emulate JSC?
+ecma_3/RegExp/regress-209919: PASS || FAIL_OK
+js1_5/extensions/regress-459606: PASS || FAIL_OK
+
+
+# PCRE's match limit is reached.  SpiderMonkey hangs on the first one,
+# JSC returns true somehow.  Maybe they up the match limit?  There is
+# an open V8 bug 676063 about this.
+ecma_3/RegExp/regress-330684: FAIL_OK
+
+
+# This test contains a regexp that runs exponentially long.  Spidermonkey
+# standalone will hang, though apparently inside Firefox it will trigger a
+# long-running-script timeout.  JSCRE passes by hitting the matchLimit and
+# just pretending that an exhaustive search found no match.
+ecma_3/RegExp/regress-307456: PASS || FAIL_OK
+
+
+# We do not detect overflow in bounds for back references and {}
+# quantifiers.  Might fix by parsing numbers differently?
+js1_5/Regress/regress-230216-2: FAIL_OK
+
+
+# Regexp too long for PCRE.
+js1_5/Regress/regress-280769: PASS || FAIL
+js1_5/Regress/regress-280769-1: PASS || FAIL
+js1_5/Regress/regress-280769-2: PASS || FAIL
+js1_5/Regress/regress-280769-4: PASS || FAIL
+js1_5/Regress/regress-280769-5: PASS || FAIL
+
+
+# We do not support static RegExp.multiline - should we?.
+js1_2/regexp/RegExp_multiline: FAIL_OK
+js1_2/regexp/RegExp_multiline_as_array: FAIL_OK
+js1_2/regexp/beginLine: FAIL_OK
+js1_2/regexp/endLine: FAIL_OK
+
+
+# Date trouble?
+js1_5/Date/regress-301738-02: FAIL_OK
+
+
+# This test fails for all browsers on in the CET timezone.
+ecma/Date/15.9.5.35-1: PASS || FAIL_OK
+
+
+# Spidermonkey allows stuff in parenthesis directly after the minutes
+# in a date.  JSC does not, so we don't either.
+js1_5/Date/regress-309925-02: FAIL_OK
+
+
+# Print string after deleting array element?
+js1_5/Expressions/regress-96526-delelem: FAIL_OK
+
+
+# Stack overflows should be InternalError: too much recursion?
+js1_5/Regress/regress-234389: FAIL_OK
+
+
+# This may very well be a bogus test. I'm not sure yet.
+js1_5/Regress/regress-320119: FAIL_OK
+
+
+# No support for toSource().
+js1_5/Regress/regress-248444: FAIL_OK
+js1_5/Regress/regress-313967-01: FAIL_OK
+js1_5/Regress/regress-313967-02: FAIL_OK
+
+# This fails because we don't have stack space for Function.prototype.apply
+# with very large numbers of arguments.  The test uses 2^24 arguments.
+js1_5/Array/regress-350256-03: FAIL_OK
+
+
+# Extra arguments not handled properly in String.prototype.match
+js1_5/Regress/regress-179524: FAIL_OK
+
+
+# Uncategorized failures. Please help categorize (or fix) these failures.
+js1_5/Regress/regress-172699: FAIL_OK
+
+
+# Calls regexp objects with function call syntax; non-ECMA behavior.
+js1_2/Objects/toString-001: FAIL_OK
+
+
+# Assumes that the prototype of a function is enumerable. Non-ECMA,
+# see section 15.3.3.1, page 86.
+ecma/GlobalObject/15.1.2.2-1: FAIL_OK
+ecma/GlobalObject/15.1.2.3-1: FAIL_OK
+ecma/GlobalObject/15.1.2.4: FAIL_OK
+ecma/GlobalObject/15.1.2.5-1: FAIL_OK
+ecma/GlobalObject/15.1.2.6: FAIL_OK
+ecma/GlobalObject/15.1.2.7: FAIL_OK
+
+
+# Tests that rely on specific details of function decompilation or
+# print strings for errors. Non-ECMA behavior.
+js1_2/function/tostring-2: FAIL_OK
+js1_5/Exceptions/regress-332472: FAIL_OK
+js1_5/Regress/regress-173067: FAIL_OK
+js1_5/Regress/regress-355556: FAIL_OK
+js1_5/Regress/regress-328664: FAIL_OK
+js1_5/Regress/regress-252892: FAIL_OK
+js1_5/Regress/regress-352208: FAIL_OK
+ecma_3/Array/15.4.5.1-01: FAIL_OK
+ecma_3/Array/regress-387501: FAIL_OK
+ecma_3/LexicalConventions/7.9.1: FAIL_OK
+ecma_3/RegExp/regress-375711: FAIL_OK
+ecma_3/Unicode/regress-352044-01: FAIL_OK
+ecma_3/extensions/regress-274152: FAIL_OK
+js1_5/Regress/regress-372364: FAIL_OK
+js1_5/Regress/regress-420919: FAIL_OK
+js1_5/Regress/regress-422348: FAIL_OK
+js1_5/Regress/regress-410852: FAIL_OK
+ecma_3/RegExp/regress-375715-04: FAIL_OK
+js1_5/decompilation/regress-456964-01: FAIL_OK
+js1_5/decompilation/regress-437288-02: FAIL_OK
+js1_5/decompilation/regress-457824: FAIL_OK
+js1_5/decompilation/regress-460116-01: FAIL_OK
+js1_5/decompilation/regress-460116-02: FAIL_OK
+js1_5/decompilation/regress-460501: FAIL_OK
+js1_5/decompilation/regress-460116-03: FAIL_OK
+js1_5/decompilation/regress-461110: FAIL_OK
+js1_5/decompilation/regress-456964-01: FAIL_OK
+js1_5/decompilation/regress-437288-02: FAIL_OK
+js1_5/decompilation/regress-457824: FAIL_OK
+js1_5/decompilation/regress-460116-01: FAIL_OK
+js1_5/decompilation/regress-460116-02: FAIL_OK
+js1_5/decompilation/regress-460116-03: FAIL_OK
+js1_5/decompilation/regress-460501: FAIL_OK
+js1_5/decompilation/regress-461110: FAIL_OK
+
+
+
+# Tests that use uneval.  Non-ECMA.
+js1_5/GC/regress-418128: FAIL_OK
+js1_5/extensions/regress-465276: FAIL_OK
+
+
+# Tests that use __count__.  Non-ECMA.
+js1_5/extensions/regress-434837-01: FAIL_OK
+
+
+# Tests that use the watch method.  Non-ECMA.
+js1_5/extensions/regress-435345-01: FAIL_OK
+js1_5/extensions/regress-455413: FAIL_OK
+
+
+# The spec specifies reverse evaluation order for < and >=.
+# See section 11.8.2 and 11.8.5.
+# We implement the spec here but the test tests the more straigtforward order.
+ecma_3/Operators/order-01: FAIL_OK
+
+
+# Uses Mozilla-specific QName, XML, XMLList and Iterator.
+js1_5/Regress/regress-407323: FAIL_OK
+js1_5/Regress/regress-407957: FAIL_OK
+
+
+# Relies on JavaScript 1.2 / 1.3 deprecated features.
+js1_2/function/String: FAIL_OK
+js1_2/operator/equality: FAIL_OK
+js1_2/version120/boolean-001: FAIL_OK
+js1_2/String/concat: FAIL_OK
+js1_2/function/Function_object: FAIL_OK
+js1_2/function/tostring-1: FAIL_OK
+js1_2/version120/regress-99663: FAIL_OK
+js1_2/regexp/RegExp_lastIndex: FAIL_OK
+js1_2/regexp/string_split: FAIL_OK
+
+
+# We do not check for bad surrogate pairs when quoting strings.
+js1_5/Regress/regress-315974: FAIL_OK
+
+
+# Use unsupported "watch".
+js1_5/Regress/regress-213482: FAIL_OK
+js1_5/Regress/regress-240577: FAIL_OK
+js1_5/Regress/regress-355344: FAIL_OK
+js1_5/Object/regress-362872-01: FAIL_OK
+js1_5/Object/regress-362872-02: FAIL_OK
+js1_5/Regress/regress-361467: FAIL_OK
+js1_5/Regress/regress-385393-06: FAIL_OK
+
+
+# Use special Mozilla getter/setter syntax
+js1_5/Regress/regress-354924: FAIL_OK
+js1_5/Regress/regress-355341: FAIL_OK
+js1_5/GC/regress-316885-01: FAIL_OK
+js1_5/GetSet/getset-002: FAIL_OK
+js1_5/GetSet/regress-353264: FAIL_OK
+js1_5/Regress/regress-361617: FAIL_OK
+js1_5/Regress/regress-362583: FAIL_OK
+js1_5/extensions/regress-356378: FAIL_OK
+js1_5/extensions/regress-452178: FAIL_OK
+
+
+# 'native' *is* a keyword in V8.
+js1_5/Regress/regress-240317: FAIL_OK
+
+
+# Requires Mozilla-specific strict mode or options() function.
+ecma_3/Object/8.6.1-01: FAIL_OK
+js1_5/Exceptions/regress-315147: FAIL_OK
+js1_5/Regress/regress-106244: FAIL_OK
+js1_5/Regress/regress-317533: FAIL_OK
+js1_5/Regress/regress-323314-1: FAIL_OK
+js1_5/Regress/regress-352197: FAIL_OK
+
+
+# Equivalent to assert(false).
+ecma_2/RegExp/exec-001: FAIL_OK
+ecma_2/String/replace-001: FAIL_OK
+
+
+# We do not strip unicode format control characters. This is really
+# required for working with non-latin character sets.  We match JSC
+# and IE here.  Firefox matches the spec (section 7.1).
+ecma_3/Unicode/uc-001: FAIL_OK
+
+
+# A non-breaking space doesn't match \s in a regular expression.  This behaviour
+# matches JSC.  All the VMs have different behaviours in which characters match
+# \s so we do the same as JSC until they change.
+ecma_3/Unicode/uc-002: PASS || FAIL_OK
+
+
+# String.prototype.split on empty strings always returns an array
+# with one element (as specified in ECMA-262).
+js1_2/Array/array_split_1: FAIL_OK
+
+
+# The concat() method is defined in Array.prototype; not Array.
+js1_5/Array/regress-313153: FAIL_OK
+
+
+# Properties stack, fileName, and lineNumber of Error instances are
+# not supported. Mozilla specific extension.
+js1_5/Exceptions/errstack-001: FAIL_OK
+js1_5/Exceptions/regress-257751: FAIL_OK
+js1_5/Regress/regress-119719: FAIL_OK
+js1_5/Regress/regress-139316: FAIL_OK
+js1_5/Regress/regress-167328: FAIL_OK
+js1_5/Regress/regress-243869: FAIL_OK
+
+
+# Unsupported import/export and <xml> literals. Mozilla extensions.
+js1_5/Regress/regress-249211: FAIL_OK
+js1_5/Regress/regress-309242: FAIL_OK
+js1_5/Regress/regress-350692: FAIL_OK
+js1_5/extensions/regress-421621: FAIL_OK
+js1_5/extensions/regress-432075: FAIL_OK
+
+
+# The length of Error functions is 1 not 3.
+js1_5/Exceptions/regress-123002: FAIL_OK
+
+
+# Reserved keywords as function names, etc is not supported.
+js1_5/LexicalConventions/regress-343675: FAIL_OK
+
+
+# Unsupported list comprehensions: [ ... for ... ] and for each.
+js1_5/Regress/regress-352009: FAIL_OK
+js1_5/Regress/regress-349648: FAIL_OK
+
+
+# Expects top level arguments (passed on command line?) to be
+# the empty string?
+js1_5/Regress/regress-336100: FAIL_OK
+
+
+# Regular expression test failures due to PCRE. We match JSC (ie, perl)
+# behavior and not the ECMA spec.
+ecma_3/RegExp/perlstress-001: PASS || FAIL_OK
+ecma_3/RegExp/regress-334158: PASS || FAIL
+
+# This test fails due to http://code.google.com/p/v8/issues/detail?id=187
+# Failure to clear captures when a lookahead is unwound.
+ecma_3/RegExp/15.10.2-1: PASS || FAIL_OK
+
+# This test requires a failure if we try to compile a function with more
+# than 65536 arguments.  This seems to be a Mozilla restriction.
+js1_5/Regress/regress-290575: FAIL_OK
+
+
+# Fails because of the way function declarations are
+# handled in V8/JSC. V8 follows IE behavior and introduce
+# all nested function declarations when entering the
+# surrounding function, whereas Spidermonkey declares
+# them dynamically when the statement is executed.
+ecma_3/Function/scope-001: FAIL_OK
+ecma_3/FunExpr/fe-001: FAIL_OK
+js1_5/Scope/regress-184107: FAIL_OK
+
+
+# Function is deletable in V8 and JSC.
+js1_5/Regress/regress-352604: FAIL_OK
+
+
+# Cannot call strings as functions. Expects not to crash.
+js1_5/Regress/regress-417893: FAIL_OK
+
+
+
+##################### FAILING TESTS #####################
+
+# This section is for tests that fail in V8 and pass in JSC.
+# Tests that fail in both V8 and JSC belong in the FAIL_OK
+# category.
+
+# This fails because we don't handle Function.prototype.apply with very large
+# numbers of arguments (depending on max stack size).  350256-02 needs more than
+# 4Mbytes of stack space.
+js1_5/Array/regress-350256-02: FAIL
+
+
+# This fails because 'delete arguments[i]' does not disconnect the
+# argument from the arguments array.  See issue #900066.
+ecma_3/Function/regress-137181: FAIL
+
+
+# Calls regexp objects with function call syntax; non-ECMA behavior.
+ecma_2/RegExp/regress-001: FAIL
+js1_2/regexp/regress-6359: FAIL
+js1_2/regexp/regress-9141: FAIL
+js1_5/Regress/regress-224956: FAIL
+js1_5/Regress/regress-325925: FAIL
+js1_2/regexp/simple_form: FAIL
+
+
+# Tests that rely on specific details of function decompilation or
+# print strings for errors. Non-ECMA behavior.
+js1_4/Regress/function-003: FAIL
+
+
+# Relies on JavaScript 1.2 / 1.3 deprecated features.
+js1_2/function/regexparg-1: FAIL
+
+# 'export' and 'import' are not keywords in V8.
+ecma_2/Exceptions/lexical-010: FAIL
+ecma_2/Exceptions/lexical-022: FAIL
+
+
+# Requires Mozilla-specific strict mode.
+ecma_2/Exceptions/lexical-011: FAIL
+ecma_2/Exceptions/lexical-014: FAIL
+ecma_2/Exceptions/lexical-016: FAIL
+ecma_2/Exceptions/lexical-021: FAIL
+ecma_2/LexicalConventions/keywords-001: FAIL
+js1_5/Regress/regress-306633: FAIL
+
+
+# This test seems designed to fail (it produces a 700Mbyte string).
+# We fail on out of memory.  The important thing is not to crash.
+js1_5/Regress/regress-303213: FAIL
+
+
+# Bug 1202592: New ecma_3/String/15.5.4.11 is failing.
+ecma_3/String/15.5.4.11: FAIL
+
+# Bug 1202597: New js1_5/Expressions/regress-394673 is failing.
+# Marked as: Will not fix. V8 throws an acceptable RangeError.
+js1_5/Expressions/regress-394673: FAIL
+
+##################### MOZILLA EXTENSION TESTS #####################
+
+ecma/extensions/15.1.2.1-1: FAIL_OK
+ecma_3/extensions/regress-385393-03: FAIL_OK
+ecma_3/extensions/7.9.1: FAIL_OK
+js1_5/extensions/catchguard-001: FAIL_OK
+js1_5/extensions/catchguard-002: FAIL_OK
+js1_5/extensions/catchguard-003: FAIL_OK
+js1_5/extensions/getset-001: FAIL_OK
+js1_5/extensions/getset-003: FAIL_OK
+js1_5/extensions/no-such-method: FAIL_OK
+js1_5/extensions/regress-104077: FAIL_OK
+js1_5/extensions/regress-226078: FAIL_OK
+js1_5/extensions/regress-303277: FAIL_OK
+js1_5/extensions/regress-304897: FAIL_OK
+js1_5/extensions/regress-306738: FAIL_OK
+js1_5/extensions/regress-311161: FAIL_OK
+js1_5/extensions/regress-311583: FAIL_OK
+js1_5/extensions/regress-311792-01: FAIL_OK
+js1_5/extensions/regress-312278: FAIL_OK
+js1_5/extensions/regress-313630: FAIL_OK
+js1_5/extensions/regress-313763: FAIL_OK
+js1_5/extensions/regress-313803: FAIL_OK
+js1_5/extensions/regress-314874: FAIL_OK
+js1_5/extensions/regress-322957: FAIL_OK
+js1_5/extensions/regress-328556: FAIL_OK
+js1_5/extensions/regress-330569: FAIL_OK
+js1_5/extensions/regress-333541: FAIL_OK
+js1_5/extensions/regress-335700: FAIL_OK
+js1_5/extensions/regress-336409-1: FAIL_OK
+js1_5/extensions/regress-336409-2: FAIL_OK
+js1_5/extensions/regress-336410-1: FAIL_OK
+js1_5/extensions/regress-336410-2: FAIL_OK
+js1_5/extensions/regress-341956-01: FAIL_OK
+js1_5/extensions/regress-341956-02: FAIL_OK
+js1_5/extensions/regress-341956-03: FAIL_OK
+js1_5/extensions/regress-342960: FAIL_OK
+js1_5/extensions/regress-345967: FAIL_OK
+js1_5/extensions/regress-346494-01: FAIL_OK
+js1_5/extensions/regress-346494: FAIL_OK
+js1_5/extensions/regress-347306-02: FAIL_OK
+js1_5/extensions/regress-348986: FAIL_OK
+js1_5/extensions/regress-349616: FAIL_OK
+js1_5/extensions/regress-350312-02: FAIL_OK
+js1_5/extensions/regress-350312-03: FAIL_OK
+js1_5/extensions/regress-350531: FAIL_OK
+js1_5/extensions/regress-351102-01: FAIL_OK
+js1_5/extensions/regress-351102-02: FAIL_OK
+js1_5/extensions/regress-351102-06: FAIL_OK
+js1_5/extensions/regress-351448: FAIL_OK
+js1_5/extensions/regress-351973: FAIL_OK
+js1_5/extensions/regress-352060: FAIL_OK
+js1_5/extensions/regress-352094: FAIL_OK
+js1_5/extensions/regress-352261: FAIL_OK
+js1_5/extensions/regress-352281: FAIL_OK
+js1_5/extensions/regress-352372: FAIL_OK
+js1_5/extensions/regress-352455: FAIL_OK
+js1_5/extensions/regress-352604: FAIL_OK
+js1_5/extensions/regress-353214: FAIL_OK
+js1_5/extensions/regress-355339: FAIL_OK
+js1_5/extensions/regress-355497: FAIL_OK
+js1_5/extensions/regress-355622: FAIL_OK
+js1_5/extensions/regress-355736: FAIL_OK
+js1_5/extensions/regress-356085: FAIL_OK
+js1_5/extensions/regress-356106: FAIL_OK
+js1_5/extensions/regress-358594-01: FAIL_OK
+js1_5/extensions/regress-358594-02: FAIL_OK
+js1_5/extensions/regress-358594-03: FAIL_OK
+js1_5/extensions/regress-358594-04: FAIL_OK
+js1_5/extensions/regress-358594-05: FAIL_OK
+js1_5/extensions/regress-358594-06: FAIL_OK
+js1_5/extensions/regress-361346: FAIL_OK
+js1_5/extensions/regress-361360: FAIL_OK
+js1_5/extensions/regress-361558: FAIL_OK
+js1_5/extensions/regress-361571: FAIL_OK
+js1_5/extensions/regress-361856: FAIL_OK
+js1_5/extensions/regress-361964: FAIL_OK
+js1_5/extensions/regress-363988: FAIL_OK
+js1_5/extensions/regress-365869: FAIL_OK
+js1_5/extensions/regress-367630: FAIL_OK
+js1_5/extensions/regress-367923: FAIL_OK
+js1_5/extensions/regress-368859: FAIL_OK
+js1_5/extensions/regress-374589: FAIL_OK
+js1_5/extensions/regress-375801: FAIL_OK
+js1_5/extensions/regress-376052: FAIL_OK
+js1_5/extensions/regress-379523: FAIL_OK
+js1_5/extensions/regress-380581: FAIL_OK
+js1_5/extensions/regress-380831: FAIL_OK
+js1_5/extensions/regress-381205: FAIL_OK
+js1_5/extensions/regress-381211: FAIL_OK
+js1_5/extensions/regress-381304: FAIL_OK
+js1_5/extensions/regress-382509: FAIL_OK
+js1_5/extensions/regress-383965: FAIL_OK
+js1_5/extensions/regress-384680: FAIL_OK
+js1_5/extensions/regress-385393-09: FAIL_OK
+js1_5/extensions/regress-407501: FAIL_OK
+js1_5/extensions/regress-418730: FAIL_OK
+js1_5/extensions/regress-420612: FAIL_OK
+js1_5/extensions/regress-420869-01: FAIL_OK
+js1_5/extensions/regress-424257: FAIL_OK
+js1_5/extensions/regress-424683-01: FAIL_OK
+js1_5/extensions/regress-44009: FAIL_OK
+js1_5/extensions/regress-50447-1: FAIL_OK
+js1_5/extensions/regress-50447: FAIL_OK
+js1_5/extensions/regress-90596-001: FAIL_OK
+js1_5/extensions/regress-90596-002: FAIL_OK
+js1_5/extensions/regress-96284-001: FAIL_OK
+js1_5/extensions/regress-96284-002: FAIL_OK
+js1_5/extensions/scope-001: FAIL_OK
+js1_5/extensions/toLocaleFormat-01: FAIL_OK
+js1_5/extensions/toLocaleFormat-02: FAIL_OK
+
+
+##################### DECOMPILATION TESTS #####################
+
+# We don't really about the outcome of running the
+# decompilation tests as long as they don't crash or
+# timeout.
+
+js1_5/decompilation/regress-344120: PASS || FAIL
+js1_5/decompilation/regress-346892: PASS || FAIL
+js1_5/decompilation/regress-346902: PASS || FAIL
+js1_5/decompilation/regress-346904: PASS || FAIL
+js1_5/decompilation/regress-346915: PASS || FAIL
+js1_5/decompilation/regress-349484: PASS || FAIL
+js1_5/decompilation/regress-349489: PASS || FAIL
+js1_5/decompilation/regress-349491: PASS || FAIL
+js1_5/decompilation/regress-349596: PASS || FAIL
+js1_5/decompilation/regress-349650: PASS || FAIL
+js1_5/decompilation/regress-349663: PASS || FAIL
+js1_5/decompilation/regress-350242: PASS || FAIL
+js1_5/decompilation/regress-350263: PASS || FAIL
+js1_5/decompilation/regress-350271: PASS || FAIL
+js1_5/decompilation/regress-350666: PASS || FAIL
+js1_5/decompilation/regress-350670: PASS || FAIL
+js1_5/decompilation/regress-351104: PASS || FAIL
+js1_5/decompilation/regress-351219: PASS || FAIL
+js1_5/decompilation/regress-351336: PASS || FAIL
+js1_5/decompilation/regress-351597: PASS || FAIL
+js1_5/decompilation/regress-351625: PASS || FAIL
+js1_5/decompilation/regress-351626: PASS || FAIL
+js1_5/decompilation/regress-351693: PASS || FAIL
+js1_5/decompilation/regress-351705: PASS || FAIL
+js1_5/decompilation/regress-351793: PASS || FAIL
+js1_5/decompilation/regress-352013: PASS || FAIL
+js1_5/decompilation/regress-352022: PASS || FAIL
+js1_5/decompilation/regress-352073: PASS || FAIL
+js1_5/decompilation/regress-352202: PASS || FAIL
+js1_5/decompilation/regress-352312: PASS || FAIL
+js1_5/decompilation/regress-352360: PASS || FAIL
+js1_5/decompilation/regress-352375: PASS || FAIL
+js1_5/decompilation/regress-352453: PASS || FAIL
+js1_5/decompilation/regress-352649: PASS || FAIL
+js1_5/decompilation/regress-352873-01: PASS || FAIL
+js1_5/decompilation/regress-352873-02: PASS || FAIL
+js1_5/decompilation/regress-353000: PASS || FAIL
+js1_5/decompilation/regress-353120: PASS || FAIL
+js1_5/decompilation/regress-353146: PASS || FAIL
+js1_5/decompilation/regress-354878: PASS || FAIL
+js1_5/decompilation/regress-354910: PASS || FAIL
+js1_5/decompilation/regress-355992: PASS || FAIL
+js1_5/decompilation/regress-356083: PASS || FAIL
+js1_5/decompilation/regress-356248: PASS || FAIL
+js1_5/decompilation/regress-371692: PASS || FAIL
+js1_5/decompilation/regress-373678: PASS || FAIL
+js1_5/decompilation/regress-375639: PASS || FAIL
+js1_5/decompilation/regress-375882: PASS || FAIL
+js1_5/decompilation/regress-376564: PASS || FAIL
+js1_5/decompilation/regress-383721: PASS || FAIL
+js1_5/decompilation/regress-406555: PASS || FAIL
+
+
+[ $FAST == yes ]
+
+# These tests take an unreasonable amount of time so we skip them
+# in fast mode.
+
+js1_5/Regress/regress-312588: SKIP
+js1_5/Regress/regress-271716-n: SKIP
+
+
+[ $FAST == yes && $ARCH == arm ]
+
+# In fast mode on arm we try to skip all tests that would time out,
+# since running the tests takes so long in the first place.
+
+js1_5/Regress/regress-280769-2: SKIP
+js1_5/Regress/regress-280769-3: SKIP
+js1_5/Regress/regress-244470: SKIP
+js1_5/Regress/regress-203278-1: SKIP
+js1_5/Regress/regress-290575: SKIP
+js1_5/Regress/regress-159334: SKIP
+js1_5/Regress/regress-321971: SKIP
+js1_5/Regress/regress-347306-01: SKIP
+js1_5/Regress/regress-280769-1: SKIP
+js1_5/Regress/regress-280769-5: SKIP
+js1_5/GC/regress-306788: SKIP
+js1_5/GC/regress-203278-2: SKIP
+js1_5/GC/regress-278725: SKIP
+js1_5/GC/regress-203278-3: SKIP
+js1_5/GC/regress-311497: SKIP
+js1_5/Array/regress-99120-02: SKIP
+ecma/Date/15.9.5.22-1: SKIP
+ecma/Date/15.9.5.20: SKIP
+ecma/Date/15.9.5.12-2: SKIP
+ecma/Date/15.9.5.8: SKIP
+ecma/Date/15.9.5.9: SKIP
+ecma/Date/15.9.5.10-2: SKIP
+ecma/Date/15.9.5.11-2: SKIP
+ecma/Expressions/11.7.2: SKIP
+ecma/Expressions/11.10-2: SKIP
+ecma/Expressions/11.7.3: SKIP
+ecma/Expressions/11.10-3: SKIP
+ecma/Expressions/11.7.1: SKIP
+ecma_3/RegExp/regress-209067: SKIP
diff --git a/deps/v8/test/mozilla/testcfg.py b/deps/v8/test/mozilla/testcfg.py
new file mode 100644
index 0000000..477b2b2
--- /dev/null
+++ b/deps/v8/test/mozilla/testcfg.py
@@ -0,0 +1,136 @@
+# Copyright 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.
+
+
+import test
+import os
+from os.path import join, exists
+
+
+EXCLUDED = ['CVS']
+
+
+FRAMEWORK = """
+  browser.js
+  shell.js
+  jsref.js
+  template.js
+""".split()
+
+
+TEST_DIRS = """
+  ecma
+  ecma_2
+  ecma_3
+  js1_1
+  js1_2
+  js1_3
+  js1_4
+  js1_5
+""".split()
+
+
+class MozillaTestCase(test.TestCase):
+
+  def __init__(self, filename, path, context, root, mode, framework):
+    super(MozillaTestCase, self).__init__(context, path)
+    self.filename = filename
+    self.mode = mode
+    self.framework = framework
+    self.root = root
+
+  def IsNegative(self):
+    return self.filename.endswith('-n.js')
+
+  def GetLabel(self):
+    return "%s mozilla %s" % (self.mode, self.GetName())
+
+  def IsFailureOutput(self, output):
+    if output.exit_code != 0:
+      return True
+    return 'FAILED!' in output.stdout
+
+  def GetCommand(self):
+    result = [self.context.GetVm(self.mode), '--expose-gc',
+              join(self.root, 'mozilla-shell-emulation.js')]
+    result += self.framework
+    result.append(self.filename)
+    return result
+
+  def GetName(self):
+    return self.path[-1]
+
+  def GetSource(self):
+    return open(self.filename).read()
+
+
+class MozillaTestConfiguration(test.TestConfiguration):
+
+  def __init__(self, context, root):
+    super(MozillaTestConfiguration, self).__init__(context, root)
+
+  def ListTests(self, current_path, path, mode):
+    tests = []
+    for test_dir in TEST_DIRS:
+      current_root = join(self.root, 'data', test_dir)
+      for root, dirs, files in os.walk(current_root):
+        for dotted in [x  for x in dirs if x.startswith('.')]:
+          dirs.remove(dotted)
+        for excluded in EXCLUDED:
+          if excluded in dirs:
+            dirs.remove(excluded)
+        root_path = root[len(self.root):].split(os.path.sep)
+        root_path = current_path + [x for x in root_path if x]
+        framework = []
+        for i in xrange(len(root_path)):
+          if i == 0: dir = root_path[1:]
+          else: dir = root_path[1:-i]
+          script = join(self.root, reduce(join, dir, ''), 'shell.js')
+          if exists(script):
+            framework.append(script)
+        framework.reverse()
+        for file in files:
+          if (not file in FRAMEWORK) and file.endswith('.js'):
+            full_path = root_path + [file[:-3]]
+            full_path = [x for x in full_path if x != 'data']
+            if self.Contains(path, full_path):
+              test = MozillaTestCase(join(root, file), full_path, self.context,
+                                     self.root, mode, framework)
+              tests.append(test)
+    return tests
+
+  def GetBuildRequirements(self):
+    return ['sample', 'sample=shell']
+
+  def GetTestStatus(self, sections, defs):
+    status_file = join(self.root, 'mozilla.status')
+    if exists(status_file):
+      test.ReadConfigurationInto(status_file, sections, defs)
+
+
+def GetConfiguration(context, root):
+  return MozillaTestConfiguration(context, root)
diff --git a/deps/v8/tools/js2c.py b/deps/v8/tools/js2c.py
new file mode 100755
index 0000000..52fe35c
--- /dev/null
+++ b/deps/v8/tools/js2c.py
@@ -0,0 +1,365 @@
+#!/usr/bin/env python
+#
+# 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.
+
+# This is a utility for converting JavaScript source code into C-style
+# char arrays. It is used for embedded JavaScript code in the V8
+# library.
+
+import os, re, sys, string
+import jsmin
+
+
+def ToCArray(lines):
+  result = []
+  for chr in lines:
+    value = ord(chr)
+    assert value < 128
+    result.append(str(value))
+  result.append("0")
+  return ", ".join(result)
+
+
+def CompressScript(lines, do_jsmin):
+  # If we're not expecting this code to be user visible, we can run it through
+  # a more aggressive minifier.
+  if do_jsmin:
+    return jsmin.jsmin(lines)
+
+  # Remove stuff from the source that we don't want to appear when
+  # people print the source code using Function.prototype.toString().
+  # Note that we could easily compress the scripts mode but don't
+  # since we want it to remain readable.
+  lines = re.sub('//.*\n', '\n', lines) # end-of-line comments
+  lines = re.sub(re.compile(r'/\*.*?\*/', re.DOTALL), '', lines) # comments.
+  lines = re.sub('\s+\n+', '\n', lines) # trailing whitespace
+  return lines
+
+
+def ReadFile(filename):
+  file = open(filename, "rt")
+  try:
+    lines = file.read()
+  finally:
+    file.close()
+  return lines
+
+
+def ReadLines(filename):
+  result = []
+  for line in open(filename, "rt"):
+    if '#' in line:
+      line = line[:line.index('#')]
+    line = line.strip()
+    if len(line) > 0:
+      result.append(line)
+  return result
+
+
+def LoadConfigFrom(name):
+  import ConfigParser
+  config = ConfigParser.ConfigParser()
+  config.read(name)
+  return config
+
+
+def ParseValue(string):
+  string = string.strip()
+  if string.startswith('[') and string.endswith(']'):
+    return string.lstrip('[').rstrip(']').split()
+  else:
+    return string
+
+
+def ExpandConstants(lines, constants):
+  for key, value in constants.items():
+    lines = lines.replace(key, str(value))
+  return lines
+
+
+def ExpandMacros(lines, macros):
+  for name, macro in macros.items():
+    start = lines.find(name + '(', 0)
+    while start != -1:
+      # Scan over the arguments
+      assert lines[start + len(name)] == '('
+      height = 1
+      end = start + len(name) + 1
+      last_match = end
+      arg_index = 0
+      mapping = { }
+      def add_arg(str):
+        # Remember to expand recursively in the arguments
+        replacement = ExpandMacros(str.strip(), macros)
+        mapping[macro.args[arg_index]] = replacement
+      while end < len(lines) and height > 0:
+        # We don't count commas at higher nesting levels.
+        if lines[end] == ',' and height == 1:
+          add_arg(lines[last_match:end])
+          last_match = end + 1
+        elif lines[end] in ['(', '{', '[']:
+          height = height + 1
+        elif lines[end] in [')', '}', ']']:
+          height = height - 1
+        end = end + 1
+      # Remember to add the last match.
+      add_arg(lines[last_match:end-1])
+      result = macro.expand(mapping)
+      # Replace the occurrence of the macro with the expansion
+      lines = lines[:start] + result + lines[end:]
+      start = lines.find(name + '(', end)
+  return lines
+
+class TextMacro:
+  def __init__(self, args, body):
+    self.args = args
+    self.body = body
+  def expand(self, mapping):
+    result = self.body
+    for key, value in mapping.items():
+        result = result.replace(key, value)
+    return result
+
+class PythonMacro:
+  def __init__(self, args, fun):
+    self.args = args
+    self.fun = fun
+  def expand(self, mapping):
+    args = []
+    for arg in self.args:
+      args.append(mapping[arg])
+    return str(self.fun(*args))
+
+CONST_PATTERN = re.compile('^const\s+([a-zA-Z0-9_]+)\s*=\s*([^;]*);$')
+MACRO_PATTERN = re.compile('^macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*=\s*([^;]*);$')
+PYTHON_MACRO_PATTERN = re.compile('^python\s+macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*=\s*([^;]*);$')
+
+def ReadMacros(lines):
+  constants = { }
+  macros = { }
+  for line in lines:
+    hash = line.find('#')
+    if hash != -1: line = line[:hash]
+    line = line.strip()
+    if len(line) is 0: continue
+    const_match = CONST_PATTERN.match(line)
+    if const_match:
+      name = const_match.group(1)
+      value = const_match.group(2).strip()
+      constants[name] = value
+    else:
+      macro_match = MACRO_PATTERN.match(line)
+      if macro_match:
+        name = macro_match.group(1)
+        args = map(string.strip, macro_match.group(2).split(','))
+        body = macro_match.group(3).strip()
+        macros[name] = TextMacro(args, body)
+      else:
+        python_match = PYTHON_MACRO_PATTERN.match(line)
+        if python_match:
+          name = python_match.group(1)
+          args = map(string.strip, python_match.group(2).split(','))
+          body = python_match.group(3).strip()
+          fun = eval("lambda " + ",".join(args) + ': ' + body)
+          macros[name] = PythonMacro(args, fun)
+        else:
+          raise ("Illegal line: " + line)
+  return (constants, macros)
+
+
+HEADER_TEMPLATE = """\
+// Copyright 2008 Google Inc. All Rights Reserved.
+
+// This file was generated from .js source files by SCons.  If you
+// want to make changes to this file you should either change the
+// javascript source files or the SConstruct script.
+
+#include "v8.h"
+#include "natives.h"
+
+namespace v8 {
+namespace internal {
+
+%(source_lines)s\
+
+  template <>
+  int NativesCollection<%(type)s>::GetBuiltinsCount() {
+    return %(builtin_count)i;
+  }
+
+  template <>
+  int NativesCollection<%(type)s>::GetDelayCount() {
+    return %(delay_count)i;
+  }
+
+  template <>
+  int NativesCollection<%(type)s>::GetIndex(const char* name) {
+%(get_index_cases)s\
+    return -1;
+  }
+
+  template <>
+  Vector<const char> NativesCollection<%(type)s>::GetScriptSource(int index) {
+%(get_script_source_cases)s\
+    return Vector<const char>("", 0);
+  }
+
+  template <>
+  Vector<const char> NativesCollection<%(type)s>::GetScriptName(int index) {
+%(get_script_name_cases)s\
+    return Vector<const char>("", 0);
+  }
+
+}  // internal
+}  // v8
+"""
+
+
+SOURCE_DECLARATION = """\
+  static const char %(id)s[] = { %(data)s };
+"""
+
+
+GET_DELAY_INDEX_CASE = """\
+    if (strcmp(name, "%(id)s") == 0) return %(i)i;
+"""
+
+
+GET_DELAY_SCRIPT_SOURCE_CASE = """\
+    if (index == %(i)i) return Vector<const char>(%(id)s, %(length)i);
+"""
+
+
+GET_DELAY_SCRIPT_NAME_CASE = """\
+    if (index == %(i)i) return Vector<const char>("%(name)s", %(length)i);
+"""
+
+def JS2C(source, target, env):
+  ids = []
+  delay_ids = []
+  modules = []
+  # Locate the macros file name.
+  consts = {}
+  macros = {}
+  for s in source:
+    if 'macros.py' == (os.path.split(str(s))[1]):
+      (consts, macros) = ReadMacros(ReadLines(str(s)))
+    else:
+      modules.append(s)
+
+  # Build source code lines
+  source_lines = [ ]
+  source_lines_empty = []
+  for s in modules:
+    delay = str(s).endswith('-delay.js')
+    lines = ReadFile(str(s))
+    do_jsmin = lines.find('// jsminify this file, js2c: jsmin') != -1
+    lines = ExpandConstants(lines, consts)
+    lines = ExpandMacros(lines, macros)
+    lines = CompressScript(lines, do_jsmin)
+    data = ToCArray(lines)
+    id = (os.path.split(str(s))[1])[:-3]
+    if delay: id = id[:-6]
+    if delay:
+      delay_ids.append((id, len(lines)))
+    else:
+      ids.append((id, len(lines)))
+    source_lines.append(SOURCE_DECLARATION % { 'id': id, 'data': data })
+    source_lines_empty.append(SOURCE_DECLARATION % { 'id': id, 'data': 0 })
+  
+  # Build delay support functions
+  get_index_cases = [ ]
+  get_script_source_cases = [ ]
+  get_script_name_cases = [ ]
+
+  i = 0
+  for (id, length) in delay_ids:
+    native_name = "native %s.js" % id
+    get_index_cases.append(GET_DELAY_INDEX_CASE % { 'id': id, 'i': i })
+    get_script_source_cases.append(GET_DELAY_SCRIPT_SOURCE_CASE % {
+      'id': id,
+      'length': length,
+      'i': i
+    })
+    get_script_name_cases.append(GET_DELAY_SCRIPT_NAME_CASE % {
+      'name': native_name,
+      'length': len(native_name),
+      'i': i
+    });
+    i = i + 1
+
+  for (id, length) in ids:
+    native_name = "native %s.js" % id
+    get_index_cases.append(GET_DELAY_INDEX_CASE % { 'id': id, 'i': i })
+    get_script_source_cases.append(GET_DELAY_SCRIPT_SOURCE_CASE % {
+      'id': id,
+      'length': length,
+      'i': i
+    })
+    get_script_name_cases.append(GET_DELAY_SCRIPT_NAME_CASE % {
+      'name': native_name,
+      'length': len(native_name),
+      'i': i
+    });
+    i = i + 1
+
+  # Emit result
+  output = open(str(target[0]), "w")
+  output.write(HEADER_TEMPLATE % {
+    'builtin_count': len(ids) + len(delay_ids),
+    'delay_count': len(delay_ids),
+    'source_lines': "\n".join(source_lines),
+    'get_index_cases': "".join(get_index_cases),
+    'get_script_source_cases': "".join(get_script_source_cases),
+    'get_script_name_cases': "".join(get_script_name_cases),
+    'type': env['TYPE']
+  })
+  output.close()
+
+  if len(target) > 1:
+    output = open(str(target[1]), "w")
+    output.write(HEADER_TEMPLATE % {
+      'builtin_count': len(ids) + len(delay_ids),
+      'delay_count': len(delay_ids),
+      'source_lines': "\n".join(source_lines_empty),
+      'get_index_cases': "".join(get_index_cases),
+      'get_script_source_cases': "".join(get_script_source_cases),
+      'get_script_name_cases': "".join(get_script_name_cases),
+      'type': env['TYPE']
+    })
+    output.close()
+
+def main():
+  natives = sys.argv[1]
+  natives_empty = sys.argv[2]
+  type = sys.argv[3]
+  source_files = sys.argv[4:]
+  JS2C(source_files, [natives, natives_empty], { 'TYPE': type })
+
+if __name__ == "__main__":
+  main()
diff --git a/deps/v8/tools/jsmin.py b/deps/v8/tools/jsmin.py
new file mode 100644
index 0000000..ae75814
--- /dev/null
+++ b/deps/v8/tools/jsmin.py
@@ -0,0 +1,218 @@
+#!/usr/bin/python
+
+# This code is original from jsmin by Douglas Crockford, it was translated to
+# Python by Baruch Even. The original code had the following copyright and
+# license.
+#
+# /* jsmin.c
+#    2007-05-22
+#
+# Copyright (c) 2002 Douglas Crockford  (www.crockford.com)
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy of
+# this software and associated documentation files (the "Software"), to deal in
+# the Software without restriction, including without limitation the rights to
+# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is furnished to do
+# so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# The Software shall be used for Good, not Evil.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# */
+
+from StringIO import StringIO
+
+def jsmin(js):
+    ins = StringIO(js)
+    outs = StringIO()
+    JavascriptMinify().minify(ins, outs)
+    str = outs.getvalue()
+    if len(str) > 0 and str[0] == '\n':
+        str = str[1:]
+    return str
+
+def isAlphanum(c):
+    """return true if the character is a letter, digit, underscore,
+           dollar sign, or non-ASCII character.
+    """
+    return ((c >= 'a' and c <= 'z') or (c >= '0' and c <= '9') or
+            (c >= 'A' and c <= 'Z') or c == '_' or c == '$' or c == '\\' or (c is not None and ord(c) > 126));
+
+class UnterminatedComment(Exception):
+    pass
+
+class UnterminatedStringLiteral(Exception):
+    pass
+
+class UnterminatedRegularExpression(Exception):
+    pass
+
+class JavascriptMinify(object):
+
+    def _outA(self):
+        self.outstream.write(self.theA)
+    def _outB(self):
+        self.outstream.write(self.theB)
+
+    def _get(self):
+        """return the next character from stdin. Watch out for lookahead. If
+           the character is a control character, translate it to a space or
+           linefeed.
+        """
+        c = self.theLookahead
+        self.theLookahead = None
+        if c == None:
+            c = self.instream.read(1)
+        if c >= ' ' or c == '\n':
+            return c
+        if c == '': # EOF
+            return '\000'
+        if c == '\r':
+            return '\n'
+        return ' '
+
+    def _peek(self):
+        self.theLookahead = self._get()
+        return self.theLookahead
+
+    def _next(self):
+        """get the next character, excluding comments. peek() is used to see
+           if an unescaped '/' is followed by a '/' or '*'.
+        """
+        c = self._get()
+        if c == '/' and self.theA != '\\':
+            p = self._peek()
+            if p == '/':
+                c = self._get()
+                while c > '\n':
+                    c = self._get()
+                return c
+            if p == '*':
+                c = self._get()
+                while 1:
+                    c = self._get()
+                    if c == '*':
+                        if self._peek() == '/':
+                            self._get()
+                            return ' '
+                    if c == '\000':
+                        raise UnterminatedComment()
+
+        return c
+
+    def _action(self, action):
+        """do something! What you do is determined by the argument:
+           1   Output A. Copy B to A. Get the next B.
+           2   Copy B to A. Get the next B. (Delete A).
+           3   Get the next B. (Delete B).
+           action treats a string as a single character. Wow!
+           action recognizes a regular expression if it is preceded by ( or , or =.
+        """
+        if action <= 1:
+            self._outA()
+
+        if action <= 2:
+            self.theA = self.theB
+            if self.theA == "'" or self.theA == '"':
+                while 1:
+                    self._outA()
+                    self.theA = self._get()
+                    if self.theA == self.theB:
+                        break
+                    if self.theA <= '\n':
+                        raise UnterminatedStringLiteral()
+                    if self.theA == '\\':
+                        self._outA()
+                        self.theA = self._get()
+
+
+        if action <= 3:
+            self.theB = self._next()
+            if self.theB == '/' and (self.theA == '(' or self.theA == ',' or
+                                     self.theA == '=' or self.theA == ':' or
+                                     self.theA == '[' or self.theA == '?' or
+                                     self.theA == '!' or self.theA == '&' or
+                                     self.theA == '|' or self.theA == ';' or
+                                     self.theA == '{' or self.theA == '}' or
+                                     self.theA == '\n'):
+                self._outA()
+                self._outB()
+                while 1:
+                    self.theA = self._get()
+                    if self.theA == '/':
+                        break
+                    elif self.theA == '\\':
+                        self._outA()
+                        self.theA = self._get()
+                    elif self.theA <= '\n':
+                        raise UnterminatedRegularExpression()
+                    self._outA()
+                self.theB = self._next()
+
+
+    def _jsmin(self):
+        """Copy the input to the output, deleting the characters which are
+           insignificant to JavaScript. Comments will be removed. Tabs will be
+           replaced with spaces. Carriage returns will be replaced with linefeeds.
+           Most spaces and linefeeds will be removed.
+        """
+        self.theA = '\n'
+        self._action(3)
+
+        while self.theA != '\000':
+            if self.theA == ' ':
+                if isAlphanum(self.theB):
+                    self._action(1)
+                else:
+                    self._action(2)
+            elif self.theA == '\n':
+                if self.theB in ['{', '[', '(', '+', '-']:
+                    self._action(1)
+                elif self.theB == ' ':
+                    self._action(3)
+                else:
+                    if isAlphanum(self.theB):
+                        self._action(1)
+                    else:
+                        self._action(2)
+            else:
+                if self.theB == ' ':
+                    if isAlphanum(self.theA):
+                        self._action(1)
+                    else:
+                        self._action(3)
+                elif self.theB == '\n':
+                    if self.theA in ['}', ']', ')', '+', '-', '"', '\'']:
+                        self._action(1)
+                    else:
+                        if isAlphanum(self.theA):
+                            self._action(1)
+                        else:
+                            self._action(3)
+                else:
+                    self._action(1)
+
+    def minify(self, instream, outstream):
+        self.instream = instream
+        self.outstream = outstream
+        self.theA = '\n'
+        self.theB = None
+        self.theLookahead = None
+
+        self._jsmin()
+        self.instream.close()
+
+if __name__ == '__main__':
+    import sys
+    jsm = JavascriptMinify()
+    jsm.minify(sys.stdin, sys.stdout)
diff --git a/deps/v8/tools/linux-tick-processor.py b/deps/v8/tools/linux-tick-processor.py
new file mode 100755
index 0000000..67c3b95
--- /dev/null
+++ b/deps/v8/tools/linux-tick-processor.py
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+#
+# Copyright 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.
+
+# Usage: process-ticks.py <logfile>
+# Where <logfile> is the log file name (eg, v8.log).
+
+import subprocess, re, sys, tickprocessor
+
+class LinuxTickProcessor(tickprocessor.TickProcessor):
+
+  def ParseVMSymbols(self, filename, start, end):
+    """Extract symbols and add them to the cpp entries."""
+    # Extra both dynamic and non-dynamic symbols.
+    command = 'nm -C -n "%s"; nm -C -n -D "%s"' % (filename, filename)
+    process = subprocess.Popen(command, shell=True,
+                               stdout=subprocess.PIPE,
+                               stderr=subprocess.STDOUT)
+    pipe = process.stdout
+    try:
+      for line in pipe:
+        row = re.match('^([0-9a-fA-F]{8}) . (.*)$', line)
+        if row:
+          addr = int(row.group(1), 16)
+          if addr < start and addr < end - start:
+            addr += start
+          self.cpp_entries.Insert(addr, tickprocessor.CodeEntry(addr, row.group(2)))
+    finally:
+      pipe.close()
+
+
+class LinuxCmdLineProcessor(tickprocessor.CmdLineProcessor):
+
+  def GetRequiredArgsNames(self):
+    return 'log_file'
+
+  def ProcessRequiredArgs(self, args):
+    if len(args) != 1:
+      self.PrintUsageAndExit()
+    else:
+      self.log_file = args[0]
+
+
+def Main():
+  cmdline_processor = LinuxCmdLineProcessor()
+  cmdline_processor.ProcessArguments()
+  tick_processor = LinuxTickProcessor()
+  cmdline_processor.RunLogfileProcessing(tick_processor)
+  tick_processor.PrintResults()
+
+
+if __name__ == '__main__':
+  Main()
diff --git a/deps/v8/tools/presubmit.py b/deps/v8/tools/presubmit.py
new file mode 100755
index 0000000..3e714de
--- /dev/null
+++ b/deps/v8/tools/presubmit.py
@@ -0,0 +1,231 @@
+#!/usr/bin/env python
+#
+# Copyright 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.
+
+
+import optparse
+import os
+from os.path import abspath, join, dirname, basename
+import re
+import sys
+import subprocess
+
+# Disabled LINT rules and reason.
+# build/include_what_you_use: Started giving false positives for variables
+#  named "string" and "map" assuming that you needed to include STL headers.
+
+ENABLED_LINT_RULES = """
+build/class
+build/deprecated
+build/endif_comment
+build/forward_decl
+build/include_order
+build/printf_format
+build/storage_class
+legal/copyright
+readability/boost
+readability/braces
+readability/casting
+readability/check
+readability/constructors
+readability/fn_size
+readability/function
+readability/multiline_comment
+readability/multiline_string
+readability/streams
+readability/todo
+readability/utf8
+runtime/arrays
+runtime/casting
+runtime/deprecated_fn
+runtime/explicit
+runtime/int
+runtime/memset
+runtime/mutex
+runtime/nonconf
+runtime/printf
+runtime/printf_format
+runtime/references
+runtime/rtti
+runtime/sizeof
+runtime/string
+runtime/virtual
+runtime/vlog
+whitespace/blank_line
+whitespace/braces
+whitespace/comma
+whitespace/comments
+whitespace/end_of_line
+whitespace/ending_newline
+whitespace/indent
+whitespace/labels
+whitespace/line_length
+whitespace/newline
+whitespace/operators
+whitespace/parens
+whitespace/tab
+whitespace/todo
+""".split()
+
+
+class SourceFileProcessor(object):
+  """
+  Utility class that can run through a directory structure, find all relevant
+  files and invoke a custom check on the files.
+  """
+
+  def Run(self, path):
+    all_files = []
+    for file in self.GetPathsToSearch():
+      all_files += self.FindFilesIn(join(path, file))
+    if not self.ProcessFiles(all_files):
+      return False
+    return True
+
+  def IgnoreDir(self, name):
+    return name.startswith('.') or name == 'data'
+
+  def IgnoreFile(self, name):
+    return name.startswith('.')
+
+  def FindFilesIn(self, path):
+    result = []
+    for (root, dirs, files) in os.walk(path):
+      for ignored in [x for x in dirs if self.IgnoreDir(x)]:
+        dirs.remove(ignored)
+      for file in files:
+        if not self.IgnoreFile(file) and self.IsRelevant(file):
+          result.append(join(root, file))
+    return result
+
+
+class CppLintProcessor(SourceFileProcessor):
+  """
+  Lint files to check that they follow the google code style.
+  """
+
+  def IsRelevant(self, name):
+    return name.endswith('.cc') or name.endswith('.h')
+
+  def IgnoreDir(self, name):
+    return (super(CppLintProcessor, self).IgnoreDir(name)
+              or (name == 'third_party'))
+
+  IGNORE_LINT = ['flag-definitions.h']
+  
+  def IgnoreFile(self, name):
+    return (super(CppLintProcessor, self).IgnoreFile(name)
+              or (name in CppLintProcessor.IGNORE_LINT))
+
+  def GetPathsToSearch(self):
+    return ['src', 'public', 'samples', join('test', 'cctest')]
+
+  def ProcessFiles(self, files):
+    filt = '-,' + ",".join(['+' + n for n in ENABLED_LINT_RULES])
+    command = ['cpplint.py', '--filter', filt] + join(files)
+    process = subprocess.Popen(command)
+    return process.wait() == 0
+
+
+COPYRIGHT_HEADER_PATTERN = re.compile(
+    r'Copyright [\d-]*200[8-9] the V8 project authors. All rights reserved.')
+
+class SourceProcessor(SourceFileProcessor):
+  """
+  Check that all files include a copyright notice.
+  """
+
+  RELEVANT_EXTENSIONS = ['.js', '.cc', '.h', '.py', '.c', 'SConscript',
+      'SConstruct', '.status']
+  def IsRelevant(self, name):
+    for ext in SourceProcessor.RELEVANT_EXTENSIONS:
+      if name.endswith(ext):
+        return True
+    return False
+
+  def GetPathsToSearch(self):
+    return ['.']
+
+  def IgnoreDir(self, name):
+    return (super(SourceProcessor, self).IgnoreDir(name)
+              or (name == 'third_party')
+              or (name == 'obj'))
+
+  IGNORE_COPYRIGHTS = ['earley-boyer.js', 'raytrace.js', 'crypto.js',
+      'libraries.cc', 'libraries-empty.cc', 'jsmin.py', 'regexp-pcre.js']
+  IGNORE_TABS = IGNORE_COPYRIGHTS + ['unicode-test.js',
+      'html-comments.js']
+
+  def ProcessContents(self, name, contents):
+    result = True
+    base = basename(name)
+    if not base in SourceProcessor.IGNORE_TABS:
+      if '\t' in contents:
+        print "%s contains tabs" % name
+        result = False
+    if not base in SourceProcessor.IGNORE_COPYRIGHTS:
+      if not COPYRIGHT_HEADER_PATTERN.search(contents):
+        print "%s is missing a correct copyright header." % name
+        result = False
+    return result
+
+  def ProcessFiles(self, files):
+    success = True
+    for file in files:
+      try:
+        handle = open(file)
+        contents = handle.read()
+        success = self.ProcessContents(file, contents) and success
+      finally:
+        handle.close()
+    return success
+
+
+def GetOptions():
+  result = optparse.OptionParser()
+  result.add_option('--no-lint', help="Do not run cpplint", default=False,
+                    action="store_true")
+  return result
+
+
+def Main():
+  workspace = abspath(join(dirname(sys.argv[0]), '..'))
+  parser = GetOptions()
+  (options, args) = parser.parse_args()
+  success = True
+  if not options.no_lint:
+    success = CppLintProcessor().Run(workspace) and success
+  success = SourceProcessor().Run(workspace) and success
+  if success:
+    return 0
+  else:
+    return 1
+
+
+if __name__ == '__main__':
+  sys.exit(Main())
diff --git a/deps/v8/tools/run-valgrind.py b/deps/v8/tools/run-valgrind.py
new file mode 100755
index 0000000..ccb9309
--- /dev/null
+++ b/deps/v8/tools/run-valgrind.py
@@ -0,0 +1,77 @@
+#!/usr/bin/python
+#
+# 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.
+
+# Simple wrapper for running valgrind and checking the output on
+# stderr for memory leaks.
+
+import subprocess
+import sys
+import re
+
+VALGRIND_ARGUMENTS = [
+  'valgrind',
+  '--error-exitcode=1',
+  '--leak-check=full',
+  '--smc-check=all'
+]
+
+# Compute the command line.
+command = VALGRIND_ARGUMENTS + sys.argv[1:]
+
+# Run valgrind.
+process = subprocess.Popen(command, stderr=subprocess.PIPE)
+code = process.wait();
+errors = process.stderr.readlines();
+
+# If valgrind produced an error, we report that to the user.
+if code != 0:
+  sys.stderr.writelines(errors)
+  sys.exit(code)
+
+# Look through the leak details and make sure that we don't
+# have any definitely, indirectly, and possibly lost bytes.
+LEAK_RE = r"(?:definitely|indirectly|possibly) lost: \d+ bytes in \d+ blocks."
+LEAK_LINE_MATCHER = re.compile(LEAK_RE)
+LEAK_OKAY_MATCHER = re.compile(r"lost: 0 bytes in 0 blocks.")
+leaks = []
+for line in errors:
+  if LEAK_LINE_MATCHER.search(line):
+    leaks.append(line)
+    if not LEAK_OKAY_MATCHER.search(line):
+      sys.stderr.writelines(errors)
+      sys.exit(1)
+
+# Make sure we found between 2 and 3 leak lines.
+if len(leaks) < 2 or len(leaks) > 3:
+  sys.stderr.writelines(errors)
+  sys.stderr.write('\n\n#### Malformed valgrind output.\n#### Exiting.\n')
+  sys.exit(1)
+
+# No leaks found.
+sys.exit(0)
diff --git a/deps/v8/tools/splaytree.js b/deps/v8/tools/splaytree.js
new file mode 100644
index 0000000..3045456
--- /dev/null
+++ b/deps/v8/tools/splaytree.js
@@ -0,0 +1,322 @@
+// 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.
+
+
+// A namespace stub. It will become more clear how to declare it properly
+// during integration of this script into Dev Tools.
+goog = { structs: {} };
+
+
+/**
+ * Constructs a Splay tree.  A splay tree is a self-balancing binary
+ * search tree with the additional property that recently accessed
+ * elements are quick to access again. It performs basic operations
+ * such as insertion, look-up and removal in O(log(n)) amortized time.
+ *
+ * @constructor
+ */
+goog.structs.SplayTree = function() {
+};
+
+
+/**
+ * Pointer to the root node of the tree.
+ *
+ * @type {goog.structs.SplayTree.Node}
+ * @private
+ */
+goog.structs.SplayTree.prototype.root_ = null;
+
+
+/**
+ * @return {boolean} Whether the tree is empty.
+ */
+goog.structs.SplayTree.prototype.isEmpty = function() {
+  return !this.root_;
+};
+
+
+
+/**
+ * Inserts a node into the tree with the specified key and value if
+ * the tree does not already contain a node with the specified key. If
+ * the value is inserted, it becomes the root of the tree.
+ *
+ * @param {number} key Key to insert into the tree.
+ * @param {*} value Value to insert into the tree.
+ */
+goog.structs.SplayTree.prototype.insert = function(key, value) {
+  if (this.isEmpty()) {
+    this.root_ = new goog.structs.SplayTree.Node(key, value);
+    return;
+  }
+  // Splay on the key to move the last node on the search path for
+  // the key to the root of the tree.
+  this.splay_(key);
+  if (this.root_.key == key) {
+    return;
+  }
+  var node = new goog.structs.SplayTree.Node(key, value);
+  if (key > this.root_.key) {
+    node.left = this.root_;
+    node.right = this.root_.right;
+    this.root_.right = null;
+  } else {
+    node.right = this.root_;
+    node.left = this.root_.left;
+    this.root_.left = null;
+  }
+  this.root_ = node;
+};
+
+
+
+/**
+ * Removes a node with the specified key from the tree if the tree
+ * contains a node with this key. The removed node is returned. If the
+ * key is not found, an exception is thrown.
+ *
+ * @param {number} key Key to find and remove from the tree.
+ * @return {goog.structs.SplayTree.Node} The removed node.
+ */
+goog.structs.SplayTree.prototype.remove = function(key) {
+  if (this.isEmpty()) {
+    throw Error('Key not found: ' + key);
+  }
+  this.splay_(key);
+  if (this.root_.key != key) {
+    throw Error('Key not found: ' + key);
+  }
+  var removed = this.root_;
+  if (!this.root_.left) {
+    this.root_ = this.root_.right;
+  } else {
+    var right = this.root_.right;
+    this.root_ = this.root_.left;
+    // Splay to make sure that the new root has an empty right child.
+    this.splay_(key);
+    // Insert the original right child as the right child of the new
+    // root.
+    this.root_.right = right;
+  }
+  return removed;
+};
+
+
+/**
+ * Returns the node having the specified key or null if the tree doesn't contain
+ * a node with the specified key.
+ *
+ * @param {number} key Key to find in the tree.
+ * @return {goog.structs.SplayTree.Node} Node having the specified key.
+ */
+goog.structs.SplayTree.prototype.find = function(key) {
+  if (this.isEmpty()) {
+    return null;
+  }
+  this.splay_(key);
+  return this.root_.key == key ? this.root_ : null;
+};
+
+
+/**
+ * @return {goog.structs.SplayTree.Node} Node having the minimum key value.
+ */
+goog.structs.SplayTree.prototype.findMin = function() {
+  if (this.isEmpty()) {
+    return null;
+  }
+  var current = this.root_;
+  while (current.left) {
+    current = current.left;
+  }
+  return current;
+};
+
+
+/**
+ * @return {goog.structs.SplayTree.Node} Node having the maximum key value.
+ */
+goog.structs.SplayTree.prototype.findMax = function(opt_startNode) {
+  if (this.isEmpty()) {
+    return null;
+  }
+  var current = opt_startNode || this.root_;
+  while (current.right) {
+    current = current.right;
+  }
+  return current;
+};
+
+
+/**
+ * @return {goog.structs.SplayTree.Node} Node having the maximum key value that
+ *     is less or equal to the specified key value.
+ */
+goog.structs.SplayTree.prototype.findGreatestLessThan = function(key) {
+  if (this.isEmpty()) {
+    return null;
+  }
+  // Splay on the key to move the node with the given key or the last
+  // node on the search path to the top of the tree.
+  this.splay_(key);
+  // Now the result is either the root node or the greatest node in
+  // the left subtree.
+  if (this.root_.key <= key) {
+    return this.root_;
+  } else if (this.root_.left) {
+    return this.findMax(this.root_.left);
+  } else {
+    return null;
+  }
+};
+
+
+/**
+ * @return {Array<*>} An array containing all the values of tree's nodes.
+ */
+goog.structs.SplayTree.prototype.exportValues = function() {
+  var result = [];
+  this.traverse_(function(node) { result.push(node.value); });
+  return result;
+};
+
+
+/**
+ * Perform the splay operation for the given key. Moves the node with
+ * the given key to the top of the tree.  If no node has the given
+ * key, the last node on the search path is moved to the top of the
+ * tree. This is the simplified top-down splaying algorithm from:
+ * "Self-adjusting Binary Search Trees" by Sleator and Tarjan
+ *
+ * @param {number} key Key to splay the tree on.
+ * @private
+ */
+goog.structs.SplayTree.prototype.splay_ = function(key) {
+  if (this.isEmpty()) {
+    return;
+  }
+  // Create a dummy node.  The use of the dummy node is a bit
+  // counter-intuitive: The right child of the dummy node will hold
+  // the L tree of the algorithm.  The left child of the dummy node
+  // will hold the R tree of the algorithm.  Using a dummy node, left
+  // and right will always be nodes and we avoid special cases.
+  var dummy, left, right;
+  dummy = left = right = new goog.structs.SplayTree.Node(null, null);
+  var current = this.root_;
+  while (true) {
+    if (key < current.key) {
+      if (!current.left) {
+        break;
+      }
+      if (key < current.left.key) {
+        // Rotate right.
+        var tmp = current.left;
+        current.left = tmp.right;
+        tmp.right = current;
+        current = tmp;
+        if (!current.left) {
+          break;
+        }
+      }
+      // Link right.
+      right.left = current;
+      right = current;
+      current = current.left;
+    } else if (key > current.key) {
+      if (!current.right) {
+        break;
+      }
+      if (key > current.right.key) {
+        // Rotate left.
+        var tmp = current.right;
+        current.right = tmp.left;
+        tmp.left = current;
+        current = tmp;
+        if (!current.right) {
+          break;
+        }
+      }
+      // Link left.
+      left.right = current;
+      left = current;
+      current = current.right;
+    } else {
+      break;
+    }
+  }
+  // Assemble.
+  left.right = current.left;
+  right.left = current.right;
+  current.left = dummy.right;
+  current.right = dummy.left;
+  this.root_ = current;
+};
+
+
+/**
+ * Performs a preorder traversal of the tree.
+ *
+ * @param {function(goog.structs.SplayTree.Node)} f Visitor function.
+ * @private
+ */
+goog.structs.SplayTree.prototype.traverse_ = function(f) {
+  var nodesToVisit = [this.root_];
+  while (nodesToVisit.length > 0) {
+    var node = nodesToVisit.shift();
+    if (node == null) {
+      continue;
+    }
+    f(node);
+    nodesToVisit.push(node.left);
+    nodesToVisit.push(node.right);
+  }
+};
+
+
+/**
+ * Constructs a Splay tree node.
+ *
+ * @param {number} key Key.
+ * @param {*} value Value.
+ */
+goog.structs.SplayTree.Node = function(key, value) {
+  this.key = key;
+  this.value = value;
+};
+
+
+/**
+ * @type {goog.structs.SplayTree.Node}
+ */
+goog.structs.SplayTree.Node.prototype.left = null;
+
+
+/**
+ * @type {goog.structs.SplayTree.Node}
+ */
+goog.structs.SplayTree.Node.prototype.right = null;
diff --git a/deps/v8/tools/splaytree.py b/deps/v8/tools/splaytree.py
new file mode 100644
index 0000000..8c3c4fe
--- /dev/null
+++ b/deps/v8/tools/splaytree.py
@@ -0,0 +1,226 @@
+# Copyright 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.
+
+
+class Node(object):
+  """Nodes in the splay tree."""
+
+  def __init__(self, key, value):
+    self.key = key
+    self.value = value
+    self.left = None
+    self.right = None
+
+
+class KeyNotFoundError(Exception):
+  """KeyNotFoundError is raised when removing a non-existing node."""
+
+  def __init__(self, key):
+    self.key = key
+
+
+class SplayTree(object):
+  """The splay tree itself is just a reference to the root of the tree."""
+
+  def __init__(self):
+    """Create a new SplayTree."""
+    self.root = None
+
+  def IsEmpty(self):
+    """Is the SplayTree empty?"""
+    return not self.root
+
+  def Insert(self, key, value):
+    """Insert a new node in the SplayTree."""
+    # If the tree is empty, insert the new node.
+    if self.IsEmpty():
+      self.root = Node(key, value)
+      return
+    # Splay on the key to move the last node on the search path for
+    # the key to the root of the tree.
+    self.Splay(key)
+    # Ignore repeated insertions with the same key.
+    if self.root.key == key:
+      return
+    # Insert the new node.
+    node = Node(key, value)
+    if key > self.root.key:
+      node.left = self.root
+      node.right = self.root.right
+      self.root.right = None
+    else:
+      node.right = self.root
+      node.left = self.root.left
+      self.root.left = None
+    self.root = node
+
+  def Remove(self, key):
+    """Remove the node with the given key from the SplayTree."""
+    # Raise exception for key that is not found if the tree is empty.
+    if self.IsEmpty():
+      raise KeyNotFoundError(key)
+    # Splay on the key to move the node with the given key to the top.
+    self.Splay(key)
+    # Raise exception for key that is not found.
+    if self.root.key != key:
+      raise KeyNotFoundError(key)
+    removed = self.root
+    # Link out the root node.
+    if not self.root.left:
+      # No left child, so the new tree is just the right child.
+      self.root = self.root.right
+    else:
+      # Left child exists.
+      right = self.root.right
+      # Make the original left child the new root.
+      self.root = self.root.left
+      # Splay to make sure that the new root has an empty right child.
+      self.Splay(key)
+      # Insert the original right child as the right child of the new
+      # root.
+      self.root.right = right
+    return removed
+
+  def Find(self, key):
+    """Returns the node with the given key or None if no such node exists."""
+    if self.IsEmpty():
+      return None
+    self.Splay(key)
+    if self.root.key == key:
+      return self.root
+    return None
+
+  def FindMax(self):
+    """Returns the node with the largest key value."""
+    if self.IsEmpty():
+      return None
+    current = self.root
+    while current.right != None:
+      current = current.right
+    return current
+
+  # Returns the node with the smallest key value.
+  def FindMin(self):
+    if self.IsEmpty():
+      return None
+    current = self.root
+    while current.left != None:
+      current = current.left
+    return current
+
+  def FindGreatestsLessThan(self, key):
+    """Returns node with greatest key less than or equal to the given key."""
+    if self.IsEmpty():
+      return None
+    # Splay on the key to move the node with the given key or the last
+    # node on the search path to the top of the tree.
+    self.Splay(key)
+    # Now the result is either the root node or the greatest node in
+    # the left subtree.
+    if self.root.key <= key:
+      return self.root
+    else:
+      tmp = self.root
+      self.root = self.root.left
+      result = self.FindMax()
+      self.root = tmp
+      return result
+
+  def ExportValueList(self):
+    """Returns a list containing all the values of the nodes in the tree."""
+    result = []
+    nodes_to_visit = [self.root]
+    while len(nodes_to_visit) > 0:
+      node = nodes_to_visit.pop()
+      if not node:
+        continue
+      result.append(node.value)
+      nodes_to_visit.append(node.left)
+      nodes_to_visit.append(node.right)
+    return result
+
+  def Splay(self, key):
+    """Perform splay operation.
+
+    Perform the splay operation for the given key. Moves the node with
+    the given key to the top of the tree.  If no node has the given
+    key, the last node on the search path is moved to the top of the
+    tree.
+
+    This uses the simplified top-down splaying algorithm from:
+
+    "Self-adjusting Binary Search Trees" by Sleator and Tarjan
+
+    """
+    if self.IsEmpty():
+      return
+    # Create a dummy node.  The use of the dummy node is a bit
+    # counter-intuitive: The right child of the dummy node will hold
+    # the L tree of the algorithm.  The left child of the dummy node
+    # will hold the R tree of the algorithm.  Using a dummy node, left
+    # and right will always be nodes and we avoid special cases.
+    dummy = left = right = Node(None, None)
+    current = self.root
+    while True:
+      if key < current.key:
+        if not current.left:
+          break
+        if key < current.left.key:
+          # Rotate right.
+          tmp = current.left
+          current.left = tmp.right
+          tmp.right = current
+          current = tmp
+          if not current.left:
+            break
+        # Link right.
+        right.left = current
+        right = current
+        current = current.left
+      elif key > current.key:
+        if not current.right:
+          break
+        if key > current.right.key:
+          # Rotate left.
+          tmp = current.right
+          current.right = tmp.left
+          tmp.left = current
+          current = tmp
+          if not current.right:
+            break
+        # Link left.
+        left.right = current
+        left = current
+        current = current.right
+      else:
+        break
+    # Assemble.
+    left.right = current.left
+    right.left = current.right
+    current.left = dummy.right
+    current.right = dummy.left
+    self.root = current
diff --git a/deps/v8/tools/stats-viewer.py b/deps/v8/tools/stats-viewer.py
new file mode 100755
index 0000000..bd6a8fb
--- /dev/null
+++ b/deps/v8/tools/stats-viewer.py
@@ -0,0 +1,372 @@
+# Copyright 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.
+
+
+"""A cross-platform execution counter viewer.
+
+The stats viewer reads counters from a binary file and displays them
+in a window, re-reading and re-displaying with regular intervals.
+"""
+
+
+import mmap
+import os
+import struct
+import sys
+import time
+import Tkinter
+
+
+# The interval, in milliseconds, between ui updates
+UPDATE_INTERVAL_MS = 100
+
+
+# Mapping from counter prefix to the formatting to be used for the counter
+COUNTER_LABELS = {"t": "%i ms.", "c": "%i"}
+
+
+# The magic number used to check if a file is not a counters file
+COUNTERS_FILE_MAGIC_NUMBER = 0xDEADFACE
+
+
+class StatsViewer(object):
+  """The main class that keeps the data used by the stats viewer."""
+
+  def __init__(self, data_name):
+    """Creates a new instance.
+
+    Args:
+      data_name: the name of the file containing the counters.
+    """
+    self.data_name = data_name
+
+    # The handle created by mmap.mmap to the counters file.  We need
+    # this to clean it up on exit.
+    self.shared_mmap = None
+
+    # A mapping from counter names to the ui element that displays
+    # them
+    self.ui_counters = {}
+
+    # The counter collection used to access the counters file
+    self.data = None
+
+    # The Tkinter root window object
+    self.root = None
+
+  def Run(self):
+    """The main entry-point to running the stats viewer."""
+    try:
+      self.data = self.MountSharedData()
+      # OpenWindow blocks until the main window is closed
+      self.OpenWindow()
+    finally:
+      self.CleanUp()
+
+  def MountSharedData(self):
+    """Mount the binary counters file as a memory-mapped file.  If
+    something goes wrong print an informative message and exit the
+    program."""
+    if not os.path.exists(self.data_name):
+      print "File %s doesn't exist." % self.data_name
+      sys.exit(1)
+    data_file = open(self.data_name, "r")
+    size = os.fstat(data_file.fileno()).st_size
+    fileno = data_file.fileno()
+    self.shared_mmap = mmap.mmap(fileno, size, access=mmap.ACCESS_READ)
+    data_access = SharedDataAccess(self.shared_mmap)
+    if data_access.IntAt(0) != COUNTERS_FILE_MAGIC_NUMBER:
+      print "File %s is not stats data." % self.data_name
+      sys.exit(1)
+    return CounterCollection(data_access)
+
+  def CleanUp(self):
+    """Cleans up the memory mapped file if necessary."""
+    if self.shared_mmap:
+      self.shared_mmap.close()
+
+  def UpdateCounters(self):
+    """Read the contents of the memory-mapped file and update the ui if
+    necessary.  If the same counters are present in the file as before
+    we just update the existing labels.  If any counters have been added
+    or removed we scrap the existing ui and draw a new one.
+    """
+    changed = False
+    counters_in_use = self.data.CountersInUse()
+    if counters_in_use != len(self.ui_counters):
+      self.RefreshCounters()
+      changed = True
+    else:
+      for i in xrange(self.data.CountersInUse()):
+        counter = self.data.Counter(i)
+        name = counter.Name()
+        if name in self.ui_counters:
+          value = counter.Value()
+          ui_counter = self.ui_counters[name]
+          counter_changed = ui_counter.Set(value)
+          changed = (changed or counter_changed)
+        else:
+          self.RefreshCounters()
+          changed = True
+          break
+    if changed:
+      # The title of the window shows the last time the file was
+      # changed.
+      self.UpdateTime()
+    self.ScheduleUpdate()
+
+  def UpdateTime(self):
+    """Update the title of the window with the current time."""
+    self.root.title("Stats Viewer [updated %s]" % time.strftime("%H:%M:%S"))
+
+  def ScheduleUpdate(self):
+    """Schedules the next ui update."""
+    self.root.after(UPDATE_INTERVAL_MS, lambda: self.UpdateCounters())
+
+  def RefreshCounters(self):
+    """Tear down and rebuild the controls in the main window."""
+    counters = self.ComputeCounters()
+    self.RebuildMainWindow(counters)
+
+  def ComputeCounters(self):
+    """Group the counters by the suffix of their name.
+
+    Since the same code-level counter (for instance "X") can result in
+    several variables in the binary counters file that differ only by a
+    two-character prefix (for instance "c:X" and "t:X") counters are
+    grouped by suffix and then displayed with custom formatting
+    depending on their prefix.
+
+    Returns:
+      A mapping from suffixes to a list of counters with that suffix,
+      sorted by prefix.
+    """
+    names = {}
+    for i in xrange(self.data.CountersInUse()):
+      counter = self.data.Counter(i)
+      name = counter.Name()
+      names[name] = counter
+
+    # By sorting the keys we ensure that the prefixes always come in the
+    # same order ("c:" before "t:") which looks more consistent in the
+    # ui.
+    sorted_keys = names.keys()
+    sorted_keys.sort()
+
+    # Group together the names whose suffix after a ':' are the same.
+    groups = {}
+    for name in sorted_keys:
+      counter = names[name]
+      if ":" in name:
+        name = name[name.find(":")+1:]
+      if not name in groups:
+        groups[name] = []
+      groups[name].append(counter)
+
+    return groups
+
+  def RebuildMainWindow(self, groups):
+    """Tear down and rebuild the main window.
+
+    Args:
+      groups: the groups of counters to display
+    """
+    # Remove elements in the current ui
+    self.ui_counters.clear()
+    for child in self.root.children.values():
+      child.destroy()
+
+    # Build new ui
+    index = 0
+    sorted_groups = groups.keys()
+    sorted_groups.sort()
+    for counter_name in sorted_groups:
+      counter_objs = groups[counter_name]
+      name = Tkinter.Label(self.root, width=50, anchor=Tkinter.W,
+                           text=counter_name)
+      name.grid(row=index, column=0, padx=1, pady=1)
+      count = len(counter_objs)
+      for i in xrange(count):
+        counter = counter_objs[i]
+        name = counter.Name()
+        var = Tkinter.StringVar()
+        value = Tkinter.Label(self.root, width=15, anchor=Tkinter.W,
+                              textvariable=var)
+        value.grid(row=index, column=(1 + i), padx=1, pady=1)
+
+        # If we know how to interpret the prefix of this counter then
+        # add an appropriate formatting to the variable
+        if (":" in name) and (name[0] in COUNTER_LABELS):
+          format = COUNTER_LABELS[name[0]]
+        else:
+          format = "%i"
+        ui_counter = UiCounter(var, format)
+        self.ui_counters[name] = ui_counter
+        ui_counter.Set(counter.Value())
+      index += 1
+    self.root.update()
+
+  def OpenWindow(self):
+    """Create and display the root window."""
+    self.root = Tkinter.Tk()
+
+    # Tkinter is no good at resizing so we disable it
+    self.root.resizable(width=False, height=False)
+    self.RefreshCounters()
+    self.ScheduleUpdate()
+    self.root.mainloop()
+
+
+class UiCounter(object):
+  """A counter in the ui."""
+
+  def __init__(self, var, format):
+    """Creates a new ui counter.
+
+    Args:
+      var: the Tkinter string variable for updating the ui
+      format: the format string used to format this counter
+    """
+    self.var = var
+    self.format = format
+    self.last_value = None
+
+  def Set(self, value):
+    """Updates the ui for this counter.
+
+    Args:
+      value: The value to display
+
+    Returns:
+      True if the value had changed, otherwise False.  The first call
+      always returns True.
+    """
+    if value == self.last_value:
+      return False
+    else:
+      self.last_value = value
+      self.var.set(self.format % value)
+      return True
+
+
+class SharedDataAccess(object):
+  """A utility class for reading data from the memory-mapped binary
+  counters file."""
+
+  def __init__(self, data):
+    """Create a new instance.
+
+    Args:
+      data: A handle to the memory-mapped file, as returned by mmap.mmap.
+    """
+    self.data = data
+
+  def ByteAt(self, index):
+    """Return the (unsigned) byte at the specified byte index."""
+    return ord(self.CharAt(index))
+
+  def IntAt(self, index):
+    """Return the little-endian 32-byte int at the specified byte index."""
+    word_str = self.data[index:index+4]
+    result, = struct.unpack("I", word_str)
+    return result
+
+  def CharAt(self, index):
+    """Return the ascii character at the specified byte index."""
+    return self.data[index]
+
+
+class Counter(object):
+  """A pointer to a single counter withing a binary counters file."""
+
+  def __init__(self, data, offset):
+    """Create a new instance.
+
+    Args:
+      data: the shared data access object containing the counter
+      offset: the byte offset of the start of this counter
+    """
+    self.data = data
+    self.offset = offset
+
+  def Value(self):
+    """Return the integer value of this counter."""
+    return self.data.IntAt(self.offset)
+
+  def Name(self):
+    """Return the ascii name of this counter."""
+    result = ""
+    index = self.offset + 4
+    current = self.data.ByteAt(index)
+    while current:
+      result += chr(current)
+      index += 1
+      current = self.data.ByteAt(index)
+    return result
+
+
+class CounterCollection(object):
+  """An overlay over a counters file that provides access to the
+  individual counters contained in the file."""
+
+  def __init__(self, data):
+    """Create a new instance.
+
+    Args:
+      data: the shared data access object
+    """
+    self.data = data
+    self.max_counters = data.IntAt(4)
+    self.max_name_size = data.IntAt(8)
+
+  def CountersInUse(self):
+    """Return the number of counters in active use."""
+    return self.data.IntAt(12)
+
+  def Counter(self, index):
+    """Return the index'th counter."""
+    return Counter(self.data, 16 + index * self.CounterSize())
+
+  def CounterSize(self):
+    """Return the size of a single counter."""
+    return 4 + self.max_name_size
+
+
+def Main(data_file):
+  """Run the stats counter.
+
+  Args:
+    data_file: The counters file to monitor.
+  """
+  StatsViewer(data_file).Run()
+
+
+if __name__ == "__main__":
+  if len(sys.argv) != 2:
+    print "Usage: stats-viewer.py <stats data>"
+    sys.exit(1)
+  Main(sys.argv[1])
diff --git a/deps/v8/tools/test.py b/deps/v8/tools/test.py
new file mode 100755
index 0000000..9981e8c
--- /dev/null
+++ b/deps/v8/tools/test.py
@@ -0,0 +1,1330 @@
+#!/usr/bin/env python
+#
+# Copyright 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.
+
+
+import imp
+import optparse
+import os
+from os.path import join, dirname, abspath, basename, isdir, exists
+import platform
+import re
+import signal
+import subprocess
+import sys
+import tempfile
+import time
+import threading
+import utils
+from Queue import Queue, Empty
+
+
+VERBOSE = False
+
+
+# ---------------------------------------------
+# --- P r o g r e s s   I n d i c a t o r s ---
+# ---------------------------------------------
+
+
+class ProgressIndicator(object):
+
+  def __init__(self, cases):
+    self.cases = cases
+    self.queue = Queue(len(cases))
+    for case in cases:
+      self.queue.put_nowait(case)
+    self.succeeded = 0
+    self.remaining = len(cases)
+    self.total = len(cases)
+    self.failed = [ ]
+    self.crashed = 0
+    self.terminate = False
+    self.lock = threading.Lock()
+
+  def PrintFailureHeader(self, test):
+    if test.IsNegative():
+      negative_marker = '[negative] '
+    else:
+      negative_marker = ''
+    print "=== %(label)s %(negative)s===" % {
+      'label': test.GetLabel(),
+      'negative': negative_marker
+    }
+    print "Path: %s" % "/".join(test.path)
+
+  def Run(self, tasks):
+    self.Starting()
+    threads = []
+    # Spawn N-1 threads and then use this thread as the last one.
+    # That way -j1 avoids threading altogether which is a nice fallback
+    # in case of threading problems.
+    for i in xrange(tasks - 1):
+      thread = threading.Thread(target=self.RunSingle, args=[])
+      threads.append(thread)
+      thread.start()
+    try:
+      self.RunSingle()
+      # Wait for the remaining threads
+      for thread in threads:
+        # Use a timeout so that signals (ctrl-c) will be processed.
+        thread.join(timeout=10000000)
+    except Exception, e:
+      # If there's an exception we schedule an interruption for any
+      # remaining threads.
+      self.terminate = True
+      # ...and then reraise the exception to bail out
+      raise
+    self.Done()
+    return not self.failed
+
+  def RunSingle(self):
+    while not self.terminate:
+      try:
+        test = self.queue.get_nowait()
+      except Empty:
+        return
+      case = test.case
+      self.lock.acquire()
+      self.AboutToRun(case)
+      self.lock.release()
+      try:
+        start = time.time()
+        output = case.Run()
+        case.duration = (time.time() - start)
+      except IOError, e:
+        assert self.terminate
+        return
+      if self.terminate:
+        return
+      self.lock.acquire()
+      if output.UnexpectedOutput():
+        self.failed.append(output)
+        if output.HasCrashed():
+          self.crashed += 1
+      else:
+        self.succeeded += 1
+      self.remaining -= 1
+      self.HasRun(output)
+      self.lock.release()
+
+
+def EscapeCommand(command):
+  parts = []
+  for part in command:
+    if ' ' in part:
+      # Escape spaces.  We may need to escape more characters for this
+      # to work properly.
+      parts.append('"%s"' % part)
+    else:
+      parts.append(part)
+  return " ".join(parts)
+
+
+class SimpleProgressIndicator(ProgressIndicator):
+
+  def Starting(self):
+    print 'Running %i tests' % len(self.cases)
+
+  def Done(self):
+    print
+    for failed in self.failed:
+      self.PrintFailureHeader(failed.test)
+      if failed.output.stderr:
+        print "--- stderr ---"
+        print failed.output.stderr.strip()
+      if failed.output.stdout:
+        print "--- stdout ---"
+        print failed.output.stdout.strip()
+      print "Command: %s" % EscapeCommand(failed.command)
+      if failed.HasCrashed():
+        print "--- CRASHED ---"
+    if len(self.failed) == 0:
+      print "==="
+      print "=== All tests succeeded"
+      print "==="
+    else:
+      print
+      print "==="
+      print "=== %i tests failed" % len(self.failed)
+      if self.crashed > 0:
+        print "=== %i tests CRASHED" % self.crashed
+      print "==="
+
+
+class VerboseProgressIndicator(SimpleProgressIndicator):
+
+  def AboutToRun(self, case):
+    print 'Starting %s...' % case.GetLabel()
+    sys.stdout.flush()
+
+  def HasRun(self, output):
+    if output.UnexpectedOutput():
+      if output.HasCrashed():
+        outcome = 'CRASH'
+      else:
+        outcome = 'FAIL'
+    else:
+      outcome = 'pass'
+    print 'Done running %s: %s' % (output.test.GetLabel(), outcome)
+
+
+class DotsProgressIndicator(SimpleProgressIndicator):
+
+  def AboutToRun(self, case):
+    pass
+
+  def HasRun(self, output):
+    total = self.succeeded + len(self.failed)
+    if (total > 1) and (total % 50 == 1):
+      sys.stdout.write('\n')
+    if output.UnexpectedOutput():
+      if output.HasCrashed():
+        sys.stdout.write('C')
+        sys.stdout.flush()
+      else:
+        sys.stdout.write('F')
+        sys.stdout.flush()
+    else:
+      sys.stdout.write('.')
+      sys.stdout.flush()
+
+
+class CompactProgressIndicator(ProgressIndicator):
+
+  def __init__(self, cases, templates):
+    super(CompactProgressIndicator, self).__init__(cases)
+    self.templates = templates
+    self.last_status_length = 0
+    self.start_time = time.time()
+
+  def Starting(self):
+    pass
+
+  def Done(self):
+    self.PrintProgress('Done')
+
+  def AboutToRun(self, case):
+    self.PrintProgress(case.GetLabel())
+
+  def HasRun(self, output):
+    if output.UnexpectedOutput():
+      self.ClearLine(self.last_status_length)
+      self.PrintFailureHeader(output.test)
+      stdout = output.output.stdout.strip()
+      if len(stdout):
+        print self.templates['stdout'] % stdout
+      stderr = output.output.stderr.strip()
+      if len(stderr):
+        print self.templates['stderr'] % stderr
+      print "Command: %s" % EscapeCommand(output.command)
+      if output.HasCrashed():
+        print "--- CRASHED ---"
+
+  def Truncate(self, str, length):
+    if length and (len(str) > (length - 3)):
+      return str[:(length-3)] + "..."
+    else:
+      return str
+
+  def PrintProgress(self, name):
+    self.ClearLine(self.last_status_length)
+    elapsed = time.time() - self.start_time
+    status = self.templates['status_line'] % {
+      'passed': self.succeeded,
+      'remaining': (((self.total - self.remaining) * 100) // self.total),
+      'failed': len(self.failed),
+      'test': name,
+      'mins': int(elapsed) / 60,
+      'secs': int(elapsed) % 60
+    }
+    status = self.Truncate(status, 78)
+    self.last_status_length = len(status)
+    print status,
+    sys.stdout.flush()
+
+
+class ColorProgressIndicator(CompactProgressIndicator):
+
+  def __init__(self, cases):
+    templates = {
+      'status_line': "[%(mins)02i:%(secs)02i|\033[34m%%%(remaining) 4d\033[0m|\033[32m+%(passed) 4d\033[0m|\033[31m-%(failed) 4d\033[0m]: %(test)s",
+      'stdout': "\033[1m%s\033[0m",
+      'stderr': "\033[31m%s\033[0m",
+    }
+    super(ColorProgressIndicator, self).__init__(cases, templates)
+
+  def ClearLine(self, last_line_length):
+    print "\033[1K\r",
+
+
+class MonochromeProgressIndicator(CompactProgressIndicator):
+
+  def __init__(self, cases):
+    templates = {
+      'status_line': "[%(mins)02i:%(secs)02i|%%%(remaining) 4d|+%(passed) 4d|-%(failed) 4d]: %(test)s",
+      'stdout': '%s',
+      'stderr': '%s',
+      'clear': lambda last_line_length: ("\r" + (" " * last_line_length) + "\r"),
+      'max_length': 78
+    }
+    super(MonochromeProgressIndicator, self).__init__(cases, templates)
+
+  def ClearLine(self, last_line_length):
+    print ("\r" + (" " * last_line_length) + "\r"),
+
+
+PROGRESS_INDICATORS = {
+  'verbose': VerboseProgressIndicator,
+  'dots': DotsProgressIndicator,
+  'color': ColorProgressIndicator,
+  'mono': MonochromeProgressIndicator
+}
+
+
+# -------------------------
+# --- F r a m e w o r k ---
+# -------------------------
+
+
+class CommandOutput(object):
+
+  def __init__(self, exit_code, timed_out, stdout, stderr):
+    self.exit_code = exit_code
+    self.timed_out = timed_out
+    self.stdout = stdout
+    self.stderr = stderr
+
+
+class TestCase(object):
+
+  def __init__(self, context, path):
+    self.path = path
+    self.context = context
+    self.failed = None
+    self.duration = None
+
+  def IsNegative(self):
+    return False
+
+  def CompareTime(self, other):
+    return cmp(other.duration, self.duration)
+
+  def DidFail(self, output):
+    if self.failed is None:
+      self.failed = self.IsFailureOutput(output)
+    return self.failed
+
+  def IsFailureOutput(self, output):
+    return output.exit_code != 0
+
+  def GetSource(self):
+    return "(no source available)"
+
+  def RunCommand(self, command):
+    full_command = self.context.processor(command)
+    output = Execute(full_command, self.context, self.context.timeout)
+    return TestOutput(self, full_command, output)
+
+  def Run(self):
+    return self.RunCommand(self.GetCommand())
+
+
+class TestOutput(object):
+
+  def __init__(self, test, command, output):
+    self.test = test
+    self.command = command
+    self.output = output
+
+  def UnexpectedOutput(self):
+    if self.HasCrashed():
+      outcome = CRASH
+    elif self.HasFailed():
+      outcome = FAIL
+    else:
+      outcome = PASS
+    return not outcome in self.test.outcomes
+
+  def HasCrashed(self):
+    if utils.IsWindows():
+      return 0x80000000 & self.output.exit_code and not (0x3FFFFF00 & self.output.exit_code)
+    else:
+      # Timed out tests will have exit_code -signal.SIGTERM.
+      if self.output.timed_out:
+        return False
+      return self.output.exit_code < 0 and \
+             self.output.exit_code != -signal.SIGABRT
+
+  def HasFailed(self):
+    execution_failed = self.test.DidFail(self.output)
+    if self.test.IsNegative():
+      return not execution_failed
+    else:
+      return execution_failed
+
+
+def KillProcessWithID(pid):
+  if utils.IsWindows():
+    os.popen('taskkill /T /F /PID %d' % pid)
+  else:
+    os.kill(pid, signal.SIGTERM)
+
+
+MAX_SLEEP_TIME = 0.1
+INITIAL_SLEEP_TIME = 0.0001
+SLEEP_TIME_FACTOR = 1.25
+
+SEM_INVALID_VALUE = -1
+SEM_NOGPFAULTERRORBOX = 0x0002 # Microsoft Platform SDK WinBase.h
+
+def Win32SetErrorMode(mode):
+  prev_error_mode = SEM_INVALID_VALUE
+  try:
+    import ctypes
+    prev_error_mode = ctypes.windll.kernel32.SetErrorMode(mode);
+  except ImportError:
+    pass
+  return prev_error_mode
+
+def RunProcess(context, timeout, args, **rest):
+  if context.verbose: print "#", " ".join(args)
+  popen_args = args
+  prev_error_mode = SEM_INVALID_VALUE;
+  if utils.IsWindows():
+    popen_args = '"' + subprocess.list2cmdline(args) + '"'
+    if context.suppress_dialogs:
+      # Try to change the error mode to avoid dialogs on fatal errors. Don't
+      # touch any existing error mode flags by merging the existing error mode.
+      # See http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx.
+      error_mode = SEM_NOGPFAULTERRORBOX;
+      prev_error_mode = Win32SetErrorMode(error_mode);
+      Win32SetErrorMode(error_mode | prev_error_mode);
+  process = subprocess.Popen(
+    shell = utils.IsWindows(),
+    args = popen_args,
+    **rest
+  )
+  if utils.IsWindows() and context.suppress_dialogs and prev_error_mode != SEM_INVALID_VALUE:
+    Win32SetErrorMode(prev_error_mode)
+  # Compute the end time - if the process crosses this limit we
+  # consider it timed out.
+  if timeout is None: end_time = None
+  else: end_time = time.time() + timeout
+  timed_out = False
+  # Repeatedly check the exit code from the process in a
+  # loop and keep track of whether or not it times out.
+  exit_code = None
+  sleep_time = INITIAL_SLEEP_TIME
+  while exit_code is None:
+    if (not end_time is None) and (time.time() >= end_time):
+      # Kill the process and wait for it to exit.
+      KillProcessWithID(process.pid)
+      exit_code = process.wait()
+      timed_out = True
+    else:
+      exit_code = process.poll()
+      time.sleep(sleep_time)
+      sleep_time = sleep_time * SLEEP_TIME_FACTOR
+      if sleep_time > MAX_SLEEP_TIME:
+        sleep_time = MAX_SLEEP_TIME
+  return (process, exit_code, timed_out)
+
+
+def PrintError(str):
+  sys.stderr.write(str)
+  sys.stderr.write('\n')
+
+
+def Execute(args, context, timeout=None):
+  (fd_out, outname) = tempfile.mkstemp()
+  (fd_err, errname) = tempfile.mkstemp()
+  (process, exit_code, timed_out) = RunProcess(
+    context,
+    timeout,
+    args = args,
+    stdout = fd_out,
+    stderr = fd_err,
+  )
+  os.close(fd_out)
+  os.close(fd_err)
+  output = file(outname).read()
+  errors = file(errname).read()
+  def CheckedUnlink(name):
+    try:
+      os.unlink(name)
+    except OSError, e:
+      PrintError("os.unlink() " + str(e))
+  CheckedUnlink(outname)
+  CheckedUnlink(errname)
+  return CommandOutput(exit_code, timed_out, output, errors)
+
+
+def ExecuteNoCapture(args, context, timeout=None):
+  (process, exit_code, timed_out) = RunProcess(
+    context,
+    timeout,
+    args = args,
+  )
+  return CommandOutput(exit_code, False, "", "")
+
+
+def CarCdr(path):
+  if len(path) == 0:
+    return (None, [ ])
+  else:
+    return (path[0], path[1:])
+
+
+class TestConfiguration(object):
+
+  def __init__(self, context, root):
+    self.context = context
+    self.root = root
+
+  def Contains(self, path, file):
+    if len(path) > len(file):
+      return False
+    for i in xrange(len(path)):
+      if not path[i].match(file[i]):
+        return False
+    return True
+
+  def GetTestStatus(self, sections, defs):
+    pass
+
+
+class TestSuite(object):
+
+  def __init__(self, name):
+    self.name = name
+
+  def GetName(self):
+    return self.name
+
+
+class TestRepository(TestSuite):
+
+  def __init__(self, path):
+    normalized_path = abspath(path)
+    super(TestRepository, self).__init__(basename(normalized_path))
+    self.path = normalized_path
+    self.is_loaded = False
+    self.config = None
+
+  def GetConfiguration(self, context):
+    if self.is_loaded:
+      return self.config
+    self.is_loaded = True
+    file = None
+    try:
+      (file, pathname, description) = imp.find_module('testcfg', [ self.path ])
+      module = imp.load_module('testcfg', file, pathname, description)
+      self.config = module.GetConfiguration(context, self.path)
+    finally:
+      if file:
+        file.close()
+    return self.config
+
+  def GetBuildRequirements(self, path, context):
+    return self.GetConfiguration(context).GetBuildRequirements()
+
+  def ListTests(self, current_path, path, context, mode):
+    return self.GetConfiguration(context).ListTests(current_path, path, mode)
+
+  def GetTestStatus(self, context, sections, defs):
+    self.GetConfiguration(context).GetTestStatus(sections, defs)
+
+
+class LiteralTestSuite(TestSuite):
+
+  def __init__(self, tests):
+    super(LiteralTestSuite, self).__init__('root')
+    self.tests = tests
+
+  def GetBuildRequirements(self, path, context):
+    (name, rest) = CarCdr(path)
+    result = [ ]
+    for test in self.tests:
+      if not name or name.match(test.GetName()):
+        result += test.GetBuildRequirements(rest, context)
+    return result
+
+  def ListTests(self, current_path, path, context, mode):
+    (name, rest) = CarCdr(path)
+    result = [ ]
+    for test in self.tests:
+      test_name = test.GetName()
+      if not name or name.match(test_name):
+        full_path = current_path + [test_name]
+        result += test.ListTests(full_path, path, context, mode)
+    return result
+
+  def GetTestStatus(self, context, sections, defs):
+    for test in self.tests:
+      test.GetTestStatus(context, sections, defs)
+
+
+SUFFIX = {'debug': '_g', 'release': ''}
+
+
+class Context(object):
+
+  def __init__(self, workspace, buildspace, verbose, vm, timeout, processor, suppress_dialogs):
+    self.workspace = workspace
+    self.buildspace = buildspace
+    self.verbose = verbose
+    self.vm_root = vm
+    self.timeout = timeout
+    self.processor = processor
+    self.suppress_dialogs = suppress_dialogs
+
+  def GetVm(self, mode):
+    name = self.vm_root + SUFFIX[mode]
+    if utils.IsWindows() and not name.endswith('.exe'):
+      name = name + '.exe'
+    return name
+
+def RunTestCases(all_cases, progress, tasks):
+  def DoSkip(case):
+    return SKIP in c.outcomes or SLOW in c.outcomes
+  cases_to_run = [ c for c in all_cases if not DoSkip(c) ]
+  progress = PROGRESS_INDICATORS[progress](cases_to_run)
+  return progress.Run(tasks)
+
+
+def BuildRequirements(context, requirements, mode, scons_flags):
+  command_line = (['scons', '-Y', context.workspace, 'mode=' + ",".join(mode)]
+                  + requirements
+                  + scons_flags)
+  output = ExecuteNoCapture(command_line, context)
+  return output.exit_code == 0
+
+
+# -------------------------------------------
+# --- T e s t   C o n f i g u r a t i o n ---
+# -------------------------------------------
+
+
+SKIP = 'skip'
+FAIL = 'fail'
+PASS = 'pass'
+OKAY = 'okay'
+TIMEOUT = 'timeout'
+CRASH = 'crash'
+SLOW = 'slow'
+
+
+class Expression(object):
+  pass
+
+
+class Constant(Expression):
+
+  def __init__(self, value):
+    self.value = value
+
+  def Evaluate(self, env, defs):
+    return self.value
+
+
+class Variable(Expression):
+
+  def __init__(self, name):
+    self.name = name
+
+  def GetOutcomes(self, env, defs):
+    if self.name in env: return ListSet([env[self.name]])
+    else: return Nothing()
+
+
+class Outcome(Expression):
+
+  def __init__(self, name):
+    self.name = name
+
+  def GetOutcomes(self, env, defs):
+    if self.name in defs:
+      return defs[self.name].GetOutcomes(env, defs)
+    else:
+      return ListSet([self.name])
+
+
+class Set(object):
+  pass
+
+
+class ListSet(Set):
+
+  def __init__(self, elms):
+    self.elms = elms
+
+  def __str__(self):
+    return "ListSet%s" % str(self.elms)
+
+  def Intersect(self, that):
+    if not isinstance(that, ListSet):
+      return that.Intersect(self)
+    return ListSet([ x for x in self.elms if x in that.elms ])
+
+  def Union(self, that):
+    if not isinstance(that, ListSet):
+      return that.Union(self)
+    return ListSet(self.elms + [ x for x in that.elms if x not in self.elms ])
+
+  def IsEmpty(self):
+    return len(self.elms) == 0
+
+
+class Everything(Set):
+
+  def Intersect(self, that):
+    return that
+
+  def Union(self, that):
+    return self
+
+  def IsEmpty(self):
+    return False
+
+
+class Nothing(Set):
+
+  def Intersect(self, that):
+    return self
+
+  def Union(self, that):
+    return that
+
+  def IsEmpty(self):
+    return True
+
+
+class Operation(Expression):
+
+  def __init__(self, left, op, right):
+    self.left = left
+    self.op = op
+    self.right = right
+
+  def Evaluate(self, env, defs):
+    if self.op == '||' or self.op == ',':
+      return self.left.Evaluate(env, defs) or self.right.Evaluate(env, defs)
+    elif self.op == 'if':
+      return False
+    elif self.op == '==':
+      inter = self.left.GetOutcomes(env, defs).Intersect(self.right.GetOutcomes(env, defs))
+      return not inter.IsEmpty()
+    else:
+      assert self.op == '&&'
+      return self.left.Evaluate(env, defs) and self.right.Evaluate(env, defs)
+
+  def GetOutcomes(self, env, defs):
+    if self.op == '||' or self.op == ',':
+      return self.left.GetOutcomes(env, defs).Union(self.right.GetOutcomes(env, defs))
+    elif self.op == 'if':
+      if self.right.Evaluate(env, defs): return self.left.GetOutcomes(env, defs)
+      else: return Nothing()
+    else:
+      assert self.op == '&&'
+      return self.left.GetOutcomes(env, defs).Intersect(self.right.GetOutcomes(env, defs))
+
+
+def IsAlpha(str):
+  for char in str:
+    if not (char.isalpha() or char.isdigit() or char == '_'):
+      return False
+  return True
+
+
+class Tokenizer(object):
+  """A simple string tokenizer that chops expressions into variables,
+  parens and operators"""
+
+  def __init__(self, expr):
+    self.index = 0
+    self.expr = expr
+    self.length = len(expr)
+    self.tokens = None
+
+  def Current(self, length = 1):
+    if not self.HasMore(length): return ""
+    return self.expr[self.index:self.index+length]
+
+  def HasMore(self, length = 1):
+    return self.index < self.length + (length - 1)
+
+  def Advance(self, count = 1):
+    self.index = self.index + count
+
+  def AddToken(self, token):
+    self.tokens.append(token)
+
+  def SkipSpaces(self):
+    while self.HasMore() and self.Current().isspace():
+      self.Advance()
+
+  def Tokenize(self):
+    self.tokens = [ ]
+    while self.HasMore():
+      self.SkipSpaces()
+      if not self.HasMore():
+        return None
+      if self.Current() == '(':
+        self.AddToken('(')
+        self.Advance()
+      elif self.Current() == ')':
+        self.AddToken(')')
+        self.Advance()
+      elif self.Current() == '$':
+        self.AddToken('$')
+        self.Advance()
+      elif self.Current() == ',':
+        self.AddToken(',')
+        self.Advance()
+      elif IsAlpha(self.Current()):
+        buf = ""
+        while self.HasMore() and IsAlpha(self.Current()):
+          buf += self.Current()
+          self.Advance()
+        self.AddToken(buf)
+      elif self.Current(2) == '&&':
+        self.AddToken('&&')
+        self.Advance(2)
+      elif self.Current(2) == '||':
+        self.AddToken('||')
+        self.Advance(2)
+      elif self.Current(2) == '==':
+        self.AddToken('==')
+        self.Advance(2)
+      else:
+        return None
+    return self.tokens
+
+
+class Scanner(object):
+  """A simple scanner that can serve out tokens from a given list"""
+
+  def __init__(self, tokens):
+    self.tokens = tokens
+    self.length = len(tokens)
+    self.index = 0
+
+  def HasMore(self):
+    return self.index < self.length
+
+  def Current(self):
+    return self.tokens[self.index]
+
+  def Advance(self):
+    self.index = self.index + 1
+
+
+def ParseAtomicExpression(scan):
+  if scan.Current() == "true":
+    scan.Advance()
+    return Constant(True)
+  elif scan.Current() == "false":
+    scan.Advance()
+    return Constant(False)
+  elif IsAlpha(scan.Current()):
+    name = scan.Current()
+    scan.Advance()
+    return Outcome(name.lower())
+  elif scan.Current() == '$':
+    scan.Advance()
+    if not IsAlpha(scan.Current()):
+      return None
+    name = scan.Current()
+    scan.Advance()
+    return Variable(name.lower())
+  elif scan.Current() == '(':
+    scan.Advance()
+    result = ParseLogicalExpression(scan)
+    if (not result) or (scan.Current() != ')'):
+      return None
+    scan.Advance()
+    return result
+  else:
+    return None
+
+
+BINARIES = ['==']
+def ParseOperatorExpression(scan):
+  left = ParseAtomicExpression(scan)
+  if not left: return None
+  while scan.HasMore() and (scan.Current() in BINARIES):
+    op = scan.Current()
+    scan.Advance()
+    right = ParseOperatorExpression(scan)
+    if not right:
+      return None
+    left = Operation(left, op, right)
+  return left
+
+
+def ParseConditionalExpression(scan):
+  left = ParseOperatorExpression(scan)
+  if not left: return None
+  while scan.HasMore() and (scan.Current() == 'if'):
+    scan.Advance()
+    right = ParseOperatorExpression(scan)
+    if not right:
+      return None
+    left=  Operation(left, 'if', right)
+  return left
+
+
+LOGICALS = ["&&", "||", ","]
+def ParseLogicalExpression(scan):
+  left = ParseConditionalExpression(scan)
+  if not left: return None
+  while scan.HasMore() and (scan.Current() in LOGICALS):
+    op = scan.Current()
+    scan.Advance()
+    right = ParseConditionalExpression(scan)
+    if not right:
+      return None
+    left = Operation(left, op, right)
+  return left
+
+
+def ParseCondition(expr):
+  """Parses a logical expression into an Expression object"""
+  tokens = Tokenizer(expr).Tokenize()
+  if not tokens:
+    print "Malformed expression: '%s'" % expr
+    return None
+  scan = Scanner(tokens)
+  ast = ParseLogicalExpression(scan)
+  if not ast:
+    print "Malformed expression: '%s'" % expr
+    return None
+  if scan.HasMore():
+    print "Malformed expression: '%s'" % expr
+    return None
+  return ast
+
+
+class ClassifiedTest(object):
+
+  def __init__(self, case, outcomes):
+    self.case = case
+    self.outcomes = outcomes
+
+
+class Configuration(object):
+  """The parsed contents of a configuration file"""
+
+  def __init__(self, sections, defs):
+    self.sections = sections
+    self.defs = defs
+
+  def ClassifyTests(self, cases, env):
+    sections = [s for s in self.sections if s.condition.Evaluate(env, self.defs)]
+    all_rules = reduce(list.__add__, [s.rules for s in sections], [])
+    unused_rules = set(all_rules)
+    result = [ ]
+    all_outcomes = set([])
+    for case in cases:
+      matches = [ r for r in all_rules if r.Contains(case.path) ]
+      outcomes = set([])
+      for rule in matches:
+        outcomes = outcomes.union(rule.GetOutcomes(env, self.defs))
+        unused_rules.discard(rule)
+      if not outcomes:
+        outcomes = [PASS]
+      case.outcomes = outcomes
+      all_outcomes = all_outcomes.union(outcomes)
+      result.append(ClassifiedTest(case, outcomes))
+    return (result, list(unused_rules), all_outcomes)
+
+
+class Section(object):
+  """A section of the configuration file.  Sections are enabled or
+  disabled prior to running the tests, based on their conditions"""
+
+  def __init__(self, condition):
+    self.condition = condition
+    self.rules = [ ]
+
+  def AddRule(self, rule):
+    self.rules.append(rule)
+
+
+class Rule(object):
+  """A single rule that specifies the expected outcome for a single
+  test."""
+
+  def __init__(self, raw_path, path, value):
+    self.raw_path = raw_path
+    self.path = path
+    self.value = value
+
+  def GetOutcomes(self, env, defs):
+    set = self.value.GetOutcomes(env, defs)
+    assert isinstance(set, ListSet)
+    return set.elms
+
+  def Contains(self, path):
+    if len(self.path) > len(path):
+      return False
+    for i in xrange(len(self.path)):
+      if not self.path[i].match(path[i]):
+        return False
+    return True
+
+
+HEADER_PATTERN = re.compile(r'\[([^]]+)\]')
+RULE_PATTERN = re.compile(r'\s*([^: ]*)\s*:(.*)')
+DEF_PATTERN = re.compile(r'^def\s*(\w+)\s*=(.*)$')
+PREFIX_PATTERN = re.compile(r'^\s*prefix\s+([\w\_\.\-\/]+)$')
+
+
+def ReadConfigurationInto(path, sections, defs):
+  current_section = Section(Constant(True))
+  sections.append(current_section)
+  prefix = []
+  for line in utils.ReadLinesFrom(path):
+    header_match = HEADER_PATTERN.match(line)
+    if header_match:
+      condition_str = header_match.group(1).strip()
+      condition = ParseCondition(condition_str)
+      new_section = Section(condition)
+      sections.append(new_section)
+      current_section = new_section
+      continue
+    rule_match = RULE_PATTERN.match(line)
+    if rule_match:
+      path = prefix + SplitPath(rule_match.group(1).strip())
+      value_str = rule_match.group(2).strip()
+      value = ParseCondition(value_str)
+      if not value:
+        return False
+      current_section.AddRule(Rule(rule_match.group(1), path, value))
+      continue
+    def_match = DEF_PATTERN.match(line)
+    if def_match:
+      name = def_match.group(1).lower()
+      value = ParseCondition(def_match.group(2).strip())
+      if not value:
+        return False
+      defs[name] = value
+      continue
+    prefix_match = PREFIX_PATTERN.match(line)
+    if prefix_match:
+      prefix = SplitPath(prefix_match.group(1).strip())
+      continue
+    print "Malformed line: '%s'." % line
+    return False
+  return True
+
+
+# ---------------
+# --- M a i n ---
+# ---------------
+
+
+ARCH_GUESS = utils.GuessArchitecture()
+
+
+def BuildOptions():
+  result = optparse.OptionParser()
+  result.add_option("-m", "--mode", help="The test modes in which to run (comma-separated)",
+      default='release')
+  result.add_option("-v", "--verbose", help="Verbose output",
+      default=False, action="store_true")
+  result.add_option("-S", dest="scons_flags", help="Flag to pass through to scons",
+      default=[], action="append")
+  result.add_option("-p", "--progress",
+      help="The style of progress indicator (verbose, dots, color, mono)",
+      choices=PROGRESS_INDICATORS.keys(), default="mono")
+  result.add_option("--no-build", help="Don't build requirements",
+      default=False, action="store_true")
+  result.add_option("--report", help="Print a summary of the tests to be run",
+      default=False, action="store_true")
+  result.add_option("-s", "--suite", help="A test suite",
+      default=[], action="append")
+  result.add_option("-t", "--timeout", help="Timeout in seconds",
+      default=60, type="int")
+  result.add_option("--arch", help='The architecture to run tests for',
+      default='none')
+  result.add_option("--simulator", help="Run tests with architecture simulator",
+      default='none')
+  result.add_option("--special-command", default=None)
+  result.add_option("--valgrind", help="Run tests through valgrind",
+      default=False, action="store_true")
+  result.add_option("--cat", help="Print the source of the tests",
+      default=False, action="store_true")
+  result.add_option("--warn-unused", help="Report unused rules",
+      default=False, action="store_true")
+  result.add_option("-j", help="The number of parallel tasks to run",
+      default=1, type="int")
+  result.add_option("--time", help="Print timing information after running",
+      default=False, action="store_true")
+  result.add_option("--suppress-dialogs", help="Suppress Windows dialogs for crashing tests",
+        dest="suppress_dialogs", default=True, action="store_true")
+  result.add_option("--no-suppress-dialogs", help="Display Windows dialogs for crashing tests",
+        dest="suppress_dialogs", action="store_false")
+  result.add_option("--shell", help="Path to V8 shell", default="shell");
+  return result
+
+
+def ProcessOptions(options):
+  global VERBOSE
+  VERBOSE = options.verbose
+  options.mode = options.mode.split(',')
+  for mode in options.mode:
+    if not mode in ['debug', 'release']:
+      print "Unknown mode %s" % mode
+      return False
+  if options.simulator != 'none':
+    # Simulator argument was set. Make sure arch and simulator agree.
+    if options.simulator != options.arch:
+      if options.arch == 'none':
+        options.arch = options.simulator
+      else:
+        print "Architecture %s does not match sim %s" %(options.arch, options.simulator)
+        return False
+    # Ensure that the simulator argument is handed down to scons.
+    options.scons_flags.append("simulator=" + options.simulator)
+  else:
+    # If options.arch is not set by the command line and no simulator setting
+    # was found, set the arch to the guess.
+    if options.arch == 'none':
+      options.arch = ARCH_GUESS
+  return True
+
+
+REPORT_TEMPLATE = """\
+Total: %(total)i tests
+ * %(skipped)4d tests will be skipped
+ * %(nocrash)4d tests are expected to be flaky but not crash
+ * %(pass)4d tests are expected to pass
+ * %(fail_ok)4d tests are expected to fail that we won't fix
+ * %(fail)4d tests are expected to fail that we should fix\
+"""
+
+def PrintReport(cases):
+  def IsFlaky(o):
+    return (PASS in o) and (FAIL in o) and (not CRASH in o) and (not OKAY in o)
+  def IsFailOk(o):
+    return (len(o) == 2) and (FAIL in o) and (OKAY in o)
+  unskipped = [c for c in cases if not SKIP in c.outcomes]
+  print REPORT_TEMPLATE % {
+    'total': len(cases),
+    'skipped': len(cases) - len(unskipped),
+    'nocrash': len([t for t in unskipped if IsFlaky(t.outcomes)]),
+    'pass': len([t for t in unskipped if list(t.outcomes) == [PASS]]),
+    'fail_ok': len([t for t in unskipped if IsFailOk(t.outcomes)]),
+    'fail': len([t for t in unskipped if list(t.outcomes) == [FAIL]])
+  }
+
+
+class Pattern(object):
+
+  def __init__(self, pattern):
+    self.pattern = pattern
+    self.compiled = None
+
+  def match(self, str):
+    if not self.compiled:
+      pattern = "^" + self.pattern.replace('*', '.*') + "$"
+      self.compiled = re.compile(pattern)
+    return self.compiled.match(str)
+
+  def __str__(self):
+    return self.pattern
+
+
+def SplitPath(s):
+  stripped = [ c.strip() for c in s.split('/') ]
+  return [ Pattern(s) for s in stripped if len(s) > 0 ]
+
+
+def GetSpecialCommandProcessor(value):
+  if (not value) or (value.find('@') == -1):
+    def ExpandCommand(args):
+      return args
+    return ExpandCommand
+  else:
+    pos = value.find('@')
+    import urllib
+    prefix = urllib.unquote(value[:pos]).split()
+    suffix = urllib.unquote(value[pos+1:]).split()
+    def ExpandCommand(args):
+      return prefix + args + suffix
+    return ExpandCommand
+
+
+BUILT_IN_TESTS = ['mjsunit', 'cctest', 'message']
+
+
+def GetSuites(test_root):
+  def IsSuite(path):
+    return isdir(path) and exists(join(path, 'testcfg.py'))
+  return [ f for f in os.listdir(test_root) if IsSuite(join(test_root, f)) ]
+
+
+def FormatTime(d):
+  millis = round(d * 1000) % 1000
+  return time.strftime("%M:%S.", time.gmtime(d)) + ("%03i" % millis)
+
+
+def Main():
+  parser = BuildOptions()
+  (options, args) = parser.parse_args()
+  if not ProcessOptions(options):
+    parser.print_help()
+    return 1
+
+  workspace = abspath(join(dirname(sys.argv[0]), '..'))
+  suites = GetSuites(join(workspace, 'test'))
+  repositories = [TestRepository(join(workspace, 'test', name)) for name in suites]
+  repositories += [TestRepository(a) for a in options.suite]
+
+  root = LiteralTestSuite(repositories)
+  if len(args) == 0:
+    paths = [SplitPath(t) for t in BUILT_IN_TESTS]
+  else:
+    paths = [ ]
+    for arg in args:
+      path = SplitPath(arg)
+      paths.append(path)
+
+  # Check for --valgrind option. If enabled, we overwrite the special
+  # command flag with a command that uses the run-valgrind.py script.
+  if options.valgrind:
+    run_valgrind = join(workspace, "tools", "run-valgrind.py")
+    options.special_command = "python -u " + run_valgrind + " @"
+
+  shell = abspath(options.shell)
+  buildspace = dirname(shell)
+  context = Context(workspace, buildspace, VERBOSE,
+                    shell,
+                    options.timeout,
+                    GetSpecialCommandProcessor(options.special_command),
+                    options.suppress_dialogs)
+  # First build the required targets
+  if not options.no_build:
+    reqs = [ ]
+    for path in paths:
+      reqs += root.GetBuildRequirements(path, context)
+    reqs = list(set(reqs))
+    if len(reqs) > 0:
+      if options.j != 1:
+        options.scons_flags += ['-j', str(options.j)]
+      if not BuildRequirements(context, reqs, options.mode, options.scons_flags):
+        return 1
+
+  # Get status for tests
+  sections = [ ]
+  defs = { }
+  root.GetTestStatus(context, sections, defs)
+  config = Configuration(sections, defs)
+
+  # List the tests
+  all_cases = [ ]
+  all_unused = [ ]
+  unclassified_tests = [ ]
+  globally_unused_rules = None
+  for path in paths:
+    for mode in options.mode:
+      if not exists(context.GetVm(mode)):
+        print "Can't find shell executable: '%s'" % context.GetVm(mode)
+        continue
+      env = {
+        'mode': mode,
+        'system': utils.GuessOS(),
+        'arch': options.arch,
+        'simulator': options.simulator
+      }
+      test_list = root.ListTests([], path, context, mode)
+      unclassified_tests += test_list
+      (cases, unused_rules, all_outcomes) = config.ClassifyTests(test_list, env)
+      if globally_unused_rules is None:
+        globally_unused_rules = set(unused_rules)
+      else:
+        globally_unused_rules = globally_unused_rules.intersection(unused_rules)
+      all_cases += cases
+      all_unused.append(unused_rules)
+
+  if options.cat:
+    visited = set()
+    for test in unclassified_tests:
+      key = tuple(test.path)
+      if key in visited:
+        continue
+      visited.add(key)
+      print "--- begin source: %s ---" % test.GetLabel()
+      source = test.GetSource().strip()
+      print source
+      print "--- end source: %s ---" % test.GetLabel()
+    return 0
+
+  if options.warn_unused:
+    for rule in globally_unused_rules:
+      print "Rule for '%s' was not used." % '/'.join([str(s) for s in rule.path])
+
+  if options.report:
+    PrintReport(all_cases)
+
+  result = None
+  if len(all_cases) == 0:
+    print "No tests to run."
+    return 0
+  else:
+    try:
+      start = time.time()
+      if RunTestCases(all_cases, options.progress, options.j):
+        result = 0
+      else:
+        result = 1
+      duration = time.time() - start
+    except KeyboardInterrupt:
+      print "Interrupted"
+      return 1
+
+  if options.time:
+    # Write the times to stderr to make it easy to separate from the
+    # test output.
+    print
+    sys.stderr.write("--- Total time: %s ---\n" % FormatTime(duration))
+    timed_tests = [ t.case for t in all_cases if not t.case.duration is None ]
+    timed_tests.sort(lambda a, b: a.CompareTime(b))
+    index = 1
+    for entry in timed_tests[:20]:
+      t = FormatTime(entry.duration)
+      sys.stderr.write("%4i (%s) %s\n" % (index, t, entry.GetLabel()))
+      index += 1
+
+  return result
+
+
+if __name__ == '__main__':
+  sys.exit(Main())
diff --git a/deps/v8/tools/tickprocessor.py b/deps/v8/tools/tickprocessor.py
new file mode 100644
index 0000000..95e6e50
--- /dev/null
+++ b/deps/v8/tools/tickprocessor.py
@@ -0,0 +1,535 @@
+# Copyright 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.
+
+import csv, splaytree, sys, re
+from operator import itemgetter
+import getopt, os, string
+
+class CodeEntry(object):
+
+  def __init__(self, start_addr, name):
+    self.start_addr = start_addr
+    self.tick_count = 0
+    self.name = name
+    self.stacks = {}
+
+  def Tick(self, pc, stack):
+    self.tick_count += 1
+    if len(stack) > 0:
+      stack.insert(0, self.ToString())
+      stack_key = tuple(stack)
+      self.stacks[stack_key] = self.stacks.setdefault(stack_key, 0) + 1
+
+  def RegionTicks(self):
+    return None
+
+  def SetStartAddress(self, start_addr):
+    self.start_addr = start_addr
+
+  def ToString(self):
+    return self.name
+
+  def IsSharedLibraryEntry(self):
+    return False
+
+  def IsICEntry(self):
+    return False
+
+
+class SharedLibraryEntry(CodeEntry):
+
+  def __init__(self, start_addr, name):
+    CodeEntry.__init__(self, start_addr, name)
+
+  def IsSharedLibraryEntry(self):
+    return True
+
+
+class JSCodeEntry(CodeEntry):
+
+  def __init__(self, start_addr, name, type, size, assembler):
+    CodeEntry.__init__(self, start_addr, name)
+    self.type = type
+    self.size = size
+    self.assembler = assembler
+    self.region_ticks = None
+    self.builtin_ic_re = re.compile('^(Keyed)?(Call|Load|Store)IC_')
+
+  def Tick(self, pc, stack):
+    super(JSCodeEntry, self).Tick(pc, stack)
+    if not pc is None:
+      offset = pc - self.start_addr
+      seen = []
+      narrowest = None
+      narrowest_width = None
+      for region in self.Regions():
+        if region.Contains(offset):
+          if (not region.name in seen):
+            seen.append(region.name)
+          if narrowest is None or region.Width() < narrowest.Width():
+            narrowest = region
+      if len(seen) == 0:
+        return
+      if self.region_ticks is None:
+        self.region_ticks = {}
+      for name in seen:
+        if not name in self.region_ticks:
+          self.region_ticks[name] = [0, 0]
+        self.region_ticks[name][0] += 1
+        if name == narrowest.name:
+          self.region_ticks[name][1] += 1
+
+  def RegionTicks(self):
+    return self.region_ticks
+
+  def Regions(self):
+    if self.assembler:
+      return self.assembler.regions
+    else:
+      return []
+
+  def ToString(self):
+    name = self.name
+    if name == '':
+      name = '<anonymous>'
+    elif name.startswith(' '):
+      name = '<anonymous>' + name
+    return self.type + ': ' + name
+
+  def IsICEntry(self):
+    return self.type in ('CallIC', 'LoadIC', 'StoreIC') or \
+      (self.type == 'Builtin' and self.builtin_ic_re.match(self.name))
+
+
+class CodeRegion(object):
+
+  def __init__(self, start_offset, name):
+    self.start_offset = start_offset
+    self.name = name
+    self.end_offset = None
+
+  def Contains(self, pc):
+    return (self.start_offset <= pc) and (pc <= self.end_offset)
+
+  def Width(self):
+    return self.end_offset - self.start_offset
+
+
+class Assembler(object):
+
+  def __init__(self):
+    # Mapping from region ids to open regions
+    self.pending_regions = {}
+    self.regions = []
+
+
+class FunctionEnumerator(object):
+
+  def __init__(self):
+    self.known_funcs = {}
+    self.next_func_id = 0
+
+  def GetFunctionId(self, name):
+    if not self.known_funcs.has_key(name):
+      self.known_funcs[name] = self.next_func_id
+      self.next_func_id += 1
+    return self.known_funcs[name]
+
+  def GetKnownFunctions(self):
+    known_funcs_items = self.known_funcs.items();
+    known_funcs_items.sort(key = itemgetter(1))
+    result = []
+    for func, id_not_used in known_funcs_items:
+      result.append(func)
+    return result
+
+
+VMStates = { 'JS': 0, 'GC': 1, 'COMPILER': 2, 'OTHER': 3, 'EXTERNAL' : 4 }
+
+
+class TickProcessor(object):
+
+  def __init__(self):
+    self.log_file = ''
+    self.deleted_code = []
+    self.vm_extent = {}
+    # Map from assembler ids to the pending assembler objects
+    self.pending_assemblers = {}
+    # Map from code addresses the have been allocated but not yet officially
+    # created to their assemblers.
+    self.assemblers = {}
+    self.js_entries = splaytree.SplayTree()
+    self.cpp_entries = splaytree.SplayTree()
+    self.total_number_of_ticks = 0
+    self.number_of_library_ticks = 0
+    self.unaccounted_number_of_ticks = 0
+    self.excluded_number_of_ticks = 0
+    self.number_of_gc_ticks = 0
+    # Flag indicating whether to ignore unaccounted ticks in the report
+    self.ignore_unknown = False
+    self.func_enum = FunctionEnumerator()
+    self.packed_stacks = []
+
+  def ProcessLogfile(self, filename, included_state = None, ignore_unknown = False, separate_ic = False, call_graph_json = False):
+    self.log_file = filename
+    self.included_state = included_state
+    self.ignore_unknown = ignore_unknown
+    self.separate_ic = separate_ic
+    self.call_graph_json = call_graph_json
+
+    try:
+      logfile = open(filename, 'rb')
+    except IOError:
+      sys.exit("Could not open logfile: " + filename)
+    try:
+      try:
+        logreader = csv.reader(logfile)
+        row_num = 1
+        for row in logreader:
+          row_num += 1
+          if row[0] == 'tick':
+            self.ProcessTick(int(row[1], 16), int(row[2], 16), int(row[3]), self.PreprocessStack(row[4:]))
+          elif row[0] == 'code-creation':
+            self.ProcessCodeCreation(row[1], int(row[2], 16), int(row[3]), row[4])
+          elif row[0] == 'code-move':
+            self.ProcessCodeMove(int(row[1], 16), int(row[2], 16))
+          elif row[0] == 'code-delete':
+            self.ProcessCodeDelete(int(row[1], 16))
+          elif row[0] == 'shared-library':
+            self.AddSharedLibraryEntry(row[1], int(row[2], 16), int(row[3], 16))
+            self.ParseVMSymbols(row[1], int(row[2], 16), int(row[3], 16))
+          elif row[0] == 'begin-code-region':
+            self.ProcessBeginCodeRegion(int(row[1], 16), int(row[2], 16), int(row[3], 16), row[4])
+          elif row[0] == 'end-code-region':
+            self.ProcessEndCodeRegion(int(row[1], 16), int(row[2], 16), int(row[3], 16))
+          elif row[0] == 'code-allocate':
+            self.ProcessCodeAllocate(int(row[1], 16), int(row[2], 16))
+      except csv.Error:
+        print("parse error in line " + str(row_num))
+        raise
+    finally:
+      logfile.close()
+
+  def AddSharedLibraryEntry(self, filename, start, end):
+    # Mark the pages used by this library.
+    i = start
+    while i < end:
+      page = i >> 12
+      self.vm_extent[page] = 1
+      i += 4096
+    # Add the library to the entries so that ticks for which we do not
+    # have symbol information is reported as belonging to the library.
+    self.cpp_entries.Insert(start, SharedLibraryEntry(start, filename))
+
+  def ParseVMSymbols(self, filename, start, end):
+    return
+
+  def ProcessCodeAllocate(self, addr, assem):
+    if assem in self.pending_assemblers:
+      assembler = self.pending_assemblers.pop(assem)
+      self.assemblers[addr] = assembler
+
+  def ProcessCodeCreation(self, type, addr, size, name):
+    if addr in self.assemblers:
+      assembler = self.assemblers.pop(addr)
+    else:
+      assembler = None
+    self.js_entries.Insert(addr, JSCodeEntry(addr, name, type, size, assembler))
+
+  def ProcessCodeMove(self, from_addr, to_addr):
+    try:
+      removed_node = self.js_entries.Remove(from_addr)
+      removed_node.value.SetStartAddress(to_addr);
+      self.js_entries.Insert(to_addr, removed_node.value)
+    except splaytree.KeyNotFoundError:
+      print('Code move event for unknown code: 0x%x' % from_addr)
+
+  def ProcessCodeDelete(self, from_addr):
+    try:
+      removed_node = self.js_entries.Remove(from_addr)
+      self.deleted_code.append(removed_node.value)
+    except splaytree.KeyNotFoundError:
+      print('Code delete event for unknown code: 0x%x' % from_addr)
+
+  def ProcessBeginCodeRegion(self, id, assm, start, name):
+    if not assm in self.pending_assemblers:
+      self.pending_assemblers[assm] = Assembler()
+    assembler = self.pending_assemblers[assm]
+    assembler.pending_regions[id] = CodeRegion(start, name)
+
+  def ProcessEndCodeRegion(self, id, assm, end):
+    assm = self.pending_assemblers[assm]
+    region = assm.pending_regions.pop(id)
+    region.end_offset = end
+    assm.regions.append(region)
+
+  def IncludeTick(self, pc, sp, state):
+    return (self.included_state is None) or (self.included_state == state)
+
+  def FindEntry(self, pc):
+    page = pc >> 12
+    if page in self.vm_extent:
+      entry = self.cpp_entries.FindGreatestsLessThan(pc)
+      if entry != None:
+        return entry.value
+      else:
+        return entry
+    max = self.js_entries.FindMax()
+    min = self.js_entries.FindMin()
+    if max != None and pc < (max.key + max.value.size) and pc > min.key:
+      return self.js_entries.FindGreatestsLessThan(pc).value
+    return None
+
+  def PreprocessStack(self, stack):
+    # remove all non-addresses (e.g. 'overflow') and convert to int
+    result = []
+    for frame in stack:
+      if frame.startswith('0x'):
+        result.append(int(frame, 16))
+    return result
+
+  def ProcessStack(self, stack):
+    result = []
+    for frame in stack:
+      entry = self.FindEntry(frame)
+      if entry != None:
+        result.append(entry.ToString())
+    return result
+
+  def ProcessTick(self, pc, sp, state, stack):
+    if state == VMStates['GC']:
+      self.number_of_gc_ticks += 1
+    if not self.IncludeTick(pc, sp, state):
+      self.excluded_number_of_ticks += 1;
+      return
+    self.total_number_of_ticks += 1
+    entry = self.FindEntry(pc)
+    if entry == None:
+      self.unaccounted_number_of_ticks += 1
+      return
+    if entry.IsSharedLibraryEntry():
+      self.number_of_library_ticks += 1
+    if entry.IsICEntry() and not self.separate_ic:
+      if len(stack) > 0:
+        caller_pc = stack.pop(0)
+        self.total_number_of_ticks -= 1
+        self.ProcessTick(caller_pc, sp, state, stack)
+      else:
+        self.unaccounted_number_of_ticks += 1
+    else:
+      entry.Tick(pc, self.ProcessStack(stack))
+      if self.call_graph_json:
+        self.AddToPackedStacks(pc, stack)
+
+  def AddToPackedStacks(self, pc, stack):
+    full_stack = stack
+    full_stack.insert(0, pc)
+    func_names = self.ProcessStack(full_stack)
+    func_ids = []
+    for func in func_names:
+      func_ids.append(self.func_enum.GetFunctionId(func))
+    self.packed_stacks.append(func_ids)
+
+  def PrintResults(self):
+    if not self.call_graph_json:
+      self.PrintStatistics()
+    else:
+      self.PrintCallGraphJSON()
+
+  def PrintStatistics(self):
+    print('Statistical profiling result from %s, (%d ticks, %d unaccounted, %d excluded).' %
+          (self.log_file,
+           self.total_number_of_ticks,
+           self.unaccounted_number_of_ticks,
+           self.excluded_number_of_ticks))
+    if self.total_number_of_ticks > 0:
+      js_entries = self.js_entries.ExportValueList()
+      js_entries.extend(self.deleted_code)
+      cpp_entries = self.cpp_entries.ExportValueList()
+      # Print the unknown ticks percentage if they are not ignored.
+      if not self.ignore_unknown and self.unaccounted_number_of_ticks > 0:
+        self.PrintHeader('Unknown')
+        self.PrintCounter(self.unaccounted_number_of_ticks)
+      # Print the library ticks.
+      self.PrintHeader('Shared libraries')
+      self.PrintEntries(cpp_entries, lambda e:e.IsSharedLibraryEntry())
+      # Print the JavaScript ticks.
+      self.PrintHeader('JavaScript')
+      self.PrintEntries(js_entries, lambda e:not e.IsSharedLibraryEntry())
+      # Print the C++ ticks.
+      self.PrintHeader('C++')
+      self.PrintEntries(cpp_entries, lambda e:not e.IsSharedLibraryEntry())
+      # Print the GC ticks.
+      self.PrintHeader('GC')
+      self.PrintCounter(self.number_of_gc_ticks)
+      # Print call profile.
+      print('\n [Call profile]:')
+      print('   total  call path')
+      js_entries.extend(cpp_entries)
+      self.PrintCallProfile(js_entries)
+
+  def PrintHeader(self, header_title):
+    print('\n [%s]:' % header_title)
+    print('   ticks  total  nonlib   name')
+
+  def PrintCounter(self, ticks_count):
+    percentage = ticks_count * 100.0 / self.total_number_of_ticks
+    print('  %(ticks)5d  %(total)5.1f%%' % {
+      'ticks' : ticks_count,
+      'total' : percentage,
+    })
+
+  def PrintEntries(self, entries, condition):
+    # If ignoring unaccounted ticks don't include these in percentage
+    # calculations
+    number_of_accounted_ticks = self.total_number_of_ticks
+    if self.ignore_unknown:
+      number_of_accounted_ticks -= self.unaccounted_number_of_ticks
+
+    number_of_non_library_ticks = number_of_accounted_ticks - self.number_of_library_ticks
+    entries.sort(key=lambda e:e.tick_count, reverse=True)
+    for entry in entries:
+      if entry.tick_count > 0 and condition(entry):
+        total_percentage = entry.tick_count * 100.0 / number_of_accounted_ticks
+        if entry.IsSharedLibraryEntry():
+          non_library_percentage = 0
+        else:
+          non_library_percentage = entry.tick_count * 100.0 / number_of_non_library_ticks
+        print('  %(ticks)5d  %(total)5.1f%% %(nonlib)6.1f%%  %(name)s' % {
+          'ticks' : entry.tick_count,
+          'total' : total_percentage,
+          'nonlib' : non_library_percentage,
+          'name' : entry.ToString()
+        })
+        region_ticks = entry.RegionTicks()
+        if not region_ticks is None:
+          items = region_ticks.items()
+          items.sort(key=lambda e: e[1][1], reverse=True)
+          for (name, ticks) in items:
+            print('                      flat   cum')
+            print('                     %(flat)5.1f%% %(accum)5.1f%% %(name)s' % {
+              'flat' : ticks[1] * 100.0 / entry.tick_count,
+              'accum' : ticks[0] * 100.0 / entry.tick_count,
+              'name': name
+            })
+
+  def PrintCallProfile(self, entries):
+    all_stacks = {}
+    total_stacks = 0
+    for entry in entries:
+      all_stacks.update(entry.stacks)
+      for count in entry.stacks.itervalues():
+        total_stacks += count
+    all_stacks_items = all_stacks.items();
+    all_stacks_items.sort(key = itemgetter(1), reverse=True)
+    missing_percentage = (self.total_number_of_ticks - total_stacks) * 100.0 / self.total_number_of_ticks
+    print('  %(ticks)5d  %(total)5.1f%%  <no call path information>' % {
+      'ticks' : self.total_number_of_ticks - total_stacks,
+      'total' : missing_percentage
+    })
+    for stack, count in all_stacks_items:
+      total_percentage = count * 100.0 / self.total_number_of_ticks
+      print('  %(ticks)5d  %(total)5.1f%%  %(call_path)s' % {
+        'ticks' : count,
+        'total' : total_percentage,
+        'call_path' : stack[0] + '  <-  ' + stack[1]
+      })
+
+  def PrintCallGraphJSON(self):
+    print('\nvar __profile_funcs = ["' +
+          '",\n"'.join(self.func_enum.GetKnownFunctions()) +
+          '"];')
+    print('var __profile_ticks = [')
+    str_packed_stacks = []
+    for stack in self.packed_stacks:
+      str_packed_stacks.append('[' + ','.join(map(str, stack)) + ']')
+    print(',\n'.join(str_packed_stacks))
+    print('];')
+
+class CmdLineProcessor(object):
+
+  def __init__(self):
+    self.options = ["js",
+                    "gc",
+                    "compiler",
+                    "other",
+                    "external",
+                    "ignore-unknown",
+                    "separate-ic",
+                    "call-graph-json"]
+    # default values
+    self.state = None
+    self.ignore_unknown = False
+    self.log_file = None
+    self.separate_ic = False
+    self.call_graph_json = False
+
+  def ProcessArguments(self):
+    try:
+      opts, args = getopt.getopt(sys.argv[1:], "jgcoe", self.options)
+    except getopt.GetoptError:
+      self.PrintUsageAndExit()
+    for key, value in opts:
+      if key in ("-j", "--js"):
+        self.state = VMStates['JS']
+      if key in ("-g", "--gc"):
+        self.state = VMStates['GC']
+      if key in ("-c", "--compiler"):
+        self.state = VMStates['COMPILER']
+      if key in ("-o", "--other"):
+        self.state = VMStates['OTHER']
+      if key in ("-e", "--external"):
+        self.state = VMStates['EXTERNAL']
+      if key in ("--ignore-unknown"):
+        self.ignore_unknown = True
+      if key in ("--separate-ic"):
+        self.separate_ic = True
+      if key in ("--call-graph-json"):
+        self.call_graph_json = True
+    self.ProcessRequiredArgs(args)
+
+  def ProcessRequiredArgs(self, args):
+    return
+
+  def GetRequiredArgsNames(self):
+    return
+
+  def PrintUsageAndExit(self):
+    print('Usage: %(script_name)s --{%(opts)s} %(req_opts)s' % {
+        'script_name': os.path.basename(sys.argv[0]),
+        'opts': string.join(self.options, ','),
+        'req_opts': self.GetRequiredArgsNames()
+    })
+    sys.exit(2)
+
+  def RunLogfileProcessing(self, tick_processor):
+    tick_processor.ProcessLogfile(self.log_file, self.state, self.ignore_unknown,
+                                  self.separate_ic, self.call_graph_json)
+
+
+if __name__ == '__main__':
+  sys.exit('You probably want to run windows-tick-processor.py or linux-tick-processor.py.')
diff --git a/deps/v8/tools/utils.py b/deps/v8/tools/utils.py
new file mode 100644
index 0000000..78d1e0d
--- /dev/null
+++ b/deps/v8/tools/utils.py
@@ -0,0 +1,80 @@
+# Copyright 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.
+
+
+import platform
+import re
+
+
+# Reads a .list file into an array of strings
+def ReadLinesFrom(name):
+  list = []
+  for line in open(name):
+    if '#' in line:
+      line = line[:line.find('#')]
+    line = line.strip()
+    if len(line) == 0:
+      continue
+    list.append(line)
+  return list
+
+
+def GuessOS():
+  id = platform.system()
+  if id == 'Linux':
+    return 'linux'
+  elif id == 'Darwin':
+    return 'macos'
+  elif id == 'Windows' or id == 'Microsoft':
+    # On Windows Vista platform.system() can return 'Microsoft' with some
+    # versions of Python, see http://bugs.python.org/issue1082
+    return 'win32'
+  elif id == 'FreeBSD':
+    return 'freebsd'
+  else:
+    return None
+
+
+def GuessArchitecture():
+  id = platform.machine()
+  if id.startswith('arm'):
+    return 'arm'
+  elif (not id) or (not re.match('(x|i[3-6])86', id) is None):
+    return 'ia32'
+  else:
+    return None
+
+
+def GuessWordsize():
+  if '64' in platform.machine():
+    return '64'
+  else:
+    return '32'
+
+
+def IsWindows():
+  return GuessOS() == 'win32'
diff --git a/deps/v8/tools/v8.xcodeproj/project.pbxproj b/deps/v8/tools/v8.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..eba4ec7
--- /dev/null
+++ b/deps/v8/tools/v8.xcodeproj/project.pbxproj
@@ -0,0 +1,1598 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 45;
+	objects = {
+
+/* Begin PBXAggregateTarget section */
+		7BF891930E73098D000BAF8A /* All */ = {
+			isa = PBXAggregateTarget;
+			buildConfigurationList = 7BF8919F0E7309BE000BAF8A /* Build configuration list for PBXAggregateTarget "All" */;
+			buildPhases = (
+			);
+			dependencies = (
+				7BF891970E73099F000BAF8A /* PBXTargetDependency */,
+				7BF891990E73099F000BAF8A /* PBXTargetDependency */,
+				893988100F2A3647007D5254 /* PBXTargetDependency */,
+				896FD03E0E78D731003DFB6A /* PBXTargetDependency */,
+				896FD0400E78D735003DFB6A /* PBXTargetDependency */,
+			);
+			name = All;
+			productName = All;
+		};
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+		58950D5E0F55519800F3E8BA /* jump-target.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D500F55514900F3E8BA /* jump-target.cc */; };
+		58950D5F0F55519D00F3E8BA /* jump-target-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D4F0F55514900F3E8BA /* jump-target-ia32.cc */; };
+		58950D600F5551A300F3E8BA /* jump-target.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D500F55514900F3E8BA /* jump-target.cc */; };
+		58950D610F5551A400F3E8BA /* jump-target-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D4E0F55514900F3E8BA /* jump-target-arm.cc */; };
+		58950D620F5551AF00F3E8BA /* register-allocator-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D530F55514900F3E8BA /* register-allocator-ia32.cc */; };
+		58950D630F5551AF00F3E8BA /* register-allocator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D540F55514900F3E8BA /* register-allocator.cc */; };
+		58950D640F5551B500F3E8BA /* register-allocator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D540F55514900F3E8BA /* register-allocator.cc */; };
+		58950D650F5551B600F3E8BA /* register-allocator-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D520F55514900F3E8BA /* register-allocator-arm.cc */; };
+		58950D660F5551C200F3E8BA /* virtual-frame.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D5A0F55514900F3E8BA /* virtual-frame.cc */; };
+		58950D670F5551C400F3E8BA /* virtual-frame-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D580F55514900F3E8BA /* virtual-frame-ia32.cc */; };
+		58950D680F5551CB00F3E8BA /* virtual-frame.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D5A0F55514900F3E8BA /* virtual-frame.cc */; };
+		58950D690F5551CE00F3E8BA /* virtual-frame-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D560F55514900F3E8BA /* virtual-frame-arm.cc */; };
+		8900116C0E71CA2300F91F35 /* libraries.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8900116B0E71CA2300F91F35 /* libraries.cc */; };
+		890A13FE0EE9C47F00E49346 /* interpreter-irregexp.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89A15C660EE4665300B48DEB /* interpreter-irregexp.cc */; };
+		890A14010EE9C4B000E49346 /* regexp-macro-assembler-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89A15C700EE466D000B48DEB /* regexp-macro-assembler-arm.cc */; };
+		890A14020EE9C4B400E49346 /* regexp-macro-assembler-irregexp.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89A15C750EE466D000B48DEB /* regexp-macro-assembler-irregexp.cc */; };
+		890A14030EE9C4B500E49346 /* regexp-macro-assembler-tracer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89A15C770EE466D000B48DEB /* regexp-macro-assembler-tracer.cc */; };
+		890A14040EE9C4B700E49346 /* regexp-macro-assembler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89A15C790EE466D000B48DEB /* regexp-macro-assembler.cc */; };
+		893988070F2A35FA007D5254 /* libv8.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8970F2F00E719FB2006AE7B5 /* libv8.a */; };
+		8939880D0F2A362A007D5254 /* d8.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89A15C920EE46A1700B48DEB /* d8.cc */; };
+		893988160F2A3688007D5254 /* d8-debug.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893988150F2A3686007D5254 /* d8-debug.cc */; };
+		893988330F2A3B8F007D5254 /* d8-js.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893988320F2A3B8B007D5254 /* d8-js.cc */; };
+		893A72240F7B101400303DD2 /* platform-posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893A72230F7B0FF200303DD2 /* platform-posix.cc */; };
+		893A72250F7B101B00303DD2 /* platform-posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893A72230F7B0FF200303DD2 /* platform-posix.cc */; };
+		893CCE640E71D83700357A03 /* code-stubs.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1110E719B8F00D62E90 /* code-stubs.cc */; };
+		8944AD100F1D4D500028D560 /* regexp-stack.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8944AD0E0F1D4D3A0028D560 /* regexp-stack.cc */; };
+		8944AD110F1D4D570028D560 /* regexp-stack.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8944AD0E0F1D4D3A0028D560 /* regexp-stack.cc */; };
+		894599A30F5D8729008DA8FB /* debug-agent.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8956B6CD0F5D86570033B5A2 /* debug-agent.cc */; };
+		89495E480E79FC23001F68C3 /* compilation-cache.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89495E460E79FC23001F68C3 /* compilation-cache.cc */; };
+		89495E490E79FC23001F68C3 /* compilation-cache.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89495E460E79FC23001F68C3 /* compilation-cache.cc */; };
+		8956B6CF0F5D86730033B5A2 /* debug-agent.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8956B6CD0F5D86570033B5A2 /* debug-agent.cc */; };
+		896FD03A0E78D717003DFB6A /* libv8-arm.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 89F23C870E78D5B2006B2466 /* libv8-arm.a */; };
+		897F767F0E71B690007ACF34 /* shell.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1B50E719C0900D62E90 /* shell.cc */; };
+		897F76850E71B6B1007ACF34 /* libv8.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8970F2F00E719FB2006AE7B5 /* libv8.a */; };
+		898BD20E0EF6CC930068B00A /* debug-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 898BD20D0EF6CC850068B00A /* debug-ia32.cc */; };
+		898BD20F0EF6CC9A0068B00A /* debug-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 898BD20C0EF6CC850068B00A /* debug-arm.cc */; };
+		89A15C7B0EE466EB00B48DEB /* regexp-macro-assembler-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89A15C720EE466D000B48DEB /* regexp-macro-assembler-ia32.cc */; };
+		89A15C810EE4674900B48DEB /* regexp-macro-assembler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89A15C790EE466D000B48DEB /* regexp-macro-assembler.cc */; };
+		89A15C830EE4675E00B48DEB /* regexp-macro-assembler-irregexp.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89A15C750EE466D000B48DEB /* regexp-macro-assembler-irregexp.cc */; };
+		89A15C850EE4678B00B48DEB /* interpreter-irregexp.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89A15C660EE4665300B48DEB /* interpreter-irregexp.cc */; };
+		89A15C8A0EE467D100B48DEB /* regexp-macro-assembler-tracer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89A15C770EE466D000B48DEB /* regexp-macro-assembler-tracer.cc */; };
+		89A88DEC0E71A5FF0043BA31 /* accessors.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF0F60E719B8F00D62E90 /* accessors.cc */; };
+		89A88DED0E71A6000043BA31 /* allocation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF0F80E719B8F00D62E90 /* allocation.cc */; };
+		89A88DEE0E71A6010043BA31 /* api.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF0FA0E719B8F00D62E90 /* api.cc */; };
+		89A88DEF0E71A60A0043BA31 /* assembler-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1010E719B8F00D62E90 /* assembler-ia32.cc */; };
+		89A88DF00E71A60A0043BA31 /* assembler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1030E719B8F00D62E90 /* assembler.cc */; };
+		89A88DF10E71A60B0043BA31 /* ast.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1050E719B8F00D62E90 /* ast.cc */; };
+		89A88DF20E71A60C0043BA31 /* bootstrapper.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1070E719B8F00D62E90 /* bootstrapper.cc */; };
+		89A88DF40E71A6160043BA31 /* builtins-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF10A0E719B8F00D62E90 /* builtins-ia32.cc */; };
+		89A88DF50E71A6170043BA31 /* builtins.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF10B0E719B8F00D62E90 /* builtins.cc */; };
+		89A88DF60E71A61C0043BA31 /* checks.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF10F0E719B8F00D62E90 /* checks.cc */; };
+		89A88DF70E71A6240043BA31 /* codegen-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1150E719B8F00D62E90 /* codegen-ia32.cc */; };
+		89A88DF80E71A6260043BA31 /* codegen.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1170E719B8F00D62E90 /* codegen.cc */; };
+		89A88DF90E71A6430043BA31 /* compiler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1190E719B8F00D62E90 /* compiler.cc */; };
+		89A88DFA0E71A6440043BA31 /* contexts.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF11C0E719B8F00D62E90 /* contexts.cc */; };
+		89A88DFB0E71A6440043BA31 /* conversions.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF11F0E719B8F00D62E90 /* conversions.cc */; };
+		89A88DFC0E71A6460043BA31 /* counters.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1210E719B8F00D62E90 /* counters.cc */; };
+		89A88DFD0E71A6470043BA31 /* cpu-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1240E719B8F00D62E90 /* cpu-ia32.cc */; };
+		89A88DFE0E71A6480043BA31 /* dateparser.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1260E719B8F00D62E90 /* dateparser.cc */; };
+		89A88DFF0E71A6530043BA31 /* debug.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1280E719B8F00D62E90 /* debug.cc */; };
+		89A88E000E71A6540043BA31 /* disasm-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF12B0E719B8F00D62E90 /* disasm-ia32.cc */; };
+		89A88E010E71A6550043BA31 /* disassembler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF12D0E719B8F00D62E90 /* disassembler.cc */; };
+		89A88E020E71A65A0043BA31 /* dtoa-config.c in Sources */ = {isa = PBXBuildFile; fileRef = 897FF12F0E719B8F00D62E90 /* dtoa-config.c */; };
+		89A88E030E71A65B0043BA31 /* execution.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1300E719B8F00D62E90 /* execution.cc */; };
+		89A88E040E71A65D0043BA31 /* factory.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1320E719B8F00D62E90 /* factory.cc */; };
+		89A88E050E71A65D0043BA31 /* flags.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1350E719B8F00D62E90 /* flags.cc */; };
+		89A88E060E71A6600043BA31 /* frames-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1390E719B8F00D62E90 /* frames-ia32.cc */; };
+		89A88E070E71A6610043BA31 /* frames.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF13C0E719B8F00D62E90 /* frames.cc */; };
+		89A88E080E71A6620043BA31 /* global-handles.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF13E0E719B8F00D62E90 /* global-handles.cc */; };
+		89A88E090E71A6640043BA31 /* handles.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1420E719B8F00D62E90 /* handles.cc */; };
+		89A88E0A0E71A6650043BA31 /* hashmap.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1440E719B8F00D62E90 /* hashmap.cc */; };
+		89A88E0B0E71A66C0043BA31 /* heap.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1470E719B8F00D62E90 /* heap.cc */; };
+		89A88E0C0E71A66D0043BA31 /* ic-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF14A0E719B8F00D62E90 /* ic-ia32.cc */; };
+		89A88E0D0E71A66E0043BA31 /* ic.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF14C0E719B8F00D62E90 /* ic.cc */; };
+		89A88E0E0E71A66F0043BA31 /* jsregexp.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF14E0E719B8F00D62E90 /* jsregexp.cc */; };
+		89A88E0F0E71A6740043BA31 /* log.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1520E719B8F00D62E90 /* log.cc */; };
+		89A88E100E71A6770043BA31 /* macro-assembler-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1560E719B8F00D62E90 /* macro-assembler-ia32.cc */; };
+		89A88E110E71A6780043BA31 /* mark-compact.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1590E719B8F00D62E90 /* mark-compact.cc */; };
+		89A88E120E71A67A0043BA31 /* messages.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF15C0E719B8F00D62E90 /* messages.cc */; };
+		89A88E130E71A6860043BA31 /* objects-debug.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1600E719B8F00D62E90 /* objects-debug.cc */; };
+		89A88E140E71A6870043BA31 /* objects.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1620E719B8F00D62E90 /* objects.cc */; };
+		89A88E150E71A68C0043BA31 /* parser.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1640E719B8F00D62E90 /* parser.cc */; };
+		89A88E160E71A68E0043BA31 /* platform-macos.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1670E719B8F00D62E90 /* platform-macos.cc */; };
+		89A88E170E71A6950043BA31 /* prettyprinter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF16B0E719B8F00D62E90 /* prettyprinter.cc */; };
+		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.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 */; };
+		89A88E1E0E71A6A30043BA31 /* serialize.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF17A0E719B8F00D62E90 /* serialize.cc */; };
+		89A88E1F0E71A6B40043BA31 /* snapshot-common.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1820E719B8F00D62E90 /* snapshot-common.cc */; };
+		89A88E200E71A6B60043BA31 /* snapshot-empty.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1830E719B8F00D62E90 /* snapshot-empty.cc */; };
+		89A88E210E71A6B70043BA31 /* spaces.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1860E719B8F00D62E90 /* spaces.cc */; };
+		89A88E220E71A6BC0043BA31 /* string-stream.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1880E719B8F00D62E90 /* string-stream.cc */; };
+		89A88E230E71A6BE0043BA31 /* stub-cache-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF18B0E719B8F00D62E90 /* stub-cache-ia32.cc */; };
+		89A88E240E71A6BF0043BA31 /* stub-cache.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF18C0E719B8F00D62E90 /* stub-cache.cc */; };
+		89A88E250E71A6C20043BA31 /* token.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF18E0E719B8F00D62E90 /* token.cc */; };
+		89A88E260E71A6C90043BA31 /* top.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1900E719B8F00D62E90 /* top.cc */; };
+		89A88E270E71A6CB0043BA31 /* unicode.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1930E719B8F00D62E90 /* unicode.cc */; };
+		89A88E280E71A6CC0043BA31 /* usage-analyzer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1950E719B8F00D62E90 /* usage-analyzer.cc */; };
+		89A88E290E71A6CE0043BA31 /* utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1970E719B8F00D62E90 /* utils.cc */; };
+		89A88E2A0E71A6D00043BA31 /* v8-counters.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1990E719B8F00D62E90 /* v8-counters.cc */; };
+		89A88E2B0E71A6D10043BA31 /* v8.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF19B0E719B8F00D62E90 /* v8.cc */; };
+		89A88E2C0E71A6D20043BA31 /* v8threads.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF19D0E719B8F00D62E90 /* v8threads.cc */; };
+		89A88E2D0E71A6D50043BA31 /* variables.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF19F0E719B8F00D62E90 /* variables.cc */; };
+		89A88E2E0E71A6D60043BA31 /* zone.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1A20E719B8F00D62E90 /* zone.cc */; };
+		89F23C3F0E78D5B2006B2466 /* accessors.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF0F60E719B8F00D62E90 /* accessors.cc */; };
+		89F23C400E78D5B2006B2466 /* allocation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF0F80E719B8F00D62E90 /* allocation.cc */; };
+		89F23C410E78D5B2006B2466 /* api.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF0FA0E719B8F00D62E90 /* api.cc */; };
+		89F23C430E78D5B2006B2466 /* assembler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1030E719B8F00D62E90 /* assembler.cc */; };
+		89F23C440E78D5B2006B2466 /* ast.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1050E719B8F00D62E90 /* ast.cc */; };
+		89F23C450E78D5B2006B2466 /* bootstrapper.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1070E719B8F00D62E90 /* bootstrapper.cc */; };
+		89F23C470E78D5B2006B2466 /* builtins.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF10B0E719B8F00D62E90 /* builtins.cc */; };
+		89F23C480E78D5B2006B2466 /* checks.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF10F0E719B8F00D62E90 /* checks.cc */; };
+		89F23C490E78D5B2006B2466 /* code-stubs.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1110E719B8F00D62E90 /* code-stubs.cc */; };
+		89F23C4B0E78D5B2006B2466 /* codegen.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1170E719B8F00D62E90 /* codegen.cc */; };
+		89F23C4C0E78D5B2006B2466 /* compiler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1190E719B8F00D62E90 /* compiler.cc */; };
+		89F23C4D0E78D5B2006B2466 /* contexts.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF11C0E719B8F00D62E90 /* contexts.cc */; };
+		89F23C4E0E78D5B2006B2466 /* conversions.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF11F0E719B8F00D62E90 /* conversions.cc */; };
+		89F23C4F0E78D5B2006B2466 /* counters.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1210E719B8F00D62E90 /* counters.cc */; };
+		89F23C510E78D5B2006B2466 /* dateparser.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1260E719B8F00D62E90 /* dateparser.cc */; };
+		89F23C520E78D5B2006B2466 /* debug.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1280E719B8F00D62E90 /* debug.cc */; };
+		89F23C540E78D5B2006B2466 /* disassembler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF12D0E719B8F00D62E90 /* disassembler.cc */; };
+		89F23C550E78D5B2006B2466 /* dtoa-config.c in Sources */ = {isa = PBXBuildFile; fileRef = 897FF12F0E719B8F00D62E90 /* dtoa-config.c */; };
+		89F23C560E78D5B2006B2466 /* execution.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1300E719B8F00D62E90 /* execution.cc */; };
+		89F23C570E78D5B2006B2466 /* factory.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1320E719B8F00D62E90 /* factory.cc */; };
+		89F23C580E78D5B2006B2466 /* flags.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1350E719B8F00D62E90 /* flags.cc */; };
+		89F23C5A0E78D5B2006B2466 /* frames.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF13C0E719B8F00D62E90 /* frames.cc */; };
+		89F23C5B0E78D5B2006B2466 /* global-handles.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF13E0E719B8F00D62E90 /* global-handles.cc */; };
+		89F23C5C0E78D5B2006B2466 /* handles.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1420E719B8F00D62E90 /* handles.cc */; };
+		89F23C5D0E78D5B2006B2466 /* hashmap.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1440E719B8F00D62E90 /* hashmap.cc */; };
+		89F23C5E0E78D5B2006B2466 /* heap.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1470E719B8F00D62E90 /* heap.cc */; };
+		89F23C600E78D5B2006B2466 /* ic.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF14C0E719B8F00D62E90 /* ic.cc */; };
+		89F23C610E78D5B2006B2466 /* jsregexp.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF14E0E719B8F00D62E90 /* jsregexp.cc */; };
+		89F23C620E78D5B2006B2466 /* libraries.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8900116B0E71CA2300F91F35 /* libraries.cc */; };
+		89F23C630E78D5B2006B2466 /* log.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1520E719B8F00D62E90 /* log.cc */; };
+		89F23C650E78D5B2006B2466 /* mark-compact.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1590E719B8F00D62E90 /* mark-compact.cc */; };
+		89F23C660E78D5B2006B2466 /* messages.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF15C0E719B8F00D62E90 /* messages.cc */; };
+		89F23C670E78D5B2006B2466 /* objects-debug.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1600E719B8F00D62E90 /* objects-debug.cc */; };
+		89F23C680E78D5B2006B2466 /* objects.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1620E719B8F00D62E90 /* objects.cc */; };
+		89F23C690E78D5B2006B2466 /* parser.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1640E719B8F00D62E90 /* parser.cc */; };
+		89F23C6A0E78D5B2006B2466 /* platform-macos.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1670E719B8F00D62E90 /* platform-macos.cc */; };
+		89F23C6B0E78D5B2006B2466 /* prettyprinter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF16B0E719B8F00D62E90 /* prettyprinter.cc */; };
+		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.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 */; };
+		89F23C720E78D5B2006B2466 /* serialize.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF17A0E719B8F00D62E90 /* serialize.cc */; };
+		89F23C730E78D5B2006B2466 /* snapshot-common.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1820E719B8F00D62E90 /* snapshot-common.cc */; };
+		89F23C740E78D5B2006B2466 /* snapshot-empty.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1830E719B8F00D62E90 /* snapshot-empty.cc */; };
+		89F23C750E78D5B2006B2466 /* spaces.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1860E719B8F00D62E90 /* spaces.cc */; };
+		89F23C760E78D5B2006B2466 /* string-stream.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1880E719B8F00D62E90 /* string-stream.cc */; };
+		89F23C780E78D5B2006B2466 /* stub-cache.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF18C0E719B8F00D62E90 /* stub-cache.cc */; };
+		89F23C790E78D5B2006B2466 /* token.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF18E0E719B8F00D62E90 /* token.cc */; };
+		89F23C7A0E78D5B2006B2466 /* top.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1900E719B8F00D62E90 /* top.cc */; };
+		89F23C7B0E78D5B2006B2466 /* unicode.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1930E719B8F00D62E90 /* unicode.cc */; };
+		89F23C7C0E78D5B2006B2466 /* usage-analyzer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1950E719B8F00D62E90 /* usage-analyzer.cc */; };
+		89F23C7D0E78D5B2006B2466 /* utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1970E719B8F00D62E90 /* utils.cc */; };
+		89F23C7E0E78D5B2006B2466 /* v8-counters.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1990E719B8F00D62E90 /* v8-counters.cc */; };
+		89F23C7F0E78D5B2006B2466 /* v8.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF19B0E719B8F00D62E90 /* v8.cc */; };
+		89F23C800E78D5B2006B2466 /* v8threads.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF19D0E719B8F00D62E90 /* v8threads.cc */; };
+		89F23C810E78D5B2006B2466 /* variables.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF19F0E719B8F00D62E90 /* variables.cc */; };
+		89F23C820E78D5B2006B2466 /* zone.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1A20E719B8F00D62E90 /* zone.cc */; };
+		89F23C8E0E78D5B6006B2466 /* shell.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1B50E719C0900D62E90 /* shell.cc */; };
+		89F23C970E78D5E3006B2466 /* assembler-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF0FE0E719B8F00D62E90 /* assembler-arm.cc */; };
+		89F23C980E78D5E7006B2466 /* builtins-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1090E719B8F00D62E90 /* builtins-arm.cc */; };
+		89F23C990E78D5E9006B2466 /* codegen-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1140E719B8F00D62E90 /* codegen-arm.cc */; };
+		89F23C9A0E78D5EC006B2466 /* cpu-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1230E719B8F00D62E90 /* cpu-arm.cc */; };
+		89F23C9B0E78D5EE006B2466 /* disasm-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF12A0E719B8F00D62E90 /* disasm-arm.cc */; };
+		89F23C9C0E78D5F1006B2466 /* frames-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1370E719B8F00D62E90 /* frames-arm.cc */; };
+		89F23C9D0E78D5FB006B2466 /* ic-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1490E719B8F00D62E90 /* ic-arm.cc */; };
+		89F23C9E0E78D5FD006B2466 /* macro-assembler-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1540E719B8F00D62E90 /* macro-assembler-arm.cc */; };
+		89F23C9F0E78D604006B2466 /* simulator-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF17D0E719B8F00D62E90 /* simulator-arm.cc */; };
+		89F23CA00E78D609006B2466 /* stub-cache-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF18A0E719B8F00D62E90 /* stub-cache-arm.cc */; };
+		89FB0E3A0F8E533F00B04B3C /* d8-posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89FB0E360F8E531900B04B3C /* d8-posix.cc */; };
+		9F92FAA90F8F28AD0089F02C /* func-name-inferrer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9F92FAA70F8F28AD0089F02C /* func-name-inferrer.cc */; };
+		9F92FAAA0F8F28AD0089F02C /* func-name-inferrer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9F92FAA70F8F28AD0089F02C /* func-name-inferrer.cc */; };
+		9FC86ABD0F5FEDAC00F22668 /* oprofile-agent.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9FC86ABB0F5FEDAC00F22668 /* oprofile-agent.cc */; };
+		9FC86ABE0F5FEDAC00F22668 /* oprofile-agent.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9FC86ABB0F5FEDAC00F22668 /* oprofile-agent.cc */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+		7BF891960E73099F000BAF8A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 8915B8680E719336009C4E19 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 8970F2EF0E719FB2006AE7B5;
+			remoteInfo = v8;
+		};
+		7BF891980E73099F000BAF8A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 8915B8680E719336009C4E19 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 897F76790E71B4CC007ACF34;
+			remoteInfo = v8_shell;
+		};
+		893988020F2A35FA007D5254 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 8915B8680E719336009C4E19 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 8970F2EF0E719FB2006AE7B5;
+			remoteInfo = v8;
+		};
+		8939880F0F2A3647007D5254 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 8915B8680E719336009C4E19 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 893987FE0F2A35FA007D5254;
+			remoteInfo = d8_shell;
+		};
+		896FD03B0E78D71F003DFB6A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 8915B8680E719336009C4E19 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 89F23C3C0E78D5B2006B2466;
+			remoteInfo = "v8-arm";
+		};
+		896FD03D0E78D731003DFB6A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 8915B8680E719336009C4E19 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 89F23C3C0E78D5B2006B2466;
+			remoteInfo = "v8-arm";
+		};
+		896FD03F0E78D735003DFB6A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 8915B8680E719336009C4E19 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 89F23C880E78D5B6006B2466;
+			remoteInfo = "v8_shell-arm";
+		};
+		897F76820E71B6AC007ACF34 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 8915B8680E719336009C4E19 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 8970F2EF0E719FB2006AE7B5;
+			remoteInfo = v8;
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+		58950D4E0F55514900F3E8BA /* jump-target-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "jump-target-arm.cc"; sourceTree = "<group>"; };
+		58950D4F0F55514900F3E8BA /* jump-target-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "jump-target-ia32.cc"; sourceTree = "<group>"; };
+		58950D500F55514900F3E8BA /* jump-target.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "jump-target.cc"; sourceTree = "<group>"; };
+		58950D510F55514900F3E8BA /* jump-target.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "jump-target.h"; sourceTree = "<group>"; };
+		58950D520F55514900F3E8BA /* register-allocator-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "register-allocator-arm.cc"; sourceTree = "<group>"; };
+		58950D530F55514900F3E8BA /* register-allocator-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "register-allocator-ia32.cc"; sourceTree = "<group>"; };
+		58950D540F55514900F3E8BA /* register-allocator.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "register-allocator.cc"; sourceTree = "<group>"; };
+		58950D550F55514900F3E8BA /* register-allocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "register-allocator.h"; sourceTree = "<group>"; };
+		58950D560F55514900F3E8BA /* virtual-frame-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "virtual-frame-arm.cc"; sourceTree = "<group>"; };
+		58950D570F55514900F3E8BA /* virtual-frame-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "virtual-frame-arm.h"; sourceTree = "<group>"; };
+		58950D580F55514900F3E8BA /* virtual-frame-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "virtual-frame-ia32.cc"; sourceTree = "<group>"; };
+		58950D590F55514900F3E8BA /* virtual-frame-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "virtual-frame-ia32.h"; sourceTree = "<group>"; };
+		58950D5A0F55514900F3E8BA /* virtual-frame.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "virtual-frame.cc"; sourceTree = "<group>"; };
+		58950D5B0F55514900F3E8BA /* virtual-frame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "virtual-frame.h"; sourceTree = "<group>"; };
+		8900116B0E71CA2300F91F35 /* libraries.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = libraries.cc; sourceTree = "<group>"; };
+		893986D40F29020C007D5254 /* apiutils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = apiutils.h; sourceTree = "<group>"; };
+		8939880B0F2A35FA007D5254 /* v8_shell */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = v8_shell; sourceTree = BUILT_PRODUCTS_DIR; };
+		893988150F2A3686007D5254 /* d8-debug.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "d8-debug.cc"; path = "../src/d8-debug.cc"; sourceTree = "<group>"; };
+		893988320F2A3B8B007D5254 /* d8-js.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "d8-js.cc"; sourceTree = "<group>"; };
+		893A72230F7B0FF200303DD2 /* platform-posix.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "platform-posix.cc"; sourceTree = "<group>"; };
+		893A722A0F7B4A3200303DD2 /* dateparser-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "dateparser-inl.h"; sourceTree = "<group>"; };
+		893A722D0F7B4A7100303DD2 /* register-allocator-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "register-allocator-inl.h"; sourceTree = "<group>"; };
+		893A72320F7B4AD700303DD2 /* d8-debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "d8-debug.h"; path = "../src/d8-debug.h"; sourceTree = "<group>"; };
+		8944AD0E0F1D4D3A0028D560 /* regexp-stack.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "regexp-stack.cc"; sourceTree = "<group>"; };
+		8944AD0F0F1D4D3A0028D560 /* regexp-stack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "regexp-stack.h"; sourceTree = "<group>"; };
+		89471C7F0EB23EE400B6874B /* flag-definitions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "flag-definitions.h"; sourceTree = "<group>"; };
+		89495E460E79FC23001F68C3 /* compilation-cache.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "compilation-cache.cc"; sourceTree = "<group>"; };
+		89495E470E79FC23001F68C3 /* compilation-cache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "compilation-cache.h"; sourceTree = "<group>"; };
+		8956B6CD0F5D86570033B5A2 /* debug-agent.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "debug-agent.cc"; sourceTree = "<group>"; };
+		8956B6CE0F5D86570033B5A2 /* debug-agent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "debug-agent.h"; sourceTree = "<group>"; };
+		8964482B0E9C00F700E7C516 /* codegen-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "codegen-ia32.h"; sourceTree = "<group>"; };
+		896448BC0E9D530500E7C516 /* codegen-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "codegen-arm.h"; sourceTree = "<group>"; };
+		8970F2F00E719FB2006AE7B5 /* libv8.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libv8.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		897F767A0E71B4CC007ACF34 /* v8_shell */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = v8_shell; sourceTree = BUILT_PRODUCTS_DIR; };
+		897FF0D40E719A8500D62E90 /* v8-debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "v8-debug.h"; sourceTree = "<group>"; };
+		897FF0D50E719A8500D62E90 /* v8.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = v8.h; sourceTree = "<group>"; };
+		897FF0E00E719B3500D62E90 /* COPYING */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = COPYING; sourceTree = "<group>"; };
+		897FF0E10E719B3500D62E90 /* dtoa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dtoa.c; sourceTree = "<group>"; };
+		897FF0F60E719B8F00D62E90 /* accessors.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = accessors.cc; sourceTree = "<group>"; };
+		897FF0F70E719B8F00D62E90 /* accessors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = accessors.h; sourceTree = "<group>"; };
+		897FF0F80E719B8F00D62E90 /* allocation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = allocation.cc; sourceTree = "<group>"; };
+		897FF0F90E719B8F00D62E90 /* allocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = allocation.h; sourceTree = "<group>"; };
+		897FF0FA0E719B8F00D62E90 /* api.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = api.cc; sourceTree = "<group>"; };
+		897FF0FB0E719B8F00D62E90 /* api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = api.h; sourceTree = "<group>"; };
+		897FF0FC0E719B8F00D62E90 /* arguments.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = arguments.h; sourceTree = "<group>"; };
+		897FF0FD0E719B8F00D62E90 /* assembler-arm-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "assembler-arm-inl.h"; sourceTree = "<group>"; };
+		897FF0FE0E719B8F00D62E90 /* assembler-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "assembler-arm.cc"; sourceTree = "<group>"; };
+		897FF0FF0E719B8F00D62E90 /* assembler-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "assembler-arm.h"; sourceTree = "<group>"; };
+		897FF1000E719B8F00D62E90 /* assembler-ia32-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "assembler-ia32-inl.h"; sourceTree = "<group>"; };
+		897FF1010E719B8F00D62E90 /* assembler-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "assembler-ia32.cc"; sourceTree = "<group>"; };
+		897FF1020E719B8F00D62E90 /* assembler-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "assembler-ia32.h"; sourceTree = "<group>"; };
+		897FF1030E719B8F00D62E90 /* assembler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = assembler.cc; sourceTree = "<group>"; };
+		897FF1040E719B8F00D62E90 /* assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assembler.h; sourceTree = "<group>"; };
+		897FF1050E719B8F00D62E90 /* ast.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ast.cc; sourceTree = "<group>"; };
+		897FF1060E719B8F00D62E90 /* ast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ast.h; sourceTree = "<group>"; };
+		897FF1070E719B8F00D62E90 /* bootstrapper.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bootstrapper.cc; sourceTree = "<group>"; };
+		897FF1080E719B8F00D62E90 /* bootstrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bootstrapper.h; sourceTree = "<group>"; };
+		897FF1090E719B8F00D62E90 /* builtins-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "builtins-arm.cc"; sourceTree = "<group>"; };
+		897FF10A0E719B8F00D62E90 /* builtins-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "builtins-ia32.cc"; sourceTree = "<group>"; };
+		897FF10B0E719B8F00D62E90 /* builtins.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = builtins.cc; sourceTree = "<group>"; };
+		897FF10C0E719B8F00D62E90 /* builtins.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = builtins.h; sourceTree = "<group>"; };
+		897FF10D0E719B8F00D62E90 /* char-predicates-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "char-predicates-inl.h"; sourceTree = "<group>"; };
+		897FF10E0E719B8F00D62E90 /* char-predicates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "char-predicates.h"; sourceTree = "<group>"; };
+		897FF10F0E719B8F00D62E90 /* checks.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = checks.cc; sourceTree = "<group>"; };
+		897FF1100E719B8F00D62E90 /* checks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = checks.h; sourceTree = "<group>"; };
+		897FF1110E719B8F00D62E90 /* code-stubs.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "code-stubs.cc"; sourceTree = "<group>"; };
+		897FF1120E719B8F00D62E90 /* code-stubs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "code-stubs.h"; sourceTree = "<group>"; };
+		897FF1130E719B8F00D62E90 /* code.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = code.h; sourceTree = "<group>"; };
+		897FF1140E719B8F00D62E90 /* codegen-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "codegen-arm.cc"; sourceTree = "<group>"; };
+		897FF1150E719B8F00D62E90 /* codegen-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "codegen-ia32.cc"; sourceTree = "<group>"; };
+		897FF1160E719B8F00D62E90 /* codegen-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "codegen-inl.h"; sourceTree = "<group>"; };
+		897FF1170E719B8F00D62E90 /* codegen.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = codegen.cc; sourceTree = "<group>"; };
+		897FF1180E719B8F00D62E90 /* codegen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = codegen.h; sourceTree = "<group>"; };
+		897FF1190E719B8F00D62E90 /* compiler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = compiler.cc; sourceTree = "<group>"; };
+		897FF11A0E719B8F00D62E90 /* compiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = compiler.h; sourceTree = "<group>"; };
+		897FF11B0E719B8F00D62E90 /* constants-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "constants-arm.h"; sourceTree = "<group>"; };
+		897FF11C0E719B8F00D62E90 /* contexts.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = contexts.cc; sourceTree = "<group>"; };
+		897FF11D0E719B8F00D62E90 /* contexts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = contexts.h; sourceTree = "<group>"; };
+		897FF11E0E719B8F00D62E90 /* conversions-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "conversions-inl.h"; sourceTree = "<group>"; };
+		897FF11F0E719B8F00D62E90 /* conversions.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = conversions.cc; sourceTree = "<group>"; };
+		897FF1200E719B8F00D62E90 /* conversions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = conversions.h; sourceTree = "<group>"; };
+		897FF1210E719B8F00D62E90 /* counters.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = counters.cc; sourceTree = "<group>"; };
+		897FF1220E719B8F00D62E90 /* counters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = counters.h; sourceTree = "<group>"; };
+		897FF1230E719B8F00D62E90 /* cpu-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "cpu-arm.cc"; sourceTree = "<group>"; };
+		897FF1240E719B8F00D62E90 /* cpu-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "cpu-ia32.cc"; sourceTree = "<group>"; };
+		897FF1250E719B8F00D62E90 /* cpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpu.h; sourceTree = "<group>"; };
+		897FF1260E719B8F00D62E90 /* dateparser.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dateparser.cc; sourceTree = "<group>"; };
+		897FF1270E719B8F00D62E90 /* dateparser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dateparser.h; sourceTree = "<group>"; };
+		897FF1280E719B8F00D62E90 /* debug.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug.cc; sourceTree = "<group>"; };
+		897FF1290E719B8F00D62E90 /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = "<group>"; };
+		897FF12A0E719B8F00D62E90 /* disasm-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "disasm-arm.cc"; sourceTree = "<group>"; };
+		897FF12B0E719B8F00D62E90 /* disasm-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "disasm-ia32.cc"; sourceTree = "<group>"; };
+		897FF12C0E719B8F00D62E90 /* disasm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = disasm.h; sourceTree = "<group>"; };
+		897FF12D0E719B8F00D62E90 /* disassembler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = disassembler.cc; sourceTree = "<group>"; };
+		897FF12E0E719B8F00D62E90 /* disassembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = disassembler.h; sourceTree = "<group>"; };
+		897FF12F0E719B8F00D62E90 /* dtoa-config.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "dtoa-config.c"; sourceTree = "<group>"; };
+		897FF1300E719B8F00D62E90 /* execution.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = execution.cc; sourceTree = "<group>"; };
+		897FF1310E719B8F00D62E90 /* execution.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = execution.h; sourceTree = "<group>"; };
+		897FF1320E719B8F00D62E90 /* factory.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = factory.cc; sourceTree = "<group>"; };
+		897FF1330E719B8F00D62E90 /* factory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = factory.h; sourceTree = "<group>"; };
+		897FF1350E719B8F00D62E90 /* flags.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = flags.cc; sourceTree = "<group>"; };
+		897FF1360E719B8F00D62E90 /* flags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = flags.h; sourceTree = "<group>"; };
+		897FF1370E719B8F00D62E90 /* frames-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "frames-arm.cc"; sourceTree = "<group>"; };
+		897FF1380E719B8F00D62E90 /* frames-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "frames-arm.h"; sourceTree = "<group>"; };
+		897FF1390E719B8F00D62E90 /* frames-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "frames-ia32.cc"; sourceTree = "<group>"; };
+		897FF13A0E719B8F00D62E90 /* frames-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "frames-ia32.h"; sourceTree = "<group>"; };
+		897FF13B0E719B8F00D62E90 /* frames-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "frames-inl.h"; sourceTree = "<group>"; };
+		897FF13C0E719B8F00D62E90 /* frames.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = frames.cc; sourceTree = "<group>"; };
+		897FF13D0E719B8F00D62E90 /* frames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = frames.h; sourceTree = "<group>"; };
+		897FF13E0E719B8F00D62E90 /* global-handles.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "global-handles.cc"; sourceTree = "<group>"; };
+		897FF13F0E719B8F00D62E90 /* global-handles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "global-handles.h"; sourceTree = "<group>"; };
+		897FF1400E719B8F00D62E90 /* globals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = globals.h; sourceTree = "<group>"; };
+		897FF1410E719B8F00D62E90 /* handles-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "handles-inl.h"; sourceTree = "<group>"; };
+		897FF1420E719B8F00D62E90 /* handles.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = handles.cc; sourceTree = "<group>"; };
+		897FF1430E719B8F00D62E90 /* handles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = handles.h; sourceTree = "<group>"; };
+		897FF1440E719B8F00D62E90 /* hashmap.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = hashmap.cc; sourceTree = "<group>"; };
+		897FF1450E719B8F00D62E90 /* hashmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hashmap.h; sourceTree = "<group>"; };
+		897FF1460E719B8F00D62E90 /* heap-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "heap-inl.h"; sourceTree = "<group>"; };
+		897FF1470E719B8F00D62E90 /* heap.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = heap.cc; sourceTree = "<group>"; };
+		897FF1480E719B8F00D62E90 /* heap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = heap.h; sourceTree = "<group>"; };
+		897FF1490E719B8F00D62E90 /* ic-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "ic-arm.cc"; sourceTree = "<group>"; };
+		897FF14A0E719B8F00D62E90 /* ic-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "ic-ia32.cc"; sourceTree = "<group>"; };
+		897FF14B0E719B8F00D62E90 /* ic-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ic-inl.h"; sourceTree = "<group>"; };
+		897FF14C0E719B8F00D62E90 /* ic.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ic.cc; sourceTree = "<group>"; };
+		897FF14D0E719B8F00D62E90 /* ic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ic.h; sourceTree = "<group>"; };
+		897FF14E0E719B8F00D62E90 /* jsregexp.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = jsregexp.cc; sourceTree = "<group>"; };
+		897FF14F0E719B8F00D62E90 /* jsregexp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jsregexp.h; sourceTree = "<group>"; };
+		897FF1500E719B8F00D62E90 /* list-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "list-inl.h"; sourceTree = "<group>"; };
+		897FF1510E719B8F00D62E90 /* list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = list.h; sourceTree = "<group>"; };
+		897FF1520E719B8F00D62E90 /* log.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = log.cc; sourceTree = "<group>"; };
+		897FF1530E719B8F00D62E90 /* log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = log.h; sourceTree = "<group>"; };
+		897FF1540E719B8F00D62E90 /* macro-assembler-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "macro-assembler-arm.cc"; sourceTree = "<group>"; };
+		897FF1550E719B8F00D62E90 /* macro-assembler-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "macro-assembler-arm.h"; sourceTree = "<group>"; };
+		897FF1560E719B8F00D62E90 /* macro-assembler-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "macro-assembler-ia32.cc"; sourceTree = "<group>"; };
+		897FF1570E719B8F00D62E90 /* macro-assembler-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "macro-assembler-ia32.h"; sourceTree = "<group>"; };
+		897FF1580E719B8F00D62E90 /* macro-assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "macro-assembler.h"; sourceTree = "<group>"; };
+		897FF1590E719B8F00D62E90 /* mark-compact.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "mark-compact.cc"; sourceTree = "<group>"; };
+		897FF15A0E719B8F00D62E90 /* mark-compact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mark-compact.h"; sourceTree = "<group>"; };
+		897FF15B0E719B8F00D62E90 /* memory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memory.h; sourceTree = "<group>"; };
+		897FF15C0E719B8F00D62E90 /* messages.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = messages.cc; sourceTree = "<group>"; };
+		897FF15D0E719B8F00D62E90 /* messages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = messages.h; sourceTree = "<group>"; };
+		897FF15E0E719B8F00D62E90 /* mksnapshot.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mksnapshot.cc; sourceTree = "<group>"; };
+		897FF15F0E719B8F00D62E90 /* natives.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = natives.h; sourceTree = "<group>"; };
+		897FF1600E719B8F00D62E90 /* objects-debug.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "objects-debug.cc"; sourceTree = "<group>"; };
+		897FF1610E719B8F00D62E90 /* objects-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "objects-inl.h"; sourceTree = "<group>"; };
+		897FF1620E719B8F00D62E90 /* objects.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = objects.cc; sourceTree = "<group>"; };
+		897FF1630E719B8F00D62E90 /* objects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = objects.h; sourceTree = "<group>"; };
+		897FF1640E719B8F00D62E90 /* parser.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parser.cc; sourceTree = "<group>"; };
+		897FF1650E719B8F00D62E90 /* parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parser.h; sourceTree = "<group>"; };
+		897FF1660E719B8F00D62E90 /* platform-linux.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "platform-linux.cc"; sourceTree = "<group>"; };
+		897FF1670E719B8F00D62E90 /* platform-macos.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "platform-macos.cc"; sourceTree = "<group>"; };
+		897FF1680E719B8F00D62E90 /* platform-nullos.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "platform-nullos.cc"; sourceTree = "<group>"; };
+		897FF1690E719B8F00D62E90 /* platform-win32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "platform-win32.cc"; sourceTree = "<group>"; };
+		897FF16A0E719B8F00D62E90 /* platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platform.h; sourceTree = "<group>"; };
+		897FF16B0E719B8F00D62E90 /* prettyprinter.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = prettyprinter.cc; sourceTree = "<group>"; };
+		897FF16C0E719B8F00D62E90 /* prettyprinter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = prettyprinter.h; sourceTree = "<group>"; };
+		897FF16D0E719B8F00D62E90 /* property.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = property.cc; sourceTree = "<group>"; };
+		897FF16E0E719B8F00D62E90 /* property.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = property.h; sourceTree = "<group>"; };
+		897FF16F0E719B8F00D62E90 /* rewriter.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rewriter.cc; sourceTree = "<group>"; };
+		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.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>"; };
+		897FF1760E719B8F00D62E90 /* scopeinfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scopeinfo.cc; sourceTree = "<group>"; };
+		897FF1770E719B8F00D62E90 /* scopeinfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scopeinfo.h; sourceTree = "<group>"; };
+		897FF1780E719B8F00D62E90 /* scopes.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scopes.cc; sourceTree = "<group>"; };
+		897FF1790E719B8F00D62E90 /* scopes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scopes.h; sourceTree = "<group>"; };
+		897FF17A0E719B8F00D62E90 /* serialize.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = serialize.cc; sourceTree = "<group>"; };
+		897FF17B0E719B8F00D62E90 /* serialize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = serialize.h; sourceTree = "<group>"; };
+		897FF17C0E719B8F00D62E90 /* shell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = shell.h; sourceTree = "<group>"; };
+		897FF17D0E719B8F00D62E90 /* simulator-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "simulator-arm.cc"; sourceTree = "<group>"; };
+		897FF17E0E719B8F00D62E90 /* simulator-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "simulator-arm.h"; sourceTree = "<group>"; };
+		897FF17F0E719B8F00D62E90 /* simulator-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "simulator-ia32.cc"; sourceTree = "<group>"; };
+		897FF1800E719B8F00D62E90 /* simulator-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "simulator-ia32.h"; sourceTree = "<group>"; };
+		897FF1810E719B8F00D62E90 /* smart-pointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "smart-pointer.h"; sourceTree = "<group>"; };
+		897FF1820E719B8F00D62E90 /* snapshot-common.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "snapshot-common.cc"; sourceTree = "<group>"; };
+		897FF1830E719B8F00D62E90 /* snapshot-empty.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "snapshot-empty.cc"; sourceTree = "<group>"; };
+		897FF1840E719B8F00D62E90 /* snapshot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = snapshot.h; sourceTree = "<group>"; };
+		897FF1850E719B8F00D62E90 /* spaces-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "spaces-inl.h"; sourceTree = "<group>"; };
+		897FF1860E719B8F00D62E90 /* spaces.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = spaces.cc; sourceTree = "<group>"; };
+		897FF1870E719B8F00D62E90 /* spaces.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = spaces.h; sourceTree = "<group>"; };
+		897FF1880E719B8F00D62E90 /* string-stream.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "string-stream.cc"; sourceTree = "<group>"; };
+		897FF1890E719B8F00D62E90 /* string-stream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "string-stream.h"; sourceTree = "<group>"; };
+		897FF18A0E719B8F00D62E90 /* stub-cache-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "stub-cache-arm.cc"; sourceTree = "<group>"; };
+		897FF18B0E719B8F00D62E90 /* stub-cache-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "stub-cache-ia32.cc"; sourceTree = "<group>"; };
+		897FF18C0E719B8F00D62E90 /* stub-cache.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "stub-cache.cc"; sourceTree = "<group>"; };
+		897FF18D0E719B8F00D62E90 /* stub-cache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "stub-cache.h"; sourceTree = "<group>"; };
+		897FF18E0E719B8F00D62E90 /* token.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = token.cc; sourceTree = "<group>"; };
+		897FF18F0E719B8F00D62E90 /* token.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = token.h; sourceTree = "<group>"; };
+		897FF1900E719B8F00D62E90 /* top.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = top.cc; sourceTree = "<group>"; };
+		897FF1910E719B8F00D62E90 /* top.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = top.h; sourceTree = "<group>"; };
+		897FF1920E719B8F00D62E90 /* unicode-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "unicode-inl.h"; sourceTree = "<group>"; };
+		897FF1930E719B8F00D62E90 /* unicode.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = unicode.cc; sourceTree = "<group>"; };
+		897FF1940E719B8F00D62E90 /* unicode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unicode.h; sourceTree = "<group>"; };
+		897FF1950E719B8F00D62E90 /* usage-analyzer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "usage-analyzer.cc"; sourceTree = "<group>"; };
+		897FF1960E719B8F00D62E90 /* usage-analyzer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "usage-analyzer.h"; sourceTree = "<group>"; };
+		897FF1970E719B8F00D62E90 /* utils.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = utils.cc; sourceTree = "<group>"; };
+		897FF1980E719B8F00D62E90 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = "<group>"; };
+		897FF1990E719B8F00D62E90 /* v8-counters.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "v8-counters.cc"; sourceTree = "<group>"; };
+		897FF19A0E719B8F00D62E90 /* v8-counters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "v8-counters.h"; sourceTree = "<group>"; };
+		897FF19B0E719B8F00D62E90 /* v8.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = v8.cc; sourceTree = "<group>"; };
+		897FF19C0E719B8F00D62E90 /* v8.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = v8.h; sourceTree = "<group>"; };
+		897FF19D0E719B8F00D62E90 /* v8threads.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = v8threads.cc; sourceTree = "<group>"; };
+		897FF19E0E719B8F00D62E90 /* v8threads.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = v8threads.h; sourceTree = "<group>"; };
+		897FF19F0E719B8F00D62E90 /* variables.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = variables.cc; sourceTree = "<group>"; };
+		897FF1A00E719B8F00D62E90 /* variables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = variables.h; sourceTree = "<group>"; };
+		897FF1A10E719B8F00D62E90 /* zone-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "zone-inl.h"; sourceTree = "<group>"; };
+		897FF1A20E719B8F00D62E90 /* zone.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = zone.cc; sourceTree = "<group>"; };
+		897FF1A30E719B8F00D62E90 /* zone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zone.h; sourceTree = "<group>"; };
+		897FF1A60E719BC100D62E90 /* apinatives.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = apinatives.js; sourceTree = "<group>"; };
+		897FF1A70E719BC100D62E90 /* array.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = array.js; sourceTree = "<group>"; };
+		897FF1A80E719BC100D62E90 /* date-delay.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "date-delay.js"; sourceTree = "<group>"; };
+		897FF1A90E719BC100D62E90 /* debug-delay.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "debug-delay.js"; sourceTree = "<group>"; };
+		897FF1AA0E719BC100D62E90 /* math.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = math.js; sourceTree = "<group>"; };
+		897FF1AB0E719BC100D62E90 /* messages.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = messages.js; sourceTree = "<group>"; };
+		897FF1AC0E719BC100D62E90 /* mirror-delay.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "mirror-delay.js"; sourceTree = "<group>"; };
+		897FF1AD0E719BC100D62E90 /* regexp-delay.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "regexp-delay.js"; sourceTree = "<group>"; };
+		897FF1AE0E719BC100D62E90 /* runtime.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = runtime.js; sourceTree = "<group>"; };
+		897FF1AF0E719BC100D62E90 /* string.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = string.js; sourceTree = "<group>"; };
+		897FF1B00E719BC100D62E90 /* uri.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = uri.js; sourceTree = "<group>"; };
+		897FF1B10E719BC100D62E90 /* v8natives.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = v8natives.js; sourceTree = "<group>"; };
+		897FF1B50E719C0900D62E90 /* shell.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shell.cc; sourceTree = "<group>"; };
+		897FF1B60E719C2300D62E90 /* js2c.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = js2c.py; sourceTree = "<group>"; };
+		897FF1B70E719C2E00D62E90 /* macros.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; name = macros.py; path = ../src/macros.py; sourceTree = "<group>"; };
+		898BD20C0EF6CC850068B00A /* debug-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "debug-arm.cc"; sourceTree = "<group>"; };
+		898BD20D0EF6CC850068B00A /* debug-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "debug-ia32.cc"; sourceTree = "<group>"; };
+		89A15C630EE4661A00B48DEB /* bytecodes-irregexp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "bytecodes-irregexp.h"; sourceTree = "<group>"; };
+		89A15C660EE4665300B48DEB /* interpreter-irregexp.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "interpreter-irregexp.cc"; sourceTree = "<group>"; };
+		89A15C670EE4665300B48DEB /* interpreter-irregexp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "interpreter-irregexp.h"; sourceTree = "<group>"; };
+		89A15C680EE4665300B48DEB /* jsregexp-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "jsregexp-inl.h"; sourceTree = "<group>"; };
+		89A15C6D0EE466A900B48DEB /* platform-freebsd.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "platform-freebsd.cc"; sourceTree = "<group>"; };
+		89A15C700EE466D000B48DEB /* regexp-macro-assembler-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "regexp-macro-assembler-arm.cc"; sourceTree = "<group>"; };
+		89A15C710EE466D000B48DEB /* regexp-macro-assembler-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "regexp-macro-assembler-arm.h"; sourceTree = "<group>"; };
+		89A15C720EE466D000B48DEB /* regexp-macro-assembler-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "regexp-macro-assembler-ia32.cc"; sourceTree = "<group>"; };
+		89A15C730EE466D000B48DEB /* regexp-macro-assembler-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "regexp-macro-assembler-ia32.h"; sourceTree = "<group>"; };
+		89A15C740EE466D000B48DEB /* regexp-macro-assembler-irregexp-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "regexp-macro-assembler-irregexp-inl.h"; sourceTree = "<group>"; };
+		89A15C750EE466D000B48DEB /* regexp-macro-assembler-irregexp.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "regexp-macro-assembler-irregexp.cc"; sourceTree = "<group>"; };
+		89A15C760EE466D000B48DEB /* regexp-macro-assembler-irregexp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "regexp-macro-assembler-irregexp.h"; sourceTree = "<group>"; };
+		89A15C770EE466D000B48DEB /* regexp-macro-assembler-tracer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "regexp-macro-assembler-tracer.cc"; sourceTree = "<group>"; };
+		89A15C780EE466D000B48DEB /* regexp-macro-assembler-tracer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "regexp-macro-assembler-tracer.h"; sourceTree = "<group>"; };
+		89A15C790EE466D000B48DEB /* regexp-macro-assembler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "regexp-macro-assembler.cc"; sourceTree = "<group>"; };
+		89A15C7A0EE466D000B48DEB /* regexp-macro-assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "regexp-macro-assembler.h"; sourceTree = "<group>"; };
+		89A15C910EE46A1700B48DEB /* d8-readline.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "d8-readline.cc"; path = "../src/d8-readline.cc"; sourceTree = "<group>"; };
+		89A15C920EE46A1700B48DEB /* d8.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = d8.cc; path = ../src/d8.cc; sourceTree = "<group>"; };
+		89A15C930EE46A1700B48DEB /* d8.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = d8.h; path = ../src/d8.h; sourceTree = "<group>"; };
+		89A15C940EE46A1700B48DEB /* d8.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = d8.js; path = ../src/d8.js; sourceTree = "<group>"; };
+		89B12E8D0E7FF2A40080BA62 /* presubmit.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = presubmit.py; sourceTree = "<group>"; };
+		89F23C870E78D5B2006B2466 /* libv8-arm.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libv8-arm.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		89F23C950E78D5B6006B2466 /* v8_shell-arm */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "v8_shell-arm"; sourceTree = BUILT_PRODUCTS_DIR; };
+		89FB0E360F8E531900B04B3C /* d8-posix.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "d8-posix.cc"; path = "../src/d8-posix.cc"; sourceTree = "<group>"; };
+		89FB0E370F8E531900B04B3C /* d8-windows.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "d8-windows.cc"; path = "../src/d8-windows.cc"; sourceTree = "<group>"; };
+		9F92FAA70F8F28AD0089F02C /* func-name-inferrer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "func-name-inferrer.cc"; sourceTree = "<group>"; };
+		9F92FAA80F8F28AD0089F02C /* func-name-inferrer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "func-name-inferrer.h"; sourceTree = "<group>"; };
+		9FC86ABB0F5FEDAC00F22668 /* oprofile-agent.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "oprofile-agent.cc"; sourceTree = "<group>"; };
+		9FC86ABC0F5FEDAC00F22668 /* oprofile-agent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "oprofile-agent.h"; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		893988050F2A35FA007D5254 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				893988070F2A35FA007D5254 /* libv8.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		8970F2EE0E719FB2006AE7B5 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		897F76780E71B4CC007ACF34 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				897F76850E71B6B1007ACF34 /* libv8.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		89F23C830E78D5B2006B2466 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		89F23C8F0E78D5B6006B2466 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				896FD03A0E78D717003DFB6A /* libv8-arm.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		8915B8660E719336009C4E19 = {
+			isa = PBXGroup;
+			children = (
+				897FF0CF0E71996900D62E90 /* v8 */,
+				897FF1C00E719CB600D62E90 /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		897FF0CF0E71996900D62E90 /* v8 */ = {
+			isa = PBXGroup;
+			children = (
+				897FF0D10E71999E00D62E90 /* include */,
+				897FF0D00E71999800D62E90 /* src */,
+				897FF1B30E719BCE00D62E90 /* samples */,
+				897FF1B40E719BE800D62E90 /* tools */,
+			);
+			name = v8;
+			path = ..;
+			sourceTree = "<group>";
+		};
+		897FF0D00E71999800D62E90 /* src */ = {
+			isa = PBXGroup;
+			children = (
+				897FF0D70E719AB300D62E90 /* C++ */,
+				897FF0D80E719ABA00D62E90 /* js */,
+				897FF0DE0E719B3400D62E90 /* third_party */,
+				89A9C1630E71C8E300BE6CCA /* generated */,
+			);
+			path = src;
+			sourceTree = "<group>";
+		};
+		897FF0D10E71999E00D62E90 /* include */ = {
+			isa = PBXGroup;
+			children = (
+				897FF0D40E719A8500D62E90 /* v8-debug.h */,
+				897FF0D50E719A8500D62E90 /* v8.h */,
+			);
+			path = include;
+			sourceTree = "<group>";
+		};
+		897FF0D70E719AB300D62E90 /* C++ */ = {
+			isa = PBXGroup;
+			children = (
+				897FF0F60E719B8F00D62E90 /* accessors.cc */,
+				897FF0F70E719B8F00D62E90 /* accessors.h */,
+				897FF0F80E719B8F00D62E90 /* allocation.cc */,
+				897FF0F90E719B8F00D62E90 /* allocation.h */,
+				897FF0FA0E719B8F00D62E90 /* api.cc */,
+				897FF0FB0E719B8F00D62E90 /* api.h */,
+				893986D40F29020C007D5254 /* apiutils.h */,
+				897FF0FC0E719B8F00D62E90 /* arguments.h */,
+				897FF0FD0E719B8F00D62E90 /* assembler-arm-inl.h */,
+				897FF0FE0E719B8F00D62E90 /* assembler-arm.cc */,
+				897FF0FF0E719B8F00D62E90 /* assembler-arm.h */,
+				897FF1000E719B8F00D62E90 /* assembler-ia32-inl.h */,
+				897FF1010E719B8F00D62E90 /* assembler-ia32.cc */,
+				897FF1020E719B8F00D62E90 /* assembler-ia32.h */,
+				897FF1030E719B8F00D62E90 /* assembler.cc */,
+				897FF1040E719B8F00D62E90 /* assembler.h */,
+				897FF1050E719B8F00D62E90 /* ast.cc */,
+				897FF1060E719B8F00D62E90 /* ast.h */,
+				897FF1070E719B8F00D62E90 /* bootstrapper.cc */,
+				897FF1080E719B8F00D62E90 /* bootstrapper.h */,
+				897FF1090E719B8F00D62E90 /* builtins-arm.cc */,
+				897FF10A0E719B8F00D62E90 /* builtins-ia32.cc */,
+				897FF10B0E719B8F00D62E90 /* builtins.cc */,
+				897FF10C0E719B8F00D62E90 /* builtins.h */,
+				89A15C630EE4661A00B48DEB /* bytecodes-irregexp.h */,
+				897FF10D0E719B8F00D62E90 /* char-predicates-inl.h */,
+				897FF10E0E719B8F00D62E90 /* char-predicates.h */,
+				897FF10F0E719B8F00D62E90 /* checks.cc */,
+				897FF1100E719B8F00D62E90 /* checks.h */,
+				897FF1110E719B8F00D62E90 /* code-stubs.cc */,
+				897FF1120E719B8F00D62E90 /* code-stubs.h */,
+				897FF1130E719B8F00D62E90 /* code.h */,
+				897FF1140E719B8F00D62E90 /* codegen-arm.cc */,
+				896448BC0E9D530500E7C516 /* codegen-arm.h */,
+				897FF1150E719B8F00D62E90 /* codegen-ia32.cc */,
+				8964482B0E9C00F700E7C516 /* codegen-ia32.h */,
+				897FF1160E719B8F00D62E90 /* codegen-inl.h */,
+				897FF1170E719B8F00D62E90 /* codegen.cc */,
+				897FF1180E719B8F00D62E90 /* codegen.h */,
+				89495E460E79FC23001F68C3 /* compilation-cache.cc */,
+				89495E470E79FC23001F68C3 /* compilation-cache.h */,
+				897FF1190E719B8F00D62E90 /* compiler.cc */,
+				897FF11A0E719B8F00D62E90 /* compiler.h */,
+				897FF11B0E719B8F00D62E90 /* constants-arm.h */,
+				897FF11C0E719B8F00D62E90 /* contexts.cc */,
+				897FF11D0E719B8F00D62E90 /* contexts.h */,
+				897FF11E0E719B8F00D62E90 /* conversions-inl.h */,
+				897FF11F0E719B8F00D62E90 /* conversions.cc */,
+				897FF1200E719B8F00D62E90 /* conversions.h */,
+				897FF1210E719B8F00D62E90 /* counters.cc */,
+				897FF1220E719B8F00D62E90 /* counters.h */,
+				897FF1230E719B8F00D62E90 /* cpu-arm.cc */,
+				897FF1240E719B8F00D62E90 /* cpu-ia32.cc */,
+				897FF1250E719B8F00D62E90 /* cpu.h */,
+				893A722A0F7B4A3200303DD2 /* dateparser-inl.h */,
+				897FF1260E719B8F00D62E90 /* dateparser.cc */,
+				897FF1270E719B8F00D62E90 /* dateparser.h */,
+				898BD20C0EF6CC850068B00A /* debug-arm.cc */,
+				898BD20D0EF6CC850068B00A /* debug-ia32.cc */,
+				897FF1280E719B8F00D62E90 /* debug.cc */,
+				897FF1290E719B8F00D62E90 /* debug.h */,
+				8956B6CD0F5D86570033B5A2 /* debug-agent.cc */,
+				8956B6CE0F5D86570033B5A2 /* debug-agent.h */,
+				897FF12A0E719B8F00D62E90 /* disasm-arm.cc */,
+				897FF12B0E719B8F00D62E90 /* disasm-ia32.cc */,
+				897FF12C0E719B8F00D62E90 /* disasm.h */,
+				897FF12D0E719B8F00D62E90 /* disassembler.cc */,
+				897FF12E0E719B8F00D62E90 /* disassembler.h */,
+				897FF12F0E719B8F00D62E90 /* dtoa-config.c */,
+				897FF1300E719B8F00D62E90 /* execution.cc */,
+				897FF1310E719B8F00D62E90 /* execution.h */,
+				897FF1320E719B8F00D62E90 /* factory.cc */,
+				897FF1330E719B8F00D62E90 /* factory.h */,
+				89471C7F0EB23EE400B6874B /* flag-definitions.h */,
+				897FF1350E719B8F00D62E90 /* flags.cc */,
+				897FF1360E719B8F00D62E90 /* flags.h */,
+				897FF1370E719B8F00D62E90 /* frames-arm.cc */,
+				897FF1380E719B8F00D62E90 /* frames-arm.h */,
+				897FF1390E719B8F00D62E90 /* frames-ia32.cc */,
+				897FF13A0E719B8F00D62E90 /* frames-ia32.h */,
+				897FF13B0E719B8F00D62E90 /* frames-inl.h */,
+				897FF13C0E719B8F00D62E90 /* frames.cc */,
+				897FF13D0E719B8F00D62E90 /* frames.h */,
+				9F92FAA70F8F28AD0089F02C /* func-name-inferrer.cc */,
+				9F92FAA80F8F28AD0089F02C /* func-name-inferrer.h */,
+				897FF13E0E719B8F00D62E90 /* global-handles.cc */,
+				897FF13F0E719B8F00D62E90 /* global-handles.h */,
+				897FF1400E719B8F00D62E90 /* globals.h */,
+				897FF1410E719B8F00D62E90 /* handles-inl.h */,
+				897FF1420E719B8F00D62E90 /* handles.cc */,
+				897FF1430E719B8F00D62E90 /* handles.h */,
+				897FF1440E719B8F00D62E90 /* hashmap.cc */,
+				897FF1450E719B8F00D62E90 /* hashmap.h */,
+				897FF1460E719B8F00D62E90 /* heap-inl.h */,
+				897FF1470E719B8F00D62E90 /* heap.cc */,
+				897FF1480E719B8F00D62E90 /* heap.h */,
+				897FF1490E719B8F00D62E90 /* ic-arm.cc */,
+				897FF14A0E719B8F00D62E90 /* ic-ia32.cc */,
+				897FF14B0E719B8F00D62E90 /* ic-inl.h */,
+				897FF14C0E719B8F00D62E90 /* ic.cc */,
+				897FF14D0E719B8F00D62E90 /* ic.h */,
+				89A15C660EE4665300B48DEB /* interpreter-irregexp.cc */,
+				89A15C670EE4665300B48DEB /* interpreter-irregexp.h */,
+				89A15C680EE4665300B48DEB /* jsregexp-inl.h */,
+				897FF14E0E719B8F00D62E90 /* jsregexp.cc */,
+				897FF14F0E719B8F00D62E90 /* jsregexp.h */,
+				58950D4E0F55514900F3E8BA /* jump-target-arm.cc */,
+				58950D4F0F55514900F3E8BA /* jump-target-ia32.cc */,
+				58950D500F55514900F3E8BA /* jump-target.cc */,
+				58950D510F55514900F3E8BA /* jump-target.h */,
+				897FF1500E719B8F00D62E90 /* list-inl.h */,
+				897FF1510E719B8F00D62E90 /* list.h */,
+				897FF1520E719B8F00D62E90 /* log.cc */,
+				897FF1530E719B8F00D62E90 /* log.h */,
+				897FF1540E719B8F00D62E90 /* macro-assembler-arm.cc */,
+				897FF1550E719B8F00D62E90 /* macro-assembler-arm.h */,
+				897FF1560E719B8F00D62E90 /* macro-assembler-ia32.cc */,
+				897FF1570E719B8F00D62E90 /* macro-assembler-ia32.h */,
+				897FF1580E719B8F00D62E90 /* macro-assembler.h */,
+				897FF1590E719B8F00D62E90 /* mark-compact.cc */,
+				897FF15A0E719B8F00D62E90 /* mark-compact.h */,
+				897FF15B0E719B8F00D62E90 /* memory.h */,
+				897FF15C0E719B8F00D62E90 /* messages.cc */,
+				897FF15D0E719B8F00D62E90 /* messages.h */,
+				897FF15E0E719B8F00D62E90 /* mksnapshot.cc */,
+				897FF15F0E719B8F00D62E90 /* natives.h */,
+				897FF1600E719B8F00D62E90 /* objects-debug.cc */,
+				897FF1610E719B8F00D62E90 /* objects-inl.h */,
+				897FF1620E719B8F00D62E90 /* objects.cc */,
+				897FF1630E719B8F00D62E90 /* objects.h */,
+				9FC86ABB0F5FEDAC00F22668 /* oprofile-agent.cc */,
+				9FC86ABC0F5FEDAC00F22668 /* oprofile-agent.h */,
+				897FF1640E719B8F00D62E90 /* parser.cc */,
+				897FF1650E719B8F00D62E90 /* parser.h */,
+				89A15C6D0EE466A900B48DEB /* platform-freebsd.cc */,
+				897FF1660E719B8F00D62E90 /* platform-linux.cc */,
+				897FF1670E719B8F00D62E90 /* platform-macos.cc */,
+				897FF1680E719B8F00D62E90 /* platform-nullos.cc */,
+				893A72230F7B0FF200303DD2 /* platform-posix.cc */,
+				897FF1690E719B8F00D62E90 /* platform-win32.cc */,
+				897FF16A0E719B8F00D62E90 /* platform.h */,
+				897FF16B0E719B8F00D62E90 /* prettyprinter.cc */,
+				897FF16C0E719B8F00D62E90 /* prettyprinter.h */,
+				897FF16D0E719B8F00D62E90 /* property.cc */,
+				897FF16E0E719B8F00D62E90 /* property.h */,
+				89A15C700EE466D000B48DEB /* regexp-macro-assembler-arm.cc */,
+				89A15C710EE466D000B48DEB /* regexp-macro-assembler-arm.h */,
+				89A15C720EE466D000B48DEB /* regexp-macro-assembler-ia32.cc */,
+				89A15C730EE466D000B48DEB /* regexp-macro-assembler-ia32.h */,
+				89A15C740EE466D000B48DEB /* regexp-macro-assembler-irregexp-inl.h */,
+				89A15C750EE466D000B48DEB /* regexp-macro-assembler-irregexp.cc */,
+				89A15C760EE466D000B48DEB /* regexp-macro-assembler-irregexp.h */,
+				89A15C770EE466D000B48DEB /* regexp-macro-assembler-tracer.cc */,
+				89A15C780EE466D000B48DEB /* regexp-macro-assembler-tracer.h */,
+				89A15C790EE466D000B48DEB /* regexp-macro-assembler.cc */,
+				89A15C7A0EE466D000B48DEB /* regexp-macro-assembler.h */,
+				8944AD0E0F1D4D3A0028D560 /* regexp-stack.cc */,
+				8944AD0F0F1D4D3A0028D560 /* regexp-stack.h */,
+				58950D520F55514900F3E8BA /* register-allocator-arm.cc */,
+				58950D530F55514900F3E8BA /* register-allocator-ia32.cc */,
+				893A722D0F7B4A7100303DD2 /* register-allocator-inl.h */,
+				58950D540F55514900F3E8BA /* register-allocator.cc */,
+				58950D550F55514900F3E8BA /* register-allocator.h */,
+				897FF16F0E719B8F00D62E90 /* rewriter.cc */,
+				897FF1700E719B8F00D62E90 /* rewriter.h */,
+				897FF1710E719B8F00D62E90 /* runtime.cc */,
+				897FF1720E719B8F00D62E90 /* runtime.h */,
+				897FF1730E719B8F00D62E90 /* scanner.cc */,
+				897FF1740E719B8F00D62E90 /* scanner.h */,
+				897FF1750E719B8F00D62E90 /* SConscript */,
+				897FF1760E719B8F00D62E90 /* scopeinfo.cc */,
+				897FF1770E719B8F00D62E90 /* scopeinfo.h */,
+				897FF1780E719B8F00D62E90 /* scopes.cc */,
+				897FF1790E719B8F00D62E90 /* scopes.h */,
+				897FF17A0E719B8F00D62E90 /* serialize.cc */,
+				897FF17B0E719B8F00D62E90 /* serialize.h */,
+				897FF17C0E719B8F00D62E90 /* shell.h */,
+				897FF17D0E719B8F00D62E90 /* simulator-arm.cc */,
+				897FF17E0E719B8F00D62E90 /* simulator-arm.h */,
+				897FF17F0E719B8F00D62E90 /* simulator-ia32.cc */,
+				897FF1800E719B8F00D62E90 /* simulator-ia32.h */,
+				897FF1810E719B8F00D62E90 /* smart-pointer.h */,
+				897FF1820E719B8F00D62E90 /* snapshot-common.cc */,
+				897FF1830E719B8F00D62E90 /* snapshot-empty.cc */,
+				897FF1840E719B8F00D62E90 /* snapshot.h */,
+				897FF1850E719B8F00D62E90 /* spaces-inl.h */,
+				897FF1860E719B8F00D62E90 /* spaces.cc */,
+				897FF1870E719B8F00D62E90 /* spaces.h */,
+				897FF1880E719B8F00D62E90 /* string-stream.cc */,
+				897FF1890E719B8F00D62E90 /* string-stream.h */,
+				897FF18A0E719B8F00D62E90 /* stub-cache-arm.cc */,
+				897FF18B0E719B8F00D62E90 /* stub-cache-ia32.cc */,
+				897FF18C0E719B8F00D62E90 /* stub-cache.cc */,
+				897FF18D0E719B8F00D62E90 /* stub-cache.h */,
+				897FF18E0E719B8F00D62E90 /* token.cc */,
+				897FF18F0E719B8F00D62E90 /* token.h */,
+				897FF1900E719B8F00D62E90 /* top.cc */,
+				897FF1910E719B8F00D62E90 /* top.h */,
+				897FF1920E719B8F00D62E90 /* unicode-inl.h */,
+				897FF1930E719B8F00D62E90 /* unicode.cc */,
+				897FF1940E719B8F00D62E90 /* unicode.h */,
+				897FF1950E719B8F00D62E90 /* usage-analyzer.cc */,
+				897FF1960E719B8F00D62E90 /* usage-analyzer.h */,
+				897FF1970E719B8F00D62E90 /* utils.cc */,
+				897FF1980E719B8F00D62E90 /* utils.h */,
+				897FF1990E719B8F00D62E90 /* v8-counters.cc */,
+				897FF19A0E719B8F00D62E90 /* v8-counters.h */,
+				897FF19B0E719B8F00D62E90 /* v8.cc */,
+				897FF19C0E719B8F00D62E90 /* v8.h */,
+				897FF19D0E719B8F00D62E90 /* v8threads.cc */,
+				897FF19E0E719B8F00D62E90 /* v8threads.h */,
+				897FF19F0E719B8F00D62E90 /* variables.cc */,
+				897FF1A00E719B8F00D62E90 /* variables.h */,
+				58950D560F55514900F3E8BA /* virtual-frame-arm.cc */,
+				58950D570F55514900F3E8BA /* virtual-frame-arm.h */,
+				58950D580F55514900F3E8BA /* virtual-frame-ia32.cc */,
+				58950D590F55514900F3E8BA /* virtual-frame-ia32.h */,
+				58950D5A0F55514900F3E8BA /* virtual-frame.cc */,
+				58950D5B0F55514900F3E8BA /* virtual-frame.h */,
+				897FF1A10E719B8F00D62E90 /* zone-inl.h */,
+				897FF1A20E719B8F00D62E90 /* zone.cc */,
+				897FF1A30E719B8F00D62E90 /* zone.h */,
+			);
+			name = "C++";
+			sourceTree = "<group>";
+		};
+		897FF0D80E719ABA00D62E90 /* js */ = {
+			isa = PBXGroup;
+			children = (
+				897FF1A60E719BC100D62E90 /* apinatives.js */,
+				897FF1A70E719BC100D62E90 /* array.js */,
+				897FF1A80E719BC100D62E90 /* date-delay.js */,
+				897FF1A90E719BC100D62E90 /* debug-delay.js */,
+				897FF1AA0E719BC100D62E90 /* math.js */,
+				897FF1AB0E719BC100D62E90 /* messages.js */,
+				897FF1AC0E719BC100D62E90 /* mirror-delay.js */,
+				897FF1AD0E719BC100D62E90 /* regexp-delay.js */,
+				897FF1AE0E719BC100D62E90 /* runtime.js */,
+				897FF1AF0E719BC100D62E90 /* string.js */,
+				897FF1B00E719BC100D62E90 /* uri.js */,
+				897FF1B10E719BC100D62E90 /* v8natives.js */,
+			);
+			name = js;
+			sourceTree = "<group>";
+		};
+		897FF0DE0E719B3400D62E90 /* third_party */ = {
+			isa = PBXGroup;
+			children = (
+				897FF0DF0E719B3400D62E90 /* dtoa */,
+			);
+			path = third_party;
+			sourceTree = "<group>";
+		};
+		897FF0DF0E719B3400D62E90 /* dtoa */ = {
+			isa = PBXGroup;
+			children = (
+				897FF0E00E719B3500D62E90 /* COPYING */,
+				897FF0E10E719B3500D62E90 /* dtoa.c */,
+			);
+			path = dtoa;
+			sourceTree = "<group>";
+		};
+		897FF1B30E719BCE00D62E90 /* samples */ = {
+			isa = PBXGroup;
+			children = (
+				89A15C910EE46A1700B48DEB /* d8-readline.cc */,
+				893988150F2A3686007D5254 /* d8-debug.cc */,
+				893A72320F7B4AD700303DD2 /* d8-debug.h */,
+				89FB0E360F8E531900B04B3C /* d8-posix.cc */,
+				89FB0E370F8E531900B04B3C /* d8-windows.cc */,
+				89A15C920EE46A1700B48DEB /* d8.cc */,
+				89A15C930EE46A1700B48DEB /* d8.h */,
+				89A15C940EE46A1700B48DEB /* d8.js */,
+				897FF1B50E719C0900D62E90 /* shell.cc */,
+			);
+			path = samples;
+			sourceTree = "<group>";
+		};
+		897FF1B40E719BE800D62E90 /* tools */ = {
+			isa = PBXGroup;
+			children = (
+				897FF1B60E719C2300D62E90 /* js2c.py */,
+				897FF1B70E719C2E00D62E90 /* macros.py */,
+				89B12E8D0E7FF2A40080BA62 /* presubmit.py */,
+			);
+			path = tools;
+			sourceTree = "<group>";
+		};
+		897FF1C00E719CB600D62E90 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				8970F2F00E719FB2006AE7B5 /* libv8.a */,
+				897F767A0E71B4CC007ACF34 /* v8_shell */,
+				89F23C870E78D5B2006B2466 /* libv8-arm.a */,
+				89F23C950E78D5B6006B2466 /* v8_shell-arm */,
+				8939880B0F2A35FA007D5254 /* v8_shell */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		89A9C1630E71C8E300BE6CCA /* generated */ = {
+			isa = PBXGroup;
+			children = (
+				893988320F2A3B8B007D5254 /* d8-js.cc */,
+				8900116B0E71CA2300F91F35 /* libraries.cc */,
+			);
+			path = generated;
+			sourceTree = CONFIGURATION_TEMP_DIR;
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		893987FE0F2A35FA007D5254 /* d8_shell */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 893988080F2A35FA007D5254 /* Build configuration list for PBXNativeTarget "d8_shell" */;
+			buildPhases = (
+				893988220F2A376C007D5254 /* ShellScript */,
+				893988030F2A35FA007D5254 /* Sources */,
+				893988050F2A35FA007D5254 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				893988010F2A35FA007D5254 /* PBXTargetDependency */,
+			);
+			name = d8_shell;
+			productName = v8_shell;
+			productReference = 8939880B0F2A35FA007D5254 /* v8_shell */;
+			productType = "com.apple.product-type.tool";
+		};
+		8970F2EF0E719FB2006AE7B5 /* v8 */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 8970F2F70E719FC1006AE7B5 /* Build configuration list for PBXNativeTarget "v8" */;
+			buildPhases = (
+				89EA6FB50E71AA1F00F59E1B /* ShellScript */,
+				8970F2ED0E719FB2006AE7B5 /* Sources */,
+				8970F2EE0E719FB2006AE7B5 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = v8;
+			productName = v8;
+			productReference = 8970F2F00E719FB2006AE7B5 /* libv8.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+		897F76790E71B4CC007ACF34 /* v8_shell */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 897F767E0E71B4EA007ACF34 /* Build configuration list for PBXNativeTarget "v8_shell" */;
+			buildPhases = (
+				897F76770E71B4CC007ACF34 /* Sources */,
+				897F76780E71B4CC007ACF34 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				897F76830E71B6AC007ACF34 /* PBXTargetDependency */,
+			);
+			name = v8_shell;
+			productName = v8_shell;
+			productReference = 897F767A0E71B4CC007ACF34 /* v8_shell */;
+			productType = "com.apple.product-type.tool";
+		};
+		89F23C3C0E78D5B2006B2466 /* v8-arm */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 89F23C840E78D5B2006B2466 /* Build configuration list for PBXNativeTarget "v8-arm" */;
+			buildPhases = (
+				89F23C3D0E78D5B2006B2466 /* ShellScript */,
+				89F23C3E0E78D5B2006B2466 /* Sources */,
+				89F23C830E78D5B2006B2466 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "v8-arm";
+			productName = "v8-arm";
+			productReference = 89F23C870E78D5B2006B2466 /* libv8-arm.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+		89F23C880E78D5B6006B2466 /* v8_shell-arm */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 89F23C920E78D5B6006B2466 /* Build configuration list for PBXNativeTarget "v8_shell-arm" */;
+			buildPhases = (
+				89F23C8D0E78D5B6006B2466 /* Sources */,
+				89F23C8F0E78D5B6006B2466 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				896FD03C0E78D71F003DFB6A /* PBXTargetDependency */,
+			);
+			name = "v8_shell-arm";
+			productName = "v8_shell-arm";
+			productReference = 89F23C950E78D5B6006B2466 /* v8_shell-arm */;
+			productType = "com.apple.product-type.tool";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		8915B8680E719336009C4E19 /* Project object */ = {
+			isa = PBXProject;
+			buildConfigurationList = 8915B86B0E719336009C4E19 /* Build configuration list for PBXProject "v8" */;
+			compatibilityVersion = "Xcode 3.1";
+			hasScannedForEncodings = 0;
+			mainGroup = 8915B8660E719336009C4E19;
+			productRefGroup = 897FF1C00E719CB600D62E90 /* Products */;
+			projectDirPath = "";
+			projectRoot = ..;
+			targets = (
+				7BF891930E73098D000BAF8A /* All */,
+				8970F2EF0E719FB2006AE7B5 /* v8 */,
+				897F76790E71B4CC007ACF34 /* v8_shell */,
+				893987FE0F2A35FA007D5254 /* d8_shell */,
+				89F23C3C0E78D5B2006B2466 /* v8-arm */,
+				89F23C880E78D5B6006B2466 /* v8_shell-arm */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		893988220F2A376C007D5254 /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "set -ex\nJS_FILES=\"d8.js\"\\\n\" macros.py\"\n\nV8ROOT=\"${SRCROOT}/..\"\n\nSRC_DIR=\"${V8ROOT}/src\"\n\nNATIVE_JS_FILES=\"\"\n\nfor i in ${JS_FILES} ; do\n  NATIVE_JS_FILES+=\"${SRC_DIR}/${i} \"\ndone\n\nV8_GENERATED_SOURCES_DIR=\"${CONFIGURATION_TEMP_DIR}/generated\"\nmkdir -p \"${V8_GENERATED_SOURCES_DIR}\"\n\nD8_CC=\"${V8_GENERATED_SOURCES_DIR}/d8-js.cc\"\nD8_EMPTY_CC=\"${V8_GENERATED_SOURCES_DIR}/d8-js-empty.cc\"\n\npython \"${V8ROOT}/tools/js2c.py\" \\\n  \"${D8_CC}.new\" \\\n  \"${D8_EMPTY_CC}.new\" \\\n  \"D8\" \\\n  ${NATIVE_JS_FILES}\n\n# Only use the new files if they're different from the existing files (if any),\n# preserving the existing files' timestamps when there are no changes.  This\n# minimizes unnecessary build activity for a no-change build.\n\nif ! diff -q \"${D8_CC}.new\" \"${D8_CC}\" >& /dev/null ; then\n  mv \"${D8_CC}.new\" \"${D8_CC}\"\nelse\n  rm \"${D8_CC}.new\"\nfi\n\nif ! diff -q \"${D8_EMPTY_CC}.new\" \"${D8_EMPTY_CC}\" >& /dev/null ; then\n  mv \"${D8_EMPTY_CC}.new\" \"${D8_EMPTY_CC}\"\nelse\n  rm \"${D8_EMPTY_CC}.new\"\nfi\n";
+		};
+		89EA6FB50E71AA1F00F59E1B /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "set -ex\nJS_FILES=\"runtime.js\"\\\n\" v8natives.js\"\\\n\" array.js\"\\\n\" string.js\"\\\n\" uri.js\"\\\n\" math.js\"\\\n\" messages.js\"\\\n\" apinatives.js\"\\\n\" debug-delay.js\"\\\n\" mirror-delay.js\"\\\n\" date-delay.js\"\\\n\" regexp-delay.js\"\\\n\" macros.py\"\n\nV8ROOT=\"${SRCROOT}/..\"\n\nSRC_DIR=\"${V8ROOT}/src\"\n\nNATIVE_JS_FILES=\"\"\n\nfor i in ${JS_FILES} ; do\n  NATIVE_JS_FILES+=\"${SRC_DIR}/${i} \"\ndone\n\nV8_GENERATED_SOURCES_DIR=\"${CONFIGURATION_TEMP_DIR}/generated\"\nmkdir -p \"${V8_GENERATED_SOURCES_DIR}\"\n\nLIBRARIES_CC=\"${V8_GENERATED_SOURCES_DIR}/libraries.cc\"\nLIBRARIES_EMPTY_CC=\"${V8_GENERATED_SOURCES_DIR}/libraries-empty.cc\"\n\npython \"${V8ROOT}/tools/js2c.py\" \\\n  \"${LIBRARIES_CC}.new\" \\\n  \"${LIBRARIES_EMPTY_CC}.new\" \\\n  \"CORE\" \\\n  ${NATIVE_JS_FILES}\n\n# Only use the new files if they're different from the existing files (if any),\n# preserving the existing files' timestamps when there are no changes.  This\n# minimizes unnecessary build activity for a no-change build.\n\nif ! diff -q \"${LIBRARIES_CC}.new\" \"${LIBRARIES_CC}\" >& /dev/null ; then\n  mv \"${LIBRARIES_CC}.new\" \"${LIBRARIES_CC}\"\nelse\n  rm \"${LIBRARIES_CC}.new\"\nfi\n\nif ! diff -q \"${LIBRARIES_EMPTY_CC}.new\" \"${LIBRARIES_EMPTY_CC}\" >& /dev/null ; then\n  mv \"${LIBRARIES_EMPTY_CC}.new\" \"${LIBRARIES_EMPTY_CC}\"\nelse\n  rm \"${LIBRARIES_EMPTY_CC}.new\"\nfi\n";
+		};
+		89F23C3D0E78D5B2006B2466 /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "set -ex\nJS_FILES=\"runtime.js\"\\\n\" v8natives.js\"\\\n\" array.js\"\\\n\" string.js\"\\\n\" uri.js\"\\\n\" math.js\"\\\n\" messages.js\"\\\n\" apinatives.js\"\\\n\" debug-delay.js\"\\\n\" mirror-delay.js\"\\\n\" date-delay.js\"\\\n\" regexp-delay.js\"\\\n\" macros.py\"\n\nV8ROOT=\"${SRCROOT}/..\"\n\nSRC_DIR=\"${V8ROOT}/src\"\n\nNATIVE_JS_FILES=\"\"\n\nfor i in ${JS_FILES} ; do\n  NATIVE_JS_FILES+=\"${SRC_DIR}/${i} \"\ndone\n\nV8_GENERATED_SOURCES_DIR=\"${CONFIGURATION_TEMP_DIR}/generated\"\nmkdir -p \"${V8_GENERATED_SOURCES_DIR}\"\n\nLIBRARIES_CC=\"${V8_GENERATED_SOURCES_DIR}/libraries.cc\"\nLIBRARIES_EMPTY_CC=\"${V8_GENERATED_SOURCES_DIR}/libraries-empty.cc\"\n\npython \"${V8ROOT}/tools/js2c.py\" \\\n  \"${LIBRARIES_CC}.new\" \\\n  \"${LIBRARIES_EMPTY_CC}.new\" \\\n  \"CORE\" \\\n  ${NATIVE_JS_FILES}\n\n# Only use the new files if they're different from the existing files (if any),\n# preserving the existing files' timestamps when there are no changes.  This\n# minimizes unnecessary build activity for a no-change build.\n\nif ! diff -q \"${LIBRARIES_CC}.new\" \"${LIBRARIES_CC}\" >& /dev/null ; then\n  mv \"${LIBRARIES_CC}.new\" \"${LIBRARIES_CC}\"\nelse\n  rm \"${LIBRARIES_CC}.new\"\nfi\n\nif ! diff -q \"${LIBRARIES_EMPTY_CC}.new\" \"${LIBRARIES_EMPTY_CC}\" >& /dev/null ; then\n  mv \"${LIBRARIES_EMPTY_CC}.new\" \"${LIBRARIES_EMPTY_CC}\"\nelse\n  rm \"${LIBRARIES_EMPTY_CC}.new\"\nfi\n";
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		893988030F2A35FA007D5254 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				8939880D0F2A362A007D5254 /* d8.cc in Sources */,
+				893988160F2A3688007D5254 /* d8-debug.cc in Sources */,
+				893988330F2A3B8F007D5254 /* d8-js.cc in Sources */,
+				89FB0E3A0F8E533F00B04B3C /* d8-posix.cc in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		8970F2ED0E719FB2006AE7B5 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				89A88DEC0E71A5FF0043BA31 /* accessors.cc in Sources */,
+				89A88DED0E71A6000043BA31 /* allocation.cc in Sources */,
+				89A88DEE0E71A6010043BA31 /* api.cc in Sources */,
+				89A88DEF0E71A60A0043BA31 /* assembler-ia32.cc in Sources */,
+				89A88DF00E71A60A0043BA31 /* assembler.cc in Sources */,
+				89A88DF10E71A60B0043BA31 /* ast.cc in Sources */,
+				89A88DF20E71A60C0043BA31 /* bootstrapper.cc in Sources */,
+				89A88DF40E71A6160043BA31 /* builtins-ia32.cc in Sources */,
+				89A88DF50E71A6170043BA31 /* builtins.cc in Sources */,
+				89A88DF60E71A61C0043BA31 /* checks.cc in Sources */,
+				893CCE640E71D83700357A03 /* code-stubs.cc in Sources */,
+				89A88DF70E71A6240043BA31 /* codegen-ia32.cc in Sources */,
+				89A88DF80E71A6260043BA31 /* codegen.cc in Sources */,
+				89495E480E79FC23001F68C3 /* compilation-cache.cc in Sources */,
+				89A88DF90E71A6430043BA31 /* compiler.cc in Sources */,
+				89A88DFA0E71A6440043BA31 /* contexts.cc in Sources */,
+				89A88DFB0E71A6440043BA31 /* conversions.cc in Sources */,
+				89A88DFC0E71A6460043BA31 /* counters.cc in Sources */,
+				89A88DFD0E71A6470043BA31 /* cpu-ia32.cc in Sources */,
+				89A88DFE0E71A6480043BA31 /* dateparser.cc in Sources */,
+				8956B6CF0F5D86730033B5A2 /* debug-agent.cc in Sources */,
+				898BD20E0EF6CC930068B00A /* debug-ia32.cc in Sources */,
+				89A88DFF0E71A6530043BA31 /* debug.cc in Sources */,
+				89A88E000E71A6540043BA31 /* disasm-ia32.cc in Sources */,
+				89A88E010E71A6550043BA31 /* disassembler.cc in Sources */,
+				89A88E020E71A65A0043BA31 /* dtoa-config.c in Sources */,
+				89A88E030E71A65B0043BA31 /* execution.cc in Sources */,
+				89A88E040E71A65D0043BA31 /* factory.cc in Sources */,
+				89A88E050E71A65D0043BA31 /* flags.cc in Sources */,
+				89A88E060E71A6600043BA31 /* frames-ia32.cc in Sources */,
+				89A88E070E71A6610043BA31 /* frames.cc in Sources */,
+				9F92FAA90F8F28AD0089F02C /* func-name-inferrer.cc in Sources */,
+				89A88E080E71A6620043BA31 /* global-handles.cc in Sources */,
+				89A88E090E71A6640043BA31 /* handles.cc in Sources */,
+				89A88E0A0E71A6650043BA31 /* hashmap.cc in Sources */,
+				89A88E0B0E71A66C0043BA31 /* heap.cc in Sources */,
+				89A88E0C0E71A66D0043BA31 /* ic-ia32.cc in Sources */,
+				89A88E0D0E71A66E0043BA31 /* ic.cc in Sources */,
+				89A15C850EE4678B00B48DEB /* interpreter-irregexp.cc in Sources */,
+				89A88E0E0E71A66F0043BA31 /* jsregexp.cc in Sources */,
+				58950D5E0F55519800F3E8BA /* jump-target.cc in Sources */,
+				58950D5F0F55519D00F3E8BA /* jump-target-ia32.cc in Sources */,
+				8900116C0E71CA2300F91F35 /* libraries.cc in Sources */,
+				89A88E0F0E71A6740043BA31 /* log.cc in Sources */,
+				89A88E100E71A6770043BA31 /* macro-assembler-ia32.cc in Sources */,
+				89A88E110E71A6780043BA31 /* mark-compact.cc in Sources */,
+				89A88E120E71A67A0043BA31 /* messages.cc in Sources */,
+				89A88E130E71A6860043BA31 /* objects-debug.cc in Sources */,
+				89A88E140E71A6870043BA31 /* objects.cc in Sources */,
+				9FC86ABD0F5FEDAC00F22668 /* oprofile-agent.cc in Sources */,
+				89A88E150E71A68C0043BA31 /* parser.cc in Sources */,
+				893A72240F7B101400303DD2 /* platform-posix.cc in Sources */,
+				89A88E160E71A68E0043BA31 /* platform-macos.cc in Sources */,
+				89A88E170E71A6950043BA31 /* prettyprinter.cc in Sources */,
+				89A88E180E71A6960043BA31 /* property.cc in Sources */,
+				89A15C7B0EE466EB00B48DEB /* regexp-macro-assembler-ia32.cc in Sources */,
+				89A15C830EE4675E00B48DEB /* regexp-macro-assembler-irregexp.cc in Sources */,
+				89A15C8A0EE467D100B48DEB /* regexp-macro-assembler-tracer.cc in Sources */,
+				89A15C810EE4674900B48DEB /* regexp-macro-assembler.cc in Sources */,
+				8944AD100F1D4D500028D560 /* regexp-stack.cc in Sources */,
+				58950D620F5551AF00F3E8BA /* register-allocator-ia32.cc in Sources */,
+				58950D630F5551AF00F3E8BA /* register-allocator.cc in Sources */,
+				89A88E190E71A6970043BA31 /* rewriter.cc in Sources */,
+				89A88E1A0E71A69B0043BA31 /* runtime.cc in Sources */,
+				89A88E1B0E71A69D0043BA31 /* scanner.cc in Sources */,
+				89A88E1C0E71A69E0043BA31 /* scopeinfo.cc in Sources */,
+				89A88E1D0E71A6A00043BA31 /* scopes.cc in Sources */,
+				89A88E1E0E71A6A30043BA31 /* serialize.cc in Sources */,
+				89A88E1F0E71A6B40043BA31 /* snapshot-common.cc in Sources */,
+				89A88E200E71A6B60043BA31 /* snapshot-empty.cc in Sources */,
+				89A88E210E71A6B70043BA31 /* spaces.cc in Sources */,
+				89A88E220E71A6BC0043BA31 /* string-stream.cc in Sources */,
+				89A88E230E71A6BE0043BA31 /* stub-cache-ia32.cc in Sources */,
+				89A88E240E71A6BF0043BA31 /* stub-cache.cc in Sources */,
+				89A88E250E71A6C20043BA31 /* token.cc in Sources */,
+				89A88E260E71A6C90043BA31 /* top.cc in Sources */,
+				89A88E270E71A6CB0043BA31 /* unicode.cc in Sources */,
+				89A88E280E71A6CC0043BA31 /* usage-analyzer.cc in Sources */,
+				89A88E290E71A6CE0043BA31 /* utils.cc in Sources */,
+				89A88E2A0E71A6D00043BA31 /* v8-counters.cc in Sources */,
+				89A88E2B0E71A6D10043BA31 /* v8.cc in Sources */,
+				89A88E2C0E71A6D20043BA31 /* v8threads.cc in Sources */,
+				89A88E2D0E71A6D50043BA31 /* variables.cc in Sources */,
+				58950D660F5551C200F3E8BA /* virtual-frame.cc in Sources */,
+				58950D670F5551C400F3E8BA /* virtual-frame-ia32.cc in Sources */,
+				89A88E2E0E71A6D60043BA31 /* zone.cc in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		897F76770E71B4CC007ACF34 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				897F767F0E71B690007ACF34 /* shell.cc in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		89F23C3E0E78D5B2006B2466 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				89F23C3F0E78D5B2006B2466 /* accessors.cc in Sources */,
+				89F23C400E78D5B2006B2466 /* allocation.cc in Sources */,
+				89F23C410E78D5B2006B2466 /* api.cc in Sources */,
+				89F23C970E78D5E3006B2466 /* assembler-arm.cc in Sources */,
+				89F23C430E78D5B2006B2466 /* assembler.cc in Sources */,
+				89F23C440E78D5B2006B2466 /* ast.cc in Sources */,
+				89F23C450E78D5B2006B2466 /* bootstrapper.cc in Sources */,
+				89F23C980E78D5E7006B2466 /* builtins-arm.cc in Sources */,
+				89F23C470E78D5B2006B2466 /* builtins.cc in Sources */,
+				89F23C480E78D5B2006B2466 /* checks.cc in Sources */,
+				89F23C490E78D5B2006B2466 /* code-stubs.cc in Sources */,
+				89F23C990E78D5E9006B2466 /* codegen-arm.cc in Sources */,
+				89F23C4B0E78D5B2006B2466 /* codegen.cc in Sources */,
+				89495E490E79FC23001F68C3 /* compilation-cache.cc in Sources */,
+				89F23C4C0E78D5B2006B2466 /* compiler.cc in Sources */,
+				89F23C4D0E78D5B2006B2466 /* contexts.cc in Sources */,
+				89F23C4E0E78D5B2006B2466 /* conversions.cc in Sources */,
+				89F23C4F0E78D5B2006B2466 /* counters.cc in Sources */,
+				89F23C9A0E78D5EC006B2466 /* cpu-arm.cc in Sources */,
+				89F23C510E78D5B2006B2466 /* dateparser.cc in Sources */,
+				894599A30F5D8729008DA8FB /* debug-agent.cc in Sources */,
+				898BD20F0EF6CC9A0068B00A /* debug-arm.cc in Sources */,
+				89F23C520E78D5B2006B2466 /* debug.cc in Sources */,
+				89F23C9B0E78D5EE006B2466 /* disasm-arm.cc in Sources */,
+				89F23C540E78D5B2006B2466 /* disassembler.cc in Sources */,
+				89F23C550E78D5B2006B2466 /* dtoa-config.c in Sources */,
+				89F23C560E78D5B2006B2466 /* execution.cc in Sources */,
+				89F23C570E78D5B2006B2466 /* factory.cc in Sources */,
+				89F23C580E78D5B2006B2466 /* flags.cc in Sources */,
+				89F23C9C0E78D5F1006B2466 /* frames-arm.cc in Sources */,
+				89F23C5A0E78D5B2006B2466 /* frames.cc in Sources */,
+				9F92FAAA0F8F28AD0089F02C /* func-name-inferrer.cc in Sources */,
+				89F23C5B0E78D5B2006B2466 /* global-handles.cc in Sources */,
+				89F23C5C0E78D5B2006B2466 /* handles.cc in Sources */,
+				89F23C5D0E78D5B2006B2466 /* hashmap.cc in Sources */,
+				89F23C5E0E78D5B2006B2466 /* heap.cc in Sources */,
+				89F23C9D0E78D5FB006B2466 /* ic-arm.cc in Sources */,
+				89F23C600E78D5B2006B2466 /* ic.cc in Sources */,
+				890A13FE0EE9C47F00E49346 /* interpreter-irregexp.cc in Sources */,
+				89F23C610E78D5B2006B2466 /* jsregexp.cc in Sources */,
+				58950D600F5551A300F3E8BA /* jump-target.cc in Sources */,
+				58950D610F5551A400F3E8BA /* jump-target-arm.cc in Sources */,
+				89F23C620E78D5B2006B2466 /* libraries.cc in Sources */,
+				89F23C630E78D5B2006B2466 /* log.cc in Sources */,
+				89F23C9E0E78D5FD006B2466 /* macro-assembler-arm.cc in Sources */,
+				89F23C650E78D5B2006B2466 /* mark-compact.cc in Sources */,
+				89F23C660E78D5B2006B2466 /* messages.cc in Sources */,
+				89F23C670E78D5B2006B2466 /* objects-debug.cc in Sources */,
+				89F23C680E78D5B2006B2466 /* objects.cc in Sources */,
+				9FC86ABE0F5FEDAC00F22668 /* oprofile-agent.cc in Sources */,
+				89F23C690E78D5B2006B2466 /* parser.cc in Sources */,
+				893A72250F7B101B00303DD2 /* platform-posix.cc in Sources */,
+				89F23C6A0E78D5B2006B2466 /* platform-macos.cc in Sources */,
+				89F23C6B0E78D5B2006B2466 /* prettyprinter.cc in Sources */,
+				89F23C6C0E78D5B2006B2466 /* property.cc in Sources */,
+				890A14010EE9C4B000E49346 /* regexp-macro-assembler-arm.cc in Sources */,
+				890A14020EE9C4B400E49346 /* regexp-macro-assembler-irregexp.cc in Sources */,
+				890A14030EE9C4B500E49346 /* regexp-macro-assembler-tracer.cc in Sources */,
+				890A14040EE9C4B700E49346 /* regexp-macro-assembler.cc in Sources */,
+				8944AD110F1D4D570028D560 /* regexp-stack.cc in Sources */,
+				58950D640F5551B500F3E8BA /* register-allocator.cc in Sources */,
+				58950D650F5551B600F3E8BA /* register-allocator-arm.cc in Sources */,
+				89F23C6D0E78D5B2006B2466 /* rewriter.cc in Sources */,
+				89F23C6E0E78D5B2006B2466 /* runtime.cc in Sources */,
+				89F23C6F0E78D5B2006B2466 /* scanner.cc in Sources */,
+				89F23C700E78D5B2006B2466 /* scopeinfo.cc in Sources */,
+				89F23C710E78D5B2006B2466 /* scopes.cc in Sources */,
+				89F23C720E78D5B2006B2466 /* serialize.cc in Sources */,
+				89F23C9F0E78D604006B2466 /* simulator-arm.cc in Sources */,
+				89F23C730E78D5B2006B2466 /* snapshot-common.cc in Sources */,
+				89F23C740E78D5B2006B2466 /* snapshot-empty.cc in Sources */,
+				89F23C750E78D5B2006B2466 /* spaces.cc in Sources */,
+				89F23C760E78D5B2006B2466 /* string-stream.cc in Sources */,
+				89F23CA00E78D609006B2466 /* stub-cache-arm.cc in Sources */,
+				89F23C780E78D5B2006B2466 /* stub-cache.cc in Sources */,
+				89F23C790E78D5B2006B2466 /* token.cc in Sources */,
+				89F23C7A0E78D5B2006B2466 /* top.cc in Sources */,
+				89F23C7B0E78D5B2006B2466 /* unicode.cc in Sources */,
+				89F23C7C0E78D5B2006B2466 /* usage-analyzer.cc in Sources */,
+				89F23C7D0E78D5B2006B2466 /* utils.cc in Sources */,
+				89F23C7E0E78D5B2006B2466 /* v8-counters.cc in Sources */,
+				89F23C7F0E78D5B2006B2466 /* v8.cc in Sources */,
+				89F23C800E78D5B2006B2466 /* v8threads.cc in Sources */,
+				89F23C810E78D5B2006B2466 /* variables.cc in Sources */,
+				58950D680F5551CB00F3E8BA /* virtual-frame.cc in Sources */,
+				58950D690F5551CE00F3E8BA /* virtual-frame-arm.cc in Sources */,
+				89F23C820E78D5B2006B2466 /* zone.cc in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		89F23C8D0E78D5B6006B2466 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				89F23C8E0E78D5B6006B2466 /* shell.cc in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+		7BF891970E73099F000BAF8A /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 8970F2EF0E719FB2006AE7B5 /* v8 */;
+			targetProxy = 7BF891960E73099F000BAF8A /* PBXContainerItemProxy */;
+		};
+		7BF891990E73099F000BAF8A /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 897F76790E71B4CC007ACF34 /* v8_shell */;
+			targetProxy = 7BF891980E73099F000BAF8A /* PBXContainerItemProxy */;
+		};
+		893988010F2A35FA007D5254 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 8970F2EF0E719FB2006AE7B5 /* v8 */;
+			targetProxy = 893988020F2A35FA007D5254 /* PBXContainerItemProxy */;
+		};
+		893988100F2A3647007D5254 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 893987FE0F2A35FA007D5254 /* d8_shell */;
+			targetProxy = 8939880F0F2A3647007D5254 /* PBXContainerItemProxy */;
+		};
+		896FD03C0E78D71F003DFB6A /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 89F23C3C0E78D5B2006B2466 /* v8-arm */;
+			targetProxy = 896FD03B0E78D71F003DFB6A /* PBXContainerItemProxy */;
+		};
+		896FD03E0E78D731003DFB6A /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 89F23C3C0E78D5B2006B2466 /* v8-arm */;
+			targetProxy = 896FD03D0E78D731003DFB6A /* PBXContainerItemProxy */;
+		};
+		896FD0400E78D735003DFB6A /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 89F23C880E78D5B6006B2466 /* v8_shell-arm */;
+			targetProxy = 896FD03F0E78D735003DFB6A /* PBXContainerItemProxy */;
+		};
+		897F76830E71B6AC007ACF34 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 8970F2EF0E719FB2006AE7B5 /* v8 */;
+			targetProxy = 897F76820E71B6AC007ACF34 /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+		7BF891940E73098D000BAF8A /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				PRODUCT_NAME = All;
+			};
+			name = Debug;
+		};
+		7BF891950E73098D000BAF8A /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				PRODUCT_NAME = All;
+			};
+			name = Release;
+		};
+		8915B8690E719336009C4E19 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				COPY_PHASE_STRIP = NO;
+				GCC_CW_ASM_SYNTAX = NO;
+				GCC_C_LANGUAGE_STANDARD = ansi;
+				GCC_DYNAMIC_NO_PIC = YES;
+				GCC_ENABLE_CPP_EXCEPTIONS = NO;
+				GCC_ENABLE_CPP_RTTI = NO;
+				GCC_ENABLE_PASCAL_STRINGS = NO;
+				GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"$(GCC_PREPROCESSOR_DEFINITIONS)",
+					DEBUG,
+				);
+				GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
+				GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
+				OTHER_CFLAGS = (
+					"$(OTHER_CFLAGS)",
+					"-fstack-protector",
+					"-fstack-protector-all",
+				);
+				PREBINDING = NO;
+				SYMROOT = ../xcodebuild;
+				USE_HEADERMAP = NO;
+				WARNING_CFLAGS = (
+					"$(WARNING_CFLAGS)",
+					"-Wall",
+					"-Wendif-labels",
+				);
+			};
+			name = Debug;
+		};
+		8915B86A0E719336009C4E19 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				DEAD_CODE_STRIPPING = YES;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				DEPLOYMENT_POSTPROCESSING = YES;
+				GCC_CW_ASM_SYNTAX = NO;
+				GCC_C_LANGUAGE_STANDARD = ansi;
+				GCC_DYNAMIC_NO_PIC = YES;
+				GCC_ENABLE_CPP_EXCEPTIONS = NO;
+				GCC_ENABLE_CPP_RTTI = NO;
+				GCC_ENABLE_PASCAL_STRINGS = NO;
+				GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
+				GCC_OPTIMIZATION_LEVEL = 2;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"$(GCC_PREPROCESSOR_DEFINITIONS)",
+					NDEBUG,
+				);
+				GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+				GCC_TREAT_WARNINGS_AS_ERRORS = NO;
+				GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
+				PREBINDING = NO;
+				STRIP_STYLE = all;
+				SYMROOT = ../xcodebuild;
+				USE_HEADERMAP = NO;
+				WARNING_CFLAGS = (
+					"$(WARNING_CFLAGS)",
+					"-Wall",
+					"-Wendif-labels",
+				);
+			};
+			name = Release;
+		};
+		893988090F2A35FA007D5254 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				HEADER_SEARCH_PATHS = ../src;
+				PRODUCT_NAME = v8_shell;
+			};
+			name = Debug;
+		};
+		8939880A0F2A35FA007D5254 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				HEADER_SEARCH_PATHS = ../src;
+				PRODUCT_NAME = v8_shell;
+			};
+			name = Release;
+		};
+		8970F2F10E719FB2006AE7B5 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DEPLOYMENT_POSTPROCESSING = NO;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"$(GCC_PREPROCESSOR_DEFINITIONS)",
+					ENABLE_DISASSEMBLER,
+					ENABLE_LOGGING_AND_PROFILING,
+				);
+				HEADER_SEARCH_PATHS = ../src;
+				PRODUCT_NAME = v8;
+				STRIP_STYLE = debugging;
+			};
+			name = Debug;
+		};
+		8970F2F20E719FB2006AE7B5 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DEPLOYMENT_POSTPROCESSING = NO;
+				HEADER_SEARCH_PATHS = ../src;
+				PRODUCT_NAME = v8;
+				STRIP_STYLE = debugging;
+			};
+			name = Release;
+		};
+		897F767C0E71B4CC007ACF34 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				HEADER_SEARCH_PATHS = ../src;
+				PRODUCT_NAME = v8_shell;
+			};
+			name = Debug;
+		};
+		897F767D0E71B4CC007ACF34 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				HEADER_SEARCH_PATHS = ../src;
+				PRODUCT_NAME = v8_shell;
+			};
+			name = Release;
+		};
+		89F23C850E78D5B2006B2466 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DEPLOYMENT_POSTPROCESSING = NO;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"$(GCC_PREPROCESSOR_DEFINITIONS)",
+					ARM,
+					ENABLE_DISASSEMBLER,
+					ENABLE_LOGGING_AND_PROFILING,
+				);
+				HEADER_SEARCH_PATHS = ../src;
+				PRODUCT_NAME = "v8-arm";
+				STRIP_STYLE = debugging;
+			};
+			name = Debug;
+		};
+		89F23C860E78D5B2006B2466 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DEPLOYMENT_POSTPROCESSING = NO;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"$(GCC_PREPROCESSOR_DEFINITIONS)",
+					ARM,
+				);
+				HEADER_SEARCH_PATHS = ../src;
+				PRODUCT_NAME = "v8-arm";
+				STRIP_STYLE = debugging;
+			};
+			name = Release;
+		};
+		89F23C930E78D5B6006B2466 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				HEADER_SEARCH_PATHS = ../src;
+				PRODUCT_NAME = "v8_shell-arm";
+			};
+			name = Debug;
+		};
+		89F23C940E78D5B6006B2466 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				HEADER_SEARCH_PATHS = ../src;
+				PRODUCT_NAME = "v8_shell-arm";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		7BF8919F0E7309BE000BAF8A /* Build configuration list for PBXAggregateTarget "All" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				7BF891940E73098D000BAF8A /* Debug */,
+				7BF891950E73098D000BAF8A /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		8915B86B0E719336009C4E19 /* Build configuration list for PBXProject "v8" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				8915B8690E719336009C4E19 /* Debug */,
+				8915B86A0E719336009C4E19 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		893988080F2A35FA007D5254 /* Build configuration list for PBXNativeTarget "d8_shell" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				893988090F2A35FA007D5254 /* Debug */,
+				8939880A0F2A35FA007D5254 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		8970F2F70E719FC1006AE7B5 /* Build configuration list for PBXNativeTarget "v8" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				8970F2F10E719FB2006AE7B5 /* Debug */,
+				8970F2F20E719FB2006AE7B5 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		897F767E0E71B4EA007ACF34 /* Build configuration list for PBXNativeTarget "v8_shell" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				897F767C0E71B4CC007ACF34 /* Debug */,
+				897F767D0E71B4CC007ACF34 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		89F23C840E78D5B2006B2466 /* Build configuration list for PBXNativeTarget "v8-arm" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				89F23C850E78D5B2006B2466 /* Debug */,
+				89F23C860E78D5B2006B2466 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		89F23C920E78D5B6006B2466 /* Build configuration list for PBXNativeTarget "v8_shell-arm" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				89F23C930E78D5B6006B2466 /* Debug */,
+				89F23C940E78D5B6006B2466 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 8915B8680E719336009C4E19 /* Project object */;
+}
diff --git a/deps/v8/tools/visual_studio/README.txt b/deps/v8/tools/visual_studio/README.txt
new file mode 100644
index 0000000..dd9802b
--- /dev/null
+++ b/deps/v8/tools/visual_studio/README.txt
@@ -0,0 +1,71 @@
+This directory contains Microsoft Visual Studio project files for including v8
+in a Visual Studio/Visual C++ Express solution. All these project files have
+been created for use with Microsoft Visual Studio 2005. They can however also
+be used in both Visual Studio 2008 and Visual C++ 2008 Express Edition. When
+using the project files in the 2008 editions minor upgrades to the files will
+be performed by Visual Studio.
+
+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).
+
+v8.vcproj
+---------
+V8 library containing all the V8 and JavaScript library code embedded as source
+which is compiled as V8 is running.
+
+v8_mksnapshot.vcproj
+--------------------
+Executable v8_mksnapshot.exe for building a heap snapshot from a running V8.
+
+v8_snapshot_cc.vcproj
+---------------------
+Uses v8_mksnapshot.exe to generate snapshot.cc, which is used in
+v8_snapshot.vcproj.
+
+v8_snapshot.vcproj
+------------------
+V8 library containing all the V8 and JavaScript library code embedded as a heap
+snapshot instead of source to be compiled as V8 is running. Using this library
+provides significantly faster startup time than v8.vcproj.
+
+The property sheets common.vsprops, debug.vsprops and release.vsprops contains
+most of the configuration options and are inhireted by the project files
+described above. The location of the output directory used are defined in
+common.vsprops.
+
+With regard to Platform SDK version V8 has no specific requriments and builds
+with either what is supplied with Visual Studio 2005 or the latest Platform SDK
+from Microsoft.
+
+When adding these projects to a solution the following dependencies needs to be
+in place:
+
+  v8.vcproj depends on v8_base.vcproj
+  v8_mksnapshot.vcproj depends on v8.vcproj
+  v8_snapshot_cc.vcproj depends on v8_mksnapshot.vcproj
+  v8_snapshot.vcproj depends on v8_snapshot_cc.vcproj and v8_base.vcproj
+
+A project which uses V8 should then depend on v8_snapshot.vcproj.
+
+If V8 without snapshot if preferred only v8_base.vcproj and v8.vcproj are
+required and a project which uses V8 should depend on v8.vcproj.
+
+Two sample project files are available as well. These are v8_shell_sample.vcproj
+for building the sample in samples\shell.cc and v8_process_sample.vcproj for
+building the sample in samples\process.cc. Add either of these (or both) to a
+solution with v8_base, v8, v8_mksnapshot and v8_snapshot set up as described
+solution with v8_base, v8, v8_mksnapshot and v8_snapshot set up as described
+above and have them depend on v8_snapshot.
+
+Finally a sample Visual Studio solution file for is provided. This solution file
+includes the two sample projects together with the V8 projects and with the
+dependencies configured as described above.
+
+Python requirements
+-------------------
+When using the Microsoft Visual Studio project files Python version 2.4 or later
+is required. Make sure that python.exe is on the path before running Visual
+Studio. The use of Python is in the command script js2c.cmd which is used in the
+Custom Build Step for v8natives.js in the v8.vcproj project.
diff --git a/deps/v8/tools/visual_studio/arm.vsprops b/deps/v8/tools/visual_studio/arm.vsprops
new file mode 100644
index 0000000..0e37d41
--- /dev/null
+++ b/deps/v8/tools/visual_studio/arm.vsprops
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="arm"
+	>
+	<Tool
+		Name="VCCLCompilerTool"
+		PreprocessorDefinitions="ARM"
+		DisableSpecificWarnings="4996"
+	/>
+</VisualStudioPropertySheet>
diff --git a/deps/v8/tools/visual_studio/common.vsprops b/deps/v8/tools/visual_studio/common.vsprops
new file mode 100644
index 0000000..f131a4a
--- /dev/null
+++ b/deps/v8/tools/visual_studio/common.vsprops
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="essential"
+	OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+	IntermediateDirectory="$(SolutionDir)$(ConfigurationName)\obj\$(ProjectName)"
+	CharacterSet="1"
+	>
+	<Tool
+		Name="VCCLCompilerTool"
+		AdditionalIncludeDirectories="$(ProjectDir)\..\..\src;$(IntDir)\DerivedSources"
+		PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T;_HAS_EXCEPTIONS=0;ENABLE_LOGGING_AND_PROFILING"
+		MinimalRebuild="false"
+		ExceptionHandling="0"
+		RuntimeTypeInfo="false"
+		WarningLevel="3"
+		WarnAsError="true"
+		Detect64BitPortabilityProblems="false"
+		DebugInformationFormat="3"
+		DisableSpecificWarnings="4355;4800"
+		EnableFunctionLevelLinking="true"
+	/>
+	<Tool
+		Name="VCLibrarianTool"
+		OutputFile="$(OutDir)\lib\$(ProjectName).lib"
+	/>
+	<Tool
+		Name="VCLinkerTool"
+		GenerateDebugInformation="true"
+		MapFileName="$(OutDir)\$(TargetName).map"
+		ImportLibrary="$(OutDir)\lib\$(TargetName).lib"
+		TargetMachine="1"
+		FixedBaseAddress="1"
+		AdditionalOptions="/IGNORE:4221 /NXCOMPAT"
+	/>
+</VisualStudioPropertySheet>
diff --git a/deps/v8/tools/visual_studio/d8.vcproj b/deps/v8/tools/visual_studio/d8.vcproj
new file mode 100644
index 0000000..a05a3f3
--- /dev/null
+++ b/deps/v8/tools/visual_studio/d8.vcproj
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="d8"
+	ProjectGUID="{7E4C7D2D-A4B9-40B9-8192-22654E626F6C}"
+	RootNamespace="d8"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			ConfigurationType="1"
+			InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="winmm.lib Ws2_32.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			ConfigurationType="1"
+			InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="winmm.lib Ws2_32.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<File
+			RelativePath="..\..\src\d8.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\src\d8.h"
+			>
+		</File>
+		<File
+			RelativePath="..\..\src\d8-debug.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\src\d8-debug.h"
+			>
+		</File>
+		<File
+			RelativePath="..\..\src\d8-windows.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\src\d8.js"
+			>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Processing js files..."
+						CommandLine=".\d8js2c.cmd ..\..\src &quot;$(IntDir)\DerivedSources&quot;"
+												Outputs="$(IntDir)\DerivedSources\natives.cc;$(IntDir)\DerivedSources\natives-empty.cc"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Processing js files..."
+						CommandLine=".\d8js2c.cmd ..\..\src &quot;$(IntDir)\DerivedSources&quot;"
+						Outputs="$(IntDir)\DerivedSources\natives.cc;$(IntDir)\DerivedSources\natives-empty.cc"
+					/>
+				</FileConfiguration>
+		</File>
+		<Filter
+			Name="generated files"
+			>
+			<File
+				RelativePath="$(IntDir)\DerivedSources\natives.cc"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/deps/v8/tools/visual_studio/d8js2c.cmd b/deps/v8/tools/visual_studio/d8js2c.cmd
new file mode 100644
index 0000000..04d8e26
--- /dev/null
+++ b/deps/v8/tools/visual_studio/d8js2c.cmd
@@ -0,0 +1,6 @@
+@echo off
+set SOURCE_DIR=%1
+set TARGET_DIR=%2
+set PYTHON="..\..\..\third_party\python_24\python.exe"
+if not exist %PYTHON% set PYTHON=python.exe
+%PYTHON% ..\js2c.py %TARGET_DIR%\natives.cc %TARGET_DIR%\natives-empty.cc D8 %SOURCE_DIR%\macros.py %SOURCE_DIR%\d8.js
diff --git a/deps/v8/tools/visual_studio/debug.vsprops b/deps/v8/tools/visual_studio/debug.vsprops
new file mode 100644
index 0000000..0abf924
--- /dev/null
+++ b/deps/v8/tools/visual_studio/debug.vsprops
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="debug"
+	>
+	<Tool
+		Name="VCCLCompilerTool"
+		Optimization="0"
+		PreprocessorDefinitions="DEBUG;_DEBUG;ENABLE_DISASSEMBLER"
+		RuntimeLibrary="1"
+	/>
+	<Tool
+		Name="VCLinkerTool"
+		LinkIncremental="2"
+	/>
+</VisualStudioPropertySheet>
diff --git a/deps/v8/tools/visual_studio/js2c.cmd b/deps/v8/tools/visual_studio/js2c.cmd
new file mode 100644
index 0000000..b6a46a2
--- /dev/null
+++ b/deps/v8/tools/visual_studio/js2c.cmd
@@ -0,0 +1,6 @@
+@echo off
+set SOURCE_DIR=%1
+set TARGET_DIR=%2
+set PYTHON="..\..\..\third_party\python_24\python.exe"
+if not exist %PYTHON% set PYTHON=python.exe
+%PYTHON% ..\js2c.py %TARGET_DIR%\natives.cc %TARGET_DIR%\natives-empty.cc CORE %SOURCE_DIR%\macros.py %SOURCE_DIR%\runtime.js %SOURCE_DIR%\v8natives.js %SOURCE_DIR%\array.js %SOURCE_DIR%\string.js %SOURCE_DIR%\uri.js %SOURCE_DIR%\math.js %SOURCE_DIR%\messages.js %SOURCE_DIR%\apinatives.js %SOURCE_DIR%\debug-delay.js %SOURCE_DIR%\mirror-delay.js %SOURCE_DIR%\date-delay.js %SOURCE_DIR%\regexp-delay.js
diff --git a/deps/v8/tools/visual_studio/release.vsprops b/deps/v8/tools/visual_studio/release.vsprops
new file mode 100644
index 0000000..d7b26bc
--- /dev/null
+++ b/deps/v8/tools/visual_studio/release.vsprops
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="release"
+	>
+	<Tool
+		Name="VCCLCompilerTool"
+		RuntimeLibrary="0"
+		Optimization="2"
+		InlineFunctionExpansion="2"
+		EnableIntrinsicFunctions="true"
+		FavorSizeOrSpeed="0"
+		OmitFramePointers="true"
+		StringPooling="true"
+	/>
+	<Tool
+		Name="VCLinkerTool"
+		LinkIncremental="1"
+		OptimizeReferences="2"
+		OptimizeForWindows98="1"
+		EnableCOMDATFolding="2"
+	/>
+</VisualStudioPropertySheet>
diff --git a/deps/v8/tools/visual_studio/v8.sln b/deps/v8/tools/visual_studio/v8.sln
new file mode 100644
index 0000000..db84858
--- /dev/null
+++ b/deps/v8/tools/visual_studio/v8.sln
@@ -0,0 +1,101 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_base", "v8_base.vcproj", "{EC8B7909-62AF-470D-A75D-E1D89C837142}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8", "v8.vcproj", "{21E22961-22BF-4493-BD3A-868F93DA5179}"
+	ProjectSection(ProjectDependencies) = postProject
+		{EC8B7909-62AF-470D-A75D-E1D89C837142} = {EC8B7909-62AF-470D-A75D-E1D89C837142}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_mksnapshot", "v8_mksnapshot.vcproj", "{865575D0-37E2-405E-8CBA-5F6C485B5A26}"
+	ProjectSection(ProjectDependencies) = postProject
+		{21E22961-22BF-4493-BD3A-868F93DA5179} = {21E22961-22BF-4493-BD3A-868F93DA5179}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_snapshot", "v8_snapshot.vcproj", "{C0334F9A-1168-4101-9DD8-C30FB252D435}"
+	ProjectSection(ProjectDependencies) = postProject
+		{0DDBDA8B-A49F-4CC7-A1D5-5BB8297C8A3F} = {0DDBDA8B-A49F-4CC7-A1D5-5BB8297C8A3F}
+		{EC8B7909-62AF-470D-A75D-E1D89C837142} = {EC8B7909-62AF-470D-A75D-E1D89C837142}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_shell_sample", "v8_shell_sample.vcproj", "{2DE20FFA-6F5E-48D9-84D8-09B044A5B119}"
+	ProjectSection(ProjectDependencies) = postProject
+		{C0334F9A-1168-4101-9DD8-C30FB252D435} = {C0334F9A-1168-4101-9DD8-C30FB252D435}
+	EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{E131F77D-B713-48F3-B86D-097ECDCC4C3A}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_process_sample", "v8_process_sample.vcproj", "{EF019874-D38A-40E3-B17C-DB5923F0A79C}"
+	ProjectSection(ProjectDependencies) = postProject
+		{C0334F9A-1168-4101-9DD8-C30FB252D435} = {C0334F9A-1168-4101-9DD8-C30FB252D435}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_cctest", "v8_cctest.vcproj", "{97ECC711-7430-4FC4-90FD-004DA880E72A}"
+	ProjectSection(ProjectDependencies) = postProject
+		{C0334F9A-1168-4101-9DD8-C30FB252D435} = {C0334F9A-1168-4101-9DD8-C30FB252D435}
+	EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{AD933CE2-1303-448E-89C8-60B1FDD18EC3}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "d8", "d8.vcproj", "{7E4C7D2D-A4B9-40B9-8192-22654E626F6C}"
+	ProjectSection(ProjectDependencies) = postProject
+		{C0334F9A-1168-4101-9DD8-C30FB252D435} = {C0334F9A-1168-4101-9DD8-C30FB252D435}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_snapshot_cc", "v8_snapshot_cc.vcproj", "{0DDBDA8B-A49F-4CC7-A1D5-5BB8297C8A3F}"
+	ProjectSection(ProjectDependencies) = postProject
+		{865575D0-37E2-405E-8CBA-5F6C485B5A26} = {865575D0-37E2-405E-8CBA-5F6C485B5A26}
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{0DDBDA8B-A49F-4CC7-A1D5-5BB8297C8A3F}.Debug|Win32.ActiveCfg = Debug|Win32
+		{0DDBDA8B-A49F-4CC7-A1D5-5BB8297C8A3F}.Debug|Win32.Build.0 = Debug|Win32
+		{0DDBDA8B-A49F-4CC7-A1D5-5BB8297C8A3F}.Release|Win32.ActiveCfg = Release|Win32
+		{0DDBDA8B-A49F-4CC7-A1D5-5BB8297C8A3F}.Release|Win32.Build.0 = Release|Win32
+		{21E22961-22BF-4493-BD3A-868F93DA5179}.Debug|Win32.ActiveCfg = Debug|Win32
+		{21E22961-22BF-4493-BD3A-868F93DA5179}.Debug|Win32.Build.0 = Debug|Win32
+		{21E22961-22BF-4493-BD3A-868F93DA5179}.Release|Win32.ActiveCfg = Release|Win32
+		{21E22961-22BF-4493-BD3A-868F93DA5179}.Release|Win32.Build.0 = Release|Win32
+		{2DE20FFA-6F5E-48D9-84D8-09B044A5B119}.Debug|Win32.ActiveCfg = Debug|Win32
+		{2DE20FFA-6F5E-48D9-84D8-09B044A5B119}.Debug|Win32.Build.0 = Debug|Win32
+		{2DE20FFA-6F5E-48D9-84D8-09B044A5B119}.Release|Win32.ActiveCfg = Release|Win32
+		{2DE20FFA-6F5E-48D9-84D8-09B044A5B119}.Release|Win32.Build.0 = Release|Win32
+		{7E4C7D2D-A4B9-40B9-8192-22654E626F6C}.Debug|Win32.ActiveCfg = Debug|Win32
+		{7E4C7D2D-A4B9-40B9-8192-22654E626F6C}.Debug|Win32.Build.0 = Debug|Win32
+		{7E4C7D2D-A4B9-40B9-8192-22654E626F6C}.Release|Win32.ActiveCfg = Release|Win32
+		{7E4C7D2D-A4B9-40B9-8192-22654E626F6C}.Release|Win32.Build.0 = Release|Win32
+		{865575D0-37E2-405E-8CBA-5F6C485B5A26}.Debug|Win32.ActiveCfg = Debug|Win32
+		{865575D0-37E2-405E-8CBA-5F6C485B5A26}.Debug|Win32.Build.0 = Debug|Win32
+		{865575D0-37E2-405E-8CBA-5F6C485B5A26}.Release|Win32.ActiveCfg = Release|Win32
+		{865575D0-37E2-405E-8CBA-5F6C485B5A26}.Release|Win32.Build.0 = Release|Win32
+		{97ECC711-7430-4FC4-90FD-004DA880E72A}.Debug|Win32.ActiveCfg = Debug|Win32
+		{97ECC711-7430-4FC4-90FD-004DA880E72A}.Debug|Win32.Build.0 = Debug|Win32
+		{97ECC711-7430-4FC4-90FD-004DA880E72A}.Release|Win32.ActiveCfg = Release|Win32
+		{97ECC711-7430-4FC4-90FD-004DA880E72A}.Release|Win32.Build.0 = Release|Win32
+		{C0334F9A-1168-4101-9DD8-C30FB252D435}.Debug|Win32.ActiveCfg = Debug|Win32
+		{C0334F9A-1168-4101-9DD8-C30FB252D435}.Debug|Win32.Build.0 = Debug|Win32
+		{C0334F9A-1168-4101-9DD8-C30FB252D435}.Release|Win32.ActiveCfg = Release|Win32
+		{C0334F9A-1168-4101-9DD8-C30FB252D435}.Release|Win32.Build.0 = Release|Win32
+		{EC8B7909-62AF-470D-A75D-E1D89C837142}.Debug|Win32.ActiveCfg = Debug|Win32
+		{EC8B7909-62AF-470D-A75D-E1D89C837142}.Debug|Win32.Build.0 = Debug|Win32
+		{EC8B7909-62AF-470D-A75D-E1D89C837142}.Release|Win32.ActiveCfg = Release|Win32
+		{EC8B7909-62AF-470D-A75D-E1D89C837142}.Release|Win32.Build.0 = Release|Win32
+		{EF019874-D38A-40E3-B17C-DB5923F0A79C}.Debug|Win32.ActiveCfg = Debug|Win32
+		{EF019874-D38A-40E3-B17C-DB5923F0A79C}.Debug|Win32.Build.0 = Debug|Win32
+		{EF019874-D38A-40E3-B17C-DB5923F0A79C}.Release|Win32.ActiveCfg = Release|Win32
+		{EF019874-D38A-40E3-B17C-DB5923F0A79C}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(NestedProjects) = preSolution
+		{2DE20FFA-6F5E-48D9-84D8-09B044A5B119} = {E131F77D-B713-48F3-B86D-097ECDCC4C3A}
+		{97ECC711-7430-4FC4-90FD-004DA880E72A} = {AD933CE2-1303-448E-89C8-60B1FDD18EC3}
+		{EF019874-D38A-40E3-B17C-DB5923F0A79C} = {E131F77D-B713-48F3-B86D-097ECDCC4C3A}
+	EndGlobalSection
+EndGlobal
diff --git a/deps/v8/tools/visual_studio/v8.vcproj b/deps/v8/tools/visual_studio/v8.vcproj
new file mode 100644
index 0000000..212fd07
--- /dev/null
+++ b/deps/v8/tools/visual_studio/v8.vcproj
@@ -0,0 +1,219 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="v8"
+	ProjectGUID="{21E22961-22BF-4493-BD3A-868F93DA5179}"
+	RootNamespace="v8"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			ConfigurationType="4"
+			InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				LinkLibraryDependencies="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			ConfigurationType="4"
+			InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				LinkLibraryDependencies="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="js"
+			>
+			<File
+				RelativePath="..\..\src\apinatives.js"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\array.js"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\date-delay.js"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\debug-delay.js"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\macros.py"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\math.js"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\messages.js"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\mirror-delay.js"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-delay.js"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\runtime.js"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\string.js"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\uri.js"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\v8natives.js"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Processing js files..."
+						CommandLine=".\js2c.cmd ..\..\src &quot;$(IntDir)\DerivedSources&quot;"
+						AdditionalDependencies="..\..\src\macros.py;..\..\src\runtime.js;..\..\src\v8natives.js;..\..\src\array.js;..\..\src\string.js;..\..\src\uri.js;..\..\src\math.js;..\..\src\messages.js;..\..\src\apinatives.js;..\..\src\debug-delay.js;..\..\src\mirror-delay.js;..\..\src\date-delay.js;..\..\src\regexp-delay.js"
+						Outputs="$(IntDir)\DerivedSources\natives.cc;$(IntDir)\DerivedSources\natives-empty.cc"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Processing js files..."
+						CommandLine=".\js2c.cmd ..\..\src &quot;$(IntDir)\DerivedSources&quot;"
+						AdditionalDependencies="..\..\src\macros.py;..\..\src\runtime.js;..\..\src\v8natives.js;..\..\src\array.js;..\..\src\string.js;..\..\src\uri.js;..\..\src\math.js;..\..\src\messages.js;..\..\src\apinatives.js;..\..\src\debug-delay.js;..\..\src\mirror-delay.js;..\..\src\date-delay.js;..\..\src\regexp-delay.js"
+						Outputs="$(IntDir)\DerivedSources\natives.cc;$(IntDir)\DerivedSources\natives-empty.cc"
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+		<Filter
+			Name="generated files"
+			>
+			<File
+				RelativePath="$(IntDir)\DerivedSources\natives.cc"
+				>
+			</File>
+		</Filter>
+		<File
+			RelativePath="..\..\src\snapshot-empty.cc"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/deps/v8/tools/visual_studio/v8_arm.sln b/deps/v8/tools/visual_studio/v8_arm.sln
new file mode 100644
index 0000000..2dc6cf5
--- /dev/null
+++ b/deps/v8/tools/visual_studio/v8_arm.sln
@@ -0,0 +1,74 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8", "v8.vcproj", "{21E22961-22BF-4493-BD3A-868F93DA5179}"
+	ProjectSection(ProjectDependencies) = postProject
+		{EC8B7909-62AF-470D-A75D-E1D89C837142} = {EC8B7909-62AF-470D-A75D-E1D89C837142}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_shell_sample", "v8_shell_sample.vcproj", "{2DE20FFA-6F5E-48D9-84D8-09B044A5B119}"
+	ProjectSection(ProjectDependencies) = postProject
+		{EC8B7909-62AF-470D-A75D-E1D89C837142} = {EC8B7909-62AF-470D-A75D-E1D89C837142}
+		{21E22961-22BF-4493-BD3A-868F93DA5179} = {21E22961-22BF-4493-BD3A-868F93DA5179}
+	EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{E131F77D-B713-48F3-B86D-097ECDCC4C3A}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_process_sample", "v8_process_sample.vcproj", "{EF019874-D38A-40E3-B17C-DB5923F0A79C}"
+	ProjectSection(ProjectDependencies) = postProject
+		{21E22961-22BF-4493-BD3A-868F93DA5179} = {21E22961-22BF-4493-BD3A-868F93DA5179}
+	EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{AD933CE2-1303-448E-89C8-60B1FDD18EC3}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "d8", "d8.vcproj", "{7E4C7D2D-A4B9-40B9-8192-22654E626F6C}"
+	ProjectSection(ProjectDependencies) = postProject
+		{21E22961-22BF-4493-BD3A-868F93DA5179} = {21E22961-22BF-4493-BD3A-868F93DA5179}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_base", "v8_base_arm.vcproj", "{EC8B7909-62AF-470D-A75D-E1D89C837142}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_cctest", "v8_cctest_arm.vcproj", "{97ECC711-7430-4FC4-90FD-004DA880E72A}"
+	ProjectSection(ProjectDependencies) = postProject
+		{21E22961-22BF-4493-BD3A-868F93DA5179} = {21E22961-22BF-4493-BD3A-868F93DA5179}
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{21E22961-22BF-4493-BD3A-868F93DA5179}.Debug|Win32.ActiveCfg = Debug|Win32
+		{21E22961-22BF-4493-BD3A-868F93DA5179}.Debug|Win32.Build.0 = Debug|Win32
+		{21E22961-22BF-4493-BD3A-868F93DA5179}.Release|Win32.ActiveCfg = Release|Win32
+		{21E22961-22BF-4493-BD3A-868F93DA5179}.Release|Win32.Build.0 = Release|Win32
+		{2DE20FFA-6F5E-48D9-84D8-09B044A5B119}.Debug|Win32.ActiveCfg = Debug|Win32
+		{2DE20FFA-6F5E-48D9-84D8-09B044A5B119}.Debug|Win32.Build.0 = Debug|Win32
+		{2DE20FFA-6F5E-48D9-84D8-09B044A5B119}.Release|Win32.ActiveCfg = Release|Win32
+		{2DE20FFA-6F5E-48D9-84D8-09B044A5B119}.Release|Win32.Build.0 = Release|Win32
+		{EF019874-D38A-40E3-B17C-DB5923F0A79C}.Debug|Win32.ActiveCfg = Debug|Win32
+		{EF019874-D38A-40E3-B17C-DB5923F0A79C}.Debug|Win32.Build.0 = Debug|Win32
+		{EF019874-D38A-40E3-B17C-DB5923F0A79C}.Release|Win32.ActiveCfg = Release|Win32
+		{EF019874-D38A-40E3-B17C-DB5923F0A79C}.Release|Win32.Build.0 = Release|Win32
+		{7E4C7D2D-A4B9-40B9-8192-22654E626F6C}.Debug|Win32.ActiveCfg = Debug|Win32
+		{7E4C7D2D-A4B9-40B9-8192-22654E626F6C}.Debug|Win32.Build.0 = Debug|Win32
+		{7E4C7D2D-A4B9-40B9-8192-22654E626F6C}.Release|Win32.ActiveCfg = Release|Win32
+		{7E4C7D2D-A4B9-40B9-8192-22654E626F6C}.Release|Win32.Build.0 = Release|Win32
+		{EC8B7909-62AF-470D-A75D-E1D89C837142}.Debug|Win32.ActiveCfg = Debug|Win32
+		{EC8B7909-62AF-470D-A75D-E1D89C837142}.Debug|Win32.Build.0 = Debug|Win32
+		{EC8B7909-62AF-470D-A75D-E1D89C837142}.Release|Win32.ActiveCfg = Release|Win32
+		{EC8B7909-62AF-470D-A75D-E1D89C837142}.Release|Win32.Build.0 = Release|Win32
+		{97ECC711-7430-4FC4-90FD-004DA880E72A}.Debug|Win32.ActiveCfg = Debug|Win32
+		{97ECC711-7430-4FC4-90FD-004DA880E72A}.Debug|Win32.Build.0 = Debug|Win32
+		{97ECC711-7430-4FC4-90FD-004DA880E72A}.Release|Win32.ActiveCfg = Release|Win32
+		{97ECC711-7430-4FC4-90FD-004DA880E72A}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(NestedProjects) = preSolution
+		{2DE20FFA-6F5E-48D9-84D8-09B044A5B119} = {E131F77D-B713-48F3-B86D-097ECDCC4C3A}
+		{EF019874-D38A-40E3-B17C-DB5923F0A79C} = {E131F77D-B713-48F3-B86D-097ECDCC4C3A}
+		{97ECC711-7430-4FC4-90FD-004DA880E72A} = {AD933CE2-1303-448E-89C8-60B1FDD18EC3}
+	EndGlobalSection
+EndGlobal
diff --git a/deps/v8/tools/visual_studio/v8_base.vcproj b/deps/v8/tools/visual_studio/v8_base.vcproj
new file mode 100644
index 0000000..776e628
--- /dev/null
+++ b/deps/v8/tools/visual_studio/v8_base.vcproj
@@ -0,0 +1,923 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="v8_base"
+	ProjectGUID="{EC8B7909-62AF-470D-A75D-E1D89C837142}"
+	RootNamespace="v8_base"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			ConfigurationType="4"
+			InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			ConfigurationType="4"
+			InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</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
+				RelativePath="..\..\src\accessors.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\accessors.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\allocation.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\allocation.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\api.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\api.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\arguments.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\assembler-ia32-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\assembler-ia32.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\assembler-ia32.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-macro-assembler-irregexp-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-stack.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\assembler.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\assembler.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\ast.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\ast.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\bootstrapper.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\bootstrapper.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\builtins-ia32.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\builtins.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\builtins.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\bytecodes-irregexp.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\char-predicates-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\char-predicates.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\checks.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\checks.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\code-stubs.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\code-stubs.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\code.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\codegen-ia32.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\codegen-ia32.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\codegen-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\codegen.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\codegen.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\compilation-cache.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\compilation-cache.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\compiler.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\compiler.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\contexts.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\contexts.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\conversions-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\conversions.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\conversions.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\counters.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\counters.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\cpu-ia32.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\cpu.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\dateparser.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\dateparser.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\debug-agent.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\debug-agent.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\debug-ia32.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\debug.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\debug.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\disassembler.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\disassembler.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\execution.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\execution.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\factory.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\factory.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\flags.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\flags.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\frames-ia32.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\frames-ia32.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\frames-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\frames.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\frames.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\func-name-inferrer.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\func-name-inferrer.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\global-handles.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\global-handles.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\globals.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\handles-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\handles.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\handles.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\hashmap.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\hashmap.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\heap-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\heap.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\heap.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\ic-ia32.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\ic-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\ic.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\ic.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\interceptors.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\interpreter-irregexp.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\interpreter-irregexp.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\jump-target.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\jump-target.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\jump-target-ia32.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\jsregexp-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\jsregexp.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\jsregexp.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\list-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\list.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\log.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\log.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\macro-assembler-ia32.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\macro-assembler-ia32.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\macro-assembler.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\mark-compact.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\mark-compact.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\memory.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\messages.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\messages.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\natives.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\objects-debug.cc"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\src\objects-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\objects.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\objects.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\oprofile-agent.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\oprofile-agent.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\parser.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\parser.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\platform-win32.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\platform.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\prettyprinter.cc"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\src\prettyprinter.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\property.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\property.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-macro-assembler-ia32.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-macro-assembler-ia32.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-macro-assembler-irregexp.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-macro-assembler-irregexp.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-macro-assembler.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-macro-assembler.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-macro-assembler-tracer.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-macro-assembler-tracer.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-stack.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\register-allocator.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\register-allocator.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\register-allocator-ia32.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\rewriter.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\rewriter.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\runtime.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\runtime.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\scanner.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\scanner.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\scopeinfo.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\scopeinfo.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\scopes.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\scopes.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\serialize.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\serialize.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\shell.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\snapshot-common.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\snapshot.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\spaces-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\spaces.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\spaces.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\string-stream.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\string-stream.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\stub-cache-ia32.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\stub-cache.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\stub-cache.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\token.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\token.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\top.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\top.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\unicode-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\unicode.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\usage-analyzer.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\usage-analyzer.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\utils.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\utils.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\v8-counters.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\v8-counters.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\v8.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\v8.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\v8threads.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\v8threads.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\variables.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\variables.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\virtual-frame.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\virtual-frame-ia32.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\virtual-frame.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\virtual-frame-ia32.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\zone-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\zone.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\zone.h"
+				>
+			</File>
+			<Filter
+				Name="third party"
+				>
+				<File
+					RelativePath="..\..\src\disasm-ia32.cc"
+					>
+				</File>
+				<File
+					RelativePath="..\..\src\disasm.h"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="generated files"
+				>
+				<File
+					RelativePath="..\..\src\unicode.cc"
+					>
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="include"
+			>
+			<File
+				RelativePath="..\..\include\debug.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\include\v8.h"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/deps/v8/tools/visual_studio/v8_base_arm.vcproj b/deps/v8/tools/visual_studio/v8_base_arm.vcproj
new file mode 100644
index 0000000..a91d63a
--- /dev/null
+++ b/deps/v8/tools/visual_studio/v8_base_arm.vcproj
@@ -0,0 +1,919 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="v8_base"
+	ProjectGUID="{EC8B7909-62AF-470D-A75D-E1D89C837142}"
+	RootNamespace="v8_base"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			ConfigurationType="4"
+			InheritedPropertySheets=".\common.vsprops;.\debug.vsprops;.\arm.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			ConfigurationType="4"
+			InheritedPropertySheets=".\common.vsprops;.\release.vsprops;.\arm.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</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
+				RelativePath="..\..\src\accessors.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\accessors.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\allocation.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\allocation.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\api.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\api.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\arguments.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\assembler-arm-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\assembler-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\assembler-arm.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-stack.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-macro-assembler-irregexp-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\assembler.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\assembler.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\ast.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\ast.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\bootstrapper.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\bootstrapper.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\builtins-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\builtins.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\builtins.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\bytecodes-irregexp.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\char-predicates-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\char-predicates.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\checks.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\checks.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\code-stubs.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\code-stubs.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\code.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\codegen-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\codegen-arm.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\codegen-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\codegen.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\codegen.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\compilation-cache.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\compilation-cache.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\compiler.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\compiler.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\constants-arm.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\contexts.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\contexts.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\conversions-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\conversions.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\conversions.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\counters.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\counters.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\cpu-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\cpu.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\dateparser.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\dateparser.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\debug-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\debug.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\debug.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\disassembler.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\disassembler.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\execution.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\execution.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\factory.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\factory.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\flags.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\flags.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\frames-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\frames-arm.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\frames-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\frames.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\frames.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\func-name-inferrer.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\func-name-inferrer.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\global-handles.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\global-handles.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\globals.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\handles-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\handles.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\handles.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\hashmap.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\hashmap.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\heap-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\heap.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\heap.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\ic-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\ic-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\ic.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\ic.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\interceptors.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\interpreter-irregexp.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\interpreter-irregexp.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\jump-target.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\jump-target.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\jump-target-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\jsregexp-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\jsregexp.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\jsregexp.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\list-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\list.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\log.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\log.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\macro-assembler-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\macro-assembler-arm.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\macro-assembler.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\mark-compact.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\mark-compact.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\memory.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\messages.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\messages.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\natives.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\objects-debug.cc"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\src\objects-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\objects.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\objects.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\parser.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\parser.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\platform-win32.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\platform.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\prettyprinter.cc"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\src\prettyprinter.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\property.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\property.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-macro-assembler-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-macro-assembler-arm.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-macro-assembler-irregexp.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-macro-assembler-irregexp.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-macro-assembler.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-macro-assembler.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-macro-assembler-tracer.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-macro-assembler-tracer.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\regexp-stack.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\register-allocator.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\register-allocator.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\register-allocator-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\rewriter.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\rewriter.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\runtime.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\runtime.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\scanner.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\scanner.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\scopeinfo.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\scopeinfo.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\scopes.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\scopes.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\serialize.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\serialize.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\shell.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\snapshot-common.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\snapshot.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\simulator-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\simulator-arm.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\spaces-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\spaces.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\spaces.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\string-stream.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\string-stream.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\stub-cache-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\stub-cache.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\stub-cache.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\token.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\token.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\top.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\top.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\unicode-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\unicode.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\usage-analyzer.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\usage-analyzer.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\utils.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\utils.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\v8-counters.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\v8-counters.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\v8.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\v8.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\v8threads.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\v8threads.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\variables.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\variables.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\virtual-frame.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\virtual-frame-arm.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\virtual-frame.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\virtual-frame-arm.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\zone-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\zone.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\zone.h"
+				>
+			</File>
+			<Filter
+				Name="third party"
+				>
+				<File
+					RelativePath="..\..\src\disasm-arm.cc"
+					>
+				</File>
+				<File
+					RelativePath="..\..\src\disasm.h"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="generated files"
+				>
+				<File
+					RelativePath="..\..\src\unicode.cc"
+					>
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="include"
+			>
+			<File
+				RelativePath="..\..\include\debug.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\include\v8.h"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/deps/v8/tools/visual_studio/v8_cctest.vcproj b/deps/v8/tools/visual_studio/v8_cctest.vcproj
new file mode 100644
index 0000000..5d49d24
--- /dev/null
+++ b/deps/v8/tools/visual_studio/v8_cctest.vcproj
@@ -0,0 +1,239 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="v8_cctest"
+	ProjectGUID="{97ECC711-7430-4FC4-90FD-004DA880E72A}"
+	RootNamespace="v8_cctest"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			ConfigurationType="1"
+			InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="winmm.lib Ws2_32.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			ConfigurationType="1"
+			InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="winmm.lib Ws2_32.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<File
+			RelativePath="..\..\test\cctest\cctest.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-alloc.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-api.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-assembler-ia32.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-ast.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-compiler.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-conversions.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-debug.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-decls.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-disasm-ia32.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-flags.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-func-name-inference.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-hashmap.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-heap.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-lock.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-log-ia32.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-mark-compact.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-platform-win32.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-serialize.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-sockets.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-spaces.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-strings.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-utils.cc"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/deps/v8/tools/visual_studio/v8_cctest_arm.vcproj b/deps/v8/tools/visual_studio/v8_cctest_arm.vcproj
new file mode 100644
index 0000000..44812f0
--- /dev/null
+++ b/deps/v8/tools/visual_studio/v8_cctest_arm.vcproj
@@ -0,0 +1,225 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="v8_cctest"
+	ProjectGUID="{97ECC711-7430-4FC4-90FD-004DA880E72A}"
+	RootNamespace="v8_cctest"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			ConfigurationType="1"
+			InheritedPropertySheets=".\common.vsprops;.\debug.vsprops;.\arm.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			ConfigurationType="1"
+			InheritedPropertySheets=".\common.vsprops;.\release.vsprops;.\arm.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<File
+			RelativePath="..\..\test\cctest\cctest.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-alloc.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-api.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-assembler-arm.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-ast.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-compiler.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-conversions.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-debug.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-decls.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-disasm-arm.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-flags.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-hashmap.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-heap.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-lock.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-mark-compact.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-platform-win32.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-serialize.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-spaces.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-strings.cc"
+			>
+		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-utils.cc"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/deps/v8/tools/visual_studio/v8_mksnapshot.vcproj b/deps/v8/tools/visual_studio/v8_mksnapshot.vcproj
new file mode 100644
index 0000000..4d5d84f
--- /dev/null
+++ b/deps/v8/tools/visual_studio/v8_mksnapshot.vcproj
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="v8_mksnapshot"
+	ProjectGUID="{865575D0-37E2-405E-8CBA-5F6C485B5A26}"
+	RootNamespace="v8_mksnapshot"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			ConfigurationType="1"
+			InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="winmm.lib Ws2_32.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			ConfigurationType="1"
+			InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="winmm.lib Ws2_32.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<File
+			RelativePath="..\..\src\mksnapshot.cc"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/deps/v8/tools/visual_studio/v8_process_sample.vcproj b/deps/v8/tools/visual_studio/v8_process_sample.vcproj
new file mode 100644
index 0000000..ea8c97d
--- /dev/null
+++ b/deps/v8/tools/visual_studio/v8_process_sample.vcproj
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="v8_process_sample"
+	ProjectGUID="{EF019874-D38A-40E3-B17C-DB5923F0A79C}"
+	RootNamespace="v8_process_sample"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			ConfigurationType="1"
+			InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="winmm.lib Ws2_32.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			ConfigurationType="1"
+			InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="winmm.lib Ws2_32.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<File
+			RelativePath="..\..\samples\process.cc"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/deps/v8/tools/visual_studio/v8_shell_sample.vcproj b/deps/v8/tools/visual_studio/v8_shell_sample.vcproj
new file mode 100644
index 0000000..b5d9c61
--- /dev/null
+++ b/deps/v8/tools/visual_studio/v8_shell_sample.vcproj
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="v8_shell_sample"
+	ProjectGUID="{2DE20FFA-6F5E-48D9-84D8-09B044A5B119}"
+	RootNamespace="v8_shell_sample"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			ConfigurationType="1"
+			InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="winmm.lib Ws2_32.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			ConfigurationType="1"
+			InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="winmm.lib Ws2_32.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<File
+			RelativePath="..\..\samples\shell.cc"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/deps/v8/tools/visual_studio/v8_snapshot.vcproj b/deps/v8/tools/visual_studio/v8_snapshot.vcproj
new file mode 100644
index 0000000..25d922f
--- /dev/null
+++ b/deps/v8/tools/visual_studio/v8_snapshot.vcproj
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="v8_snapshot"
+	ProjectGUID="{C0334F9A-1168-4101-9DD8-C30FB252D435}"
+	RootNamespace="v8_snapshot"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			ConfigurationType="4"
+			InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				LinkLibraryDependencies="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			ConfigurationType="4"
+			InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				LinkLibraryDependencies="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="generated files"
+			SourceControlFiles="false"
+			>
+			<File
+				RelativePath="$(IntDir)\..\v8\DerivedSources\natives-empty.cc"
+				>
+			</File>
+			<File
+				RelativePath="$(IntDir)\..\v8_snapshot_cc\DerivedSources\snapshot.cc"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/deps/v8/tools/visual_studio/v8_snapshot_cc.vcproj b/deps/v8/tools/visual_studio/v8_snapshot_cc.vcproj
new file mode 100644
index 0000000..1cfac24
--- /dev/null
+++ b/deps/v8/tools/visual_studio/v8_snapshot_cc.vcproj
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="v8_snapshot_cc"
+	ProjectGUID="{0DDBDA8B-A49F-4CC7-A1D5-5BB8297C8A3F}"
+	RootNamespace="v8_snapshot_cc"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			ConfigurationType="10"
+			InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			ConfigurationType="10"
+			InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="generated files"
+			SourceControlFiles="false"
+			>
+      <File
+        RelativePath="$(OutDir)\v8_mksnapshot.exe"
+        >
+        <FileConfiguration
+          Name="Debug|Win32"
+          >
+          <Tool
+            Name="VCCustomBuildTool"
+            Description="Building snapshot..."
+            CommandLine="&quot;$(OutDir)\v8_mksnapshot.exe&quot; &quot;$(IntDir)\DerivedSources\snapshot.cc&quot;&#x0D;&#x0A;"
+            AdditionalDependencies="$(OutDir)\v8_mksnapshot.exe"
+            Outputs="$(IntDir)\DerivedSources\snapshot.cc"
+          />
+        </FileConfiguration>
+        <FileConfiguration
+          Name="Release|Win32"
+          >
+          <Tool
+            Name="VCCustomBuildTool"
+            Description="Building snapshot..."
+            CommandLine="&quot;$(OutDir)\v8_mksnapshot.exe&quot; &quot;$(IntDir)\DerivedSources\snapshot.cc&quot;&#x0D;&#x0A;"
+            AdditionalDependencies="$(OutDir)\v8_mksnapshot.exe"
+            Outputs="$(IntDir)\DerivedSources\snapshot.cc"
+          />
+        </FileConfiguration>
+      </File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/deps/v8/tools/windows-tick-processor.py b/deps/v8/tools/windows-tick-processor.py
new file mode 100755
index 0000000..ade2bf2
--- /dev/null
+++ b/deps/v8/tools/windows-tick-processor.py
@@ -0,0 +1,137 @@
+#!/usr/bin/env python
+#
+# Copyright 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.
+
+
+# Usage: process-ticks.py <binary> <logfile>
+#
+# Where <binary> is the binary program name (eg, v8_shell.exe) and
+# <logfile> is the log file name (eg, v8.log).
+#
+# This tick processor expects to find a map file for the binary named
+# binary.map if the binary is named binary.exe. The tick processor
+# only works for statically linked executables - no information about
+# shared libraries is logged from v8 on Windows.
+
+import os, re, sys, tickprocessor
+
+class WindowsTickProcessor(tickprocessor.TickProcessor):
+
+  def Unmangle(self, name):
+    """Performs very simple unmangling of C++ names.
+
+    Does not handle arguments and template arguments. The mangled names have
+    the form:
+
+       ?LookupInDescriptor@JSObject@internal@v8@@...arguments info...
+
+    """
+    # Name is mangled if it starts with a question mark.
+    is_mangled = re.match("^\?(.*)", name)
+    if is_mangled:
+      substrings = is_mangled.group(1).split('@')
+      try:
+        # The function name is terminated by two @s in a row.  Find the
+        # substrings that are part of the function name.
+        index = substrings.index('')
+        substrings = substrings[0:index]
+      except ValueError:
+        # If we did not find two @s in a row, the mangled name is not in
+        # the format we expect and we give up.
+        return name
+      substrings.reverse()
+      function_name = "::".join(substrings)
+      return function_name
+    return name
+
+
+  def ParseMapFile(self, filename):
+    """Parse map file and add symbol information to the cpp entries."""
+    # Locate map file.
+    has_dot = re.match('^([a-zA-F0-9_-]*)[\.]?.*$', filename)
+    if has_dot:
+      map_file_name = has_dot.group(1) + '.map'
+      try:
+        map_file = open(map_file_name, 'rb')
+      except IOError:
+        sys.exit("Could not open map file: " + map_file_name)
+    else:
+      sys.exit("Could not find map file for executable: " + filename)
+    try:
+      max_addr = 0
+      min_addr = 2**30
+      # Process map file and search for function entries.
+      row_regexp = re.compile(' 0001:[0-9a-fA-F]{8}\s*([_\?@$0-9a-zA-Z]*)\s*([0-9a-fA-F]{8}).*')
+      for line in map_file:
+        row = re.match(row_regexp, line)
+        if row:
+          addr = int(row.group(2), 16)
+          if addr > max_addr:
+            max_addr = addr
+          if addr < min_addr:
+            min_addr = addr
+          mangled_name = row.group(1)
+          name = self.Unmangle(mangled_name)
+          self.cpp_entries.Insert(addr, tickprocessor.CodeEntry(addr, name));
+      i = min_addr
+      # Mark the pages for which there are functions in the map file.
+      while i < max_addr:
+        page = i >> 12
+        self.vm_extent[page] = 1
+        i += 4096
+    finally:
+      map_file.close()
+
+
+class WindowsCmdLineProcessor(tickprocessor.CmdLineProcessor):
+
+  def __init__(self):
+    super(WindowsCmdLineProcessor, self).__init__()
+    self.binary_file = None
+
+  def GetRequiredArgsNames(self):
+    return 'binary log_file'
+
+  def ProcessRequiredArgs(self, args):
+    if len(args) != 2:
+      self.PrintUsageAndExit()
+    else:
+      self.binary_file = args[0]
+      self.log_file = args[1]
+
+
+def Main():
+  cmdline_processor = WindowsCmdLineProcessor()
+  cmdline_processor.ProcessArguments()
+  tickprocessor = WindowsTickProcessor()
+  tickprocessor.ParseMapFile(cmdline_processor.binary_file)
+  cmdline_processor.RunLogfileProcessing(tickprocessor)
+  tickprocessor.PrintResults()
+
+if __name__ == '__main__':
+  Main()
diff --git a/wscript b/wscript
index fee5bd6..38b2391 100644
--- a/wscript
+++ b/wscript
@@ -82,8 +82,8 @@ def build(bld):
   #v8lib = bld.env["staticlib_PATTERN"] % "v8"
   v8 = bld.new_task_gen(
     target=join("deps/v8",v8lib),
-    rule='cp -rf %s %s && cd %s && scons -Q mode=debug library=static snapshot=on' 
-    #rule='cp -rf %s %s && cd %s && scons -Q library=static snapshot=on' 
+    rule='cp -rf %s %s && cd %s && python scons.py -Q mode=debug library=static snapshot=on' 
+    #rule='cp -rf %s %s && cd %s && python scons.py -Q library=static snapshot=on' 
       % ( v8dir_src , deps_tgt , v8dir_tgt),
     before="cxx"
   )
@@ -91,20 +91,20 @@ def build(bld):
   #bld.env["STATICLIB_V8"] = "v8"
   bld.env["STATICLIB_V8"] = "v8_g"
   bld.env["LIBPATH_V8"] = v8dir_tgt
-  bld.env["LINKFLAGS_V8"] = "-pthread"
+  bld.env["LINKFLAGS_V8"] = "-pthread -lrt"
 
   ### oi
   oi = bld.new_task_gen("cc", "staticlib")
-  oi.source = "deps/oi/oi_socket.c deps/oi/oi_buf.c"
-  oi.includes = "deps/oi/"
+  oi.source = "deps/liboi/oi_socket.c deps/liboi/oi_buf.c"
+  oi.includes = "deps/liboi/"
   oi.name = "oi"
   oi.target = "oi"
   oi.uselib = "GNUTLS"
 
   ### ebb
   ebb = bld.new_task_gen("cc", "staticlib")
-  ebb.source = "deps/ebb/ebb_request_parser.rl"
-  ebb.includes = "deps/ebb/"
+  ebb.source = "deps/libebb/ebb_request_parser.rl"
+  ebb.includes = "deps/libebb/"
   ebb.name = "ebb"
   ebb.target = "ebb"
 
@@ -139,8 +139,8 @@ def build(bld):
     deps/v8/include
     deps/libev
     deps/libeio
-    deps/oi 
-    deps/ebb
+    deps/liboi 
+    deps/libebb
   """
   node.uselib_local = "oi ev eio ebb"
   node.uselib = "V8"
